summaryrefslogtreecommitdiffstats
path: root/chromium/ui/views
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-08 14:30:41 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-08-12 13:49:54 +0200
commitab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch)
tree498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ui/views
parent4ce69f7403811819800e7c5ae1318b2647e778d1 (diff)
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ui/views')
-rw-r--r--chromium/ui/views/DEPS9
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.cc130
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.h83
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_wrapper.h43
-rw-r--r--chromium/ui/views/accessibility/ax_view_obj_wrapper.cc91
-rw-r--r--chromium/ui/views/accessibility/ax_view_obj_wrapper.h38
-rw-r--r--chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc55
-rw-r--r--chromium/ui/views/accessibility/ax_widget_obj_wrapper.h44
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.cc64
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.h42
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility.h4
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility_win.cc297
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility_win.h57
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc112
-rw-r--r--chromium/ui/views/accessible_pane_view.cc6
-rw-r--r--chromium/ui/views/accessible_pane_view.h2
-rw-r--r--chromium/ui/views/accessible_pane_view_unittest.cc4
-rw-r--r--chromium/ui/views/animation/bounds_animator.cc15
-rw-r--r--chromium/ui/views/animation/bounds_animator.h27
-rw-r--r--chromium/ui/views/animation/bounds_animator_unittest.cc15
-rw-r--r--chromium/ui/views/background.cc5
-rw-r--r--chromium/ui/views/border.cc39
-rw-r--r--chromium/ui/views/border.h33
-rw-r--r--chromium/ui/views/bubble/bubble_border.cc3
-rw-r--r--chromium/ui/views/bubble/bubble_border.h8
-rw-r--r--chromium/ui/views/bubble/bubble_delegate.cc117
-rw-r--r--chromium/ui/views/bubble/bubble_delegate.h42
-rw-r--r--chromium/ui/views/bubble/bubble_delegate_unittest.cc75
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc101
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h19
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view_unittest.cc3
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter.cc30
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter.h33
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter_unittest.cc116
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.cc44
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.h19
-rw-r--r--chromium/ui/views/button_drag_utils.cc27
-rw-r--r--chromium/ui/views/button_drag_utils.h15
-rw-r--r--chromium/ui/views/cocoa/bridged_content_view.h33
-rw-r--r--chromium/ui/views/cocoa/bridged_content_view.mm50
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.h62
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.mm78
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_unittest.mm117
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.cc31
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.h2
-rw-r--r--chromium/ui/views/controls/button/blue_button.cc83
-rw-r--r--chromium/ui/views/controls/button/blue_button.h1
-rw-r--r--chromium/ui/views/controls/button/blue_button_unittest.cc59
-rw-r--r--chromium/ui/views/controls/button/button.cc28
-rw-r--r--chromium/ui/views/controls/button/button.h16
-rw-r--r--chromium/ui/views/controls/button/checkbox.cc14
-rw-r--r--chromium/ui/views/controls/button/checkbox.h4
-rw-r--r--chromium/ui/views/controls/button/custom_button.cc15
-rw-r--r--chromium/ui/views/controls/button/custom_button.h6
-rw-r--r--chromium/ui/views/controls/button/custom_button_unittest.cc24
-rw-r--r--chromium/ui/views/controls/button/image_button.cc23
-rw-r--r--chromium/ui/views/controls/button/image_button.h17
-rw-r--r--chromium/ui/views/controls/button/image_button_unittest.cc25
-rw-r--r--chromium/ui/views/controls/button/label_button.cc161
-rw-r--r--chromium/ui/views/controls/button/label_button.h54
-rw-r--r--chromium/ui/views/controls/button/label_button_border.cc50
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc53
-rw-r--r--chromium/ui/views/controls/button/menu_button.cc62
-rw-r--r--chromium/ui/views/controls/button/menu_button.h18
-rw-r--r--chromium/ui/views/controls/button/menu_button_unittest.cc199
-rw-r--r--chromium/ui/views/controls/button/radio_button.cc10
-rw-r--r--chromium/ui/views/controls/button/radio_button.h6
-rw-r--r--chromium/ui/views/controls/button/text_button.cc185
-rw-r--r--chromium/ui/views/controls/button/text_button.h72
-rw-r--r--chromium/ui/views/controls/combobox/combobox.cc244
-rw-r--r--chromium/ui/views/controls/combobox/combobox.h53
-rw-r--r--chromium/ui/views/controls/combobox/combobox_listener.h21
-rw-r--r--chromium/ui/views/controls/combobox/combobox_unittest.cc244
-rw-r--r--chromium/ui/views/controls/image_view.cc42
-rw-r--r--chromium/ui/views/controls/image_view.h16
-rw-r--r--chromium/ui/views/controls/label.cc261
-rw-r--r--chromium/ui/views/controls/label.h169
-rw-r--r--chromium/ui/views/controls/label_unittest.cc477
-rw-r--r--chromium/ui/views/controls/link.cc115
-rw-r--r--chromium/ui/views/controls/link.h26
-rw-r--r--chromium/ui/views/controls/menu/display_change_listener_mac.cc16
-rw-r--r--chromium/ui/views/controls/menu/menu.cc26
-rw-r--r--chromium/ui/views/controls/menu/menu.h30
-rw-r--r--chromium/ui/views/controls/menu/menu_config.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_config.h17
-rw-r--r--chromium/ui/views/controls/menu/menu_config_aura.cc (renamed from chromium/ui/views/controls/menu/menu_config_views.cc)8
-rw-r--r--chromium/ui/views/controls/menu/menu_config_mac.cc26
-rw-r--r--chromium/ui/views/controls/menu/menu_config_win.cc21
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc376
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.h63
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_aura.cc115
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc267
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_win.cc27
-rw-r--r--chromium/ui/views/controls/menu/menu_delegate.cc29
-rw-r--r--chromium/ui/views/controls/menu/menu_delegate.h34
-rw-r--r--chromium/ui/views/controls/menu/menu_event_dispatcher_linux.cc91
-rw-r--r--chromium/ui/views/controls/menu/menu_event_dispatcher_linux.h32
-rw-r--r--chromium/ui/views/controls/menu/menu_host.cc20
-rw-r--r--chromium/ui/views/controls/menu/menu_host_root_view.cc9
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.cc5
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc238
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.h98
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop.h57
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_aura.cc202
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_aura.h52
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_mac.cc51
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_mac.h35
-rw-r--r--chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc95
-rw-r--r--chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h36
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter.cc32
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter.h7
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter_unittest.cc11
-rw-r--r--chromium/ui/views/controls/menu/menu_runner.cc32
-rw-r--r--chromium/ui/views/controls/menu/menu_runner.h15
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_handler.h4
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.cc43
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.h11
-rw-r--r--chromium/ui/views/controls/menu/menu_separator.h6
-rw-r--r--chromium/ui/views/controls/menu/menu_separator_views.cc4
-rw-r--r--chromium/ui/views/controls/menu/menu_separator_win.cc11
-rw-r--r--chromium/ui/views/controls/menu/menu_types.h26
-rw-r--r--chromium/ui/views/controls/menu/menu_win.cc572
-rw-r--r--chromium/ui/views/controls/menu/menu_win.h139
-rw-r--r--chromium/ui/views/controls/menu/native_menu_win.cc40
-rw-r--r--chromium/ui/views/controls/menu/native_menu_win.h4
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.cc68
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.h30
-rw-r--r--chromium/ui/views/controls/message_box_view.cc43
-rw-r--r--chromium/ui/views/controls/message_box_view.h14
-rw-r--r--chromium/ui/views/controls/native/native_view_host.cc20
-rw-r--r--chromium/ui/views/controls/native/native_view_host.h6
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc7
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.h1
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura_unittest.cc19
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.cc18
-rw-r--r--chromium/ui/views/controls/native/native_view_host_unittest.cc15
-rw-r--r--chromium/ui/views/controls/native/native_view_host_win.cc157
-rw-r--r--chromium/ui/views/controls/native/native_view_host_win.h47
-rw-r--r--chromium/ui/views/controls/native/native_view_host_wrapper.h4
-rw-r--r--chromium/ui/views/controls/native_control.cc389
-rw-r--r--chromium/ui/views/controls/native_control.h126
-rw-r--r--chromium/ui/views/controls/native_control_win.cc226
-rw-r--r--chromium/ui/views/controls/native_control_win.h99
-rw-r--r--chromium/ui/views/controls/prefix_delegate.h2
-rw-r--r--chromium/ui/views/controls/prefix_selector.cc25
-rw-r--r--chromium/ui/views/controls/prefix_selector.h15
-rw-r--r--chromium/ui/views/controls/prefix_selector_unittest.cc6
-rw-r--r--chromium/ui/views/controls/progress_bar.cc21
-rw-r--r--chromium/ui/views/controls/progress_bar.h10
-rw-r--r--chromium/ui/views/controls/progress_bar_unittest.cc16
-rw-r--r--chromium/ui/views/controls/resize_area.cc22
-rw-r--r--chromium/ui/views/controls/resize_area.h2
-rw-r--r--chromium/ui/views/controls/scroll_view.cc54
-rw-r--r--chromium/ui/views/controls/scroll_view.h15
-rw-r--r--chromium/ui/views/controls/scroll_view_unittest.cc103
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar.cc39
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar.h10
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc5
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc309
-rw-r--r--chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.h91
-rw-r--r--chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc6
-rw-r--r--chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/native_scroll_bar.cc7
-rw-r--r--chromium/ui/views/controls/scrollbar/native_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc10
-rw-r--r--chromium/ui/views/controls/scrollbar/native_scroll_bar_views.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc16
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.cc6
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc11
-rw-r--r--chromium/ui/views/controls/separator.cc10
-rw-r--r--chromium/ui/views/controls/separator.h7
-rw-r--r--chromium/ui/views/controls/single_split_view.cc28
-rw-r--r--chromium/ui/views/controls/single_split_view.h8
-rw-r--r--chromium/ui/views/controls/single_split_view_listener.h4
-rw-r--r--chromium/ui/views/controls/single_split_view_unittest.cc58
-rw-r--r--chromium/ui/views/controls/slide_out_view.cc26
-rw-r--r--chromium/ui/views/controls/slider.cc77
-rw-r--r--chromium/ui/views/controls/slider.h26
-rw-r--r--chromium/ui/views/controls/slider_unittest.cc382
-rw-r--r--chromium/ui/views/controls/styled_label.cc147
-rw-r--r--chromium/ui/views/controls/styled_label.h29
-rw-r--r--chromium/ui/views/controls/styled_label_unittest.cc161
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc42
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.h8
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane_listener.h4
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc4
-rw-r--r--chromium/ui/views/controls/table/table_grouper.h6
-rw-r--r--chromium/ui/views/controls/table/table_header.cc33
-rw-r--r--chromium/ui/views/controls/table/table_header.h8
-rw-r--r--chromium/ui/views/controls/table/table_utils.cc25
-rw-r--r--chromium/ui/views/controls/table/table_utils.h18
-rw-r--r--chromium/ui/views/controls/table/table_utils_unittest.cc70
-rw-r--r--chromium/ui/views/controls/table/table_view.cc31
-rw-r--r--chromium/ui/views/controls/table/table_view.h10
-rw-r--r--chromium/ui/views/controls/table/table_view_observer.h3
-rw-r--r--chromium/ui/views/controls/table/table_view_unittest.cc23
-rw-r--r--chromium/ui/views/controls/table/test_table_model.cc6
-rw-r--r--chromium/ui/views/controls/table/test_table_model.h2
-rw-r--r--chromium/ui/views/controls/textfield/native_textfield_views.cc1545
-rw-r--r--chromium/ui/views/controls/textfield/native_textfield_views.h345
-rw-r--r--chromium/ui/views/controls/textfield/native_textfield_wrapper.h188
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc1817
-rw-r--r--chromium/ui/views/controls/textfield/textfield.h450
-rw-r--r--chromium/ui/views/controls/textfield/textfield_controller.cc16
-rw-r--r--chromium/ui/views/controls/textfield/textfield_controller.h24
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.cc (renamed from chromium/ui/views/controls/textfield/textfield_views_model.cc)336
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.h (renamed from chromium/ui/views/controls/textfield/textfield_views_model.h)157
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model_unittest.cc (renamed from chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc)808
-rw-r--r--chromium/ui/views/controls/textfield/textfield_test_api.cc30
-rw-r--r--chromium/ui/views/controls/textfield/textfield_test_api.h43
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc (renamed from chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc)1080
-rw-r--r--chromium/ui/views/controls/throbber.cc2
-rw-r--r--chromium/ui/views/controls/throbber.h2
-rw-r--r--chromium/ui/views/controls/tree/tree_view.cc44
-rw-r--r--chromium/ui/views/controls/tree/tree_view.h21
-rw-r--r--chromium/ui/views/controls/tree/tree_view_unittest.cc14
-rw-r--r--chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc4
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.cc44
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.h20
-rw-r--r--chromium/ui/views/controls/webview/webview.cc236
-rw-r--r--chromium/ui/views/controls/webview/webview.gyp3
-rw-r--r--chromium/ui/views/controls/webview/webview.h51
-rw-r--r--chromium/ui/views/controls/webview/webview_interactive_uitest.cc82
-rw-r--r--chromium/ui/views/controls/webview/webview_tests.gyp38
-rw-r--r--chromium/ui/views/corewm/DEPS61
-rw-r--r--chromium/ui/views/corewm/base_focus_rules.cc196
-rw-r--r--chromium/ui/views/corewm/base_focus_rules.h47
-rw-r--r--chromium/ui/views/corewm/capture_controller.cc145
-rw-r--r--chromium/ui/views/corewm/capture_controller.h88
-rw-r--r--chromium/ui/views/corewm/capture_controller_unittest.cc82
-rw-r--r--chromium/ui/views/corewm/compound_event_filter.cc279
-rw-r--r--chromium/ui/views/corewm/compound_event_filter.h93
-rw-r--r--chromium/ui/views/corewm/compound_event_filter_unittest.cc205
-rw-r--r--chromium/ui/views/corewm/corewm_switches.cc21
-rw-r--r--chromium/ui/views/corewm/corewm_switches.h27
-rw-r--r--chromium/ui/views/corewm/cursor_height_provider_win.cc146
-rw-r--r--chromium/ui/views/corewm/cursor_height_provider_win.h21
-rw-r--r--chromium/ui/views/corewm/cursor_manager.cc235
-rw-r--r--chromium/ui/views/corewm/cursor_manager.h92
-rw-r--r--chromium/ui/views/corewm/cursor_manager_unittest.cc353
-rw-r--r--chromium/ui/views/corewm/desktop_capture_controller_unittest.cc60
-rw-r--r--chromium/ui/views/corewm/focus_controller.cc365
-rw-r--r--chromium/ui/views/corewm/focus_controller.h130
-rw-r--r--chromium/ui/views/corewm/focus_controller_unittest.cc1110
-rw-r--r--chromium/ui/views/corewm/focus_rules.h68
-rw-r--r--chromium/ui/views/corewm/image_grid.cc308
-rw-r--r--chromium/ui/views/corewm/image_grid.h228
-rw-r--r--chromium/ui/views/corewm/image_grid_unittest.cc341
-rw-r--r--chromium/ui/views/corewm/input_method_event_filter.cc81
-rw-r--r--chromium/ui/views/corewm/input_method_event_filter.h58
-rw-r--r--chromium/ui/views/corewm/input_method_event_filter_unittest.cc91
-rw-r--r--chromium/ui/views/corewm/native_cursor_manager.h67
-rw-r--r--chromium/ui/views/corewm/native_cursor_manager_delegate.h36
-rw-r--r--chromium/ui/views/corewm/shadow.cc195
-rw-r--r--chromium/ui/views/corewm/shadow.h88
-rw-r--r--chromium/ui/views/corewm/shadow_controller.cc273
-rw-r--r--chromium/ui/views/corewm/shadow_controller.h71
-rw-r--r--chromium/ui/views/corewm/shadow_controller_unittest.cc214
-rw-r--r--chromium/ui/views/corewm/shadow_types.cc25
-rw-r--r--chromium/ui/views/corewm/shadow_types.h36
-rw-r--r--chromium/ui/views/corewm/tooltip.h2
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.cc130
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.h22
-rw-r--r--chromium/ui/views/corewm/tooltip_aura_unittest.cc70
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.cc61
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.h10
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_test_helper.cc4
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_test_helper.h10
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc452
-rw-r--r--chromium/ui/views/corewm/tooltip_win.cc30
-rw-r--r--chromium/ui/views/corewm/tooltip_win.h2
-rw-r--r--chromium/ui/views/corewm/transient_window_stacking_client.cc95
-rw-r--r--chromium/ui/views/corewm/transient_window_stacking_client.h32
-rw-r--r--chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc175
-rw-r--r--chromium/ui/views/corewm/visibility_controller.cc87
-rw-r--r--chromium/ui/views/corewm/visibility_controller.h75
-rw-r--r--chromium/ui/views/corewm/visibility_controller_unittest.cc57
-rw-r--r--chromium/ui/views/corewm/window_animations.cc573
-rw-r--r--chromium/ui/views/corewm/window_animations.h101
-rw-r--r--chromium/ui/views/corewm/window_animations_unittest.cc143
-rw-r--r--chromium/ui/views/corewm/window_modality_controller.cc196
-rw-r--r--chromium/ui/views/corewm/window_modality_controller.h73
-rw-r--r--chromium/ui/views/corewm/window_util.cc141
-rw-r--r--chromium/ui/views/corewm/window_util.h53
-rw-r--r--chromium/ui/views/corewm/window_util_unittest.cc117
-rw-r--r--chromium/ui/views/cull_set.cc26
-rw-r--r--chromium/ui/views/cull_set.h47
-rw-r--r--chromium/ui/views/debug_utils.cc6
-rw-r--r--chromium/ui/views/drag_utils.cc43
-rw-r--r--chromium/ui/views/drag_utils_aura.cc27
-rw-r--r--chromium/ui/views/event_utils.h31
-rw-r--r--chromium/ui/views/event_utils_aura.cc60
-rw-r--r--chromium/ui/views/event_utils_win.cc64
-rw-r--r--chromium/ui/views/examples/DEPS2
-rw-r--r--chromium/ui/views/examples/bubble_example.cc15
-rw-r--r--chromium/ui/views/examples/bubble_example.h7
-rw-r--r--chromium/ui/views/examples/button_example.cc17
-rw-r--r--chromium/ui/views/examples/button_example.h10
-rw-r--r--chromium/ui/views/examples/checkbox_example.cc2
-rw-r--r--chromium/ui/views/examples/checkbox_example.h5
-rw-r--r--chromium/ui/views/examples/combobox_example.cc8
-rw-r--r--chromium/ui/views/examples/combobox_example.h18
-rw-r--r--chromium/ui/views/examples/content_client/DEPS4
-rw-r--r--chromium/ui/views/examples/content_client/examples_browser_main_parts.cc95
-rw-r--r--chromium/ui/views/examples/content_client/examples_browser_main_parts.h57
-rw-r--r--chromium/ui/views/examples/content_client/examples_content_browser_client.cc36
-rw-r--r--chromium/ui/views/examples/content_client/examples_content_browser_client.h44
-rw-r--r--chromium/ui/views/examples/content_client/examples_main.cc25
-rw-r--r--chromium/ui/views/examples/content_client/examples_main_delegate.cc80
-rw-r--r--chromium/ui/views/examples/content_client/examples_main_delegate.h43
-rw-r--r--chromium/ui/views/examples/double_split_view_example.cc6
-rw-r--r--chromium/ui/views/examples/double_split_view_example.h7
-rw-r--r--chromium/ui/views/examples/example_base.cc3
-rw-r--r--chromium/ui/views/examples/example_base.h5
-rw-r--r--chromium/ui/views/examples/example_combobox_model.cc4
-rw-r--r--chromium/ui/views/examples/example_combobox_model.h7
-rw-r--r--chromium/ui/views/examples/examples.gyp187
-rw-r--r--chromium/ui/views/examples/examples_main.cc84
-rw-r--r--chromium/ui/views/examples/examples_window.cc182
-rw-r--r--chromium/ui/views/examples/examples_window.h18
-rw-r--r--chromium/ui/views/examples/examples_window_with_content.cc210
-rw-r--r--chromium/ui/views/examples/examples_window_with_content.h6
-rw-r--r--chromium/ui/views/examples/examples_with_content_main_exe.cc49
-rw-r--r--chromium/ui/views/examples/label_example.cc43
-rw-r--r--chromium/ui/views/examples/label_example.h7
-rw-r--r--chromium/ui/views/examples/link_example.cc2
-rw-r--r--chromium/ui/views/examples/link_example.h10
-rw-r--r--chromium/ui/views/examples/menu_example.cc30
-rw-r--r--chromium/ui/views/examples/menu_example.h7
-rw-r--r--chromium/ui/views/examples/message_box_example.cc2
-rw-r--r--chromium/ui/views/examples/message_box_example.h10
-rw-r--r--chromium/ui/views/examples/multiline_example.cc56
-rw-r--r--chromium/ui/views/examples/multiline_example.h14
-rw-r--r--chromium/ui/views/examples/progress_bar_example.cc4
-rw-r--r--chromium/ui/views/examples/progress_bar_example.h10
-rw-r--r--chromium/ui/views/examples/radio_button_example.cc6
-rw-r--r--chromium/ui/views/examples/radio_button_example.h10
-rw-r--r--chromium/ui/views/examples/scroll_view_example.cc4
-rw-r--r--chromium/ui/views/examples/scroll_view_example.h10
-rw-r--r--chromium/ui/views/examples/single_split_view_example.cc10
-rw-r--r--chromium/ui/views/examples/single_split_view_example.h11
-rw-r--r--chromium/ui/views/examples/slider_example.cc2
-rw-r--r--chromium/ui/views/examples/slider_example.h10
-rw-r--r--chromium/ui/views/examples/tabbed_pane_example.cc4
-rw-r--r--chromium/ui/views/examples/tabbed_pane_example.h9
-rw-r--r--chromium/ui/views/examples/table_example.cc14
-rw-r--r--chromium/ui/views/examples/table_example.h15
-rw-r--r--chromium/ui/views/examples/text_example.cc218
-rw-r--r--chromium/ui/views/examples/text_example.h17
-rw-r--r--chromium/ui/views/examples/textfield_example.cc14
-rw-r--r--chromium/ui/views/examples/textfield_example.h12
-rw-r--r--chromium/ui/views/examples/throbber_example.cc2
-rw-r--r--chromium/ui/views/examples/throbber_example.h7
-rw-r--r--chromium/ui/views/examples/tree_view_example.cc12
-rw-r--r--chromium/ui/views/examples/tree_view_example.h14
-rw-r--r--chromium/ui/views/examples/webview_example.cc3
-rw-r--r--chromium/ui/views/examples/webview_example.h5
-rw-r--r--chromium/ui/views/examples/widget_example.cc8
-rw-r--r--chromium/ui/views/examples/widget_example.h10
-rw-r--r--chromium/ui/views/focus/accelerator_handler.h46
-rw-r--r--chromium/ui/views/focus/accelerator_handler_aura.cc26
-rw-r--r--chromium/ui/views/focus/accelerator_handler_win.cc55
-rw-r--r--chromium/ui/views/focus/focus_manager.cc70
-rw-r--r--chromium/ui/views/focus/focus_manager.h11
-rw-r--r--chromium/ui/views/focus/focus_manager_test.cc18
-rw-r--r--chromium/ui/views/focus/focus_manager_test.h9
-rw-r--r--chromium/ui/views/focus/focus_manager_unittest.cc131
-rw-r--r--chromium/ui/views/focus/focus_manager_unittest_win.cc281
-rw-r--r--chromium/ui/views/focus/focus_traversal_unittest.cc38
-rw-r--r--chromium/ui/views/focus/view_storage.h2
-rw-r--r--chromium/ui/views/ime/OWNERS6
-rw-r--r--chromium/ui/views/ime/input_method.h9
-rw-r--r--chromium/ui/views/ime/input_method_bridge.cc27
-rw-r--r--chromium/ui/views/ime/input_method_bridge.h10
-rw-r--r--chromium/ui/views/ime/mock_input_method.cc21
-rw-r--r--chromium/ui/views/ime/mock_input_method.h8
-rw-r--r--chromium/ui/views/ime/null_input_method.cc62
-rw-r--r--chromium/ui/views/ime/null_input_method.h50
-rw-r--r--chromium/ui/views/layout/box_layout.cc93
-rw-r--r--chromium/ui/views/layout/box_layout.h52
-rw-r--r--chromium/ui/views/layout/box_layout_unittest.cc114
-rw-r--r--chromium/ui/views/layout/fill_layout.cc4
-rw-r--r--chromium/ui/views/layout/fill_layout.h5
-rw-r--r--chromium/ui/views/layout/grid_layout.cc52
-rw-r--r--chromium/ui/views/layout/grid_layout.h28
-rw-r--r--chromium/ui/views/layout/grid_layout_unittest.cc33
-rw-r--r--chromium/ui/views/layout/layout_manager.cc3
-rw-r--r--chromium/ui/views/layout/layout_manager.h4
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.cc3
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.gyp2
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.h52
-rw-r--r--chromium/ui/views/linux_ui/status_icon_linux.h2
-rw-r--r--chromium/ui/views/linux_ui/window_button_order_provider.cc83
-rw-r--r--chromium/ui/views/masked_view_targeter.cc46
-rw-r--r--chromium/ui/views/masked_view_targeter.h46
-rw-r--r--chromium/ui/views/metrics_aura.cc1
-rw-r--r--chromium/ui/views/metrics_mac.cc25
-rw-r--r--chromium/ui/views/metrics_win.cc22
-rw-r--r--chromium/ui/views/mouse_watcher_aura.cc (renamed from chromium/ui/views/mouse_watcher.cc)96
-rw-r--r--chromium/ui/views/native_cursor.h21
-rw-r--r--chromium/ui/views/native_cursor_aura.cc31
-rw-r--r--chromium/ui/views/native_cursor_mac.mm39
-rw-r--r--chromium/ui/views/painter.cc100
-rw-r--r--chromium/ui/views/painter.h6
-rw-r--r--chromium/ui/views/run_all_unittests.cc13
-rw-r--r--chromium/ui/views/touchui/touch_editing_menu.cc44
-rw-r--r--chromium/ui/views/touchui/touch_editing_menu.h8
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.cc207
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.h37
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc454
-rw-r--r--chromium/ui/views/view.cc477
-rw-r--r--chromium/ui/views/view.h123
-rw-r--r--chromium/ui/views/view_aura.cc33
-rw-r--r--chromium/ui/views/view_constants_aura.cc2
-rw-r--r--chromium/ui/views/view_constants_aura.h4
-rw-r--r--chromium/ui/views/view_model.cc5
-rw-r--r--chromium/ui/views/view_targeter.cc79
-rw-r--r--chromium/ui/views/view_targeter.h51
-rw-r--r--chromium/ui/views/view_targeter_unittest.cc386
-rw-r--r--chromium/ui/views/view_unittest.cc979
-rw-r--r--chromium/ui/views/view_unittest_aura.cc160
-rw-r--r--chromium/ui/views/view_win.cc28
-rw-r--r--chromium/ui/views/views.gyp678
-rw-r--r--chromium/ui/views/views_delegate.cc81
-rw-r--r--chromium/ui/views/views_delegate.h87
-rw-r--r--chromium/ui/views/views_switches.cc9
-rw-r--r--chromium/ui/views/views_switches.h4
-rw-r--r--chromium/ui/views/views_touch_selection_controller_factory.h25
-rw-r--r--chromium/ui/views/views_touch_selection_controller_factory_aura.cc22
-rw-r--r--chromium/ui/views/views_touch_selection_controller_factory_mac.cc17
-rw-r--r--chromium/ui/views/widget/aero_tooltip_manager.cc115
-rw-r--r--chromium/ui/views/widget/aero_tooltip_manager.h59
-rw-r--r--chromium/ui/views/widget/child_window_message_processor.cc28
-rw-r--r--chromium/ui/views/widget/child_window_message_processor.h47
-rw-r--r--chromium/ui/views/widget/desktop_aura/OWNERS5
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc37
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc556
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h101
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc679
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h11
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc14
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc58
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc51
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h48
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc494
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h117
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc306
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win_unittest.cc55
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc50
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.h7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_position_client_unittest.cc16
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc158
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h9
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc272
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h)47
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h)10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_ozone.cc (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc)6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc)550
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h)82
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc)1100
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h (renamed from chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h)178
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc448
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc116
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h27
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc53
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h19
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_scoped_capture.cc31
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_scoped_capture.h29
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.cc97
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.h53
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_unittest.cc389
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc244
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h45
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc162
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h29
-rw-r--r--chromium/ui/views/widget/drop_target_win.cc63
-rw-r--r--chromium/ui/views/widget/drop_target_win.h55
-rw-r--r--chromium/ui/views/widget/monitor_win.cc19
-rw-r--r--chromium/ui/views/widget/monitor_win.h10
-rw-r--r--chromium/ui/views/widget/native_widget.h7
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc228
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h34
-rw-r--r--chromium/ui/views/widget/native_widget_aura_unittest.cc249
-rw-r--r--chromium/ui/views/widget/native_widget_delegate.h13
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h117
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm448
-rw-r--r--chromium/ui/views/widget/native_widget_private.h19
-rw-r--r--chromium/ui/views/widget/native_widget_unittest.cc1
-rw-r--r--chromium/ui/views/widget/native_widget_win.cc1068
-rw-r--r--chromium/ui/views/widget/native_widget_win.h278
-rw-r--r--chromium/ui/views/widget/native_widget_win_unittest.cc83
-rw-r--r--chromium/ui/views/widget/root_view.cc624
-rw-r--r--chromium/ui/views/widget/root_view.h46
-rw-r--r--chromium/ui/views/widget/root_view_test_helper.h33
-rw-r--r--chromium/ui/views/widget/root_view_unittest.cc198
-rw-r--r--chromium/ui/views/widget/tooltip_manager_aura.cc16
-rw-r--r--chromium/ui/views/widget/tooltip_manager_aura.h2
-rw-r--r--chromium/ui/views/widget/tooltip_manager_win.cc357
-rw-r--r--chromium/ui/views/widget/tooltip_manager_win.h135
-rw-r--r--chromium/ui/views/widget/widget.cc298
-rw-r--r--chromium/ui/views/widget/widget.h129
-rw-r--r--chromium/ui/views/widget/widget_aura_utils.cc16
-rw-r--r--chromium/ui/views/widget/widget_aura_utils.h4
-rw-r--r--chromium/ui/views/widget/widget_delegate.cc16
-rw-r--r--chromium/ui/views/widget/widget_delegate.h15
-rw-r--r--chromium/ui/views/widget/widget_hwnd_utils.cc14
-rw-r--r--chromium/ui/views/widget/widget_hwnd_utils.h3
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc288
-rw-r--r--chromium/ui/views/widget/widget_observer.h1
-rw-r--r--chromium/ui/views/widget/widget_removals_observer.h30
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc826
-rw-r--r--chromium/ui/views/widget/window_reorderer_unittest.cc2
-rw-r--r--chromium/ui/views/win/DEPS2
-rw-r--r--chromium/ui/views/win/appbar.cc88
-rw-r--r--chromium/ui/views/win/appbar.h70
-rw-r--r--chromium/ui/views/win/fullscreen_handler.cc4
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc774
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h257
-rw-r--r--chromium/ui/views/win/hwnd_message_handler_delegate.h16
-rw-r--r--chromium/ui/views/win/hwnd_util_aurawin.cc13
-rw-r--r--chromium/ui/views/win/hwnd_util_win.cc39
-rw-r--r--chromium/ui/views/window/client_view.cc12
-rw-r--r--chromium/ui/views/window/client_view.h8
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc245
-rw-r--r--chromium/ui/views/window/custom_frame_view.h33
-rw-r--r--chromium/ui/views/window/custom_frame_view_unittest.cc252
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc61
-rw-r--r--chromium/ui/views/window/dialog_client_view.h3
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc68
-rw-r--r--chromium/ui/views/window/dialog_delegate.h25
-rw-r--r--chromium/ui/views/window/dialog_delegate_unittest.cc40
-rw-r--r--chromium/ui/views/window/frame_background.cc39
-rw-r--r--chromium/ui/views/window/frame_background.h15
-rw-r--r--chromium/ui/views/window/native_frame_view.cc37
-rw-r--r--chromium/ui/views/window/native_frame_view.h9
-rw-r--r--chromium/ui/views/window/non_client_view.cc54
-rw-r--r--chromium/ui/views/window/non_client_view.h40
-rw-r--r--chromium/ui/views/window/window_button_order_provider.cc41
-rw-r--r--chromium/ui/views/window/window_button_order_provider.h56
555 files changed, 23756 insertions, 26929 deletions
diff --git a/chromium/ui/views/DEPS b/chromium/ui/views/DEPS
index 7619dc0cb17..b29fbd88a07 100644
--- a/chromium/ui/views/DEPS
+++ b/chromium/ui/views/DEPS
@@ -4,13 +4,20 @@ include_rules = [
"+skia/ext",
"+third_party/iaccessible2",
"+third_party/skia",
+ "+ui/accessibility",
"+ui/aura",
"+ui/base",
"+ui/compositor",
+ "+ui/display",
"+ui/events",
"+ui/gfx",
- "+ui/ozone",
+ "+ui/gl/gl_surface.h", # To initialize GL for tests.
"+ui/native_theme",
+ "+ui/ozone",
+ "+ui/wm/core",
+ "+ui/wm/public",
+
+ "-testing/gmock",
]
specific_include_rules = {
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
new file mode 100644
index 00000000000..ae2df2068ab
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -0,0 +1,130 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+
+#include "base/memory/singleton.h"
+#include "base/stl_util.h"
+#include "ui/aura/window.h"
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+#include "ui/views/accessibility/ax_view_obj_wrapper.h"
+#include "ui/views/accessibility/ax_widget_obj_wrapper.h"
+#include "ui/views/accessibility/ax_window_obj_wrapper.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+// static
+AXAuraObjCache* AXAuraObjCache::GetInstance() {
+ return Singleton<AXAuraObjCache>::get();
+}
+
+AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(View* view) {
+ return CreateInternal<AXViewObjWrapper>(view, view_to_id_map_);
+}
+
+AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(Widget* widget) {
+ return CreateInternal<AXWidgetObjWrapper>(widget, widget_to_id_map_);
+}
+
+AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(aura::Window* window) {
+ return CreateInternal<AXWindowObjWrapper>(window, window_to_id_map_);
+}
+
+int32 AXAuraObjCache::GetID(View* view) {
+ return GetIDInternal(view, view_to_id_map_);
+}
+
+int32 AXAuraObjCache::GetID(Widget* widget) {
+ return GetIDInternal(widget, widget_to_id_map_);
+}
+
+int32 AXAuraObjCache::GetID(aura::Window* window) {
+ return GetIDInternal(window, window_to_id_map_);
+}
+
+void AXAuraObjCache::Remove(View* view) {
+ RemoveInternal(view, view_to_id_map_);
+}
+
+void AXAuraObjCache::Remove(Widget* widget) {
+ RemoveInternal(widget, widget_to_id_map_);
+}
+
+void AXAuraObjCache::Remove(aura::Window* window) {
+ RemoveInternal(window, window_to_id_map_);
+}
+
+AXAuraObjWrapper* AXAuraObjCache::Get(int32 id) {
+ std::map<int32, AXAuraObjWrapper*>::iterator it = cache_.find(id);
+
+ if (it == cache_.end())
+ return NULL;
+
+ return it->second;
+}
+
+void AXAuraObjCache::Remove(int32 id) {
+ AXAuraObjWrapper* obj = Get(id);
+
+ if (id == -1 || !obj)
+ return;
+
+ cache_.erase(id);
+ delete obj;
+}
+
+AXAuraObjCache::AXAuraObjCache() : current_id_(1) {
+}
+
+AXAuraObjCache::~AXAuraObjCache() {
+ STLDeleteContainerPairSecondPointers(cache_.begin(), cache_.end());
+ cache_.clear();
+}
+
+template <typename AuraViewWrapper, typename AuraView>
+AXAuraObjWrapper* AXAuraObjCache::CreateInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map) {
+ if (!aura_view)
+ return NULL;
+
+ typename std::map<AuraView*, int32>::iterator it =
+ aura_view_to_id_map.find(aura_view);
+
+ if (it != aura_view_to_id_map.end())
+ return Get(it->second);
+
+ AXAuraObjWrapper* wrapper = new AuraViewWrapper(aura_view);
+ aura_view_to_id_map[aura_view] = current_id_;
+ cache_[current_id_] = wrapper;
+ current_id_++;
+ return wrapper;
+}
+
+template<typename AuraView> int32 AXAuraObjCache::GetIDInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map) {
+ if (!aura_view)
+ return -1;
+
+ typename std::map<AuraView*, int32>::iterator it =
+ aura_view_to_id_map.find(aura_view);
+
+ if (it != aura_view_to_id_map.end())
+ return it->second;
+
+ return -1;
+}
+
+template<typename AuraView>
+void AXAuraObjCache::RemoveInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map) {
+ int32 id = GetID(aura_view);
+ if (id == -1)
+ return;
+ aura_view_to_id_map.erase(aura_view);
+ Remove(id);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.h b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
new file mode 100644
index 00000000000..6e5d9e829a9
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
@@ -0,0 +1,83 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "ui/views/views_export.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace views {
+class AXAuraObjWrapper;
+class View;
+class Widget;
+
+// A cache responsible for assigning id's to a set of interesting Aura views.
+class VIEWS_EXPORT AXAuraObjCache {
+ public:
+ // Get the single instance of this class.
+ static AXAuraObjCache* GetInstance();
+
+ // Get or create an entry in the cache based on an Aura view.
+ AXAuraObjWrapper* GetOrCreate(View* view);
+ AXAuraObjWrapper* GetOrCreate(Widget* widget);
+ AXAuraObjWrapper* GetOrCreate(aura::Window* window);
+
+ // Gets an id given an Aura view.
+ int32 GetID(View* view);
+ int32 GetID(Widget* widget);
+ int32 GetID(aura::Window* window);
+
+ // Gets the next unique id for this cache. Useful for non-Aura view backed
+ // views.
+ int32 GetNextID() { return current_id_++; }
+
+ // Removes an entry from this cache based on an Aura view.
+ void Remove(View* view);
+ void Remove(Widget* widget);
+ void Remove(aura::Window* window);
+
+ // Lookup a cached entry based on an id.
+ AXAuraObjWrapper* Get(int32 id);
+
+ // Remove a cached entry based on an id.
+ void Remove(int32 id);
+
+ private:
+ friend struct DefaultSingletonTraits<AXAuraObjCache>;
+
+ AXAuraObjCache();
+ virtual ~AXAuraObjCache();
+
+ template <typename AuraViewWrapper, typename AuraView>
+ AXAuraObjWrapper* CreateInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map);
+
+ template<typename AuraView> int32 GetIDInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map);
+
+ template<typename AuraView> void RemoveInternal(
+ AuraView* aura_view, std::map<AuraView*, int32>& aura_view_to_id_map);
+
+ std::map<views::View*, int32> view_to_id_map_;
+ std::map<views::Widget*, int32> widget_to_id_map_;
+ std::map<aura::Window*, int32> window_to_id_map_;
+
+ std::map<int32, AXAuraObjWrapper*> cache_;
+ int32 current_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXAuraObjCache);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_CACHE_H_
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_wrapper.h b/chromium/ui/views/accessibility/ax_aura_obj_wrapper.h
new file mode 100644
index 00000000000..00f9c593c0c
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_aura_obj_wrapper.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_WRAPPER_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_WRAPPER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+struct AXNodeData;
+} // namespace ui
+
+namespace views {
+
+// An interface abstraction for Aura views that exposes the view-tree formed
+// by the implementing view types.
+class VIEWS_EXPORT AXAuraObjWrapper {
+ public:
+ virtual ~AXAuraObjWrapper() {}
+
+ // Traversal and serialization.
+ virtual AXAuraObjWrapper* GetParent() = 0;
+ virtual void GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) = 0;
+ virtual void Serialize(ui::AXNodeData* out_node_data) = 0;
+ virtual int32 GetID() = 0;
+
+ // Actions.
+ virtual void DoDefault() {}
+ virtual void Focus() {}
+ virtual void MakeVisible() {}
+ virtual void SetSelection(int32 start, int32 end) {}
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_AURA_OBJ_WRAPPER_H_
diff --git a/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc
new file mode 100644
index 00000000000..b5c60775c75
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -0,0 +1,91 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_view_obj_wrapper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+AXViewObjWrapper::AXViewObjWrapper(View* view) : view_(view) {
+ DCHECK(view->GetWidget());
+ if (view->GetWidget())
+ AXAuraObjCache::GetInstance()->GetOrCreate(view->GetWidget());
+}
+
+AXViewObjWrapper::~AXViewObjWrapper() {}
+
+AXAuraObjWrapper* AXViewObjWrapper::GetParent() {
+ AXAuraObjCache* cache = AXAuraObjCache::GetInstance();
+ if (view_->parent())
+ return cache->GetOrCreate(view_->parent());
+
+ return cache->GetOrCreate(view_->GetWidget());
+}
+
+void AXViewObjWrapper::GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) {
+ // TODO(dtseng): Need to handle |Widget| child of |View|.
+ for (int i = 0; i < view_->child_count(); ++i) {
+ AXAuraObjWrapper* child =
+ AXAuraObjCache::GetInstance()->GetOrCreate(view_->child_at(i));
+ out_children->push_back(child);
+ }
+}
+
+void AXViewObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
+ ui::AXViewState view_data;
+ view_->GetAccessibleState(&view_data);
+ out_node_data->id = GetID();
+ out_node_data->role = view_data.role;
+
+ out_node_data->state = view_data.state();
+ if (view_->HasFocus())
+ out_node_data->state |= 1 << ui::AX_STATE_FOCUSED;
+ if (view_->IsFocusable())
+ out_node_data->state |= 1 << ui::AX_STATE_FOCUSABLE;
+
+ out_node_data->location = view_->GetBoundsInScreen();
+
+ out_node_data->AddStringAttribute(
+ ui::AX_ATTR_NAME, base::UTF16ToUTF8(view_data.name));
+ out_node_data->AddStringAttribute(
+ ui::AX_ATTR_VALUE, base::UTF16ToUTF8(view_data.value));
+
+ out_node_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START,
+ view_data.selection_start);
+ out_node_data->AddIntAttribute(ui::AX_ATTR_TEXT_SEL_END,
+ view_data.selection_end);
+}
+
+int32 AXViewObjWrapper::GetID() {
+ return AXAuraObjCache::GetInstance()->GetID(view_);
+}
+
+void AXViewObjWrapper::DoDefault() {
+ gfx::Rect rect = view_->GetBoundsInScreen();
+ gfx::Point center = rect.CenterPoint();
+ view_->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED, center, center,
+ ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON));
+}
+
+void AXViewObjWrapper::Focus() {
+ view_->RequestFocus();
+}
+
+void AXViewObjWrapper::MakeVisible() {
+ // TODO(dtseng): Implement.
+}
+
+void AXViewObjWrapper::SetSelection(int32 start, int32 end) {
+ // TODO(dtseng): Implement.
+}
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_view_obj_wrapper.h b/chromium/ui/views/accessibility/ax_view_obj_wrapper.h
new file mode 100644
index 00000000000..6838d07243c
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_view_obj_wrapper.h
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_AX_VIEW_OBJ_WRAPPER_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_VIEW_OBJ_WRAPPER_H_
+
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+
+namespace views {
+class View;
+
+// Describes a |View| for use with other AX classes.
+class AXViewObjWrapper : public AXAuraObjWrapper {
+ public:
+ explicit AXViewObjWrapper(View* view);
+ virtual ~AXViewObjWrapper();
+
+ // AXAuraObjWrapper overrides.
+ virtual AXAuraObjWrapper* GetParent() OVERRIDE;
+ virtual void GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) OVERRIDE;
+ virtual void Serialize(ui::AXNodeData* out_node_data) OVERRIDE;
+ virtual int32 GetID() OVERRIDE;
+ virtual void DoDefault() OVERRIDE;
+ virtual void Focus() OVERRIDE;
+ virtual void MakeVisible() OVERRIDE;
+ virtual void SetSelection(int32 start, int32 end) OVERRIDE;
+
+ private:
+ View* view_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXViewObjWrapper);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_VIEW_OBJ_WRAPPER_H_
diff --git a/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc
new file mode 100644
index 00000000000..36a3143e365
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_widget_obj_wrapper.h"
+
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+AXWidgetObjWrapper::AXWidgetObjWrapper(Widget* widget) : widget_(widget) {
+ widget->AddObserver(this);
+ widget->AddRemovalsObserver(this);
+}
+
+AXWidgetObjWrapper::~AXWidgetObjWrapper() {
+ widget_->RemoveObserver(this);
+ widget_->RemoveRemovalsObserver(this);
+ widget_ = NULL;
+}
+
+AXAuraObjWrapper* AXWidgetObjWrapper::GetParent() {
+ return AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetNativeView());
+}
+
+void AXWidgetObjWrapper::GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) {
+ out_children->push_back(
+ AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetRootView()));
+}
+
+void AXWidgetObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
+ out_node_data->id = GetID();
+ out_node_data->role = ui::AX_ROLE_CLIENT;
+ out_node_data->location = widget_->GetWindowBoundsInScreen();
+ // TODO(dtseng): Set better states.
+ out_node_data->state = 0;
+}
+
+int32 AXWidgetObjWrapper::GetID() {
+ return AXAuraObjCache::GetInstance()->GetID(widget_);
+}
+
+void AXWidgetObjWrapper::OnWidgetDestroying(Widget* widget) {
+ AXAuraObjCache::GetInstance()->Remove(widget);
+}
+
+void AXWidgetObjWrapper::OnWillRemoveView(Widget* widget, View* view) {
+ AXAuraObjCache::GetInstance()->Remove(view);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_widget_obj_wrapper.h b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.h
new file mode 100644
index 00000000000..61ff1e90f28
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_AX_WIDGET_OBJ_WRAPPER_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_WIDGET_OBJ_WRAPPER_H_
+
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+#include "ui/views/widget/widget_observer.h"
+#include "ui/views/widget/widget_removals_observer.h"
+
+namespace views {
+class Widget;
+
+// Describes a |Widget| for use with other AX classes.
+class AXWidgetObjWrapper : public AXAuraObjWrapper,
+ public WidgetObserver,
+ public WidgetRemovalsObserver {
+ public:
+ explicit AXWidgetObjWrapper(Widget* widget);
+ virtual ~AXWidgetObjWrapper();
+
+ // AXAuraObjWrapper overrides.
+ virtual AXAuraObjWrapper* GetParent() OVERRIDE;
+ virtual void GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) OVERRIDE;
+ virtual void Serialize(ui::AXNodeData* out_node_data) OVERRIDE;
+ virtual int32 GetID() OVERRIDE;
+
+ // WidgetObserver overrides.
+ virtual void OnWidgetDestroying(Widget* widget) OVERRIDE;
+
+ // WidgetRemovalsObserver overrides.
+ virtual void OnWillRemoveView(Widget* widget, View* view) OVERRIDE;
+
+ private:
+ Widget* widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXWidgetObjWrapper);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_WIDGET_OBJ_WRAPPER_H_
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
new file mode 100644
index 00000000000..b358de58c91
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_window_obj_wrapper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/aura/window.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+AXWindowObjWrapper::AXWindowObjWrapper(
+ aura::Window* window) : window_(window) {
+ window->AddObserver(this);
+}
+
+AXWindowObjWrapper::~AXWindowObjWrapper() {
+ window_->RemoveObserver(this);
+ window_ = NULL;
+}
+
+AXAuraObjWrapper* AXWindowObjWrapper::GetParent() {
+ if (!window_->parent())
+ return NULL;
+
+ return AXAuraObjCache::GetInstance()->GetOrCreate(window_->parent());
+}
+
+void AXWindowObjWrapper::GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) {
+ aura::Window::Windows children = window_->children();
+ for (size_t i = 0; i < children.size(); ++i) {
+ out_children->push_back(
+ AXAuraObjCache::GetInstance()->GetOrCreate(children[i]));
+ }
+
+ // Also consider any associated widgets as children.
+ Widget* widget = Widget::GetWidgetForNativeView(window_);
+ if (widget)
+ out_children->push_back(AXAuraObjCache::GetInstance()->GetOrCreate(widget));
+}
+
+void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
+ out_node_data->id = GetID();
+ out_node_data->role = ui::AX_ROLE_WINDOW;
+ // TODO(dtseng): Set better states.
+ out_node_data->state = 0;
+ out_node_data->location = window_->bounds();
+ out_node_data->AddStringAttribute(
+ ui::AX_ATTR_NAME, base::UTF16ToUTF8(window_->title()));
+}
+
+int32 AXWindowObjWrapper::GetID() {
+ return AXAuraObjCache::GetInstance()->GetID(window_);
+}
+
+void AXWindowObjWrapper::OnWindowDestroying(aura::Window* window) {
+ AXAuraObjCache::GetInstance()->Remove(window);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.h b/chromium/ui/views/accessibility/ax_window_obj_wrapper.h
new file mode 100644
index 00000000000..b3cd235cfb7
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ACCESSIBILITY_AX_WINDOW_OBJ_WRAPPER_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_WINDOW_OBJ_WRAPPER_H_
+
+#include "ui/aura/window_observer.h"
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+
+namespace aura {
+class Window;
+} // namespace aura
+
+namespace views {
+
+// Describes a |Window| for use with other AX classes.
+class AXWindowObjWrapper : public AXAuraObjWrapper,
+ public aura::WindowObserver {
+ public:
+ explicit AXWindowObjWrapper(aura::Window* window);
+ virtual ~AXWindowObjWrapper();
+
+ // AXAuraObjWrapper overrides.
+ virtual AXAuraObjWrapper* GetParent() OVERRIDE;
+ virtual void GetChildren(
+ std::vector<AXAuraObjWrapper*>* out_children) OVERRIDE;
+ virtual void Serialize(ui::AXNodeData* out_node_data) OVERRIDE;
+ virtual int32 GetID() OVERRIDE;
+
+ // WindowObserver overrides.
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
+
+ private:
+ aura::Window* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXWindowObjWrapper);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_WINDOW_OBJ_WRAPPER_H_
diff --git a/chromium/ui/views/accessibility/native_view_accessibility.h b/chromium/ui/views/accessibility/native_view_accessibility.h
index 2fc4c4423b6..2b9f5927710 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility.h
+++ b/chromium/ui/views/accessibility/native_view_accessibility.h
@@ -5,7 +5,7 @@
#ifndef UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_H_
#define UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_H_
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
@@ -18,7 +18,7 @@ class VIEWS_EXPORT NativeViewAccessibility {
static NativeViewAccessibility* Create(View* view);
virtual void NotifyAccessibilityEvent(
- ui::AccessibilityTypes::Event event_type) {}
+ ui::AXEvent event_type) {}
virtual gfx::NativeViewAccessible GetNativeObject();
diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win.cc b/chromium/ui/views/accessibility/native_view_accessibility_win.cc
index 3e20cbbc4a9..670de4dd8ec 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/chromium/ui/views/accessibility/native_view_accessibility_win.cc
@@ -4,8 +4,8 @@
#include "ui/views/accessibility/native_view_accessibility_win.h"
-#include <UIAutomationClient.h>
#include <oleacc.h>
+#include <UIAutomationClient.h>
#include <set>
#include <vector>
@@ -15,8 +15,9 @@
#include "base/win/scoped_comptr.h"
#include "base/win/windows_version.h"
#include "third_party/iaccessible2/ia2_api_all.h"
-#include "ui/base/accessibility/accessible_text_utils.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_text_utils.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/win/accessibility_ids_win.h"
#include "ui/base/win/accessibility_misc_utils.h"
#include "ui/base/win/atl_module.h"
@@ -26,8 +27,6 @@
#include "ui/views/widget/widget.h"
#include "ui/views/win/hwnd_util.h"
-using ui::AccessibilityTypes;
-
namespace views {
namespace {
@@ -190,6 +189,7 @@ void AccessibleWebViewRegistry::QueryIAccessible2Interface(View* web_view) {
long NativeViewAccessibilityWin::next_unique_id_ = 1;
int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0};
int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0;
+std::vector<int> NativeViewAccessibilityWin::alert_target_view_storage_ids_;
// static
NativeViewAccessibility* NativeViewAccessibility::Create(View* view) {
@@ -211,10 +211,11 @@ NativeViewAccessibilityWin::NativeViewAccessibilityWin()
}
NativeViewAccessibilityWin::~NativeViewAccessibilityWin() {
+ RemoveAlertTarget();
}
void NativeViewAccessibilityWin::NotifyAccessibilityEvent(
- ui::AccessibilityTypes::Event event_type) {
+ ui::AXEvent event_type) {
if (!view_)
return;
@@ -237,6 +238,10 @@ void NativeViewAccessibilityWin::NotifyAccessibilityEvent(
::NotifyWinEvent(MSAAEvent(event_type), hwnd, OBJID_CLIENT, child_id);
next_view_storage_id_index_ =
(next_view_storage_id_index_ + 1) % kMaxViewStorageIds;
+
+ // Keep track of views that are a target of an alert event.
+ if (event_type == ui::AX_EVENT_ALERT)
+ AddAlertTarget();
}
gfx::NativeViewAccessible NativeViewAccessibilityWin::GetNativeObject() {
@@ -557,9 +562,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accDefaultAction(
if (!view_)
return E_FAIL;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- string16 temp_action = state.default_action;
+ base::string16 temp_action = state.default_action;
if (!temp_action.empty()) {
*def_action = SysAllocString(temp_action.c_str());
@@ -578,7 +583,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accDescription(
if (!view_)
return E_FAIL;
- string16 temp_desc;
+ base::string16 temp_desc;
view_->GetTooltipText(gfx::Point(), &temp_desc);
if (!temp_desc.empty()) {
@@ -624,9 +629,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accKeyboardShortcut(
if (!view_)
return E_FAIL;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- string16 temp_key = state.keyboard_shortcut;
+ base::string16 temp_key = state.keyboard_shortcut;
if (!temp_key.empty()) {
*acc_key = SysAllocString(temp_key.c_str());
@@ -646,9 +651,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accName(
return E_FAIL;
// Retrieve the current view's name.
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- string16 temp_name = state.name;
+ base::string16 temp_name = state.name;
if (!temp_name.empty()) {
// Return name retrieved.
*name = SysAllocString(temp_name.c_str());
@@ -694,7 +699,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accRole(
if (!view_)
return E_FAIL;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
role->vt = VT_I4;
role->lVal = MSAARole(state.role);
@@ -733,9 +738,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_accValue(VARIANT var_id,
return E_FAIL;
// Retrieve the current view's value.
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- string16 temp_value = state.value;
+ base::string16 temp_value = state.value;
if (!temp_value.empty()) {
// Return value retrieved.
@@ -758,7 +763,7 @@ STDMETHODIMP NativeViewAccessibilityWin::put_accValue(VARIANT var_id,
return E_FAIL;
// Return an error if the view can't set the value.
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
if (state.set_value_callback.is_null())
return E_FAIL;
@@ -782,9 +787,9 @@ STDMETHODIMP NativeViewAccessibilityWin::accSelect(
STDMETHODIMP NativeViewAccessibilityWin::get_accHelp(
VARIANT var_id, BSTR* help) {
- if (help)
- *help = NULL;
- return E_NOTIMPL;
+ base::string16 temp = base::UTF8ToUTF16(view_->GetClassName());
+ *help = SysAllocString(temp.c_str());
+ return S_OK;
}
STDMETHODIMP NativeViewAccessibilityWin::get_accHelpTopic(
@@ -815,7 +820,7 @@ STDMETHODIMP NativeViewAccessibilityWin::role(LONG* role) {
if (!role)
return E_INVALIDARG;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
*role = MSAARole(state.role);
return S_OK;
@@ -831,14 +836,14 @@ STDMETHODIMP NativeViewAccessibilityWin::get_states(AccessibleStates* states) {
if (!states)
return E_INVALIDARG;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
// There are only a couple of states we need to support
// in IAccessible2. If any more are added, we may want to
// add a helper function like MSAAState.
*states = IA2_STATE_OPAQUE;
- if (state.state & AccessibilityTypes::STATE_EDITABLE)
+ if (state.HasStateFlag(ui::AX_STATE_EDITABLE))
*states |= IA2_STATE_EDITABLE;
return S_OK;
@@ -866,6 +871,59 @@ STDMETHODIMP NativeViewAccessibilityWin::get_windowHandle(HWND* window_handle) {
return *window_handle ? S_OK : S_FALSE;
}
+STDMETHODIMP NativeViewAccessibilityWin::get_relationTargetsOfType(
+ BSTR type_bstr,
+ long max_targets,
+ IUnknown ***targets,
+ long *n_targets) {
+ if (!view_)
+ return E_FAIL;
+
+ if (!targets || !n_targets)
+ return E_INVALIDARG;
+
+ *n_targets = 0;
+ *targets = NULL;
+
+ // Only respond to requests for relations of type "alerts" on the
+ // root view.
+ base::string16 type(type_bstr);
+ if (type != L"alerts" || view_->parent())
+ return S_FALSE;
+
+ // Collect all of the alert views that are still valid.
+ std::vector<View*> alert_views;
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) {
+ int view_storage_id = alert_target_view_storage_ids_[i];
+ View* view = view_storage->RetrieveView(view_storage_id);
+ if (!view || !view_->Contains(view))
+ continue;
+ alert_views.push_back(view);
+ }
+
+ long count = alert_views.size();
+ if (count == 0)
+ return S_FALSE;
+
+ // Don't return more targets than max_targets - but note that the caller
+ // is allowed to specify max_targets=0 to mean no limit.
+ if (max_targets > 0 && count > max_targets)
+ count = max_targets;
+
+ // Return the number of targets.
+ *n_targets = count;
+
+ // Allocate COM memory for the result array and populate it.
+ *targets = static_cast<IUnknown**>(
+ CoTaskMemAlloc(count * sizeof(IUnknown*)));
+ for (long i = 0; i < count; ++i) {
+ (*targets)[i] = alert_views[i]->GetNativeViewAccessible();
+ (*targets)[i]->AddRef();
+ }
+ return S_OK;
+}
+
//
// IAccessibleText
//
@@ -877,7 +935,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_nCharacters(LONG* n_characters) {
if (!n_characters)
return E_INVALIDARG;
- string16 text = TextForIAccessibleText();
+ base::string16 text = TextForIAccessibleText();
*n_characters = static_cast<LONG>(text.size());
return S_OK;
}
@@ -889,7 +947,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_caretOffset(LONG* offset) {
if (!offset)
return E_INVALIDARG;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
*offset = static_cast<LONG>(state.selection_end);
return S_OK;
@@ -902,7 +960,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_nSelections(LONG* n_selections) {
if (!n_selections)
return E_INVALIDARG;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
if (state.selection_start != state.selection_end)
*n_selections = 1;
@@ -920,7 +978,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_selection(LONG selection_index,
if (!start_offset || !end_offset || selection_index != 0)
return E_INVALIDARG;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
*start_offset = static_cast<LONG>(state.selection_start);
*end_offset = static_cast<LONG>(state.selection_end);
@@ -933,9 +991,9 @@ STDMETHODIMP NativeViewAccessibilityWin::get_text(LONG start_offset,
if (!view_)
return E_FAIL;
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- string16 text_str = TextForIAccessibleText();
+ base::string16 text_str = TextForIAccessibleText();
LONG len = static_cast<LONG>(text_str.size());
if (start_offset == IA2_TEXT_OFFSET_LENGTH) {
@@ -963,7 +1021,8 @@ STDMETHODIMP NativeViewAccessibilityWin::get_text(LONG start_offset,
if (end_offset > len)
return E_INVALIDARG;
- string16 substr = text_str.substr(start_offset, end_offset - start_offset);
+ base::string16 substr =
+ text_str.substr(start_offset, end_offset - start_offset);
if (substr.empty())
return S_FALSE;
@@ -989,7 +1048,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_textAtOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = FindBoundary(
text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
@@ -1015,7 +1074,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_textBeforeOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = FindBoundary(
text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
@@ -1040,7 +1099,7 @@ STDMETHODIMP NativeViewAccessibilityWin::get_textAfterOffset(
return S_FALSE;
}
- const string16& text_str = TextForIAccessibleText();
+ const base::string16& text_str = TextForIAccessibleText();
*start_offset = offset;
*end_offset = FindBoundary(
@@ -1071,11 +1130,12 @@ STDMETHODIMP NativeViewAccessibilityWin::QueryService(
if (!view_)
return E_FAIL;
- if (riid == IID_IAccessible2)
+ if (riid == IID_IAccessible2 || riid == IID_IAccessible2_2)
AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support();
if (guidService == IID_IAccessible ||
guidService == IID_IAccessible2 ||
+ guidService == IID_IAccessible2_2 ||
guidService == IID_IAccessibleText) {
return QueryInterface(riid, object);
}
@@ -1100,13 +1160,14 @@ STDMETHODIMP NativeViewAccessibilityWin::GetPatternProvider(
<< " for pattern id: "
<< id;
if (id == UIA_ValuePatternId || id == UIA_TextPatternId) {
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
long role = MSAARole(state.role);
if (role == ROLE_SYSTEM_TEXT) {
DVLOG(1) << "Returning UIA text provider";
- base::win::UIATextProvider::CreateTextProvider(true, provider);
+ base::win::UIATextProvider::CreateTextProvider(
+ state.value, true, provider);
return S_OK;
}
}
@@ -1120,7 +1181,7 @@ STDMETHODIMP NativeViewAccessibilityWin::GetPropertyValue(PROPERTYID id,
<< " for property id: "
<< id;
if (id == UIA_ControlTypePropertyId) {
- ui::AccessibleViewState state;
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
long role = MSAARole(state.role);
if (role == ROLE_SYSTEM_TEXT) {
@@ -1149,27 +1210,25 @@ void NativeViewAccessibility::UnregisterWebView(View* web_view) {
AccessibleWebViewRegistry::GetInstance()->UnregisterWebView(web_view);
}
-int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) {
+int32 NativeViewAccessibilityWin::MSAAEvent(ui::AXEvent event) {
switch (event) {
- case AccessibilityTypes::EVENT_ALERT:
+ case ui::AX_EVENT_ALERT:
return EVENT_SYSTEM_ALERT;
- case AccessibilityTypes::EVENT_FOCUS:
+ case ui::AX_EVENT_FOCUS:
return EVENT_OBJECT_FOCUS;
- case AccessibilityTypes::EVENT_MENUSTART:
+ case ui::AX_EVENT_MENU_START:
return EVENT_SYSTEM_MENUSTART;
- case AccessibilityTypes::EVENT_MENUEND:
+ case ui::AX_EVENT_MENU_END:
return EVENT_SYSTEM_MENUEND;
- case AccessibilityTypes::EVENT_MENUPOPUPSTART:
+ case ui::AX_EVENT_MENU_POPUP_START:
return EVENT_SYSTEM_MENUPOPUPSTART;
- case AccessibilityTypes::EVENT_MENUPOPUPEND:
+ case ui::AX_EVENT_MENU_POPUP_END:
return EVENT_SYSTEM_MENUPOPUPEND;
- case AccessibilityTypes::EVENT_NAME_CHANGED:
+ case ui::AX_EVENT_TEXT_CHANGED:
return EVENT_OBJECT_NAMECHANGE;
- case AccessibilityTypes::EVENT_TEXT_CHANGED:
- return EVENT_OBJECT_VALUECHANGE;
- case AccessibilityTypes::EVENT_SELECTION_CHANGED:
+ case ui::AX_EVENT_SELECTION_CHANGED:
return IA2_EVENT_TEXT_CARET_MOVED;
- case AccessibilityTypes::EVENT_VALUE_CHANGED:
+ case ui::AX_EVENT_VALUE_CHANGED:
return EVENT_OBJECT_VALUECHANGE;
default:
// Not supported or invalid event.
@@ -1178,109 +1237,109 @@ int32 NativeViewAccessibilityWin::MSAAEvent(AccessibilityTypes::Event event) {
}
}
-int32 NativeViewAccessibilityWin::MSAARole(AccessibilityTypes::Role role) {
+int32 NativeViewAccessibilityWin::MSAARole(ui::AXRole role) {
switch (role) {
- case AccessibilityTypes::ROLE_ALERT:
+ case ui::AX_ROLE_ALERT:
return ROLE_SYSTEM_ALERT;
- case AccessibilityTypes::ROLE_APPLICATION:
+ case ui::AX_ROLE_APPLICATION:
return ROLE_SYSTEM_APPLICATION;
- case AccessibilityTypes::ROLE_BUTTONDROPDOWN:
+ case ui::AX_ROLE_BUTTON_DROP_DOWN:
return ROLE_SYSTEM_BUTTONDROPDOWN;
- case AccessibilityTypes::ROLE_BUTTONMENU:
+ case ui::AX_ROLE_POP_UP_BUTTON:
return ROLE_SYSTEM_BUTTONMENU;
- case AccessibilityTypes::ROLE_CHECKBUTTON:
+ case ui::AX_ROLE_CHECK_BOX:
return ROLE_SYSTEM_CHECKBUTTON;
- case AccessibilityTypes::ROLE_COMBOBOX:
+ case ui::AX_ROLE_COMBO_BOX:
return ROLE_SYSTEM_COMBOBOX;
- case AccessibilityTypes::ROLE_DIALOG:
+ case ui::AX_ROLE_DIALOG:
return ROLE_SYSTEM_DIALOG;
- case AccessibilityTypes::ROLE_GRAPHIC:
- return ROLE_SYSTEM_GRAPHIC;
- case AccessibilityTypes::ROLE_GROUPING:
+ case ui::AX_ROLE_GROUP:
return ROLE_SYSTEM_GROUPING;
- case AccessibilityTypes::ROLE_LINK:
+ case ui::AX_ROLE_IMAGE:
+ return ROLE_SYSTEM_GRAPHIC;
+ case ui::AX_ROLE_LINK:
return ROLE_SYSTEM_LINK;
- case AccessibilityTypes::ROLE_LOCATION_BAR:
+ case ui::AX_ROLE_LOCATION_BAR:
return ROLE_SYSTEM_GROUPING;
- case AccessibilityTypes::ROLE_MENUBAR:
+ case ui::AX_ROLE_MENU_BAR:
return ROLE_SYSTEM_MENUBAR;
- case AccessibilityTypes::ROLE_MENUITEM:
+ case ui::AX_ROLE_MENU_ITEM:
return ROLE_SYSTEM_MENUITEM;
- case AccessibilityTypes::ROLE_MENUPOPUP:
+ case ui::AX_ROLE_MENU_LIST_POPUP:
return ROLE_SYSTEM_MENUPOPUP;
- case AccessibilityTypes::ROLE_OUTLINE:
+ case ui::AX_ROLE_TREE:
return ROLE_SYSTEM_OUTLINE;
- case AccessibilityTypes::ROLE_OUTLINEITEM:
+ case ui::AX_ROLE_TREE_ITEM:
return ROLE_SYSTEM_OUTLINEITEM;
- case AccessibilityTypes::ROLE_PAGETAB:
+ case ui::AX_ROLE_TAB:
return ROLE_SYSTEM_PAGETAB;
- case AccessibilityTypes::ROLE_PAGETABLIST:
+ case ui::AX_ROLE_TAB_LIST:
return ROLE_SYSTEM_PAGETABLIST;
- case AccessibilityTypes::ROLE_PANE:
+ case ui::AX_ROLE_PANE:
return ROLE_SYSTEM_PANE;
- case AccessibilityTypes::ROLE_PROGRESSBAR:
+ case ui::AX_ROLE_PROGRESS_INDICATOR:
return ROLE_SYSTEM_PROGRESSBAR;
- case AccessibilityTypes::ROLE_PUSHBUTTON:
+ case ui::AX_ROLE_BUTTON:
return ROLE_SYSTEM_PUSHBUTTON;
- case AccessibilityTypes::ROLE_RADIOBUTTON:
+ case ui::AX_ROLE_RADIO_BUTTON:
return ROLE_SYSTEM_RADIOBUTTON;
- case AccessibilityTypes::ROLE_SCROLLBAR:
+ case ui::AX_ROLE_SCROLL_BAR:
return ROLE_SYSTEM_SCROLLBAR;
- case AccessibilityTypes::ROLE_SEPARATOR:
+ case ui::AX_ROLE_SPLITTER:
return ROLE_SYSTEM_SEPARATOR;
- case AccessibilityTypes::ROLE_SLIDER:
+ case ui::AX_ROLE_SLIDER:
return ROLE_SYSTEM_SLIDER;
- case AccessibilityTypes::ROLE_STATICTEXT:
+ case ui::AX_ROLE_STATIC_TEXT:
return ROLE_SYSTEM_STATICTEXT;
- case AccessibilityTypes::ROLE_TEXT:
+ case ui::AX_ROLE_TEXT_FIELD:
return ROLE_SYSTEM_TEXT;
- case AccessibilityTypes::ROLE_TITLEBAR:
+ case ui::AX_ROLE_TITLE_BAR:
return ROLE_SYSTEM_TITLEBAR;
- case AccessibilityTypes::ROLE_TOOLBAR:
+ case ui::AX_ROLE_TOOLBAR:
return ROLE_SYSTEM_TOOLBAR;
- case AccessibilityTypes::ROLE_WINDOW:
+ case ui::AX_ROLE_WINDOW:
return ROLE_SYSTEM_WINDOW;
- case AccessibilityTypes::ROLE_CLIENT:
+ case ui::AX_ROLE_CLIENT:
default:
// This is the default role for MSAA.
return ROLE_SYSTEM_CLIENT;
}
}
-int32 NativeViewAccessibilityWin::MSAAState(AccessibilityTypes::State state) {
+int32 NativeViewAccessibilityWin::MSAAState(const ui::AXViewState& state) {
// This maps MSAA states for get_accState(). See also the IAccessible2
// interface get_states().
int32 msaa_state = 0;
- if (state & AccessibilityTypes::STATE_CHECKED)
+ if (state.HasStateFlag(ui::AX_STATE_CHECKED))
msaa_state |= STATE_SYSTEM_CHECKED;
- if (state & AccessibilityTypes::STATE_COLLAPSED)
+ if (state.HasStateFlag(ui::AX_STATE_COLLAPSED))
msaa_state |= STATE_SYSTEM_COLLAPSED;
- if (state & AccessibilityTypes::STATE_DEFAULT)
+ if (state.HasStateFlag(ui::AX_STATE_DEFAULT))
msaa_state |= STATE_SYSTEM_DEFAULT;
- if (state & AccessibilityTypes::STATE_EXPANDED)
+ if (state.HasStateFlag(ui::AX_STATE_EXPANDED))
msaa_state |= STATE_SYSTEM_EXPANDED;
- if (state & AccessibilityTypes::STATE_HASPOPUP)
+ if (state.HasStateFlag(ui::AX_STATE_HASPOPUP))
msaa_state |= STATE_SYSTEM_HASPOPUP;
- if (state & AccessibilityTypes::STATE_HOTTRACKED)
+ if (state.HasStateFlag(ui::AX_STATE_HOVERED))
msaa_state |= STATE_SYSTEM_HOTTRACKED;
- if (state & AccessibilityTypes::STATE_INVISIBLE)
+ if (state.HasStateFlag(ui::AX_STATE_INVISIBLE))
msaa_state |= STATE_SYSTEM_INVISIBLE;
- if (state & AccessibilityTypes::STATE_LINKED)
+ if (state.HasStateFlag(ui::AX_STATE_LINKED))
msaa_state |= STATE_SYSTEM_LINKED;
- if (state & AccessibilityTypes::STATE_OFFSCREEN)
+ if (state.HasStateFlag(ui::AX_STATE_OFFSCREEN))
msaa_state |= STATE_SYSTEM_OFFSCREEN;
- if (state & AccessibilityTypes::STATE_PRESSED)
+ if (state.HasStateFlag(ui::AX_STATE_PRESSED))
msaa_state |= STATE_SYSTEM_PRESSED;
- if (state & AccessibilityTypes::STATE_PROTECTED)
+ if (state.HasStateFlag(ui::AX_STATE_PROTECTED))
msaa_state |= STATE_SYSTEM_PROTECTED;
- if (state & AccessibilityTypes::STATE_READONLY)
+ if (state.HasStateFlag(ui::AX_STATE_READ_ONLY))
msaa_state |= STATE_SYSTEM_READONLY;
- if (state & AccessibilityTypes::STATE_SELECTED)
+ if (state.HasStateFlag(ui::AX_STATE_SELECTED))
msaa_state |= STATE_SYSTEM_SELECTED;
- if (state & AccessibilityTypes::STATE_FOCUSED)
+ if (state.HasStateFlag(ui::AX_STATE_FOCUSED))
msaa_state |= STATE_SYSTEM_FOCUSED;
- if (state & AccessibilityTypes::STATE_UNAVAILABLE)
+ if (state.HasStateFlag(ui::AX_STATE_DISABLED))
msaa_state |= STATE_SYSTEM_UNAVAILABLE;
return msaa_state;
}
@@ -1339,22 +1398,22 @@ void NativeViewAccessibilityWin::SetState(
msaa_state->lVal |= STATE_SYSTEM_FOCUSED;
// Add on any view-specific states.
- ui::AccessibleViewState view_state;
+ ui::AXViewState view_state;
view->GetAccessibleState(&view_state);
- msaa_state->lVal |= MSAAState(view_state.state);
+ msaa_state->lVal |= MSAAState(view_state);
}
-string16 NativeViewAccessibilityWin::TextForIAccessibleText() {
- ui::AccessibleViewState state;
+base::string16 NativeViewAccessibilityWin::TextForIAccessibleText() {
+ ui::AXViewState state;
view_->GetAccessibleState(&state);
- if (state.role == AccessibilityTypes::ROLE_TEXT)
+ if (state.role == ui::AX_ROLE_TEXT_FIELD)
return state.value;
else
return state.name;
}
void NativeViewAccessibilityWin::HandleSpecialTextOffset(
- const string16& text, LONG* offset) {
+ const base::string16& text, LONG* offset) {
if (*offset == IA2_TEXT_OFFSET_LENGTH) {
*offset = static_cast<LONG>(text.size());
} else if (*offset == IA2_TEXT_OFFSET_CARET) {
@@ -1378,7 +1437,7 @@ ui::TextBoundaryType NativeViewAccessibilityWin::IA2TextBoundaryToTextBoundary(
}
LONG NativeViewAccessibilityWin::FindBoundary(
- const string16& text,
+ const base::string16& text,
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
ui::TextBoundaryDirection direction) {
@@ -1414,4 +1473,32 @@ void NativeViewAccessibilityWin::PopulateChildWidgetVector(
}
}
+void NativeViewAccessibilityWin::AddAlertTarget() {
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ for (size_t i = 0; i < alert_target_view_storage_ids_.size(); ++i) {
+ int view_storage_id = alert_target_view_storage_ids_[i];
+ View* view = view_storage->RetrieveView(view_storage_id);
+ if (view == view_)
+ return;
+ }
+ int view_storage_id = view_storage->CreateStorageID();
+ view_storage->StoreView(view_storage_id, view_);
+ alert_target_view_storage_ids_.push_back(view_storage_id);
+}
+
+void NativeViewAccessibilityWin::RemoveAlertTarget() {
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ size_t i = 0;
+ while (i < alert_target_view_storage_ids_.size()) {
+ int view_storage_id = alert_target_view_storage_ids_[i];
+ View* view = view_storage->RetrieveView(view_storage_id);
+ if (view == NULL || view == view_) {
+ alert_target_view_storage_ids_.erase(
+ alert_target_view_storage_ids_.begin() + i);
+ } else {
+ ++i;
+ }
+ }
+}
+
} // namespace views
diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win.h b/chromium/ui/views/accessibility/native_view_accessibility_win.h
index 83d03dbe5d8..ef593612345 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility_win.h
+++ b/chromium/ui/views/accessibility/native_view_accessibility_win.h
@@ -12,9 +12,10 @@
#include <UIAutomationCore.h>
#include <set>
+#include <vector>
#include "third_party/iaccessible2/ia2_api_all.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/view.h"
@@ -38,7 +39,7 @@ namespace views {
class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
NativeViewAccessibilityWin
: public CComObjectRootEx<CComMultiThreadModel>,
- public IDispatchImpl<IAccessible2, &IID_IAccessible2,
+ public IDispatchImpl<IAccessible2_2, &IID_IAccessible2_2,
&LIBID_IAccessible2Lib>,
public IAccessibleText,
public IServiceProvider,
@@ -47,20 +48,21 @@ NativeViewAccessibilityWin
public NativeViewAccessibility {
public:
BEGIN_COM_MAP(NativeViewAccessibilityWin)
- COM_INTERFACE_ENTRY2(IDispatch, IAccessible2)
- COM_INTERFACE_ENTRY2(IAccessible, IAccessible2)
+ COM_INTERFACE_ENTRY2(IDispatch, IAccessible2_2)
+ COM_INTERFACE_ENTRY(IAccessible)
COM_INTERFACE_ENTRY(IAccessible2)
- COM_INTERFACE_ENTRY(IAccessibleText)
- COM_INTERFACE_ENTRY(IServiceProvider)
+ COM_INTERFACE_ENTRY(IAccessible2_2)
COM_INTERFACE_ENTRY(IAccessibleEx)
+ COM_INTERFACE_ENTRY(IAccessibleText)
COM_INTERFACE_ENTRY(IRawElementProviderSimple)
+ COM_INTERFACE_ENTRY(IServiceProvider)
END_COM_MAP()
virtual ~NativeViewAccessibilityWin();
// NativeViewAccessibility.
virtual void NotifyAccessibilityEvent(
- ui::AccessibilityTypes::Event event_type) OVERRIDE;
+ ui::AXEvent event_type) OVERRIDE;
virtual gfx::NativeViewAccessible GetNativeObject() OVERRIDE;
virtual void Destroy() OVERRIDE;
@@ -145,6 +147,11 @@ NativeViewAccessibilityWin
STDMETHODIMP get_windowHandle(HWND* window_handle);
+ STDMETHODIMP get_relationTargetsOfType(BSTR type,
+ long max_targets,
+ IUnknown ***targets,
+ long *n_targets);
+
//
// IAccessible2 methods not implemented.
//
@@ -152,6 +159,9 @@ NativeViewAccessibilityWin
STDMETHODIMP get_attributes(BSTR* attributes) {
return E_NOTIMPL;
}
+ STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) {
+ return E_NOTIMPL;
+ }
STDMETHODIMP get_indexInParent(LONG* index_in_parent) {
return E_NOTIMPL;
}
@@ -205,6 +215,10 @@ NativeViewAccessibilityWin
STDMETHODIMP get_locale(IA2Locale* locale) {
return E_NOTIMPL;
}
+ STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
+ long* caret_offset) {
+ return E_NOTIMPL;
+ }
//
// IAccessibleText methods.
@@ -337,17 +351,17 @@ NativeViewAccessibilityWin
// Static methods
- // Returns a conversion from the event (as defined in accessibility_types.h)
+ // Returns a conversion from the event (as defined in ax_enums.idl)
// to an MSAA event.
- static int32 MSAAEvent(ui::AccessibilityTypes::Event event);
+ static int32 MSAAEvent(ui::AXEvent event);
- // Returns a conversion from the Role (as defined in accessibility_types.h)
+ // Returns a conversion from the Role (as defined in ax_enums.idl)
// to an MSAA role.
- static int32 MSAARole(ui::AccessibilityTypes::Role role);
+ static int32 MSAARole(ui::AXRole role);
- // Returns a conversion from the State (as defined in accessibility_types.h)
+ // Returns a conversion from the State (as defined in ax_enums.idl)
// to MSAA states set.
- static int32 MSAAState(ui::AccessibilityTypes::State state);
+ static int32 MSAAState(const ui::AXViewState& state);
protected:
NativeViewAccessibilityWin();
@@ -374,11 +388,11 @@ NativeViewAccessibilityWin
void SetState(VARIANT* msaa_state, View* view);
// Return the text to use for IAccessibleText.
- string16 TextForIAccessibleText();
+ base::string16 TextForIAccessibleText();
// If offset is a member of IA2TextSpecialOffsets this function updates the
// value of offset and returns, otherwise offset remains unchanged.
- void HandleSpecialTextOffset(const string16& text, LONG* offset);
+ void HandleSpecialTextOffset(const base::string16& text, LONG* offset);
// Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
@@ -386,7 +400,7 @@ NativeViewAccessibilityWin
// Search forwards (direction == 1) or backwards (direction == -1)
// from the given offset until the given boundary is found, and
// return the offset of that boundary.
- LONG FindBoundary(const string16& text,
+ LONG FindBoundary(const base::string16& text,
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
ui::TextBoundaryDirection direction);
@@ -396,6 +410,12 @@ NativeViewAccessibilityWin
// NativeViewHost.
void PopulateChildWidgetVector(std::vector<Widget*>* child_widgets);
+ // Adds this view to alert_target_view_storage_ids_.
+ void AddAlertTarget();
+
+ // Removes this view from alert_target_view_storage_ids_.
+ void RemoveAlertTarget();
+
// Give CComObject access to the class constructor.
template <class Base> friend class CComObject;
@@ -418,6 +438,11 @@ NativeViewAccessibilityWin
// Next index into |view_storage_ids_| to use.
static int next_view_storage_id_index_;
+ // A vector of view storage ids of views that have been the target of
+ // an alert event, in order to provide an api to quickly identify all
+ // open alerts.
+ static std::vector<int> alert_target_view_storage_ids_;
+
DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityWin);
};
diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc b/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc
index 5bd5bed7b91..3edab8e258e 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc
+++ b/chromium/ui/views/accessibility/native_view_accessibility_win_unittest.cc
@@ -7,14 +7,33 @@
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"
+#include "third_party/iaccessible2/ia2_api_all.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/test/views_test_base.h"
+using base::win::ScopedBstr;
+using base::win::ScopedComPtr;
+using base::win::ScopedVariant;
+
namespace views {
namespace test {
-typedef ViewsTestBase NativeViewAcccessibilityWinTest;
+class NativeViewAcccessibilityWinTest : public ViewsTestBase {
+ public:
+ NativeViewAcccessibilityWinTest() {}
+ virtual ~NativeViewAcccessibilityWinTest() {}
+
+ protected:
+ void GetIAccessible2InterfaceForView(View* view, IAccessible2_2** result) {
+ ScopedComPtr<IAccessible> view_accessible(
+ view->GetNativeViewAccessible());
+ ScopedComPtr<IServiceProvider> service_provider;
+ ASSERT_EQ(S_OK, view_accessible.QueryInterface(service_provider.Receive()));
+ ASSERT_EQ(S_OK,
+ service_provider->QueryService(IID_IAccessible2_2, result));
+ }
+};
TEST_F(NativeViewAcccessibilityWinTest, TextfieldAccessibility) {
Widget widget;
@@ -31,32 +50,32 @@ TEST_F(NativeViewAcccessibilityWinTest, TextfieldAccessibility) {
textfield->SetText(L"Value");
content->AddChildView(textfield);
- base::win::ScopedComPtr<IAccessible> content_accessible(
+ ScopedComPtr<IAccessible> content_accessible(
content->GetNativeViewAccessible());
LONG child_count = 0;
ASSERT_EQ(S_OK, content_accessible->get_accChildCount(&child_count));
ASSERT_EQ(1L, child_count);
- base::win::ScopedComPtr<IDispatch> textfield_dispatch;
- base::win::ScopedComPtr<IAccessible> textfield_accessible;
- base::win::ScopedVariant child_index(1);
+ ScopedComPtr<IDispatch> textfield_dispatch;
+ ScopedComPtr<IAccessible> textfield_accessible;
+ ScopedVariant child_index(1);
ASSERT_EQ(S_OK, content_accessible->get_accChild(
child_index, textfield_dispatch.Receive()));
ASSERT_EQ(S_OK, textfield_dispatch.QueryInterface(
textfield_accessible.Receive()));
- base::win::ScopedBstr name;
- base::win::ScopedVariant childid_self(CHILDID_SELF);
+ ScopedBstr name;
+ ScopedVariant childid_self(CHILDID_SELF);
ASSERT_EQ(S_OK, textfield_accessible->get_accName(
childid_self, name.Receive()));
ASSERT_STREQ(L"Name", name);
- base::win::ScopedBstr value;
+ ScopedBstr value;
ASSERT_EQ(S_OK, textfield_accessible->get_accValue(
childid_self, value.Receive()));
ASSERT_STREQ(L"Value", value);
- base::win::ScopedBstr new_value(L"New value");
+ ScopedBstr new_value(L"New value");
ASSERT_EQ(S_OK, textfield_accessible->put_accValue(childid_self, new_value));
ASSERT_STREQ(L"New value", textfield->text().c_str());
@@ -81,17 +100,16 @@ TEST_F(NativeViewAcccessibilityWinTest, UnattachedWebView) {
content->AddChildView(web_view);
NativeViewAccessibility::RegisterWebView(web_view);
- base::win::ScopedComPtr<IAccessible> web_view_accessible(
+ ScopedComPtr<IAccessible> web_view_accessible(
web_view->GetNativeViewAccessible());
- base::win::ScopedComPtr<IDispatch> result_dispatch;
- base::win::ScopedVariant child_index(-999);
+ ScopedComPtr<IDispatch> result_dispatch;
+ ScopedVariant child_index(-999);
ASSERT_EQ(E_FAIL, web_view_accessible->get_accChild(
child_index, result_dispatch.Receive()));
NativeViewAccessibility::UnregisterWebView(web_view);
}
-#if defined(USE_AURA)
TEST_F(NativeViewAcccessibilityWinTest, AuraOwnedWidgets) {
Widget widget;
Widget::InitParams init_params =
@@ -99,7 +117,7 @@ TEST_F(NativeViewAcccessibilityWinTest, AuraOwnedWidgets) {
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(init_params);
- base::win::ScopedComPtr<IAccessible> root_view_accessible(
+ ScopedComPtr<IAccessible> root_view_accessible(
widget.GetRootView()->GetNativeViewAccessible());
LONG child_count = 0;
@@ -110,7 +128,6 @@ TEST_F(NativeViewAcccessibilityWinTest, AuraOwnedWidgets) {
Widget::InitParams owned_init_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
owned_init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- owned_init_params.child = false;
owned_init_params.parent = widget.GetNativeView();
owned_widget.Init(owned_init_params);
owned_widget.Show();
@@ -118,7 +135,70 @@ TEST_F(NativeViewAcccessibilityWinTest, AuraOwnedWidgets) {
ASSERT_EQ(S_OK, root_view_accessible->get_accChildCount(&child_count));
ASSERT_EQ(2L, child_count);
}
-#endif
+
+TEST_F(NativeViewAcccessibilityWinTest, RetrieveAllAlerts) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(init_params);
+
+ View* content = new View;
+ widget.SetContentsView(content);
+
+ View* infobar = new View;
+ content->AddChildView(infobar);
+
+ View* infobar2 = new View;
+ content->AddChildView(infobar2);
+
+ View* root_view = content->parent();
+ ASSERT_EQ(NULL, root_view->parent());
+
+ ScopedComPtr<IAccessible2_2> root_view_accessible;
+ GetIAccessible2InterfaceForView(root_view, root_view_accessible.Receive());
+
+ ScopedComPtr<IAccessible2_2> infobar_accessible;
+ GetIAccessible2InterfaceForView(infobar, infobar_accessible.Receive());
+
+ ScopedComPtr<IAccessible2_2> infobar2_accessible;
+ GetIAccessible2InterfaceForView(infobar2, infobar2_accessible.Receive());
+
+ // Initially, there are no alerts
+ ScopedBstr alerts_bstr(L"alerts");
+ IUnknown** targets;
+ long n_targets;
+ ASSERT_EQ(S_FALSE, root_view_accessible->get_relationTargetsOfType(
+ alerts_bstr, 0, &targets, &n_targets));
+ ASSERT_EQ(0, n_targets);
+
+ // Fire alert events on the infobars.
+ infobar->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
+ infobar2->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
+
+ // Now calling get_relationTargetsOfType should retrieve the alerts.
+ ASSERT_EQ(S_OK, root_view_accessible->get_relationTargetsOfType(
+ alerts_bstr, 0, &targets, &n_targets));
+ ASSERT_EQ(2, n_targets);
+ ASSERT_TRUE(infobar_accessible.IsSameObject(targets[0]));
+ ASSERT_TRUE(infobar2_accessible.IsSameObject(targets[1]));
+ CoTaskMemFree(targets);
+
+ // If we set max_targets to 1, we should only get the first one.
+ ASSERT_EQ(S_OK, root_view_accessible->get_relationTargetsOfType(
+ alerts_bstr, 1, &targets, &n_targets));
+ ASSERT_EQ(1, n_targets);
+ ASSERT_TRUE(infobar_accessible.IsSameObject(targets[0]));
+ CoTaskMemFree(targets);
+
+ // If we delete the first view, we should only get the second one now.
+ delete infobar;
+ ASSERT_EQ(S_OK, root_view_accessible->get_relationTargetsOfType(
+ alerts_bstr, 0, &targets, &n_targets));
+ ASSERT_EQ(1, n_targets);
+ ASSERT_TRUE(infobar2_accessible.IsSameObject(targets[0]));
+ CoTaskMemFree(targets);
+}
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/accessible_pane_view.cc b/chromium/ui/views/accessible_pane_view.cc
index 35ca7bf6e83..a0bbd5665fc 100644
--- a/chromium/ui/views/accessible_pane_view.cc
+++ b/chromium/ui/views/accessible_pane_view.cc
@@ -5,7 +5,7 @@
#include "ui/views/accessible_pane_view.h"
#include "base/message_loop/message_loop.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/focus/view_storage.h"
#include "ui/views/widget/widget.h"
@@ -207,8 +207,8 @@ void AccessiblePaneView::SetVisible(bool flag) {
View::SetVisible(flag);
}
-void AccessiblePaneView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_PANE;
+void AccessiblePaneView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_PANE;
}
void AccessiblePaneView::RequestFocus() {
diff --git a/chromium/ui/views/accessible_pane_view.h b/chromium/ui/views/accessible_pane_view.h
index b3ab9b770e1..cde84a75243 100644
--- a/chromium/ui/views/accessible_pane_view.h
+++ b/chromium/ui/views/accessible_pane_view.h
@@ -44,7 +44,7 @@ class VIEWS_EXPORT AccessiblePaneView : public View,
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator)
OVERRIDE;
virtual void SetVisible(bool flag) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual void RequestFocus() OVERRIDE;
// Overridden from FocusChangeListener:
diff --git a/chromium/ui/views/accessible_pane_view_unittest.cc b/chromium/ui/views/accessible_pane_view_unittest.cc
index 02778d6beb5..4468f2ffe3e 100644
--- a/chromium/ui/views/accessible_pane_view_unittest.cc
+++ b/chromium/ui/views/accessible_pane_view_unittest.cc
@@ -57,7 +57,7 @@ void TestBarView::ButtonPressed(Button* sender, const ui::Event& event) {
void TestBarView::Init() {
SetLayoutManager(new FillLayout());
- string16 label;
+ base::string16 label;
child_button_.reset(new LabelButton(this, label));
AddChildView(child_button_.get());
second_child_button_.reset(new LabelButton(this, label));
@@ -101,7 +101,6 @@ TEST_F(AccessiblePaneViewTest, SimpleSetPaneFocus) {
// This test will not work properly in Windows because it uses ::GetNextWindow
// on deactivate which is rather unpredictable where the focus will land.
-#if !defined(OS_WIN)||defined(USE_AURA)
TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) {
View* test_view_main = new View();
scoped_ptr<Widget> widget_main(new Widget());
@@ -145,7 +144,6 @@ TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) {
widget_main->CloseNow();
widget_main.reset();
}
-#endif // !defined(OS_WIN)||defined(USE_AURA)
TEST_F(AccessiblePaneViewTest, TwoSetPaneFocus) {
TestBarView* test_view = new TestBarView();
diff --git a/chromium/ui/views/animation/bounds_animator.cc b/chromium/ui/views/animation/bounds_animator.cc
index 839294ff74c..ba9412722e0 100644
--- a/chromium/ui/views/animation/bounds_animator.cc
+++ b/chromium/ui/views/animation/bounds_animator.cc
@@ -110,13 +110,12 @@ const SlideAnimation* BoundsAnimator::GetAnimationForView(View* view) {
return !IsAnimating(view) ? NULL : data_[view].animation;
}
-void BoundsAnimator::SetAnimationDelegate(View* view,
- AnimationDelegate* delegate,
- bool delete_when_done) {
+void BoundsAnimator::SetAnimationDelegate(
+ View* view,
+ scoped_ptr<AnimationDelegate> delegate) {
DCHECK(IsAnimating(view));
- data_[view].delegate = delegate;
- data_[view].delete_delegate_when_done = delete_when_done;
+ data_[view].delegate = delegate.release();
}
void BoundsAnimator::StopAnimatingView(View* view) {
@@ -177,10 +176,8 @@ void BoundsAnimator::CleanupData(bool send_cancel, Data* data, View* view) {
if (send_cancel && data->delegate)
data->delegate->AnimationCanceled(data->animation);
- if (data->delete_delegate_when_done) {
- delete static_cast<OwnedAnimationDelegate*>(data->delegate);
- data->delegate = NULL;
- }
+ delete data->delegate;
+ data->delegate = NULL;
if (data->animation) {
data->animation->set_delegate(NULL);
diff --git a/chromium/ui/views/animation/bounds_animator.h b/chromium/ui/views/animation/bounds_animator.h
index 1688dd56235..1a88cdf0575 100644
--- a/chromium/ui/views/animation/bounds_animator.h
+++ b/chromium/ui/views/animation/bounds_animator.h
@@ -38,13 +38,6 @@ class View;
class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
public gfx::AnimationContainerObserver {
public:
- // If |delete_when_done| is set to true in |SetAnimationDelegate| the
- // |AnimationDelegate| must subclass this class.
- class OwnedAnimationDelegate : public gfx::AnimationDelegate {
- public:
- virtual ~OwnedAnimationDelegate() {}
- };
-
explicit BoundsAnimator(View* view);
virtual ~BoundsAnimator();
@@ -74,12 +67,9 @@ class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
// Stops animating the specified view.
void StopAnimatingView(View* view);
- // Sets the delegate for the animation created for the specified view. If
- // |delete_when_done| is true the |delegate| is deleted when done and
- // |delegate| must subclass OwnedAnimationDelegate.
+ // Sets the delegate for the animation for the specified view.
void SetAnimationDelegate(View* view,
- gfx::AnimationDelegate* delegate,
- bool delete_when_done);
+ scoped_ptr<gfx::AnimationDelegate> delegate);
// Returns true if BoundsAnimator is animating the bounds of |view|.
bool IsAnimating(View* view) const;
@@ -95,6 +85,9 @@ class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
// milliseconds.
void SetAnimationDuration(int duration_ms);
+ // Gets the currently used animation duration.
+ int GetAnimationDuration() const { return animation_duration_ms_; }
+
// Sets the tween type for new animations. Default is EASE_OUT.
void set_tween_type(gfx::Tween::Type type) { tween_type_ = type; }
@@ -108,13 +101,7 @@ class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
private:
// Tracks data about the view being animated.
struct Data {
- Data()
- : delete_delegate_when_done(false),
- animation(NULL),
- delegate(NULL) {}
-
- // If true the delegate is deleted when done.
- bool delete_delegate_when_done;
+ Data() : animation(NULL), delegate(NULL) {}
// The initial bounds.
gfx::Rect start_bounds;
@@ -125,7 +112,7 @@ class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
// The animation. We own this.
gfx::SlideAnimation* animation;
- // Additional delegate for the animation, may be null.
+ // Delegate for the animation, may be null. We own this.
gfx::AnimationDelegate* delegate;
};
diff --git a/chromium/ui/views/animation/bounds_animator_unittest.cc b/chromium/ui/views/animation/bounds_animator_unittest.cc
index 0928fe665b0..6294d8a5912 100644
--- a/chromium/ui/views/animation/bounds_animator_unittest.cc
+++ b/chromium/ui/views/animation/bounds_animator_unittest.cc
@@ -32,7 +32,7 @@ class TestBoundsAnimator : public BoundsAnimator {
DISALLOW_COPY_AND_ASSIGN(TestBoundsAnimator);
};
-class OwnedDelegate : public BoundsAnimator::OwnedAnimationDelegate {
+class OwnedDelegate : public gfx::AnimationDelegate {
public:
OwnedDelegate() {}
@@ -110,12 +110,12 @@ class BoundsAnimatorTest : public testing::Test {
// Checks animate view to.
TEST_F(BoundsAnimatorTest, AnimateViewTo) {
- TestAnimationDelegate delegate;
gfx::Rect initial_bounds(0, 0, 10, 10);
child()->SetBoundsRect(initial_bounds);
gfx::Rect target_bounds(10, 10, 20, 20);
animator()->AnimateViewTo(child(), target_bounds);
- animator()->SetAnimationDelegate(child(), &delegate, false);
+ animator()->SetAnimationDelegate(
+ child(), scoped_ptr<gfx::AnimationDelegate>(new TestAnimationDelegate()));
// The animator should be animating now.
EXPECT_TRUE(animator()->IsAnimating());
@@ -136,7 +136,8 @@ TEST_F(BoundsAnimatorTest, AnimateViewTo) {
// Make sure an AnimationDelegate is deleted when canceled.
TEST_F(BoundsAnimatorTest, DeleteDelegateOnCancel) {
animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
- animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
+ animator()->SetAnimationDelegate(
+ child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate()));
animator()->Cancel();
@@ -152,7 +153,8 @@ TEST_F(BoundsAnimatorTest, DeleteDelegateOnCancel) {
// scheduled.
TEST_F(BoundsAnimatorTest, DeleteDelegateOnNewAnimate) {
animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
- animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
+ animator()->SetAnimationDelegate(
+ child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate()));
animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
@@ -166,7 +168,8 @@ TEST_F(BoundsAnimatorTest, StopAnimating) {
scoped_ptr<OwnedDelegate> delegate(new OwnedDelegate());
animator()->AnimateViewTo(child(), gfx::Rect(0, 0, 10, 10));
- animator()->SetAnimationDelegate(child(), new OwnedDelegate(), true);
+ animator()->SetAnimationDelegate(
+ child(), scoped_ptr<gfx::AnimationDelegate>(new OwnedDelegate()));
animator()->StopAnimatingView(child());
diff --git a/chromium/ui/views/background.cc b/chromium/ui/views/background.cc
index b37318dc2b4..bb2ddd0928e 100644
--- a/chromium/ui/views/background.cc
+++ b/chromium/ui/views/background.cc
@@ -94,12 +94,7 @@ Background* Background::CreateSolidBackground(SkColor color) {
//static
Background* Background::CreateStandardPanelBackground() {
// TODO(beng): Should be in NativeTheme.
-#if defined(USE_AURA)
return CreateSolidBackground(SK_ColorWHITE);
-#else
- return CreateVerticalGradientBackground(SkColorSetRGB(246, 250, 255),
- SkColorSetRGB(219, 235, 255));
-#endif
}
//static
diff --git a/chromium/ui/views/border.cc b/chromium/ui/views/border.cc
index f347c2a8369..0ff340642e0 100644
--- a/chromium/ui/views/border.cc
+++ b/chromium/ui/views/border.cc
@@ -133,36 +133,37 @@ Border::~Border() {
}
// static
-Border* Border::CreateSolidBorder(int thickness, SkColor color) {
- return new SolidBorder(thickness, color);
+scoped_ptr<Border> Border::NullBorder() {
+ return scoped_ptr<Border>();
}
// static
-Border* Border::CreateEmptyBorder(int top, int left, int bottom, int right) {
- return new EmptyBorder(top, left, bottom, right);
+scoped_ptr<Border> Border::CreateSolidBorder(int thickness, SkColor color) {
+ return scoped_ptr<Border>(new SolidBorder(thickness, color));
}
// static
-Border* Border::CreateSolidSidedBorder(int top,
- int left,
- int bottom,
- int right,
- SkColor color) {
- return new SidedSolidBorder(top, left, bottom, right, color);
+scoped_ptr<Border> Border::CreateEmptyBorder(int top,
+ int left,
+ int bottom,
+ int right) {
+ return scoped_ptr<Border>(new EmptyBorder(top, left, bottom, right));
}
// static
-Border* Border::CreateBorderPainter(Painter* painter,
- const gfx::Insets& insets) {
- return new BorderPainter(painter, insets);
+scoped_ptr<Border> Border::CreateSolidSidedBorder(int top,
+ int left,
+ int bottom,
+ int right,
+ SkColor color) {
+ return scoped_ptr<Border>(
+ new SidedSolidBorder(top, left, bottom, right, color));
}
-TextButtonBorder* Border::AsTextButtonBorder() {
- return NULL;
-}
-
-const TextButtonBorder* Border::AsTextButtonBorder() const {
- return NULL;
+// static
+scoped_ptr<Border> Border::CreateBorderPainter(Painter* painter,
+ const gfx::Insets& insets) {
+ return scoped_ptr<Border>(new BorderPainter(painter, insets));
}
} // namespace views
diff --git a/chromium/ui/views/border.h b/chromium/ui/views/border.h
index 2e9c56bf4bf..d2657c60c13 100644
--- a/chromium/ui/views/border.h
+++ b/chromium/ui/views/border.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_BORDER_H_
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/insets.h"
#include "ui/views/views_export.h"
@@ -26,7 +27,7 @@ class View;
//
// The border class is used to display a border around a view.
// To set a border on a view, just call SetBorder on the view, for example:
-// view->set_border(Border::CreateSolidBorder(1, SkColorSetRGB(25, 25, 112));
+// view->SetBorder(Border::CreateSolidBorder(1, SkColorSetRGB(25, 25, 112));
// Once set on a view, the border is owned by the view.
//
// IMPORTANT NOTE: not all views support borders at this point. In order to
@@ -36,34 +37,38 @@ class View;
//
////////////////////////////////////////////////////////////////////////////////
-class TextButtonBorder;
-
class VIEWS_EXPORT Border {
public:
Border();
virtual ~Border();
+ // Convenience for creating a scoped_ptr with no Border.
+ static scoped_ptr<Border> NullBorder();
+
// Creates a border that is a simple line of the specified thickness and
// color.
- static Border* CreateSolidBorder(int thickness, SkColor color);
+ static scoped_ptr<Border> CreateSolidBorder(int thickness, SkColor color);
// Creates a border for reserving space. The returned border does not
// paint anything.
- static Border* CreateEmptyBorder(int top, int left, int bottom, int right);
+ static scoped_ptr<Border> CreateEmptyBorder(int top,
+ int left,
+ int bottom,
+ int right);
// Creates a border of the specified color, and specified thickness on each
// side.
- static Border* CreateSolidSidedBorder(int top,
- int left,
- int bottom,
- int right,
- SkColor color);
+ static scoped_ptr<Border> CreateSolidSidedBorder(int top,
+ int left,
+ int bottom,
+ int right,
+ SkColor color);
// Creates a Border from the specified Painter. The border owns the painter,
// thus the painter is deleted when the Border is deleted.
// |insets| define size of an area allocated for a Border.
- static Border* CreateBorderPainter(Painter* painter,
- const gfx::Insets& insets);
+ static scoped_ptr<Border> CreateBorderPainter(Painter* painter,
+ const gfx::Insets& insets);
// Renders the border for the specified view.
virtual void Paint(const View& view, gfx::Canvas* canvas) = 0;
@@ -79,10 +84,6 @@ class VIEWS_EXPORT Border {
// content laid out relative to these images.
virtual gfx::Size GetMinimumSize() const = 0;
- // Manual RTTI for text buttons.
- virtual TextButtonBorder* AsTextButtonBorder();
- virtual const TextButtonBorder* AsTextButtonBorder() const;
-
private:
DISALLOW_COPY_AND_ASSIGN(Border);
};
diff --git a/chromium/ui/views/bubble/bubble_border.cc b/chromium/ui/views/bubble/bubble_border.cc
index aa9064ee970..03b422aefb2 100644
--- a/chromium/ui/views/bubble/bubble_border.cc
+++ b/chromium/ui/views/bubble/bubble_border.cc
@@ -156,7 +156,8 @@ BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color)
arrow_paint_type_(PAINT_NORMAL),
alignment_(ALIGN_ARROW_TO_MID_ANCHOR),
shadow_(shadow),
- background_color_(color) {
+ background_color_(color),
+ use_theme_background_color_(false) {
DCHECK(shadow < SHADOW_COUNT);
images_ = GetBorderImages(shadow);
}
diff --git a/chromium/ui/views/bubble/bubble_border.h b/chromium/ui/views/bubble/bubble_border.h
index 4fb961e6fb4..15f0f85f60d 100644
--- a/chromium/ui/views/bubble/bubble_border.h
+++ b/chromium/ui/views/bubble/bubble_border.h
@@ -136,6 +136,13 @@ class VIEWS_EXPORT BubbleBorder : public Border {
void set_background_color(SkColor color) { background_color_ = color; }
SkColor background_color() const { return background_color_; }
+ // If true, the background color should be determined by the host's
+ // NativeTheme.
+ void set_use_theme_background_color(bool use_theme_background_color) {
+ use_theme_background_color_ = use_theme_background_color;
+ }
+ bool use_theme_background_color() { return use_theme_background_color_; }
+
// Sets a desired pixel distance between the arrow tip and the outside edge of
// the neighboring border image. For example: |----offset----|
// '(' represents shadow around the '{' edge: ((({ ^ })))
@@ -178,6 +185,7 @@ class VIEWS_EXPORT BubbleBorder : public Border {
Shadow shadow_;
internal::BorderImages* images_;
SkColor background_color_;
+ bool use_theme_background_color_;
DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
};
diff --git a/chromium/ui/views/bubble/bubble_delegate.cc b/chromium/ui/views/bubble/bubble_delegate.cc
index dbd0cae85fe..0eab071ad0c 100644
--- a/chromium/ui/views/bubble/bubble_delegate.cc
+++ b/chromium/ui/views/bubble/bubble_delegate.cc
@@ -4,8 +4,8 @@
#include "ui/views/bubble/bubble_delegate.h"
-#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/gfx/animation/slide_animation.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/rect.h"
#include "ui/native_theme/native_theme.h"
@@ -18,9 +18,6 @@
#include "ui/base/win/shell.h"
#endif
-// The duration of the fade animation in milliseconds.
-static const int kHideFadeDurationMS = 200;
-
// The defaut margin between the content and the inside border, in pixels.
static const int kDefaultMargin = 6;
@@ -39,7 +36,8 @@ Widget* CreateBubbleWidget(BubbleDelegateView* bubble) {
bubble_params.parent = bubble->parent_window();
else if (bubble->anchor_widget())
bubble_params.parent = bubble->anchor_widget()->GetNativeView();
- bubble_params.can_activate = bubble->CanActivate();
+ bubble_params.activatable = bubble->CanActivate() ?
+ Widget::InitParams::ACTIVATABLE_YES : Widget::InitParams::ACTIVATABLE_NO;
bubble->OnBeforeBubbleWidgetInit(&bubble_params, bubble_widget);
bubble_widget->Init(bubble_params);
return bubble_widget;
@@ -52,12 +50,10 @@ BubbleDelegateView::BubbleDelegateView()
close_on_deactivate_(true),
anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()),
anchor_widget_(NULL),
- move_with_anchor_(false),
arrow_(BubbleBorder::TOP_LEFT),
shadow_(BubbleBorder::SMALL_SHADOW),
color_explicitly_set_(false),
margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin),
- original_opacity_(255),
use_focusless_(false),
accept_events_(true),
border_accepts_events_(true),
@@ -74,12 +70,10 @@ BubbleDelegateView::BubbleDelegateView(
close_on_deactivate_(true),
anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()),
anchor_widget_(NULL),
- move_with_anchor_(false),
arrow_(arrow),
shadow_(BubbleBorder::SMALL_SHADOW),
color_explicitly_set_(false),
margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin),
- original_opacity_(255),
use_focusless_(false),
accept_events_(true),
border_accepts_events_(true),
@@ -91,6 +85,8 @@ BubbleDelegateView::BubbleDelegateView(
}
BubbleDelegateView::~BubbleDelegateView() {
+ if (GetWidget())
+ GetWidget()->RemoveObserver(this);
SetLayoutManager(NULL);
SetAnchorView(NULL);
}
@@ -102,11 +98,14 @@ Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate) {
bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView());
Widget* bubble_widget = CreateBubbleWidget(bubble_delegate);
-#if defined(OS_WIN) && defined(USE_AURA)
+#if defined(OS_WIN)
// If glass is enabled, the bubble is allowed to extend outside the bounds of
// the parent frame and let DWM handle compositing. If not, then we don't
// want to allow the bubble to extend the frame because it will be clipped.
bubble_delegate->set_adjust_if_offscreen(ui::win::IsAeroGlassEnabled());
+#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Linux clips bubble windows that extend outside their parent window bounds.
+ bubble_delegate->set_adjust_if_offscreen(false);
#endif
bubble_delegate->SizeToContents();
@@ -133,15 +132,19 @@ View* BubbleDelegateView::GetContentsView() {
NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView(
Widget* widget) {
BubbleFrameView* frame = new BubbleFrameView(margins());
+ // Note: In CreateBubble, the call to SizeToContents() will cause
+ // the relayout that this call requires.
+ frame->SetTitleFontList(GetTitleFontList());
BubbleBorder::Arrow adjusted_arrow = arrow();
if (base::i18n::IsRTL())
adjusted_arrow = BubbleBorder::horizontal_mirror(adjusted_arrow);
- frame->SetBubbleBorder(new BubbleBorder(adjusted_arrow, shadow(), color()));
+ frame->SetBubbleBorder(scoped_ptr<BubbleBorder>(
+ new BubbleBorder(adjusted_arrow, shadow(), color())));
return frame;
}
-void BubbleDelegateView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_DIALOG;
+void BubbleDelegateView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_DIALOG;
}
void BubbleDelegateView::OnWidgetDestroying(Widget* widget) {
@@ -174,19 +177,15 @@ void BubbleDelegateView::OnWidgetActivationChanged(Widget* widget,
void BubbleDelegateView::OnWidgetBoundsChanged(Widget* widget,
const gfx::Rect& new_bounds) {
- if (anchor_widget() == widget) {
- if (move_with_anchor())
- SizeToContents();
- else
- GetWidget()->Close();
- }
+ if (anchor_widget() == widget)
+ SizeToContents();
}
View* BubbleDelegateView::GetAnchorView() const {
return ViewStorage::GetInstance()->RetrieveView(anchor_view_storage_id_);
}
-gfx::Rect BubbleDelegateView::GetAnchorRect() {
+gfx::Rect BubbleDelegateView::GetAnchorRect() const {
if (!GetAnchorView())
return anchor_rect_;
@@ -199,36 +198,6 @@ void BubbleDelegateView::OnBeforeBubbleWidgetInit(Widget::InitParams* params,
Widget* widget) const {
}
-void BubbleDelegateView::StartFade(bool fade_in) {
-#if defined(USE_AURA)
- // Use AURA's window layer animation instead of fading. This ensures that
- // hosts which rely on the layer animation callbacks to close the window
- // work correctly.
- if (fade_in)
- GetWidget()->Show();
- else
- GetWidget()->Close();
-#else
- fade_animation_.reset(new gfx::SlideAnimation(this));
- fade_animation_->SetSlideDuration(GetFadeDuration());
- fade_animation_->Reset(fade_in ? 0.0 : 1.0);
- if (fade_in) {
- original_opacity_ = 0;
- GetWidget()->SetOpacity(original_opacity_);
- GetWidget()->Show();
- fade_animation_->Show();
- } else {
- original_opacity_ = 255;
- fade_animation_->Hide();
- }
-#endif
-}
-
-void BubbleDelegateView::ResetFade() {
- fade_animation_.reset();
- GetWidget()->SetOpacity(original_opacity_);
-}
-
void BubbleDelegateView::SetAlignment(BubbleBorder::BubbleAlignment alignment) {
GetBubbleFrameView()->bubble_border()->set_alignment(alignment);
SizeToContents();
@@ -248,8 +217,6 @@ bool BubbleDelegateView::AcceleratorPressed(
const ui::Accelerator& accelerator) {
if (!close_on_esc() || accelerator.key_code() != ui::VKEY_ESCAPE)
return false;
- if (fade_animation_.get())
- fade_animation_->Reset();
GetWidget()->Close();
return true;
}
@@ -258,22 +225,6 @@ void BubbleDelegateView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
UpdateColorsFromTheme(theme);
}
-void BubbleDelegateView::AnimationEnded(const gfx::Animation* animation) {
- if (animation != fade_animation_.get())
- return;
- bool closed = fade_animation_->GetCurrentValue() == 0;
- fade_animation_->Reset();
- if (closed)
- GetWidget()->Close();
-}
-
-void BubbleDelegateView::AnimationProgressed(const gfx::Animation* animation) {
- if (animation != fade_animation_.get())
- return;
- DCHECK(fade_animation_->is_animating());
- GetWidget()->SetOpacity(fade_animation_->GetCurrentValue() * 255);
-}
-
void BubbleDelegateView::Init() {}
void BubbleDelegateView::SetAnchorView(View* anchor_view) {
@@ -298,7 +249,11 @@ void BubbleDelegateView::SetAnchorView(View* anchor_view) {
if (anchor_view)
view_storage->StoreView(anchor_view_storage_id_, anchor_view);
- if (GetWidget())
+ // Do not update anchoring for NULL views; this could indicate that our
+ // NativeWindow is being destroyed, so it would be dangerous for us to update
+ // our anchor bounds at that point. (It's safe to skip this, since if we were
+ // to update the bounds when |anchor_view| is NULL, the bubble won't move.)
+ if (anchor_view && GetWidget())
OnAnchorBoundsChanged();
}
@@ -321,19 +276,20 @@ BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const {
gfx::Rect BubbleDelegateView::GetBubbleBounds() {
// The argument rect has its origin at the bubble's arrow anchor point;
// its size is the preferred size of the bubble's client view (this view).
+ bool anchor_minimized = anchor_widget() && anchor_widget()->IsMinimized();
return GetBubbleFrameView()->GetUpdatedWindowBounds(GetAnchorRect(),
- GetPreferredSize(), adjust_if_offscreen_);
+ GetPreferredSize(), adjust_if_offscreen_ && !anchor_minimized);
}
-int BubbleDelegateView::GetFadeDuration() {
- return kHideFadeDurationMS;
+const gfx::FontList& BubbleDelegateView::GetTitleFontList() const {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return rb.GetFontList(ui::ResourceBundle::MediumFont);
}
+
void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
- if (!color_explicitly_set_) {
- color_ = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_WindowBackground);
- }
+ if (!color_explicitly_set_)
+ color_ = theme->GetSystemColor(ui::NativeTheme::kColorId_DialogBackground);
set_background(Background::CreateSolidBackground(color()));
BubbleFrameView* frame_view = GetBubbleFrameView();
if (frame_view)
@@ -341,9 +297,12 @@ void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
}
void BubbleDelegateView::HandleVisibilityChanged(Widget* widget, bool visible) {
- if (widget == GetWidget() && visible && anchor_widget() &&
+ if (widget == GetWidget() && anchor_widget() &&
anchor_widget()->GetTopLevelWidget()) {
- anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering();
+ if (visible)
+ anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering();
+ else
+ anchor_widget()->GetTopLevelWidget()->EnableInactiveRendering();
}
}
diff --git a/chromium/ui/views/bubble/bubble_delegate.h b/chromium/ui/views/bubble/bubble_delegate.h
index 4bf8ff68c73..e61111b096d 100644
--- a/chromium/ui/views/bubble/bubble_delegate.h
+++ b/chromium/ui/views/bubble/bubble_delegate.h
@@ -6,15 +6,14 @@
#define UI_VIEWS_BUBBLE_BUBBLE_DELEGATE_H_
#include "base/gtest_prod_util.h"
-#include "ui/gfx/animation/animation_delegate.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
namespace gfx {
+class FontList;
class Rect;
-class SlideAnimation;
}
namespace views {
@@ -24,7 +23,6 @@ class BubbleFrameView;
// BubbleDelegateView creates frame and client views for bubble Widgets.
// BubbleDelegateView itself is the client's contents view.
class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
- public gfx::AnimationDelegate,
public WidgetObserver {
public:
BubbleDelegateView();
@@ -40,7 +38,7 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
virtual bool ShouldShowCloseButton() const OVERRIDE;
virtual View* GetContentsView() OVERRIDE;
virtual NonClientFrameView* CreateNonClientFrameView(Widget* widget) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// WidgetObserver overrides:
virtual void OnWidgetDestroying(Widget* widget) OVERRIDE;
@@ -97,23 +95,13 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
bool adjust_if_offscreen() const { return adjust_if_offscreen_; }
void set_adjust_if_offscreen(bool adjust) { adjust_if_offscreen_ = adjust; }
- bool move_with_anchor() const { return move_with_anchor_; }
- void set_move_with_anchor(bool move) { move_with_anchor_ = move; }
-
// Get the arrow's anchor rect in screen space.
- virtual gfx::Rect GetAnchorRect();
+ virtual gfx::Rect GetAnchorRect() const;
// Allows delegates to provide custom parameters before widget initialization.
virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
Widget* widget) const;
- // Fade the bubble in or out by animation Widget transparency.
- // Fade-in calls Widget::Show; fade-out calls Widget::Close upon completion.
- void StartFade(bool fade_in);
-
- // Restores bubble opacity to its value before StartFade() was called.
- void ResetFade();
-
// Sets the bubble alignment relative to the anchor. This may only be called
// after calling CreateBubble.
void SetAlignment(BubbleBorder::BubbleAlignment alignment);
@@ -130,17 +118,14 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
// Get bubble bounds from the anchor rect and client view's preferred size.
virtual gfx::Rect GetBubbleBounds();
- // Returns the duration in milliseconds for the fade animation.
- virtual int GetFadeDuration();
+ // Return a FontList to use for the title of the bubble.
+ // (The default is MediumFont).
+ virtual const gfx::FontList& GetTitleFontList() const;
// View overrides:
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
- // gfx::AnimationDelegate overrides:
- virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
- virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
-
// Perform view initialization on the contents for bubble sizing.
virtual void Init();
@@ -158,6 +143,7 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
private:
friend class BubbleBorderDelegate;
+ friend class BubbleWindowTargeter;
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate);
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest);
@@ -168,9 +154,6 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
// Handles widget visibility changes.
void HandleVisibilityChanged(Widget* widget, bool visible);
- // Fade animation for bubble.
- scoped_ptr<gfx::SlideAnimation> fade_animation_;
-
// Flags controlling bubble closure on the escape key and deactivation.
bool close_on_esc_;
bool close_on_deactivate_;
@@ -182,10 +165,7 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
Widget* anchor_widget_;
// The anchor rect used in the absence of an anchor view.
- gfx::Rect anchor_rect_;
-
- // If true, the bubble will re-anchor (and may resize) with |anchor_widget_|.
- bool move_with_anchor_;
+ mutable gfx::Rect anchor_rect_;
// The arrow's location on the bubble.
BubbleBorder::Arrow arrow_;
@@ -203,12 +183,6 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
// Insets applied to the |anchor_view_| bounds.
gfx::Insets anchor_view_insets_;
- // Original opacity of the bubble.
- int original_opacity_;
-
- // The widget hosting the border for this bubble (non-Aura Windows only).
- Widget* border_widget_;
-
// If true, the bubble does not take focus on display; default is false.
bool use_focusless_;
diff --git a/chromium/ui/views/bubble/bubble_delegate_unittest.cc b/chromium/ui/views/bubble/bubble_delegate_unittest.cc
index 7e2c718f950..9070c2fe758 100644
--- a/chromium/ui/views/bubble/bubble_delegate_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_delegate_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/run_loop.h"
#include "ui/base/hit_test.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/bubble/bubble_frame_view.h"
@@ -11,10 +10,6 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#endif
-
namespace views {
namespace {
@@ -39,8 +34,9 @@ class TestBubbleDelegateView : public BubbleDelegateView {
// BubbleDelegateView overrides:
virtual View* GetInitiallyFocusedView() OVERRIDE { return view_; }
- virtual gfx::Size GetPreferredSize() OVERRIDE { return gfx::Size(200, 200); }
- virtual int GetFadeDuration() OVERRIDE { return 1; }
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
+ return gfx::Size(200, 200);
+ }
private:
View* view_;
@@ -105,12 +101,10 @@ TEST_F(BubbleDelegateTest, CloseAnchorWidget) {
EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget());
EXPECT_FALSE(bubble_observer.widget_closed());
-#if defined(USE_AURA)
// TODO(msw): Remove activation hack to prevent bookkeeping errors in:
// aura::test::TestActivationClient::OnWindowDestroyed().
scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget());
EXPECT_FALSE(bubble_observer.widget_closed());
-#endif
// Ensure that closing the anchor widget also closes the bubble itself.
anchor_widget->CloseNow();
@@ -198,12 +192,10 @@ TEST_F(BubbleDelegateTest, ResetAnchorWidget) {
EXPECT_NE(anchor_widget, bubble_delegate->anchor_widget());
EXPECT_FALSE(bubble_observer.widget_closed());
-#if defined(USE_AURA)
// TODO(msw): Remove activation hack to prevent bookkeeping errors in:
// aura::test::TestActivationClient::OnWindowDestroyed().
scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget());
EXPECT_FALSE(bubble_observer.widget_closed());
-#endif
// Ensure that closing the parent widget also closes the bubble itself.
parent_widget->CloseNow();
@@ -244,7 +236,7 @@ TEST_F(BubbleDelegateTest, NonClientHitTest) {
}
}
-TEST_F(BubbleDelegateTest, CloseWhenAnchorWidgetBoundsChanged) {
+TEST_F(BubbleDelegateTest, VisibleWhenAnchorWidgetBoundsChanged) {
scoped_ptr<Widget> anchor_widget(CreateTestWidget());
BubbleDelegateView* bubble_delegate = new BubbleDelegateView(
anchor_widget->GetContentsView(), BubbleBorder::NONE);
@@ -255,66 +247,7 @@ TEST_F(BubbleDelegateTest, CloseWhenAnchorWidgetBoundsChanged) {
bubble_widget->Show();
EXPECT_TRUE(bubble_widget->IsVisible());
anchor_widget->SetBounds(gfx::Rect(10, 10, 100, 100));
- EXPECT_FALSE(bubble_widget->IsVisible());
-}
-
-// This class provides functionality to verify that the BubbleView shows up
-// when we call BubbleDelegateView::StartFade(true) and is destroyed when we
-// call BubbleDelegateView::StartFade(false).
-class BubbleWidgetClosingTest : public BubbleDelegateTest,
- public views::WidgetObserver {
- public:
- BubbleWidgetClosingTest() : bubble_destroyed_(false) {
-#if defined(USE_AURA)
- aura::Env::CreateInstance();
- loop_.set_dispatcher(aura::Env::GetInstance()->GetDispatcher());
-#endif
- }
-
- virtual ~BubbleWidgetClosingTest() {}
-
- void Observe(views::Widget* widget) {
- widget->AddObserver(this);
- }
-
- // views::WidgetObserver overrides.
- virtual void OnWidgetDestroyed(Widget* widget) OVERRIDE {
- bubble_destroyed_ = true;
- widget->RemoveObserver(this);
- loop_.Quit();
- }
-
- bool bubble_destroyed() const { return bubble_destroyed_; }
-
- void RunNestedLoop() {
- loop_.Run();
- }
-
- private:
- bool bubble_destroyed_;
- base::RunLoop loop_;
-
- DISALLOW_COPY_AND_ASSIGN(BubbleWidgetClosingTest);
-};
-
-TEST_F(BubbleWidgetClosingTest, TestBubbleVisibilityAndClose) {
- scoped_ptr<Widget> anchor_widget(CreateTestWidget());
- TestBubbleDelegateView* bubble_delegate =
- new TestBubbleDelegateView(anchor_widget->GetContentsView());
- Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
- EXPECT_FALSE(bubble_widget->IsVisible());
-
- bubble_delegate->StartFade(true);
EXPECT_TRUE(bubble_widget->IsVisible());
-
- EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(),
- bubble_widget->GetFocusManager()->GetFocusedView());
-
- Observe(bubble_widget);
-
- bubble_delegate->StartFade(false);
- RunNestedLoop();
- EXPECT_TRUE(bubble_destroyed());
}
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index 7e0fd5e745a..384c4fa46a8 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -12,6 +12,7 @@
#include "ui/gfx/path.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/skia_util.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/widget/widget.h"
@@ -20,10 +21,11 @@
namespace {
-// Padding, in pixels, for the title view, when it exists.
+// Insets for the title bar views in pixels.
const int kTitleTopInset = 12;
const int kTitleLeftInset = 19;
const int kTitleBottomInset = 12;
+const int kTitleRightInset = 7;
// Get the |vertical| or horizontal amount that |available_bounds| overflows
// |window_bounds|.
@@ -57,7 +59,8 @@ const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
// static
gfx::Insets BubbleFrameView::GetTitleInsets() {
- return gfx::Insets(kTitleTopInset, kTitleLeftInset, kTitleBottomInset, 0);
+ return gfx::Insets(kTitleTopInset, kTitleLeftInset,
+ kTitleBottomInset, kTitleRightInset);
}
BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
@@ -67,19 +70,20 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
close_(NULL),
titlebar_extra_view_(NULL) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- title_ = new Label(string16(), rb.GetFont(ui::ResourceBundle::MediumFont));
+ title_ = new Label(base::string16(),
+ rb.GetFontList(ui::ResourceBundle::MediumFont));
title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
AddChildView(title_);
- close_ = new LabelButton(this, string16());
+ close_ = new LabelButton(this, base::string16());
close_->SetImage(CustomButton::STATE_NORMAL,
*rb.GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia());
close_->SetImage(CustomButton::STATE_HOVERED,
*rb.GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia());
close_->SetImage(CustomButton::STATE_PRESSED,
*rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia());
+ close_->SetBorder(scoped_ptr<Border>());
close_->SetSize(close_->GetPreferredSize());
- close_->set_border(NULL);
close_->SetVisible(false);
AddChildView(close_);
}
@@ -154,11 +158,15 @@ void BubbleFrameView::UpdateWindowIcon() {}
void BubbleFrameView::UpdateWindowTitle() {
title_->SetText(GetWidget()->widget_delegate()->ShouldShowWindowTitle() ?
- GetWidget()->widget_delegate()->GetWindowTitle() : string16());
+ GetWidget()->widget_delegate()->GetWindowTitle() : base::string16());
// Update the close button visibility too, otherwise it's not intialized.
ResetWindowControls();
}
+void BubbleFrameView::SetTitleFontList(const gfx::FontList& font_list) {
+ title_->SetFontList(font_list);
+}
+
gfx::Insets BubbleFrameView::GetInsets() const {
gfx::Insets insets = content_margins_;
const int title_height = title_->text().empty() ? 0 :
@@ -168,39 +176,40 @@ gfx::Insets BubbleFrameView::GetInsets() const {
return insets;
}
-gfx::Size BubbleFrameView::GetPreferredSize() {
+gfx::Size BubbleFrameView::GetPreferredSize() const {
return GetSizeForClientSize(GetWidget()->client_view()->GetPreferredSize());
}
-gfx::Size BubbleFrameView::GetMinimumSize() {
+gfx::Size BubbleFrameView::GetMinimumSize() const {
return GetSizeForClientSize(GetWidget()->client_view()->GetMinimumSize());
}
void BubbleFrameView::Layout() {
- gfx::Rect bounds(GetLocalBounds());
- bounds.Inset(border()->GetInsets());
- // Small additional insets yield the desired 10px visual close button insets.
- bounds.Inset(0, 0, close_->width() + 1, 0);
- close_->SetPosition(gfx::Point(bounds.right(), bounds.y() + 2));
-
- gfx::Rect title_bounds(bounds);
- title_bounds.Inset(kTitleLeftInset, kTitleTopInset, 0, 0);
+ gfx::Rect bounds(GetContentsBounds());
+ bounds.Inset(GetTitleInsets());
+ if (bounds.IsEmpty())
+ return;
+
+ // The close button top inset is actually smaller than the title top inset.
+ close_->SetPosition(gfx::Point(bounds.right() - close_->width(),
+ bounds.y() - 5));
+
gfx::Size title_size(title_->GetPreferredSize());
- const int title_width = std::max(0, close_->bounds().x() - title_bounds.x());
+ const int title_width = std::max(0, close_->x() - bounds.x());
title_size.SetToMin(gfx::Size(title_width, title_size.height()));
- title_bounds.set_size(title_size);
- title_->SetBoundsRect(title_bounds);
+ bounds.set_size(title_size);
+ title_->SetBoundsRect(bounds);
if (titlebar_extra_view_) {
- const int extra_width = close_->bounds().x() - title_->bounds().right();
+ const int extra_width = close_->x() - title_->bounds().right();
gfx::Size size = titlebar_extra_view_->GetPreferredSize();
size.SetToMin(gfx::Size(std::max(0, extra_width), size.height()));
gfx::Rect titlebar_extra_view_bounds(
- bounds.right() - size.width(),
- title_bounds.y(),
+ close_->x() - size.width(),
+ bounds.y(),
size.width(),
- title_bounds.height());
- titlebar_extra_view_bounds.Subtract(title_bounds);
+ bounds.height());
+ titlebar_extra_view_bounds.Subtract(bounds);
titlebar_extra_view_->SetBoundsRect(titlebar_extra_view_bounds);
}
}
@@ -220,17 +229,25 @@ void BubbleFrameView::OnThemeChanged() {
UpdateWindowIcon();
}
+void BubbleFrameView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
+ if (bubble_border_ && bubble_border_->use_theme_background_color()) {
+ bubble_border_->set_background_color(GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_DialogBackground));
+ SchedulePaint();
+ }
+}
+
void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
if (sender == close_)
GetWidget()->Close();
}
-void BubbleFrameView::SetBubbleBorder(BubbleBorder* border) {
- bubble_border_ = border;
- set_border(bubble_border_);
+void BubbleFrameView::SetBubbleBorder(scoped_ptr<BubbleBorder> border) {
+ bubble_border_ = border.get();
+ SetBorder(border.PassAs<Border>());
// Update the background, which relies on the border.
- set_background(new views::BubbleBackground(border));
+ set_background(new views::BubbleBackground(bubble_border_));
}
void BubbleFrameView::SetTitlebarExtraView(View* view) {
@@ -243,27 +260,23 @@ void BubbleFrameView::SetTitlebarExtraView(View* view) {
gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
gfx::Size client_size,
bool adjust_if_offscreen) {
- gfx::Insets insets(GetInsets());
- client_size.Enlarge(insets.width(), insets.height());
+ gfx::Size size(GetSizeForClientSize(client_size));
const BubbleBorder::Arrow arrow = bubble_border_->arrow();
if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) {
+ // Try to mirror the anchoring if the bubble does not fit on the screen.
if (!bubble_border_->is_arrow_at_center(arrow)) {
- // Try to mirror the anchoring if the bubble does not fit on the screen.
- MirrorArrowIfOffScreen(true, anchor_rect, client_size);
- MirrorArrowIfOffScreen(false, anchor_rect, client_size);
+ MirrorArrowIfOffScreen(true, anchor_rect, size);
+ MirrorArrowIfOffScreen(false, anchor_rect, size);
} else {
- // Mirror as needed vertically if the arrow is on a horizontal edge and
- // vice-versa.
- MirrorArrowIfOffScreen(BubbleBorder::is_arrow_on_horizontal(arrow),
- anchor_rect,
- client_size);
- OffsetArrowIfOffScreen(anchor_rect, client_size);
+ const bool mirror_vertical = BubbleBorder::is_arrow_on_horizontal(arrow);
+ MirrorArrowIfOffScreen(mirror_vertical, anchor_rect, size);
+ OffsetArrowIfOffScreen(anchor_rect, size);
}
}
// Calculate the bounds with the arrow in its updated location and offset.
- return bubble_border_->GetBounds(anchor_rect, client_size);
+ return bubble_border_->GetBounds(anchor_rect, size);
}
gfx::Rect BubbleFrameView::GetAvailableScreenBounds(const gfx::Rect& rect) {
@@ -337,9 +350,8 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
SchedulePaint();
}
-gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) {
- gfx::Size size(
- GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size());
+gfx::Size BubbleFrameView::GetSizeForClientSize(
+ const gfx::Size& client_size) const {
// Accommodate the width of the title bar elements.
int title_bar_width = GetInsets().width() + border()->GetInsets().width();
if (!title_->text().empty())
@@ -348,7 +360,10 @@ gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) {
title_bar_width += close_->width() + 1;
if (titlebar_extra_view_ != NULL)
title_bar_width += titlebar_extra_view_->GetPreferredSize().width();
+ gfx::Size size(client_size);
size.SetToMax(gfx::Size(title_bar_width, 0));
+ const gfx::Insets insets(GetInsets());
+ size.Enlarge(insets.width(), insets.height());
return size;
}
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index d033c8d0d10..a17a4f8f487 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -12,6 +12,10 @@
#include "ui/views/controls/button/button.h"
#include "ui/views/window/non_client_view.h"
+namespace gfx {
+class FontList;
+}
+
namespace views {
class Label;
@@ -43,21 +47,26 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
virtual void UpdateWindowIcon() OVERRIDE;
virtual void UpdateWindowTitle() OVERRIDE;
+ // Set the FontList to be used for the title of the bubble.
+ // Caller must arrange to update the layout to have the call take effect.
+ void SetTitleFontList(const gfx::FontList& font_list);
+
// View overrides:
virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual void ChildPreferredSizeChanged(View* child) OVERRIDE;
virtual void OnThemeChanged() OVERRIDE;
+ virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
// Overridden from ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
- // Use bubble_border() and SetBubbleBorder(), not border() and set_border().
+ // Use bubble_border() and SetBubbleBorder(), not border() and SetBorder().
BubbleBorder* bubble_border() const { return bubble_border_; }
- void SetBubbleBorder(BubbleBorder* border);
+ void SetBubbleBorder(scoped_ptr<BubbleBorder> border);
gfx::Insets content_margins() const { return content_margins_; }
@@ -89,7 +98,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
const gfx::Size& client_size);
// Calculates the size needed to accommodate the given client area.
- gfx::Size GetSizeForClientSize(const gfx::Size& client_size);
+ gfx::Size GetSizeForClientSize(const gfx::Size& client_size) const;
// The bubble border.
BubbleBorder* bubble_border_;
diff --git a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
index ef5d58d8b00..1bd9e348a18 100644
--- a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -23,7 +23,8 @@ class TestBubbleFrameView : public BubbleFrameView {
TestBubbleFrameView()
: BubbleFrameView(gfx::Insets(kMargin, kMargin, kMargin, kMargin)),
available_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
- SetBubbleBorder(new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor));
+ SetBubbleBorder(scoped_ptr<views::BubbleBorder>(
+ new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor)));
}
virtual ~TestBubbleFrameView() {}
diff --git a/chromium/ui/views/bubble/bubble_window_targeter.cc b/chromium/ui/views/bubble/bubble_window_targeter.cc
new file mode 100644
index 00000000000..19e0c85f91a
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_window_targeter.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/bubble/bubble_window_targeter.h"
+
+#include "ui/aura/window.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+
+namespace views {
+
+BubbleWindowTargeter::BubbleWindowTargeter(BubbleDelegateView* bubble)
+ : wm::MaskedWindowTargeter(bubble->GetWidget()->GetNativeView()),
+ bubble_(bubble) {
+}
+
+BubbleWindowTargeter::~BubbleWindowTargeter() {
+}
+
+bool BubbleWindowTargeter::GetHitTestMask(aura::Window* window,
+ gfx::Path* mask) const {
+ mask->addRect(
+ gfx::RectToSkRect(bubble_->GetBubbleFrameView()->GetContentsBounds()));
+ return true;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_window_targeter.h b/chromium/ui/views/bubble/bubble_window_targeter.h
new file mode 100644
index 00000000000..45b1d5c551b
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_window_targeter.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/views_export.h"
+#include "ui/wm/core/masked_window_targeter.h"
+
+namespace aura {
+class Window;
+}
+
+namespace views {
+class BubbleDelegateView;
+
+// A convenient window-targeter that uses a mask based on the content-bounds of
+// the bubble-frame.
+class VIEWS_EXPORT BubbleWindowTargeter
+ : public NON_EXPORTED_BASE(wm::MaskedWindowTargeter) {
+ public:
+ explicit BubbleWindowTargeter(BubbleDelegateView* bubble);
+ virtual ~BubbleWindowTargeter();
+
+ private:
+ // wm::MaskedWindowTargeter:
+ virtual bool GetHitTestMask(aura::Window* window,
+ gfx::Path* mask) const OVERRIDE;
+
+ views::BubbleDelegateView* bubble_;
+
+ DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeter);
+};
+
+} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc b/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
new file mode 100644
index 00000000000..479f6e93d39
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/bubble/bubble_window_targeter.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+namespace {
+
+class WidgetOwnsNativeBubble : public BubbleDelegateView {
+ public:
+ WidgetOwnsNativeBubble(View* content, BubbleBorder::Arrow arrow)
+ : BubbleDelegateView(content, arrow) {
+ }
+
+ virtual ~WidgetOwnsNativeBubble() {}
+
+ private:
+ // BubbleDelegateView:
+ virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
+ Widget* widget) const OVERRIDE {
+ params->ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetOwnsNativeBubble);
+};
+
+} // namespace
+
+class BubbleWindowTargeterTest : public ViewsTestBase {
+ public:
+ BubbleWindowTargeterTest()
+ : bubble_delegate_(NULL) {
+ }
+ virtual ~BubbleWindowTargeterTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ViewsTestBase::SetUp();
+ CreateAnchorWidget();
+ CreateBubbleWidget();
+
+ anchor_widget()->Show();
+ bubble_widget()->Show();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ bubble_delegate_ = NULL;
+ bubble_widget_.reset();
+ anchor_.reset();
+ ViewsTestBase::TearDown();
+ }
+
+ Widget* anchor_widget() { return anchor_.get(); }
+ Widget* bubble_widget() { return bubble_widget_.get(); }
+ BubbleDelegateView* bubble_delegate() { return bubble_delegate_; }
+
+ private:
+ void CreateAnchorWidget() {
+ anchor_.reset(new Widget());
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ anchor_->Init(params);
+ }
+
+ void CreateBubbleWidget() {
+ bubble_delegate_ = new WidgetOwnsNativeBubble(
+ anchor_->GetContentsView(), BubbleBorder::NONE);
+ bubble_delegate_->set_color(SK_ColorGREEN);
+ bubble_widget_.reset(BubbleDelegateView::CreateBubble(bubble_delegate_));
+ }
+
+ scoped_ptr<Widget> anchor_;
+ scoped_ptr<Widget> bubble_widget_;
+ BubbleDelegateView* bubble_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeterTest);
+};
+
+TEST_F(BubbleWindowTargeterTest, HitTest) {
+ ui::EventTarget* root = bubble_widget()->GetNativeWindow()->GetRootWindow();
+ ui::EventTargeter* targeter = root->GetEventTargeter();
+ aura::Window* bubble_window = bubble_widget()->GetNativeWindow();
+ gfx::Rect bubble_bounds = bubble_window->GetBoundsInRootWindow();
+
+ {
+ bubble_delegate()->set_margins(gfx::Insets());
+ ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
+ bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1));
+ }
+ {
+ bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20));
+ ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
+ bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1));
+ }
+
+ bubble_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
+ new BubbleWindowTargeter(bubble_delegate())));
+ {
+ bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20));
+ ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
+ bubble_bounds.origin(), ui::EF_NONE, ui::EF_NONE);
+ EXPECT_NE(bubble_window, targeter->FindTargetForEvent(root, &move1));
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/bubble/tray_bubble_view.cc b/chromium/ui/views/bubble/tray_bubble_view.cc
index 3f947ab9134..243e58b3cfe 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.cc
+++ b/chromium/ui/views/bubble/tray_bubble_view.cc
@@ -11,7 +11,8 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/effects/SkBlurImageFilter.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_delegate.h"
@@ -22,6 +23,7 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/bubble/bubble_window_targeter.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
@@ -325,17 +327,14 @@ TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window,
mouse_actively_entered_(false) {
set_parent_window(parent_window);
set_notify_enter_exit_on_child(true);
- set_move_with_anchor(true);
set_close_on_deactivate(init_params.close_on_deactivate);
set_margins(gfx::Insets());
bubble_border_ = new TrayBubbleBorder(this, GetAnchorView(), params_);
- if (get_use_acceleration_when_possible()) {
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(true);
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(true);
- bubble_content_mask_.reset(
- new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
- }
+ bubble_content_mask_.reset(
+ new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
}
TrayBubbleView::~TrayBubbleView() {
@@ -350,17 +349,17 @@ void TrayBubbleView::InitializeAndShowBubble() {
SetAlignment(params_.arrow_alignment);
bubble_border_->UpdateArrowOffset();
- if (get_use_acceleration_when_possible())
- layer()->parent()->SetMaskLayer(bubble_content_mask_->layer());
+ layer()->parent()->SetMaskLayer(bubble_content_mask_->layer());
GetWidget()->Show();
+ GetWidget()->GetNativeWindow()->SetEventTargeter(
+ scoped_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this)));
UpdateBubble();
}
void TrayBubbleView::UpdateBubble() {
SizeToContents();
- if (get_use_acceleration_when_possible())
- bubble_content_mask_->layer()->SetBounds(layer()->bounds());
+ bubble_content_mask_->layer()->SetBounds(layer()->bounds());
GetWidget()->GetRootView()->SchedulePaint();
}
@@ -390,11 +389,11 @@ gfx::Insets TrayBubbleView::GetBorderInsets() const {
void TrayBubbleView::Init() {
BoxLayout* layout = new BottomAlignedBoxLayout(this);
- layout->set_spread_blank_space(true);
+ layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_FILL);
SetLayoutManager(layout);
}
-gfx::Rect TrayBubbleView::GetAnchorRect() {
+gfx::Rect TrayBubbleView::GetAnchorRect() const {
if (!delegate_)
return gfx::Rect();
return delegate_->GetAnchorRect(anchor_widget(),
@@ -408,7 +407,7 @@ bool TrayBubbleView::CanActivate() const {
NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(Widget* widget) {
BubbleFrameView* frame = new BubbleFrameView(margins());
- frame->SetBubbleBorder(bubble_border_);
+ frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(bubble_border_));
return frame;
}
@@ -421,21 +420,21 @@ void TrayBubbleView::GetWidgetHitTestMask(gfx::Path* mask) const {
mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds()));
}
-gfx::Size TrayBubbleView::GetPreferredSize() {
+gfx::Size TrayBubbleView::GetPreferredSize() const {
return gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_));
}
-gfx::Size TrayBubbleView::GetMaximumSize() {
+gfx::Size TrayBubbleView::GetMaximumSize() const {
gfx::Size size = GetPreferredSize();
size.set_width(params_.max_width);
return size;
}
-int TrayBubbleView::GetHeightForWidth(int width) {
+int TrayBubbleView::GetHeightForWidth(int width) const {
int height = GetInsets().height();
width = std::max(width - GetInsets().width(), 0);
for (int i = 0; i < child_count(); ++i) {
- View* child = child_at(i);
+ const View* child = child_at(i);
if (child->visible())
height += child->GetHeightForWidth(width);
}
@@ -478,9 +477,9 @@ void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) {
delegate_->OnMouseExitedView();
}
-void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) {
+void TrayBubbleView::GetAccessibleState(ui::AXViewState* state) {
if (delegate_ && params_.can_activate) {
- state->role = ui::AccessibilityTypes::ROLE_WINDOW;
+ state->role = ui::AX_ROLE_WINDOW;
state->name = delegate_->GetAccessibleNameForBubble();
}
}
@@ -500,8 +499,7 @@ void TrayBubbleView::ChildPreferredSizeChanged(View* child) {
void TrayBubbleView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
- if (get_use_acceleration_when_possible() && details.is_add &&
- details.child == this) {
+ if (details.is_add && details.child == this) {
details.parent->SetPaintToLayer(true);
details.parent->SetFillsBoundsOpaquely(true);
details.parent->layer()->SetMasksToBounds(true);
diff --git a/chromium/ui/views/bubble/tray_bubble_view.h b/chromium/ui/views/bubble/tray_bubble_view.h
index 1e9d48298ea..54f6cc88033 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.h
+++ b/chromium/ui/views/bubble/tray_bubble_view.h
@@ -71,13 +71,14 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
// Called from GetAccessibleState(); should return the appropriate
// accessible name for the bubble.
- virtual string16 GetAccessibleNameForBubble() = 0;
+ virtual base::string16 GetAccessibleNameForBubble() = 0;
// Passes responsibility for BubbleDelegateView::GetAnchorRect to the
// delegate.
- virtual gfx::Rect GetAnchorRect(views::Widget* anchor_widget,
- AnchorType anchor_type,
- AnchorAlignment anchor_alignment) = 0;
+ virtual gfx::Rect GetAnchorRect(
+ views::Widget* anchor_widget,
+ AnchorType anchor_type,
+ AnchorAlignment anchor_alignment) const = 0;
// Called when a bubble wants to hide/destroy itself (e.g. last visible
// child view was closed).
@@ -153,15 +154,15 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
virtual void GetWidgetHitTestMask(gfx::Path* mask) const OVERRIDE;
// Overridden from views::BubbleDelegateView.
- virtual gfx::Rect GetAnchorRect() OVERRIDE;
+ virtual gfx::Rect GetAnchorRect() const OVERRIDE;
// Overridden from views::View.
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
- virtual int GetHeightForWidth(int width) OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
+ virtual int GetHeightForWidth(int width) const OVERRIDE;
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// Overridden from MouseWatcherListener
virtual void MouseMovedOutOfHost() OVERRIDE;
diff --git a/chromium/ui/views/button_drag_utils.cc b/chromium/ui/views/button_drag_utils.cc
index 9305a07d3b0..2c4f25ade3b 100644
--- a/chromium/ui/views/button_drag_utils.cc
+++ b/chromium/ui/views/button_drag_utils.cc
@@ -10,6 +10,7 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/image/image.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/drag_utils.h"
@@ -18,20 +19,29 @@
namespace button_drag_utils {
// Maximum width of the link drag image in pixels.
-static const int kLinkDragImageMaxWidth = 200;
+static const int kLinkDragImageMaxWidth = 150;
void SetURLAndDragImage(const GURL& url,
- const string16& title,
+ const base::string16& title,
const gfx::ImageSkia& icon,
+ const gfx::Point* press_pt,
ui::OSExchangeData* data,
views::Widget* widget) {
DCHECK(url.is_valid() && data);
-
data->SetURL(url, title);
+ SetDragImage(url, title, icon, press_pt, data, widget);
+}
+void SetDragImage(const GURL& url,
+ const base::string16& title,
+ const gfx::ImageSkia& icon,
+ const gfx::Point* press_pt,
+ ui::OSExchangeData* data,
+ views::Widget* widget) {
// Create a button to render the drag image for us.
views::TextButton button(NULL,
- title.empty() ? UTF8ToUTF16(url.spec()) : title);
+ title.empty() ? base::UTF8ToUTF16(url.spec())
+ : title);
button.set_max_width(kLinkDragImageMaxWidth);
if (icon.isNull()) {
button.SetIcon(*ui::ResourceBundle::GetSharedInstance().GetImageNamed(
@@ -42,12 +52,17 @@ void SetURLAndDragImage(const GURL& url,
gfx::Size prefsize = button.GetPreferredSize();
button.SetBounds(0, 0, prefsize.width(), prefsize.height());
+ gfx::Vector2d press_point;
+ if (press_pt)
+ press_point = press_pt->OffsetFromOrigin();
+ else
+ press_point = gfx::Vector2d(prefsize.width() / 2, prefsize.height() / 2);
+
// Render the image.
scoped_ptr<gfx::Canvas> canvas(
views::GetCanvasForDragImage(widget, prefsize));
button.PaintButton(canvas.get(), views::TextButton::PB_FOR_DRAG);
- drag_utils::SetDragImageOnDataObject(*canvas, prefsize,
- gfx::Vector2d(prefsize.width() / 2, prefsize.height() / 2), data);
+ drag_utils::SetDragImageOnDataObject(*canvas, press_point, data);
}
} // namespace button_drag_utils
diff --git a/chromium/ui/views/button_drag_utils.h b/chromium/ui/views/button_drag_utils.h
index 1f93c9517de..8f1a7eedf7d 100644
--- a/chromium/ui/views/button_drag_utils.h
+++ b/chromium/ui/views/button_drag_utils.h
@@ -12,6 +12,7 @@ class GURL;
namespace gfx {
class ImageSkia;
+class Point;
}
namespace ui {
@@ -25,13 +26,23 @@ class Widget;
namespace button_drag_utils {
// Sets url and title on data as well as setting a suitable image for dragging.
-// The image looks like that of the bookmark buttons.
+// The image looks like that of the bookmark buttons. |press_pt| is optional
+// offset; otherwise, it centers the drag image.
VIEWS_EXPORT void SetURLAndDragImage(const GURL& url,
- const string16& title,
+ const base::string16& title,
const gfx::ImageSkia& icon,
+ const gfx::Point* press_pt,
ui::OSExchangeData* data,
views::Widget* widget);
+// As above, but only sets the image.
+VIEWS_EXPORT void SetDragImage(const GURL& url,
+ const base::string16& title,
+ const gfx::ImageSkia& icon,
+ const gfx::Point* press_pt,
+ ui::OSExchangeData* data,
+ views::Widget* widget);
+
} // namespace drag_utils
#endif // UI_VIEWS_BUTTON_DRAG_UTILS_H_
diff --git a/chromium/ui/views/cocoa/bridged_content_view.h b/chromium/ui/views/cocoa/bridged_content_view.h
new file mode 100644
index 00000000000..e7c83f74af5
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridged_content_view.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
+#define UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
+
+#import <Cocoa/Cocoa.h>
+
+namespace views {
+class View;
+}
+
+// The NSView that sits as the root contentView of the NSWindow, whilst it has
+// a views::RootView present. Bridges requests from Cocoa to the hosted
+// views::View.
+@interface BridgedContentView : NSView {
+ @private
+ // Weak. The hosted RootView, owned by hostedView_->GetWidget().
+ views::View* hostedView_;
+}
+
+@property(readonly, nonatomic) views::View* hostedView;
+
+// Initialize the NSView -> views::View bridge. |viewToHost| must be non-NULL.
+- (id)initWithView:(views::View*)viewToHost;
+
+// Clear the hosted view. For example, if it is about to be destroyed.
+- (void)clearView;
+
+@end
+
+#endif // UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
diff --git a/chromium/ui/views/cocoa/bridged_content_view.mm b/chromium/ui/views/cocoa/bridged_content_view.mm
new file mode 100644
index 00000000000..bd9a511a244
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridged_content_view.mm
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/cocoa/bridged_content_view.h"
+
+#include "base/logging.h"
+#include "ui/gfx/canvas_paint_mac.h"
+#include "ui/views/view.h"
+
+@implementation BridgedContentView
+
+@synthesize hostedView = hostedView_;
+
+- (id)initWithView:(views::View*)viewToHost {
+ DCHECK(viewToHost);
+ gfx::Rect bounds = viewToHost->bounds();
+ // To keep things simple, assume the origin is (0, 0) until there exists a use
+ // case for something other than that.
+ DCHECK(bounds.origin().IsOrigin());
+ NSRect initialFrame = NSMakeRect(0, 0, bounds.width(), bounds.height());
+ if ((self = [super initWithFrame:initialFrame]))
+ hostedView_ = viewToHost;
+
+ return self;
+}
+
+- (void)clearView {
+ hostedView_ = NULL;
+}
+
+// NSView implementation.
+
+- (void)setFrameSize:(NSSize)newSize {
+ [super setFrameSize:newSize];
+ if (!hostedView_)
+ return;
+
+ hostedView_->SetSize(gfx::Size(newSize.width, newSize.height));
+}
+
+- (void)drawRect:(NSRect)dirtyRect {
+ if (!hostedView_)
+ return;
+
+ gfx::CanvasSkiaPaint canvas(dirtyRect, false /* opaque */);
+ hostedView_->Paint(&canvas, views::CullSet());
+}
+
+@end
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.h b/chromium/ui/views/cocoa/bridged_native_widget.h
new file mode 100644
index 00000000000..59754d1d129
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridged_native_widget.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
+#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/views/ime/input_method_delegate.h"
+#include "ui/views/views_export.h"
+
+@class BridgedContentView;
+
+namespace ui {
+class InputMethod;
+}
+
+namespace views {
+
+class InputMethod;
+class View;
+
+// A bridge to an NSWindow managed by an instance of NativeWidgetMac or
+// DesktopNativeWidgetMac. Serves as a helper class to bridge requests from the
+// NativeWidgetMac to the Cocoa window. Behaves a bit like an aura::Window.
+class VIEWS_EXPORT BridgedNativeWidget : public internal::InputMethodDelegate {
+
+ public:
+ BridgedNativeWidget();
+ virtual ~BridgedNativeWidget();
+
+ // Initialize the bridge, "retains" ownership of |window|.
+ void Init(base::scoped_nsobject<NSWindow> window);
+
+ // Set or clears the views::View bridged by the content view. This does NOT
+ // take ownership of |view|.
+ void SetRootView(views::View* view);
+
+ // See widget.h for documentation.
+ InputMethod* CreateInputMethod();
+ ui::InputMethod* GetHostInputMethod();
+
+ BridgedContentView* ns_view() { return bridged_view_; }
+ NSWindow* ns_window() { return window_; }
+
+ // Overridden from internal::InputMethodDelegate:
+ virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE;
+
+ private:
+ base::scoped_nsobject<NSWindow> window_;
+ base::scoped_nsobject<BridgedContentView> bridged_view_;
+ scoped_ptr<ui::InputMethod> input_method_;
+
+ DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidget);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.mm b/chromium/ui/views/cocoa/bridged_native_widget.mm
new file mode 100644
index 00000000000..e4b754f78d8
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridged_native_widget.mm
@@ -0,0 +1,78 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/cocoa/bridged_native_widget.h"
+
+#include "base/logging.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/input_method_factory.h"
+#include "ui/base/ui_base_switches_util.h"
+#import "ui/views/cocoa/bridged_content_view.h"
+#include "ui/views/ime/input_method_bridge.h"
+#include "ui/views/ime/null_input_method.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+BridgedNativeWidget::BridgedNativeWidget() {
+}
+
+BridgedNativeWidget::~BridgedNativeWidget() {
+ SetRootView(NULL);
+}
+
+void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window) {
+ DCHECK(!window_);
+ window_.swap(window);
+}
+
+void BridgedNativeWidget::SetRootView(views::View* view) {
+ if (view == [bridged_view_ hostedView])
+ return;
+
+ [bridged_view_ clearView];
+ bridged_view_.reset();
+ // Note that there can still be references to the old |bridged_view_|
+ // floating around in Cocoa libraries at this point. However, references to
+ // the old views::View will be gone, so any method calls will become no-ops.
+
+ if (view) {
+ bridged_view_.reset([[BridgedContentView alloc] initWithView:view]);
+ // Objective C initializers can return nil. However, if |view| is non-NULL
+ // this should be treated as an error and caught early.
+ CHECK(bridged_view_);
+ }
+ [window_ setContentView:bridged_view_];
+}
+
+InputMethod* BridgedNativeWidget::CreateInputMethod() {
+ if (switches::IsTextInputFocusManagerEnabled())
+ return new NullInputMethod();
+
+ return new InputMethodBridge(this, GetHostInputMethod(), true);
+}
+
+ui::InputMethod* BridgedNativeWidget::GetHostInputMethod() {
+ if (!input_method_) {
+ // Delegate is NULL because Mac IME does not need DispatchKeyEventPostIME
+ // callbacks.
+ input_method_ = ui::CreateInputMethod(NULL, nil);
+ }
+ return input_method_.get();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BridgedNativeWidget, internal::InputMethodDelegate:
+
+void BridgedNativeWidget::DispatchKeyEventPostIME(const ui::KeyEvent& key) {
+ // Mac key events don't go through this, but some unit tests that use
+ // MockInputMethod do.
+ Widget* widget = [bridged_view_ hostedView]->GetWidget();
+ widget->OnKeyEvent(const_cast<ui::KeyEvent*>(&key));
+ if (!key.handled() && widget->GetFocusManager())
+ widget->GetFocusManager()->OnKeyEvent(key);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
new file mode 100644
index 00000000000..6d30f41f13c
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -0,0 +1,117 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/cocoa/bridged_native_widget.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/memory/scoped_ptr.h"
+#import "testing/gtest_mac.h"
+#import "ui/gfx/test/ui_cocoa_test_helper.h"
+#import "ui/views/cocoa/bridged_content_view.h"
+#include "ui/views/ime/input_method.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+class BridgedNativeWidgetTest : public ui::CocoaTest {
+ public:
+ BridgedNativeWidgetTest();
+ virtual ~BridgedNativeWidgetTest();
+
+ // testing::Test:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ protected:
+ // TODO(tapted): Make this a EventCountView from widget_unittest.cc.
+ scoped_ptr<views::View> view_;
+ scoped_ptr<BridgedNativeWidget> bridge_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTest);
+};
+
+BridgedNativeWidgetTest::BridgedNativeWidgetTest() {
+}
+
+BridgedNativeWidgetTest::~BridgedNativeWidgetTest() {
+}
+
+void BridgedNativeWidgetTest::SetUp() {
+ ui::CocoaTest::SetUp();
+
+ view_.reset(new views::View);
+ bridge_.reset(new BridgedNativeWidget);
+ base::scoped_nsobject<NSWindow> window([test_window() retain]);
+ bridge_->Init(window);
+ bridge_->SetRootView(view_.get());
+
+ [test_window() makePretendKeyWindowAndSetFirstResponder:bridge_->ns_view()];
+}
+
+void BridgedNativeWidgetTest::TearDown() {
+ [test_window() clearPretendKeyWindowAndFirstResponder];
+
+ bridge_.reset();
+ view_.reset();
+
+ ui::CocoaTest::TearDown();
+}
+
+// The TEST_VIEW macro expects the view it's testing to have a superview. In
+// these tests, the NSView bridge is a contentView, at the root. These mimic
+// what TEST_VIEW usually does.
+TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewAddRemove) {
+ base::scoped_nsobject<BridgedContentView> view([bridge_->ns_view() retain]);
+ EXPECT_NSEQ([test_window() contentView], view);
+ EXPECT_NSEQ(test_window(), [view window]);
+
+ // The superview of a contentView is an NSNextStepFrame.
+ EXPECT_TRUE([view superview]);
+ EXPECT_TRUE([view hostedView]);
+
+ // Destroying the C++ bridge should remove references to any C++ objects in
+ // the ObjectiveC object, and remove it from the hierarchy.
+ bridge_.reset();
+ EXPECT_FALSE([view hostedView]);
+ EXPECT_FALSE([view superview]);
+ EXPECT_FALSE([view window]);
+ EXPECT_FALSE([test_window() contentView]);
+}
+
+TEST_F(BridgedNativeWidgetTest, BridgedNativeWidgetTest_TestViewDisplay) {
+ [bridge_->ns_view() display];
+}
+
+// Test that resizing the window resizes the root view appropriately.
+TEST_F(BridgedNativeWidgetTest, ViewSizeTracksWindow) {
+ const int kTestNewWidth = 400;
+ const int kTestNewHeight = 300;
+
+ // |test_window()| is borderless, so these should align.
+ NSSize window_size = [test_window() frame].size;
+ EXPECT_EQ(view_->width(), static_cast<int>(window_size.width));
+ EXPECT_EQ(view_->height(), static_cast<int>(window_size.height));
+
+ // Make sure a resize actually occurs.
+ EXPECT_NE(kTestNewWidth, view_->width());
+ EXPECT_NE(kTestNewHeight, view_->height());
+
+ [test_window() setFrame:NSMakeRect(0, 0, kTestNewWidth, kTestNewHeight)
+ display:NO];
+ EXPECT_EQ(kTestNewWidth, view_->width());
+ EXPECT_EQ(kTestNewHeight, view_->height());
+}
+
+TEST_F(BridgedNativeWidgetTest, CreateInputMethod) {
+ scoped_ptr<views::InputMethod> input_method(bridge_->CreateInputMethod());
+ EXPECT_TRUE(input_method);
+}
+
+TEST_F(BridgedNativeWidgetTest, GetHostInputMethod) {
+ EXPECT_TRUE(bridge_->GetHostInputMethod());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc
index 3c649f9718a..8c283da829d 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_view.cc
@@ -32,18 +32,19 @@ const int kHueIndicatorSize = 5;
const int kBorderWidth = 1;
const int kTextfieldLengthInChars = 14;
-string16 GetColorText(SkColor color) {
- return ASCIIToUTF16(base::StringPrintf("#%02x%02x%02x",
- SkColorGetR(color),
- SkColorGetG(color),
- SkColorGetB(color)));
+base::string16 GetColorText(SkColor color) {
+ return base::ASCIIToUTF16(base::StringPrintf("#%02x%02x%02x",
+ SkColorGetR(color),
+ SkColorGetG(color),
+ SkColorGetB(color)));
}
-bool GetColorFromText(const string16& text, SkColor* result) {
+bool GetColorFromText(const base::string16& text, SkColor* result) {
if (text.size() != 6 && !(text.size() == 7 && text[0] == '#'))
return false;
- std::string input = UTF16ToUTF8((text.size() == 6) ? text : text.substr(1));
+ std::string input =
+ base::UTF16ToUTF8((text.size() == 6) ? text : text.substr(1));
std::vector<uint8> hex;
if (!base::HexStringToBytes(input, &hex))
return false;
@@ -125,7 +126,7 @@ class ColorChooserView::HueView : public LocatedEventHandlerView {
virtual void ProcessEventAtLocation(const gfx::Point& point) OVERRIDE;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
ColorChooserView* chooser_view_;
@@ -163,7 +164,7 @@ void ColorChooserView::HueView::ProcessEventAtLocation(
SchedulePaint();
}
-gfx::Size ColorChooserView::HueView::GetPreferredSize() {
+gfx::Size ColorChooserView::HueView::GetPreferredSize() const {
// We put indicators on the both sides of the hue bar.
return gfx::Size(kHueBarWidth + kHueIndicatorSize * 2 + kBorderWidth * 2,
kSaturationValueSize + kBorderWidth * 2);
@@ -237,7 +238,7 @@ class ColorChooserView::SaturationValueView : public LocatedEventHandlerView {
virtual void ProcessEventAtLocation(const gfx::Point& point) OVERRIDE;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
ColorChooserView* chooser_view_;
@@ -252,7 +253,7 @@ ColorChooserView::SaturationValueView::SaturationValueView(
: chooser_view_(chooser_view),
hue_(0) {
SetFocusable(false);
- set_border(Border::CreateSolidBorder(kBorderWidth, SK_ColorGRAY));
+ SetBorder(Border::CreateSolidBorder(kBorderWidth, SK_ColorGRAY));
}
void ColorChooserView::SaturationValueView::OnHueChanged(SkScalar hue) {
@@ -291,7 +292,7 @@ void ColorChooserView::SaturationValueView::ProcessEventAtLocation(
chooser_view_->OnSaturationValueChosen(saturation, value);
}
-gfx::Size ColorChooserView::SaturationValueView::GetPreferredSize() {
+gfx::Size ColorChooserView::SaturationValueView::GetPreferredSize() const {
return gfx::Size(kSaturationValueSize + kBorderWidth * 2,
kSaturationValueSize + kBorderWidth * 2);
}
@@ -348,7 +349,7 @@ class ColorChooserView::SelectedColorPatchView : public views::View {
ColorChooserView::SelectedColorPatchView::SelectedColorPatchView() {
SetFocusable(false);
SetVisible(true);
- set_border(Border::CreateSolidBorder(kBorderWidth, SK_ColorGRAY));
+ SetBorder(Border::CreateSolidBorder(kBorderWidth, SK_ColorGRAY));
}
void ColorChooserView::SelectedColorPatchView::SetColor(SkColor color) {
@@ -393,7 +394,7 @@ ColorChooserView::ColorChooserView(ColorChooserListener* listener,
GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 0);
textfield_ = new Textfield();
- textfield_->SetController(this);
+ textfield_->set_controller(this);
textfield_->set_default_width_in_chars(kTextfieldLengthInChars);
layout->AddView(textfield_);
selected_color_patch_ = new SelectedColorPatchView();
@@ -454,7 +455,7 @@ View* ColorChooserView::GetContentsView() {
}
void ColorChooserView::ContentsChanged(Textfield* sender,
- const string16& new_contents) {
+ const base::string16& new_contents) {
SkColor color = SK_ColorBLACK;
if (GetColorFromText(new_contents, &color)) {
SkColorToHSV(color, hsv_);
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.h b/chromium/ui/views/color_chooser/color_chooser_view.h
index c77e0b66c17..e7fda323c87 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.h
+++ b/chromium/ui/views/color_chooser/color_chooser_view.h
@@ -55,7 +55,7 @@ class VIEWS_EXPORT ColorChooserView : public WidgetDelegateView,
// TextfieldController overrides:
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) OVERRIDE;
+ const base::string16& new_contents) OVERRIDE;
virtual bool HandleKeyEvent(Textfield* sender,
const ui::KeyEvent& key_event) OVERRIDE;
diff --git a/chromium/ui/views/controls/button/blue_button.cc b/chromium/ui/views/controls/button/blue_button.cc
index 3e52afd896e..e3a9487ff6c 100644
--- a/chromium/ui/views/controls/button/blue_button.cc
+++ b/chromium/ui/views/controls/button/blue_button.cc
@@ -5,19 +5,13 @@
#include "ui/views/controls/button/blue_button.h"
#include "grit/ui_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/sys_color_change_listener.h"
#include "ui/views/controls/button/label_button_border.h"
namespace {
-// Insets for the unified blue_button images. This assumes that the images
-// are of a 9 grid, of 5x5 size each.
-const int kBlueButtonInsets = 5;
-
-// Default text and shadow colors for the blue button.
-const SkColor kBlueButtonTextColor = SK_ColorWHITE;
+// Default shadow color for the blue button.
const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA);
} // namespace
@@ -27,42 +21,11 @@ namespace views {
// static
const char BlueButton::kViewClassName[] = "views/BlueButton";
-BlueButton::BlueButton(ButtonListener* listener, const string16& text)
+BlueButton::BlueButton(ButtonListener* listener, const base::string16& text)
: LabelButton(listener, text) {
// Inherit STYLE_BUTTON insets, minimum size, alignment, etc.
SetStyle(STYLE_BUTTON);
-
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- const gfx::Insets insets(kBlueButtonInsets,
- kBlueButtonInsets,
- kBlueButtonInsets,
- kBlueButtonInsets);
-
- LabelButtonBorder* button_border = static_cast<LabelButtonBorder*>(border());
- button_border->SetPainter(false, STATE_NORMAL,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_NORMAL), insets));
- button_border->SetPainter(false, STATE_HOVERED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_HOVER), insets));
- button_border->SetPainter(false, STATE_PRESSED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_PRESSED), insets));
- button_border->SetPainter(false, STATE_DISABLED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_DISABLED), insets));
- button_border->SetPainter(true, STATE_NORMAL,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_NORMAL), insets));
- button_border->SetPainter(true, STATE_HOVERED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_HOVER), insets));
- button_border->SetPainter(true, STATE_PRESSED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_PRESSED), insets));
- button_border->SetPainter(true, STATE_DISABLED,
- Painter::CreateImagePainter(
- *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_DISABLED), insets));
+ UpdateThemedBorder();
}
BlueButton::~BlueButton() {}
@@ -70,10 +33,18 @@ BlueButton::~BlueButton() {}
void BlueButton::ResetColorsFromNativeTheme() {
LabelButton::ResetColorsFromNativeTheme();
if (!gfx::IsInvertedColorScheme()) {
- for (size_t state = STATE_NORMAL; state < STATE_COUNT; ++state)
- SetTextColor(static_cast<ButtonState>(state), kBlueButtonTextColor);
- label()->SetShadowColors(kBlueButtonShadowColor, kBlueButtonShadowColor);
- label()->SetShadowOffset(0, 1);
+ SetTextColor(STATE_NORMAL, GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_BlueButtonEnabledColor));
+ SetTextColor(STATE_HOVERED, GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_BlueButtonHoverColor));
+ SetTextColor(STATE_PRESSED, GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_BlueButtonHighlightColor));
+ SetTextColor(STATE_DISABLED, GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_BlueButtonDisabledColor));
+
+ // TODO(estade): this is not great on system themes.
+ label()->set_shadows(gfx::ShadowValues(1,
+ gfx::ShadowValue(gfx::Point(0, 1), 0, kBlueButtonShadowColor)));
}
}
@@ -81,4 +52,28 @@ const char* BlueButton::GetClassName() const {
return BlueButton::kViewClassName;
}
+scoped_ptr<LabelButtonBorder> BlueButton::CreateDefaultBorder() const {
+ // Insets for splitting the images.
+ const gfx::Insets insets(5, 5, 5, 5);
+ scoped_ptr<LabelButtonBorder> button_border(new LabelButtonBorder(style()));
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ button_border->SetPainter(false, STATE_NORMAL, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_NORMAL), insets));
+ button_border->SetPainter(false, STATE_HOVERED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_HOVER), insets));
+ button_border->SetPainter(false, STATE_PRESSED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_PRESSED), insets));
+ button_border->SetPainter(false, STATE_DISABLED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_DISABLED), insets));
+ button_border->SetPainter(true, STATE_NORMAL, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_NORMAL), insets));
+ button_border->SetPainter(true, STATE_HOVERED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_HOVER), insets));
+ button_border->SetPainter(true, STATE_PRESSED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_FOCUSED_PRESSED), insets));
+ button_border->SetPainter(true, STATE_DISABLED, Painter::CreateImagePainter(
+ *rb.GetImageSkiaNamed(IDR_BLUE_BUTTON_DISABLED), insets));
+ return button_border.Pass();
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/button/blue_button.h b/chromium/ui/views/controls/button/blue_button.h
index a169fba85d1..8c83c007ec6 100644
--- a/chromium/ui/views/controls/button/blue_button.h
+++ b/chromium/ui/views/controls/button/blue_button.h
@@ -22,6 +22,7 @@ class VIEWS_EXPORT BlueButton : public LabelButton {
// Overridden from LabelButton:
virtual void ResetColorsFromNativeTheme() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
+ virtual scoped_ptr<LabelButtonBorder> CreateDefaultBorder() const OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(BlueButton);
};
diff --git a/chromium/ui/views/controls/button/blue_button_unittest.cc b/chromium/ui/views/controls/button/blue_button_unittest.cc
new file mode 100644
index 00000000000..908e747d24c
--- /dev/null
+++ b/chromium/ui/views/controls/button/blue_button_unittest.cc
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/button/blue_button.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/controls/button/label_button_border.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace views {
+
+namespace {
+
+class TestBlueButton : public BlueButton {
+ public:
+ TestBlueButton() : BlueButton(NULL, base::ASCIIToUTF16("foo")) {}
+ virtual ~TestBlueButton() {}
+
+ using BlueButton::OnNativeThemeChanged;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestBlueButton);
+};
+
+} // namespace
+
+typedef ViewsTestBase BlueButtonTest;
+
+TEST_F(BlueButtonTest, Border) {
+ // Compared to a normal LabelButton...
+ LabelButton button(NULL, base::ASCIIToUTF16("foo"));
+ button.SetBoundsRect(gfx::Rect(gfx::Point(0, 0), button.GetPreferredSize()));
+ gfx::Canvas button_canvas(button.bounds().size(), 1.0, true);
+ button.border()->Paint(button, &button_canvas);
+
+ // ... a special blue border should be used.
+ TestBlueButton blue_button;
+ blue_button.SetBoundsRect(gfx::Rect(gfx::Point(0, 0),
+ blue_button.GetPreferredSize()));
+ gfx::Canvas canvas(blue_button.bounds().size(), 1.0, true);
+ blue_button.border()->Paint(blue_button, &canvas);
+ EXPECT_EQ(button.GetText(), blue_button.GetText());
+ EXPECT_FALSE(gfx::BitmapsAreEqual(button_canvas.ExtractImageRep().sk_bitmap(),
+ canvas.ExtractImageRep().sk_bitmap()));
+
+ // Make sure it's still used after the native theme "changes".
+ blue_button.OnNativeThemeChanged(NULL);
+ gfx::Canvas canvas2(blue_button.bounds().size(), 1.0, true);
+ blue_button.border()->Paint(blue_button, &canvas2);
+
+ EXPECT_TRUE(gfx::BitmapsAreEqual(canvas.ExtractImageRep().sk_bitmap(),
+ canvas2.ExtractImageRep().sk_bitmap()));
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/button/button.cc b/chromium/ui/views/controls/button/button.cc
index 96e2e27432c..4e7f51b5450 100644
--- a/chromium/ui/views/controls/button/button.cc
+++ b/chromium/ui/views/controls/button/button.cc
@@ -5,31 +5,47 @@
#include "ui/views/controls/button/button.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
namespace views {
////////////////////////////////////////////////////////////////////////////////
+// Button, static public:
+
+// static
+Button::ButtonState Button::GetButtonStateFrom(ui::NativeTheme::State state) {
+ switch (state) {
+ case ui::NativeTheme::kDisabled: return Button::STATE_DISABLED;
+ case ui::NativeTheme::kHovered: return Button::STATE_HOVERED;
+ case ui::NativeTheme::kNormal: return Button::STATE_NORMAL;
+ case ui::NativeTheme::kPressed: return Button::STATE_PRESSED;
+ case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state;
+ }
+ return Button::STATE_NORMAL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Button, public:
Button::~Button() {
}
-void Button::SetTooltipText(const string16& tooltip_text) {
+void Button::SetTooltipText(const base::string16& tooltip_text) {
tooltip_text_ = tooltip_text;
if (accessible_name_.empty())
accessible_name_ = tooltip_text_;
TooltipTextChanged();
}
-void Button::SetAccessibleName(const string16& name) {
+void Button::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
////////////////////////////////////////////////////////////////////////////////
// Button, View overrides:
-bool Button::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
+bool Button::GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const {
if (tooltip_text_.empty())
return false;
@@ -37,8 +53,8 @@ bool Button::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
return true;
}
-void Button::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
+void Button::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_BUTTON;
state->name = accessible_name_;
}
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index d038015f870..37d639dd6a8 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -5,6 +5,7 @@
#ifndef UI_VIEWS_CONTROLS_BUTTON_BUTTON_H_
#define UI_VIEWS_CONTROLS_BUTTON_BUTTON_H_
+#include "ui/native_theme/native_theme.h"
#include "ui/views/view.h"
namespace views {
@@ -42,21 +43,22 @@ class VIEWS_EXPORT Button : public View {
enum ButtonStyle {
STYLE_BUTTON = 0,
STYLE_TEXTBUTTON,
- STYLE_NATIVE_TEXTBUTTON,
STYLE_COUNT,
};
- void SetTooltipText(const string16& tooltip_text);
+ static ButtonState GetButtonStateFrom(ui::NativeTheme::State state);
+
+ void SetTooltipText(const base::string16& tooltip_text);
int tag() const { return tag_; }
void set_tag(int tag) { tag_ = tag; }
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
// Overridden from View:
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
protected:
// Construct the Button with a Listener. The listener can be NULL. This can be
@@ -72,10 +74,10 @@ class VIEWS_EXPORT Button : public View {
private:
// The text shown in a tooltip.
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
// Accessibility data.
- string16 accessible_name_;
+ base::string16 accessible_name_;
// The id tag associated with this button. Used to disambiguate buttons in
// the ButtonListener implementation.
diff --git a/chromium/ui/views/controls/button/checkbox.cc b/chromium/ui/views/controls/button/checkbox.cc
index ec33a47e2b1..22c5f88e2d6 100644
--- a/chromium/ui/views/controls/button/checkbox.cc
+++ b/chromium/ui/views/controls/button/checkbox.cc
@@ -5,7 +5,7 @@
#include "ui/views/controls/button/checkbox.h"
#include "grit/ui_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/painter.h"
@@ -15,15 +15,16 @@ namespace views {
// static
const char Checkbox::kViewClassName[] = "Checkbox";
-Checkbox::Checkbox(const string16& label)
+Checkbox::Checkbox(const base::string16& label)
: LabelButton(NULL, label),
checked_(false) {
SetHorizontalAlignment(gfx::ALIGN_LEFT);
- LabelButtonBorder* button_border = static_cast<LabelButtonBorder*>(border());
+ scoped_ptr<LabelButtonBorder> button_border(new LabelButtonBorder(style()));
button_border->SetPainter(false, STATE_HOVERED, NULL);
button_border->SetPainter(false, STATE_PRESSED, NULL);
// Inset the trailing side by a couple pixels for the focus border.
button_border->set_insets(gfx::Insets(0, 0, 0, 2));
+ SetBorder(button_border.PassAs<Border>());
SetFocusable(true);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -93,10 +94,11 @@ const char* Checkbox::GetClassName() const {
return kViewClassName;
}
-void Checkbox::GetAccessibleState(ui::AccessibleViewState* state) {
+void Checkbox::GetAccessibleState(ui::AXViewState* state) {
LabelButton::GetAccessibleState(state);
- state->role = ui::AccessibilityTypes::ROLE_CHECKBUTTON;
- state->state = checked() ? ui::AccessibilityTypes::STATE_CHECKED : 0;
+ state->role = ui::AX_ROLE_CHECK_BOX;
+ if (checked())
+ state->AddStateFlag(ui::AX_STATE_CHECKED);
}
void Checkbox::OnFocus() {
diff --git a/chromium/ui/views/controls/button/checkbox.h b/chromium/ui/views/controls/button/checkbox.h
index a603bd5b2dd..7bfd5bcf7d1 100644
--- a/chromium/ui/views/controls/button/checkbox.h
+++ b/chromium/ui/views/controls/button/checkbox.h
@@ -19,7 +19,7 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
public:
static const char kViewClassName[];
- explicit Checkbox(const string16& label);
+ explicit Checkbox(const base::string16& label);
virtual ~Checkbox();
// Sets a listener for this checkbox. Checkboxes aren't required to have them
@@ -34,7 +34,7 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
// Overridden from LabelButton:
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
virtual const gfx::ImageSkia& GetImage(ButtonState for_state) OVERRIDE;
diff --git a/chromium/ui/views/controls/button/custom_button.cc b/chromium/ui/views/controls/button/custom_button.cc
index 2be2a2301e1..0e237a31273 100644
--- a/chromium/ui/views/controls/button/custom_button.cc
+++ b/chromium/ui/views/controls/button/custom_button.cc
@@ -4,7 +4,7 @@
#include "ui/views/controls/button/custom_button.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/animation/throb_animation.h"
@@ -101,7 +101,7 @@ void CustomButton::SetHotTracked(bool is_hot_tracked) {
SetState(is_hot_tracked ? STATE_HOVERED : STATE_NORMAL);
if (is_hot_tracked)
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
}
bool CustomButton::IsHotTracked() const {
@@ -199,6 +199,7 @@ bool CustomButton::OnKeyPressed(const ui::KeyEvent& event) {
ui::MouseEvent synthetic_event(ui::ET_MOUSE_RELEASED,
gfx::Point(),
gfx::Point(),
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
NotifyClick(synthetic_event);
} else {
@@ -216,6 +217,7 @@ bool CustomButton::OnKeyReleased(const ui::KeyEvent& event) {
ui::MouseEvent synthetic_event(ui::ET_MOUSE_RELEASED,
gfx::Point(),
gfx::Point(),
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
NotifyClick(synthetic_event);
return true;
@@ -260,6 +262,7 @@ bool CustomButton::AcceleratorPressed(const ui::Accelerator& accelerator) {
ui::MouseEvent synthetic_event(ui::ET_MOUSE_RELEASED,
gfx::Point(),
gfx::Point(),
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
NotifyClick(synthetic_event);
return true;
@@ -281,17 +284,17 @@ void CustomButton::OnDragDone() {
SetState(STATE_NORMAL);
}
-void CustomButton::GetAccessibleState(ui::AccessibleViewState* state) {
+void CustomButton::GetAccessibleState(ui::AXViewState* state) {
Button::GetAccessibleState(state);
switch (state_) {
case STATE_HOVERED:
- state->state = ui::AccessibilityTypes::STATE_HOTTRACKED;
+ state->AddStateFlag(ui::AX_STATE_HOVERED);
break;
case STATE_PRESSED:
- state->state = ui::AccessibilityTypes::STATE_PRESSED;
+ state->AddStateFlag(ui::AX_STATE_PRESSED);
break;
case STATE_DISABLED:
- state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE;
+ state->AddStateFlag(ui::AX_STATE_DISABLED);
break;
case STATE_NORMAL:
case STATE_COUNT:
diff --git a/chromium/ui/views/controls/button/custom_button.h b/chromium/ui/views/controls/button/custom_button.h
index 9ac502d3d96..4614a5c7323 100644
--- a/chromium/ui/views/controls/button/custom_button.h
+++ b/chromium/ui/views/controls/button/custom_button.h
@@ -18,8 +18,8 @@ namespace views {
class CustomButtonStateChangedDelegate;
-// A button with custom rendering. The common base class of ImageButton and
-// TextButton.
+// A button with custom rendering. The common base class of ImageButton,
+// LabelButton and TextButton.
// Note that this type of button is not focusable by default and will not be
// part of the focus chain. Call SetFocusable(true) to make it part of the
// focus chain.
@@ -84,7 +84,7 @@ class VIEWS_EXPORT CustomButton : public Button,
virtual void ShowContextMenu(const gfx::Point& p,
ui::MenuSourceType source_type) OVERRIDE;
virtual void OnDragDone() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE;
// Overridden from gfx::AnimationDelegate:
diff --git a/chromium/ui/views/controls/button/custom_button_unittest.cc b/chromium/ui/views/controls/button/custom_button_unittest.cc
index f7b11e648ed..84836716701 100644
--- a/chromium/ui/views/controls/button/custom_button_unittest.cc
+++ b/chromium/ui/views/controls/button/custom_button_unittest.cc
@@ -5,6 +5,9 @@
#include "ui/views/controls/button/custom_button.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/test_cursor_client.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/layout.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/button/checkbox.h"
@@ -16,12 +19,6 @@
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/test/views_test_base.h"
-#if defined(USE_AURA)
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/test_cursor_client.h"
-#include "ui/aura/window.h"
-#endif
-
namespace views {
namespace {
@@ -38,7 +35,6 @@ class TestCustomButton : public CustomButton {
DISALLOW_COPY_AND_ASSIGN(TestCustomButton);
};
-#if defined(USE_AURA)
void PerformGesture(CustomButton* button, ui::EventType event_type) {
ui::GestureEventDetails gesture_details(event_type, 0, 0);
base::TimeDelta time_stamp = base::TimeDelta::FromMicroseconds(0);
@@ -46,7 +42,6 @@ void PerformGesture(CustomButton* button, ui::EventType event_type) {
gesture_details, 1);
button->OnGestureEvent(&gesture_event);
}
-#endif // USE_AURA
} // namespace
@@ -63,10 +58,8 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
widget->Init(params);
widget->Show();
-#if defined(USE_AURA)
aura::test::TestCursorClient cursor_client(
widget->GetNativeView()->GetRootWindow());
-#endif
// Position the widget in a way so that it is under the cursor.
gfx::Point cursor = gfx::Screen::GetScreenFor(
@@ -80,10 +73,12 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
gfx::Point center(10, 10);
button->OnMousePressed(ui::MouseEvent(ui::ET_MOUSE_PRESSED, center, center,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON));
EXPECT_EQ(CustomButton::STATE_PRESSED, button->state());
button->OnMouseReleased(ui::MouseEvent(ui::ET_MOUSE_RELEASED, center, center,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON));
EXPECT_EQ(CustomButton::STATE_HOVERED, button->state());
@@ -99,7 +94,6 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
button->SetVisible(true);
EXPECT_EQ(CustomButton::STATE_HOVERED, button->state());
-#if defined(USE_AURA)
// In Aura views, no new hover effects are invoked if mouse events
// are disabled.
cursor_client.DisableMouseEvents();
@@ -115,10 +109,8 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
button->SetVisible(true);
EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
-#endif
}
-#if defined(USE_AURA)
// Tests that gesture events correctly change the button state.
TEST_F(CustomButtonTest, GestureEventsSetState) {
// Create a widget so that the CustomButton can query the hover state
@@ -148,12 +140,10 @@ TEST_F(CustomButtonTest, GestureEventsSetState) {
EXPECT_EQ(CustomButton::STATE_NORMAL, button->state());
}
-#endif // USE_AURA
-
// Make sure all subclasses of CustomButton are correctly recognized
// as CustomButton.
TEST_F(CustomButtonTest, AsCustomButton) {
- string16 text;
+ base::string16 text;
TextButton text_button(NULL, text);
EXPECT_TRUE(CustomButton::AsCustomButton(&text_button));
@@ -176,7 +166,7 @@ TEST_F(CustomButtonTest, AsCustomButton) {
Link link(text);
EXPECT_FALSE(CustomButton::AsCustomButton(&link));
- Textfield textfield(Textfield::STYLE_DEFAULT);
+ Textfield textfield;
EXPECT_FALSE(CustomButton::AsCustomButton(&textfield));
}
diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc
index 6a842346d2c..ecbd4a10724 100644
--- a/chromium/ui/views/controls/button/image_button.cc
+++ b/chromium/ui/views/controls/button/image_button.cc
@@ -5,7 +5,7 @@
#include "ui/views/controls/button/image_button.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
@@ -60,14 +60,6 @@ void ImageButton::SetBackground(SkColor color,
*image, *mask);
}
-void ImageButton::SetOverlayImage(const gfx::ImageSkia* image) {
- if (!image) {
- overlay_image_ = gfx::ImageSkia();
- return;
- }
- overlay_image_ = *image;
-}
-
void ImageButton::SetImageAlignment(HorizontalAlignment h_align,
VerticalAlignment v_align) {
h_alignment_ = h_align;
@@ -82,7 +74,7 @@ void ImageButton::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
////////////////////////////////////////////////////////////////////////////////
// ImageButton, View overrides:
-gfx::Size ImageButton::GetPreferredSize() {
+gfx::Size ImageButton::GetPreferredSize() const {
gfx::Size size = preferred_size_;
if (!images_[STATE_NORMAL].isNull()) {
size = gfx::Size(images_[STATE_NORMAL].width(),
@@ -116,9 +108,6 @@ void ImageButton::OnPaint(gfx::Canvas* canvas) {
canvas->DrawImageInt(background_image_, position.x(), position.y());
canvas->DrawImageInt(img, position.x(), position.y());
-
- if (!overlay_image_.isNull())
- canvas->DrawImageInt(overlay_image_, position.x(), position.y());
}
Painter::PaintFocusPainter(this, canvas, focus_painter());
@@ -206,7 +195,7 @@ void ToggleImageButton::SetToggled(bool toggled) {
toggled_ = toggled;
SchedulePaint();
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_VALUE_CHANGED, true);
}
void ToggleImageButton::SetToggledImage(ButtonState state,
@@ -220,7 +209,7 @@ void ToggleImageButton::SetToggledImage(ButtonState state,
}
}
-void ToggleImageButton::SetToggledTooltipText(const string16& tooltip) {
+void ToggleImageButton::SetToggledTooltipText(const base::string16& tooltip) {
toggled_tooltip_text_ = tooltip;
}
@@ -249,7 +238,7 @@ void ToggleImageButton::SetImage(ButtonState state,
// ToggleImageButton, View overrides:
bool ToggleImageButton::GetTooltipText(const gfx::Point& p,
- string16* tooltip) const {
+ base::string16* tooltip) const {
if (!toggled_ || toggled_tooltip_text_.empty())
return Button::GetTooltipText(p, tooltip);
@@ -257,7 +246,7 @@ bool ToggleImageButton::GetTooltipText(const gfx::Point& p,
return true;
}
-void ToggleImageButton::GetAccessibleState(ui::AccessibleViewState* state) {
+void ToggleImageButton::GetAccessibleState(ui::AXViewState* state) {
ImageButton::GetAccessibleState(state);
GetTooltipText(gfx::Point(), &state->name);
}
diff --git a/chromium/ui/views/controls/button/image_button.h b/chromium/ui/views/controls/button/image_button.h
index 4977b06d398..fc02b8ac9ce 100644
--- a/chromium/ui/views/controls/button/image_button.h
+++ b/chromium/ui/views/controls/button/image_button.h
@@ -51,10 +51,6 @@ class VIEWS_EXPORT ImageButton : public CustomButton {
const gfx::ImageSkia* image,
const gfx::ImageSkia* mask);
- // Set an |image| to draw on top of the normal / hot / pushed image.
- // Pass NULL for no image.
- void SetOverlayImage(const gfx::ImageSkia* image);
-
// Sets how the image is laid out within the button's bounds.
void SetImageAlignment(HorizontalAlignment h_align,
VerticalAlignment v_align);
@@ -73,7 +69,7 @@ class VIEWS_EXPORT ImageButton : public CustomButton {
}
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
@@ -96,9 +92,6 @@ class VIEWS_EXPORT ImageButton : public CustomButton {
gfx::ImageSkia background_image_;
- // Image to draw on top of normal / hot / pushed image. Usually empty.
- gfx::ImageSkia overlay_image_;
-
private:
FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, Basics);
FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBorder);
@@ -145,7 +138,7 @@ class VIEWS_EXPORT ToggleImageButton : public ImageButton {
void SetToggledImage(ButtonState state, const gfx::ImageSkia* image);
// Set the tooltip text displayed when the button is toggled.
- void SetToggledTooltipText(const string16& tooltip);
+ void SetToggledTooltipText(const base::string16& tooltip);
// Overridden from ImageButton:
virtual const gfx::ImageSkia& GetImage(ButtonState state) const OVERRIDE;
@@ -154,8 +147,8 @@ class VIEWS_EXPORT ToggleImageButton : public ImageButton {
// Overridden from View:
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
private:
// The parent class's images_ member is used for the current images,
@@ -168,7 +161,7 @@ class VIEWS_EXPORT ToggleImageButton : public ImageButton {
// The parent class's tooltip_text_ is displayed when not toggled, and
// this one is shown when toggled.
- string16 toggled_tooltip_text_;
+ base::string16 toggled_tooltip_text_;
DISALLOW_COPY_AND_ASSIGN(ToggleImageButton);
};
diff --git a/chromium/ui/views/controls/button/image_button_unittest.cc b/chromium/ui/views/controls/button/image_button_unittest.cc
index 995b2056de4..406d02c3ae2 100644
--- a/chromium/ui/views/controls/button/image_button_unittest.cc
+++ b/chromium/ui/views/controls/button/image_button_unittest.cc
@@ -60,25 +60,6 @@ TEST_F(ImageButtonTest, Basics) {
EXPECT_FALSE(button.GetImageToPaint().isNull());
EXPECT_EQ(10, button.GetImageToPaint().width());
EXPECT_EQ(20, button.GetImageToPaint().height());
-
- // Set an overlay image.
- gfx::ImageSkia overlay_image = CreateTestImage(12, 22);
- button.SetOverlayImage(&overlay_image);
- EXPECT_EQ(12, button.overlay_image_.width());
- EXPECT_EQ(22, button.overlay_image_.height());
-
- // By convention, preferred size doesn't change, even though pushed image
- // is bigger.
- EXPECT_EQ("10x20", button.GetPreferredSize().ToString());
-
- // We're still painting the normal image.
- EXPECT_FALSE(button.GetImageToPaint().isNull());
- EXPECT_EQ(10, button.GetImageToPaint().width());
- EXPECT_EQ(20, button.GetImageToPaint().height());
-
- // Reset the overlay image.
- button.SetOverlayImage(NULL);
- EXPECT_TRUE(button.overlay_image_.isNull());
}
TEST_F(ImageButtonTest, SetAndGetImage) {
@@ -116,11 +97,11 @@ TEST_F(ImageButtonTest, ImagePositionWithBorder) {
EXPECT_EQ(gfx::Point().ToString(),
button.ComputeImagePaintPosition(image).ToString());
- button.set_border(views::Border::CreateEmptyBorder(10, 5, 0, 0));
+ button.SetBorder(views::Border::CreateEmptyBorder(10, 5, 0, 0));
EXPECT_EQ(gfx::Point(5, 10).ToString(),
button.ComputeImagePaintPosition(image).ToString());
- button.set_border(NULL);
+ button.SetBorder(Border::NullBorder());
button.SetBounds(0, 0, 50, 50);
EXPECT_EQ(gfx::Point().ToString(),
button.ComputeImagePaintPosition(image).ToString());
@@ -129,7 +110,7 @@ TEST_F(ImageButtonTest, ImagePositionWithBorder) {
ImageButton::ALIGN_MIDDLE);
EXPECT_EQ(gfx::Point(15, 10).ToString(),
button.ComputeImagePaintPosition(image).ToString());
- button.set_border(views::Border::CreateEmptyBorder(10, 10, 0, 0));
+ button.SetBorder(views::Border::CreateEmptyBorder(10, 10, 0, 0));
EXPECT_EQ(gfx::Point(20, 15).ToString(),
button.ComputeImagePaintPosition(image).ToString());
}
diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc
index 30db5d13d9a..c0399147775 100644
--- a/chromium/ui/views/controls/button/label_button.cc
+++ b/chromium/ui/views/controls/button/label_button.cc
@@ -8,14 +8,17 @@
#include "grit/ui_resources.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/sys_color_change_listener.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/background.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/painter.h"
#include "ui/views/window/dialog_delegate.h"
-#if defined(OS_WIN)
-#include "ui/native_theme/native_theme_win.h"
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "ui/views/linux_ui/linux_ui.h"
#endif
namespace {
@@ -23,9 +26,11 @@ namespace {
// The spacing between the icon and text.
const int kSpacing = 5;
+#if !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
// Default text and shadow colors for STYLE_BUTTON.
const SkColor kStyleButtonTextColor = SK_ColorBLACK;
const SkColor kStyleButtonShadowColor = SK_ColorWHITE;
+#endif
} // namespace
@@ -37,7 +42,7 @@ const int LabelButton::kHoverAnimationDurationMs = 170;
// static
const char LabelButton::kViewClassName[] = "LabelButton";
-LabelButton::LabelButton(ButtonListener* listener, const string16& text)
+LabelButton::LabelButton(ButtonListener* listener, const base::string16& text)
: CustomButton(listener),
image_(new ImageView()),
label_(new Label()),
@@ -45,9 +50,11 @@ LabelButton::LabelButton(ButtonListener* listener, const string16& text)
button_state_colors_(),
explicitly_set_colors_(),
is_default_(false),
- style_(STYLE_TEXTBUTTON) {
+ style_(STYLE_TEXTBUTTON),
+ border_is_themed_border_(true) {
SetAnimationDuration(kHoverAnimationDurationMs);
SetText(text);
+ SetFontList(gfx::FontList());
AddChildView(image_);
image_->set_interactive(false);
@@ -75,11 +82,11 @@ void LabelButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
UpdateImage();
}
-const string16& LabelButton::GetText() const {
+const base::string16& LabelButton::GetText() const {
return label_->text();
}
-void LabelButton::SetText(const string16& text) {
+void LabelButton::SetText(const base::string16& text) {
SetAccessibleName(text);
label_->SetText(text);
}
@@ -93,6 +100,14 @@ void LabelButton::SetTextColor(ButtonState for_state, SkColor color) {
explicitly_set_colors_[for_state] = true;
}
+void LabelButton::SetTextShadows(const gfx::ShadowValues& shadows) {
+ label_->set_shadows(shadows);
+}
+
+void LabelButton::SetTextSubpixelRenderingEnabled(bool enabled) {
+ label_->set_subpixel_rendering_enabled(enabled);
+}
+
bool LabelButton::GetTextMultiLine() const {
return label_->is_multi_line();
}
@@ -101,20 +116,27 @@ void LabelButton::SetTextMultiLine(bool text_multi_line) {
label_->SetMultiLine(text_multi_line);
}
-const gfx::Font& LabelButton::GetFont() const {
- return label_->font();
+const gfx::FontList& LabelButton::GetFontList() const {
+ return label_->font_list();
}
-void LabelButton::SetFont(const gfx::Font& font) {
- label_->SetFont(font);
+void LabelButton::SetFontList(const gfx::FontList& font_list) {
+ cached_normal_font_list_ = font_list;
+ cached_bold_font_list_ = font_list.DeriveWithStyle(
+ font_list.GetFontStyle() | gfx::Font::BOLD);
+
+ // STYLE_BUTTON uses bold text to indicate default buttons.
+ label_->SetFontList(
+ style_ == STYLE_BUTTON && is_default_ ?
+ cached_bold_font_list_ : cached_normal_font_list_);
}
-void LabelButton::SetElideBehavior(Label::ElideBehavior elide_behavior) {
+void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
label_->SetElideBehavior(elide_behavior);
}
gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const {
- return label_->horizontal_alignment();
+ return label_->GetHorizontalAlignment();
}
void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
@@ -122,6 +144,10 @@ void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
InvalidateLayout();
}
+void LabelButton::SetDirectionalityMode(gfx::DirectionalityMode mode) {
+ label_->set_directionality_mode(mode);
+}
+
void LabelButton::SetIsDefault(bool is_default) {
if (is_default == is_default_)
return;
@@ -131,20 +157,13 @@ void LabelButton::SetIsDefault(bool is_default) {
// STYLE_BUTTON uses bold text to indicate default buttons.
if (style_ == STYLE_BUTTON) {
- int style = label_->font().GetStyle();
- style = is_default ? style | gfx::Font::BOLD : style & ~gfx::Font::BOLD;
- label_->SetFont(label_->font().DeriveFont(0, style));
+ label_->SetFontList(
+ is_default ? cached_bold_font_list_ : cached_normal_font_list_);
}
}
void LabelButton::SetStyle(ButtonStyle style) {
- // Use the new button style instead of the native button style.
- // TODO(msw): Officialy deprecate and remove STYLE_NATIVE_TEXTBUTTON.
- if (style == STYLE_NATIVE_TEXTBUTTON)
- style = STYLE_BUTTON;
-
style_ = style;
- set_border(new LabelButtonBorder(style));
// Inset the button focus rect from the actual border; roughly match Windows.
if (style == STYLE_BUTTON) {
SetFocusPainter(scoped_ptr<Painter>());
@@ -152,34 +171,33 @@ void LabelButton::SetStyle(ButtonStyle style) {
SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(
gfx::Insets(3, 3, 3, 3)));
}
- if (style == STYLE_BUTTON || style == STYLE_NATIVE_TEXTBUTTON) {
+ if (style == STYLE_BUTTON) {
label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
SetFocusable(true);
}
if (style == STYLE_BUTTON)
set_min_size(gfx::Size(70, 33));
- // Invalidate the layout to pickup the new insets from the border.
- InvalidateLayout();
- ResetColorsFromNativeTheme();
+
+ OnNativeThemeChanged(GetNativeTheme());
}
void LabelButton::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
focus_painter_ = focus_painter.Pass();
}
-gfx::Size LabelButton::GetPreferredSize() {
+gfx::Size LabelButton::GetPreferredSize() const {
// Use a temporary label copy for sizing to avoid calculation side-effects.
- gfx::Font font = GetFont();
- Label label(GetText(), font);
+ Label label(GetText(), cached_normal_font_list_);
+ label.set_shadows(label_->shadows());
label.SetMultiLine(GetTextMultiLine());
if (style() == STYLE_BUTTON) {
// Some text appears wider when rendered normally than when rendered bold.
// Accommodate the widest, as buttons may show bold and shouldn't resize.
const int current_width = label.GetPreferredSize().width();
- label.SetFont(font.DeriveFont(0, font.GetStyle() ^ gfx::Font::BOLD));
+ label.SetFontList(cached_bold_font_list_);
if (label.GetPreferredSize().width() < current_width)
- label.SetFont(font);
+ label.SetFontList(cached_normal_font_list_);
}
// Resize multi-line labels given the current limited available width.
@@ -197,7 +215,7 @@ gfx::Size LabelButton::GetPreferredSize() {
size.Enlarge(image_size.width() + insets.width(), insets.height());
// Make the size at least as large as the minimum size needed by the border.
- size.SetToMax(border()->GetMinimumSize());
+ size.SetToMax(border() ? border()->GetMinimumSize() : gfx::Size());
// Increase the minimum size monotonically with the preferred size.
size.SetToMax(min_size_);
@@ -217,17 +235,17 @@ void LabelButton::Layout() {
adjusted_alignment = (adjusted_alignment == gfx::ALIGN_LEFT) ?
gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
- gfx::Rect child_area(GetLocalBounds());
+ gfx::Rect child_area(GetChildAreaBounds());
child_area.Inset(GetInsets());
gfx::Size image_size(image_->GetPreferredSize());
- image_size.set_width(std::min(image_size.width(), child_area.width()));
- image_size.set_height(std::min(image_size.height(), child_area.height()));
+ image_size.SetToMin(child_area.size());
// The label takes any remaining width after sizing the image, unless both
// views are centered. In that case, using the tighter preferred label width
// avoids wasted space within the label that would look like awkward padding.
- gfx::Size label_size(child_area.size());
+ // Labels can paint over the full button height, including the border height.
+ gfx::Size label_size(child_area.width(), height());
if (!image_size.IsEmpty() && !label_size.IsEmpty()) {
label_size.set_width(
std::max(child_area.width() - image_size.width() - kSpacing, 0));
@@ -250,8 +268,8 @@ void LabelButton::Layout() {
image_origin.Offset(child_area.width() - image_size.width(), 0);
}
- gfx::Point label_origin(child_area.origin());
- if (!image_size.IsEmpty() &&adjusted_alignment != gfx::ALIGN_RIGHT)
+ gfx::Point label_origin(child_area.x(), 0);
+ if (!image_size.IsEmpty() && adjusted_alignment != gfx::ALIGN_RIGHT)
label_origin.set_x(image_origin.x() + image_size.width() + kSpacing);
image_->SetBoundsRect(gfx::Rect(image_origin, image_size));
@@ -262,6 +280,19 @@ const char* LabelButton::GetClassName() const {
return kViewClassName;
}
+scoped_ptr<LabelButtonBorder> LabelButton::CreateDefaultBorder() const {
+ return scoped_ptr<LabelButtonBorder>(new LabelButtonBorder(style_));
+}
+
+void LabelButton::SetBorder(scoped_ptr<Border> border) {
+ border_is_themed_border_ = false;
+ View::SetBorder(border.Pass());
+}
+
+gfx::Rect LabelButton::GetChildAreaBounds() {
+ return GetLocalBounds();
+}
+
void LabelButton::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
@@ -284,9 +315,9 @@ void LabelButton::GetExtraParams(ui::NativeTheme::ExtraParams* params) const {
params->button.indeterminate = false;
params->button.is_default = is_default_;
params->button.is_focused = HasFocus() && IsAccessibilityFocusable();
- params->button.has_border = style() == STYLE_NATIVE_TEXTBUTTON;
+ params->button.has_border = false;
params->button.classic_state = 0;
- params->button.background_color = label()->background_color();
+ params->button.background_color = label_->background_color();
}
void LabelButton::ResetColorsFromNativeTheme() {
@@ -300,26 +331,31 @@ void LabelButton::ResetColorsFromNativeTheme() {
// Certain styles do not change text color when hovered or pressed.
bool constant_text_color = false;
-#if defined(OS_WIN)
- constant_text_color |= (style() == STYLE_NATIVE_TEXTBUTTON &&
- theme == ui::NativeThemeWin::instance());
-#endif
-
// Use hardcoded colors for inverted color scheme support and STYLE_BUTTON.
if (gfx::IsInvertedColorScheme()) {
constant_text_color = true;
colors[STATE_NORMAL] = SK_ColorWHITE;
label_->SetBackgroundColor(SK_ColorBLACK);
+ label_->set_background(Background::CreateSolidBackground(SK_ColorBLACK));
label_->SetAutoColorReadabilityEnabled(true);
- label_->ClearEmbellishing();
+ label_->set_shadows(gfx::ShadowValues());
} else if (style() == STYLE_BUTTON) {
+ // TODO(erg): This is disabled on desktop linux because of the binary asset
+ // confusion. These details should either be pushed into ui::NativeThemeWin
+ // or should be obsoleted by rendering buttons with paint calls instead of
+ // with static assets. http://crbug.com/350498
+#if !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
constant_text_color = true;
colors[STATE_NORMAL] = kStyleButtonTextColor;
label_->SetBackgroundColor(theme->GetSystemColor(
ui::NativeTheme::kColorId_ButtonBackgroundColor));
label_->SetAutoColorReadabilityEnabled(false);
- label_->SetShadowColors(kStyleButtonShadowColor, kStyleButtonShadowColor);
- label_->SetShadowOffset(0, 1);
+ label_->set_shadows(gfx::ShadowValues(1,
+ gfx::ShadowValue(gfx::Point(0, 1), 0, kStyleButtonShadowColor)));
+#endif
+ label_->set_background(NULL);
+ } else {
+ label_->set_background(NULL);
}
if (constant_text_color)
@@ -337,6 +373,27 @@ void LabelButton::UpdateImage() {
image_->SetImage(GetImage(state()));
}
+void LabelButton::UpdateThemedBorder() {
+ // Don't override borders set by others.
+ if (!border_is_themed_border_)
+ return;
+
+ scoped_ptr<LabelButtonBorder> label_button_border = CreateDefaultBorder();
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ views::LinuxUI* linux_ui = views::LinuxUI::instance();
+ if (linux_ui) {
+ SetBorder(linux_ui->CreateNativeBorder(
+ this, label_button_border.Pass()));
+ } else
+#endif
+ {
+ SetBorder(label_button_border.PassAs<Border>());
+ }
+
+ border_is_themed_border_ = true;
+}
+
void LabelButton::StateChanged() {
const gfx::Size previous_image_size(image_->GetPreferredSize());
UpdateImage();
@@ -354,6 +411,9 @@ void LabelButton::ChildPreferredSizeChanged(View* child) {
void LabelButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
ResetColorsFromNativeTheme();
+ UpdateThemedBorder();
+ // Invalidate the layout to pickup the new insets from the border.
+ InvalidateLayout();
}
ui::NativeTheme::Part LabelButton::GetThemePart() const {
@@ -378,13 +438,6 @@ ui::NativeTheme::State LabelButton::GetThemeState(
}
const gfx::Animation* LabelButton::GetThemeAnimation() const {
-#if defined(OS_WIN)
- if (style() == STYLE_NATIVE_TEXTBUTTON &&
- GetNativeTheme() == ui::NativeThemeWin::instance()) {
- return ui::NativeThemeWin::instance()->IsThemingActive() ?
- hover_animation_.get() : NULL;
- }
-#endif
return hover_animation_.get();
}
diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h
index ad7e226ad5e..80beb3c90d5 100644
--- a/chromium/ui/views/controls/button/label_button.h
+++ b/chromium/ui/views/controls/button/label_button.h
@@ -8,7 +8,6 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/font.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/image_view.h"
@@ -17,6 +16,7 @@
namespace views {
+class LabelButtonBorder;
class Painter;
// LabelButton is an alternative to TextButton, it's not focusable by default.
@@ -28,7 +28,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
static const char kViewClassName[];
- LabelButton(ButtonListener* listener, const string16& text);
+ LabelButton(ButtonListener* listener, const base::string16& text);
virtual ~LabelButton();
// Get or set the image shown for the specified button state.
@@ -37,28 +37,37 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
void SetImage(ButtonState for_state, const gfx::ImageSkia& image);
// Get or set the text shown on the button.
- const string16& GetText() const;
- void SetText(const string16& text);
+ const base::string16& GetText() const;
+ virtual void SetText(const base::string16& text);
// Set the text color shown for the specified button state.
void SetTextColor(ButtonState for_state, SkColor color);
+ // Set drop shadows underneath the text.
+ void SetTextShadows(const gfx::ShadowValues& shadows);
+
+ // Sets whether subpixel rendering is used on the label.
+ void SetTextSubpixelRenderingEnabled(bool enabled);
+
// Get or set the text's multi-line property to break on '\n', etc.
bool GetTextMultiLine() const;
void SetTextMultiLine(bool text_multi_line);
- // Get or set the font used by this button.
- const gfx::Font& GetFont() const;
- void SetFont(const gfx::Font& font);
+ // Get or set the font list used by this button.
+ const gfx::FontList& GetFontList() const;
+ void SetFontList(const gfx::FontList& font_list);
// Set the elide behavior of this button.
- void SetElideBehavior(Label::ElideBehavior elide_behavior);
+ void SetElideBehavior(gfx::ElideBehavior elide_behavior);
// Get or set the horizontal alignment used for the button; reversed in RTL.
// The optional image will lead the text, unless the button is right-aligned.
gfx::HorizontalAlignment GetHorizontalAlignment() const;
void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
+ // Set the directionality mode used for the button text.
+ void SetDirectionalityMode(gfx::DirectionalityMode mode);
+
// Call set_min_size(gfx::Size()) to clear the monotonically increasing size.
void set_min_size(const gfx::Size& min_size) { min_size_ = min_size; }
void set_max_size(const gfx::Size& max_size) { max_size_ = max_size; }
@@ -72,9 +81,11 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
void SetStyle(ButtonStyle style);
void SetFocusPainter(scoped_ptr<Painter> focus_painter);
+ Painter* focus_painter() { return focus_painter_.get(); }
// View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual void SetBorder(scoped_ptr<Border> border) OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
@@ -82,10 +93,15 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
ImageView* image() const { return image_; }
Label* label() const { return label_; }
+ // Returns the available area for the label and image. Subclasses can change
+ // these bounds if they need room to do manual painting.
+ virtual gfx::Rect GetChildAreaBounds();
+
// View:
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
+ virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
// Fill |params| with information about the button.
virtual void GetExtraParams(ui::NativeTheme::ExtraParams* params) const;
@@ -93,9 +109,17 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
// Resets colors from the NativeTheme, explicitly set colors are unchanged.
virtual void ResetColorsFromNativeTheme();
+ // Creates the default border for this button. This can be overridden by
+ // subclasses or by LinuxUI.
+ virtual scoped_ptr<LabelButtonBorder> CreateDefaultBorder() const;
+
// Updates the image view to contain the appropriate button state image.
void UpdateImage();
+ // Updates the border as per the NativeTheme, unless a different border was
+ // set with SetBorder.
+ void UpdateThemedBorder();
+
// NativeThemeDelegate:
virtual gfx::Rect GetThemePaintRect() const OVERRIDE;
@@ -104,14 +128,13 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, Label);
FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, Image);
FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, LabelAndImage);
- FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, Font);
+ FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, FontList);
// CustomButton:
virtual void StateChanged() OVERRIDE;
// View:
virtual void ChildPreferredSizeChanged(View* child) OVERRIDE;
- virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
// NativeThemeDelegate:
virtual ui::NativeTheme::Part GetThemePart() const OVERRIDE;
@@ -127,6 +150,10 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
ImageView* image_;
Label* label_;
+ // The cached font lists in the normal and bold style.
+ gfx::FontList cached_normal_font_list_;
+ gfx::FontList cached_bold_font_list_;
+
// The images and colors for each button state.
gfx::ImageSkia button_state_images_[STATE_COUNT];
SkColor button_state_colors_[STATE_COUNT];
@@ -135,7 +162,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
bool explicitly_set_colors_[STATE_COUNT];
// |min_size_| increases monotonically with the preferred size.
- gfx::Size min_size_;
+ mutable gfx::Size min_size_;
// |max_size_| may be set to clamp the preferred size.
gfx::Size max_size_;
@@ -147,6 +174,9 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
// The button's overall style.
ButtonStyle style_;
+ // True if current border was set by UpdateThemedBorder. Defaults to true.
+ bool border_is_themed_border_;
+
scoped_ptr<Painter> focus_painter_;
DISALLOW_COPY_AND_ASSIGN(LabelButton);
diff --git a/chromium/ui/views/controls/button/label_button_border.cc b/chromium/ui/views/controls/button/label_button_border.cc
index d124764fd76..23e9319ded3 100644
--- a/chromium/ui/views/controls/button/label_button_border.cc
+++ b/chromium/ui/views/controls/button/label_button_border.cc
@@ -31,36 +31,20 @@ const int kButtonInsets = 5;
const int kTextHoveredImages[] = IMAGE_GRID(IDR_TEXTBUTTON_HOVER);
const int kTextPressedImages[] = IMAGE_GRID(IDR_TEXTBUTTON_PRESSED);
-Button::ButtonState GetButtonState(ui::NativeTheme::State state) {
- switch (state) {
- case ui::NativeTheme::kDisabled: return Button::STATE_DISABLED;
- case ui::NativeTheme::kHovered: return Button::STATE_HOVERED;
- case ui::NativeTheme::kNormal: return Button::STATE_NORMAL;
- case ui::NativeTheme::kPressed: return Button::STATE_PRESSED;
- case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state;
- }
- return Button::STATE_NORMAL;
-}
-
-// A helper function to paint the native theme or images as appropriate.
+// A helper function to paint the appropriate broder images.
void PaintHelper(LabelButtonBorder* border,
gfx::Canvas* canvas,
- const ui::NativeTheme* theme,
- ui::NativeTheme::Part part,
ui::NativeTheme::State state,
const gfx::Rect& rect,
const ui::NativeTheme::ExtraParams& extra) {
- if (border->style() == Button::STYLE_NATIVE_TEXTBUTTON) {
- theme->Paint(canvas->sk_canvas(), part, state, rect, extra);
- } else {
- Painter* painter =
- border->GetPainter(extra.button.is_focused, GetButtonState(state));
- // Paint any corresponding unfocused painter if there is no focused painter.
- if (!painter && extra.button.is_focused)
- painter = border->GetPainter(false, GetButtonState(state));
- if (painter)
- Painter::PaintPainterAt(canvas, painter, rect);
- }
+ Painter* painter =
+ border->GetPainter(extra.button.is_focused,
+ Button::GetButtonStateFrom(state));
+ // Paint any corresponding unfocused painter if there is no focused painter.
+ if (!painter && extra.button.is_focused)
+ painter = border->GetPainter(false, Button::GetButtonStateFrom(state));
+ if (painter)
+ Painter::PaintPainterAt(canvas, painter, rect);
}
} // namespace
@@ -105,8 +89,6 @@ LabelButtonBorder::LabelButtonBorder(Button::ButtonStyle style)
Painter::CreateImageGridPainter(kTextHoveredImages));
SetPainter(false, Button::STATE_PRESSED,
Painter::CreateImageGridPainter(kTextPressedImages));
- } else if (style == Button::STYLE_NATIVE_TEXTBUTTON) {
- set_insets(gfx::Insets(5, 12, 5, 12));
}
}
@@ -115,10 +97,8 @@ LabelButtonBorder::~LabelButtonBorder() {}
void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) {
const NativeThemeDelegate* native_theme_delegate =
static_cast<const LabelButton*>(&view);
- ui::NativeTheme::Part part = native_theme_delegate->GetThemePart();
gfx::Rect rect(native_theme_delegate->GetThemePaintRect());
ui::NativeTheme::ExtraParams extra;
- const ui::NativeTheme* theme = view.GetNativeTheme();
const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation();
ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra);
@@ -127,7 +107,7 @@ void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) {
const SkRect sk_rect = gfx::RectToSkRect(rect);
canvas->sk_canvas()->saveLayer(&sk_rect, NULL);
state = native_theme_delegate->GetBackgroundThemeState(&extra);
- PaintHelper(this, canvas, theme, part, state, rect, extra);
+ PaintHelper(this, canvas, state, rect, extra);
SkPaint paint;
skia::RefPtr<SkXfermode> sk_lerp_xfer =
@@ -135,18 +115,12 @@ void LabelButtonBorder::Paint(const View& view, gfx::Canvas* canvas) {
paint.setXfermode(sk_lerp_xfer.get());
canvas->sk_canvas()->saveLayer(&sk_rect, &paint);
state = native_theme_delegate->GetForegroundThemeState(&extra);
- PaintHelper(this, canvas, theme, part, state, rect, extra);
+ PaintHelper(this, canvas, state, rect, extra);
canvas->sk_canvas()->restore();
canvas->sk_canvas()->restore();
} else {
- PaintHelper(this, canvas, theme, part, state, rect, extra);
- }
-
- // For inverted color schemes, draw a solid fill with the button color.
- if (gfx::IsInvertedColorScheme()) {
- rect.Inset(insets_);
- canvas->FillRect(rect, extra.button.background_color);
+ PaintHelper(this, canvas, state, rect, extra);
}
}
diff --git a/chromium/ui/views/controls/button/label_button_unittest.cc b/chromium/ui/views/controls/button/label_button_unittest.cc
index fe2d1f670c1..74f77b702e6 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -2,14 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/controls/button/label_button.h"
+
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/size.h"
-#include "ui/views/controls/button/label_button.h"
+#include "ui/gfx/text_utils.h"
#include "ui/views/test/views_test_base.h"
+using base::ASCIIToUTF16;
+
namespace {
gfx::ImageSkia CreateTestImage(int width, int height) {
@@ -26,7 +30,7 @@ namespace views {
typedef ViewsTestBase LabelButtonTest;
TEST_F(LabelButtonTest, Init) {
- const string16 text(ASCIIToUTF16("abc"));
+ const base::string16 text(ASCIIToUTF16("abc"));
LabelButton button(NULL, text);
EXPECT_TRUE(button.GetImage(Button::STATE_NORMAL).isNull());
@@ -45,19 +49,19 @@ TEST_F(LabelButtonTest, Init) {
}
TEST_F(LabelButtonTest, Label) {
- LabelButton button(NULL, string16());
+ LabelButton button(NULL, base::string16());
EXPECT_TRUE(button.GetText().empty());
- const gfx::Font font;
- const string16 short_text(ASCIIToUTF16("abcdefghijklm"));
- const string16 long_text(ASCIIToUTF16("abcdefghijklmnopqrstuvwxyz"));
- const int short_text_width = gfx::Canvas::GetStringWidth(short_text, font);
- const int long_text_width = gfx::Canvas::GetStringWidth(long_text, font);
+ const gfx::FontList font_list;
+ const base::string16 short_text(ASCIIToUTF16("abcdefghijklm"));
+ const base::string16 long_text(ASCIIToUTF16("abcdefghijklmnopqrstuvwxyz"));
+ const int short_text_width = gfx::GetStringWidth(short_text, font_list);
+ const int long_text_width = gfx::GetStringWidth(long_text, font_list);
// The width increases monotonically with string size (it does not shrink).
EXPECT_LT(button.GetPreferredSize().width(), short_text_width);
button.SetText(short_text);
- EXPECT_GT(button.GetPreferredSize().height(), font.GetHeight());
+ EXPECT_GT(button.GetPreferredSize().height(), font_list.GetHeight());
EXPECT_GT(button.GetPreferredSize().width(), short_text_width);
EXPECT_LT(button.GetPreferredSize().width(), long_text_width);
button.SetText(long_text);
@@ -76,7 +80,7 @@ TEST_F(LabelButtonTest, Label) {
}
TEST_F(LabelButtonTest, Image) {
- LabelButton button(NULL, string16());
+ LabelButton button(NULL, base::string16());
const int small_size = 50, large_size = 100;
const gfx::ImageSkia small_image = CreateTestImage(small_size, small_size);
@@ -108,15 +112,15 @@ TEST_F(LabelButtonTest, Image) {
}
TEST_F(LabelButtonTest, LabelAndImage) {
- LabelButton button(NULL, string16());
+ LabelButton button(NULL, base::string16());
- const gfx::Font font;
- const string16 text(ASCIIToUTF16("abcdefghijklm"));
- const int text_width = gfx::Canvas::GetStringWidth(text, font);
+ const gfx::FontList font_list;
+ const base::string16 text(ASCIIToUTF16("abcdefghijklm"));
+ const int text_width = gfx::GetStringWidth(text, font_list);
const int image_size = 50;
const gfx::ImageSkia image = CreateTestImage(image_size, image_size);
- ASSERT_LT(font.GetHeight(), image_size);
+ ASSERT_LT(font_list.GetHeight(), image_size);
// The width increases monotonically with content size (it does not shrink).
EXPECT_LT(button.GetPreferredSize().width(), text_width);
@@ -124,7 +128,7 @@ TEST_F(LabelButtonTest, LabelAndImage) {
EXPECT_LT(button.GetPreferredSize().height(), image_size);
button.SetText(text);
EXPECT_GT(button.GetPreferredSize().width(), text_width);
- EXPECT_GT(button.GetPreferredSize().height(), font.GetHeight());
+ EXPECT_GT(button.GetPreferredSize().height(), font_list.GetHeight());
EXPECT_LT(button.GetPreferredSize().width(), text_width + image_size);
EXPECT_LT(button.GetPreferredSize().height(), image_size);
button.SetImage(Button::STATE_NORMAL, image);
@@ -146,7 +150,7 @@ TEST_F(LabelButtonTest, LabelAndImage) {
EXPECT_EQ(gfx::ALIGN_RIGHT, button.GetHorizontalAlignment());
EXPECT_LT(button.label_->bounds().right(), button.image_->bounds().x());
- button.SetText(string16());
+ button.SetText(base::string16());
EXPECT_GT(button.GetPreferredSize().width(), text_width + image_size);
EXPECT_GT(button.GetPreferredSize().height(), image_size);
button.SetImage(Button::STATE_NORMAL, gfx::ImageSkia());
@@ -164,24 +168,25 @@ TEST_F(LabelButtonTest, LabelAndImage) {
EXPECT_LT(button.GetPreferredSize().height(), image_size);
}
-TEST_F(LabelButtonTest, Font) {
- const string16 text(ASCIIToUTF16("abc"));
+TEST_F(LabelButtonTest, FontList) {
+ const base::string16 text(ASCIIToUTF16("abc"));
LabelButton button(NULL, text);
- const gfx::Font original_font = button.GetFont();
- const gfx::Font large_font = original_font.DeriveFont(100);
+ const gfx::FontList original_font_list = button.GetFontList();
+ const gfx::FontList large_font_list =
+ original_font_list.DeriveWithSizeDelta(100);
const int original_width = button.GetPreferredSize().width();
const int original_height = button.GetPreferredSize().height();
// The button size increases when the font size is increased.
- button.SetFont(large_font);
+ button.SetFontList(large_font_list);
EXPECT_GT(button.GetPreferredSize().width(), original_width);
EXPECT_GT(button.GetPreferredSize().height(), original_height);
// The button returns to its original size when the minimal size is cleared
// and the original font size is restored.
button.set_min_size(gfx::Size());
- button.SetFont(original_font);
+ button.SetFontList(original_font_list);
EXPECT_EQ(original_width, button.GetPreferredSize().width());
EXPECT_EQ(original_height, button.GetPreferredSize().height());
}
diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc
index 728c0371f1c..29271cea51f 100644
--- a/chromium/ui/views/controls/button/menu_button.cc
+++ b/chromium/ui/views/controls/button/menu_button.cc
@@ -7,7 +7,7 @@
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
#include "grit/ui_strings.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -16,6 +16,7 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/text_constants.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/mouse_constants.h"
@@ -43,10 +44,10 @@ const int MenuButton::kMenuMarkerPaddingRight = -1;
////////////////////////////////////////////////////////////////////////////////
MenuButton::MenuButton(ButtonListener* listener,
- const string16& text,
+ const base::string16& text,
MenuButtonListener* menu_button_listener,
bool show_menu_marker)
- : TextButton(listener, text),
+ : LabelButton(listener, text),
menu_visible_(false),
menu_offset_(kDefaultMenuOffsetX, kDefaultMenuOffsetY),
listener_(menu_button_listener),
@@ -54,7 +55,7 @@ MenuButton::MenuButton(ButtonListener* listener,
menu_marker_(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
IDR_MENU_DROPARROW).ToImageSkia()),
destroyed_flag_(NULL) {
- set_alignment(TextButton::ALIGN_LEFT);
+ SetHorizontalAlignment(gfx::ALIGN_LEFT);
}
MenuButton::~MenuButton() {
@@ -133,8 +134,8 @@ bool MenuButton::Activate() {
return true;
}
-void MenuButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
- TextButton::PaintButton(canvas, mode);
+void MenuButton::OnPaint(gfx::Canvas* canvas) {
+ LabelButton::OnPaint(canvas);
if (show_menu_marker_)
PaintMenuMarker(canvas);
@@ -146,8 +147,8 @@ void MenuButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
//
////////////////////////////////////////////////////////////////////////////////
-gfx::Size MenuButton::GetPreferredSize() {
- gfx::Size prefsize = TextButton::GetPreferredSize();
+gfx::Size MenuButton::GetPreferredSize() const {
+ gfx::Size prefsize = LabelButton::GetPreferredSize();
if (show_menu_marker_) {
prefsize.Enlarge(menu_marker_->width() + kMenuMarkerPaddingLeft +
kMenuMarkerPaddingRight,
@@ -186,7 +187,7 @@ void MenuButton::OnMouseReleased(const ui::MouseEvent& event) {
HitTestPoint(event.location())) {
Activate();
} else {
- TextButton::OnMouseReleased(event);
+ LabelButton::OnMouseReleased(event);
}
}
@@ -202,12 +203,14 @@ void MenuButton::OnMouseExited(const ui::MouseEvent& event) {
}
void MenuButton::OnGestureEvent(ui::GestureEvent* event) {
- if (state() != STATE_DISABLED && event->type() == ui::ET_GESTURE_TAP) {
- if (Activate())
- event->StopPropagation();
+ if (state() != STATE_DISABLED && event->type() == ui::ET_GESTURE_TAP &&
+ !Activate()) {
+ // When |Activate()| returns |false|, it means that a menu is shown and
+ // has handled the gesture event. So, there is no need to further process
+ // the gesture event here.
return;
}
- TextButton::OnGestureEvent(event);
+ LabelButton::OnGestureEvent(event);
}
bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) {
@@ -220,16 +223,12 @@ bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) {
case ui::VKEY_UP:
case ui::VKEY_DOWN: {
// WARNING: we may have been deleted by the time Activate returns.
- bool ret = Activate();
-#if defined(USE_AURA)
- // This is to prevent the keyboard event from being dispatched twice.
- // The Activate function returns false in most cases. In AURA if the
- // keyboard event is not handled, we pass it to the default handler
- // which dispatches the event back to us causing the menu to get
- // displayed again.
- ret = true;
-#endif
- return ret;
+ Activate();
+ // This is to prevent the keyboard event from being dispatched twice. If
+ // the keyboard event is not handled, we pass it to the default handler
+ // which dispatches the event back to us causing the menu to get displayed
+ // again. Return true to prevent this.
+ return true;
}
default:
break;
@@ -244,11 +243,11 @@ bool MenuButton::OnKeyReleased(const ui::KeyEvent& event) {
return false;
}
-void MenuButton::GetAccessibleState(ui::AccessibleViewState* state) {
+void MenuButton::GetAccessibleState(ui::AXViewState* state) {
CustomButton::GetAccessibleState(state);
- state->role = ui::AccessibilityTypes::ROLE_BUTTONMENU;
+ state->role = ui::AX_ROLE_POP_UP_BUTTON;
state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS);
- state->state = ui::AccessibilityTypes::STATE_HASPOPUP;
+ state->AddStateFlag(ui::AX_STATE_HASPOPUP);
}
void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) {
@@ -267,6 +266,17 @@ void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) {
canvas->DrawImageInt(*menu_marker_, arrow_bounds.x(), arrow_bounds.y());
}
+gfx::Rect MenuButton::GetChildAreaBounds() {
+ gfx::Size s = size();
+
+ if (show_menu_marker_) {
+ s.set_width(s.width() - menu_marker_->width() - kMenuMarkerPaddingLeft -
+ kMenuMarkerPaddingRight);
+ }
+
+ return gfx::Rect(s);
+}
+
int MenuButton::GetMaximumScreenXCoordinate() {
if (!GetWidget()) {
NOTREACHED();
diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h
index 2262dab4637..257d2f62ea9 100644
--- a/chromium/ui/views/controls/button/menu_button.h
+++ b/chromium/ui/views/controls/button/menu_button.h
@@ -9,9 +9,8 @@
#include "base/strings/string16.h"
#include "base/time/time.h"
-#include "ui/gfx/font.h"
#include "ui/views/background.h"
-#include "ui/views/controls/button/text_button.h"
+#include "ui/views/controls/button/label_button.h"
namespace views {
@@ -24,7 +23,7 @@ class MenuButtonListener;
// A button that shows a menu when the left mouse button is pushed
//
////////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT MenuButton : public TextButton {
+class VIEWS_EXPORT MenuButton : public LabelButton {
public:
static const char kViewClassName[];
@@ -34,7 +33,7 @@ class VIEWS_EXPORT MenuButton : public TextButton {
// Create a Button.
MenuButton(ButtonListener* listener,
- const string16& text,
+ const base::string16& text,
MenuButtonListener* menu_button_listener,
bool show_menu_marker);
virtual ~MenuButton();
@@ -51,24 +50,25 @@ class VIEWS_EXPORT MenuButton : public TextButton {
// Activate the button (called when the button is pressed).
virtual bool Activate();
- // Overridden from TextButton for the potential use of a drop marker.
- virtual void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) OVERRIDE;
-
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
+ virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
protected:
// Paint the menu marker image.
void PaintMenuMarker(gfx::Canvas* canvas);
+ // Overridden from LabelButton:
+ virtual gfx::Rect GetChildAreaBounds() OVERRIDE;
+
// True if the menu is currently visible.
bool menu_visible_;
diff --git a/chromium/ui/views/controls/button/menu_button_unittest.cc b/chromium/ui/views/controls/button/menu_button_unittest.cc
new file mode 100644
index 00000000000..6a18b21b104
--- /dev/null
+++ b/chromium/ui/views/controls/button/menu_button_unittest.cc
@@ -0,0 +1,199 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/button/menu_button.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/views/controls/button/menu_button_listener.h"
+#include "ui/views/test/views_test_base.h"
+
+using base::ASCIIToUTF16;
+
+namespace views {
+
+class MenuButtonTest : public ViewsTestBase {
+ public:
+ MenuButtonTest() : widget_(NULL), button_(NULL) {}
+ virtual ~MenuButtonTest() {}
+
+ virtual void TearDown() OVERRIDE {
+ if (widget_ && !widget_->IsClosed())
+ widget_->Close();
+
+ ViewsTestBase::TearDown();
+ }
+
+ Widget* widget() { return widget_; }
+ MenuButton* button() { return button_; }
+
+ protected:
+ // Creates a MenuButton with a ButtonListener. In this case, the MenuButton
+ // acts like a regular button.
+ void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) {
+ CreateWidget();
+
+ const base::string16 label(ASCIIToUTF16("button"));
+ button_ = new MenuButton(button_listener, label, NULL, false);
+ button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
+ widget_->SetContentsView(button_);
+
+ widget_->Show();
+ }
+
+ // Creates a MenuButton with a MenuButtonListener. In this case, when the
+ // MenuButton is pushed, it notifies the MenuButtonListener to open a
+ // drop-down menu.
+ void CreateMenuButtonWithMenuButtonListener(
+ MenuButtonListener* menu_button_listener) {
+ CreateWidget();
+
+ const base::string16 label(ASCIIToUTF16("button"));
+ button_ = new MenuButton(NULL, label, menu_button_listener, false);
+ button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
+ widget_->SetContentsView(button_);
+
+ widget_->Show();
+ }
+
+ private:
+ void CreateWidget() {
+ DCHECK(!widget_);
+
+ widget_ = new Widget;
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ widget_->Init(params);
+ }
+
+ Widget* widget_;
+ MenuButton* button_;
+};
+
+class TestButtonListener : public ButtonListener {
+ public:
+ TestButtonListener()
+ : last_sender_(NULL),
+ last_sender_state_(Button::STATE_NORMAL),
+ last_event_type_(ui::ET_UNKNOWN) {}
+ virtual ~TestButtonListener() {}
+
+ virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE {
+ last_sender_ = sender;
+ CustomButton* custom_button = CustomButton::AsCustomButton(sender);
+ DCHECK(custom_button);
+ last_sender_state_ = custom_button->state();
+ last_event_type_ = event.type();
+ }
+
+ Button* last_sender() { return last_sender_; }
+ Button::ButtonState last_sender_state() { return last_sender_state_; }
+ ui::EventType last_event_type() { return last_event_type_; }
+
+ private:
+ Button* last_sender_;
+ Button::ButtonState last_sender_state_;
+ ui::EventType last_event_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestButtonListener);
+};
+
+class TestMenuButtonListener : public MenuButtonListener {
+ public:
+ TestMenuButtonListener() {}
+ virtual ~TestMenuButtonListener() {}
+
+ virtual void OnMenuButtonClicked(View* source,
+ const gfx::Point& /*point*/) OVERRIDE {
+ last_source_ = source;
+ CustomButton* custom_button = CustomButton::AsCustomButton(source);
+ DCHECK(custom_button);
+ last_source_state_ = custom_button->state();
+ }
+
+ View* last_source() { return last_source_; }
+ Button::ButtonState last_source_state() { return last_source_state_; }
+
+ private:
+ View* last_source_;
+ Button::ButtonState last_source_state_;
+};
+
+// Tests if the listener is notified correctly, when a mouse click happens on a
+// MenuButton that has a regular ButtonListener.
+TEST_F(MenuButtonTest, ActivateNonDropDownOnMouseClick) {
+ scoped_ptr<TestButtonListener> button_listener(new TestButtonListener);
+ CreateMenuButtonWithButtonListener(button_listener.get());
+
+ aura::test::EventGenerator generator(
+ widget()->GetNativeView()->GetRootWindow());
+
+ generator.set_current_location(gfx::Point(10, 10));
+ generator.ClickLeftButton();
+
+ // Check that MenuButton has notified the listener on mouse-released event,
+ // while it was in hovered state.
+ EXPECT_EQ(button(), button_listener->last_sender());
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, button_listener->last_event_type());
+ EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state());
+}
+
+// Tests if the listener is notified correctly when a gesture tap happens on a
+// MenuButton that has a regular ButtonListener.
+TEST_F(MenuButtonTest, ActivateNonDropDownOnGestureTap) {
+ scoped_ptr<TestButtonListener> button_listener(new TestButtonListener);
+ CreateMenuButtonWithButtonListener(button_listener.get());
+
+ aura::test::EventGenerator generator(
+ widget()->GetNativeView()->GetRootWindow());
+
+ generator.GestureTapAt(gfx::Point(10, 10));
+
+ // Check that MenuButton has notified the listener on gesture tap event, while
+ // it was in hovered state.
+ EXPECT_EQ(button(), button_listener->last_sender());
+ EXPECT_EQ(ui::ET_GESTURE_TAP, button_listener->last_event_type());
+ EXPECT_EQ(Button::STATE_HOVERED, button_listener->last_sender_state());
+}
+
+// Tests if the listener is notified correctly when a mouse click happens on a
+// MenuButton that has a MenuButtonListener.
+TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
+ scoped_ptr<TestMenuButtonListener> menu_button_listener(
+ new TestMenuButtonListener);
+ CreateMenuButtonWithMenuButtonListener(menu_button_listener.get());
+
+ aura::test::EventGenerator generator(
+ widget()->GetNativeView()->GetRootWindow());
+
+ generator.set_current_location(gfx::Point(10, 10));
+ generator.ClickLeftButton();
+
+ // Check that MenuButton has notified the listener, while it was in pressed
+ // state.
+ EXPECT_EQ(button(), menu_button_listener->last_source());
+ EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state());
+}
+
+// Tests if the listener is notified correctly when a gesture tap happens on a
+// MenuButton that has a MenuButtonListener.
+TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) {
+ scoped_ptr<TestMenuButtonListener> menu_button_listener(
+ new TestMenuButtonListener);
+ CreateMenuButtonWithMenuButtonListener(menu_button_listener.get());
+
+ aura::test::EventGenerator generator(
+ widget()->GetNativeView()->GetRootWindow());
+
+ generator.GestureTapAt(gfx::Point(10, 10));
+
+ // Check that MenuButton has notified the listener, while it was in pressed
+ // state.
+ EXPECT_EQ(button(), menu_button_listener->last_source());
+ EXPECT_EQ(Button::STATE_PRESSED, menu_button_listener->last_source_state());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/button/radio_button.cc b/chromium/ui/views/controls/button/radio_button.cc
index 224e9893873..a015d5e1da8 100644
--- a/chromium/ui/views/controls/button/radio_button.cc
+++ b/chromium/ui/views/controls/button/radio_button.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "grit/ui_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/widget/widget.h"
@@ -15,7 +15,7 @@ namespace views {
// static
const char RadioButton::kViewClassName[] = "RadioButton";
-RadioButton::RadioButton(const string16& label, int group_id)
+RadioButton::RadioButton(const base::string16& label, int group_id)
: Checkbox(label) {
SetGroup(group_id);
@@ -94,9 +94,9 @@ const char* RadioButton::GetClassName() const {
return kViewClassName;
}
-void RadioButton::GetAccessibleState(ui::AccessibleViewState* state) {
+void RadioButton::GetAccessibleState(ui::AXViewState* state) {
Checkbox::GetAccessibleState(state);
- state->role = ui::AccessibilityTypes::ROLE_RADIOBUTTON;
+ state->role = ui::AX_ROLE_RADIO_BUTTON;
}
View* RadioButton::GetSelectedViewForGroup(int group) {
@@ -123,7 +123,7 @@ bool RadioButton::IsGroupFocusTraversable() const {
void RadioButton::OnFocus() {
Checkbox::OnFocus();
SetChecked(true);
- ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), 0);
+ ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), 0, 0);
LabelButton::NotifyClick(event);
}
diff --git a/chromium/ui/views/controls/button/radio_button.h b/chromium/ui/views/controls/button/radio_button.h
index a7afff4ed41..edbb2c694cd 100644
--- a/chromium/ui/views/controls/button/radio_button.h
+++ b/chromium/ui/views/controls/button/radio_button.h
@@ -17,12 +17,12 @@ class VIEWS_EXPORT RadioButton : public Checkbox {
// The button's class name.
static const char kViewClassName[];
- RadioButton(const string16& label, int group_id);
+ RadioButton(const base::string16& label, int group_id);
virtual ~RadioButton();
// Overridden from View:
virtual const char* GetClassName() const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual View* GetSelectedViewForGroup(int group) OVERRIDE;
virtual bool IsGroupFocusTraversable() const OVERRIDE;
virtual void OnFocus() OVERRIDE;
@@ -30,7 +30,7 @@ class VIEWS_EXPORT RadioButton : public Checkbox {
// Overridden from Button:
virtual void NotifyClick(const ui::Event& event) OVERRIDE;
- // Overridden from TextButtonBase:
+ // Overridden from LabelButton:
virtual ui::NativeTheme::Part GetThemePart() const OVERRIDE;
// Overridden from Checkbox:
diff --git a/chromium/ui/views/controls/button/text_button.cc b/chromium/ui/views/controls/button/text_button.cc
index e829405b9f4..bf12f8e086d 100644
--- a/chromium/ui/views/controls/button/text_button.cc
+++ b/chromium/ui/views/controls/button/text_button.cc
@@ -88,14 +88,6 @@ void TextButtonBorder::SetInsets(const gfx::Insets& insets) {
insets_ = insets;
}
-TextButtonBorder* TextButtonBorder::AsTextButtonBorder() {
- return this;
-}
-
-const TextButtonBorder* TextButtonBorder::AsTextButtonBorder() const {
- return this;
-}
-
// TextButtonDefaultBorder ----------------------------------------------------
@@ -199,15 +191,10 @@ void TextButtonNativeThemeBorder::Paint(const View& view, gfx::Canvas* canvas) {
// TextButtonBase -------------------------------------------------------------
-TextButtonBase::TextButtonBase(ButtonListener* listener, const string16& text)
+TextButtonBase::TextButtonBase(ButtonListener* listener,
+ const base::string16& text)
: CustomButton(listener),
alignment_(ALIGN_LEFT),
- font_(ResourceBundle::GetSharedInstance().GetFont(
- ResourceBundle::BaseFont)),
- has_text_shadow_(false),
- active_text_shadow_color_(0),
- inactive_text_shadow_color_(0),
- text_shadow_offset_(gfx::Point(1, 1)),
min_width_(0),
min_height_(0),
max_width_(0),
@@ -220,8 +207,6 @@ TextButtonBase::TextButtonBase(ButtonListener* listener, const string16& text)
use_hover_color_from_theme_(true),
focus_painter_(Painter::CreateDashedFocusPainter()) {
SetText(text);
- // OnNativeThemeChanged sets the color member variables.
- TextButtonBase::OnNativeThemeChanged(GetNativeTheme());
SetAnimationDuration(kHoverAnimationDurationMs);
}
@@ -239,7 +224,7 @@ void TextButtonBase::SetIsDefault(bool is_default) {
SchedulePaint();
}
-void TextButtonBase::SetText(const string16& text) {
+void TextButtonBase::SetText(const base::string16& text) {
if (text == text_)
return;
text_ = text;
@@ -247,8 +232,8 @@ void TextButtonBase::SetText(const string16& text) {
UpdateTextSize();
}
-void TextButtonBase::SetFont(const gfx::Font& font) {
- font_ = font;
+void TextButtonBase::SetFontList(const gfx::FontList& font_list) {
+ font_list_ = font_list;
UpdateTextSize();
}
@@ -274,21 +259,6 @@ void TextButtonBase::SetHoverColor(SkColor color) {
use_hover_color_from_theme_ = false;
}
-void TextButtonBase::SetTextShadowColors(SkColor active_color,
- SkColor inactive_color) {
- active_text_shadow_color_ = active_color;
- inactive_text_shadow_color_ = inactive_color;
- has_text_shadow_ = true;
-}
-
-void TextButtonBase::SetTextShadowOffset(int x, int y) {
- text_shadow_offset_.SetPoint(x, y);
-}
-
-void TextButtonBase::ClearEmbellishing() {
- has_text_shadow_ = false;
-}
-
void TextButtonBase::ClearMaxTextSize() {
max_text_size_ = text_size_;
}
@@ -306,7 +276,7 @@ void TextButtonBase::SetMultiLine(bool multi_line) {
}
}
-gfx::Size TextButtonBase::GetPreferredSize() {
+gfx::Size TextButtonBase::GetPreferredSize() const {
gfx::Insets insets = GetInsets();
// Use the max size to set the button boundaries.
@@ -326,7 +296,7 @@ gfx::Size TextButtonBase::GetPreferredSize() {
return prefsize;
}
-int TextButtonBase::GetHeightForWidth(int w) {
+int TextButtonBase::GetHeightForWidth(int w) const {
if (!multi_line_)
return View::GetHeightForWidth(w);
@@ -377,17 +347,51 @@ void TextButtonBase::UpdateTextSize() {
}
}
-void TextButtonBase::CalculateTextSize(gfx::Size* text_size, int max_width) {
- int h = font_.GetHeight();
+void TextButtonBase::CalculateTextSize(gfx::Size* text_size,
+ int max_width) const {
+ int h = font_list_.GetHeight();
int w = multi_line_ ? max_width : 0;
int flags = ComputeCanvasStringFlags();
if (!multi_line_)
flags |= gfx::Canvas::NO_ELLIPSIS;
- gfx::Canvas::SizeStringInt(text_, font_, &w, &h, 0, flags);
+ gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, 0, flags);
text_size->SetSize(w, h);
}
+void TextButtonBase::OnPaintText(gfx::Canvas* canvas, PaintButtonMode mode) {
+ gfx::Rect text_bounds(GetTextBounds());
+ if (text_bounds.width() > 0) {
+ // Because the text button can (at times) draw multiple elements on the
+ // canvas, we can not mirror the button by simply flipping the canvas as
+ // doing this will mirror the text itself. Flipping the canvas will also
+ // make the icons look wrong because icons are almost always represented as
+ // direction-insensitive images and such images should never be flipped
+ // horizontally.
+ //
+ // Due to the above, we must perform the flipping manually for RTL UIs.
+ text_bounds.set_x(GetMirroredXForRect(text_bounds));
+
+ SkColor text_color = (show_multiple_icon_states_ &&
+ (state() == STATE_HOVERED || state() == STATE_PRESSED)) ?
+ color_hover_ : color_;
+
+ int draw_string_flags = gfx::Canvas::DefaultCanvasTextAlignment() |
+ ComputeCanvasStringFlags();
+
+ if (mode == PB_FOR_DRAG) {
+ // Disable sub-pixel rendering as background is transparent.
+ draw_string_flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
+ canvas->DrawStringRectWithHalo(text_, font_list_,
+ SK_ColorBLACK, SK_ColorWHITE,
+ text_bounds, draw_string_flags);
+ } else {
+ canvas->DrawStringRectWithFlags(text_, font_list_, text_color,
+ text_bounds, draw_string_flags);
+ }
+ }
+}
+
int TextButtonBase::ComputeCanvasStringFlags() const {
if (!multi_line_)
return 0;
@@ -475,59 +479,10 @@ void TextButtonBase::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
}
- gfx::Rect text_bounds(GetTextBounds());
- if (text_bounds.width() > 0) {
- // Because the text button can (at times) draw multiple elements on the
- // canvas, we can not mirror the button by simply flipping the canvas as
- // doing this will mirror the text itself. Flipping the canvas will also
- // make the icons look wrong because icons are almost always represented as
- // direction-insensitive images and such images should never be flipped
- // horizontally.
- //
- // Due to the above, we must perform the flipping manually for RTL UIs.
- text_bounds.set_x(GetMirroredXForRect(text_bounds));
-
- SkColor text_color = (show_multiple_icon_states_ &&
- (state() == STATE_HOVERED || state() == STATE_PRESSED)) ?
- color_hover_ : color_;
-
- int draw_string_flags = gfx::Canvas::DefaultCanvasTextAlignment() |
- ComputeCanvasStringFlags();
-
- if (mode == PB_FOR_DRAG) {
- // Disable sub-pixel rendering as background is transparent.
- draw_string_flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
-
-#if defined(OS_WIN)
- // TODO(erg): Either port DrawStringWithHalo to linux or find an
- // alternative here.
- canvas->DrawStringWithHalo(text_, font_, SK_ColorBLACK, SK_ColorWHITE,
- text_bounds.x(), text_bounds.y(), text_bounds.width(),
- text_bounds.height(), draw_string_flags);
-#else
- canvas->DrawStringInt(text_,
- font_,
- text_color,
- text_bounds.x(),
- text_bounds.y(),
- text_bounds.width(),
- text_bounds.height(),
- draw_string_flags);
-#endif
- } else {
- gfx::ShadowValues shadows;
- if (has_text_shadow_) {
- SkColor color = GetWidget()->IsActive() ? active_text_shadow_color_ :
- inactive_text_shadow_color_;
- shadows.push_back(gfx::ShadowValue(text_shadow_offset_, 0, color));
- }
- canvas->DrawStringWithShadows(text_, font_, text_color, text_bounds,
- 0, draw_string_flags, shadows);
- }
- }
+ OnPaintText(canvas, mode);
}
-gfx::Size TextButtonBase::GetMinimumSize() {
+gfx::Size TextButtonBase::GetMinimumSize() const {
return max_text_size_;
}
@@ -609,14 +564,15 @@ ui::NativeTheme::State TextButtonBase::GetForegroundThemeState(
// TextButton -----------------------------------------------------------------
-TextButton::TextButton(ButtonListener* listener, const string16& text)
+TextButton::TextButton(ButtonListener* listener, const base::string16& text)
: TextButtonBase(listener, text),
icon_placement_(ICON_ON_LEFT),
has_hover_icon_(false),
has_pushed_icon_(false),
icon_text_spacing_(kDefaultIconTextSpacing),
- ignore_minimum_size_(true) {
- set_border(new TextButtonDefaultBorder);
+ ignore_minimum_size_(true),
+ full_justification_(false) {
+ SetBorder(scoped_ptr<Border>(new TextButtonDefaultBorder));
SetFocusPainter(Painter::CreateDashedFocusPainterWithInsets(
gfx::Insets(kFocusRectInset, kFocusRectInset,
kFocusRectInset, kFocusRectInset)));
@@ -642,7 +598,7 @@ void TextButton::SetPushedIcon(const gfx::ImageSkia& icon) {
SchedulePaint();
}
-gfx::Size TextButton::GetPreferredSize() {
+gfx::Size TextButton::GetPreferredSize() const {
gfx::Size prefsize(TextButtonBase::GetPreferredSize());
prefsize.Enlarge(icon_.width(), 0);
prefsize.set_height(std::max(prefsize.height(), icon_.height()));
@@ -657,8 +613,8 @@ gfx::Size TextButton::GetPreferredSize() {
#if defined(OS_WIN)
// Clamp the size returned to at least the minimum size.
if (!ignore_minimum_size_) {
- gfx::PlatformFontWin* platform_font =
- static_cast<gfx::PlatformFontWin*>(font_.platform_font());
+ gfx::PlatformFontWin* platform_font = static_cast<gfx::PlatformFontWin*>(
+ font_list_.GetPrimaryFont().platform_font());
prefsize.set_width(std::max(
prefsize.width(),
platform_font->horizontal_dlus_to_pixels(kMinWidthDLUs)));
@@ -675,22 +631,37 @@ gfx::Size TextButton::GetPreferredSize() {
}
void TextButton::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
+ if (full_justification_ && icon_placement_ == ICON_ON_LEFT)
+ set_alignment(ALIGN_RIGHT);
+
TextButtonBase::PaintButton(canvas, mode);
+ OnPaintIcon(canvas, mode);
+}
+void TextButton::OnPaintIcon(gfx::Canvas* canvas, PaintButtonMode mode) {
const gfx::ImageSkia& icon = GetImageToPaint();
if (icon.width() > 0) {
gfx::Rect text_bounds = GetTextBounds();
- int icon_x;
+ int icon_x = 0;
int spacing = text_.empty() ? 0 : icon_text_spacing_;
gfx::Insets insets = GetInsets();
- if (icon_placement_ == ICON_ON_LEFT) {
- icon_x = text_bounds.x() - icon.width() - spacing;
- } else if (icon_placement_ == ICON_ON_RIGHT) {
- icon_x = text_bounds.right() + spacing;
- } else { // ICON_CENTERED
- DCHECK(text_.empty());
- icon_x = (width() - insets.width() - icon.width()) / 2 + insets.left();
+ switch (icon_placement_) {
+ case ICON_ON_LEFT:
+ icon_x = full_justification_ ? insets.left()
+ : text_bounds.x() - icon.width() - spacing;
+ break;
+ case ICON_ON_RIGHT:
+ icon_x = full_justification_ ? width() - insets.right() - icon.width()
+ : text_bounds.right() + spacing;
+ break;
+ case ICON_CENTERED:
+ DCHECK(text_.empty());
+ icon_x = (width() - insets.width() - icon.width()) / 2 + insets.left();
+ break;
+ default:
+ NOTREACHED();
+ break;
}
int available_height = height() - insets.height();
@@ -707,6 +678,10 @@ void TextButton::set_ignore_minimum_size(bool ignore_minimum_size) {
ignore_minimum_size_ = ignore_minimum_size;
}
+void TextButton::set_full_justification(bool full_justification) {
+ full_justification_ = full_justification;
+}
+
const char* TextButton::GetClassName() const {
return kViewClassName;
}
diff --git a/chromium/ui/views/controls/button/text_button.h b/chromium/ui/views/controls/button/text_button.h
index 4dc61577803..49c4f3f8c17 100644
--- a/chromium/ui/views/controls/button/text_button.h
+++ b/chromium/ui/views/controls/button/text_button.h
@@ -11,7 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/custom_button.h"
@@ -35,10 +35,6 @@ class VIEWS_EXPORT TextButtonBorder : public Border {
virtual gfx::Size GetMinimumSize() const OVERRIDE;
private:
- // Border:
- virtual TextButtonBorder* AsTextButtonBorder() OVERRIDE;
- virtual const TextButtonBorder* AsTextButtonBorder() const OVERRIDE;
-
gfx::Insets insets_;
DISALLOW_COPY_AND_ASSIGN(TextButtonBorder);
@@ -112,8 +108,8 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
// Call SetText once per string in your set of possible values at button
// creation time, so that it can contain the largest of them and avoid
// resizing the button when the text changes.
- virtual void SetText(const string16& text);
- const string16& text() const { return text_; }
+ virtual void SetText(const base::string16& text);
+ const base::string16& text() const { return text_; }
enum TextAlignment {
ALIGN_LEFT,
@@ -143,24 +139,14 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
void set_min_width(int min_width) { min_width_ = min_width; }
void set_min_height(int min_height) { min_height_ = min_height; }
void set_max_width(int max_width) { max_width_ = max_width; }
- void SetFont(const gfx::Font& font);
- // Return the font used by this button.
- gfx::Font font() const { return font_; }
+ const gfx::FontList& font_list() const { return font_list_; }
+ void SetFontList(const gfx::FontList& font_list);
void SetEnabledColor(SkColor color);
void SetDisabledColor(SkColor color);
void SetHighlightColor(SkColor color);
void SetHoverColor(SkColor color);
- // Enables a drop shadow underneath the text.
- void SetTextShadowColors(SkColor active_color, SkColor inactive_color);
-
- // Sets the drop shadow's offset from the text.
- void SetTextShadowOffset(int x, int y);
-
- // Disables shadows.
- void ClearEmbellishing();
-
// Sets whether or not to show the hot and pushed states for the button icon
// (if present) in addition to the normal state. Defaults to true.
bool show_multiple_icon_states() const { return show_multiple_icon_states_; }
@@ -175,9 +161,9 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
virtual void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode);
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
- virtual int GetHeightForWidth(int w) OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual int GetHeightForWidth(int w) const OVERRIDE;
virtual void OnEnabledChanged() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
@@ -185,18 +171,23 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
protected:
- TextButtonBase(ButtonListener* listener, const string16& text);
+ TextButtonBase(ButtonListener* listener, const base::string16& text);
// Called when enabled or disabled state changes, or the colors for those
// states change.
virtual void UpdateColor();
// Updates text_size_ and max_text_size_ from the current text/font. This is
- // invoked when the font or text changes.
+ // invoked when the font list or text changes.
void UpdateTextSize();
// Calculate the size of the text size without setting any of the members.
- void CalculateTextSize(gfx::Size* text_size, int max_width);
+ void CalculateTextSize(gfx::Size* text_size, int max_width) const;
+
+ // Paint the button's text into the specified canvas. If |mode| is
+ // |PB_FOR_DRAG|, the function paints a drag image representation. Derived
+ // can override this function to change only the text rendering.
+ virtual void OnPaintText(gfx::Canvas* canvas, PaintButtonMode mode);
void set_color_enabled(SkColor color) { color_enabled_ = color; }
void set_color_disabled(SkColor color) { color_disabled_ = color; }
@@ -239,10 +230,10 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
gfx::Rect GetContentBounds(int extra_width) const;
// The text string that is displayed in the button.
- string16 text_;
+ base::string16 text_;
// The size of the text string.
- gfx::Size text_size_;
+ mutable gfx::Size text_size_;
// Track the size of the largest text string seen so far, so that
// changing text_ will not resize the button boundary.
@@ -251,16 +242,8 @@ class VIEWS_EXPORT TextButtonBase : public CustomButton,
// The alignment of the text string within the button.
TextAlignment alignment_;
- // The font used to paint the text.
- gfx::Font font_;
-
- // Flag indicating if a shadow should be drawn behind the text.
- bool has_text_shadow_;
- // Optional shadow text colors for active and inactive widget states.
- SkColor active_text_shadow_color_;
- SkColor inactive_text_shadow_color_;
- // Space between the text and its shadow. Defaults to (1,1).
- gfx::Point text_shadow_offset_;
+ // The font list used to paint the text.
+ gfx::FontList font_list_;
// The dimensions of the button will be at least these values.
int min_width_;
@@ -310,7 +293,7 @@ class VIEWS_EXPORT TextButton : public TextButtonBase {
// The button's class name.
static const char kViewClassName[];
- TextButton(ButtonListener* listener, const string16& text);
+ TextButton(ButtonListener* listener, const base::string16& text);
virtual ~TextButton();
void set_icon_text_spacing(int icon_text_spacing) {
@@ -340,14 +323,21 @@ class VIEWS_EXPORT TextButton : public TextButtonBase {
void set_ignore_minimum_size(bool ignore_minimum_size);
+ void set_full_justification(bool full_justification);
+
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
// Overridden from TextButtonBase:
virtual void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) OVERRIDE;
protected:
+ // Paint the button's icon into the specified canvas. If |mode| is
+ // |PB_FOR_DRAG|, the function paints a drag image representation. Derived
+ // can override this function to change only the icon rendering.
+ virtual void OnPaintIcon(gfx::Canvas* canvas, PaintButtonMode mode);
+
gfx::ImageSkia icon() const { return icon_; }
virtual const gfx::ImageSkia& GetImageToPaint() const;
@@ -382,6 +372,10 @@ class VIEWS_EXPORT TextButton : public TextButtonBase {
// is true. Set to false to prevent narrower buttons.
bool ignore_minimum_size_;
+ // True if the icon and the text are aligned along both the left and right
+ // margins of the button.
+ bool full_justification_;
+
DISALLOW_COPY_AND_ASSIGN(TextButton);
};
diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc
index 7feb5ffd0a7..b2a456d4906 100644
--- a/chromium/ui/views/controls/combobox/combobox.cc
+++ b/chromium/ui/views/controls/combobox/combobox.cc
@@ -4,10 +4,12 @@
#include "ui/views/controls/combobox/combobox.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
@@ -16,6 +18,8 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/scoped_canvas.h"
+#include "ui/gfx/text_utils.h"
+#include "ui/native_theme/common_theme.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/color_constants.h"
@@ -23,6 +27,7 @@
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/focusable_border.h"
+#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/menu_runner_handler.h"
#include "ui/views/controls/menu/submenu_view.h"
@@ -53,8 +58,6 @@ const int kDisclosureArrowButtonRightPadding = 12;
// Define the id of the first item in the menu (since it needs to be > 0)
const int kFirstMenuItemId = 1000;
-const SkColor kInvalidTextColor = SK_ColorWHITE;
-
// Used to indicate that no item is currently selected by the user.
const int kNoSelection = -1;
@@ -81,24 +84,6 @@ const int kFocusedPressedMenuButtonImages[] =
#undef MENU_IMAGE_GRID
-// The background to use for invalid comboboxes.
-class InvalidBackground : public Background {
- public:
- InvalidBackground() {}
- virtual ~InvalidBackground() {}
-
- // Overridden from Background:
- virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE {
- gfx::Rect bounds(view->GetLocalBounds());
- // Inset by 2 to leave 1 empty pixel between background and border.
- bounds.Inset(2, 2, 2, 2);
- canvas->FillRect(bounds, kWarningColor);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(InvalidBackground);
-};
-
// The transparent button which holds a button state but is not rendered.
class TransparentButton : public CustomButton {
public:
@@ -108,6 +93,11 @@ class TransparentButton : public CustomButton {
}
virtual ~TransparentButton() {}
+ virtual bool OnMousePressed(const ui::MouseEvent& mouse_event) OVERRIDE {
+ parent()->RequestFocus();
+ return true;
+ }
+
double GetAnimationValue() const {
return hover_animation_->GetCurrentValue();
}
@@ -238,15 +228,14 @@ const char Combobox::kViewClassName[] = "views/Combobox";
Combobox::Combobox(ui::ComboboxModel* model)
: model_(model),
- style_(STYLE_SHOW_DROP_DOWN_ON_CLICK),
+ style_(STYLE_NORMAL),
listener_(NULL),
selected_index_(model_->GetDefaultIndex()),
invalid_(false),
- disclosure_arrow_(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- IDR_MENU_DROPARROW).ToImageSkia()),
dropdown_open_(false),
text_button_(new TransparentButton(this)),
- arrow_button_(new TransparentButton(this)) {
+ arrow_button_(new TransparentButton(this)),
+ weak_ptr_factory_(this) {
model_->AddObserver(this);
UpdateFromModel();
SetFocusable(true);
@@ -285,9 +274,9 @@ Combobox::~Combobox() {
}
// static
-const gfx::Font& Combobox::GetFont() {
+const gfx::FontList& Combobox::GetFontList() {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- return rb.GetFont(ui::ResourceBundle::BaseFont);
+ return rb.GetFontList(ui::ResourceBundle::BaseFont);
}
void Combobox::SetStyle(Style style) {
@@ -295,8 +284,11 @@ void Combobox::SetStyle(Style style) {
return;
style_ = style;
+ if (style_ == STYLE_ACTION)
+ selected_index_ = 0;
UpdateBorder();
+ UpdateFromModel();
PreferredSizeChanged();
}
@@ -307,11 +299,17 @@ void Combobox::ModelChanged() {
}
void Combobox::SetSelectedIndex(int index) {
+ if (style_ == STYLE_ACTION)
+ return;
+
selected_index_ = index;
SchedulePaint();
}
bool Combobox::SelectValue(const base::string16& value) {
+ if (style_ == STYLE_ACTION)
+ return false;
+
for (int i = 0; i < model()->GetItemCount(); ++i) {
if (value == model()->GetItemAt(i)) {
SetSelectedIndex(i);
@@ -321,7 +319,7 @@ bool Combobox::SelectValue(const base::string16& value) {
return false;
}
-void Combobox::SetAccessibleName(const string16& name) {
+void Combobox::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
@@ -331,7 +329,6 @@ void Combobox::SetInvalid(bool invalid) {
invalid_ = invalid;
- set_background(invalid_ ? new InvalidBackground() : NULL);
UpdateBorder();
SchedulePaint();
}
@@ -350,13 +347,14 @@ void Combobox::Layout() {
int arrow_button_width = 0;
switch (style_) {
- case STYLE_SHOW_DROP_DOWN_ON_CLICK: {
+ case STYLE_NORMAL: {
arrow_button_width = width();
break;
}
- case STYLE_NOTIFY_ON_CLICK: {
+ case STYLE_ACTION: {
arrow_button_width = GetDisclosureArrowLeftPadding() +
- disclosure_arrow_->width() + GetDisclosureArrowRightPadding();
+ ArrowSize().width() +
+ GetDisclosureArrowRightPadding();
text_button_width = width() - arrow_button_width;
break;
}
@@ -377,10 +375,10 @@ bool Combobox::IsCommandEnabled(int id) const {
void Combobox::ExecuteCommand(int id) {
selected_index_ = MenuCommandToIndex(id);
- OnSelectionChanged();
+ OnPerformAction();
}
-bool Combobox::GetAccelerator(int id, ui::Accelerator* accel) {
+bool Combobox::GetAccelerator(int id, ui::Accelerator* accel) const {
return false;
}
@@ -393,26 +391,27 @@ int Combobox::GetSelectedRow() {
}
void Combobox::SetSelectedRow(int row) {
+ int prev_index = selected_index_;
SetSelectedIndex(row);
+ if (selected_index_ != prev_index)
+ OnPerformAction();
}
-string16 Combobox::GetTextForRow(int row) {
- return model()->IsItemSeparatorAt(row) ? string16() : model()->GetItemAt(row);
+base::string16 Combobox::GetTextForRow(int row) {
+ return model()->IsItemSeparatorAt(row) ? base::string16() :
+ model()->GetItemAt(row);
}
////////////////////////////////////////////////////////////////////////////////
// Combobox, View overrides:
-gfx::Size Combobox::GetPreferredSize() {
- if (content_size_.IsEmpty())
- UpdateFromModel();
-
+gfx::Size Combobox::GetPreferredSize() const {
// The preferred size will drive the local bounds which in turn is used to set
// the minimum width for the dropdown list.
gfx::Insets insets = GetInsets();
int total_width = std::max(kMinComboboxWidth, content_size_.width()) +
insets.width() + GetDisclosureArrowLeftPadding() +
- disclosure_arrow_->width() + GetDisclosureArrowRightPadding();
+ ArrowSize().width() + GetDisclosureArrowRightPadding();
return gfx::Size(total_width, content_size_.height() + insets.height());
}
@@ -475,7 +474,7 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
// Click the button only when the button style mode.
case ui::VKEY_SPACE:
- if (style_ == STYLE_NOTIFY_ON_CLICK) {
+ if (style_ == STYLE_ACTION) {
// When pressing space, the click event will be raised after the key is
// released.
text_button_->SetState(Button::STATE_PRESSED);
@@ -486,9 +485,9 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
// Click the button only when the button style mode.
case ui::VKEY_RETURN:
- if (style_ != STYLE_NOTIFY_ON_CLICK)
+ if (style_ != STYLE_ACTION)
return false;
- HandleClickEvent();
+ OnPerformAction();
break;
default:
@@ -498,34 +497,35 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
if (show_menu) {
UpdateFromModel();
ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD);
- } else if (new_index != selected_index_ && new_index != kNoSelection) {
+ } else if (new_index != selected_index_ && new_index != kNoSelection &&
+ style_ != STYLE_ACTION) {
DCHECK(!model()->IsItemSeparatorAt(new_index));
selected_index_ = new_index;
- OnSelectionChanged();
+ OnPerformAction();
}
return true;
}
bool Combobox::OnKeyReleased(const ui::KeyEvent& e) {
- if (style_ != STYLE_NOTIFY_ON_CLICK)
+ if (style_ != STYLE_ACTION)
return false; // crbug.com/127520
- if (e.key_code() == ui::VKEY_SPACE)
- HandleClickEvent();
+ if (e.key_code() == ui::VKEY_SPACE && style_ == STYLE_ACTION)
+ OnPerformAction();
return false;
}
void Combobox::OnPaint(gfx::Canvas* canvas) {
switch (style_) {
- case STYLE_SHOW_DROP_DOWN_ON_CLICK: {
+ case STYLE_NORMAL: {
OnPaintBackground(canvas);
PaintText(canvas);
OnPaintBorder(canvas);
break;
}
- case STYLE_NOTIFY_ON_CLICK: {
+ case STYLE_ACTION: {
PaintButtons(canvas);
PaintText(canvas);
break;
@@ -548,23 +548,27 @@ void Combobox::OnBlur() {
SchedulePaint();
}
-void Combobox::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_COMBOBOX;
+void Combobox::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_COMBO_BOX;
state->name = accessible_name_;
state->value = model_->GetItemAt(selected_index_);
state->index = selected_index_;
state->count = model_->GetItemCount();
}
-void Combobox::OnModelChanged() {
+void Combobox::OnComboboxModelChanged(ui::ComboboxModel* model) {
+ DCHECK_EQ(model, model_);
ModelChanged();
}
void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
+ if (!enabled())
+ return;
+
RequestFocus();
if (sender == text_button_) {
- HandleClickEvent();
+ OnPerformAction();
} else {
DCHECK_EQ(arrow_button_, sender);
// TODO(hajimehoshi): Fix the problem that the arrow button blinks when
@@ -583,40 +587,50 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
}
void Combobox::UpdateFromModel() {
- int max_width = 0;
- const gfx::Font& font = Combobox::GetFont();
+ const gfx::FontList& font_list = Combobox::GetFontList();
MenuItemView* menu = new MenuItemView(this);
// MenuRunner owns |menu|.
dropdown_list_menu_runner_.reset(new MenuRunner(menu));
int num_items = model()->GetItemCount();
+ int width = 0;
+ bool text_item_appended = false;
for (int i = 0; i < num_items; ++i) {
+ // When STYLE_ACTION is used, the first item and the following separators
+ // are not added to the dropdown menu. It is assumed that the first item is
+ // always selected and rendered on the top of the action button.
if (model()->IsItemSeparatorAt(i)) {
- menu->AppendSeparator();
+ if (text_item_appended || style_ != STYLE_ACTION)
+ menu->AppendSeparator();
continue;
}
- string16 text = model()->GetItemAt(i);
+ base::string16 text = model()->GetItemAt(i);
// Inserting the Unicode formatting characters if necessary so that the
// text is displayed correctly in right-to-left UIs.
base::i18n::AdjustStringForLocaleDirection(&text);
- menu->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL);
- max_width = std::max(max_width, font.GetStringWidth(text));
+ if (style_ != STYLE_ACTION || i > 0) {
+ menu->AppendMenuItem(i + kFirstMenuItemId, text, MenuItemView::NORMAL);
+ text_item_appended = true;
+ }
+
+ if (style_ != STYLE_ACTION || i == selected_index_)
+ width = std::max(width, gfx::GetStringWidth(text, font_list));
}
- content_size_.SetSize(max_width, font.GetHeight());
+ content_size_.SetSize(width, font_list.GetHeight());
}
void Combobox::UpdateBorder() {
- FocusableBorder* border = new FocusableBorder();
- if (style_ == STYLE_NOTIFY_ON_CLICK)
+ scoped_ptr<FocusableBorder> border(new FocusableBorder());
+ if (style_ == STYLE_ACTION)
border->SetInsets(8, 13, 8, 13);
if (invalid_)
border->SetColor(kWarningColor);
- set_border(border);
+ SetBorder(border.PassAs<Border>());
}
void Combobox::AdjustBoundsForRTLUI(gfx::Rect* rect) const {
@@ -632,45 +646,52 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
int x = insets.left();
int y = insets.top();
int text_height = height() - insets.height();
- SkColor text_color = invalid() ? kInvalidTextColor :
- GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor);
+ SkColor text_color = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_LabelEnabledColor);
DCHECK_GE(selected_index_, 0);
DCHECK_LT(selected_index_, model()->GetItemCount());
if (selected_index_ < 0 || selected_index_ > model()->GetItemCount())
selected_index_ = 0;
- string16 text = model()->GetItemAt(selected_index_);
+ base::string16 text = model()->GetItemAt(selected_index_);
- int disclosure_arrow_offset = width() - disclosure_arrow_->width() -
+ gfx::Size arrow_size = ArrowSize();
+ int disclosure_arrow_offset = width() - arrow_size.width() -
GetDisclosureArrowLeftPadding() - GetDisclosureArrowRightPadding();
- const gfx::Font& font = Combobox::GetFont();
- int text_width = font.GetStringWidth(text);
+ const gfx::FontList& font_list = Combobox::GetFontList();
+ int text_width = gfx::GetStringWidth(text, font_list);
if ((text_width + insets.width()) > disclosure_arrow_offset)
text_width = disclosure_arrow_offset - insets.width();
gfx::Rect text_bounds(x, y, text_width, text_height);
AdjustBoundsForRTLUI(&text_bounds);
- canvas->DrawStringInt(text, font, text_color, text_bounds);
+ canvas->DrawStringRect(text, font_list, text_color, text_bounds);
int arrow_x = disclosure_arrow_offset + GetDisclosureArrowLeftPadding();
gfx::Rect arrow_bounds(arrow_x,
- height() / 2 - disclosure_arrow_->height() / 2,
- disclosure_arrow_->width(),
- disclosure_arrow_->height());
+ height() / 2 - arrow_size.height() / 2,
+ arrow_size.width(),
+ arrow_size.height());
AdjustBoundsForRTLUI(&arrow_bounds);
- SkPaint paint;
- // This makes the arrow subtractive.
- if (invalid())
- paint.setXfermodeMode(SkXfermode::kDstOut_Mode);
- canvas->DrawImageInt(*disclosure_arrow_, arrow_bounds.x(), arrow_bounds.y(),
- paint);
+ // TODO(estade): hack alert! Remove this direct call into CommonTheme. For now
+ // STYLE_ACTION isn't properly themed so we have to override the NativeTheme
+ // behavior. See crbug.com/384071
+ if (style_ == STYLE_ACTION) {
+ ui::CommonThemePaintComboboxArrow(canvas->sk_canvas(), arrow_bounds);
+ } else {
+ ui::NativeTheme::ExtraParams ignored;
+ GetNativeTheme()->Paint(canvas->sk_canvas(),
+ ui::NativeTheme::kComboboxArrow,
+ ui::NativeTheme::kNormal,
+ arrow_bounds,
+ ignored);
+ }
}
void Combobox::PaintButtons(gfx::Canvas* canvas) {
- DCHECK(style_ == STYLE_NOTIFY_ON_CLICK);
+ DCHECK(style_ == STYLE_ACTION);
gfx::ScopedCanvas scoped_canvas(canvas);
if (base::i18n::IsRTL()) {
@@ -739,10 +760,12 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
gfx::Rect lb = GetLocalBounds();
gfx::Point menu_position(lb.origin());
- // Inset the menu's requested position so the border of the menu lines up
- // with the border of the combobox.
- menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft);
- menu_position.set_y(menu_position.y() + kMenuBorderWidthTop);
+ if (style_ == STYLE_NORMAL) {
+ // Inset the menu's requested position so the border of the menu lines up
+ // with the border of the combobox.
+ menu_position.set_x(menu_position.x() + kMenuBorderWidthLeft);
+ menu_position.set_y(menu_position.y() + kMenuBorderWidthTop);
+ }
lb.set_width(lb.width() - (kMenuBorderWidthLeft + kMenuBorderWidthRight));
View::ConvertPointToScreen(this, &menu_position);
@@ -757,8 +780,10 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
arrow_button_->SetState(Button::STATE_PRESSED);
}
dropdown_open_ = true;
+ MenuAnchorPosition anchor_position =
+ style_ == STYLE_ACTION ? MENU_ANCHOR_TOPRIGHT : MENU_ANCHOR_TOPLEFT;
if (dropdown_list_menu_runner_->RunMenuAt(GetWidget(), NULL, bounds,
- MenuItemView::TOPLEFT, source_type,
+ anchor_position, source_type,
MenuRunner::COMBOBOX) ==
MenuRunner::MENU_DELETED) {
return;
@@ -774,12 +799,17 @@ void Combobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
SetMouseHandler(NULL);
}
-void Combobox::OnSelectionChanged() {
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_VALUE_CHANGED, false);
+void Combobox::OnPerformAction() {
+ NotifyAccessibilityEvent(ui::AX_EVENT_VALUE_CHANGED, false);
SchedulePaint();
+
+ // This combobox may be deleted by the listener.
+ base::WeakPtr<Combobox> weak_ptr = weak_ptr_factory_.GetWeakPtr();
if (listener_)
- listener_->OnSelectedIndexChanged(this);
- // |this| may now be deleted.
+ listener_->OnPerformAction(this);
+
+ if (weak_ptr && style_ == STYLE_ACTION)
+ selected_index_ = 0;
}
int Combobox::MenuCommandToIndex(int menu_command_id) const {
@@ -792,9 +822,9 @@ int Combobox::MenuCommandToIndex(int menu_command_id) const {
int Combobox::GetDisclosureArrowLeftPadding() const {
switch (style_) {
- case STYLE_SHOW_DROP_DOWN_ON_CLICK:
+ case STYLE_NORMAL:
return kDisclosureArrowLeftPadding;
- case STYLE_NOTIFY_ON_CLICK:
+ case STYLE_ACTION:
return kDisclosureArrowButtonLeftPadding;
}
NOTREACHED();
@@ -803,21 +833,31 @@ int Combobox::GetDisclosureArrowLeftPadding() const {
int Combobox::GetDisclosureArrowRightPadding() const {
switch (style_) {
- case STYLE_SHOW_DROP_DOWN_ON_CLICK:
+ case STYLE_NORMAL:
return kDisclosureArrowRightPadding;
- case STYLE_NOTIFY_ON_CLICK:
+ case STYLE_ACTION:
return kDisclosureArrowButtonRightPadding;
}
NOTREACHED();
return 0;
}
-void Combobox::HandleClickEvent() {
- if (style_ != STYLE_NOTIFY_ON_CLICK)
- return;
-
- if (listener_)
- listener_->OnComboboxTextButtonClicked(this);
+gfx::Size Combobox::ArrowSize() const {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // TODO(estade): hack alert! This should always use GetNativeTheme(). For now
+ // STYLE_ACTION isn't properly themed so we have to override the NativeTheme
+ // behavior. See crbug.com/384071
+ const ui::NativeTheme* native_theme_for_arrow = style_ == STYLE_ACTION ?
+ ui::NativeTheme::instance() :
+ GetNativeTheme();
+#else
+ const ui::NativeTheme* native_theme_for_arrow = GetNativeTheme();
+#endif
+
+ ui::NativeTheme::ExtraParams ignored;
+ return native_theme_for_arrow->GetPartSize(ui::NativeTheme::kComboboxArrow,
+ ui::NativeTheme::kNormal,
+ ignored);
}
} // namespace views
diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h
index 8ec45c9e211..22781a8ab1f 100644
--- a/chromium/ui/views/controls/combobox/combobox.h
+++ b/chromium/ui/views/controls/combobox/combobox.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "ui/base/models/combobox_model_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
@@ -16,7 +17,7 @@
#include "ui/views/controls/prefix_delegate.h"
namespace gfx {
-class Font;
+class FontList;
class SlideAnimation;
}
@@ -36,10 +37,14 @@ class Painter;
class PrefixSelector;
// A non-editable combobox (aka a drop-down list or selector).
-// Combobox has two distinct parts, the drop down arrow and the text. When the
-// user clicks on the text the drop down is either shown
-// (STYLE_SHOW_DROP_DOWN_ON_CLICK) or the listener is notified
-// (STYLE_NOTIFY_ON_CLICK).
+// Combobox has two distinct parts, the drop down arrow and the text. Combobox
+// offers two distinct behaviors:
+// * STYLE_NORMAL: typical combobox, clicking on the text and/or button shows
+// the drop down, arrow keys change selection, selected index can be changed by
+// the user to something other than the first item.
+// * STYLE_ACTION: clicking on the text notifies the listener. The menu can be
+// shown only by clicking on the arrow. The selected index is always reverted to
+// 0 after the listener is notified.
class VIEWS_EXPORT Combobox : public MenuDelegate,
public PrefixDelegate,
public ui::ComboboxModelObserver,
@@ -47,8 +52,8 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
public:
// The style of the combobox.
enum Style {
- STYLE_SHOW_DROP_DOWN_ON_CLICK,
- STYLE_NOTIFY_ON_CLICK,
+ STYLE_NORMAL,
+ STYLE_ACTION,
};
// The combobox's class name.
@@ -58,7 +63,7 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
explicit Combobox(ui::ComboboxModel* model);
virtual ~Combobox();
- static const gfx::Font& GetFont();
+ static const gfx::FontList& GetFontList();
// Sets the listener which will be called when a selection has been made.
void set_listener(ComboboxListener* listener) { listener_ = listener; }
@@ -79,7 +84,7 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
ui::ComboboxModel* model() const { return model_; }
// Set the accessible name of the combobox.
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
// Visually marks the combobox as having an invalid value selected.
// When invalid, it paints with white text on a red background.
@@ -88,7 +93,7 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
bool invalid() const { return invalid_; }
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE;
@@ -96,7 +101,7 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
virtual void Layout() OVERRIDE;
@@ -104,23 +109,26 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
virtual bool IsItemChecked(int id) const OVERRIDE;
virtual bool IsCommandEnabled(int id) const OVERRIDE;
virtual void ExecuteCommand(int id) OVERRIDE;
- virtual bool GetAccelerator(int id, ui::Accelerator* accelerator) OVERRIDE;
+ virtual bool GetAccelerator(int id,
+ ui::Accelerator* accelerator) const OVERRIDE;
// Overridden from PrefixDelegate:
virtual int GetRowCount() OVERRIDE;
virtual int GetSelectedRow() OVERRIDE;
virtual void SetSelectedRow(int row) OVERRIDE;
- virtual string16 GetTextForRow(int row) OVERRIDE;
+ virtual base::string16 GetTextForRow(int row) OVERRIDE;
// Overriden from ComboboxModelObserver:
- virtual void OnModelChanged() OVERRIDE;
+ virtual void OnComboboxModelChanged(ui::ComboboxModel* model) OVERRIDE;
// Overriden from ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(ComboboxTest, Click);
+ FRIEND_TEST_ALL_PREFIXES(ComboboxTest, ClickButDisabled);
FRIEND_TEST_ALL_PREFIXES(ComboboxTest, NotifyOnClickWithMouse);
+ FRIEND_TEST_ALL_PREFIXES(ComboboxTest, ContentWidth);
// Updates the combobox's content from its model.
void UpdateFromModel();
@@ -141,7 +149,9 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
void ShowDropDownMenu(ui::MenuSourceType source_type);
// Called when the selection is changed by the user.
- void OnSelectionChanged();
+ void OnPerformAction();
+ void NotifyPerformAction();
+ void AfterPerformAction();
// Converts a menu command ID to a menu item index.
int MenuCommandToIndex(int menu_command_id) const;
@@ -149,6 +159,9 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
int GetDisclosureArrowLeftPadding() const;
int GetDisclosureArrowRightPadding() const;
+ // Returns the size of the disclosure arrow.
+ gfx::Size ArrowSize() const;
+
// Handles the clicking event.
void HandleClickEvent();
@@ -168,14 +181,11 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
bool invalid_;
// The accessible name of this combobox.
- string16 accessible_name_;
+ base::string16 accessible_name_;
// A helper used to select entries by keyboard input.
scoped_ptr<PrefixSelector> selector_;
- // The disclosure arrow next to the currently selected item from the list.
- const gfx::ImageSkia* disclosure_arrow_;
-
// Responsible for showing the context menu.
scoped_ptr<MenuRunner> dropdown_list_menu_runner_;
@@ -191,7 +201,7 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
base::Time closed_time_;
// The maximum dimensions of the content in the dropdown
- gfx::Size content_size_;
+ mutable gfx::Size content_size_;
// The painters or images that are used when |style_| is STYLE_BUTTONS. The
// first index means the state of unfocused or focused.
@@ -209,6 +219,9 @@ class VIEWS_EXPORT Combobox : public MenuDelegate,
CustomButton* text_button_;
CustomButton* arrow_button_;
+ // Used for making calbacks.
+ base::WeakPtrFactory<Combobox> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(Combobox);
};
diff --git a/chromium/ui/views/controls/combobox/combobox_listener.h b/chromium/ui/views/controls/combobox/combobox_listener.h
index 2609f647023..2522e03c7d8 100644
--- a/chromium/ui/views/controls/combobox/combobox_listener.h
+++ b/chromium/ui/views/controls/combobox/combobox_listener.h
@@ -5,19 +5,24 @@
#ifndef UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_LISTENER_H_
#define UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_LISTENER_H_
+#include "ui/views/views_export.h"
+
namespace views {
class Combobox;
-// An interface implemented by an object to let it know that the selected index
-// has changed.
-class ComboboxListener {
+// Interface used to notify consumers when something interesting happens to a
+// Combobox.
+class VIEWS_EXPORT ComboboxListener {
public:
- virtual void OnSelectedIndexChanged(Combobox* combobox) = 0;
-
- // Handles when the combobox's style is the button style and the button is
- // clicked.
- virtual void OnComboboxTextButtonClicked(Combobox* combobox) {}
+ // Invoked when the user does the appropriate gesture that some action should
+ // be performed. For both STYLE_NORMAL and STYLE_ACTION this is invoked if the
+ // user clicks on the menu button and then clicks an item. For STYLE_NORMAL
+ // this is also invoked when the menu is not showing and the does a gesture to
+ // change the selection (for example, presses the home or end keys). This is
+ // not invoked when the menu is shown and the user changes the selection
+ // without closing the menu.
+ virtual void OnPerformAction(Combobox* combobox) = 0;
protected:
virtual ~ComboboxListener() {}
diff --git a/chromium/ui/views/controls/combobox/combobox_unittest.cc b/chromium/ui/views/controls/combobox/combobox_unittest.cc
index 7b68c4578e3..67625a2aea1 100644
--- a/chromium/ui/views/controls/combobox/combobox_unittest.cc
+++ b/chromium/ui/views/controls/combobox/combobox_unittest.cc
@@ -8,8 +8,10 @@
#include "base/basictypes.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/base/ime/text_input_client.h"
#include "ui/base/models/combobox_model.h"
#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/menu/menu_runner.h"
@@ -19,6 +21,8 @@
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace {
@@ -27,15 +31,14 @@ namespace {
// shown or not.
class TestMenuRunnerHandler : public MenuRunnerHandler {
public:
- TestMenuRunnerHandler()
- : executed_(false) {}
+ TestMenuRunnerHandler() : executed_(false) {}
bool executed() const { return executed_; }
virtual MenuRunner::RunResult RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
+ MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
int32 types) OVERRIDE {
executed_ = true;
@@ -55,8 +58,7 @@ class TestCombobox : public Combobox {
explicit TestCombobox(ui::ComboboxModel* model)
: Combobox(model),
key_handled_(false),
- key_received_(false) {
- }
+ key_received_(false) {}
virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
key_received_ = true;
@@ -94,7 +96,7 @@ class TestComboboxModel : public ui::ComboboxModel {
virtual int GetItemCount() const OVERRIDE {
return 10;
}
- virtual string16 GetItemAt(int index) OVERRIDE {
+ virtual base::string16 GetItemAt(int index) OVERRIDE {
if (IsItemSeparatorAt(index)) {
NOTREACHED();
return ASCIIToUTF16("SEPARATOR");
@@ -115,13 +117,35 @@ class TestComboboxModel : public ui::ComboboxModel {
DISALLOW_COPY_AND_ASSIGN(TestComboboxModel);
};
+// A combobox model which refers to a vector.
+class VectorComboboxModel : public ui::ComboboxModel {
+ public:
+ explicit VectorComboboxModel(std::vector<std::string>* values)
+ : values_(values) {}
+ virtual ~VectorComboboxModel() {}
+
+ // ui::ComboboxModel:
+ virtual int GetItemCount() const OVERRIDE {
+ return (int)values_->size();
+ }
+ virtual base::string16 GetItemAt(int index) OVERRIDE {
+ return ASCIIToUTF16(values_->at(index));
+ }
+ virtual bool IsItemSeparatorAt(int index) OVERRIDE {
+ return false;
+ }
+
+ private:
+ std::vector<std::string>* values_;
+};
+
class EvilListener : public ComboboxListener {
public:
- EvilListener() : deleted_(false) {};
+ EvilListener() : deleted_(false) {}
virtual ~EvilListener() {};
// ComboboxListener:
- virtual void OnSelectedIndexChanged(Combobox* combobox) OVERRIDE {
+ virtual void OnPerformAction(Combobox* combobox) OVERRIDE {
delete combobox;
deleted_ = true;
}
@@ -136,31 +160,29 @@ class EvilListener : public ComboboxListener {
class TestComboboxListener : public views::ComboboxListener {
public:
- TestComboboxListener()
- : on_selected_index_changed_called_(false),
- on_combobox_text_button_clicked_called_(false) {
- }
+ TestComboboxListener() : perform_action_index_(-1), actions_performed_(0) {}
virtual ~TestComboboxListener() {}
- virtual void OnSelectedIndexChanged(views::Combobox* combobox) OVERRIDE {
- on_selected_index_changed_called_ = true;
+ virtual void OnPerformAction(views::Combobox* combobox) OVERRIDE {
+ perform_action_index_ = combobox->selected_index();
+ actions_performed_++;
}
- virtual void OnComboboxTextButtonClicked(views::Combobox* combobox) OVERRIDE {
- on_combobox_text_button_clicked_called_ = true;
+ int perform_action_index() const {
+ return perform_action_index_;
}
- bool on_selected_index_changed_called() const {
- return on_selected_index_changed_called_;
+ bool on_perform_action_called() const {
+ return actions_performed_ > 0;
}
- bool on_combobox_text_button_clicked_called() const {
- return on_combobox_text_button_clicked_called_;
+ int actions_performed() const {
+ return actions_performed_;
}
private:
- bool on_selected_index_changed_called_;
- bool on_combobox_text_button_clicked_called_;
+ int perform_action_index_;
+ int actions_performed_;
private:
DISALLOW_COPY_AND_ASSIGN(TestComboboxListener);
@@ -170,7 +192,7 @@ class TestComboboxListener : public views::ComboboxListener {
class ComboboxTest : public ViewsTestBase {
public:
- ComboboxTest() : widget_(NULL), combobox_(NULL), input_method_(NULL) {}
+ ComboboxTest() : widget_(NULL), combobox_(NULL) {}
virtual void TearDown() OVERRIDE {
if (widget_)
@@ -193,11 +215,10 @@ class ComboboxTest : public ViewsTestBase {
widget_->SetContentsView(container);
container->AddChildView(combobox_);
- input_method_ = new MockInputMethod();
- widget_->ReplaceInputMethod(input_method_);
+ widget_->ReplaceInputMethod(new MockInputMethod);
// Assumes the Widget is always focused.
- input_method_->OnFocus();
+ widget_->GetInputMethod()->OnFocus();
combobox_->RequestFocus();
combobox_->SizeToPreferredSize();
@@ -210,7 +231,7 @@ class ComboboxTest : public ViewsTestBase {
void SendKeyEventWithType(ui::KeyboardCode key_code, ui::EventType type) {
ui::KeyEvent event(type, key_code, 0, false);
- input_method_->DispatchKeyEvent(event);
+ widget_->GetInputMethod()->DispatchKeyEvent(event);
}
View* GetFocusedView() {
@@ -220,10 +241,12 @@ class ComboboxTest : public ViewsTestBase {
void PerformClick(const gfx::Point& point) {
ui::MouseEvent pressed_event = ui::MouseEvent(ui::ET_MOUSE_PRESSED, point,
point,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
widget_->OnMouseEvent(&pressed_event);
ui::MouseEvent released_event = ui::MouseEvent(ui::ET_MOUSE_RELEASED, point,
point,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
widget_->OnMouseEvent(&released_event);
}
@@ -236,9 +259,6 @@ class ComboboxTest : public ViewsTestBase {
// Combobox does not take ownership of the model, hence it needs to be scoped.
scoped_ptr<TestComboboxModel> model_;
-
- // For testing input method related behaviors.
- MockInputMethod* input_method_;
};
TEST_F(ComboboxTest, KeyTest) {
@@ -435,15 +455,48 @@ TEST_F(ComboboxTest, SelectValue) {
EXPECT_EQ(1, combobox_->selected_index());
EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("BANANAS")));
EXPECT_EQ(1, combobox_->selected_index());
+
+ // With the action style, the selected index is always 0.
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
+ EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("PEANUT BUTTER")));
+ EXPECT_EQ(0, combobox_->selected_index());
+ EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("JELLY")));
+ EXPECT_EQ(0, combobox_->selected_index());
+ EXPECT_FALSE(combobox_->SelectValue(ASCIIToUTF16("BANANAS")));
+ EXPECT_EQ(0, combobox_->selected_index());
+}
+
+TEST_F(ComboboxTest, SelectIndexActionStyle) {
+ InitCombobox();
+
+ // With the action style, the selected index is always 0.
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
+ combobox_->SetSelectedIndex(1);
+ EXPECT_EQ(0, combobox_->selected_index());
+ combobox_->SetSelectedIndex(2);
+ EXPECT_EQ(0, combobox_->selected_index());
+ combobox_->SetSelectedIndex(3);
+ EXPECT_EQ(0, combobox_->selected_index());
}
TEST_F(ComboboxTest, ListenerHandlesDelete) {
TestComboboxModel model;
- TestCombobox* combobox = new TestCombobox(&model); // Deleted on change.
- EvilListener evil_listener;
- combobox->set_listener(&evil_listener);
+
+ // |combobox| will be deleted on change.
+ TestCombobox* combobox = new TestCombobox(&model);
+ scoped_ptr<EvilListener> evil_listener(new EvilListener());
+ combobox->set_listener(evil_listener.get());
+ ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2));
+ EXPECT_TRUE(evil_listener->deleted());
+
+ // With STYLE_ACTION
+ // |combobox| will be deleted on change.
+ combobox = new TestCombobox(&model);
+ evil_listener.reset(new EvilListener());
+ combobox->set_listener(evil_listener.get());
+ combobox->SetStyle(Combobox::STYLE_ACTION);
ASSERT_NO_FATAL_FAILURE(combobox->ExecuteCommand(2));
- EXPECT_TRUE(evil_listener.deleted());
+ EXPECT_TRUE(evil_listener->deleted());
}
TEST_F(ComboboxTest, Click) {
@@ -462,24 +515,46 @@ TEST_F(ComboboxTest, Click) {
test_api.SetMenuRunnerHandler(menu_runner_handler.Pass());
PerformClick(gfx::Point(combobox_->x() + 1,
combobox_->y() + combobox_->height() / 2));
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
EXPECT_TRUE(test_menu_runner_handler->executed());
}
+TEST_F(ComboboxTest, ClickButDisabled) {
+ InitCombobox();
+
+ TestComboboxListener listener;
+ combobox_->set_listener(&listener);
+
+ combobox_->Layout();
+ combobox_->SetEnabled(false);
+
+ // Click the left side, but nothing happens since the combobox is disabled.
+ TestMenuRunnerHandler* test_menu_runner_handler = new TestMenuRunnerHandler();
+ scoped_ptr<MenuRunnerHandler> menu_runner_handler(test_menu_runner_handler);
+ test::MenuRunnerTestAPI test_api(
+ combobox_->dropdown_list_menu_runner_.get());
+ test_api.SetMenuRunnerHandler(menu_runner_handler.Pass());
+ PerformClick(gfx::Point(combobox_->x() + 1,
+ combobox_->y() + combobox_->height() / 2));
+ EXPECT_FALSE(listener.on_perform_action_called());
+ EXPECT_FALSE(test_menu_runner_handler->executed());
+}
+
TEST_F(ComboboxTest, NotifyOnClickWithReturnKey) {
InitCombobox();
TestComboboxListener listener;
combobox_->set_listener(&listener);
- // With STYLE_SHOW_DROP_DOWN_ON_CLICK, the click event is ignored.
+ // With STYLE_NORMAL, the click event is ignored.
SendKeyEvent(ui::VKEY_RETURN);
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
- // With STYLE_NOTIFY_ON_CLICK, the click event is notified.
- combobox_->SetStyle(Combobox::STYLE_NOTIFY_ON_CLICK);
+ // With STYLE_ACTION, the click event is notified.
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
SendKeyEvent(ui::VKEY_RETURN);
- EXPECT_TRUE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_TRUE(listener.on_perform_action_called());
+ EXPECT_EQ(0, listener.perform_action_index());
}
TEST_F(ComboboxTest, NotifyOnClickWithSpaceKey) {
@@ -488,18 +563,19 @@ TEST_F(ComboboxTest, NotifyOnClickWithSpaceKey) {
TestComboboxListener listener;
combobox_->set_listener(&listener);
- // With STYLE_SHOW_DROP_DOWN_ON_CLICK, the click event is ignored.
+ // With STYLE_NORMAL, the click event is ignored.
SendKeyEvent(ui::VKEY_SPACE);
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED);
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
- // With STYLE_NOTIFY_ON_CLICK, the click event is notified after releasing.
- combobox_->SetStyle(Combobox::STYLE_NOTIFY_ON_CLICK);
+ // With STYLE_ACTION, the click event is notified after releasing.
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
SendKeyEvent(ui::VKEY_SPACE);
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
SendKeyEventWithType(ui::VKEY_SPACE, ui::ET_KEY_RELEASED);
- EXPECT_TRUE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_TRUE(listener.on_perform_action_called());
+ EXPECT_EQ(0, listener.perform_action_index());
}
TEST_F(ComboboxTest, NotifyOnClickWithMouse) {
@@ -508,7 +584,7 @@ TEST_F(ComboboxTest, NotifyOnClickWithMouse) {
TestComboboxListener listener;
combobox_->set_listener(&listener);
- combobox_->SetStyle(Combobox::STYLE_NOTIFY_ON_CLICK);
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
combobox_->Layout();
// Click the right side (arrow button). The menu is shown.
@@ -520,7 +596,7 @@ TEST_F(ComboboxTest, NotifyOnClickWithMouse) {
PerformClick(gfx::Point(combobox_->x() + combobox_->width() - 1,
combobox_->y() + combobox_->height() / 2));
- EXPECT_FALSE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_FALSE(listener.on_perform_action_called());
EXPECT_TRUE(test_menu_runner_handler->executed());
// Click the left side (text button). The click event is notified.
@@ -531,8 +607,9 @@ TEST_F(ComboboxTest, NotifyOnClickWithMouse) {
test_api->SetMenuRunnerHandler(menu_runner_handler.Pass());
PerformClick(gfx::Point(combobox_->x() + 1,
combobox_->y() + combobox_->height() / 2));
- EXPECT_TRUE(listener.on_combobox_text_button_clicked_called());
+ EXPECT_TRUE(listener.on_perform_action_called());
EXPECT_FALSE(test_menu_runner_handler->executed());
+ EXPECT_EQ(0, listener.perform_action_index());
}
TEST_F(ComboboxTest, ConsumingPressKeyEvents) {
@@ -543,13 +620,74 @@ TEST_F(ComboboxTest, ConsumingPressKeyEvents) {
EXPECT_FALSE(combobox_->OnKeyPressed(
ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0, false)));
- // When the combobox's style is STYLE_NOTIFY_ON_CLICK, pressing events of
- // a space key or an enter key will be consumed.
- combobox_->SetStyle(Combobox::STYLE_NOTIFY_ON_CLICK);
+ // When the combobox's style is STYLE_ACTION, pressing events of a space key
+ // or an enter key will be consumed.
+ combobox_->SetStyle(Combobox::STYLE_ACTION);
EXPECT_TRUE(combobox_->OnKeyPressed(
ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0, false)));
EXPECT_TRUE(combobox_->OnKeyPressed(
ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0, false)));
}
+TEST_F(ComboboxTest, ContentWidth) {
+ std::vector<std::string> values;
+ VectorComboboxModel model(&values);
+ TestCombobox combobox(&model);
+
+ std::string long_item = "this is the long item";
+ std::string short_item = "s";
+
+ values.resize(1);
+ values[0] = long_item;
+ combobox.ModelChanged();
+
+ const int long_item_width = combobox.content_size_.width();
+
+ values[0] = short_item;
+ combobox.ModelChanged();
+
+ const int short_item_width = combobox.content_size_.width();
+
+ values.resize(2);
+ values[0] = short_item;
+ values[1] = long_item;
+ combobox.ModelChanged();
+
+ // When the style is STYLE_NORMAL, the width will fit with the longest item.
+ combobox.SetStyle(Combobox::STYLE_NORMAL);
+ EXPECT_EQ(long_item_width, combobox.content_size_.width());
+
+ // When the style is STYLE_ACTION, the width will fit with the first items'
+ // width.
+ combobox.SetStyle(Combobox::STYLE_ACTION);
+ EXPECT_EQ(short_item_width, combobox.content_size_.width());
+}
+
+TEST_F(ComboboxTest, TypingPrefixNotifiesListener) {
+ InitCombobox();
+
+ TestComboboxListener listener;
+ combobox_->set_listener(&listener);
+
+ // Type the first character of the second menu item ("JELLY").
+ combobox_->GetTextInputClient()->InsertChar('J', ui::EF_NONE);
+ EXPECT_EQ(1, listener.actions_performed());
+ EXPECT_EQ(1, listener.perform_action_index());
+
+ // Type the second character of "JELLY", item shouldn't change and
+ // OnPerformAction() shouldn't be re-called.
+ combobox_->GetTextInputClient()->InsertChar('E', ui::EF_NONE);
+ EXPECT_EQ(1, listener.actions_performed());
+ EXPECT_EQ(1, listener.perform_action_index());
+
+ // Clears the typed text.
+ combobox_->OnBlur();
+
+ // Type the first character of "PEANUT BUTTER", which should change the
+ // selected index and perform an action.
+ combobox_->GetTextInputClient()->InsertChar('P', ui::EF_NONE);
+ EXPECT_EQ(2, listener.actions_performed());
+ EXPECT_EQ(2, listener.perform_action_index());
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index 2bbf91cab9e..5b758f8e1c7 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -7,13 +7,25 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkPaint.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/insets.h"
#include "ui/views/painter.h"
namespace views {
+namespace {
+
+// Returns the pixels for the bitmap in |image| at scale |image_scale|.
+void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
+ DCHECK_NE(0.0f, image_scale);
+ const SkBitmap& bitmap = img.GetRepresentation(image_scale).sk_bitmap();
+ SkAutoLockPixels pixel_lock(bitmap);
+ return bitmap.getPixels();
+}
+
+} // namespace
+
ImageView::ImageView()
: image_size_set_(false),
horiz_alignment_(CENTER),
@@ -58,7 +70,7 @@ void ImageView::SetImageSize(const gfx::Size& image_size) {
PreferredSizeChanged();
}
-bool ImageView::GetImageSize(gfx::Size* image_size) {
+bool ImageView::GetImageSize(gfx::Size* image_size) const {
DCHECK(image_size);
if (image_size_set_)
*image_size = image_size_;
@@ -79,7 +91,7 @@ void ImageView::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
focus_painter_ = focus_painter.Pass();
}
-gfx::Size ImageView::GetPreferredSize() {
+gfx::Size ImageView::GetPreferredSize() const {
gfx::Insets insets = GetInsets();
if (image_size_set_) {
gfx::Size image_size;
@@ -99,8 +111,7 @@ bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
// the backing store but also the pixels of the last image we painted.
return image_.BackedBySameObjectAs(img) &&
last_paint_scale_ != 0.0f &&
- last_painted_bitmap_pixels_ ==
- img.GetRepresentation(last_paint_scale_).sk_bitmap().getPixels();
+ last_painted_bitmap_pixels_ == GetBitmapPixels(img, last_paint_scale_);
}
gfx::Point ImageView::ComputeImageOrigin(const gfx::Size& image_size) const {
@@ -150,8 +161,8 @@ void ImageView::OnPaint(gfx::Canvas* canvas) {
Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
}
-void ImageView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_GRAPHIC;
+void ImageView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_IMAGE;
state->name = tooltip_text_;
}
@@ -177,15 +188,16 @@ ImageView::Alignment ImageView::GetVerticalAlignment() const {
return vert_alignment_;
}
-void ImageView::SetTooltipText(const string16& tooltip) {
+void ImageView::SetTooltipText(const base::string16& tooltip) {
tooltip_text_ = tooltip;
}
-string16 ImageView::GetTooltipText() const {
+base::string16 ImageView::GetTooltipText() const {
return tooltip_text_;
}
-bool ImageView::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
+bool ImageView::GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const {
if (tooltip_text_.empty())
return false;
@@ -193,11 +205,10 @@ bool ImageView::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
return true;
}
-bool ImageView::HitTestRect(const gfx::Rect& rect) const {
- return interactive_ ? View::HitTestRect(rect) : false;
+bool ImageView::CanProcessEventsWithinSubtree() const {
+ return interactive_;
}
-
void ImageView::OnPaintImage(gfx::Canvas* canvas) {
last_paint_scale_ = canvas->image_scale();
last_painted_bitmap_pixels_ = NULL;
@@ -212,15 +223,14 @@ void ImageView::OnPaintImage(gfx::Canvas* canvas) {
if (image_bounds.size() != gfx::Size(image_.width(), image_.height())) {
// Resize case
SkPaint paint;
- paint.setFilterBitmap(true);
+ paint.setFilterLevel(SkPaint::kLow_FilterLevel);
canvas->DrawImageInt(image_, 0, 0, image_.width(), image_.height(),
image_bounds.x(), image_bounds.y(), image_bounds.width(),
image_bounds.height(), true, paint);
} else {
canvas->DrawImageInt(image_, image_bounds.x(), image_bounds.y());
}
- last_painted_bitmap_pixels_ =
- image_.GetRepresentation(last_paint_scale_).sk_bitmap().getPixels();
+ last_painted_bitmap_pixels_ = GetBitmapPixels(image_, last_paint_scale_);
}
} // namespace views
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index b0f4ce852ff..a05b106ecfa 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -55,7 +55,7 @@ class VIEWS_EXPORT ImageView : public View {
// Return the preferred size for the receiving view. Returns false if the
// preferred size is not defined, which means that the view uses the image
// size.
- bool GetImageSize(gfx::Size* image_size);
+ bool GetImageSize(gfx::Size* image_size) const;
// Returns the actual bounds of the visible image inside the view.
gfx::Rect GetImageBounds() const;
@@ -72,22 +72,22 @@ class VIEWS_EXPORT ImageView : public View {
Alignment GetVerticalAlignment() const;
// Set / Get the tooltip text.
- void SetTooltipText(const string16& tooltip);
- string16 GetTooltipText() const;
+ void SetTooltipText(const base::string16& tooltip);
+ base::string16 GetTooltipText() const;
void set_interactive(bool interactive) { interactive_ = interactive; }
void SetFocusPainter(scoped_ptr<Painter> focus_painter);
// Overriden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
- virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE;
private:
void OnPaintImage(gfx::Canvas* canvas);
@@ -117,7 +117,7 @@ class VIEWS_EXPORT ImageView : public View {
Alignment vert_alignment_;
// The current tooltip text.
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
// A flag controlling hit test handling for interactivity.
bool interactive_;
diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc
index 7d4bc7e8470..648a0e660bc 100644
--- a/chromium/ui/views/controls/label.cc
+++ b/chromium/ui/views/controls/label.cc
@@ -14,27 +14,21 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/insets.h"
-#include "ui/gfx/shadow_value.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
+#include "ui/gfx/utf16_indexing.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
namespace {
-// The padding for the focus border when rendering focused text.
-const int kFocusBorderPadding = 1;
const int kCachedSizeLimit = 10;
-
-gfx::FontList GetDefaultFontList() {
- return ui::ResourceBundle::GetSharedInstance().GetFontList(
- ui::ResourceBundle::BaseFont);
-}
+const base::char16 kPasswordReplacementChar = '*';
} // namespace
@@ -42,23 +36,20 @@ namespace views {
// static
const char Label::kViewClassName[] = "Label";
+const int Label::kFocusBorderPadding = 1;
Label::Label() {
- Init(string16(), GetDefaultFontList());
+ Init(base::string16(), gfx::FontList());
}
-Label::Label(const string16& text) {
- Init(text, GetDefaultFontList());
+Label::Label(const base::string16& text) {
+ Init(text, gfx::FontList());
}
-Label::Label(const string16& text, const gfx::FontList& font_list) {
+Label::Label(const base::string16& text, const gfx::FontList& font_list) {
Init(text, font_list);
}
-Label::Label(const string16& text, const gfx::Font& font) {
- Init(text, gfx::FontList(font));
-}
-
Label::~Label() {
}
@@ -69,18 +60,22 @@ void Label::SetFontList(const gfx::FontList& font_list) {
SchedulePaint();
}
-const gfx::Font& Label::font() const {
- return font_list_.GetPrimaryFont();
-}
-
-void Label::SetFont(const gfx::Font& font) {
- SetFontList(gfx::FontList(font));
+void Label::SetText(const base::string16& text) {
+ if (text != text_)
+ SetTextInternal(text);
}
-void Label::SetText(const string16& text) {
- if (text == text_)
- return;
+void Label::SetTextInternal(const base::string16& text) {
text_ = text;
+
+ if (is_obscured_) {
+ size_t obscured_text_length =
+ static_cast<size_t>(gfx::UTF16IndexToOffset(text_, 0, text_.length()));
+ layout_text_.assign(obscured_text_length, kPasswordReplacementChar);
+ } else {
+ layout_text_ = text_;
+ }
+
ResetCachedSize();
PreferredSizeChanged();
SchedulePaint();
@@ -109,26 +104,10 @@ void Label::SetBackgroundColor(SkColor color) {
RecalculateColors();
}
-void Label::SetShadowColors(SkColor enabled_color, SkColor disabled_color) {
- enabled_shadow_color_ = enabled_color;
- disabled_shadow_color_ = disabled_color;
- has_shadow_ = true;
-}
-
-void Label::SetShadowOffset(int x, int y) {
- shadow_offset_.SetPoint(x, y);
-}
-
-void Label::ClearEmbellishing() {
- has_shadow_ = false;
-}
-
void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
- // If the View's UI layout is right-to-left and directionality_mode_ is
- // USE_UI_DIRECTIONALITY, we need to flip the alignment so that the alignment
- // settings take into account the text directionality.
- if (base::i18n::IsRTL() && (directionality_mode_ == USE_UI_DIRECTIONALITY) &&
- (alignment != gfx::ALIGN_CENTER)) {
+ // If the UI layout is right-to-left, flip the alignment direction.
+ if (base::i18n::IsRTL() &&
+ (alignment == gfx::ALIGN_LEFT || alignment == gfx::ALIGN_RIGHT)) {
alignment = (alignment == gfx::ALIGN_LEFT) ?
gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
}
@@ -138,6 +117,15 @@ void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
}
}
+gfx::HorizontalAlignment Label::GetHorizontalAlignment() const {
+ if (horizontal_alignment_ != gfx::ALIGN_TO_HEAD)
+ return horizontal_alignment_;
+
+ const base::i18n::TextDirection dir =
+ base::i18n::GetFirstStrongCharacterDirection(layout_text());
+ return dir == base::i18n::RIGHT_TO_LEFT ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
+}
+
void Label::SetLineHeight(int height) {
if (height != line_height_) {
line_height_ = height;
@@ -148,7 +136,8 @@ void Label::SetLineHeight(int height) {
}
void Label::SetMultiLine(bool multi_line) {
- DCHECK(!multi_line || elide_behavior_ != ELIDE_IN_MIDDLE);
+ DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL ||
+ elide_behavior_ == gfx::TRUNCATE));
if (multi_line != is_multi_line_) {
is_multi_line_ = multi_line;
ResetCachedSize();
@@ -157,6 +146,13 @@ void Label::SetMultiLine(bool multi_line) {
}
}
+void Label::SetObscured(bool obscured) {
+ if (obscured != is_obscured_) {
+ is_obscured_ = obscured;
+ SetTextInternal(text_);
+ }
+}
+
void Label::SetAllowCharacterBreak(bool allow_character_break) {
if (allow_character_break != allow_character_break_) {
allow_character_break_ = allow_character_break;
@@ -166,8 +162,9 @@ void Label::SetAllowCharacterBreak(bool allow_character_break) {
}
}
-void Label::SetElideBehavior(ElideBehavior elide_behavior) {
- DCHECK(elide_behavior != ELIDE_IN_MIDDLE || !is_multi_line_);
+void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
+ DCHECK(!is_multi_line_ || (elide_behavior_ == gfx::ELIDE_TAIL ||
+ elide_behavior_ == gfx::TRUNCATE));
if (elide_behavior != elide_behavior_) {
elide_behavior_ = elide_behavior;
ResetCachedSize();
@@ -176,18 +173,18 @@ void Label::SetElideBehavior(ElideBehavior elide_behavior) {
}
}
-void Label::SetTooltipText(const string16& tooltip_text) {
+void Label::SetTooltipText(const base::string16& tooltip_text) {
tooltip_text_ = tooltip_text;
}
void Label::SizeToFit(int max_width) {
DCHECK(is_multi_line_);
- std::vector<string16> lines;
- base::SplitString(text_, '\n', &lines);
+ std::vector<base::string16> lines;
+ base::SplitString(layout_text(), '\n', &lines);
int label_width = 0;
- for (std::vector<string16>::const_iterator iter = lines.begin();
+ for (std::vector<base::string16>::const_iterator iter = lines.begin();
iter != lines.end(); ++iter) {
label_width = std::max(label_width, gfx::GetStringWidth(*iter, font_list_));
}
@@ -201,17 +198,9 @@ void Label::SizeToFit(int max_width) {
SizeToPreferredSize();
}
-void Label::SetHasFocusBorder(bool has_focus_border) {
- has_focus_border_ = has_focus_border;
- if (is_multi_line_) {
- ResetCachedSize();
- PreferredSizeChanged();
- }
-}
-
gfx::Insets Label::GetInsets() const {
gfx::Insets insets = View::GetInsets();
- if (focusable() || has_focus_border_) {
+ if (focusable()) {
insets += gfx::Insets(kFocusBorderPadding, kFocusBorderPadding,
kFocusBorderPadding, kFocusBorderPadding);
}
@@ -222,7 +211,7 @@ int Label::GetBaseline() const {
return GetInsets().top() + font_list_.GetBaseline();
}
-gfx::Size Label::GetPreferredSize() {
+gfx::Size Label::GetPreferredSize() const {
// Return a size of (0, 0) if the label is not visible and if the
// collapse_when_hidden_ flag is set.
// TODO(munjal): This logic probably belongs to the View class. But for now,
@@ -231,13 +220,27 @@ gfx::Size Label::GetPreferredSize() {
if (!visible() && collapse_when_hidden_)
return gfx::Size();
- gfx::Size prefsize(GetTextSize());
+ gfx::Size size(GetTextSize());
+ gfx::Insets insets = GetInsets();
+ size.Enlarge(insets.width(), insets.height());
+ return size;
+}
+
+gfx::Size Label::GetMinimumSize() const {
+ gfx::Size text_size(GetTextSize());
+ if ((!visible() && collapse_when_hidden_) || text_size.IsEmpty())
+ return gfx::Size();
+
+ gfx::Size size(gfx::GetStringWidth(base::string16(gfx::kEllipsisUTF16),
+ font_list_),
+ font_list_.GetHeight());
+ size.SetToMin(text_size); // The actual text may be shorter than an ellipsis.
gfx::Insets insets = GetInsets();
- prefsize.Enlarge(insets.width(), insets.height());
- return prefsize;
+ size.Enlarge(insets.width(), insets.height());
+ return size;
}
-int Label::GetHeightForWidth(int w) {
+int Label::GetHeightForWidth(int w) const {
if (!is_multi_line_)
return View::GetHeightForWidth(w);
@@ -253,7 +256,8 @@ int Label::GetHeightForWidth(int w) {
int h = font_list_.GetHeight();
const int flags = ComputeDrawStringFlags();
- gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags);
+ gfx::Canvas::SizeStringInt(
+ layout_text(), font_list_, &w, &h, line_height_, flags);
cached_heights_[cached_heights_cursor_] = gfx::Size(cache_width, h);
cached_heights_cursor_ = (cached_heights_cursor_ + 1) % kCachedSizeLimit;
return h + GetInsets().height();
@@ -278,11 +282,12 @@ View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) {
return this;
}
-bool Label::HitTestRect(const gfx::Rect& rect) const {
+bool Label::CanProcessEventsWithinSubtree() const {
+ // Send events to the parent view for handling.
return false;
}
-bool Label::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
+bool Label::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
DCHECK(tooltip);
// If a tooltip has been explicitly set, use it.
@@ -293,30 +298,30 @@ bool Label::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
// Show the full text if the text does not fit.
if (ShouldShowDefaultTooltip()) {
- *tooltip = text_;
+ *tooltip = layout_text();
return true;
}
return false;
}
-void Label::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_STATICTEXT;
- state->state = ui::AccessibilityTypes::STATE_READONLY;
- state->name = text_;
+void Label::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_STATIC_TEXT;
+ state->AddStateFlag(ui::AX_STATE_READ_ONLY);
+ state->name = layout_text();
}
void Label::PaintText(gfx::Canvas* canvas,
- const string16& text,
+ const base::string16& text,
const gfx::Rect& text_bounds,
int flags) {
- gfx::ShadowValues shadows;
- if (has_shadow_)
- shadows.push_back(gfx::ShadowValue(shadow_offset_, 0,
- enabled() ? enabled_shadow_color_ : disabled_shadow_color_));
- canvas->DrawStringRectWithShadows(text, font_list_,
- enabled() ? actual_enabled_color_ : actual_disabled_color_,
- text_bounds, line_height_, flags, shadows);
+ SkColor color = enabled() ? actual_enabled_color_ : actual_disabled_color_;
+ if (elide_behavior_ == gfx::FADE_TAIL) {
+ canvas->DrawFadedString(text, font_list_, color, text_bounds, flags);
+ } else {
+ canvas->DrawStringRectWithShadows(text, font_list_, color, text_bounds,
+ line_height_, flags, shadows_);
+ }
if (HasFocus()) {
gfx::Rect focus_bounds = text_bounds;
@@ -339,8 +344,11 @@ gfx::Size Label::GetTextSize() const {
int flags = ComputeDrawStringFlags();
if (!is_multi_line_)
flags |= gfx::Canvas::NO_ELLIPSIS;
- gfx::Canvas::SizeStringInt(text_, font_list_, &w, &h, line_height_, flags);
+ gfx::Canvas::SizeStringInt(
+ layout_text(), font_list_, &w, &h, line_height_, flags);
text_size_.SetSize(w, h);
+ const gfx::Insets shadow_margin = -gfx::ShadowValue::GetMargin(shadows_);
+ text_size_.Enlarge(shadow_margin.width(), shadow_margin.height());
text_size_valid_ = true;
}
@@ -358,7 +366,7 @@ void Label::OnPaint(gfx::Canvas* canvas) {
// interfere with that.
OnPaintBorder(canvas);
- string16 paint_text;
+ base::string16 paint_text;
gfx::Rect text_bounds;
int flags = 0;
CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
@@ -369,23 +377,20 @@ void Label::OnNativeThemeChanged(const ui::NativeTheme* theme) {
UpdateColorsFromTheme(theme);
}
-void Label::Init(const string16& text, const gfx::FontList& font_list) {
+void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
font_list_ = font_list;
enabled_color_set_ = disabled_color_set_ = background_color_set_ = false;
+ subpixel_rendering_enabled_ = true;
auto_color_readability_ = true;
UpdateColorsFromTheme(ui::NativeTheme::instance());
horizontal_alignment_ = gfx::ALIGN_CENTER;
line_height_ = 0;
is_multi_line_ = false;
+ is_obscured_ = false;
allow_character_break_ = false;
- elide_behavior_ = ELIDE_AT_END;
+ elide_behavior_ = gfx::ELIDE_TAIL;
collapse_when_hidden_ = false;
- directionality_mode_ = USE_UI_DIRECTIONALITY;
- has_focus_border_ = false;
- enabled_shadow_color_ = 0;
- disabled_shadow_color_ = 0;
- shadow_offset_.SetPoint(1, 1);
- has_shadow_ = false;
+ directionality_mode_ = gfx::DIRECTIONALITY_FROM_UI;
cached_heights_.resize(kCachedSizeLimit);
ResetCachedSize();
@@ -404,52 +409,50 @@ void Label::RecalculateColors() {
}
gfx::Rect Label::GetTextBounds() const {
- gfx::Rect available_rect(GetAvailableRect());
+ gfx::Rect available(GetAvailableRect());
gfx::Size text_size(GetTextSize());
- text_size.set_width(std::min(available_rect.width(), text_size.width()));
-
- gfx::Insets insets = GetInsets();
- gfx::Point text_origin(insets.left(), insets.top());
- switch (horizontal_alignment_) {
+ text_size.set_width(std::min(available.width(), text_size.width()));
+ gfx::Point origin(GetInsets().left(), GetInsets().top());
+ switch (GetHorizontalAlignment()) {
case gfx::ALIGN_LEFT:
break;
case gfx::ALIGN_CENTER:
- // We put any extra margin pixel on the left rather than the right. We
- // used to do this because measurement on Windows used
- // GetTextExtentPoint32(), which could report a value one too large on the
- // right; we now use DrawText(), and who knows if it can also do this.
- text_origin.Offset((available_rect.width() + 1 - text_size.width()) / 2,
- 0);
+ // Put any extra margin pixel on the left to match the legacy behavior
+ // from the use of GetTextExtentPoint32() on Windows.
+ origin.Offset((available.width() + 1 - text_size.width()) / 2, 0);
break;
case gfx::ALIGN_RIGHT:
- text_origin.set_x(available_rect.right() - text_size.width());
+ origin.set_x(available.right() - text_size.width());
break;
default:
NOTREACHED();
break;
}
- text_origin.Offset(0,
- std::max(0, (available_rect.height() - text_size.height())) / 2);
- return gfx::Rect(text_origin, text_size);
+ origin.Offset(0, std::max(0, (available.height() - text_size.height())) / 2);
+ return gfx::Rect(origin, text_size);
}
int Label::ComputeDrawStringFlags() const {
int flags = 0;
// We can't use subpixel rendering if the background is non-opaque.
- if (SkColorGetA(background_color_) != 0xFF)
+ if (SkColorGetA(background_color_) != 0xFF || !subpixel_rendering_enabled_)
flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
- if (directionality_mode_ == AUTO_DETECT_DIRECTIONALITY) {
+ if (directionality_mode_ == gfx::DIRECTIONALITY_FORCE_LTR) {
+ flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
+ } else if (directionality_mode_ == gfx::DIRECTIONALITY_FORCE_RTL) {
+ flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
+ } else if (directionality_mode_ == gfx::DIRECTIONALITY_FROM_TEXT) {
base::i18n::TextDirection direction =
- base::i18n::GetFirstStrongCharacterDirection(text_);
+ base::i18n::GetFirstStrongCharacterDirection(layout_text());
if (direction == base::i18n::RIGHT_TO_LEFT)
flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
else
flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
}
- switch (horizontal_alignment_) {
+ switch (GetHorizontalAlignment()) {
case gfx::ALIGN_LEFT:
flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
break;
@@ -459,6 +462,9 @@ int Label::ComputeDrawStringFlags() const {
case gfx::ALIGN_RIGHT:
flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
break;
+ default:
+ NOTREACHED();
+ break;
}
if (!is_multi_line_)
@@ -485,31 +491,25 @@ gfx::Rect Label::GetAvailableRect() const {
return bounds;
}
-void Label::CalculateDrawStringParams(string16* paint_text,
+void Label::CalculateDrawStringParams(base::string16* paint_text,
gfx::Rect* text_bounds,
int* flags) const {
DCHECK(paint_text && text_bounds && flags);
- // TODO(msw): Use ElideRectangleText to support eliding multi-line text. Once
- // this is done, we can set NO_ELLIPSIS unconditionally at the bottom.
- if (is_multi_line_ || (elide_behavior_ == NO_ELIDE)) {
- *paint_text = text_;
- } else if (elide_behavior_ == ELIDE_IN_MIDDLE) {
- *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(),
- gfx::ELIDE_IN_MIDDLE);
- } else if (elide_behavior_ == ELIDE_AT_END) {
- *paint_text = gfx::ElideText(text_, font_list_, GetAvailableRect().width(),
- gfx::ELIDE_AT_END);
+ const bool forbid_ellipsis = elide_behavior_ == gfx::TRUNCATE ||
+ elide_behavior_ == gfx::FADE_TAIL;
+ if (is_multi_line_ || forbid_ellipsis) {
+ *paint_text = layout_text();
} else {
- DCHECK_EQ(ELIDE_AS_EMAIL, elide_behavior_);
- *paint_text = gfx::ElideEmail(text_, font_list_,
- GetAvailableRect().width());
+ *paint_text = gfx::ElideText(layout_text(), font_list_,
+ GetAvailableRect().width(), elide_behavior_);
}
*text_bounds = GetTextBounds();
*flags = ComputeDrawStringFlags();
- if (!is_multi_line_ || (elide_behavior_ == NO_ELIDE))
- *flags |= gfx::Canvas::NO_ELLIPSIS;
+ // TODO(msw): Elide multi-line text with ElideRectangleText instead.
+ if (!is_multi_line_ || forbid_ellipsis)
+ *flags |= gfx::Canvas::NO_ELLIPSIS;
}
void Label::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
@@ -536,8 +536,9 @@ void Label::ResetCachedSize() {
}
bool Label::ShouldShowDefaultTooltip() const {
- return !is_multi_line_ &&
- gfx::GetStringWidth(text_, font_list_) > GetAvailableRect().width();
+ return !is_multi_line_ && !is_obscured_ &&
+ gfx::GetStringWidth(layout_text(), font_list_) >
+ GetAvailableRect().width();
}
} // namespace views
diff --git a/chromium/ui/views/controls/label.h b/chromium/ui/views/controls/label.h
index 40534ff654f..f146b18d4af 100644
--- a/chromium/ui/views/controls/label.h
+++ b/chromium/ui/views/controls/label.h
@@ -13,61 +13,33 @@
#include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/font_list.h"
+#include "ui/gfx/shadow_value.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/view.h"
namespace views {
-/////////////////////////////////////////////////////////////////////////////
-//
-// Label class
-//
-// A label is a view subclass that can display a string.
-//
-/////////////////////////////////////////////////////////////////////////////
+// A view subclass that can display a string.
class VIEWS_EXPORT Label : public View {
public:
// Internal class name.
static const char kViewClassName[];
- // The following enum is used to indicate whether using the Chrome UI's
- // directionality as the label's directionality, or auto-detecting the label's
- // directionality.
- //
- // If the label text originates from the Chrome UI, we should use the Chrome
- // UI's directionality as the label's directionality.
- //
- // If the text originates from a web page, its directionality is determined
- // based on its first character with strong directionality, disregarding what
- // directionality the Chrome UI is.
- enum DirectionalityMode {
- USE_UI_DIRECTIONALITY = 0,
- AUTO_DETECT_DIRECTIONALITY
- };
-
- enum ElideBehavior {
- NO_ELIDE, // Do not elide the label text; truncate as needed.
- ELIDE_IN_MIDDLE, // Add ellipsis in the middle of the string as needed.
- ELIDE_AT_END, // Add ellipsis at the end of the string as needed.
- ELIDE_AS_EMAIL, // Elide while retaining username/domain chars as needed.
- };
+ // The padding for the focus border when rendering focused text.
+ static const int kFocusBorderPadding;
Label();
- explicit Label(const string16& text);
- Label(const string16& text, const gfx::FontList& font_list);
- Label(const string16& text, const gfx::Font& font); // OBSOLETE
+ explicit Label(const base::string16& text);
+ Label(const base::string16& text, const gfx::FontList& font_list);
virtual ~Label();
// Gets or sets the fonts used by this label.
const gfx::FontList& font_list() const { return font_list_; }
virtual void SetFontList(const gfx::FontList& font_list);
- // Obsolete gfx::Font version. Should use gfx::FontList version instead.
- const gfx::Font& font() const; // OBSOLETE
- virtual void SetFont(const gfx::Font& font); // OBSOLETE
// Get or set the label text.
- const string16& text() const { return text_; }
- void SetText(const string16& text);
+ const base::string16& text() const { return text_; }
+ virtual void SetText(const base::string16& text);
// Enables or disables auto-color-readability (enabled by default). If this
// is enabled, then calls to set any foreground or background color will
@@ -87,37 +59,30 @@ class VIEWS_EXPORT Label : public View {
void SetBackgroundColor(SkColor color);
SkColor background_color() const { return background_color_; }
- // Enables a drop shadow underneath the text.
- void SetShadowColors(SkColor enabled_color, SkColor disabled_color);
-
- // Sets the drop shadow's offset from the text.
- void SetShadowOffset(int x, int y);
+ // Set drop shadows underneath the text.
+ void set_shadows(const gfx::ShadowValues& shadows) {
+ shadows_ = shadows;
+ text_size_valid_ = false;
+ }
+ const gfx::ShadowValues& shadows() const { return shadows_; }
- // Disables shadows.
- void ClearEmbellishing();
+ // Sets whether subpixel rendering is used; the default is true, but this
+ // feature also requires an opaque background color.
+ void set_subpixel_rendering_enabled(bool subpixel_rendering_enabled) {
+ subpixel_rendering_enabled_ = subpixel_rendering_enabled;
+ }
- // Sets horizontal alignment. If the locale is RTL, and the directionality
- // mode is USE_UI_DIRECTIONALITY, the alignment is flipped around.
- //
- // Caveat: for labels originating from a web page, the directionality mode
- // should be reset to AUTO_DETECT_DIRECTIONALITY before the horizontal
- // alignment is set. Otherwise, the label's alignment specified as a parameter
- // will be flipped in RTL locales.
+ // Sets the horizontal alignment; the argument value is mirrored in RTL UI.
void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
+ gfx::HorizontalAlignment GetHorizontalAlignment() const;
- gfx::HorizontalAlignment horizontal_alignment() const {
- return horizontal_alignment_;
- }
-
- // Sets the directionality mode. The directionality mode is initialized to
- // USE_UI_DIRECTIONALITY when the label is constructed. USE_UI_DIRECTIONALITY
- // applies to every label that originates from the Chrome UI. However, if the
- // label originates from a web page, its directionality is auto-detected.
- void set_directionality_mode(DirectionalityMode mode) {
+ // Sets the directionality mode. The default value is DIRECTIONALITY_FROM_UI,
+ // which should be suitable for most text originating from UI string assets.
+ // Most text originating from web content should use DIRECTIONALITY_FROM_TEXT.
+ void set_directionality_mode(gfx::DirectionalityMode mode) {
directionality_mode_ = mode;
}
-
- DirectionalityMode directionality_mode() const {
+ gfx::DirectionalityMode directionality_mode() const {
return directionality_mode_;
}
@@ -131,20 +96,27 @@ class VIEWS_EXPORT Label : public View {
bool is_multi_line() const { return is_multi_line_; }
void SetMultiLine(bool multi_line);
+ // Get or set if the label text should be obscured before rendering (e.g.
+ // should "Password!" display as "*********"); default is false.
+ bool is_obscured() const { return is_obscured_; }
+ void SetObscured(bool obscured);
+
+ // Get the text as displayed to the user, respecting the 'obscured' flag.
+ const base::string16& layout_text() const { return layout_text_; }
+
// Sets whether the label text can be split on words.
// Default is false. This only works when is_multi_line is true.
void SetAllowCharacterBreak(bool allow_character_break);
- // Sets whether the label text should be elided in the middle or end (if
- // necessary). The default is to elide at the end.
- // NOTE: Eliding in the middle is not supported for multi-line strings.
- void SetElideBehavior(ElideBehavior elide_behavior);
+ // 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.
+ void SetElideBehavior(gfx::ElideBehavior 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.
- void SetTooltipText(const string16& tooltip_text);
+ void SetTooltipText(const base::string16& tooltip_text);
// Resizes the label so its width is set to the width of the longest line and
// its height deduced accordingly.
@@ -160,33 +132,33 @@ class VIEWS_EXPORT Label : public View {
void set_collapse_when_hidden(bool value) { collapse_when_hidden_ = value; }
bool collapse_when_hidden() const { return collapse_when_hidden_; }
- void SetHasFocusBorder(bool has_focus_border);
-
- // Overridden from View:
+ // View:
virtual gfx::Insets GetInsets() const OVERRIDE;
virtual int GetBaseline() const OVERRIDE;
// Overridden to compute the size required to display this label.
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ // Returns the width of an ellipsis if the label is non-empty, or 0 otherwise.
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
// Returns the height necessary to display this label with the provided width.
// This method is used to layout multi-line labels. It is equivalent to
// GetPreferredSize().height() if the receiver is not multi-line.
- virtual int GetHeightForWidth(int w) OVERRIDE;
+ virtual int GetHeightForWidth(int w) const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE;
- virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// Gets the tooltip text for labels that are wider than their bounds, except
// when the label is multiline, in which case it just returns false (no
// tooltip). If a custom tooltip has been specified with SetTooltipText()
// it is returned instead.
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
protected:
// Called by Paint to paint the text. Override this to change how
// text is painted.
virtual void PaintText(gfx::Canvas* canvas,
- const string16& text,
+ const base::string16& text,
const gfx::Rect& text_bounds,
int flags);
@@ -207,12 +179,14 @@ class VIEWS_EXPORT Label : public View {
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineString);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawSingleLineStringInRTL);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineStringInRTL);
- FRIEND_TEST_ALL_PREFIXES(LabelTest, AutoDetectDirectionality);
-
- // Calls ComputeDrawStringFlags().
+ FRIEND_TEST_ALL_PREFIXES(LabelTest, DirectionalityFromText);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DisableSubpixelRendering);
- void Init(const string16& text, const gfx::FontList& font_list);
+ // Sets both |text_| and |layout_text_| to appropriate values, taking
+ // the label's 'obscured' status into account.
+ void SetTextInternal(const base::string16& text);
+
+ void Init(const base::string16& text, const gfx::FontList& font_list);
void RecalculateColors();
@@ -224,7 +198,7 @@ class VIEWS_EXPORT Label : public View {
gfx::Rect GetAvailableRect() const;
// Returns parameters to be used for the DrawString call.
- void CalculateDrawStringParams(string16* paint_text,
+ void CalculateDrawStringParams(base::string16* paint_text,
gfx::Rect* text_bounds,
int* flags) const;
@@ -237,7 +211,8 @@ class VIEWS_EXPORT Label : public View {
bool ShouldShowDefaultTooltip() const;
- string16 text_;
+ base::string16 text_;
+ base::string16 layout_text_;
gfx::FontList font_list_;
SkColor requested_enabled_color_;
SkColor actual_enabled_color_;
@@ -250,39 +225,27 @@ class VIEWS_EXPORT Label : public View {
bool disabled_color_set_;
bool background_color_set_;
+ bool subpixel_rendering_enabled_;
bool auto_color_readability_;
mutable gfx::Size text_size_;
mutable bool text_size_valid_;
int line_height_;
bool is_multi_line_;
+ bool is_obscured_;
bool allow_character_break_;
- ElideBehavior elide_behavior_;
+ gfx::ElideBehavior elide_behavior_;
gfx::HorizontalAlignment horizontal_alignment_;
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
// Whether to collapse the label when it's not visible.
bool collapse_when_hidden_;
- // The following member variable is used to control whether the
- // directionality is auto-detected based on first strong directionality
- // character or is determined by chrome UI's locale.
- DirectionalityMode directionality_mode_;
- // When embedded in a larger control that is focusable, setting this flag
- // allows this view to reserve space for a focus border that it otherwise
- // might not have because it is not itself focusable.
- bool has_focus_border_;
-
- // Colors for shadow.
- SkColor enabled_shadow_color_;
- SkColor disabled_shadow_color_;
-
- // Space between text and shadow.
- gfx::Point shadow_offset_;
-
- // Should a shadow be drawn behind the text?
- bool has_shadow_;
+ // Controls whether the directionality is auto-detected based on first strong
+ // directionality character or is determined by the application UI's locale.
+ gfx::DirectionalityMode directionality_mode_;
+ gfx::ShadowValues shadows_;
// The cached heights to avoid recalculation in GetHeightForWidth().
- std::vector<gfx::Size> cached_heights_;
- int cached_heights_cursor_;
+ mutable std::vector<gfx::Size> cached_heights_;
+ mutable int cached_heights_cursor_;
DISALLOW_COPY_AND_ASSIGN(Label);
};
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index e2a37c3a167..8b16d0f6844 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -7,16 +7,25 @@
#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h"
#include "ui/views/border.h"
+using base::ASCIIToUTF16;
+
namespace views {
// All text sizing measurements (width and height) should be greater than this.
const int kMinTextDimension = 4;
+// A test utility function to set the application default text direction.
+void SetRTL(bool rtl) {
+ // Override the current locale/direction.
+ base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
+ EXPECT_EQ(rtl, base::i18n::IsRTL());
+}
+
TEST(LabelTest, FontPropertySymbol) {
Label label;
std::string font_name("symbol");
@@ -39,7 +48,7 @@ TEST(LabelTest, FontPropertyArial) {
TEST(LabelTest, TextProperty) {
Label label;
- string16 test_text(ASCIIToUTF16("A random string."));
+ base::string16 test_text(ASCIIToUTF16("A random string."));
label.SetText(test_text);
EXPECT_EQ(test_text, label.text());
}
@@ -53,38 +62,45 @@ TEST(LabelTest, ColorProperty) {
}
TEST(LabelTest, AlignmentProperty) {
- Label label;
- bool reverse_alignment = base::i18n::IsRTL();
+ const bool was_rtl = base::i18n::IsRTL();
- label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
- EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT,
- label.horizontal_alignment());
- label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
- EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
- label.horizontal_alignment());
- label.SetHorizontalAlignment(gfx::ALIGN_CENTER);
- EXPECT_EQ(gfx::ALIGN_CENTER, label.horizontal_alignment());
+ Label label;
+ for (size_t i = 0; i < 2; ++i) {
+ // Toggle the application default text direction (to try each direction).
+ SetRTL(!base::i18n::IsRTL());
+ bool reverse_alignment = base::i18n::IsRTL();
+
+ // The alignment should be flipped in RTL UI.
+ label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
+ EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT,
+ label.GetHorizontalAlignment());
+ label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
+ label.GetHorizontalAlignment());
+ label.SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ 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(rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
+ label.GetHorizontalAlignment());
+ }
+ }
- // The label's alignment should not be flipped if the directionality mode is
- // AUTO_DETECT_DIRECTIONALITY.
- label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
- label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
- EXPECT_EQ(gfx::ALIGN_RIGHT, label.horizontal_alignment());
- label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
- EXPECT_EQ(gfx::ALIGN_LEFT, label.horizontal_alignment());
- label.SetHorizontalAlignment(gfx::ALIGN_CENTER);
- EXPECT_EQ(gfx::ALIGN_CENTER, label.horizontal_alignment());
+ EXPECT_EQ(was_rtl, base::i18n::IsRTL());
}
TEST(LabelTest, DirectionalityModeProperty) {
Label label;
- EXPECT_EQ(Label::USE_UI_DIRECTIONALITY, label.directionality_mode());
+ EXPECT_EQ(gfx::DIRECTIONALITY_FROM_UI, label.directionality_mode());
- label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
- EXPECT_EQ(Label::AUTO_DETECT_DIRECTIONALITY, label.directionality_mode());
+ label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT);
+ EXPECT_EQ(gfx::DIRECTIONALITY_FROM_TEXT, label.directionality_mode());
- label.set_directionality_mode(Label::USE_UI_DIRECTIONALITY);
- EXPECT_EQ(Label::USE_UI_DIRECTIONALITY, label.directionality_mode());
+ label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_UI);
+ EXPECT_EQ(gfx::DIRECTIONALITY_FROM_UI, label.directionality_mode());
}
TEST(LabelTest, MultiLineProperty) {
@@ -96,24 +112,59 @@ TEST(LabelTest, MultiLineProperty) {
EXPECT_FALSE(label.is_multi_line());
}
-TEST(LabelTest, TooltipProperty) {
+TEST(LabelTest, ObscuredProperty) {
Label label;
- string16 test_text(ASCIIToUTF16("My cool string."));
+ base::string16 test_text(ASCIIToUTF16("Password!"));
label.SetText(test_text);
- string16 tooltip;
+ // Should be false by default...
+ EXPECT_FALSE(label.is_obscured());
+ EXPECT_EQ(test_text, label.layout_text());
+ EXPECT_EQ(test_text, label.text());
+
+ label.SetObscured(true);
+ EXPECT_TRUE(label.is_obscured());
+ EXPECT_EQ(ASCIIToUTF16("*********"), label.layout_text());
+ EXPECT_EQ(test_text, label.text());
+
+ label.SetText(test_text + test_text);
+ EXPECT_EQ(ASCIIToUTF16("******************"), label.layout_text());
+ EXPECT_EQ(test_text + test_text, label.text());
+
+ label.SetObscured(false);
+ EXPECT_FALSE(label.is_obscured());
+ EXPECT_EQ(test_text + test_text, label.layout_text());
+ EXPECT_EQ(test_text + test_text, label.text());
+}
+
+TEST(LabelTest, ObscuredSurrogatePair) {
+ // 'MUSICAL SYMBOL G CLEF': represented in UTF-16 as two characters
+ // forming the surrogate pair 0x0001D11E.
+ Label label;
+ base::string16 test_text = base::UTF8ToUTF16("\xF0\x9D\x84\x9E");
+ label.SetText(test_text);
+
+ label.SetObscured(true);
+ EXPECT_EQ(ASCIIToUTF16("*"), label.layout_text());
+ EXPECT_EQ(test_text, label.text());
+}
+
+TEST(LabelTest, TooltipProperty) {
+ Label label;
+ label.SetText(ASCIIToUTF16("My cool string."));
+
+ base::string16 tooltip;
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
- EXPECT_EQ(test_text, tooltip);
+ EXPECT_EQ(label.text(), tooltip);
- string16 tooltip_text(ASCIIToUTF16("The tooltip!"));
+ base::string16 tooltip_text(ASCIIToUTF16("The tooltip!"));
label.SetTooltipText(tooltip_text);
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
EXPECT_EQ(tooltip_text, tooltip);
- string16 empty_text;
- label.SetTooltipText(empty_text);
+ label.SetTooltipText(base::string16());
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
- EXPECT_EQ(test_text, tooltip);
+ EXPECT_EQ(label.text(), tooltip);
// Make the label big enough to hold the text
// and expect there to be no tooltip.
@@ -125,13 +176,21 @@ TEST(LabelTest, TooltipProperty) {
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
EXPECT_EQ(tooltip_text, tooltip);
// Clear out the tooltip.
- label.SetTooltipText(empty_text);
+ label.SetTooltipText(base::string16());
// Shrink the bounds and the tooltip should come back.
label.SetBounds(0, 0, 1, 1);
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
- // Make the label multiline and there is no tooltip again.
+ // Make the label obscured and there is no tooltip.
+ label.SetObscured(true);
+ EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
+
+ // Obscuring the text shouldn't permanently clobber the tooltip.
+ label.SetObscured(false);
+ EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
+
+ // Make the label multiline and there is no tooltip.
label.SetMultiLine(true);
EXPECT_FALSE(label.GetTooltipText(gfx::Point(), &tooltip));
@@ -140,25 +199,23 @@ TEST(LabelTest, TooltipProperty) {
EXPECT_TRUE(label.GetTooltipText(gfx::Point(), &tooltip));
EXPECT_EQ(tooltip_text, tooltip);
// Clear out the tooltip.
- label.SetTooltipText(empty_text);
+ label.SetTooltipText(base::string16());
}
TEST(LabelTest, Accessibility) {
Label label;
- string16 test_text(ASCIIToUTF16("My special text."));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("My special text."));
- ui::AccessibleViewState state;
+ ui::AXViewState state;
label.GetAccessibleState(&state);
- EXPECT_EQ(ui::AccessibilityTypes::ROLE_STATICTEXT, state.role);
- EXPECT_EQ(test_text, state.name);
- EXPECT_TRUE(ui::AccessibilityTypes::STATE_READONLY & state.state);
+ EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, state.role);
+ EXPECT_EQ(label.text(), state.name);
+ EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY));
}
TEST(LabelTest, SingleLineSizing) {
Label label;
- string16 test_text(ASCIIToUTF16("A not so random string in one line."));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("A not so random string in one line."));
// GetPreferredSize
gfx::Size required_size = label.GetPreferredSize();
@@ -167,10 +224,8 @@ TEST(LabelTest, SingleLineSizing) {
// Test everything with borders.
gfx::Insets border(10, 20, 30, 40);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
// GetPreferredSize and borders.
label.SetBounds(0, 0, 0, 0);
@@ -183,28 +238,23 @@ TEST(LabelTest, SingleLineSizing) {
TEST(LabelTest, MultilineSmallAvailableWidthSizing) {
Label label;
- string16 test_text(ASCIIToUTF16("Too Wide."));
-
label.SetMultiLine(true);
label.SetAllowCharacterBreak(true);
- label.SetElideBehavior(Label::ELIDE_AT_END);
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("Too Wide."));
// Check that Label can be laid out at a variety of small sizes,
// splitting the words into up to one character per line if necessary.
// Incorrect word splitting may cause infinite loops in text layout.
gfx::Size required_size = label.GetPreferredSize();
- for (int i = 1; i < required_size.width(); ++i) {
+ for (int i = 1; i < required_size.width(); ++i)
EXPECT_GT(label.GetHeightForWidth(i), 0);
- }
}
TEST(LabelTest, MultiLineSizing) {
Label label;
label.SetFocusable(false);
- string16 test_text(
+ label.SetText(
ASCIIToUTF16("A random string\nwith multiple lines\nand returns!"));
- label.SetText(test_text);
label.SetMultiLine(true);
// GetPreferredSize
@@ -248,10 +298,8 @@ TEST(LabelTest, MultiLineSizing) {
// Test everything with borders.
gfx::Insets border(10, 20, 30, 40);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
// SizeToFit and borders.
label.SizeToFit(0);
@@ -283,37 +331,23 @@ TEST(LabelTest, MultiLineSizing) {
required_size.width() + border.width());
}
-TEST(LabelTest, AutoDetectDirectionality) {
+TEST(LabelTest, DirectionalityFromText) {
Label label;
- label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
+ label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT);
+ label.SetBounds(0, 0, 1000, 1000);
+ base::string16 paint_text;
+ gfx::Rect text_bounds;
+ int flags = -1;
// Test text starts with RTL character.
- string16 test_text(WideToUTF16(L" \x5d0\x5d1\x5d2 abc"));
- label.SetText(test_text);
- gfx::Size required_size(label.GetPreferredSize());
- gfx::Size extra(22, 8);
- label.SetBounds(0,
- 0,
- required_size.width() + extra.width(),
- required_size.height() + extra.height());
-
- string16 paint_text;
- gfx::Rect text_bounds;
- int flags;
+ label.SetText(base::WideToUTF16(L" \x5d0\x5d1\x5d2 abc"));
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(gfx::Canvas::FORCE_RTL_DIRECTIONALITY,
flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY));
// Test text starts with LTR character.
- test_text = (WideToUTF16(L"ltr \x5d0\x5d1\x5d2 abc"));
- label.SetText(test_text);
- required_size = label.GetPreferredSize();
- label.SetBounds(0,
- 0,
- required_size.width() + extra.width(),
- required_size.height() + extra.height());
-
+ label.SetText(base::WideToUTF16(L"ltr \x5d0\x5d1\x5d2 abc"));
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(gfx::Canvas::FORCE_LTR_DIRECTIONALITY,
flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY |
@@ -323,28 +357,23 @@ TEST(LabelTest, AutoDetectDirectionality) {
TEST(LabelTest, DrawSingleLineString) {
Label label;
label.SetFocusable(false);
+ // Force a directionality to simplify alignment value testing.
+ label.set_directionality_mode(gfx::DIRECTIONALITY_FORCE_LTR);
- // Turn off mirroring so that we don't need to figure out if
- // align right really means align left.
- label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
-
- string16 test_text(ASCIIToUTF16("Here's a string with no returns."));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("Here's a string with no returns."));
gfx::Size required_size(label.GetPreferredSize());
gfx::Size extra(22, 8);
- label.SetBounds(0,
- 0,
- required_size.width() + extra.width(),
+ label.SetBounds(0, 0, required_size.width() + extra.width(),
required_size.height() + extra.height());
// Do some basic verifications for all three alignments.
- string16 paint_text;
+ base::string16 paint_text;
gfx::Rect text_bounds;
- int flags;
+ int flags = -1;
// Centered text.
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be centered horizontally and vertically.
EXPECT_EQ(extra.width() / 2, text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -360,7 +389,7 @@ TEST(LabelTest, DrawSingleLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be left aligned horizontally and centered vertically.
EXPECT_EQ(0, text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -376,7 +405,7 @@ TEST(LabelTest, DrawSingleLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be right aligned horizontally and centered vertically.
EXPECT_EQ(extra.width(), text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -389,19 +418,15 @@ TEST(LabelTest, DrawSingleLineString) {
// Test single line drawing with a border.
gfx::Insets border(39, 34, 8, 96);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
gfx::Size required_size_with_border(label.GetPreferredSize());
EXPECT_EQ(required_size.width() + border.width(),
required_size_with_border.width());
EXPECT_EQ(required_size.height() + border.height(),
required_size_with_border.height());
- label.SetBounds(0,
- 0,
- required_size_with_border.width() + extra.width(),
+ label.SetBounds(0, 0, required_size_with_border.width() + extra.width(),
required_size_with_border.height() + extra.height());
// Centered text with border.
@@ -409,7 +434,7 @@ TEST(LabelTest, DrawSingleLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be centered horizontally and vertically within the border.
EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -425,7 +450,7 @@ TEST(LabelTest, DrawSingleLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be left aligned horizontally and centered vertically.
EXPECT_EQ(border.left(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -441,7 +466,7 @@ TEST(LabelTest, DrawSingleLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be right aligned horizontally and centered vertically.
EXPECT_EQ(border.left() + extra.width(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -453,33 +478,29 @@ TEST(LabelTest, DrawSingleLineString) {
gfx::Canvas::TEXT_ALIGN_RIGHT));
}
-// On Linux the underlying pango routines require a max height in order to
-// ellide multiline text. So until that can be resolved, we set all
-// multiline lables to not ellide in Linux only.
+// Pango needs a max height to elide multiline text; that is not supported here.
TEST(LabelTest, DrawMultiLineString) {
Label label;
label.SetFocusable(false);
+ // Force a directionality to simplify alignment value testing.
+ label.set_directionality_mode(gfx::DIRECTIONALITY_FORCE_LTR);
+ // Set a background color to prevent gfx::Canvas::NO_SUBPIXEL_RENDERING flags.
+ label.SetBackgroundColor(SK_ColorWHITE);
- // Turn off mirroring so that we don't need to figure out if
- // align right really means align left.
- label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
-
- string16 test_text(ASCIIToUTF16("Another string\nwith returns\n\n!"));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!"));
label.SetMultiLine(true);
label.SizeToFit(0);
gfx::Size extra(50, 10);
- label.SetBounds(label.x(),
- label.y(),
+ label.SetBounds(label.x(), label.y(),
label.width() + extra.width(),
label.height() + extra.height());
// Do some basic verifications for all three alignments.
- string16 paint_text;
+ base::string16 paint_text;
gfx::Rect text_bounds;
- int flags;
+ int flags = -1;
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width() / 2, text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
@@ -487,18 +508,17 @@ TEST(LabelTest, DrawMultiLineString) {
int expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_CENTER |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
gfx::Rect center_bounds(text_bounds);
label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(0, text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
@@ -506,17 +526,16 @@ TEST(LabelTest, DrawMultiLineString) {
expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_LEFT |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width(), text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
@@ -524,21 +543,17 @@ TEST(LabelTest, DrawMultiLineString) {
expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_RIGHT |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
// Test multiline drawing with a border.
gfx::Insets border(19, 92, 23, 2);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
label.SizeToFit(0);
- label.SetBounds(label.x(),
- label.y(),
+ label.SetBounds(label.x(), label.y(),
label.width() + extra.width(),
label.height() + extra.height());
@@ -546,7 +561,7 @@ TEST(LabelTest, DrawMultiLineString) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
@@ -554,17 +569,16 @@ TEST(LabelTest, DrawMultiLineString) {
expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_CENTER |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(border.left(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
@@ -572,17 +586,16 @@ TEST(LabelTest, DrawMultiLineString) {
expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_LEFT |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width() + border.left(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
@@ -590,11 +603,10 @@ TEST(LabelTest, DrawMultiLineString) {
expected_flags = gfx::Canvas::MULTI_LINE |
gfx::Canvas::TEXT_ALIGN_RIGHT |
gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
-#if defined(OS_WIN)
- EXPECT_EQ(expected_flags, flags);
-#else
- EXPECT_EQ(expected_flags | gfx::Canvas::NO_ELLIPSIS, flags);
+#if !defined(OS_WIN)
+ expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif
+ EXPECT_EQ(expected_flags, expected_flags);
}
TEST(LabelTest, DrawSingleLineStringInRTL) {
@@ -604,23 +616,20 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
std::string locale = l10n_util::GetApplicationLocale("");
base::i18n::SetICUDefaultLocale("he");
- string16 test_text(ASCIIToUTF16("Here's a string with no returns."));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("Here's a string with no returns."));
gfx::Size required_size(label.GetPreferredSize());
gfx::Size extra(22, 8);
- label.SetBounds(0,
- 0,
- required_size.width() + extra.width(),
+ label.SetBounds(0, 0, required_size.width() + extra.width(),
required_size.height() + extra.height());
// Do some basic verifications for all three alignments.
- string16 paint_text;
+ base::string16 paint_text;
gfx::Rect text_bounds;
- int flags;
+ int flags = -1;
// Centered text.
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be centered horizontally and vertically.
EXPECT_EQ(extra.width() / 2, text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -636,7 +645,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be right aligned horizontally and centered vertically.
EXPECT_EQ(extra.width(), text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -652,7 +661,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be left aligned horizontally and centered vertically.
EXPECT_EQ(0, text_bounds.x());
EXPECT_EQ(extra.height() / 2 , text_bounds.y());
@@ -666,19 +675,15 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
// Test single line drawing with a border.
gfx::Insets border(39, 34, 8, 96);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
gfx::Size required_size_with_border(label.GetPreferredSize());
EXPECT_EQ(required_size.width() + border.width(),
required_size_with_border.width());
EXPECT_EQ(required_size.height() + border.height(),
required_size_with_border.height());
- label.SetBounds(0,
- 0,
- required_size_with_border.width() + extra.width(),
+ label.SetBounds(0, 0, required_size_with_border.width() + extra.width(),
required_size_with_border.height() + extra.height());
// Centered text with border.
@@ -686,7 +691,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be centered horizontally and vertically within the border.
EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -702,7 +707,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be right aligned horizontally and centered vertically.
EXPECT_EQ(border.left() + extra.width(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -718,7 +723,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
// The text should be left aligned horizontally and centered vertically.
EXPECT_EQ(border.left(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2 , text_bounds.y());
@@ -744,34 +749,28 @@ TEST(LabelTest, DrawMultiLineStringInRTL) {
std::string locale = l10n_util::GetApplicationLocale("");
base::i18n::SetICUDefaultLocale("he");
- string16 test_text(ASCIIToUTF16("Another string\nwith returns\n\n!"));
- label.SetText(test_text);
+ label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!"));
label.SetMultiLine(true);
label.SizeToFit(0);
gfx::Size extra(50, 10);
- label.SetBounds(label.x(),
- label.y(),
+ label.SetBounds(label.x(), label.y(),
label.width() + extra.width(),
label.height() + extra.height());
// Do some basic verifications for all three alignments.
- string16 paint_text;
+ base::string16 paint_text;
gfx::Rect text_bounds;
- int flags;
+ int flags = -1;
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width() / 2, text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
EXPECT_GT(text_bounds.height(), kMinTextDimension);
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_CENTER, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_CENTER |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_CENTER & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
gfx::Rect center_bounds(text_bounds);
@@ -779,49 +778,38 @@ TEST(LabelTest, DrawMultiLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width(), text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
EXPECT_GT(text_bounds.height(), kMinTextDimension);
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_RIGHT, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_RIGHT |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_RIGHT & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(0, text_bounds.x());
EXPECT_EQ(extra.height() / 2, text_bounds.y());
EXPECT_GT(text_bounds.width(), kMinTextDimension);
EXPECT_GT(text_bounds.height(), kMinTextDimension);
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_LEFT, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_LEFT |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_LEFT & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
// Test multiline drawing with a border.
gfx::Insets border(19, 92, 23, 2);
- label.set_border(Border::CreateEmptyBorder(border.top(),
- border.left(),
- border.bottom(),
- border.right()));
+ label.SetBorder(Border::CreateEmptyBorder(
+ border.top(), border.left(), border.bottom(), border.right()));
label.SizeToFit(0);
- label.SetBounds(label.x(),
- label.y(),
+ label.SetBounds(label.x(), label.y(),
label.width() + extra.width(),
label.height() + extra.height());
@@ -829,75 +817,64 @@ TEST(LabelTest, DrawMultiLineStringInRTL) {
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(border.left() + extra.width() / 2, text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
EXPECT_EQ(center_bounds.height(), text_bounds.height());
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_CENTER, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_CENTER |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_CENTER & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(border.left() + extra.width(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
EXPECT_EQ(center_bounds.height(), text_bounds.height());
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_RIGHT, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_RIGHT |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_RIGHT & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear();
text_bounds.SetRect(0, 0, 0, 0);
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
- EXPECT_EQ(test_text, paint_text);
+ EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(border.left(), text_bounds.x());
EXPECT_EQ(border.top() + extra.height() / 2, text_bounds.y());
EXPECT_EQ(center_bounds.width(), text_bounds.width());
EXPECT_EQ(center_bounds.height(), text_bounds.height());
-#if defined(OS_WIN)
- EXPECT_EQ(gfx::Canvas::MULTI_LINE | gfx::Canvas::TEXT_ALIGN_LEFT, flags);
-#else
- EXPECT_EQ(
- gfx::Canvas::MULTI_LINE |
- gfx::Canvas::TEXT_ALIGN_LEFT |
- gfx::Canvas::NO_ELLIPSIS,
- flags);
+ EXPECT_TRUE(gfx::Canvas::MULTI_LINE & flags);
+ EXPECT_TRUE(gfx::Canvas::TEXT_ALIGN_LEFT & flags);
+#if !defined(OS_WIN)
+ EXPECT_TRUE(gfx::Canvas::NO_ELLIPSIS & flags);
#endif
// Reset Locale
base::i18n::SetICUDefaultLocale(locale);
}
-// Check that we disable subpixel rendering when a transparent background is
-// being used.
+// Ensure the subpixel rendering flag and background color alpha are respected.
TEST(LabelTest, DisableSubpixelRendering) {
Label label;
label.SetBackgroundColor(SK_ColorWHITE);
- EXPECT_EQ(
- 0, label.ComputeDrawStringFlags() & gfx::Canvas::NO_SUBPIXEL_RENDERING);
-
+ const int flag = gfx::Canvas::NO_SUBPIXEL_RENDERING;
+ EXPECT_EQ(0, label.ComputeDrawStringFlags() & flag);
+ label.set_subpixel_rendering_enabled(false);
+ EXPECT_EQ(flag, label.ComputeDrawStringFlags() & flag);
+ label.set_subpixel_rendering_enabled(true);
+ EXPECT_EQ(0, label.ComputeDrawStringFlags() & flag);
+ // Text cannot be drawn with subpixel rendering on transparent backgrounds.
label.SetBackgroundColor(SkColorSetARGB(64, 255, 255, 255));
- EXPECT_EQ(
- gfx::Canvas::NO_SUBPIXEL_RENDERING,
- label.ComputeDrawStringFlags() & gfx::Canvas::NO_SUBPIXEL_RENDERING);
+ EXPECT_EQ(flag, label.ComputeDrawStringFlags() & flag);
}
// Check that labels support GetTooltipHandlerForPoint.
diff --git a/chromium/ui/views/controls/link.cc b/chromium/ui/views/controls/link.cc
index d02a0b89c73..d8a08a40c92 100644
--- a/chromium/ui/views/controls/link.cc
+++ b/chromium/ui/views/controls/link.cc
@@ -8,27 +8,25 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/controls/link_listener.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+#include "ui/views/native_cursor.h"
namespace views {
const char Link::kViewClassName[] = "Link";
-Link::Link() : Label(string16()) {
+Link::Link() : Label(base::string16()) {
Init();
}
-Link::Link(const string16& title) : Label(title) {
+Link::Link(const base::string16& title) : Label(title) {
Init();
}
@@ -43,11 +41,6 @@ SkColor Link::GetDefaultEnabledColor() {
#endif
}
-void Link::OnEnabledChanged() {
- RecalculateFont();
- View::OnEnabledChanged();
-}
-
const char* Link::GetClassName() const {
return kViewClassName;
}
@@ -55,37 +48,13 @@ const char* Link::GetClassName() const {
gfx::NativeCursor Link::GetCursor(const ui::MouseEvent& event) {
if (!enabled())
return gfx::kNullCursor;
-#if defined(USE_AURA)
- return ui::kCursorHand;
-#elif defined(OS_WIN)
- static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_HAND);
- return g_hand_cursor;
-#endif
-}
-
-void Link::OnPaint(gfx::Canvas* canvas) {
- Label::OnPaint(canvas);
-
- if (HasFocus())
- canvas->DrawFocusRect(GetLocalBounds());
-}
-
-void Link::OnFocus() {
- Label::OnFocus();
- // We render differently focused.
- SchedulePaint();
-}
-
-void Link::OnBlur() {
- Label::OnBlur();
- // We render differently focused.
- SchedulePaint();
+ return GetNativeHandCursor();
}
-bool Link::HitTestRect(const gfx::Rect& rect) const {
- // We need to allow clicks on the link. So we override the implementation in
- // Label and use the default implementation of View.
- return View::HitTestRect(rect);
+bool Link::CanProcessEventsWithinSubtree() const {
+ // Links need to be able to accept events (e.g., clicking) even though
+ // in general Labels do not.
+ return View::CanProcessEventsWithinSubtree();
}
bool Link::OnMousePressed(const ui::MouseEvent& event) {
@@ -139,17 +108,6 @@ bool Link::OnKeyPressed(const ui::KeyEvent& event) {
return true;
}
-bool Link::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
- // Make sure we don't process space or enter as accelerators.
- return (event.key_code() == ui::VKEY_SPACE) ||
- (event.key_code() == ui::VKEY_RETURN);
-}
-
-void Link::GetAccessibleState(ui::AccessibleViewState* state) {
- Label::GetAccessibleState(state);
- state->role = ui::AccessibilityTypes::ROLE_LINK;
-}
-
void Link::OnGestureEvent(ui::GestureEvent* event) {
if (!enabled())
return;
@@ -167,9 +125,45 @@ void Link::OnGestureEvent(ui::GestureEvent* event) {
event->SetHandled();
}
-void Link::SetFont(const gfx::Font& font) {
- Label::SetFont(font);
+bool Link::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
+ // Make sure we don't process space or enter as accelerators.
+ return (event.key_code() == ui::VKEY_SPACE) ||
+ (event.key_code() == ui::VKEY_RETURN);
+}
+
+void Link::GetAccessibleState(ui::AXViewState* state) {
+ Label::GetAccessibleState(state);
+ state->role = ui::AX_ROLE_LINK;
+}
+
+void Link::OnEnabledChanged() {
RecalculateFont();
+ View::OnEnabledChanged();
+}
+
+void Link::OnFocus() {
+ Label::OnFocus();
+ // We render differently focused.
+ SchedulePaint();
+}
+
+void Link::OnBlur() {
+ Label::OnBlur();
+ // We render differently focused.
+ SchedulePaint();
+}
+
+void Link::SetFontList(const gfx::FontList& font_list) {
+ Label::SetFontList(font_list);
+ RecalculateFont();
+}
+
+void Link::SetText(const base::string16& text) {
+ Label::SetText(text);
+ // Disable focusability for empty links. Otherwise Label::GetInsets() will
+ // give them an unconditional 1-px. inset on every side to allow for a focus
+ // border, when in this case we probably wanted zero width.
+ SetFocusable(!text.empty());
}
void Link::SetEnabledColor(SkColor color) {
@@ -205,7 +199,12 @@ void Link::Init() {
SetPressedColor(SK_ColorRED);
#endif
RecalculateFont();
- SetFocusable(true);
+
+ // Label::Init() calls SetText(), but if that's being called from Label(), our
+ // SetText() override will not be reached (because the constructed class is
+ // only a Label at the moment, not yet a Link). So so the set_focusable()
+ // call explicitly here.
+ SetFocusable(!text().empty());
}
void Link::SetPressed(bool pressed) {
@@ -220,11 +219,11 @@ void Link::SetPressed(bool pressed) {
void Link::RecalculateFont() {
// Underline the link iff it is enabled and |underline_| is true.
- const int style = font().GetStyle();
+ const int style = font_list().GetFontStyle();
const int intended_style = (enabled() && underline_) ?
(style | gfx::Font::UNDERLINE) : (style & ~gfx::Font::UNDERLINE);
if (style != intended_style)
- Label::SetFont(font().DeriveFont(0, intended_style));
+ Label::SetFontList(font_list().DeriveWithStyle(intended_style));
}
} // namespace views
diff --git a/chromium/ui/views/controls/link.h b/chromium/ui/views/controls/link.h
index f6a876de863..4d5cf6b7afa 100644
--- a/chromium/ui/views/controls/link.h
+++ b/chromium/ui/views/controls/link.h
@@ -25,7 +25,7 @@ class LinkListener;
class VIEWS_EXPORT Link : public Label {
public:
Link();
- explicit Link(const string16& title);
+ explicit Link(const base::string16& title);
virtual ~Link();
static SkColor GetDefaultEnabledColor();
@@ -33,30 +33,26 @@ class VIEWS_EXPORT Link : public Label {
const LinkListener* listener() { return listener_; }
void set_listener(LinkListener* listener) { listener_ = listener; }
- // Overridden from View:
- virtual void OnEnabledChanged() OVERRIDE;
+ // Label:
virtual const char* GetClassName() const OVERRIDE;
virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnFocus() OVERRIDE;
- virtual void OnBlur() OVERRIDE;
- virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseCaptureLost() OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool SkipDefaultKeyEventProcessing(
const ui::KeyEvent& event) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
-
- // Overridden from ui::EventHandler:
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
- // Overridden from Label:
- virtual void SetFont(const gfx::Font& font) OVERRIDE;
-
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
+ virtual void OnEnabledChanged() OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnBlur() OVERRIDE;
+ virtual void SetFontList(const gfx::FontList& font_list) OVERRIDE;
+ virtual void SetText(const base::string16& text) OVERRIDE;
virtual void SetEnabledColor(SkColor color) OVERRIDE;
+
void SetPressedColor(SkColor color);
void SetUnderline(bool underline);
diff --git a/chromium/ui/views/controls/menu/display_change_listener_mac.cc b/chromium/ui/views/controls/menu/display_change_listener_mac.cc
new file mode 100644
index 00000000000..d9dfeda5cfd
--- /dev/null
+++ b/chromium/ui/views/controls/menu/display_change_listener_mac.cc
@@ -0,0 +1,16 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_runner.h"
+
+namespace views {
+namespace internal {
+
+// static
+DisplayChangeListener* DisplayChangeListener::Create(Widget*, MenuRunner*) {
+ return NULL;
+}
+
+} // namespace internal
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu.cc b/chromium/ui/views/controls/menu/menu.cc
index 597dba4419f..0cffae8f50e 100644
--- a/chromium/ui/views/controls/menu/menu.cc
+++ b/chromium/ui/views/controls/menu/menu.cc
@@ -17,8 +17,8 @@ bool Menu::Delegate::IsItemDefault(int id) const {
return false;
}
-string16 Menu::Delegate::GetLabel(int id) const {
- return string16();
+base::string16 Menu::Delegate::GetLabel(int id) const {
+ return base::string16();
}
bool Menu::Delegate::GetAcceleratorInfo(int id, ui::Accelerator* accel) {
@@ -49,7 +49,7 @@ bool Menu::Delegate::IsCommandEnabled(int id) const {
return true;
}
-bool Menu::Delegate::GetContextualLabel(int id, string16* out) const {
+bool Menu::Delegate::GetContextualLabel(int id, base::string16* out) const {
return false;
}
@@ -76,14 +76,14 @@ Menu::~Menu() {
}
void Menu::AppendMenuItem(int item_id,
- const string16& label,
+ const base::string16& label,
MenuItemType type) {
AddMenuItem(-1, item_id, label, type);
}
void Menu::AddMenuItem(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
MenuItemType type) {
if (type == SEPARATOR)
AddSeparator(index);
@@ -91,27 +91,27 @@ void Menu::AddMenuItem(int index,
AddMenuItemInternal(index, item_id, label, gfx::ImageSkia(), type);
}
-Menu* Menu::AppendSubMenu(int item_id, const string16& label) {
+Menu* Menu::AppendSubMenu(int item_id, const base::string16& label) {
return AddSubMenu(-1, item_id, label);
}
-Menu* Menu::AddSubMenu(int index, int item_id, const string16& label) {
+Menu* Menu::AddSubMenu(int index, int item_id, const base::string16& label) {
return AddSubMenuWithIcon(index, item_id, label, gfx::ImageSkia());
}
Menu* Menu::AppendSubMenuWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) {
return AddSubMenuWithIcon(-1, item_id, label, icon);
}
-void Menu::AppendMenuItemWithLabel(int item_id, const string16& label) {
+void Menu::AppendMenuItemWithLabel(int item_id, const base::string16& label) {
AddMenuItemWithLabel(-1, item_id, label);
}
void Menu::AddMenuItemWithLabel(int index,
int item_id,
- const string16& label) {
+ const base::string16& label) {
AddMenuItem(index, item_id, label, Menu::NORMAL);
}
@@ -120,7 +120,7 @@ void Menu::AppendDelegateMenuItem(int item_id) {
}
void Menu::AddDelegateMenuItem(int index, int item_id) {
- AddMenuItem(index, item_id, string16(), Menu::NORMAL);
+ AddMenuItem(index, item_id, base::string16(), Menu::NORMAL);
}
void Menu::AppendSeparator() {
@@ -128,14 +128,14 @@ void Menu::AppendSeparator() {
}
void Menu::AppendMenuItemWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) {
AddMenuItemWithIcon(-1, item_id, label, icon);
}
void Menu::AddMenuItemWithIcon(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) {
AddMenuItemInternal(index, item_id, label, icon, Menu::NORMAL);
}
diff --git a/chromium/ui/views/controls/menu/menu.h b/chromium/ui/views/controls/menu/menu.h
index 5a774df7320..099a98ee543 100644
--- a/chromium/ui/views/controls/menu/menu.h
+++ b/chromium/ui/views/controls/menu/menu.h
@@ -45,7 +45,7 @@ class VIEWS_EXPORT Menu {
virtual bool IsItemDefault(int id) const;
// The string shown for the menu item.
- virtual string16 GetLabel(int id) const;
+ virtual base::string16 GetLabel(int id) const;
// The delegate needs to implement this function if it wants to display
// the shortcut text next to each menu item. If there is an accelerator
@@ -94,7 +94,7 @@ class VIEWS_EXPORT Menu {
// Controller
virtual bool SupportsCommand(int id) const;
virtual bool IsCommandEnabled(int id) const;
- virtual bool GetContextualLabel(int id, string16* out) const;
+ virtual bool GetContextualLabel(int id, base::string16* out) const;
virtual void ExecuteCommand(int id) {
}
@@ -151,35 +151,37 @@ class VIEWS_EXPORT Menu {
// label The text label shown.
// type The type of item.
void AppendMenuItem(int item_id,
- const string16& label,
+ const base::string16& label,
MenuItemType type);
void AddMenuItem(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
MenuItemType type);
// Append a submenu to this menu.
// The returned pointer is owned by this menu.
Menu* AppendSubMenu(int item_id,
- const string16& label);
- Menu* AddSubMenu(int index, int item_id, const string16& label);
+ const base::string16& label);
+ Menu* AddSubMenu(int index, int item_id, const base::string16& label);
// Append a submenu with an icon to this menu
// The returned pointer is owned by this menu.
// Unless the icon is empty, calling this function forces the Menu class
// to draw the menu, instead of relying on Windows.
Menu* AppendSubMenuWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon);
virtual Menu* AddSubMenuWithIcon(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) = 0;
// This is a convenience for standard text label menu items where the label
// is provided with this call.
- void AppendMenuItemWithLabel(int item_id, const string16& label);
- void AddMenuItemWithLabel(int index, int item_id, const string16& label);
+ void AppendMenuItemWithLabel(int item_id, const base::string16& label);
+ void AddMenuItemWithLabel(int index,
+ int item_id,
+ const base::string16& label);
// This is a convenience for text label menu items where the label is
// provided by the delegate.
@@ -194,11 +196,11 @@ class VIEWS_EXPORT Menu {
// needs an icon. Calling this function forces the Menu class to draw
// the menu, instead of relying on Windows.
void AppendMenuItemWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon);
virtual void AddMenuItemWithIcon(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon);
// Enables or disables the item with the specified id.
@@ -206,7 +208,7 @@ class VIEWS_EXPORT Menu {
virtual void EnableMenuItemAt(int index, bool enabled) = 0;
// Sets menu label at specified index.
- virtual void SetMenuLabel(int item_id, const string16& label) = 0;
+ virtual void SetMenuLabel(int item_id, const base::string16& label) = 0;
// Sets an icon for an item with a given item_id. Calling this function
// also forces the Menu class to draw the menu, instead of relying on Windows.
@@ -234,7 +236,7 @@ class VIEWS_EXPORT Menu {
virtual void AddMenuItemInternal(int index,
int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon,
MenuItemType type) = 0;
diff --git a/chromium/ui/views/controls/menu/menu_config.cc b/chromium/ui/views/controls/menu/menu_config.cc
index 1c34ac0b3e0..9eaba83f6db 100644
--- a/chromium/ui/views/controls/menu/menu_config.cc
+++ b/chromium/ui/views/controls/menu/menu_config.cc
@@ -5,14 +5,11 @@
#include "ui/views/controls/menu/menu_config.h"
#include "build/build_config.h"
-#include "ui/base/layout.h"
-#include "ui/native_theme/native_theme.h"
namespace views {
MenuConfig::MenuConfig(const ui::NativeTheme* theme)
- : text_color(SK_ColorBLACK),
- arrow_color(SK_ColorBLACK),
+ : arrow_color(SK_ColorBLACK),
menu_vertical_border_size(3),
menu_horizontal_border_size(0),
submenu_horizontal_inset(3),
@@ -28,8 +25,6 @@ MenuConfig::MenuConfig(const ui::NativeTheme* theme)
check_width(16),
check_height(16),
radio_width(16),
- radio_height(16),
- arrow_height(9),
arrow_width(9),
gutter_width(0),
separator_height(11),
@@ -48,12 +43,6 @@ MenuConfig::MenuConfig(const ui::NativeTheme* theme)
native_theme(theme),
show_delay(400),
corner_radius(0) {
- // Use 40px tall menu items when running in touch optimized mode.
- // For Windows use 40px tall menu items when running in touch optimized mode.
- if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) {
- item_top_margin = item_no_icon_top_margin = 12;
- item_bottom_margin = item_no_icon_bottom_margin = 13;
- }
Init(theme);
}
diff --git a/chromium/ui/views/controls/menu/menu_config.h b/chromium/ui/views/controls/menu/menu_config.h
index 96eb21ac219..3cdbccdbf4d 100644
--- a/chromium/ui/views/controls/menu/menu_config.h
+++ b/chromium/ui/views/controls/menu/menu_config.h
@@ -6,7 +6,7 @@
#define UI_VIEWS_CONTROLS_MENU_MENU_CONFIG_H_
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/views_export.h"
namespace ui {
@@ -23,11 +23,8 @@ struct VIEWS_EXPORT MenuConfig {
static const MenuConfig& instance(const ui::NativeTheme* theme);
- // Font used by menus.
- gfx::Font font;
-
- // Normal text color.
- SkColor text_color;
+ // Font list used by menus.
+ gfx::FontList font_list;
// Color for the arrow to scroll bookmarks.
SkColor arrow_color;
@@ -70,12 +67,10 @@ struct VIEWS_EXPORT MenuConfig {
int check_width;
int check_height;
- // Size of the radio bullet.
+ // Width of the radio bullet.
int radio_width;
- int radio_height;
- // Size of the submenu arrow.
- int arrow_height;
+ // Width of the submenu arrow.
int arrow_width;
// Width of the gutter. Only used if render_gutter is true.
@@ -136,9 +131,7 @@ struct VIEWS_EXPORT MenuConfig {
void Init(const ui::NativeTheme* theme);
// TODO: temporary until we standardize.
-#if defined(USE_AURA)
void InitAura(const ui::NativeTheme* theme);
-#endif
};
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_config_views.cc b/chromium/ui/views/controls/menu/menu_config_aura.cc
index d0b48443711..2e464d22488 100644
--- a/chromium/ui/views/controls/menu/menu_config_views.cc
+++ b/chromium/ui/views/controls/menu/menu_config_aura.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -30,20 +30,16 @@ void MenuConfig::Init(const ui::NativeTheme* theme) {
#endif
void MenuConfig::InitAura(const ui::NativeTheme* theme) {
- text_color = theme->GetSystemColor(
- ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor);
submenu_horizontal_inset = 1;
arrow_to_edge_padding = 20;
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- arrow_width =
- rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia()->width();
+ arrow_width = rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).Width();
gfx::ImageSkia check = GetMenuCheckImage(false);
check_height = check.height();
item_min_height = 29;
separator_spacing_height = 7;
separator_lower_height = 8;
separator_upper_height = 8;
- font = rb.GetFont(ResourceBundle::BaseFont);
label_to_arrow_padding = 20;
label_to_minor_text_padding = 20;
always_use_icon_to_label_padding = true;
diff --git a/chromium/ui/views/controls/menu/menu_config_mac.cc b/chromium/ui/views/controls/menu/menu_config_mac.cc
new file mode 100644
index 00000000000..dd38e72fe7e
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_config_mac.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_config.h"
+
+#include "grit/ui_resources.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/native_theme/native_theme_mac.h"
+#include "ui/views/controls/menu/menu_image_util.h"
+
+namespace views {
+
+void MenuConfig::Init(const ui::NativeTheme* theme) {
+ NOTIMPLEMENTED();
+}
+
+// static
+const MenuConfig& MenuConfig::instance(const ui::NativeTheme* theme) {
+ CR_DEFINE_STATIC_LOCAL(
+ MenuConfig, mac_instance, (theme ? theme : ui::NativeTheme::instance()));
+ return mac_instance;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_config_win.cc b/chromium/ui/views/controls/menu/menu_config_win.cc
index e0bde54c30b..4ef5fac3070 100644
--- a/chromium/ui/views/controls/menu/menu_config_win.cc
+++ b/chromium/ui/views/controls/menu/menu_config_win.cc
@@ -13,11 +13,8 @@
#include "base/win/win_util.h"
#include "ui/base/l10n/l10n_util_win.h"
#include "ui/gfx/color_utils.h"
-#include "ui/native_theme/native_theme_win.h"
-
-#if defined(USE_AURA)
#include "ui/native_theme/native_theme_aura.h"
-#endif
+#include "ui/native_theme/native_theme_win.h"
using ui::NativeTheme;
using ui::NativeThemeWin;
@@ -25,15 +22,10 @@ using ui::NativeThemeWin;
namespace views {
void MenuConfig::Init(const NativeTheme* theme) {
-#if defined(USE_AURA)
if (theme == ui::NativeThemeAura::instance()) {
InitAura(theme);
return;
}
-#endif
- text_color = NativeThemeWin::instance()->GetThemeColorWithDefault(
- NativeThemeWin::MENU, MENU_POPUPITEM, MPI_NORMAL, TMT_TEXTCOLOR,
- COLOR_MENUTEXT);
arrow_color = color_utils::GetSysSkColor(COLOR_MENUTEXT);
@@ -43,7 +35,7 @@ void MenuConfig::Init(const NativeTheme* theme) {
{
base::win::ScopedHFONT new_font(CreateFontIndirect(&metrics.lfMenuFont));
DLOG_ASSERT(new_font.Get());
- font = gfx::Font(new_font);
+ font_list = gfx::FontList(gfx::Font(new_font));
}
NativeTheme::ExtraParams extra;
extra.menu_check.is_radio = false;
@@ -61,23 +53,18 @@ void MenuConfig::Init(const NativeTheme* theme) {
extra.menu_check.is_radio = true;
gfx::Size radio_size = NativeThemeWin::instance()->GetPartSize(
NativeTheme::kMenuCheck, NativeTheme::kNormal, extra);
- if (!radio_size.IsEmpty()) {
+ if (!radio_size.IsEmpty())
radio_width = radio_size.width();
- radio_height = radio_size.height();
- } else {
+ else
radio_width = GetSystemMetrics(SM_CXMENUCHECK);
- radio_height = GetSystemMetrics(SM_CYMENUCHECK);
- }
gfx::Size arrow_size = NativeThemeWin::instance()->GetPartSize(
NativeTheme::kMenuPopupArrow, NativeTheme::kNormal, extra);
if (!arrow_size.IsEmpty()) {
arrow_width = arrow_size.width();
- arrow_height = arrow_size.height();
} else {
// Sadly I didn't see a specify metrics for this.
arrow_width = GetSystemMetrics(SM_CXMENUCHECK);
- arrow_height = GetSystemMetrics(SM_CYMENUCHECK);
}
BOOL show_cues;
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index 3b0e5d552c0..d5b5a84e8f1 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -4,23 +4,18 @@
#include "ui/views/controls/menu/menu_controller.h"
-#if defined(OS_WIN)
-#include <windowsx.h>
-#endif
-
#include "base/i18n/case_conversion.h"
#include "base/i18n/rtl.h"
-#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/l10n/l10n_util.h"
-#include "ui/events/event_constants.h"
+#include "ui/events/event.h"
#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/point.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/vector2d.h"
#include "ui/native_theme/native_theme.h"
@@ -28,32 +23,26 @@
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller_delegate.h"
#include "ui/views/controls/menu/menu_host_root_view.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/menu_message_loop.h"
#include "ui/views/controls/menu/menu_scroll_view_container.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/drag_utils.h"
-#include "ui/views/event_utils.h"
#include "ui/views/focus/view_storage.h"
#include "ui/views/mouse_constants.h"
+#include "ui/views/view.h"
#include "ui/views/view_constants.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#endif
-
#if defined(OS_WIN)
-#include "ui/views/win/hwnd_message_handler.h"
+#include "ui/base/win/internal_constants.h"
+#include "ui/gfx/win/dpi.h"
#include "ui/views/win/hwnd_util.h"
#endif
-#if defined(USE_X11)
-#include <X11/Xlib.h>
-#endif
-
using base::Time;
using base::TimeDelta;
using ui::OSExchangeData;
@@ -87,17 +76,17 @@ const int kBubbleTipSizeTopBottom = 11;
const float kMaximumLengthMovedToActivate = 4.0f;
// Returns true if the mnemonic of |menu| matches key.
-bool MatchesMnemonic(MenuItemView* menu, char16 key) {
- return menu->GetMnemonic() == key;
+bool MatchesMnemonic(MenuItemView* menu, base::char16 key) {
+ return key != 0 && menu->GetMnemonic() == key;
}
// Returns true if |menu| doesn't have a mnemonic and first character of the its
// title is |key|.
-bool TitleMatchesMnemonic(MenuItemView* menu, char16 key) {
+bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) {
if (menu->GetMnemonic())
return false;
- string16 lower_title = base::i18n::ToLower(menu->title());
+ base::string16 lower_title = base::i18n::ToLower(menu->title());
return !lower_title.empty() && lower_title[0] == key;
}
@@ -279,8 +268,9 @@ struct MenuController::SelectByCharDetails {
MenuController::State::State()
: item(NULL),
submenu_open(false),
- anchor(MenuItemView::TOPLEFT),
- context_menu(false) {}
+ anchor(MENU_ANCHOR_TOPLEFT),
+ context_menu(false) {
+}
MenuController::State::~State() {}
@@ -298,7 +288,7 @@ MenuItemView* MenuController::Run(Widget* parent,
MenuButton* button,
MenuItemView* root,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition position,
+ MenuAnchorPosition position,
bool context_menu,
int* result_event_flags) {
exit_type_ = EXIT_NONE;
@@ -385,7 +375,7 @@ MenuItemView* MenuController::Run(Widget* parent,
// Close any open menus.
SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
-#if defined(OS_WIN) && defined(USE_AURA)
+#if defined(OS_WIN)
// On Windows, if we select the menu item by touch and if the window at the
// location is another window on the same thread, that window gets a
// WM_MOUSEACTIVATE message and ends up activating itself, which is not
@@ -400,7 +390,7 @@ MenuItemView* MenuController::Run(Widget* parent,
HWND window = ::WindowFromPoint(cursor_pos);
if (::GetWindowThreadProcessId(window, NULL) ==
::GetCurrentThreadId()) {
- ::SetProp(window, views::kIgnoreTouchMouseActivateForWindow,
+ ::SetProp(window, ui::kIgnoreTouchMouseActivateForWindow,
reinterpret_cast<HANDLE>(true));
}
}
@@ -596,13 +586,11 @@ void MenuController::OnMouseEntered(SubmenuView* source,
// do anything here.
}
-#if defined(USE_AURA)
bool MenuController::OnMouseWheel(SubmenuView* source,
const ui::MouseWheelEvent& event) {
MenuPart part = GetMenuPart(source, event.location());
return part.submenu && part.submenu->OnMouseWheel(event);
}
-#endif
void MenuController::OnGestureEvent(SubmenuView* source,
ui::GestureEvent* event) {
@@ -809,6 +797,7 @@ void MenuController::OnWidgetDestroying(Widget* widget) {
DCHECK_EQ(owner_, widget);
owner_->RemoveObserver(this);
owner_ = NULL;
+ message_loop_->ClearOwner();
}
// static
@@ -875,7 +864,7 @@ void MenuController::SetSelection(MenuItemView* menu_item,
(MenuDepth(menu_item) != 1 ||
menu_item->GetType() != MenuItemView::SUBMENU)) {
menu_item->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_FOCUS, true);
+ ui::AX_EVENT_FOCUS, true);
}
}
@@ -912,14 +901,7 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source,
#if defined(OS_WIN)
// We're going to close and we own the mouse capture. We need to repost the
// mouse down, otherwise the window the user clicked on won't get the event.
- if (!state_.item) {
- // We some times get an event after closing all the menus. Ignore it. Make
- // sure the menu is in fact not visible. If the menu is visible, then
- // we're in a bad state where we think the menu isn't visibile but it is.
- DCHECK(!source->GetWidget()->IsVisible());
- } else {
- RepostEvent(source, event);
- }
+ RepostEvent(source, event);
#endif
// And close.
@@ -936,14 +918,15 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source,
}
Cancel(exit_type);
-#if defined(USE_AURA) && !defined(OS_WIN)
+#if defined(OS_CHROMEOS)
// We're going to exit the menu and want to repost the event so that is
// is handled normally after the context menu has exited. We call
// RepostEvent after Cancel so that mouse capture has been released so
// that finding the event target is unaffected by the current capture.
RepostEvent(source, event);
#endif
-
+ // Do not repost events for Linux Aura because this behavior is more
+ // consistent with the behavior of other Linux apps.
return;
}
@@ -982,7 +965,7 @@ void MenuController::StartDrag(SubmenuView* source,
OSExchangeData data;
item->GetDelegate()->WriteDragData(item, &data);
- drag_utils::SetDragImageOnDataObject(*canvas, item->size(),
+ drag_utils::SetDragImageOnDataObject(*canvas,
press_loc.OffsetFromOrigin(),
&data);
StopScrolling();
@@ -1002,94 +985,6 @@ void MenuController::StartDrag(SubmenuView* source,
} // else case, someone canceled us, don't do anything
}
-#if defined(OS_WIN)
-bool MenuController::Dispatch(const MSG& msg) {
- DCHECK(blocking_run_);
-
- if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) {
- // We must translate/dispatch the message here, otherwise we would drop
- // the message on the floor.
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- return false;
- }
-
- // NOTE: we don't get WM_ACTIVATE or anything else interesting in here.
- switch (msg.message) {
- case WM_CONTEXTMENU: {
- MenuItemView* item = pending_state_.item;
- if (item && item->GetRootMenuItem() != item) {
- gfx::Point screen_loc(0, item->height());
- View::ConvertPointToScreen(item, &screen_loc);
- ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE;
- if (GET_X_LPARAM(msg.lParam) == -1 && GET_Y_LPARAM(msg.lParam) == -1)
- source_type = ui::MENU_SOURCE_KEYBOARD;
- item->GetDelegate()->ShowContextMenu(item, item->GetCommand(),
- screen_loc, source_type);
- }
- return true;
- }
-
- // NOTE: focus wasn't changed when the menu was shown. As such, don't
- // dispatch key events otherwise the focused window will get the events.
- case WM_KEYDOWN: {
- bool result = OnKeyDown(ui::KeyboardCodeFromNative(msg));
- TranslateMessage(&msg);
- return result;
- }
- case WM_CHAR:
- return !SelectByChar(static_cast<char16>(msg.wParam));
- case WM_KEYUP:
- return true;
-
- case WM_SYSKEYUP:
- // We may have been shown on a system key, as such don't do anything
- // here. If another system key is pushed we'll get a WM_SYSKEYDOWN and
- // close the menu.
- return true;
-
- case WM_CANCELMODE:
- case WM_SYSKEYDOWN:
- // Exit immediately on system keys.
- Cancel(EXIT_ALL);
- return false;
-
- default:
- break;
- }
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- return exit_type_ == EXIT_NONE;
-}
-#elif defined(USE_AURA)
-bool MenuController::Dispatch(const base::NativeEvent& event) {
- if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) {
- aura::Env::GetInstance()->GetDispatcher()->Dispatch(event);
- return false;
- }
- // Activates mnemonics only when it it pressed without modifiers except for
- // caps and shift.
- int flags = ui::EventFlagsFromNative(event) &
- ~ui::EF_CAPS_LOCK_DOWN & ~ui::EF_SHIFT_DOWN;
- if (flags == ui::EF_NONE) {
- switch (ui::EventTypeFromNative(event)) {
- case ui::ET_KEY_PRESSED:
- if (!OnKeyDown(ui::KeyboardCodeFromNative(event)))
- return false;
-
- return !SelectByChar(ui::KeyboardCodeFromNative(event));
- case ui::ET_KEY_RELEASED:
- return true;
- default:
- break;
- }
- }
-
- aura::Env::GetInstance()->GetDispatcher()->Dispatch(event);
- return exit_type_ == EXIT_NONE;
-}
-#endif
-
bool MenuController::OnKeyDown(ui::KeyboardCode key_code) {
DCHECK(blocking_run_);
@@ -1124,7 +1019,7 @@ bool MenuController::OnKeyDown(ui::KeyboardCode key_code) {
break;
case ui::VKEY_F4:
- if (!accept_on_f4_)
+ if (!is_combobox_)
break;
// Fallthrough to accept on F4, so combobox menus match Windows behavior.
case ui::VKEY_RETURN:
@@ -1156,11 +1051,6 @@ bool MenuController::OnKeyDown(ui::KeyboardCode key_code) {
CloseSubmenu();
break;
-#if defined(OS_WIN)
- case VK_APPS:
- break;
-#endif
-
default:
break;
}
@@ -1191,8 +1081,9 @@ MenuController::MenuController(ui::NativeTheme* theme,
menu_config_(theme),
closing_event_time_(base::TimeDelta()),
menu_start_time_(base::TimeTicks()),
- accept_on_f4_(false),
- item_selected_by_touch_(false) {
+ is_combobox_(false),
+ item_selected_by_touch_(false),
+ message_loop_(MenuMessageLoop::Create()) {
active_instance_ = this;
}
@@ -1206,6 +1097,10 @@ MenuController::~MenuController() {
StopCancelAllTimer();
}
+void MenuController::RunMessageLoop(bool nested_menu) {
+ message_loop_->Run(this, owner_, nested_menu);
+}
+
MenuController::SendAcceleratorResultType
MenuController::SendAcceleratorToHotTrackedView() {
CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item);
@@ -1220,10 +1115,9 @@ MenuController::SendAcceleratorResultType
ACCELERATOR_PROCESSED : ACCELERATOR_PROCESSED_EXIT;
}
-void MenuController::UpdateInitialLocation(
- const gfx::Rect& bounds,
- MenuItemView::AnchorPosition position,
- bool context_menu) {
+void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
+ MenuAnchorPosition position,
+ bool context_menu) {
pending_state_.context_menu = context_menu;
pending_state_.initial_bounds = bounds;
if (bounds.height() > 1) {
@@ -1234,10 +1128,10 @@ void MenuController::UpdateInitialLocation(
// Reverse anchor position for RTL languages.
if (base::i18n::IsRTL() &&
- (position == MenuItemView::TOPRIGHT ||
- position == MenuItemView::TOPLEFT)) {
- pending_state_.anchor = position == MenuItemView::TOPRIGHT ?
- MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT;
+ (position == MENU_ANCHOR_TOPRIGHT || position == MENU_ANCHOR_TOPLEFT)) {
+ pending_state_.anchor = position == MENU_ANCHOR_TOPRIGHT
+ ? MENU_ANCHOR_TOPLEFT
+ : MENU_ANCHOR_TOPRIGHT;
} else {
pending_state_.anchor = position;
}
@@ -1246,7 +1140,7 @@ void MenuController::UpdateInitialLocation(
// avoid repeated system queries for the info.
pending_state_.monitor_bounds = GetScreen()->GetDisplayNearestPoint(
bounds.origin()).work_area();
-#if defined(USE_ASH)
+
if (!pending_state_.monitor_bounds.Contains(bounds)) {
// Use the monitor area if the work area doesn't contain the bounds. This
// handles showing a menu from the launcher.
@@ -1255,7 +1149,6 @@ void MenuController::UpdateInitialLocation(
if (monitor_area.Contains(bounds))
pending_state_.monitor_bounds = monitor_area;
}
-#endif
}
void MenuController::Accept(MenuItemView* item, int event_flags) {
@@ -1293,7 +1186,7 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source,
// if there is a sibling menu we should show.
gfx::Point screen_point(mouse_location);
View::ConvertPointToScreen(source_view, &screen_point);
- MenuItemView::AnchorPosition anchor;
+ MenuAnchorPosition anchor;
bool has_mnemonics;
MenuButton* button = NULL;
MenuItemView* alt_menu = source->GetMenuItem()->GetDelegate()->
@@ -1717,11 +1610,11 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item,
x += 1;
y = state_.initial_bounds.bottom();
- if (state_.anchor == MenuItemView::TOPRIGHT) {
+ if (state_.anchor == MENU_ANCHOR_TOPRIGHT) {
x = x + state_.initial_bounds.width() - pref.width();
if (menu_config.offset_context_menus && state_.context_menu)
x -= 1;
- } else if (state_.anchor == MenuItemView::BOTTOMCENTER) {
+ } else if (state_.anchor == MENU_ANCHOR_BOTTOMCENTER) {
x = x - (pref.width() - state_.initial_bounds.width()) / 2;
if (pref.height() >
state_.initial_bounds.y() + kCenteredContextMenuYOffset) {
@@ -1770,7 +1663,7 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item,
// The menu should never overlap the owning button. So move it.
// We use the anchor view style to determine the preferred position
// relative to the owning button.
- if (state_.anchor == MenuItemView::TOPLEFT) {
+ if (state_.anchor == MENU_ANCHOR_TOPLEFT) {
// The menu starts with the same x coordinate as the owning button.
if (x + state_.initial_bounds.width() + pref.width() >
state_.monitor_bounds.right())
@@ -1883,16 +1776,16 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item,
int max_height = state_.monitor_bounds.height();
// In case of bubbles, the maximum width is limited by the space
// between the display corner and the target area + the tip size.
- if (state_.anchor == MenuItemView::BUBBLE_LEFT) {
+ if (state_.anchor == MENU_ANCHOR_BUBBLE_LEFT) {
max_width = owner_bounds.x() - state_.monitor_bounds.x() +
kBubbleTipSizeLeftRight;
- } else if (state_.anchor == MenuItemView::BUBBLE_RIGHT) {
+ } else if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) {
max_width = state_.monitor_bounds.right() - owner_bounds.right() +
kBubbleTipSizeLeftRight;
- } else if (state_.anchor == MenuItemView::BUBBLE_ABOVE) {
+ } else if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) {
max_height = owner_bounds.y() - state_.monitor_bounds.y() +
kBubbleTipSizeTopBottom;
- } else if (state_.anchor == MenuItemView::BUBBLE_BELOW) {
+ } else if (state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) {
max_height = state_.monitor_bounds.bottom() - owner_bounds.bottom() +
kBubbleTipSizeTopBottom;
}
@@ -1907,9 +1800,9 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item,
item->GetDelegate()->GetMaxWidthForMenu(item)));
int x, y;
- if (state_.anchor == MenuItemView::BUBBLE_ABOVE ||
- state_.anchor == MenuItemView::BUBBLE_BELOW) {
- if (state_.anchor == MenuItemView::BUBBLE_ABOVE)
+ if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE ||
+ state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) {
+ if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE)
y = owner_bounds.y() - pref.height() + kBubbleTipSizeTopBottom;
else
y = owner_bounds.bottom() - kBubbleTipSizeTopBottom;
@@ -1924,7 +1817,7 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item,
submenu->GetScrollViewContainer()->SetBubbleArrowOffset(
pref.width() / 2 - x + x_old);
} else {
- if (state_.anchor == MenuItemView::BUBBLE_RIGHT)
+ if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT)
x = owner_bounds.right() - kBubbleTipSizeLeftRight;
else
x = owner_bounds.x() - pref.width() + kBubbleTipSizeLeftRight;
@@ -2046,8 +1939,8 @@ void MenuController::CloseSubmenu() {
MenuController::SelectByCharDetails MenuController::FindChildForMnemonic(
MenuItemView* parent,
- char16 key,
- bool (*match_function)(MenuItemView* menu, char16 mnemonic)) {
+ base::char16 key,
+ bool (*match_function)(MenuItemView* menu, base::char16 mnemonic)) {
SubmenuView* submenu = parent->GetSubmenu();
DCHECK(submenu);
SelectByCharDetails details;
@@ -2098,9 +1991,9 @@ bool MenuController::AcceptOrSelect(MenuItemView* parent,
return false;
}
-bool MenuController::SelectByChar(char16 character) {
- char16 char_array[] = { character, 0 };
- char16 key = base::i18n::ToLower(char_array)[0];
+bool MenuController::SelectByChar(base::char16 character) {
+ base::char16 char_array[] = { character, 0 };
+ base::char16 key = base::i18n::ToLower(char_array)[0];
MenuItemView* item = pending_state_.item;
if (!item->HasSubmenu() || !item->GetSubmenu()->IsShowing())
item = item->GetParentMenuItem();
@@ -2116,61 +2009,114 @@ bool MenuController::SelectByChar(char16 character) {
if (details.first_match != -1)
return AcceptOrSelect(item, details);
- // If no mnemonics found, look at first character of titles.
- details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
- if (details.first_match != -1)
- return AcceptOrSelect(item, details);
+ if (is_combobox_) {
+ item->GetSubmenu()->GetTextInputClient()->InsertChar(character, 0);
+ } else {
+ // If no mnemonics found, look at first character of titles.
+ details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
+ if (details.first_match != -1)
+ return AcceptOrSelect(item, details);
+ }
return false;
}
void MenuController::RepostEvent(SubmenuView* source,
const ui::LocatedEvent& event) {
+ if (!event.IsMouseEvent()) {
+ // TODO(rbyers): Gesture event repost is tricky to get right
+ // crbug.com/170987.
+ DCHECK(event.IsGestureEvent());
+ return;
+ }
+
+#if defined(OS_WIN)
+ if (!state_.item) {
+ // We some times get an event after closing all the menus. Ignore it. Make
+ // sure the menu is in fact not visible. If the menu is visible, then
+ // we're in a bad state where we think the menu isn't visibile but it is.
+ DCHECK(!source->GetWidget()->IsVisible());
+ return;
+ }
+
+ state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture();
+#endif
+
gfx::Point screen_loc(event.location());
View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
-
gfx::NativeView native_view = source->GetWidget()->GetNativeView();
+ if (!native_view)
+ return;
+
gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
- if (!window)
- return;
-
#if defined(OS_WIN)
- // Release the capture.
- SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu();
- submenu->ReleaseCapture();
-
- gfx::NativeView view = submenu->GetWidget()->GetNativeView();
- if (view) {
- DWORD view_tid = GetWindowThreadProcessId(HWNDForNativeView(view), NULL);
- if (view_tid != GetWindowThreadProcessId(HWNDForNativeView(window), NULL)) {
+ // Convert screen_loc to pixels for the Win32 API's like WindowFromPoint,
+ // PostMessage/SendMessage to work correctly. These API's expect the
+ // coordinates to be in pixels.
+ // PostMessage() to metro windows isn't allowed (access will be denied). Don't
+ // try to repost with Win32 if the window under the mouse press is in metro.
+ if (!ViewsDelegate::views_delegate ||
+ !ViewsDelegate::views_delegate->IsWindowInMetro(window)) {
+ gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc);
+ HWND target_window = window ? HWNDForNativeWindow(window) :
+ WindowFromPoint(screen_loc_pixels.ToPOINT());
+ HWND source_window = HWNDForNativeView(native_view);
+ if (!target_window || !source_window ||
+ GetWindowThreadProcessId(source_window, NULL) !=
+ GetWindowThreadProcessId(target_window, NULL)) {
// Even though we have mouse capture, windows generates a mouse event if
// the other window is in a separate thread. Only repost an event if
- // |view| was created on the same thread, else the target window can get
- // double events leading to bad behavior.
+ // |target_window| and |source_window| were created on the same thread,
+ // else double events can occur and lead to bad behavior.
return;
}
- }
-#endif
- scoped_ptr<ui::LocatedEvent> clone;
- if (event.IsMouseEvent()) {
- clone.reset(new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event)));
- } else if (event.IsGestureEvent()) {
- // TODO(rbyers): Gesture event repost is tricky to get right
- // crbug.com/170987.
- return;
- } else {
- NOTREACHED();
+ // Determine whether the click was in the client area or not.
+ // NOTE: WM_NCHITTEST coordinates are relative to the screen.
+ LPARAM coords = MAKELPARAM(screen_loc_pixels.x(), screen_loc_pixels.y());
+ LRESULT nc_hit_result = SendMessage(target_window, WM_NCHITTEST, 0, coords);
+ const bool client_area = nc_hit_result == HTCLIENT;
+
+ // TODO(sky): this isn't right. The event to generate should correspond with
+ // the event we just got. MouseEvent only tells us what is down, which may
+ // differ. Need to add ability to get changed button from MouseEvent.
+ int event_type;
+ int flags = event.flags();
+ if (flags & ui::EF_LEFT_MOUSE_BUTTON) {
+ event_type = client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
+ } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) {
+ event_type = client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN;
+ } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) {
+ event_type = client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN;
+ } else {
+ NOTREACHED();
+ return;
+ }
+
+ int window_x = screen_loc_pixels.x();
+ int window_y = screen_loc_pixels.y();
+ if (client_area) {
+ POINT pt = { window_x, window_y };
+ ScreenToClient(target_window, &pt);
+ window_x = pt.x;
+ window_y = pt.y;
+ }
+
+ WPARAM target = client_area ? event.native_event().wParam : nc_hit_result;
+ LPARAM window_coords = MAKELPARAM(window_x, window_y);
+ PostMessage(target_window, event_type, target, window_coords);
return;
}
- clone->set_location(screen_loc);
+#endif
+ // Non-Windows Aura or |window| is in metro mode.
+ if (!window)
+ return;
- RepostLocatedEvent(window, *clone);
+ message_loop_->RepostEventToWindow(event, window, screen_loc);
}
-
void MenuController::SetDropMenuItem(
MenuItemView* new_target,
MenuDelegate::DropPosition new_position) {
@@ -2230,12 +2176,13 @@ void MenuController::UpdateActiveMouseView(SubmenuView* event_source,
target_menu, active_mouse_view, &target_point);
ui::MouseEvent mouse_entered_event(ui::ET_MOUSE_ENTERED,
target_point, target_point,
- 0);
+ 0, 0);
active_mouse_view->OnMouseEntered(mouse_entered_event);
ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED,
target_point, target_point,
- event.flags());
+ event.flags(),
+ event.changed_button_flags());
active_mouse_view->OnMousePressed(mouse_pressed_event);
}
}
@@ -2245,7 +2192,8 @@ void MenuController::UpdateActiveMouseView(SubmenuView* event_source,
View::ConvertPointToTarget(target_menu, active_mouse_view, &target_point);
ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED,
target_point, target_point,
- event.flags());
+ event.flags(),
+ event.changed_button_flags());
active_mouse_view->OnMouseDragged(mouse_dragged_event);
}
}
@@ -2261,7 +2209,7 @@ void MenuController::SendMouseReleaseToActiveView(SubmenuView* event_source,
&target_loc);
View::ConvertPointFromScreen(active_mouse_view, &target_loc);
ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, target_loc, target_loc,
- event.flags());
+ event.flags(), event.changed_button_flags());
// Reset active mouse view before sending mouse released. That way if it calls
// back to us, we aren't in a weird state.
SetActiveMouseView(NULL);
@@ -2293,20 +2241,22 @@ View* MenuController::GetActiveMouseView() {
void MenuController::SetExitType(ExitType type) {
exit_type_ = type;
// Exit nested message loops as soon as possible. We do this as
- // MessageLoop::Dispatcher is only invoked before native events, which means
+ // MessagePumpDispatcher is only invoked before native events, which means
// its entirely possible for a Widget::CloseNow() task to be processed before
- // the next native message. By using QuitNow() we ensures the nested message
- // loop returns as soon as possible and avoids having deleted views classes
- // (such as widgets and rootviews) on the stack when the nested message loop
- // stops.
+ // the next native message. We quite the nested message loop as soon as
+ // possible to avoid having deleted views classes (such as widgets and
+ // rootviews) on the stack when the nested message loop stops.
//
- // It's safe to invoke QuitNow multiple times, it only effects the current
- // loop.
- bool quit_now = ShouldQuitNow() && exit_type_ != EXIT_NONE &&
+ // It's safe to invoke QuitNestedMessageLoop() multiple times, it only effects
+ // the current loop.
+ bool quit_now = message_loop_->ShouldQuitNow() && exit_type_ != EXIT_NONE &&
message_loop_depth_;
-
if (quit_now)
- base::MessageLoop::current()->QuitNow();
+ TerminateNestedMessageLoop();
+}
+
+void MenuController::TerminateNestedMessageLoop() {
+ message_loop_->QuitNow();
}
void MenuController::HandleMouseLocation(SubmenuView* source,
@@ -2341,4 +2291,10 @@ void MenuController::HandleMouseLocation(SubmenuView* source,
}
}
+gfx::Screen* MenuController::GetScreen() {
+ Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL;
+ return root ? gfx::Screen::GetScreenFor(root->GetNativeView())
+ : gfx::Screen::GetNativeScreen();
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h
index 1404d54e5d6..30c56f0f04b 100644
--- a/chromium/ui/views/controls/menu/menu_controller.h
+++ b/chromium/ui/views/controls/menu/menu_controller.h
@@ -13,30 +13,39 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/timer/timer.h"
+#include "ui/events/event.h"
#include "ui/events/event_constants.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_delegate.h"
-#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/widget/widget_observer.h"
-namespace ui {
-class NativeTheme;
-class OSExchangeData;
+namespace base {
+class MessagePumpDispatcher;
}
namespace gfx {
class Screen;
}
+namespace ui {
+class NativeTheme;
+class OSExchangeData;
+class ScopedEventDispatcher;
+}
namespace views {
class MenuButton;
class MenuHostRootView;
+class MenuItemView;
+class MenuMessageLoop;
class MouseEvent;
class SubmenuView;
class View;
namespace internal {
class MenuControllerDelegate;
+class MenuEventDispatcher;
+class MenuMessagePumpDispatcher;
class MenuRunnerImpl;
}
@@ -45,8 +54,7 @@ class MenuRunnerImpl;
// MenuController is used internally by the various menu classes to manage
// showing, selecting and drag/drop for menus. All relevant events are
// forwarded to the MenuController from SubmenuView and MenuHost.
-class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
- public WidgetObserver {
+class VIEWS_EXPORT MenuController : public WidgetObserver {
public:
// Enumeration of how the menu should exit.
enum ExitType {
@@ -74,7 +82,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
MenuButton* button,
MenuItemView* root,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition position,
+ MenuAnchorPosition position,
bool context_menu,
int* event_flags);
@@ -84,8 +92,12 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
// Whether or not drag operation is in progress.
bool drag_in_progress() const { return drag_in_progress_; }
+ // Returns the owner of child windows.
+ // WARNING: this may be NULL.
+ Widget* owner() { return owner_; }
+
// Get the anchor position wich is used to show this menu.
- MenuItemView::AnchorPosition GetAnchorPosition() { return state_.anchor; }
+ MenuAnchorPosition GetAnchorPosition() { return state_.anchor; }
// Cancels the current Run. See ExitType for a description of what happens
// with the various parameters.
@@ -101,7 +113,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
// Returns the time from the event which closed the menu - or 0.
base::TimeDelta closing_event_time() const { return closing_event_time_; }
- void set_accept_on_f4(bool accept_on_f4) { accept_on_f4_ = accept_on_f4; }
+ void set_is_combobox(bool is_combobox) { is_combobox_ = is_combobox; }
// Various events, forwarded from the submenu.
//
@@ -112,9 +124,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
void OnMouseReleased(SubmenuView* source, const ui::MouseEvent& event);
void OnMouseMoved(SubmenuView* source, const ui::MouseEvent& event);
void OnMouseEntered(SubmenuView* source, const ui::MouseEvent& event);
-#if defined(USE_AURA)
bool OnMouseWheel(SubmenuView* source, const ui::MouseWheelEvent& event);
-#endif
void OnGestureEvent(SubmenuView* source, ui::GestureEvent* event);
bool GetDropFormats(
@@ -142,7 +152,10 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
static void TurnOffMenuSelectionHoldForTest();
private:
+ friend class internal::MenuEventDispatcher;
+ friend class internal::MenuMessagePumpDispatcher;
friend class internal::MenuRunnerImpl;
+ friend class MenuControllerTest;
friend class MenuHostRootView;
friend class MenuItemView;
friend class SubmenuView;
@@ -194,7 +207,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
gfx::Rect initial_bounds;
// Position of the initial menu.
- MenuItemView::AnchorPosition anchor;
+ MenuAnchorPosition anchor;
// The direction child menus have opened in.
std::list<bool> open_leading;
@@ -253,10 +266,6 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
const ui::LocatedEvent& event);
void StartDrag(SubmenuView* source, const gfx::Point& location);
- // Dispatcher method. This returns true if the menu was canceled, or
- // if the message is such that the menu should be closed.
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
// Key processing. The return value of this is returned from Dispatch.
// In other words, if this returns false (which happens if escape was
// pressed, or a matching mnemonic was found) the message loop returns.
@@ -279,7 +288,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
SendAcceleratorResultType SendAcceleratorToHotTrackedView();
void UpdateInitialLocation(const gfx::Rect& bounds,
- MenuItemView::AnchorPosition position,
+ MenuAnchorPosition position,
bool context_menu);
// Invoked when the user accepts the selected item. This is only used
@@ -416,8 +425,8 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
// |match_function| is used to determine which menus match.
SelectByCharDetails FindChildForMnemonic(
MenuItemView* parent,
- char16 key,
- bool (*match_function)(MenuItemView* menu, char16 mnemonic));
+ base::char16 key,
+ bool (*match_function)(MenuItemView* menu, base::char16 mnemonic));
// Selects or accepts the appropriate menu item based on |details|. Returns
// true if |Accept| was invoked (which happens if there aren't multiple item
@@ -426,7 +435,7 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
// Selects by mnemonic, and if that doesn't work tries the first character of
// the title. Returns true if a match was selected and the menu should exit.
- bool SelectByChar(char16 key);
+ bool SelectByChar(base::char16 key);
// For Windows and Aura we repost an event for some events that dismiss
// the context menu. The event is then reprocessed to cause its result
@@ -468,9 +477,12 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
void SetActiveMouseView(View* view);
View* GetActiveMouseView();
- // Sets exit type.
+ // Sets exit type. Calling this can terminate the active nested message-loop.
void SetExitType(ExitType type);
+ // Terminates the current nested message-loop.
+ void TerminateNestedMessageLoop();
+
// Returns true if SetExitType() should quit the message loop.
bool ShouldQuitNow() const;
@@ -584,12 +596,15 @@ class VIEWS_EXPORT MenuController : public base::MessageLoop::Dispatcher,
// screen coordinates). Otherwise this will be (0, 0).
gfx::Point menu_start_mouse_press_loc_;
- // Whether the menu should accept on F4, like Windows native Combobox menus.
- bool accept_on_f4_;
+ // Controls behavior differences between a combobox and other types of menu
+ // (like a context menu).
+ bool is_combobox_;
// Set to true if the menu item was selected by touch.
bool item_selected_by_touch_;
+ scoped_ptr<MenuMessageLoop> message_loop_;
+
DISALLOW_COPY_AND_ASSIGN(MenuController);
};
diff --git a/chromium/ui/views/controls/menu/menu_controller_aura.cc b/chromium/ui/views/controls/menu/menu_controller_aura.cc
deleted file mode 100644
index 48bf3118ff6..00000000000
--- a/chromium/ui/views/controls/menu/menu_controller_aura.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_controller.h"
-
-#include "base/run_loop.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/dispatcher_client.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/gfx/screen.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-namespace {
-
-// ActivationChangeObserverImpl is used to observe activation changes and close
-// the menu. Additionally it listens for the root window to be destroyed and
-// cancel the menu as well.
-class ActivationChangeObserverImpl
- : public aura::client::ActivationChangeObserver,
- public aura::WindowObserver,
- public ui::EventHandler {
- public:
- ActivationChangeObserverImpl(MenuController* controller,
- aura::Window* root)
- : controller_(controller),
- root_(root) {
- aura::client::GetActivationClient(root_)->AddObserver(this);
- root_->AddObserver(this);
- root_->AddPreTargetHandler(this);
- }
-
- virtual ~ActivationChangeObserverImpl() {
- Cleanup();
- }
-
- // aura::client::ActivationChangeObserver overrides:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- if (!controller_->drag_in_progress())
- controller_->CancelAll();
- }
-
- // aura::WindowObserver overrides:
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- Cleanup();
- }
-
- // ui::EventHandler overrides:
- virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
- controller_->CancelAll();
- }
-
- private:
- void Cleanup() {
- if (!root_)
- return;
- // The ActivationClient may have been destroyed by the time we get here.
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(root_);
- if (client)
- client->RemoveObserver(this);
- root_->RemovePreTargetHandler(this);
- root_->RemoveObserver(this);
- root_ = NULL;
- }
-
- MenuController* controller_;
- aura::Window* root_;
-
- DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
-};
-
-aura::Window* GetOwnerRootWindow(views::Widget* owner) {
- return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
-}
-
-} // namespace
-
-void MenuController::RunMessageLoop(bool nested_menu) {
- // |owner_| may be NULL.
- aura::Window* root = GetOwnerRootWindow(owner_);
- if (root) {
- scoped_ptr<ActivationChangeObserverImpl> observer;
- if (!nested_menu)
- observer.reset(new ActivationChangeObserverImpl(this, root));
- aura::client::GetDispatcherClient(root)->
- RunWithDispatcher(this, owner_->GetNativeWindow(), true);
- } else {
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- base::MessageLoop::ScopedNestableTaskAllower allow(loop);
- base::RunLoop run_loop(this);
- run_loop.Run();
- }
-}
-
-bool MenuController::ShouldQuitNow() const {
- aura::Window* root = GetOwnerRootWindow(owner_);
- return !aura::client::GetDragDropClient(root) ||
- !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
-}
-
-gfx::Screen* MenuController::GetScreen() {
- aura::Window* root = GetOwnerRootWindow(owner_);
- return root ?
- gfx::Screen::GetScreenFor(root) : gfx::Screen::GetNativeScreen();
-}
-
-
-} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
new file mode 100644
index 00000000000..1c98f95bc9c
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -0,0 +1,267 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_controller.h"
+
+#include "base/run_loop.h"
+#include "ui/aura/scoped_window_targeter.h"
+#include "ui/aura/window.h"
+#include "ui/events/event_targeter.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/wm/public/dispatcher_client.h"
+
+#if defined(OS_WIN)
+#include "base/message_loop/message_pump_dispatcher.h"
+#elif defined(USE_X11)
+#include <X11/Xlib.h>
+#undef Bool
+#undef None
+#include "ui/events/test/events_test_utils_x11.h"
+#elif defined(USE_OZONE)
+#include "ui/events/event.h"
+#endif
+
+namespace views {
+
+namespace {
+
+class TestMenuItemView : public MenuItemView {
+ public:
+ TestMenuItemView() : MenuItemView(NULL) {}
+ virtual ~TestMenuItemView() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestMenuItemView);
+};
+
+class TestPlatformEventSource : public ui::PlatformEventSource {
+ public:
+ TestPlatformEventSource() {}
+ virtual ~TestPlatformEventSource() {}
+
+ uint32_t Dispatch(const ui::PlatformEvent& event) {
+ return DispatchEvent(event);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource);
+};
+
+class TestNullTargeter : public ui::EventTargeter {
+ public:
+ TestNullTargeter() {}
+ virtual ~TestNullTargeter() {}
+
+ virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
+ ui::Event* event) OVERRIDE {
+ return NULL;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestNullTargeter);
+};
+
+class TestDispatcherClient : public aura::client::DispatcherClient {
+ public:
+ TestDispatcherClient() : dispatcher_(NULL) {}
+ virtual ~TestDispatcherClient() {}
+
+ base::MessagePumpDispatcher* dispatcher() {
+ return dispatcher_;
+ }
+
+ // aura::client::DispatcherClient:
+ virtual void PrepareNestedLoopClosures(
+ base::MessagePumpDispatcher* dispatcher,
+ base::Closure* run_closure,
+ base::Closure* quit_closure) OVERRIDE {
+ scoped_ptr<base::RunLoop> run_loop(new base::RunLoop());
+ *quit_closure = run_loop->QuitClosure();
+ *run_closure = base::Bind(&TestDispatcherClient::RunNestedDispatcher,
+ base::Unretained(this),
+ base::Passed(&run_loop),
+ dispatcher);
+ }
+
+ private:
+ void RunNestedDispatcher(scoped_ptr<base::RunLoop> run_loop,
+ base::MessagePumpDispatcher* dispatcher) {
+ base::AutoReset<base::MessagePumpDispatcher*> reset_dispatcher(&dispatcher_,
+ dispatcher);
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ run_loop->Run();
+ }
+
+ base::MessagePumpDispatcher* dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDispatcherClient);
+};
+
+} // namespace
+
+class MenuControllerTest : public ViewsTestBase {
+ public:
+ MenuControllerTest() : controller_(NULL) {}
+ virtual ~MenuControllerTest() {
+ ResetMenuController();
+ }
+
+ // Dispatches |count| number of items, each in a separate iteration of the
+ // message-loop, by posting a task.
+ void Step3_DispatchEvents(int count) {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ controller_->exit_type_ = MenuController::EXIT_ALL;
+
+ DispatchEvent();
+ if (count) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::Step3_DispatchEvents,
+ base::Unretained(this),
+ count - 1));
+ } else {
+ EXPECT_TRUE(run_loop_->running());
+ run_loop_->Quit();
+ }
+ }
+
+ // Runs a nested message-loop that does not involve the menu itself.
+ void Step2_RunNestedLoop() {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::Step3_DispatchEvents,
+ base::Unretained(this),
+ 3));
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ }
+
+ void Step1_RunMenu() {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::Step2_RunNestedLoop,
+ base::Unretained(this)));
+ scoped_ptr<Widget> owner(CreateOwnerWidget());
+ RunMenu(owner.get());
+ }
+
+ scoped_ptr<Widget> CreateOwnerWidget() {
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget->Init(params);
+ widget->Show();
+
+ aura::client::SetDispatcherClient(
+ widget->GetNativeWindow()->GetRootWindow(), &dispatcher_client_);
+ return widget.Pass();
+ }
+
+ void RunMenu(views::Widget* owner) {
+ scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView);
+ ResetMenuController();
+ controller_ = new MenuController(NULL, true, NULL);
+ controller_->owner_ = owner;
+ controller_->showing_ = true;
+ controller_->SetSelection(menu_item.get(),
+ MenuController::SELECTION_UPDATE_IMMEDIATELY);
+ controller_->RunMessageLoop(false);
+ }
+
+#if defined(USE_X11)
+ void DispatchEscapeAndExpect(MenuController::ExitType exit_type) {
+ ui::ScopedXI2Event key_event;
+ key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0);
+ event_source_.Dispatch(key_event);
+ EXPECT_EQ(exit_type, controller_->exit_type());
+ controller_->exit_type_ = MenuController::EXIT_ALL;
+ DispatchEvent();
+ }
+#endif
+
+ void DispatchEvent() {
+#if defined(USE_X11)
+ XEvent xevent;
+ memset(&xevent, 0, sizeof(xevent));
+ event_source_.Dispatch(&xevent);
+#elif defined(OS_WIN)
+ MSG msg;
+ memset(&msg, 0, sizeof(MSG));
+ dispatcher_client_.dispatcher()->Dispatch(msg);
+#elif defined(USE_OZONE)
+ ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0, true);
+ dispatcher_client_.dispatcher()->Dispatch(&event);
+#else
+#error Unsupported platform
+#endif
+ }
+
+ private:
+ void ResetMenuController() {
+ if (controller_) {
+ // These properties are faked by RunMenu for the purposes of testing and
+ // need to be undone before we call the destructor.
+ controller_->owner_ = NULL;
+ controller_->showing_ = false;
+ delete controller_;
+ controller_ = NULL;
+ }
+ }
+
+ // A weak pointer to the MenuController owned by this class.
+ MenuController* controller_;
+ scoped_ptr<base::RunLoop> run_loop_;
+ TestPlatformEventSource event_source_;
+ TestDispatcherClient dispatcher_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
+};
+
+TEST_F(MenuControllerTest, Basic) {
+ base::MessageLoop::ScopedNestableTaskAllower allow_nested(
+ base::MessageLoop::current());
+ message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this)));
+}
+
+#if defined(OS_LINUX) && defined(USE_X11)
+// Tests that an event targeter which blocks events will be honored by the menu
+// event dispatcher.
+TEST_F(MenuControllerTest, EventTargeter) {
+ {
+ // Verify that the menu handles the escape key under normal circumstances.
+ scoped_ptr<Widget> owner(CreateOwnerWidget());
+ message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
+ base::Unretained(this),
+ MenuController::EXIT_OUTERMOST));
+ RunMenu(owner.get());
+ }
+
+ {
+ // With the NULL targeter instantiated and assigned we expect the menu to
+ // not handle the key event.
+ scoped_ptr<Widget> owner(CreateOwnerWidget());
+ aura::ScopedWindowTargeter scoped_targeter(
+ owner->GetNativeWindow()->GetRootWindow(),
+ scoped_ptr<ui::EventTargeter>(new TestNullTargeter));
+ message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
+ base::Unretained(this),
+ MenuController::EXIT_NONE));
+ RunMenu(owner.get());
+ }
+}
+#endif
+
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_controller_win.cc b/chromium/ui/views/controls/menu/menu_controller_win.cc
deleted file mode 100644
index bbf7e9b1366..00000000000
--- a/chromium/ui/views/controls/menu/menu_controller_win.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_controller.h"
-
-#include "base/run_loop.h"
-#include "ui/gfx/screen.h"
-
-namespace views {
-
-void MenuController::RunMessageLoop(bool nested_menu) {
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- base::MessageLoop::ScopedNestableTaskAllower allow(loop);
- base::RunLoop run_loop(this);
- run_loop.Run();
-}
-
-bool MenuController::ShouldQuitNow() const {
- return true;
-}
-
-gfx::Screen* MenuController::GetScreen() {
- return gfx::Screen::GetNativeScreen();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_delegate.cc b/chromium/ui/views/controls/menu/menu_delegate.cc
index 90ab5cbe1b2..6778545f415 100644
--- a/chromium/ui/views/controls/menu/menu_delegate.cc
+++ b/chromium/ui/views/controls/menu/menu_delegate.cc
@@ -2,9 +2,11 @@
// 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_config.h"
#include "ui/views/controls/menu/menu_delegate.h"
+#include "ui/events/event.h"
+#include "ui/views/controls/menu/menu_config.h"
+
namespace views {
MenuDelegate::~MenuDelegate() {}
@@ -13,14 +15,19 @@ bool MenuDelegate::IsItemChecked(int id) const {
return false;
}
-string16 MenuDelegate::GetLabel(int id) const {
- return string16();
+base::string16 MenuDelegate::GetLabel(int id) const {
+ return base::string16();
}
-const gfx::Font* MenuDelegate::GetLabelFont(int id) const {
+const gfx::FontList* MenuDelegate::GetLabelFontList(int id) const {
return NULL;
}
+bool MenuDelegate::GetShouldUseDisabledEmphasizedForegroundColor(
+ int command_id) const {
+ return false;
+}
+
bool MenuDelegate::GetBackgroundColor(int command_id,
bool is_hovered,
SkColor* override_color) const {
@@ -33,12 +40,12 @@ bool MenuDelegate::GetForegroundColor(int command_id,
return false;
}
-string16 MenuDelegate::GetTooltipText(int id,
+base::string16 MenuDelegate::GetTooltipText(int id,
const gfx::Point& screen_loc) const {
- return string16();
+ return base::string16();
}
-bool MenuDelegate::GetAccelerator(int id, ui::Accelerator* accelerator) {
+bool MenuDelegate::GetAccelerator(int id, ui::Accelerator* accelerator) const {
return false;
}
@@ -57,7 +64,11 @@ bool MenuDelegate::IsCommandEnabled(int id) const {
return true;
}
-bool MenuDelegate::GetContextualLabel(int id, string16* out) const {
+bool MenuDelegate::IsCommandVisible(int id) const {
+ return true;
+}
+
+bool MenuDelegate::GetContextualLabel(int id, base::string16* out) const {
return false;
}
@@ -126,7 +137,7 @@ int MenuDelegate::GetDragOperations(MenuItemView* sender) {
MenuItemView* MenuDelegate::GetSiblingMenu(MenuItemView* menu,
const gfx::Point& screen_point,
- MenuItemView::AnchorPosition* anchor,
+ MenuAnchorPosition* anchor,
bool* has_mnemonics,
MenuButton** button) {
return NULL;
diff --git a/chromium/ui/views/controls/menu/menu_delegate.h b/chromium/ui/views/controls/menu/menu_delegate.h
index f171d570b7e..fafccd790f9 100644
--- a/chromium/ui/views/controls/menu/menu_delegate.h
+++ b/chromium/ui/views/controls/menu/menu_delegate.h
@@ -10,23 +10,29 @@
#include "base/logging.h"
#include "base/strings/string16.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/views/controls/menu/menu_types.h"
+#include "ui/views/views_export.h"
using ui::OSExchangeData;
namespace gfx {
-class Font;
+class FontList;
+class Point;
}
namespace ui {
class Accelerator;
+class DropTargetEvent;
}
namespace views {
class MenuButton;
+class MenuItemView;
// MenuDelegate --------------------------------------------------------------
@@ -61,14 +67,21 @@ class VIEWS_EXPORT MenuDelegate {
// The string shown for the menu item. This is only invoked when an item is
// added with an empty label.
- virtual string16 GetLabel(int id) const;
+ virtual base::string16 GetLabel(int id) const;
// The font for the menu item label.
- virtual const gfx::Font* GetLabelFont(int id) const;
+ virtual const gfx::FontList* GetLabelFontList(int id) const;
+
+ // Whether this item should be displayed with a bolder color when disabled.
+ virtual bool GetShouldUseDisabledEmphasizedForegroundColor(
+ int command_id) const;
// Override the text color of a given menu item dependent on the
// |command_id| and its |is_hovered| state. Returns true if it chooses to
// override the color.
+ //
+ // TODO(erg): Remove this interface. Injecting raw colors into the menu
+ // circumvents the NativeTheme.
virtual bool GetForegroundColor(int command_id,
bool is_hovered,
SkColor* override_color) const;
@@ -76,17 +89,21 @@ class VIEWS_EXPORT MenuDelegate {
// Override the background color of a given menu item dependent on the
// |command_id| and its |is_hovered| state. Returns true if it chooses to
// override the color.
+ //
+ // TODO(erg): Remove this interface. Injecting raw colors into the menu
+ // circumvents the NativeTheme.
virtual bool GetBackgroundColor(int command_id,
bool is_hovered,
SkColor* override_color) const;
// The tooltip shown for the menu item. This is invoked when the user
// hovers over the item, and no tooltip text has been set for that item.
- virtual string16 GetTooltipText(int id, const gfx::Point& screen_loc) const;
+ virtual base::string16 GetTooltipText(int id,
+ const gfx::Point& screen_loc) const;
// If there is an accelerator for the menu item with id |id| it is set in
// |accelerator| and true is returned.
- virtual bool GetAccelerator(int id, ui::Accelerator* accelerator);
+ virtual bool GetAccelerator(int id, ui::Accelerator* accelerator) const;
// Shows the context menu with the specified id. This is invoked when the
// user does the appropriate gesture to show a context menu. The id
@@ -104,7 +121,8 @@ class VIEWS_EXPORT MenuDelegate {
// Controller
virtual bool SupportsCommand(int id) const;
virtual bool IsCommandEnabled(int id) const;
- virtual bool GetContextualLabel(int id, string16* out) const;
+ virtual bool IsCommandVisible(int id) const;
+ virtual bool GetContextualLabel(int id, base::string16* out) const;
virtual void ExecuteCommand(int id) {
}
@@ -202,7 +220,7 @@ class VIEWS_EXPORT MenuDelegate {
// The delegate owns the returned menu, not the controller.
virtual MenuItemView* GetSiblingMenu(MenuItemView* menu,
const gfx::Point& screen_point,
- MenuItemView::AnchorPosition* anchor,
+ MenuAnchorPosition* anchor,
bool* has_mnemonics,
MenuButton** button);
diff --git a/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.cc b/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.cc
new file mode 100644
index 00000000000..181ba241afe
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.cc
@@ -0,0 +1,91 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+namespace internal {
+
+MenuEventDispatcher::MenuEventDispatcher(MenuController* controller)
+ : menu_controller_(controller) {}
+
+MenuEventDispatcher::~MenuEventDispatcher() {}
+
+bool MenuEventDispatcher::CanDispatchEvent(const ui::PlatformEvent& event) {
+ return true;
+}
+
+uint32_t MenuEventDispatcher::DispatchEvent(const ui::PlatformEvent& event) {
+ bool should_quit = false;
+ bool should_perform_default = true;
+ bool should_process_event = true;
+
+ // Check if the event should be handled.
+ scoped_ptr<ui::Event> ui_event(ui::EventFromNative(event));
+ if (ui_event && menu_controller_->owner()) {
+ aura::Window* menu_window = menu_controller_->owner()->GetNativeWindow();
+ aura::Window* target_window = static_cast<aura::Window*>(
+ static_cast<ui::EventTarget*>(menu_window->GetRootWindow())->
+ GetEventTargeter()->FindTargetForEvent(menu_window,
+ ui_event.get()));
+ // TODO(flackr): The event shouldn't be handled if target_window is not
+ // menu_window, however the event targeter does not properly target the
+ // open menu. For now, we allow targeters to prevent handling by the menu.
+ if (!target_window)
+ should_process_event = false;
+ }
+
+ if (menu_controller_->exit_type() == MenuController::EXIT_ALL ||
+ menu_controller_->exit_type() == MenuController::EXIT_DESTROYED) {
+ should_quit = true;
+ } else if (should_process_event) {
+ switch (ui::EventTypeFromNative(event)) {
+ case ui::ET_KEY_PRESSED: {
+ if (!menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(event))) {
+ should_quit = true;
+ should_perform_default = false;
+ break;
+ }
+
+ // Do not check mnemonics if the Alt or Ctrl modifiers are pressed.
+ int flags = ui::EventFlagsFromNative(event);
+ if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) {
+ char c = ui::GetCharacterFromKeyCode(
+ ui::KeyboardCodeFromNative(event), flags);
+ if (menu_controller_->SelectByChar(c)) {
+ should_quit = true;
+ should_perform_default = false;
+ break;
+ }
+ }
+ should_quit = false;
+ should_perform_default = false;
+ break;
+ }
+ case ui::ET_KEY_RELEASED:
+ should_quit = false;
+ should_perform_default = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (should_quit || menu_controller_->exit_type() != MenuController::EXIT_NONE)
+ menu_controller_->TerminateNestedMessageLoop();
+
+ return should_perform_default ? ui::POST_DISPATCH_PERFORM_DEFAULT
+ : ui::POST_DISPATCH_NONE;
+}
+
+} // namespace internal
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.h b/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.h
new file mode 100644
index 00000000000..bdc76fd88ba
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_event_dispatcher_linux.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+
+namespace views {
+
+class MenuController;
+
+namespace internal {
+
+// A message-pump dispatcher object used to dispatch events from the nested
+// message-loop initiated by the MenuController.
+class MenuEventDispatcher : public ui::PlatformEventDispatcher {
+ public:
+ explicit MenuEventDispatcher(MenuController* menu_controller);
+ virtual ~MenuEventDispatcher();
+
+ private:
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+
+ MenuController* menu_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuEventDispatcher);
+};
+
+} // namespace internal
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_host.cc b/chromium/ui/views/controls/menu/menu_host.cc
index 4645e1ba6aa..2716ec8bb78 100644
--- a/chromium/ui/views/controls/menu/menu_host.cc
+++ b/chromium/ui/views/controls/menu/menu_host.cc
@@ -18,10 +18,6 @@
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/views/corewm/shadow_types.h"
-#endif
-
namespace views {
////////////////////////////////////////////////////////////////////////////////
@@ -49,7 +45,8 @@ void MenuHost::InitMenuHost(Widget* parent,
bool rounded_border = menu_controller && menu_config.corner_radius > 0;
bool bubble_border = submenu_->GetScrollViewContainer() &&
submenu_->GetScrollViewContainer()->HasBubbleBorder();
- params.has_dropshadow = !bubble_border;
+ params.shadow_type = bubble_border ? Widget::InitParams::SHADOW_TYPE_NONE
+ : Widget::InitParams::SHADOW_TYPE_DROP;
params.opacity = (bubble_border || rounded_border) ?
Widget::InitParams::TRANSLUCENT_WINDOW :
Widget::InitParams::OPAQUE_WINDOW;
@@ -57,14 +54,7 @@ void MenuHost::InitMenuHost(Widget* parent,
params.bounds = bounds;
Init(params);
-#if defined(USE_AURA)
- if (bubble_border)
- SetShadowType(GetNativeView(), views::corewm::SHADOW_TYPE_NONE);
-#endif
-
SetContentsView(contents_view);
- if (bubble_border || rounded_border)
- SetOpacity(0);
ShowMenuHost(do_capture);
}
@@ -76,13 +66,11 @@ void MenuHost::ShowMenuHost(bool do_capture) {
// Doing a capture may make us get capture lost. Ignore it while we're in the
// process of showing.
base::AutoReset<bool> reseter(&ignore_capture_lost_, true);
- Show();
+ ShowInactive();
if (do_capture) {
-#if defined(USE_AURA)
// Cancel existing touches, so we don't miss some touch release/cancel
// events due to the menu taking capture.
- ui::GestureRecognizer::Get()->TransferEventsTo(GetNativeWindow(), NULL);
-#endif // USE_AURA
+ ui::GestureRecognizer::Get()->TransferEventsTo(NULL, NULL);
native_widget_private()->SetCapture();
}
}
diff --git a/chromium/ui/views/controls/menu/menu_host_root_view.cc b/chromium/ui/views/controls/menu/menu_host_root_view.cc
index 2577d909b7b..3bce4a49b6e 100644
--- a/chromium/ui/views/controls/menu/menu_host_root_view.cc
+++ b/chromium/ui/views/controls/menu/menu_host_root_view.cc
@@ -51,17 +51,8 @@ void MenuHostRootView::OnMouseMoved(const ui::MouseEvent& event) {
}
bool MenuHostRootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
-#if defined(USE_AURA)
- // Aura uses MenuController to forward events like other mouse events.
return GetMenuController() &&
GetMenuController()->OnMouseWheel(submenu_, event);
-#else
- // Windows uses focus_util_win::RerouteMouseWheel to forward events to
- // the right menu.
- // RootView::OnMouseWheel forwards to the focused view. We don't have a
- // focused view, so we need to override this then forward to the menu.
- return submenu_->OnMouseWheel(event);
-#endif
}
void MenuHostRootView::DispatchGestureEvent(ui::GestureEvent* event) {
diff --git a/chromium/ui/views/controls/menu/menu_image_util.cc b/chromium/ui/views/controls/menu/menu_image_util.cc
index a50980b3500..60315736fe2 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.cc
+++ b/chromium/ui/views/controls/menu/menu_image_util.cc
@@ -54,7 +54,7 @@ class RadioButtonImageSource : public gfx::CanvasImageSource {
skia::RefPtr<SkShader> shader = skia::AdoptRef(
SkGradientShader::CreateLinear(
gradient_points, gradient_colors, NULL, arraysize(gradient_points),
- SkShader::kClamp_TileMode, NULL));
+ SkShader::kClamp_TileMode));
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setAntiAlias(true);
@@ -76,8 +76,7 @@ class RadioButtonImageSource : public gfx::CanvasImageSource {
shader = skia::AdoptRef(
SkGradientShader::CreateLinear(
selected_gradient_points, selected_gradient_colors, NULL,
- arraysize(selected_gradient_points),
- SkShader::kClamp_TileMode, NULL));
+ arraysize(selected_gradient_points), SkShader::kClamp_TileMode));
paint.setShader(shader.get());
paint.setStyle(SkPaint::kFill_Style);
canvas->sk_canvas()->drawCircle(radius, radius,
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index 2adc1ad2f17..f24c61059c6 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -9,12 +9,15 @@
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
#include "grit/ui_strings.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/text_utils.h"
#include "ui/native_theme/common_theme.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/image_view.h"
@@ -47,7 +50,7 @@ class EmptyMenuMenuItem : public MenuItemView {
}
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE {
+ base::string16* tooltip) const OVERRIDE {
// Empty menu items shouldn't have a tooltip.
return false;
}
@@ -116,7 +119,7 @@ void MenuItemView::ChildPreferredSizeChanged(View* child) {
}
bool MenuItemView::GetTooltipText(const gfx::Point& p,
- string16* tooltip) const {
+ base::string16* tooltip) const {
*tooltip = tooltip_;
if (!tooltip->empty())
return true;
@@ -147,15 +150,15 @@ bool MenuItemView::GetTooltipText(const gfx::Point& p,
return !tooltip->empty();
}
-void MenuItemView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_MENUITEM;
+void MenuItemView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_MENU_ITEM;
- string16 item_text;
+ base::string16 item_text;
if (IsContainer()) {
// The first child is taking over, just use its accessible name instead of
// |title_|.
View* child = child_at(0);
- ui::AccessibleViewState state;
+ ui::AXViewState state;
child->GetAccessibleState(&state);
item_text = state.name;
} else {
@@ -165,12 +168,12 @@ void MenuItemView::GetAccessibleState(ui::AccessibleViewState* state) {
switch (GetType()) {
case SUBMENU:
- state->state |= ui::AccessibilityTypes::STATE_HASPOPUP;
+ state->AddStateFlag(ui::AX_STATE_HASPOPUP);
break;
case CHECKBOX:
case RADIO:
- state->state |= GetDelegate()->IsItemChecked(GetCommand()) ?
- ui::AccessibilityTypes::STATE_CHECKED : 0;
+ if (GetDelegate()->IsItemChecked(GetCommand()))
+ state->AddStateFlag(ui::AX_STATE_CHECKED);
break;
case NORMAL:
case SEPARATOR:
@@ -181,22 +184,22 @@ void MenuItemView::GetAccessibleState(ui::AccessibleViewState* state) {
}
// static
-bool MenuItemView::IsBubble(MenuItemView::AnchorPosition anchor) {
- return anchor == MenuItemView::BUBBLE_LEFT ||
- anchor == MenuItemView::BUBBLE_RIGHT ||
- anchor == MenuItemView::BUBBLE_ABOVE ||
- anchor == MenuItemView::BUBBLE_BELOW;
+bool MenuItemView::IsBubble(MenuAnchorPosition anchor) {
+ return anchor == MENU_ANCHOR_BUBBLE_LEFT ||
+ anchor == MENU_ANCHOR_BUBBLE_RIGHT ||
+ anchor == MENU_ANCHOR_BUBBLE_ABOVE ||
+ anchor == MENU_ANCHOR_BUBBLE_BELOW;
}
// static
-string16 MenuItemView::GetAccessibleNameForMenuItem(
- const string16& item_text, const string16& minor_text) {
- string16 accessible_name = item_text;
+base::string16 MenuItemView::GetAccessibleNameForMenuItem(
+ const base::string16& item_text, const base::string16& minor_text) {
+ base::string16 accessible_name = item_text;
// Filter out the "&" for accessibility clients.
size_t index = 0;
- const char16 amp = '&';
- while ((index = accessible_name.find(amp, index)) != string16::npos &&
+ const base::char16 amp = '&';
+ while ((index = accessible_name.find(amp, index)) != base::string16::npos &&
index + 1 < accessible_name.length()) {
accessible_name.replace(index, accessible_name.length() - index,
accessible_name.substr(index + 1));
@@ -225,9 +228,9 @@ void MenuItemView::Cancel() {
MenuItemView* MenuItemView::AddMenuItemAt(
int index,
int item_id,
- const string16& label,
- const string16& sublabel,
- const string16& minor_text,
+ const base::string16& label,
+ const base::string16& sublabel,
+ const base::string16& minor_text,
const gfx::ImageSkia& icon,
Type type,
ui::MenuSeparatorType separator_style) {
@@ -251,6 +254,8 @@ MenuItemView* MenuItemView::AddMenuItemAt(
item->SetIcon(icon);
if (type == SUBMENU)
item->CreateSubmenu();
+ if (GetDelegate() && !GetDelegate()->IsCommandVisible(item_id))
+ item->SetVisible(false);
submenu_->AddChildViewAt(item, index);
return item;
}
@@ -271,51 +276,52 @@ void MenuItemView::RemoveMenuItemAt(int index) {
}
MenuItemView* MenuItemView::AppendMenuItem(int item_id,
- const string16& label,
+ const base::string16& label,
Type type) {
- return AppendMenuItemImpl(item_id, label, string16(), string16(),
+ return AppendMenuItemImpl(item_id, label, base::string16(), base::string16(),
gfx::ImageSkia(), type, ui::NORMAL_SEPARATOR);
}
MenuItemView* MenuItemView::AppendSubMenu(int item_id,
- const string16& label) {
- return AppendMenuItemImpl(item_id, label, string16(), string16(),
+ const base::string16& label) {
+ return AppendMenuItemImpl(item_id, label, base::string16(), base::string16(),
gfx::ImageSkia(), SUBMENU, ui::NORMAL_SEPARATOR);
}
MenuItemView* MenuItemView::AppendSubMenuWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) {
- return AppendMenuItemImpl(item_id, label, string16(), string16(), icon,
- SUBMENU, ui::NORMAL_SEPARATOR);
+ return AppendMenuItemImpl(item_id, label, base::string16(), base::string16(),
+ icon, SUBMENU, ui::NORMAL_SEPARATOR);
}
-MenuItemView* MenuItemView::AppendMenuItemWithLabel(int item_id,
- const string16& label) {
+MenuItemView* MenuItemView::AppendMenuItemWithLabel(
+ int item_id,
+ const base::string16& label) {
return AppendMenuItem(item_id, label, NORMAL);
}
MenuItemView* MenuItemView::AppendDelegateMenuItem(int item_id) {
- return AppendMenuItem(item_id, string16(), NORMAL);
+ return AppendMenuItem(item_id, base::string16(), NORMAL);
}
void MenuItemView::AppendSeparator() {
- AppendMenuItemImpl(0, string16(), string16(), string16(), gfx::ImageSkia(),
- SEPARATOR, ui::NORMAL_SEPARATOR);
+ AppendMenuItemImpl(0, base::string16(), base::string16(), base::string16(),
+ gfx::ImageSkia(), SEPARATOR, ui::NORMAL_SEPARATOR);
}
MenuItemView* MenuItemView::AppendMenuItemWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon) {
- return AppendMenuItemImpl(item_id, label, string16(), string16(), icon,
- NORMAL, ui::NORMAL_SEPARATOR);
+ return AppendMenuItemImpl(item_id, label, base::string16(), base::string16(),
+ icon, NORMAL, ui::NORMAL_SEPARATOR);
}
MenuItemView* MenuItemView::AppendMenuItemImpl(
int item_id,
- const string16& label,
- const string16& sublabel,
- const string16& minor_text,
+ const base::string16& label,
+ const base::string16& sublabel,
+ const base::string16& minor_text,
const gfx::ImageSkia& icon,
Type type,
ui::MenuSeparatorType separator_style) {
@@ -338,17 +344,17 @@ SubmenuView* MenuItemView::GetSubmenu() const {
return submenu_;
}
-void MenuItemView::SetTitle(const string16& title) {
+void MenuItemView::SetTitle(const base::string16& title) {
title_ = title;
invalidate_dimensions(); // Triggers preferred size recalculation.
}
-void MenuItemView::SetSubtitle(const string16& subtitle) {
+void MenuItemView::SetSubtitle(const base::string16& subtitle) {
subtitle_ = subtitle;
invalidate_dimensions(); // Triggers preferred size recalculation.
}
-void MenuItemView::SetMinorText(const string16& minor_text) {
+void MenuItemView::SetMinorText(const base::string16& minor_text) {
minor_text_ = minor_text;
invalidate_dimensions(); // Triggers preferred size recalculation.
}
@@ -358,7 +364,7 @@ void MenuItemView::SetSelected(bool selected) {
SchedulePaint();
}
-void MenuItemView::SetTooltip(const string16& tooltip, int item_id) {
+void MenuItemView::SetTooltip(const base::string16& tooltip, int item_id) {
MenuItemView* item = GetMenuItemByID(item_id);
DCHECK(item);
item->tooltip_ = tooltip;
@@ -399,13 +405,13 @@ void MenuItemView::OnPaint(gfx::Canvas* canvas) {
PaintButton(canvas, PB_NORMAL);
}
-gfx::Size MenuItemView::GetPreferredSize() {
+gfx::Size MenuItemView::GetPreferredSize() const {
const MenuItemDimensions& dimensions(GetDimensions());
return gfx::Size(dimensions.standard_width + dimensions.children_width,
dimensions.height);
}
-const MenuItemView::MenuItemDimensions& MenuItemView::GetDimensions() {
+const MenuItemView::MenuItemDimensions& MenuItemView::GetDimensions() const {
if (!is_dimensions_valid())
dimensions_ = CalculateDimensions();
DCHECK(is_dimensions_valid());
@@ -441,16 +447,16 @@ const MenuItemView* MenuItemView::GetRootMenuItem() const {
return item;
}
-char16 MenuItemView::GetMnemonic() {
+base::char16 MenuItemView::GetMnemonic() {
if (!GetRootMenuItem()->has_mnemonics_)
return 0;
size_t index = 0;
do {
index = title_.find('&', index);
- if (index != string16::npos) {
+ if (index != base::string16::npos) {
if (index + 1 != title_.size() && title_[index + 1] != '&') {
- char16 char_array[] = { title_[index + 1], 0 };
+ base::char16 char_array[] = { title_[index + 1], 0 };
// TODO(jshin): What about Turkish locale? See http://crbug.com/81719.
// If the mnemonic is capital I and the UI language is Turkish,
// lowercasing it results in 'small dotless i', which is different
@@ -459,7 +465,7 @@ char16 MenuItemView::GetMnemonic() {
}
index++;
}
- } while (index != string16::npos);
+ } while (index != base::string16::npos);
return 0;
}
@@ -685,14 +691,14 @@ int MenuItemView::GetDrawStringFlags() {
return flags;
}
-const gfx::Font& MenuItemView::GetFont() {
+const gfx::FontList& MenuItemView::GetFontList() const {
const MenuDelegate* delegate = GetDelegate();
if (delegate) {
- const gfx::Font* font = delegate->GetLabelFont(GetCommand());
- if (font)
- return *font;
+ const gfx::FontList* font_list = delegate->GetLabelFontList(GetCommand());
+ if (font_list)
+ return *font_list;
}
- return GetMenuConfig().font;
+ return GetMenuConfig().font_list;
}
void MenuItemView::AddEmptyMenus() {
@@ -738,13 +744,6 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
(NonIconChildViewsCount() == 0));
- int icon_x = config.item_left_margin + left_icon_margin_;
- int top_margin = GetTopMargin();
- int bottom_margin = GetBottomMargin();
- int icon_y = top_margin + (height() - config.item_top_margin -
- bottom_margin - config.check_height) / 2;
- int icon_height = config.check_height;
- int available_height = height() - top_margin - bottom_margin;
MenuDelegate *delegate = GetDelegate();
// Render the background. As MenuScrollViewContainer draws the background, we
// only need the background when we want it to look different, as when we're
@@ -766,21 +765,27 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
ui::NativeTheme::ExtraParams());
}
+ const int icon_x = config.item_left_margin + left_icon_margin_;
+ const int top_margin = GetTopMargin();
+ const int bottom_margin = GetBottomMargin();
+ const int available_height = height() - top_margin - bottom_margin;
+
// Render the check.
if (type_ == CHECKBOX && delegate->IsItemChecked(GetCommand())) {
- gfx::ImageSkia check = GetMenuCheckImage(IsSelected());
+ gfx::ImageSkia check = GetMenuCheckImage(render_selection);
// Don't use config.check_width here as it's padded
// to force more padding (AURA).
- gfx::Rect check_bounds(icon_x, icon_y, check.width(), icon_height);
+ gfx::Rect check_bounds(icon_x,
+ top_margin + (available_height - check.height()) / 2,
+ check.width(),
+ check.height());
AdjustBoundsForRTLUI(&check_bounds);
canvas->DrawImageInt(check, check_bounds.x(), check_bounds.y());
} else if (type_ == RADIO) {
gfx::ImageSkia image =
GetRadioButtonImage(delegate->IsItemChecked(GetCommand()));
gfx::Rect radio_bounds(icon_x,
- top_margin +
- (height() - top_margin - bottom_margin -
- image.height()) / 2,
+ top_margin + (available_height - image.height()) / 2,
image.width(),
image.height());
AdjustBoundsForRTLUI(&radio_bounds);
@@ -788,12 +793,18 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
}
// Render the foreground.
- ui::NativeTheme::ColorId color_id =
- ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor;
+ ui::NativeTheme::ColorId color_id;
if (enabled()) {
color_id = render_selection ?
ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor:
ui::NativeTheme::kColorId_EnabledMenuItemForegroundColor;
+ } else {
+ bool emphasized = delegate &&
+ delegate->GetShouldUseDisabledEmphasizedForegroundColor(
+ GetCommand());
+ color_id = emphasized ?
+ ui::NativeTheme::kColorId_DisabledEmphasizedMenuItemForegroundColor :
+ ui::NativeTheme::kColorId_DisabledMenuItemForegroundColor;
}
SkColor fg_color = native_theme->GetSystemColor(color_id);
SkColor override_foreground_color;
@@ -802,7 +813,7 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
&override_foreground_color))
fg_color = override_foreground_color;
- const gfx::Font& font = GetFont();
+ const gfx::FontList& font_list = GetFontList();
int accel_width = parent_menu_item_->GetSubmenu()->max_minor_text_width();
int label_start = GetLabelStartForThisItem();
@@ -817,19 +828,15 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
int flags = GetDrawStringFlags();
if (mode == PB_FOR_DRAG)
flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
- canvas->DrawStringInt(title(), font, fg_color,
- text_bounds.x(), text_bounds.y(), text_bounds.width(),
- text_bounds.height(), flags);
+ canvas->DrawStringRectWithFlags(title(), font_list, fg_color, text_bounds,
+ flags);
if (!subtitle_.empty()) {
- canvas->DrawStringInt(
+ canvas->DrawStringRectWithFlags(
subtitle_,
- font,
+ font_list,
GetNativeTheme()->GetSystemColor(
ui::NativeTheme::kColorId_ButtonDisabledColor),
- text_bounds.x(),
- text_bounds.y() + GetFont().GetHeight(),
- text_bounds.width(),
- text_bounds.height(),
+ text_bounds + gfx::Vector2d(0, font_list.GetHeight()),
flags);
}
@@ -837,24 +844,23 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
// Render the submenu indicator (arrow).
if (HasSubmenu()) {
+ gfx::ImageSkia arrow = GetSubmenuArrowImage(render_selection);
gfx::Rect arrow_bounds(this->width() - config.arrow_width -
config.arrow_to_edge_padding,
- top_margin + (available_height -
- config.arrow_width) / 2,
- config.arrow_width, height());
+ top_margin + (available_height - arrow.height()) / 2,
+ config.arrow_width,
+ arrow.height());
AdjustBoundsForRTLUI(&arrow_bounds);
- canvas->DrawImageInt(GetSubmenuArrowImage(IsSelected()),
- arrow_bounds.x(), arrow_bounds.y());
+ canvas->DrawImageInt(arrow, arrow_bounds.x(), arrow_bounds.y());
}
}
void MenuItemView::PaintMinorText(gfx::Canvas* canvas,
bool render_selection) {
- string16 minor_text = GetMinorText();
+ base::string16 minor_text = GetMinorText();
if (minor_text.empty())
return;
- const gfx::Font& font = GetFont();
int available_height = height() - GetTopMargin() - GetBottomMargin();
int max_accel_width =
parent_menu_item_->GetSubmenu()->max_minor_text_width();
@@ -870,16 +876,13 @@ void MenuItemView::PaintMinorText(gfx::Canvas* canvas,
flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
else
flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
- canvas->DrawStringInt(
+ canvas->DrawStringRectWithFlags(
minor_text,
- font,
+ GetFontList(),
GetNativeTheme()->GetSystemColor(render_selection ?
ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor :
ui::NativeTheme::kColorId_ButtonDisabledColor),
- accel_bounds.x(),
- accel_bounds.y(),
- accel_bounds.width(),
- accel_bounds.height(),
+ accel_bounds,
flags);
}
@@ -894,38 +897,36 @@ void MenuItemView::DestroyAllMenuHosts() {
}
}
-int MenuItemView::GetTopMargin() {
+int MenuItemView::GetTopMargin() const {
if (top_margin_ >= 0)
return top_margin_;
- MenuItemView* root = GetRootMenuItem();
+ const MenuItemView* root = GetRootMenuItem();
return root && root->has_icons_
? GetMenuConfig().item_top_margin :
GetMenuConfig().item_no_icon_top_margin;
}
-int MenuItemView::GetBottomMargin() {
+int MenuItemView::GetBottomMargin() const {
if (bottom_margin_ >= 0)
return bottom_margin_;
- MenuItemView* root = GetRootMenuItem();
+ const MenuItemView* root = GetRootMenuItem();
return root && root->has_icons_
? GetMenuConfig().item_bottom_margin :
GetMenuConfig().item_no_icon_bottom_margin;
}
-gfx::Size MenuItemView::GetChildPreferredSize() {
+gfx::Size MenuItemView::GetChildPreferredSize() const {
if (!has_children())
return gfx::Size();
- if (IsContainer()) {
- View* child = child_at(0);
- return child->GetPreferredSize();
- }
+ if (IsContainer())
+ return child_at(0)->GetPreferredSize();
int width = 0;
for (int i = 0; i < child_count(); ++i) {
- View* child = child_at(i);
+ const View* child = child_at(i);
if (icon_view_ && (icon_view_ == child))
continue;
if (i)
@@ -941,7 +942,7 @@ gfx::Size MenuItemView::GetChildPreferredSize() {
return gfx::Size(width, height);
}
-MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() {
+MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() const {
gfx::Size child_size = GetChildPreferredSize();
MenuItemDimensions dimensions;
@@ -961,7 +962,7 @@ MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() {
return dimensions;
// Determine the length of the label text.
- const gfx::Font& font = GetFont();
+ const gfx::FontList& font_list = GetFontList();
// Get Icon margin overrides for this particular item.
const MenuDelegate* delegate = GetDelegate();
@@ -976,27 +977,30 @@ MenuItemView::MenuItemDimensions MenuItemView::CalculateDimensions() {
}
int label_start = GetLabelStartForThisItem();
- int string_width = font.GetStringWidth(title_);
- if (!subtitle_.empty())
- string_width = std::max(string_width, font.GetStringWidth(subtitle_));
+ int string_width = gfx::GetStringWidth(title_, font_list);
+ if (!subtitle_.empty()) {
+ string_width = std::max(string_width,
+ gfx::GetStringWidth(subtitle_, font_list));
+ }
dimensions.standard_width = string_width + label_start +
item_right_margin_;
// Determine the length of the right-side text.
- string16 minor_text = GetMinorText();
+ base::string16 minor_text = GetMinorText();
dimensions.minor_text_width =
- minor_text.empty() ? 0 : GetFont().GetStringWidth(minor_text);
+ minor_text.empty() ? 0 : gfx::GetStringWidth(minor_text, font_list);
// Determine the height to use.
+ dimensions.height =
+ std::max(dimensions.height,
+ (subtitle_.empty() ? 0 : font_list.GetHeight()) +
+ font_list.GetHeight() + GetBottomMargin() + GetTopMargin());
dimensions.height = std::max(dimensions.height,
- (subtitle_.empty() ? 0 : font.GetHeight()) +
- font.GetHeight() + GetBottomMargin() + GetTopMargin());
- dimensions.height = std::max(dimensions.height,
- GetMenuConfig().item_min_height);
+ GetMenuConfig().item_min_height);
return dimensions;
}
-int MenuItemView::GetLabelStartForThisItem() {
+int MenuItemView::GetLabelStartForThisItem() const {
int label_start = label_start_ + left_icon_margin_ + right_icon_margin_;
if ((type_ == CHECKBOX || type_ == RADIO) && icon_view_) {
label_start += icon_view_->size().width() +
@@ -1005,10 +1009,10 @@ int MenuItemView::GetLabelStartForThisItem() {
return label_start;
}
-string16 MenuItemView::GetMinorText() {
+base::string16 MenuItemView::GetMinorText() const {
if (id() == kEmptyMenuItemViewID) {
// Don't query the delegate for menus that represent no children.
- return string16();
+ return base::string16();
}
ui::Accelerator accelerator;
diff --git a/chromium/ui/views/controls/menu/menu_item_view.h b/chromium/ui/views/controls/menu/menu_item_view.h
index 2d394bae2f2..4f0ea441caa 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.h
+++ b/chromium/ui/views/controls/menu/menu_item_view.h
@@ -15,6 +15,7 @@
#include "ui/base/models/menu_separator_types.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/menu/menu_config.h"
+#include "ui/views/controls/menu/menu_types.h"
#include "ui/views/view.h"
#if defined(OS_WIN)
@@ -24,7 +25,7 @@
#endif
namespace gfx {
-class Font;
+class FontList;
}
namespace views {
@@ -83,21 +84,6 @@ class VIEWS_EXPORT MenuItemView : public View {
EMPTY
};
- // Where the menu should be anchored to for non-RTL languages. The
- // opposite position will be used if base::i18n:IsRTL() is true.
- // The BUBBLE flags are used when the menu should get enclosed by a bubble.
- // Note that BUBBLE flags should only be used with menus which have no
- // children.
- enum AnchorPosition {
- TOPLEFT,
- TOPRIGHT,
- BOTTOMCENTER,
- BUBBLE_LEFT,
- BUBBLE_RIGHT,
- BUBBLE_ABOVE,
- BUBBLE_BELOW
- };
-
// Where the menu should be drawn, above or below the bounds (when
// the bounds is non-empty). POSITION_BEST_FIT (default) positions
// the menu below the bounds unless the menu does not fit on the
@@ -132,8 +118,8 @@ class VIEWS_EXPORT MenuItemView : public View {
// Overridden from View:
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// Returns the preferred height of menu items. This is only valid when the
// menu is about to be shown.
@@ -143,12 +129,12 @@ class VIEWS_EXPORT MenuItemView : public View {
static int label_start() { return label_start_; }
// Returns if a given |anchor| is a bubble or not.
- static bool IsBubble(MenuItemView::AnchorPosition anchor);
+ static bool IsBubble(MenuAnchorPosition anchor);
// Returns the accessible name to be used with screen readers. Mnemonics are
// removed and the menu item accelerator text is appended.
- static string16 GetAccessibleNameForMenuItem(
- const string16& item_text, const string16& accelerator_text);
+ static base::string16 GetAccessibleNameForMenuItem(
+ const base::string16& item_text, const base::string16& accelerator_text);
// Hides and cancels the menu. This does nothing if the menu is not open.
void Cancel();
@@ -157,9 +143,9 @@ class VIEWS_EXPORT MenuItemView : public View {
// called after adding menu items if the menu may be active.
MenuItemView* AddMenuItemAt(int index,
int item_id,
- const string16& label,
- const string16& sublabel,
- const string16& minor_text,
+ const base::string16& label,
+ const base::string16& sublabel,
+ const base::string16& minor_text,
const gfx::ImageSkia& icon,
Type type,
ui::MenuSeparatorType separator_style);
@@ -177,24 +163,24 @@ class VIEWS_EXPORT MenuItemView : public View {
// label The text label shown.
// type The type of item.
MenuItemView* AppendMenuItem(int item_id,
- const string16& label,
+ const base::string16& label,
Type type);
// Append a submenu to this menu.
// The returned pointer is owned by this menu.
MenuItemView* AppendSubMenu(int item_id,
- const string16& label);
+ const base::string16& label);
// Append a submenu with an icon to this menu.
// The returned pointer is owned by this menu.
MenuItemView* AppendSubMenuWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon);
// This is a convenience for standard text label menu items where the label
// is provided with this call.
MenuItemView* AppendMenuItemWithLabel(int item_id,
- const string16& label);
+ const base::string16& label);
// This is a convenience for text label menu items where the label is
// provided by the delegate.
@@ -207,14 +193,14 @@ class VIEWS_EXPORT MenuItemView : public View {
// needs an icon. Calling this function forces the Menu class to draw
// the menu, instead of relying on Windows.
MenuItemView* AppendMenuItemWithIcon(int item_id,
- const string16& label,
+ const base::string16& label,
const gfx::ImageSkia& icon);
// All the AppendXXX methods funnel into this.
MenuItemView* AppendMenuItemImpl(int item_id,
- const string16& label,
- const string16& sublabel,
- const string16& minor_text,
+ const base::string16& label,
+ const base::string16& sublabel,
+ const base::string16& minor_text,
const gfx::ImageSkia& icon,
Type type,
ui::MenuSeparatorType separator_style);
@@ -234,14 +220,14 @@ class VIEWS_EXPORT MenuItemView : public View {
const MenuItemView* GetParentMenuItem() const { return parent_menu_item_; }
// Sets/Gets the title.
- void SetTitle(const string16& title);
- const string16& title() const { return title_; }
+ void SetTitle(const base::string16& title);
+ const base::string16& title() const { return title_; }
// Sets the subtitle.
- void SetSubtitle(const string16& subtitle);
+ void SetSubtitle(const base::string16& subtitle);
// Sets the minor text.
- void SetMinorText(const string16& minor_text);
+ void SetMinorText(const base::string16& minor_text);
// Returns the type of this menu.
const Type& GetType() const { return type_; }
@@ -254,7 +240,7 @@ class VIEWS_EXPORT MenuItemView : public View {
bool IsSelected() const { return selected_; }
// Sets the |tooltip| for a menu item view with |item_id| identifier.
- void SetTooltip(const string16& tooltip, int item_id);
+ void SetTooltip(const base::string16& tooltip, int item_id);
// Sets the icon for the descendant identified by item_id.
void SetIcon(const gfx::ImageSkia& icon, int item_id);
@@ -277,10 +263,10 @@ class VIEWS_EXPORT MenuItemView : public View {
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
// Returns the preferred size of this item.
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
// Return the preferred dimensions of the item in pixel.
- const MenuItemDimensions& GetDimensions();
+ const MenuItemDimensions& GetDimensions() const;
// Returns the object responsible for controlling showing the menu.
MenuController* GetMenuController();
@@ -297,7 +283,7 @@ class VIEWS_EXPORT MenuItemView : public View {
// Returns the mnemonic for this MenuItemView, or 0 if this MenuItemView
// doesn't have a mnemonic.
- char16 GetMnemonic();
+ base::char16 GetMnemonic();
// Do we have icons? This only has effect on the top menu. Turning this on
// makes the menus slightly wider and taller.
@@ -344,11 +330,11 @@ class VIEWS_EXPORT MenuItemView : public View {
virtual const char* GetClassName() const OVERRIDE;
// Returns the preferred size (and padding) of any children.
- virtual gfx::Size GetChildPreferredSize();
+ virtual gfx::Size GetChildPreferredSize() const;
// Returns the various margins.
- int GetTopMargin();
- int GetBottomMargin();
+ int GetTopMargin() const;
+ int GetBottomMargin() const;
private:
friend class internal::MenuRunnerImpl; // For access to ~MenuItemView.
@@ -372,11 +358,11 @@ class VIEWS_EXPORT MenuItemView : public View {
bool has_mnemonics,
bool show_mnemonics);
- // Returns the flags passed to DrawStringInt.
+ // Returns the flags passed to DrawStringRect.
int GetDrawStringFlags();
- // Returns the font to use for menu text.
- const gfx::Font& GetFont();
+ // Returns the font list to use for menu text.
+ const gfx::FontList& GetFontList() const;
// If this menu item has no children a child is added showing it has no
// children. Otherwise AddEmtpyMenus is recursively invoked on child menu
@@ -403,13 +389,13 @@ class VIEWS_EXPORT MenuItemView : public View {
// Returns the text that should be displayed on the end (right) of the menu
// item. This will be the accelerator (if one exists), otherwise |subtitle_|.
- string16 GetMinorText();
+ base::string16 GetMinorText() const;
// Calculates and returns the MenuItemDimensions.
- MenuItemDimensions CalculateDimensions();
+ MenuItemDimensions CalculateDimensions() const;
// Get the horizontal position at which to draw the menu item's label.
- int GetLabelStartForThisItem();
+ int GetLabelStartForThisItem() const;
// Used by MenuController to cache the menu position in use by the
// active menu.
@@ -464,13 +450,13 @@ class VIEWS_EXPORT MenuItemView : public View {
SubmenuView* submenu_;
// Title.
- string16 title_;
+ base::string16 title_;
// Subtitle/sublabel.
- string16 subtitle_;
+ base::string16 subtitle_;
// Minor text.
- string16 minor_text_;
+ base::string16 minor_text_;
// Does the title have a mnemonic? Only useful on the root menu item.
bool has_mnemonics_;
@@ -486,7 +472,7 @@ class VIEWS_EXPORT MenuItemView : public View {
View* icon_view_;
// The tooltip to show on hover for this menu item.
- string16 tooltip_;
+ base::string16 tooltip_;
// Width of a menu icon area.
static int icon_area_width_;
@@ -502,7 +488,7 @@ class VIEWS_EXPORT MenuItemView : public View {
// Cached dimensions. This is cached as text sizing calculations are quite
// costly.
- MenuItemDimensions dimensions_;
+ mutable MenuItemDimensions dimensions_;
// Removed items to be deleted in ChildrenChanged().
std::vector<View*> removed_items_;
@@ -513,8 +499,8 @@ class VIEWS_EXPORT MenuItemView : public View {
// Horizontal icon margins in pixels, which can differ between MenuItems.
// These values will be set in the layout process.
- int left_icon_margin_;
- int right_icon_margin_;
+ mutable int left_icon_margin_;
+ mutable int right_icon_margin_;
// |menu_position_| is the requested position with respect to the bounds.
// |actual_menu_position_| is used by the controller to cache the
diff --git a/chromium/ui/views/controls/menu/menu_message_loop.h b/chromium/ui/views/controls/menu/menu_message_loop.h
new file mode 100644
index 00000000000..a435d85f402
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_loop.h
@@ -0,0 +1,57 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_H_
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace ui {
+class LocatedEvent;
+}
+
+namespace views {
+
+class MenuController;
+class Widget;
+
+// Interface used by MenuController to run a nested message loop while
+// showing a menu, allowing for platform specific implementations.
+class MenuMessageLoop {
+ public:
+ virtual ~MenuMessageLoop() {}
+
+ // Create a platform specific instance.
+ static MenuMessageLoop* Create();
+
+ // Runs the platform specific bits of the message loop. If |nested_menu| is
+ // true we're being asked to run a menu from within a menu (eg a context
+ // menu).
+ virtual void Run(MenuController*, Widget* owner, bool nested_menu) = 0;
+
+ // Returns true if it is a good time to call QuitNow().
+ // Returns false otherwise, for example if a drag and drop is in progress.
+ virtual bool ShouldQuitNow() const = 0;
+
+ // Quit an earlier call to Run().
+ virtual void QuitNow() = 0;
+
+ // Repost |event| to |window|.
+ // |screen_loc| is the event's location in screen coordinates.
+ virtual void RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) = 0;
+
+ // Clear any references to the owner widget that was passed into the previous
+ // call to Run().
+ virtual void ClearOwner() = 0;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_H_
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_aura.cc b/chromium/ui/views/controls/menu/menu_message_loop_aura.cc
new file mode 100644
index 00000000000..0d7e99aab03
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_loop_aura.cc
@@ -0,0 +1,202 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_loop_aura.h"
+
+#if defined(OS_WIN)
+#include <windowsx.h>
+#endif
+
+#include "base/run_loop.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/event.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/scoped_event_dispatcher.h"
+#include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/dispatcher_client.h"
+#include "ui/wm/public/drag_drop_client.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/internal_constants.h"
+#include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h"
+#include "ui/views/win/hwnd_util.h"
+#else
+#include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
+#endif
+
+using aura::client::ScreenPositionClient;
+
+namespace views {
+
+namespace {
+
+aura::Window* GetOwnerRootWindow(views::Widget* owner) {
+ return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
+}
+
+// ActivationChangeObserverImpl is used to observe activation changes and close
+// the menu. Additionally it listens for the root window to be destroyed and
+// cancel the menu as well.
+class ActivationChangeObserverImpl
+ : public aura::client::ActivationChangeObserver,
+ public aura::WindowObserver,
+ public ui::EventHandler {
+ public:
+ ActivationChangeObserverImpl(MenuController* controller, aura::Window* root)
+ : controller_(controller), root_(root) {
+ aura::client::GetActivationClient(root_)->AddObserver(this);
+ root_->AddObserver(this);
+ root_->AddPreTargetHandler(this);
+ }
+
+ virtual ~ActivationChangeObserverImpl() { Cleanup(); }
+
+ // aura::client::ActivationChangeObserver:
+ virtual void OnWindowActivated(aura::Window* gained_active,
+ aura::Window* lost_active) OVERRIDE {
+ if (!controller_->drag_in_progress())
+ controller_->CancelAll();
+ }
+
+ // aura::WindowObserver:
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { Cleanup(); }
+
+ // ui::EventHandler:
+ virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
+ controller_->CancelAll();
+ }
+
+ private:
+ void Cleanup() {
+ if (!root_)
+ return;
+ // The ActivationClient may have been destroyed by the time we get here.
+ aura::client::ActivationClient* client =
+ aura::client::GetActivationClient(root_);
+ if (client)
+ client->RemoveObserver(this);
+ root_->RemovePreTargetHandler(this);
+ root_->RemoveObserver(this);
+ root_ = NULL;
+ }
+
+ MenuController* controller_;
+ aura::Window* root_;
+
+ DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
+};
+
+} // namespace
+
+// static
+MenuMessageLoop* MenuMessageLoop::Create() {
+ return new MenuMessageLoopAura;
+}
+
+MenuMessageLoopAura::MenuMessageLoopAura() : owner_(NULL) {
+}
+
+MenuMessageLoopAura::~MenuMessageLoopAura() {
+}
+
+void MenuMessageLoopAura::RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) {
+ aura::Window* root = window->GetRootWindow();
+ ScreenPositionClient* spc = aura::client::GetScreenPositionClient(root);
+ if (!spc)
+ return;
+
+ gfx::Point root_loc(screen_loc);
+ spc->ConvertPointFromScreen(root, &root_loc);
+
+ ui::MouseEvent clone(static_cast<const ui::MouseEvent&>(event));
+ clone.set_location(root_loc);
+ clone.set_root_location(root_loc);
+ root->GetHost()->dispatcher()->RepostEvent(clone);
+}
+
+void MenuMessageLoopAura::Run(MenuController* controller,
+ Widget* owner,
+ bool nested_menu) {
+ // |owner_| may be NULL.
+ owner_ = owner;
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ // It is possible for the same MenuMessageLoopAura to start a nested
+ // message-loop while it is already running a nested loop. So make sure the
+ // quit-closure gets reset to the outer loop's quit-closure once the innermost
+ // loop terminates.
+ base::AutoReset<base::Closure> reset_quit_closure(&message_loop_quit_,
+ base::Closure());
+
+#if defined(OS_WIN)
+ internal::MenuMessagePumpDispatcher nested_dispatcher(controller);
+ if (root) {
+ scoped_ptr<ActivationChangeObserverImpl> observer;
+ if (!nested_menu)
+ observer.reset(new ActivationChangeObserverImpl(controller, root));
+ aura::client::DispatcherRunLoop run_loop(
+ aura::client::GetDispatcherClient(root), &nested_dispatcher);
+ message_loop_quit_ = run_loop.QuitClosure();
+ run_loop.Run();
+ } else {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop(&nested_dispatcher);
+ message_loop_quit_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+#else
+ internal::MenuEventDispatcher event_dispatcher(controller);
+ scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
+ nested_dispatcher_.Pass();
+ if (ui::PlatformEventSource::GetInstance()) {
+ nested_dispatcher_ =
+ ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
+ &event_dispatcher);
+ }
+ if (root) {
+ scoped_ptr<ActivationChangeObserverImpl> observer;
+ if (!nested_menu)
+ observer.reset(new ActivationChangeObserverImpl(controller, root));
+ aura::client::DispatcherRunLoop run_loop(
+ aura::client::GetDispatcherClient(root), NULL);
+ message_loop_quit_ = run_loop.QuitClosure();
+ run_loop.Run();
+ } else {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop;
+ message_loop_quit_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ nested_dispatcher_ = old_dispatcher.Pass();
+#endif
+}
+
+bool MenuMessageLoopAura::ShouldQuitNow() const {
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ return !aura::client::GetDragDropClient(root) ||
+ !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
+}
+
+void MenuMessageLoopAura::QuitNow() {
+ CHECK(!message_loop_quit_.is_null());
+ message_loop_quit_.Run();
+ // Restore the previous dispatcher.
+ nested_dispatcher_.reset();
+}
+
+void MenuMessageLoopAura::ClearOwner() {
+ owner_ = NULL;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_aura.h b/chromium/ui/views/controls/menu/menu_message_loop_aura.h
new file mode 100644
index 00000000000..49e8a392827
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_loop_aura.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_AURA_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_AURA_H_
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/views/controls/menu/menu_message_loop.h"
+
+namespace base {
+class MessagePumpDispatcher;
+}
+
+namespace ui {
+class ScopedEventDispatcher;
+}
+
+namespace views {
+
+class MenuMessageLoopAura : public MenuMessageLoop {
+ public:
+ MenuMessageLoopAura();
+ virtual ~MenuMessageLoopAura();
+
+ // Overridden from MenuMessageLoop:
+ virtual void Run(MenuController* controller,
+ Widget* owner,
+ bool nested_menu) OVERRIDE;
+ virtual bool ShouldQuitNow() const OVERRIDE;
+ virtual void QuitNow() OVERRIDE;
+ virtual void RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) OVERRIDE;
+ virtual void ClearOwner() OVERRIDE;
+
+ private:
+ // Owner of child windows.
+ // WARNING: this may be NULL.
+ Widget* owner_;
+
+ scoped_ptr<ui::ScopedEventDispatcher> nested_dispatcher_;
+ base::Closure message_loop_quit_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuMessageLoopAura);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_AURA_H_
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_mac.cc b/chromium/ui/views/controls/menu/menu_message_loop_mac.cc
new file mode 100644
index 00000000000..b1c10cca7d8
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_loop_mac.cc
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_loop_mac.h"
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace views {
+
+// static
+MenuMessageLoop* MenuMessageLoop::Create() {
+ return new MenuMessageLoopMac;
+}
+
+MenuMessageLoopMac::MenuMessageLoopMac() {
+}
+
+MenuMessageLoopMac::~MenuMessageLoopMac() {
+}
+
+void MenuMessageLoopMac::RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) {
+ NOTIMPLEMENTED();
+}
+
+void MenuMessageLoopMac::Run(MenuController* controller,
+ Widget* owner,
+ bool nested_menu) {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop;
+ run_loop.Run();
+}
+
+bool MenuMessageLoopMac::ShouldQuitNow() const {
+ return true;
+}
+
+void MenuMessageLoopMac::QuitNow() {
+ base::MessageLoop::current()->QuitNow();
+}
+
+void MenuMessageLoopMac::ClearOwner() {
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_mac.h b/chromium/ui/views/controls/menu/menu_message_loop_mac.h
new file mode 100644
index 00000000000..b77d263ffbb
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_loop_mac.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_MAC_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_MAC_H_
+
+#include "base/compiler_specific.h"
+#include "ui/views/controls/menu/menu_message_loop.h"
+
+namespace views {
+
+class MenuMessageLoopMac : public MenuMessageLoop {
+ public:
+ MenuMessageLoopMac();
+ virtual ~MenuMessageLoopMac();
+
+ // Overridden from MenuMessageLoop:
+ virtual void Run(MenuController* controller,
+ Widget* owner,
+ bool nested_menu) OVERRIDE;
+ virtual bool ShouldQuitNow() const OVERRIDE;
+ virtual void QuitNow() OVERRIDE;
+ virtual void RepostEventToWindow(const ui::LocatedEvent& event,
+ gfx::NativeWindow window,
+ const gfx::Point& screen_loc) OVERRIDE;
+ virtual void ClearOwner() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MenuMessageLoopMac);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_LOOP_MAC_H_
diff --git a/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc b/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc
new file mode 100644
index 00000000000..8f905d029ae
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h"
+
+#include <windowsx.h>
+
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+
+namespace views {
+namespace internal {
+
+MenuMessagePumpDispatcher::MenuMessagePumpDispatcher(MenuController* controller)
+ : menu_controller_(controller) {}
+
+MenuMessagePumpDispatcher::~MenuMessagePumpDispatcher() {}
+
+uint32_t MenuMessagePumpDispatcher::Dispatch(const MSG& msg) {
+ DCHECK(menu_controller_->IsBlockingRun());
+
+ bool should_quit = false;
+ bool should_perform_default = true;
+ if (menu_controller_->exit_type() == MenuController::EXIT_ALL ||
+ menu_controller_->exit_type() == MenuController::EXIT_DESTROYED) {
+ should_quit = true;
+ } else {
+ // NOTE: we don't get WM_ACTIVATE or anything else interesting in here.
+ switch (msg.message) {
+ case WM_CONTEXTMENU: {
+ MenuItemView* item = menu_controller_->pending_state_.item;
+ if (item && item->GetRootMenuItem() != item) {
+ gfx::Point screen_loc(0, item->height());
+ View::ConvertPointToScreen(item, &screen_loc);
+ ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE;
+ if (GET_X_LPARAM(msg.lParam) == -1 && GET_Y_LPARAM(msg.lParam) == -1)
+ source_type = ui::MENU_SOURCE_KEYBOARD;
+ item->GetDelegate()->ShowContextMenu(
+ item, item->GetCommand(), screen_loc, source_type);
+ }
+ should_quit = false;
+ should_perform_default = false;
+ break;
+ }
+
+ // NOTE: focus wasn't changed when the menu was shown. As such, don't
+ // dispatch key events otherwise the focused window will get the events.
+ case WM_KEYDOWN: {
+ bool result =
+ menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(msg));
+ TranslateMessage(&msg);
+ should_perform_default = false;
+ should_quit = !result;
+ break;
+ }
+ case WM_CHAR: {
+ should_quit = menu_controller_->SelectByChar(
+ static_cast<base::char16>(msg.wParam));
+ should_perform_default = false;
+ break;
+ }
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ // We may have been shown on a system key, as such don't do anything
+ // here. If another system key is pushed we'll get a WM_SYSKEYDOWN and
+ // close the menu.
+ should_quit = false;
+ should_perform_default = false;
+ break;
+
+ case WM_CANCELMODE:
+ case WM_SYSKEYDOWN:
+ // Exit immediately on system keys.
+ menu_controller_->Cancel(MenuController::EXIT_ALL);
+ should_quit = true;
+ should_perform_default = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (should_quit || menu_controller_->exit_type() != MenuController::EXIT_NONE)
+ menu_controller_->TerminateNestedMessageLoop();
+ return should_perform_default ? POST_DISPATCH_PERFORM_DEFAULT
+ : POST_DISPATCH_NONE;
+}
+
+} // namespace internal
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h b/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h
new file mode 100644
index 00000000000..31f1b369610
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_WIN_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_WIN_H_
+
+#include "base/macros.h"
+#include "base/message_loop/message_pump_dispatcher.h"
+
+namespace views {
+
+class MenuController;
+
+namespace internal {
+
+// A message-pump dispatcher object used to dispatch events from the nested
+// message-loop initiated by the MenuController.
+class MenuMessagePumpDispatcher : public base::MessagePumpDispatcher {
+ public:
+ explicit MenuMessagePumpDispatcher(MenuController* menu_controller);
+ virtual ~MenuMessagePumpDispatcher();
+
+ private:
+ // base::MessagePumpDispatcher:
+ virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
+
+ MenuController* menu_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuMessagePumpDispatcher);
+};
+
+} // namespace internal
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_WIN_H_
diff --git a/chromium/ui/views/controls/menu/menu_model_adapter.cc b/chromium/ui/views/controls/menu/menu_model_adapter.cc
index 07f1f403fd8..55c5d7d21d9 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter.cc
+++ b/chromium/ui/views/controls/menu/menu_model_adapter.cc
@@ -8,6 +8,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/gfx/image/image.h"
+#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/views_delegate.h"
@@ -59,7 +60,7 @@ MenuItemView* MenuModelAdapter::AddMenuItemFromModelAt(ui::MenuModel* model,
int item_id) {
gfx::Image icon;
model->GetIconAt(model_index, &icon);
- string16 label, sublabel, minor_text;
+ base::string16 label, sublabel, minor_text;
ui::MenuSeparatorType separator_style = ui::NORMAL_SEPARATOR;
MenuItemView::Type type;
ui::MenuModel::ItemType menu_type = model->GetTypeAt(model_index);
@@ -161,7 +162,7 @@ bool MenuModelAdapter::IsTriggerableEvent(MenuItemView* source,
}
bool MenuModelAdapter::GetAccelerator(int id,
- ui::Accelerator* accelerator) {
+ ui::Accelerator* accelerator) const {
ui::MenuModel* model = menu_model_;
int index = 0;
if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
@@ -171,27 +172,27 @@ bool MenuModelAdapter::GetAccelerator(int id,
return false;
}
-string16 MenuModelAdapter::GetLabel(int id) const {
+base::string16 MenuModelAdapter::GetLabel(int id) const {
ui::MenuModel* model = menu_model_;
int index = 0;
if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
return model->GetLabelAt(index);
NOTREACHED();
- return string16();
+ return base::string16();
}
-const gfx::Font* MenuModelAdapter::GetLabelFont(int id) const {
+const gfx::FontList* MenuModelAdapter::GetLabelFontList(int id) const {
ui::MenuModel* model = menu_model_;
int index = 0;
if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) {
- const gfx::Font* font = model->GetLabelFontAt(index);
- if (font)
- return font;
+ const gfx::FontList* font_list = model->GetLabelFontListAt(index);
+ if (font_list)
+ return font_list;
}
// This line may be reached for the empty menu item.
- return MenuDelegate::GetLabelFont(id);
+ return MenuDelegate::GetLabelFontList(id);
}
bool MenuModelAdapter::IsCommandEnabled(int id) const {
@@ -204,6 +205,16 @@ bool MenuModelAdapter::IsCommandEnabled(int id) const {
return false;
}
+bool MenuModelAdapter::IsCommandVisible(int id) const {
+ ui::MenuModel* model = menu_model_;
+ int index = 0;
+ if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
+ return model->IsVisibleAt(index);
+
+ NOTREACHED();
+ return false;
+}
+
bool MenuModelAdapter::IsItemChecked(int id) const {
ui::MenuModel* model = menu_model_;
int index = 0;
@@ -264,9 +275,6 @@ void MenuModelAdapter::BuildMenuImpl(MenuItemView* menu, ui::MenuModel* model) {
for (int i = 0; i < item_count; ++i) {
MenuItemView* item = AppendMenuItem(menu, model, i);
- if (item)
- item->SetVisible(model->IsVisibleAt(i));
-
if (model->GetTypeAt(i) == ui::MenuModel::TYPE_SUBMENU) {
DCHECK(item);
DCHECK_EQ(MenuItemView::SUBMENU, item->GetType());
diff --git a/chromium/ui/views/controls/menu/menu_model_adapter.h b/chromium/ui/views/controls/menu/menu_model_adapter.h
index 4db9dbe2cf9..353d010c533 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter.h
+++ b/chromium/ui/views/controls/menu/menu_model_adapter.h
@@ -67,10 +67,11 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate {
virtual bool IsTriggerableEvent(MenuItemView* source,
const ui::Event& e) OVERRIDE;
virtual bool GetAccelerator(int id,
- ui::Accelerator* accelerator) OVERRIDE;
- virtual string16 GetLabel(int id) const OVERRIDE;
- virtual const gfx::Font* GetLabelFont(int id) const OVERRIDE;
+ ui::Accelerator* accelerator) const OVERRIDE;
+ virtual base::string16 GetLabel(int id) const OVERRIDE;
+ virtual const gfx::FontList* GetLabelFontList(int id) const OVERRIDE;
virtual bool IsCommandEnabled(int id) const OVERRIDE;
+ virtual bool IsCommandVisible(int id) const OVERRIDE;
virtual bool IsItemChecked(int id) const OVERRIDE;
virtual void SelectionChanged(MenuItemView* menu) OVERRIDE;
virtual void WillShowMenu(MenuItemView* menu) OVERRIDE;
diff --git a/chromium/ui/views/controls/menu/menu_model_adapter_unittest.cc b/chromium/ui/views/controls/menu/menu_model_adapter_unittest.cc
index 6ce3a376270..cba4d2fa7fb 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_model_adapter_unittest.cc
@@ -2,12 +2,13 @@
// 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_model_adapter.h"
+
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/models/menu_model_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/test/views_test_base.h"
@@ -51,7 +52,7 @@ class MenuModelBase : public ui::MenuModel {
return index + command_id_base_;
}
- virtual string16 GetLabelAt(int index) const OVERRIDE {
+ virtual base::string16 GetLabelAt(int index) const OVERRIDE {
return items_[index].label;
}
@@ -59,7 +60,7 @@ class MenuModelBase : public ui::MenuModel {
return false;
}
- virtual const gfx::Font* GetLabelFontAt(int index) const OVERRIDE {
+ virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE {
return NULL;
}
@@ -128,12 +129,12 @@ class MenuModelBase : public ui::MenuModel {
const std::string& item_label,
ui::MenuModel* item_submenu)
: type(item_type),
- label(ASCIIToUTF16(item_label)),
+ label(base::ASCIIToUTF16(item_label)),
submenu(item_submenu) {
}
ItemType type;
- string16 label;
+ base::string16 label;
ui::MenuModel* submenu;
};
diff --git a/chromium/ui/views/controls/menu/menu_runner.cc b/chromium/ui/views/controls/menu/menu_runner.cc
index e254dbffc55..ca36d026433 100644
--- a/chromium/ui/views/controls/menu/menu_runner.cc
+++ b/chromium/ui/views/controls/menu/menu_runner.cc
@@ -12,6 +12,7 @@
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_controller_delegate.h"
#include "ui/views/controls/menu/menu_delegate.h"
+#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner_handler.h"
#include "ui/views/widget/widget.h"
@@ -43,7 +44,7 @@ class MenuRunnerImpl : public internal::MenuControllerDelegate {
MenuRunner::RunResult RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
+ MenuAnchorPosition anchor,
int32 types) WARN_UNUSED_RESULT;
void Cancel();
@@ -140,12 +141,11 @@ void MenuRunnerImpl::Release() {
}
}
-MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(
- Widget* parent,
- MenuButton* button,
- const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
- int32 types) {
+MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(Widget* parent,
+ MenuButton* button,
+ const gfx::Rect& bounds,
+ MenuAnchorPosition anchor,
+ int32 types) {
closing_event_time_ = base::TimeDelta();
if (running_) {
// Ignore requests to show the menu while it's already showing. MenuItemView
@@ -186,7 +186,7 @@ MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(
controller = new MenuController(theme, !for_drop_, this);
owns_controller_ = true;
}
- controller->set_accept_on_f4((types & MenuRunner::COMBOBOX) != 0);
+ controller->set_is_combobox((types & MenuRunner::COMBOBOX) != 0);
controller_ = controller;
menu_->set_controller(controller_);
menu_->PrepareForRun(owns_controller_,
@@ -278,16 +278,6 @@ bool MenuRunnerImpl::ShouldShowMnemonics(MenuButton* button) {
return show_mnemonics;
}
-// In theory we could implement this every where, but for now we're only
-// implementing it on aura.
-#if !defined(USE_AURA)
-// static
-DisplayChangeListener* DisplayChangeListener::Create(Widget* widget,
- MenuRunner* runner) {
- return NULL;
-}
-#endif
-
} // namespace internal
MenuRunner::MenuRunner(ui::MenuModel* menu_model)
@@ -310,7 +300,7 @@ MenuItemView* MenuRunner::GetMenu() {
MenuRunner::RunResult MenuRunner::RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
+ MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
int32 types) {
if (runner_handler_.get()) {
@@ -331,11 +321,11 @@ MenuRunner::RunResult MenuRunner::RunMenuAt(Widget* parent,
case ui::MENU_SOURCE_NONE:
case ui::MENU_SOURCE_KEYBOARD:
case ui::MENU_SOURCE_MOUSE:
- anchor = MenuItemView::TOPLEFT;
+ anchor = MENU_ANCHOR_TOPLEFT;
break;
case ui::MENU_SOURCE_TOUCH:
case ui::MENU_SOURCE_TOUCH_EDIT_MENU:
- anchor = MenuItemView::BOTTOMCENTER;
+ anchor = MENU_ANCHOR_BOTTOMCENTER;
break;
default:
break;
diff --git a/chromium/ui/views/controls/menu/menu_runner.h b/chromium/ui/views/controls/menu/menu_runner.h
index 6b46362f18e..824afdf8d4b 100644
--- a/chromium/ui/views/controls/menu/menu_runner.h
+++ b/chromium/ui/views/controls/menu/menu_runner.h
@@ -8,7 +8,17 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/base/ui_base_types.h"
+#include "ui/views/controls/menu/menu_types.h"
+#include "ui/views/views_export.h"
+
+namespace base {
+class TimeDelta;
+}
+
+namespace gfx {
+class Rect;
+}
namespace ui {
class MenuModel;
@@ -17,6 +27,7 @@ class MenuModel;
namespace views {
class MenuButton;
+class MenuItemView;
class MenuModelAdapter;
class MenuRunnerHandler;
class Widget;
@@ -103,7 +114,7 @@ class VIEWS_EXPORT MenuRunner {
RunResult RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
+ MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
int32 types) WARN_UNUSED_RESULT;
diff --git a/chromium/ui/views/controls/menu/menu_runner_handler.h b/chromium/ui/views/controls/menu/menu_runner_handler.h
index 46f801af685..47d75c80fce 100644
--- a/chromium/ui/views/controls/menu/menu_runner_handler.h
+++ b/chromium/ui/views/controls/menu/menu_runner_handler.h
@@ -6,11 +6,11 @@
#define UI_VIEWS_CONTROLS_MENU_MENU_RUNNER_HANDLER_H_
#include "base/basictypes.h"
-#include "ui/views/controls/menu/menu_item_view.h"
namespace views {
class MenuButton;
+class MenuItemView;
class Widget;
// Used internally by MenuRunner to show the menu. Can be set in tests (see
@@ -21,7 +21,7 @@ class VIEWS_EXPORT MenuRunnerHandler {
virtual MenuRunner::RunResult RunMenuAt(Widget* parent,
MenuButton* button,
const gfx::Rect& bounds,
- MenuItemView::AnchorPosition anchor,
+ MenuAnchorPosition anchor,
ui::MenuSourceType source_type,
int32 types) = 0;
};
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 7b8edbecab5..451bd1537ad 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -6,8 +6,9 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/canvas.h"
+#include "ui/native_theme/native_theme_aura.h"
#include "ui/views/border.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/controls/menu/menu_config.h"
@@ -16,10 +17,6 @@
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/round_rect_painter.h"
-#if defined(USE_AURA)
-#include "ui/native_theme/native_theme_aura.h"
-#endif
-
using ui::NativeTheme;
namespace views {
@@ -43,7 +40,7 @@ class MenuScrollButton : public View {
pref_height_(MenuItemView::pref_menu_height()) {
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return gfx::Size(
host_->GetMenuItem()->GetMenuConfig().scroll_arrow_height * 2 - 1,
pref_height_);
@@ -246,7 +243,7 @@ void MenuScrollViewContainer::Layout() {
scroll_view_->Layout();
}
-gfx::Size MenuScrollViewContainer::GetPreferredSize() {
+gfx::Size MenuScrollViewContainer::GetPreferredSize() const {
gfx::Size prefsize = scroll_view_->GetContents()->GetPreferredSize();
gfx::Insets insets = GetInsets();
prefsize.Enlarge(insets.width(), insets.height());
@@ -254,15 +251,15 @@ gfx::Size MenuScrollViewContainer::GetPreferredSize() {
}
void MenuScrollViewContainer::GetAccessibleState(
- ui::AccessibleViewState* state) {
+ ui::AXViewState* state) {
// Get the name from the submenu view.
content_view_->GetAccessibleState(state);
// Now change the role.
- state->role = ui::AccessibilityTypes::ROLE_MENUBAR;
+ state->role = ui::AX_ROLE_MENU_BAR;
// Some AT (like NVDA) will not process focus events on menu item children
// unless a parent claims to be focused.
- state->state = ui::AccessibilityTypes::STATE_FOCUSED;
+ state->AddStateFlag(ui::AX_STATE_FOCUSED);
}
void MenuScrollViewContainer::OnBoundsChanged(
@@ -284,7 +281,7 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
int padding = menu_config.corner_radius > 0 ?
kBorderPaddingDueToRoundedCorners : 0;
-#if defined(USE_AURA)
+#if defined(USE_AURA) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
if (menu_config.native_theme == ui::NativeThemeAura::instance()) {
// In case of NativeThemeAura the border gets drawn with the shadow.
// Furthermore no additional padding is wanted.
@@ -299,13 +296,14 @@ void MenuScrollViewContainer::CreateDefaultBorder() {
int right = menu_config.menu_horizontal_border_size + padding;
if (use_border) {
- set_border(views::Border::CreateBorderPainter(
- new views::RoundRectPainter(menu_config.native_theme->GetSystemColor(
+ SetBorder(views::Border::CreateBorderPainter(
+ new views::RoundRectPainter(
+ menu_config.native_theme->GetSystemColor(
ui::NativeTheme::kColorId_MenuBorderColor),
menu_config.corner_radius),
- gfx::Insets(top, left, bottom, right)));
+ gfx::Insets(top, left, bottom, right)));
} else {
- set_border(Border::CreateEmptyBorder(top, left, bottom, right));
+ SetBorder(Border::CreateEmptyBorder(top, left, bottom, right));
}
}
@@ -313,21 +311,20 @@ void MenuScrollViewContainer::CreateBubbleBorder() {
bubble_border_ = new BubbleBorder(arrow_,
BubbleBorder::SMALL_SHADOW,
SK_ColorWHITE);
- set_border(bubble_border_);
+ SetBorder(scoped_ptr<Border>(bubble_border_));
set_background(new BubbleBackground(bubble_border_));
}
-BubbleBorder::Arrow
-MenuScrollViewContainer::BubbleBorderTypeFromAnchor(
- MenuItemView::AnchorPosition anchor) {
+BubbleBorder::Arrow MenuScrollViewContainer::BubbleBorderTypeFromAnchor(
+ MenuAnchorPosition anchor) {
switch (anchor) {
- case views::MenuItemView::BUBBLE_LEFT:
+ case MENU_ANCHOR_BUBBLE_LEFT:
return BubbleBorder::RIGHT_CENTER;
- case views::MenuItemView::BUBBLE_RIGHT:
+ case MENU_ANCHOR_BUBBLE_RIGHT:
return BubbleBorder::LEFT_CENTER;
- case views::MenuItemView::BUBBLE_ABOVE:
+ case MENU_ANCHOR_BUBBLE_ABOVE:
return BubbleBorder::BOTTOM_CENTER;
- case views::MenuItemView::BUBBLE_BELOW:
+ case MENU_ANCHOR_BUBBLE_BELOW:
return BubbleBorder::TOP_CENTER;
default:
return BubbleBorder::NONE;
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 83baa2a3939..dc7c1acf164 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.h
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.h
@@ -7,7 +7,7 @@
#include "ui/views/view.h"
#include "ui/views/bubble/bubble_border.h"
-#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/menu_types.h"
namespace views {
@@ -33,8 +33,8 @@ class MenuScrollViewContainer : public View {
// View overrides.
virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE;
virtual void Layout() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
protected:
// View override.
@@ -47,8 +47,7 @@ class MenuScrollViewContainer : public View {
// Create the bubble border.
void CreateBubbleBorder();
- BubbleBorder::Arrow BubbleBorderTypeFromAnchor(
- MenuItemView::AnchorPosition anchor);
+ BubbleBorder::Arrow BubbleBorderTypeFromAnchor(MenuAnchorPosition anchor);
class MenuScrollView;
@@ -65,7 +64,7 @@ class MenuScrollViewContainer : public View {
// If set the currently set border is a bubble border.
BubbleBorder::Arrow arrow_;
- // The currently set border.
+ // Weak reference to the currently set border.
BubbleBorder* bubble_border_;
DISALLOW_COPY_AND_ASSIGN(MenuScrollViewContainer);
diff --git a/chromium/ui/views/controls/menu/menu_separator.h b/chromium/ui/views/controls/menu/menu_separator.h
index 4098ae8f0ae..da459e2b07a 100644
--- a/chromium/ui/views/controls/menu/menu_separator.h
+++ b/chromium/ui/views/controls/menu/menu_separator.h
@@ -21,13 +21,11 @@ class MenuSeparator : public View {
// View overrides.
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
private:
-#if defined(USE_AURA)
void OnPaintAura(gfx::Canvas* canvas);
- gfx::Size GetPreferredSizeAura();
-#endif
+ gfx::Size GetPreferredSizeAura() const;
// The type of the separator.
const ui::MenuSeparatorType type_;
diff --git a/chromium/ui/views/controls/menu/menu_separator_views.cc b/chromium/ui/views/controls/menu/menu_separator_views.cc
index affbae48966..34f85453501 100644
--- a/chromium/ui/views/controls/menu/menu_separator_views.cc
+++ b/chromium/ui/views/controls/menu/menu_separator_views.cc
@@ -23,7 +23,7 @@ void MenuSeparator::OnPaint(gfx::Canvas* canvas) {
OnPaintAura(canvas);
}
-gfx::Size MenuSeparator::GetPreferredSize() {
+gfx::Size MenuSeparator::GetPreferredSize() const {
return GetPreferredSizeAura();
}
#endif
@@ -47,7 +47,7 @@ void MenuSeparator::OnPaintAura(gfx::Canvas* canvas) {
ui::NativeTheme::kColorId_MenuSeparatorColor));
}
-gfx::Size MenuSeparator::GetPreferredSizeAura() {
+gfx::Size MenuSeparator::GetPreferredSizeAura() const {
const MenuConfig& menu_config = parent_menu_item_->GetMenuConfig();
int height = menu_config.separator_height;
switch(type_) {
diff --git a/chromium/ui/views/controls/menu/menu_separator_win.cc b/chromium/ui/views/controls/menu/menu_separator_win.cc
index 6f95334790a..ccbcaed263e 100644
--- a/chromium/ui/views/controls/menu/menu_separator_win.cc
+++ b/chromium/ui/views/controls/menu/menu_separator_win.cc
@@ -11,24 +11,19 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/rect.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/native_theme/native_theme_aura.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_item_view.h"
-#if defined(USE_AURA)
-#include "ui/native_theme/native_theme_aura.h"
-#endif
-
namespace views {
void MenuSeparator::OnPaint(gfx::Canvas* canvas) {
const MenuConfig& config = parent_menu_item_->GetMenuConfig();
-#if defined(USE_AURA)
if (config.native_theme == ui::NativeThemeAura::instance()) {
OnPaintAura(canvas);
return;
}
-#endif
int start_x = 0;
if (config.render_gutter) {
@@ -52,13 +47,11 @@ void MenuSeparator::OnPaint(gfx::Canvas* canvas) {
ui::NativeTheme::kNormal, separator_bounds, extra);
}
-gfx::Size MenuSeparator::GetPreferredSize() {
+gfx::Size MenuSeparator::GetPreferredSize() const {
const MenuConfig& config = parent_menu_item_->GetMenuConfig();
-#if defined(USE_AURA)
if (config.native_theme == ui::NativeThemeAura::instance())
return GetPreferredSizeAura();
-#endif
return gfx::Size(10, // Just in case we're the only item in a menu.
config.separator_height);
diff --git a/chromium/ui/views/controls/menu/menu_types.h b/chromium/ui/views/controls/menu/menu_types.h
new file mode 100644
index 00000000000..160dd5ae3d1
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_types.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_TYPES_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_TYPES_H_
+
+namespace views {
+
+// Where a popup menu should be anchored to for non-RTL languages. The opposite
+// position will be used if base::i18n:IsRTL() is true. The BUBBLE flags are
+// used when the menu should get enclosed by a bubble. Note that BUBBLE flags
+// should only be used with menus which have no children.
+enum MenuAnchorPosition {
+ MENU_ANCHOR_TOPLEFT,
+ MENU_ANCHOR_TOPRIGHT,
+ MENU_ANCHOR_BOTTOMCENTER,
+ MENU_ANCHOR_BUBBLE_LEFT,
+ MENU_ANCHOR_BUBBLE_RIGHT,
+ MENU_ANCHOR_BUBBLE_ABOVE,
+ MENU_ANCHOR_BUBBLE_BELOW
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_TYPES_H_
diff --git a/chromium/ui/views/controls/menu/menu_win.cc b/chromium/ui/views/controls/menu/menu_win.cc
deleted file mode 100644
index d88659ff7d4..00000000000
--- a/chromium/ui/views/controls/menu/menu_win.cc
+++ /dev/null
@@ -1,572 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_win.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/win/window_impl.h"
-#include "ui/views/layout/layout_constants.h"
-
-namespace views {
-
-// The width of an icon, including the pixels between the icon and
-// the item label.
-const int kIconWidth = 23;
-// Margins between the top of the item and the label.
-const int kItemTopMargin = 3;
-// Margins between the bottom of the item and the label.
-const int kItemBottomMargin = 4;
-// Margins between the left of the item and the icon.
-const int kItemLeftMargin = 4;
-// The width for displaying the sub-menu arrow.
-const int kArrowWidth = 10;
-
-// Current active MenuHostWindow. If NULL, no menu is active.
-static MenuHostWindow* active_host_window = NULL;
-
-// The data of menu items needed to display.
-struct MenuWin::ItemData {
- string16 label;
- gfx::ImageSkia icon;
- bool submenu;
-};
-
-namespace {
-
-static int ChromeGetMenuItemID(HMENU hMenu, int pos) {
- // The built-in Windows GetMenuItemID doesn't work for submenus,
- // so here's our own implementation.
- MENUITEMINFO mii = {0};
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_ID;
- GetMenuItemInfo(hMenu, pos, TRUE, &mii);
- return mii.wID;
-}
-
-// MenuHostWindow -------------------------------------------------------------
-
-// MenuHostWindow is the HWND the HMENU is parented to. MenuHostWindow is used
-// to intercept right clicks on the HMENU and notify the delegate as well as
-// for drawing icons.
-//
-class MenuHostWindow : public gfx::WindowImpl {
- public:
- MenuHostWindow(MenuWin* menu, HWND parent_window) : menu_(menu) {
- int extended_style = 0;
- // If the menu needs to be created with a right-to-left UI layout, we must
- // set the appropriate RTL flags (such as WS_EX_LAYOUTRTL) property for the
- // underlying HWND.
- if (menu_->delegate()->IsRightToLeftUILayout())
- extended_style |= l10n_util::GetExtendedStyles();
- set_window_style(WS_CHILD);
- set_window_ex_style(extended_style);
- Init(parent_window, gfx::Rect());
- }
-
- ~MenuHostWindow() {
- DestroyWindow(hwnd());
- }
-
- BEGIN_MSG_MAP_EX(MenuHostWindow);
- MSG_WM_RBUTTONUP(OnRButtonUp)
- MSG_WM_MEASUREITEM(OnMeasureItem)
- MSG_WM_DRAWITEM(OnDrawItem)
- END_MSG_MAP();
-
- private:
- // NOTE: I really REALLY tried to use WM_MENURBUTTONUP, but I ran into
- // two problems in using it:
- // 1. It doesn't contain the coordinates of the mouse.
- // 2. It isn't invoked for menuitems representing a submenu that have children
- // menu items (not empty).
-
- void OnRButtonUp(UINT w_param, const CPoint& loc) {
- int id;
- if (menu_->delegate() && FindMenuIDByLocation(menu_, loc, &id))
- menu_->delegate()->ShowContextMenu(menu_, id, gfx::Point(loc), true);
- }
-
- void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* lpmis) {
- MenuWin::ItemData* data =
- reinterpret_cast<MenuWin::ItemData*>(lpmis->itemData);
- if (data != NULL) {
- gfx::Font font;
- lpmis->itemWidth = font.GetStringWidth(data->label) + kIconWidth +
- kItemLeftMargin + views::kItemLabelSpacing -
- GetSystemMetrics(SM_CXMENUCHECK);
- if (data->submenu)
- lpmis->itemWidth += kArrowWidth;
- // If the label contains an accelerator, make room for tab.
- if (data->label.find(L'\t') != string16::npos)
- lpmis->itemWidth += font.GetStringWidth(L" ");
- lpmis->itemHeight = font.GetHeight() + kItemBottomMargin + kItemTopMargin;
- } else {
- // Measure separator size.
- lpmis->itemHeight = GetSystemMetrics(SM_CYMENU) / 2;
- lpmis->itemWidth = 0;
- }
- }
-
- void OnDrawItem(UINT wParam, DRAWITEMSTRUCT* lpdis) {
- HDC hDC = lpdis->hDC;
- COLORREF prev_bg_color, prev_text_color;
-
- // Set background color and text color
- if (lpdis->itemState & ODS_SELECTED) {
- prev_bg_color = SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT));
- prev_text_color = SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
- } else {
- prev_bg_color = SetBkColor(hDC, GetSysColor(COLOR_MENU));
- if (lpdis->itemState & ODS_DISABLED)
- prev_text_color = SetTextColor(hDC, GetSysColor(COLOR_GRAYTEXT));
- else
- prev_text_color = SetTextColor(hDC, GetSysColor(COLOR_MENUTEXT));
- }
-
- if (lpdis->itemData) {
- MenuWin::ItemData* data =
- reinterpret_cast<MenuWin::ItemData*>(lpdis->itemData);
-
- // Draw the background.
- HBRUSH hbr = CreateSolidBrush(GetBkColor(hDC));
- FillRect(hDC, &lpdis->rcItem, hbr);
- DeleteObject(hbr);
-
- // Draw the label.
- RECT rect = lpdis->rcItem;
- rect.top += kItemTopMargin;
- // Should we add kIconWidth only when icon.width() != 0 ?
- rect.left += kItemLeftMargin + kIconWidth;
- rect.right -= views::kItemLabelSpacing;
- UINT format = DT_TOP | DT_SINGLELINE;
- // Check whether the mnemonics should be underlined.
- BOOL underline_mnemonics;
- SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &underline_mnemonics, 0);
- if (!underline_mnemonics)
- format |= DT_HIDEPREFIX;
- gfx::Font font;
- HGDIOBJ old_font =
- static_cast<HFONT>(SelectObject(hDC, font.GetNativeFont()));
-
- // If an accelerator is specified (with a tab delimiting the rest of the
- // label from the accelerator), we have to justify the fist part on the
- // left and the accelerator on the right.
- // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the
- // window system UI font and will not hit here.
- string16 label = data->label;
- string16 accel;
- string16::size_type tab_pos = label.find(L'\t');
- if (tab_pos != string16::npos) {
- accel = label.substr(tab_pos);
- label = label.substr(0, tab_pos);
- }
- DrawTextEx(hDC, const_cast<wchar_t*>(label.data()),
- static_cast<int>(label.size()), &rect, format | DT_LEFT, NULL);
- if (!accel.empty())
- DrawTextEx(hDC, const_cast<wchar_t*>(accel.data()),
- static_cast<int>(accel.size()), &rect,
- format | DT_RIGHT, NULL);
- SelectObject(hDC, old_font);
-
- // Draw the icon after the label, otherwise it would be covered
- // by the label.
- gfx::ImageSkiaRep icon_image_rep = data->icon.GetRepresentation(1.0f);
- if (data->icon.width() != 0 && data->icon.height() != 0) {
- gfx::Canvas canvas(icon_image_rep, false);
- skia::DrawToNativeContext(
- canvas.sk_canvas(), hDC, lpdis->rcItem.left + kItemLeftMargin,
- lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top -
- data->icon.height()) / 2, NULL);
- }
-
- } else {
- // Draw the separator
- lpdis->rcItem.top += (lpdis->rcItem.bottom - lpdis->rcItem.top) / 3;
- DrawEdge(hDC, &lpdis->rcItem, EDGE_ETCHED, BF_TOP);
- }
-
- SetBkColor(hDC, prev_bg_color);
- SetTextColor(hDC, prev_text_color);
- }
-
- bool FindMenuIDByLocation(MenuWin* menu, const CPoint& loc, int* id) {
- int index = MenuItemFromPoint(NULL, menu->menu_, loc);
- if (index != -1) {
- *id = ChromeGetMenuItemID(menu->menu_, index);
- return true;
- } else {
- for (std::vector<MenuWin*>::iterator i = menu->submenus_.begin();
- i != menu->submenus_.end(); ++i) {
- if (FindMenuIDByLocation(*i, loc, id))
- return true;
- }
- }
- return false;
- }
-
- // The menu that created us.
- MenuWin* menu_;
-
- DISALLOW_COPY_AND_ASSIGN(MenuHostWindow);
-};
-
-} // namespace
-
-// static
-Menu* Menu::Create(Delegate* delegate,
- AnchorPoint anchor,
- gfx::NativeView parent) {
- return new MenuWin(delegate, anchor, parent);
-}
-
-// static
-Menu* Menu::GetSystemMenu(gfx::NativeWindow parent) {
- return new views::MenuWin(::GetSystemMenu(parent, FALSE));
-}
-
-MenuWin::MenuWin(Delegate* d, AnchorPoint anchor, HWND owner)
- : Menu(d, anchor),
- menu_(CreatePopupMenu()),
- owner_(owner),
- is_menu_visible_(false),
- owner_draw_(l10n_util::NeedOverrideDefaultUIFont(NULL, NULL)) {
- DCHECK(delegate());
-}
-
-MenuWin::MenuWin(HMENU hmenu)
- : Menu(NULL, TOPLEFT),
- menu_(hmenu),
- owner_(NULL),
- is_menu_visible_(false),
- owner_draw_(false) {
- DCHECK(menu_);
-}
-
-MenuWin::~MenuWin() {
- STLDeleteContainerPointers(submenus_.begin(), submenus_.end());
- STLDeleteContainerPointers(item_data_.begin(), item_data_.end());
- DestroyMenu(menu_);
-}
-
-void MenuWin::AddMenuItemWithIcon(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon) {
- owner_draw_ = true;
- Menu::AddMenuItemWithIcon(index, item_id, label, icon);
-}
-
-Menu* MenuWin::AddSubMenuWithIcon(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon) {
- MenuWin* submenu = new MenuWin(this);
- submenus_.push_back(submenu);
- AddMenuItemInternal(index, item_id, label, icon, submenu->menu_, NORMAL);
- return submenu;
-}
-
-void MenuWin::AddSeparator(int index) {
- MENUITEMINFO mii;
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_FTYPE;
- mii.fType = MFT_SEPARATOR;
- InsertMenuItem(menu_, index, TRUE, &mii);
-}
-
-void MenuWin::EnableMenuItemByID(int item_id, bool enabled) {
- UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED;
- EnableMenuItem(menu_, item_id, MF_BYCOMMAND | enable_flags);
-}
-
-void MenuWin::EnableMenuItemAt(int index, bool enabled) {
- UINT enable_flags = enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED;
- EnableMenuItem(menu_, index, MF_BYPOSITION | enable_flags);
-}
-
-void MenuWin::SetMenuLabel(int item_id, const string16& label) {
- MENUITEMINFO mii = {0};
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_STRING;
- mii.dwTypeData = const_cast<wchar_t*>(label.c_str());
- mii.cch = static_cast<UINT>(label.size());
- SetMenuItemInfo(menu_, item_id, false, &mii);
-}
-
-bool MenuWin::SetIcon(const gfx::ImageSkia& icon, int item_id) {
- if (!owner_draw_)
- owner_draw_ = true;
-
- const int num_items = GetMenuItemCount(menu_);
- int sep_count = 0;
- for (int i = 0; i < num_items; ++i) {
- if (!(GetMenuState(menu_, i, MF_BYPOSITION) & MF_SEPARATOR)) {
- if (ChromeGetMenuItemID(menu_, i) == item_id) {
- item_data_[i - sep_count]->icon = icon;
- // When the menu is running, we use SetMenuItemInfo to let Windows
- // update the item information so that the icon being displayed
- // could change immediately.
- if (active_host_window) {
- MENUITEMINFO mii;
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_FTYPE | MIIM_DATA;
- mii.fType = MFT_OWNERDRAW;
- mii.dwItemData =
- reinterpret_cast<ULONG_PTR>(item_data_[i - sep_count]);
- SetMenuItemInfo(menu_, item_id, false, &mii);
- }
- return true;
- }
- } else {
- ++sep_count;
- }
- }
-
- // Continue searching for the item in submenus.
- for (size_t i = 0; i < submenus_.size(); ++i) {
- if (submenus_[i]->SetIcon(icon, item_id))
- return true;
- }
-
- return false;
-}
-
-void MenuWin::RunMenuAt(int x, int y) {
- SetMenuInfo();
-
- delegate()->MenuWillShow();
-
- // NOTE: we don't use TPM_RIGHTBUTTON here as it breaks selecting by way of
- // press, drag, release. See bugs 718 and 8560.
- UINT flags =
- GetTPMAlignFlags() | TPM_LEFTBUTTON | TPM_RETURNCMD | TPM_RECURSE;
- is_menu_visible_ = true;
- DCHECK(owner_);
- // In order for context menus on menus to work, the context menu needs to
- // share the same window as the first menu is parented to.
- bool created_host = false;
- if (!active_host_window) {
- created_host = true;
- active_host_window = new MenuHostWindow(this, owner_);
- }
- UINT selected_id =
- TrackPopupMenuEx(menu_, flags, x, y, active_host_window->hwnd(), NULL);
- if (created_host) {
- delete active_host_window;
- active_host_window = NULL;
- }
- is_menu_visible_ = false;
-
- // Execute the chosen command
- if (selected_id != 0)
- delegate()->ExecuteCommand(selected_id);
-}
-
-void MenuWin::Cancel() {
- DCHECK(is_menu_visible_);
- EndMenu();
-}
-
-int MenuWin::ItemCount() {
- return GetMenuItemCount(menu_);
-}
-
-void MenuWin::AddMenuItemInternal(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon,
- MenuItemType type) {
- AddMenuItemInternal(index, item_id, label, icon, NULL, type);
-}
-
-void MenuWin::AddMenuItemInternal(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon,
- HMENU submenu,
- MenuItemType type) {
- DCHECK(type != SEPARATOR) << "Call AddSeparator instead!";
-
- if (!owner_draw_ && !icon.isNull())
- owner_draw_ = true;
-
- if (label.empty() && !delegate()) {
- // No label and no delegate; don't add an empty menu.
- // It appears under some circumstance we're getting an empty label
- // (l10n_util::GetStringUTF16(IDS_TASK_MANAGER) returns ""). This shouldn't
- // happen, but I'm working over the crash here.
- NOTREACHED();
- return;
- }
-
- MENUITEMINFO mii;
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_FTYPE | MIIM_ID;
- if (submenu) {
- mii.fMask |= MIIM_SUBMENU;
- mii.hSubMenu = submenu;
- }
-
- // Set the type and ID.
- if (!owner_draw_) {
- mii.fType = MFT_STRING;
- mii.fMask |= MIIM_STRING;
- } else {
- mii.fType = MFT_OWNERDRAW;
- }
-
- if (type == RADIO)
- mii.fType |= MFT_RADIOCHECK;
-
- mii.wID = item_id;
-
- // Set the item data.
- MenuWin::ItemData* data = new ItemData;
- item_data_.push_back(data);
- data->submenu = submenu != NULL;
-
- string16 actual_label(label.empty() ? delegate()->GetLabel(item_id) : label);
-
- // Find out if there is a shortcut we need to append to the label.
- ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE);
- if (delegate() && delegate()->GetAcceleratorInfo(item_id, &accelerator)) {
- actual_label += L'\t';
- actual_label += accelerator.GetShortcutText();
- }
- labels_.push_back(actual_label);
-
- if (owner_draw_) {
- if (icon.width() != 0 && icon.height() != 0)
- data->icon = icon;
- else
- data->icon = delegate()->GetIcon(item_id);
- } else {
- mii.dwTypeData = const_cast<wchar_t*>(labels_.back().c_str());
- }
-
- InsertMenuItem(menu_, index, TRUE, &mii);
-}
-
-MenuWin::MenuWin(MenuWin* parent)
- : Menu(parent->delegate(), parent->anchor()),
- menu_(CreatePopupMenu()),
- owner_(parent->owner_),
- is_menu_visible_(false),
- owner_draw_(parent->owner_draw_) {
-}
-
-void MenuWin::SetMenuInfo() {
- const int num_items = GetMenuItemCount(menu_);
- int sep_count = 0;
- for (int i = 0; i < num_items; ++i) {
- MENUITEMINFO mii_info;
- mii_info.cbSize = sizeof(mii_info);
- // Get the menu's original type.
- mii_info.fMask = MIIM_FTYPE;
- GetMenuItemInfo(menu_, i, MF_BYPOSITION, &mii_info);
- // Set item states.
- if (!(mii_info.fType & MF_SEPARATOR)) {
- const int id = ChromeGetMenuItemID(menu_, i);
-
- MENUITEMINFO mii;
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_STATE | MIIM_FTYPE | MIIM_DATA | MIIM_STRING;
- // We also need MFT_STRING for owner drawn items in order to let Windows
- // handle the accelerators for us.
- mii.fType = MFT_STRING;
- if (owner_draw_)
- mii.fType |= MFT_OWNERDRAW;
- // If the menu originally has radiocheck type, we should follow it.
- if (mii_info.fType & MFT_RADIOCHECK)
- mii.fType |= MFT_RADIOCHECK;
- mii.fState = GetStateFlagsForItemID(id);
-
- // Validate the label. If there is a contextual label, use it, otherwise
- // default to the static label
- string16 label;
- if (!delegate()->GetContextualLabel(id, &label))
- label = labels_[i - sep_count];
-
- if (owner_draw_) {
- item_data_[i - sep_count]->label = label;
- mii.dwItemData = reinterpret_cast<ULONG_PTR>(item_data_[i - sep_count]);
- }
- mii.dwTypeData = const_cast<wchar_t*>(label.c_str());
- mii.cch = static_cast<UINT>(label.size());
- SetMenuItemInfo(menu_, i, true, &mii);
- } else {
- // Set data for owner drawn separators. Set dwItemData NULL to indicate
- // a separator.
- if (owner_draw_) {
- MENUITEMINFO mii;
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_FTYPE;
- mii.fType = MFT_SEPARATOR | MFT_OWNERDRAW;
- mii.dwItemData = NULL;
- SetMenuItemInfo(menu_, i, true, &mii);
- }
- ++sep_count;
- }
- }
-
- for (size_t i = 0; i < submenus_.size(); ++i)
- submenus_[i]->SetMenuInfo();
-}
-
-UINT MenuWin::GetStateFlagsForItemID(int item_id) const {
- // Use the delegate to get enabled and checked state.
- UINT flags =
- delegate()->IsCommandEnabled(item_id) ? MFS_ENABLED : MFS_DISABLED;
-
- if (delegate()->IsItemChecked(item_id))
- flags |= MFS_CHECKED;
-
- if (delegate()->IsItemDefault(item_id))
- flags |= MFS_DEFAULT;
-
- return flags;
-}
-
-DWORD MenuWin::GetTPMAlignFlags() const {
- // The manner in which we handle the menu alignment depends on whether or not
- // the menu is displayed within a mirrored view. If the UI is mirrored, the
- // alignment needs to be fliped so that instead of aligning the menu to the
- // right of the point, we align it to the left and vice versa.
- DWORD align_flags = TPM_TOPALIGN;
- switch (anchor()) {
- case TOPLEFT:
- if (delegate()->IsRightToLeftUILayout()) {
- align_flags |= TPM_RIGHTALIGN;
- } else {
- align_flags |= TPM_LEFTALIGN;
- }
- break;
-
- case TOPRIGHT:
- if (delegate()->IsRightToLeftUILayout()) {
- align_flags |= TPM_LEFTALIGN;
- } else {
- align_flags |= TPM_RIGHTALIGN;
- }
- break;
-
- default:
- NOTREACHED();
- return 0;
- }
- return align_flags;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_win.h b/chromium/ui/views/controls/menu/menu_win.h
deleted file mode 100644
index 284f26a4f85..00000000000
--- a/chromium/ui/views/controls/menu/menu_win.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_MENU_MENU_WIN_H_
-#define UI_VIEWS_CONTROLS_MENU_MENU_WIN_H_
-
-#include <windows.h>
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ui/views/controls/menu/menu.h"
-
-namespace views {
-
-namespace {
-class MenuHostWindow;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Menu class
-//
-// A wrapper around a Win32 HMENU handle that provides convenient APIs for
-// menu construction, display and subsequent command execution.
-//
-///////////////////////////////////////////////////////////////////////////////
-class MenuWin : public Menu {
- public:
- // Construct a Menu using the specified controller to determine command
- // state.
- // delegate A Menu::Delegate implementation that provides more
- // information about the Menu presentation.
- // anchor An alignment hint for the popup menu.
- // owner The window that the menu is being brought up relative
- // to. Not actually used for anything but must not be
- // NULL.
- MenuWin(Delegate* d, AnchorPoint anchor, HWND owner);
- // Alternatively, a Menu object can be constructed wrapping an existing
- // HMENU. This can be used to use the convenience methods to insert
- // menu items and manage label string ownership. However this kind of
- // Menu object cannot use the delegate.
- explicit MenuWin(HMENU hmenu);
- virtual ~MenuWin();
-
- // Overridden from Menu:
- virtual void AddMenuItemWithIcon(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon) OVERRIDE;
- virtual Menu* AddSubMenuWithIcon(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon) OVERRIDE;
- virtual void AddSeparator(int index) OVERRIDE;
- virtual void EnableMenuItemByID(int item_id, bool enabled) OVERRIDE;
- virtual void EnableMenuItemAt(int index, bool enabled) OVERRIDE;
- virtual void SetMenuLabel(int item_id, const string16& label) OVERRIDE;
- virtual bool SetIcon(const gfx::ImageSkia& icon, int item_id) OVERRIDE;
- virtual void RunMenuAt(int x, int y) OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual int ItemCount() OVERRIDE;
-
- virtual HMENU GetMenuHandle() const {
- return menu_;
- }
-
- // Gets the Win32 TPM alignment flags for the specified AnchorPoint.
- DWORD GetTPMAlignFlags() const;
-
- protected:
- virtual void AddMenuItemInternal(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon,
- MenuItemType type) OVERRIDE;
-
- private:
- friend class MenuHostWindow;
-
- // The data of menu items needed to display.
- struct ItemData;
-
- void AddMenuItemInternal(int index,
- int item_id,
- const string16& label,
- const gfx::ImageSkia& icon,
- HMENU submenu,
- MenuItemType type);
-
- explicit MenuWin(MenuWin* parent);
-
- // Sets menu information before displaying, including sub-menus.
- void SetMenuInfo();
-
- // Get all the state flags for the |fState| field of MENUITEMINFO for the
- // item with the specified id. |delegate| is consulted if non-NULL about
- // the state of the item in preference to |controller_|.
- UINT GetStateFlagsForItemID(int item_id) const;
-
- // The Win32 Menu Handle we wrap
- HMENU menu_;
-
- // The window that would receive WM_COMMAND messages when the user selects
- // an item from the menu.
- HWND owner_;
-
- // This list is used to store the default labels for the menu items.
- // We may use contextual labels when RunMenu is called, so we must save
- // a copy of default ones here.
- std::vector<string16> labels_;
-
- // A flag to indicate whether this menu will be drawn by the Menu class.
- // If it's true, all the menu items will be owner drawn. Otherwise,
- // all the drawing will be done by Windows.
- bool owner_draw_;
-
- // This list is to store the string labels and icons to display. It's used
- // when owner_draw_ is true. We give MENUITEMINFO pointers to these
- // structures to specify what we'd like to draw. If owner_draw_ is false,
- // we only give MENUITEMINFO pointers to the labels_.
- // The label member of the ItemData structure comes from either labels_ or
- // the GetContextualLabel.
- std::vector<ItemData*> item_data_;
-
- // Our sub-menus, if any.
- std::vector<MenuWin*> submenus_;
-
- // Whether the menu is visible.
- bool is_menu_visible_;
-
- DISALLOW_COPY_AND_ASSIGN(MenuWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_MENU_MENU_WIN_H_
diff --git a/chromium/ui/views/controls/menu/native_menu_win.cc b/chromium/ui/views/controls/menu/native_menu_win.cc
index c260af9bcce..caddd70c4a5 100644
--- a/chromium/ui/views/controls/menu/native_menu_win.cc
+++ b/chromium/ui/views/controls/menu/native_menu_win.cc
@@ -18,10 +18,11 @@
#include "ui/base/models/menu_model.h"
#include "ui/events/keycodes/keyboard_codes.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/gfx/image/image_skia.h"
-#include "ui/gfx/rect.h"
+#include "ui/gfx/text_utils.h"
#include "ui/gfx/win/hwnd_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_win.h"
@@ -51,7 +52,7 @@ struct NativeMenuWin::ItemData {
// The Windows API requires that whoever creates the menus must own the
// strings used for labels, and keep them around for the lifetime of the
// created menu. So be it.
- string16 label;
+ base::string16 label;
// Someone needs to own submenus, it may as well be us.
scoped_ptr<Menu2> submenu;
@@ -171,17 +172,18 @@ class NativeMenuWin::MenuHostWindow {
void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* measure_item_struct) {
NativeMenuWin::ItemData* data = GetItemData(measure_item_struct->itemData);
if (data) {
- gfx::Font font;
- measure_item_struct->itemWidth = font.GetStringWidth(data->label) +
+ gfx::FontList font_list;
+ measure_item_struct->itemWidth =
+ gfx::GetStringWidth(data->label, font_list) +
kIconWidth + kItemLeftMargin + views::kItemLabelSpacing -
GetSystemMetrics(SM_CXMENUCHECK);
if (data->submenu.get())
measure_item_struct->itemWidth += kArrowWidth;
// If the label contains an accelerator, make room for tab.
- if (data->label.find(L'\t') != string16::npos)
- measure_item_struct->itemWidth += font.GetStringWidth(L" ");
+ if (data->label.find(L'\t') != base::string16::npos)
+ measure_item_struct->itemWidth += gfx::GetStringWidth(L" ", font_list);
measure_item_struct->itemHeight =
- font.GetHeight() + kItemBottomMargin + kItemTopMargin;
+ font_list.GetHeight() + kItemBottomMargin + kItemTopMargin;
} else {
// Measure separator size.
measure_item_struct->itemHeight = GetSystemMetrics(SM_CYMENU) / 2;
@@ -225,19 +227,19 @@ class NativeMenuWin::MenuHostWindow {
SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &underline_mnemonics, 0);
if (!underline_mnemonics)
format |= DT_HIDEPREFIX;
- gfx::Font font;
- HGDIOBJ old_font =
- static_cast<HFONT>(SelectObject(dc, font.GetNativeFont()));
+ gfx::FontList font_list;
+ HGDIOBJ old_font = static_cast<HFONT>(
+ SelectObject(dc, font_list.GetPrimaryFont().GetNativeFont()));
// If an accelerator is specified (with a tab delimiting the rest of the
// label from the accelerator), we have to justify the fist part on the
// left and the accelerator on the right.
// TODO(jungshik): This will break in RTL UI. Currently, he/ar use the
// window system UI font and will not hit here.
- string16 label = data->label;
- string16 accel;
- string16::size_type tab_pos = label.find(L'\t');
- if (tab_pos != string16::npos) {
+ base::string16 label = data->label;
+ base::string16 accel;
+ base::string16::size_type tab_pos = label.find(L'\t');
+ if (tab_pos != base::string16::npos) {
accel = label.substr(tab_pos);
label = label.substr(0, tab_pos);
}
@@ -626,7 +628,7 @@ void NativeMenuWin::AddMenuItemAt(int menu_index, int model_index) {
mii.fType = MFT_OWNERDRAW;
ItemData* item_data = new ItemData;
- item_data->label = string16();
+ item_data->label = base::string16();
ui::MenuModel::ItemType type = model_->GetTypeAt(model_index);
if (type == ui::MenuModel::TYPE_SUBMENU) {
item_data->submenu.reset(new Menu2(model_->GetSubmenuModelAt(model_index)));
@@ -678,7 +680,7 @@ void NativeMenuWin::SetMenuItemState(int menu_index, bool enabled, bool checked,
void NativeMenuWin::SetMenuItemLabel(int menu_index,
int model_index,
- const string16& label) {
+ const base::string16& label) {
if (IsSeparatorItemAt(menu_index))
return;
@@ -690,8 +692,8 @@ void NativeMenuWin::SetMenuItemLabel(int menu_index,
void NativeMenuWin::UpdateMenuItemInfoForString(MENUITEMINFO* mii,
int model_index,
- const string16& label) {
- string16 formatted = label;
+ const base::string16& label) {
+ base::string16 formatted = label;
ui::MenuModel::ItemType type = model_->GetTypeAt(model_index);
// Strip out any tabs, otherwise they get interpreted as accelerators and can
// lead to weird behavior.
diff --git a/chromium/ui/views/controls/menu/native_menu_win.h b/chromium/ui/views/controls/menu/native_menu_win.h
index ca6f37bc5c8..ce3a072e416 100644
--- a/chromium/ui/views/controls/menu/native_menu_win.h
+++ b/chromium/ui/views/controls/menu/native_menu_win.h
@@ -74,7 +74,7 @@ class VIEWS_EXPORT NativeMenuWin : public MenuWrapper {
// Sets the label of the item at the specified index.
void SetMenuItemLabel(int menu_index,
int model_index,
- const string16& label);
+ const base::string16& label);
// Updates the local data structure with the correctly formatted version of
// |label| at the specified model_index, and adds string data to |mii| if
@@ -82,7 +82,7 @@ class VIEWS_EXPORT NativeMenuWin : public MenuWrapper {
// of the peculiarities of the Windows menu API.
void UpdateMenuItemInfoForString(MENUITEMINFO* mii,
int model_index,
- const string16& label);
+ const base::string16& label);
// Returns the alignment flags to be passed to TrackPopupMenuEx, based on the
// supplied alignment and the UI text direction.
diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc
index 9184ca9abfb..a6ef56a888e 100644
--- a/chromium/ui/views/controls/menu/submenu_view.cc
+++ b/chromium/ui/views/controls/menu/submenu_view.cc
@@ -7,12 +7,14 @@
#include <algorithm>
#include "base/compiler_specific.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_host.h"
+#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_scroll_view_container.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
@@ -41,7 +43,9 @@ SubmenuView::SubmenuView(MenuItemView* parent)
max_minor_text_width_(0),
minimum_preferred_width_(0),
resize_open_menu_(false),
- scroll_animator_(new ScrollAnimator(this)) {
+ scroll_animator_(new ScrollAnimator(this)),
+ roundoff_error_(0),
+ prefix_selector_(this) {
DCHECK(parent);
// We'll delete ourselves, otherwise the ScrollView would delete us on close.
set_owned_by_client();
@@ -117,7 +121,7 @@ void SubmenuView::Layout() {
}
}
-gfx::Size SubmenuView::GetPreferredSize() {
+gfx::Size SubmenuView::GetPreferredSize() const {
if (!has_children())
return gfx::Size();
@@ -128,11 +132,11 @@ gfx::Size SubmenuView::GetPreferredSize() {
int max_simple_width = 0;
int height = 0;
for (int i = 0; i < child_count(); ++i) {
- View* child = child_at(i);
+ const View* child = child_at(i);
if (!child->visible())
continue;
if (child->id() == MenuItemView::kMenuItemViewID) {
- MenuItemView* menu = static_cast<MenuItemView*>(child);
+ const MenuItemView* menu = static_cast<const MenuItemView*>(child);
const MenuItemView::MenuItemDimensions& dimensions =
menu->GetDimensions();
max_simple_width = std::max(
@@ -162,15 +166,20 @@ gfx::Size SubmenuView::GetPreferredSize() {
height + insets.height());
}
-void SubmenuView::GetAccessibleState(ui::AccessibleViewState* state) {
+void SubmenuView::GetAccessibleState(ui::AXViewState* state) {
// Inherit most of the state from the parent menu item, except the role.
if (GetMenuItem())
GetMenuItem()->GetAccessibleState(state);
- state->role = ui::AccessibilityTypes::ROLE_MENUPOPUP;
+ state->role = ui::AX_ROLE_MENU_LIST_POPUP;
+}
+
+ui::TextInputClient* SubmenuView::GetTextInputClient() {
+ return &prefix_selector_;
}
-void SubmenuView::PaintChildren(gfx::Canvas* canvas) {
- View::PaintChildren(canvas);
+void SubmenuView::PaintChildren(gfx::Canvas* canvas,
+ const views::CullSet& cull_set) {
+ View::PaintChildren(canvas, cull_set);
if (drop_item_ && drop_position_ != MenuDelegate::DROP_ON)
PaintDropIndicator(canvas, drop_item_, drop_position_);
@@ -293,6 +302,35 @@ void SubmenuView::OnGestureEvent(ui::GestureEvent* event) {
event->SetHandled();
}
+int SubmenuView::GetRowCount() {
+ return GetMenuItemCount();
+}
+
+int SubmenuView::GetSelectedRow() {
+ int row = 0;
+ for (int i = 0; i < child_count(); ++i) {
+ if (child_at(i)->id() != MenuItemView::kMenuItemViewID)
+ continue;
+
+ if (static_cast<MenuItemView*>(child_at(i))->IsSelected())
+ return row;
+
+ row++;
+ }
+
+ return -1;
+}
+
+void SubmenuView::SetSelectedRow(int row) {
+ GetMenuItem()->GetMenuController()->SetSelection(
+ GetMenuItemAt(row),
+ MenuController::SELECTION_DEFAULT);
+}
+
+base::string16 SubmenuView::GetTextForRow(int row) {
+ return GetMenuItemAt(row)->title();
+}
+
bool SubmenuView::IsShowing() {
return host_ && host_->IsMenuHostVisible();
}
@@ -313,10 +351,10 @@ void SubmenuView::ShowAt(Widget* parent,
}
GetScrollViewContainer()->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_MENUSTART,
+ ui::AX_EVENT_MENU_START,
true);
NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_MENUPOPUPSTART,
+ ui::AX_EVENT_MENU_POPUP_START,
true);
}
@@ -327,9 +365,9 @@ void SubmenuView::Reposition(const gfx::Rect& bounds) {
void SubmenuView::Close() {
if (host_) {
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_MENUPOPUPEND, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_MENU_POPUP_END, true);
GetScrollViewContainer()->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_MENUEND, true);
+ ui::AX_EVENT_MENU_END, true);
host_->DestroyMenuHost();
host_ = NULL;
@@ -446,7 +484,9 @@ bool SubmenuView::OnScroll(float dx, float dy) {
const gfx::Rect& vis_bounds = GetVisibleBounds();
const gfx::Rect& full_bounds = bounds();
int x = vis_bounds.x();
- int y = vis_bounds.y() - static_cast<int>(dy);
+ float y_f = vis_bounds.y() - dy - roundoff_error_;
+ int y = gfx::ToRoundedInt(y_f);
+ roundoff_error_ = y - y_f;
// clamp y to [0, full_height - vis_height)
y = std::min(y, full_bounds.height() - vis_bounds.height() - 1);
y = std::max(y, 0);
diff --git a/chromium/ui/views/controls/menu/submenu_view.h b/chromium/ui/views/controls/menu/submenu_view.h
index 19e0d46ffa2..1b7d36243d2 100644
--- a/chromium/ui/views/controls/menu/submenu_view.h
+++ b/chromium/ui/views/controls/menu/submenu_view.h
@@ -10,6 +10,8 @@
#include "base/compiler_specific.h"
#include "ui/views/animation/scroll_animator.h"
#include "ui/views/controls/menu/menu_delegate.h"
+#include "ui/views/controls/prefix_delegate.h"
+#include "ui/views/controls/prefix_selector.h"
#include "ui/views/view.h"
namespace views {
@@ -26,14 +28,14 @@ class MenuScrollViewContainer;
// . Forwards the appropriate events to the MenuController. This allows the
// MenuController to update the selection as the user moves the mouse around.
// . Renders the drop indicator during a drop operation.
-// . Shows and hides the window (a NativeWidgetWin) when the menu is shown on
+// . Shows and hides the window (a NativeWidget) when the menu is shown on
// screen.
//
// SubmenuView is itself contained in a MenuScrollViewContainer.
// MenuScrollViewContainer handles showing as much of the SubmenuView as the
// screen allows. If the SubmenuView is taller than the screen, scroll buttons
// are provided that allow the user to see all the menu items.
-class VIEWS_EXPORT SubmenuView : public View,
+class VIEWS_EXPORT SubmenuView : public PrefixDelegate,
public ScrollDelegate {
public:
// The submenu's class name.
@@ -53,13 +55,15 @@ class VIEWS_EXPORT SubmenuView : public View,
// Positions and sizes the child views. This tiles the views vertically,
// giving each child the available width.
virtual void Layout() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
// Override from View.
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
+ virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
// Painting.
- virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
+ virtual void PaintChildren(gfx::Canvas* canvas,
+ const views::CullSet& cull_view) OVERRIDE;
// Drag and drop methods. These are forwarded to the MenuController.
virtual bool GetDropFormats(
@@ -79,6 +83,12 @@ class VIEWS_EXPORT SubmenuView : public View,
// Scrolls on menu item boundaries.
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ // Overridden from PrefixDelegate.
+ virtual int GetRowCount() OVERRIDE;
+ virtual int GetSelectedRow() OVERRIDE;
+ virtual void SetSelectedRow(int row) OVERRIDE;
+ virtual base::string16 GetTextForRow(int row) OVERRIDE;
+
// Returns true if the menu is showing.
bool IsShowing();
@@ -191,7 +201,7 @@ class VIEWS_EXPORT SubmenuView : public View,
MenuScrollViewContainer* scroll_view_container_;
// See description above getter.
- int max_minor_text_width_;
+ mutable int max_minor_text_width_;
// Minimum width returned in GetPreferredSize().
int minimum_preferred_width_;
@@ -202,6 +212,14 @@ class VIEWS_EXPORT SubmenuView : public View,
// The submenu's scroll animator
scoped_ptr<ScrollAnimator> scroll_animator_;
+ // Difference between current position and cumulative deltas passed to
+ // OnScroll.
+ // TODO(tdresser): This should be removed when raw pixel scrolling for views
+ // is enabled. See crbug.com/329354.
+ float roundoff_error_;
+
+ PrefixSelector prefix_selector_;
+
DISALLOW_COPY_AND_ASSIGN(SubmenuView);
};
diff --git a/chromium/ui/views/controls/message_box_view.cc b/chromium/ui/views/controls/message_box_view.cc
index 3c2cde95292..671ca6194ec 100644
--- a/chromium/ui/views/controls/message_box_view.cc
+++ b/chromium/ui/views/controls/message_box_view.cc
@@ -8,7 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/views/controls/button/checkbox.h"
@@ -36,7 +36,7 @@ const int kDefaultMessageWidth = 320;
// 001C..001E ; B # Cc [3] <control-001C>..<control-001E>
// 0085 ; B # Cc <control-0085>
// 2029 ; B # Zp PARAGRAPH SEPARATOR
-bool IsParagraphSeparator(char16 c) {
+bool IsParagraphSeparator(base::char16 c) {
return ( c == 0x000A || c == 0x000D || c == 0x001C || c == 0x001D ||
c == 0x001E || c == 0x0085 || c == 0x2029);
}
@@ -44,8 +44,8 @@ bool IsParagraphSeparator(char16 c) {
// Splits |text| into a vector of paragraphs.
// Given an example "\nabc\ndef\n\n\nhij\n", the split results should be:
// "", "abc", "def", "", "", "hij", and "".
-void SplitStringIntoParagraphs(const string16& text,
- std::vector<string16>* paragraphs) {
+void SplitStringIntoParagraphs(const base::string16& text,
+ std::vector<base::string16>* paragraphs) {
paragraphs->clear();
size_t start = 0;
@@ -65,7 +65,7 @@ namespace views {
///////////////////////////////////////////////////////////////////////////////
// MessageBoxView, public:
-MessageBoxView::InitParams::InitParams(const string16& message)
+MessageBoxView::InitParams::InitParams(const base::string16& message)
: options(NO_OPTIONS),
message(message),
message_width(kDefaultMessageWidth),
@@ -85,8 +85,8 @@ MessageBoxView::MessageBoxView(const InitParams& params)
MessageBoxView::~MessageBoxView() {}
-string16 MessageBoxView::GetInputText() {
- return prompt_field_ ? prompt_field_->text() : string16();
+base::string16 MessageBoxView::GetInputText() {
+ return prompt_field_ ? prompt_field_->text() : base::string16();
}
bool MessageBoxView::IsCheckBoxSelected() {
@@ -101,7 +101,7 @@ void MessageBoxView::SetIcon(const gfx::ImageSkia& icon) {
ResetLayoutManager();
}
-void MessageBoxView::SetCheckBoxLabel(const string16& label) {
+void MessageBoxView::SetCheckBoxLabel(const base::string16& label) {
if (!checkbox_)
checkbox_ = new Checkbox(label);
else
@@ -115,7 +115,8 @@ void MessageBoxView::SetCheckBoxSelected(bool selected) {
checkbox_->SetChecked(selected);
}
-void MessageBoxView::SetLink(const string16& text, LinkListener* listener) {
+void MessageBoxView::SetLink(const base::string16& text,
+ LinkListener* listener) {
if (text.empty()) {
DCHECK(!listener);
delete link_;
@@ -132,8 +133,8 @@ void MessageBoxView::SetLink(const string16& text, LinkListener* listener) {
ResetLayoutManager();
}
-void MessageBoxView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_ALERT;
+void MessageBoxView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_ALERT;
}
///////////////////////////////////////////////////////////////////////////////
@@ -145,7 +146,7 @@ void MessageBoxView::ViewHierarchyChanged(
if (prompt_field_)
prompt_field_->SelectAll(true);
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
}
}
@@ -162,7 +163,7 @@ bool MessageBoxView::AcceleratorPressed(const ui::Accelerator& accelerator) {
return false;
ui::ScopedClipboardWriter scw(clipboard, ui::CLIPBOARD_TYPE_COPY_PASTE);
- string16 text = message_labels_[0]->text();
+ base::string16 text = message_labels_[0]->text();
for (size_t i = 1; i < message_labels_.size(); ++i)
text += message_labels_[i]->text();
scw.WriteText(text);
@@ -174,23 +175,15 @@ bool MessageBoxView::AcceleratorPressed(const ui::Accelerator& accelerator) {
void MessageBoxView::Init(const InitParams& params) {
if (params.options & DETECT_DIRECTIONALITY) {
- std::vector<string16> texts;
+ std::vector<base::string16> texts;
SplitStringIntoParagraphs(params.message, &texts);
- // If the text originates from a web page, its alignment is based on its
- // first character with strong directionality.
- base::i18n::TextDirection message_direction =
- base::i18n::GetFirstStrongCharacterDirection(params.message);
- gfx::HorizontalAlignment alignment =
- (message_direction == base::i18n::RIGHT_TO_LEFT) ?
- gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
for (size_t i = 0; i < texts.size(); ++i) {
Label* message_label = new Label(texts[i]);
- // Don't set multi-line to true if the text is empty, else the label will
- // have a height of 0.
+ // Avoid empty multi-line labels, which have a height of 0.
message_label->SetMultiLine(!texts[i].empty());
message_label->SetAllowCharacterBreak(true);
- message_label->set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
- message_label->SetHorizontalAlignment(alignment);
+ message_label->set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT);
+ message_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
message_labels_.push_back(message_label);
}
} else {
diff --git a/chromium/ui/views/controls/message_box_view.h b/chromium/ui/views/controls/message_box_view.h
index 1d92a379be4..cb708e6013d 100644
--- a/chromium/ui/views/controls/message_box_view.h
+++ b/chromium/ui/views/controls/message_box_view.h
@@ -42,12 +42,12 @@ class VIEWS_EXPORT MessageBoxView : public View {
};
struct VIEWS_EXPORT InitParams {
- explicit InitParams(const string16& message);
+ explicit InitParams(const base::string16& message);
~InitParams();
uint16 options;
- string16 message;
- string16 default_prompt;
+ base::string16 message;
+ base::string16 default_prompt;
int message_width;
int inter_row_vertical_spacing;
};
@@ -60,7 +60,7 @@ class VIEWS_EXPORT MessageBoxView : public View {
views::Textfield* text_box() { return prompt_field_; }
// Returns user entered data in the prompt field.
- string16 GetInputText();
+ base::string16 GetInputText();
// Returns true if a checkbox is selected, false otherwise. (And false if
// the message box has no checkbox.)
@@ -73,17 +73,17 @@ class VIEWS_EXPORT MessageBoxView : public View {
// Adds a checkbox with the specified label to the message box if this is the
// first call. Otherwise, it changes the label of the current checkbox. To
// start, the message box has no checkbox until this function is called.
- void SetCheckBoxLabel(const string16& label);
+ void SetCheckBoxLabel(const base::string16& label);
// Sets the state of the check-box.
void SetCheckBoxSelected(bool selected);
// Sets the text and the listener of the link. If |text| is empty, the link
// is removed.
- void SetLink(const string16& text, LinkListener* listener);
+ void SetLink(const base::string16& text, LinkListener* listener);
// View:
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
protected:
// View:
diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc
index 28b1fe3aec7..c1b230c452e 100644
--- a/chromium/ui/views/controls/native/native_view_host.cc
+++ b/chromium/ui/views/controls/native/native_view_host.cc
@@ -5,6 +5,7 @@
#include "ui/views/controls/native/native_view_host.h"
#include "base/logging.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/gfx/canvas.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/native/native_view_host_wrapper.h"
@@ -16,16 +17,6 @@ namespace views {
const char NativeViewHost::kViewClassName[] = "NativeViewHost";
const char kWidgetNativeViewHostKey[] = "WidgetNativeViewHost";
-#if defined(USE_AURA)
-// Views implementation draws the focus.
-// TODO(oshima): Eliminate this flag and consolidate
-// the focus border code.
-const bool NativeViewHost::kRenderNativeControlFocus = false;
-#else
-// static
-const bool NativeViewHost::kRenderNativeControlFocus = true;
-#endif
-
////////////////////////////////////////////////////////////////////////////////
// NativeViewHost, public:
@@ -74,7 +65,7 @@ void NativeViewHost::NativeViewDestroyed() {
////////////////////////////////////////////////////////////////////////////////
// NativeViewHost, View overrides:
-gfx::Size NativeViewHost::GetPreferredSize() {
+gfx::Size NativeViewHost::GetPreferredSize() const {
return preferred_size_;
}
@@ -182,7 +173,7 @@ const char* NativeViewHost::GetClassName() const {
void NativeViewHost::OnFocus() {
native_wrapper_->SetFocus();
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
}
gfx::NativeViewAccessible NativeViewHost::GetNativeViewAccessible() {
@@ -196,6 +187,10 @@ gfx::NativeViewAccessible NativeViewHost::GetNativeViewAccessible() {
return View::GetNativeViewAccessible();
}
+gfx::NativeCursor NativeViewHost::GetCursor(const ui::MouseEvent& event) {
+ return native_wrapper_->GetCursor(event.x(), event.y());
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeViewHost, private:
@@ -226,5 +221,4 @@ void NativeViewHost::ClearFocus() {
}
}
-
} // 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 bdc51510550..d5dd9b59fdb 100644
--- a/chromium/ui/views/controls/native/native_view_host.h
+++ b/chromium/ui/views/controls/native/native_view_host.h
@@ -28,9 +28,6 @@ class VIEWS_EXPORT NativeViewHost : public View {
// The NativeViewHost's class name.
static const char kViewClassName[];
- // Should views render the focus when on native controls?
- static const bool kRenderNativeControlFocus;
-
NativeViewHost();
virtual ~NativeViewHost();
@@ -80,12 +77,13 @@ class VIEWS_EXPORT NativeViewHost : public View {
void NativeViewDestroyed();
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
+ virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
protected:
virtual bool NeedsNotificationWhenVisibleBoundsChange() const OVERRIDE;
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 a71e230be47..49bf733bbe2 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/view_constants_aura.h"
#include "ui/views/widget/widget.h"
@@ -100,6 +101,12 @@ gfx::NativeViewAccessible NativeViewHostAura::GetNativeViewAccessible() {
return NULL;
}
+gfx::NativeCursor NativeViewHostAura::GetCursor(int x, int y) {
+ if (host_->native_view())
+ return host_->native_view()->GetCursor(gfx::Point(x, y));
+ return gfx::kNullCursor;
+}
+
void NativeViewHostAura::OnWindowDestroyed(aura::Window* window) {
DCHECK(window == host_->native_view());
host_->NativeViewDestroyed();
diff --git a/chromium/ui/views/controls/native/native_view_host_aura.h b/chromium/ui/views/controls/native/native_view_host_aura.h
index eba4b99c9fd..8ef4e455f3d 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.h
+++ b/chromium/ui/views/controls/native/native_view_host_aura.h
@@ -34,6 +34,7 @@ class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
virtual void HideWidget() OVERRIDE;
virtual void SetFocus() OVERRIDE;
virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
+ virtual gfx::NativeCursor GetCursor(int x, int y) OVERRIDE;
private:
// Overridden from aura::WindowObserver:
diff --git a/chromium/ui/views/controls/native/native_view_host_aura_unittest.cc b/chromium/ui/views/controls/native/native_view_host_aura_unittest.cc
index 7653cc905c3..f6dc561f2f0 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura_unittest.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura_unittest.cc
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
@@ -24,6 +25,10 @@ class NativeViewHostAuraTest : public ViewsTestBase {
return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get());
}
+ Widget* toplevel() {
+ return toplevel_.get();
+ }
+
NativeViewHost* host() {
return host_.get();
}
@@ -95,4 +100,18 @@ TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) {
EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey));
}
+// Tests that the NativeViewHost reports the cursor set on its native view.
+TEST_F(NativeViewHostAuraTest, CursorForNativeView) {
+ CreateHost();
+
+ toplevel()->SetCursor(ui::kCursorHand);
+ child()->SetCursor(ui::kCursorWait);
+ ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
+ gfx::Point(0, 0), 0, 0);
+
+ EXPECT_EQ(ui::kCursorWait, host()->GetCursor(move_event).native_type());
+
+ DestroyHost();
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.cc b/chromium/ui/views/controls/native/native_view_host_mac.cc
new file mode 100644
index 00000000000..53bb00b7a0e
--- /dev/null
+++ b/chromium/ui/views/controls/native/native_view_host_mac.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/native/native_view_host_wrapper.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeViewHostWrapper, public:
+
+// static
+NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
+ NativeViewHost* host) {
+ return NULL;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/native/native_view_host_unittest.cc b/chromium/ui/views/controls/native/native_view_host_unittest.cc
index f30980bca8b..247782437a5 100644
--- a/chromium/ui/views/controls/native/native_view_host_unittest.cc
+++ b/chromium/ui/views/controls/native/native_view_host_unittest.cc
@@ -4,19 +4,12 @@
#include "ui/views/controls/native/native_view_host.h"
-#if defined(OS_WIN) && !defined(USE_AURA)
-#include <windows.h>
-#endif
-
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/aura/window.h"
-#endif
-
namespace views {
class NativeViewHostTest : public ViewsTestBase {
@@ -93,15 +86,9 @@ class NativeViewHierarchyChangedTestView : public View {
DISALLOW_COPY_AND_ASSIGN(NativeViewHierarchyChangedTestView);
};
-#if defined(USE_AURA)
aura::Window* GetNativeParent(aura::Window* window) {
return window->parent();
}
-#elif defined(OS_WIN)
-HWND GetNativeParent(HWND window) {
- return GetParent(window);
-}
-#endif
class ViewHierarchyChangedTestHost : public NativeViewHost {
public:
diff --git a/chromium/ui/views/controls/native/native_view_host_win.cc b/chromium/ui/views/controls/native/native_view_host_win.cc
deleted file mode 100644
index e7b74c3c7a1..00000000000
--- a/chromium/ui/views/controls/native/native_view_host_win.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/native/native_view_host_win.h"
-
-#include <oleacc.h>
-
-#include "base/logging.h"
-#include "ui/base/win/hidden_window.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/window_impl.h"
-#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/widget/native_widget.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeViewHostWin, public:
-
-NativeViewHostWin::NativeViewHostWin(NativeViewHost* host)
- : host_(host),
- installed_clip_(false) {
-}
-
-NativeViewHostWin::~NativeViewHostWin() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeViewHostWin, NativeViewHostWrapper implementation:
-void NativeViewHostWin::NativeViewWillAttach() {
- // First hide the new window. We don't want anything to draw (like sub-hwnd
- // borders), when NativeViewHost changes the parent.
- ShowWindow(host_->native_view(), SW_HIDE);
-}
-
-void NativeViewHostWin::NativeViewDetaching(bool destroyed) {
- if (!destroyed) {
- if (installed_clip_)
- UninstallClip();
- Widget::ReparentNativeView(host_->native_view(), ui::GetHiddenWindow());
- }
- installed_clip_ = false;
-}
-
-void NativeViewHostWin::AddedToWidget() {
- if (!IsWindow(host_->native_view()))
- return;
- HWND parent_hwnd = GetParent(host_->native_view());
- HWND widget_hwnd = host_->GetWidget()->GetNativeView();
- if (parent_hwnd != widget_hwnd)
- SetParent(host_->native_view(), widget_hwnd);
- if (host_->IsDrawn())
- ShowWindow(host_->native_view(), SW_SHOW);
- else
- ShowWindow(host_->native_view(), SW_HIDE);
- host_->Layout();
-}
-
-void NativeViewHostWin::RemovedFromWidget() {
- if (!IsWindow(host_->native_view()))
- return;
- ShowWindow(host_->native_view(), SW_HIDE);
- SetParent(host_->native_view(), NULL);
-}
-
-void NativeViewHostWin::InstallClip(int x, int y, int w, int h) {
- HRGN clip_region = CreateRectRgn(x, y, x + w, y + h);
- // NOTE: SetWindowRgn owns the region (as well as the deleting the
- // current region), as such we don't delete the old region.
- SetWindowRgn(host_->native_view(), clip_region, TRUE);
- installed_clip_ = true;
-}
-
-bool NativeViewHostWin::HasInstalledClip() {
- return installed_clip_;
-}
-
-void NativeViewHostWin::UninstallClip() {
- SetWindowRgn(host_->native_view(), 0, TRUE);
- installed_clip_ = false;
-}
-
-void NativeViewHostWin::ShowWidget(int x, int y, int w, int h) {
- UINT swp_flags = SWP_DEFERERASE |
- SWP_NOACTIVATE |
- SWP_NOCOPYBITS |
- SWP_NOOWNERZORDER |
- SWP_NOZORDER;
- gfx::Rect bounds = gfx::win::DIPToScreenRect(gfx::Rect(x,y,w,h));
-
- // Only send the SHOWWINDOW flag if we're invisible, to avoid flashing.
- if (!IsWindowVisible(host_->native_view()))
- swp_flags = (swp_flags | SWP_SHOWWINDOW) & ~SWP_NOREDRAW;
-
- if (host_->fast_resize()) {
- // In a fast resize, we move the window and clip it with SetWindowRgn.
- RECT win_rect;
- GetWindowRect(host_->native_view(), &win_rect);
- gfx::Rect rect(win_rect);
- SetWindowPos(host_->native_view(), 0, bounds.x(), bounds.y(),
- rect.width(), rect.height(),
- swp_flags);
-
- InstallClip(0, 0, bounds.width(), bounds.height());
- } else {
- SetWindowPos(host_->native_view(), 0, bounds.x(), bounds.y(),
- bounds.width(), bounds.height(), swp_flags);
- }
-}
-
-void NativeViewHostWin::HideWidget() {
- if (!IsWindowVisible(host_->native_view()))
- return; // Currently not visible, nothing to do.
-
- // The window is currently visible, but its clipped by another view. Hide
- // it.
- SetWindowPos(host_->native_view(), 0, 0, 0, 0, 0,
- SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
- SWP_NOREDRAW | SWP_NOOWNERZORDER);
-}
-
-void NativeViewHostWin::SetFocus() {
- ::SetFocus(host_->native_view());
-}
-
-gfx::NativeViewAccessible NativeViewHostWin::GetNativeViewAccessible() {
- HWND hwnd = host_->native_view();
- if (!IsWindow(hwnd))
- return NULL;
-
- IAccessible* accessible = NULL;
- HRESULT success = ::AccessibleObjectFromWindow(
- hwnd, OBJID_CLIENT, IID_IAccessible,
- reinterpret_cast<void**>(&accessible));
-
- if (success == S_OK) {
- return accessible;
- } else {
- return NULL;
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeViewHostWrapper, public:
-
-// static
-NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
- NativeViewHost* host) {
- return new NativeViewHostWin(host);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/native/native_view_host_win.h b/chromium/ui/views/controls/native/native_view_host_win.h
deleted file mode 100644
index ea94b351ea3..00000000000
--- a/chromium/ui/views/controls/native/native_view_host_win.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WIN_H_
-#define UI_VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WIN_H_
-
-#include "base/basictypes.h"
-#include "ui/views/controls/native/native_view_host_wrapper.h"
-
-namespace views {
-
-class NativeViewHost;
-
-// A Windows implementation of NativeViewHostWrapper
-class NativeViewHostWin : public NativeViewHostWrapper {
- public:
- explicit NativeViewHostWin(NativeViewHost* host);
- virtual ~NativeViewHostWin();
-
- // Overridden from NativeViewHostWrapper:
- virtual void NativeViewWillAttach();
- virtual void NativeViewDetaching(bool destroyed);
- virtual void AddedToWidget();
- virtual void RemovedFromWidget();
- virtual void InstallClip(int x, int y, int w, int h);
- virtual bool HasInstalledClip();
- virtual void UninstallClip();
- virtual void ShowWidget(int x, int y, int w, int h);
- virtual void HideWidget();
- virtual void SetFocus();
- virtual gfx::NativeViewAccessible GetNativeViewAccessible();
-
- private:
- // Our associated NativeViewHost.
- NativeViewHost* host_;
-
- // Have we installed a region on the gfx::NativeView used to clip to only the
- // visible portion of the gfx::NativeView ?
- bool installed_clip_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeViewHostWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_NATIVE_NATIVE_VIEW_HOST_WIN_H_
diff --git a/chromium/ui/views/controls/native/native_view_host_wrapper.h b/chromium/ui/views/controls/native/native_view_host_wrapper.h
index 3b3cb37fbdc..306aa0148bb 100644
--- a/chromium/ui/views/controls/native/native_view_host_wrapper.h
+++ b/chromium/ui/views/controls/native/native_view_host_wrapper.h
@@ -62,6 +62,10 @@ class VIEWS_EXPORT NativeViewHostWrapper {
// view.
virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0;
+ // Returns the native cursor corresponding to the point (x, y)
+ // in the native view.
+ virtual gfx::NativeCursor GetCursor(int x, int y) = 0;
+
// Creates a platform-specific instance of an object implementing this
// interface.
static NativeViewHostWrapper* CreateWrapper(NativeViewHost* host);
diff --git a/chromium/ui/views/controls/native_control.cc b/chromium/ui/views/controls/native_control.cc
deleted file mode 100644
index faebbc81f90..00000000000
--- a/chromium/ui/views/controls/native_control.cc
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/native_control.h"
-
-#include <atlbase.h>
-#include <atlapp.h>
-#include <atlcrack.h>
-#include <atlframe.h>
-#include <atlmisc.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/base/accessibility/accessibility_types.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/view_prop.h"
-#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/widget/widget.h"
-
-using ui::ViewProp;
-
-namespace views {
-
-// Maps to the NativeControl.
-static const char* const kNativeControlKey = "__NATIVE_CONTROL__";
-
-class NativeControlContainer : public CWindowImpl<NativeControlContainer,
- CWindow,
- CWinTraits<WS_CHILD | WS_CLIPSIBLINGS |
- WS_CLIPCHILDREN>> {
- public:
- explicit NativeControlContainer(NativeControl* parent)
- : parent_(parent),
- control_(NULL),
- original_handler_(NULL) {
- }
-
- void Init() {
- Create(parent_->GetWidget()->GetNativeView());
- ::ShowWindow(m_hWnd, SW_SHOW);
- }
-
- virtual ~NativeControlContainer() {
- }
-
- // NOTE: If you add a new message, be sure and verify parent_ is valid before
- // calling into parent_.
- DECLARE_FRAME_WND_CLASS(L"ChromeViewsNativeControlContainer", NULL);
- BEGIN_MSG_MAP(NativeControlContainer);
- MSG_WM_CREATE(OnCreate);
- MSG_WM_ERASEBKGND(OnEraseBkgnd);
- MSG_WM_PAINT(OnPaint);
- MSG_WM_SIZE(OnSize);
- MSG_WM_NOTIFY(OnNotify);
- MSG_WM_COMMAND(OnCommand);
- MSG_WM_DESTROY(OnDestroy);
- MSG_WM_CONTEXTMENU(OnContextMenu);
- MSG_WM_CTLCOLORBTN(OnCtlColorBtn);
- MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic)
- END_MSG_MAP();
-
- HWND GetControl() {
- return control_;
- }
-
- // Called when the parent is getting deleted. This control stays around until
- // it gets the OnFinalMessage call.
- void ResetParent() {
- parent_ = NULL;
- }
-
- void OnFinalMessage(HWND hwnd) {
- if (parent_)
- parent_->NativeControlDestroyed();
- delete this;
- }
-
- private:
- friend class NativeControl;
-
- LRESULT OnCreate(LPCREATESTRUCT create_struct) {
- control_ = parent_->CreateNativeControl(m_hWnd);
-
- // We subclass the control hwnd so we get the WM_KEYDOWN messages.
- original_handler_ = gfx::SetWindowProc(
- control_, &NativeControl::NativeControlWndProc);
- prop_.reset(new ViewProp(control_, kNativeControlKey , parent_));
-
- ::ShowWindow(control_, SW_SHOW);
- return 1;
- }
-
- LRESULT OnEraseBkgnd(HDC dc) {
- return 1;
- }
-
- void OnPaint(HDC ignore) {
- PAINTSTRUCT ps;
- HDC dc = ::BeginPaint(*this, &ps);
- ::EndPaint(*this, &ps);
- }
-
- void OnSize(int type, const CSize& sz) {
- ::MoveWindow(control_, 0, 0, sz.cx, sz.cy, TRUE);
- }
-
- LRESULT OnCommand(UINT code, int id, HWND source) {
- return parent_ ? parent_->OnCommand(code, id, source) : 0;
- }
-
- LRESULT OnNotify(int w_param, LPNMHDR l_param) {
- if (parent_)
- return parent_->OnNotify(w_param, l_param);
- else
- return 0;
- }
-
- void OnDestroy() {
- if (parent_)
- parent_->OnDestroy();
- }
-
- void OnContextMenu(HWND window, const POINT& location) {
- if (parent_)
- parent_->OnContextMenu(location);
- }
-
- // We need to find an ancestor with a non-null background, and
- // ask it for a (solid color) brush that approximates
- // the background. The caller will use this when drawing
- // the native control as a background color, particularly
- // for radiobuttons and XP style pushbuttons.
- LRESULT OnCtlColor(UINT msg, HDC dc, HWND control) {
- const View *ancestor = parent_;
- while (ancestor) {
- const Background *background = ancestor->background();
- if (background) {
- HBRUSH brush = background->GetNativeControlBrush();
- if (brush)
- return reinterpret_cast<LRESULT>(brush);
- }
- ancestor = ancestor->parent();
- }
-
- // COLOR_BTNFACE is the default for dialog box backgrounds.
- return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_BTNFACE));
- }
-
- LRESULT OnCtlColorBtn(HDC dc, HWND control) {
- return OnCtlColor(WM_CTLCOLORBTN, dc, control);
- }
-
- LRESULT OnCtlColorStatic(HDC dc, HWND control) {
- return OnCtlColor(WM_CTLCOLORSTATIC, dc, control);
- }
-
- NativeControl* parent_;
- HWND control_;
-
- // Message handler that was set before we reset it.
- WNDPROC original_handler_;
-
- scoped_ptr<ViewProp> prop_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeControlContainer);
-};
-
-NativeControl::NativeControl() : hwnd_view_(NULL),
- container_(NULL),
- fixed_width_(-1),
- horizontal_alignment_(CENTER),
- fixed_height_(-1),
- vertical_alignment_(CENTER) {
- SetFocusable(true);
-}
-
-NativeControl::~NativeControl() {
- if (container_) {
- container_->ResetParent();
- ::DestroyWindow(*container_);
- }
-}
-
-void NativeControl::ValidateNativeControl() {
- if (hwnd_view_ == NULL) {
- hwnd_view_ = new NativeViewHost;
- AddChildView(hwnd_view_);
- }
-
- if (!container_ && visible()) {
- container_ = new NativeControlContainer(this);
- container_->Init();
- hwnd_view_->Attach(*container_);
- if (!enabled())
- EnableWindow(GetNativeControlHWND(), enabled());
-
- // This message ensures that the focus border is shown.
- ::SendMessage(container_->GetControl(),
- WM_CHANGEUISTATE,
- MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS),
- 0);
- }
-}
-
-void NativeControl::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (details.is_add && details.parent != this && !container_ && GetWidget()) {
- ValidateNativeControl();
- Layout();
- }
-}
-
-void NativeControl::Layout() {
- if (!container_ && GetWidget())
- ValidateNativeControl();
-
- if (hwnd_view_) {
- gfx::Rect lb = GetLocalBounds();
-
- int x = lb.x();
- int y = lb.y();
- int width = lb.width();
- int height = lb.height();
- if (fixed_width_ > 0) {
- width = std::min(fixed_width_, width);
- switch (horizontal_alignment_) {
- case LEADING:
- // Nothing to do.
- break;
- case CENTER:
- x += (lb.width() - width) / 2;
- break;
- case TRAILING:
- x = x + lb.width() - width;
- break;
- default:
- NOTREACHED();
- }
- }
-
- if (fixed_height_ > 0) {
- height = std::min(fixed_height_, height);
- switch (vertical_alignment_) {
- case LEADING:
- // Nothing to do.
- break;
- case CENTER:
- y += (lb.height() - height) / 2;
- break;
- case TRAILING:
- y = y + lb.height() - height;
- break;
- default:
- NOTREACHED();
- }
- }
-
- hwnd_view_->SetBounds(x, y, width, height);
- }
-}
-
-void NativeControl::OnContextMenu(const POINT& location) {
- if (!context_menu_controller())
- return;
-
- if (location.x == -1 && location.y == -1) {
- ShowContextMenu(GetKeyboardContextMenuLocation(),
- ui::MENU_SOURCE_KEYBOARD);
- } else {
- ShowContextMenu(gfx::Point(location), ui::MENU_SOURCE_MOUSE);
- }
-}
-
-void NativeControl::OnFocus() {
- if (container_) {
- DCHECK(container_->GetControl());
- ::SetFocus(container_->GetControl());
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, false);
- }
-}
-
-HWND NativeControl::GetNativeControlHWND() {
- if (container_)
- return container_->GetControl();
- else
- return NULL;
-}
-
-void NativeControl::NativeControlDestroyed() {
- if (hwnd_view_)
- hwnd_view_->Detach();
- container_ = NULL;
-}
-
-void NativeControl::SetVisible(bool is_visible) {
- if (is_visible != visible()) {
- View::SetVisible(is_visible);
- if (!is_visible && container_)
- ::DestroyWindow(*container_);
- else if (is_visible && !container_)
- ValidateNativeControl();
- }
-}
-
-void NativeControl::OnEnabledChanged() {
- View::OnEnabledChanged();
- if (GetNativeControlHWND())
- EnableWindow(GetNativeControlHWND(), enabled());
-}
-
-void NativeControl::OnPaint(gfx::Canvas* canvas) {
-}
-
-void NativeControl::VisibilityChanged(View* starting_from, bool is_visible) {
- SetVisible(is_visible);
-}
-
-void NativeControl::SetFixedWidth(int width, Alignment alignment) {
- DCHECK_GT(width, 0);
- fixed_width_ = width;
- horizontal_alignment_ = alignment;
-}
-
-void NativeControl::SetFixedHeight(int height, Alignment alignment) {
- DCHECK_GT(height, 0);
- fixed_height_ = height;
- vertical_alignment_ = alignment;
-}
-
-DWORD NativeControl::GetAdditionalExStyle() const {
- // If the UI for the view is mirrored, we should make sure we add the
- // extended window style for a right-to-left layout so the subclass creates
- // a mirrored HWND for the underlying control.
- DWORD ex_style = 0;
- if (base::i18n::IsRTL())
- ex_style |= l10n_util::GetExtendedStyles();
-
- return ex_style;
-}
-
-DWORD NativeControl::GetAdditionalRTLStyle() const {
- // If the UI for the view is mirrored, we should make sure we add the
- // extended window style for a right-to-left layout so the subclass creates
- // a mirrored HWND for the underlying control.
- DWORD ex_style = 0;
- if (base::i18n::IsRTL())
- ex_style |= l10n_util::GetExtendedTooltipStyles();
-
- return ex_style;
-}
-
-// static
-LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- NativeControl* native_control = static_cast<NativeControl*>(
- ViewProp::GetValue(window, kNativeControlKey));
- DCHECK(native_control);
- WNDPROC original_handler = native_control->container_->original_handler_;
- DCHECK(original_handler);
-
- if (message == WM_KEYDOWN &&
- native_control->OnKeyDown(ui::KeyboardCodeForWindowsKeyCode(w_param))) {
- return 0;
- } else if (message == WM_SETFOCUS) {
- // Let the focus manager know that the focus changed.
- FocusManager* focus_manager = native_control->GetFocusManager();
- if (focus_manager) {
- focus_manager->SetFocusedView(native_control);
- } else {
- NOTREACHED();
- }
- } else if (message == WM_DESTROY) {
- gfx::SetWindowProc(window, reinterpret_cast<WNDPROC>(original_handler));
- native_control->container_->prop_.reset();
- }
-
- return CallWindowProc(reinterpret_cast<WNDPROC>(original_handler), window,
- message, w_param, l_param);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/native_control.h b/chromium/ui/views/controls/native_control.h
deleted file mode 100644
index 80aa5887cf1..00000000000
--- a/chromium/ui/views/controls/native_control.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_NATIVE_CONTROL_H_
-#define UI_VIEWS_CONTROLS_NATIVE_CONTROL_H_
-
-#include <windows.h>
-
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/views/view.h"
-
-namespace views {
-
-class NativeViewHost;
-class NativeControlContainer;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// NativeControl is an abstract view that is used to implement views wrapping
-// native controls. Subclasses can simply implement CreateNativeControl() to
-// wrap a new kind of control
-//
-////////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT NativeControl : public View {
- public:
- enum Alignment {
- LEADING = 0,
- CENTER,
- TRAILING };
-
- NativeControl();
- virtual ~NativeControl();
-
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE;
- virtual void Layout();
-
- // Overridden to properly set the native control state.
- virtual void SetVisible(bool f);
- virtual void OnEnabledChanged();
-
- // Overridden to do nothing.
- virtual void OnPaint(gfx::Canvas* canvas);
-
- protected:
- friend class NativeControlContainer;
-
- // Overridden by sub-classes to create the windows control which is wrapped
- virtual HWND CreateNativeControl(HWND parent_container) = 0;
-
- // Invoked when the native control sends a WM_NOTIFY message to its parent
- virtual LRESULT OnNotify(int w_param, LPNMHDR l_param) = 0;
-
- // Invoked when the native control sends a WM_COMMAND message to its parent
- virtual LRESULT OnCommand(UINT code, int id, HWND source) { return 0; }
-
- // Invoked when the appropriate gesture for a context menu is issued.
- virtual void OnContextMenu(const POINT& location);
-
- // Overridden so to set the native focus to the native control.
- virtual void OnFocus();
-
- // Invoked when the native control sends a WM_DESTORY message to its parent.
- virtual void OnDestroy() { }
-
- // Return the native control
- virtual HWND GetNativeControlHWND();
-
- // Invoked by the native windows control when it has been destroyed. This is
- // invoked AFTER WM_DESTORY has been sent. Any window commands send to the
- // HWND will most likely fail.
- void NativeControlDestroyed();
-
- // Overridden so that the control properly reflects parent's visibility.
- virtual void VisibilityChanged(View* starting_from, bool is_visible);
-
- // Controls that have fixed sizes should call these methods to specify the
- // actual size and how they should be aligned within their parent.
- void SetFixedWidth(int width, Alignment alignment);
- void SetFixedHeight(int height, Alignment alignment);
-
- // Invoked when a key is pressed on the control.
- // Should return true if the key message was processed, false otherwise.
- virtual bool OnKeyDown(ui::KeyboardCode virtual_key_code) { return false; }
-
- // Returns additional extended style flags. When subclasses call
- // CreateWindowEx in order to create the underlying control, they must OR the
- // ExStyle parameter with the value returned by this function.
- //
- // We currently use this method in order to add flags such as WS_EX_LAYOUTRTL
- // to the HWND for views with right-to-left UI layout.
- DWORD GetAdditionalExStyle() const;
-
- // TODO(xji): we use the following temporary function as we transition the
- // various native controls to use the right set of RTL flags. This function
- // will go away (and be replaced by GetAdditionalExStyle()) once all the
- // controls are properly transitioned.
- DWORD GetAdditionalRTLStyle() const;
-
- // This variable is protected to provide subclassers direct access. However
- // subclassers should always check for NULL since this variable is only
- // initialized in ValidateNativeControl().
- NativeViewHost* hwnd_view_;
-
- // Fixed size information. -1 for a size means no fixed size.
- int fixed_width_;
- Alignment horizontal_alignment_;
- int fixed_height_;
- Alignment vertical_alignment_;
-
- private:
-
- void ValidateNativeControl();
-
- static LRESULT CALLBACK NativeControlWndProc(HWND window, UINT message,
- WPARAM w_param, LPARAM l_param);
-
- NativeControlContainer* container_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeControl);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_NATIVE_CONTROL_H_
diff --git a/chromium/ui/views/controls/native_control_win.cc b/chromium/ui/views/controls/native_control_win.cc
deleted file mode 100644
index c50411d13f5..00000000000
--- a/chromium/ui/views/controls/native_control_win.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/native_control_win.h"
-
-#include <windowsx.h>
-
-#include "base/logging.h"
-#include "ui/base/accessibility/accessibility_types.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/view_prop.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/views/controls/combobox/combobox.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/widget/widget.h"
-
-using ui::ViewProp;
-
-const char kNativeControlWinKey[] = "__NATIVE_CONTROL_WIN__";
-
-namespace views {
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeControlWin, public:
-
-NativeControlWin::NativeControlWin() : original_wndproc_(NULL) {
-}
-
-NativeControlWin::~NativeControlWin() {
- HWND hwnd = native_view();
- if (hwnd) {
- // Destroy the hwnd if it still exists. Otherwise we won't have shut things
- // down correctly, leading to leaking and crashing if another message
- // comes in for the hwnd.
- Detach();
- DestroyWindow(hwnd);
- }
-}
-
-bool NativeControlWin::ProcessMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) {
- switch (message) {
- case WM_CONTEXTMENU:
- ShowContextMenu(gfx::Point(GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param)));
- *result = 0;
- return true;
- case WM_CTLCOLORBTN:
- case WM_CTLCOLORSTATIC:
- *result = GetControlColor(message, reinterpret_cast<HDC>(w_param),
- native_view());
- return true;
- }
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeControlWin, View overrides:
-
-void NativeControlWin::OnEnabledChanged() {
- View::OnEnabledChanged();
- if (native_view())
- EnableWindow(native_view(), enabled());
-}
-
-void NativeControlWin::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- // Call the base class to hide the view if we're being removed.
- NativeViewHost::ViewHierarchyChanged(details);
-
- // Create the HWND when we're added to a valid Widget. Many controls need a
- // parent HWND to function properly.
- if (details.is_add && GetWidget() && !native_view())
- CreateNativeControl();
-}
-
-void NativeControlWin::VisibilityChanged(View* starting_from, bool is_visible) {
- // We might get called due to visibility changes at any point in the
- // hierarchy, lets check whether we are really visible or not.
- bool is_drawn = IsDrawn();
- if (!is_drawn && native_view()) {
- // We destroy the child control HWND when we become invisible because of the
- // performance cost of maintaining many HWNDs.
- HWND hwnd = native_view();
- Detach();
- DestroyWindow(hwnd);
- } else if (is_drawn && !native_view()) {
- if (GetWidget())
- CreateNativeControl();
- }
- if (is_drawn) {
- // The view becomes visible after native control is created.
- // Layout now.
- Layout();
- }
-}
-
-void NativeControlWin::OnFocus() {
- DCHECK(native_view());
- SetFocus(native_view());
-
- // Since we are being wrapped by a view, accessibility should receive
- // the super class as the focused view.
- View* parent_view = parent();
-
- // Due to some controls not behaving as expected without having
- // a native win32 control, we don't always send a native (MSAA)
- // focus notification.
- bool send_native_event =
- strcmp(parent_view->GetClassName(), Combobox::kViewClassName) &&
- parent_view->HasFocus();
-
- // Send the accessibility focus notification.
- parent_view->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_FOCUS, send_native_event);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeControlWin, protected:
-
-void NativeControlWin::ShowContextMenu(const gfx::Point& location) {
- if (!context_menu_controller())
- return;
-
- if (location.x() == -1 && location.y() == -1) {
- View::ShowContextMenu(GetKeyboardContextMenuLocation(),
- ui::MENU_SOURCE_KEYBOARD);
- } else {
- View::ShowContextMenu(location, ui::MENU_SOURCE_MOUSE);
- }
-}
-
-void NativeControlWin::NativeControlCreated(HWND native_control) {
- // Associate this object with the control's HWND so that NativeWidgetWin can
- // find this object when it receives messages from it.
- props_.push_back(new ViewProp(native_control, kNativeControlWinKey, this));
- props_.push_back(ChildWindowMessageProcessor::Register(native_control, this));
-
- // Subclass so we get WM_KEYDOWN and WM_SETFOCUS messages.
- original_wndproc_ = gfx::SetWindowProc(
- native_control, &NativeControlWin::NativeControlWndProc);
-
- Attach(native_control);
- // native_view() is now valid.
-
- // Update the newly created HWND with any resident enabled state.
- EnableWindow(native_view(), enabled());
-
- // This message ensures that the focus border is shown.
- SendMessage(native_view(), WM_CHANGEUISTATE,
- MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
-}
-
-DWORD NativeControlWin::GetAdditionalExStyle() const {
- // If the UI for the view is mirrored, we should make sure we add the
- // extended window style for a right-to-left layout so the subclass creates
- // a mirrored HWND for the underlying control.
- DWORD ex_style = 0;
- if (base::i18n::IsRTL())
- ex_style |= l10n_util::GetExtendedStyles();
-
- return ex_style;
-}
-
-DWORD NativeControlWin::GetAdditionalRTLStyle() const {
- // If the UI for the view is mirrored, we should make sure we add the
- // extended window style for a right-to-left layout so the subclass creates
- // a mirrored HWND for the underlying control.
- DWORD ex_style = 0;
- if (base::i18n::IsRTL())
- ex_style |= l10n_util::GetExtendedTooltipStyles();
-
- return ex_style;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeControlWin, private:
-
-LRESULT NativeControlWin::GetControlColor(UINT message, HDC dc, HWND sender) {
- View *ancestor = this;
- while (ancestor) {
- const Background* background = ancestor->background();
- if (background) {
- HBRUSH brush = background->GetNativeControlBrush();
- if (brush)
- return reinterpret_cast<LRESULT>(brush);
- }
- ancestor = ancestor->parent();
- }
-
- // COLOR_BTNFACE is the default for dialog box backgrounds.
- return reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_BTNFACE));
-}
-
-// static
-LRESULT NativeControlWin::NativeControlWndProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- NativeControlWin* native_control = reinterpret_cast<NativeControlWin*>(
- ViewProp::GetValue(window, kNativeControlWinKey));
- DCHECK(native_control);
-
- if (message == WM_KEYDOWN &&
- native_control->OnKeyDown(static_cast<int>(w_param))) {
- return 0;
- } else if (message == WM_SETFOCUS) {
- // Let the focus manager know that the focus changed.
- FocusManager* focus_manager = native_control->GetFocusManager();
- if (focus_manager) {
- focus_manager->SetFocusedView(native_control->focus_view());
- } else {
- NOTREACHED();
- }
- } else if (message == WM_DESTROY) {
- native_control->props_.clear();
- gfx::SetWindowProc(window, native_control->original_wndproc_);
- }
-
- return CallWindowProc(native_control->original_wndproc_, window, message,
- w_param, l_param);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/native_control_win.h b/chromium/ui/views/controls/native_control_win.h
deleted file mode 100644
index 3ee5681f1dc..00000000000
--- a/chromium/ui/views/controls/native_control_win.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
-#define UI_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_vector.h"
-#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/widget/child_window_message_processor.h"
-
-namespace ui {
-class ViewProp;
-}
-
-namespace views {
-
-// A View that hosts a native Windows control.
-class NativeControlWin : public ChildWindowMessageProcessor,
- public NativeViewHost {
- public:
- NativeControlWin();
- virtual ~NativeControlWin();
-
- // Called by our subclassed window procedure when a WM_KEYDOWN message is
- // received by the HWND created by an object derived from NativeControlWin.
- // Returns true if the key was processed, false otherwise.
- virtual bool OnKeyDown(int vkey) { return false; }
-
- // Overridden from ChildWindowMessageProcessor:
- virtual bool ProcessMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) OVERRIDE;
-
- // Overridden from View:
- virtual void OnEnabledChanged() OVERRIDE;
-
- protected:
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE;
- virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE;
- virtual void OnFocus() OVERRIDE;
-
- // Called by the containing NativeWidgetWin when a WM_CONTEXTMENU message is
- // received from the HWND created by an object derived from NativeControlWin.
- virtual void ShowContextMenu(const gfx::Point& location);
-
- // Called when the NativeControlWin is attached to a View hierarchy with a
- // valid Widget. The NativeControlWin should use this opportunity to create
- // its associated HWND.
- virtual void CreateNativeControl() = 0;
-
- // MUST be called by the subclass implementation of |CreateNativeControl|
- // immediately after creating the control HWND, otherwise it won't be attached
- // to the NativeViewHost and will be effectively orphaned.
- virtual void NativeControlCreated(HWND native_control);
-
- // Returns additional extended style flags. When subclasses call
- // CreateWindowEx in order to create the underlying control, they must OR the
- // ExStyle parameter with the value returned by this function.
- //
- // We currently use this method in order to add flags such as WS_EX_LAYOUTRTL
- // to the HWND for views with right-to-left UI layout.
- DWORD GetAdditionalExStyle() const;
-
- // TODO(xji): we use the following temporary function as we transition the
- // various native controls to use the right set of RTL flags. This function
- // will go away (and be replaced by GetAdditionalExStyle()) once all the
- // controls are properly transitioned.
- DWORD GetAdditionalRTLStyle() const;
-
- private:
- typedef ScopedVector<ui::ViewProp> ViewProps;
-
- // Called by the containing NativeWidgetWin when a message of type
- // WM_CTLCOLORBTN or WM_CTLCOLORSTATIC is sent from the HWND created by an
- // object derived from NativeControlWin.
- LRESULT GetControlColor(UINT message, HDC dc, HWND sender);
-
- // Our subclass window procedure for the attached control.
- static LRESULT CALLBACK NativeControlWndProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param);
-
- // The window procedure before we subclassed.
- WNDPROC original_wndproc_;
-
- ViewProps props_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeControlWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
diff --git a/chromium/ui/views/controls/prefix_delegate.h b/chromium/ui/views/controls/prefix_delegate.h
index 41d30d43cc8..07d85989f0e 100644
--- a/chromium/ui/views/controls/prefix_delegate.h
+++ b/chromium/ui/views/controls/prefix_delegate.h
@@ -23,7 +23,7 @@ class VIEWS_EXPORT PrefixDelegate : public View {
virtual void SetSelectedRow(int row) = 0;
// Returns the item at the specified row.
- virtual string16 GetTextForRow(int row) = 0;
+ virtual base::string16 GetTextForRow(int row) = 0;
protected:
virtual ~PrefixDelegate() {}
diff --git a/chromium/ui/views/controls/prefix_selector.cc b/chromium/ui/views/controls/prefix_selector.cc
index d66a0346c84..c901edd2c11 100644
--- a/chromium/ui/views/controls/prefix_selector.cc
+++ b/chromium/ui/views/controls/prefix_selector.cc
@@ -47,12 +47,12 @@ void PrefixSelector::ConfirmCompositionText() {
void PrefixSelector::ClearCompositionText() {
}
-void PrefixSelector::InsertText(const string16& text) {
+void PrefixSelector::InsertText(const base::string16& text) {
OnTextInput(text);
}
-void PrefixSelector::InsertChar(char16 ch, int flags) {
- OnTextInput(string16(1, ch));
+void PrefixSelector::InsertChar(base::char16 ch, int flags) {
+ OnTextInput(base::string16(1, ch));
}
gfx::NativeWindow PrefixSelector::GetAttachedWindow() const {
@@ -115,7 +115,7 @@ bool PrefixSelector::DeleteRange(const gfx::Range& range) {
}
bool PrefixSelector::GetTextFromRange(const gfx::Range& range,
- string16* text) const {
+ base::string16* text) const {
return false;
}
@@ -143,7 +143,14 @@ void PrefixSelector::OnCandidateWindowUpdated() {
void PrefixSelector::OnCandidateWindowHidden() {
}
-void PrefixSelector::OnTextInput(const string16& text) {
+bool PrefixSelector::IsEditingCommandEnabled(int command_id) {
+ return false;
+}
+
+void PrefixSelector::ExecuteEditingCommand(int command_id) {
+}
+
+void PrefixSelector::OnTextInput(const base::string16& text) {
// Small hack to filter out 'tab' and 'enter' input, as the expectation is
// that they are control characters and will not affect the currently-active
// prefix.
@@ -171,9 +178,9 @@ void PrefixSelector::OnTextInput(const string16& text) {
time_of_last_key_ = now;
const int start_row = row;
- const string16 lower_text(base::i18n::ToLower(current_text_));
+ const base::string16 lower_text(base::i18n::ToLower(current_text_));
do {
- if (TextAtRowMatchesText(row, current_text_)) {
+ if (TextAtRowMatchesText(row, lower_text)) {
prefix_delegate_->SetSelectedRow(row);
return;
}
@@ -182,8 +189,8 @@ void PrefixSelector::OnTextInput(const string16& text) {
}
bool PrefixSelector::TextAtRowMatchesText(int row,
- const string16& lower_text) {
- const string16 model_text(
+ const base::string16& lower_text) {
+ const base::string16 model_text(
base::i18n::ToLower(prefix_delegate_->GetTextForRow(row)));
return (model_text.size() >= lower_text.size()) &&
(model_text.compare(0, lower_text.size(), lower_text) == 0);
diff --git a/chromium/ui/views/controls/prefix_selector.h b/chromium/ui/views/controls/prefix_selector.h
index 57f6dcfe183..255046f60df 100644
--- a/chromium/ui/views/controls/prefix_selector.h
+++ b/chromium/ui/views/controls/prefix_selector.h
@@ -29,8 +29,8 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
const ui::CompositionText& composition) OVERRIDE;
virtual void ConfirmCompositionText() OVERRIDE;
virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const string16& text) OVERRIDE;
- virtual void InsertChar(char16 ch, int flags) OVERRIDE;
+ virtual void InsertText(const base::string16& text) OVERRIDE;
+ virtual void InsertChar(base::char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
@@ -45,7 +45,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
virtual bool GetTextFromRange(const gfx::Range& range,
- string16* text) const OVERRIDE;
+ base::string16* text) const OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) OVERRIDE;
@@ -55,12 +55,15 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
virtual void OnCandidateWindowUpdated() OVERRIDE;
virtual void OnCandidateWindowHidden() OVERRIDE;
+ virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE;
+ virtual void ExecuteEditingCommand(int command_id) OVERRIDE;
+
private:
// Invoked when text is typed. Tries to change the selection appropriately.
- void OnTextInput(const string16& text);
+ void OnTextInput(const base::string16& text);
// Returns true if the text of the node at |row| starts with |lower_text|.
- bool TextAtRowMatchesText(int row, const string16& lower_text);
+ bool TextAtRowMatchesText(int row, const base::string16& lower_text);
// Clears |current_text_| and resets |time_of_last_key_|.
void ClearText();
@@ -70,7 +73,7 @@ class VIEWS_EXPORT PrefixSelector : public ui::TextInputClient {
// Time OnTextInput() was last invoked.
base::TimeTicks time_of_last_key_;
- string16 current_text_;
+ base::string16 current_text_;
DISALLOW_COPY_AND_ASSIGN(PrefixSelector);
};
diff --git a/chromium/ui/views/controls/prefix_selector_unittest.cc b/chromium/ui/views/controls/prefix_selector_unittest.cc
index c39e6cc652a..031c0079aee 100644
--- a/chromium/ui/views/controls/prefix_selector_unittest.cc
+++ b/chromium/ui/views/controls/prefix_selector_unittest.cc
@@ -11,6 +11,8 @@
#include "ui/views/controls/prefix_delegate.h"
#include "ui/views/test/views_test_base.h"
+using base::ASCIIToUTF16;
+
namespace views {
class TestPrefixDelegate : public PrefixDelegate {
@@ -36,12 +38,12 @@ class TestPrefixDelegate : public PrefixDelegate {
selected_row_ = row;
}
- virtual string16 GetTextForRow(int row) OVERRIDE {
+ virtual base::string16 GetTextForRow(int row) OVERRIDE {
return rows_[row];
}
private:
- std::vector<string16> rows_;
+ std::vector<base::string16> rows_;
int selected_row_;
DISALLOW_COPY_AND_ASSIGN(TestPrefixDelegate);
diff --git a/chromium/ui/views/controls/progress_bar.cc b/chromium/ui/views/controls/progress_bar.cc
index 087c2df9830..0d6ed17f5e0 100644
--- a/chromium/ui/views/controls/progress_bar.cc
+++ b/chromium/ui/views/controls/progress_bar.cc
@@ -11,7 +11,7 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkXfermode.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/canvas.h"
namespace {
@@ -81,7 +81,7 @@ void FillRoundRect(gfx::Canvas* canvas,
p[1].iset(x, y + h);
}
skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
- p, colors, points, count, SkShader::kClamp_TileMode, NULL));
+ p, colors, points, count, SkShader::kClamp_TileMode));
paint.setShader(s.get());
canvas->DrawPath(path, paint);
@@ -167,22 +167,23 @@ void ProgressBar::SetValue(double value) {
}
}
-void ProgressBar::SetTooltipText(const string16& tooltip_text) {
+void ProgressBar::SetTooltipText(const base::string16& tooltip_text) {
tooltip_text_ = tooltip_text;
}
-bool ProgressBar::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
+bool ProgressBar::GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const {
DCHECK(tooltip);
*tooltip = tooltip_text_;
return !tooltip_text_.empty();
}
-void ProgressBar::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_PROGRESSBAR;
- state->state = ui::AccessibilityTypes::STATE_READONLY;
+void ProgressBar::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_PROGRESS_INDICATOR;
+ state->AddStateFlag(ui::AX_STATE_READ_ONLY);
}
-gfx::Size ProgressBar::GetPreferredSize() {
+gfx::Size ProgressBar::GetPreferredSize() const {
gfx::Size pref_size(100, 11);
gfx::Insets insets = GetInsets();
pref_size.Enlarge(insets.width(), insets.height());
@@ -227,7 +228,7 @@ void ProgressBar::OnPaint(gfx::Canvas* canvas) {
kCornerRadius,
0,
&inner_path);
- canvas->ClipPath(inner_path);
+ canvas->ClipPath(inner_path, false);
const SkColor bar_colors[] = {
kBarTopColor,
@@ -299,7 +300,7 @@ void ProgressBar::OnPaint(gfx::Canvas* canvas) {
skia::RefPtr<SkShader> s =
skia::AdoptRef(SkGradientShader::CreateLinear(
p, highlight_colors, highlight_points,
- arraysize(highlight_colors), SkShader::kClamp_TileMode, NULL));
+ arraysize(highlight_colors), SkShader::kClamp_TileMode));
paint.setShader(s.get());
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
canvas->DrawRect(gfx::Rect(highlight_left, 0,
diff --git a/chromium/ui/views/controls/progress_bar.h b/chromium/ui/views/controls/progress_bar.h
index 1f3d595534c..b6d3851baaf 100644
--- a/chromium/ui/views/controls/progress_bar.h
+++ b/chromium/ui/views/controls/progress_bar.h
@@ -35,18 +35,18 @@ class VIEWS_EXPORT ProgressBar : public View {
// Sets the tooltip text. Default behavior for a progress bar is to show no
// tooltip on mouse hover. Calling this lets you set a custom tooltip. To
// revert to default behavior, call this with an empty string.
- void SetTooltipText(const string16& tooltip_text);
+ void SetTooltipText(const base::string16& tooltip_text);
// Overridden from View:
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
private:
static const char kViewClassName[];
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
@@ -58,7 +58,7 @@ class VIEWS_EXPORT ProgressBar : public View {
double current_value_;
// Tooltip text.
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
DISALLOW_COPY_AND_ASSIGN(ProgressBar);
};
diff --git a/chromium/ui/views/controls/progress_bar_unittest.cc b/chromium/ui/views/controls/progress_bar_unittest.cc
index 78df2e17d0d..b9067b20c9b 100644
--- a/chromium/ui/views/controls/progress_bar_unittest.cc
+++ b/chromium/ui/views/controls/progress_bar_unittest.cc
@@ -6,16 +6,16 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
namespace views {
TEST(ProgressBarTest, TooltipTextProperty) {
ProgressBar bar;
- string16 tooltip = ASCIIToUTF16("Some text");
+ base::string16 tooltip = base::ASCIIToUTF16("Some text");
EXPECT_FALSE(bar.GetTooltipText(gfx::Point(), &tooltip));
- EXPECT_EQ(string16(), tooltip);
- string16 tooltip_text = ASCIIToUTF16("My progress");
+ EXPECT_EQ(base::string16(), tooltip);
+ base::string16 tooltip_text = base::ASCIIToUTF16("My progress");
bar.SetTooltipText(tooltip_text);
EXPECT_TRUE(bar.GetTooltipText(gfx::Point(), &tooltip));
EXPECT_EQ(tooltip_text, tooltip);
@@ -25,11 +25,11 @@ TEST(ProgressBarTest, Accessibility) {
ProgressBar bar;
bar.SetValue(62);
- ui::AccessibleViewState state;
+ ui::AXViewState state;
bar.GetAccessibleState(&state);
- EXPECT_EQ(ui::AccessibilityTypes::ROLE_PROGRESSBAR, state.role);
- EXPECT_EQ(string16(), state.name);
- EXPECT_TRUE(ui::AccessibilityTypes::STATE_READONLY & state.state);
+ EXPECT_EQ(ui::AX_ROLE_PROGRESS_INDICATOR, state.role);
+ EXPECT_EQ(base::string16(), state.name);
+ EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY));
}
} // namespace views
diff --git a/chromium/ui/views/controls/resize_area.cc b/chromium/ui/views/controls/resize_area.cc
index 845f2e8d42d..8a5159f7eda 100644
--- a/chromium/ui/views/controls/resize_area.cc
+++ b/chromium/ui/views/controls/resize_area.cc
@@ -5,13 +5,11 @@
#include "ui/views/controls/resize_area.h"
#include "base/logging.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/resize_area_delegate.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+#include "ui/views/native_cursor.h"
namespace views {
@@ -33,14 +31,8 @@ const char* ResizeArea::GetClassName() const {
}
gfx::NativeCursor ResizeArea::GetCursor(const ui::MouseEvent& event) {
- if (!enabled())
- return gfx::kNullCursor;
-#if defined(USE_AURA)
- return ui::kCursorEastWestResize;
-#elif defined(OS_WIN)
- static HCURSOR g_resize_cursor = LoadCursor(NULL, IDC_SIZEWE);
- return g_resize_cursor;
-#endif
+ return enabled() ? GetNativeEastWestResizeCursor()
+ : gfx::kNullCursor;
}
bool ResizeArea::OnMousePressed(const ui::MouseEvent& event) {
@@ -73,8 +65,8 @@ void ResizeArea::OnMouseCaptureLost() {
ReportResizeAmount(initial_position_, true);
}
-void ResizeArea::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_SEPARATOR;
+void ResizeArea::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_SPLITTER;
}
void ResizeArea::ReportResizeAmount(int resize_amount, bool last_update) {
diff --git a/chromium/ui/views/controls/resize_area.h b/chromium/ui/views/controls/resize_area.h
index 288b912ba80..12ec310026e 100644
--- a/chromium/ui/views/controls/resize_area.h
+++ b/chromium/ui/views/controls/resize_area.h
@@ -32,7 +32,7 @@ class VIEWS_EXPORT ResizeArea : public View {
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseCaptureLost() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
private:
// Report the amount the user resized by to the delegate, accounting for
diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc
index d835c1ebdf8..51db071b71f 100644
--- a/chromium/ui/views/controls/scroll_view.cc
+++ b/chromium/ui/views/controls/scroll_view.cc
@@ -20,22 +20,16 @@ namespace {
// Subclass of ScrollView that resets the border when the theme changes.
class ScrollViewWithBorder : public views::ScrollView {
public:
- ScrollViewWithBorder() {
- SetThemeSpecificState();
- }
+ ScrollViewWithBorder() {}
// View overrides;
virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE {
- SetThemeSpecificState();
+ SetBorder(Border::CreateSolidBorder(
+ 1,
+ theme->GetSystemColor(ui::NativeTheme::kColorId_UnfocusedBorderColor)));
}
private:
- void SetThemeSpecificState() {
- set_border(Border::CreateSolidBorder(
- 1, GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_UnfocusedBorderColor)));
- }
-
DISALLOW_COPY_AND_ASSIGN(ScrollViewWithBorder);
};
@@ -116,6 +110,8 @@ ScrollView::ScrollView()
horiz_sb_(new NativeScrollBar(true)),
vert_sb_(new NativeScrollBar(false)),
resize_corner_(NULL),
+ min_height_(-1),
+ max_height_(-1),
hide_horizontal_scrollbar_(false) {
set_notify_enter_exit_on_child(true);
@@ -162,6 +158,11 @@ gfx::Rect ScrollView::GetVisibleRect() const {
contents_viewport_->width(), contents_viewport_->height());
}
+void ScrollView::ClipHeightTo(int min_height, int max_height) {
+ min_height_ = min_height;
+ max_height_ = max_height;
+}
+
int ScrollView::GetScrollBarWidth() const {
return vert_sb_ ? vert_sb_->GetLayoutSize() : 0;
}
@@ -186,7 +187,40 @@ void ScrollView::SetVerticalScrollBar(ScrollBar* vert_sb) {
vert_sb_ = vert_sb;
}
+gfx::Size ScrollView::GetPreferredSize() const {
+ if (!is_bounded())
+ return View::GetPreferredSize();
+
+ gfx::Size size = contents()->GetPreferredSize();
+ size.SetToMax(gfx::Size(size.width(), min_height_));
+ size.SetToMin(gfx::Size(size.width(), max_height_));
+ gfx::Insets insets = GetInsets();
+ size.Enlarge(insets.width(), insets.height());
+ return size;
+}
+
+int ScrollView::GetHeightForWidth(int width) const {
+ if (!is_bounded())
+ return View::GetHeightForWidth(width);
+
+ gfx::Insets insets = GetInsets();
+ width = std::max(0, width - insets.width());
+ int height = contents()->GetHeightForWidth(width) + insets.height();
+ return std::min(std::max(height, min_height_), max_height_);
+}
+
void ScrollView::Layout() {
+ if (is_bounded()) {
+ int content_width = width();
+ int content_height = contents()->GetHeightForWidth(content_width);
+ if (content_height > height()) {
+ content_width = std::max(content_width - GetScrollBarWidth(), 0);
+ content_height = contents()->GetHeightForWidth(content_width);
+ }
+ if (contents()->bounds().size() != gfx::Size(content_width, content_height))
+ contents()->SetBounds(0, 0, content_width, content_height);
+ }
+
// Most views will want to auto-fit the available space. Most of them want to
// use all available width (without overflowing) and only overflow in
// height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc.
diff --git a/chromium/ui/views/controls/scroll_view.h b/chromium/ui/views/controls/scroll_view.h
index da87ffdc753..c1c18713af0 100644
--- a/chromium/ui/views/controls/scroll_view.h
+++ b/chromium/ui/views/controls/scroll_view.h
@@ -31,6 +31,7 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
static const char kViewClassName[];
ScrollView();
+
virtual ~ScrollView();
// Creates a ScrollView with a theme specific border.
@@ -52,6 +53,13 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
hide_horizontal_scrollbar_ = visible;
}
+ // Turns this scroll view into a bounded scroll view, with a fixed height.
+ // By default, a ScrollView will stretch to fill its outer container.
+ void ClipHeightTo(int min_height, int max_height);
+
+ // Returns whether or not the ScrollView is bounded (as set by ClipHeightTo).
+ bool is_bounded() const { return max_height_ >= 0 && min_height_ >= 0; }
+
// Retrieves the width/height of scrollbars. These return 0 if the scrollbar
// has not yet been created.
int GetScrollBarWidth() const;
@@ -67,6 +75,8 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
void SetVerticalScrollBar(ScrollBar* vert_sb);
// View overrides:
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual int GetHeightForWidth(int width) const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
virtual bool OnMouseWheel(const ui::MouseWheelEvent& e) OVERRIDE;
@@ -127,6 +137,11 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
// Resize corner.
View* resize_corner_;
+ // The min and max height for the bounded scroll view. These are negative
+ // values if the view is not bounded.
+ int min_height_;
+ int max_height_;
+
// If true, never show the horizontal scrollbar (even if the contents is wider
// than the viewport).
bool hide_horizontal_scrollbar_;
diff --git a/chromium/ui/views/controls/scroll_view_unittest.cc b/chromium/ui/views/controls/scroll_view_unittest.cc
index f0bdbd5443d..8f34377553f 100644
--- a/chromium/ui/views/controls/scroll_view_unittest.cc
+++ b/chromium/ui/views/controls/scroll_view_unittest.cc
@@ -5,11 +5,17 @@
#include "ui/views/controls/scroll_view.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
+#include "ui/views/test/test_views.h"
namespace views {
namespace {
+const int kWidth = 100;
+const int kMinHeight = 50;
+const int kMaxHeight = 100;
+
// View implementation that allows setting the preferred size.
class CustomView : public View {
public:
@@ -20,7 +26,7 @@ class CustomView : public View {
PreferredSizeChanged();
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return preferred_size_;
}
@@ -148,7 +154,6 @@ TEST(ScrollViewTest, ScrollBarsWithHeader) {
ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
-
// Size the contents such that horizontal scrollbar is needed.
contents->SetBounds(0, 0, 400, 50);
scroll_view.Layout();
@@ -214,7 +219,6 @@ TEST(ScrollViewTest, HeaderScrollsWithContent) {
EXPECT_EQ("-1,0", header->bounds().origin().ToString());
}
-
// Verifies ScrollRectToVisible() on the child works.
TEST(ScrollViewTest, ScrollRectToVisible) {
ScrollView scroll_view;
@@ -237,4 +241,97 @@ TEST(ScrollViewTest, ScrollRectToVisible) {
EXPECT_EQ(-(415 - viewport_height), contents->y());
}
+// Verifies ClipHeightTo() uses the height of the content when it is between the
+// minimum and maximum height values.
+TEST(ScrollViewTest, ClipHeightToNormalContentHeight) {
+ ScrollView scroll_view;
+
+ scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+ const int kNormalContentHeight = 75;
+ scroll_view.SetContents(
+ new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight)));
+
+ EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
+ scroll_view.GetPreferredSize());
+
+ scroll_view.SizeToPreferredSize();
+ scroll_view.Layout();
+
+ EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
+ scroll_view.contents()->size());
+ EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view.size());
+}
+
+// Verifies ClipHeightTo() uses the minimum height when the content is shorter
+// thamn the minimum height value.
+TEST(ScrollViewTest, ClipHeightToShortContentHeight) {
+ ScrollView scroll_view;
+
+ scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+ const int kShortContentHeight = 10;
+ scroll_view.SetContents(
+ new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight)));
+
+ EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.GetPreferredSize());
+
+ scroll_view.SizeToPreferredSize();
+ scroll_view.Layout();
+
+ EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight),
+ scroll_view.contents()->size());
+ EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.size());
+}
+
+// Verifies ClipHeightTo() uses the maximum height when the content is longer
+// thamn the maximum height value.
+TEST(ScrollViewTest, ClipHeightToTallContentHeight) {
+ ScrollView scroll_view;
+
+ // Use a scrollbar that is disabled by default, so the width of the content is
+ // not affected.
+ scroll_view.SetVerticalScrollBar(new views::OverlayScrollBar(false));
+
+ scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+ const int kTallContentHeight = 1000;
+ scroll_view.SetContents(
+ new views::StaticSizedView(gfx::Size(kWidth, kTallContentHeight)));
+
+ EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.GetPreferredSize());
+
+ scroll_view.SizeToPreferredSize();
+ scroll_view.Layout();
+
+ EXPECT_EQ(gfx::Size(kWidth, kTallContentHeight),
+ scroll_view.contents()->size());
+ EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
+}
+
+// Verifies that when ClipHeightTo() produces a scrollbar, it reduces the width
+// of the inner content of the ScrollView.
+TEST(ScrollViewTest, ClipHeightToScrollbarUsesWidth) {
+ ScrollView scroll_view;
+
+ scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+ // Create a view that will be much taller than it is wide.
+ scroll_view.SetContents(new views::ProportionallySizedView(1000));
+
+ // Without any width, it will default to 0,0 but be overridden by min height.
+ scroll_view.SizeToPreferredSize();
+ EXPECT_EQ(gfx::Size(0, kMinHeight), scroll_view.GetPreferredSize());
+
+ gfx::Size new_size(kWidth, scroll_view.GetHeightForWidth(kWidth));
+ scroll_view.SetSize(new_size);
+ scroll_view.Layout();
+
+ int scroll_bar_width = scroll_view.GetScrollBarWidth();
+ int expected_width = kWidth - scroll_bar_width;
+ EXPECT_EQ(scroll_view.contents()->size().width(), expected_width);
+ EXPECT_EQ(scroll_view.contents()->size().height(), 1000 * expected_width);
+ EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc
index 6271c2e1bfe..5e4d6a56fa3 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc
@@ -17,6 +17,7 @@
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/scroll_view.h"
@@ -235,10 +236,19 @@ void BaseScrollBar::OnGestureEvent(ui::GestureEvent* event) {
}
if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
- if (ScrollByContentsOffset(IsHorizontal() ? event->details().scroll_x() :
- event->details().scroll_y())) {
- event->SetHandled();
+ float scroll_amount_f;
+ int scroll_amount;
+ if (IsHorizontal()) {
+ scroll_amount_f = event->details().scroll_x() - roundoff_error_.x();
+ scroll_amount = gfx::ToRoundedInt(scroll_amount_f);
+ roundoff_error_.set_x(scroll_amount - scroll_amount_f);
+ } else {
+ scroll_amount_f = event->details().scroll_y() - roundoff_error_.y();
+ scroll_amount = gfx::ToRoundedInt(scroll_amount_f);
+ roundoff_error_.set_y(scroll_amount - scroll_amount_f);
}
+ if (ScrollByContentsOffset(scroll_amount))
+ event->SetHandled();
return;
}
@@ -295,17 +305,22 @@ void BaseScrollBar::ShowContextMenuForView(View* source,
menu->AppendSeparator();
menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollPrev);
menu->AppendDelegateMenuItem(ScrollBarContextMenuCommand_ScrollNext);
- if (menu_runner_->RunMenuAt(GetWidget(), NULL, gfx::Rect(p, gfx::Size()),
- views::MenuItemView::TOPLEFT, source_type, MenuRunner::HAS_MNEMONICS |
- views::MenuRunner::CONTEXT_MENU) ==
- MenuRunner::MENU_DELETED)
+ if (menu_runner_->RunMenuAt(
+ GetWidget(),
+ NULL,
+ gfx::Rect(p, gfx::Size()),
+ MENU_ANCHOR_TOPLEFT,
+ source_type,
+ MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
+ MenuRunner::MENU_DELETED) {
return;
+ }
}
///////////////////////////////////////////////////////////////////////////////
// BaseScrollBar, Menu::Delegate implementation:
-string16 BaseScrollBar::GetLabel(int id) const {
+base::string16 BaseScrollBar::GetLabel(int id) const {
int ids_value = 0;
switch (id) {
case ScrollBarContextMenuCommand_ScrollHere:
@@ -337,7 +352,7 @@ string16 BaseScrollBar::GetLabel(int id) const {
NOTREACHED() << "Invalid BaseScrollBar Context Menu command!";
}
- return ids_value ? l10n_util::GetStringUTF16(ids_value) : string16();
+ return ids_value ? l10n_util::GetStringUTF16(ids_value) : base::string16();
}
bool BaseScrollBar::IsCommandEnabled(int id) const {
@@ -378,7 +393,8 @@ void BaseScrollBar::ExecuteCommand(int id) {
///////////////////////////////////////////////////////////////////////////////
// BaseScrollBar, ScrollBar implementation:
-void BaseScrollBar::Update(int viewport_size, int content_size,
+void BaseScrollBar::Update(int viewport_size,
+ int content_size,
int contents_scroll_offset) {
ScrollBar::Update(viewport_size, content_size, contents_scroll_offset);
@@ -394,6 +410,7 @@ void BaseScrollBar::Update(int viewport_size, int content_size,
contents_scroll_offset = 0;
if (contents_scroll_offset > content_size)
contents_scroll_offset = content_size;
+ contents_scroll_offset_ = contents_scroll_offset;
// Thumb Height and Thumb Pos.
// The height of the thumb is the ratio of the Viewport height to the
@@ -488,7 +505,7 @@ int BaseScrollBar::CalculateThumbPosition(int contents_scroll_offset) const {
}
int BaseScrollBar::CalculateContentsOffset(int thumb_position,
- bool scroll_to_middle) const {
+ bool scroll_to_middle) const {
if (scroll_to_middle)
thumb_position = thumb_position - (thumb_->GetSize() / 2);
return (thumb_position * contents_size_) / GetTrackSize();
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
index a517b6c0645..068ad4ddb6f 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
@@ -64,7 +64,7 @@ class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
CustomButton::ButtonState new_state);
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE = 0;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE = 0;
virtual void Layout() OVERRIDE = 0;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
@@ -93,7 +93,7 @@ class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
ui::MenuSourceType source_type) OVERRIDE;
// Menu::Delegate overrides:
- virtual string16 GetLabel(int id) const OVERRIDE;
+ virtual base::string16 GetLabel(int id) const OVERRIDE;
virtual bool IsCommandEnabled(int id) const OVERRIDE;
virtual void ExecuteCommand(int id) OVERRIDE;
@@ -178,6 +178,12 @@ class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
scoped_ptr<MenuRunner> menu_runner_;
scoped_ptr<ScrollAnimator> scroll_animator_;
+ // Difference between current position and cumulative deltas obtained from
+ // scroll update events.
+ // TODO(tdresser): This should be removed when raw pixel scrolling for views
+ // is enabled. See crbug.com/329354.
+ gfx::Vector2dF roundoff_error_;
+
DISALLOW_COPY_AND_ASSIGN(BaseScrollBar);
};
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 6eba692d626..0a765c42962 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -35,15 +35,12 @@ void BaseScrollBarButton::OnMouseCaptureLost() {
void BaseScrollBarButton::RepeaterNotifyClick() {
// TODO(sky): See if we can convert to using |Screen| everywhere.
-#if defined(OS_WIN) && !defined(USE_AURA)
- gfx::Point cursor_point(GetMessagePos());
-#else
// TODO(scottmg): Native is wrong: http://crbug.com/133312
gfx::Point cursor_point =
gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
-#endif
ui::MouseEvent event(ui::ET_MOUSE_RELEASED,
cursor_point, cursor_point,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
Button::NotifyClick(event);
}
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 0859fa903c1..c755441b8b4 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
@@ -44,7 +44,7 @@ class VIEWS_EXPORT BaseScrollBarThumb : public View {
int GetPosition() const;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE = 0;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE = 0;
protected:
// View overrides:
diff --git a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc
deleted file mode 100644
index 2597cee0b78..00000000000
--- a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/scrollbar/bitmap_scroll_bar.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "grit/ui_strings.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/views/controls/menu/menu.h"
-#include "ui/views/controls/scroll_view.h"
-#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
-#include "ui/views/widget/widget.h"
-
-#if defined(OS_LINUX)
-#include "ui/views/screen.h"
-#endif
-
-#undef min
-#undef max
-
-namespace views {
-
-namespace {
-
-// The distance the mouse can be dragged outside the bounds of the thumb during
-// dragging before the scrollbar will snap back to its regular position.
-const int kScrollThumbDragOutSnap = 100;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// AutorepeatButton
-//
-// A button that activates on mouse pressed rather than released, and that
-// continues to fire the clicked action as the mouse button remains pressed
-// down on the button.
-//
-///////////////////////////////////////////////////////////////////////////////
-class AutorepeatButton : public ImageButton {
- public:
- explicit AutorepeatButton(ButtonListener* listener)
- : ImageButton(listener),
- repeater_(base::Bind(&AutorepeatButton::NotifyClick,
- base::Unretained(this))) {
- }
- virtual ~AutorepeatButton() {}
-
- protected:
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
- Button::NotifyClick(event);
- repeater_.Start();
- return true;
- }
-
- virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE {
- OnMouseCaptureLost();
- }
-
- virtual void OnMouseCaptureLost() OVERRIDE {
- repeater_.Stop();
- }
-
- private:
- void NotifyClick() {
-#if defined(OS_WIN)
- gfx::Point cursor_point(GetMessagePos());
-#elif defined(OS_LINUX)
- gfx::Point cursor_point = gfx::Screen::GetCursorScreenPoint();
-#endif
- ui::MouseEvent event(ui::ET_MOUSE_RELEASED,
- cursor_point, cursor_point,
- ui::EF_LEFT_MOUSE_BUTTON);
- Button::NotifyClick(event);
- }
-
- // The repeat controller that we use to repeatedly click the button when the
- // mouse button is down.
- RepeatController repeater_;
-
- DISALLOW_COPY_AND_ASSIGN(AutorepeatButton);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// BitmapScrollBarThumb
-//
-// A view that acts as the thumb in the scroll bar track that the user can
-// drag to scroll the associated contents view within the viewport.
-//
-///////////////////////////////////////////////////////////////////////////////
-class BitmapScrollBarThumb : public BaseScrollBarThumb {
- public:
- explicit BitmapScrollBarThumb(BitmapScrollBar* scroll_bar)
- : BaseScrollBarThumb(scroll_bar),
- scroll_bar_(scroll_bar) {
- }
- virtual ~BitmapScrollBarThumb() { }
-
- // View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE {
- return gfx::Size(background_image()->width(),
- start_cap_image()->height() +
- end_cap_image()->height() +
- grippy_image()->height());
- }
-
- protected:
- // View overrides:
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
- canvas->DrawImageInt(*start_cap_image(), 0, 0);
- int top_cap_height = start_cap_image()->height();
- int bottom_cap_height = end_cap_image()->height();
- int thumb_body_height = height() - top_cap_height - bottom_cap_height;
- canvas->TileImageInt(*background_image(), 0, top_cap_height,
- background_image()->width(), thumb_body_height);
- canvas->DrawImageInt(*end_cap_image(), 0,
- height() - bottom_cap_height);
-
- // Paint the grippy over the track.
- int grippy_x = (width() - grippy_image()->width()) / 2;
- int grippy_y = (thumb_body_height - grippy_image()->height()) / 2;
- canvas->DrawImageInt(*grippy_image(), grippy_x, grippy_y);
- }
-
- private:
- // Returns the image rendered at the start of the thumb.
- gfx::ImageSkia* start_cap_image() const {
- return scroll_bar_->images_[BitmapScrollBar::THUMB_START_CAP][GetState()];
- }
-
- // Returns the image rendered at the end of the thumb.
- gfx::ImageSkia* end_cap_image() const {
- return scroll_bar_->images_[BitmapScrollBar::THUMB_END_CAP][GetState()];
- }
-
- // Returns the image that is tiled in the background of the thumb between
- // the start and the end caps.
- gfx::ImageSkia* background_image() const {
- return scroll_bar_->images_[BitmapScrollBar::THUMB_MIDDLE][GetState()];
- }
-
- // Returns the image that is rendered in the middle of the thumb
- // transparently over the background image.
- gfx::ImageSkia* grippy_image() const {
- return scroll_bar_->images_[BitmapScrollBar::THUMB_GRIPPY]
- [CustomButton::STATE_NORMAL];
- }
-
- // The BitmapScrollBar that owns us.
- BitmapScrollBar* scroll_bar_;
-
- DISALLOW_COPY_AND_ASSIGN(BitmapScrollBarThumb);
-};
-
-} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-// BitmapScrollBar, public:
-
-BitmapScrollBar::BitmapScrollBar(bool horizontal, bool show_scroll_buttons)
- : BaseScrollBar(horizontal, new BitmapScrollBarThumb(this)),
- prev_button_(new AutorepeatButton(this)),
- next_button_(new AutorepeatButton(this)),
- show_scroll_buttons_(show_scroll_buttons) {
- if (!show_scroll_buttons_) {
- prev_button_->SetVisible(false);
- next_button_->SetVisible(false);
- }
-
- AddChildView(prev_button_);
- AddChildView(next_button_);
-
- set_context_menu_controller(this);
- prev_button_->set_context_menu_controller(this);
- next_button_->set_context_menu_controller(this);
-}
-
-void BitmapScrollBar::SetImage(ScrollBarPart part,
- CustomButton::ButtonState state,
- gfx::ImageSkia* image_skia) {
- DCHECK(part < PART_COUNT);
- DCHECK(state < CustomButton::STATE_COUNT);
- switch (part) {
- case PREV_BUTTON:
- prev_button_->SetImage(state, image_skia);
- break;
- case NEXT_BUTTON:
- next_button_->SetImage(state, image_skia);
- break;
- case THUMB_START_CAP:
- case THUMB_MIDDLE:
- case THUMB_END_CAP:
- case THUMB_GRIPPY:
- case THUMB_TRACK:
- images_[part][state] = image_skia;
- break;
- }
-}
-
-int BitmapScrollBar::GetLayoutSize() const {
- gfx::Size prefsize = prev_button_->GetPreferredSize();
- return IsHorizontal() ? prefsize.height() : prefsize.width();
-}
-
-gfx::Rect BitmapScrollBar::GetTrackBounds() const {
- gfx::Size prefsize = prev_button_->GetPreferredSize();
- if (IsHorizontal()) {
- if (!show_scroll_buttons_)
- prefsize.set_width(0);
- int new_width =
- std::max(0, width() - (prefsize.width() * 2));
- gfx::Rect track_bounds(prefsize.width(), 0, new_width, prefsize.height());
- return track_bounds;
- }
- if (!show_scroll_buttons_)
- prefsize.set_height(0);
- gfx::Rect track_bounds(0, prefsize.height(), prefsize.width(),
- std::max(0, height() - (prefsize.height() * 2)));
- return track_bounds;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// BitmapScrollBar, View implementation:
-
-gfx::Size BitmapScrollBar::GetPreferredSize() {
- // In this case, we're returning the desired width of the scrollbar and its
- // minimum allowable height.
- gfx::Size button_prefsize = prev_button_->GetPreferredSize();
- return gfx::Size(button_prefsize.width(), button_prefsize.height() * 2);
-}
-
-void BitmapScrollBar::Layout() {
- // Size and place the two scroll buttons.
- if (show_scroll_buttons_) {
- gfx::Size prefsize = prev_button_->GetPreferredSize();
- prev_button_->SetBounds(0, 0, prefsize.width(), prefsize.height());
- prefsize = next_button_->GetPreferredSize();
- if (IsHorizontal()) {
- next_button_->SetBounds(width() - prefsize.width(), 0, prefsize.width(),
- prefsize.height());
- } else {
- next_button_->SetBounds(0, height() - prefsize.height(), prefsize.width(),
- prefsize.height());
- }
- } else {
- prev_button_->SetBounds(0, 0, 0, 0);
- next_button_->SetBounds(0, 0, 0, 0);
- }
-
- BaseScrollBarThumb* thumb = GetThumb();
- // Size and place the thumb
- gfx::Size thumb_prefsize = thumb->GetPreferredSize();
- gfx::Rect track_bounds = GetTrackBounds();
-
- // Preserve the height/width of the thumb (depending on orientation) as set
- // by the last call to |Update|, but coerce the width/height to be the
- // appropriate value for the images provided.
- if (IsHorizontal()) {
- thumb->SetBounds(thumb->x(), thumb->y(), thumb->width(),
- thumb_prefsize.height());
- } else {
- thumb->SetBounds(thumb->x(), thumb->y(), thumb_prefsize.width(),
- thumb->height());
- }
-
- // Hide the thumb if the track isn't tall enough to display even a tiny
- // thumb. The user can only use the mousewheel, scroll buttons or keyboard
- // in this scenario.
- if ((IsHorizontal() && (track_bounds.width() < thumb_prefsize.width()) ||
- (!IsHorizontal() && (track_bounds.height() < thumb_prefsize.height())))) {
- thumb->SetVisible(false);
- } else if (!thumb->visible()) {
- thumb->SetVisible(true);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// BitmapScrollBar, View implementation:
-
-void BitmapScrollBar::OnPaint(gfx::Canvas* canvas) {
- // Paint the track.
- gfx::Rect track_bounds = GetTrackBounds();
- canvas->TileImageInt(*images_[THUMB_TRACK][GetThumbTrackState()],
- track_bounds.x(), track_bounds.y(),
- track_bounds.width(), track_bounds.height());
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// BitmapScrollBar, ButtonListener implementation:
-
-void BitmapScrollBar::ButtonPressed(Button* sender, const ui::Event& event) {
- if (sender == prev_button_) {
- ScrollByAmount(SCROLL_PREV_LINE);
- } else if (sender == next_button_) {
- ScrollByAmount(SCROLL_NEXT_LINE);
- }
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.h b/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.h
deleted file mode 100644
index ac97af499cc..00000000000
--- a/chromium/ui/views/controls/scrollbar/bitmap_scroll_bar.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_BITMAP_SCROLL_BAR_H_
-#define UI_VIEWS_CONTROLS_SCROLLBAR_BITMAP_SCROLL_BAR_H_
-
-#include "ui/views/controls/scrollbar/base_scroll_bar.h"
-
-namespace views {
-
-namespace {
-class BitmapScrollBarThumb;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// BitmapScrollBar
-//
-// A ScrollBar subclass that implements a scroll bar rendered using images
-// that the user provides. There are images for the up and down buttons, as
-// well as for the thumb and track. This is intended for creating UIs that
-// have customized, non-native appearances, like floating HUDs etc.
-//
-///////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT BitmapScrollBar : public BaseScrollBar,
- public ButtonListener {
- public:
- BitmapScrollBar(bool horizontal, bool show_scroll_buttons);
- virtual ~BitmapScrollBar() { }
-
- // A list of parts that the user may supply images for.
- enum ScrollBarPart {
- // The button used to represent scrolling up/left by 1 line.
- PREV_BUTTON = 0,
- // The button used to represent scrolling down/right by 1 line.
- // IMPORTANT: The code assumes the prev and next
- // buttons have equal width and equal height.
- NEXT_BUTTON,
- // The top/left segment of the thumb on the scrollbar.
- THUMB_START_CAP,
- // The tiled background image of the thumb.
- THUMB_MIDDLE,
- // The bottom/right segment of the thumb on the scrollbar.
- THUMB_END_CAP,
- // The grippy that is rendered in the center of the thumb.
- THUMB_GRIPPY,
- // The tiled background image of the thumb track.
- THUMB_TRACK,
- PART_COUNT
- };
-
- // Sets the image to be rendered for the specified part and state.
- void SetImage(ScrollBarPart part,
- CustomButton::ButtonState state,
- gfx::ImageSkia* image_skia);
-
-
- gfx::Rect GetTrackBounds() const;
-
- protected:
- // View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual void Layout() OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
-
- // ScrollBar overrides:
- virtual int GetLayoutSize() const OVERRIDE;
-
- // BaseButton::ButtonListener overrides:
- virtual void ButtonPressed(Button* sender,
- const ui::Event& event) OVERRIDE;
-
- private:
- // Up/Down/Left/Right buttons.
- ImageButton* prev_button_;
- ImageButton* next_button_;
-
- // The thumb needs to be able to access the part images.
- friend BitmapScrollBarThumb;
- gfx::ImageSkia* images_[PART_COUNT][CustomButton::STATE_COUNT];
-
- // True if the scroll buttons at each end of the scroll bar should be shown.
- bool show_scroll_buttons_;
-
- DISALLOW_COPY_AND_ASSIGN(BitmapScrollBar);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_SCROLLBAR_BITMAP_SCROLL_BAR_H_
diff --git a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc
index f263068ecd7..b3d1e6a3c32 100644
--- a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc
@@ -28,7 +28,7 @@ class KennedyScrollBarThumb : public BaseScrollBarThumb {
protected:
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
private:
@@ -42,7 +42,7 @@ KennedyScrollBarThumb::KennedyScrollBarThumb(BaseScrollBar* scroll_bar)
KennedyScrollBarThumb::~KennedyScrollBarThumb() {
}
-gfx::Size KennedyScrollBarThumb::GetPreferredSize() {
+gfx::Size KennedyScrollBarThumb::GetPreferredSize() const {
return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
}
@@ -77,7 +77,7 @@ int KennedyScrollBar::GetLayoutSize() const {
return kScrollbarWidth;
}
-gfx::Size KennedyScrollBar::GetPreferredSize() {
+gfx::Size KennedyScrollBar::GetPreferredSize() const {
return GetTrackBounds().size();
}
diff --git a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h
index 332948387a5..ace3fae31ec 100644
--- a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h
@@ -25,7 +25,7 @@ class VIEWS_EXPORT KennedyScrollBar : public BaseScrollBar {
virtual int GetLayoutSize() const OVERRIDE;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc
index 9a913709a4b..7b45dd6e052 100644
--- a/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar.cc
@@ -9,13 +9,10 @@
#include "base/message_loop/message_loop.h"
#include "ui/events/event.h"
+#include "ui/views/controls/scrollbar/native_scroll_bar_views.h"
#include "ui/views/controls/scrollbar/native_scroll_bar_wrapper.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/views/controls/scrollbar/native_scroll_bar_views.h"
-#endif
-
namespace views {
// static
@@ -45,7 +42,7 @@ int NativeScrollBar::GetVerticalScrollBarWidth(
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBar, View overrides:
-gfx::Size NativeScrollBar::GetPreferredSize() {
+gfx::Size NativeScrollBar::GetPreferredSize() const {
if (native_wrapper_)
return native_wrapper_->GetView()->GetPreferredSize();
return gfx::Size();
diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar.h b/chromium/ui/views/controls/scrollbar/native_scroll_bar.h
index 70d5a83d37a..058784d55ac 100644
--- a/chromium/ui/views/controls/scrollbar/native_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar.h
@@ -40,7 +40,7 @@ class VIEWS_EXPORT NativeScrollBar : public ScrollBar {
FRIEND_TEST_ALL_PREFIXES(NativeScrollBarTest, Scrolling);
// Overridden from View.
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc
index a8402e5c655..b4f83ccdf7b 100644
--- a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc
+++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.cc
@@ -32,7 +32,7 @@ class ScrollBarButton : public BaseScrollBarButton {
ScrollBarButton(ButtonListener* listener, Type type);
virtual ~ScrollBarButton();
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE {
return "ScrollBarButton";
}
@@ -54,7 +54,7 @@ class ScrollBarThumb : public BaseScrollBarThumb {
explicit ScrollBarThumb(BaseScrollBar* scroll_bar);
virtual ~ScrollBarThumb();
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE {
return "ScrollBarThumb";
}
@@ -83,7 +83,7 @@ ScrollBarButton::ScrollBarButton(ButtonListener* listener, Type type)
ScrollBarButton::~ScrollBarButton() {
}
-gfx::Size ScrollBarButton::GetPreferredSize() {
+gfx::Size ScrollBarButton::GetPreferredSize() const {
return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
GetNativeThemeState(),
GetNativeThemeParams());
@@ -164,7 +164,7 @@ ScrollBarThumb::ScrollBarThumb(BaseScrollBar* scroll_bar)
ScrollBarThumb::~ScrollBarThumb() {
}
-gfx::Size ScrollBarThumb::GetPreferredSize() {
+gfx::Size ScrollBarThumb::GetPreferredSize() const {
return GetNativeTheme()->GetPartSize(GetNativeThemePart(),
GetNativeThemeState(),
GetNativeThemeParams());
@@ -292,7 +292,7 @@ void NativeScrollBarViews::OnPaint(gfx::Canvas* canvas) {
GetNativeTheme()->Paint(canvas->sk_canvas(), part_, state_, bounds, params_);
}
-gfx::Size NativeScrollBarViews::GetPreferredSize() {
+gfx::Size NativeScrollBarViews::GetPreferredSize() const {
const ui::NativeTheme* theme = native_scroll_bar_->GetNativeTheme();
if (native_scroll_bar_->IsHorizontal())
return gfx::Size(0, GetHorizontalScrollBarHeight(theme));
diff --git a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.h b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.h
index 72d1821cbbf..38dbe0b6f8e 100644
--- a/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.h
+++ b/chromium/ui/views/controls/scrollbar/native_scroll_bar_views.h
@@ -36,7 +36,7 @@ class VIEWS_EXPORT NativeScrollBarViews : public BaseScrollBar,
// View overrides:
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
// ScrollBar overrides:
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index 176f7b9554e..1396bd1ec99 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -30,7 +30,7 @@ class OverlayScrollBarThumb : public BaseScrollBarThumb,
protected:
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
// gfx::AnimationDelegate overrides:
@@ -44,18 +44,16 @@ class OverlayScrollBarThumb : public BaseScrollBarThumb,
OverlayScrollBarThumb::OverlayScrollBarThumb(BaseScrollBar* scroll_bar)
: BaseScrollBarThumb(scroll_bar),
animation_opacity_(0.0) {
- if (get_use_acceleration_when_possible()) {
- // This is necessary, otherwise the thumb will be rendered below the views
- // if those views paint to their own layers.
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
- }
+ // This is necessary, otherwise the thumb will be rendered below the views if
+ // those views paint to their own layers.
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
}
OverlayScrollBarThumb::~OverlayScrollBarThumb() {
}
-gfx::Size OverlayScrollBarThumb::GetPreferredSize() {
+gfx::Size OverlayScrollBarThumb::GetPreferredSize() const {
return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
}
@@ -140,7 +138,7 @@ void OverlayScrollBar::OnGestureEvent(ui::GestureEvent* event) {
BaseScrollBar::OnGestureEvent(event);
}
-gfx::Size OverlayScrollBar::GetPreferredSize() {
+gfx::Size OverlayScrollBar::GetPreferredSize() const {
return gfx::Size();
}
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
index b061da08586..428a27715c4 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
@@ -28,7 +28,7 @@ class VIEWS_EXPORT OverlayScrollBar : public BaseScrollBar {
virtual void OnMouseExitedScrollView(const ui::MouseEvent& event) OVERRIDE;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.cc b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
index 5374d32ceef..014cf3b53fa 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
@@ -4,15 +4,15 @@
#include "ui/views/controls/scrollbar/scroll_bar.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
namespace views {
ScrollBar::~ScrollBar() {
}
-void ScrollBar::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_SCROLLBAR;
+void ScrollBar::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_SCROLL_BAR;
}
bool ScrollBar::IsHorizontal() const {
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.h b/chromium/ui/views/controls/scrollbar/scroll_bar.h
index aa3800eb614..c8a31c43016 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.h
@@ -60,7 +60,7 @@ class VIEWS_EXPORT ScrollBar : public View {
virtual ~ScrollBar();
// Overridden from View:
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// Returns whether this scrollbar is horizontal.
bool IsHorizontal() const;
diff --git a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
index cdf256a6207..c3c96df9b03 100644
--- a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
+++ b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
@@ -156,4 +156,15 @@ TEST_F(NativeScrollBarTest, MAYBE_ScrollBarFitsToBottom) {
scrollbar_->GetPosition());
}
+TEST_F(NativeScrollBarTest, ScrollToEndAfterShrinkAndExpand) {
+ // Scroll to the end of the content.
+ scrollbar_->Update(100, 101, 0);
+ EXPECT_TRUE(scrollbar_->ScrollByContentsOffset(-1));
+ // Shrink and then re-exapnd the content.
+ scrollbar_->Update(100, 100, 0);
+ scrollbar_->Update(100, 101, 0);
+ // Ensure the scrollbar allows scrolling to the end.
+ EXPECT_TRUE(scrollbar_->ScrollByContentsOffset(-1));
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/separator.cc b/chromium/ui/views/controls/separator.cc
index bbac3ede9de..a8fe6da7ef3 100644
--- a/chromium/ui/views/controls/separator.cc
+++ b/chromium/ui/views/controls/separator.cc
@@ -4,7 +4,7 @@
#include "ui/views/controls/separator.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/gfx/canvas.h"
namespace views {
@@ -28,17 +28,17 @@ Separator::~Separator() {
////////////////////////////////////////////////////////////////////////////////
// Separator, View overrides:
-gfx::Size Separator::GetPreferredSize() {
+gfx::Size Separator::GetPreferredSize() const {
if (orientation_ == HORIZONTAL)
return gfx::Size(width(), kSeparatorHeight);
return gfx::Size(kSeparatorHeight, height());
}
-void Separator::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_SEPARATOR;
+void Separator::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_SPLITTER;
}
-void Separator::Paint(gfx::Canvas* canvas) {
+void Separator::Paint(gfx::Canvas* canvas, const views::CullSet& cull_set) {
canvas->FillRect(bounds(), kDefaultColor);
}
diff --git a/chromium/ui/views/controls/separator.h b/chromium/ui/views/controls/separator.h
index 53d10041864..6f45f8cec7f 100644
--- a/chromium/ui/views/controls/separator.h
+++ b/chromium/ui/views/controls/separator.h
@@ -28,9 +28,10 @@ class VIEWS_EXPORT Separator : public View {
virtual ~Separator();
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
- virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
+ virtual void Paint(gfx::Canvas* canvas,
+ const views::CullSet& cull_set) OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
private:
diff --git a/chromium/ui/views/controls/single_split_view.cc b/chromium/ui/views/controls/single_split_view.cc
index 85dab92fa5d..fe50141293c 100644
--- a/chromium/ui/views/controls/single_split_view.cc
+++ b/chromium/ui/views/controls/single_split_view.cc
@@ -5,14 +5,12 @@
#include "ui/views/controls/single_split_view.h"
#include "skia/ext/skia_utils_win.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/gfx/canvas.h"
#include "ui/views/background.h"
#include "ui/views/controls/single_split_view_listener.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+#include "ui/views/native_cursor.h"
namespace views {
@@ -62,16 +60,16 @@ const char* SingleSplitView::GetClassName() const {
return kViewClassName;
}
-void SingleSplitView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_GROUPING;
+void SingleSplitView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_GROUP;
state->name = accessible_name_;
}
-gfx::Size SingleSplitView::GetPreferredSize() {
+gfx::Size SingleSplitView::GetPreferredSize() const {
int width = 0;
int height = 0;
for (int i = 0; i < 2 && i < child_count(); ++i) {
- View* view = child_at(i);
+ const View* view = child_at(i);
gfx::Size pref = view->GetPreferredSize();
if (is_horizontal_) {
width += pref.width();
@@ -91,14 +89,8 @@ gfx::Size SingleSplitView::GetPreferredSize() {
gfx::NativeCursor SingleSplitView::GetCursor(const ui::MouseEvent& event) {
if (!IsPointInDivider(event.location()))
return gfx::kNullCursor;
-#if defined(USE_AURA)
- return is_horizontal_ ?
- ui::kCursorEastWestResize : ui::kCursorNorthSouthResize;
-#elif defined(OS_WIN)
- static HCURSOR we_resize_cursor = LoadCursor(NULL, IDC_SIZEWE);
- static HCURSOR ns_resize_cursor = LoadCursor(NULL, IDC_SIZENS);
- return is_horizontal_ ? we_resize_cursor : ns_resize_cursor;
-#endif
+ return is_horizontal_ ? GetNativeEastWestResizeCursor()
+ : GetNativeNorthSouthResizeCursor();
}
int SingleSplitView::GetDividerSize() const {
@@ -148,7 +140,7 @@ void SingleSplitView::CalculateChildrenBounds(
}
}
-void SingleSplitView::SetAccessibleName(const string16& name) {
+void SingleSplitView::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
diff --git a/chromium/ui/views/controls/single_split_view.h b/chromium/ui/views/controls/single_split_view.h
index f4a336a6ef6..c03c8340e35 100644
--- a/chromium/ui/views/controls/single_split_view.h
+++ b/chromium/ui/views/controls/single_split_view.h
@@ -34,11 +34,11 @@ class VIEWS_EXPORT SingleSplitView : public View {
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// SingleSplitView's preferred size is the sum of the preferred widths
// and the max of the heights.
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
// Overriden to return a resize cursor when over the divider.
virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
@@ -77,7 +77,7 @@ class VIEWS_EXPORT SingleSplitView : public View {
gfx::Rect* leading_bounds,
gfx::Rect* trailing_bounds) const;
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
protected:
// View overrides.
@@ -137,7 +137,7 @@ class VIEWS_EXPORT SingleSplitView : public View {
SingleSplitViewListener* listener_;
// The accessible name of this view.
- string16 accessible_name_;
+ base::string16 accessible_name_;
DISALLOW_COPY_AND_ASSIGN(SingleSplitView);
};
diff --git a/chromium/ui/views/controls/single_split_view_listener.h b/chromium/ui/views/controls/single_split_view_listener.h
index 5c33c665214..0d589c9cfb8 100644
--- a/chromium/ui/views/controls/single_split_view_listener.h
+++ b/chromium/ui/views/controls/single_split_view_listener.h
@@ -5,13 +5,15 @@
#ifndef UI_VIEWS_CONTROLS_SINGLE_SPLIT_VIEW_LISTENER_H_
#define UI_VIEWS_CONTROLS_SINGLE_SPLIT_VIEW_LISTENER_H_
+#include "ui/views/views_export.h"
+
namespace views {
class SingleSplitView;
// An interface implemented by objects that want to be notified when the
// splitter moves.
-class SingleSplitViewListener {
+class VIEWS_EXPORT SingleSplitViewListener {
public:
// Invoked when split handle is moved by the user. |sender|'s divider_offset
// is already set to the new value, but Layout has not happened yet.
diff --git a/chromium/ui/views/controls/single_split_view_unittest.cc b/chromium/ui/views/controls/single_split_view_unittest.cc
index f82c1b5b090..cfea48ea4ab 100644
--- a/chromium/ui/views/controls/single_split_view_unittest.cc
+++ b/chromium/ui/views/controls/single_split_view_unittest.cc
@@ -2,15 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/controls/single_split_view.h"
+
#include "base/logging.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/controls/single_split_view.h"
#include "ui/views/controls/single_split_view_listener.h"
-using ::testing::_;
-using ::testing::Return;
-
namespace {
static void VerifySplitViewLayout(const views::SingleSplitView& split) {
@@ -44,9 +41,21 @@ static void VerifySplitViewLayout(const views::SingleSplitView& split) {
}
}
-class MockObserver : public views::SingleSplitViewListener {
+class SingleSplitViewListenerImpl : public views::SingleSplitViewListener {
public:
- MOCK_METHOD1(SplitHandleMoved, bool(views::SingleSplitView*));
+ SingleSplitViewListenerImpl() : count_(0) {}
+
+ virtual bool SplitHandleMoved(views::SingleSplitView* sender) OVERRIDE {
+ ++count_;
+ return false;
+ }
+
+ int count() const { return count_; }
+
+ private:
+ int count_;
+
+ DISALLOW_COPY_AND_ASSIGN(SingleSplitViewListenerImpl);
};
class MinimumSizedView: public views::View {
@@ -55,10 +64,10 @@ class MinimumSizedView: public views::View {
private:
gfx::Size min_size_;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
};
-gfx::Size MinimumSizedView::GetMinimumSize() {
+gfx::Size MinimumSizedView::GetMinimumSize() const {
return min_size_;
}
@@ -141,20 +150,14 @@ TEST(SingleSplitViewTest, Resize) {
}
TEST(SingleSplitViewTest, MouseDrag) {
- MockObserver observer;
const int kMinimumChildSize = 25;
MinimumSizedView *child0 =
new MinimumSizedView(gfx::Size(5, kMinimumChildSize));
MinimumSizedView *child1 =
new MinimumSizedView(gfx::Size(5, kMinimumChildSize));
+ SingleSplitViewListenerImpl listener;
SingleSplitView split(
- child0, child1, SingleSplitView::VERTICAL_SPLIT, &observer);
-
- ON_CALL(observer, SplitHandleMoved(_))
- .WillByDefault(Return(true));
- // SplitHandleMoved is called for two mouse moves and one mouse capture loss.
- EXPECT_CALL(observer, SplitHandleMoved(_))
- .Times(5);
+ child0, child1, SingleSplitView::VERTICAL_SPLIT, &listener);
const int kTotalSplitSize = 100;
split.SetBounds(0, 0, 10, kTotalSplitSize);
@@ -166,49 +169,53 @@ TEST(SingleSplitViewTest, MouseDrag) {
gfx::Point press_point(7, kInitialDividerOffset + kMouseOffset);
ui::MouseEvent mouse_pressed(
- ui::ET_MOUSE_PRESSED, press_point, press_point, 0);
+ ui::ET_MOUSE_PRESSED, press_point, press_point, 0, 0);
ASSERT_TRUE(split.OnMousePressed(mouse_pressed));
EXPECT_EQ(kInitialDividerOffset, split.divider_offset());
+ EXPECT_EQ(0, listener.count());
// Drag divider to the bottom.
gfx::Point drag_1_point(
5, kInitialDividerOffset + kMouseOffset + kMouseMoveDelta);
ui::MouseEvent mouse_dragged_1(
- ui::ET_MOUSE_DRAGGED, drag_1_point, drag_1_point, 0);
+ ui::ET_MOUSE_DRAGGED, drag_1_point, drag_1_point, 0, 0);
ASSERT_TRUE(split.OnMouseDragged(mouse_dragged_1));
EXPECT_EQ(kInitialDividerOffset + kMouseMoveDelta, split.divider_offset());
+ EXPECT_EQ(1, listener.count());
// Drag divider to the top, beyond first child minimum size.
gfx::Point drag_2_point(
7, kMinimumChildSize - 5);
ui::MouseEvent mouse_dragged_2(
- ui::ET_MOUSE_DRAGGED, drag_2_point, drag_2_point, 0);
+ ui::ET_MOUSE_DRAGGED, drag_2_point, drag_2_point, 0,0 );
ASSERT_TRUE(split.OnMouseDragged(mouse_dragged_2));
- EXPECT_EQ(kMinimumChildSize,
- split.divider_offset());
+ EXPECT_EQ(kMinimumChildSize, split.divider_offset());
+ EXPECT_EQ(2, listener.count());
// Drag divider to the bottom, beyond second child minimum size.
gfx::Point drag_3_point(
7, kTotalSplitSize - kMinimumChildSize + 5);
ui::MouseEvent mouse_dragged_3(
- ui::ET_MOUSE_DRAGGED, drag_3_point, drag_3_point, 0);
+ ui::ET_MOUSE_DRAGGED, drag_3_point, drag_3_point, 0, 0);
ASSERT_TRUE(split.OnMouseDragged(mouse_dragged_3));
EXPECT_EQ(kTotalSplitSize - kMinimumChildSize - split.GetDividerSize(),
split.divider_offset());
+ EXPECT_EQ(3, listener.count());
// Drag divider between childs' minimum sizes.
gfx::Point drag_4_point(
6, kInitialDividerOffset + kMouseOffset + kMouseMoveDelta * 2);
ui::MouseEvent mouse_dragged_4(
- ui::ET_MOUSE_DRAGGED, drag_4_point, drag_4_point, 0);
+ ui::ET_MOUSE_DRAGGED, drag_4_point, drag_4_point, 0, 0);
ASSERT_TRUE(split.OnMouseDragged(mouse_dragged_4));
EXPECT_EQ(kInitialDividerOffset + kMouseMoveDelta * 2,
split.divider_offset());
+ EXPECT_EQ(4, listener.count());
gfx::Point release_point(
7, kInitialDividerOffset + kMouseOffset + kMouseMoveDelta * 2);
ui::MouseEvent mouse_released(
- ui::ET_MOUSE_RELEASED, release_point, release_point, 0);
+ ui::ET_MOUSE_RELEASED, release_point, release_point, 0, 0);
split.OnMouseReleased(mouse_released);
EXPECT_EQ(kInitialDividerOffset + kMouseMoveDelta * 2,
split.divider_offset());
@@ -217,6 +224,7 @@ TEST(SingleSplitViewTest, MouseDrag) {
// This shouldn't occur after mouse release, but it's sufficient for testing.
split.OnMouseCaptureLost();
EXPECT_EQ(kInitialDividerOffset, split.divider_offset());
+ EXPECT_EQ(5, listener.count());
}
} // namespace views
diff --git a/chromium/ui/views/controls/slide_out_view.cc b/chromium/ui/views/controls/slide_out_view.cc
index d7cb3f6ef5f..d3cafecf7eb 100644
--- a/chromium/ui/views/controls/slide_out_view.cc
+++ b/chromium/ui/views/controls/slide_out_view.cc
@@ -14,10 +14,8 @@ SlideOutView::SlideOutView()
: gesture_scroll_amount_(0.f) {
// If accelerated compositing is not available, this widget tracks the
// OnSlideOut event but does not render any visible changes.
- if (get_use_acceleration_when_possible()) {
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
- }
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
}
SlideOutView::~SlideOutView() {
@@ -47,13 +45,11 @@ void SlideOutView::OnGestureEvent(ui::GestureEvent* event) {
// The scroll-update events include the incremental scroll amount.
gesture_scroll_amount_ += event->details().scroll_x();
- if (get_use_acceleration_when_possible()) {
- gfx::Transform transform;
- transform.Translate(gesture_scroll_amount_, 0.0);
- layer()->SetTransform(transform);
- layer()->SetOpacity(
- 1.f - std::min(fabsf(gesture_scroll_amount_) / width(), 1.f));
- }
+ gfx::Transform transform;
+ transform.Translate(gesture_scroll_amount_, 0.0);
+ layer()->SetTransform(transform);
+ layer()->SetOpacity(
+ 1.f - std::min(fabsf(gesture_scroll_amount_) / width(), 1.f));
} else if (event->type() == ui::ET_GESTURE_SCROLL_END) {
const float kScrollRatioForClosingNotification = 0.5f;
@@ -70,9 +66,6 @@ void SlideOutView::OnGestureEvent(ui::GestureEvent* event) {
}
void SlideOutView::RestoreVisualState() {
- if (!get_use_acceleration_when_possible())
- return;
-
// Restore the layer state.
const int kSwipeRestoreDurationMS = 150;
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
@@ -83,11 +76,6 @@ void SlideOutView::RestoreVisualState() {
}
void SlideOutView::SlideOutAndClose(SlideDirection direction) {
- if (!get_use_acceleration_when_possible()) {
- // No animations, so don't wait to fire the OnSlideOut event.
- OnSlideOut();
- return;
- }
const int kSwipeOutTotalDurationMS = 150;
int swipe_out_duration = kSwipeOutTotalDurationMS * layer()->opacity();
ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
diff --git a/chromium/ui/views/controls/slider.cc b/chromium/ui/views/controls/slider.cc
index 4be6f5a2d56..74e803d454b 100644
--- a/chromium/ui/views/controls/slider.cc
+++ b/chromium/ui/views/controls/slider.cc
@@ -4,6 +4,8 @@
#include "ui/views/controls/slider.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
@@ -12,7 +14,7 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPaint.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/gfx/animation/slide_animation.h"
@@ -45,7 +47,7 @@ enum BorderElements {
CENTER_RIGHT,
RIGHT,
};
-}
+} // namespace
namespace views {
@@ -81,7 +83,7 @@ void Slider::SetValueInternal(float value, SliderChangeReason reason) {
value_is_valid_ = true;
if (value < 0.0)
- value = 0.0;
+ value = 0.0;
else if (value > 1.0)
value = 1.0;
if (value_ == value)
@@ -104,7 +106,7 @@ void Slider::SetValueInternal(float value, SliderChangeReason reason) {
}
if (accessibility_events_enabled_ && GetWidget()) {
NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_VALUE_CHANGED, true);
+ ui::AX_EVENT_VALUE_CHANGED, true);
}
}
@@ -167,7 +169,7 @@ void Slider::UpdateState(bool control_on) {
SchedulePaint();
}
-void Slider::SetAccessibleName(const string16& name) {
+void Slider::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
@@ -184,7 +186,7 @@ void Slider::OnPaintFocus(gfx::Canvas* canvas) {
}
}
-gfx::Size Slider::GetPreferredSize() {
+gfx::Size Slider::GetPreferredSize() const {
const int kSizeMajor = 200;
const int kSizeMinor = 40;
@@ -267,8 +269,7 @@ void Slider::OnPaint(gfx::Canvas* canvas) {
bool Slider::OnMousePressed(const ui::MouseEvent& event) {
if (!event.IsOnlyLeftMouseButton())
return false;
- if (listener_)
- listener_->SliderDragStarted(this);
+ OnSliderDragStarted();
PrepareForMove(event.location());
MoveButtonTo(event.location());
return true;
@@ -280,8 +281,7 @@ bool Slider::OnMouseDragged(const ui::MouseEvent& event) {
}
void Slider::OnMouseReleased(const ui::MouseEvent& event) {
- if (listener_)
- listener_->SliderDragEnded(this);
+ OnSliderDragEnded();
}
bool Slider::OnKeyPressed(const ui::KeyEvent& event) {
@@ -305,16 +305,37 @@ bool Slider::OnKeyPressed(const ui::KeyEvent& event) {
return false;
}
+void Slider::OnFocus() {
+ View::OnFocus();
+ SchedulePaint();
+}
+
+void Slider::OnBlur() {
+ View::OnBlur();
+ SchedulePaint();
+}
+
void Slider::OnGestureEvent(ui::GestureEvent* event) {
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
- event->type() == ui::ET_GESTURE_TAP_DOWN) {
- PrepareForMove(event->location());
- MoveButtonTo(event->location());
- event->SetHandled();
- } else if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
- event->type() == ui::ET_GESTURE_SCROLL_END) {
- MoveButtonTo(event->location());
- event->SetHandled();
+ switch (event->type()) {
+ // In a multi point gesture only the touch point will generate
+ // an ET_GESTURE_TAP_DOWN event.
+ case ui::ET_GESTURE_TAP_DOWN:
+ OnSliderDragStarted();
+ PrepareForMove(event->location());
+ // Intentional fall through to next case.
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ MoveButtonTo(event->location());
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_END:
+ MoveButtonTo(event->location());
+ event->SetHandled();
+ if (event->details().touch_points() <= 1)
+ OnSliderDragEnded();
+ break;
+ default:
+ break;
}
}
@@ -323,11 +344,21 @@ void Slider::AnimationProgressed(const gfx::Animation* animation) {
SchedulePaint();
}
-void Slider::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_SLIDER;
+void Slider::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_SLIDER;
state->name = accessible_name_;
- state->value = UTF8ToUTF16(
- base::StringPrintf("%d%%", (int)(value_ * 100 + 0.5)));
+ state->value = base::UTF8ToUTF16(
+ base::StringPrintf("%d%%", static_cast<int>(value_ * 100 + 0.5)));
+}
+
+void Slider::OnSliderDragStarted() {
+ if (listener_)
+ listener_->SliderDragStarted(this);
+}
+
+void Slider::OnSliderDragEnded() {
+ if (listener_)
+ listener_->SliderDragEnded(this);
}
} // namespace views
diff --git a/chromium/ui/views/controls/slider.h b/chromium/ui/views/controls/slider.h
index cec24c2755b..33a760bfd66 100644
--- a/chromium/ui/views/controls/slider.h
+++ b/chromium/ui/views/controls/slider.h
@@ -18,6 +18,10 @@ class SlideAnimation;
namespace views {
+namespace test {
+class SliderTestApi;
+}
+
class Slider;
enum SliderChangeReason {
@@ -57,7 +61,7 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
// Set the delta used for changing the value via keyboard.
void SetKeyboardIncrement(float increment);
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
void set_enable_accessibility_events(bool enabled) {
accessibility_events_enabled_ = enabled;
@@ -69,6 +73,8 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
void UpdateState(bool control_on);
private:
+ friend class test::SliderTestApi;
+
void SetValueInternal(float value, SliderChangeReason reason);
// Should be called on the Mouse Down event. Used to calculate relative
@@ -81,14 +87,22 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
void OnPaintFocus(gfx::Canvas* canvas);
+ // Notify the listener_, if not NULL, that dragging started.
+ void OnSliderDragStarted();
+
+ // Notify the listener_, if not NULL, that dragging ended.
+ void OnSliderDragEnded();
+
// views::View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnBlur() OVERRIDE;
// ui::EventHandler overrides:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
@@ -96,6 +110,10 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
// gfx::AnimationDelegate overrides:
virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+ void set_listener(SliderListener* listener) {
+ listener_ = listener;
+ }
+
SliderListener* listener_;
Orientation orientation_;
@@ -105,7 +123,7 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
float keyboard_increment_;
float animating_value_;
bool value_is_valid_;
- string16 accessible_name_;
+ base::string16 accessible_name_;
bool accessibility_events_enabled_;
SkColor focus_border_color_;
diff --git a/chromium/ui/views/controls/slider_unittest.cc b/chromium/ui/views/controls/slider_unittest.cc
index 7add734ec36..da6700e0f72 100644
--- a/chromium/ui/views/controls/slider_unittest.cc
+++ b/chromium/ui/views/controls/slider_unittest.cc
@@ -4,73 +4,381 @@
#include "ui/views/controls/slider.h"
+#include <string>
+
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/events/event.h"
+#include "ui/events/gesture_event_details.h"
+#include "ui/views/test/slider_test_api.h"
+#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
namespace {
-void ClickAt(views::View* view, int x, int y) {
- gfx::Point point(x, y);
- ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- view->OnMousePressed(press);
- ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- view->OnMouseReleased(release);
+// A views::SliderListener that tracks simple event call history.
+class TestSliderListener : public views::SliderListener {
+ public:
+ TestSliderListener();
+ virtual ~TestSliderListener();
+
+ int last_event_epoch() {
+ return last_event_epoch_;
+ }
+
+ int last_drag_started_epoch() {
+ return last_drag_started_epoch_;
+ }
+
+ int last_drag_ended_epoch() {
+ return last_drag_ended_epoch_;
+ }
+
+ views::Slider* last_drag_started_sender() {
+ return last_drag_started_sender_;
+ }
+
+ views::Slider* last_drag_ended_sender() {
+ return last_drag_ended_sender_;
+ }
+
+ // Resets the state of this as if it were newly created.
+ virtual void ResetCallHistory();
+
+ // views::SliderListener:
+ virtual void SliderValueChanged(views::Slider* sender,
+ float value,
+ float old_value,
+ views::SliderChangeReason reason) OVERRIDE;
+ virtual void SliderDragStarted(views::Slider* sender) OVERRIDE;
+ virtual void SliderDragEnded(views::Slider* sender) OVERRIDE;
+
+ private:
+ // The epoch of the last event.
+ int last_event_epoch_;
+ // The epoch of the last time SliderDragStarted was called.
+ int last_drag_started_epoch_;
+ // The epoch of the last time SliderDragEnded was called.
+ int last_drag_ended_epoch_;
+ // The sender from the last SliderDragStarted call.
+ views::Slider* last_drag_started_sender_;
+ // The sender from the last SliderDragEnded call.
+ views::Slider* last_drag_ended_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSliderListener);
+};
+
+TestSliderListener::TestSliderListener()
+ : last_event_epoch_(0),
+ last_drag_started_epoch_(-1),
+ last_drag_ended_epoch_(-1),
+ last_drag_started_sender_(NULL),
+ last_drag_ended_sender_(NULL) {
+}
+
+TestSliderListener::~TestSliderListener() {
+ last_drag_started_sender_ = NULL;
+ last_drag_ended_sender_ = NULL;
+}
+
+void TestSliderListener::ResetCallHistory() {
+ last_event_epoch_ = 0;
+ last_drag_started_epoch_ = -1;
+ last_drag_ended_epoch_ = -1;
+ last_drag_started_sender_ = NULL;
+ last_drag_ended_sender_ = NULL;
+}
+
+void TestSliderListener::SliderValueChanged(views::Slider* sender,
+ float value,
+ float old_value,
+ views::SliderChangeReason reason) {
+ ++last_event_epoch_;
+}
+
+void TestSliderListener::SliderDragStarted(views::Slider* sender) {
+ last_drag_started_sender_ = sender;
+ last_drag_started_epoch_ = ++last_event_epoch_;
}
+void TestSliderListener::SliderDragEnded(views::Slider* sender) {
+ last_drag_ended_sender_ = sender;
+ last_drag_ended_epoch_ = ++last_event_epoch_;
}
+} // namespace
+
namespace views {
-TEST(SliderTest, UpdateFromClickHorizontal) {
- scoped_ptr<Slider> slider(new Slider(NULL, Slider::HORIZONTAL));
- View* view = slider.get();
- gfx::Size size = view->GetPreferredSize();
- view->SetSize(size);
+// Base test fixture for Slider tests.
+class SliderTest : public views::ViewsTestBase {
+ public:
+ explicit SliderTest(Slider::Orientation orientation);
+ virtual ~SliderTest();
+
+ protected:
+ Slider* slider() {
+ return slider_;
+ }
+
+ TestSliderListener& slider_listener() {
+ return slider_listener_;
+ }
+
+ int max_x() {
+ return max_x_;
+ }
+
+ int max_y() {
+ return max_y_;
+ }
+
+ virtual void ClickAt(int x, int y);
+
+ // testing::Test:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ aura::test::EventGenerator* event_generator() {
+ return event_generator_.get();
+ }
- ClickAt(view, 0, 0);
- EXPECT_EQ(0.0f, slider->value());
+ private:
+ // The Slider's orientation
+ Slider::Orientation orientation_;
+ // The Slider to be tested.
+ Slider* slider_;
+ // A simple SliderListener test double.
+ TestSliderListener slider_listener_;
+ // Stores the default locale at test setup so it can be restored
+ // during test teardown.
+ std::string default_locale_;
+ // The maximum x value within the bounds of the slider.
+ int max_x_;
+ // The maximum y value within the bounds of the slider.
+ int max_y_;
+ // The widget container for the slider being tested.
+ views::Widget* widget_;
+ // An event generator.
+ scoped_ptr<aura::test::EventGenerator> event_generator_;
- ClickAt(view, view->width(), 0);
- EXPECT_EQ(1.0f, slider->value());
+ DISALLOW_COPY_AND_ASSIGN(SliderTest);
+};
+
+SliderTest::SliderTest(Slider::Orientation orientation)
+ : orientation_(orientation),
+ slider_(NULL),
+ default_locale_(""),
+ max_x_(0),
+ max_y_(0) {
+}
+
+SliderTest::~SliderTest() {
}
-TEST(SliderTest, UpdateFromClickVertical) {
- scoped_ptr<Slider> slider(new Slider(NULL, Slider::VERTICAL));
- View* view = slider.get();
+void SliderTest::SetUp() {
+ views::ViewsTestBase::SetUp();
+
+ slider_ = new Slider(NULL, orientation_);
+ View* view = slider_;
gfx::Size size = view->GetPreferredSize();
view->SetSize(size);
+ max_x_ = size.width() - 1;
+ max_y_ = size.height() - 1;
+ default_locale_ = l10n_util::GetApplicationLocale("");
+
+ views::Widget::InitParams init_params(CreateParams(
+ views::Widget::InitParams::TYPE_WINDOW_FRAMELESS));
+ init_params.bounds = gfx::Rect(size);
- ClickAt(view, 0, 0);
- EXPECT_EQ(1.0f, slider->value());
+ widget_ = new views::Widget();
+ widget_->Init(init_params);
+ widget_->SetContentsView(slider_);
+ widget_->Show();
- ClickAt(view, 0, view->height());
- EXPECT_EQ(0.0f, slider->value());
+ aura::Window* native_window = widget_->GetNativeWindow();
+ event_generator_.reset(new aura::test::EventGenerator(
+ native_window->GetRootWindow()));
}
-TEST(SliderTest, UpdateFromClickRTLHorizontal) {
- std::string locale = l10n_util::GetApplicationLocale("");
+void SliderTest::TearDown() {
+ if (widget_ && !widget_->IsClosed())
+ widget_->Close();
+
+ base::i18n::SetICUDefaultLocale(default_locale_);
+
+ views::ViewsTestBase::TearDown();
+}
+
+void SliderTest::ClickAt(int x, int y) {
+ gfx::Point point(x, y);
+ event_generator_->MoveMouseTo(point);
+ event_generator_->ClickLeftButton();
+}
+
+// Test fixture for horizontally oriented slider tests.
+class HorizontalSliderTest : public SliderTest {
+ public:
+ HorizontalSliderTest();
+ virtual ~HorizontalSliderTest();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HorizontalSliderTest);
+};
+
+HorizontalSliderTest::HorizontalSliderTest()
+ : SliderTest(Slider::HORIZONTAL) {
+}
+
+HorizontalSliderTest::~HorizontalSliderTest() {
+}
+
+// Test fixture for vertically oriented slider tests.
+class VerticalSliderTest : public SliderTest {
+ public:
+ VerticalSliderTest();
+ virtual ~VerticalSliderTest();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VerticalSliderTest);
+};
+
+VerticalSliderTest::VerticalSliderTest()
+ : SliderTest(Slider::VERTICAL) {
+}
+
+VerticalSliderTest::~VerticalSliderTest() {
+}
+
+TEST_F(HorizontalSliderTest, UpdateFromClickHorizontal) {
+ ClickAt(0, 0);
+ EXPECT_EQ(0.0f, slider()->value());
+
+ ClickAt(max_x(), 0);
+ EXPECT_EQ(1.0f, slider()->value());
+}
+
+TEST_F(VerticalSliderTest, UpdateFromClickVertical) {
+ ClickAt(0, 0);
+ EXPECT_EQ(1.0f, slider()->value());
+
+ ClickAt(0, max_y());
+ EXPECT_EQ(0.0f, slider()->value());
+}
+
+TEST_F(HorizontalSliderTest, UpdateFromClickRTLHorizontal) {
base::i18n::SetICUDefaultLocale("he");
- scoped_ptr<Slider> slider(new Slider(NULL, Slider::HORIZONTAL));
- View* view = slider.get();
- gfx::Size size = view->GetPreferredSize();
- view->SetSize(size);
+ ClickAt(0, 0);
+ EXPECT_EQ(1.0f, slider()->value());
+
+ ClickAt(max_x(), 0);
+ EXPECT_EQ(0.0f, slider()->value());
+}
+
+// Test the slider location after a tap gesture.
+TEST_F(HorizontalSliderTest, SliderValueForTapGesture) {
+ // Tap below the minimum.
+ slider()->SetValue(0.5);
+ event_generator()->GestureTapAt(gfx::Point(0, 0));
+ EXPECT_FLOAT_EQ(0, slider()->value());
+
+ // Tap above the maximum.
+ slider()->SetValue(0.5);
+ event_generator()->GestureTapAt(gfx::Point(max_x(), max_y()));
+ EXPECT_FLOAT_EQ(1, slider()->value());
+
+ // 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);
+}
+
+// Test the slider location after a scroll gesture.
+TEST_F(HorizontalSliderTest, SliderValueForScrollGesture) {
+ // Scroll below the minimum.
+ slider()->SetValue(0.5);
+ 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());
+
+ // 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());
+
+ // Scroll somewhere in the middle.
+ slider()->SetValue(0.25);
+ event_generator()->GestureScrollSequence(
+ 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);
+}
+
+// Verifies the correct SliderListener events are raised for a tap gesture.
+TEST_F(HorizontalSliderTest, SliderListenerEventsForTapGesture) {
+ test::SliderTestApi slider_test_api(slider());
+ slider_test_api.SetListener(&slider_listener());
+
+ event_generator()->GestureTapAt(gfx::Point(0, 0));
+ EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
+ EXPECT_EQ(2, slider_listener().last_drag_ended_epoch());
+ EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
+ EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
+}
+
+// Verifies the correct SliderListener events are raised for a scroll gesture.
+TEST_F(HorizontalSliderTest, SliderListenerEventsForScrollGesture) {
+ test::SliderTestApi slider_test_api(slider());
+ slider_test_api.SetListener(&slider_listener());
+
+ event_generator()->GestureScrollSequence(
+ gfx::Point(0.25 * max_x(), 0.25 * max_y()),
+ gfx::Point(0.75 * max_x(), 0.75 * max_y()),
+ base::TimeDelta::FromMilliseconds(0),
+ 5 /* steps */);
+
+ EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
+ EXPECT_GT(slider_listener().last_drag_ended_epoch(),
+ slider_listener().last_drag_started_epoch());
+ EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
+ EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
+}
- ClickAt(view, 0, 0);
- EXPECT_EQ(1.0f, slider->value());
+// Verifies the correct SliderListener events are raised for a multi
+// finger scroll gesture.
+TEST_F(HorizontalSliderTest, SliderListenerEventsForMultiFingerScrollGesture) {
+ test::SliderTestApi slider_test_api(slider());
+ slider_test_api.SetListener(&slider_listener());
- ClickAt(view, view->width(), 0);
- EXPECT_EQ(0.0f, slider->value());
+ gfx::Point points[] = {gfx::Point(0, 0.1 * max_y()),
+ gfx::Point(0, 0.2 * max_y())};
+ event_generator()->GestureMultiFingerScroll(2 /* count */, points,
+ 0 /* event_separation_time_ms */, 5 /* steps */,
+ 2 /* move_x */, 0 /* move_y */);
- // Reset locale.
- base::i18n::SetICUDefaultLocale(locale);
+ EXPECT_EQ(1, slider_listener().last_drag_started_epoch());
+ EXPECT_GT(slider_listener().last_drag_ended_epoch(),
+ slider_listener().last_drag_started_epoch());
+ EXPECT_EQ(slider(), slider_listener().last_drag_started_sender());
+ EXPECT_EQ(slider(), slider_listener().last_drag_ended_sender());
}
} // namespace views
diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc
index 96cc275c2d1..e7ee56c0b44 100644
--- a/chromium/ui/views/controls/styled_label.cc
+++ b/chromium/ui/views/controls/styled_label.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/strings/string_util.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/text_elider.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/label.h"
@@ -15,17 +16,22 @@
namespace views {
+
+// Helpers --------------------------------------------------------------------
+
namespace {
// Calculates the height of a line of text. Currently returns the height of
// a label.
-int CalculateLineHeight() {
+int CalculateLineHeight(const gfx::FontList& font_list) {
Label label;
+ label.SetFontList(font_list);
return label.GetPreferredSize().height();
}
scoped_ptr<Label> CreateLabelRange(
- const string16& text,
+ const base::string16& text,
+ const gfx::FontList& font_list,
const StyledLabel::RangeStyleInfo& style_info,
views::LinkListener* link_listener) {
scoped_ptr<Label> result;
@@ -36,26 +42,27 @@ scoped_ptr<Label> CreateLabelRange(
link->SetUnderline((style_info.font_style & gfx::Font::UNDERLINE) != 0);
result.reset(link);
} else {
- Label* label = new Label(text);
- // Give the label a focus border so that its preferred size matches
- // links' preferred sizes
- label->SetHasFocusBorder(true);
-
- result.reset(label);
+ result.reset(new Label(text));
}
result->SetEnabledColor(style_info.color);
+ result->SetFontList(font_list);
if (!style_info.tooltip.empty())
result->SetTooltipText(style_info.tooltip);
- if (style_info.font_style != gfx::Font::NORMAL)
- result->SetFont(result->font().DeriveFont(0, style_info.font_style));
+ if (style_info.font_style != gfx::Font::NORMAL) {
+ result->SetFontList(
+ result->font_list().DeriveWithStyle(style_info.font_style));
+ }
- return scoped_ptr<Label>(result.release());
+ return result.Pass();
}
} // namespace
+
+// StyledLabel::RangeStyleInfo ------------------------------------------------
+
StyledLabel::RangeStyleInfo::RangeStyleInfo()
: font_style(gfx::Font::NORMAL),
color(ui::NativeTheme::instance()->GetSystemColor(
@@ -74,35 +81,49 @@ StyledLabel::RangeStyleInfo StyledLabel::RangeStyleInfo::CreateForLink() {
return result;
}
+
+// StyledLabel::StyleRange ----------------------------------------------------
+
bool StyledLabel::StyleRange::operator<(
const StyledLabel::StyleRange& other) const {
- // Intentionally reversed so the priority queue is sorted by smallest first.
- return range.start() > other.range.start();
+ return range.start() < other.range.start();
}
-StyledLabel::StyledLabel(const string16& text, StyledLabelListener* listener)
+
+// StyledLabel ----------------------------------------------------------------
+
+StyledLabel::StyledLabel(const base::string16& text,
+ StyledLabelListener* listener)
: listener_(listener),
displayed_on_background_color_set_(false),
auto_color_readability_enabled_(true) {
- TrimWhitespace(text, TRIM_TRAILING, &text_);
+ base::TrimWhitespace(text, base::TRIM_TRAILING, &text_);
}
StyledLabel::~StyledLabel() {}
-void StyledLabel::SetText(const string16& text) {
+void StyledLabel::SetText(const base::string16& text) {
text_ = text;
- style_ranges_ = std::priority_queue<StyleRange>();
+ style_ranges_.clear();
RemoveAllChildViews(true);
PreferredSizeChanged();
}
+void StyledLabel::SetBaseFontList(const gfx::FontList& font_list) {
+ font_list_ = font_list;
+ PreferredSizeChanged();
+}
+
void StyledLabel::AddStyleRange(const gfx::Range& range,
const RangeStyleInfo& style_info) {
DCHECK(!range.is_reversed());
DCHECK(!range.is_empty());
DCHECK(gfx::Range(0, text_.size()).Contains(range));
- style_ranges_.push(StyleRange(range, style_info));
+ // Insert the new range in sorted order.
+ StyleRanges new_range;
+ new_range.push_front(StyleRange(range, style_info));
+ style_ranges_.merge(new_range);
PreferredSizeChanged();
}
@@ -119,20 +140,37 @@ void StyledLabel::SetDisplayedOnBackgroundColor(SkColor color) {
gfx::Insets StyledLabel::GetInsets() const {
gfx::Insets insets = View::GetInsets();
- const gfx::Insets focus_border_padding(1, 1, 1, 1);
- insets += focus_border_padding;
+
+ // We need a focus border iff we contain a link that will have a focus border.
+ // That in turn will be true only if the link is non-empty.
+ for (StyleRanges::const_iterator i(style_ranges_.begin());
+ i != style_ranges_.end(); ++i) {
+ if (i->style_info.is_link && !i->range.is_empty()) {
+ const gfx::Insets focus_border_padding(
+ Label::kFocusBorderPadding, Label::kFocusBorderPadding,
+ Label::kFocusBorderPadding, Label::kFocusBorderPadding);
+ insets += focus_border_padding;
+ break;
+ }
+ }
+
return insets;
}
-int StyledLabel::GetHeightForWidth(int w) {
- if (w != calculated_size_.width())
- calculated_size_ = gfx::Size(w, CalculateAndDoLayout(w, true));
-
+int StyledLabel::GetHeightForWidth(int w) const {
+ if (w != calculated_size_.width()) {
+ // TODO(erg): Munge the const-ness of the style label. CalculateAndDoLayout
+ // doesn't actually make any changes to member variables when |dry_run| is
+ // set to true. In general, the mutating and non-mutating parts shouldn't
+ // be in the same codepath.
+ calculated_size_ =
+ const_cast<StyledLabel*>(this)->CalculateAndDoLayout(w, true);
+ }
return calculated_size_.height();
}
void StyledLabel::Layout() {
- CalculateAndDoLayout(GetLocalBounds().width(), false);
+ calculated_size_ = CalculateAndDoLayout(GetLocalBounds().width(), false);
}
void StyledLabel::PreferredSizeChanged() {
@@ -145,7 +183,7 @@ void StyledLabel::LinkClicked(Link* source, int event_flags) {
listener_->StyledLabelLinkClicked(link_targets_[source], event_flags);
}
-int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
+gfx::Size StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
if (!dry_run) {
RemoveAllChildViews(true);
link_targets_.clear();
@@ -153,41 +191,43 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
width -= GetInsets().width();
if (width <= 0 || text_.empty())
- return 0;
+ return gfx::Size();
- const int line_height = CalculateLineHeight();
+ const int line_height = CalculateLineHeight(font_list_);
// The index of the line we're on.
int line = 0;
// The x position (in pixels) of the line we're on, relative to content
// bounds.
int x = 0;
- string16 remaining_string = text_;
- std::priority_queue<StyleRange> style_ranges = style_ranges_;
+ base::string16 remaining_string = text_;
+ StyleRanges::const_iterator current_range = style_ranges_.begin();
// Iterate over the text, creating a bunch of labels and links and laying them
// out in the appropriate positions.
while (!remaining_string.empty()) {
// Don't put whitespace at beginning of a line with an exception for the
// first line (so the text's leading whitespace is respected).
- if (x == 0 && line > 0)
- TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string);
+ if (x == 0 && line > 0) {
+ base::TrimWhitespace(remaining_string, base::TRIM_LEADING,
+ &remaining_string);
+ }
gfx::Range range(gfx::Range::InvalidRange());
- if (!style_ranges.empty())
- range = style_ranges.top().range;
+ if (current_range != style_ranges_.end())
+ range = current_range->range;
const size_t position = text_.size() - remaining_string.size();
const gfx::Rect chunk_bounds(x, 0, width - x, 2 * line_height);
- std::vector<string16> substrings;
- gfx::FontList text_font_list;
+ std::vector<base::string16> substrings;
+ gfx::FontList text_font_list = font_list_;
// If the start of the remaining text is inside a styled range, the font
// style may differ from the base font. The font specified by the range
// should be used when eliding text.
if (position >= range.start()) {
- text_font_list = text_font_list.DeriveFontListWithSizeDeltaAndStyle(
- 0, style_ranges.top().style_info.font_style);
+ text_font_list = text_font_list.DeriveWithStyle(
+ current_range->style_info.font_style);
}
gfx::ElideRectangleText(remaining_string,
text_font_list,
@@ -197,7 +237,7 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
&substrings);
DCHECK(!substrings.empty());
- string16 chunk = substrings[0];
+ base::string16 chunk = substrings[0];
if (chunk.empty()) {
// Nothing fits on this line. Start a new line.
// If x is 0, first line may have leading whitespace that doesn't fit in a
@@ -205,7 +245,8 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
// anything; abort.
if (x == 0) {
if (line == 0) {
- TrimWhitespace(remaining_string, TRIM_LEADING, &remaining_string);
+ base::TrimWhitespace(remaining_string, base::TRIM_LEADING,
+ &remaining_string);
continue;
}
break;
@@ -218,7 +259,7 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
scoped_ptr<Label> label;
if (position >= range.start()) {
- const RangeStyleInfo& style_info = style_ranges.top().style_info;
+ const RangeStyleInfo& style_info = current_range->style_info;
if (style_info.disable_line_wrapping && chunk.size() < range.length() &&
position == range.start() && x != 0) {
@@ -231,42 +272,44 @@ int StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
chunk = chunk.substr(0, std::min(chunk.size(), range.end() - position));
- label = CreateLabelRange(chunk, style_info, this);
+ label = CreateLabelRange(chunk, font_list_, style_info, this);
if (style_info.is_link && !dry_run)
link_targets_[label.get()] = range;
if (position + chunk.size() >= range.end())
- style_ranges.pop();
+ ++current_range;
} else {
// This chunk is normal text.
if (position + chunk.size() > range.start())
chunk = chunk.substr(0, range.start() - position);
- label = CreateLabelRange(chunk, default_style_info_, this);
+ label = CreateLabelRange(chunk, font_list_, default_style_info_, this);
}
if (displayed_on_background_color_set_)
label->SetBackgroundColor(displayed_on_background_color_);
label->SetAutoColorReadabilityEnabled(auto_color_readability_enabled_);
- // Lay out the views to overlap by 1 pixel to compensate for their border
- // spacing. Otherwise, "<a>link</a>," will render as "link ,".
- const int overlap = 1;
+ // Calculate the size of the optional focus border, and overlap by that
+ // amount. Otherwise, "<a>link</a>," will render as "link ,".
+ gfx::Insets focus_border_insets(label->GetInsets());
+ focus_border_insets += -label->View::GetInsets();
const gfx::Size view_size = label->GetPreferredSize();
- DCHECK_EQ(line_height, view_size.height() - 2 * overlap);
+ DCHECK_EQ(line_height, view_size.height() - focus_border_insets.height());
if (!dry_run) {
label->SetBoundsRect(gfx::Rect(
- gfx::Point(GetInsets().left() + x - overlap,
- GetInsets().top() + line * line_height - overlap),
+ gfx::Point(GetInsets().left() + x - focus_border_insets.left(),
+ GetInsets().top() + line * line_height -
+ focus_border_insets.top()),
view_size));
AddChildView(label.release());
}
- x += view_size.width() - 2 * overlap;
+ x += view_size.width() - focus_border_insets.width();
remaining_string = remaining_string.substr(chunk.size());
}
- return (line + 1) * line_height + GetInsets().height();
+ return gfx::Size(width, (line + 1) * line_height + GetInsets().height());
}
} // namespace views
diff --git a/chromium/ui/views/controls/styled_label.h b/chromium/ui/views/controls/styled_label.h
index adf5993a767..4c599a0d438 100644
--- a/chromium/ui/views/controls/styled_label.h
+++ b/chromium/ui/views/controls/styled_label.h
@@ -5,12 +5,13 @@
#ifndef UI_VIEWS_CONTROLS_STYLED_LABEL_H_
#define UI_VIEWS_CONTROLS_STYLED_LABEL_H_
+#include <list>
#include <map>
-#include <queue>
#include "base/basictypes.h"
#include "base/strings/string16.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/range/range.h"
#include "ui/gfx/size.h"
#include "ui/views/controls/link_listener.h"
@@ -44,7 +45,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
SkColor color;
// Tooltip for the range.
- string16 tooltip;
+ base::string16 tooltip;
// If set, the whole range will be put on a single line.
bool disable_line_wrapping;
@@ -54,11 +55,15 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
};
// Note that any trailing whitespace in |text| will be trimmed.
- StyledLabel(const string16& text, StyledLabelListener* listener);
+ StyledLabel(const base::string16& text, StyledLabelListener* listener);
virtual ~StyledLabel();
// Sets the text to be displayed, and clears any previous styling.
- void SetText(const string16& text);
+ void SetText(const base::string16& text);
+
+ // Sets the fonts used by all labels. Can be augemented by styling set by
+ // AddStyleRange and SetDefaultStyle.
+ void SetBaseFontList(const gfx::FontList& font_list);
// Marks the given range within |text_| with style defined by |style_info|.
// |range| must be contained in |text_|.
@@ -82,7 +87,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
// View implementation:
virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual int GetHeightForWidth(int w) OVERRIDE;
+ virtual int GetHeightForWidth(int w) const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void PreferredSizeChanged() OVERRIDE;
@@ -103,15 +108,19 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
gfx::Range range;
RangeStyleInfo style_info;
};
+ typedef std::list<StyleRange> StyleRanges;
// Calculates how to layout child views, creates them and sets their size
// and position. |width| is the horizontal space, in pixels, that the view
// has to work with. If |dry_run| is true, the view hierarchy is not touched.
- // The return value is the height in pixels.
- int CalculateAndDoLayout(int width, bool dry_run);
+ // The return value is the necessary size.
+ gfx::Size CalculateAndDoLayout(int width, bool dry_run);
// The text to display.
- string16 text_;
+ base::string16 text_;
+
+ // Fonts used to display text. Can be augmented by RangeStyleInfo.
+ gfx::FontList font_list_;
// The default style to use for any part of the text that isn't within
// a range in |style_ranges_|.
@@ -121,7 +130,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
StyledLabelListener* listener_;
// The ranges that should be linkified, sorted by start position.
- std::priority_queue<StyleRange> style_ranges_;
+ StyleRanges style_ranges_;
// A mapping from a view to the range it corresponds to in |text_|. Only views
// that correspond to ranges with is_link style set will be added to the map.
@@ -129,7 +138,7 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
// This variable saves the result of the last GetHeightForWidth call in order
// to avoid repeated calculation.
- gfx::Size calculated_size_;
+ mutable gfx::Size calculated_size_;
// Background color on which the label is drawn, for auto color readability.
SkColor displayed_on_background_color_;
diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc
index 18595edf3d5..d360aedb1b0 100644
--- a/chromium/ui/views/controls/styled_label_unittest.cc
+++ b/chromium/ui/views/controls/styled_label_unittest.cc
@@ -9,14 +9,19 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/border.h"
#include "ui/views/controls/link.h"
#include "ui/views/controls/styled_label.h"
#include "ui/views/controls/styled_label_listener.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+
+using base::ASCIIToUTF16;
namespace views {
-class StyledLabelTest : public testing::Test, public StyledLabelListener {
+class StyledLabelTest : public ViewsTestBase, public StyledLabelListener {
public:
StyledLabelTest() {}
virtual ~StyledLabelTest() {}
@@ -30,6 +35,7 @@ class StyledLabelTest : public testing::Test, public StyledLabelListener {
void InitStyledLabel(const std::string& ascii_text) {
styled_.reset(new StyledLabel(ASCIIToUTF16(ascii_text), this));
+ styled_->set_owned_by_client();
}
int StyledLabelContentHeightForWidth(int w) {
@@ -105,7 +111,7 @@ TEST_F(StyledLabelTest, BasicWrapping) {
StyledLabelContentHeightForWidth(label_preferred_size.width()));
// Also respect the border.
- styled()->set_border(Border::CreateEmptyBorder(3, 3, 3, 3));
+ styled()->SetBorder(Border::CreateEmptyBorder(3, 3, 3, 3));
styled()->SetBounds(
0,
0,
@@ -113,15 +119,19 @@ TEST_F(StyledLabelTest, BasicWrapping) {
styled()->GetInsets().height() + 2 * label_preferred_size.height());
styled()->Layout();
ASSERT_EQ(2, styled()->child_count());
- EXPECT_EQ(3, styled()->child_at(0)->bounds().x());
- EXPECT_EQ(3, styled()->child_at(0)->bounds().y());
- EXPECT_EQ(styled()->bounds().height() - 3,
- styled()->child_at(1)->bounds().bottom());
+ EXPECT_EQ(3, styled()->child_at(0)->x());
+ EXPECT_EQ(3, styled()->child_at(0)->y());
+ EXPECT_EQ(styled()->height() - 3, styled()->child_at(1)->bounds().bottom());
}
TEST_F(StyledLabelTest, CreateLinks) {
const std::string text("This is a test block of text.");
InitStyledLabel(text);
+
+ // Without links, there should be no focus border.
+ EXPECT_TRUE(styled()->GetInsets().empty());
+
+ // Now let's add some links.
styled()->AddStyleRange(gfx::Range(0, 1),
StyledLabel::RangeStyleInfo::CreateForLink());
styled()->AddStyleRange(gfx::Range(1, 2),
@@ -131,9 +141,13 @@ TEST_F(StyledLabelTest, CreateLinks) {
styled()->AddStyleRange(gfx::Range(12, 13),
StyledLabel::RangeStyleInfo::CreateForLink());
+ // Now there should be a focus border because there are non-empty Links.
+ EXPECT_FALSE(styled()->GetInsets().empty());
+
+ // Verify layout creates the right number of children.
styled()->SetBounds(0, 0, 1000, 1000);
styled()->Layout();
- ASSERT_EQ(7, styled()->child_count());
+ EXPECT_EQ(7, styled()->child_count());
}
TEST_F(StyledLabelTest, DontBreakLinks) {
@@ -153,13 +167,15 @@ TEST_F(StyledLabelTest, DontBreakLinks) {
styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
styled()->Layout();
ASSERT_EQ(2, styled()->child_count());
- EXPECT_EQ(0, styled()->child_at(0)->bounds().x());
- EXPECT_EQ(0, styled()->child_at(1)->bounds().x());
+ // The label has no focus border while the link (and thus overall styled
+ // label) does, so the label should be inset by the width of the focus border.
+ EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
+ EXPECT_EQ(0, styled()->child_at(1)->x());
}
TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) {
const std::string text("This is a test block of text, ");
- const std::string unbreakable_text("and this should not be breaked");
+ const std::string unbreakable_text("and this should not be broken");
InitStyledLabel(text + unbreakable_text);
StyledLabel::RangeStyleInfo style_info;
style_info.disable_line_wrapping = true;
@@ -177,8 +193,8 @@ TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) {
styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
styled()->Layout();
ASSERT_EQ(2, styled()->child_count());
- EXPECT_EQ(0, styled()->child_at(0)->bounds().x());
- EXPECT_EQ(0, styled()->child_at(1)->bounds().x());
+ EXPECT_EQ(0, styled()->child_at(0)->x());
+ EXPECT_EQ(0, styled()->child_at(1)->x());
}
TEST_F(StyledLabelTest, StyledRangeUnderlined) {
@@ -197,8 +213,9 @@ TEST_F(StyledLabelTest, StyledRangeUnderlined) {
ASSERT_EQ(2, styled()->child_count());
ASSERT_EQ(std::string(Label::kViewClassName),
styled()->child_at(1)->GetClassName());
- EXPECT_EQ(gfx::Font::UNDERLINE,
- static_cast<Label*>(styled()->child_at(1))->font().GetStyle());
+ EXPECT_EQ(
+ gfx::Font::UNDERLINE,
+ static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
}
TEST_F(StyledLabelTest, StyledRangeBold) {
@@ -215,7 +232,7 @@ TEST_F(StyledLabelTest, StyledRangeBold) {
// and normal style.
Label label(ASCIIToUTF16(bold_text));
const gfx::Size normal_label_size = label.GetPreferredSize();
- label.SetFont(label.font().DeriveFont(0, gfx::Font::BOLD));
+ label.SetFontList(label.font_list().DeriveWithStyle(gfx::Font::BOLD));
const gfx::Size bold_label_size = label.GetPreferredSize();
ASSERT_GE(bold_label_size.width(), normal_label_size.width());
@@ -230,7 +247,7 @@ TEST_F(StyledLabelTest, StyledRangeBold) {
StyledLabel unstyled(ASCIIToUTF16(bold_text), this);
unstyled.SetBounds(0, 0, styled_width, pref_height);
unstyled.Layout();
- ASSERT_EQ(1, unstyled.child_count());
+ EXPECT_EQ(1, unstyled.child_count());
styled()->SetBounds(0, 0, styled_width, pref_height);
styled()->Layout();
@@ -240,22 +257,25 @@ TEST_F(StyledLabelTest, StyledRangeBold) {
// The bold text should be broken up into two parts.
ASSERT_EQ(std::string(Label::kViewClassName),
styled()->child_at(0)->GetClassName());
- EXPECT_EQ(gfx::Font::BOLD,
- static_cast<Label*>(styled()->child_at(0))->font().GetStyle());
+ EXPECT_EQ(
+ gfx::Font::BOLD,
+ static_cast<Label*>(styled()->child_at(0))->font_list().GetFontStyle());
ASSERT_EQ(std::string(Label::kViewClassName),
styled()->child_at(1)->GetClassName());
- EXPECT_EQ(gfx::Font::BOLD,
- static_cast<Label*>(styled()->child_at(1))->font().GetStyle());
+ EXPECT_EQ(
+ gfx::Font::BOLD,
+ static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
ASSERT_EQ(std::string(Label::kViewClassName),
styled()->child_at(2)->GetClassName());
- EXPECT_EQ(gfx::Font::NORMAL,
- static_cast<Label*>(styled()->child_at(2))->font().GetStyle());
+ EXPECT_EQ(
+ gfx::Font::NORMAL,
+ static_cast<Label*>(styled()->child_at(2))->font_list().GetFontStyle());
// The second bold part should start on a new line.
- EXPECT_EQ(0, styled()->child_at(0)->bounds().x());
- EXPECT_EQ(0, styled()->child_at(1)->bounds().x());
- EXPECT_EQ(styled()->child_at(1)->bounds().right() - 2,
- styled()->child_at(2)->bounds().x());
+ EXPECT_EQ(0, styled()->child_at(0)->x());
+ EXPECT_EQ(0, styled()->child_at(1)->x());
+ EXPECT_EQ(styled()->child_at(1)->bounds().right(),
+ styled()->child_at(2)->x());
}
TEST_F(StyledLabelTest, Color) {
@@ -274,16 +294,25 @@ TEST_F(StyledLabelTest, Color) {
text_red.size() + text_link.size()),
style_info_link);
+ styled()->SetBounds(0, 0, 1000, 1000);
+ styled()->Layout();
+
+ Widget* widget = new Widget();
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ widget->Init(params);
+ View* container = new View();
+ widget->SetContentsView(container);
+ container->AddChildView(styled());
+
// Obtain the default text color for a label.
- Label label(ASCIIToUTF16(text));
- const SkColor kDefaultTextColor = label.enabled_color();
+ Label* label = new Label(ASCIIToUTF16(text));
+ container->AddChildView(label);
+ const SkColor kDefaultTextColor = label->enabled_color();
// Obtain the default text color for a link;
- Link link(ASCIIToUTF16(text_link));
- const SkColor kDefaultLinkColor = link.enabled_color();
-
- styled()->SetBounds(0, 0, 1000, 1000);
- styled()->Layout();
+ Link* link = new Link(ASCIIToUTF16(text_link));
+ container->AddChildView(link);
+ const SkColor kDefaultLinkColor = link->enabled_color();
EXPECT_EQ(SK_ColorRED,
static_cast<Label*>(styled()->child_at(0))->enabled_color());
@@ -291,23 +320,18 @@ TEST_F(StyledLabelTest, Color) {
static_cast<Label*>(styled()->child_at(1))->enabled_color());
EXPECT_EQ(kDefaultTextColor,
static_cast<Label*>(styled()->child_at(2))->enabled_color());
-}
-TEST_F(StyledLabelTest, ColorReadability) {
- const std::string text(
- "This is a block of text that needs color adjustment.");
- InitStyledLabel(text);
+ // Test adjusted color readability.
styled()->SetDisplayedOnBackgroundColor(SK_ColorBLACK);
-
- // Obtain the text color if it were a pure label.
- Label label(ASCIIToUTF16(text));
- label.SetBackgroundColor(SK_ColorBLACK);
-
- styled()->SetBounds(0, 0, 1000, 1000);
styled()->Layout();
+ label->SetBackgroundColor(SK_ColorBLACK);
- EXPECT_EQ(label.enabled_color(),
- static_cast<Label*>(styled()->child_at(0))->enabled_color());
+ const SkColor kAdjustedTextColor = label->enabled_color();
+ EXPECT_NE(kAdjustedTextColor, kDefaultTextColor);
+ EXPECT_EQ(kAdjustedTextColor,
+ static_cast<Label*>(styled()->child_at(2))->enabled_color());
+
+ widget->CloseNow();
}
TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
@@ -343,15 +367,18 @@ TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
EXPECT_EQ(label_preferred_size.width(), styled()->width());
ASSERT_EQ(5, styled()->child_count());
- EXPECT_EQ(0, styled()->child_at(0)->bounds().x());
- EXPECT_EQ(styled()->child_at(0)->bounds().right() - 2,
- styled()->child_at(1)->bounds().x());
- EXPECT_EQ(0, styled()->child_at(2)->bounds().x());
- EXPECT_EQ(styled()->child_at(2)->bounds().right() - 2,
- styled()->child_at(3)->bounds().x());
- EXPECT_EQ(0, styled()->child_at(4)->bounds().x());
-
- string16 tooltip;
+ // The labels have no focus border while the link (and thus overall styled
+ // label) does, so the labels should be inset by the width of the focus
+ // border.
+ EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
+ EXPECT_EQ(styled()->child_at(0)->bounds().right(),
+ styled()->child_at(1)->x());
+ EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(2)->x());
+ EXPECT_EQ(styled()->child_at(2)->bounds().right(),
+ styled()->child_at(3)->x());
+ EXPECT_EQ(0, styled()->child_at(4)->x());
+
+ base::string16 tooltip;
EXPECT_TRUE(
styled()->child_at(1)->GetTooltipText(gfx::Point(1, 1), &tooltip));
EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
@@ -360,11 +387,29 @@ TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
}
+TEST_F(StyledLabelTest, SetBaseFontList) {
+ const std::string text("This is a test block of text.");
+ InitStyledLabel(text);
+ std::string font_name("arial");
+ gfx::Font font(font_name, 30);
+ styled()->SetBaseFontList(gfx::FontList(font));
+ Label label(ASCIIToUTF16(text), gfx::FontList(font));
+
+ styled()->SetBounds(0,
+ 0,
+ label.GetPreferredSize().width(),
+ label.GetPreferredSize().height());
+
+ // Make sure we have the same sizing as a label.
+ EXPECT_EQ(label.GetPreferredSize().height(), styled()->height());
+ EXPECT_EQ(label.GetPreferredSize().width(), styled()->width());
+}
+
TEST_F(StyledLabelTest, HandleEmptyLayout) {
- const std::string text("This is a test block of text, ");
+ const std::string text("This is a test block of text.");
InitStyledLabel(text);
styled()->Layout();
- ASSERT_EQ(0, styled()->child_count());
+ EXPECT_EQ(0, styled()->child_count());
}
-} // namespace
+} // namespace views
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 3f2d5da96f5..3d181e0c8ce 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -5,10 +5,11 @@
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
#include "base/logging.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
#include "ui/views/layout/layout_manager.h"
@@ -33,7 +34,7 @@ const char TabbedPane::kViewClassName[] = "TabbedPane";
// The tab view shown in the tab strip.
class Tab : public View {
public:
- Tab(TabbedPane* tabbed_pane, const string16& title, View* contents);
+ Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents);
virtual ~Tab();
View* contents() const { return contents_; }
@@ -46,7 +47,7 @@ class Tab : public View {
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
private:
@@ -75,7 +76,7 @@ class TabStrip : public View {
virtual ~TabStrip();
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
@@ -85,12 +86,14 @@ class TabStrip : public View {
DISALLOW_COPY_AND_ASSIGN(TabStrip);
};
-Tab::Tab(TabbedPane* tabbed_pane, const string16& title, View* contents)
+Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
: tabbed_pane_(tabbed_pane),
- title_(new Label(title, gfx::Font().DeriveFont(0, gfx::Font::BOLD))),
+ title_(new Label(title,
+ ui::ResourceBundle::GetSharedInstance().GetFontList(
+ ui::ResourceBundle::BoldFont))),
tab_state_(TAB_ACTIVE),
contents_(contents) {
- // Calculate this now while the font is guaranteed to be bold.
+ // Calculate this now while the font list is guaranteed to be bold.
preferred_title_size_ = title_->GetPreferredSize();
SetState(TAB_INACTIVE);
@@ -136,7 +139,7 @@ void Tab::OnGestureEvent(ui::GestureEvent* event) {
event->SetHandled();
}
-gfx::Size Tab::GetPreferredSize() {
+gfx::Size Tab::GetPreferredSize() const {
gfx::Size size(preferred_title_size_);
size.Enlarge(21, 9);
const int kTabMinWidth = 54;
@@ -157,18 +160,19 @@ void Tab::SetState(TabState tab_state) {
return;
tab_state_ = tab_state;
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
switch (tab_state) {
case TAB_INACTIVE:
title_->SetEnabledColor(kTabTitleColor_Inactive);
- title_->SetFont(gfx::Font());
+ title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BaseFont));
break;
case TAB_ACTIVE:
title_->SetEnabledColor(kTabTitleColor_Active);
- title_->SetFont(gfx::Font().DeriveFont(0, gfx::Font::BOLD));
+ title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
break;
case TAB_HOVERED:
title_->SetEnabledColor(kTabTitleColor_Hovered);
- title_->SetFont(gfx::Font());
+ title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BaseFont));
break;
}
SchedulePaint();
@@ -178,7 +182,7 @@ TabStrip::TabStrip(TabbedPane* tabbed_pane) : tabbed_pane_(tabbed_pane) {}
TabStrip::~TabStrip() {}
-gfx::Size TabStrip::GetPreferredSize() {
+gfx::Size TabStrip::GetPreferredSize() const {
gfx::Size size;
for (int i = 0; i < child_count(); ++i) {
const gfx::Size child_size = child_at(i)->GetPreferredSize();
@@ -255,12 +259,12 @@ View* TabbedPane::GetSelectedTab() {
NULL : GetTabAt(selected_tab_index())->contents();
}
-void TabbedPane::AddTab(const string16& title, View* contents) {
+void TabbedPane::AddTab(const base::string16& title, View* contents) {
AddTabAtIndex(tab_strip_->child_count(), title, contents);
}
void TabbedPane::AddTabAtIndex(int index,
- const string16& title,
+ const base::string16& title,
View* contents) {
DCHECK(index >= 0 && index <= GetTabCount());
contents->SetVisible(false);
@@ -304,7 +308,7 @@ void TabbedPane::SelectTab(Tab* tab) {
SelectTabAt(index);
}
-gfx::Size TabbedPane::GetPreferredSize() {
+gfx::Size TabbedPane::GetPreferredSize() const {
gfx::Size size;
for (int i = 0; i < contents_->child_count(); ++i)
size.SetToMax(contents_->child_at(i)->GetPreferredSize());
@@ -360,12 +364,12 @@ void TabbedPane::OnFocus() {
View* selected_tab = GetSelectedTab();
if (selected_tab) {
selected_tab->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_FOCUS, true);
+ ui::AX_EVENT_FOCUS, true);
}
}
-void TabbedPane::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST;
+void TabbedPane::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_TAB_LIST;
}
} // 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 a837464a120..83c7fefb058 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -40,12 +40,12 @@ 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 string16& title, View* contents);
+ void AddTab(const base::string16& title, View* 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(int index, const string16& title, View* contents);
+ void AddTabAtIndex(int index, const base::string16& title, View* contents);
// Selects the tab at |index|, which must be valid.
void SelectTabAt(int index);
@@ -54,7 +54,7 @@ class VIEWS_EXPORT TabbedPane : public View {
void SelectTab(Tab* tab);
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
private:
@@ -69,7 +69,7 @@ class VIEWS_EXPORT TabbedPane : public View {
const ViewHierarchyChangedDetails& details) OVERRIDE;
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
virtual void OnFocus() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
// A listener notified when tab selection changes. Weak, not owned.
TabbedPaneListener* listener_;
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_listener.h b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_listener.h
index d2607889ef1..83376f79df0 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_listener.h
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_listener.h
@@ -5,11 +5,13 @@
#ifndef UI_VIEWS_CONTROLS_TABBED_PANE_TABBED_PANE_LISTENER_H_
#define UI_VIEWS_CONTROLS_TABBED_PANE_TABBED_PANE_LISTENER_H_
+#include "ui/views/views_export.h"
+
namespace views {
// An interface implemented by an object to let it know that a tabbed pane was
// selected by the user at the specified index.
-class TabbedPaneListener {
+class VIEWS_EXPORT TabbedPaneListener {
public:
// Called when the tab at |index| is selected by the user.
virtual void TabSelectedAt(int index) = 0;
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 f887a8d2ff4..f81c2a870cb 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
@@ -9,6 +9,8 @@
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
#include "ui/views/test/views_test_base.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace {
@@ -20,7 +22,7 @@ class FixedSizeView : public View {
: size_(size) {}
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return size_;
}
diff --git a/chromium/ui/views/controls/table/table_grouper.h b/chromium/ui/views/controls/table/table_grouper.h
index d6659ac1956..ce100e4c98a 100644
--- a/chromium/ui/views/controls/table/table_grouper.h
+++ b/chromium/ui/views/controls/table/table_grouper.h
@@ -5,9 +5,11 @@
#ifndef UI_VIEWS_CONTROLS_TABLE_TABLE_GROUPER_H_
#define UI_VIEWS_CONTROLS_TABLE_TABLE_GROUPER_H_
+#include "ui/views/views_export.h"
+
namespace views {
-struct GroupRange {
+struct VIEWS_EXPORT GroupRange {
int start;
int length;
};
@@ -15,7 +17,7 @@ struct GroupRange {
// TableGrouper is used by TableView to group a set of rows and treat them
// as one. Rows that fall in the same group are selected together and sorted
// together.
-class TableGrouper {
+class VIEWS_EXPORT TableGrouper {
public:
virtual void GetGroupRange(int model_index, GroupRange* range) = 0;
diff --git a/chromium/ui/views/controls/table/table_header.cc b/chromium/ui/views/controls/table/table_header.cc
index 16d28e3e010..a9d730f958e 100644
--- a/chromium/ui/views/controls/table/table_header.cc
+++ b/chromium/ui/views/controls/table/table_header.cc
@@ -5,15 +5,14 @@
#include "ui/views/controls/table/table_header.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/text_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/controls/table/table_utils.h"
#include "ui/views/controls/table/table_view.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+#include "ui/views/native_cursor.h"
namespace views {
@@ -38,15 +37,6 @@ const SkColor kSeparatorColor = SkColorSetRGB(0xAA, 0xAA, 0xAA);
// Size of the sort indicator (doesn't include padding).
const int kSortIndicatorSize = 8;
-gfx::NativeCursor GetResizeCursor() {
-#if defined(USE_AURA)
- return ui::kCursorColumnResize;
-#elif defined(OS_WIN)
- static HCURSOR g_hand_cursor = LoadCursor(NULL, IDC_SIZEWE);
- return g_hand_cursor;
-#endif
-}
-
} // namespace
// static
@@ -95,7 +85,8 @@ void TableHeader::OnPaint(gfx::Canvas* canvas) {
if (width <= 0)
continue;
- const int title_width = font_.GetStringWidth(columns[i].column.title);
+ const int title_width =
+ gfx::GetStringWidth(columns[i].column.title, font_list_);
const bool paint_sort_indicator =
(columns[i].column.id == sorted_column_id &&
title_width + kSortIndicatorWidth <= width);
@@ -105,10 +96,10 @@ void TableHeader::OnPaint(gfx::Canvas* canvas) {
width -= kSortIndicatorWidth;
}
- canvas->DrawStringInt(
- columns[i].column.title, font_, kTextColor,
- GetMirroredXWithWidthInView(x, width), kVerticalPadding, width,
- height() - kVerticalPadding * 2,
+ canvas->DrawStringRectWithFlags(
+ columns[i].column.title, font_list_, kTextColor,
+ gfx::Rect(GetMirroredXWithWidthInView(x, width), kVerticalPadding,
+ width, height() - kVerticalPadding * 2),
TableColumnAlignmentToCanvasAlignment(columns[i].column.alignment));
if (paint_sort_indicator) {
@@ -168,13 +159,13 @@ void TableHeader::OnPaint(gfx::Canvas* canvas) {
}
}
-gfx::Size TableHeader::GetPreferredSize() {
- return gfx::Size(1, kVerticalPadding * 2 + font_.GetHeight());
+gfx::Size TableHeader::GetPreferredSize() const {
+ return gfx::Size(1, kVerticalPadding * 2 + font_list_.GetHeight());
}
gfx::NativeCursor TableHeader::GetCursor(const ui::MouseEvent& event) {
return GetResizeColumn(GetMirroredXInView(event.x())) != -1 ?
- GetResizeCursor() : View::GetCursor(event);
+ GetNativeColumnResizeCursor() : View::GetCursor(event);
}
bool TableHeader::OnMousePressed(const ui::MouseEvent& event) {
diff --git a/chromium/ui/views/controls/table/table_header.h b/chromium/ui/views/controls/table/table_header.h
index 2aa280d2d92..a595de949c6 100644
--- a/chromium/ui/views/controls/table/table_header.h
+++ b/chromium/ui/views/controls/table/table_header.h
@@ -5,7 +5,7 @@
#ifndef UI_VIEWS_CONTROLS_TABLE_TABLE_HEADER_H_
#define UI_VIEWS_CONTROLS_TABLE_TABLE_HEADER_H_
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
@@ -25,12 +25,12 @@ class VIEWS_EXPORT TableHeader : public views::View {
explicit TableHeader(TableView* table);
virtual ~TableHeader();
- const gfx::Font& font() const { return font_; }
+ const gfx::FontList& font_list() const { return font_list_; }
// views::View overrides.
virtual void Layout() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
@@ -70,7 +70,7 @@ class VIEWS_EXPORT TableHeader : public views::View {
bool is_resizing() const { return resize_details_.get() != NULL; }
- const gfx::Font font_;
+ const gfx::FontList font_list_;
TableView* table_;
diff --git a/chromium/ui/views/controls/table/table_utils.cc b/chromium/ui/views/controls/table/table_utils.cc
index 1e730d0a938..393c22dbc6f 100644
--- a/chromium/ui/views/controls/table/table_utils.cc
+++ b/chromium/ui/views/controls/table/table_utils.cc
@@ -6,26 +6,28 @@
#include "base/logging.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/text_utils.h"
#include "ui/views/controls/table/table_view.h"
namespace views {
const int kUnspecifiedColumnWidth = 90;
-int WidthForContent(const gfx::Font& header_font,
- const gfx::Font& content_font,
+int WidthForContent(const gfx::FontList& header_font_list,
+ const gfx::FontList& content_font_list,
int padding,
int header_padding,
const ui::TableColumn& column,
ui::TableModel* model) {
int width = header_padding;
if (!column.title.empty())
- width = header_font.GetStringWidth(column.title) + header_padding;
+ width = gfx::GetStringWidth(column.title, header_font_list) +
+ header_padding;
for (int i = 0, row_count = model->RowCount(); i < row_count; ++i) {
const int cell_width =
- content_font.GetStringWidth(model->GetText(i, column.id));
+ gfx::GetStringWidth(model->GetText(i, column.id), content_font_list);
width = std::max(width, cell_width);
}
return width + padding;
@@ -34,8 +36,8 @@ int WidthForContent(const gfx::Font& header_font,
std::vector<int> CalculateTableColumnSizes(
int width,
int first_column_padding,
- const gfx::Font& header_font,
- const gfx::Font& content_font,
+ const gfx::FontList& header_font_list,
+ const gfx::FontList& content_font_list,
int padding,
int header_padding,
const std::vector<ui::TableColumn>& columns,
@@ -49,11 +51,12 @@ std::vector<int> CalculateTableColumnSizes(
if (column.percent > 0) {
total_percent += column.percent;
// Make sure there is at least enough room for the header.
- content_widths[i] = header_font.GetStringWidth(column.title) + padding +
- header_padding;
+ content_widths[i] = gfx::GetStringWidth(column.title, header_font_list)
+ + padding + header_padding;
} else {
- content_widths[i] = WidthForContent(header_font, content_font, padding,
- header_padding, column, model);
+ content_widths[i] = WidthForContent(header_font_list, content_font_list,
+ padding, header_padding, column,
+ model);
if (i == 0)
content_widths[i] += first_column_padding;
}
diff --git a/chromium/ui/views/controls/table/table_utils.h b/chromium/ui/views/controls/table/table_utils.h
index 3c5d4c78175..ec387102e69 100644
--- a/chromium/ui/views/controls/table/table_utils.h
+++ b/chromium/ui/views/controls/table/table_utils.h
@@ -11,7 +11,7 @@
#include "ui/views/views_export.h"
namespace gfx {
-class Font;
+class FontList;
}
namespace views {
@@ -23,23 +23,23 @@ VIEWS_EXPORT extern const int kUnspecifiedColumnWidth;
// Returns the width needed to display the contents of the specified column.
// This is used internally by CalculateTableColumnSizes() and generally not
// useful by itself. |header_padding| is padding added to the header.
-VIEWS_EXPORT int WidthForContent(const gfx::Font& header_font,
- const gfx::Font& content_font,
+VIEWS_EXPORT int WidthForContent(const gfx::FontList& header_font_list,
+ const gfx::FontList& content_font_list,
int padding,
int header_padding,
const ui::TableColumn& column,
ui::TableModel* model);
// Determines the width for each of the specified columns. |width| is the width
-// to fit the columns into. |header_font| the font used to draw the header and
-// |content_font| the header used to draw the content. |padding| is extra
-// horizontal spaced added to each cell, and |header_padding| added to the
-// width needed for the header.
+// to fit the columns into. |header_font_list| the font list used to draw the
+// header and |content_font_list| the header used to draw the content. |padding|
+// is extra horizontal spaced added to each cell, and |header_padding| added to
+// the width needed for the header.
VIEWS_EXPORT std::vector<int> CalculateTableColumnSizes(
int width,
int first_column_padding,
- const gfx::Font& header_font,
- const gfx::Font& content_font,
+ const gfx::FontList& header_font_list,
+ const gfx::FontList& content_font_list,
int padding,
int header_padding,
const std::vector<ui::TableColumn>& columns,
diff --git a/chromium/ui/views/controls/table/table_utils_unittest.cc b/chromium/ui/views/controls/table/table_utils_unittest.cc
index e6c6369d0b8..98b1fd2f786 100644
--- a/chromium/ui/views/controls/table/table_utils_unittest.cc
+++ b/chromium/ui/views/controls/table/table_utils_unittest.cc
@@ -6,7 +6,7 @@
#include "base/strings/string_number_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/controls/table/test_table_model.h"
using ui::TableColumn;
@@ -40,17 +40,19 @@ TEST(TableUtilsTest, SetWidthHonored) {
std::vector<TableColumn> columns;
columns.push_back(CreateTableColumnWithWidth(20));
columns.push_back(CreateTableColumnWithWidth(30));
- gfx::Font font;
- std::vector<int> result(
- CalculateTableColumnSizes(100, 0, font, font, 0, 0, columns, &model));
+ gfx::FontList font_list;
+ std::vector<int> result(CalculateTableColumnSizes(
+ 100, 0, font_list, font_list, 0, 0, columns, &model));
EXPECT_EQ("20,30", IntVectorToString(result));
// Same with some padding, it should be ignored.
- result = CalculateTableColumnSizes(100, 0, font, font, 2, 0, columns, &model);
+ result = CalculateTableColumnSizes(
+ 100, 0, font_list, font_list, 2, 0, columns, &model);
EXPECT_EQ("20,30", IntVectorToString(result));
// Same with not enough space, it shouldn't matter.
- result = CalculateTableColumnSizes(10, 0, font, font, 2, 0, columns, &model);
+ result = CalculateTableColumnSizes(
+ 10, 0, font_list, font_list, 2, 0, columns, &model);
EXPECT_EQ("20,30", IntVectorToString(result));
}
@@ -61,11 +63,12 @@ TEST(TableUtilsTest, LastColumnGetsAllSpace) {
std::vector<TableColumn> columns;
columns.push_back(ui::TableColumn());
columns.push_back(ui::TableColumn());
- gfx::Font font;
- std::vector<int> result(
- CalculateTableColumnSizes(500, 0, font, font, 0, 0, columns, &model));
+ gfx::FontList font_list;
+ std::vector<int> result(CalculateTableColumnSizes(
+ 500, 0, font_list, font_list, 0, 0, columns, &model));
EXPECT_NE(0, result[0]);
- EXPECT_GE(result[1], WidthForContent(font, font, 0, 0, columns[1], &model));
+ EXPECT_GE(result[1],
+ WidthForContent(font_list, font_list, 0, 0, columns[1], &model));
EXPECT_EQ(500, result[0] + result[1]);
}
@@ -77,38 +80,45 @@ TEST(TableUtilsTest, SingleResizableColumn) {
columns.push_back(ui::TableColumn());
columns.push_back(ui::TableColumn());
columns[2].percent = 1.0f;
- gfx::Font font;
- std::vector<int> result(
- CalculateTableColumnSizes(500, 0, font, font, 0, 0, columns, &model));
- EXPECT_EQ(result[0], WidthForContent(font, font, 0, 0, columns[0], &model));
- EXPECT_EQ(result[1], WidthForContent(font, font, 0, 0, columns[1], &model));
+ gfx::FontList font_list;
+ std::vector<int> result(CalculateTableColumnSizes(
+ 500, 0, font_list, font_list, 0, 0, columns, &model));
+ EXPECT_EQ(result[0],
+ WidthForContent(font_list, font_list, 0, 0, columns[0], &model));
+ EXPECT_EQ(result[1],
+ WidthForContent(font_list, font_list, 0, 0, columns[1], &model));
EXPECT_EQ(500 - result[0] - result[1], result[2]);
// The same with a slightly larger width passed in.
- result =
- CalculateTableColumnSizes(1000, 0, font, font, 0, 0, columns, &model);
- EXPECT_EQ(result[0], WidthForContent(font, font, 0, 0, columns[0], &model));
- EXPECT_EQ(result[1], WidthForContent(font, font, 0, 0, columns[1], &model));
+ result = CalculateTableColumnSizes(
+ 1000, 0, font_list, font_list, 0, 0, columns, &model);
+ EXPECT_EQ(result[0],
+ WidthForContent(font_list, font_list, 0, 0, columns[0], &model));
+ EXPECT_EQ(result[1],
+ WidthForContent(font_list, font_list, 0, 0, columns[1], &model));
EXPECT_EQ(1000 - result[0] - result[1], result[2]);
// Verify padding for the first column is honored.
- result =
- CalculateTableColumnSizes(1000, 10, font, font, 0, 0, columns, &model);
+ result = CalculateTableColumnSizes(
+ 1000, 10, font_list, font_list, 0, 0, columns, &model);
EXPECT_EQ(result[0],
- WidthForContent(font, font, 0, 0, columns[0], &model) + 10);
- EXPECT_EQ(result[1], WidthForContent(font, font, 0, 0, columns[1], &model));
+ WidthForContent(font_list, font_list, 0, 0, columns[0], &model)
+ + 10);
+ EXPECT_EQ(result[1],
+ WidthForContent(font_list, font_list, 0, 0, columns[1], &model));
EXPECT_EQ(1000 - result[0] - result[1], result[2]);
// Just enough space to show the first two columns. Should force last column
// to min size.
- result =
- CalculateTableColumnSizes(1000, 0, font, font, 0, 0, columns, &model);
- result = CalculateTableColumnSizes(result[0] + result[1], 0, font, font, 0, 0,
- columns, &model);
- EXPECT_EQ(result[0], WidthForContent(font, font, 0, 0, columns[0], &model));
- EXPECT_EQ(result[1], WidthForContent(font, font, 0, 0, columns[1], &model));
+ result = CalculateTableColumnSizes(
+ 1000, 0, font_list, font_list, 0, 0, columns, &model);
+ result = CalculateTableColumnSizes(
+ result[0] + result[1], 0, font_list, font_list, 0, 0, columns, &model);
+ EXPECT_EQ(result[0],
+ WidthForContent(font_list, font_list, 0, 0, columns[0], &model));
+ EXPECT_EQ(result[1],
+ WidthForContent(font_list, font_list, 0, 0, columns[1], &model));
EXPECT_EQ(kUnspecifiedColumnWidth, result[2]);
}
} // namespace views
-
diff --git a/chromium/ui/views/controls/table/table_view.cc b/chromium/ui/views/controls/table/table_view.cc
index 8a27a1f7a91..e5120d49295 100644
--- a/chromium/ui/views/controls/table/table_view.cc
+++ b/chromium/ui/views/controls/table/table_view.cc
@@ -13,6 +13,7 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/skia_util.h"
+#include "ui/gfx/text_utils.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/table/table_grouper.h"
@@ -124,7 +125,7 @@ TableView::TableView(ui::TableModel* model,
table_type_(table_type),
single_selection_(single_selection),
table_view_observer_(NULL),
- row_height_(font_.GetHeight() + kTextVerticalPadding * 2),
+ row_height_(font_list_.GetHeight() + kTextVerticalPadding * 2),
last_parent_width_(0),
layout_width_(0),
grouper_(NULL),
@@ -317,7 +318,7 @@ void TableView::Layout() {
SetBounds(x(), y(), width, height);
}
-gfx::Size TableView::GetPreferredSize() {
+gfx::Size TableView::GetPreferredSize() const {
int width = 50;
if (header_ && !visible_columns_.empty())
width = visible_columns_.back().x + visible_columns_.back().width;
@@ -404,7 +405,7 @@ void TableView::OnGestureEvent(ui::GestureEvent* event) {
}
bool TableView::GetTooltipText(const gfx::Point& p,
- string16* tooltip) const {
+ base::string16* tooltip) const {
return GetTooltipImpl(p, tooltip, NULL);
}
@@ -522,14 +523,14 @@ void TableView::OnPaint(gfx::Canvas* canvas) {
text_x += kImageSize + kTextHorizontalPadding;
}
if (text_x < cell_bounds.right() - kTextHorizontalPadding) {
- canvas->DrawStringInt(
- model_->GetText(model_index, visible_columns_[j].column.id), font_,
- is_selected ? selected_fg_color : fg_color,
- GetMirroredXWithWidthInView(text_x, cell_bounds.right() - text_x -
- kTextHorizontalPadding),
- cell_bounds.y() + kTextVerticalPadding,
- cell_bounds.right() - text_x,
- cell_bounds.height() - kTextVerticalPadding * 2,
+ canvas->DrawStringRectWithFlags(
+ model_->GetText(model_index, visible_columns_[j].column.id),
+ font_list_, is_selected ? selected_fg_color : fg_color,
+ gfx::Rect(GetMirroredXWithWidthInView(
+ text_x, cell_bounds.right() - text_x - kTextHorizontalPadding),
+ cell_bounds.y() + kTextVerticalPadding,
+ cell_bounds.right() - text_x,
+ cell_bounds.height() - kTextVerticalPadding * 2),
TableColumnAlignmentToCanvasAlignment(
visible_columns_[j].column.alignment));
}
@@ -684,7 +685,7 @@ void TableView::UpdateVisibleColumnSizes() {
first_column_padding += kGroupingIndicatorSize + kTextHorizontalPadding;
std::vector<int> sizes = views::CalculateTableColumnSizes(
- layout_width_, first_column_padding, header_->font(), font_,
+ layout_width_, first_column_padding, header_->font_list(), font_list_,
std::max(kTextHorizontalPadding, TableHeader::kHorizontalPadding) * 2,
TableHeader::kSortIndicatorWidth, columns, model_);
DCHECK_EQ(visible_columns_.size(), sizes.size());
@@ -871,7 +872,7 @@ GroupRange TableView::GetGroupRange(int model_index) const {
}
bool TableView::GetTooltipImpl(const gfx::Point& location,
- string16* tooltip,
+ base::string16* tooltip,
gfx::Point* tooltip_origin) const {
const int row = location.y() / row_height_;
if (row < 0 || row >= RowCount() || visible_columns_.empty())
@@ -883,7 +884,7 @@ bool TableView::GetTooltipImpl(const gfx::Point& location,
x > (visible_columns_[column].x + visible_columns_[column].width))
return false;
- const string16 text(model_->GetText(ViewToModel(row),
+ const base::string16 text(model_->GetText(ViewToModel(row),
visible_columns_[column].column.id));
if (text.empty())
return false;
@@ -892,7 +893,7 @@ bool TableView::GetTooltipImpl(const gfx::Point& location,
AdjustCellBoundsForText(column, &cell_bounds);
const int right = std::min(GetVisibleBounds().right(), cell_bounds.right());
if (right > cell_bounds.x() &&
- font_.GetStringWidth(text) <= (right - cell_bounds.x()))
+ gfx::GetStringWidth(text, font_list_) <= (right - cell_bounds.x()))
return false;
if (tooltip)
diff --git a/chromium/ui/views/controls/table/table_view.h b/chromium/ui/views/controls/table/table_view.h
index c2a94724a52..96268067c6b 100644
--- a/chromium/ui/views/controls/table/table_view.h
+++ b/chromium/ui/views/controls/table/table_view.h
@@ -11,7 +11,7 @@
#include "ui/base/models/list_selection_model.h"
#include "ui/base/models/table_model.h"
#include "ui/base/models/table_model_observer.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
@@ -166,12 +166,12 @@ class VIEWS_EXPORT TableView
// View overrides:
virtual void Layout() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
virtual bool GetTooltipTextOrigin(const gfx::Point& p,
gfx::Point* loc) const OVERRIDE;
@@ -291,7 +291,7 @@ class VIEWS_EXPORT TableView
// sets |tooltip| and/or |tooltip_origin| as appropriate, each of which may be
// NULL.
bool GetTooltipImpl(const gfx::Point& location,
- string16* tooltip,
+ base::string16* tooltip,
gfx::Point* tooltip_origin) const;
ui::TableModel* model_;
@@ -316,7 +316,7 @@ class VIEWS_EXPORT TableView
// The selection, in terms of the model.
ui::ListSelectionModel selection_model_;
- gfx::Font font_;
+ gfx::FontList font_list_;
int row_height_;
diff --git a/chromium/ui/views/controls/table/table_view_observer.h b/chromium/ui/views/controls/table/table_view_observer.h
index 44400eee1c7..9cea2603c50 100644
--- a/chromium/ui/views/controls/table/table_view_observer.h
+++ b/chromium/ui/views/controls/table/table_view_observer.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_CONTROLS_TABLE_TABLE_VIEW_OBSERVER_H_
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/views_export.h"
namespace views {
@@ -13,7 +14,7 @@ class TableView;
class TableView2;
// TableViewObserver is notified about the TableView selection.
-class TableViewObserver {
+class VIEWS_EXPORT TableViewObserver {
public:
virtual ~TableViewObserver() {}
diff --git a/chromium/ui/views/controls/table/table_view_unittest.cc b/chromium/ui/views/controls/table/table_view_unittest.cc
index 4d89f3272b3..1d59358d31e 100644
--- a/chromium/ui/views/controls/table/table_view_unittest.cc
+++ b/chromium/ui/views/controls/table/table_view_unittest.cc
@@ -67,7 +67,7 @@ class TestTableModel2 : public ui::TableModel {
// ui::TableModel:
virtual int RowCount() OVERRIDE;
- virtual string16 GetText(int row, int column_id) OVERRIDE;
+ virtual base::string16 GetText(int row, int column_id) OVERRIDE;
virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
virtual int CompareValues(int row1, int row2, int column_id) OVERRIDE;
@@ -115,7 +115,7 @@ int TestTableModel2::RowCount() {
return static_cast<int>(rows_.size());
}
-string16 TestTableModel2::GetText(int row, int column_id) {
+base::string16 TestTableModel2::GetText(int row, int column_id) {
return base::IntToString16(rows_[row][column_id]);
}
@@ -175,9 +175,9 @@ class TableViewTest : public testing::Test {
virtual void SetUp() OVERRIDE {
model_.reset(new TestTableModel2);
std::vector<ui::TableColumn> columns(2);
- columns[0].title = ASCIIToUTF16("Title Column 0");
+ columns[0].title = base::ASCIIToUTF16("Title Column 0");
columns[0].sortable = true;
- columns[1].title = ASCIIToUTF16("Title Column 1");
+ columns[1].title = base::ASCIIToUTF16("Title Column 1");
columns[1].id = 1;
columns[1].sortable = true;
table_ = new TestTableView(model_.get(), columns);
@@ -191,7 +191,8 @@ class TableViewTest : public testing::Test {
const int y = row * table_->row_height();
const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(0, y),
gfx::Point(0, y),
- ui::EF_LEFT_MOUSE_BUTTON | flags);
+ ui::EF_LEFT_MOUSE_BUTTON | flags,
+ ui::EF_LEFT_MOUSE_BUTTON);
table_->OnMousePressed(pressed);
}
@@ -289,10 +290,12 @@ TEST_F(TableViewTest, Resize) {
EXPECT_NE(0, x);
// Drag the mouse 1 pixel to the left.
const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(x, 0),
- gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON);
+ gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
helper_->header()->OnMousePressed(pressed);
const ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, gfx::Point(x - 1, 0),
- gfx::Point(x - 1, 0), ui::EF_LEFT_MOUSE_BUTTON);
+ gfx::Point(x - 1, 0), ui::EF_LEFT_MOUSE_BUTTON,
+ 0);
helper_->header()->OnMouseDragged(dragged);
// This should shrink the first column and pull the second column in.
@@ -378,11 +381,13 @@ TEST_F(TableViewTest, SortOnMouse) {
EXPECT_NE(0, x);
// Press and release the mouse.
const ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(x, 0),
- gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON);
+ gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
// The header must return true, else it won't normally get the release.
EXPECT_TRUE(helper_->header()->OnMousePressed(pressed));
const ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(x, 0),
- gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON);
+ gfx::Point(x, 0), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
helper_->header()->OnMouseReleased(release);
ASSERT_EQ(1u, table_->sort_descriptors().size());
diff --git a/chromium/ui/views/controls/table/test_table_model.cc b/chromium/ui/views/controls/table/test_table_model.cc
index c855aa163ec..6cac56cff3d 100644
--- a/chromium/ui/views/controls/table/test_table_model.cc
+++ b/chromium/ui/views/controls/table/test_table_model.cc
@@ -22,9 +22,9 @@ int TestTableModel::RowCount() {
return row_count_;
}
-string16 TestTableModel::GetText(int row, int column_id) {
- return ASCIIToUTF16(base::IntToString(row) + "x" +
- base::IntToString(column_id));
+base::string16 TestTableModel::GetText(int row, int column_id) {
+ return base::ASCIIToUTF16(base::IntToString(row) + "x" +
+ base::IntToString(column_id));
}
gfx::ImageSkia TestTableModel::GetIcon(int row) {
diff --git a/chromium/ui/views/controls/table/test_table_model.h b/chromium/ui/views/controls/table/test_table_model.h
index d093102fbe9..8338aae78a5 100644
--- a/chromium/ui/views/controls/table/test_table_model.h
+++ b/chromium/ui/views/controls/table/test_table_model.h
@@ -15,7 +15,7 @@ class TestTableModel : public ui::TableModel {
// ui::TableModel overrides:
virtual int RowCount() OVERRIDE;
- virtual string16 GetText(int row, int column_id) OVERRIDE;
+ virtual base::string16 GetText(int row, int column_id) OVERRIDE;
virtual gfx::ImageSkia GetIcon(int row) OVERRIDE;
virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
diff --git a/chromium/ui/views/controls/textfield/native_textfield_views.cc b/chromium/ui/views/controls/textfield/native_textfield_views.cc
deleted file mode 100644
index f8fc36217d2..00000000000
--- a/chromium/ui/views/controls/textfield/native_textfield_views.cc
+++ /dev/null
@@ -1,1545 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/textfield/native_textfield_views.h"
-
-#include <algorithm>
-#include <set>
-
-#include "base/bind.h"
-#include "base/debug/trace_event.h"
-#include "base/i18n/case_conversion.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "grit/ui_strings.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/clipboard/clipboard.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/drag_utils.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/ui_base_switches_util.h"
-#include "ui/compositor/layer.h"
-#include "ui/events/event.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/insets.h"
-#include "ui/gfx/range/range.h"
-#include "ui/gfx/render_text.h"
-#include "ui/gfx/text_constants.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/views/background.h"
-#include "ui/views/border.h"
-#include "ui/views/controls/focusable_border.h"
-#include "ui/views/controls/menu/menu_item_view.h"
-#include "ui/views/controls/menu/menu_model_adapter.h"
-#include "ui/views/controls/menu/menu_runner.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/controls/textfield/textfield_controller.h"
-#include "ui/views/controls/textfield/textfield_views_model.h"
-#include "ui/views/drag_utils.h"
-#include "ui/views/ime/input_method.h"
-#include "ui/views/metrics.h"
-#include "ui/views/widget/widget.h"
-
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
-
-#if defined(OS_WIN) && defined(USE_AURA)
-#include "base/win/win_util.h"
-#endif
-
-namespace {
-
-void ConvertRectToScreen(const views::View* src, gfx::Rect* r) {
- DCHECK(src);
-
- gfx::Point new_origin = r->origin();
- views::View::ConvertPointToScreen(src, &new_origin);
- r->set_origin(new_origin);
-}
-
-} // namespace
-
-namespace views {
-
-const char NativeTextfieldViews::kViewClassName[] =
- "views/NativeTextfieldViews";
-
-NativeTextfieldViews::NativeTextfieldViews(Textfield* parent)
- : textfield_(parent),
- model_(new TextfieldViewsModel(this)),
- text_border_(new FocusableBorder()),
- is_cursor_visible_(false),
- is_drop_cursor_visible_(false),
- skip_input_method_cancel_composition_(false),
- initiating_drag_(false),
- cursor_timer_(this),
- aggregated_clicks_(0) {
- set_border(text_border_);
- GetRenderText()->SetFontList(textfield_->font_list());
- UpdateColorsFromTheme(GetNativeTheme());
- set_context_menu_controller(this);
- parent->set_context_menu_controller(this);
- set_drag_controller(this);
-}
-
-NativeTextfieldViews::~NativeTextfieldViews() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, View overrides:
-
-bool NativeTextfieldViews::OnMousePressed(const ui::MouseEvent& event) {
- OnBeforeUserAction();
- TrackMouseClicks(event);
-
- TextfieldController* controller = textfield_->GetController();
- if (!(controller && controller->HandleMouseEvent(textfield_, event)) &&
- !textfield_->OnMousePressed(event)) {
- HandleMousePressEvent(event);
- }
-
- OnAfterUserAction();
- touch_selection_controller_.reset();
- return true;
-}
-
-bool NativeTextfieldViews::ExceededDragThresholdFromLastClickLocation(
- const ui::MouseEvent& event) {
- return ExceededDragThreshold(event.location() - last_click_location_);
-}
-
-bool NativeTextfieldViews::OnMouseDragged(const ui::MouseEvent& event) {
- // Don't adjust the cursor on a potential drag and drop, or if the mouse
- // movement from the last mouse click does not exceed the drag threshold.
- if (initiating_drag_ || !ExceededDragThresholdFromLastClickLocation(event) ||
- !event.IsOnlyLeftMouseButton()) {
- return true;
- }
-
- OnBeforeUserAction();
- // TODO: Remove once NativeTextfield implementations are consolidated to
- // Textfield.
- if (!textfield_->OnMouseDragged(event)) {
- MoveCursorTo(event.location(), true);
- if (aggregated_clicks_ == 1) {
- model_->SelectWord();
- // Expand the selection so the initially selected word remains selected.
- gfx::Range selection = GetRenderText()->selection();
- const size_t min = std::min(selection.GetMin(),
- double_click_word_.GetMin());
- const size_t max = std::max(selection.GetMax(),
- double_click_word_.GetMax());
- const bool reversed = selection.is_reversed();
- selection.set_start(reversed ? max : min);
- selection.set_end(reversed ? min : max);
- model_->SelectRange(selection);
- }
- SchedulePaint();
- }
- OnAfterUserAction();
- return true;
-}
-
-void NativeTextfieldViews::OnMouseReleased(const ui::MouseEvent& event) {
- OnBeforeUserAction();
- // TODO: Remove once NativeTextfield implementations are consolidated to
- // Textfield.
- textfield_->OnMouseReleased(event);
- // Cancel suspected drag initiations, the user was clicking in the selection.
- if (initiating_drag_ && MoveCursorTo(event.location(), false))
- SchedulePaint();
- initiating_drag_ = false;
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::OnGestureEvent(ui::GestureEvent* event) {
- textfield_->OnGestureEvent(event);
- if (event->handled())
- return;
-
- switch (event->type()) {
- case ui::ET_GESTURE_TAP_DOWN:
- OnBeforeUserAction();
- textfield_->RequestFocus();
- // We don't deselect if the point is in the selection
- // because TAP_DOWN may turn into a LONG_PRESS.
- if (!GetRenderText()->IsPointInSelection(event->location()) &&
- MoveCursorTo(event->location(), false))
- SchedulePaint();
- OnAfterUserAction();
- event->SetHandled();
- break;
- case ui::ET_GESTURE_SCROLL_UPDATE:
- OnBeforeUserAction();
- if (MoveCursorTo(event->location(), true))
- SchedulePaint();
- OnAfterUserAction();
- event->SetHandled();
- break;
- case ui::ET_GESTURE_SCROLL_END:
- case ui::ET_SCROLL_FLING_START:
- CreateTouchSelectionControllerAndNotifyIt();
- event->SetHandled();
- break;
- case ui::ET_GESTURE_TAP:
- if (event->details().tap_count() == 1) {
- CreateTouchSelectionControllerAndNotifyIt();
- } else {
- OnBeforeUserAction();
- SelectAll(false);
- OnAfterUserAction();
- event->SetHandled();
- }
- break;
- case ui::ET_GESTURE_LONG_PRESS:
- // If long press happens outside selection, select word and show context
- // menu (If touch selection is enabled, context menu is shown by the
- // |touch_selection_controller_|, hence we mark the event handled.
- // Otherwise, the regular context menu will be shown by views).
- // If long press happens in selected text and touch drag drop is enabled,
- // we will turn off touch selection (if one exists) and let views do drag
- // drop.
- if (!GetRenderText()->IsPointInSelection(event->location())) {
- OnBeforeUserAction();
- model_->SelectWord();
- touch_selection_controller_.reset(
- ui::TouchSelectionController::create(this));
- OnCaretBoundsChanged();
- SchedulePaint();
- OnAfterUserAction();
- if (touch_selection_controller_.get())
- event->SetHandled();
- } else if (switches::IsTouchDragDropEnabled()) {
- initiating_drag_ = true;
- touch_selection_controller_.reset();
- } else {
- if (!touch_selection_controller_.get())
- CreateTouchSelectionControllerAndNotifyIt();
- if (touch_selection_controller_.get())
- event->SetHandled();
- }
- return;
- case ui::ET_GESTURE_LONG_TAP:
- if (!touch_selection_controller_.get())
- CreateTouchSelectionControllerAndNotifyIt();
-
- // If touch selection is enabled, the context menu on long tap will be
- // shown by the |touch_selection_controller_|, hence we mark the event
- // handled so views does not try to show context menu on it.
- if (touch_selection_controller_.get())
- event->SetHandled();
- break;
- default:
- View::OnGestureEvent(event);
- return;
- }
- PlatformGestureEventHandling(event);
-}
-
-bool NativeTextfieldViews::OnKeyPressed(const ui::KeyEvent& event) {
- // OnKeyPressed/OnKeyReleased/OnFocus/OnBlur will never be invoked on
- // NativeTextfieldViews as it will never gain focus.
- NOTREACHED();
- return false;
-}
-
-bool NativeTextfieldViews::OnKeyReleased(const ui::KeyEvent& event) {
- NOTREACHED();
- return false;
-}
-
-bool NativeTextfieldViews::GetDropFormats(
- int* formats,
- std::set<OSExchangeData::CustomFormat>* custom_formats) {
- if (!textfield_->enabled() || textfield_->read_only())
- return false;
- // TODO(msw): Can we support URL, FILENAME, etc.?
- *formats = ui::OSExchangeData::STRING;
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->AppendDropFormats(formats, custom_formats);
- return true;
-}
-
-bool NativeTextfieldViews::CanDrop(const OSExchangeData& data) {
- int formats;
- std::set<OSExchangeData::CustomFormat> custom_formats;
- GetDropFormats(&formats, &custom_formats);
- return textfield_->enabled() && !textfield_->read_only() &&
- data.HasAnyFormat(formats, custom_formats);
-}
-
-int NativeTextfieldViews::OnDragUpdated(const ui::DropTargetEvent& event) {
- DCHECK(CanDrop(event.data()));
-
- const gfx::Range& selection = GetRenderText()->selection();
- drop_cursor_position_ = GetRenderText()->FindCursorPosition(event.location());
- bool in_selection = !selection.is_empty() &&
- selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
- is_drop_cursor_visible_ = !in_selection;
- // TODO(msw): Pan over text when the user drags to the visible text edge.
- OnCaretBoundsChanged();
- SchedulePaint();
-
- if (initiating_drag_) {
- if (in_selection)
- return ui::DragDropTypes::DRAG_NONE;
- return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
- ui::DragDropTypes::DRAG_MOVE;
- }
- return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
-}
-
-void NativeTextfieldViews::OnDragExited() {
- is_drop_cursor_visible_ = false;
- SchedulePaint();
-}
-
-int NativeTextfieldViews::OnPerformDrop(const ui::DropTargetEvent& event) {
- DCHECK(CanDrop(event.data()));
-
- is_drop_cursor_visible_ = false;
-
- TextfieldController* controller = textfield_->GetController();
- if (controller) {
- int drag_operation = controller->OnDrop(event.data());
- if (drag_operation != ui::DragDropTypes::DRAG_NONE)
- return drag_operation;
- }
-
- DCHECK(!initiating_drag_ ||
- !GetRenderText()->IsPointInSelection(event.location()));
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
-
- gfx::SelectionModel drop_destination_model =
- GetRenderText()->FindCursorPosition(event.location());
- string16 text;
- event.data().GetString(&text);
- text = GetTextForDisplay(text);
-
- // Delete the current selection for a drag and drop within this view.
- const bool move = initiating_drag_ && !event.IsControlDown() &&
- event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
- if (move) {
- // Adjust the drop destination if it is on or after the current selection.
- size_t drop = drop_destination_model.caret_pos();
- drop -= GetSelectedRange().Intersect(gfx::Range(0, drop)).length();
- model_->DeleteSelectionAndInsertTextAt(text, drop);
- } else {
- model_->MoveCursorTo(drop_destination_model);
- // Drop always inserts text even if the textfield is not in insert mode.
- model_->InsertText(text);
- }
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
- return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
-}
-
-void NativeTextfieldViews::OnDragDone() {
- initiating_drag_ = false;
- is_drop_cursor_visible_ = false;
-}
-
-void NativeTextfieldViews::OnPaint(gfx::Canvas* canvas) {
- OnPaintBackground(canvas);
- PaintTextAndCursor(canvas);
- if (textfield_->draw_border())
- OnPaintBorder(canvas);
-}
-
-void NativeTextfieldViews::OnFocus() {
- NOTREACHED();
-}
-
-void NativeTextfieldViews::OnBlur() {
- NOTREACHED();
-}
-
-void NativeTextfieldViews::OnNativeThemeChanged(const ui::NativeTheme* theme) {
- UpdateColorsFromTheme(theme);
-}
-
-void NativeTextfieldViews::SelectRect(const gfx::Point& start,
- const gfx::Point& end) {
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return;
-
- gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
- gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
- gfx::SelectionModel selection(
- gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
- end_caret.caret_affinity());
-
- OnBeforeUserAction();
- model_->SelectSelectionModel(selection);
- OnCaretBoundsChanged();
- SchedulePaint();
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::MoveCaretTo(const gfx::Point& point) {
- SelectRect(point, point);
-}
-
-void NativeTextfieldViews::GetSelectionEndPoints(gfx::Rect* p1,
- gfx::Rect* p2) {
- gfx::RenderText* render_text = GetRenderText();
- const gfx::SelectionModel& sel = render_text->selection_model();
- gfx::SelectionModel start_sel =
- render_text->GetSelectionModelForSelectionStart();
- *p1 = render_text->GetCursorBounds(start_sel, true);
- *p2 = render_text->GetCursorBounds(sel, true);
-}
-
-gfx::Rect NativeTextfieldViews::GetBounds() {
- return bounds();
-}
-
-gfx::NativeView NativeTextfieldViews::GetNativeView() {
- return GetWidget()->GetNativeView();
-}
-
-void NativeTextfieldViews::ConvertPointToScreen(gfx::Point* point) {
- View::ConvertPointToScreen(this, point);
-}
-
-void NativeTextfieldViews::ConvertPointFromScreen(gfx::Point* point) {
- View::ConvertPointFromScreen(this, point);
-}
-
-bool NativeTextfieldViews::DrawsHandles() {
- return false;
-}
-
-void NativeTextfieldViews::OpenContextMenu(const gfx::Point& anchor) {
- touch_selection_controller_.reset();
- ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
-}
-
-gfx::NativeCursor NativeTextfieldViews::GetCursor(const ui::MouseEvent& event) {
- bool in_selection = GetRenderText()->IsPointInSelection(event.location());
- bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
- bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
-#if defined(USE_AURA)
- return text_cursor ? ui::kCursorIBeam : ui::kCursorNull;
-#elif defined(OS_WIN)
- static HCURSOR ibeam = LoadCursor(NULL, IDC_IBEAM);
- static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
- return text_cursor ? ibeam : arrow;
-#endif
-}
-
-/////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, ContextMenuController overrides:
-void NativeTextfieldViews::ShowContextMenuForView(
- View* source,
- const gfx::Point& point,
- ui::MenuSourceType source_type) {
- UpdateContextMenu();
- if (context_menu_runner_->RunMenuAt(GetWidget(), NULL,
- gfx::Rect(point, gfx::Size()), views::MenuItemView::TOPLEFT,
- source_type,
- MenuRunner::HAS_MNEMONICS | views::MenuRunner::CONTEXT_MENU) ==
- MenuRunner::MENU_DELETED)
- return;
-}
-
-/////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, views::DragController overrides:
-void NativeTextfieldViews::WriteDragDataForView(views::View* sender,
- const gfx::Point& press_pt,
- OSExchangeData* data) {
- DCHECK_NE(ui::DragDropTypes::DRAG_NONE,
- GetDragOperationsForView(sender, press_pt));
- data->SetString(GetSelectedText());
- scoped_ptr<gfx::Canvas> canvas(
- views::GetCanvasForDragImage(textfield_->GetWidget(), size()));
- GetRenderText()->DrawSelectedTextForDrag(canvas.get());
- drag_utils::SetDragImageOnDataObject(*canvas, size(),
- press_pt.OffsetFromOrigin(),
- data);
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnWriteDragData(data);
-}
-
-int NativeTextfieldViews::GetDragOperationsForView(views::View* sender,
- const gfx::Point& p) {
- int drag_operations = ui::DragDropTypes::DRAG_COPY;
- if (!textfield_->enabled() || textfield_->IsObscured() ||
- !GetRenderText()->IsPointInSelection(p))
- drag_operations = ui::DragDropTypes::DRAG_NONE;
- else if (sender == this && !textfield_->read_only())
- drag_operations =
- ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnGetDragOperationsForTextfield(&drag_operations);
- return drag_operations;
-}
-
-bool NativeTextfieldViews::CanStartDragForView(View* sender,
- const gfx::Point& press_pt,
- const gfx::Point& p) {
- return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
-}
-
-/////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, NativeTextifieldWrapper overrides:
-
-string16 NativeTextfieldViews::GetText() const {
- return model_->GetText();
-}
-
-void NativeTextfieldViews::UpdateText() {
- model_->SetText(GetTextForDisplay(textfield_->text()));
- OnCaretBoundsChanged();
- SchedulePaint();
- textfield_->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
-}
-
-void NativeTextfieldViews::AppendText(const string16& text) {
- if (text.empty())
- return;
- model_->Append(GetTextForDisplay(text));
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-void NativeTextfieldViews::InsertOrReplaceText(const string16& text) {
- if (text.empty())
- return;
- model_->InsertText(text);
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-base::i18n::TextDirection NativeTextfieldViews::GetTextDirection() const {
- return GetRenderText()->GetTextDirection();
-}
-
-string16 NativeTextfieldViews::GetSelectedText() const {
- return model_->GetSelectedText();
-}
-
-void NativeTextfieldViews::SelectAll(bool reversed) {
- model_->SelectAll(reversed);
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-void NativeTextfieldViews::ClearSelection() {
- model_->ClearSelection();
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-void NativeTextfieldViews::UpdateBorder() {
- // By default, if a caller calls Textfield::RemoveBorder() and does not set
- // any explicit margins, they should get zero margins. But also call
- // UpdateXXXMargins() so we respect any explicitly-set margins.
- //
- // NOTE: If someday Textfield supports toggling |draw_border_| back on, we'll
- // need to update this conditional to set the insets to their default values.
- if (!textfield_->draw_border())
- text_border_->SetInsets(0, 0, 0, 0);
- UpdateHorizontalMargins();
- UpdateVerticalMargins();
-}
-
-void NativeTextfieldViews::UpdateTextColor() {
- SetColor(textfield_->GetTextColor());
-}
-
-void NativeTextfieldViews::UpdateBackgroundColor() {
- const SkColor color = textfield_->GetBackgroundColor();
- set_background(Background::CreateSolidBackground(color));
- GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
- SchedulePaint();
-}
-
-void NativeTextfieldViews::UpdateReadOnly() {
- OnTextInputTypeChanged();
-}
-
-void NativeTextfieldViews::UpdateFont() {
- GetRenderText()->SetFontList(textfield_->font_list());
- OnCaretBoundsChanged();
-}
-
-void NativeTextfieldViews::UpdateIsObscured() {
- GetRenderText()->SetObscured(textfield_->IsObscured());
- OnCaretBoundsChanged();
- SchedulePaint();
- OnTextInputTypeChanged();
-}
-
-void NativeTextfieldViews::UpdateEnabled() {
- SetEnabled(textfield_->enabled());
- SchedulePaint();
- OnTextInputTypeChanged();
-}
-
-gfx::Insets NativeTextfieldViews::CalculateInsets() {
- return GetInsets();
-}
-
-void NativeTextfieldViews::UpdateHorizontalMargins() {
- int left, right;
- if (!textfield_->GetHorizontalMargins(&left, &right))
- return;
- gfx::Insets inset = GetInsets();
- text_border_->SetInsets(inset.top(), left, inset.bottom(), right);
- OnBoundsChanged(GetBounds());
-}
-
-void NativeTextfieldViews::UpdateVerticalMargins() {
- int top, bottom;
- if (!textfield_->GetVerticalMargins(&top, &bottom))
- return;
- gfx::Insets inset = GetInsets();
- text_border_->SetInsets(top, inset.left(), bottom, inset.right());
- OnBoundsChanged(GetBounds());
-}
-
-bool NativeTextfieldViews::SetFocus() {
- return false;
-}
-
-View* NativeTextfieldViews::GetView() {
- return this;
-}
-
-gfx::NativeView NativeTextfieldViews::GetTestingHandle() const {
- NOTREACHED();
- return NULL;
-}
-
-bool NativeTextfieldViews::IsIMEComposing() const {
- return model_->HasCompositionText();
-}
-
-gfx::Range NativeTextfieldViews::GetSelectedRange() const {
- return GetRenderText()->selection();
-}
-
-void NativeTextfieldViews::SelectRange(const gfx::Range& range) {
- model_->SelectRange(range);
- OnCaretBoundsChanged();
- SchedulePaint();
- textfield_->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
-}
-
-gfx::SelectionModel NativeTextfieldViews::GetSelectionModel() const {
- return GetRenderText()->selection_model();
-}
-
-void NativeTextfieldViews::SelectSelectionModel(
- const gfx::SelectionModel& sel) {
- model_->SelectSelectionModel(sel);
- OnCaretBoundsChanged();
- SchedulePaint();
-}
-
-size_t NativeTextfieldViews::GetCursorPosition() const {
- return model_->GetCursorPosition();
-}
-
-bool NativeTextfieldViews::GetCursorEnabled() const {
- return GetRenderText()->cursor_enabled();
-}
-
-void NativeTextfieldViews::SetCursorEnabled(bool enabled) {
- GetRenderText()->SetCursorEnabled(enabled);
-}
-
-bool NativeTextfieldViews::HandleKeyPressed(const ui::KeyEvent& e) {
- TextfieldController* controller = textfield_->GetController();
- bool handled = false;
- if (controller)
- handled = controller->HandleKeyEvent(textfield_, e);
- touch_selection_controller_.reset();
- return handled || HandleKeyEvent(e);
-}
-
-bool NativeTextfieldViews::HandleKeyReleased(const ui::KeyEvent& e) {
- return false; // crbug.com/127520
-}
-
-void NativeTextfieldViews::HandleFocus() {
- GetRenderText()->set_focused(true);
- is_cursor_visible_ = true;
- SchedulePaint();
- GetInputMethod()->OnFocus();
- OnCaretBoundsChanged();
-
- const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
- if (caret_blink_ms != 0) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&NativeTextfieldViews::UpdateCursor,
- cursor_timer_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(caret_blink_ms));
- }
-}
-
-void NativeTextfieldViews::HandleBlur() {
- GetRenderText()->set_focused(false);
- GetInputMethod()->OnBlur();
- // Stop blinking cursor.
- cursor_timer_.InvalidateWeakPtrs();
- if (is_cursor_visible_) {
- is_cursor_visible_ = false;
- RepaintCursor();
- }
-
- touch_selection_controller_.reset();
-}
-
-ui::TextInputClient* NativeTextfieldViews::GetTextInputClient() {
- return textfield_->read_only() ? NULL : this;
-}
-
-void NativeTextfieldViews::ClearEditHistory() {
- model_->ClearEditHistory();
-}
-
-int NativeTextfieldViews::GetFontHeight() {
- return GetRenderText()->font_list().GetHeight();
-}
-
-int NativeTextfieldViews::GetTextfieldBaseline() const {
- return GetRenderText()->GetBaseline();
-}
-
-int NativeTextfieldViews::GetWidthNeededForText() const {
- return GetRenderText()->GetContentWidth() + GetInsets().width();
-}
-
-void NativeTextfieldViews::ExecuteTextCommand(int command_id) {
- ExecuteCommand(command_id, 0);
-}
-
-bool NativeTextfieldViews::HasTextBeingDragged() {
- return initiating_drag_;
-}
-
-gfx::Point NativeTextfieldViews::GetContextMenuLocation() {
- return GetCaretBounds().bottom_right();
-}
-
-/////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, ui::SimpleMenuModel::Delegate overrides:
-
-bool NativeTextfieldViews::IsCommandIdChecked(int command_id) const {
- return true;
-}
-
-bool NativeTextfieldViews::IsCommandIdEnabled(int command_id) const {
- TextfieldController* controller = textfield_->GetController();
- if (controller && controller->HandlesCommand(command_id))
- return controller->IsCommandIdEnabled(command_id);
-
- bool editable = !textfield_->read_only();
- string16 result;
- switch (command_id) {
- case IDS_APP_UNDO:
- return editable && model_->CanUndo();
- case IDS_APP_CUT:
- return editable && model_->HasSelection() && !textfield_->IsObscured();
- case IDS_APP_COPY:
- return model_->HasSelection() && !textfield_->IsObscured();
- case IDS_APP_PASTE:
- ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
- return editable && !result.empty();
- case IDS_APP_DELETE:
- return editable && model_->HasSelection();
- case IDS_APP_SELECT_ALL:
- return !model_->GetText().empty();
- default:
- return controller->IsCommandIdEnabled(command_id);
- }
-}
-
-bool NativeTextfieldViews::GetAcceleratorForCommandId(int command_id,
- ui::Accelerator* accelerator) {
- return false;
-}
-
-bool NativeTextfieldViews::IsItemForCommandIdDynamic(int command_id) const {
- const TextfieldController* controller = textfield_->GetController();
- return controller && controller->IsItemForCommandIdDynamic(command_id);
-}
-
-string16 NativeTextfieldViews::GetLabelForCommandId(int command_id) const {
- const TextfieldController* controller = textfield_->GetController();
- return controller ? controller->GetLabelForCommandId(command_id) : string16();
-}
-
-void NativeTextfieldViews::ExecuteCommand(int command_id, int event_flags) {
- touch_selection_controller_.reset();
- if (!IsCommandIdEnabled(command_id))
- return;
-
- TextfieldController* controller = textfield_->GetController();
- if (controller && controller->HandlesCommand(command_id)) {
- controller->ExecuteCommand(command_id, 0);
- } else {
- bool text_changed = false;
- switch (command_id) {
- case IDS_APP_UNDO:
- OnBeforeUserAction();
- text_changed = model_->Undo();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
- break;
- case IDS_APP_CUT:
- OnBeforeUserAction();
- text_changed = Cut();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
- break;
- case IDS_APP_COPY:
- OnBeforeUserAction();
- Copy();
- OnAfterUserAction();
- break;
- case IDS_APP_PASTE:
- OnBeforeUserAction();
- text_changed = Paste();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
- break;
- case IDS_APP_DELETE:
- OnBeforeUserAction();
- text_changed = model_->Delete();
- UpdateAfterChange(text_changed, text_changed);
- OnAfterUserAction();
- break;
- case IDS_APP_SELECT_ALL:
- OnBeforeUserAction();
- SelectAll(false);
- UpdateAfterChange(false, true);
- OnAfterUserAction();
- break;
- default:
- controller->ExecuteCommand(command_id, 0);
- break;
- }
- }
-}
-
-void NativeTextfieldViews::SetColor(SkColor value) {
- GetRenderText()->SetColor(value);
- SchedulePaint();
-}
-
-void NativeTextfieldViews::ApplyColor(SkColor value, const gfx::Range& range) {
- GetRenderText()->ApplyColor(value, range);
- SchedulePaint();
-}
-
-void NativeTextfieldViews::SetStyle(gfx::TextStyle style, bool value) {
- GetRenderText()->SetStyle(style, value);
- SchedulePaint();
-}
-
-void NativeTextfieldViews::ApplyStyle(gfx::TextStyle style,
- bool value,
- const gfx::Range& range) {
- GetRenderText()->ApplyStyle(style, value, range);
- SchedulePaint();
-}
-
-void NativeTextfieldViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- // Set the RenderText display area.
- gfx::Insets insets = GetInsets();
- gfx::Rect display_rect(insets.left(),
- insets.top(),
- width() - insets.width(),
- height() - insets.height());
- GetRenderText()->SetDisplayRect(display_rect);
- OnCaretBoundsChanged();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// NativeTextfieldViews, ui::TextInputClient implementation, private:
-
-void NativeTextfieldViews::SetCompositionText(
- const ui::CompositionText& composition) {
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->SetCompositionText(composition);
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::ConfirmCompositionText() {
- if (!model_->HasCompositionText())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->ConfirmCompositionText();
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::ClearCompositionText() {
- if (!model_->HasCompositionText())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- model_->CancelCompositionText();
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::InsertText(const string16& text) {
- // TODO(suzhe): Filter invalid characters.
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || text.empty())
- return;
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- if (GetRenderText()->insert_mode())
- model_->InsertText(GetTextForDisplay(text));
- else
- model_->ReplaceText(GetTextForDisplay(text));
- skip_input_method_cancel_composition_ = false;
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-}
-
-void NativeTextfieldViews::InsertChar(char16 ch, int flags) {
- if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE ||
- !ShouldInsertChar(ch, flags)) {
- return;
- }
-
- OnBeforeUserAction();
- skip_input_method_cancel_composition_ = true;
- if (GetRenderText()->insert_mode())
- model_->InsertChar(ch);
- else
- model_->ReplaceChar(ch);
- skip_input_method_cancel_composition_ = false;
-
- model_->SetText(GetTextForDisplay(GetText()));
-
- UpdateAfterChange(true, true);
- OnAfterUserAction();
-
- if (textfield_->IsObscured()) {
- const base::TimeDelta& reveal_duration =
- textfield_->obscured_reveal_duration();
- if (reveal_duration != base::TimeDelta()) {
- const size_t change_offset = model_->GetCursorPosition();
- DCHECK_GT(change_offset, 0u);
- RevealObscuredChar(change_offset - 1, reveal_duration);
- }
- }
-}
-
-gfx::NativeWindow NativeTextfieldViews::GetAttachedWindow() const {
- // Imagine the following hierarchy.
- // [NativeWidget A] - FocusManager
- // [View]
- // [NativeWidget B]
- // [View]
- // [View X]
- // An important thing is that [NativeWidget A] owns Win32 input focus even
- // when [View X] is logically focused by FocusManager. As a result, an Win32
- // IME may want to interact with the native view of [NativeWidget A] rather
- // than that of [NativeWidget B]. This is why we need to call
- // GetTopLevelWidget() here.
- return GetWidget()->GetTopLevelWidget()->GetNativeView();
-}
-
-ui::TextInputType NativeTextfieldViews::GetTextInputType() const {
- return textfield_->GetTextInputType();
-}
-
-ui::TextInputMode NativeTextfieldViews::GetTextInputMode() const {
- return ui::TEXT_INPUT_MODE_DEFAULT;
-}
-
-bool NativeTextfieldViews::CanComposeInline() const {
- return true;
-}
-
-gfx::Rect NativeTextfieldViews::GetCaretBounds() const {
- // TextInputClient::GetCaretBounds is expected to return a value in screen
- // coordinates.
- gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
- ConvertRectToScreen(this, &rect);
- return rect;
-}
-
-bool NativeTextfieldViews::GetCompositionCharacterBounds(
- uint32 index,
- gfx::Rect* rect) const {
- DCHECK(rect);
- if (!HasCompositionText())
- return false;
- const gfx::Range& composition_range = GetRenderText()->GetCompositionRange();
- DCHECK(!composition_range.is_empty());
-
- size_t text_index = composition_range.start() + index;
- if (composition_range.end() <= text_index)
- return false;
- if (!GetRenderText()->IsCursorablePosition(text_index)) {
- text_index = GetRenderText()->IndexOfAdjacentGrapheme(
- text_index, gfx::CURSOR_BACKWARD);
- }
- if (text_index < composition_range.start())
- return false;
- const gfx::SelectionModel caret(text_index, gfx::CURSOR_BACKWARD);
- *rect = GetRenderText()->GetCursorBounds(caret, false);
- ConvertRectToScreen(this, rect);
-
- return true;
-}
-
-bool NativeTextfieldViews::HasCompositionText() const {
- return model_->HasCompositionText();
-}
-
-bool NativeTextfieldViews::GetTextRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
-
- model_->GetTextRange(range);
- return true;
-}
-
-bool NativeTextfieldViews::GetCompositionTextRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
-
- model_->GetCompositionTextRange(range);
- return true;
-}
-
-bool NativeTextfieldViews::GetSelectionRange(gfx::Range* range) const {
- if (!ImeEditingAllowed())
- return false;
- *range = GetSelectedRange();
- return true;
-}
-
-bool NativeTextfieldViews::SetSelectionRange(const gfx::Range& range) {
- if (!ImeEditingAllowed() || !range.IsValid())
- return false;
-
- OnBeforeUserAction();
- SelectRange(range);
- OnAfterUserAction();
- return true;
-}
-
-bool NativeTextfieldViews::DeleteRange(const gfx::Range& range) {
- if (!ImeEditingAllowed() || range.is_empty())
- return false;
-
- OnBeforeUserAction();
- model_->SelectRange(range);
- if (model_->HasSelection()) {
- model_->DeleteSelection();
- UpdateAfterChange(true, true);
- }
- OnAfterUserAction();
- return true;
-}
-
-bool NativeTextfieldViews::GetTextFromRange(
- const gfx::Range& range,
- string16* text) const {
- if (!ImeEditingAllowed() || !range.IsValid())
- return false;
-
- gfx::Range text_range;
- if (!GetTextRange(&text_range) || !text_range.Contains(range))
- return false;
-
- *text = model_->GetTextFromRange(range);
- return true;
-}
-
-void NativeTextfieldViews::OnInputMethodChanged() {
- // TODO(msw): NOTIMPLEMENTED(); see http://crbug.com/140402
-}
-
-bool NativeTextfieldViews::ChangeTextDirectionAndLayoutAlignment(
- base::i18n::TextDirection direction) {
- // Restore text directionality mode when the indicated direction matches the
- // current forced mode; otherwise, force the mode indicated. This helps users
- // manage BiDi text layout without getting stuck in forced LTR or RTL modes.
- const gfx::DirectionalityMode mode = direction == base::i18n::RIGHT_TO_LEFT ?
- gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
- if (mode == GetRenderText()->directionality_mode())
- GetRenderText()->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
- else
- GetRenderText()->SetDirectionalityMode(mode);
- SchedulePaint();
- return true;
-}
-
-void NativeTextfieldViews::ExtendSelectionAndDelete(
- size_t before,
- size_t after) {
- gfx::Range range = GetSelectedRange();
- DCHECK_GE(range.start(), before);
-
- range.set_start(range.start() - before);
- range.set_end(range.end() + after);
- gfx::Range text_range;
- if (GetTextRange(&text_range) && text_range.Contains(range))
- DeleteRange(range);
-}
-
-void NativeTextfieldViews::EnsureCaretInRect(const gfx::Rect& rect) {
-}
-
-void NativeTextfieldViews::OnCandidateWindowShown() {
-}
-
-void NativeTextfieldViews::OnCandidateWindowUpdated() {
-}
-
-void NativeTextfieldViews::OnCandidateWindowHidden() {
-}
-
-void NativeTextfieldViews::OnCompositionTextConfirmedOrCleared() {
- if (skip_input_method_cancel_composition_)
- return;
- DCHECK(textfield_->GetInputMethod());
- textfield_->GetInputMethod()->CancelComposition(textfield_);
-}
-
-gfx::RenderText* NativeTextfieldViews::GetRenderText() const {
- return model_->render_text();
-}
-
-string16 NativeTextfieldViews::GetTextForDisplay(const string16& text) {
- return textfield_->style() & Textfield::STYLE_LOWERCASE ?
- base::i18n::ToLower(text) : text;
-}
-
-void NativeTextfieldViews::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
- UpdateTextColor();
- UpdateBackgroundColor();
- gfx::RenderText* render_text = GetRenderText();
- render_text->set_cursor_color(textfield_->GetTextColor());
- render_text->set_selection_color(theme->GetSystemColor(
- ui::NativeTheme::kColorId_TextfieldSelectionColor));
- render_text->set_selection_background_focused_color(theme->GetSystemColor(
- ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused));
-}
-
-void NativeTextfieldViews::UpdateCursor() {
- const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
- is_cursor_visible_ = !is_cursor_visible_ || (caret_blink_ms == 0);
- RepaintCursor();
- if (caret_blink_ms != 0) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&NativeTextfieldViews::UpdateCursor,
- cursor_timer_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(caret_blink_ms));
- }
-}
-
-void NativeTextfieldViews::RepaintCursor() {
- gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
- r.Inset(-1, -1, -1, -1);
- SchedulePaintInRect(r);
-}
-
-void NativeTextfieldViews::PaintTextAndCursor(gfx::Canvas* canvas) {
- TRACE_EVENT0("views", "NativeTextfieldViews::PaintTextAndCursor");
- canvas->Save();
- GetRenderText()->set_cursor_visible(!is_drop_cursor_visible_ &&
- is_cursor_visible_ && !model_->HasSelection());
- // Draw the text, cursor, and selection.
- GetRenderText()->Draw(canvas);
-
- // Draw the detached drop cursor that marks where the text will be dropped.
- if (is_drop_cursor_visible_)
- GetRenderText()->DrawCursor(canvas, drop_cursor_position_);
-
- // Draw placeholder text if needed.
- if (model_->GetText().empty() &&
- !textfield_->GetPlaceholderText().empty()) {
- canvas->DrawStringInt(
- textfield_->GetPlaceholderText(),
- GetRenderText()->GetPrimaryFont(),
- textfield_->placeholder_text_color(),
- GetRenderText()->display_rect());
- }
- canvas->Restore();
-}
-
-bool NativeTextfieldViews::HandleKeyEvent(const ui::KeyEvent& key_event) {
- // TODO(oshima): Refactor and consolidate with ExecuteCommand.
- if (key_event.type() == ui::ET_KEY_PRESSED) {
- ui::KeyboardCode key_code = key_event.key_code();
- if (key_code == ui::VKEY_TAB || key_event.IsUnicodeKeyCode())
- return false;
-
- OnBeforeUserAction();
- const bool editable = !textfield_->read_only();
- const bool readable = !textfield_->IsObscured();
- const bool shift = key_event.IsShiftDown();
- const bool control = key_event.IsControlDown();
- const bool alt = key_event.IsAltDown() || key_event.IsAltGrDown();
- bool text_changed = false;
- bool cursor_changed = false;
- switch (key_code) {
- case ui::VKEY_Z:
- if (control && !shift && !alt && editable)
- cursor_changed = text_changed = model_->Undo();
- else if (control && shift && !alt && editable)
- cursor_changed = text_changed = model_->Redo();
- break;
- case ui::VKEY_Y:
- if (control && !alt && editable)
- cursor_changed = text_changed = model_->Redo();
- break;
- case ui::VKEY_A:
- if (control && !alt) {
- model_->SelectAll(false);
- cursor_changed = true;
- }
- break;
- case ui::VKEY_X:
- if (control && !alt && editable && readable)
- cursor_changed = text_changed = Cut();
- break;
- case ui::VKEY_C:
- if (control && !alt && readable)
- Copy();
- break;
- case ui::VKEY_V:
- if (control && !alt && editable)
- cursor_changed = text_changed = Paste();
- break;
- case ui::VKEY_RIGHT:
- case ui::VKEY_LEFT: {
- // We should ignore the alt-left/right keys because alt key doesn't make
- // any special effects for them and they can be shortcut keys such like
- // forward/back of the browser history.
- if (alt)
- break;
- const gfx::Range selection_range = GetSelectedRange();
- model_->MoveCursor(
- control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
- (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
- shift);
- cursor_changed = GetSelectedRange() != selection_range;
- break;
- }
- case ui::VKEY_END:
- case ui::VKEY_HOME:
- if ((key_code == ui::VKEY_HOME) ==
- (GetRenderText()->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
- model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
- else
- model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
- cursor_changed = true;
- break;
- case ui::VKEY_BACK:
- case ui::VKEY_DELETE:
- if (!editable)
- break;
- if (!model_->HasSelection()) {
- gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
- gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
- if (shift && control) {
- // If both shift and control are pressed, then erase up to the
- // beginning/end of the buffer in ChromeOS. In windows, do nothing.
-#if defined(OS_WIN)
- break;
-#else
- model_->MoveCursor(gfx::LINE_BREAK, direction, true);
-#endif
- } else if (control) {
- // If only control is pressed, then erase the previous/next word.
- model_->MoveCursor(gfx::WORD_BREAK, direction, true);
- }
- }
- if (key_code == ui::VKEY_BACK)
- model_->Backspace();
- else if (shift && model_->HasSelection() && readable)
- Cut();
- else
- model_->Delete();
-
- // Consume backspace and delete keys even if the edit did nothing. This
- // prevents potential unintended side-effects of further event handling.
- text_changed = true;
- break;
- case ui::VKEY_INSERT:
- if (control && !shift && readable)
- Copy();
- else if (shift && !control && editable)
- cursor_changed = text_changed = Paste();
- break;
- default:
- break;
- }
-
- // We must have input method in order to support text input.
- DCHECK(textfield_->GetInputMethod());
-
- UpdateAfterChange(text_changed, cursor_changed);
- OnAfterUserAction();
- return (text_changed || cursor_changed);
- }
- return false;
-}
-
-bool NativeTextfieldViews::MoveCursorTo(const gfx::Point& point, bool select) {
- if (!model_->MoveCursorTo(point, select))
- return false;
- OnCaretBoundsChanged();
- return true;
-}
-
-void NativeTextfieldViews::PropagateTextChange() {
- textfield_->SyncText();
-}
-
-void NativeTextfieldViews::UpdateAfterChange(bool text_changed,
- bool cursor_changed) {
- if (text_changed) {
- PropagateTextChange();
- textfield_->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
- }
- if (cursor_changed) {
- is_cursor_visible_ = true;
- RepaintCursor();
- if (!text_changed) {
- // TEXT_CHANGED implies SELECTION_CHANGED, so we only need to fire
- // this if only the selection changed.
- textfield_->NotifyAccessibilityEvent(
- ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
- }
- }
- if (text_changed || cursor_changed) {
- OnCaretBoundsChanged();
- SchedulePaint();
- }
-}
-
-void NativeTextfieldViews::UpdateContextMenu() {
- if (!context_menu_contents_.get()) {
- context_menu_contents_.reset(new ui::SimpleMenuModel(this));
- context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
- context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
- context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
- context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
- context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
- context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
- context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
- context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
- IDS_APP_SELECT_ALL);
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->UpdateContextMenu(context_menu_contents_.get());
-
- context_menu_delegate_.reset(
- new views::MenuModelAdapter(context_menu_contents_.get()));
- context_menu_runner_.reset(
- new MenuRunner(new views::MenuItemView(context_menu_delegate_.get())));
- }
-
- context_menu_delegate_->BuildMenu(context_menu_runner_->GetMenu());
-}
-
-void NativeTextfieldViews::OnTextInputTypeChanged() {
- // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
- if (textfield_->GetInputMethod())
- textfield_->GetInputMethod()->OnTextInputTypeChanged(textfield_);
-}
-
-void NativeTextfieldViews::OnCaretBoundsChanged() {
- // TODO(suzhe): changed from DCHECK. See http://crbug.com/81320.
- if (textfield_->GetInputMethod())
- textfield_->GetInputMethod()->OnCaretBoundsChanged(textfield_);
-
- // Notify selection controller
- if (touch_selection_controller_.get())
- touch_selection_controller_->SelectionChanged();
-}
-
-void NativeTextfieldViews::OnBeforeUserAction() {
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnBeforeUserAction(textfield_);
-}
-
-void NativeTextfieldViews::OnAfterUserAction() {
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnAfterUserAction(textfield_);
-}
-
-bool NativeTextfieldViews::Cut() {
- if (!textfield_->read_only() && !textfield_->IsObscured() && model_->Cut()) {
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnAfterCutOrCopy();
- return true;
- }
- return false;
-}
-
-bool NativeTextfieldViews::Copy() {
- if (!textfield_->IsObscured() && model_->Copy()) {
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnAfterCutOrCopy();
- return true;
- }
- return false;
-}
-
-bool NativeTextfieldViews::Paste() {
- if (textfield_->read_only())
- return false;
-
- const string16 original_text = GetText();
- const bool success = model_->Paste();
-
- if (success) {
- // As Paste is handled in model_->Paste(), the RenderText may contain
- // upper case characters. This is not consistent with other places
- // which keeps RenderText only containing lower case characters.
- string16 new_text = GetTextForDisplay(GetText());
- model_->SetText(new_text);
-
- TextfieldController* controller = textfield_->GetController();
- if (controller)
- controller->OnAfterPaste();
- }
- return success;
-}
-
-void NativeTextfieldViews::TrackMouseClicks(const ui::MouseEvent& event) {
- if (event.IsOnlyLeftMouseButton()) {
- base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
- if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
- !ExceededDragThresholdFromLastClickLocation(event)) {
- // Upon clicking after a triple click, the count should go back to double
- // click and alternate between double and triple. This assignment maps
- // 0 to 1, 1 to 2, 2 to 1.
- aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
- } else {
- aggregated_clicks_ = 0;
- }
- last_click_time_ = event.time_stamp();
- last_click_location_ = event.location();
- }
-}
-
-void NativeTextfieldViews::HandleMousePressEvent(const ui::MouseEvent& event) {
- if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton())
- textfield_->RequestFocus();
-
- if (!event.IsOnlyLeftMouseButton())
- return;
-
- initiating_drag_ = false;
- bool can_drag = true;
-
- switch (aggregated_clicks_) {
- case 0:
- if (can_drag && GetRenderText()->IsPointInSelection(event.location()))
- initiating_drag_ = true;
- else
- MoveCursorTo(event.location(), event.IsShiftDown());
- break;
- case 1:
- MoveCursorTo(event.location(), false);
- model_->SelectWord();
- double_click_word_ = GetRenderText()->selection();
- OnCaretBoundsChanged();
- break;
- case 2:
- model_->SelectAll(false);
- OnCaretBoundsChanged();
- break;
- default:
- NOTREACHED();
- }
- SchedulePaint();
-}
-
-bool NativeTextfieldViews::ImeEditingAllowed() const {
- // We don't allow the input method to retrieve or delete content from a
- // password field.
- ui::TextInputType t = GetTextInputType();
- return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
-}
-
-// static
-bool NativeTextfieldViews::ShouldInsertChar(char16 ch, int flags) {
- // Filter out all control characters, including tab and new line characters,
- // and all characters with Alt modifier. But we need to allow characters with
- // AltGr modifier.
- // On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a different
- // flag that we don't care about.
- return ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
- (flags & ~(ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN)) != ui::EF_ALT_DOWN;
-}
-
-void NativeTextfieldViews::CreateTouchSelectionControllerAndNotifyIt() {
- if (!touch_selection_controller_) {
- touch_selection_controller_.reset(
- ui::TouchSelectionController::create(this));
- }
- if (touch_selection_controller_)
- touch_selection_controller_->SelectionChanged();
-}
-
-void NativeTextfieldViews::PlatformGestureEventHandling(
- const ui::GestureEvent* event) {
-#if defined(OS_WIN) && defined(USE_AURA)
- if (event->type() == ui::ET_GESTURE_TAP && !textfield_->read_only())
- base::win::DisplayVirtualKeyboard();
-#endif
-}
-
-void NativeTextfieldViews::RevealObscuredChar(int index,
- const base::TimeDelta& duration) {
- GetRenderText()->SetObscuredRevealIndex(index);
- SchedulePaint();
-
- if (index != -1) {
- obscured_reveal_timer_.Start(
- FROM_HERE,
- duration,
- base::Bind(&NativeTextfieldViews::RevealObscuredChar,
- base::Unretained(this), -1, base::TimeDelta()));
- }
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/textfield/native_textfield_views.h b/chromium/ui/views/controls/textfield/native_textfield_views.h
deleted file mode 100644
index e85f44dd1b6..00000000000
--- a/chromium/ui/views/controls/textfield/native_textfield_views.h
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_
-#define UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_
-
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "base/timer/timer.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/base/models/simple_menu_model.h"
-#include "ui/base/touch/touch_editing_controller.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/font.h"
-#include "ui/views/border.h"
-#include "ui/views/context_menu_controller.h"
-#include "ui/views/controls/textfield/native_textfield_wrapper.h"
-#include "ui/views/controls/textfield/textfield_views_model.h"
-#include "ui/views/drag_controller.h"
-#include "ui/views/view.h"
-
-namespace base {
-class Time;
-}
-
-namespace gfx {
-class Canvas;
-}
-
-namespace views {
-
-class FocusableBorder;
-class MenuModelAdapter;
-class MenuRunner;
-
-// A views/skia only implementation of NativeTextfieldWrapper.
-// No platform specific code is used.
-// Following features are not yet supported.
-// * BIDI/Complex script.
-// * Support surrogate pair, or maybe we should just use UTF32 internally.
-// * X selection (only if we want to support).
-// Once completed, this will replace Textfield, NativeTextfieldWin and
-// NativeTextfieldGtk.
-class VIEWS_EXPORT NativeTextfieldViews : public View,
- public ui::TouchEditable,
- public ContextMenuController,
- public DragController,
- public NativeTextfieldWrapper,
- public ui::TextInputClient,
- public TextfieldViewsModel::Delegate {
- public:
- explicit NativeTextfieldViews(Textfield* parent);
- virtual ~NativeTextfieldViews();
-
- // View overrides:
- virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
- virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
- virtual bool GetDropFormats(
- int* formats,
- std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
- virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE;
- virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
- virtual void OnDragExited() OVERRIDE;
- virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
- virtual void OnDragDone() OVERRIDE;
- virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnFocus() OVERRIDE;
- virtual void OnBlur() OVERRIDE;
- virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
-
- // ui::TouchEditable overrides:
- virtual void SelectRect(const gfx::Point& start,
- const gfx::Point& end) OVERRIDE;
- virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE;
- virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE;
- virtual gfx::Rect GetBounds() OVERRIDE;
- virtual gfx::NativeView GetNativeView() OVERRIDE;
- virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE;
- virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE;
- virtual bool DrawsHandles() OVERRIDE;
- virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE;
-
- // ContextMenuController overrides:
- virtual void ShowContextMenuForView(View* source,
- const gfx::Point& point,
- ui::MenuSourceType source_type) OVERRIDE;
-
- // Overridden from DragController:
- virtual void WriteDragDataForView(View* sender,
- const gfx::Point& press_pt,
- ui::OSExchangeData* data) OVERRIDE;
- virtual int GetDragOperationsForView(View* sender,
- const gfx::Point& p) OVERRIDE;
- virtual bool CanStartDragForView(View* sender,
- const gfx::Point& press_pt,
- const gfx::Point& p) OVERRIDE;
-
- // NativeTextfieldWrapper overrides:
- virtual string16 GetText() const OVERRIDE;
- virtual void UpdateText() OVERRIDE;
- virtual void AppendText(const string16& text) OVERRIDE;
- virtual void InsertOrReplaceText(const string16& text) OVERRIDE;
- virtual base::i18n::TextDirection GetTextDirection() const OVERRIDE;
- virtual string16 GetSelectedText() const OVERRIDE;
- virtual void SelectAll(bool reversed) OVERRIDE;
- virtual void ClearSelection() OVERRIDE;
- virtual void UpdateBorder() OVERRIDE;
- virtual void UpdateTextColor() OVERRIDE;
- virtual void UpdateBackgroundColor() OVERRIDE;
- virtual void UpdateReadOnly() OVERRIDE;
- virtual void UpdateFont() OVERRIDE;
- virtual void UpdateIsObscured() OVERRIDE;
- virtual void UpdateEnabled() OVERRIDE;
- virtual gfx::Insets CalculateInsets() OVERRIDE;
- virtual void UpdateHorizontalMargins() OVERRIDE;
- virtual void UpdateVerticalMargins() OVERRIDE;
- virtual bool SetFocus() OVERRIDE;
- virtual View* GetView() OVERRIDE;
- virtual gfx::NativeView GetTestingHandle() const OVERRIDE;
- virtual bool IsIMEComposing() const OVERRIDE;
- virtual gfx::Range GetSelectedRange() const OVERRIDE;
- virtual void SelectRange(const gfx::Range& range) OVERRIDE;
- virtual gfx::SelectionModel GetSelectionModel() const OVERRIDE;
- virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE;
- virtual size_t GetCursorPosition() const OVERRIDE;
- virtual bool GetCursorEnabled() const OVERRIDE;
- virtual void SetCursorEnabled(bool enabled) OVERRIDE;
- virtual bool HandleKeyPressed(const ui::KeyEvent& e) OVERRIDE;
- virtual bool HandleKeyReleased(const ui::KeyEvent& e) OVERRIDE;
- virtual void HandleFocus() OVERRIDE;
- virtual void HandleBlur() OVERRIDE;
- virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
- virtual void SetColor(SkColor value) OVERRIDE;
- virtual void ApplyColor(SkColor value, const gfx::Range& range) OVERRIDE;
- virtual void SetStyle(gfx::TextStyle style, bool value) OVERRIDE;
- virtual void ApplyStyle(gfx::TextStyle style,
- bool value,
- const gfx::Range& range) OVERRIDE;
- virtual void ClearEditHistory() OVERRIDE;
- virtual int GetFontHeight() OVERRIDE;
- virtual int GetTextfieldBaseline() const OVERRIDE;
- virtual int GetWidthNeededForText() const OVERRIDE;
- virtual void ExecuteTextCommand(int command_id) OVERRIDE;
- virtual bool HasTextBeingDragged() OVERRIDE;
- virtual gfx::Point GetContextMenuLocation() OVERRIDE;
-
- // ui::SimpleMenuModel::Delegate overrides
- virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
- virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
- virtual bool GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) OVERRIDE;
- virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE;
- virtual string16 GetLabelForCommandId(int command_id) const OVERRIDE;
- virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
-
- // class name of internal
- static const char kViewClassName[];
-
- protected:
- // View override.
- virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
-
- private:
- friend class NativeTextfieldViewsTest;
- friend class TouchSelectionControllerImplTest;
-
- // Overridden from ui::TextInputClient:
- virtual void SetCompositionText(
- const ui::CompositionText& composition) OVERRIDE;
- virtual void ConfirmCompositionText() OVERRIDE;
- virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const string16& text) OVERRIDE;
- virtual void InsertChar(char16 ch, int flags) OVERRIDE;
- virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
- virtual ui::TextInputType GetTextInputType() const OVERRIDE;
- virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
- virtual bool CanComposeInline() const OVERRIDE;
- virtual gfx::Rect GetCaretBounds() const OVERRIDE;
- virtual bool GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) const OVERRIDE;
- virtual bool HasCompositionText() const OVERRIDE;
- virtual bool GetTextRange(gfx::Range* range) const OVERRIDE;
- virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE;
- virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE;
- virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
- virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const gfx::Range& range,
- string16* text) const OVERRIDE;
- virtual void OnInputMethodChanged() OVERRIDE;
- virtual bool ChangeTextDirectionAndLayoutAlignment(
- base::i18n::TextDirection direction) OVERRIDE;
- virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
- virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
- virtual void OnCandidateWindowShown() OVERRIDE;
- virtual void OnCandidateWindowUpdated() OVERRIDE;
- virtual void OnCandidateWindowHidden() OVERRIDE;
-
- // Overridden from TextfieldViewsModel::Delegate:
- virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE;
-
- // Returns the TextfieldViewsModel's text/cursor/selection rendering model.
- gfx::RenderText* GetRenderText() const;
-
- // Converts |text| according to textfield style, e.g. lower case if
- // |textfield_| has STYLE_LOWERCASE style.
- string16 GetTextForDisplay(const string16& text);
-
- // Updates any colors that have not been explicitly set from the theme.
- void UpdateColorsFromTheme(const ui::NativeTheme* theme);
-
- // A callback function to periodically update the cursor state.
- void UpdateCursor();
-
- // Repaint the cursor.
- void RepaintCursor();
-
- // Update the cursor_bounds and text_offset.
- void UpdateCursorBoundsAndTextOffset(size_t cursor_pos, bool insert_mode);
-
- void PaintTextAndCursor(gfx::Canvas* canvas);
-
- // Handle the keyevent.
- bool HandleKeyEvent(const ui::KeyEvent& key_event);
-
- // Helper function to call MoveCursorTo on the TextfieldViewsModel.
- bool MoveCursorTo(const gfx::Point& point, bool select);
-
- // Utility function to inform the parent textfield (and its controller if any)
- // that the text in the textfield has changed.
- void PropagateTextChange();
-
- // Does necessary updates when the text and/or the position of the cursor
- // changed.
- void UpdateAfterChange(bool text_changed, bool cursor_changed);
-
- // Utility function to prepare the context menu.
- void UpdateContextMenu();
-
- // Convenience method to call InputMethod::OnTextInputTypeChanged();
- void OnTextInputTypeChanged();
-
- // Convenience method to call InputMethod::OnCaretBoundsChanged();
- void OnCaretBoundsChanged();
-
- // Convenience method to call TextfieldController::OnBeforeUserAction();
- void OnBeforeUserAction();
-
- // Convenience method to call TextfieldController::OnAfterUserAction();
- void OnAfterUserAction();
-
- // Calls |model_->Cut()| and notifies TextfieldController on success.
- bool Cut();
-
- // Calls |model_->Copy()| and notifies TextfieldController on success.
- bool Copy();
-
- // Calls |model_->Paste()| and calls TextfieldController::ContentsChanged()
- // explicitly if paste succeeded.
- bool Paste();
-
- // Tracks the mouse clicks for single/double/triple clicks.
- void TrackMouseClicks(const ui::MouseEvent& event);
-
- // Handles mouse press events.
- void HandleMousePressEvent(const ui::MouseEvent& event);
-
- // Returns true if the current text input type allows access by the IME.
- bool ImeEditingAllowed() const;
-
- // Returns true if distance between |event| and |last_click_location_|
- // exceeds the drag threshold.
- bool ExceededDragThresholdFromLastClickLocation(const ui::MouseEvent& event);
-
- // Checks if a char is ok to be inserted into the textfield. The |ch| is a
- // modified character, i.e., modifiers took effect when generating this char.
- static bool ShouldInsertChar(char16 ch, int flags);
-
- void CreateTouchSelectionControllerAndNotifyIt();
-
- // Platform specific gesture event handling.
- void PlatformGestureEventHandling(const ui::GestureEvent* event);
-
- // Reveals the obscured char at |index| for the given |duration|. If |index|
- // is -1, existing revealed index will be cleared.
- void RevealObscuredChar(int index, const base::TimeDelta& duration);
-
- // The parent textfield, the owner of this object.
- Textfield* textfield_;
-
- // The text model.
- scoped_ptr<TextfieldViewsModel> model_;
-
- // The focusable border. This is always non-NULL, but may not actually be
- // drawn. If it is not drawn, then by default it's also zero-sized unless the
- // Textfield has explicitly-set margins.
- FocusableBorder* text_border_;
-
- // The textfield's text and drop cursor visibility.
- bool is_cursor_visible_;
-
- // The drop cursor is a visual cue for where dragged text will be dropped.
- bool is_drop_cursor_visible_;
- // Position of the drop cursor, if it is visible.
- gfx::SelectionModel drop_cursor_position_;
-
- // True if InputMethod::CancelComposition() should not be called.
- bool skip_input_method_cancel_composition_;
-
- // Is the user potentially dragging and dropping from this view?
- bool initiating_drag_;
-
- // A runnable method factory for callback to update the cursor.
- base::WeakPtrFactory<NativeTextfieldViews> cursor_timer_;
-
- // State variables used to track double and triple clicks.
- size_t aggregated_clicks_;
- base::TimeDelta last_click_time_;
- gfx::Point last_click_location_;
- gfx::Range double_click_word_;
-
- // Context menu and its content list for the textfield.
- scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
- scoped_ptr<views::MenuModelAdapter> context_menu_delegate_;
- scoped_ptr<views::MenuRunner> context_menu_runner_;
-
- scoped_ptr<ui::TouchSelectionController> touch_selection_controller_;
-
- // A timer to control the duration of showing the last typed char in
- // obscured text. When the timer is running, the last typed char is shown
- // and when the time expires, the last typed char is obscured.
- base::OneShotTimer<NativeTextfieldViews> obscured_reveal_timer_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeTextfieldViews);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_
diff --git a/chromium/ui/views/controls/textfield/native_textfield_wrapper.h b/chromium/ui/views/controls/textfield/native_textfield_wrapper.h
deleted file mode 100644
index eafd2f59dd7..00000000000
--- a/chromium/ui/views/controls/textfield/native_textfield_wrapper.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_WRAPPER_H_
-#define UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_WRAPPER_H_
-
-#include "base/i18n/rtl.h"
-#include "base/strings/string16.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/range/range.h"
-#include "ui/gfx/selection_model.h"
-#include "ui/gfx/text_constants.h"
-#include "ui/views/views_export.h"
-
-namespace gfx {
-class Insets;
-class Point;
-} // namespace gfx
-
-namespace ui {
-class KeyEvent;
-class TextInputClient;
-} // namespace ui
-
-namespace views {
-
-class Textfield;
-class View;
-
-// An interface implemented by an object that provides a platform-native
-// text field.
-class VIEWS_EXPORT NativeTextfieldWrapper {
- public:
- // The Textfield calls this when it is destroyed to clean up the wrapper
- // object.
- virtual ~NativeTextfieldWrapper() {}
-
- // Gets the text displayed in the wrapped native text field.
- virtual string16 GetText() const = 0;
-
- // Updates the text displayed with the text held by the Textfield.
- virtual void UpdateText() = 0;
-
- // Adds the specified text to the text already displayed by the wrapped native
- // text field.
- virtual void AppendText(const string16& text) = 0;
-
- // Inserts |text| at the current cursor position, replacing any selected text.
- virtual void InsertOrReplaceText(const string16& text) = 0;
-
- // Returns the text direction.
- virtual base::i18n::TextDirection GetTextDirection() const = 0;
-
- // Gets the text that is selected in the wrapped native text field.
- virtual string16 GetSelectedText() const = 0;
-
- // Select the entire text range. If |reversed| is true, the range will end at
- // the logical beginning of the text; this generally shows the leading portion
- // of text that overflows its display area.
- virtual void SelectAll(bool reversed) = 0;
-
- // Clears the selection within the edit field and sets the caret to the end.
- virtual void ClearSelection() = 0;
-
- // Updates whether there is a visible border.
- virtual void UpdateBorder() = 0;
-
- // Updates the text color used when painting the native text field.
- virtual void UpdateTextColor() = 0;
-
- // Updates the background color used when painting the native text field.
- virtual void UpdateBackgroundColor() = 0;
-
- // Updates the read-only state of the native text field.
- virtual void UpdateReadOnly() = 0;
-
- // Updates the font used to render text in the native text field.
- virtual void UpdateFont() = 0;
-
- // Updates the visibility of the text in the native text field.
- virtual void UpdateIsObscured() = 0;
-
- // Updates the enabled state of the native text field.
- virtual void UpdateEnabled() = 0;
-
- // Returns the insets for the text field.
- virtual gfx::Insets CalculateInsets() = 0;
-
- // Updates the horizontal margins for the native text field.
- virtual void UpdateHorizontalMargins() = 0;
-
- // Updates the vertical margins for the native text field.
- virtual void UpdateVerticalMargins() = 0;
-
- // Sets the focus to the text field. Returns false if the wrapper
- // didn't take focus.
- virtual bool SetFocus() = 0;
-
- // Retrieves the views::View that hosts the native control.
- virtual View* GetView() = 0;
-
- // Returns a handle to the underlying native view for testing.
- virtual gfx::NativeView GetTestingHandle() const = 0;
-
- // Returns whether or not an IME is composing text.
- virtual bool IsIMEComposing() const = 0;
-
- // Gets the selected range.
- virtual gfx::Range GetSelectedRange() const = 0;
-
- // Selects the text given by |range|.
- virtual void SelectRange(const gfx::Range& range) = 0;
-
- // Gets the selection model.
- virtual gfx::SelectionModel GetSelectionModel() const = 0;
-
- // Selects the text given by |sel|.
- virtual void SelectSelectionModel(const gfx::SelectionModel& sel) = 0;
-
- // Returns the currnet cursor position.
- virtual size_t GetCursorPosition() const = 0;
-
- // Get or set whether or not the cursor is enabled.
- virtual bool GetCursorEnabled() const = 0;
- virtual void SetCursorEnabled(bool enabled) = 0;
-
- // Following methods are to forward key/focus related events to the
- // views wrapper so that TextfieldViews can handle key inputs without
- // having focus.
-
- // Invoked when a key is pressed/release on Textfield. Subclasser
- // should return true if the event has been processed and false
- // otherwise.
- // See also View::OnKeyPressed/OnKeyReleased.
- virtual bool HandleKeyPressed(const ui::KeyEvent& e) = 0;
- virtual bool HandleKeyReleased(const ui::KeyEvent& e) = 0;
-
- // Invoked when focus is being moved from or to the Textfield.
- // See also View::OnFocus/OnBlur.
- virtual void HandleFocus() = 0;
- virtual void HandleBlur() = 0;
-
- // Returns the View's TextInputClient instance or NULL if the View doesn't
- // support text input.
- virtual ui::TextInputClient* GetTextInputClient() = 0;
-
- // Set the text colors; see the corresponding Textfield functions for details.
- virtual void SetColor(SkColor value) = 0;
- virtual void ApplyColor(SkColor value, const gfx::Range& range) = 0;
-
- // Set the text styles; see the corresponding Textfield functions for details.
- virtual void SetStyle(gfx::TextStyle style, bool value) = 0;
- virtual void ApplyStyle(gfx::TextStyle style,
- bool value,
- const gfx::Range& range) = 0;
-
- // Clears Edit history.
- virtual void ClearEditHistory() = 0;
-
- // Get the height in pixels of the first font used in this textfield.
- virtual int GetFontHeight() = 0;
-
- // Returns the baseline of the textfield. This should not take into account
- // any insets.
- virtual int GetTextfieldBaseline() const = 0;
-
- // Returns the width necessary to display the current text, including any
- // necessary space for the cursor or border/margin.
- virtual int GetWidthNeededForText() const = 0;
-
- // Performs the action associated with the specified command id. Not called
- // ExecuteCommand to avoid name clash.
- virtual void ExecuteTextCommand(int command_id) = 0;
-
- // Returns whether there is a drag operation originating from the textfield.
- virtual bool HasTextBeingDragged() = 0;
-
- // Returns the location for keyboard-triggered context menus.
- virtual gfx::Point GetContextMenuLocation() = 0;
-
- // Creates an appropriate NativeTextfieldWrapper for the platform.
- static NativeTextfieldWrapper* CreateWrapper(Textfield* field);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_WRAPPER_H_
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index de590dc304c..f28f8f27e18 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -6,40 +6,235 @@
#include <string>
-#include "base/command_line.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "ui/base/accessibility/accessible_view_state.h"
-#include "ui/base/ime/text_input_type.h"
+#include "base/debug/trace_event.h"
+#include "grit/ui_strings.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_switches.h"
+#include "ui/base/ui_base_switches_util.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/display.h"
#include "ui/gfx/insets.h"
-#include "ui/gfx/range/range.h"
-#include "ui/gfx/selection_model.h"
+#include "ui/gfx/screen.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/focusable_border.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/native/native_view_host.h"
-#include "ui/views/controls/textfield/native_textfield_views.h"
-#include "ui/views/controls/textfield/native_textfield_wrapper.h"
#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/drag_utils.h"
+#include "ui/views/ime/input_method.h"
+#include "ui/views/metrics.h"
+#include "ui/views/native_cursor.h"
#include "ui/views/painter.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "base/strings/utf_string_conversions.h"
+#include "ui/events/linux/text_edit_command_auralinux.h"
+#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
+#endif
+
+namespace views {
+
namespace {
// Default placeholder text color.
const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
-gfx::FontList GetDefaultFontList() {
- return ResourceBundle::GetSharedInstance().GetFontList(
- ResourceBundle::BaseFont);
+const int kNoCommand = 0;
+
+void ConvertRectToScreen(const View* src, gfx::Rect* r) {
+ DCHECK(src);
+
+ gfx::Point new_origin = r->origin();
+ View::ConvertPointToScreen(src, &new_origin);
+ r->set_origin(new_origin);
}
-} // namespace
+// Get the drag selection timer delay, respecting animation scaling for testing.
+int GetDragSelectionDelay() {
+ switch (ui::ScopedAnimationDurationScaleMode::duration_scale_mode()) {
+ case ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION: return 100;
+ case ui::ScopedAnimationDurationScaleMode::FAST_DURATION: return 25;
+ case ui::ScopedAnimationDurationScaleMode::SLOW_DURATION: return 400;
+ case ui::ScopedAnimationDurationScaleMode::ZERO_DURATION: return 0;
+ }
+ return 100;
+}
+
+// Get the default command for a given key |event| and selection state.
+int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) {
+ if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
+ return kNoCommand;
+
+ const bool shift = event.IsShiftDown();
+ const bool control = event.IsControlDown();
+ const bool alt = event.IsAltDown() || event.IsAltGrDown();
+ switch (event.key_code()) {
+ case ui::VKEY_Z:
+ if (control && !shift && !alt)
+ return IDS_APP_UNDO;
+ return (control && shift && !alt) ? IDS_APP_REDO : kNoCommand;
+ case ui::VKEY_Y:
+ return (control && !alt) ? IDS_APP_REDO : kNoCommand;
+ case ui::VKEY_A:
+ return (control && !alt) ? IDS_APP_SELECT_ALL : kNoCommand;
+ case ui::VKEY_X:
+ return (control && !alt) ? IDS_APP_CUT : kNoCommand;
+ case ui::VKEY_C:
+ return (control && !alt) ? IDS_APP_COPY : kNoCommand;
+ case ui::VKEY_V:
+ return (control && !alt) ? IDS_APP_PASTE : kNoCommand;
+ case ui::VKEY_RIGHT:
+ // Ignore alt+right, which may be a browser navigation shortcut.
+ if (alt)
+ return kNoCommand;
+ if (!shift)
+ return control ? IDS_MOVE_WORD_RIGHT : IDS_MOVE_RIGHT;
+ return control ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_RIGHT_AND_MODIFY_SELECTION;
+ case ui::VKEY_LEFT:
+ // Ignore alt+left, which may be a browser navigation shortcut.
+ if (alt)
+ return kNoCommand;
+ if (!shift)
+ return control ? IDS_MOVE_WORD_LEFT : IDS_MOVE_LEFT;
+ return control ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_LEFT_AND_MODIFY_SELECTION;
+ case ui::VKEY_HOME:
+ return shift ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_BEGINNING_OF_LINE;
+ case ui::VKEY_END:
+ return shift ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_END_OF_LINE;
+ case ui::VKEY_BACK:
+ if (!control || has_selection)
+ return IDS_DELETE_BACKWARD;
+#if defined(OS_LINUX)
+ // Only erase by line break on Linux and ChromeOS.
+ if (shift)
+ return IDS_DELETE_TO_BEGINNING_OF_LINE;
+#endif
+ return IDS_DELETE_WORD_BACKWARD;
+ case ui::VKEY_DELETE:
+ if (!control || has_selection)
+ return (shift && has_selection) ? IDS_APP_CUT : IDS_DELETE_FORWARD;
+#if defined(OS_LINUX)
+ // Only erase by line break on Linux and ChromeOS.
+ if (shift)
+ return IDS_DELETE_TO_END_OF_LINE;
+#endif
+ return IDS_DELETE_WORD_FORWARD;
+ case ui::VKEY_INSERT:
+ if (control && !shift)
+ return IDS_APP_COPY;
+ return (shift && !control) ? IDS_APP_PASTE : kNoCommand;
+ default:
+ return kNoCommand;
+ }
+}
-namespace views {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// Convert a custom text edit |command| to the equivalent views command ID.
+int GetViewsCommand(const ui::TextEditCommandAuraLinux& command, bool rtl) {
+ const bool select = command.extend_selection();
+ switch (command.command_id()) {
+ case ui::TextEditCommandAuraLinux::COPY:
+ return IDS_APP_COPY;
+ case ui::TextEditCommandAuraLinux::CUT:
+ return IDS_APP_CUT;
+ case ui::TextEditCommandAuraLinux::DELETE_BACKWARD:
+ return IDS_DELETE_BACKWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_FORWARD:
+ return IDS_DELETE_FORWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_LINE:
+ case ui::TextEditCommandAuraLinux::DELETE_TO_BEGINING_OF_PARAGRAPH:
+ return IDS_DELETE_TO_BEGINNING_OF_LINE;
+ case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_LINE:
+ case ui::TextEditCommandAuraLinux::DELETE_TO_END_OF_PARAGRAPH:
+ return IDS_DELETE_TO_END_OF_LINE;
+ case ui::TextEditCommandAuraLinux::DELETE_WORD_BACKWARD:
+ return IDS_DELETE_WORD_BACKWARD;
+ case ui::TextEditCommandAuraLinux::DELETE_WORD_FORWARD:
+ return IDS_DELETE_WORD_FORWARD;
+ case ui::TextEditCommandAuraLinux::INSERT_TEXT:
+ return kNoCommand;
+ case ui::TextEditCommandAuraLinux::MOVE_BACKWARD:
+ if (rtl)
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_DOWN:
+ return IDS_MOVE_DOWN;
+ case ui::TextEditCommandAuraLinux::MOVE_FORWARD:
+ if (rtl)
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_LEFT:
+ return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN:
+ case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP:
+ return kNoCommand;
+ case ui::TextEditCommandAuraLinux::MOVE_RIGHT:
+ return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH:
+ return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_BEGINNING_OF_LINE;
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_DOCUMENT:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_LINE:
+ case ui::TextEditCommandAuraLinux::MOVE_TO_END_OF_PARAGRAPH:
+ return select ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
+ IDS_MOVE_TO_END_OF_LINE;
+ case ui::TextEditCommandAuraLinux::MOVE_UP:
+ return IDS_MOVE_UP;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_BACKWARD:
+ if (rtl) {
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ }
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_FORWARD:
+ if (rtl) {
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ }
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_LEFT:
+ return select ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_LEFT;
+ case ui::TextEditCommandAuraLinux::MOVE_WORD_RIGHT:
+ return select ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+ IDS_MOVE_WORD_RIGHT;
+ case ui::TextEditCommandAuraLinux::PASTE:
+ return IDS_APP_PASTE;
+ case ui::TextEditCommandAuraLinux::SELECT_ALL:
+ return IDS_APP_SELECT_ALL;
+ case ui::TextEditCommandAuraLinux::SET_MARK:
+ case ui::TextEditCommandAuraLinux::UNSELECT:
+ case ui::TextEditCommandAuraLinux::INVALID_COMMAND:
+ return kNoCommand;
+ }
+ return kNoCommand;
+}
+#endif
+
+} // namespace
// static
const char Textfield::kViewClassName[] = "Textfield";
@@ -56,153 +251,102 @@ size_t Textfield::GetCaretBlinkMs() {
}
Textfield::Textfield()
- : native_wrapper_(NULL),
+ : model_(new TextfieldModel(this)),
controller_(NULL),
- style_(STYLE_DEFAULT),
- font_list_(GetDefaultFontList()),
read_only_(false),
default_width_in_chars_(0),
- draw_border_(true),
- text_color_(SK_ColorBLACK),
use_default_text_color_(true),
- background_color_(SK_ColorWHITE),
use_default_background_color_(true),
- horizontal_margins_were_set_(false),
- vertical_margins_were_set_(false),
- placeholder_text_color_(kDefaultPlaceholderTextColor),
- text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
- weak_ptr_factory_(this) {
- SetFocusable(true);
-
- if (ViewsDelegate::views_delegate) {
- obscured_reveal_duration_ = ViewsDelegate::views_delegate->
- GetDefaultTextfieldObscuredRevealDuration();
- }
-
- if (NativeViewHost::kRenderNativeControlFocus)
- focus_painter_ = Painter::CreateDashedFocusPainter();
-}
-
-Textfield::Textfield(StyleFlags style)
- : native_wrapper_(NULL),
- controller_(NULL),
- style_(style),
- font_list_(GetDefaultFontList()),
- read_only_(false),
- default_width_in_chars_(0),
- draw_border_(true),
+ use_default_selection_text_color_(true),
+ use_default_selection_background_color_(true),
text_color_(SK_ColorBLACK),
- use_default_text_color_(true),
background_color_(SK_ColorWHITE),
- use_default_background_color_(true),
- horizontal_margins_were_set_(false),
- vertical_margins_were_set_(false),
+ selection_text_color_(SK_ColorWHITE),
+ selection_background_color_(SK_ColorBLUE),
placeholder_text_color_(kDefaultPlaceholderTextColor),
text_input_type_(ui::TEXT_INPUT_TYPE_TEXT),
+ performing_user_action_(false),
+ skip_input_method_cancel_composition_(false),
+ cursor_visible_(false),
+ drop_cursor_visible_(false),
+ initiating_drag_(false),
+ aggregated_clicks_(0),
weak_ptr_factory_(this) {
+ set_context_menu_controller(this);
+ set_drag_controller(this);
+ SetBorder(scoped_ptr<Border>(new FocusableBorder()));
SetFocusable(true);
- if (IsObscured())
- SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
if (ViewsDelegate::views_delegate) {
- obscured_reveal_duration_ = ViewsDelegate::views_delegate->
+ password_reveal_duration_ = ViewsDelegate::views_delegate->
GetDefaultTextfieldObscuredRevealDuration();
}
-
- if (NativeViewHost::kRenderNativeControlFocus)
- focus_painter_ = Painter::CreateDashedFocusPainter();
-}
-
-Textfield::~Textfield() {
-}
-
-void Textfield::SetController(TextfieldController* controller) {
- controller_ = controller;
}
-TextfieldController* Textfield::GetController() const {
- return controller_;
-}
+Textfield::~Textfield() {}
void Textfield::SetReadOnly(bool read_only) {
// Update read-only without changing the focusable state (or active, etc.).
read_only_ = read_only;
- if (native_wrapper_) {
- native_wrapper_->UpdateReadOnly();
- native_wrapper_->UpdateTextColor();
- native_wrapper_->UpdateBackgroundColor();
- }
-}
-
-bool Textfield::IsObscured() const {
- return style_ & STYLE_OBSCURED;
-}
-
-void Textfield::SetObscured(bool obscured) {
- if (obscured) {
- style_ = static_cast<StyleFlags>(style_ | STYLE_OBSCURED);
- SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
- } else {
- style_ = static_cast<StyleFlags>(style_ & ~STYLE_OBSCURED);
- SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
- }
- if (native_wrapper_)
- native_wrapper_->UpdateIsObscured();
-}
-
-ui::TextInputType Textfield::GetTextInputType() const {
- if (read_only() || !enabled())
- return ui::TEXT_INPUT_TYPE_NONE;
- return text_input_type_;
+ if (GetInputMethod())
+ GetInputMethod()->OnTextInputTypeChanged(this);
+ SetColor(GetTextColor());
+ UpdateBackgroundColor();
}
void Textfield::SetTextInputType(ui::TextInputType type) {
+ GetRenderText()->SetObscured(type == ui::TEXT_INPUT_TYPE_PASSWORD);
text_input_type_ = type;
- bool should_be_obscured = type == ui::TEXT_INPUT_TYPE_PASSWORD;
- if (IsObscured() != should_be_obscured)
- SetObscured(should_be_obscured);
+ OnCaretBoundsChanged();
+ if (GetInputMethod())
+ GetInputMethod()->OnTextInputTypeChanged(this);
+ SchedulePaint();
}
-void Textfield::SetText(const string16& text) {
- text_ = text;
- if (native_wrapper_)
- native_wrapper_->UpdateText();
+void Textfield::SetText(const base::string16& new_text) {
+ model_->SetText(new_text);
+ OnCaretBoundsChanged();
+ SchedulePaint();
+ NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
}
-void Textfield::AppendText(const string16& text) {
- text_ += text;
- if (native_wrapper_)
- native_wrapper_->AppendText(text);
+void Textfield::AppendText(const base::string16& new_text) {
+ if (new_text.empty())
+ return;
+ model_->Append(new_text);
+ OnCaretBoundsChanged();
+ SchedulePaint();
}
-void Textfield::InsertOrReplaceText(const string16& text) {
- if (native_wrapper_) {
- native_wrapper_->InsertOrReplaceText(text);
- text_ = native_wrapper_->GetText();
- }
+void Textfield::InsertOrReplaceText(const base::string16& new_text) {
+ if (new_text.empty())
+ return;
+ model_->InsertText(new_text);
+ OnCaretBoundsChanged();
+ SchedulePaint();
}
base::i18n::TextDirection Textfield::GetTextDirection() const {
- return native_wrapper_ ?
- native_wrapper_->GetTextDirection() : base::i18n::UNKNOWN_DIRECTION;
+ return GetRenderText()->GetTextDirection();
}
-void Textfield::SelectAll(bool reversed) {
- if (native_wrapper_)
- native_wrapper_->SelectAll(reversed);
+base::string16 Textfield::GetSelectedText() const {
+ return model_->GetSelectedText();
}
-string16 Textfield::GetSelectedText() const {
- return native_wrapper_ ? native_wrapper_->GetSelectedText() : string16();
+void Textfield::SelectAll(bool reversed) {
+ model_->SelectAll(reversed);
+ UpdateSelectionClipboard();
+ UpdateAfterChange(false, true);
}
-void Textfield::ClearSelection() const {
- if (native_wrapper_)
- native_wrapper_->ClearSelection();
+void Textfield::ClearSelection() {
+ model_->ClearSelection();
+ UpdateAfterChange(false, true);
}
bool Textfield::HasSelection() const {
- return native_wrapper_ && !native_wrapper_->GetSelectedRange().is_empty();
+ return !GetSelectedRange().is_empty();
}
SkColor Textfield::GetTextColor() const {
@@ -217,14 +361,12 @@ SkColor Textfield::GetTextColor() const {
void Textfield::SetTextColor(SkColor color) {
text_color_ = color;
use_default_text_color_ = false;
- if (native_wrapper_)
- native_wrapper_->UpdateTextColor();
+ SetColor(color);
}
void Textfield::UseDefaultTextColor() {
use_default_text_color_ = true;
- if (native_wrapper_)
- native_wrapper_->UpdateTextColor();
+ SetColor(GetTextColor());
}
SkColor Textfield::GetBackgroundColor() const {
@@ -239,173 +381,149 @@ SkColor Textfield::GetBackgroundColor() const {
void Textfield::SetBackgroundColor(SkColor color) {
background_color_ = color;
use_default_background_color_ = false;
- if (native_wrapper_)
- native_wrapper_->UpdateBackgroundColor();
+ UpdateBackgroundColor();
}
void Textfield::UseDefaultBackgroundColor() {
use_default_background_color_ = true;
- if (native_wrapper_)
- native_wrapper_->UpdateBackgroundColor();
+ UpdateBackgroundColor();
}
-bool Textfield::GetCursorEnabled() const {
- return native_wrapper_ && native_wrapper_->GetCursorEnabled();
+SkColor Textfield::GetSelectionTextColor() const {
+ return use_default_selection_text_color_ ?
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_TextfieldSelectionColor) :
+ selection_text_color_;
}
-void Textfield::SetCursorEnabled(bool enabled) {
- if (native_wrapper_)
- native_wrapper_->SetCursorEnabled(enabled);
+void Textfield::SetSelectionTextColor(SkColor color) {
+ selection_text_color_ = color;
+ use_default_selection_text_color_ = false;
+ GetRenderText()->set_selection_color(GetSelectionTextColor());
+ SchedulePaint();
}
-void Textfield::SetFontList(const gfx::FontList& font_list) {
- font_list_ = font_list;
- if (native_wrapper_)
- native_wrapper_->UpdateFont();
- PreferredSizeChanged();
+void Textfield::UseDefaultSelectionTextColor() {
+ use_default_selection_text_color_ = true;
+ GetRenderText()->set_selection_color(GetSelectionTextColor());
+ SchedulePaint();
}
-const gfx::Font& Textfield::GetPrimaryFont() const {
- return font_list_.GetPrimaryFont();
+SkColor Textfield::GetSelectionBackgroundColor() const {
+ return use_default_selection_background_color_ ?
+ GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_TextfieldSelectionBackgroundFocused) :
+ selection_background_color_;
}
-void Textfield::SetFont(const gfx::Font& font) {
- SetFontList(gfx::FontList(font));
+void Textfield::SetSelectionBackgroundColor(SkColor color) {
+ selection_background_color_ = color;
+ use_default_selection_background_color_ = false;
+ GetRenderText()->set_selection_background_focused_color(
+ GetSelectionBackgroundColor());
+ SchedulePaint();
}
-void Textfield::SetHorizontalMargins(int left, int right) {
- if (horizontal_margins_were_set_ &&
- left == margins_.left() && right == margins_.right()) {
- return;
- }
- margins_.Set(margins_.top(), left, margins_.bottom(), right);
- horizontal_margins_were_set_ = true;
- if (native_wrapper_)
- native_wrapper_->UpdateHorizontalMargins();
- PreferredSizeChanged();
+void Textfield::UseDefaultSelectionBackgroundColor() {
+ use_default_selection_background_color_ = true;
+ GetRenderText()->set_selection_background_focused_color(
+ GetSelectionBackgroundColor());
+ SchedulePaint();
}
-void Textfield::SetVerticalMargins(int top, int bottom) {
- if (vertical_margins_were_set_ &&
- top == margins_.top() && bottom == margins_.bottom()) {
- return;
- }
- margins_.Set(top, margins_.left(), bottom, margins_.right());
- vertical_margins_were_set_ = true;
- if (native_wrapper_)
- native_wrapper_->UpdateVerticalMargins();
- PreferredSizeChanged();
+bool Textfield::GetCursorEnabled() const {
+ return GetRenderText()->cursor_enabled();
}
-void Textfield::RemoveBorder() {
- if (!draw_border_)
- return;
+void Textfield::SetCursorEnabled(bool enabled) {
+ GetRenderText()->SetCursorEnabled(enabled);
+}
+
+const gfx::FontList& Textfield::GetFontList() const {
+ return GetRenderText()->font_list();
+}
- draw_border_ = false;
- if (native_wrapper_)
- native_wrapper_->UpdateBorder();
+void Textfield::SetFontList(const gfx::FontList& font_list) {
+ GetRenderText()->SetFontList(font_list);
+ OnCaretBoundsChanged();
+ PreferredSizeChanged();
}
base::string16 Textfield::GetPlaceholderText() const {
return placeholder_text_;
}
-bool Textfield::GetHorizontalMargins(int* left, int* right) {
- if (!horizontal_margins_were_set_)
- return false;
-
- *left = margins_.left();
- *right = margins_.right();
- return true;
+gfx::HorizontalAlignment Textfield::GetHorizontalAlignment() const {
+ return GetRenderText()->horizontal_alignment();
}
-bool Textfield::GetVerticalMargins(int* top, int* bottom) {
- if (!vertical_margins_were_set_)
- return false;
-
- *top = margins_.top();
- *bottom = margins_.bottom();
- return true;
+void Textfield::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
+ GetRenderText()->SetHorizontalAlignment(alignment);
}
-void Textfield::UpdateAllProperties() {
- if (native_wrapper_) {
- native_wrapper_->UpdateText();
- native_wrapper_->UpdateTextColor();
- native_wrapper_->UpdateBackgroundColor();
- native_wrapper_->UpdateReadOnly();
- native_wrapper_->UpdateFont();
- native_wrapper_->UpdateEnabled();
- native_wrapper_->UpdateBorder();
- native_wrapper_->UpdateIsObscured();
- native_wrapper_->UpdateHorizontalMargins();
- native_wrapper_->UpdateVerticalMargins();
- }
-}
-
-void Textfield::SyncText() {
- if (native_wrapper_) {
- string16 new_text = native_wrapper_->GetText();
- if (new_text != text_) {
- text_ = new_text;
- if (controller_)
- controller_->ContentsChanged(this, text_);
- }
- }
+void Textfield::ShowImeIfNeeded() {
+ if (enabled() && !read_only())
+ GetInputMethod()->ShowImeIfNeeded();
}
bool Textfield::IsIMEComposing() const {
- return native_wrapper_ && native_wrapper_->IsIMEComposing();
+ return model_->HasCompositionText();
}
-gfx::Range Textfield::GetSelectedRange() const {
- return native_wrapper_->GetSelectedRange();
+const gfx::Range& Textfield::GetSelectedRange() const {
+ return GetRenderText()->selection();
}
void Textfield::SelectRange(const gfx::Range& range) {
- native_wrapper_->SelectRange(range);
+ model_->SelectRange(range);
+ UpdateAfterChange(false, true);
}
-gfx::SelectionModel Textfield::GetSelectionModel() const {
- return native_wrapper_->GetSelectionModel();
+const gfx::SelectionModel& Textfield::GetSelectionModel() const {
+ return GetRenderText()->selection_model();
}
void Textfield::SelectSelectionModel(const gfx::SelectionModel& sel) {
- native_wrapper_->SelectSelectionModel(sel);
+ model_->SelectSelectionModel(sel);
+ UpdateAfterChange(false, true);
}
size_t Textfield::GetCursorPosition() const {
- return native_wrapper_->GetCursorPosition();
+ return model_->GetCursorPosition();
}
void Textfield::SetColor(SkColor value) {
- return native_wrapper_->SetColor(value);
+ GetRenderText()->SetColor(value);
+ SchedulePaint();
}
void Textfield::ApplyColor(SkColor value, const gfx::Range& range) {
- return native_wrapper_->ApplyColor(value, range);
+ GetRenderText()->ApplyColor(value, range);
+ SchedulePaint();
}
void Textfield::SetStyle(gfx::TextStyle style, bool value) {
- return native_wrapper_->SetStyle(style, value);
+ GetRenderText()->SetStyle(style, value);
+ SchedulePaint();
}
void Textfield::ApplyStyle(gfx::TextStyle style,
bool value,
const gfx::Range& range) {
- return native_wrapper_->ApplyStyle(style, value, range);
+ GetRenderText()->ApplyStyle(style, value, range);
+ SchedulePaint();
}
void Textfield::ClearEditHistory() {
- native_wrapper_->ClearEditHistory();
+ model_->ClearEditHistory();
}
-void Textfield::SetAccessibleName(const string16& name) {
+void Textfield::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
void Textfield::ExecuteCommand(int command_id) {
- native_wrapper_->ExecuteTextCommand(command_id);
+ ExecuteCommand(command_id, ui::EF_NONE);
}
void Textfield::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
@@ -413,101 +531,360 @@ void Textfield::SetFocusPainter(scoped_ptr<Painter> focus_painter) {
}
bool Textfield::HasTextBeingDragged() {
- return native_wrapper_->HasTextBeingDragged();
+ return initiating_drag_;
}
////////////////////////////////////////////////////////////////////////////////
// Textfield, View overrides:
-void Textfield::Layout() {
- if (native_wrapper_) {
- native_wrapper_->GetView()->SetBoundsRect(GetContentsBounds());
- native_wrapper_->GetView()->Layout();
- }
+int Textfield::GetBaseline() const {
+ return GetInsets().top() + GetRenderText()->GetBaseline();
}
-int Textfield::GetBaseline() const {
- gfx::Insets insets = GetTextInsets();
- const int baseline = native_wrapper_ ?
- native_wrapper_->GetTextfieldBaseline() : font_list_.GetBaseline();
- return insets.top() + baseline;
+gfx::Size Textfield::GetPreferredSize() const {
+ const gfx::Insets& insets = GetInsets();
+ return gfx::Size(GetFontList().GetExpectedTextWidth(default_width_in_chars_) +
+ insets.width(), GetFontList().GetHeight() + insets.height());
}
-gfx::Size Textfield::GetPreferredSize() {
- gfx::Insets insets = GetTextInsets();
+const char* Textfield::GetClassName() const {
+ return kViewClassName;
+}
- const int font_height = native_wrapper_ ? native_wrapper_->GetFontHeight() :
- font_list_.GetHeight();
- return gfx::Size(
- GetPrimaryFont().GetExpectedTextWidth(default_width_in_chars_)
- + insets.width(),
- font_height + insets.height());
+gfx::NativeCursor Textfield::GetCursor(const ui::MouseEvent& event) {
+ bool in_selection = GetRenderText()->IsPointInSelection(event.location());
+ bool drag_event = event.type() == ui::ET_MOUSE_DRAGGED;
+ bool text_cursor = !initiating_drag_ && (drag_event || !in_selection);
+ return text_cursor ? GetNativeIBeamCursor() : gfx::kNullCursor;
}
-void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
- SelectAll(false);
+bool Textfield::OnMousePressed(const ui::MouseEvent& event) {
+ TrackMouseClicks(event);
+
+ if (!controller_ || !controller_->HandleMouseEvent(this, event)) {
+ if (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) {
+ RequestFocus();
+ ShowImeIfNeeded();
+ }
+
+ if (event.IsOnlyLeftMouseButton()) {
+ OnBeforeUserAction();
+ initiating_drag_ = false;
+ switch (aggregated_clicks_) {
+ case 0:
+ if (GetRenderText()->IsPointInSelection(event.location()))
+ initiating_drag_ = true;
+ else
+ MoveCursorTo(event.location(), event.IsShiftDown());
+ break;
+ case 1:
+ model_->MoveCursorTo(event.location(), false);
+ model_->SelectWord();
+ UpdateAfterChange(false, true);
+ double_click_word_ = GetRenderText()->selection();
+ break;
+ case 2:
+ SelectAll(false);
+ break;
+ default:
+ NOTREACHED();
+ }
+ OnAfterUserAction();
+ }
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ if (event.IsOnlyMiddleMouseButton()) {
+ if (GetRenderText()->IsPointInSelection(event.location())) {
+ OnBeforeUserAction();
+ ClearSelection();
+ ui::ScopedClipboardWriter(
+ ui::Clipboard::GetForCurrentThread(),
+ ui::CLIPBOARD_TYPE_SELECTION).WriteText(base::string16());
+ OnAfterUserAction();
+ } else if(!read_only()) {
+ PasteSelectionClipboard(event);
+ }
+ }
+#endif
+ }
+
+ return true;
}
-bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
- // Skip any accelerator handling of backspace; textfields handle this key.
- // Also skip processing of [Alt]+<num-pad digit> Unicode alt key codes.
- return e.key_code() == ui::VKEY_BACK || e.IsUnicodeKeyCode();
+bool Textfield::OnMouseDragged(const ui::MouseEvent& event) {
+ last_drag_location_ = event.location();
+
+ // Don't adjust the cursor on a potential drag and drop, or if the mouse
+ // movement from the last mouse click does not exceed the drag threshold.
+ if (initiating_drag_ || !event.IsOnlyLeftMouseButton() ||
+ !ExceededDragThreshold(last_drag_location_ - last_click_location_)) {
+ return true;
+ }
+
+ // A timer is used to continuously scroll while selecting beyond side edges.
+ if ((event.location().x() > 0 && event.location().x() < size().width()) ||
+ GetDragSelectionDelay() == 0) {
+ drag_selection_timer_.Stop();
+ SelectThroughLastDragLocation();
+ } else if (!drag_selection_timer_.IsRunning()) {
+ drag_selection_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(GetDragSelectionDelay()),
+ this, &Textfield::SelectThroughLastDragLocation);
+ }
+
+ return true;
}
-void Textfield::OnPaint(gfx::Canvas* canvas) {
- View::OnPaint(canvas);
- if (NativeViewHost::kRenderNativeControlFocus)
- Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
+void Textfield::OnMouseReleased(const ui::MouseEvent& event) {
+ OnBeforeUserAction();
+ drag_selection_timer_.Stop();
+ // Cancel suspected drag initiations, the user was clicking in the selection.
+ if (initiating_drag_)
+ MoveCursorTo(event.location(), false);
+ initiating_drag_ = false;
+ UpdateSelectionClipboard();
+ OnAfterUserAction();
+}
+
+bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
+ bool handled = controller_ && controller_->HandleKeyEvent(this, event);
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
+ ui::GetTextEditKeyBindingsDelegate();
+ std::vector<ui::TextEditCommandAuraLinux> commands;
+ if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
+ const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+ for (size_t i = 0; i < commands.size(); ++i) {
+ const int command = GetViewsCommand(commands[i], rtl);
+ if (IsCommandIdEnabled(command)) {
+ ExecuteCommand(command);
+ handled = true;
+ }
+ }
+ return handled;
+ }
+#endif
+
+ const int command = GetCommandForKeyEvent(event, HasSelection());
+ if (!handled && IsCommandIdEnabled(command)) {
+ ExecuteCommand(command);
+ handled = true;
+ }
+ return handled;
+}
+
+ui::TextInputClient* Textfield::GetTextInputClient() {
+ return read_only_ ? NULL : this;
+}
+
+void Textfield::OnGestureEvent(ui::GestureEvent* event) {
+ switch (event->type()) {
+ case ui::ET_GESTURE_TAP_DOWN:
+ OnBeforeUserAction();
+ RequestFocus();
+ ShowImeIfNeeded();
+
+ // We don't deselect if the point is in the selection
+ // because TAP_DOWN may turn into a LONG_PRESS.
+ if (!GetRenderText()->IsPointInSelection(event->location()))
+ MoveCursorTo(event->location(), false);
+ OnAfterUserAction();
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ OnBeforeUserAction();
+ MoveCursorTo(event->location(), true);
+ OnAfterUserAction();
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_SCROLL_END:
+ case ui::ET_SCROLL_FLING_START:
+ CreateTouchSelectionControllerAndNotifyIt();
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_TAP:
+ if (event->details().tap_count() == 1) {
+ CreateTouchSelectionControllerAndNotifyIt();
+ } else {
+ DestroyTouchSelection();
+ OnBeforeUserAction();
+ SelectAll(false);
+ OnAfterUserAction();
+ event->SetHandled();
+ }
+#if defined(OS_WIN)
+ if (!read_only())
+ base::win::DisplayVirtualKeyboard();
+#endif
+ break;
+ case ui::ET_GESTURE_LONG_PRESS:
+ // If long press happens outside selection, select word and show context
+ // menu (If touch selection is enabled, context menu is shown by the
+ // |touch_selection_controller_|, hence we mark the event handled.
+ // Otherwise, the regular context menu will be shown by views).
+ // If long press happens in selected text and touch drag drop is enabled,
+ // we will turn off touch selection (if one exists) and let views do drag
+ // drop.
+ if (!GetRenderText()->IsPointInSelection(event->location())) {
+ OnBeforeUserAction();
+ model_->SelectWord();
+ touch_selection_controller_.reset(
+ ui::TouchSelectionController::create(this));
+ UpdateAfterChange(false, true);
+ OnAfterUserAction();
+ if (touch_selection_controller_)
+ event->SetHandled();
+ } else if (switches::IsTouchDragDropEnabled()) {
+ initiating_drag_ = true;
+ DestroyTouchSelection();
+ } else {
+ if (!touch_selection_controller_)
+ CreateTouchSelectionControllerAndNotifyIt();
+ if (touch_selection_controller_)
+ event->SetHandled();
+ }
+ return;
+ case ui::ET_GESTURE_LONG_TAP:
+ if (!touch_selection_controller_)
+ CreateTouchSelectionControllerAndNotifyIt();
+
+ // If touch selection is enabled, the context menu on long tap will be
+ // shown by the |touch_selection_controller_|, hence we mark the event
+ // handled so views does not try to show context menu on it.
+ if (touch_selection_controller_)
+ event->SetHandled();
+ break;
+ default:
+ return;
+ }
}
-bool Textfield::OnKeyPressed(const ui::KeyEvent& e) {
- return native_wrapper_ && native_wrapper_->HandleKeyPressed(e);
+void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
+ SelectAll(false);
}
-bool Textfield::OnKeyReleased(const ui::KeyEvent& e) {
- return native_wrapper_ && native_wrapper_->HandleKeyReleased(e);
+bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Skip any accelerator handling that conflicts with custom keybindings.
+ ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
+ ui::GetTextEditKeyBindingsDelegate();
+ std::vector<ui::TextEditCommandAuraLinux> commands;
+ if (delegate && delegate->MatchEvent(event, &commands)) {
+ const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+ for (size_t i = 0; i < commands.size(); ++i)
+ if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl)))
+ return true;
+ }
+#endif
+
+ // Skip backspace accelerator handling; editable textfields handle this key.
+ // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
+ const bool is_backspace = event.key_code() == ui::VKEY_BACK;
+ return (is_backspace && !read_only()) || event.IsUnicodeKeyCode();
}
-bool Textfield::OnMouseDragged(const ui::MouseEvent& e) {
- if (!e.IsOnlyRightMouseButton())
- return View::OnMouseDragged(e);
+bool Textfield::GetDropFormats(
+ int* formats,
+ std::set<OSExchangeData::CustomFormat>* custom_formats) {
+ if (!enabled() || read_only())
+ return false;
+ // TODO(msw): Can we support URL, FILENAME, etc.?
+ *formats = ui::OSExchangeData::STRING;
+ if (controller_)
+ controller_->AppendDropFormats(formats, custom_formats);
return true;
}
-void Textfield::OnFocus() {
- if (native_wrapper_)
- native_wrapper_->HandleFocus();
+bool Textfield::CanDrop(const OSExchangeData& data) {
+ int formats;
+ std::set<OSExchangeData::CustomFormat> custom_formats;
+ GetDropFormats(&formats, &custom_formats);
+ return enabled() && !read_only() &&
+ data.HasAnyFormat(formats, custom_formats);
+}
+
+int Textfield::OnDragUpdated(const ui::DropTargetEvent& event) {
+ DCHECK(CanDrop(event.data()));
+ gfx::RenderText* render_text = GetRenderText();
+ const gfx::Range& selection = render_text->selection();
+ drop_cursor_position_ = render_text->FindCursorPosition(event.location());
+ bool in_selection = !selection.is_empty() &&
+ selection.Contains(gfx::Range(drop_cursor_position_.caret_pos()));
+ drop_cursor_visible_ = !in_selection;
+ // TODO(msw): Pan over text when the user drags to the visible text edge.
+ OnCaretBoundsChanged();
+ SchedulePaint();
- // Forward the focus to the wrapper if it exists.
- if (!native_wrapper_ || !native_wrapper_->SetFocus()) {
- // If there is no wrapper or the wrapper didn't take focus, call
- // View::Focus to clear the native focus so that we still get
- // keyboard messages.
- View::OnFocus();
+ if (initiating_drag_) {
+ if (in_selection)
+ return ui::DragDropTypes::DRAG_NONE;
+ return event.IsControlDown() ? ui::DragDropTypes::DRAG_COPY :
+ ui::DragDropTypes::DRAG_MOVE;
}
+ return ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE;
+}
- // Border typically draws focus indicator.
+void Textfield::OnDragExited() {
+ drop_cursor_visible_ = false;
SchedulePaint();
}
-void Textfield::OnBlur() {
- if (native_wrapper_)
- native_wrapper_->HandleBlur();
+int Textfield::OnPerformDrop(const ui::DropTargetEvent& event) {
+ DCHECK(CanDrop(event.data()));
+ drop_cursor_visible_ = false;
- // Border typically draws focus indicator.
- SchedulePaint();
+ if (controller_) {
+ int drag_operation = controller_->OnDrop(event.data());
+ if (drag_operation != ui::DragDropTypes::DRAG_NONE)
+ return drag_operation;
+ }
+
+ gfx::RenderText* render_text = GetRenderText();
+ DCHECK(!initiating_drag_ ||
+ !render_text->IsPointInSelection(event.location()));
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+
+ gfx::SelectionModel drop_destination_model =
+ render_text->FindCursorPosition(event.location());
+ base::string16 new_text;
+ event.data().GetString(&new_text);
+
+ // Delete the current selection for a drag and drop within this view.
+ const bool move = initiating_drag_ && !event.IsControlDown() &&
+ event.source_operations() & ui::DragDropTypes::DRAG_MOVE;
+ if (move) {
+ // Adjust the drop destination if it is on or after the current selection.
+ size_t pos = drop_destination_model.caret_pos();
+ pos -= render_text->selection().Intersect(gfx::Range(0, pos)).length();
+ model_->DeleteSelectionAndInsertTextAt(new_text, pos);
+ } else {
+ model_->MoveCursorTo(drop_destination_model);
+ // Drop always inserts text even if the textfield is not in insert mode.
+ model_->InsertText(new_text);
+ }
+ skip_input_method_cancel_composition_ = false;
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+ return move ? ui::DragDropTypes::DRAG_MOVE : ui::DragDropTypes::DRAG_COPY;
+}
+
+void Textfield::OnDragDone() {
+ initiating_drag_ = false;
+ drop_cursor_visible_ = false;
}
-void Textfield::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_TEXT;
+void Textfield::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_TEXT_FIELD;
state->name = accessible_name_;
if (read_only())
- state->state |= ui::AccessibilityTypes::STATE_READONLY;
- if (IsObscured())
- state->state |= ui::AccessibilityTypes::STATE_PROTECTED;
- state->value = text_;
+ state->AddStateFlag(ui::AX_STATE_READ_ONLY);
+ if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
+ state->AddStateFlag(ui::AX_STATE_PROTECTED);
+ state->value = text();
- const gfx::Range range = native_wrapper_->GetSelectedRange();
+ const gfx::Range range = GetSelectedRange();
state->selection_start = range.start();
state->selection_end = range.end();
@@ -518,61 +895,881 @@ void Textfield::GetAccessibleState(ui::AccessibleViewState* state) {
}
}
-ui::TextInputClient* Textfield::GetTextInputClient() {
- return native_wrapper_ ? native_wrapper_->GetTextInputClient() : NULL;
+void Textfield::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ GetRenderText()->SetDisplayRect(GetContentsBounds());
+ OnCaretBoundsChanged();
+}
+
+void Textfield::OnEnabledChanged() {
+ View::OnEnabledChanged();
+ if (GetInputMethod())
+ GetInputMethod()->OnTextInputTypeChanged(this);
+ SchedulePaint();
+}
+
+void Textfield::OnPaint(gfx::Canvas* canvas) {
+ OnPaintBackground(canvas);
+ PaintTextAndCursor(canvas);
+ OnPaintBorder(canvas);
+}
+
+void Textfield::OnFocus() {
+ GetRenderText()->set_focused(true);
+ cursor_visible_ = true;
+ SchedulePaint();
+ GetInputMethod()->OnFocus();
+ OnCaretBoundsChanged();
+
+ const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
+ if (caret_blink_ms != 0) {
+ cursor_repaint_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(caret_blink_ms), this,
+ &Textfield::UpdateCursor);
+ }
+
+ View::OnFocus();
+ SchedulePaint();
+}
+
+void Textfield::OnBlur() {
+ GetRenderText()->set_focused(false);
+ GetInputMethod()->OnBlur();
+ cursor_repaint_timer_.Stop();
+ if (cursor_visible_) {
+ cursor_visible_ = false;
+ RepaintCursor();
+ }
+
+ DestroyTouchSelection();
+
+ // Border typically draws focus indicator.
+ SchedulePaint();
}
gfx::Point Textfield::GetKeyboardContextMenuLocation() {
- return native_wrapper_ ? native_wrapper_->GetContextMenuLocation() :
- View::GetKeyboardContextMenuLocation();
+ return GetCaretBounds().bottom_right();
}
-void Textfield::OnEnabledChanged() {
- View::OnEnabledChanged();
- if (native_wrapper_)
- native_wrapper_->UpdateEnabled();
+void Textfield::OnNativeThemeChanged(const ui::NativeTheme* theme) {
+ gfx::RenderText* render_text = GetRenderText();
+ render_text->SetColor(GetTextColor());
+ UpdateBackgroundColor();
+ render_text->set_cursor_color(GetTextColor());
+ render_text->set_selection_color(GetSelectionTextColor());
+ render_text->set_selection_background_focused_color(
+ GetSelectionBackgroundColor());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, TextfieldModel::Delegate overrides:
+
+void Textfield::OnCompositionTextConfirmedOrCleared() {
+ if (!skip_input_method_cancel_composition_)
+ GetInputMethod()->CancelComposition(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, ContextMenuController overrides:
+
+void Textfield::ShowContextMenuForView(View* source,
+ const gfx::Point& point,
+ ui::MenuSourceType source_type) {
+ UpdateContextMenu();
+ ignore_result(context_menu_runner_->RunMenuAt(
+ GetWidget(),
+ NULL,
+ gfx::Rect(point, gfx::Size()),
+ MENU_ANCHOR_TOPLEFT,
+ source_type,
+ MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, DragController overrides:
+
+void Textfield::WriteDragDataForView(View* sender,
+ const gfx::Point& press_pt,
+ OSExchangeData* data) {
+ const base::string16& selected_text(GetSelectedText());
+ data->SetString(selected_text);
+ Label label(selected_text, GetFontList());
+ label.SetBackgroundColor(GetBackgroundColor());
+ label.set_subpixel_rendering_enabled(false);
+ gfx::Size size(label.GetPreferredSize());
+ gfx::NativeView native_view = GetWidget()->GetNativeView();
+ gfx::Display display = gfx::Screen::GetScreenFor(native_view)->
+ GetDisplayNearestWindow(native_view);
+ size.SetToMin(gfx::Size(display.size().width(), height()));
+ label.SetBoundsRect(gfx::Rect(size));
+ scoped_ptr<gfx::Canvas> canvas(
+ GetCanvasForDragImage(GetWidget(), label.size()));
+ label.SetEnabledColor(GetTextColor());
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Desktop Linux Aura does not yet support transparency in drag images.
+ canvas->DrawColor(GetBackgroundColor());
+#endif
+ label.Paint(canvas.get(), views::CullSet());
+ const gfx::Vector2d kOffset(-15, 0);
+ drag_utils::SetDragImageOnDataObject(*canvas, kOffset, data);
+ if (controller_)
+ controller_->OnWriteDragData(data);
+}
+
+int Textfield::GetDragOperationsForView(View* sender, const gfx::Point& p) {
+ int drag_operations = ui::DragDropTypes::DRAG_COPY;
+ if (!enabled() || text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD ||
+ !GetRenderText()->IsPointInSelection(p)) {
+ drag_operations = ui::DragDropTypes::DRAG_NONE;
+ } else if (sender == this && !read_only()) {
+ drag_operations =
+ ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY;
+ }
+ if (controller_)
+ controller_->OnGetDragOperationsForTextfield(&drag_operations);
+ return drag_operations;
}
-void Textfield::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (details.is_add && !native_wrapper_ && GetWidget()) {
- // The native wrapper's lifetime will be managed by the view hierarchy after
- // we call AddChildView.
- native_wrapper_ = NativeTextfieldWrapper::CreateWrapper(this);
- AddChildViewAt(native_wrapper_->GetView(), 0);
- Layout();
- UpdateAllProperties();
+bool Textfield::CanStartDragForView(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p) {
+ return initiating_drag_ && GetRenderText()->IsPointInSelection(press_pt);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, ui::TouchEditable overrides:
+
+void Textfield::SelectRect(const gfx::Point& start, const gfx::Point& end) {
+ if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
+ return;
+
+ gfx::SelectionModel start_caret = GetRenderText()->FindCursorPosition(start);
+ gfx::SelectionModel end_caret = GetRenderText()->FindCursorPosition(end);
+ gfx::SelectionModel selection(
+ gfx::Range(start_caret.caret_pos(), end_caret.caret_pos()),
+ end_caret.caret_affinity());
+
+ OnBeforeUserAction();
+ SelectSelectionModel(selection);
+ OnAfterUserAction();
+}
+
+void Textfield::MoveCaretTo(const gfx::Point& point) {
+ SelectRect(point, point);
+}
+
+void Textfield::GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) {
+ gfx::RenderText* render_text = GetRenderText();
+ const gfx::SelectionModel& sel = render_text->selection_model();
+ gfx::SelectionModel start_sel =
+ render_text->GetSelectionModelForSelectionStart();
+ *p1 = render_text->GetCursorBounds(start_sel, true);
+ *p2 = render_text->GetCursorBounds(sel, true);
+}
+
+gfx::Rect Textfield::GetBounds() {
+ return GetLocalBounds();
+}
+
+gfx::NativeView Textfield::GetNativeView() const {
+ return GetWidget()->GetNativeView();
+}
+
+void Textfield::ConvertPointToScreen(gfx::Point* point) {
+ View::ConvertPointToScreen(this, point);
+}
+
+void Textfield::ConvertPointFromScreen(gfx::Point* point) {
+ View::ConvertPointFromScreen(this, point);
+}
+
+bool Textfield::DrawsHandles() {
+ return false;
+}
+
+void Textfield::OpenContextMenu(const gfx::Point& anchor) {
+ DestroyTouchSelection();
+ ShowContextMenu(anchor, ui::MENU_SOURCE_TOUCH_EDIT_MENU);
+}
+
+void Textfield::DestroyTouchSelection() {
+ touch_selection_controller_.reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, ui::SimpleMenuModel::Delegate overrides:
+
+bool Textfield::IsCommandIdChecked(int command_id) const {
+ return true;
+}
+
+bool Textfield::IsCommandIdEnabled(int command_id) const {
+ base::string16 result;
+ bool editable = !read_only();
+ bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
+ switch (command_id) {
+ case IDS_APP_UNDO:
+ return editable && model_->CanUndo();
+ case IDS_APP_REDO:
+ return editable && model_->CanRedo();
+ case IDS_APP_CUT:
+ return editable && readable && model_->HasSelection();
+ case IDS_APP_COPY:
+ return readable && model_->HasSelection();
+ case IDS_APP_PASTE:
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ return editable && !result.empty();
+ case IDS_APP_DELETE:
+ return editable && model_->HasSelection();
+ case IDS_APP_SELECT_ALL:
+ return !text().empty();
+ case IDS_DELETE_FORWARD:
+ case IDS_DELETE_BACKWARD:
+ case IDS_DELETE_TO_BEGINNING_OF_LINE:
+ case IDS_DELETE_TO_END_OF_LINE:
+ case IDS_DELETE_WORD_BACKWARD:
+ case IDS_DELETE_WORD_FORWARD:
+ return editable;
+ case IDS_MOVE_LEFT:
+ case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
+ case IDS_MOVE_RIGHT:
+ case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
+ case IDS_MOVE_WORD_LEFT:
+ case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
+ case IDS_MOVE_WORD_RIGHT:
+ case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
+ case IDS_MOVE_TO_BEGINNING_OF_LINE:
+ case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
+ case IDS_MOVE_TO_END_OF_LINE:
+ case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
+ return true;
+ default:
+ return false;
}
}
-const char* Textfield::GetClassName() const {
- return kViewClassName;
+bool Textfield::GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) {
+ return false;
+}
+
+void Textfield::ExecuteCommand(int command_id, int event_flags) {
+ DestroyTouchSelection();
+ if (!IsCommandIdEnabled(command_id))
+ return;
+
+ bool text_changed = false;
+ bool cursor_changed = false;
+ bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+ gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
+ gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
+ gfx::SelectionModel selection_model = GetSelectionModel();
+
+ OnBeforeUserAction();
+ switch (command_id) {
+ case IDS_APP_UNDO:
+ text_changed = cursor_changed = model_->Undo();
+ break;
+ case IDS_APP_REDO:
+ text_changed = cursor_changed = model_->Redo();
+ break;
+ case IDS_APP_CUT:
+ text_changed = cursor_changed = Cut();
+ break;
+ case IDS_APP_COPY:
+ Copy();
+ break;
+ case IDS_APP_PASTE:
+ text_changed = cursor_changed = Paste();
+ break;
+ case IDS_APP_DELETE:
+ text_changed = cursor_changed = model_->Delete();
+ break;
+ case IDS_APP_SELECT_ALL:
+ SelectAll(false);
+ break;
+ case IDS_DELETE_BACKWARD:
+ text_changed = cursor_changed = model_->Backspace();
+ break;
+ case IDS_DELETE_FORWARD:
+ text_changed = cursor_changed = model_->Delete();
+ break;
+ case IDS_DELETE_TO_END_OF_LINE:
+ model_->MoveCursor(gfx::LINE_BREAK, end, true);
+ text_changed = cursor_changed = model_->Delete();
+ break;
+ case IDS_DELETE_TO_BEGINNING_OF_LINE:
+ model_->MoveCursor(gfx::LINE_BREAK, begin, true);
+ text_changed = cursor_changed = model_->Backspace();
+ break;
+ case IDS_DELETE_WORD_BACKWARD:
+ model_->MoveCursor(gfx::WORD_BREAK, begin, true);
+ text_changed = cursor_changed = model_->Backspace();
+ break;
+ case IDS_DELETE_WORD_FORWARD:
+ model_->MoveCursor(gfx::WORD_BREAK, end, true);
+ text_changed = cursor_changed = model_->Delete();
+ break;
+ case IDS_MOVE_LEFT:
+ model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
+ break;
+ case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
+ break;
+ case IDS_MOVE_RIGHT:
+ model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
+ break;
+ case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
+ break;
+ case IDS_MOVE_WORD_LEFT:
+ model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
+ break;
+ case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
+ break;
+ case IDS_MOVE_WORD_RIGHT:
+ model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
+ break;
+ case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
+ break;
+ case IDS_MOVE_TO_BEGINNING_OF_LINE:
+ model_->MoveCursor(gfx::LINE_BREAK, begin, false);
+ break;
+ case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::LINE_BREAK, begin, true);
+ break;
+ case IDS_MOVE_TO_END_OF_LINE:
+ model_->MoveCursor(gfx::LINE_BREAK, end, false);
+ break;
+ case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
+ model_->MoveCursor(gfx::LINE_BREAK, end, true);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ cursor_changed |= GetSelectionModel() != selection_model;
+ if (cursor_changed)
+ UpdateSelectionClipboard();
+ UpdateAfterChange(text_changed, cursor_changed);
+ OnAfterUserAction();
}
////////////////////////////////////////////////////////////////////////////////
-// Textfield, private:
+// Textfield, ui::TextInputClient overrides:
+
+void Textfield::SetCompositionText(const ui::CompositionText& composition) {
+ if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
+ return;
+
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+ model_->SetCompositionText(composition);
+ skip_input_method_cancel_composition_ = false;
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+}
+
+void Textfield::ConfirmCompositionText() {
+ if (!model_->HasCompositionText())
+ return;
+
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+ model_->ConfirmCompositionText();
+ skip_input_method_cancel_composition_ = false;
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+}
+
+void Textfield::ClearCompositionText() {
+ if (!model_->HasCompositionText())
+ return;
+
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+ model_->CancelCompositionText();
+ skip_input_method_cancel_composition_ = false;
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+}
+
+void Textfield::InsertText(const base::string16& new_text) {
+ // TODO(suzhe): Filter invalid characters.
+ if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || new_text.empty())
+ return;
+
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+ if (GetRenderText()->insert_mode())
+ model_->InsertText(new_text);
+ else
+ model_->ReplaceText(new_text);
+ skip_input_method_cancel_composition_ = false;
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+}
+
+void Textfield::InsertChar(base::char16 ch, int flags) {
+ const int kControlModifierMask = ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
+ ui::EF_COMMAND_DOWN | ui::EF_ALTGR_DOWN |
+ ui::EF_MOD3_DOWN;
+
+ // Filter out all control characters, including tab and new line characters,
+ // and all characters with Alt modifier. But allow characters with the AltGr
+ // modifier. On Windows AltGr is represented by Alt+Ctrl, and on Linux it's a
+ // different flag that we don't care about.
+ const bool should_insert_char =
+ ((ch >= 0x20 && ch < 0x7F) || ch > 0x9F) &&
+ (flags & kControlModifierMask) != ui::EF_ALT_DOWN;
+ if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE || !should_insert_char)
+ return;
+
+ OnBeforeUserAction();
+ skip_input_method_cancel_composition_ = true;
+ if (GetRenderText()->insert_mode())
+ model_->InsertChar(ch);
+ else
+ model_->ReplaceChar(ch);
+ skip_input_method_cancel_composition_ = false;
+
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+
+ if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD &&
+ password_reveal_duration_ != base::TimeDelta()) {
+ const size_t change_offset = model_->GetCursorPosition();
+ DCHECK_GT(change_offset, 0u);
+ RevealPasswordChar(change_offset - 1);
+ }
+}
+
+gfx::NativeWindow Textfield::GetAttachedWindow() const {
+ // Imagine the following hierarchy.
+ // [NativeWidget A] - FocusManager
+ // [View]
+ // [NativeWidget B]
+ // [View]
+ // [View X]
+ // An important thing is that [NativeWidget A] owns Win32 input focus even
+ // when [View X] is logically focused by FocusManager. As a result, an Win32
+ // IME may want to interact with the native view of [NativeWidget A] rather
+ // than that of [NativeWidget B]. This is why we need to call
+ // GetTopLevelWidget() here.
+ return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
+}
+
+ui::TextInputType Textfield::GetTextInputType() const {
+ if (read_only() || !enabled())
+ return ui::TEXT_INPUT_TYPE_NONE;
+ return text_input_type_;
+}
+
+ui::TextInputMode Textfield::GetTextInputMode() const {
+ return ui::TEXT_INPUT_MODE_DEFAULT;
+}
+
+bool Textfield::CanComposeInline() const {
+ return true;
+}
+
+gfx::Rect Textfield::GetCaretBounds() const {
+ gfx::Rect rect = GetRenderText()->GetUpdatedCursorBounds();
+ ConvertRectToScreen(this, &rect);
+ return rect;
+}
+
+bool Textfield::GetCompositionCharacterBounds(uint32 index,
+ gfx::Rect* rect) const {
+ DCHECK(rect);
+ if (!HasCompositionText())
+ return false;
+ gfx::RenderText* render_text = GetRenderText();
+ const gfx::Range& composition_range = render_text->GetCompositionRange();
+ DCHECK(!composition_range.is_empty());
+
+ size_t text_index = composition_range.start() + index;
+ if (composition_range.end() <= text_index)
+ return false;
+ if (!render_text->IsValidCursorIndex(text_index)) {
+ text_index = render_text->IndexOfAdjacentGrapheme(
+ text_index, gfx::CURSOR_BACKWARD);
+ }
+ if (text_index < composition_range.start())
+ return false;
+ const gfx::SelectionModel caret(text_index, gfx::CURSOR_BACKWARD);
+ *rect = render_text->GetCursorBounds(caret, false);
+ ConvertRectToScreen(this, rect);
+ return true;
+}
+
+bool Textfield::HasCompositionText() const {
+ return model_->HasCompositionText();
+}
+
+bool Textfield::GetTextRange(gfx::Range* range) const {
+ if (!ImeEditingAllowed())
+ return false;
+
+ model_->GetTextRange(range);
+ return true;
+}
+
+bool Textfield::GetCompositionTextRange(gfx::Range* range) const {
+ if (!ImeEditingAllowed())
+ return false;
+
+ model_->GetCompositionTextRange(range);
+ return true;
+}
-gfx::Insets Textfield::GetTextInsets() const {
- gfx::Insets insets = GetInsets();
- if (draw_border_ && native_wrapper_)
- insets += native_wrapper_->CalculateInsets();
- return insets;
+bool Textfield::GetSelectionRange(gfx::Range* range) const {
+ if (!ImeEditingAllowed())
+ return false;
+ *range = GetRenderText()->selection();
+ return true;
+}
+
+bool Textfield::SetSelectionRange(const gfx::Range& range) {
+ if (!ImeEditingAllowed() || !range.IsValid())
+ return false;
+ OnBeforeUserAction();
+ SelectRange(range);
+ OnAfterUserAction();
+ return true;
+}
+
+bool Textfield::DeleteRange(const gfx::Range& range) {
+ if (!ImeEditingAllowed() || range.is_empty())
+ return false;
+
+ OnBeforeUserAction();
+ model_->SelectRange(range);
+ if (model_->HasSelection()) {
+ model_->DeleteSelection();
+ UpdateAfterChange(true, true);
+ }
+ OnAfterUserAction();
+ return true;
+}
+
+bool Textfield::GetTextFromRange(const gfx::Range& range,
+ base::string16* range_text) const {
+ if (!ImeEditingAllowed() || !range.IsValid())
+ return false;
+
+ gfx::Range text_range;
+ if (!GetTextRange(&text_range) || !text_range.Contains(range))
+ return false;
+
+ *range_text = model_->GetTextFromRange(range);
+ return true;
+}
+
+void Textfield::OnInputMethodChanged() {}
+
+bool Textfield::ChangeTextDirectionAndLayoutAlignment(
+ base::i18n::TextDirection direction) {
+ // Restore text directionality mode when the indicated direction matches the
+ // current forced mode; otherwise, force the mode indicated. This helps users
+ // manage BiDi text layout without getting stuck in forced LTR or RTL modes.
+ const gfx::DirectionalityMode mode = direction == base::i18n::RIGHT_TO_LEFT ?
+ gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
+ if (mode == GetRenderText()->directionality_mode())
+ GetRenderText()->SetDirectionalityMode(gfx::DIRECTIONALITY_FROM_TEXT);
+ else
+ GetRenderText()->SetDirectionalityMode(mode);
+ SchedulePaint();
+ return true;
}
-void Textfield::AccessibilitySetValue(const string16& new_value) {
+void Textfield::ExtendSelectionAndDelete(size_t before, size_t after) {
+ gfx::Range range = GetRenderText()->selection();
+ DCHECK_GE(range.start(), before);
+
+ range.set_start(range.start() - before);
+ range.set_end(range.end() + after);
+ gfx::Range text_range;
+ if (GetTextRange(&text_range) && text_range.Contains(range))
+ DeleteRange(range);
+}
+
+void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
+
+void Textfield::OnCandidateWindowShown() {}
+
+void Textfield::OnCandidateWindowUpdated() {}
+
+void Textfield::OnCandidateWindowHidden() {}
+
+bool Textfield::IsEditingCommandEnabled(int command_id) {
+ return IsCommandIdEnabled(command_id);
+}
+
+void Textfield::ExecuteEditingCommand(int command_id) {
+ ExecuteCommand(command_id);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, protected:
+
+gfx::RenderText* Textfield::GetRenderText() const {
+ return model_->render_text();
+}
+
+base::string16 Textfield::GetSelectionClipboardText() const {
+ base::string16 selection_clipboard_text;
+ ui::Clipboard::GetForCurrentThread()->ReadText(
+ ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
+ return selection_clipboard_text;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Textfield, private:
+
+void Textfield::AccessibilitySetValue(const base::string16& new_value) {
if (!read_only()) {
SetText(new_value);
ClearSelection();
}
}
-////////////////////////////////////////////////////////////////////////////////
-// NativeTextfieldWrapper, public:
+void Textfield::UpdateBackgroundColor() {
+ const SkColor color = GetBackgroundColor();
+ set_background(Background::CreateSolidBackground(color));
+ GetRenderText()->set_background_is_transparent(SkColorGetA(color) != 0xFF);
+ SchedulePaint();
+}
-// static
-NativeTextfieldWrapper* NativeTextfieldWrapper::CreateWrapper(
- Textfield* field) {
- return new NativeTextfieldViews(field);
+void Textfield::UpdateAfterChange(bool text_changed, bool cursor_changed) {
+ if (text_changed) {
+ if (controller_)
+ controller_->ContentsChanged(this, text());
+ NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
+ }
+ if (cursor_changed) {
+ cursor_visible_ = true;
+ RepaintCursor();
+ if (cursor_repaint_timer_.IsRunning())
+ cursor_repaint_timer_.Reset();
+ if (!text_changed) {
+ // TEXT_CHANGED implies SELECTION_CHANGED, so we only need to fire
+ // this if only the selection changed.
+ NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION_CHANGED, true);
+ }
+ }
+ if (text_changed || cursor_changed) {
+ OnCaretBoundsChanged();
+ SchedulePaint();
+ }
+}
+
+void Textfield::UpdateCursor() {
+ const size_t caret_blink_ms = Textfield::GetCaretBlinkMs();
+ cursor_visible_ = !cursor_visible_ || (caret_blink_ms == 0);
+ RepaintCursor();
+}
+
+void Textfield::RepaintCursor() {
+ gfx::Rect r(GetRenderText()->GetUpdatedCursorBounds());
+ r.Inset(-1, -1, -1, -1);
+ SchedulePaintInRect(r);
+}
+
+void Textfield::PaintTextAndCursor(gfx::Canvas* canvas) {
+ TRACE_EVENT0("views", "Textfield::PaintTextAndCursor");
+ canvas->Save();
+
+ // Draw placeholder text if needed.
+ gfx::RenderText* render_text = GetRenderText();
+ if (text().empty() && !GetPlaceholderText().empty()) {
+ canvas->DrawStringRect(GetPlaceholderText(), GetFontList(),
+ placeholder_text_color(), render_text->display_rect());
+ }
+
+ // Draw the text, cursor, and selection.
+ render_text->set_cursor_visible(cursor_visible_ && !drop_cursor_visible_ &&
+ !HasSelection());
+ render_text->Draw(canvas);
+
+ // Draw the detached drop cursor that marks where the text will be dropped.
+ if (drop_cursor_visible_)
+ render_text->DrawCursor(canvas, drop_cursor_position_);
+
+ canvas->Restore();
+}
+
+void Textfield::MoveCursorTo(const gfx::Point& point, bool select) {
+ if (model_->MoveCursorTo(point, select))
+ UpdateAfterChange(false, true);
+}
+
+void Textfield::SelectThroughLastDragLocation() {
+ OnBeforeUserAction();
+ model_->MoveCursorTo(last_drag_location_, true);
+ if (aggregated_clicks_ == 1) {
+ model_->SelectWord();
+ // Expand the selection so the initially selected word remains selected.
+ gfx::Range selection = GetRenderText()->selection();
+ const size_t min = std::min(selection.GetMin(),
+ double_click_word_.GetMin());
+ const size_t max = std::max(selection.GetMax(),
+ double_click_word_.GetMax());
+ const bool reversed = selection.is_reversed();
+ selection.set_start(reversed ? max : min);
+ selection.set_end(reversed ? min : max);
+ model_->SelectRange(selection);
+ }
+ UpdateAfterChange(false, true);
+ OnAfterUserAction();
+}
+
+void Textfield::OnCaretBoundsChanged() {
+ if (GetInputMethod())
+ GetInputMethod()->OnCaretBoundsChanged(this);
+ if (touch_selection_controller_)
+ touch_selection_controller_->SelectionChanged();
+}
+
+void Textfield::OnBeforeUserAction() {
+ DCHECK(!performing_user_action_);
+ performing_user_action_ = true;
+ if (controller_)
+ controller_->OnBeforeUserAction(this);
+}
+
+void Textfield::OnAfterUserAction() {
+ if (controller_)
+ controller_->OnAfterUserAction(this);
+ DCHECK(performing_user_action_);
+ performing_user_action_ = false;
+}
+
+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);
+ return true;
+ }
+ return false;
+}
+
+bool Textfield::Copy() {
+ if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) {
+ if (controller_)
+ controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ return true;
+ }
+ return false;
+}
+
+bool Textfield::Paste() {
+ if (!read_only() && model_->Paste()) {
+ if (controller_)
+ controller_->OnAfterPaste();
+ return true;
+ }
+ return false;
+}
+
+void Textfield::UpdateContextMenu() {
+ if (!context_menu_contents_.get()) {
+ context_menu_contents_.reset(new ui::SimpleMenuModel(this));
+ context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
+ context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
+ context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
+ context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
+ context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
+ context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
+ context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
+ context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
+ IDS_APP_SELECT_ALL);
+ if (controller_)
+ controller_->UpdateContextMenu(context_menu_contents_.get());
+ }
+ context_menu_runner_.reset(new MenuRunner(context_menu_contents_.get()));
+}
+
+void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
+ if (event.IsOnlyLeftMouseButton()) {
+ base::TimeDelta time_delta = event.time_stamp() - last_click_time_;
+ if (time_delta.InMilliseconds() <= GetDoubleClickInterval() &&
+ !ExceededDragThreshold(event.location() - last_click_location_)) {
+ // Upon clicking after a triple click, the count should go back to double
+ // click and alternate between double and triple. This assignment maps
+ // 0 to 1, 1 to 2, 2 to 1.
+ aggregated_clicks_ = (aggregated_clicks_ % 2) + 1;
+ } else {
+ aggregated_clicks_ = 0;
+ }
+ last_click_time_ = event.time_stamp();
+ last_click_location_ = event.location();
+ }
+}
+
+bool Textfield::ImeEditingAllowed() const {
+ // Disallow input method editing of password fields.
+ ui::TextInputType t = GetTextInputType();
+ return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
+}
+
+void Textfield::RevealPasswordChar(int index) {
+ GetRenderText()->SetObscuredRevealIndex(index);
+ SchedulePaint();
+
+ if (index != -1) {
+ password_reveal_timer_.Start(FROM_HERE, password_reveal_duration_,
+ base::Bind(&Textfield::RevealPasswordChar,
+ weak_ptr_factory_.GetWeakPtr(), -1));
+ }
+}
+
+void Textfield::CreateTouchSelectionControllerAndNotifyIt() {
+ if (!touch_selection_controller_) {
+ touch_selection_controller_.reset(
+ ui::TouchSelectionController::create(this));
+ }
+ if (touch_selection_controller_)
+ touch_selection_controller_->SelectionChanged();
+}
+
+void Textfield::UpdateSelectionClipboard() const {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ if (performing_user_action_ && HasSelection()) {
+ ui::ScopedClipboardWriter(
+ ui::Clipboard::GetForCurrentThread(),
+ ui::CLIPBOARD_TYPE_SELECTION).WriteText(GetSelectedText());
+ if (controller_)
+ controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
+ }
+#endif
+}
+
+void Textfield::PasteSelectionClipboard(const ui::MouseEvent& event) {
+ DCHECK(event.IsOnlyMiddleMouseButton());
+ DCHECK(!read_only());
+ base::string16 selection_clipboard_text = GetSelectionClipboardText();
+ if (!selection_clipboard_text.empty()) {
+ OnBeforeUserAction();
+ gfx::Range range = GetSelectionModel().selection();
+ gfx::LogicalCursorDirection affinity = GetSelectionModel().caret_affinity();
+ const gfx::SelectionModel mouse =
+ GetRenderText()->FindCursorPosition(event.location());
+ model_->MoveCursorTo(mouse);
+ model_->InsertText(selection_clipboard_text);
+ // Update the new selection range as needed.
+ if (range.GetMin() >= mouse.caret_pos()) {
+ const size_t length = selection_clipboard_text.length();
+ range = gfx::Range(range.start() + length, range.end() + length);
+ }
+ model_->MoveCursorTo(gfx::SelectionModel(range, affinity));
+ UpdateAfterChange(true, true);
+ OnAfterUserAction();
+ }
}
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield.h b/chromium/ui/views/controls/textfield/textfield.h
index 307e562c20e..e8361774a94 100644
--- a/chromium/ui/views/controls/textfield/textfield.h
+++ b/chromium/ui/views/controls/textfield/textfield.h
@@ -12,103 +12,77 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
+#include "base/timer/timer.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/touch/touch_editing_controller.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/font_list.h"
-#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/range/range.h"
+#include "ui/gfx/selection_model.h"
#include "ui/gfx/text_constants.h"
-#include "ui/views/controls/textfield/native_textfield_wrapper.h"
+#include "ui/views/context_menu_controller.h"
+#include "ui/views/controls/textfield/textfield_model.h"
+#include "ui/views/drag_controller.h"
#include "ui/views/view.h"
-#if !defined(OS_LINUX)
-#include "base/logging.h"
-#endif
-
-namespace gfx {
-class Range;
-class ImageSkia;
-}
-
-namespace ui {
-class TextInputClient;
-} // namespace ui
-
namespace views {
-class ImageView;
+class MenuRunner;
class Painter;
class TextfieldController;
-// This class implements a View that wraps a native text (edit) field.
-class VIEWS_EXPORT Textfield : public View {
+// A views/skia textfield implementation. No platform-specific code is used.
+class VIEWS_EXPORT Textfield : public View,
+ public TextfieldModel::Delegate,
+ public ContextMenuController,
+ public DragController,
+ public ui::TouchEditable,
+ public ui::TextInputClient {
public:
// The textfield's class name.
static const char kViewClassName[];
- enum StyleFlags {
- STYLE_DEFAULT = 0,
- STYLE_OBSCURED = 1 << 0,
- STYLE_LOWERCASE = 1 << 1
- };
-
// Returns the text cursor blink time in milliseconds, or 0 for no blinking.
static size_t GetCaretBlinkMs();
Textfield();
- explicit Textfield(StyleFlags style);
virtual ~Textfield();
- // TextfieldController accessors
- void SetController(TextfieldController* controller);
- TextfieldController* GetController() const;
+ // Set the controller for this textfield.
+ void set_controller(TextfieldController* controller) {
+ controller_ = controller;
+ }
// Gets/Sets whether or not the Textfield is read-only.
bool read_only() const { return read_only_; }
void SetReadOnly(bool read_only);
- // Gets/sets the STYLE_OBSCURED bit, controlling whether characters in this
- // Textfield are displayed as asterisks/bullets.
- bool IsObscured() const;
- void SetObscured(bool obscured);
-
- // Gets/sets the duration to reveal the last typed char when the obscured bit
- // is set. A duration of zero effectively disables the feature. Other values
- // cause the last typed char to be shown for the defined duration. Note this
- // only works with NativeTextfieldViews.
- const base::TimeDelta& obscured_reveal_duration() const {
- return obscured_reveal_duration_;
- }
- void set_obscured_reveal_duration(const base::TimeDelta& duration) {
- obscured_reveal_duration_ = duration;
- }
-
- // Gets/Sets the input type of this textfield.
- ui::TextInputType GetTextInputType() const;
+ // Sets the input type; displays only asterisks for TEXT_INPUT_TYPE_PASSWORD.
void SetTextInputType(ui::TextInputType type);
- // Gets/Sets the text currently displayed in the Textfield.
- const string16& text() const { return text_; }
+ // Gets the text currently displayed in the Textfield.
+ const base::string16& text() const { return model_->text(); }
// Sets the text currently displayed in the Textfield. This doesn't
// change the cursor position if the current cursor is within the
// new text's range, or moves the cursor to the end if the cursor is
// out of the new text's range.
- void SetText(const string16& text);
+ void SetText(const base::string16& new_text);
// Appends the given string to the previously-existing text in the field.
- void AppendText(const string16& text);
+ void AppendText(const base::string16& new_text);
- // Inserts |text| at the current cursor position, replacing any selected text.
- void InsertOrReplaceText(const string16& text);
+ // Inserts |new_text| at the cursor position, replacing any selected text.
+ void InsertOrReplaceText(const base::string16& new_text);
// Returns the text direction.
base::i18n::TextDirection GetTextDirection() const;
// Returns the text that is currently selected.
- string16 GetSelectedText() const;
+ base::string16 GetSelectedText() const;
// Select the entire text range. If |reversed| is true, the range will end at
// the logical beginning of the text; this generally shows the leading portion
@@ -116,56 +90,51 @@ class VIEWS_EXPORT Textfield : public View {
void SelectAll(bool reversed);
// Clears the selection within the edit field and sets the caret to the end.
- void ClearSelection() const;
+ void ClearSelection();
// Checks if there is any selected text.
bool HasSelection() const;
- // Accessor for |style_|.
- StyleFlags style() const { return style_; }
-
- // Gets/Sets the text color to be used when painting the Textfield.
- // Call |UseDefaultTextColor| to restore the default system color.
+ // Gets/sets the text color to be used when painting the Textfield.
+ // Call UseDefaultTextColor() to restore the default system color.
SkColor GetTextColor() const;
void SetTextColor(SkColor color);
void UseDefaultTextColor();
- // Gets/Sets the background color to be used when painting the Textfield.
- // Call |UseDefaultBackgroundColor| to restore the default system color.
+ // Gets/sets the background color to be used when painting the Textfield.
+ // Call UseDefaultBackgroundColor() to restore the default system color.
SkColor GetBackgroundColor() const;
void SetBackgroundColor(SkColor color);
void UseDefaultBackgroundColor();
+ // Gets/sets the selection text color to be used when painting the Textfield.
+ // Call UseDefaultSelectionTextColor() to restore the default system color.
+ SkColor GetSelectionTextColor() const;
+ void SetSelectionTextColor(SkColor color);
+ void UseDefaultSelectionTextColor();
+
+ // Gets/sets the selection background color to be used when painting the
+ // Textfield. Call UseDefaultSelectionBackgroundColor() to restore the default
+ // system color.
+ SkColor GetSelectionBackgroundColor() const;
+ void SetSelectionBackgroundColor(SkColor color);
+ void UseDefaultSelectionBackgroundColor();
+
// Gets/Sets whether or not the cursor is enabled.
bool GetCursorEnabled() const;
void SetCursorEnabled(bool enabled);
// Gets/Sets the fonts used when rendering the text within the Textfield.
- const gfx::FontList& font_list() const { return font_list_; }
+ const gfx::FontList& GetFontList() const;
void SetFontList(const gfx::FontList& font_list);
- const gfx::Font& GetPrimaryFont() const;
- void SetFont(const gfx::Font& font);
-
- // Sets the left and right margin (in pixels) within the text box. On Windows
- // this is accomplished by packing the left and right margin into a single
- // 32 bit number, so the left and right margins are effectively 16 bits.
- void SetHorizontalMargins(int left, int right);
-
- // Sets the top and bottom margins (in pixels) within the textfield.
- // NOTE: in most cases height could be changed instead.
- void SetVerticalMargins(int top, int bottom);
// Sets the default width of the text control. See default_width_in_chars_.
void set_default_width_in_chars(int default_width) {
default_width_in_chars_ = default_width;
}
- // Removes the border from the edit box, giving it a 2D look.
- bool draw_border() const { return draw_border_; }
- void RemoveBorder();
-
// Sets the text to display when empty.
- void set_placeholder_text(const string16& text) {
+ void set_placeholder_text(const base::string16& text) {
placeholder_text_ = text;
}
virtual base::string16 GetPlaceholderText() const;
@@ -175,59 +144,40 @@ class VIEWS_EXPORT Textfield : public View {
placeholder_text_color_ = color;
}
- // Getter for the horizontal margins that were set. Returns false if
- // horizontal margins weren't set.
- bool GetHorizontalMargins(int* left, int* right);
-
- // Getter for the vertical margins that were set. Returns false if vertical
- // margins weren't set.
- bool GetVerticalMargins(int* top, int* bottom);
+ // Get or set the horizontal alignment used for the button from the underlying
+ // RenderText object.
+ gfx::HorizontalAlignment GetHorizontalAlignment() const;
+ void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
- // Updates all properties on the textfield. This is invoked internally.
- // Users of Textfield never need to invoke this directly.
- void UpdateAllProperties();
-
- // Invoked by the edit control when the value changes. This method set
- // the text_ member variable to the value contained in edit control.
- // This is important because the edit control can be replaced if it has
- // been deleted during a window close.
- void SyncText();
+ // Displays a virtual keyboard or alternate input view if enabled.
+ void ShowImeIfNeeded();
// Returns whether or not an IME is composing text.
bool IsIMEComposing() const;
- // Gets the selected range. This is views-implementation only and
- // has to be called after the wrapper is created.
- // TODO(msw): Return a const reference when NativeTextfieldWin is gone.
- gfx::Range GetSelectedRange() const;
+ // Gets the selected logical text range.
+ const gfx::Range& GetSelectedRange() const;
- // Selects the text given by |range|. This is views-implementation only and
- // has to be called after the wrapper is created.
+ // Selects the specified logical text range.
void SelectRange(const gfx::Range& range);
- // Gets the selection model. This is views-implementation only and
- // has to be called after the wrapper is created.
- // TODO(msw): Return a const reference when NativeTextfieldWin is gone.
- gfx::SelectionModel GetSelectionModel() const;
+ // Gets the text selection model.
+ const gfx::SelectionModel& GetSelectionModel() const;
- // Selects the text given by |sel|. This is views-implementation only and
- // has to be called after the wrapper is created.
+ // Sets the specified text selection model.
void SelectSelectionModel(const gfx::SelectionModel& sel);
- // Returns the current cursor position. This is views-implementation
- // only and has to be called after the wrapper is created.
+ // Returns the current cursor position.
size_t GetCursorPosition() const;
// Set the text color over the entire text or a logical character range.
- // Empty and invalid ranges are ignored. This is views-implementation only and
- // has to be called after the wrapper is created.
+ // Empty and invalid ranges are ignored.
void SetColor(SkColor value);
void ApplyColor(SkColor value, const gfx::Range& range);
// Set various text styles over the entire text or a logical character range.
// The respective |style| is applied if |value| is true, or removed if false.
- // Empty and invalid ranges are ignored. This is views-implementation only and
- // has to be called after the wrapper is created.
+ // Empty and invalid ranges are ignored.
void SetStyle(gfx::TextStyle style, bool value);
void ApplyStyle(gfx::TextStyle style, bool value, const gfx::Range& range);
@@ -235,69 +185,201 @@ class VIEWS_EXPORT Textfield : public View {
void ClearEditHistory();
// Set the accessible name of the text field.
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
// Performs the action associated with the specified command id.
void ExecuteCommand(int command_id);
void SetFocusPainter(scoped_ptr<Painter> focus_painter);
- // Provided only for testing:
- gfx::NativeView GetTestingHandle() const {
- return native_wrapper_ ? native_wrapper_->GetTestingHandle() : NULL;
- }
- NativeTextfieldWrapper* GetNativeWrapperForTesting() const {
- return native_wrapper_;
- }
-
// Returns whether there is a drag operation originating from the textfield.
bool HasTextBeingDragged();
- // Overridden from View:
- virtual void Layout() OVERRIDE;
+ // View overrides:
virtual int GetBaseline() const OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual const char* GetClassName() const OVERRIDE;
+ virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
+ virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
+ virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
+ virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
+ virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
+ virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual void AboutToRequestFocusFromTabTraversal(bool reverse) OVERRIDE;
- virtual bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) OVERRIDE;
+ virtual bool SkipDefaultKeyEventProcessing(
+ const ui::KeyEvent& event) OVERRIDE;
+ virtual bool GetDropFormats(
+ int* formats,
+ std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
+ virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE;
+ virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
+ virtual void OnDragExited() OVERRIDE;
+ virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
+ virtual void OnDragDone() OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
+ virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
virtual void OnEnabledChanged() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE;
- virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE;
- virtual bool OnMouseDragged(const ui::MouseEvent& e) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
- virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE;
+ virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
+
+ // TextfieldModel::Delegate overrides:
+ virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE;
+
+ // ContextMenuController overrides:
+ virtual void ShowContextMenuForView(View* source,
+ const gfx::Point& point,
+ ui::MenuSourceType source_type) OVERRIDE;
+
+ // DragController overrides:
+ virtual void WriteDragDataForView(View* sender,
+ const gfx::Point& press_pt,
+ ui::OSExchangeData* data) OVERRIDE;
+ virtual int GetDragOperationsForView(View* sender,
+ const gfx::Point& p) OVERRIDE;
+ virtual bool CanStartDragForView(View* sender,
+ const gfx::Point& press_pt,
+ const gfx::Point& p) OVERRIDE;
+
+ // ui::TouchEditable overrides:
+ virtual void SelectRect(const gfx::Point& start,
+ const gfx::Point& end) OVERRIDE;
+ virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE;
+ virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE;
+ virtual gfx::Rect GetBounds() OVERRIDE;
+ virtual gfx::NativeView GetNativeView() const OVERRIDE;
+ virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE;
+ virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE;
+ virtual bool DrawsHandles() OVERRIDE;
+ virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE;
+ virtual void DestroyTouchSelection() OVERRIDE;
+
+ // ui::SimpleMenuModel::Delegate overrides:
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) OVERRIDE;
+ virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
+
+ // ui::TextInputClient overrides:
+ virtual void SetCompositionText(
+ const ui::CompositionText& composition) OVERRIDE;
+ virtual void ConfirmCompositionText() OVERRIDE;
+ virtual void ClearCompositionText() OVERRIDE;
+ virtual void InsertText(const base::string16& text) OVERRIDE;
+ virtual void InsertChar(base::char16 ch, int flags) OVERRIDE;
+ virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
+ virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
+ virtual bool CanComposeInline() const OVERRIDE;
+ virtual gfx::Rect GetCaretBounds() const OVERRIDE;
+ virtual bool GetCompositionCharacterBounds(uint32 index,
+ gfx::Rect* rect) const OVERRIDE;
+ virtual bool HasCompositionText() const OVERRIDE;
+ virtual bool GetTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE;
+ virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE;
+ virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
+ virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
+ virtual bool GetTextFromRange(const gfx::Range& range,
+ base::string16* text) const OVERRIDE;
+ virtual void OnInputMethodChanged() OVERRIDE;
+ virtual bool ChangeTextDirectionAndLayoutAlignment(
+ base::i18n::TextDirection direction) OVERRIDE;
+ virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
+ virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
+ virtual void OnCandidateWindowShown() OVERRIDE;
+ virtual void OnCandidateWindowUpdated() OVERRIDE;
+ virtual void OnCandidateWindowHidden() OVERRIDE;
+ virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE;
+ virtual void ExecuteEditingCommand(int command_id) OVERRIDE;
protected:
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE;
- virtual const char* GetClassName() const OVERRIDE;
+ // Returns the TextfieldModel's text/cursor/selection rendering model.
+ gfx::RenderText* GetRenderText() const;
+
+ gfx::Point last_click_location() const { return last_click_location_; }
- // The object that actually implements the native text field.
- NativeTextfieldWrapper* native_wrapper_;
+ // Get the text from the selection clipboard.
+ virtual base::string16 GetSelectionClipboardText() const;
private:
- // Returns the insets to the rectangle where text is actually painted.
- gfx::Insets GetTextInsets() const;
+ friend class TextfieldTestApi;
// Handles a request to change the value of this text field from software
// using an accessibility API (typically automation software, screen readers
// don't normally use this). Sets the value and clears the selection.
- void AccessibilitySetValue(const string16& new_value);
+ void AccessibilitySetValue(const base::string16& new_value);
- // This is the current listener for events from this Textfield.
- TextfieldController* controller_;
+ // Updates the painted background color.
+ void UpdateBackgroundColor();
+
+ // Does necessary updates when the text and/or cursor position changes.
+ void UpdateAfterChange(bool text_changed, bool cursor_changed);
+
+ // A callback function to periodically update the cursor state.
+ void UpdateCursor();
+
+ // Repaint the cursor.
+ void RepaintCursor();
+
+ void PaintTextAndCursor(gfx::Canvas* canvas);
+
+ // Helper function to call MoveCursorTo on the TextfieldModel.
+ void MoveCursorTo(const gfx::Point& point, bool select);
+
+ // Helper function to update the selection on a mouse drag.
+ void SelectThroughLastDragLocation();
+
+ // Convenience method to notify the InputMethod and TouchSelectionController.
+ void OnCaretBoundsChanged();
+
+ // Convenience method to call TextfieldController::OnBeforeUserAction();
+ void OnBeforeUserAction();
- // The mask of style options for this Textfield.
- StyleFlags style_;
+ // Convenience method to call TextfieldController::OnAfterUserAction();
+ void OnAfterUserAction();
- // The fonts used to render the text in the Textfield.
- gfx::FontList font_list_;
+ // Calls |model_->Cut()| and notifies TextfieldController on success.
+ bool Cut();
- // The text displayed in the Textfield.
- string16 text_;
+ // Calls |model_->Copy()| and notifies TextfieldController on success.
+ bool Copy();
+
+ // Calls |model_->Paste()| and calls TextfieldController::ContentsChanged()
+ // explicitly if paste succeeded.
+ bool Paste();
+
+ // Utility function to prepare the context menu.
+ void UpdateContextMenu();
+
+ // Tracks the mouse clicks for single/double/triple clicks.
+ void TrackMouseClicks(const ui::MouseEvent& event);
+
+ // Returns true if the current text input type allows access by the IME.
+ bool ImeEditingAllowed() const;
+
+ // Reveals the password character at |index| for a set duration.
+ // If |index| is -1, the existing revealed character will be reset.
+ void RevealPasswordChar(int index);
+
+ void CreateTouchSelectionControllerAndNotifyIt();
+
+ // Updates the selection clipboard to any non-empty text selection.
+ void UpdateSelectionClipboard() const;
+
+ // Pastes the selection clipboard for the specified mouse event.
+ void PasteSelectionClipboard(const ui::MouseEvent& event);
+
+ // The text model.
+ scoped_ptr<TextfieldModel> model_;
+
+ // This is the current listener for events from this Textfield.
+ TextfieldController* controller_;
// True if this Textfield cannot accept input and is read-only.
bool read_only_;
@@ -306,48 +388,72 @@ class VIEWS_EXPORT Textfield : public View {
// This will be reported as the "desired size". Defaults to 0.
int default_width_in_chars_;
- // Whether the border is drawn.
- bool draw_border_;
-
- // Text color. Only used if |use_default_text_color_| is false.
- SkColor text_color_;
+ scoped_ptr<Painter> focus_painter_;
- // Should we use the system text color instead of |text_color_|?
+ // Flags indicating whether various system colors should be used, and if not,
+ // what overriding color values should be used instead.
bool use_default_text_color_;
-
- // Background color. Only used if |use_default_background_color_| is false.
- SkColor background_color_;
-
- // Should we use the system background color instead of |background_color_|?
bool use_default_background_color_;
-
- // Holds inner textfield margins.
- gfx::Insets margins_;
-
- // Holds whether margins were set.
- bool horizontal_margins_were_set_;
- bool vertical_margins_were_set_;
+ bool use_default_selection_text_color_;
+ bool use_default_selection_background_color_;
+ SkColor text_color_;
+ SkColor background_color_;
+ SkColor selection_text_color_;
+ SkColor selection_background_color_;
// Text to display when empty.
- string16 placeholder_text_;
+ base::string16 placeholder_text_;
// Placeholder text color.
SkColor placeholder_text_color_;
// The accessible name of the text field.
- string16 accessible_name_;
+ base::string16 accessible_name_;
// The input type of this text field.
ui::TextInputType text_input_type_;
- // The duration to reveal the last typed char for obscured textfields.
- base::TimeDelta obscured_reveal_duration_;
+ // The duration and timer to reveal the last typed password character.
+ base::TimeDelta password_reveal_duration_;
+ base::OneShotTimer<Textfield> password_reveal_timer_;
+
+ // Tracks whether a user action is being performed; i.e. OnBeforeUserAction()
+ // has been called, but OnAfterUserAction() has not yet been called.
+ bool performing_user_action_;
+
+ // True if InputMethod::CancelComposition() should not be called.
+ bool skip_input_method_cancel_composition_;
+
+ // The text editing cursor repaint timer and visibility.
+ base::RepeatingTimer<Textfield> cursor_repaint_timer_;
+ bool cursor_visible_;
+
+ // The drop cursor is a visual cue for where dragged text will be dropped.
+ bool drop_cursor_visible_;
+ gfx::SelectionModel drop_cursor_position_;
+
+ // Is the user potentially dragging and dropping from this view?
+ bool initiating_drag_;
+
+ // A timer and point used to modify the selection when dragging.
+ base::RepeatingTimer<Textfield> drag_selection_timer_;
+ gfx::Point last_drag_location_;
+
+ // State variables used to track double and triple clicks.
+ size_t aggregated_clicks_;
+ base::TimeDelta last_click_time_;
+ gfx::Point last_click_location_;
+ gfx::Range double_click_word_;
+
+ scoped_ptr<ui::TouchSelectionController> touch_selection_controller_;
+
+ // Context menu related members.
+ scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
+ scoped_ptr<views::MenuRunner> context_menu_runner_;
// Used to bind callback functions to this object.
base::WeakPtrFactory<Textfield> weak_ptr_factory_;
- scoped_ptr<Painter> focus_painter_;
-
DISALLOW_COPY_AND_ASSIGN(Textfield);
};
diff --git a/chromium/ui/views/controls/textfield/textfield_controller.cc b/chromium/ui/views/controls/textfield/textfield_controller.cc
index 8f72be8a1c4..1d90f3c06df 100644
--- a/chromium/ui/views/controls/textfield/textfield_controller.cc
+++ b/chromium/ui/views/controls/textfield/textfield_controller.cc
@@ -23,20 +23,4 @@ int TextfieldController::OnDrop(const ui::OSExchangeData& data) {
return ui::DragDropTypes::DRAG_NONE;
}
-bool TextfieldController::IsCommandIdEnabled(int command_id) const {
- return false;
-}
-
-bool TextfieldController::IsItemForCommandIdDynamic(int command_id) const {
- return false;
-}
-
-string16 TextfieldController::GetLabelForCommandId(int command_id) const {
- return string16();
-}
-
-bool TextfieldController::HandlesCommand(int command_id) const {
- return false;
-}
-
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_controller.h b/chromium/ui/views/controls/textfield/textfield_controller.h
index d72442b41ad..4a01d384f4b 100644
--- a/chromium/ui/views/controls/textfield/textfield_controller.h
+++ b/chromium/ui/views/controls/textfield/textfield_controller.h
@@ -29,7 +29,7 @@ class VIEWS_EXPORT TextfieldController {
// user. It won't be called if the text is changed by calling
// Textfield::SetText() or Textfield::AppendText().
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) {}
+ const base::string16& new_contents) {}
// This method is called to get notified about keystrokes in the edit.
// Returns true if the message was handled and should not be processed
@@ -52,7 +52,7 @@ class VIEWS_EXPORT TextfieldController {
virtual void OnAfterUserAction(Textfield* sender) {}
// Called after performing a Cut or Copy operation.
- virtual void OnAfterCutOrCopy() {}
+ virtual void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) {}
// Called after performing a Paste operation.
virtual void OnAfterPaste() {}
@@ -79,26 +79,6 @@ class VIEWS_EXPORT TextfieldController {
// Gives the controller a chance to modify the context menu contents.
virtual void UpdateContextMenu(ui::SimpleMenuModel* menu_contents) {}
- // Returns true if the |command_id| should be enabled in the context menu.
- virtual bool IsCommandIdEnabled(int command_id) const;
-
- // Returns true if the item label for the |command_id| is dynamic in the
- // context menu.
- virtual bool IsItemForCommandIdDynamic(int command_id) const;
-
- // Returns the label string for the |coomand_id|.
- virtual string16 GetLabelForCommandId(int command_id) const;
-
- // Returns whether the controller handles the specified command. This is used
- // to handle a command the textfield would normally handle. For example, to
- // have the controller handle |IDS_APP_PASTE| override and return true if
- // |command_id| == |IDS_APP_PASTE|.
- // This is only invoked if the command is enabled.
- virtual bool HandlesCommand(int command_id) const;
-
- // Execute context menu command specified by |command_id|.
- virtual void ExecuteCommand(int command_id, int event_flag) {}
-
protected:
virtual ~TextfieldController() {}
};
diff --git a/chromium/ui/views/controls/textfield/textfield_views_model.cc b/chromium/ui/views/controls/textfield/textfield_model.cc
index 222d0860644..db0dc73b1b0 100644
--- a/chromium/ui/views/controls/textfield/textfield_views_model.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model.cc
@@ -1,69 +1,57 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/controls/textfield/textfield_views_model.h"
+#include "ui/views/controls/textfield/textfield_model.h"
#include <algorithm>
-#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
#include "ui/gfx/range/range.h"
-#include "ui/gfx/render_text.h"
-#include "ui/gfx/text_constants.h"
#include "ui/gfx/utf16_indexing.h"
-#include "ui/views/controls/textfield/textfield.h"
namespace views {
namespace internal {
-// An edit object holds enough information/state to undo/redo the
-// change. Two edits are merged when possible, for example, when
-// you type new characters in sequence. |Commit()| can be used to
-// mark an edit as an independent edit and it shouldn't be merged.
-// (For example, when you did undo/redo, or a text is appended via
-// API)
+// Edit holds state information to undo/redo editing changes. Editing operations
+// are merged when possible, like when characters are typed in sequence. Calling
+// Commit() marks an edit as an independent operation that shouldn't be merged.
class Edit {
public:
enum Type {
INSERT_EDIT,
DELETE_EDIT,
- REPLACE_EDIT
+ REPLACE_EDIT,
};
- virtual ~Edit() {
- }
+ virtual ~Edit() {}
// Revert the change made by this edit in |model|.
- void Undo(TextfieldViewsModel* model) {
+ void Undo(TextfieldModel* model) {
model->ModifyText(new_text_start_, new_text_end(),
old_text_, old_text_start_,
old_cursor_pos_);
}
// Apply the change of this edit to the |model|.
- void Redo(TextfieldViewsModel* model) {
+ void Redo(TextfieldModel* model) {
model->ModifyText(old_text_start_, old_text_end(),
new_text_, new_text_start_,
new_cursor_pos_);
}
- // Try to merge the |edit| into this edit. Returns true if merge was
- // successful, or false otherwise. Merged edit will be deleted after
- // redo and should not be reused.
+ // Try to merge the |edit| into this edit and returns true on success. The
+ // merged edit will be deleted after redo and should not be reused.
bool Merge(const Edit* edit) {
// Don't merge if previous edit is DELETE. This happens when a
// user deletes characters then hits return. In this case, the
// delete should be treated as separate edit that can be undone
// and should not be merged with the replace edit.
- if (type_ != DELETE_EDIT && edit->merge_with_previous()) {
+ if (type_ != DELETE_EDIT && edit->force_merge()) {
MergeReplace(edit);
return true;
}
@@ -81,11 +69,11 @@ class Edit {
Edit(Type type,
MergeType merge_type,
size_t old_cursor_pos,
- const string16& old_text,
+ const base::string16& old_text,
size_t old_text_start,
bool delete_backward,
size_t new_cursor_pos,
- const string16& new_text,
+ const base::string16& new_text,
size_t new_text_start)
: type_(type),
merge_type_(merge_type),
@@ -98,8 +86,7 @@ class Edit {
new_text_start_(new_text_start) {
}
- // A template method pattern that provides specific merge
- // implementation for each type of edit.
+ // Each type of edit provides its own specific merge implementation.
virtual bool DoMerge(const Edit* edit) = 0;
Type type() const { return type_; }
@@ -108,9 +95,7 @@ class Edit {
bool mergeable() const { return merge_type_ == MERGEABLE; }
// Should this edit be forcibly merged with the previous edit?
- bool merge_with_previous() const {
- return merge_type_ == MERGE_WITH_PREVIOUS;
- }
+ bool force_merge() const { return merge_type_ == FORCE_MERGE; }
// Returns the end index of the |old_text_|.
size_t old_text_end() const { return old_text_start_ + old_text_.length(); }
@@ -118,14 +103,13 @@ class Edit {
// Returns the end index of the |new_text_|.
size_t new_text_end() const { return new_text_start_ + new_text_.length(); }
- // Merge the replace edit into the current edit. This is a special case to
- // handle an omnibox setting autocomplete string after new character is
- // typed in.
+ // Merge the replace edit into the current edit. This handles the special case
+ // where an omnibox autocomplete string is set after a new character is typed.
void MergeReplace(const Edit* edit) {
CHECK_EQ(REPLACE_EDIT, edit->type_);
CHECK_EQ(0U, edit->old_text_start_);
CHECK_EQ(0U, edit->new_text_start_);
- string16 old_text = edit->old_text_;
+ base::string16 old_text = edit->old_text_;
old_text.erase(new_text_start_, new_text_.length());
old_text.insert(old_text_start_, old_text_);
// SetText() replaces entire text. Set |old_text_| to the entire
@@ -146,7 +130,7 @@ class Edit {
// Old cursor position.
size_t old_cursor_pos_;
// Deleted text by this edit.
- string16 old_text_;
+ base::string16 old_text_;
// The index of |old_text_|.
size_t old_text_start_;
// True if the deletion is made backward.
@@ -154,7 +138,7 @@ class Edit {
// New cursor position.
size_t new_cursor_pos_;
// Added text.
- string16 new_text_;
+ base::string16 new_text_;
// The index of |new_text_|
size_t new_text_start_;
@@ -163,11 +147,11 @@ class Edit {
class InsertEdit : public Edit {
public:
- InsertEdit(bool mergeable, const string16& new_text, size_t at)
+ InsertEdit(bool mergeable, const base::string16& new_text, size_t at)
: Edit(INSERT_EDIT,
mergeable ? MERGEABLE : DO_NOT_MERGE,
at /* old cursor */,
- string16(),
+ base::string16(),
at,
false /* N/A */,
at + new_text.length() /* new cursor */,
@@ -191,12 +175,12 @@ class InsertEdit : public Edit {
class ReplaceEdit : public Edit {
public:
ReplaceEdit(MergeType merge_type,
- const string16& old_text,
+ const base::string16& old_text,
size_t old_cursor_pos,
size_t old_text_start,
bool backward,
size_t new_cursor_pos,
- const string16& new_text,
+ const base::string16& new_text,
size_t new_text_start)
: Edit(REPLACE_EDIT, merge_type,
old_cursor_pos,
@@ -224,7 +208,7 @@ class ReplaceEdit : public Edit {
class DeleteEdit : public Edit {
public:
DeleteEdit(bool mergeable,
- const string16& text,
+ const base::string16& text,
size_t text_start,
bool backward)
: Edit(DELETE_EDIT,
@@ -234,7 +218,7 @@ class DeleteEdit : public Edit {
text_start,
backward,
text_start,
- string16(),
+ base::string16(),
text_start) {
}
@@ -244,16 +228,14 @@ class DeleteEdit : public Edit {
return false;
if (delete_backward_) {
- // backspace can be merged only with backspace at the
- // same position.
+ // backspace can be merged only with backspace at the same position.
if (!edit->delete_backward_ || old_text_start_ != edit->old_text_end())
return false;
old_text_start_ = edit->old_text_start_;
old_text_ = edit->old_text_ + old_text_;
new_cursor_pos_ = edit->new_cursor_pos_;
} else {
- // delete can be merged only with delete at the same
- // position.
+ // delete can be merged only with delete at the same position.
if (edit->delete_backward_ || old_text_start_ != edit->old_text_start_)
return false;
old_text_ += edit->old_text_;
@@ -286,70 +268,61 @@ using internal::InsertEdit;
using internal::ReplaceEdit;
using internal::MergeType;
using internal::DO_NOT_MERGE;
-using internal::MERGE_WITH_PREVIOUS;
+using internal::FORCE_MERGE;
using internal::MERGEABLE;
/////////////////////////////////////////////////////////////////
-// TextfieldViewsModel: public
+// TextfieldModel: public
-TextfieldViewsModel::Delegate::~Delegate() {
-}
+TextfieldModel::Delegate::~Delegate() {}
-TextfieldViewsModel::TextfieldViewsModel(Delegate* delegate)
+TextfieldModel::TextfieldModel(Delegate* delegate)
: delegate_(delegate),
render_text_(gfx::RenderText::CreateInstance()),
current_edit_(edit_history_.end()) {
}
-TextfieldViewsModel::~TextfieldViewsModel() {
+TextfieldModel::~TextfieldModel() {
ClearEditHistory();
ClearComposition();
}
-const string16& TextfieldViewsModel::GetText() const {
- return render_text_->text();
-}
-
-bool TextfieldViewsModel::SetText(const string16& text) {
+bool TextfieldModel::SetText(const base::string16& new_text) {
bool changed = false;
if (HasCompositionText()) {
ConfirmCompositionText();
changed = true;
}
- if (GetText() != text) {
+ if (text() != new_text) {
if (changed) // No need to remember composition.
Undo();
size_t old_cursor = GetCursorPosition();
// SetText moves the cursor to the end.
- size_t new_cursor = text.length();
+ size_t new_cursor = new_text.length();
SelectAll(false);
// If there is a composition text, don't merge with previous edit.
// Otherwise, force merge the edits.
- ExecuteAndRecordReplace(
- changed ? DO_NOT_MERGE : MERGE_WITH_PREVIOUS,
- old_cursor,
- new_cursor,
- text,
- 0U);
+ ExecuteAndRecordReplace(changed ? DO_NOT_MERGE : FORCE_MERGE,
+ old_cursor, new_cursor, new_text, 0U);
render_text_->SetCursorPosition(new_cursor);
}
ClearSelection();
return changed;
}
-void TextfieldViewsModel::Append(const string16& text) {
+void TextfieldModel::Append(const base::string16& new_text) {
if (HasCompositionText())
ConfirmCompositionText();
size_t save = GetCursorPosition();
MoveCursor(gfx::LINE_BREAK,
render_text_->GetVisualDirectionOfLogicalEnd(),
false);
- InsertText(text);
+ InsertText(new_text);
render_text_->SetCursorPosition(save);
ClearSelection();
}
-bool TextfieldViewsModel::Delete() {
+bool TextfieldModel::Delete() {
if (HasCompositionText()) {
// No undo/redo for composition text.
CancelCompositionText();
@@ -359,7 +332,7 @@ bool TextfieldViewsModel::Delete() {
DeleteSelection();
return true;
}
- if (GetText().length() > GetCursorPosition()) {
+ if (text().length() > GetCursorPosition()) {
size_t cursor_position = GetCursorPosition();
size_t next_grapheme_index = render_text_->IndexOfAdjacentGrapheme(
cursor_position, gfx::CURSOR_FORWARD);
@@ -370,7 +343,7 @@ bool TextfieldViewsModel::Delete() {
return false;
}
-bool TextfieldViewsModel::Backspace() {
+bool TextfieldModel::Backspace() {
if (HasCompositionText()) {
// No undo/redo for composition text.
CancelCompositionText();
@@ -383,103 +356,104 @@ bool TextfieldViewsModel::Backspace() {
size_t cursor_position = GetCursorPosition();
if (cursor_position > 0) {
// Delete one code point, which may be two UTF-16 words.
- size_t previous_char =
- gfx::UTF16OffsetToIndex(GetText(), cursor_position, -1);
+ size_t previous_char = gfx::UTF16OffsetToIndex(text(), cursor_position, -1);
ExecuteAndRecordDelete(gfx::Range(cursor_position, previous_char), true);
return true;
}
return false;
}
-size_t TextfieldViewsModel::GetCursorPosition() const {
+size_t TextfieldModel::GetCursorPosition() const {
return render_text_->cursor_position();
}
-void TextfieldViewsModel::MoveCursor(gfx::BreakType break_type,
- gfx::VisualCursorDirection direction,
- bool select) {
+void TextfieldModel::MoveCursor(gfx::BreakType break_type,
+ gfx::VisualCursorDirection direction,
+ bool select) {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->MoveCursor(break_type, direction, select);
}
-bool TextfieldViewsModel::MoveCursorTo(const gfx::SelectionModel& model) {
+bool TextfieldModel::MoveCursorTo(const gfx::SelectionModel& cursor) {
if (HasCompositionText()) {
ConfirmCompositionText();
// ConfirmCompositionText() updates cursor position. Need to reflect it in
// the SelectionModel parameter of MoveCursorTo().
- gfx::Range range(render_text_->selection().start(), model.caret_pos());
+ gfx::Range range(render_text_->selection().start(), cursor.caret_pos());
if (!range.is_empty())
return render_text_->SelectRange(range);
return render_text_->MoveCursorTo(
- gfx::SelectionModel(model.caret_pos(), model.caret_affinity()));
+ gfx::SelectionModel(cursor.caret_pos(), cursor.caret_affinity()));
}
- return render_text_->MoveCursorTo(model);
+ return render_text_->MoveCursorTo(cursor);
}
-bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) {
+bool TextfieldModel::MoveCursorTo(const gfx::Point& point, bool select) {
if (HasCompositionText())
ConfirmCompositionText();
- return render_text_->MoveCursorTo(point, select);
+ gfx::SelectionModel cursor = render_text_->FindCursorPosition(point);
+ if (select)
+ cursor.set_selection_start(render_text_->selection().start());
+ return render_text_->MoveCursorTo(cursor);
}
-string16 TextfieldViewsModel::GetSelectedText() const {
- return GetText().substr(render_text_->selection().GetMin(),
- render_text_->selection().length());
+base::string16 TextfieldModel::GetSelectedText() const {
+ return text().substr(render_text_->selection().GetMin(),
+ render_text_->selection().length());
}
-void TextfieldViewsModel::SelectRange(const gfx::Range& range) {
+void TextfieldModel::SelectRange(const gfx::Range& range) {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->SelectRange(range);
}
-void TextfieldViewsModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
+void TextfieldModel::SelectSelectionModel(const gfx::SelectionModel& sel) {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->MoveCursorTo(sel);
}
-void TextfieldViewsModel::SelectAll(bool reversed) {
+void TextfieldModel::SelectAll(bool reversed) {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->SelectAll(reversed);
}
-void TextfieldViewsModel::SelectWord() {
+void TextfieldModel::SelectWord() {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->SelectWord();
}
-void TextfieldViewsModel::ClearSelection() {
+void TextfieldModel::ClearSelection() {
if (HasCompositionText())
ConfirmCompositionText();
render_text_->ClearSelection();
}
-bool TextfieldViewsModel::CanUndo() {
+bool TextfieldModel::CanUndo() {
return edit_history_.size() && current_edit_ != edit_history_.end();
}
-bool TextfieldViewsModel::CanRedo() {
+bool TextfieldModel::CanRedo() {
if (!edit_history_.size())
return false;
- // There is no redo iff the current edit is the last element
- // in the history.
+ // There is no redo iff the current edit is the last element in the history.
EditHistory::iterator iter = current_edit_;
return iter == edit_history_.end() || // at the top.
++iter != edit_history_.end();
}
-bool TextfieldViewsModel::Undo() {
+bool TextfieldModel::Undo() {
if (!CanUndo())
return false;
DCHECK(!HasCompositionText());
- if (HasCompositionText()) // safe guard for release build.
+ if (HasCompositionText())
CancelCompositionText();
- string16 old = GetText();
+ base::string16 old = text();
size_t old_cursor = GetCursorPosition();
(*current_edit_)->Commit();
(*current_edit_)->Undo(this);
@@ -488,27 +462,27 @@ bool TextfieldViewsModel::Undo() {
current_edit_ = edit_history_.end();
else
current_edit_--;
- return old != GetText() || old_cursor != GetCursorPosition();
+ return old != text() || old_cursor != GetCursorPosition();
}
-bool TextfieldViewsModel::Redo() {
+bool TextfieldModel::Redo() {
if (!CanRedo())
return false;
DCHECK(!HasCompositionText());
- if (HasCompositionText()) // safe guard for release build.
+ if (HasCompositionText())
CancelCompositionText();
if (current_edit_ == edit_history_.end())
current_edit_ = edit_history_.begin();
else
current_edit_ ++;
- string16 old = GetText();
+ base::string16 old = text();
size_t old_cursor = GetCursorPosition();
(*current_edit_)->Redo(this);
- return old != GetText() || old_cursor != GetCursorPosition();
+ return old != text() || old_cursor != GetCursorPosition();
}
-bool TextfieldViewsModel::Cut() {
+bool TextfieldModel::Cut() {
if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
ui::ScopedClipboardWriter(
ui::Clipboard::GetForCurrentThread(),
@@ -526,7 +500,7 @@ bool TextfieldViewsModel::Cut() {
return false;
}
-bool TextfieldViewsModel::Copy() {
+bool TextfieldModel::Copy() {
if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
ui::ScopedClipboardWriter(
ui::Clipboard::GetForCurrentThread(),
@@ -536,49 +510,50 @@ bool TextfieldViewsModel::Copy() {
return false;
}
-bool TextfieldViewsModel::Paste() {
- string16 result;
+bool TextfieldModel::Paste() {
+ base::string16 result;
ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE,
&result);
- if (!result.empty()) {
- InsertTextInternal(result, false);
- return true;
- }
- return false;
+ if (result.empty())
+ return false;
+
+ InsertTextInternal(result, false);
+ return true;
}
-bool TextfieldViewsModel::HasSelection() const {
+bool TextfieldModel::HasSelection() const {
return !render_text_->selection().is_empty();
}
-void TextfieldViewsModel::DeleteSelection() {
+void TextfieldModel::DeleteSelection() {
DCHECK(!HasCompositionText());
DCHECK(HasSelection());
ExecuteAndRecordDelete(render_text_->selection(), false);
}
-void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
- const string16& text, size_t position) {
+void TextfieldModel::DeleteSelectionAndInsertTextAt(
+ const base::string16& new_text,
+ size_t position) {
if (HasCompositionText())
CancelCompositionText();
ExecuteAndRecordReplace(DO_NOT_MERGE,
GetCursorPosition(),
- position + text.length(),
- text,
+ position + new_text.length(),
+ new_text,
position);
}
-string16 TextfieldViewsModel::GetTextFromRange(const gfx::Range& range) const {
- if (range.IsValid() && range.GetMin() < GetText().length())
- return GetText().substr(range.GetMin(), range.length());
- return string16();
+base::string16 TextfieldModel::GetTextFromRange(const gfx::Range& range) const {
+ if (range.IsValid() && range.GetMin() < text().length())
+ return text().substr(range.GetMin(), range.length());
+ return base::string16();
}
-void TextfieldViewsModel::GetTextRange(gfx::Range* range) const {
- *range = gfx::Range(0, GetText().length());
+void TextfieldModel::GetTextRange(gfx::Range* range) const {
+ *range = gfx::Range(0, text().length());
}
-void TextfieldViewsModel::SetCompositionText(
+void TextfieldModel::SetCompositionText(
const ui::CompositionText& composition) {
if (HasCompositionText())
CancelCompositionText();
@@ -589,7 +564,7 @@ void TextfieldViewsModel::SetCompositionText(
return;
size_t cursor = GetCursorPosition();
- string16 new_text = GetText();
+ base::string16 new_text = text();
render_text_->SetText(new_text.insert(cursor, composition.text));
gfx::Range range(cursor, cursor + composition.text.length());
render_text_->SetCompositionRange(range);
@@ -601,8 +576,7 @@ void TextfieldViewsModel::SetCompositionText(
// Because the target clause is more important than the actual selection
// range (or caret position) in the composition here we use a selection-like
// marker instead to show this range.
- // TODO(yukawa, msw): Support thick underline in RenderText and remove
- // this workaround.
+ // TODO(yukawa, msw): Support thick underlines and remove this workaround.
render_text_->SelectRange(gfx::Range(
cursor + emphasized_range.GetMin(),
cursor + emphasized_range.GetMax()));
@@ -615,67 +589,72 @@ void TextfieldViewsModel::SetCompositionText(
}
}
-void TextfieldViewsModel::ConfirmCompositionText() {
+void TextfieldModel::ConfirmCompositionText() {
DCHECK(HasCompositionText());
gfx::Range range = render_text_->GetCompositionRange();
- string16 text = GetText().substr(range.start(), range.length());
+ base::string16 composition = text().substr(range.start(), range.length());
// TODO(oshima): current behavior on ChromeOS is a bit weird and not
// sure exactly how this should work. Find out and fix if necessary.
- AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
+ AddOrMergeEditHistory(new InsertEdit(false, composition, range.start()));
render_text_->SetCursorPosition(range.end());
ClearComposition();
if (delegate_)
delegate_->OnCompositionTextConfirmedOrCleared();
}
-void TextfieldViewsModel::CancelCompositionText() {
+void TextfieldModel::CancelCompositionText() {
DCHECK(HasCompositionText());
gfx::Range range = render_text_->GetCompositionRange();
ClearComposition();
- string16 new_text = GetText();
+ base::string16 new_text = text();
render_text_->SetText(new_text.erase(range.start(), range.length()));
render_text_->SetCursorPosition(range.start());
if (delegate_)
delegate_->OnCompositionTextConfirmedOrCleared();
}
-void TextfieldViewsModel::ClearComposition() {
+void TextfieldModel::ClearComposition() {
render_text_->SetCompositionRange(gfx::Range::InvalidRange());
}
-void TextfieldViewsModel::GetCompositionTextRange(gfx::Range* range) const {
+void TextfieldModel::GetCompositionTextRange(gfx::Range* range) const {
*range = gfx::Range(render_text_->GetCompositionRange());
}
-bool TextfieldViewsModel::HasCompositionText() const {
+bool TextfieldModel::HasCompositionText() const {
return !render_text_->GetCompositionRange().is_empty();
}
+void TextfieldModel::ClearEditHistory() {
+ STLDeleteElements(&edit_history_);
+ current_edit_ = edit_history_.end();
+}
+
/////////////////////////////////////////////////////////////////
-// TextfieldViewsModel: private
+// TextfieldModel: private
-void TextfieldViewsModel::InsertTextInternal(const string16& text,
- bool mergeable) {
+void TextfieldModel::InsertTextInternal(const base::string16& new_text,
+ bool mergeable) {
if (HasCompositionText()) {
CancelCompositionText();
- ExecuteAndRecordInsert(text, mergeable);
+ ExecuteAndRecordInsert(new_text, mergeable);
} else if (HasSelection()) {
ExecuteAndRecordReplaceSelection(mergeable ? MERGEABLE : DO_NOT_MERGE,
- text);
+ new_text);
} else {
- ExecuteAndRecordInsert(text, mergeable);
+ ExecuteAndRecordInsert(new_text, mergeable);
}
}
-void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
- bool mergeable) {
+void TextfieldModel::ReplaceTextInternal(const base::string16& new_text,
+ bool mergeable) {
if (HasCompositionText()) {
CancelCompositionText();
} else if (!HasSelection()) {
size_t cursor = GetCursorPosition();
const gfx::SelectionModel& model = render_text_->selection_model();
// When there is no selection, the default is to replace the next grapheme
- // with |text|. So, need to find the index of next grapheme first.
+ // with |new_text|. So, need to find the index of next grapheme first.
size_t next =
render_text_->IndexOfAdjacentGrapheme(cursor, gfx::CURSOR_FORWARD);
if (next == model.caret_pos())
@@ -684,15 +663,10 @@ void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
render_text_->SelectRange(gfx::Range(next, model.caret_pos()));
}
// Edit history is recorded in InsertText.
- InsertTextInternal(text, mergeable);
-}
-
-void TextfieldViewsModel::ClearEditHistory() {
- STLDeleteElements(&edit_history_);
- current_edit_ = edit_history_.end();
+ InsertTextInternal(new_text, mergeable);
}
-void TextfieldViewsModel::ClearRedoHistory() {
+void TextfieldModel::ClearRedoHistory() {
if (edit_history_.begin() == edit_history_.end())
return;
if (current_edit_ == edit_history_.end()) {
@@ -705,20 +679,20 @@ void TextfieldViewsModel::ClearRedoHistory() {
edit_history_.erase(delete_start, edit_history_.end());
}
-void TextfieldViewsModel::ExecuteAndRecordDelete(gfx::Range range,
- bool mergeable) {
+void TextfieldModel::ExecuteAndRecordDelete(gfx::Range range, bool mergeable) {
size_t old_text_start = range.GetMin();
- const string16 text = GetText().substr(old_text_start, range.length());
+ const base::string16 old_text = text().substr(old_text_start, range.length());
bool backward = range.is_reversed();
- Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
+ Edit* edit = new DeleteEdit(mergeable, old_text, old_text_start, backward);
bool delete_edit = AddOrMergeEditHistory(edit);
edit->Redo(this);
if (delete_edit)
delete edit;
}
-void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
- MergeType merge_type, const string16& new_text) {
+void TextfieldModel::ExecuteAndRecordReplaceSelection(
+ MergeType merge_type,
+ const base::string16& new_text) {
size_t new_text_start = render_text_->selection().GetMin();
size_t new_cursor_pos = new_text_start + new_text.length();
ExecuteAndRecordReplace(merge_type,
@@ -728,11 +702,11 @@ void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
new_text_start);
}
-void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
- size_t old_cursor_pos,
- size_t new_cursor_pos,
- const string16& new_text,
- size_t new_text_start) {
+void TextfieldModel::ExecuteAndRecordReplace(MergeType merge_type,
+ size_t old_cursor_pos,
+ size_t new_cursor_pos,
+ const base::string16& new_text,
+ size_t new_text_start) {
size_t old_text_start = render_text_->selection().GetMin();
bool backward = render_text_->selection().is_reversed();
Edit* edit = new ReplaceEdit(merge_type,
@@ -749,28 +723,27 @@ void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
delete edit;
}
-void TextfieldViewsModel::ExecuteAndRecordInsert(const string16& text,
- bool mergeable) {
- Edit* edit = new InsertEdit(mergeable, text, GetCursorPosition());
+void TextfieldModel::ExecuteAndRecordInsert(const base::string16& new_text,
+ bool mergeable) {
+ Edit* edit = new InsertEdit(mergeable, new_text, GetCursorPosition());
bool delete_edit = AddOrMergeEditHistory(edit);
edit->Redo(this);
if (delete_edit)
delete edit;
}
-bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) {
+bool TextfieldModel::AddOrMergeEditHistory(Edit* edit) {
ClearRedoHistory();
if (current_edit_ != edit_history_.end() && (*current_edit_)->Merge(edit)) {
- // If a current edit exists and has been merged with a new edit,
- // don't add to the history, and return true to delete |edit| after
- // redo.
+ // If a current edit exists and has been merged with a new edit, don't add
+ // to the history, and return true to delete |edit| after redo.
return true;
}
edit_history_.push_back(edit);
if (current_edit_ == edit_history_.end()) {
- // If there is no redoable edit, this is the 1st edit because
- // RedoHistory has been already deleted.
+ // If there is no redoable edit, this is the 1st edit because RedoHistory
+ // has been already deleted.
DCHECK_EQ(1u, edit_history_.size());
current_edit_ = edit_history_.begin();
} else {
@@ -779,21 +752,20 @@ bool TextfieldViewsModel::AddOrMergeEditHistory(Edit* edit) {
return false;
}
-void TextfieldViewsModel::ModifyText(size_t delete_from,
- size_t delete_to,
- const string16& new_text,
- size_t new_text_insert_at,
- size_t new_cursor_pos) {
+void TextfieldModel::ModifyText(size_t delete_from,
+ size_t delete_to,
+ const base::string16& new_text,
+ size_t new_text_insert_at,
+ size_t new_cursor_pos) {
DCHECK_LE(delete_from, delete_to);
- string16 text = GetText();
+ base::string16 old_text = text();
ClearComposition();
if (delete_from != delete_to)
- render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
+ render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from));
if (!new_text.empty())
- render_text_->SetText(text.insert(new_text_insert_at, new_text));
+ render_text_->SetText(old_text.insert(new_text_insert_at, new_text));
render_text_->SetCursorPosition(new_cursor_pos);
- // TODO(oshima): mac selects the text that is just undone (but gtk doesn't).
- // This looks fine feature and we may want to do the same.
+ // TODO(oshima): Select text that was just undone, like Mac (but not GTK).
}
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_views_model.h b/chromium/ui/views/controls/textfield/textfield_model.h
index 1af734054a9..6ae3398ee46 100644
--- a/chromium/ui/views/controls/textfield/textfield_views_model.h
+++ b/chromium/ui/views/controls/textfield/textfield_model.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_
-#define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_
+#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
+#define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
#include <list>
#include <vector>
@@ -11,44 +11,34 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
-#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ime/composition_text.h"
-#include "ui/gfx/rect.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/views_export.h"
-namespace gfx {
-class Range;
-class RenderText;
-} // namespace gfx
-
namespace views {
namespace internal {
// Internal Edit class that keeps track of edits for undo/redo.
class Edit;
-// C++ doesn't allow forward decl enum, so let's define here.
+// The types of merge behavior implemented by Edit operations.
enum MergeType {
- // The edit should not be merged with next edit. It still may
- // be merged with an edit with MERGE_WITH_PREVIOUS.
+ // The edit should not usually be merged with next edit.
DO_NOT_MERGE,
- // The edit can be merged with next edit when possible.
+ // The edit should be merged with next edit when possible.
MERGEABLE,
- // Does the edit have to be merged with previous edit?
- // This forces the merge even if the previous edit is marked
- // as DO_NOT_MERGE.
- MERGE_WITH_PREVIOUS,
+ // The edit should be merged with the prior edit, even if marked DO_NOT_MERGE.
+ FORCE_MERGE,
};
} // namespace internal
-// A model that represents a text content for TextfieldViews.
+// A model that represents text content for a views::Textfield.
// It supports editing, selection and cursor manipulation.
-class VIEWS_EXPORT TextfieldViewsModel {
+class VIEWS_EXPORT TextfieldModel {
public:
- // Delegate interface implemented by the textfield view class to provided
+ // Delegate interface implemented by the textfield view class to provide
// additional functionalities required by the model.
class VIEWS_EXPORT Delegate {
public:
@@ -59,47 +49,46 @@ class VIEWS_EXPORT TextfieldViewsModel {
virtual ~Delegate();
};
- explicit TextfieldViewsModel(Delegate* delegate);
- virtual ~TextfieldViewsModel();
+ explicit TextfieldModel(Delegate* delegate);
+ virtual ~TextfieldModel();
// Edit related methods.
- const string16& GetText() const;
- // Sets the text. Returns true if the text has been modified. The
- // current composition text will be confirmed first. Setting
- // the same text will not add edit history because it's not user
- // visible change nor user-initiated change. This allow a client
- // code to set the same text multiple times without worrying about
- // messing edit history.
- bool SetText(const string16& text);
+ const base::string16& text() const { return render_text_->text(); }
+ // Sets the text. Returns true if the text has been modified. The current
+ // composition text will be confirmed first. Setting the same text will not
+ // add edit history because it's not user visible change nor user-initiated
+ // change. This allow a client code to set the same text multiple times
+ // without worrying about messing edit history.
+ bool SetText(const base::string16& new_text);
gfx::RenderText* render_text() { return render_text_.get(); }
- // Inserts given |text| at the current cursor position.
+ // Inserts given |new_text| at the current cursor position.
// The current composition text will be cleared.
- void InsertText(const string16& text) {
- InsertTextInternal(text, false);
+ void InsertText(const base::string16& new_text) {
+ InsertTextInternal(new_text, false);
}
// Inserts a character at the current cursor position.
- void InsertChar(char16 c) {
- InsertTextInternal(string16(&c, 1), true);
+ void InsertChar(base::char16 c) {
+ InsertTextInternal(base::string16(&c, 1), true);
}
// Replaces characters at the current position with characters in given text.
// The current composition text will be cleared.
- void ReplaceText(const string16& text) {
- ReplaceTextInternal(text, false);
+ void ReplaceText(const base::string16& new_text) {
+ ReplaceTextInternal(new_text, false);
}
// Replaces the char at the current position with given character.
- void ReplaceChar(char16 c) {
- ReplaceTextInternal(string16(&c, 1), true);
+ void ReplaceChar(base::char16 c) {
+ ReplaceTextInternal(base::string16(&c, 1), true);
}
// Appends the text.
// The current composition text will be confirmed.
- void Append(const string16& text);
+ void Append(const base::string16& new_text);
// Deletes the first character after the current cursor position (as if, the
// the user has pressed delete key in the textfield). Returns true if
@@ -124,19 +113,17 @@ class VIEWS_EXPORT TextfieldViewsModel {
gfx::VisualCursorDirection direction,
bool select);
- // Moves the selection to the specified selection in |selection|.
- // If there is composition text, it will be confirmed, which will update the
- // selection range, and it overrides the selection_start to which the
- // selection will move to.
- bool MoveCursorTo(const gfx::SelectionModel& selection);
+ // Updates the cursor to the specified selection model. Any composition text
+ // will be confirmed, which may alter the specified selection range start.
+ bool MoveCursorTo(const gfx::SelectionModel& cursor);
- // Helper function to call MoveCursorTo on the TextfieldViewsModel.
+ // Helper function to call MoveCursorTo on the TextfieldModel.
bool MoveCursorTo(const gfx::Point& point, bool select);
- // Selection related method
+ // Selection related methods.
// Returns the selected text.
- string16 GetSelectedText() const;
+ base::string16 GetSelectedText() const;
// The current composition text will be confirmed. The selection starts with
// the range's start position, and ends with the range's end position,
@@ -195,13 +182,12 @@ class VIEWS_EXPORT TextfieldViewsModel {
// composition text.
void DeleteSelection();
- // Deletes the selected text (if any) and insert text at given
- // position.
- void DeleteSelectionAndInsertTextAt(
- const string16& text, size_t position);
+ // Deletes the selected text (if any) and insert text at given position.
+ void DeleteSelectionAndInsertTextAt(const base::string16& new_text,
+ size_t position);
// Retrieves the text content in a given range.
- string16 GetTextFromRange(const gfx::Range& range) const;
+ base::string16 GetTextFromRange(const gfx::Range& range) const;
// Retrieves the range containing all text in the model.
void GetTextRange(gfx::Range* range) const;
@@ -226,30 +212,23 @@ class VIEWS_EXPORT TextfieldViewsModel {
// Returns true if there is composition text.
bool HasCompositionText() const;
+ // Clears all edit history.
+ void ClearEditHistory();
+
private:
- friend class NativeTextfieldViews;
- friend class NativeTextfieldViewsTest;
- friend class TextfieldViewsModelTest;
- friend class UndoRedo_BasicTest;
- friend class UndoRedo_CutCopyPasteTest;
- friend class UndoRedo_ReplaceTest;
friend class internal::Edit;
- FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_BasicTest);
- FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest);
- FRIEND_TEST_ALL_PREFIXES(TextfieldViewsModelTest, UndoRedo_ReplaceTest);
+ FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_BasicTest);
+ FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_CutCopyPasteTest);
+ FRIEND_TEST_ALL_PREFIXES(TextfieldModelTest, UndoRedo_ReplaceTest);
- // Insert the given |text|. |mergeable| indicates if this insert
- // operation can be merged to previous edit in the edit history.
- void InsertTextInternal(const string16& text, bool mergeable);
+ // Insert the given |new_text|. |mergeable| indicates if this insert operation
+ // can be merged with previous edits in the history.
+ void InsertTextInternal(const base::string16& new_text, bool mergeable);
- // Replace the current text with the given |text|. |mergeable|
- // indicates if this replace operation can be merged to previous
- // edit in the edit history.
- void ReplaceTextInternal(const string16& text, bool mergeable);
-
- // Clears all edit history.
- void ClearEditHistory();
+ // Replace the current text with the given |new_text|. |mergeable| indicates
+ // if this replace operation can be merged with previous edits in the history.
+ void ReplaceTextInternal(const base::string16& new_text, bool mergeable);
// Clears redo history.
void ClearRedoHistory();
@@ -257,13 +236,13 @@ class VIEWS_EXPORT TextfieldViewsModel {
// Executes and records edit operations.
void ExecuteAndRecordDelete(gfx::Range range, bool mergeable);
void ExecuteAndRecordReplaceSelection(internal::MergeType merge_type,
- const string16& text);
+ const base::string16& new_text);
void ExecuteAndRecordReplace(internal::MergeType merge_type,
size_t old_cursor_pos,
size_t new_cursor_pos,
- const string16& text,
+ const base::string16& new_text,
size_t new_text_start);
- void ExecuteAndRecordInsert(const string16& text, bool mergeable);
+ void ExecuteAndRecordInsert(const base::string16& new_text, bool mergeable);
// Adds or merge |edit| into edit history. Return true if the edit
// has been merged and must be deleted after redo.
@@ -276,14 +255,13 @@ class VIEWS_EXPORT TextfieldViewsModel {
// 3) Move the cursor to |new_cursor_pos|.
void ModifyText(size_t delete_from,
size_t delete_to,
- const string16& new_text,
+ const base::string16& new_text,
size_t new_text_insert_at,
size_t new_cursor_pos);
void ClearComposition();
- // Pointer to a TextfieldViewsModel::Delegate instance, should be provided by
- // the View object.
+ // The TextfieldModel::Delegate instance should be provided by the owner.
Delegate* delegate_;
// The stylized text, cursor, selection, and the visual layout model.
@@ -295,19 +273,20 @@ class VIEWS_EXPORT TextfieldViewsModel {
// An iterator that points to the current edit that can be undone.
// This iterator moves from the |end()|, meaining no edit to undo,
// to the last element (one before |end()|), meaning no edit to redo.
- // There is no edit to undo (== end()) when:
- // 1) in initial state. (nothing to undo)
- // 2) very 1st edit is undone.
- // 3) all edit history is removed.
- // There is no edit to redo (== last element or no element) when:
- // 1) in initial state. (nothing to redo)
- // 2) new edit is added. (redo history is cleared)
- // 3) redone all undone edits.
+ //
+ // There is no edit to undo (== end()) when:
+ // 1) in initial state. (nothing to undo)
+ // 2) very 1st edit is undone.
+ // 3) all edit history is removed.
+ // There is no edit to redo (== last element or no element) when:
+ // 1) in initial state. (nothing to redo)
+ // 2) new edit is added. (redo history is cleared)
+ // 3) redone all undone edits.
EditHistory::iterator current_edit_;
- DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModel);
+ DISALLOW_COPY_AND_ASSIGN(TextfieldModel);
};
} // namespace views
-#endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_VIEWS_MODEL_H_
+#endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_MODEL_H_
diff --git a/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
index b23fb10b453..f3947ff0c1c 100644
--- a/chromium/ui/views/controls/textfield/textfield_views_model_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,7 +15,7 @@
#include "ui/gfx/range/range.h"
#include "ui/gfx/render_text.h"
#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/controls/textfield/textfield_views_model.h"
+#include "ui/views/controls/textfield/textfield_model.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/test/views_test_base.h"
@@ -23,7 +23,7 @@
#include "base/win/windows_version.h"
#endif
-#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
+#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(base::ASCIIToUTF16(ascii), utf16)
namespace {
@@ -34,7 +34,7 @@ struct WordAndCursor {
size_t cursor;
};
-void MoveCursorTo(views::TextfieldViewsModel& model, size_t pos) {
+void MoveCursorTo(views::TextfieldModel& model, size_t pos) {
model.MoveCursorTo(gfx::SelectionModel(pos, gfx::CURSOR_FORWARD));
}
@@ -42,10 +42,10 @@ void MoveCursorTo(views::TextfieldViewsModel& model, size_t pos) {
namespace views {
-class TextfieldViewsModelTest : public ViewsTestBase,
- public TextfieldViewsModel::Delegate {
+class TextfieldModelTest : public ViewsTestBase,
+ public TextfieldModel::Delegate {
public:
- TextfieldViewsModelTest()
+ TextfieldModelTest()
: ViewsTestBase(),
composition_text_confirmed_or_cleared_(false) {
}
@@ -55,123 +55,116 @@ class TextfieldViewsModelTest : public ViewsTestBase,
}
protected:
- void ResetModel(TextfieldViewsModel* model) const {
- model->SetText(string16());
+ void ResetModel(TextfieldModel* model) const {
+ model->SetText(base::string16());
model->ClearEditHistory();
}
bool composition_text_confirmed_or_cleared_;
private:
- DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModelTest);
+ DISALLOW_COPY_AND_ASSIGN(TextfieldModelTest);
};
-TEST_F(TextfieldViewsModelTest, EditString) {
- TextfieldViewsModel model(NULL);
- // append two strings
- model.Append(ASCIIToUTF16("HILL"));
- EXPECT_STR_EQ("HILL", model.GetText());
- model.Append(ASCIIToUTF16("WORLD"));
- EXPECT_STR_EQ("HILLWORLD", model.GetText());
+TEST_F(TextfieldModelTest, EditString) {
+ TextfieldModel model(NULL);
+ // Append two strings.
+ model.Append(base::ASCIIToUTF16("HILL"));
+ EXPECT_STR_EQ("HILL", model.text());
+ model.Append(base::ASCIIToUTF16("WORLD"));
+ EXPECT_STR_EQ("HILLWORLD", model.text());
- // Insert "E" to make hello
+ // Insert "E" and replace "I" with "L" to make "HELLO".
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.InsertChar('E');
- EXPECT_STR_EQ("HEILLWORLD", model.GetText());
- // Replace "I" with "L"
+ EXPECT_STR_EQ("HEILLWORLD", model.text());
model.ReplaceChar('L');
- EXPECT_STR_EQ("HELLLWORLD", model.GetText());
+ EXPECT_STR_EQ("HELLLWORLD", model.text());
model.ReplaceChar('L');
model.ReplaceChar('O');
- EXPECT_STR_EQ("HELLOWORLD", model.GetText());
+ EXPECT_STR_EQ("HELLOWORLD", model.text());
- // Delete 6th char "W", then delete 5th char O"
+ // Delete 6th char "W", then delete 5th char "O".
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("HELLOORLD", model.GetText());
+ EXPECT_STR_EQ("HELLOORLD", model.text());
EXPECT_TRUE(model.Backspace());
EXPECT_EQ(4U, model.GetCursorPosition());
- EXPECT_STR_EQ("HELLORLD", model.GetText());
+ EXPECT_STR_EQ("HELLORLD", model.text());
- // Move the cursor to start. backspace should fail.
+ // Move the cursor to start; backspace should fail.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
EXPECT_FALSE(model.Backspace());
- EXPECT_STR_EQ("HELLORLD", model.GetText());
- // Move the cursor to the end. delete should fail.
+ EXPECT_STR_EQ("HELLORLD", model.text());
+ // Move the cursor to the end; delete should fail, but backspace should work.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_FALSE(model.Delete());
- EXPECT_STR_EQ("HELLORLD", model.GetText());
- // but backspace should work.
+ EXPECT_STR_EQ("HELLORLD", model.text());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("HELLORL", model.GetText());
+ EXPECT_STR_EQ("HELLORL", model.text());
MoveCursorTo(model, 5);
- model.ReplaceText(ASCIIToUTF16(" WOR"));
- EXPECT_STR_EQ("HELLO WORL", model.GetText());
+ model.ReplaceText(base::ASCIIToUTF16(" WOR"));
+ EXPECT_STR_EQ("HELLO WORL", model.text());
}
-TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, EditString_SimpleRTL) {
+ TextfieldModel model(NULL);
// Append two strings.
- model.Append(WideToUTF16(L"\x05d0\x05d1\x05d2"));
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2"), model.GetText());
- model.Append(WideToUTF16(L"\x05e0\x05e1\x05e2"));
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"),
- model.GetText());
+ model.Append(base::WideToUTF16(L"\x05d0\x05d1\x05d2"));
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05d1\x05d2"), model.text());
+ model.Append(base::WideToUTF16(L"\x05e0\x05e1\x05e2"));
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"),
+ model.text());
- // Insert 0x05f0.
+ // Insert "\x05f0".
MoveCursorTo(model, 1);
model.InsertChar(0x05f0);
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
- model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
+ model.text());
// Replace "\x05d1" with "\x05f1".
model.ReplaceChar(0x05f1);
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
- model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
+ model.text());
- // Delete and backspace.
+ // Test Delete and backspace.
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Delete());
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"),
- model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"),
+ model.text());
EXPECT_TRUE(model.Backspace());
EXPECT_EQ(2U, model.GetCursorPosition());
- EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.text());
}
-TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
- // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
- // font support for some scripts - http://crbug.com/106450
+TEST_F(TextfieldModelTest, EditString_ComplexScript) {
+ // TODO(msw): XP fails due to lack of font support: http://crbug.com/106450
bool on_windows_xp = false;
#if defined(OS_WIN)
on_windows_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
#endif
- TextfieldViewsModel model(NULL);
+ TextfieldModel model(NULL);
// Append two Hindi strings.
- model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
- EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"),
- model.GetText());
- model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d"));
- EXPECT_EQ(WideToUTF16(
- L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
- model.GetText());
-
- // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
- // font support for some scripts - http://crbug.com/106450
+ model.Append(base::WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
+ EXPECT_EQ(base::WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"), model.text());
+ model.Append(base::WideToUTF16(L"\x0915\x094d\x092e\x094d"));
+ EXPECT_EQ(base::WideToUTF16(
+ L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"), model.text());
+
if (!on_windows_xp) {
- // Check it is not able to place cursor in middle of a grapheme.
+ // Ensure the cursor cannot be placed in the middle of a grapheme.
MoveCursorTo(model, 1);
EXPECT_EQ(0U, model.GetCursorPosition());
MoveCursorTo(model, 2);
EXPECT_EQ(2U, model.GetCursorPosition());
model.InsertChar('a');
- EXPECT_EQ(WideToUTF16(
+ EXPECT_EQ(base::WideToUTF16(
L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
- model.GetText());
+ model.text());
// ReplaceChar will replace the whole grapheme.
model.ReplaceChar('b');
@@ -179,9 +172,9 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
- EXPECT_EQ(WideToUTF16(
+ EXPECT_EQ(base::WideToUTF16(
L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
- model.GetText());
+ model.text());
#endif
EXPECT_EQ(4U, model.GetCursorPosition());
}
@@ -193,22 +186,20 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
EXPECT_TRUE(model.Delete());
- EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
- model.GetText());
- MoveCursorTo(model, model.GetText().length());
- EXPECT_EQ(model.GetText().length(), model.GetCursorPosition());
+ EXPECT_EQ(base::WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
+ model.text());
+ MoveCursorTo(model, model.text().length());
+ EXPECT_EQ(model.text().length(), model.GetCursorPosition());
EXPECT_TRUE(model.Backspace());
- EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"),
- model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"),
+ model.text());
#endif
// Test cursor position and deletion for Hindi Virama.
- model.SetText(WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E"));
+ model.SetText(base::WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E"));
MoveCursorTo(model, 0);
EXPECT_EQ(0U, model.GetCursorPosition());
- // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
- // font support for some scripts - http://crbug.com/106450
if (!on_windows_xp) {
MoveCursorTo(model, 1);
EXPECT_EQ(0U, model.GetCursorPosition());
@@ -222,44 +213,46 @@ TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
MoveCursorTo(model, 2);
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Backspace());
- EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.text());
#endif
- model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
+ model.SetText(
+ base::WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
MoveCursorTo(model, 0);
EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete());
- EXPECT_EQ(WideToUTF16(L""), model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L""), model.text());
// The first 2 characters are not strong directionality characters.
- model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
+ model.SetText(
+ base::WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
EXPECT_TRUE(model.Backspace());
- EXPECT_EQ(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"),
- model.GetText());
+ EXPECT_EQ(base::WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"),
+ model.text());
}
-TEST_F(TextfieldViewsModelTest, EmptyString) {
- TextfieldViewsModel model(NULL);
- EXPECT_EQ(string16(), model.GetText());
- EXPECT_EQ(string16(), model.GetSelectedText());
+TEST_F(TextfieldModelTest, EmptyString) {
+ TextfieldModel model(NULL);
+ EXPECT_EQ(base::string16(), model.text());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
EXPECT_EQ(0U, model.GetCursorPosition());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_EQ(0U, model.GetCursorPosition());
- EXPECT_EQ(string16(), model.GetSelectedText());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
EXPECT_FALSE(model.Delete());
EXPECT_FALSE(model.Backspace());
}
-TEST_F(TextfieldViewsModelTest, Selection) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO"));
+TEST_F(TextfieldModelTest, Selection) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO"));
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_STR_EQ("E", model.GetSelectedText());
@@ -271,7 +264,7 @@ TEST_F(TextfieldViewsModelTest, Selection) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_STR_EQ("ELLO", model.GetSelectedText());
model.ClearSelection();
- EXPECT_EQ(string16(), model.GetSelectedText());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
// SelectAll(false) selects towards the end.
model.SelectAll(false);
@@ -301,122 +294,123 @@ TEST_F(TextfieldViewsModelTest, Selection) {
EXPECT_EQ(5U, model.GetCursorPosition());
}
-TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) {
+TEST_F(TextfieldModelTest, Selection_BidiWithNonSpacingMarks) {
// Selection is a logical operation. And it should work with the arrow
// keys doing visual movements, while the selection is logical between
// the (logical) start and end points. Selection is simply defined as
// the portion of text between the logical positions of the start and end
// caret positions.
- TextfieldViewsModel model(NULL);
+ TextfieldModel model(NULL);
// TODO(xji): temporarily disable in platform Win since the complex script
// characters turned into empty square due to font regression. So, not able
// to test 2 characters belong to the same grapheme.
#if defined(OS_LINUX)
- model.Append(WideToUTF16(
+ model.Append(base::WideToUTF16(
L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"));
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
- EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"c"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_EQ(gfx::Range(2, 7), model.render_text()->selection());
- EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"),
+ EXPECT_EQ(base::WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"),
model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
- EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"c"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
EXPECT_EQ(gfx::Range(2, 10), model.render_text()->selection());
- EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"d"),
+ EXPECT_EQ(base::WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"d"),
model.GetSelectedText());
model.ClearSelection();
- EXPECT_EQ(string16(), model.GetSelectedText());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
model.SelectAll(false);
- EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"),
- model.GetSelectedText());
+ EXPECT_EQ(
+ base::WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"),
+ model.GetSelectedText());
#endif
// In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is
// an RTL character.
- model.SetText(WideToUTF16(L"a\x05E9" L"b"));
+ model.SetText(base::WideToUTF16(L"a\x05E9" L"b"));
MoveCursorTo(model, 0);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
- EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
- EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
- EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_EQ(3U, model.GetCursorPosition());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
- EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"b"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
- EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"b"), model.GetSelectedText());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
- EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
- EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a\x05E9"), model.GetSelectedText());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
- EXPECT_EQ(WideToUTF16(L"\x05E9" L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"\x05E9" L"b"), model.GetSelectedText());
model.ClearSelection();
- EXPECT_EQ(string16(), model.GetSelectedText());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
model.SelectAll(false);
- EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
+ EXPECT_EQ(base::WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
}
-TEST_F(TextfieldViewsModelTest, SelectionAndEdit) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO"));
+TEST_F(TextfieldModelTest, SelectionAndEdit) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO"));
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "EL"
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("HLO", model.GetText());
+ EXPECT_STR_EQ("HLO", model.text());
- model.Append(ASCIIToUTF16("ILL"));
+ model.Append(base::ASCIIToUTF16("ILL"));
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "LO"
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("HILL", model.GetText());
+ EXPECT_STR_EQ("HILL", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "I"
model.InsertChar('E');
- EXPECT_STR_EQ("HELL", model.GetText());
+ EXPECT_STR_EQ("HELL", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "H"
model.ReplaceChar('B');
- EXPECT_STR_EQ("BELL", model.GetText());
+ EXPECT_STR_EQ("BELL", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); // "ELL"
model.ReplaceChar('E');
- EXPECT_STR_EQ("BEE", model.GetText());
+ EXPECT_STR_EQ("BEE", model.text());
}
-TEST_F(TextfieldViewsModelTest, Word) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, Word) {
+ TextfieldModel model(NULL);
model.Append(
- ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
+ base::ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_EQ(3U, model.GetCursorPosition());
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
@@ -456,16 +450,16 @@ TEST_F(TextfieldViewsModelTest, Word) {
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
model.ReplaceChar('4');
- EXPECT_EQ(string16(), model.GetSelectedText());
- EXPECT_STR_EQ("42", model.GetText());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
+ EXPECT_STR_EQ("42", model.text());
}
-TEST_F(TextfieldViewsModelTest, SetText) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO"));
+TEST_F(TextfieldModelTest, SetText) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
- model.SetText(ASCIIToUTF16("GOODBYE"));
- EXPECT_STR_EQ("GOODBYE", model.GetText());
+ model.SetText(base::ASCIIToUTF16("GOODBYE"));
+ EXPECT_STR_EQ("GOODBYE", model.text());
// SetText move the cursor to the end of the new text.
EXPECT_EQ(7U, model.GetCursorPosition());
model.SelectAll(false);
@@ -473,37 +467,38 @@ TEST_F(TextfieldViewsModelTest, SetText) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_EQ(7U, model.GetCursorPosition());
- model.SetText(ASCIIToUTF16("BYE"));
+ model.SetText(base::ASCIIToUTF16("BYE"));
// Setting shorter string moves the cursor to the end of the new string.
EXPECT_EQ(3U, model.GetCursorPosition());
- EXPECT_EQ(string16(), model.GetSelectedText());
- model.SetText(string16());
+ EXPECT_EQ(base::string16(), model.GetSelectedText());
+ model.SetText(base::string16());
EXPECT_EQ(0U, model.GetCursorPosition());
}
-TEST_F(TextfieldViewsModelTest, Clipboard) {
+TEST_F(TextfieldModelTest, Clipboard) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- const string16 initial_clipboard_text = ASCIIToUTF16("initial text");
+ const base::string16 initial_clipboard_text =
+ base::ASCIIToUTF16("initial text");
ui::ScopedClipboardWriter(clipboard, ui::CLIPBOARD_TYPE_COPY_PASTE).
WriteText(initial_clipboard_text);
- string16 clipboard_text;
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO WORLD"));
+ base::string16 clipboard_text;
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO WORLD"));
// Cut with an empty selection should do nothing.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_FALSE(model.Cut());
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.GetText());
+ 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);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.GetText());
+ EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
// Cut on obscured (password) text should do nothing.
@@ -512,15 +507,15 @@ TEST_F(TextfieldViewsModelTest, Clipboard) {
EXPECT_FALSE(model.Cut());
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.GetText());
+ EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
- // Copy on obscured text should do nothing.
+ // Copy on obscured (password) text should do nothing.
model.SelectAll(false);
EXPECT_FALSE(model.Copy());
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
- EXPECT_STR_EQ("HELLO WORLD", model.GetText());
+ EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
// Cut with non-empty selection.
@@ -530,7 +525,7 @@ TEST_F(TextfieldViewsModelTest, Clipboard) {
EXPECT_TRUE(model.Cut());
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
EXPECT_STR_EQ("WORLD", clipboard_text);
- EXPECT_STR_EQ("HELLO ", model.GetText());
+ EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
// Copy with non-empty selection.
@@ -538,69 +533,71 @@ TEST_F(TextfieldViewsModelTest, Clipboard) {
EXPECT_TRUE(model.Copy());
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
EXPECT_STR_EQ("HELLO ", clipboard_text);
- EXPECT_STR_EQ("HELLO ", model.GetText());
+ EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
// Test that paste works regardless of the obscured bit.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO HELLO ", model.GetText());
+ EXPECT_STR_EQ("HELLO HELLO ", model.text());
EXPECT_EQ(12U, model.GetCursorPosition());
model.render_text()->SetObscured(true);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("HELLO HELLO HELLO ", model.GetText());
+ EXPECT_STR_EQ("HELLO HELLO HELLO ", model.text());
EXPECT_EQ(18U, model.GetCursorPosition());
}
-static void SelectWordTestVerifier(const TextfieldViewsModel& model,
- const string16 &expected_selected_string, size_t expected_cursor_pos) {
+static void SelectWordTestVerifier(
+ const TextfieldModel& model,
+ const base::string16 &expected_selected_string,
+ size_t expected_cursor_pos) {
EXPECT_EQ(expected_selected_string, model.GetSelectedText());
EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition());
}
-TEST_F(TextfieldViewsModelTest, SelectWordTest) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16(" HELLO !! WO RLD "));
+TEST_F(TextfieldModelTest, SelectWordTest) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16(" HELLO !! WO RLD "));
// Test when cursor is at the beginning.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16(" "), 2U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16(" "), 2U);
// Test when cursor is at the beginning of a word.
MoveCursorTo(model, 2);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16("HELLO"), 7U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16("HELLO"), 7U);
// Test when cursor is at the end of a word.
MoveCursorTo(model, 15);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16(" "), 20U);
// Test when cursor is somewhere in a non-alpha-numeric fragment.
for (size_t cursor_pos = 8; cursor_pos < 13U; cursor_pos++) {
MoveCursorTo(model, cursor_pos);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16(" !! "), 13U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16(" !! "), 13U);
}
// Test when cursor is somewhere in a whitespace fragment.
MoveCursorTo(model, 17);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16(" "), 20U);
// Test when cursor is at the end.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.SelectWord();
- SelectWordTestVerifier(model, ASCIIToUTF16(" "), 24U);
+ SelectWordTestVerifier(model, base::ASCIIToUTF16(" "), 24U);
}
// TODO(xji): temporarily disable in platform Win since the complex script
// characters and Chinese characters are turned into empty square due to font
// regression.
#if defined(OS_LINUX)
-TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, SelectWordTest_MixScripts) {
+ TextfieldModel model(NULL);
std::vector<WordAndCursor> word_and_cursor;
word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
@@ -617,22 +614,22 @@ TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) {
word_and_cursor.push_back(WordAndCursor(L"\x5929", 14));
// The text consists of Ascii, Hebrew, Hindi with Virama sign, and Chinese.
- model.SetText(WideToUTF16(L"a\x05d0 \x05d1\x05d2 \x0915\x094d\x0915 "
- L"\x4E2D\x56FD\x82B1\x5929"));
+ model.SetText(base::WideToUTF16(L"a\x05d0 \x05d1\x05d2 \x0915\x094d\x0915 "
+ L"\x4E2D\x56FD\x82B1\x5929"));
for (size_t i = 0; i < word_and_cursor.size(); ++i) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
for (size_t j = 0; j < i; ++j)
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.SelectWord();
- SelectWordTestVerifier(model, WideToUTF16(word_and_cursor[i].word),
+ SelectWordTestVerifier(model, base::WideToUTF16(word_and_cursor[i].word),
word_and_cursor[i].cursor);
}
}
#endif
-TEST_F(TextfieldViewsModelTest, RangeTest) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO WORLD"));
+TEST_F(TextfieldModelTest, RangeTest) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO WORLD"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
gfx::Range range = model.render_text()->selection();
EXPECT_TRUE(range.is_empty());
@@ -694,9 +691,9 @@ TEST_F(TextfieldViewsModelTest, RangeTest) {
EXPECT_EQ(0U, range.end());
}
-TEST_F(TextfieldViewsModelTest, SelectRangeTest) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO WORLD"));
+TEST_F(TextfieldModelTest, SelectRangeTest) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO WORLD"));
gfx::Range range(0, 6);
EXPECT_FALSE(range.is_reversed());
model.SelectRange(range);
@@ -738,9 +735,9 @@ TEST_F(TextfieldViewsModelTest, SelectRangeTest) {
EXPECT_TRUE(model.GetSelectedText().empty());
}
-TEST_F(TextfieldViewsModelTest, SelectionTest) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO WORLD"));
+TEST_F(TextfieldModelTest, SelectionTest) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO WORLD"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
gfx::Range selection = model.render_text()->selection();
EXPECT_EQ(gfx::Range(0), selection);
@@ -780,9 +777,9 @@ TEST_F(TextfieldViewsModelTest, SelectionTest) {
EXPECT_EQ(gfx::Range(11, 0), selection);
}
-TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) {
- TextfieldViewsModel model(NULL);
- model.Append(ASCIIToUTF16("HELLO WORLD"));
+TEST_F(TextfieldModelTest, SelectSelectionModelTest) {
+ TextfieldModel model(NULL);
+ model.Append(base::ASCIIToUTF16("HELLO WORLD"));
model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(0, 6),
gfx::CURSOR_BACKWARD));
EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
@@ -813,9 +810,9 @@ TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) {
EXPECT_TRUE(model.GetSelectedText().empty());
}
-TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
- TextfieldViewsModel model(this);
- model.Append(ASCIIToUTF16("1234590"));
+TEST_F(TextfieldModelTest, CompositionTextTest) {
+ TextfieldModel model(this);
+ model.Append(base::ASCIIToUTF16("1234590"));
model.SelectRange(gfx::Range(5, 5));
EXPECT_FALSE(model.HasSelection());
EXPECT_EQ(5U, model.GetCursorPosition());
@@ -825,7 +822,7 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
EXPECT_EQ(gfx::Range(0, 7), range);
ui::CompositionText composition;
- composition.text = ASCIIToUTF16("678");
+ composition.text = base::ASCIIToUTF16("678");
composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
// Cursor should be at the end of composition when characters are just typed.
@@ -834,7 +831,7 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
EXPECT_TRUE(model.HasCompositionText());
EXPECT_FALSE(model.HasSelection());
- // Cancel composition
+ // Cancel the composition.
model.CancelCompositionText();
composition_text_confirmed_or_cleared_ = false;
@@ -850,11 +847,11 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
model.GetTextRange(&range);
EXPECT_EQ(10U, range.end());
- EXPECT_STR_EQ("1234567890", model.GetText());
+ EXPECT_STR_EQ("1234567890", model.text());
model.GetCompositionTextRange(&range);
EXPECT_EQ(gfx::Range(5, 8), range);
- // composition text
+ // Check the composition text.
EXPECT_STR_EQ("456", model.GetTextFromRange(gfx::Range(3, 6)));
EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection());
@@ -867,74 +864,74 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
EXPECT_EQ(5U, model.GetCursorPosition());
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890", model.GetText());
- EXPECT_TRUE(model.SetText(ASCIIToUTF16("1234567890")));
+ EXPECT_STR_EQ("1234567890", model.text());
+ EXPECT_TRUE(model.SetText(base::ASCIIToUTF16("1234567890")));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890678", model.GetText());
+ EXPECT_STR_EQ("1234567890678", model.text());
- model.InsertText(UTF8ToUTF16("-"));
+ model.InsertText(base::UTF8ToUTF16("-"));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-", model.GetText());
+ EXPECT_STR_EQ("1234567890-", model.text());
EXPECT_FALSE(model.HasCompositionText());
EXPECT_FALSE(model.HasSelection());
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
EXPECT_STR_EQ("-", model.GetSelectedText());
model.SetCompositionText(composition);
- EXPECT_STR_EQ("1234567890678", model.GetText());
+ EXPECT_STR_EQ("1234567890678", model.text());
- model.ReplaceText(UTF8ToUTF16("-"));
+ model.ReplaceText(base::UTF8ToUTF16("-"));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-", model.GetText());
+ EXPECT_STR_EQ("1234567890-", model.text());
EXPECT_FALSE(model.HasCompositionText());
EXPECT_FALSE(model.HasSelection());
model.SetCompositionText(composition);
- model.Append(UTF8ToUTF16("-"));
+ model.Append(base::UTF8ToUTF16("-"));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.GetText());
+ EXPECT_STR_EQ("1234567890-678-", model.text());
model.SetCompositionText(composition);
model.Delete();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.GetText());
+ EXPECT_STR_EQ("1234567890-678-", model.text());
model.SetCompositionText(composition);
model.Backspace();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("1234567890-678-", model.GetText());
+ EXPECT_STR_EQ("1234567890-678-", model.text());
- model.SetText(string16());
+ model.SetText(base::string16());
model.SetCompositionText(composition);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.GetText());
+ EXPECT_STR_EQ("678", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
model.SetCompositionText(composition);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("676788", model.GetText());
+ EXPECT_STR_EQ("676788", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
model.SetCompositionText(composition);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("676788678", model.GetText());
+ EXPECT_STR_EQ("676788678", model.text());
- model.SetText(string16());
+ model.SetText(base::string16());
model.SetCompositionText(composition);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
@@ -944,13 +941,13 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678678", model.GetText());
+ EXPECT_STR_EQ("678678", model.text());
model.SetCompositionText(composition);
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.GetText());
+ EXPECT_STR_EQ("678", model.text());
model.SetCompositionText(composition);
gfx::SelectionModel sel(
@@ -959,25 +956,25 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
model.MoveCursorTo(sel);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678678", model.GetText());
+ EXPECT_STR_EQ("678678", model.text());
model.SetCompositionText(composition);
model.SelectRange(gfx::Range(0, 3));
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.GetText());
+ EXPECT_STR_EQ("678", model.text());
model.SetCompositionText(composition);
model.SelectAll(false);
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.GetText());
+ EXPECT_STR_EQ("678", model.text());
model.SetCompositionText(composition);
model.SelectWord();
EXPECT_TRUE(composition_text_confirmed_or_cleared_);
composition_text_confirmed_or_cleared_ = false;
- EXPECT_STR_EQ("678", model.GetText());
+ EXPECT_STR_EQ("678", model.text());
model.SetCompositionText(composition);
model.ClearSelection();
@@ -989,528 +986,497 @@ TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
EXPECT_FALSE(composition_text_confirmed_or_cleared_);
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_BasicTest) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, UndoRedo_BasicTest) {
+ TextfieldModel model(NULL);
model.InsertChar('a');
- EXPECT_FALSE(model.Redo()); // nothing to redo
+ EXPECT_FALSE(model.Redo()); // There is nothing to redo.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a", model.GetText());
+ EXPECT_STR_EQ("a", model.text());
// Continuous inserts are treated as one edit.
model.InsertChar('b');
model.InsertChar('c');
- EXPECT_STR_EQ("abc", model.GetText());
+ EXPECT_STR_EQ("abc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("a", model.GetText());
+ EXPECT_STR_EQ("a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
// Undoing further shouldn't change the text.
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
// Redoing to the latest text.
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a", model.GetText());
+ EXPECT_STR_EQ("a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("abc", model.GetText());
+ EXPECT_STR_EQ("abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
// Backspace ===============================
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("ab", model.GetText());
+ EXPECT_STR_EQ("ab", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abc", model.GetText());
+ EXPECT_STR_EQ("abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ab", model.GetText());
+ EXPECT_STR_EQ("ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
// Continous backspaces are treated as one edit.
EXPECT_TRUE(model.Backspace());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
// Extra backspace shouldn't affect the history.
EXPECT_FALSE(model.Backspace());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ab", model.GetText());
+ EXPECT_STR_EQ("ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abc", model.GetText());
+ EXPECT_STR_EQ("abc", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("a", model.GetText());
+ EXPECT_STR_EQ("a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
// Clear history
model.ClearEditHistory();
EXPECT_FALSE(model.Undo());
EXPECT_FALSE(model.Redo());
- EXPECT_STR_EQ("a", model.GetText());
+ EXPECT_STR_EQ("a", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
// Delete ===============================
- model.SetText(ASCIIToUTF16("ABCDE"));
+ model.SetText(base::ASCIIToUTF16("ABCDE"));
model.ClearEditHistory();
MoveCursorTo(model, 2);
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("ABDE", model.GetText());
+ EXPECT_STR_EQ("ABDE", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("BDE", model.GetText());
+ EXPECT_STR_EQ("BDE", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABDE", model.GetText());
+ EXPECT_STR_EQ("ABDE", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABDE", model.GetText());
+ EXPECT_STR_EQ("ABDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
// Continous deletes are treated as one edit.
EXPECT_TRUE(model.Delete());
EXPECT_TRUE(model.Delete());
- EXPECT_STR_EQ("AB", model.GetText());
+ EXPECT_STR_EQ("AB", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABDE", model.GetText());
+ EXPECT_STR_EQ("ABDE", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("AB", model.GetText());
+ EXPECT_STR_EQ("AB", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_SetText) {
+TEST_F(TextfieldModelTest, UndoRedo_SetText) {
// This is to test the undo/redo behavior of omnibox.
- TextfieldViewsModel model(NULL);
+ TextfieldModel model(NULL);
model.InsertChar('w');
- EXPECT_STR_EQ("w", model.GetText());
+ EXPECT_STR_EQ("w", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
- model.SetText(ASCIIToUTF16("www.google.com"));
+ model.SetText(base::ASCIIToUTF16("www.google.com"));
EXPECT_EQ(14U, model.GetCursorPosition());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
model.SelectRange(gfx::Range(14, 1));
model.InsertChar('w');
- EXPECT_STR_EQ("ww", model.GetText());
- model.SetText(ASCIIToUTF16("www.google.com"));
+ EXPECT_STR_EQ("ww", model.text());
+ model.SetText(base::ASCIIToUTF16("www.google.com"));
model.SelectRange(gfx::Range(14, 2));
model.InsertChar('w');
- EXPECT_STR_EQ("www", model.GetText());
- model.SetText(ASCIIToUTF16("www.google.com"));
+ EXPECT_STR_EQ("www", model.text());
+ model.SetText(base::ASCIIToUTF16("www.google.com"));
model.SelectRange(gfx::Range(14, 3));
model.InsertChar('.');
- EXPECT_STR_EQ("www.", model.GetText());
- model.SetText(ASCIIToUTF16("www.google.com"));
+ EXPECT_STR_EQ("www.", model.text());
+ model.SetText(base::ASCIIToUTF16("www.google.com"));
model.SelectRange(gfx::Range(14, 4));
model.InsertChar('y');
- EXPECT_STR_EQ("www.y", model.GetText());
- model.SetText(ASCIIToUTF16("www.youtube.com"));
- EXPECT_STR_EQ("www.youtube.com", model.GetText());
+ EXPECT_STR_EQ("www.y", model.text());
+ model.SetText(base::ASCIIToUTF16("www.youtube.com"));
+ EXPECT_STR_EQ("www.youtube.com", model.text());
EXPECT_EQ(15U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("www.youtube.com", model.GetText());
+ EXPECT_STR_EQ("www.youtube.com", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_BackspaceThenSetText) {
+TEST_F(TextfieldModelTest, UndoRedo_BackspaceThenSetText) {
// This is to test the undo/redo behavior of omnibox.
- TextfieldViewsModel model(NULL);
+ TextfieldModel model(NULL);
model.InsertChar('w');
- EXPECT_STR_EQ("w", model.GetText());
+ EXPECT_STR_EQ("w", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
- model.SetText(ASCIIToUTF16("www.google.com"));
+ model.SetText(base::ASCIIToUTF16("www.google.com"));
EXPECT_EQ(14U, model.GetCursorPosition());
- EXPECT_STR_EQ("www.google.com", model.GetText());
- model.SetText(ASCIIToUTF16("www.google.com")); // Confirm the text.
+ EXPECT_STR_EQ("www.google.com", model.text());
+ model.SetText(base::ASCIIToUTF16("www.google.com")); // Confirm the text.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_EQ(14U, model.GetCursorPosition());
EXPECT_TRUE(model.Backspace());
EXPECT_TRUE(model.Backspace());
- EXPECT_STR_EQ("www.google.c", model.GetText());
- // Autocomplete sets the text
- model.SetText(ASCIIToUTF16("www.google.com/search=www.google.c"));
- EXPECT_STR_EQ("www.google.com/search=www.google.c", model.GetText());
+ EXPECT_STR_EQ("www.google.c", model.text());
+ // Autocomplete sets the text.
+ model.SetText(base::ASCIIToUTF16("www.google.com/search=www.google.c"));
+ EXPECT_STR_EQ("www.google.com/search=www.google.c", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.c", model.GetText());
+ EXPECT_STR_EQ("www.google.c", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("www.google.com", model.GetText());
+ EXPECT_STR_EQ("www.google.com", model.text());
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) {
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("ABCDE"));
- EXPECT_FALSE(model.Redo()); // nothing to redo
- // Cut
+TEST_F(TextfieldModelTest, UndoRedo_CutCopyPasteTest) {
+ TextfieldModel model(NULL);
+ model.SetText(base::ASCIIToUTF16("ABCDE"));
+ EXPECT_FALSE(model.Redo()); // There is nothing to redo.
+ // Test Cut.
model.SelectRange(gfx::Range(1, 3));
model.Cut();
- EXPECT_STR_EQ("ADE", model.GetText());
+ EXPECT_STR_EQ("ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
- EXPECT_FALSE(model.Undo()); // no more undo
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_FALSE(model.Undo()); // There is no more to undo.
+ EXPECT_STR_EQ("", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ADE", model.GetText());
+ EXPECT_STR_EQ("ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
- EXPECT_FALSE(model.Redo()); // no more redo
- EXPECT_STR_EQ("ADE", model.GetText());
+ EXPECT_FALSE(model.Redo()); // There is no more to redo.
+ EXPECT_STR_EQ("ADE", model.text());
model.Paste();
model.Paste();
model.Paste();
- EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ADE", model.GetText());
+ EXPECT_STR_EQ("ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.GetText()); // Redoing SetText
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
- // Redo
+ // Test Redo.
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ADE", model.GetText());
+ EXPECT_STR_EQ("ADE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCDE", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
- // with SelectRange
+ // Test using SelectRange.
model.SelectRange(gfx::Range(1, 3));
EXPECT_TRUE(model.Cut());
- EXPECT_STR_EQ("ABCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCDE", model.text());
EXPECT_EQ(1U, model.GetCursorPosition());
model.SelectRange(gfx::Range(1, 1));
EXPECT_FALSE(model.Cut());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("ABCBCDEBC", model.GetText());
+ EXPECT_STR_EQ("ABCBCDEBC", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCDE", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
- // empty cut shouldn't create an edit.
+ // An empty cut shouldn't create an edit.
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
+ EXPECT_STR_EQ("ABCBCBCDE", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
- // Copy
+ // Test Copy.
ResetModel(&model);
- model.SetText(ASCIIToUTF16("12345"));
- EXPECT_STR_EQ("12345", model.GetText());
+ model.SetText(base::ASCIIToUTF16("12345"));
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
model.SelectRange(gfx::Range(1, 3));
- model.Copy(); // Copy "23"
- EXPECT_STR_EQ("12345", model.GetText());
+ model.Copy(); // Copy "23".
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
model.Paste(); // Paste "23" into "23".
- EXPECT_STR_EQ("12345", model.GetText());
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
model.Paste();
- EXPECT_STR_EQ("1232345", model.GetText());
+ EXPECT_STR_EQ("1232345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("12345", model.GetText());
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
- // TODO(oshima): We need to change the return type from bool to enum.
+ // TODO(oshima): Change the return type from bool to enum.
EXPECT_FALSE(model.Undo()); // No text change.
- EXPECT_STR_EQ("12345", model.GetText());
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_FALSE(model.Undo());
- // Redo
+ // Test Redo.
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("12345", model.GetText());
+ EXPECT_STR_EQ("12345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("12345", model.GetText()); // For 1st paste
+ EXPECT_STR_EQ("12345", model.text()); // For 1st paste
EXPECT_EQ(3U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("1232345", model.GetText());
+ EXPECT_STR_EQ("1232345", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
- EXPECT_STR_EQ("1232345", model.GetText());
+ EXPECT_STR_EQ("1232345", model.text());
- // Test using SelectRange
+ // Test using SelectRange.
model.SelectRange(gfx::Range(1, 3));
model.Copy();
- EXPECT_STR_EQ("1232345", model.GetText());
+ EXPECT_STR_EQ("1232345", model.text());
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
EXPECT_TRUE(model.Paste());
- EXPECT_STR_EQ("123234523", model.GetText());
+ EXPECT_STR_EQ("123234523", model.text());
EXPECT_EQ(9U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("1232345", model.GetText());
+ EXPECT_STR_EQ("1232345", model.text());
EXPECT_EQ(7U, model.GetCursorPosition());
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_CursorTest) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, UndoRedo_CursorTest) {
+ TextfieldModel model(NULL);
model.InsertChar('a');
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
model.InsertChar('b');
// Moving the cursor shouldn't create a new edit.
- EXPECT_STR_EQ("ab", model.GetText());
+ EXPECT_STR_EQ("ab", model.text());
EXPECT_FALSE(model.Redo());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_FALSE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ab", model.GetText());
+ EXPECT_STR_EQ("ab", model.text());
EXPECT_EQ(2U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
-void RunInsertReplaceTest(TextfieldViewsModel& model) {
+void RunInsertReplaceTest(TextfieldModel& model) {
const bool reverse = model.render_text()->selection().is_reversed();
model.InsertChar('1');
model.InsertChar('2');
model.InsertChar('3');
- EXPECT_STR_EQ("a123d", model.GetText());
+ EXPECT_STR_EQ("a123d", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abcd", model.GetText());
+ EXPECT_STR_EQ("abcd", model.text());
EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("abcd", model.GetText());
- EXPECT_EQ(4U, model.GetCursorPosition()); // By SetText
+ EXPECT_STR_EQ("abcd", model.text());
+ EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a123d", model.GetText());
+ EXPECT_STR_EQ("a123d", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
-void RunOverwriteReplaceTest(TextfieldViewsModel& model) {
+void RunOverwriteReplaceTest(TextfieldModel& model) {
const bool reverse = model.render_text()->selection().is_reversed();
model.ReplaceChar('1');
model.ReplaceChar('2');
model.ReplaceChar('3');
model.ReplaceChar('4');
- EXPECT_STR_EQ("a1234", model.GetText());
+ EXPECT_STR_EQ("a1234", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("abcd", model.GetText());
+ EXPECT_STR_EQ("abcd", model.text());
EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_EQ(0U, model.GetCursorPosition());
EXPECT_FALSE(model.Undo());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("abcd", model.GetText());
+ EXPECT_STR_EQ("abcd", model.text());
EXPECT_EQ(4U, model.GetCursorPosition());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("a1234", model.GetText());
+ EXPECT_STR_EQ("a1234", model.text());
EXPECT_EQ(5U, model.GetCursorPosition());
EXPECT_FALSE(model.Redo());
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) {
- // By Cursor
- {
- SCOPED_TRACE("forward & insert by cursor");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
- model.SelectRange(gfx::Range(1, 3));
- RunInsertReplaceTest(model);
- }
- {
- SCOPED_TRACE("backward & insert by cursor");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
- model.SelectRange(gfx::Range(3, 1));
- RunInsertReplaceTest(model);
- }
- {
- SCOPED_TRACE("forward & overwrite by cursor");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
- model.SelectRange(gfx::Range(1, 3));
- RunOverwriteReplaceTest(model);
- }
- {
- SCOPED_TRACE("backward & overwrite by cursor");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
- model.SelectRange(gfx::Range(3, 1));
- RunOverwriteReplaceTest(model);
- }
- // By SelectRange API
+TEST_F(TextfieldModelTest, UndoRedo_ReplaceTest) {
{
- SCOPED_TRACE("forward & insert by SelectRange");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
+ SCOPED_TRACE("Select forwards and insert.");
+ TextfieldModel model(NULL);
+ model.SetText(base::ASCIIToUTF16("abcd"));
model.SelectRange(gfx::Range(1, 3));
RunInsertReplaceTest(model);
}
{
- SCOPED_TRACE("backward & insert by SelectRange");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
+ SCOPED_TRACE("Select reversed and insert.");
+ TextfieldModel model(NULL);
+ model.SetText(base::ASCIIToUTF16("abcd"));
model.SelectRange(gfx::Range(3, 1));
RunInsertReplaceTest(model);
}
{
- SCOPED_TRACE("forward & overwrite by SelectRange");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
+ SCOPED_TRACE("Select forwards and overwrite.");
+ TextfieldModel model(NULL);
+ model.SetText(base::ASCIIToUTF16("abcd"));
model.SelectRange(gfx::Range(1, 3));
RunOverwriteReplaceTest(model);
}
{
- SCOPED_TRACE("backward & overwrite by SelectRange");
- TextfieldViewsModel model(NULL);
- model.SetText(ASCIIToUTF16("abcd"));
+ SCOPED_TRACE("Select reversed and overwrite.");
+ TextfieldModel model(NULL);
+ model.SetText(base::ASCIIToUTF16("abcd"));
model.SelectRange(gfx::Range(3, 1));
RunOverwriteReplaceTest(model);
}
}
-TEST_F(TextfieldViewsModelTest, UndoRedo_CompositionText) {
- TextfieldViewsModel model(NULL);
+TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
+ TextfieldModel model(NULL);
ui::CompositionText composition;
- composition.text = ASCIIToUTF16("abc");
+ composition.text = base::ASCIIToUTF16("abc");
composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
composition.selection = gfx::Range(2, 3);
- model.SetText(ASCIIToUTF16("ABCDE"));
+ model.SetText(base::ASCIIToUTF16("ABCDE"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.InsertChar('x');
- EXPECT_STR_EQ("ABCDEx", model.GetText());
+ EXPECT_STR_EQ("ABCDEx", model.text());
EXPECT_TRUE(model.Undo()); // set composition should forget undone edit.
model.SetCompositionText(composition);
EXPECT_TRUE(model.HasCompositionText());
EXPECT_TRUE(model.HasSelection());
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
- // Accepting composition
+ // Confirm the composition.
model.ConfirmCompositionText();
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("", model.GetText());
+ EXPECT_STR_EQ("", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
- // Canceling composition
+ // Cancel the composition.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("abcABCDEabc", model.GetText());
+ EXPECT_STR_EQ("abcABCDEabc", model.text());
model.CancelCompositionText();
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
- // SetText with the same text as the result.
+ // Call SetText with the same text as the result.
ResetModel(&model);
- model.SetText(ASCIIToUTF16("ABCDE"));
+ model.SetText(base::ASCIIToUTF16("ABCDE"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
- model.SetText(ASCIIToUTF16("ABCDEabc"));
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
+ model.SetText(base::ASCIIToUTF16("ABCDEabc"));
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
EXPECT_FALSE(model.Redo());
- // SetText with the different text than the result should not
- // remember composition text.
+ // Call SetText with a different result; the composition should be forgotten.
ResetModel(&model);
- model.SetText(ASCIIToUTF16("ABCDE"));
+ model.SetText(base::ASCIIToUTF16("ABCDE"));
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
model.SetCompositionText(composition);
- EXPECT_STR_EQ("ABCDEabc", model.GetText());
- model.SetText(ASCIIToUTF16("1234"));
- EXPECT_STR_EQ("1234", model.GetText());
+ EXPECT_STR_EQ("ABCDEabc", model.text());
+ model.SetText(base::ASCIIToUTF16("1234"));
+ EXPECT_STR_EQ("1234", model.text());
EXPECT_TRUE(model.Undo());
- EXPECT_STR_EQ("ABCDE", model.GetText());
+ EXPECT_STR_EQ("ABCDE", model.text());
EXPECT_TRUE(model.Redo());
- EXPECT_STR_EQ("1234", model.GetText());
+ EXPECT_STR_EQ("1234", model.text());
EXPECT_FALSE(model.Redo());
- // TODO(oshima): We need MockInputMethod to test the behavior with IME.
+ // TODO(oshima): Test the behavior with an IME.
}
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_test_api.cc b/chromium/ui/views/controls/textfield/textfield_test_api.cc
new file mode 100644
index 00000000000..be45d24cc42
--- /dev/null
+++ b/chromium/ui/views/controls/textfield/textfield_test_api.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/textfield/textfield_test_api.h"
+
+namespace views {
+
+TextfieldTestApi::TextfieldTestApi(Textfield* textfield)
+ : textfield_(textfield) {
+ DCHECK(textfield);
+}
+
+void TextfieldTestApi::UpdateContextMenu() {
+ textfield_->UpdateContextMenu();
+}
+
+gfx::RenderText* TextfieldTestApi::GetRenderText() const {
+ return textfield_->GetRenderText();
+}
+
+void TextfieldTestApi::CreateTouchSelectionControllerAndNotifyIt() {
+ textfield_->CreateTouchSelectionControllerAndNotifyIt();
+}
+
+void TextfieldTestApi::ResetTouchSelectionController() {
+ textfield_->touch_selection_controller_.reset();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_test_api.h b/chromium/ui/views/controls/textfield/textfield_test_api.h
new file mode 100644
index 00000000000..1af2ffcdf62
--- /dev/null
+++ b/chromium/ui/views/controls/textfield/textfield_test_api.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_TEST_API_H_
+#define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_TEST_API_H_
+
+#include "ui/views/controls/textfield/textfield.h"
+
+namespace views {
+
+// Helper class to access internal state of Textfield in tests.
+class TextfieldTestApi {
+ public:
+ explicit TextfieldTestApi(Textfield* textfield);
+
+ void UpdateContextMenu();
+
+ gfx::RenderText* GetRenderText() const;
+
+ void CreateTouchSelectionControllerAndNotifyIt();
+
+ void ResetTouchSelectionController();
+
+ TextfieldModel* model() const { return textfield_->model_.get(); }
+
+ ui::MenuModel* context_menu_contents() const {
+ return textfield_->context_menu_contents_.get();
+ }
+
+ ui::TouchSelectionController* touch_selection_controller() const {
+ return textfield_->touch_selection_controller_.get();
+ }
+
+ private:
+ Textfield* textfield_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextfieldTestApi);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_TEST_API_H_
diff --git a/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index 33196ec3159..8a8f9ace8f5 100644
--- a/chromium/ui/views/controls/textfield/native_textfield_views_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -1,41 +1,35 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/controls/textfield/native_textfield_views.h"
+#include "ui/views/controls/textfield/textfield.h"
#include <set>
#include <string>
#include <vector>
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
#include "base/pickle.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_strings.h"
-#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/render_text.h"
-#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
-#include "ui/views/controls/textfield/textfield_views_model.h"
+#include "ui/views/controls/textfield/textfield_model.h"
+#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/ime/mock_input_method.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"
@@ -43,20 +37,24 @@
#include "base/win/windows_version.h"
#endif
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
+#endif
+
+using base::ASCIIToUTF16;
+using base::UTF8ToUTF16;
+using base::WideToUTF16;
+
#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
namespace {
-const char16 kHebrewLetterSamekh = 0x05E1;
+const base::char16 kHebrewLetterSamekh = 0x05E1;
// A Textfield wrapper to intercept OnKey[Pressed|Released]() ressults.
class TestTextfield : public views::Textfield {
public:
- explicit TestTextfield(StyleFlags style)
- : Textfield(style),
- key_handled_(false),
- key_received_(false) {
- }
+ TestTextfield() : Textfield(), key_handled_(false), key_received_(false) {}
virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
key_received_ = true;
@@ -82,20 +80,6 @@ class TestTextfield : public views::Textfield {
DISALLOW_COPY_AND_ASSIGN(TestTextfield);
};
-// A helper class for use with ui::TextInputClient::GetTextFromRange().
-class GetTextHelper {
- public:
- GetTextHelper() {}
-
- void set_text(const string16& text) { text_ = text; }
- const string16& text() const { return text_; }
-
- private:
- string16 text_;
-
- DISALLOW_COPY_AND_ASSIGN(GetTextHelper);
-};
-
// Convenience to make constructing a GestureEvent simpler.
class GestureEventForTest : public ui::GestureEvent {
public:
@@ -109,24 +93,31 @@ class GestureEventForTest : public ui::GestureEvent {
DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
};
+base::string16 GetClipboardText(ui::ClipboardType type) {
+ base::string16 text;
+ ui::Clipboard::GetForCurrentThread()->ReadText(type, &text);
+ return text;
+}
+
+void SetClipboardText(ui::ClipboardType type, const std::string& text) {
+ ui::ScopedClipboardWriter(ui::Clipboard::GetForCurrentThread(), type)
+ .WriteText(ASCIIToUTF16(text));
+}
+
} // namespace
namespace views {
-// TODO(oshima): Move tests that are independent of TextfieldViews to
-// textfield_unittests.cc once we move the test utility functions
-// from chrome/browser/automation/ to ui/base/test/.
-class NativeTextfieldViewsTest : public ViewsTestBase,
- public TextfieldController {
+class TextfieldTest : public ViewsTestBase, public TextfieldController {
public:
- NativeTextfieldViewsTest()
+ TextfieldTest()
: widget_(NULL),
textfield_(NULL),
- textfield_view_(NULL),
model_(NULL),
input_method_(NULL),
on_before_user_action_(0),
- on_after_user_action_(0) {
+ on_after_user_action_(0),
+ copied_to_clipboard_(ui::CLIPBOARD_TYPE_LAST) {
}
// ::testing::Test:
@@ -140,21 +131,21 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
ViewsTestBase::TearDown();
}
+ ui::ClipboardType GetAndResetCopiedToClipboard() {
+ ui::ClipboardType clipboard_type = copied_to_clipboard_;
+ copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
+ return clipboard_type;
+ }
+
// TextfieldController:
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) OVERRIDE {
+ const base::string16& new_contents) OVERRIDE {
// Paste calls TextfieldController::ContentsChanged() explicitly even if the
// paste action did not change the content. So |new_contents| may match
// |last_contents_|. For more info, see http://crbug.com/79002
last_contents_ = new_contents;
}
- virtual bool HandleKeyEvent(Textfield* sender,
- const ui::KeyEvent& key_event) OVERRIDE {
- // TODO(oshima): figure out how to test the keystroke.
- return false;
- }
-
virtual void OnBeforeUserAction(Textfield* sender) OVERRIDE {
++on_before_user_action_;
}
@@ -163,14 +154,18 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
++on_after_user_action_;
}
- void InitTextfield(Textfield::StyleFlags style) {
- InitTextfields(style, 1);
+ virtual void OnAfterCutOrCopy(ui::ClipboardType clipboard_type) OVERRIDE {
+ copied_to_clipboard_ = clipboard_type;
}
- void InitTextfields(Textfield::StyleFlags style, int count) {
+ void InitTextfield() {
+ InitTextfields(1);
+ }
+
+ void InitTextfields(int count) {
ASSERT_FALSE(textfield_);
- textfield_ = new TestTextfield(style);
- textfield_->SetController(this);
+ textfield_ = new TestTextfield();
+ textfield_->set_controller(this);
widget_ = new Widget();
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.bounds = gfx::Rect(100, 100, 100, 100);
@@ -178,20 +173,17 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
View* container = new View();
widget_->SetContentsView(container);
container->AddChildView(textfield_);
-
- textfield_view_ = static_cast<NativeTextfieldViews*>(
- textfield_->GetNativeWrapperForTesting());
- DCHECK(textfield_view_);
- textfield_view_->SetBoundsRect(params.bounds);
+ textfield_->SetBoundsRect(params.bounds);
textfield_->set_id(1);
+ test_api_.reset(new TextfieldTestApi(textfield_));
for (int i = 1; i < count; i++) {
- Textfield* textfield = new Textfield(style);
+ Textfield* textfield = new Textfield();
container->AddChildView(textfield);
textfield->set_id(i + 1);
}
- model_ = textfield_view_->model_.get();
+ model_ = test_api_->model();
model_->ClearEditHistory();
input_method_ = new MockInputMethod();
@@ -203,12 +195,8 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
}
ui::MenuModel* GetContextMenuModel() {
- textfield_view_->UpdateContextMenu();
- return textfield_view_->context_menu_contents_.get();
- }
-
- ui::TouchSelectionController* GetTouchSelectionController() {
- return textfield_view_->touch_selection_controller_.get();
+ test_api_->UpdateContextMenu();
+ return test_api_->context_menu_contents();
}
protected:
@@ -233,7 +221,7 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
SendKeyEvent(key_code, false, false);
}
- void SendKeyEvent(char16 ch) {
+ void SendKeyEvent(base::char16 ch) {
if (ch < 0x80) {
ui::KeyboardCode code =
ch == ' ' ? ui::VKEY_SPACE :
@@ -246,73 +234,51 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
}
}
- string16 GetClipboardText() const {
- string16 text;
- ui::Clipboard::GetForCurrentThread()->
- ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text);
- return text;
- }
-
- void SetClipboardText(const std::string& text) {
- ui::ScopedClipboardWriter clipboard_writer(
- ui::Clipboard::GetForCurrentThread(),
- ui::CLIPBOARD_TYPE_COPY_PASTE);
- clipboard_writer.WriteText(ASCIIToUTF16(text));
- }
-
View* GetFocusedView() {
return widget_->GetFocusManager()->GetFocusedView();
}
int GetCursorPositionX(int cursor_pos) {
- gfx::RenderText* render_text = textfield_view_->GetRenderText();
- return render_text->GetCursorBounds(
+ return test_api_->GetRenderText()->GetCursorBounds(
gfx::SelectionModel(cursor_pos, gfx::CURSOR_FORWARD), false).x();
}
// Get the current cursor bounds.
gfx::Rect GetCursorBounds() {
- gfx::RenderText* render_text = textfield_view_->GetRenderText();
- gfx::Rect bounds = render_text->GetUpdatedCursorBounds();
- return bounds;
+ return test_api_->GetRenderText()->GetUpdatedCursorBounds();
}
// Get the cursor bounds of |sel|.
gfx::Rect GetCursorBounds(const gfx::SelectionModel& sel) {
- gfx::RenderText* render_text = textfield_view_->GetRenderText();
- gfx::Rect bounds = render_text->GetCursorBounds(sel, true);
- return bounds;
+ return test_api_->GetRenderText()->GetCursorBounds(sel, true);
}
gfx::Rect GetDisplayRect() {
- return textfield_view_->GetRenderText()->display_rect();
+ return test_api_->GetRenderText()->display_rect();
}
// Mouse click on the point whose x-axis is |bound|'s x plus |x_offset| and
// y-axis is in the middle of |bound|'s vertical range.
void MouseClick(const gfx::Rect bound, int x_offset) {
- gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
+ gfx::Point point(bound.x() + x_offset, bound.y() + bound.height() / 2);
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMouseReleased(release);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release);
}
// This is to avoid double/triple click.
void NonClientMouseClick() {
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT);
- textfield_view_->OnMousePressed(click);
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT);
- textfield_view_->OnMouseReleased(release);
- }
-
- // Wrap for visibility in test classes.
- ui::TextInputType GetTextInputType() {
- return textfield_view_->GetTextInputType();
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_NON_CLIENT,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release);
}
void VerifyTextfieldContextMenuContents(bool textfield_has_selection,
@@ -322,7 +288,8 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
EXPECT_TRUE(menu->IsEnabledAt(1 /* Separator */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(2 /* CUT */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(3 /* COPY */));
- EXPECT_NE(GetClipboardText().empty(), menu->IsEnabledAt(4 /* PASTE */));
+ EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
+ menu->IsEnabledAt(4 /* PASTE */));
EXPECT_EQ(textfield_has_selection, menu->IsEnabledAt(5 /* DELETE */));
EXPECT_TRUE(menu->IsEnabledAt(6 /* Separator */));
EXPECT_TRUE(menu->IsEnabledAt(7 /* SELECT ALL */));
@@ -332,11 +299,11 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
Widget* widget_;
TestTextfield* textfield_;
- NativeTextfieldViews* textfield_view_;
- TextfieldViewsModel* model_;
+ scoped_ptr<TextfieldTestApi> test_api_;
+ TextfieldModel* model_;
// The string from Controller::ContentsChanged callback.
- string16 last_contents_;
+ base::string16 last_contents_;
// For testing input method related behaviors.
MockInputMethod* input_method_;
@@ -348,112 +315,36 @@ class NativeTextfieldViewsTest : public ViewsTestBase,
int on_after_user_action_;
private:
- DISALLOW_COPY_AND_ASSIGN(NativeTextfieldViewsTest);
+ ui::ClipboardType copied_to_clipboard_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
};
-TEST_F(NativeTextfieldViewsTest, ModelChangesTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, ModelChangesTest) {
+ InitTextfield();
// TextfieldController::ContentsChanged() shouldn't be called when changing
// text programmatically.
last_contents_.clear();
textfield_->SetText(ASCIIToUTF16("this is"));
- EXPECT_STR_EQ("this is", model_->GetText());
+ EXPECT_STR_EQ("this is", model_->text());
EXPECT_STR_EQ("this is", textfield_->text());
EXPECT_TRUE(last_contents_.empty());
textfield_->AppendText(ASCIIToUTF16(" a test"));
- EXPECT_STR_EQ("this is a test", model_->GetText());
+ EXPECT_STR_EQ("this is a test", model_->text());
EXPECT_STR_EQ("this is a test", textfield_->text());
EXPECT_TRUE(last_contents_.empty());
- EXPECT_EQ(string16(), textfield_->GetSelectedText());
+ EXPECT_EQ(base::string16(), textfield_->GetSelectedText());
textfield_->SelectAll(false);
EXPECT_STR_EQ("this is a test", textfield_->GetSelectedText());
EXPECT_TRUE(last_contents_.empty());
}
-TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCase) {
- // Check if |model_|'s text is properly lowercased for STYLE_LOWERCASE.
- InitTextfield(Textfield::STYLE_LOWERCASE);
- EXPECT_EQ(0U, textfield_->GetCursorPosition());
-
- last_contents_.clear();
- textfield_->SetText(ASCIIToUTF16("THIS IS"));
- EXPECT_EQ(7U, textfield_->GetCursorPosition());
-
- EXPECT_STR_EQ("this is", model_->GetText());
- EXPECT_STR_EQ("THIS IS", textfield_->text());
- EXPECT_TRUE(last_contents_.empty());
-
- textfield_->AppendText(ASCIIToUTF16(" A TEST"));
- EXPECT_EQ(7U, textfield_->GetCursorPosition());
- EXPECT_STR_EQ("this is a test", model_->GetText());
- EXPECT_STR_EQ("THIS IS A TEST", textfield_->text());
-
- EXPECT_TRUE(last_contents_.empty());
-}
-
-TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCaseI18n) {
- // Check if lower case conversion works for non-ASCII characters.
- InitTextfield(Textfield::STYLE_LOWERCASE);
- EXPECT_EQ(0U, textfield_->GetCursorPosition());
-
- last_contents_.clear();
- // Zenkaku Japanese "ABCabc"
- textfield_->SetText(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43"));
- EXPECT_EQ(6U, textfield_->GetCursorPosition());
- // Zenkaku Japanese "abcabc"
- EXPECT_EQ(WideToUTF16(L"\xFF41\xFF42\xFF43\xFF41\xFF42\xFF43"),
- model_->GetText());
- // Zenkaku Japanese "ABCabc"
- EXPECT_EQ(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43"),
- textfield_->text());
- EXPECT_TRUE(last_contents_.empty());
-
- // Zenkaku Japanese "XYZxyz"
- textfield_->AppendText(WideToUTF16(L"\xFF38\xFF39\xFF3A\xFF58\xFF59\xFF5A"));
- EXPECT_EQ(6U, textfield_->GetCursorPosition());
- // Zenkaku Japanese "abcabcxyzxyz"
- EXPECT_EQ(WideToUTF16(L"\xFF41\xFF42\xFF43\xFF41\xFF42\xFF43"
- L"\xFF58\xFF59\xFF5A\xFF58\xFF59\xFF5A"),
- model_->GetText());
- // Zenkaku Japanese "ABCabcXYZxyz"
- EXPECT_EQ(WideToUTF16(L"\xFF21\xFF22\xFF23\xFF41\xFF42\xFF43"
- L"\xFF38\xFF39\xFF3A\xFF58\xFF59\xFF5A"),
- textfield_->text());
- EXPECT_TRUE(last_contents_.empty());
-}
-
-TEST_F(NativeTextfieldViewsTest, ModelChangesTestLowerCaseWithLocale) {
- // Check if lower case conversion honors locale properly.
- std::string locale = l10n_util::GetApplicationLocale("");
- base::i18n::SetICUDefaultLocale("tr");
-
- InitTextfield(Textfield::STYLE_LOWERCASE);
- EXPECT_EQ(0U, textfield_->GetCursorPosition());
-
- last_contents_.clear();
- // Turkish 'I' should be converted to dotless 'i' (U+0131).
- textfield_->SetText(WideToUTF16(L"I"));
- EXPECT_EQ(1U, textfield_->GetCursorPosition());
- EXPECT_EQ(WideToUTF16(L"\x0131"), model_->GetText());
- EXPECT_EQ(WideToUTF16(L"I"), textfield_->text());
- EXPECT_TRUE(last_contents_.empty());
-
- base::i18n::SetICUDefaultLocale(locale);
-
- // On default (en) locale, 'I' should be converted to 'i'.
- textfield_->SetText(WideToUTF16(L"I"));
- EXPECT_EQ(1U, textfield_->GetCursorPosition());
- EXPECT_EQ(WideToUTF16(L"i"), model_->GetText());
- EXPECT_EQ(WideToUTF16(L"I"), textfield_->text());
- EXPECT_TRUE(last_contents_.empty());
-}
-
-TEST_F(NativeTextfieldViewsTest, KeyTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, KeyTest) {
+ InitTextfield();
// Event flags: key, alt, shift, ctrl, caps-lock.
SendKeyEvent(ui::VKEY_T, false, true, false, false);
SendKeyEvent(ui::VKEY_E, false, false, false, false);
@@ -466,9 +357,9 @@ TEST_F(NativeTextfieldViewsTest, KeyTest) {
EXPECT_STR_EQ("TexT!1!1", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, ControlAndSelectTest) {
+TEST_F(TextfieldTest, ControlAndSelectTest) {
// Insert a test string in a textfield.
- InitTextfield(Textfield::STYLE_DEFAULT);
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("one two three"));
SendKeyEvent(ui::VKEY_HOME, false /* shift */, false /* control */);
SendKeyEvent(ui::VKEY_RIGHT, true, false);
@@ -501,9 +392,9 @@ TEST_F(NativeTextfieldViewsTest, ControlAndSelectTest) {
EXPECT_STR_EQ("ZERO ", textfield_->GetSelectedText());
}
-TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) {
+TEST_F(TextfieldTest, InsertionDeletionTest) {
// Insert a test string in a textfield.
- InitTextfield(Textfield::STYLE_DEFAULT);
+ InitTextfield();
for (size_t i = 0; i < 10; i++)
SendKeyEvent(static_cast<ui::KeyboardCode>(ui::VKEY_A + i));
EXPECT_STR_EQ("abcdefghij", textfield_->text());
@@ -528,13 +419,13 @@ TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) {
SendKeyEvent(ui::VKEY_BACK, false, false, true, false);
EXPECT_STR_EQ("one two three ", textfield_->text());
- // Delete text preceeding the cursor in chromeos, do nothing in windows.
+ // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
SendKeyEvent(ui::VKEY_LEFT, false, false, true, false);
SendKeyEvent(ui::VKEY_BACK, false, true, true, false);
-#if defined(OS_WIN)
- EXPECT_STR_EQ("one two three ", textfield_->text());
-#else
+#if defined(OS_LINUX)
EXPECT_STR_EQ("three ", textfield_->text());
+#else
+ EXPECT_STR_EQ("one three ", textfield_->text());
#endif
// Delete the next word from cursor.
@@ -543,21 +434,22 @@ TEST_F(NativeTextfieldViewsTest, InsertionDeletionTest) {
SendKeyEvent(ui::VKEY_DELETE, false, false, true, false);
EXPECT_STR_EQ(" two three four", textfield_->text());
- // Delete text following the cursor in chromeos, do nothing in windows.
+ // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false);
SendKeyEvent(ui::VKEY_DELETE, false, true, true, false);
-#if defined(OS_WIN)
- EXPECT_STR_EQ(" two three four", textfield_->text());
-#else
+#if defined(OS_LINUX)
EXPECT_STR_EQ(" two", textfield_->text());
+#else
+ EXPECT_STR_EQ(" two four", textfield_->text());
#endif
}
-TEST_F(NativeTextfieldViewsTest, PasswordTest) {
- InitTextfield(Textfield::STYLE_OBSCURED);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
+TEST_F(TextfieldTest, PasswordTest) {
+ InitTextfield();
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
EXPECT_TRUE(textfield_->enabled());
- EXPECT_TRUE(textfield_->focusable());
+ EXPECT_TRUE(textfield_->IsFocusable());
last_contents_.clear();
textfield_->SetText(ASCIIToUTF16("password"));
@@ -565,143 +457,154 @@ TEST_F(NativeTextfieldViewsTest, PasswordTest) {
EXPECT_STR_EQ("password", textfield_->text());
EXPECT_TRUE(last_contents_.empty());
model_->SelectAll(false);
- SetClipboardText("foo");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
// Cut and copy should be disabled.
- EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT));
- textfield_view_->ExecuteCommand(IDS_APP_CUT, 0);
+ EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
+ textfield_->ExecuteCommand(IDS_APP_CUT, 0);
SendKeyEvent(ui::VKEY_X, false, true);
- EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY));
- textfield_view_->ExecuteCommand(IDS_APP_COPY, 0);
+ EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
+ textfield_->ExecuteCommand(IDS_APP_COPY, 0);
SendKeyEvent(ui::VKEY_C, false, true);
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("foo", string16(GetClipboardText()));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("password", textfield_->text());
// [Shift]+[Delete] should just delete without copying text to the clipboard.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_DELETE, true, false);
// Paste should work normally.
- EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE));
- textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0);
+ EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
+ textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendKeyEvent(ui::VKEY_INSERT, true, false);
- EXPECT_STR_EQ("foo", string16(GetClipboardText()));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("foofoofoo", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, InputTypeSetsObscured) {
- InitTextfield(Textfield::STYLE_DEFAULT);
-
- // Defaults to TEXT
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType());
-
- // Setting to TEXT_INPUT_TYPE_PASSWORD also sets obscured state of textfield.
- textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
- EXPECT_TRUE(textfield_->IsObscured());
-}
-
-TEST_F(NativeTextfieldViewsTest, ObscuredSetsInputType) {
- InitTextfield(Textfield::STYLE_DEFAULT);
-
- // Defaults to TEXT
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType());
-
- textfield_->SetObscured(true);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, GetTextInputType());
-
- textfield_->SetObscured(false);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType());
-}
-
-TEST_F(NativeTextfieldViewsTest, TextInputType) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, TextInputType) {
+ InitTextfield();
// Defaults to TEXT
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, textfield_->GetTextInputType());
// And can be set.
textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_URL);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, textfield_->GetTextInputType());
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
// Readonly textfields have type NONE
textfield_->SetReadOnly(true);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
textfield_->SetReadOnly(false);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_URL, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
// As do disabled textfields
textfield_->SetEnabled(false);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, GetTextInputType());
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, textfield_->GetTextInputType());
+
+ textfield_->SetEnabled(true);
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
}
-TEST_F(NativeTextfieldViewsTest, OnKeyPressReturnValueTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, OnKeyPress) {
+ InitTextfield();
- // Character keys will be handled by input method.
+ // Character keys are handled by the input method.
SendKeyEvent(ui::VKEY_A);
EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled());
textfield_->clear();
- // Home will be handled.
- SendKeyEvent(ui::VKEY_HOME);
+ // Arrow keys and home/end are handled by the textfield.
+ SendKeyEvent(ui::VKEY_LEFT);
EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled());
textfield_->clear();
- // F24, up/down key won't be handled.
- SendKeyEvent(ui::VKEY_F24);
+ SendKeyEvent(ui::VKEY_RIGHT);
EXPECT_TRUE(textfield_->key_received());
- EXPECT_FALSE(textfield_->key_handled());
+ EXPECT_TRUE(textfield_->key_handled());
textfield_->clear();
- SendKeyEvent(ui::VKEY_UP);
+ SendKeyEvent(ui::VKEY_HOME);
EXPECT_TRUE(textfield_->key_received());
- EXPECT_FALSE(textfield_->key_handled());
+ EXPECT_TRUE(textfield_->key_handled());
textfield_->clear();
- SendKeyEvent(ui::VKEY_DOWN);
+ SendKeyEvent(ui::VKEY_END);
EXPECT_TRUE(textfield_->key_received());
- EXPECT_FALSE(textfield_->key_handled());
+ EXPECT_TRUE(textfield_->key_handled());
textfield_->clear();
- // Empty Textfield does not handle left/right.
- textfield_->SetText(string16());
- SendKeyEvent(ui::VKEY_LEFT);
+ // F24, up/down key won't be handled.
+ SendKeyEvent(ui::VKEY_F24);
EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled());
textfield_->clear();
- SendKeyEvent(ui::VKEY_RIGHT);
+ SendKeyEvent(ui::VKEY_UP);
EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled());
textfield_->clear();
- // Add a char. Right key should not be handled when cursor is at the end.
- SendKeyEvent(ui::VKEY_B);
- SendKeyEvent(ui::VKEY_RIGHT);
+ SendKeyEvent(ui::VKEY_DOWN);
EXPECT_TRUE(textfield_->key_received());
EXPECT_FALSE(textfield_->key_handled());
textfield_->clear();
+}
- // First left key is handled to move cursor left to the beginning.
- SendKeyEvent(ui::VKEY_LEFT);
+// Tests that default key bindings are handled even with a delegate installed.
+TEST_F(TextfieldTest, OnKeyPressBinding) {
+ InitTextfield();
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Install a TextEditKeyBindingsDelegateAuraLinux that does nothing.
+ class TestDelegate : public ui::TextEditKeyBindingsDelegateAuraLinux {
+ public:
+ TestDelegate() {}
+ virtual ~TestDelegate() {}
+
+ virtual bool MatchEvent(
+ const ui::Event& event,
+ std::vector<ui::TextEditCommandAuraLinux>* commands) OVERRIDE {
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestDelegate);
+ };
+
+ TestDelegate delegate;
+ ui::SetTextEditKeyBindingsDelegate(&delegate);
+#endif
+
+ SendKeyEvent(ui::VKEY_A, false, false);
+ EXPECT_STR_EQ("a", textfield_->text());
+ textfield_->clear();
+
+ // Undo/Redo command keys are handled by the textfield.
+ SendKeyEvent(ui::VKEY_Z, false, true);
EXPECT_TRUE(textfield_->key_received());
EXPECT_TRUE(textfield_->key_handled());
+ EXPECT_TRUE(textfield_->text().empty());
textfield_->clear();
- // Now left key should not be handled.
- SendKeyEvent(ui::VKEY_LEFT);
+ SendKeyEvent(ui::VKEY_Z, true, true);
EXPECT_TRUE(textfield_->key_received());
- EXPECT_FALSE(textfield_->key_handled());
+ EXPECT_TRUE(textfield_->key_handled());
+ EXPECT_STR_EQ("a", textfield_->text());
textfield_->clear();
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ ui::SetTextEditKeyBindingsDelegate(NULL);
+#endif
}
-TEST_F(NativeTextfieldViewsTest, CursorMovement) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, CursorMovement) {
+ InitTextfield();
// Test with trailing whitespace.
textfield_->SetText(ASCIIToUTF16("one two hre "));
@@ -750,8 +653,8 @@ TEST_F(NativeTextfieldViewsTest, CursorMovement) {
EXPECT_STR_EQ("one two", last_contents_);
}
-TEST_F(NativeTextfieldViewsTest, FocusTraversalTest) {
- InitTextfields(Textfield::STYLE_DEFAULT, 3);
+TEST_F(TextfieldTest, FocusTraversalTest) {
+ InitTextfields(3);
textfield_->RequestFocus();
EXPECT_EQ(1, GetFocusedView()->id());
@@ -777,21 +680,21 @@ TEST_F(NativeTextfieldViewsTest, FocusTraversalTest) {
textfield_->RequestFocus();
EXPECT_EQ(1, GetFocusedView()->id());
- // Test if clicking on textfield view sets the focus to textfield_.
+ // Test if clicking on textfield view sets the focus.
widget_->GetFocusManager()->AdvanceFocus(true);
EXPECT_EQ(3, GetFocusedView()->id());
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click);
EXPECT_EQ(1, GetFocusedView()->id());
}
-TEST_F(NativeTextfieldViewsTest, ContextMenuDisplayTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, ContextMenuDisplayTest) {
+ InitTextfield();
EXPECT_TRUE(textfield_->context_menu_controller());
textfield_->SetText(ASCIIToUTF16("hello world"));
ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
- textfield_view_->ClearEditHistory();
+ textfield_->ClearEditHistory();
EXPECT_TRUE(GetContextMenuModel());
VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
@@ -805,183 +708,183 @@ TEST_F(NativeTextfieldViewsTest, ContextMenuDisplayTest) {
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
// Exercise the "paste enabled?" check in the verifier.
- SetClipboardText("Test");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
}
-TEST_F(NativeTextfieldViewsTest, DoubleAndTripleClickTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DoubleAndTripleClickTest) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent double_click(
ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK);
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
+ ui::EF_LEFT_MOUSE_BUTTON);
// Test for double click.
- textfield_view_->OnMousePressed(click);
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMousePressed(click);
+ textfield_->OnMouseReleased(release);
EXPECT_TRUE(textfield_->GetSelectedText().empty());
- textfield_view_->OnMousePressed(double_click);
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMousePressed(double_click);
+ textfield_->OnMouseReleased(release);
EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
// Test for triple click.
- textfield_view_->OnMousePressed(click);
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMousePressed(click);
+ textfield_->OnMouseReleased(release);
EXPECT_STR_EQ("hello world", textfield_->GetSelectedText());
// Another click should reset back to double click.
- textfield_view_->OnMousePressed(click);
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMousePressed(click);
+ textfield_->OnMouseReleased(release);
EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
}
-TEST_F(NativeTextfieldViewsTest, DragToSelect) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragToSelect) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
const int kStart = GetCursorPositionX(5);
const int kEnd = 500;
gfx::Point start_point(kStart, 0);
gfx::Point end_point(kEnd, 0);
ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, start_point, start_point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent click_b(ui::ET_MOUSE_PRESSED, end_point, end_point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent drag_left(ui::ET_MOUSE_DRAGGED, gfx::Point(), gfx::Point(),
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
ui::MouseEvent drag_right(ui::ET_MOUSE_DRAGGED, end_point, end_point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, end_point, end_point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click_a);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click_a);
EXPECT_TRUE(textfield_->GetSelectedText().empty());
// Check that dragging left selects the beginning of the string.
- textfield_view_->OnMouseDragged(drag_left);
- string16 text_left = textfield_->GetSelectedText();
+ textfield_->OnMouseDragged(drag_left);
+ base::string16 text_left = textfield_->GetSelectedText();
EXPECT_STR_EQ("hello", text_left);
// Check that dragging right selects the rest of the string.
- textfield_view_->OnMouseDragged(drag_right);
- string16 text_right = textfield_->GetSelectedText();
+ textfield_->OnMouseDragged(drag_right);
+ base::string16 text_right = textfield_->GetSelectedText();
EXPECT_STR_EQ(" world", text_right);
// Check that releasing in the same location does not alter the selection.
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMouseReleased(release);
EXPECT_EQ(text_right, textfield_->GetSelectedText());
// Check that dragging from beyond the text length works too.
- textfield_view_->OnMousePressed(click_b);
- textfield_view_->OnMouseDragged(drag_left);
- textfield_view_->OnMouseReleased(release);
+ textfield_->OnMousePressed(click_b);
+ textfield_->OnMouseDragged(drag_left);
+ textfield_->OnMouseReleased(release);
EXPECT_EQ(textfield_->text(), textfield_->GetSelectedText());
}
#if defined(OS_WIN)
-TEST_F(NativeTextfieldViewsTest, DragAndDrop_AcceptDrop) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragAndDrop_AcceptDrop) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
ui::OSExchangeData data;
- string16 string(ASCIIToUTF16("string "));
+ base::string16 string(ASCIIToUTF16("string "));
data.SetString(string);
int formats = 0;
std::set<OSExchangeData::CustomFormat> custom_formats;
// Ensure that disabled textfields do not accept drops.
textfield_->SetEnabled(false);
- EXPECT_FALSE(textfield_view_->GetDropFormats(&formats, &custom_formats));
+ EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
EXPECT_EQ(0, formats);
EXPECT_TRUE(custom_formats.empty());
- EXPECT_FALSE(textfield_view_->CanDrop(data));
+ EXPECT_FALSE(textfield_->CanDrop(data));
textfield_->SetEnabled(true);
// Ensure that read-only textfields do not accept drops.
textfield_->SetReadOnly(true);
- EXPECT_FALSE(textfield_view_->GetDropFormats(&formats, &custom_formats));
+ EXPECT_FALSE(textfield_->GetDropFormats(&formats, &custom_formats));
EXPECT_EQ(0, formats);
EXPECT_TRUE(custom_formats.empty());
- EXPECT_FALSE(textfield_view_->CanDrop(data));
+ EXPECT_FALSE(textfield_->CanDrop(data));
textfield_->SetReadOnly(false);
// Ensure that enabled and editable textfields do accept drops.
- EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats));
+ EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
EXPECT_EQ(ui::OSExchangeData::STRING, formats);
EXPECT_TRUE(custom_formats.empty());
- EXPECT_TRUE(textfield_view_->CanDrop(data));
+ EXPECT_TRUE(textfield_->CanDrop(data));
gfx::Point drop_point(GetCursorPositionX(6), 0);
ui::DropTargetEvent drop(data, drop_point, drop_point,
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE);
EXPECT_EQ(ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_MOVE,
- textfield_view_->OnDragUpdated(drop));
- EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_view_->OnPerformDrop(drop));
+ textfield_->OnDragUpdated(drop));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, textfield_->OnPerformDrop(drop));
EXPECT_STR_EQ("hello string world", textfield_->text());
// Ensure that textfields do not accept non-OSExchangeData::STRING types.
ui::OSExchangeData bad_data;
bad_data.SetFilename(base::FilePath(FILE_PATH_LITERAL("x")));
-#if defined(OS_WIN)
ui::OSExchangeData::CustomFormat fmt = ui::Clipboard::GetBitmapFormatType();
bad_data.SetPickledData(fmt, Pickle());
bad_data.SetFileContents(base::FilePath(L"x"), "x");
- bad_data.SetHtml(string16(ASCIIToUTF16("x")), GURL("x.org"));
+ bad_data.SetHtml(base::string16(ASCIIToUTF16("x")), GURL("x.org"));
ui::OSExchangeData::DownloadFileInfo download(base::FilePath(), NULL);
bad_data.SetDownloadFileInfo(download);
-#endif
- EXPECT_FALSE(textfield_view_->CanDrop(bad_data));
+ EXPECT_FALSE(textfield_->CanDrop(bad_data));
}
#endif
-TEST_F(NativeTextfieldViewsTest, DragAndDrop_InitiateDrag) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragAndDrop_InitiateDrag) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello string world"));
// Ensure the textfield will provide selected text for drag data.
- string16 string;
+ base::string16 string;
ui::OSExchangeData data;
const gfx::Range kStringRange(6, 12);
textfield_->SelectRange(kStringRange);
const gfx::Point kStringPoint(GetCursorPositionX(9), 0);
- textfield_view_->WriteDragDataForView(NULL, kStringPoint, &data);
+ textfield_->WriteDragDataForView(NULL, kStringPoint, &data);
EXPECT_TRUE(data.GetString(&string));
EXPECT_EQ(textfield_->GetSelectedText(), string);
// Ensure that disabled textfields do not support drag operations.
textfield_->SetEnabled(false);
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
- textfield_view_->GetDragOperationsForView(NULL, kStringPoint));
+ textfield_->GetDragOperationsForView(NULL, kStringPoint));
textfield_->SetEnabled(true);
// Ensure that textfields without selections do not support drag operations.
textfield_->ClearSelection();
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
- textfield_view_->GetDragOperationsForView(NULL, kStringPoint));
+ textfield_->GetDragOperationsForView(NULL, kStringPoint));
textfield_->SelectRange(kStringRange);
// Ensure that password textfields do not support drag operations.
- textfield_->SetObscured(true);
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
- textfield_view_->GetDragOperationsForView(NULL, kStringPoint));
- textfield_->SetObscured(false);
+ textfield_->GetDragOperationsForView(NULL, kStringPoint));
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
// Ensure that textfields only initiate drag operations inside the selection.
ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, kStringPoint, kStringPoint,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(press_event);
+ textfield_->OnMousePressed(press_event);
EXPECT_EQ(ui::DragDropTypes::DRAG_NONE,
- textfield_view_->GetDragOperationsForView(NULL, gfx::Point()));
- EXPECT_FALSE(textfield_view_->CanStartDragForView(NULL, gfx::Point(),
- gfx::Point()));
+ textfield_->GetDragOperationsForView(NULL, gfx::Point()));
+ EXPECT_FALSE(textfield_->CanStartDragForView(NULL, gfx::Point(),
+ gfx::Point()));
EXPECT_EQ(ui::DragDropTypes::DRAG_COPY,
- textfield_view_->GetDragOperationsForView(NULL, kStringPoint));
- EXPECT_TRUE(textfield_view_->CanStartDragForView(NULL, kStringPoint,
- gfx::Point()));
+ textfield_->GetDragOperationsForView(NULL, kStringPoint));
+ EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
+ gfx::Point()));
// Ensure that textfields support local moves.
EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
- textfield_view_->GetDragOperationsForView(textfield_view_, kStringPoint));
+ textfield_->GetDragOperationsForView(textfield_, kStringPoint));
}
-TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheRight) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragAndDrop_ToTheRight) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
- string16 string;
+ base::string16 string;
ui::OSExchangeData data;
int formats = 0;
int operations = 0;
@@ -991,31 +894,29 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheRight) {
textfield_->SelectRange(gfx::Range(1, 5));
gfx::Point point(GetCursorPositionX(3), 0);
ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click_a);
- EXPECT_TRUE(textfield_view_->CanStartDragForView(textfield_view_,
- click_a.location(), gfx::Point()));
- operations = textfield_view_->GetDragOperationsForView(textfield_view_,
- click_a.location());
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click_a);
+ EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
+ gfx::Point()));
+ operations = textfield_->GetDragOperationsForView(textfield_,
+ click_a.location());
EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
operations);
- textfield_view_->WriteDragDataForView(NULL, click_a.location(), &data);
+ textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
EXPECT_TRUE(data.GetString(&string));
EXPECT_EQ(textfield_->GetSelectedText(), string);
- EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats));
+ EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
EXPECT_EQ(ui::OSExchangeData::STRING, formats);
EXPECT_TRUE(custom_formats.empty());
// Drop "ello" after "w".
const gfx::Point kDropPoint(GetCursorPositionX(7), 0);
- EXPECT_TRUE(textfield_view_->CanDrop(data));
+ EXPECT_TRUE(textfield_->CanDrop(data));
ui::DropTargetEvent drop_a(data, kDropPoint, kDropPoint, operations);
- EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE,
- textfield_view_->OnDragUpdated(drop_a));
- EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE,
- textfield_view_->OnPerformDrop(drop_a));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
EXPECT_STR_EQ("h welloorld", textfield_->text());
- textfield_view_->OnDragDone();
+ textfield_->OnDragDone();
// Undo/Redo the drag&drop change.
SendKeyEvent(ui::VKEY_Z, false, true);
@@ -1032,11 +933,11 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheRight) {
EXPECT_STR_EQ("h welloorld", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheLeft) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragAndDrop_ToTheLeft) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
- string16 string;
+ base::string16 string;
ui::OSExchangeData data;
int formats = 0;
int operations = 0;
@@ -1046,31 +947,29 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheLeft) {
textfield_->SelectRange(gfx::Range(5, 10));
gfx::Point point(GetCursorPositionX(7), 0);
ui::MouseEvent click_a(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click_a);
- EXPECT_TRUE(textfield_view_->CanStartDragForView(textfield_view_,
- click_a.location(), gfx::Point()));
- operations = textfield_view_->GetDragOperationsForView(textfield_view_,
- click_a.location());
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click_a);
+ EXPECT_TRUE(textfield_->CanStartDragForView(textfield_, click_a.location(),
+ gfx::Point()));
+ operations = textfield_->GetDragOperationsForView(textfield_,
+ click_a.location());
EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE | ui::DragDropTypes::DRAG_COPY,
operations);
- textfield_view_->WriteDragDataForView(NULL, click_a.location(), &data);
+ textfield_->WriteDragDataForView(NULL, click_a.location(), &data);
EXPECT_TRUE(data.GetString(&string));
EXPECT_EQ(textfield_->GetSelectedText(), string);
- EXPECT_TRUE(textfield_view_->GetDropFormats(&formats, &custom_formats));
+ EXPECT_TRUE(textfield_->GetDropFormats(&formats, &custom_formats));
EXPECT_EQ(ui::OSExchangeData::STRING, formats);
EXPECT_TRUE(custom_formats.empty());
// Drop " worl" after "h".
- EXPECT_TRUE(textfield_view_->CanDrop(data));
+ EXPECT_TRUE(textfield_->CanDrop(data));
gfx::Point drop_point(GetCursorPositionX(1), 0);
ui::DropTargetEvent drop_a(data, drop_point, drop_point, operations);
- EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE,
- textfield_view_->OnDragUpdated(drop_a));
- EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE,
- textfield_view_->OnPerformDrop(drop_a));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop_a));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnPerformDrop(drop_a));
EXPECT_STR_EQ("h worlellod", textfield_->text());
- textfield_view_->OnDragDone();
+ textfield_->OnDragDone();
// Undo/Redo the drag&drop change.
SendKeyEvent(ui::VKEY_Z, false, true);
@@ -1087,42 +986,42 @@ TEST_F(NativeTextfieldViewsTest, DragAndDrop_ToTheLeft) {
EXPECT_STR_EQ("h worlellod", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, DragAndDrop_Canceled) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, DragAndDrop_Canceled) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
// Start dragging "worl".
textfield_->SelectRange(gfx::Range(6, 10));
gfx::Point point(GetCursorPositionX(8), 0);
ui::MouseEvent click(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(click);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(click);
ui::OSExchangeData data;
- textfield_view_->WriteDragDataForView(NULL, click.location(), &data);
- EXPECT_TRUE(textfield_view_->CanDrop(data));
+ textfield_->WriteDragDataForView(NULL, click.location(), &data);
+ EXPECT_TRUE(textfield_->CanDrop(data));
// Drag the text over somewhere valid, outside the current selection.
gfx::Point drop_point(GetCursorPositionX(2), 0);
ui::DropTargetEvent drop(data, drop_point, drop_point,
ui::DragDropTypes::DRAG_MOVE);
- EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_view_->OnDragUpdated(drop));
+ EXPECT_EQ(ui::DragDropTypes::DRAG_MOVE, textfield_->OnDragUpdated(drop));
// "Cancel" the drag, via move and release over the selection, and OnDragDone.
gfx::Point drag_point(GetCursorPositionX(9), 0);
ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, drag_point, drag_point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, drag_point, drag_point,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMouseDragged(drag);
- textfield_view_->OnMouseReleased(release);
- textfield_view_->OnDragDone();
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseDragged(drag);
+ textfield_->OnMouseReleased(release);
+ textfield_->OnDragDone();
EXPECT_EQ(ASCIIToUTF16("hello world"), textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, ReadOnlyTest) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("read only"));
textfield_->SetReadOnly(true);
EXPECT_TRUE(textfield_->enabled());
- EXPECT_TRUE(textfield_->focusable());
+ EXPECT_TRUE(textfield_->IsFocusable());
SendKeyEvent(ui::VKEY_HOME);
EXPECT_EQ(0U, textfield_->GetCursorPosition());
@@ -1140,32 +1039,32 @@ TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) {
EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
// Cut should be disabled.
- SetClipboardText("Test");
- EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT));
- textfield_view_->ExecuteCommand(IDS_APP_CUT, 0);
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
+ textfield_->ExecuteCommand(IDS_APP_CUT, 0);
SendKeyEvent(ui::VKEY_X, false, true);
SendKeyEvent(ui::VKEY_DELETE, true, false);
- EXPECT_STR_EQ("Test", string16(GetClipboardText()));
+ EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("read only", textfield_->text());
// Paste should be disabled.
- EXPECT_FALSE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE));
- textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0);
+ EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
+ textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendKeyEvent(ui::VKEY_INSERT, true, false);
EXPECT_STR_EQ("read only", textfield_->text());
// Copy should work normally.
- SetClipboardText("Test");
- EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY));
- textfield_view_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("read only", string16(GetClipboardText()));
- SetClipboardText("Test");
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "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");
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("read only", string16(GetClipboardText()));
- SetClipboardText("Test");
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("read only", string16(GetClipboardText()));
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
// SetText should work even in read only mode.
textfield_->SetText(ASCIIToUTF16(" four five six "));
@@ -1183,8 +1082,8 @@ TEST_F(NativeTextfieldViewsTest, ReadOnlyTest) {
EXPECT_STR_EQ(" four five six ", textfield_->GetSelectedText());
}
-TEST_F(NativeTextfieldViewsTest, TextInputClientTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, TextInputClientTest) {
+ InitTextfield();
ui::TextInputClient* client = textfield_->GetTextInputClient();
EXPECT_TRUE(client);
EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, client->GetTextInputType());
@@ -1199,15 +1098,9 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) {
EXPECT_TRUE(client->GetSelectionRange(&range));
EXPECT_EQ(gfx::Range(1, 4), range);
- // This code can't be compiled because of a bug in base::Callback.
-#if 0
- GetTextHelper helper;
- base::Callback<void(string16)> callback =
- base::Bind(&GetTextHelper::set_text, base::Unretained(&helper));
-
- EXPECT_TRUE(client->GetTextFromRange(range, callback));
- EXPECT_STR_EQ("123", helper.text());
-#endif
+ base::string16 substring;
+ EXPECT_TRUE(client->GetTextFromRange(range, &substring));
+ EXPECT_STR_EQ("123", substring);
EXPECT_TRUE(client->DeleteRange(range));
EXPECT_STR_EQ("0456789", textfield_->text());
@@ -1227,8 +1120,8 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) {
EXPECT_TRUE(client->GetCompositionTextRange(&range));
EXPECT_STR_EQ("0321456789", textfield_->text());
EXPECT_EQ(gfx::Range(1, 4), range);
- EXPECT_EQ(2, on_before_user_action_);
- EXPECT_EQ(2, on_after_user_action_);
+ EXPECT_EQ(1, on_before_user_action_);
+ EXPECT_EQ(1, on_after_user_action_);
input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
on_before_user_action_ = on_after_user_action_ = 0;
@@ -1239,8 +1132,8 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) {
EXPECT_FALSE(client->HasCompositionText());
EXPECT_FALSE(input_method_->cancel_composition_called());
EXPECT_STR_EQ("0123456789", textfield_->text());
- EXPECT_EQ(2, on_before_user_action_);
- EXPECT_EQ(2, on_after_user_action_);
+ EXPECT_EQ(1, on_before_user_action_);
+ EXPECT_EQ(1, on_after_user_action_);
input_method_->Clear();
input_method_->SetCompositionTextForNextKey(composition);
@@ -1283,13 +1176,13 @@ TEST_F(NativeTextfieldViewsTest, TextInputClientTest) {
textfield_->SetReadOnly(false);
input_method_->Clear();
- textfield_->SetObscured(true);
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
EXPECT_TRUE(input_method_->text_input_type_changed());
EXPECT_TRUE(textfield_->GetTextInputClient());
}
-TEST_F(NativeTextfieldViewsTest, UndoRedoTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, UndoRedoTest) {
+ InitTextfield();
SendKeyEvent(ui::VKEY_A);
EXPECT_STR_EQ("a", textfield_->text());
SendKeyEvent(ui::VKEY_Z, false, true);
@@ -1313,8 +1206,7 @@ TEST_F(NativeTextfieldViewsTest, UndoRedoTest) {
// SetText
SendKeyEvent(ui::VKEY_C);
// Undo'ing append moves the cursor to the end for now.
- // no-op SetText won't add new edit. See TextfieldViewsModel::SetText
- // description.
+ // A no-op SetText won't add a new edit; see TextfieldModel::SetText.
EXPECT_STR_EQ("abc", textfield_->text());
textfield_->SetText(ASCIIToUTF16("abc"));
EXPECT_STR_EQ("abc", textfield_->text());
@@ -1383,62 +1275,70 @@ TEST_F(NativeTextfieldViewsTest, UndoRedoTest) {
EXPECT_STR_EQ("", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, CutCopyPaste) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, CutCopyPaste) {
+ InitTextfield();
// Ensure IDS_APP_CUT cuts.
textfield_->SetText(ASCIIToUTF16("123"));
textfield_->SelectAll(false);
- EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_CUT));
- textfield_view_->ExecuteCommand(IDS_APP_CUT, 0);
- EXPECT_STR_EQ("123", string16(GetClipboardText()));
+ 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("", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, 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", string16(GetClipboardText()));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("456", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_X, false, true);
- EXPECT_STR_EQ("456", string16(GetClipboardText()));
+ EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
// Ensure [Shift]+[Delete] cuts.
textfield_->SetText(ASCIIToUTF16("123"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_DELETE, true, false);
- EXPECT_STR_EQ("123", string16(GetClipboardText()));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
// Ensure IDS_APP_COPY copies.
textfield_->SetText(ASCIIToUTF16("789"));
textfield_->SelectAll(false);
- EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_COPY));
- textfield_view_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("789", string16(GetClipboardText()));
+ 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());
// 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", string16(GetClipboardText()));
+ EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("012", string16(GetClipboardText()));
+ EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[Insert] copies.
textfield_->SetText(ASCIIToUTF16("345"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, false, true);
- EXPECT_STR_EQ("345", string16(GetClipboardText()));
+ EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("345", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
// Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
// also ensure that [Ctrl]+[Alt]+[V] does nothing.
- SetClipboardText("abc");
- textfield_->SetText(string16());
- EXPECT_TRUE(textfield_view_->IsCommandIdEnabled(IDS_APP_PASTE));
- textfield_view_->ExecuteCommand(IDS_APP_PASTE, 0);
+ SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
+ textfield_->SetText(base::string16());
+ EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
+ textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
EXPECT_STR_EQ("abc", textfield_->text());
SendKeyEvent(ui::VKEY_V, false, true);
EXPECT_STR_EQ("abcabc", textfield_->text());
@@ -1450,12 +1350,13 @@ TEST_F(NativeTextfieldViewsTest, CutCopyPaste) {
// Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, true, true);
- EXPECT_STR_EQ("abc", string16(GetClipboardText()));
+ EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
EXPECT_STR_EQ("abcabcabc", textfield_->text());
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
}
-TEST_F(NativeTextfieldViewsTest, OvertypeMode) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, OvertypeMode) {
+ InitTextfield();
// Overtype mode should be disabled (no-op [Insert]).
textfield_->SetText(ASCIIToUTF16("2"));
SendKeyEvent(ui::VKEY_HOME);
@@ -1464,8 +1365,8 @@ TEST_F(NativeTextfieldViewsTest, OvertypeMode) {
EXPECT_STR_EQ("12", textfield_->text());
}
-TEST_F(NativeTextfieldViewsTest, TextCursorDisplayTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, TextCursorDisplayTest) {
+ InitTextfield();
// LTR-RTL string in LTR context.
SendKeyEvent('a');
EXPECT_STR_EQ("a", textfield_->text());
@@ -1516,11 +1417,11 @@ TEST_F(NativeTextfieldViewsTest, TextCursorDisplayTest) {
EXPECT_LT(prev_x, x);
}
-TEST_F(NativeTextfieldViewsTest, TextCursorDisplayInRTLTest) {
+TEST_F(TextfieldTest, TextCursorDisplayInRTLTest) {
std::string locale = l10n_util::GetApplicationLocale("");
base::i18n::SetICUDefaultLocale("he");
- InitTextfield(Textfield::STYLE_DEFAULT);
+ InitTextfield();
// LTR-RTL string in RTL context.
SendKeyEvent('a');
EXPECT_STR_EQ("a", textfield_->text());
@@ -1574,8 +1475,8 @@ TEST_F(NativeTextfieldViewsTest, TextCursorDisplayInRTLTest) {
base::i18n::SetICUDefaultLocale(locale);
}
-TEST_F(NativeTextfieldViewsTest, HitInsideTextAreaTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, HitInsideTextAreaTest) {
+ InitTextfield();
textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
std::vector<gfx::Rect> cursor_bounds;
@@ -1629,8 +1530,8 @@ TEST_F(NativeTextfieldViewsTest, HitInsideTextAreaTest) {
}
}
-TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, HitOutsideTextAreaTest) {
+ InitTextfield();
// LTR-RTL string in LTR context.
textfield_->SetText(WideToUTF16(L"ab\x05E1\x5E2"));
@@ -1661,11 +1562,11 @@ TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaTest) {
EXPECT_EQ(bound, GetCursorBounds());
}
-TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaInRTLTest) {
+TEST_F(TextfieldTest, HitOutsideTextAreaInRTLTest) {
std::string locale = l10n_util::GetApplicationLocale("");
base::i18n::SetICUDefaultLocale("he");
- InitTextfield(Textfield::STYLE_DEFAULT);
+ InitTextfield();
// RTL-LTR string in RTL context.
textfield_->SetText(WideToUTF16(L"\x05E1\x5E2" L"ab"));
@@ -1697,10 +1598,10 @@ TEST_F(NativeTextfieldViewsTest, HitOutsideTextAreaInRTLTest) {
base::i18n::SetICUDefaultLocale(locale);
}
-TEST_F(NativeTextfieldViewsTest, OverflowTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, OverflowTest) {
+ InitTextfield();
- string16 str;
+ base::string16 str;
for (int i = 0; i < 500; ++i)
SendKeyEvent('a');
SendKeyEvent(kHebrewLetterSamekh);
@@ -1723,13 +1624,13 @@ TEST_F(NativeTextfieldViewsTest, OverflowTest) {
EXPECT_EQ(501U, textfield_->GetCursorPosition());
}
-TEST_F(NativeTextfieldViewsTest, OverflowInRTLTest) {
+TEST_F(TextfieldTest, OverflowInRTLTest) {
std::string locale = l10n_util::GetApplicationLocale("");
base::i18n::SetICUDefaultLocale("he");
- InitTextfield(Textfield::STYLE_DEFAULT);
+ InitTextfield();
- string16 str;
+ base::string16 str;
for (int i = 0; i < 500; ++i)
SendKeyEvent('a');
SendKeyEvent(kHebrewLetterSamekh);
@@ -1754,10 +1655,10 @@ TEST_F(NativeTextfieldViewsTest, OverflowInRTLTest) {
base::i18n::SetICUDefaultLocale(locale);
}
-TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBoundsTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, GetCompositionCharacterBoundsTest) {
+ InitTextfield();
- string16 str;
+ base::string16 str;
const uint32 char_count = 10UL;
ui::CompositionText composition;
composition.text = UTF8ToUTF16("0123456789");
@@ -1777,8 +1678,8 @@ TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBoundsTest) {
gfx::Rect cursor_bounds = GetCursorBounds();
gfx::Point top_left(prev_cursor.x(), prev_cursor.y());
gfx::Point bottom_right(cursor_bounds.x(), prev_cursor.bottom());
- views::View::ConvertPointToScreen(textfield_view_, &top_left);
- views::View::ConvertPointToScreen(textfield_view_, &bottom_right);
+ views::View::ConvertPointToScreen(textfield_, &top_left);
+ views::View::ConvertPointToScreen(textfield_, &bottom_right);
char_rect_in_screen_coord[i].set_origin(top_left);
char_rect_in_screen_coord[i].set_width(bottom_right.x() - top_left.x());
char_rect_in_screen_coord[i].set_height(bottom_right.y() - top_left.y());
@@ -1798,10 +1699,10 @@ TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBoundsTest) {
EXPECT_FALSE(client->GetCompositionCharacterBounds(char_count + 100, &rect));
}
-TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBounds_ComplexText) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, GetCompositionCharacterBounds_ComplexText) {
+ InitTextfield();
- const char16 kUtf16Chars[] = {
+ const base::char16 kUtf16Chars[] = {
// U+0020 SPACE
0x0020,
// U+1F408 (CAT) as surrogate pair
@@ -1835,8 +1736,8 @@ TEST_F(NativeTextfieldViewsTest, GetCompositionCharacterBounds_ComplexText) {
// The word we select by double clicking should remain selected regardless of
// where we drag the mouse afterwards without releasing the left button.
-TEST_F(NativeTextfieldViewsTest, KeepInitiallySelectedWord) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, KeepInitiallySelectedWord) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("abc def ghi"));
@@ -1850,73 +1751,192 @@ TEST_F(NativeTextfieldViewsTest, KeepInitiallySelectedWord) {
const gfx::Point middle(middle_cursor.x(),
middle_cursor.y() + middle_cursor.height() / 2);
ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, middle, middle,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMousePressed(press_event);
+ textfield_->OnMousePressed(press_event);
EXPECT_EQ(gfx::Range(4, 7), textfield_->GetSelectedRange());
// Drag the mouse to the beginning of the textfield.
ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, beginning, beginning,
- ui::EF_LEFT_MOUSE_BUTTON);
- textfield_view_->OnMouseDragged(drag_event);
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
+ textfield_->OnMouseDragged(drag_event);
EXPECT_EQ(gfx::Range(7, 0), textfield_->GetSelectedRange());
}
-// Touch selection and draggin currently only works for chromeos.
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+TEST_F(TextfieldTest, SelectionClipboard) {
+ InitTextfield();
+ textfield_->SetText(ASCIIToUTF16("0123"));
+ gfx::Point point_1(GetCursorPositionX(1), 0);
+ gfx::Point point_2(GetCursorPositionX(2), 0);
+ gfx::Point point_3(GetCursorPositionX(3), 0);
+ gfx::Point point_4(GetCursorPositionX(4), 0);
+
+ // Text selected by the mouse should be placed on the selection clipboard.
+ ui::MouseEvent press(ui::ET_MOUSE_PRESSED, point_1, point_1,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(press);
+ ui::MouseEvent drag(ui::ET_MOUSE_DRAGGED, point_3, point_3,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseDragged(drag);
+ ui::MouseEvent release(ui::ET_MOUSE_RELEASED, point_3, point_3,
+ ui::EF_LEFT_MOUSE_BUTTON, 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));
+
+ // 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());
+
+ // Shift-click selection modifications should update the clipboard.
+ NonClientMouseClick();
+ ui::MouseEvent press_2(ui::ET_MOUSE_PRESSED, point_2, point_2,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ press_2.set_flags(press_2.flags() | ui::EF_SHIFT_DOWN);
+ textfield_->OnMousePressed(press_2);
+ ui::MouseEvent release_2(ui::ET_MOUSE_RELEASED, point_2, point_2,
+ ui::EF_LEFT_MOUSE_BUTTON, 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());
+
+ // 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());
+ SendKeyEvent(ui::VKEY_LEFT, true, false);
+ EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ SendKeyEvent(ui::VKEY_RIGHT, true, true);
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, 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());
+
+ // Middle clicking should paste at the mouse (not cursor) location.
+ ui::MouseEvent middle(ui::ET_MOUSE_PRESSED, point_4, point_4,
+ ui::EF_MIDDLE_MOUSE_BUTTON, ui::EF_MIDDLE_MOUSE_BUTTON);
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("01230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+
+ // Middle click pasting should adjust trailing cursors.
+ textfield_->SelectRange(gfx::Range(5, 5));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(9, 9), textfield_->GetSelectedRange());
+
+ // Middle click pasting should adjust trailing selections.
+ textfield_->SelectRange(gfx::Range(7, 9));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("0123012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(11, 13), textfield_->GetSelectedRange());
+
+ // Middle clicking in the selection should clear the clipboard and selection.
+ textfield_->SelectRange(gfx::Range(2, 6));
+ textfield_->OnMousePressed(middle);
+ EXPECT_STR_EQ("0123012301230123", textfield_->text());
+ EXPECT_EQ(gfx::Range(6, 6), textfield_->GetSelectedRange());
+ EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
+
+ // Double and triple clicking should update the clipboard contents.
+ textfield_->SetText(ASCIIToUTF16("ab cd ef"));
+ gfx::Point word(GetCursorPositionX(4), 0);
+ ui::MouseEvent press_word(ui::ET_MOUSE_PRESSED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMousePressed(press_word);
+ ui::MouseEvent release_word(ui::ET_MOUSE_RELEASED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ textfield_->OnMouseReleased(release_word);
+ ui::MouseEvent double_click(ui::ET_MOUSE_PRESSED, word, word,
+ ui::EF_LEFT_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ 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());
+ 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());
+
+ // 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());
+
+ SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
+ textfield_->SelectAll(false);
+ EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+}
+#endif
+
+// Touch selection and dragging currently only works for chromeos.
#if defined(OS_CHROMEOS)
-TEST_F(NativeTextfieldViewsTest, TouchSelectionAndDraggingTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, TouchSelectionAndDraggingTest) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
- EXPECT_FALSE(GetTouchSelectionController());
- const int eventX = GetCursorPositionX(2);
- const int eventY = 0;
+ EXPECT_FALSE(test_api_->touch_selection_controller());
+ const int x = GetCursorPositionX(2);
+ GestureEventForTest tap(ui::ET_GESTURE_TAP, x, 0, 1.0f, 0.0f);
+ GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, x, 0, 0.0f, 0.0f);
+ GestureEventForTest long_press(ui::ET_GESTURE_LONG_PRESS, x, 0, 0.0f, 0.0f);
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
// Tapping on the textfield should turn on the TouchSelectionController.
- GestureEventForTest tap(ui::ET_GESTURE_TAP, eventX, eventY, 1.0f, 0.0f);
- textfield_view_->OnGestureEvent(&tap);
- EXPECT_TRUE(GetTouchSelectionController());
+ textfield_->OnGestureEvent(&tap);
+ EXPECT_TRUE(test_api_->touch_selection_controller());
// Un-focusing the textfield should reset the TouchSelectionController
- textfield_view_->GetFocusManager()->ClearFocus();
- EXPECT_FALSE(GetTouchSelectionController());
+ textfield_->GetFocusManager()->ClearFocus();
+ EXPECT_FALSE(test_api_->touch_selection_controller());
// With touch editing enabled, long press should not show context menu.
// Instead, select word and invoke TouchSelectionController.
- GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, eventX, eventY, 0.0f,
- 0.0f);
- textfield_view_->OnGestureEvent(&tap_down);
- GestureEventForTest long_press(ui::ET_GESTURE_LONG_PRESS, eventX, eventY,
- 0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&long_press);
+ textfield_->OnGestureEvent(&tap_down);
+ textfield_->OnGestureEvent(&long_press);
EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
- EXPECT_TRUE(GetTouchSelectionController());
+ EXPECT_TRUE(test_api_->touch_selection_controller());
- // Long pressing again in the selecting region should not do anything since
- // touch drag drop is not yet enabled.
- textfield_view_->OnGestureEvent(&tap_down);
- textfield_view_->OnGestureEvent(&long_press);
+ // With touch drag drop enabled, long pressing in the selected region should
+ // start a drag and remove TouchSelectionController.
+ ASSERT_TRUE(switches::IsTouchDragDropEnabled());
+ textfield_->OnGestureEvent(&tap_down);
+ textfield_->OnGestureEvent(&long_press);
EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
- EXPECT_TRUE(GetTouchSelectionController());
- EXPECT_TRUE(long_press.handled());
+ EXPECT_FALSE(test_api_->touch_selection_controller());
- // After enabling touch drag drop, long pressing in the selected region should
- // start a drag and remove TouchSelectionController.
+ // After disabling touch drag drop, long pressing again in the selection
+ // region should not do anything.
CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableTouchDragDrop);
- textfield_view_->OnGestureEvent(&tap_down);
-
- // Create a new long press event since the previous one is not marked handled.
- GestureEventForTest long_press2(ui::ET_GESTURE_LONG_PRESS, eventX, eventY,
- 0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&long_press2);
+ switches::kDisableTouchDragDrop);
+ ASSERT_FALSE(switches::IsTouchDragDropEnabled());
+ textfield_->OnGestureEvent(&tap_down);
+ textfield_->OnGestureEvent(&long_press);
EXPECT_STR_EQ("hello", textfield_->GetSelectedText());
- EXPECT_FALSE(GetTouchSelectionController());
+ EXPECT_TRUE(test_api_->touch_selection_controller());
+ EXPECT_TRUE(long_press.handled());
}
-TEST_F(NativeTextfieldViewsTest, TouchScrubbingSelection) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, TouchScrubbingSelection) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("hello world"));
- EXPECT_FALSE(GetTouchSelectionController());
+ EXPECT_FALSE(test_api_->touch_selection_controller());
CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
@@ -1926,37 +1946,37 @@ TEST_F(NativeTextfieldViewsTest, TouchScrubbingSelection) {
GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, scrubbing_start, 0,
0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&tap_down);
+ textfield_->OnGestureEvent(&tap_down);
GestureEventForTest tap_cancel(ui::ET_GESTURE_TAP_CANCEL, scrubbing_start, 0,
0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&tap_cancel);
+ textfield_->OnGestureEvent(&tap_cancel);
GestureEventForTest scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, scrubbing_start,
0, 0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&scroll_begin);
+ textfield_->OnGestureEvent(&scroll_begin);
GestureEventForTest scroll_update(ui::ET_GESTURE_SCROLL_UPDATE, scrubbing_end,
0, scrubbing_end - scrubbing_start, 0.0f);
- textfield_view_->OnGestureEvent(&scroll_update);
+ textfield_->OnGestureEvent(&scroll_update);
GestureEventForTest scroll_end(ui::ET_GESTURE_SCROLL_END, scrubbing_end, 0,
0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&scroll_end);
+ textfield_->OnGestureEvent(&scroll_end);
GestureEventForTest end(ui::ET_GESTURE_END, scrubbing_end, 0, 0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&end);
+ textfield_->OnGestureEvent(&end);
// In the end, part of text should have been selected and handles should have
// appeared.
EXPECT_STR_EQ("ello ", textfield_->GetSelectedText());
- EXPECT_TRUE(GetTouchSelectionController());
+ EXPECT_TRUE(test_api_->touch_selection_controller());
}
#endif
-// Long_Press gesture in NativeTextfieldViews can initiate a drag and drop now.
-TEST_F(NativeTextfieldViewsTest, TestLongPressInitiatesDragDrop) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+// Long_Press gesture in Textfield can initiate a drag and drop now.
+TEST_F(TextfieldTest, TestLongPressInitiatesDragDrop) {
+ InitTextfield();
textfield_->SetText(ASCIIToUTF16("Hello string world"));
// Ensure the textfield will provide selected text for drag data.
@@ -1970,13 +1990,13 @@ TEST_F(NativeTextfieldViewsTest, TestLongPressInitiatesDragDrop) {
// Create a long press event in the selected region should start a drag.
GestureEventForTest long_press(ui::ET_GESTURE_LONG_PRESS, kStringPoint.x(),
kStringPoint.y(), 0.0f, 0.0f);
- textfield_view_->OnGestureEvent(&long_press);
- EXPECT_TRUE(textfield_view_->CanStartDragForView(NULL,
- kStringPoint, kStringPoint));
+ textfield_->OnGestureEvent(&long_press);
+ EXPECT_TRUE(textfield_->CanStartDragForView(NULL, kStringPoint,
+ kStringPoint));
}
-TEST_F(NativeTextfieldViewsTest, GetTextfieldBaseline_FontFallbackTest) {
- InitTextfield(Textfield::STYLE_DEFAULT);
+TEST_F(TextfieldTest, GetTextfieldBaseline_FontFallbackTest) {
+ InitTextfield();
textfield_->SetText(UTF8ToUTF16("abc"));
const int old_baseline = textfield_->GetBaseline();
diff --git a/chromium/ui/views/controls/throbber.cc b/chromium/ui/views/controls/throbber.cc
index 25272de0536..5df35606378 100644
--- a/chromium/ui/views/controls/throbber.cc
+++ b/chromium/ui/views/controls/throbber.cc
@@ -68,7 +68,7 @@ void Throbber::Run() {
SchedulePaint();
}
-gfx::Size Throbber::GetPreferredSize() {
+gfx::Size Throbber::GetPreferredSize() const {
return gfx::Size(frames_->height(), frames_->height());
}
diff --git a/chromium/ui/views/controls/throbber.h b/chromium/ui/views/controls/throbber.h
index 8ae3895a22a..08188c39cf5 100644
--- a/chromium/ui/views/controls/throbber.h
+++ b/chromium/ui/views/controls/throbber.h
@@ -37,7 +37,7 @@ class VIEWS_EXPORT Throbber : public View {
void SetFrames(const gfx::ImageSkia* frames);
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
protected:
diff --git a/chromium/ui/views/controls/tree/tree_view.cc b/chromium/ui/views/controls/tree/tree_view.cc
index 2c7bd55c396..f514fe45fcd 100644
--- a/chromium/ui/views/controls/tree/tree_view.cc
+++ b/chromium/ui/views/controls/tree/tree_view.cc
@@ -9,11 +9,12 @@
#include "base/i18n/rtl.h"
#include "base/message_loop/message_loop.h"
#include "grit/ui_resources.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -78,8 +79,7 @@ TreeView::TreeView()
editable_(true),
controller_(NULL),
root_shown_(true),
- has_custom_icons_(false),
- row_height_(font_.GetHeight() + kTextVerticalPadding * 2) {
+ row_height_(font_list_.GetHeight() + kTextVerticalPadding * 2) {
SetFocusable(true);
closed_icon_ = *ui::ResourceBundle::GetSharedInstance().GetImageNamed(
(base::i18n::IsRTL() ? IDR_FOLDER_CLOSED_RTL
@@ -158,9 +158,9 @@ void TreeView::StartEditing(TreeModelNode* node) {
// Add the editor immediately as GetPreferredSize returns the wrong thing if
// not parented.
AddChildView(editor_);
- editor_->SetFont(font_);
+ editor_->SetFontList(font_list_);
empty_editor_size_ = editor_->GetPreferredSize();
- editor_->SetController(this);
+ editor_->set_controller(this);
}
editor_->SetText(selected_node_->model_node()->GetTitle());
LayoutEditor();
@@ -245,7 +245,7 @@ void TreeView::SetSelectedNode(TreeModelNode* model_node) {
if (changed) {
// TODO(dmazzoni): Decide if EVENT_SELECTION_CHANGED is a better choice for
// sub-item selection event.
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
}
}
@@ -350,7 +350,7 @@ void TreeView::Layout() {
LayoutEditor();
}
-gfx::Size TreeView::GetPreferredSize() {
+gfx::Size TreeView::GetPreferredSize() const {
return preferred_size_;
}
@@ -403,14 +403,14 @@ void TreeView::ShowContextMenu(const gfx::Point& p,
View::ShowContextMenu(p, source_type);
}
-void TreeView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_OUTLINE;
- state->state = ui::AccessibilityTypes::STATE_READONLY;
+void TreeView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_TREE;
+ state->AddStateFlag(ui::AX_STATE_READ_ONLY);
if (!selected_node_)
return;
// Get selected item info.
- state->role = ui::AccessibilityTypes::ROLE_OUTLINEITEM;
+ state->role = ui::AX_ROLE_TREE_ITEM;
state->name = selected_node_->model_node()->GetTitle();
}
@@ -482,7 +482,7 @@ void TreeView::TreeNodeChanged(TreeModel* model, TreeModelNode* model_node) {
}
void TreeView::ContentsChanged(Textfield* sender,
- const string16& new_contents) {
+ const base::string16& new_contents) {
}
bool TreeView::HandleKeyEvent(Textfield* sender,
@@ -525,7 +525,7 @@ void TreeView::SetSelectedRow(int row) {
SetSelectedNode(GetNodeForRow(row));
}
-string16 TreeView::GetTextForRow(int row) {
+base::string16 TreeView::GetTextForRow(int row) {
return GetNodeForRow(row)->GetTitle();
}
@@ -694,7 +694,7 @@ void TreeView::ConfigureInternalNode(TreeModelNode* model_node,
void TreeView::UpdateNodeTextWidth(InternalNode* node) {
int width = 0, height = 0;
- gfx::Canvas::SizeStringInt(node->model_node()->GetTitle(), font_,
+ gfx::Canvas::SizeStringInt(node->model_node()->GetTitle(), font_list_,
&width, &height, 0, gfx::Canvas::NO_ELLIPSIS);
node->set_text_width(width);
}
@@ -729,7 +729,7 @@ void TreeView::LayoutEditor() {
row_bounds.set_width(row_bounds.width() - text_offset_);
row_bounds.Inset(kTextHorizontalPadding, kTextVerticalPadding);
row_bounds.Inset(-empty_editor_size_.width() / 2,
- -(empty_editor_size_.height() - font_.GetHeight()) / 2);
+ -(empty_editor_size_.height() - font_list_.GetHeight()) / 2);
// Give a little extra space for editing.
row_bounds.set_width(row_bounds.width() + 50);
editor_->SetBoundsRect(row_bounds);
@@ -803,12 +803,14 @@ void TreeView::PaintRow(gfx::Canvas* canvas,
}
const ui::NativeTheme::ColorId color_id =
text_color_id(HasFocus(), node == selected_node_);
- canvas->DrawStringInt(node->model_node()->GetTitle(), font_,
- GetNativeTheme()->GetSystemColor(color_id),
- text_bounds.x() + kTextHorizontalPadding,
- text_bounds.y() + kTextVerticalPadding,
- text_bounds.width() - kTextHorizontalPadding * 2,
- text_bounds.height() - kTextVerticalPadding * 2);
+ const gfx::Rect internal_bounds(
+ text_bounds.x() + kTextHorizontalPadding,
+ text_bounds.y() + kTextVerticalPadding,
+ text_bounds.width() - kTextHorizontalPadding * 2,
+ text_bounds.height() - kTextVerticalPadding * 2);
+ canvas->DrawStringRect(node->model_node()->GetTitle(), font_list_,
+ GetNativeTheme()->GetSystemColor(color_id),
+ internal_bounds);
}
}
diff --git a/chromium/ui/views/controls/tree/tree_view.h b/chromium/ui/views/controls/tree/tree_view.h
index de571c789bf..3cae3b52376 100644
--- a/chromium/ui/views/controls/tree/tree_view.h
+++ b/chromium/ui/views/controls/tree/tree_view.h
@@ -11,13 +11,17 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "ui/base/models/tree_node_model.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/controls/prefix_delegate.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/view.h"
+namespace gfx {
+class Rect;
+} // namespace gfx
+
namespace views {
class Textfield;
@@ -117,14 +121,14 @@ class VIEWS_EXPORT TreeView : public ui::TreeModelObserver,
// View overrides:
virtual void Layout() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual void ShowContextMenu(const gfx::Point& p,
ui::MenuSourceType source_type) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
// TreeModelObserver overrides:
@@ -141,7 +145,7 @@ class VIEWS_EXPORT TreeView : public ui::TreeModelObserver,
// TextfieldController overrides:
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) OVERRIDE;
+ const base::string16& new_contents) OVERRIDE;
virtual bool HandleKeyEvent(Textfield* sender,
const ui::KeyEvent& key_event) OVERRIDE;
@@ -155,7 +159,7 @@ class VIEWS_EXPORT TreeView : public ui::TreeModelObserver,
virtual int GetRowCount() OVERRIDE;
virtual int GetSelectedRow() OVERRIDE;
virtual void SetSelectedRow(int row) OVERRIDE;
- virtual string16 GetTextForRow(int row) OVERRIDE;
+ virtual base::string16 GetTextForRow(int row) OVERRIDE;
protected:
// View overrides:
@@ -370,14 +374,11 @@ class VIEWS_EXPORT TreeView : public ui::TreeModelObserver,
// Whether or not the root is shown in the tree.
bool root_shown_;
- // Did the model return a non-empty set of icons from GetIcons?
- bool has_custom_icons_;
-
// Cached preferred size.
gfx::Size preferred_size_;
- // Font used to display text.
- gfx::Font font_;
+ // Font list used to display text.
+ gfx::FontList font_list_;
// Height of each row. Based on font and some padding.
int row_height_;
diff --git a/chromium/ui/views/controls/tree/tree_view_unittest.cc b/chromium/ui/views/controls/tree/tree_view_unittest.cc
index 1864ff9a9bf..bf73da99ec1 100644
--- a/chromium/ui/views/controls/tree/tree_view_unittest.cc
+++ b/chromium/ui/views/controls/tree/tree_view_unittest.cc
@@ -17,6 +17,8 @@ using ui::TreeModel;
using ui::TreeModelNode;
using ui::TreeNode;
+using base::ASCIIToUTF16;
+
namespace views {
class TestNode : public TreeNode<TestNode> {
@@ -68,7 +70,7 @@ class TreeViewTest : public ViewsTestBase {
private:
std::string InternalNodeAsString(TreeView::InternalNode* node);
- TestNode* GetNodeByTitleImpl(TestNode* node, const string16& title);
+ TestNode* GetNodeByTitleImpl(TestNode* node, const base::string16& title);
DISALLOW_COPY_AND_ASSIGN(TreeViewTest);
};
@@ -88,12 +90,14 @@ std::string TreeViewTest::TreeViewContentsAsString() {
std::string TreeViewTest::GetSelectedNodeTitle() {
TreeModelNode* model_node = tree_.GetSelectedNode();
- return model_node ? UTF16ToASCII(model_node->GetTitle()) : std::string();
+ return model_node ? base::UTF16ToASCII(model_node->GetTitle())
+ : std::string();
}
std::string TreeViewTest::GetEditingNodeTitle() {
TreeModelNode* model_node = tree_.GetEditingNode();
- return model_node ? UTF16ToASCII(model_node->GetTitle()) : std::string();
+ return model_node ? base::UTF16ToASCII(model_node->GetTitle())
+ : std::string();
}
TestNode* TreeViewTest::GetNodeByTitle(const std::string& title) {
@@ -118,7 +122,7 @@ int TreeViewTest::GetRowCount() {
}
TestNode* TreeViewTest::GetNodeByTitleImpl(TestNode* node,
- const string16& title) {
+ const base::string16& title) {
if (node->GetTitle() == title)
return node;
for (int i = 0; i < node->child_count(); ++i) {
@@ -131,7 +135,7 @@ TestNode* TreeViewTest::GetNodeByTitleImpl(TestNode* node,
std::string TreeViewTest::InternalNodeAsString(
TreeView::InternalNode* node) {
- std::string result = UTF16ToASCII(node->model_node()->GetTitle());
+ 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) {
diff --git a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc
index c1148c74e44..463ef7e3a05 100644
--- a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc
+++ b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_win.cc
@@ -57,13 +57,9 @@ void UnhandledKeyboardEventHandler::HandleKeyboardEvent(
// Any unhandled keyboard/character messages should be defproced.
// This allows stuff like F10, etc to work correctly.
-#if defined(USE_AURA)
if (!event.os_event)
return;
const MSG& message(event.os_event->native_event());
-#else
- const MSG& message(event.os_event);
-#endif
DefWindowProc(message.hwnd, message.message, message.wParam, message.lParam);
}
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.cc b/chromium/ui/views/controls/webview/web_dialog_view.cc
index 7f88f022f55..ffb5cbafbde 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.cc
+++ b/chromium/ui/views/controls/webview/web_dialog_view.cc
@@ -12,22 +12,18 @@
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
+#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"
-#if defined(USE_AURA)
-#include "ui/events/event.h"
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/native_widget_aura.h"
-#endif
-
using content::NativeWebKeyboardEvent;
using content::WebContents;
using content::WebUIMessageHandler;
@@ -46,7 +42,6 @@ WebDialogView::WebDialogView(
WebContentsHandler* handler)
: ClientView(NULL, NULL),
WebDialogWebContentsDelegate(context, handler),
- initialized_(false),
delegate_(delegate),
web_view_(new views::WebView(context)),
is_attempting_close_dialog_(false),
@@ -71,14 +66,14 @@ content::WebContents* WebDialogView::web_contents() {
////////////////////////////////////////////////////////////////////////////////
// WebDialogView, views::View implementation:
-gfx::Size WebDialogView::GetPreferredSize() {
+gfx::Size WebDialogView::GetPreferredSize() const {
gfx::Size out;
if (delegate_)
delegate_->GetDialogSize(&out);
return out;
}
-gfx::Size WebDialogView::GetMinimumSize() {
+gfx::Size WebDialogView::GetMinimumSize() const {
gfx::Size out;
if (delegate_)
delegate_->GetMinimumDialogSize(&out);
@@ -118,8 +113,7 @@ bool WebDialogView::CanClose() {
if (!is_attempting_close_dialog_) {
// Fire beforeunload event when user attempts to close the dialog.
is_attempting_close_dialog_ = true;
- web_view_->
- web_contents()->GetRenderViewHost()->FirePageBeforeUnload(false);
+ web_view_->web_contents()->DispatchBeforeUnload(false);
}
return false;
}
@@ -128,6 +122,8 @@ bool WebDialogView::CanClose() {
// WebDialogView, views::WidgetDelegate implementation:
bool WebDialogView::CanResize() const {
+ if (delegate_)
+ return delegate_->CanResizeDialog();
return true;
}
@@ -135,10 +131,10 @@ ui::ModalType WebDialogView::GetModalType() const {
return GetDialogModalType();
}
-string16 WebDialogView::GetWindowTitle() const {
+base::string16 WebDialogView::GetWindowTitle() const {
if (delegate_)
return delegate_->GetDialogTitle();
- return string16();
+ return base::string16();
}
std::string WebDialogView::GetWindowName() const {
@@ -188,7 +184,7 @@ ui::ModalType WebDialogView::GetDialogModalType() const {
return ui::MODAL_TYPE_NONE;
}
-string16 WebDialogView::GetDialogTitle() const {
+base::string16 WebDialogView::GetDialogTitle() const {
return GetWindowTitle();
}
@@ -282,23 +278,10 @@ void WebDialogView::MoveContents(WebContents* source, const gfx::Rect& pos) {
// they're all browser-specific. (This may change in the future.)
void WebDialogView::HandleKeyboardEvent(content::WebContents* source,
const NativeWebKeyboardEvent& event) {
-#if defined(USE_AURA)
if (!event.os_event)
return;
- ui::KeyEvent aura_event(event.os_event->native_event(), false);
- ui::EventHandler* event_handler =
- GetWidget()->native_widget()->GetEventHandler();
-
- DCHECK(event_handler);
- if (event_handler)
- event_handler->OnKeyEvent(&aura_event);
-#elif defined(OS_WIN)
- // Any unhandled keyboard/character messages should be defproced.
- // This allows stuff like F10, etc to work correctly.
- DefWindowProc(event.os_event.hwnd, event.os_event.message,
- event.os_event.wParam, event.os_event.lParam);
-#endif
+ GetWidget()->native_widget_private()->RepostNativeEvent(event.os_event);
}
void WebDialogView::CloseContents(WebContents* source) {
@@ -335,7 +318,8 @@ void WebDialogView::AddNewContents(content::WebContents* source,
was_blocked);
}
-void WebDialogView::LoadingStateChanged(content::WebContents* source) {
+void WebDialogView::LoadingStateChanged(content::WebContents* source,
+ bool to_different_document) {
if (delegate_)
delegate_->OnLoadingStateChanged(source);
}
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.h b/chromium/ui/views/controls/webview/web_dialog_view.h
index bb2eb395e52..2e69ad314ba 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.h
+++ b/chromium/ui/views/controls/webview/web_dialog_view.h
@@ -52,8 +52,8 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
content::WebContents* web_contents();
// Overridden from views::ClientView:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator)
OVERRIDE;
virtual void ViewHierarchyChanged(
@@ -63,7 +63,7 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
// Overridden from views::WidgetDelegate:
virtual bool CanResize() const OVERRIDE;
virtual ui::ModalType GetModalType() const OVERRIDE;
- virtual string16 GetWindowTitle() const OVERRIDE;
+ virtual base::string16 GetWindowTitle() const OVERRIDE;
virtual std::string GetWindowName() const OVERRIDE;
virtual void WindowClosing() OVERRIDE;
virtual views::View* GetContentsView() OVERRIDE;
@@ -75,7 +75,7 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
// Overridden from ui::WebDialogDelegate:
virtual ui::ModalType GetDialogModalType() const OVERRIDE;
- virtual string16 GetDialogTitle() const OVERRIDE;
+ virtual base::string16 GetDialogTitle() const OVERRIDE;
virtual GURL GetDialogContentURL() const OVERRIDE;
virtual void GetWebUIMessageHandlers(
std::vector<content::WebUIMessageHandler*>* handlers) const OVERRIDE;
@@ -110,7 +110,8 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
const gfx::Rect& initial_pos,
bool user_gesture,
bool* was_blocked) OVERRIDE;
- virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+ virtual void LoadingStateChanged(content::WebContents* source,
+ bool to_different_document) OVERRIDE;
virtual void BeforeUnloadFired(content::WebContents* tab,
bool proceed,
bool* proceed_to_fire_unload) OVERRIDE;
@@ -121,11 +122,6 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
// Initializes the contents of the dialog.
void InitDialog();
- // Whether the view is initialized. That is, dialog accelerators is registered
- // and FreezeUpdates property is set to prevent WM from showing the window
- // until the property is removed.
- bool initialized_;
-
// This view is a delegate to the HTML content since it needs to get notified
// about when the dialog is closing. For all other actions (besides dialog
// closing) we delegate to the creator of this view, which we keep track of
@@ -142,11 +138,11 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
// beforeunload event.
bool before_unload_fired_;
- // Whether the dialog is closed from WebUI in response to a "DialogClose"
+ // Whether the dialog is closed from WebUI in response to a "dialogClose"
// message.
bool closed_via_webui_;
- // A json string returned to WebUI from a "DialogClosed" message.
+ // A json string returned to WebUI from a "dialogClose" message.
std::string dialog_close_retval_;
// Whether CloseContents() has been called.
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index f2ea02f48fb..21de7261231 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -10,10 +10,10 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
#include "ipc/ipc_message.h"
-#include "ui/base/accessibility/accessibility_types.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/events/event.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -29,63 +29,51 @@ const char WebView::kViewClassName[] = "WebView";
// WebView, public:
WebView::WebView(content::BrowserContext* browser_context)
- : wcv_holder_(new NativeViewHost),
- web_contents_(NULL),
+ : holder_(new NativeViewHost()),
embed_fullscreen_widget_mode_enabled_(false),
is_embedding_fullscreen_widget_(false),
browser_context_(browser_context),
allow_accelerators_(false) {
- AddChildView(wcv_holder_);
+ AddChildView(holder_); // Takes ownership of |holder_|.
NativeViewAccessibility::RegisterWebView(this);
}
WebView::~WebView() {
+ SetWebContents(NULL); // Make sure all necessary tear-down takes place.
NativeViewAccessibility::UnregisterWebView(this);
}
content::WebContents* WebView::GetWebContents() {
- CreateWebContentsWithSiteInstance(NULL);
- return web_contents_;
-}
-
-void WebView::CreateWebContentsWithSiteInstance(
- content::SiteInstance* site_instance) {
- if (!web_contents_) {
- wc_owner_.reset(CreateWebContents(browser_context_, site_instance));
- web_contents_ = wc_owner_.get();
- web_contents_->SetDelegate(this);
- AttachWebContents();
+ if (!web_contents()) {
+ wc_owner_.reset(CreateWebContents(browser_context_));
+ wc_owner_->SetDelegate(this);
+ SetWebContents(wc_owner_.get());
}
+ return web_contents();
}
-void WebView::SetWebContents(content::WebContents* web_contents) {
- if (web_contents == web_contents_)
+void WebView::SetWebContents(content::WebContents* replacement) {
+ if (replacement == web_contents())
return;
DetachWebContents();
- if (wc_owner_ != web_contents)
+ WebContentsObserver::Observe(replacement);
+ // web_contents() now returns |replacement| from here onwards.
+ if (wc_owner_ != replacement)
wc_owner_.reset();
- web_contents_ = web_contents;
if (embed_fullscreen_widget_mode_enabled_) {
is_embedding_fullscreen_widget_ =
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
+ web_contents() && web_contents()->GetFullscreenRenderWidgetHostView();
} else {
- is_embedding_fullscreen_widget_ = false;
+ DCHECK(!is_embedding_fullscreen_widget_);
}
AttachWebContents();
+ NotifyMaybeTextInputClientChanged();
}
void WebView::SetEmbedFullscreenWidgetMode(bool enable) {
- bool should_be_embedded = enable;
- if (!embed_fullscreen_widget_mode_enabled_ && enable) {
- DCHECK(!is_embedding_fullscreen_widget_);
- embed_fullscreen_widget_mode_enabled_ = true;
- should_be_embedded =
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
- } else if (embed_fullscreen_widget_mode_enabled_ && !enable) {
- embed_fullscreen_widget_mode_enabled_ = false;
- }
- if (should_be_embedded != is_embedding_fullscreen_widget_)
- ReattachForFullscreenChange(should_be_embedded);
+ DCHECK(!web_contents())
+ << "Cannot change mode while a WebContents is attached.";
+ embed_fullscreen_widget_mode_enabled_ = enable;
}
void WebView::LoadInitialURL(const GURL& url) {
@@ -95,7 +83,7 @@ void WebView::LoadInitialURL(const GURL& url) {
}
void WebView::SetFastResize(bool fast_resize) {
- wcv_holder_->set_fast_resize(fast_resize);
+ holder_->set_fast_resize(fast_resize);
}
void WebView::OnWebContentsFocused(content::WebContents* web_contents) {
@@ -116,8 +104,68 @@ const char* WebView::GetClassName() const {
return kViewClassName;
}
+ui::TextInputClient* WebView::GetTextInputClient() {
+ // This function delegates the text input handling to the underlying
+ // content::RenderWidgetHostView. So when the underlying RWHV is destroyed or
+ // replaced with another one, we have to notify the FocusManager through
+ // FocusManager::OnTextInputClientChanged() that the focused TextInputClient
+ // needs to be updated.
+ if (switches::IsTextInputFocusManagerEnabled() &&
+ web_contents() && !web_contents()->IsBeingDestroyed()) {
+ content::RenderWidgetHostView* host_view =
+ is_embedding_fullscreen_widget_ ?
+ web_contents()->GetFullscreenRenderWidgetHostView() :
+ web_contents()->GetRenderWidgetHostView();
+ if (host_view)
+ return host_view->GetTextInputClient();
+ }
+ return NULL;
+}
+
void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- wcv_holder_->SetSize(bounds().size());
+ // In most cases, the holder is simply sized to fill this WebView's bounds.
+ // Only WebContentses that are in fullscreen mode and being screen-captured
+ // will engage the special layout/sizing behavior.
+ gfx::Rect holder_bounds(bounds().size());
+ if (!embed_fullscreen_widget_mode_enabled_ ||
+ !web_contents() ||
+ web_contents()->GetCapturerCount() == 0 ||
+ web_contents()->GetPreferredSize().IsEmpty() ||
+ !(is_embedding_fullscreen_widget_ ||
+ (web_contents()->GetDelegate() &&
+ web_contents()->GetDelegate()->
+ IsFullscreenForTabOrPending(web_contents())))) {
+ holder_->SetBoundsRect(holder_bounds);
+ return;
+ }
+
+ // Size the holder to the capture video resolution and center it. If this
+ // WebView is not large enough to contain the holder at the preferred size,
+ // scale down to fit (preserving aspect ratio).
+ const gfx::Size capture_size = web_contents()->GetPreferredSize();
+ if (capture_size.width() <= holder_bounds.width() &&
+ capture_size.height() <= holder_bounds.height()) {
+ // No scaling, just centering.
+ holder_bounds.ClampToCenteredSize(capture_size);
+ } else {
+ // Scale down, preserving aspect ratio, and center.
+ // TODO(miu): This is basically media::ComputeLetterboxRegion(), and it
+ // looks like others have written this code elsewhere. Let's considate
+ // into a shared function ui/gfx/geometry or around there.
+ const int64 x = static_cast<int64>(capture_size.width()) *
+ holder_bounds.height();
+ const int64 y = static_cast<int64>(capture_size.height()) *
+ holder_bounds.width();
+ if (y < x) {
+ holder_bounds.ClampToCenteredSize(gfx::Size(
+ holder_bounds.width(), static_cast<int>(y / capture_size.width())));
+ } else {
+ holder_bounds.ClampToCenteredSize(gfx::Size(
+ static_cast<int>(x / capture_size.height()), holder_bounds.height()));
+ }
+ }
+
+ holder_->SetBoundsRect(holder_bounds);
}
void WebView::ViewHierarchyChanged(
@@ -135,48 +183,48 @@ bool WebView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
// We'll first give the page a chance to process the key events. If it does
// not process them, they'll be returned to us and we'll treat them as
// accelerators then.
- return web_contents_ && !web_contents_->IsCrashed();
+ return web_contents() && !web_contents()->IsCrashed();
}
bool WebView::IsFocusable() const {
// We need to be focusable when our contents is not a view hierarchy, as
// clicking on the contents needs to focus us.
- return !!web_contents_;
+ return !!web_contents();
}
void WebView::OnFocus() {
- if (!web_contents_)
+ if (!web_contents())
return;
if (is_embedding_fullscreen_widget_) {
content::RenderWidgetHostView* const current_fs_view =
- web_contents_->GetFullscreenRenderWidgetHostView();
+ web_contents()->GetFullscreenRenderWidgetHostView();
if (current_fs_view)
current_fs_view->Focus();
} else {
- web_contents_->GetView()->Focus();
+ web_contents()->Focus();
}
}
void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) {
- if (web_contents_)
- web_contents_->FocusThroughTabTraversal(reverse);
+ if (web_contents())
+ web_contents()->FocusThroughTabTraversal(reverse);
}
-void WebView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_GROUPING;
+void WebView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_GROUP;
}
gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
- if (web_contents_) {
+ if (web_contents()) {
content::RenderWidgetHostView* host_view =
- web_contents_->GetRenderWidgetHostView();
+ web_contents()->GetRenderWidgetHostView();
if (host_view)
return host_view->GetNativeViewAccessible();
}
return View::GetNativeViewAccessible();
}
-gfx::Size WebView::GetPreferredSize() {
+gfx::Size WebView::GetPreferredSize() const {
if (preferred_size_ == gfx::Size())
return View::GetPreferredSize();
else
@@ -189,7 +237,7 @@ gfx::Size WebView::GetPreferredSize() {
void WebView::WebContentsFocused(content::WebContents* web_contents) {
DCHECK(wc_owner_.get());
// The WebView is only the delegate of WebContentses it creates itself.
- OnWebContentsFocused(web_contents_);
+ OnWebContentsFocused(wc_owner_.get());
}
bool WebView::EmbedsFullscreenWidget() const {
@@ -200,19 +248,16 @@ bool WebView::EmbedsFullscreenWidget() const {
////////////////////////////////////////////////////////////////////////////////
// WebView, content::WebContentsObserver implementation:
+void WebView::RenderViewDeleted(content::RenderViewHost* render_view_host) {
+ NotifyMaybeTextInputClientChanged();
+}
+
void WebView::RenderViewHostChanged(content::RenderViewHost* old_host,
content::RenderViewHost* new_host) {
FocusManager* const focus_manager = GetFocusManager();
if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus();
-}
-
-void WebView::WebContentsDestroyed(content::WebContents* web_contents) {
- // We watch for destruction of WebContents that we host but do not own. If we
- // own a WebContents that is being destroyed, we're doing the destroying, so
- // we don't want to recursively tear it down while it's being torn down.
- if (!wc_owner_.get())
- SetWebContents(NULL);
+ NotifyMaybeTextInputClientChanged();
}
void WebView::DidShowFullscreenWidget(int routing_id) {
@@ -225,21 +270,27 @@ void WebView::DidDestroyFullscreenWidget(int routing_id) {
ReattachForFullscreenChange(false);
}
+void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen) {
+ if (embed_fullscreen_widget_mode_enabled_)
+ ReattachForFullscreenChange(entered_fullscreen);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebView, private:
void WebView::AttachWebContents() {
// Prevents attachment if the WebView isn't already in a Widget, or it's
// already attached.
- if (!GetWidget() || !web_contents_)
+ if (!GetWidget() || !web_contents())
return;
const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ?
- web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() :
- web_contents_->GetView()->GetNativeView();
- if (wcv_holder_->native_view() == view_to_attach)
+ web_contents()->GetFullscreenRenderWidgetHostView()->GetNativeView() :
+ web_contents()->GetNativeView();
+ OnBoundsChanged(bounds());
+ if (holder_->native_view() == view_to_attach)
return;
- wcv_holder_->Attach(view_to_attach);
+ holder_->Attach(view_to_attach);
// The view will not be focused automatically when it is attached, so we need
// to pass on focus to it if the FocusManager thinks the view is focused. Note
@@ -248,58 +299,61 @@ void WebView::AttachWebContents() {
if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus();
- WebContentsObserver::Observe(web_contents_);
-
-#if defined(OS_WIN) && defined(USE_AURA)
+#if defined(OS_WIN)
if (!is_embedding_fullscreen_widget_) {
- web_contents_->SetParentNativeViewAccessible(
+ web_contents()->SetParentNativeViewAccessible(
parent()->GetNativeViewAccessible());
}
#endif
}
void WebView::DetachWebContents() {
- if (web_contents_) {
- wcv_holder_->Detach();
+ if (web_contents()) {
+ holder_->Detach();
#if defined(OS_WIN)
- if (!is_embedding_fullscreen_widget_) {
-#if !defined(USE_AURA)
- // TODO(beng): This should either not be necessary, or be done implicitly
- // by NativeViewHostWin on Detach(). As it stands, this is needed so that
- // the of the detached contents knows to tell the renderer it's been
- // hidden.
- //
- // Moving this out of here would also mean we wouldn't be potentially
- // calling member functions on a half-destroyed WebContents.
- ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE);
-#else
- web_contents_->SetParentNativeViewAccessible(NULL);
-#endif
- }
+ if (!is_embedding_fullscreen_widget_)
+ web_contents()->SetParentNativeViewAccessible(NULL);
#endif
}
- WebContentsObserver::Observe(NULL);
}
void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
- DetachWebContents();
- is_embedding_fullscreen_widget_ = enter_fullscreen &&
- web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
- AttachWebContents();
+ DCHECK(embed_fullscreen_widget_mode_enabled_);
+ const bool web_contents_has_separate_fs_widget =
+ 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();
+ is_embedding_fullscreen_widget_ =
+ enter_fullscreen && web_contents_has_separate_fs_widget;
+ AttachWebContents();
+ } else {
+ // Entering or exiting "non-Flash" fullscreen mode, where the native view is
+ // the same. So, do not change attachment.
+ OnBoundsChanged(bounds());
+ }
+ NotifyMaybeTextInputClientChanged();
+}
+
+void WebView::NotifyMaybeTextInputClientChanged() {
+ // Update the TextInputClient as needed; see GetTextInputClient().
+ FocusManager* const focus_manager = GetFocusManager();
+ if (focus_manager)
+ focus_manager->OnTextInputClientChanged(this);
}
content::WebContents* WebView::CreateWebContents(
- content::BrowserContext* browser_context,
- content::SiteInstance* site_instance) {
+ content::BrowserContext* browser_context) {
content::WebContents* contents = NULL;
if (ViewsDelegate::views_delegate) {
contents = ViewsDelegate::views_delegate->CreateWebContents(
- browser_context, site_instance);
+ browser_context, NULL);
}
if (!contents) {
content::WebContents::CreateParams create_params(
- browser_context, site_instance);
+ browser_context, NULL);
return content::WebContents::Create(create_params);
}
diff --git a/chromium/ui/views/controls/webview/webview.gyp b/chromium/ui/views/controls/webview/webview.gyp
index 6d74ef2dfad..39d40201d80 100644
--- a/chromium/ui/views/controls/webview/webview.gyp
+++ b/chromium/ui/views/controls/webview/webview.gyp
@@ -17,9 +17,10 @@
'../../../../content/content.gyp:content_browser',
'../../../../skia/skia.gyp:skia',
'../../../../url/url.gyp:url_lib',
+ '../../../base/ui_base.gyp:ui_base',
'../../../events/events.gyp:events',
'../../../gfx/gfx.gyp:gfx',
- '../../../ui.gyp:ui',
+ '../../../gfx/gfx.gyp:gfx_geometry',
'../../../web_dialogs/web_dialogs.gyp:web_dialogs',
'../../views.gyp:views',
],
diff --git a/chromium/ui/views/controls/webview/webview.h b/chromium/ui/views/controls/webview/webview.h
index ae789be2aaa..5cbb8874286 100644
--- a/chromium/ui/views/controls/webview/webview.h
+++ b/chromium/ui/views/controls/webview/webview.h
@@ -13,14 +13,24 @@
#include "ui/views/controls/webview/webview_export.h"
#include "ui/views/view.h"
-namespace content {
-class SiteInstance;
-}
-
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.,
+// for browser tabs).
+//
+// WebView creates and owns a single child view, a NativeViewHost, which will
+// hold and display the native view provided by a WebContents.
+//
+// EmbedFullscreenWidgetMode: When enabled, WebView will observe for WebContents
+// fullscreen changes and automatically swap the normal native view with the
+// fullscreen native view (if different). In addition, if the WebContents is
+// being screen-captured, the view will be centered within WebView, sized to
+// the aspect ratio of the capture video resolution, and scaling will be avoided
+// whenever possible.
class WEBVIEW_EXPORT WebView : public View,
public content::WebContentsDelegate,
public content::WebContentsObserver {
@@ -34,10 +44,6 @@ class WEBVIEW_EXPORT WebView : public View,
// WebView owns this implicitly created WebContents.
content::WebContents* GetWebContents();
- // Creates a WebContents if none is yet assocaited with this WebView, with the
- // specified site instance. The WebView owns this WebContents.
- void CreateWebContentsWithSiteInstance(content::SiteInstance* site_instance);
-
// WebView does not assume ownership of WebContents set via this method, only
// those it implicitly creates via GetWebContents() above.
void SetWebContents(content::WebContents* web_contents);
@@ -48,7 +54,9 @@ class WEBVIEW_EXPORT WebView : public View,
// widget or restore the normal WebContentsView.
void SetEmbedFullscreenWidgetMode(bool mode);
- content::WebContents* web_contents() { return web_contents_; }
+ content::WebContents* web_contents() const {
+ return content::WebContentsObserver::web_contents();
+ }
content::BrowserContext* browser_context() { return browser_context_; }
@@ -86,8 +94,9 @@ class WEBVIEW_EXPORT WebView : public View,
// Overridden from View:
virtual const char* GetClassName() const OVERRIDE;
+ virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
- private:
+ protected:
// Overridden from View:
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
virtual void ViewHierarchyChanged(
@@ -97,44 +106,48 @@ class WEBVIEW_EXPORT WebView : public View,
virtual bool IsFocusable() const OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void AboutToRequestFocusFromTabTraversal(bool reverse) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
// Overridden from content::WebContentsDelegate:
virtual void WebContentsFocused(content::WebContents* web_contents) OVERRIDE;
virtual bool EmbedsFullscreenWidget() const OVERRIDE;
// Overridden from content::WebContentsObserver:
+ virtual void RenderViewDeleted(
+ content::RenderViewHost* render_view_host) OVERRIDE;
virtual void RenderViewHostChanged(
content::RenderViewHost* old_host,
content::RenderViewHost* new_host) OVERRIDE;
- virtual void WebContentsDestroyed(
- content::WebContents* web_contents) OVERRIDE;
virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE;
virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE;
+ virtual void DidToggleFullscreenModeForTab(bool entered_fullscreen) OVERRIDE;
// Workaround for MSVC++ linker bug/feature that requires
// instantiation of the inline IPC::Listener methods in all translation units.
virtual void OnChannelConnected(int32 peer_id) OVERRIDE {}
virtual void OnChannelError() OVERRIDE {}
+ virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE {}
+ private:
void AttachWebContents();
void DetachWebContents();
void ReattachForFullscreenChange(bool enter_fullscreen);
+ void NotifyMaybeTextInputClientChanged();
// Create a regular or test web contents (based on whether we're running
// in a unit test or not).
content::WebContents* CreateWebContents(
- content::BrowserContext* browser_context,
- content::SiteInstance* site_instance);
+ content::BrowserContext* browser_context);
- NativeViewHost* wcv_holder_;
+ NativeViewHost* const holder_;
+ // Non-NULL if |web_contents()| was created and is owned by this WebView.
scoped_ptr<content::WebContents> wc_owner_;
- content::WebContents* web_contents_;
// When true, WebView auto-embeds fullscreen widgets as a child view.
bool embed_fullscreen_widget_mode_enabled_;
// Set to true while WebView is embedding a fullscreen widget view as a child
- // view instead of the normal WebContentsView render view.
+ // 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_;
content::BrowserContext* browser_context_;
bool allow_accelerators_;
diff --git a/chromium/ui/views/controls/webview/webview_interactive_uitest.cc b/chromium/ui/views/controls/webview/webview_interactive_uitest.cc
new file mode 100644
index 00000000000..f1179b83eab
--- /dev/null
+++ b/chromium/ui/views/controls/webview/webview_interactive_uitest.cc
@@ -0,0 +1,82 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/webview/webview.h"
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread.h"
+#include "ui/base/ime/text_input_focus_manager.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/views/test/webview_test_helper.h"
+#include "ui/views/test/widget_test.h"
+
+namespace {
+
+class WebViewInteractiveUiTest : public views::test::WidgetTest {
+ public:
+ WebViewInteractiveUiTest()
+ : ui_thread_(content::BrowserThread::UI, base::MessageLoop::current()) {}
+
+ virtual void SetUp() OVERRIDE {
+ gfx::GLSurface::InitializeOneOffForTests();
+ WidgetTest::SetUp();
+ }
+
+ protected:
+ content::BrowserContext* browser_context() { return &browser_context_; }
+
+ private:
+ content::TestBrowserContext browser_context_;
+ views::WebViewTestHelper webview_test_helper_;
+ content::TestBrowserThread ui_thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebViewInteractiveUiTest);
+};
+
+TEST_F(WebViewInteractiveUiTest, TextInputClientIsUpToDate) {
+ // WebViewInteractiveUiTest.TextInputClientIsUpToDate needs
+ // kEnableTextInputFocusManager flag to be enabled.
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager);
+
+ // Create a top level widget and a webview as its content.
+ views::Widget* widget = CreateTopLevelFramelessPlatformWidget();
+ views::WebView* webview = new views::WebView(browser_context());
+ widget->SetContentsView(webview);
+ widget->Show();
+ webview->RequestFocus();
+
+ ui::TextInputFocusManager* text_input_focus_manager =
+ ui::TextInputFocusManager::GetInstance();
+ const ui::TextInputClient* null_text_input_client = NULL;
+ EXPECT_EQ(null_text_input_client, webview->GetTextInputClient());
+ EXPECT_EQ(text_input_focus_manager->GetFocusedTextInputClient(),
+ webview->GetTextInputClient());
+
+ // Case 1: Creates a new WebContents.
+ webview->GetWebContents();
+ webview->RequestFocus();
+ ui::TextInputClient* client1 = webview->GetTextInputClient();
+ EXPECT_NE(null_text_input_client, client1);
+ EXPECT_EQ(text_input_focus_manager->GetFocusedTextInputClient(), client1);
+
+ // Case 2: Replaces a WebContents by SetWebContents().
+ content::WebContents::CreateParams params(browser_context());
+ scoped_ptr<content::WebContents> web_contents(
+ content::WebContents::Create(params));
+ webview->SetWebContents(web_contents.get());
+ ui::TextInputClient* client2 = webview->GetTextInputClient();
+ EXPECT_NE(null_text_input_client, client2);
+ EXPECT_EQ(text_input_focus_manager->GetFocusedTextInputClient(), client2);
+ EXPECT_NE(client1, client2);
+
+ widget->Close();
+ RunPendingMessages();
+}
+
+} // namespace
diff --git a/chromium/ui/views/controls/webview/webview_tests.gyp b/chromium/ui/views/controls/webview/webview_tests.gyp
new file mode 100644
index 00000000000..0adc5c2befc
--- /dev/null
+++ b/chromium/ui/views/controls/webview/webview_tests.gyp
@@ -0,0 +1,38 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'webview_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../../../base/base.gyp:base',
+ '../../../../content/content.gyp:content',
+ '../../../../content/content_shell_and_tests.gyp:test_support_content',
+ '../../../../ipc/ipc.gyp:test_support_ipc',
+ '../../../../skia/skia.gyp:skia',
+ '../../../../testing/gtest.gyp:gtest',
+ '../../../aura/aura.gyp:aura',
+ '../../../base/ui_base.gyp:ui_base',
+ '../../../events/events.gyp:events',
+ '../../../gfx/gfx.gyp:gfx',
+ '../../../gfx/gfx.gyp:gfx_geometry',
+ '../../views.gyp:views',
+ '../../views.gyp:views_test_support',
+ 'webview.gyp:webview',
+ ],
+ 'include_dirs': [
+ '../../../..',
+ ],
+ 'sources': [
+ '../../test/webview_test_helper.cc',
+ '../../test/webview_test_helper.h',
+ ],
+ },
+ ],
+}
diff --git a/chromium/ui/views/corewm/DEPS b/chromium/ui/views/corewm/DEPS
index 06abf634093..a2d52d61d09 100644
--- a/chromium/ui/views/corewm/DEPS
+++ b/chromium/ui/views/corewm/DEPS
@@ -1,4 +1,57 @@
-# This code should not depend on Views.
-
-"-ui/views",
-"+ui/views/views_export.h"
+# This code should not depend on Views.
+
+include_rules = [
+ "-ui/views",
+ "+ui/views/corewm",
+ "+ui/views/views_export.h",
+]
+
+# TODO: temporary, don't add more.
+specific_include_rules = {
+ "tooltip_controller.cc": [
+ "+ui/views/widget/tooltip_manager.h",
+ ],
+
+ "tooltip_aura.cc": [
+ "+ui/views/background.h",
+ "+ui/views/border.h",
+ "+ui/views/widget/widget.h",
+ ],
+
+ "desktop_capture_controller_unittest.cc": [
+ "+ui/views/test/views_test_base.h",
+ "+ui/views/view.h",
+ "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h",
+ "+ui/views/widget/desktop_aura/desktop_screen_position_client.h",
+ "+ui/views/widget/root_view.h",
+ "+ui/views/widget/widget.h",
+ ],
+
+ "tooltip_controller_unittest.cc": [
+ "+ui/views/test/desktop_test_views_delegate.h",
+ "+ui/views/test/test_views_delegate.h",
+ "+ui/views/view.h",
+ "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h",
+ "+ui/views/widget/desktop_aura/desktop_screen.h",
+ "+ui/views/widget/tooltip_manager.h",
+ "+ui/views/widget/widget.h",
+ ],
+
+ "tooltip_aura.h": [
+ "+ui/views/controls/label.h",
+ "+ui/views/widget/widget_observer.h",
+ ],
+
+ "tooltip_controller_test_helper.h": [
+ "+ui/views/view.h",
+ ],
+
+ "capture_controller_unittest.cc": [
+ "+ui/views/test/views_test_base.h",
+ "+ui/views/view.h",
+ "+ui/views/widget/desktop_aura/desktop_native_widget_aura.h",
+ "+ui/views/widget/desktop_aura/desktop_screen_position_client.h",
+ "+ui/views/widget/root_view.h",
+ "+ui/views/widget/widget.h",
+ ],
+}
diff --git a/chromium/ui/views/corewm/base_focus_rules.cc b/chromium/ui/views/corewm/base_focus_rules.cc
deleted file mode 100644
index 9520c749cd0..00000000000
--- a/chromium/ui/views/corewm/base_focus_rules.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/base_focus_rules.h"
-
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/views/corewm/window_modality_controller.h"
-
-namespace views {
-namespace corewm {
-namespace {
-
-aura::Window* GetFocusedWindow(aura::Window* context) {
- aura::client::FocusClient* focus_client =
- aura::client::GetFocusClient(context);
- return focus_client ? focus_client->GetFocusedWindow() : NULL;
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// BaseFocusRules, protected:
-
-BaseFocusRules::BaseFocusRules() {
-}
-
-BaseFocusRules::~BaseFocusRules() {
-}
-
-bool BaseFocusRules::IsWindowConsideredVisibleForActivation(
- aura::Window* window) const {
- return window->IsVisible();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// BaseFocusRules, FocusRules implementation:
-
-bool BaseFocusRules::IsToplevelWindow(aura::Window* window) const {
- // The window must in a valid hierarchy.
- if (!window->GetRootWindow())
- return false;
-
- // The window must exist within a container that supports activation.
- // The window cannot be blocked by a modal transient.
- return SupportsChildActivation(window->parent());
-}
-
-bool BaseFocusRules::CanActivateWindow(aura::Window* window) const {
- // It is possible to activate a NULL window, it is equivalent to clearing
- // activation.
- if (!window)
- return true;
-
- // Only toplevel windows can be activated.
- if (!IsToplevelWindow(window))
- return false;
-
- // The window must be visible.
- if (!IsWindowConsideredVisibleForActivation(window))
- return false;
-
- // The window's activation delegate must allow this window to be activated.
- if (aura::client::GetActivationDelegate(window) &&
- !aura::client::GetActivationDelegate(window)->ShouldActivate()) {
- return false;
- }
-
- // A window must be focusable to be activatable. We don't call
- // CanFocusWindow() from here because it will call back to us via
- // GetActivatableWindow().
- if (!window->CanFocus())
- return false;
-
- // The window cannot be blocked by a modal transient.
- return !GetModalTransient(window);
-}
-
-bool BaseFocusRules::CanFocusWindow(aura::Window* window) const {
- // It is possible to focus a NULL window, it is equivalent to clearing focus.
- if (!window)
- return true;
-
- // The focused window is always inside the active window, so windows that
- // aren't activatable can't contain the focused window.
- aura::Window* activatable = GetActivatableWindow(window);
- if (!activatable || !activatable->Contains(window))
- return false;
- return window->CanFocus();
-}
-
-aura::Window* BaseFocusRules::GetToplevelWindow(aura::Window* window) const {
- aura::Window* parent = window->parent();
- aura::Window* child = window;
- while (parent) {
- if (IsToplevelWindow(child))
- return child;
-
- parent = parent->parent();
- child = child->parent();
- }
- return NULL;
-}
-
-aura::Window* BaseFocusRules::GetActivatableWindow(aura::Window* window) const {
- aura::Window* parent = window->parent();
- aura::Window* child = window;
- while (parent) {
- if (CanActivateWindow(child))
- return child;
-
- // CanActivateWindow() above will return false if |child| is blocked by a
- // modal transient. In this case the modal is or contains the activatable
- // window. We recurse because the modal may itself be blocked by a modal
- // transient.
- aura::Window* modal_transient = GetModalTransient(child);
- if (modal_transient)
- return GetActivatableWindow(modal_transient);
-
- if (child->transient_parent()) {
- // To avoid infinite recursion, if |child| has a transient parent
- // whose own modal transient is |child| itself, just return |child|.
- aura::Window* parent_modal_transient =
- GetModalTransient(child->transient_parent());
- if (parent_modal_transient == child)
- return child;
-
- return GetActivatableWindow(child->transient_parent());
- }
-
- parent = parent->parent();
- child = child->parent();
- }
- return NULL;
-}
-
-aura::Window* BaseFocusRules::GetFocusableWindow(aura::Window* window) const {
- if (CanFocusWindow(window))
- return window;
-
- // |window| may be in a hierarchy that is non-activatable, in which case we
- // need to cut over to the activatable hierarchy.
- aura::Window* activatable = GetActivatableWindow(window);
- if (!activatable) {
- // There may not be a related activatable hierarchy to cut over to, in which
- // case we try an unrelated one.
- aura::Window* toplevel = GetToplevelWindow(window);
- if (toplevel)
- activatable = GetNextActivatableWindow(toplevel);
- if (!activatable)
- return NULL;
- }
-
- if (!activatable->Contains(window)) {
- // If there's already a child window focused in the activatable hierarchy,
- // just use that (i.e. don't shift focus), otherwise we need to at least cut
- // over to the activatable hierarchy.
- aura::Window* focused = GetFocusedWindow(activatable);
- return activatable->Contains(focused) ? focused : activatable;
- }
-
- while (window && !CanFocusWindow(window))
- window = window->parent();
- return window;
-}
-
-aura::Window* BaseFocusRules::GetNextActivatableWindow(
- aura::Window* ignore) const {
- DCHECK(ignore);
-
- // Can be called from the RootWindow's destruction, which has a NULL parent.
- if (!ignore->parent())
- return NULL;
-
- // In the basic scenarios handled by BasicFocusRules, the pool of activatable
- // windows is limited to the |ignore|'s siblings.
- const aura::Window::Windows& siblings = ignore->parent()->children();
- DCHECK(!siblings.empty());
-
- for (aura::Window::Windows::const_reverse_iterator rit = siblings.rbegin();
- rit != siblings.rend();
- ++rit) {
- aura::Window* cur = *rit;
- if (cur == ignore)
- continue;
- if (CanActivateWindow(cur))
- return cur;
- }
- return NULL;
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/base_focus_rules.h b/chromium/ui/views/corewm/base_focus_rules.h
deleted file mode 100644
index 4c564b0e798..00000000000
--- a/chromium/ui/views/corewm/base_focus_rules.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_
-#define UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ui/views/corewm/focus_rules.h"
-
-namespace views {
-namespace corewm {
-
-// A set of basic focus and activation rules. Specializations should most likely
-// subclass this and call up to these methods rather than reimplementing them.
-class VIEWS_EXPORT BaseFocusRules : public FocusRules {
- protected:
- BaseFocusRules();
- virtual ~BaseFocusRules();
-
- // Returns true if the children of |window| can be activated.
- virtual bool SupportsChildActivation(aura::Window* window) const = 0;
-
- // Returns true if |window| is considered visible for activation purposes.
- virtual bool IsWindowConsideredVisibleForActivation(
- aura::Window* window) const;
-
- // Overridden from FocusRules:
- virtual bool IsToplevelWindow(aura::Window* window) const OVERRIDE;
- virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE;
- virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE;
- virtual aura::Window* GetToplevelWindow(aura::Window* window) const OVERRIDE;
- virtual aura::Window* GetActivatableWindow(
- aura::Window* window) const OVERRIDE;
- virtual aura::Window* GetFocusableWindow(aura::Window* window) const OVERRIDE;
- virtual aura::Window* GetNextActivatableWindow(
- aura::Window* ignore) const OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BaseFocusRules);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_BASE_FOCUS_RULES_H_
diff --git a/chromium/ui/views/corewm/capture_controller.cc b/chromium/ui/views/corewm/capture_controller.cc
deleted file mode 100644
index 9a65e381da1..00000000000
--- a/chromium/ui/views/corewm/capture_controller.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/capture_controller.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-
-namespace views {
-namespace corewm {
-
-////////////////////////////////////////////////////////////////////////////////
-// CaptureController, public:
-
-void CaptureController::Attach(aura::Window* root) {
- DCHECK_EQ(0u, root_windows_.count(root));
- root_windows_.insert(root);
- aura::client::SetCaptureClient(root, this);
-}
-
-void CaptureController::Detach(aura::Window* root) {
- root_windows_.erase(root);
- aura::client::SetCaptureClient(root, NULL);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CaptureController, aura::client::CaptureClient implementation:
-
-void CaptureController::SetCapture(aura::Window* new_capture_window) {
- if (capture_window_ == new_capture_window)
- return;
-
- // Make sure window has a root window.
- DCHECK(!new_capture_window || new_capture_window->GetRootWindow());
- DCHECK(!capture_window_ || capture_window_->GetRootWindow());
-
- aura::Window* old_capture_window = capture_window_;
- aura::Window* old_capture_root = old_capture_window ?
- old_capture_window->GetRootWindow() : NULL;
-
- // Copy the list in case it's modified out from under us.
- RootWindows root_windows(root_windows_);
-
- // If we're actually starting capture, then cancel any touches/gestures
- // that aren't already locked to the new window, and transfer any on the
- // old capture window to the new one. When capture is released we have no
- // distinction between the touches/gestures that were in the window all
- // along (and so shouldn't be canceled) and those that got moved, so
- // just leave them all where they are.
- if (new_capture_window) {
- ui::GestureRecognizer::Get()->TransferEventsTo(old_capture_window,
- new_capture_window);
- }
-
- capture_window_ = new_capture_window;
-
- for (RootWindows::const_iterator i = root_windows.begin();
- i != root_windows.end(); ++i) {
- aura::client::CaptureDelegate* delegate = (*i)->GetDispatcher();
- delegate->UpdateCapture(old_capture_window, new_capture_window);
- }
-
- aura::Window* capture_root =
- capture_window_ ? capture_window_->GetRootWindow() : NULL;
- if (capture_root != old_capture_root) {
- if (old_capture_root) {
- aura::client::CaptureDelegate* delegate =
- old_capture_root->GetDispatcher();
- delegate->ReleaseNativeCapture();
- }
- if (capture_root) {
- aura::client::CaptureDelegate* delegate = capture_root->GetDispatcher();
- delegate->SetNativeCapture();
- }
- }
-}
-
-void CaptureController::ReleaseCapture(aura::Window* window) {
- if (capture_window_ != window)
- return;
- SetCapture(NULL);
-}
-
-aura::Window* CaptureController::GetCaptureWindow() {
- return capture_window_;
-}
-
-aura::Window* CaptureController::GetGlobalCaptureWindow() {
- return capture_window_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CaptureController, private:
-
-CaptureController::CaptureController()
- : capture_window_(NULL) {
-}
-
-CaptureController::~CaptureController() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// ScopedCaptureClient:
-
-// static
-CaptureController* ScopedCaptureClient::capture_controller_ = NULL;
-
-ScopedCaptureClient::ScopedCaptureClient(aura::Window* root)
- : root_window_(root) {
- root->AddObserver(this);
- if (!capture_controller_)
- capture_controller_ = new CaptureController;
- capture_controller_->Attach(root);
-}
-
-ScopedCaptureClient::~ScopedCaptureClient() {
- Shutdown();
-}
-
-// static
-bool ScopedCaptureClient::IsActive() {
- return capture_controller_ && capture_controller_->is_active();
-}
-
-void ScopedCaptureClient::OnWindowDestroyed(aura::Window* window) {
- DCHECK_EQ(window, root_window_);
- Shutdown();
-}
-
-void ScopedCaptureClient::Shutdown() {
- if (!root_window_)
- return;
-
- root_window_->RemoveObserver(this);
- capture_controller_->Detach(root_window_);
- if (!capture_controller_->is_active()) {
- delete capture_controller_;
- capture_controller_ = NULL;
- }
- root_window_ = NULL;
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/capture_controller.h b/chromium/ui/views/corewm/capture_controller.h
deleted file mode 100644
index e7d1ffd6eca..00000000000
--- a/chromium/ui/views/corewm/capture_controller.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_
-#define UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ui/aura/client/capture_client.h"
-#include "ui/aura/window_observer.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-
-// Internal CaptureClient implementation. See ScopedCaptureClient for details.
-class VIEWS_EXPORT CaptureController : public aura::client::CaptureClient {
- public:
- // Adds |root| to the list of RootWindows notified when capture changes.
- void Attach(aura::Window* root);
-
- // Removes |root| from the list of RootWindows notified when capture changes.
- void Detach(aura::Window* root);
-
- // Returns true if this CaptureController is installed on at least one
- // RootWindow.
- bool is_active() const { return !root_windows_.empty(); }
-
- // Overridden from aura::client::CaptureClient:
- virtual void SetCapture(aura::Window* window) OVERRIDE;
- virtual void ReleaseCapture(aura::Window* window) OVERRIDE;
- virtual aura::Window* GetCaptureWindow() OVERRIDE;
- virtual aura::Window* GetGlobalCaptureWindow() OVERRIDE;
-
- private:
- friend class ScopedCaptureClient;
- typedef std::set<aura::Window*> RootWindows;
-
- CaptureController();
- virtual ~CaptureController();
-
- // The current capture window. NULL if there is no capture window.
- aura::Window* capture_window_;
-
- // Set of RootWindows notified when capture changes.
- RootWindows root_windows_;
-
- DISALLOW_COPY_AND_ASSIGN(CaptureController);
-};
-
-// ScopedCaptureClient is responsible for creating a CaptureClient for a
-// RootWindow. Specifically it creates a single CaptureController that is shared
-// among all ScopedCaptureClients and adds the RootWindow to it.
-class VIEWS_EXPORT ScopedCaptureClient : public aura::WindowObserver {
- public:
- explicit ScopedCaptureClient(aura::Window* root);
- virtual ~ScopedCaptureClient();
-
- // Returns true if there is a CaptureController with at least one RootWindow.
- static bool IsActive();
-
- aura::client::CaptureClient* capture_client() {
- return capture_controller_;
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
-
- private:
- // Invoked from destructor and OnWindowDestroyed() to cleanup.
- void Shutdown();
-
- // The single CaptureController instance.
- static CaptureController* capture_controller_;
-
- // RootWindow this ScopedCaptureClient was create for.
- aura::Window* root_window_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedCaptureClient);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_CAPTURE_CONTROLLER_H_
diff --git a/chromium/ui/views/corewm/capture_controller_unittest.cc b/chromium/ui/views/corewm/capture_controller_unittest.cc
index 558a4030f51..ffece4a89ab 100644
--- a/chromium/ui/views/corewm/capture_controller_unittest.cc
+++ b/chromium/ui/views/corewm/capture_controller_unittest.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/corewm/capture_controller.h"
+#include "ui/wm/core/capture_controller.h"
#include "base/logging.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/views/test/views_test_base.h"
@@ -32,25 +32,21 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
virtual void SetUp() OVERRIDE {
AuraTestBase::SetUp();
- capture_controller_.reset(new corewm::ScopedCaptureClient(root_window()));
+ capture_controller_.reset(new wm::ScopedCaptureClient(root_window()));
- second_root_.reset(new aura::RootWindow(
- aura::RootWindow::CreateParams(gfx::Rect(0, 0, 800, 600))));
- second_root_->Init();
- second_root_->window()->Show();
- second_root_->SetHostSize(gfx::Size(800, 600));
+ second_host_.reset(aura::WindowTreeHost::Create(gfx::Rect(0, 0, 800, 600)));
+ second_host_->InitHost();
+ second_host_->window()->Show();
+ second_host_->SetBounds(gfx::Rect(800, 600));
second_capture_controller_.reset(
- new corewm::ScopedCaptureClient(second_root_->window()));
+ new wm::ScopedCaptureClient(second_host_->window()));
#if !defined(OS_CHROMEOS)
- desktop_position_client_.reset(new DesktopScreenPositionClient());
- aura::client::SetScreenPositionClient(root_window(),
- desktop_position_client_.get());
-
- second_desktop_position_client_.reset(new DesktopScreenPositionClient());
- aura::client::SetScreenPositionClient(
- second_root_->window(),
- second_desktop_position_client_.get());
+ desktop_position_client_.reset(
+ new DesktopScreenPositionClient(root_window()));
+
+ second_desktop_position_client_.reset(
+ new DesktopScreenPositionClient(second_host_->window()));
#endif
}
@@ -63,7 +59,7 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
second_capture_controller_.reset();
// Kill any active compositors before we hit the compositor shutdown paths.
- second_root_.reset();
+ second_host_.reset();
#if !defined(OS_CHROMEOS)
desktop_position_client_.reset();
@@ -81,9 +77,9 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
return second_capture_controller_->capture_client()->GetCaptureWindow();
}
- scoped_ptr<corewm::ScopedCaptureClient> capture_controller_;
- scoped_ptr<aura::RootWindow> second_root_;
- scoped_ptr<corewm::ScopedCaptureClient> second_capture_controller_;
+ scoped_ptr<wm::ScopedCaptureClient> capture_controller_;
+ scoped_ptr<aura::WindowTreeHost> second_host_;
+ scoped_ptr<wm::ScopedCaptureClient> second_capture_controller_;
#if !defined(OS_CHROMEOS)
scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client_;
scoped_ptr<aura::client::ScreenPositionClient>
@@ -96,50 +92,50 @@ class CaptureControllerTest : public aura::test::AuraTestBase {
// Makes sure that internal details that are set on mouse down (such as
// mouse_pressed_handler()) are cleared when another root window takes capture.
TEST_F(CaptureControllerTest, ResetMouseEventHandlerOnCapture) {
- // Create a window inside the RootWindow.
+ // Create a window inside the WindowEventDispatcher.
scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL));
- // Make a synthesized mouse down event. Ensure that the RootWindow will
- // dispatch further mouse events to |w1|.
+ // Make a synthesized mouse down event. Ensure that the WindowEventDispatcher
+ // will dispatch further mouse events to |w1|.
ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5),
- gfx::Point(5, 5), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(
- &mouse_pressed_event);
- EXPECT_EQ(w1.get(), dispatcher()->mouse_pressed_handler());
+ gfx::Point(5, 5), 0, 0);
+ DispatchEventUsingWindowDispatcher(&mouse_pressed_event);
+ EXPECT_EQ(w1.get(), host()->dispatcher()->mouse_pressed_handler());
- // Build a window in the second RootWindow.
+ // Build a window in the second WindowEventDispatcher.
scoped_ptr<aura::Window> w2(
- CreateNormalWindow(2, second_root_->window(), NULL));
+ CreateNormalWindow(2, second_host_->window(), NULL));
// The act of having the second window take capture should clear out mouse
- // pressed handler in the first RootWindow.
+ // pressed handler in the first WindowEventDispatcher.
w2->SetCapture();
- EXPECT_EQ(NULL, dispatcher()->mouse_pressed_handler());
+ EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
}
// Makes sure that when one window gets capture, it forces the release on the
// other. This is needed has to be handled explicitly on Linux, and is a sanity
// check on Windows.
TEST_F(CaptureControllerTest, ResetOtherWindowCaptureOnCapture) {
- // Create a window inside the RootWindow.
+ // Create a window inside the WindowEventDispatcher.
scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL));
w1->SetCapture();
// Both capture clients should return the same capture window.
EXPECT_EQ(w1.get(), GetCaptureWindow());
EXPECT_EQ(w1.get(), GetSecondCaptureWindow());
- // Build a window in the second RootWindow and give it capture. Both capture
- // clients should return the same capture window.
+ // Build a window in the second WindowEventDispatcher and give it capture.
+ // Both capture clients should return the same capture window.
scoped_ptr<aura::Window> w2(
- CreateNormalWindow(2, second_root_->window(), NULL));
+ CreateNormalWindow(2, second_host_->window(), NULL));
w2->SetCapture();
EXPECT_EQ(w2.get(), GetCaptureWindow());
EXPECT_EQ(w2.get(), GetSecondCaptureWindow());
}
-// Verifies the touch target for the RootWindow gets reset on releasing capture.
+// Verifies the touch target for the WindowEventDispatcher gets reset on
+// releasing capture.
TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) {
- // Create a window inside the RootWindow.
+ // Create a window inside the WindowEventDispatcher.
scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL));
aura::test::EventGenerator event_generator1(root_window());
event_generator1.PressTouch();
@@ -148,17 +144,17 @@ TEST_F(CaptureControllerTest, TouchTargetResetOnCaptureChange) {
EXPECT_EQ(w1.get(), GetCaptureWindow());
EXPECT_EQ(w1.get(), GetSecondCaptureWindow());
- // Build a window in the second RootWindow and give it capture. Both capture
- // clients should return the same capture window.
+ // Build a window in the second WindowEventDispatcher and give it capture.
+ // Both capture clients should return the same capture window.
scoped_ptr<aura::Window> w2(
- CreateNormalWindow(2, second_root_->window(), NULL));
+ CreateNormalWindow(2, second_host_->window(), NULL));
w2->SetCapture();
EXPECT_EQ(w2.get(), GetCaptureWindow());
EXPECT_EQ(w2.get(), GetSecondCaptureWindow());
// Release capture on the window. Releasing capture should reset the touch
- // target of the first RootWindow (as it no longer contains the capture
- // target).
+ // target of the first WindowEventDispatcher (as it no longer contains the
+ // capture target).
w2->ReleaseCapture();
EXPECT_EQ(static_cast<aura::Window*>(NULL), GetCaptureWindow());
EXPECT_EQ(static_cast<aura::Window*>(NULL), GetSecondCaptureWindow());
diff --git a/chromium/ui/views/corewm/compound_event_filter.cc b/chromium/ui/views/corewm/compound_event_filter.cc
deleted file mode 100644
index efeca5cad2a..00000000000
--- a/chromium/ui/views/corewm/compound_event_filter.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/compound_event_filter.h"
-
-#include "base/containers/hash_tables.h"
-#include "base/logging.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/base/hit_test.h"
-#include "ui/events/event.h"
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-bool ShouldHideCursorOnKeyEvent(const ui::KeyEvent& event) {
-#if defined(OS_CHROMEOS)
- // All alt and control key commands are ignored.
- if (event.IsAltDown() || event.IsControlDown())
- return false;
-
- static bool inited = false;
- static base::hash_set<int32> ignored_keys;
- if (!inited) {
- // Modifiers.
- ignored_keys.insert(ui::VKEY_SHIFT);
- ignored_keys.insert(ui::VKEY_CONTROL);
- ignored_keys.insert(ui::VKEY_MENU);
-
- // Search key == VKEY_LWIN.
- ignored_keys.insert(ui::VKEY_LWIN);
-
- // Function keys.
- for (int key = ui::VKEY_F1; key <= ui::VKEY_F24; ++key)
- ignored_keys.insert(key);
-
- // Media keys.
- for (int key = ui::VKEY_BROWSER_BACK; key <= ui::VKEY_MEDIA_LAUNCH_APP2;
- ++key) {
- ignored_keys.insert(key);
- }
-
-#if defined(OS_POSIX)
- ignored_keys.insert(ui::VKEY_WLAN);
- ignored_keys.insert(ui::VKEY_POWER);
- ignored_keys.insert(ui::VKEY_BRIGHTNESS_DOWN);
- ignored_keys.insert(ui::VKEY_BRIGHTNESS_UP);
- ignored_keys.insert(ui::VKEY_KBD_BRIGHTNESS_DOWN);
- ignored_keys.insert(ui::VKEY_KBD_BRIGHTNESS_UP);
-#endif
-
- inited = true;
- }
-
- if (ignored_keys.count(event.key_code()) > 0)
- return false;
-
- return true;
-#else // !defined(OS_CHROMEOS)
- return false;
-#endif // defined(OS_CHROMEOS)
-}
-
-// Returns true if the cursor should be hidden on touch events.
-bool ShouldHideCursorOnTouch() {
-#if defined(OS_CHROMEOS)
- return true;
-#else
- // Not necessary on windows as windows does it for us. If we do need this
- // funcionality on linux (non-chromeos) we need to make sure
- // CompoundEventFilter shows on the right root (it currently doesn't always).
- return false;
-#endif
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// CompoundEventFilter, public:
-
-CompoundEventFilter::CompoundEventFilter() {
-}
-
-CompoundEventFilter::~CompoundEventFilter() {
- // Additional filters are not owned by CompoundEventFilter and they
- // should all be removed when running here. |handlers_| has
- // check_empty == true and will DCHECK failure if it is not empty.
-}
-
-// static
-gfx::NativeCursor CompoundEventFilter::CursorForWindowComponent(
- int window_component) {
- switch (window_component) {
- case HTBOTTOM:
- return ui::kCursorSouthResize;
- case HTBOTTOMLEFT:
- return ui::kCursorSouthWestResize;
- case HTBOTTOMRIGHT:
- return ui::kCursorSouthEastResize;
- case HTLEFT:
- return ui::kCursorWestResize;
- case HTRIGHT:
- return ui::kCursorEastResize;
- case HTTOP:
- return ui::kCursorNorthResize;
- case HTTOPLEFT:
- return ui::kCursorNorthWestResize;
- case HTTOPRIGHT:
- return ui::kCursorNorthEastResize;
- default:
- return ui::kCursorNull;
- }
-}
-
-void CompoundEventFilter::AddHandler(ui::EventHandler* handler) {
- handlers_.AddObserver(handler);
-}
-
-void CompoundEventFilter::RemoveHandler(ui::EventHandler* handler) {
- handlers_.RemoveObserver(handler);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CompoundEventFilter, private:
-
-void CompoundEventFilter::UpdateCursor(aura::Window* target,
- ui::MouseEvent* event) {
- // If drag and drop is in progress, let the drag drop client set the cursor
- // instead of setting the cursor here.
- aura::Window* root_window = target->GetRootWindow();
- aura::client::DragDropClient* drag_drop_client =
- aura::client::GetDragDropClient(root_window);
- if (drag_drop_client && drag_drop_client->IsDragDropInProgress())
- return;
-
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window);
- if (cursor_client) {
- gfx::NativeCursor cursor = target->GetCursor(event->location());
- if (event->flags() & ui::EF_IS_NON_CLIENT) {
- int window_component =
- target->delegate()->GetNonClientComponent(event->location());
- cursor = CursorForWindowComponent(window_component);
- }
-
- cursor_client->SetCursor(cursor);
- }
-}
-
-void CompoundEventFilter::FilterKeyEvent(ui::KeyEvent* event) {
- if (handlers_.might_have_observers()) {
- ObserverListBase<ui::EventHandler>::Iterator it(handlers_);
- ui::EventHandler* handler;
- while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL)
- handler->OnKeyEvent(event);
- }
-}
-
-void CompoundEventFilter::FilterMouseEvent(ui::MouseEvent* event) {
- if (handlers_.might_have_observers()) {
- ObserverListBase<ui::EventHandler>::Iterator it(handlers_);
- ui::EventHandler* handler;
- while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL)
- handler->OnMouseEvent(event);
- }
-}
-
-void CompoundEventFilter::FilterTouchEvent(ui::TouchEvent* event) {
- if (handlers_.might_have_observers()) {
- ObserverListBase<ui::EventHandler>::Iterator it(handlers_);
- ui::EventHandler* handler;
- while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL)
- handler->OnTouchEvent(event);
- }
-}
-
-void CompoundEventFilter::SetCursorVisibilityOnEvent(aura::Window* target,
- ui::Event* event,
- bool show) {
- if (event->flags() & ui::EF_IS_SYNTHESIZED)
- return;
-
- aura::client::CursorClient* client =
- aura::client::GetCursorClient(target->GetRootWindow());
- if (!client)
- return;
-
- if (show)
- client->ShowCursor();
- else
- client->HideCursor();
-}
-
-void CompoundEventFilter::SetMouseEventsEnableStateOnEvent(aura::Window* target,
- ui::Event* event,
- bool enable) {
- if (event->flags() & ui::EF_IS_SYNTHESIZED)
- return;
- aura::client::CursorClient* client =
- aura::client::GetCursorClient(target->GetRootWindow());
- if (!client)
- return;
-
- if (enable)
- client->EnableMouseEvents();
- else
- client->DisableMouseEvents();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CompoundEventFilter, ui::EventHandler implementation:
-
-void CompoundEventFilter::OnKeyEvent(ui::KeyEvent* event) {
- if (ShouldHideCursorOnKeyEvent(*event)) {
- SetCursorVisibilityOnEvent(
- static_cast<aura::Window*>(event->target()), event, false);
- }
-
- FilterKeyEvent(event);
-}
-
-void CompoundEventFilter::OnMouseEvent(ui::MouseEvent* event) {
- aura::Window* window = static_cast<aura::Window*>(event->target());
- aura::WindowTracker window_tracker;
- window_tracker.Add(window);
-
- // We must always update the cursor, otherwise the cursor can get stuck if an
- // event filter registered with us consumes the event.
- // It should also update the cursor for clicking and wheels for ChromeOS boot.
- // When ChromeOS is booted, it hides the mouse cursor but immediate mouse
- // operation will show the cursor.
- // We also update the cursor for mouse enter in case a mouse cursor is sent to
- // outside of the root window and moved back for some reasons (e.g. running on
- // on Desktop for testing, or a bug in pointer barrier).
- if (event->type() == ui::ET_MOUSE_ENTERED ||
- event->type() == ui::ET_MOUSE_MOVED ||
- event->type() == ui::ET_MOUSE_PRESSED ||
- event->type() == ui::ET_MOUSEWHEEL) {
- SetMouseEventsEnableStateOnEvent(window, event, true);
- SetCursorVisibilityOnEvent(window, event, true);
- UpdateCursor(window, event);
- }
-
- FilterMouseEvent(event);
-}
-
-void CompoundEventFilter::OnScrollEvent(ui::ScrollEvent* event) {
-}
-
-void CompoundEventFilter::OnTouchEvent(ui::TouchEvent* event) {
- FilterTouchEvent(event);
- if (ShouldHideCursorOnTouch() && !event->handled() &&
- event->type() == ui::ET_TOUCH_PRESSED &&
- !aura::Env::GetInstance()->IsMouseButtonDown()) {
- SetMouseEventsEnableStateOnEvent(
- static_cast<aura::Window*>(event->target()), event, false);
- }
-}
-
-void CompoundEventFilter::OnGestureEvent(ui::GestureEvent* event) {
- if (handlers_.might_have_observers()) {
- ObserverListBase<ui::EventHandler>::Iterator it(handlers_);
- ui::EventHandler* handler;
- while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL)
- handler->OnGestureEvent(event);
- }
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/compound_event_filter.h b/chromium/ui/views/corewm/compound_event_filter.h
deleted file mode 100644
index 7f724c35e06..00000000000
--- a/chromium/ui/views/corewm/compound_event_filter.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_
-#define UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_
-
-#include "base/compiler_specific.h"
-#include "base/observer_list.h"
-#include "ui/events/event.h"
-#include "ui/events/event_handler.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/views/views_export.h"
-
-namespace aura {
-class CursorManager;
-class RootWindow;
-}
-
-namespace ui {
-class GestureEvent;
-class KeyEvent;
-class LocatedEvent;
-class MouseEvent;
-class TouchEvent;
-}
-
-namespace views {
-namespace corewm {
-
-// CompoundEventFilter gets all events first and can provide actions to those
-// events. It implements global features such as click to activate a window and
-// cursor change when moving mouse.
-// Additional event filters can be added to CompoundEventFilter. Events will
-// pass through those additional filters in their addition order and could be
-// consumed by any of those filters. If an event is consumed by a filter, the
-// rest of the filter(s) and CompoundEventFilter will not see the consumed
-// event.
-class VIEWS_EXPORT CompoundEventFilter : public ui::EventHandler {
- public:
- CompoundEventFilter();
- virtual ~CompoundEventFilter();
-
- // Returns the cursor for the specified component.
- static gfx::NativeCursor CursorForWindowComponent(int window_component);
-
- // Adds/removes additional event filters. This does not take ownership of
- // the EventHandler.
- // NOTE: These handlers are deprecated. Use env::AddPreTargetEventHandler etc.
- // instead.
- void AddHandler(ui::EventHandler* filter);
- void RemoveHandler(ui::EventHandler* filter);
-
- private:
- // Updates the cursor if the target provides a custom one, and provides
- // default resize cursors for window edges.
- void UpdateCursor(aura::Window* target, ui::MouseEvent* event);
-
- // Dispatches event to additional filters.
- void FilterKeyEvent(ui::KeyEvent* event);
- void FilterMouseEvent(ui::MouseEvent* event);
- void FilterTouchEvent(ui::TouchEvent* event);
-
- // Sets the visibility of the cursor if the event is not synthesized.
- void SetCursorVisibilityOnEvent(aura::Window* target,
- ui::Event* event,
- bool show);
-
- // Enables or disables mouse events if the event is not synthesized.
- void SetMouseEventsEnableStateOnEvent(aura::Window* target,
- ui::Event* event,
- bool enable);
-
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
- // Additional pre-target event handlers.
- ObserverList<ui::EventHandler, true> handlers_;
-
- // True if the cursur was hidden by the filter.
- bool cursor_hidden_by_filter_;
-
- DISALLOW_COPY_AND_ASSIGN(CompoundEventFilter);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_COMPOUND_EVENT_FILTER_H_
diff --git a/chromium/ui/views/corewm/compound_event_filter_unittest.cc b/chromium/ui/views/corewm/compound_event_filter_unittest.cc
deleted file mode 100644
index 6b852e4cd55..00000000000
--- a/chromium/ui/views/corewm/compound_event_filter_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/compound_event_filter.h"
-
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/test/test_cursor_client.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-
-namespace {
-
-#if defined(OS_CHROMEOS)
-base::TimeDelta GetTime() {
- return ui::EventTimeForNow();
-}
-#endif // defined(OS_CHROMEOS)
-
-}
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-// An event filter that consumes all gesture events.
-class ConsumeGestureEventFilter : public ui::EventHandler {
- public:
- ConsumeGestureEventFilter() {}
- virtual ~ConsumeGestureEventFilter() {}
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnGestureEvent(ui::GestureEvent* e) OVERRIDE {
- e->StopPropagation();
- }
-
- DISALLOW_COPY_AND_ASSIGN(ConsumeGestureEventFilter);
-};
-
-} // namespace
-
-typedef aura::test::AuraTestBase CompoundEventFilterTest;
-
-#if defined(OS_CHROMEOS)
-// A keypress only hides the cursor on ChromeOS (crbug.com/304296).
-TEST_F(CompoundEventFilterTest, CursorVisibilityChange) {
- scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
- aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
- aura::test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
- gfx::Rect(5, 5, 100, 100), root_window()));
- window->Show();
- window->SetCapture();
-
- aura::test::TestCursorClient cursor_client(root_window());
-
- // Send key event to hide the cursor.
- ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
- dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(&key);
- EXPECT_FALSE(cursor_client.IsCursorVisible());
-
- // Synthesized mouse event should not show the cursor.
- ui::MouseEvent enter(ui::ET_MOUSE_ENTERED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- enter.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&enter);
- EXPECT_FALSE(cursor_client.IsCursorVisible());
-
- ui::MouseEvent move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- move.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&move);
- EXPECT_FALSE(cursor_client.IsCursorVisible());
-
- ui::MouseEvent real_move(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&real_move);
- EXPECT_TRUE(cursor_client.IsCursorVisible());
-
- // Send key event to hide the cursor again.
- dispatcher()->AsRootWindowHostDelegate()->OnHostKeyEvent(&key);
- EXPECT_FALSE(cursor_client.IsCursorVisible());
-
- // Mouse synthesized exit event should not show the cursor.
- ui::MouseEvent exit(ui::ET_MOUSE_EXITED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- exit.set_flags(enter.flags() | ui::EF_IS_SYNTHESIZED);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&exit);
- EXPECT_FALSE(cursor_client.IsCursorVisible());
-}
-
-TEST_F(CompoundEventFilterTest, TouchHidesCursor) {
- scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
- aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
- aura::test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
- gfx::Rect(5, 5, 100, 100), root_window()));
- window->Show();
- window->SetCapture();
-
- aura::test::TestCursorClient cursor_client(root_window());
-
- ui::MouseEvent mouse0(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse0);
- EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
-
- // This press is required for the GestureRecognizer to associate a target
- // with kTouchId
- ui::TouchEvent press0(
- ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press0);
- EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
-
- ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 1, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
- EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
-
- ui::TouchEvent release(
- ui::ET_TOUCH_RELEASED, gfx::Point(10, 10), 1, GetTime());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
- EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
-
- ui::MouseEvent mouse1(ui::ET_MOUSE_MOVED, gfx::Point(10, 10),
- gfx::Point(10, 10), 0);
- // Move the cursor again. The cursor should be visible.
- dispatcher()->AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse1);
- EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
-
- // Now activate the window and press on it again.
- ui::TouchEvent press1(
- ui::ET_TOUCH_PRESSED, gfx::Point(90, 90), 1, GetTime());
- aura::client::GetActivationClient(
- root_window())->ActivateWindow(window.get());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press1);
- EXPECT_FALSE(cursor_client.IsMouseEventsEnabled());
- aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
-}
-#endif // defined(OS_CHROMEOS)
-
-// Tests that if an event filter consumes a gesture, then it doesn't focus the
-// window.
-TEST_F(CompoundEventFilterTest, FilterConsumedGesture) {
- scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
- scoped_ptr<ui::EventHandler> gesure_handler(new ConsumeGestureEventFilter);
- compound_filter->AddHandler(gesure_handler.get());
- aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
- aura::test::TestWindowDelegate delegate;
- DCHECK(root_window());
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
- gfx::Rect(5, 5, 100, 100), root_window()));
- window->Show();
-
- EXPECT_TRUE(window->CanFocus());
- EXPECT_FALSE(window->HasFocus());
-
- // Tap on the window should not focus it since the filter will be consuming
- // the gestures.
- aura::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
- generator.PressTouch();
- EXPECT_FALSE(window->HasFocus());
-
- compound_filter->RemoveHandler(gesure_handler.get());
- aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
-}
-
-// Verifies we don't attempt to hide the mouse when the mouse is down and a
-// touch event comes in.
-TEST_F(CompoundEventFilterTest, DontHideWhenMouseDown) {
- aura::test::EventGenerator event_generator(root_window());
-
- scoped_ptr<CompoundEventFilter> compound_filter(new CompoundEventFilter);
- aura::Env::GetInstance()->AddPreTargetHandler(compound_filter.get());
- aura::test::TestWindowDelegate delegate;
- scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(&delegate, 1234,
- gfx::Rect(5, 5, 100, 100), root_window()));
- window->Show();
-
- aura::test::TestCursorClient cursor_client(root_window());
-
- // Move and press the mouse over the window.
- event_generator.MoveMouseTo(10, 10);
- EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
- event_generator.PressLeftButton();
- EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
- EXPECT_TRUE(aura::Env::GetInstance()->IsMouseButtonDown());
-
- // Do a touch event. As the mouse button is down this should not disable mouse
- // events.
- event_generator.PressTouch();
- EXPECT_TRUE(cursor_client.IsMouseEventsEnabled());
- aura::Env::GetInstance()->RemovePreTargetHandler(compound_filter.get());
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/corewm_switches.cc b/chromium/ui/views/corewm/corewm_switches.cc
deleted file mode 100644
index 8f0dd82a6a9..00000000000
--- a/chromium/ui/views/corewm/corewm_switches.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/corewm_switches.h"
-
-#include "base/command_line.h"
-
-namespace views {
-namespace corewm {
-namespace switches {
-
-const char kNoDropShadows[] = "aura-no-shadows";
-
-// If present animations are disabled.
-const char kWindowAnimationsDisabled[] =
- "views-corewm-window-animations-disabled";
-
-} // namespace switches
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/corewm_switches.h b/chromium/ui/views/corewm/corewm_switches.h
deleted file mode 100644
index 63c5251745d..00000000000
--- a/chromium/ui/views/corewm/corewm_switches.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_COREWM_SWITCHES_H_
-#define UI_VIEWS_COREWM_COREWM_SWITCHES_H_
-
-#include "build/build_config.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-namespace switches {
-
-// Note: If you add a switch, consider if it needs to be copied to a subsequent
-// command line if the process executes a new copy of itself. (For example,
-// see chromeos::LoginUtil::GetOffTheRecordCommandLine().)
-
-// Please keep alphabetized.
-VIEWS_EXPORT extern const char kNoDropShadows[];
-VIEWS_EXPORT extern const char kWindowAnimationsDisabled[];
-
-} // namespace switches
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_COREWM_SWITCHES_H_
diff --git a/chromium/ui/views/corewm/cursor_height_provider_win.cc b/chromium/ui/views/corewm/cursor_height_provider_win.cc
new file mode 100644
index 00000000000..97ed7a3465e
--- /dev/null
+++ b/chromium/ui/views/corewm/cursor_height_provider_win.cc
@@ -0,0 +1,146 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/corewm/cursor_height_provider_win.h"
+
+#include <windows.h>
+#include <algorithm>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_hdc.h"
+
+namespace {
+typedef scoped_ptr<uint32_t> PixelData;
+typedef std::map<HCURSOR, int> HeightStorage;
+
+const uint32_t kBitsPeruint32 = sizeof(uint32_t) * 8;
+// All bits are 1 for transparent portion of monochromatic mask.
+const uint32_t kTransparentMask = 0xffffffff;
+// This is height of default pointer arrow in Windows 7.
+const int kDefaultHeight = 20;
+// Masks are monochromatic.
+const size_t kNumberOfColors = 2;
+const size_t KHeaderAndPalette =
+ sizeof(BITMAPINFOHEADER) + kNumberOfColors * sizeof(RGBQUAD);
+
+static HeightStorage* cached_heights = NULL;
+
+// Extracts the pixel data of provided bitmap
+PixelData GetBitmapData(HBITMAP handle, const BITMAPINFO& info, HDC hdc) {
+ PixelData data;
+ // Masks are monochromatic.
+ DCHECK_EQ(info.bmiHeader.biBitCount, 1);
+ if (info.bmiHeader.biBitCount != 1)
+ return data.Pass();
+
+ // When getting pixel data palette is appended to memory pointed by
+ // BITMAPINFO passed so allocate additional memory to store additional data.
+ scoped_ptr<BITMAPINFO> header(
+ reinterpret_cast<BITMAPINFO*>(new char[KHeaderAndPalette]));
+ memcpy(header.get(), &(info.bmiHeader), sizeof(info.bmiHeader));
+
+ data.reset(new uint32_t[info.bmiHeader.biSizeImage / sizeof(uint32_t)]);
+
+ int result = GetDIBits(hdc,
+ handle,
+ 0,
+ info.bmiHeader.biHeight,
+ data.get(),
+ header.get(),
+ DIB_RGB_COLORS);
+
+ if (result == 0)
+ data.reset();
+
+ return data.Pass();
+}
+
+// Checks if the specifed row is transparent in provided bitmap.
+bool IsRowTransparent(const PixelData& data,
+ const uint32_t row_size,
+ const uint32_t last_byte_mask,
+ const uint32_t y) {
+ // Set the padding bits to 1 to make mask matching easier.
+ *(data.get() + (y + 1) * row_size - 1) |= last_byte_mask;
+ for (uint32_t i = y * row_size; i < (y + 1) * row_size; ++i) {
+ if (*(data.get() + i) != kTransparentMask)
+ return false;
+ }
+ return true;
+}
+
+// Gets the vertical offset between specified cursor's hotpoint and it's bottom.
+//
+// Gets the cursor image data and extract cursor's visible height.
+// Based on that get's what should be the vertical offset between cursor's
+// hot point and the tooltip.
+int CalculateCursorHeight(HCURSOR cursor_handle) {
+ base::win::ScopedGetDC hdc(NULL);
+
+ ICONINFO icon = {0};
+ GetIconInfo(cursor_handle, &icon);
+
+ BITMAPINFO bitmap_info = {0};
+ bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader);
+ if (GetDIBits(hdc, icon.hbmMask, 0, 0, NULL, &bitmap_info, DIB_RGB_COLORS) ==
+ 0)
+ return kDefaultHeight;
+
+ // Rows are padded to full DWORDs. OR with this mask will set them to 1
+ // to simplify matching with |transparent_mask|.
+ uint32_t last_byte_mask = ~0;
+ const unsigned char bits_to_shift = sizeof(last_byte_mask) * 8 -
+ (bitmap_info.bmiHeader.biWidth % kBitsPeruint32);
+ if (bits_to_shift != kBitsPeruint32)
+ last_byte_mask = (last_byte_mask << bits_to_shift);
+ else
+ last_byte_mask = 0;
+
+ const uint32_t row_size =
+ (bitmap_info.bmiHeader.biWidth + kBitsPeruint32 - 1) / kBitsPeruint32;
+ PixelData data(GetBitmapData(icon.hbmMask, bitmap_info, hdc));
+ if (data == NULL)
+ return kDefaultHeight;
+
+ const int cursor_height = GetSystemMetrics(SM_CYCURSOR);
+ // Crash data seems to indicate cursor_height may be bigger than the bitmap.
+ int i = std::max(0, static_cast<int>(bitmap_info.bmiHeader.biHeight) -
+ cursor_height);
+ for (; i < bitmap_info.bmiHeader.biHeight; ++i) {
+ if (!IsRowTransparent(data, row_size, last_byte_mask, i)) {
+ i--;
+ break;
+ }
+ }
+ return bitmap_info.bmiHeader.biHeight - i - icon.yHotspot;
+}
+
+} // namespace
+
+namespace views {
+namespace corewm {
+
+int GetCurrentCursorVisibleHeight() {
+ CURSORINFO cursor = {0};
+ cursor.cbSize = sizeof(cursor);
+ GetCursorInfo(&cursor);
+
+ if (cached_heights == NULL)
+ cached_heights = new HeightStorage;
+
+ HeightStorage::const_iterator cached_height =
+ cached_heights->find(cursor.hCursor);
+ if (cached_height != cached_heights->end())
+ return cached_height->second;
+
+ const int height = CalculateCursorHeight(cursor.hCursor);
+ (*cached_heights)[cursor.hCursor] = height;
+
+ return height;
+}
+
+} // namespace corewm
+} // namespace views
diff --git a/chromium/ui/views/corewm/cursor_height_provider_win.h b/chromium/ui/views/corewm/cursor_height_provider_win.h
new file mode 100644
index 00000000000..c93134491f2
--- /dev/null
+++ b/chromium/ui/views/corewm/cursor_height_provider_win.h
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_
+#define UI_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_
+
+namespace views {
+namespace corewm {
+
+// Gets the visible height of current cursor.
+//
+// The height is offset between cursor's hot point and it's
+// bottom edge, derived from first non-transparent row of cursor's mask.
+
+int GetCurrentCursorVisibleHeight();
+
+} // namespace corewm
+} // namespace views
+
+#endif // UI_VIEWS_COREWM_CURSOR_HEIGHT_PROVIDER_WIN_H_
diff --git a/chromium/ui/views/corewm/cursor_manager.cc b/chromium/ui/views/corewm/cursor_manager.cc
deleted file mode 100644
index 2335fdd1cbf..00000000000
--- a/chromium/ui/views/corewm/cursor_manager.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/cursor_manager.h"
-
-#include "base/logging.h"
-#include "ui/aura/client/cursor_client_observer.h"
-#include "ui/views/corewm/native_cursor_manager.h"
-#include "ui/views/corewm/native_cursor_manager_delegate.h"
-
-namespace views {
-namespace corewm {
-
-namespace internal {
-
-// Represents the cursor state which is composed of cursor type, visibility, and
-// mouse events enable state. When mouse events are disabled, the cursor is
-// always invisible.
-class CursorState {
- public:
- CursorState()
- : cursor_(ui::kCursorNone),
- visible_(true),
- scale_(1.f),
- cursor_set_(ui::CURSOR_SET_NORMAL),
- mouse_events_enabled_(true),
- visible_on_mouse_events_enabled_(true) {
- }
-
- gfx::NativeCursor cursor() const { return cursor_; }
- void set_cursor(gfx::NativeCursor cursor) { cursor_ = cursor; }
-
- bool visible() const { return visible_; }
- void SetVisible(bool visible) {
- if (mouse_events_enabled_)
- visible_ = visible;
- // Ignores the call when mouse events disabled.
- }
-
- float scale() const { return scale_; }
- void set_scale(float scale) {
- scale_ = scale;
- }
-
- ui::CursorSetType cursor_set() const { return cursor_set_; }
- void set_cursor_set(ui::CursorSetType cursor_set) {
- cursor_set_ = cursor_set;
- }
-
- bool mouse_events_enabled() const { return mouse_events_enabled_; }
- void SetMouseEventsEnabled(bool enabled) {
- if (mouse_events_enabled_ == enabled)
- return;
- mouse_events_enabled_ = enabled;
-
- // Restores the visibility when mouse events are enabled.
- if (enabled) {
- visible_ = visible_on_mouse_events_enabled_;
- } else {
- visible_on_mouse_events_enabled_ = visible_;
- visible_ = false;
- }
- }
-
- private:
- gfx::NativeCursor cursor_;
- bool visible_;
- float scale_;
- ui::CursorSetType cursor_set_;
- bool mouse_events_enabled_;
-
- // The visibility to set when mouse events are enabled.
- bool visible_on_mouse_events_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(CursorState);
-};
-
-} // namespace internal
-
-CursorManager::CursorManager(scoped_ptr<NativeCursorManager> delegate)
- : delegate_(delegate.Pass()),
- cursor_lock_count_(0),
- current_state_(new internal::CursorState),
- state_on_unlock_(new internal::CursorState) {
-}
-
-CursorManager::~CursorManager() {
-}
-
-void CursorManager::SetCursor(gfx::NativeCursor cursor) {
- state_on_unlock_->set_cursor(cursor);
- if (cursor_lock_count_ == 0 &&
- GetCursor() != state_on_unlock_->cursor()) {
- delegate_->SetCursor(state_on_unlock_->cursor(), this);
- }
-}
-
-gfx::NativeCursor CursorManager::GetCursor() const {
- return current_state_->cursor();
-}
-
-void CursorManager::ShowCursor() {
- state_on_unlock_->SetVisible(true);
- if (cursor_lock_count_ == 0 &&
- IsCursorVisible() != state_on_unlock_->visible()) {
- delegate_->SetVisibility(state_on_unlock_->visible(), this);
- FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
- OnCursorVisibilityChanged(true));
- }
-}
-
-void CursorManager::HideCursor() {
- state_on_unlock_->SetVisible(false);
- if (cursor_lock_count_ == 0 &&
- IsCursorVisible() != state_on_unlock_->visible()) {
- delegate_->SetVisibility(state_on_unlock_->visible(), this);
- FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
- OnCursorVisibilityChanged(false));
- }
-}
-
-bool CursorManager::IsCursorVisible() const {
- return current_state_->visible();
-}
-
-void CursorManager::SetScale(float scale) {
- state_on_unlock_->set_scale(scale);
- if (GetScale() != state_on_unlock_->scale())
- delegate_->SetScale(state_on_unlock_->scale(), this);
-}
-
-float CursorManager::GetScale() const {
- return current_state_->scale();
-}
-
-void CursorManager::SetCursorSet(ui::CursorSetType cursor_set) {
- state_on_unlock_->set_cursor_set(cursor_set);
- if (GetCursorSet() != state_on_unlock_->cursor_set())
- delegate_->SetCursorSet(state_on_unlock_->cursor_set(), this);
-}
-
-ui::CursorSetType CursorManager::GetCursorSet() const {
- return current_state_->cursor_set();
-}
-
-void CursorManager::EnableMouseEvents() {
- state_on_unlock_->SetMouseEventsEnabled(true);
- if (cursor_lock_count_ == 0 &&
- IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
- delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
- this);
- }
-}
-
-void CursorManager::DisableMouseEvents() {
- state_on_unlock_->SetMouseEventsEnabled(false);
- if (cursor_lock_count_ == 0 &&
- IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
- delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
- this);
- }
-}
-
-bool CursorManager::IsMouseEventsEnabled() const {
- return current_state_->mouse_events_enabled();
-}
-
-void CursorManager::SetDisplay(const gfx::Display& display) {
- delegate_->SetDisplay(display, this);
-}
-
-void CursorManager::LockCursor() {
- cursor_lock_count_++;
-}
-
-void CursorManager::UnlockCursor() {
- cursor_lock_count_--;
- DCHECK_GE(cursor_lock_count_, 0);
- if (cursor_lock_count_ > 0)
- return;
-
- if (GetCursor() != state_on_unlock_->cursor()) {
- delegate_->SetCursor(state_on_unlock_->cursor(), this);
- }
- if (IsMouseEventsEnabled() != state_on_unlock_->mouse_events_enabled()) {
- delegate_->SetMouseEventsEnabled(state_on_unlock_->mouse_events_enabled(),
- this);
- }
- if (IsCursorVisible() != state_on_unlock_->visible()) {
- delegate_->SetVisibility(state_on_unlock_->visible(),
- this);
- }
-}
-
-bool CursorManager::IsCursorLocked() const {
- return cursor_lock_count_ > 0;
-}
-
-void CursorManager::AddObserver(
- aura::client::CursorClientObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void CursorManager::RemoveObserver(
- aura::client::CursorClientObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-void CursorManager::CommitCursor(gfx::NativeCursor cursor) {
- current_state_->set_cursor(cursor);
-}
-
-void CursorManager::CommitVisibility(bool visible) {
- // TODO(tdanderson): Find a better place for this so we don't
- // notify the observers more than is necessary.
- FOR_EACH_OBSERVER(aura::client::CursorClientObserver, observers_,
- OnCursorVisibilityChanged(visible));
- current_state_->SetVisible(visible);
-}
-
-void CursorManager::CommitScale(float scale) {
- current_state_->set_scale(scale);
-}
-
-void CursorManager::CommitCursorSet(ui::CursorSetType cursor_set) {
- current_state_->set_cursor_set(cursor_set);
-}
-
-void CursorManager::CommitMouseEventsEnabled(bool enabled) {
- current_state_->SetMouseEventsEnabled(enabled);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/cursor_manager.h b/chromium/ui/views/corewm/cursor_manager.h
deleted file mode 100644
index 29f890ae6bd..00000000000
--- a/chromium/ui/views/corewm/cursor_manager.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_CURSOR_MANAGER_H_
-#define UI_VIEWS_COREWM_CURSOR_MANAGER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/base/cursor/cursor.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/point.h"
-#include "ui/views/corewm/native_cursor_manager_delegate.h"
-#include "ui/views/views_export.h"
-
-namespace gfx {
-class Display;
-}
-
-namespace views {
-namespace corewm {
-
-namespace internal {
-class CursorState;
-}
-
-class NativeCursorManager;
-
-// This class receives requests to change cursor properties, as well as
-// requests to queue any further changes until a later time. It sends changes
-// to the NativeCursorManager, which communicates back to us when these changes
-// were made through the NativeCursorManagerDelegate interface.
-class VIEWS_EXPORT CursorManager : public aura::client::CursorClient,
- public NativeCursorManagerDelegate {
- public:
- CursorManager(scoped_ptr<NativeCursorManager> delegate);
- virtual ~CursorManager();
-
- // Overridden from aura::client::CursorClient:
- virtual void SetCursor(gfx::NativeCursor) OVERRIDE;
- virtual gfx::NativeCursor GetCursor() const OVERRIDE;
- virtual void ShowCursor() OVERRIDE;
- virtual void HideCursor() OVERRIDE;
- virtual bool IsCursorVisible() const OVERRIDE;
- virtual void SetScale(float scale) OVERRIDE;
- virtual float GetScale() const OVERRIDE;
- virtual void SetCursorSet(ui::CursorSetType cursor_set) OVERRIDE;
- virtual ui::CursorSetType GetCursorSet() const OVERRIDE;
- virtual void EnableMouseEvents() OVERRIDE;
- virtual void DisableMouseEvents() OVERRIDE;
- virtual bool IsMouseEventsEnabled() const OVERRIDE;
- virtual void SetDisplay(const gfx::Display& display) OVERRIDE;
- virtual void LockCursor() OVERRIDE;
- virtual void UnlockCursor() OVERRIDE;
- virtual bool IsCursorLocked() const OVERRIDE;
- virtual void AddObserver(
- aura::client::CursorClientObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- aura::client::CursorClientObserver* observer) OVERRIDE;
-
- private:
- // Overridden from NativeCursorManagerDelegate:
- virtual void CommitCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual void CommitVisibility(bool visible) OVERRIDE;
- virtual void CommitScale(float scale) OVERRIDE;
- virtual void CommitCursorSet(ui::CursorSetType cursor_set) OVERRIDE;
- virtual void CommitMouseEventsEnabled(bool enabled) OVERRIDE;
-
- scoped_ptr<NativeCursorManager> delegate_;
-
- // Number of times LockCursor() has been invoked without a corresponding
- // UnlockCursor().
- int cursor_lock_count_;
-
- // The current state of the cursor.
- scoped_ptr<internal::CursorState> current_state_;
-
- // The cursor state to restore when the cursor is unlocked.
- scoped_ptr<internal::CursorState> state_on_unlock_;
-
- ObserverList<aura::client::CursorClientObserver> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(CursorManager);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_CURSOR_MANAGER_H_
diff --git a/chromium/ui/views/corewm/cursor_manager_unittest.cc b/chromium/ui/views/corewm/cursor_manager_unittest.cc
deleted file mode 100644
index a9c507782a5..00000000000
--- a/chromium/ui/views/corewm/cursor_manager_unittest.cc
+++ /dev/null
@@ -1,353 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/cursor_manager.h"
-
-#include "ui/aura/client/cursor_client_observer.h"
-#include "ui/views/corewm/native_cursor_manager.h"
-#include "ui/views/test/views_test_base.h"
-
-namespace {
-
-class TestingCursorManager : public views::corewm::NativeCursorManager {
- public:
- // Overridden from views::corewm::NativeCursorManager:
- virtual void SetDisplay(
- const gfx::Display& display,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {}
-
- virtual void SetCursor(
- gfx::NativeCursor cursor,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {
- delegate->CommitCursor(cursor);
- }
-
- virtual void SetVisibility(
- bool visible,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {
- delegate->CommitVisibility(visible);
- }
-
- virtual void SetMouseEventsEnabled(
- bool enabled,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {
- delegate->CommitMouseEventsEnabled(enabled);
- }
-
- virtual void SetCursorSet(
- ui::CursorSetType cursor_set,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {
- delegate->CommitCursorSet(cursor_set);
- }
-
- virtual void SetScale(
- float scale,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {
- delegate->CommitScale(scale);
- }
-};
-
-} // namespace
-
-class CursorManagerTest : public views::ViewsTestBase {
- protected:
- CursorManagerTest()
- : delegate_(new TestingCursorManager),
- cursor_manager_(scoped_ptr<views::corewm::NativeCursorManager>(
- delegate_)) {
- }
-
- TestingCursorManager* delegate_;
- views::corewm::CursorManager cursor_manager_;
-};
-
-class TestingCursorClientObserver : public aura::client::CursorClientObserver {
- public:
- TestingCursorClientObserver()
- : cursor_visibility_(false),
- did_visibility_change_(false) {}
- void reset() { cursor_visibility_ = did_visibility_change_ = false; }
- bool is_cursor_visible() const { return cursor_visibility_; }
- bool did_visibility_change() const { return did_visibility_change_; }
-
- // Overridden from aura::client::CursorClientObserver:
- virtual void OnCursorVisibilityChanged(bool is_visible) OVERRIDE {
- cursor_visibility_ = is_visible;
- did_visibility_change_ = true;
- }
-
- private:
- bool cursor_visibility_;
- bool did_visibility_change_;
-
- DISALLOW_COPY_AND_ASSIGN(TestingCursorClientObserver);
-};
-
-TEST_F(CursorManagerTest, ShowHideCursor) {
- cursor_manager_.SetCursor(ui::kCursorCopy);
- EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type());
-
- cursor_manager_.ShowCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- cursor_manager_.HideCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- // The current cursor does not change even when the cursor is not shown.
- EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type());
-
- // Check if cursor visibility is locked.
- cursor_manager_.LockCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- cursor_manager_.ShowCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
-
- cursor_manager_.LockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- cursor_manager_.HideCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
-
- // Checks setting visiblity while cursor is locked does not affect the
- // subsequent uses of UnlockCursor.
- cursor_manager_.LockCursor();
- cursor_manager_.HideCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
-
- cursor_manager_.ShowCursor();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
-
- cursor_manager_.LockCursor();
- cursor_manager_.ShowCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
-
- cursor_manager_.HideCursor();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
-}
-
-// Verifies that LockCursor/UnlockCursor work correctly with
-// EnableMouseEvents and DisableMouseEvents
-TEST_F(CursorManagerTest, EnableDisableMouseEvents) {
- cursor_manager_.SetCursor(ui::kCursorCopy);
- EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type());
-
- cursor_manager_.EnableMouseEvents();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- // The current cursor does not change even when the cursor is not shown.
- EXPECT_EQ(ui::kCursorCopy, cursor_manager_.GetCursor().native_type());
-
- // Check if cursor enable state is locked.
- cursor_manager_.LockCursor();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.EnableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.LockCursor();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.DisableMouseEvents();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-
- // Checks enabling cursor while cursor is locked does not affect the
- // subsequent uses of UnlockCursor.
- cursor_manager_.LockCursor();
- cursor_manager_.DisableMouseEvents();
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.LockCursor();
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.DisableMouseEvents();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-}
-
-TEST_F(CursorManagerTest, SetCursorSet) {
- EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet());
-
- cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL);
- EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet());
-
- cursor_manager_.SetCursorSet(ui::CURSOR_SET_LARGE);
- EXPECT_EQ(ui::CURSOR_SET_LARGE, cursor_manager_.GetCursorSet());
-
- cursor_manager_.SetCursorSet(ui::CURSOR_SET_NORMAL);
- EXPECT_EQ(ui::CURSOR_SET_NORMAL, cursor_manager_.GetCursorSet());
-}
-
-TEST_F(CursorManagerTest, SetScale) {
- EXPECT_EQ(1.f, cursor_manager_.GetScale());
- cursor_manager_.SetScale(2.f);
- EXPECT_EQ(2.f, cursor_manager_.GetScale());
-
- // Cusror scale does change even while cursor is locked.
- cursor_manager_.LockCursor();
- EXPECT_EQ(2.f, cursor_manager_.GetScale());
- cursor_manager_.SetScale(2.5f);
- EXPECT_EQ(2.5f, cursor_manager_.GetScale());
- cursor_manager_.UnlockCursor();
-
- EXPECT_EQ(2.5f, cursor_manager_.GetScale());
- cursor_manager_.SetScale(1.f);
- EXPECT_EQ(1.f, cursor_manager_.GetScale());
-}
-
-TEST_F(CursorManagerTest, IsMouseEventsEnabled) {
- cursor_manager_.EnableMouseEvents();
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-}
-
-// Verifies that the mouse events enable state changes correctly when
-// ShowCursor/HideCursor and EnableMouseEvents/DisableMouseEvents are used
-// together.
-TEST_F(CursorManagerTest, ShowAndEnable) {
- // Changing the visibility of the cursor does not affect the enable state.
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.ShowCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.HideCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.ShowCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- // When mouse events are disabled, it also gets invisible.
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-
- // When mouse events are enabled, it restores the visibility state.
- cursor_manager_.EnableMouseEvents();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.ShowCursor();
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.EnableMouseEvents();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- cursor_manager_.HideCursor();
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.EnableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_TRUE(cursor_manager_.IsMouseEventsEnabled());
-
- // When mouse events are disabled, ShowCursor is ignored.
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.ShowCursor();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
- cursor_manager_.DisableMouseEvents();
- EXPECT_FALSE(cursor_manager_.IsCursorVisible());
- EXPECT_FALSE(cursor_manager_.IsMouseEventsEnabled());
-}
-
-// Verifies that calling DisableMouseEvents multiple times in a row makes no
-// difference compared with calling it once.
-// This is a regression test for http://crbug.com/169404.
-TEST_F(CursorManagerTest, MultipleDisableMouseEvents) {
- cursor_manager_.DisableMouseEvents();
- cursor_manager_.DisableMouseEvents();
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
-}
-
-// Verifies that calling EnableMouseEvents multiple times in a row makes no
-// difference compared with calling it once.
-TEST_F(CursorManagerTest, MultipleEnableMouseEvents) {
- cursor_manager_.DisableMouseEvents();
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.EnableMouseEvents();
- cursor_manager_.LockCursor();
- cursor_manager_.UnlockCursor();
- EXPECT_TRUE(cursor_manager_.IsCursorVisible());
-}
-
-TEST_F(CursorManagerTest, TestCursorClientObserver) {
- // Add two observers. Both should have OnCursorVisibilityChanged()
- // invoked when the visibility of the cursor changes.
- TestingCursorClientObserver observer_a;
- TestingCursorClientObserver observer_b;
- cursor_manager_.AddObserver(&observer_a);
- cursor_manager_.AddObserver(&observer_b);
-
- // Initial state before any events have been sent.
- observer_a.reset();
- observer_b.reset();
- EXPECT_FALSE(observer_a.did_visibility_change());
- EXPECT_FALSE(observer_b.did_visibility_change());
- EXPECT_FALSE(observer_a.is_cursor_visible());
- EXPECT_FALSE(observer_b.is_cursor_visible());
-
- // Hide the cursor using HideCursor().
- cursor_manager_.HideCursor();
- EXPECT_TRUE(observer_a.did_visibility_change());
- EXPECT_TRUE(observer_b.did_visibility_change());
- EXPECT_FALSE(observer_a.is_cursor_visible());
- EXPECT_FALSE(observer_b.is_cursor_visible());
-
- // Show the cursor using ShowCursor().
- observer_a.reset();
- observer_b.reset();
- cursor_manager_.ShowCursor();
- EXPECT_TRUE(observer_a.did_visibility_change());
- EXPECT_TRUE(observer_b.did_visibility_change());
- EXPECT_TRUE(observer_a.is_cursor_visible());
- EXPECT_TRUE(observer_b.is_cursor_visible());
-
- // Remove observer_b. Its OnCursorVisibilityChanged() should
- // not be invoked past this point.
- cursor_manager_.RemoveObserver(&observer_b);
-
- // Hide the cursor using HideCursor().
- observer_a.reset();
- observer_b.reset();
- cursor_manager_.HideCursor();
- EXPECT_TRUE(observer_a.did_visibility_change());
- EXPECT_FALSE(observer_b.did_visibility_change());
- EXPECT_FALSE(observer_a.is_cursor_visible());
-
- // Show the cursor using ShowCursor().
- observer_a.reset();
- observer_b.reset();
- cursor_manager_.ShowCursor();
- EXPECT_TRUE(observer_a.did_visibility_change());
- EXPECT_FALSE(observer_b.did_visibility_change());
- EXPECT_TRUE(observer_a.is_cursor_visible());
-}
diff --git a/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc
index c655ec8081c..8807aafdd6e 100644
--- a/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc
+++ b/chromium/ui/views/corewm/desktop_capture_controller_unittest.cc
@@ -2,14 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/corewm/capture_controller.h"
+#include "ui/wm/core/capture_controller.h"
#include "base/logging.h"
+#include "base/path_service.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_paths.h"
#include "ui/events/event.h"
+#include "ui/gl/gl_surface.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
@@ -22,7 +27,22 @@
namespace views {
-typedef ViewsTestBase DesktopCaptureControllerTest;
+class DesktopCaptureControllerTest : public ViewsTestBase {
+ public:
+ DesktopCaptureControllerTest() {}
+ virtual ~DesktopCaptureControllerTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ gfx::GLSurface::InitializeOneOffForTests();
+ base::FilePath pak_dir;
+ PathService::Get(base::DIR_MODULE, &pak_dir);
+ base::FilePath pak_file;
+ pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+
+ ViewsTestBase::SetUp();
+ }
+};
// This class provides functionality to verify whether the View instance
// received the gesture event.
@@ -72,13 +92,16 @@ TEST_F(DesktopCaptureControllerTest, ResetMouseHandlers) {
generator1.MoveMouseToCenterOf(w1->GetNativeView());
generator1.PressLeftButton();
EXPECT_FALSE(w1->HasCapture());
- aura::RootWindow* w1_root = w1->GetNativeView()->GetDispatcher();
- EXPECT_TRUE(w1_root->mouse_pressed_handler() != NULL);
- EXPECT_TRUE(w1_root->mouse_moved_handler() != NULL);
+ aura::WindowEventDispatcher* w1_dispatcher =
+ w1->GetNativeView()->GetHost()->dispatcher();
+ EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() != NULL);
+ EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() != NULL);
w2->SetCapture(w2->GetRootView());
EXPECT_TRUE(w2->HasCapture());
- EXPECT_TRUE(w1_root->mouse_pressed_handler() == NULL);
- EXPECT_TRUE(w1_root->mouse_moved_handler() == NULL);
+ EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() == NULL);
+ EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() == NULL);
+ w2->ReleaseCapture();
+ RunPendingMessages();
}
// Tests aura::Window capture and whether gesture events are sent to the window
@@ -93,8 +116,8 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
scoped_ptr<Widget> widget1(new Widget());
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- scoped_ptr<corewm::ScopedCaptureClient> scoped_capture_client(
- new corewm::ScopedCaptureClient(params.context->GetRootWindow()));
+ scoped_ptr<wm::ScopedCaptureClient> scoped_capture_client(
+ new wm::ScopedCaptureClient(params.context->GetRootWindow()));
aura::client::CaptureClient* capture_client =
scoped_capture_client->capture_client();
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
@@ -103,7 +126,8 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
internal::RootView* root1 =
static_cast<internal::RootView*>(widget1->GetRootView());
- desktop_position_client1.reset(new DesktopScreenPositionClient());
+ desktop_position_client1.reset(
+ new DesktopScreenPositionClient(params.context->GetRootWindow()));
aura::client::SetScreenPositionClient(
widget1->GetNativeView()->GetRootWindow(),
desktop_position_client1.get());
@@ -122,10 +146,12 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
internal::RootView* root2 =
static_cast<internal::RootView*>(widget2->GetRootView());
- desktop_position_client2.reset(new DesktopScreenPositionClient());
+ desktop_position_client2.reset(
+ new DesktopScreenPositionClient(params.context->GetRootWindow()));
aura::client::SetScreenPositionClient(
widget2->GetNativeView()->GetRootWindow(),
desktop_position_client2.get());
+ ui::EventDispatchDetails details;
DesktopViewInputTest* v2 = new DesktopViewInputTest();
v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
@@ -146,7 +172,10 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS,
0.0f, 0.0f), 0);
- root1->DispatchGestureEvent(&g1);
+ details = root1->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_TRUE(v1->received_gesture_event());
EXPECT_FALSE(v2->received_gesture_event());
v1->Reset();
@@ -158,7 +187,10 @@ TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
EXPECT_TRUE(widget2->GetNativeView()->HasCapture());
EXPECT_EQ(capture_client->GetCaptureWindow(), widget2->GetNativeView());
- root2->DispatchGestureEvent(&g1);
+ details = root2->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_TRUE(v2->received_gesture_event());
EXPECT_FALSE(v1->received_gesture_event());
diff --git a/chromium/ui/views/corewm/focus_controller.cc b/chromium/ui/views/corewm/focus_controller.cc
deleted file mode 100644
index 17add8417fb..00000000000
--- a/chromium/ui/views/corewm/focus_controller.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/focus_controller.h"
-
-#include "base/auto_reset.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/capture_client.h"
-#include "ui/aura/client/focus_change_observer.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/events/event.h"
-#include "ui/views/corewm/focus_rules.h"
-
-namespace views {
-namespace corewm {
-namespace {
-
-// When a modal window is activated, we bring its entire transient parent chain
-// to the front. This function must be called before the modal transient is
-// stacked at the top to ensure correct stacking order.
-void StackTransientParentsBelowModalWindow(aura::Window* window) {
- if (window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_WINDOW)
- return;
-
- aura::Window* transient_parent = window->transient_parent();
- while (transient_parent) {
- transient_parent->parent()->StackChildAtTop(transient_parent);
- transient_parent = transient_parent->transient_parent();
- }
-}
-
-// Stack's |window|'s layer above |relative_to|'s layer.
-void StackWindowLayerAbove(aura::Window* window, aura::Window* relative_to) {
- // Stack |window| above the last transient child of |relative_to| that shares
- // the same parent.
- const aura::Window::Windows& window_transients(
- relative_to->transient_children());
- for (aura::Window::Windows::const_iterator i = window_transients.begin();
- i != window_transients.end(); ++i) {
- aura::Window* transient = *i;
- if (transient->parent() == relative_to->parent())
- relative_to = transient;
- }
- if (window != relative_to) {
- window->layer()->parent()->StackAbove(window->layer(),
- relative_to->layer());
- }
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, public:
-
-FocusController::FocusController(FocusRules* rules)
- : active_window_(NULL),
- focused_window_(NULL),
- updating_focus_(false),
- updating_activation_(false),
- rules_(rules),
- observer_manager_(this) {
- DCHECK(rules);
-}
-
-FocusController::~FocusController() {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, aura::client::ActivationClient implementation:
-
-void FocusController::AddObserver(
- aura::client::ActivationChangeObserver* observer) {
- activation_observers_.AddObserver(observer);
-}
-
-void FocusController::RemoveObserver(
- aura::client::ActivationChangeObserver* observer) {
- activation_observers_.RemoveObserver(observer);
-}
-
-void FocusController::ActivateWindow(aura::Window* window) {
- FocusWindow(window);
-}
-
-void FocusController::DeactivateWindow(aura::Window* window) {
- if (window)
- FocusWindow(rules_->GetNextActivatableWindow(window));
-}
-
-aura::Window* FocusController::GetActiveWindow() {
- return active_window_;
-}
-
-aura::Window* FocusController::GetActivatableWindow(aura::Window* window) {
- return rules_->GetActivatableWindow(window);
-}
-
-aura::Window* FocusController::GetToplevelWindow(aura::Window* window) {
- return rules_->GetToplevelWindow(window);
-}
-
-bool FocusController::OnWillFocusWindow(aura::Window* window,
- const ui::Event* event) {
- NOTREACHED();
- return false;
-}
-
-bool FocusController::CanActivateWindow(aura::Window* window) const {
- return rules_->CanActivateWindow(window);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, aura::client::FocusClient implementation:
-
-void FocusController::AddObserver(
- aura::client::FocusChangeObserver* observer) {
- focus_observers_.AddObserver(observer);
-}
-
-void FocusController::RemoveObserver(
- aura::client::FocusChangeObserver* observer) {
- focus_observers_.RemoveObserver(observer);
-}
-
-void FocusController::FocusWindow(aura::Window* window) {
- if (window &&
- (window->Contains(focused_window_) || window->Contains(active_window_))) {
- return;
- }
-
- // We should not be messing with the focus if the window has capture, unless
- // no has focus.
- if (window && (aura::client::GetCaptureWindow(window) == window) &&
- focused_window_) {
- return;
- }
-
- // Focusing a window also activates its containing activatable window. Note
- // that the rules could redirect activation activation and/or focus.
- aura::Window* focusable = rules_->GetFocusableWindow(window);
- aura::Window* activatable =
- focusable ? rules_->GetActivatableWindow(focusable) : NULL;
-
- // We need valid focusable/activatable windows in the event we're not clearing
- // focus. "Clearing focus" is inferred by whether or not |window| passed to
- // this function is non-NULL.
- if (window && (!focusable || !activatable))
- return;
- DCHECK((focusable && activatable) || !window);
-
- // Activation change observers may change the focused window. If this happens
- // we must not adjust the focus below since this will clobber that change.
- aura::Window* last_focused_window = focused_window_;
- if (!updating_activation_)
- SetActiveWindow(window, activatable);
-
- // If the window's ActivationChangeObserver shifted focus to a valid window,
- // we don't want to focus the window we thought would be focused by default.
- bool activation_changed_focus = last_focused_window != focused_window_;
- if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) {
- if (active_window_ && focusable)
- DCHECK(active_window_->Contains(focusable));
- SetFocusedWindow(focusable);
- }
-}
-
-void FocusController::ResetFocusWithinActiveWindow(aura::Window* window) {
- DCHECK(window);
- if (!active_window_)
- return;
- if (!active_window_->Contains(window))
- return;
- SetFocusedWindow(window);
-}
-
-aura::Window* FocusController::GetFocusedWindow() {
- return focused_window_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, ui::EventHandler implementation:
-void FocusController::OnKeyEvent(ui::KeyEvent* event) {
-}
-
-void FocusController::OnMouseEvent(ui::MouseEvent* event) {
- if (event->type() == ui::ET_MOUSE_PRESSED)
- WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
-}
-
-void FocusController::OnScrollEvent(ui::ScrollEvent* event) {
-}
-
-void FocusController::OnTouchEvent(ui::TouchEvent* event) {
-}
-
-void FocusController::OnGestureEvent(ui::GestureEvent* event) {
- if (event->type() == ui::ET_GESTURE_BEGIN &&
- event->details().touch_points() == 1) {
- WindowFocusedFromInputEvent(static_cast<aura::Window*>(event->target()));
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, aura::WindowObserver implementation:
-
-void FocusController::OnWindowVisibilityChanged(aura::Window* window,
- bool visible) {
- if (!visible) {
- WindowLostFocusFromDispositionChange(window, window->parent());
- // Despite the focus change, we need to keep the window being hidden
- // stacked above the new window so it stays open on top as it animates away.
- aura::Window* next_window = GetActiveWindow();
- if (next_window && next_window->parent() == window->parent())
- StackWindowLayerAbove(window, next_window);
- }
-}
-
-void FocusController::OnWindowDestroying(aura::Window* window) {
- WindowLostFocusFromDispositionChange(window, window->parent());
-}
-
-void FocusController::OnWindowHierarchyChanging(
- const HierarchyChangeParams& params) {
- if (params.receiver == active_window_ &&
- params.target->Contains(params.receiver) && (!params.new_parent ||
- aura::client::GetFocusClient(params.new_parent) !=
- aura::client::GetFocusClient(params.receiver))) {
- WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
- }
-}
-
-void FocusController::OnWindowHierarchyChanged(
- const HierarchyChangeParams& params) {
- if (params.receiver == focused_window_ &&
- params.target->Contains(params.receiver) && (!params.new_parent ||
- aura::client::GetFocusClient(params.new_parent) !=
- aura::client::GetFocusClient(params.receiver))) {
- WindowLostFocusFromDispositionChange(params.receiver, params.old_parent);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FocusController, private:
-
-void FocusController::SetFocusedWindow(aura::Window* window) {
- if (updating_focus_ || window == focused_window_)
- return;
- DCHECK(rules_->CanFocusWindow(window));
- if (window)
- DCHECK_EQ(window, rules_->GetFocusableWindow(window));
-
- base::AutoReset<bool> updating_focus(&updating_focus_, true);
- aura::Window* lost_focus = focused_window_;
- if (focused_window_ && observer_manager_.IsObserving(focused_window_) &&
- focused_window_ != active_window_) {
- observer_manager_.Remove(focused_window_);
- }
- focused_window_ = window;
- if (focused_window_ && !observer_manager_.IsObserving(focused_window_))
- observer_manager_.Add(focused_window_);
-
- FOR_EACH_OBSERVER(aura::client::FocusChangeObserver,
- focus_observers_,
- OnWindowFocused(focused_window_, lost_focus));
- aura::client::FocusChangeObserver* observer =
- aura::client::GetFocusChangeObserver(lost_focus);
- if (observer)
- observer->OnWindowFocused(focused_window_, lost_focus);
- observer = aura::client::GetFocusChangeObserver(focused_window_);
- if (observer)
- observer->OnWindowFocused(focused_window_, lost_focus);
-}
-
-void FocusController::SetActiveWindow(aura::Window* requested_window,
- aura::Window* window) {
- if (updating_activation_)
- return;
-
- if (window == active_window_) {
- if (requested_window) {
- FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
- activation_observers_,
- OnAttemptToReactivateWindow(requested_window,
- active_window_));
- }
- return;
- }
-
- DCHECK(rules_->CanActivateWindow(window));
- if (window)
- DCHECK_EQ(window, rules_->GetActivatableWindow(window));
-
- base::AutoReset<bool> updating_activation(&updating_activation_, true);
- aura::Window* lost_activation = active_window_;
- // Allow for the window losing activation to be deleted during dispatch. If
- // it is deleted pass NULL to observers instead of a deleted window.
- aura::WindowTracker window_tracker;
- if (lost_activation)
- window_tracker.Add(lost_activation);
- if (active_window_ && observer_manager_.IsObserving(active_window_) &&
- focused_window_ != active_window_) {
- observer_manager_.Remove(active_window_);
- }
- active_window_ = window;
- if (active_window_ && !observer_manager_.IsObserving(active_window_))
- observer_manager_.Add(active_window_);
- if (active_window_) {
- StackTransientParentsBelowModalWindow(active_window_);
- active_window_->parent()->StackChildAtTop(active_window_);
- }
-
- aura::client::ActivationChangeObserver* observer = NULL;
- if (window_tracker.Contains(lost_activation)) {
- observer = aura::client::GetActivationChangeObserver(lost_activation);
- if (observer)
- observer->OnWindowActivated(active_window_, lost_activation);
- }
- observer = aura::client::GetActivationChangeObserver(active_window_);
- if (observer) {
- observer->OnWindowActivated(
- active_window_,
- window_tracker.Contains(lost_activation) ? lost_activation : NULL);
- }
- FOR_EACH_OBSERVER(aura::client::ActivationChangeObserver,
- activation_observers_,
- OnWindowActivated(active_window_,
- window_tracker.Contains(lost_activation) ?
- lost_activation : NULL));
-}
-
-void FocusController::WindowLostFocusFromDispositionChange(
- aura::Window* window,
- aura::Window* next) {
- // A window's modality state will interfere with focus restoration during its
- // destruction.
- window->ClearProperty(aura::client::kModalKey);
- // TODO(beng): See if this function can be replaced by a call to
- // FocusWindow().
- // Activation adjustments are handled first in the event of a disposition
- // changed. If an activation change is necessary, focus is reset as part of
- // that process so there's no point in updating focus independently.
- if (window == active_window_) {
- aura::Window* next_activatable = rules_->GetNextActivatableWindow(window);
- SetActiveWindow(NULL, next_activatable);
- if (!(active_window_ && active_window_->Contains(focused_window_)))
- SetFocusedWindow(next_activatable);
- } else if (window->Contains(focused_window_)) {
- // Active window isn't changing, but focused window might be.
- SetFocusedWindow(rules_->GetFocusableWindow(next));
- }
-}
-
-void FocusController::WindowFocusedFromInputEvent(aura::Window* window) {
- // Only focus |window| if it or any of its parents can be focused. Otherwise
- // FocusWindow() will focus the topmost window, which may not be the
- // currently focused one.
- if (rules_->CanFocusWindow(GetToplevelWindow(window)))
- FocusWindow(window);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/focus_controller.h b/chromium/ui/views/corewm/focus_controller.h
deleted file mode 100644
index 1dc69b78219..00000000000
--- a/chromium/ui/views/corewm/focus_controller.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_
-#define UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "base/scoped_observer.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/window_observer.h"
-#include "ui/events/event_handler.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-
-class FocusRules;
-
-// FocusController handles focus and activation changes for an environment
-// encompassing one or more RootWindows. Within an environment there can be
-// only one focused and one active window at a time. When focus or activation
-// changes notifications are sent using the
-// aura::client::Focus/ActivationChangeObserver interfaces.
-// Changes to focus and activation can be from three sources:
-// . the Aura Client API (implemented here in aura::client::ActivationClient).
-// (The FocusController must be set as the ActivationClient implementation
-// for all RootWindows).
-// . input events (implemented here in ui::EventHandler).
-// (The FocusController must be registered as a pre-target handler for
-// the applicable environment owner, either a RootWindow or another type).
-// . Window disposition changes (implemented here in aura::WindowObserver).
-// (The FocusController registers itself as an observer of the active and
-// focused windows).
-class VIEWS_EXPORT FocusController : public aura::client::ActivationClient,
- public aura::client::FocusClient,
- public ui::EventHandler,
- public aura::WindowObserver {
- public:
- // |rules| cannot be NULL.
- explicit FocusController(FocusRules* rules);
- virtual ~FocusController();
-
- private:
- // Overridden from aura::client::ActivationClient:
- virtual void AddObserver(
- aura::client::ActivationChangeObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- aura::client::ActivationChangeObserver* observer) OVERRIDE;
- virtual void ActivateWindow(aura::Window* window) OVERRIDE;
- virtual void DeactivateWindow(aura::Window* window) OVERRIDE;
- virtual aura::Window* GetActiveWindow() OVERRIDE;
- virtual aura::Window* GetActivatableWindow(aura::Window* window) OVERRIDE;
- virtual aura::Window* GetToplevelWindow(aura::Window* window) OVERRIDE;
- virtual bool OnWillFocusWindow(aura::Window* window,
- const ui::Event* event) OVERRIDE;
- virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE;
-
- // Overridden from aura::client::FocusClient:
- virtual void AddObserver(
- aura::client::FocusChangeObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- aura::client::FocusChangeObserver* observer) OVERRIDE;
- virtual void FocusWindow(aura::Window* window) OVERRIDE;
- virtual void ResetFocusWithinActiveWindow(aura::Window* window) OVERRIDE;
- virtual aura::Window* GetFocusedWindow() OVERRIDE;
-
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE;
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
- virtual void OnWindowHierarchyChanging(
- const HierarchyChangeParams& params) OVERRIDE;
- virtual void OnWindowHierarchyChanged(
- const HierarchyChangeParams& params) OVERRIDE;
-
- // Internal implementation that sets the focused window, fires events etc.
- // This function must be called with a valid focusable window.
- void SetFocusedWindow(aura::Window* window);
-
- // Internal implementation that sets the active window, fires events etc.
- // This function must be called with a valid |activatable_window|.
- // |requested window| refers to the window that was passed in to an external
- // request (e.g. FocusWindow or ActivateWindow). It may be NULL, e.g. if
- // SetActiveWindow was not called by an external request. |activatable_window|
- // refers to the actual window to be activated, which may be different.
- void SetActiveWindow(aura::Window* requested_window,
- aura::Window* activatable_window);
-
- // Called when a window's disposition changed such that it and its hierarchy
- // are no longer focusable/activatable. |next| is a valid window that is used
- // as a starting point for finding a window to focus next based on rules.
- void WindowLostFocusFromDispositionChange(aura::Window* window,
- aura::Window* next);
-
- // Called when an attempt is made to focus or activate a window via an input
- // event targeted at that window. Rules determine the best focusable window
- // for the input window.
- void WindowFocusedFromInputEvent(aura::Window* window);
-
- aura::Window* active_window_;
- aura::Window* focused_window_;
-
- bool updating_focus_;
- bool updating_activation_;
-
- scoped_ptr<FocusRules> rules_;
-
- ObserverList<aura::client::ActivationChangeObserver> activation_observers_;
- ObserverList<aura::client::FocusChangeObserver> focus_observers_;
-
- ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusController);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_FOCUS_CONTROLLER_H_
diff --git a/chromium/ui/views/corewm/focus_controller_unittest.cc b/chromium/ui/views/corewm/focus_controller_unittest.cc
deleted file mode 100644
index cfccd056c97..00000000000
--- a/chromium/ui/views/corewm/focus_controller_unittest.cc
+++ /dev/null
@@ -1,1110 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/focus_controller.h"
-
-#include <map>
-
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/default_capture_client.h"
-#include "ui/aura/client/focus_change_observer.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tracker.h"
-#include "ui/events/event_handler.h"
-#include "ui/views/corewm/base_focus_rules.h"
-
-namespace views {
-namespace corewm {
-
-class FocusNotificationObserver : public aura::client::ActivationChangeObserver,
- public aura::client::FocusChangeObserver {
- public:
- FocusNotificationObserver()
- : activation_changed_count_(0),
- focus_changed_count_(0),
- reactivation_count_(0),
- reactivation_requested_window_(NULL),
- reactivation_actual_window_(NULL) {}
- virtual ~FocusNotificationObserver() {}
-
- void ExpectCounts(int activation_changed_count, int focus_changed_count) {
- EXPECT_EQ(activation_changed_count, activation_changed_count_);
- EXPECT_EQ(focus_changed_count, focus_changed_count_);
- }
- int reactivation_count() const {
- return reactivation_count_;
- }
- aura::Window* reactivation_requested_window() const {
- return reactivation_requested_window_;
- }
- aura::Window* reactivation_actual_window() const {
- return reactivation_actual_window_;
- }
-
- private:
- // Overridden from aura::client::ActivationChangeObserver:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- ++activation_changed_count_;
- }
- virtual void OnAttemptToReactivateWindow(
- aura::Window* request_active,
- aura::Window* actual_active) OVERRIDE {
- ++reactivation_count_;
- reactivation_requested_window_ = request_active;
- reactivation_actual_window_ = actual_active;
- }
-
- // Overridden from aura::client::FocusChangeObserver:
- virtual void OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) OVERRIDE {
- ++focus_changed_count_;
- }
-
- int activation_changed_count_;
- int focus_changed_count_;
- int reactivation_count_;
- aura::Window* reactivation_requested_window_;
- aura::Window* reactivation_actual_window_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver);
-};
-
-// ActivationChangeObserver that keeps a vector of all the windows that lost
-// active.
-class RecordingActivationChangeObserver
- : public aura::client::ActivationChangeObserver {
- public:
- explicit RecordingActivationChangeObserver(aura::Window* root)
- : root_(root) {
- aura::client::GetActivationClient(root_)->AddObserver(this);
- }
- virtual ~RecordingActivationChangeObserver() {
- aura::client::GetActivationClient(root_)->RemoveObserver(this);
- }
-
- // Each time we get OnWindowActivated() the |lost_active| parameter is
- // added here.
- const std::vector<aura::Window*>& lost() const { return lost_; }
-
- // Overridden from aura::client::ActivationChangeObserver:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- lost_.push_back(lost_active);
- }
-
- private:
- aura::Window* root_;
- std::vector<aura::Window*> lost_;
-
- DISALLOW_COPY_AND_ASSIGN(RecordingActivationChangeObserver);
-};
-
-// ActivationChangeObserver that deletes the window losing activation.
-class DeleteOnLoseActivationChangeObserver
- : public aura::client::ActivationChangeObserver {
- public:
- explicit DeleteOnLoseActivationChangeObserver(aura::Window* window)
- : root_(window->GetRootWindow()),
- window_(window) {
- aura::client::GetActivationClient(root_)->AddObserver(this);
- }
- virtual ~DeleteOnLoseActivationChangeObserver() {
- aura::client::GetActivationClient(root_)->RemoveObserver(this);
- }
-
- bool did_delete() const { return window_ == NULL; }
-
- // Overridden from aura::client::ActivationChangeObserver:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- if (window_ && lost_active == window_) {
- window_ = NULL;
- delete lost_active;
- }
- }
-
- private:
- aura::Window* root_;
- aura::Window* window_;
-
- DISALLOW_COPY_AND_ASSIGN(DeleteOnLoseActivationChangeObserver);
-};
-
-class ScopedFocusNotificationObserver : public FocusNotificationObserver {
- public:
- ScopedFocusNotificationObserver(aura::Window* root_window)
- : root_window_(root_window) {
- aura::client::GetActivationClient(root_window_)->AddObserver(this);
- aura::client::GetFocusClient(root_window_)->AddObserver(this);
- }
- virtual ~ScopedFocusNotificationObserver() {
- aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
- aura::client::GetFocusClient(root_window_)->RemoveObserver(this);
- }
-
- private:
- aura::Window* root_window_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver);
-};
-
-class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver {
- public:
- ScopedTargetFocusNotificationObserver(aura::Window* root_window, int id)
- : target_(root_window->GetChildById(id)) {
- aura::client::SetActivationChangeObserver(target_, this);
- aura::client::SetFocusChangeObserver(target_, this);
- tracker_.Add(target_);
- }
- virtual ~ScopedTargetFocusNotificationObserver() {
- if (tracker_.Contains(target_)) {
- aura::client::SetActivationChangeObserver(target_, NULL);
- aura::client::SetFocusChangeObserver(target_, NULL);
- }
- }
-
- private:
- aura::Window* target_;
- aura::WindowTracker tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedTargetFocusNotificationObserver);
-};
-
-class FocusShiftingActivationObserver
- : public aura::client::ActivationChangeObserver {
- public:
- explicit FocusShiftingActivationObserver(aura::Window* activated_window)
- : activated_window_(activated_window),
- shift_focus_to_(NULL) {}
- virtual ~FocusShiftingActivationObserver() {}
-
- void set_shift_focus_to(aura::Window* shift_focus_to) {
- shift_focus_to_ = shift_focus_to;
- }
-
- private:
- // Overridden from aura::client::ActivationChangeObserver:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- // Shift focus to a child. This should prevent the default focusing from
- // occurring in FocusController::FocusWindow().
- if (gained_active == activated_window_) {
- aura::client::FocusClient* client =
- aura::client::GetFocusClient(gained_active);
- client->FocusWindow(shift_focus_to_);
- }
- }
-
- aura::Window* activated_window_;
- aura::Window* shift_focus_to_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver);
-};
-
-// BaseFocusRules subclass that allows basic overrides of focus/activation to
-// be tested. This is intended more as a test that the override system works at
-// all, rather than as an exhaustive set of use cases, those should be covered
-// in tests for those FocusRules implementations.
-class TestFocusRules : public BaseFocusRules {
- public:
- TestFocusRules() : focus_restriction_(NULL) {}
-
- // Restricts focus and activation to this window and its child hierarchy.
- void set_focus_restriction(aura::Window* focus_restriction) {
- focus_restriction_ = focus_restriction;
- }
-
- // Overridden from BaseFocusRules:
- virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE {
- // In FocusControllerTests, only the RootWindow has activatable children.
- return window->GetRootWindow() == window;
- }
- virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE {
- // Restricting focus to a non-activatable child window means the activatable
- // parent outside the focus restriction is activatable.
- bool can_activate =
- CanFocusOrActivate(window) || window->Contains(focus_restriction_);
- return can_activate ? BaseFocusRules::CanActivateWindow(window) : false;
- }
- virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE {
- return CanFocusOrActivate(window) ?
- BaseFocusRules::CanFocusWindow(window) : false;
- }
- virtual aura::Window* GetActivatableWindow(
- aura::Window* window) const OVERRIDE {
- return BaseFocusRules::GetActivatableWindow(
- CanFocusOrActivate(window) ? window : focus_restriction_);
- }
- virtual aura::Window* GetFocusableWindow(
- aura::Window* window) const OVERRIDE {
- return BaseFocusRules::GetFocusableWindow(
- CanFocusOrActivate(window) ? window : focus_restriction_);
- }
- virtual aura::Window* GetNextActivatableWindow(
- aura::Window* ignore) const OVERRIDE {
- aura::Window* next_activatable =
- BaseFocusRules::GetNextActivatableWindow(ignore);
- return CanFocusOrActivate(next_activatable) ?
- next_activatable : GetActivatableWindow(focus_restriction_);
- }
-
- private:
- bool CanFocusOrActivate(aura::Window* window) const {
- return !focus_restriction_ || focus_restriction_->Contains(window);
- }
-
- aura::Window* focus_restriction_;
-
- DISALLOW_COPY_AND_ASSIGN(TestFocusRules);
-};
-
-// Common infrastructure shared by all FocusController test types.
-class FocusControllerTestBase : public aura::test::AuraTestBase {
- protected:
- FocusControllerTestBase() {}
-
- // Overridden from aura::test::AuraTestBase:
- virtual void SetUp() OVERRIDE {
- // FocusController registers itself as an Env observer so it can catch all
- // window initializations, including the root_window()'s, so we create it
- // before allowing the base setup.
- test_focus_rules_ = new TestFocusRules;
- focus_controller_.reset(new FocusController(test_focus_rules_));
- aura::test::AuraTestBase::SetUp();
- root_window()->AddPreTargetHandler(focus_controller_.get());
- aura::client::SetFocusClient(root_window(), focus_controller_.get());
- aura::client::SetActivationClient(root_window(), focus_controller_.get());
-
- // Hierarchy used by all tests:
- // root_window
- // +-- w1
- // | +-- w11
- // | +-- w12
- // +-- w2
- // | +-- w21
- // | +-- w211
- // +-- w3
- aura::Window* w1 = aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 1,
- gfx::Rect(0, 0, 50, 50), root_window());
- aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 11,
- gfx::Rect(5, 5, 10, 10), w1);
- aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 12,
- gfx::Rect(15, 15, 10, 10), w1);
- aura::Window* w2 = aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 2,
- gfx::Rect(75, 75, 50, 50), root_window());
- aura::Window* w21 = aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 21,
- gfx::Rect(5, 5, 10, 10), w2);
- aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 211,
- gfx::Rect(1, 1, 5, 5), w21);
- aura::test::CreateTestWindowWithDelegate(
- aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 3,
- gfx::Rect(125, 125, 50, 50), root_window());
- }
- virtual void TearDown() OVERRIDE {
- root_window()->RemovePreTargetHandler(focus_controller_.get());
- aura::test::AuraTestBase::TearDown();
- test_focus_rules_ = NULL; // Owned by FocusController.
- focus_controller_.reset();
- }
-
- void FocusWindow(aura::Window* window) {
- aura::client::GetFocusClient(root_window())->FocusWindow(window);
- }
- aura::Window* GetFocusedWindow() {
- return aura::client::GetFocusClient(root_window())->GetFocusedWindow();
- }
- int GetFocusedWindowId() {
- aura::Window* focused_window = GetFocusedWindow();
- return focused_window ? focused_window->id() : -1;
- }
- void ActivateWindow(aura::Window* window) {
- aura::client::GetActivationClient(root_window())->ActivateWindow(window);
- }
- void DeactivateWindow(aura::Window* window) {
- aura::client::GetActivationClient(root_window())->DeactivateWindow(window);
- }
- aura::Window* GetActiveWindow() {
- return aura::client::GetActivationClient(root_window())->GetActiveWindow();
- }
- int GetActiveWindowId() {
- aura::Window* active_window = GetActiveWindow();
- return active_window ? active_window->id() : -1;
- }
-
- TestFocusRules* test_focus_rules() { return test_focus_rules_; }
-
- // Test functions.
- virtual void BasicFocus() = 0;
- virtual void BasicActivation() = 0;
- virtual void FocusEvents() = 0;
- virtual void DuplicateFocusEvents() {}
- virtual void ActivationEvents() = 0;
- virtual void ReactivationEvents() {}
- virtual void DuplicateActivationEvents() {}
- virtual void ShiftFocusWithinActiveWindow() {}
- virtual void ShiftFocusToChildOfInactiveWindow() {}
- virtual void ShiftFocusToParentOfFocusedWindow() {}
- virtual void FocusRulesOverride() = 0;
- virtual void ActivationRulesOverride() = 0;
- virtual void ShiftFocusOnActivation() {}
- virtual void ShiftFocusOnActivationDueToHide() {}
- virtual void NoShiftActiveOnActivation() {}
- virtual void NoFocusChangeOnClickOnCaptureWindow() {}
- virtual void ChangeFocusWhenNothingFocusedAndCaptured() {}
- virtual void DontPassDeletedWindow() {}
-
- private:
- scoped_ptr<FocusController> focus_controller_;
- TestFocusRules* test_focus_rules_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase);
-};
-
-// Test base for tests where focus is directly set to a target window.
-class FocusControllerDirectTestBase : public FocusControllerTestBase {
- protected:
- FocusControllerDirectTestBase() {}
-
- // Different test types shift focus in different ways.
- virtual void FocusWindowDirect(aura::Window* window) = 0;
- virtual void ActivateWindowDirect(aura::Window* window) = 0;
- virtual void DeactivateWindowDirect(aura::Window* window) = 0;
-
- // Input events do not change focus if the window can not be focused.
- virtual bool IsInputEvent() = 0;
-
- void FocusWindowById(int id) {
- aura::Window* window = root_window()->GetChildById(id);
- DCHECK(window);
- FocusWindowDirect(window);
- }
- void ActivateWindowById(int id) {
- aura::Window* window = root_window()->GetChildById(id);
- DCHECK(window);
- ActivateWindowDirect(window);
- }
-
- // Overridden from FocusControllerTestBase:
- virtual void BasicFocus() OVERRIDE {
- EXPECT_EQ(NULL, GetFocusedWindow());
- FocusWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
- FocusWindowById(2);
- EXPECT_EQ(2, GetFocusedWindowId());
- }
- virtual void BasicActivation() OVERRIDE {
- EXPECT_EQ(NULL, GetActiveWindow());
- ActivateWindowById(1);
- EXPECT_EQ(1, GetActiveWindowId());
- ActivateWindowById(2);
- EXPECT_EQ(2, GetActiveWindowId());
- // Verify that attempting to deactivate NULL does not crash and does not
- // change activation.
- DeactivateWindow(NULL);
- EXPECT_EQ(2, GetActiveWindowId());
- DeactivateWindow(GetActiveWindow());
- EXPECT_EQ(1, GetActiveWindowId());
- }
- virtual void FocusEvents() OVERRIDE {
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
- ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
-
- root_observer.ExpectCounts(0, 0);
- observer1.ExpectCounts(0, 0);
- observer2.ExpectCounts(0, 0);
-
- FocusWindowById(1);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
- observer2.ExpectCounts(0, 0);
-
- FocusWindowById(2);
- root_observer.ExpectCounts(2, 2);
- observer1.ExpectCounts(2, 2);
- observer2.ExpectCounts(1, 1);
- }
- virtual void DuplicateFocusEvents() OVERRIDE {
- // Focusing an existing focused window should not resend focus events.
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
-
- root_observer.ExpectCounts(0, 0);
- observer1.ExpectCounts(0, 0);
-
- FocusWindowById(1);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
-
- FocusWindowById(1);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
- }
- virtual void ActivationEvents() OVERRIDE {
- ActivateWindowById(1);
-
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
- ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
-
- root_observer.ExpectCounts(0, 0);
- observer1.ExpectCounts(0, 0);
- observer2.ExpectCounts(0, 0);
-
- ActivateWindowById(2);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
- observer2.ExpectCounts(1, 1);
- }
- virtual void ReactivationEvents() OVERRIDE {
- ActivateWindowById(1);
- ScopedFocusNotificationObserver root_observer(root_window());
- EXPECT_EQ(0, root_observer.reactivation_count());
- root_window()->GetChildById(2)->Hide();
- // When we attempt to activate "2", which cannot be activated because it
- // is not visible, "1" will be reactivated.
- ActivateWindowById(2);
- EXPECT_EQ(1, root_observer.reactivation_count());
- EXPECT_EQ(root_window()->GetChildById(2),
- root_observer.reactivation_requested_window());
- EXPECT_EQ(root_window()->GetChildById(1),
- root_observer.reactivation_actual_window());
- }
- virtual void DuplicateActivationEvents() OVERRIDE {
- // Activating an existing active window should not resend activation events.
- ActivateWindowById(1);
-
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
- ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
-
- root_observer.ExpectCounts(0, 0);
- observer1.ExpectCounts(0, 0);
- observer2.ExpectCounts(0, 0);
-
- ActivateWindowById(2);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
- observer2.ExpectCounts(1, 1);
-
- ActivateWindowById(2);
- root_observer.ExpectCounts(1, 1);
- observer1.ExpectCounts(1, 1);
- observer2.ExpectCounts(1, 1);
- }
- virtual void ShiftFocusWithinActiveWindow() OVERRIDE {
- ActivateWindowById(1);
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
- FocusWindowById(11);
- EXPECT_EQ(11, GetFocusedWindowId());
- FocusWindowById(12);
- EXPECT_EQ(12, GetFocusedWindowId());
- }
- virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE {
- ActivateWindowById(2);
- EXPECT_EQ(2, GetActiveWindowId());
- EXPECT_EQ(2, GetFocusedWindowId());
- FocusWindowById(11);
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(11, GetFocusedWindowId());
- }
- virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE {
- ActivateWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
- FocusWindowById(11);
- EXPECT_EQ(11, GetFocusedWindowId());
- FocusWindowById(1);
- // Focus should _not_ shift to the parent of the already-focused window.
- EXPECT_EQ(11, GetFocusedWindowId());
- }
- virtual void FocusRulesOverride() OVERRIDE {
- EXPECT_EQ(NULL, GetFocusedWindow());
- FocusWindowById(11);
- EXPECT_EQ(11, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211));
- FocusWindowById(12);
- // Input events leave focus unchanged; direct API calls will change focus
- // to the restricted window.
- int focused_window = IsInputEvent() ? 11 : 211;
- EXPECT_EQ(focused_window, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(NULL);
- FocusWindowById(12);
- EXPECT_EQ(12, GetFocusedWindowId());
- }
- virtual void ActivationRulesOverride() OVERRIDE {
- ActivateWindowById(1);
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
-
- aura::Window* w3 = root_window()->GetChildById(3);
- test_focus_rules()->set_focus_restriction(w3);
-
- ActivateWindowById(2);
- // Input events leave activation unchanged; direct API calls will activate
- // the restricted window.
- int active_window = IsInputEvent() ? 1 : 3;
- EXPECT_EQ(active_window, GetActiveWindowId());
- EXPECT_EQ(active_window, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(NULL);
- ActivateWindowById(2);
- EXPECT_EQ(2, GetActiveWindowId());
- EXPECT_EQ(2, GetFocusedWindowId());
- }
- virtual void ShiftFocusOnActivation() OVERRIDE {
- // When a window is activated, by default that window is also focused.
- // An ActivationChangeObserver may shift focus to another window within the
- // same activatable window.
- ActivateWindowById(2);
- EXPECT_EQ(2, GetFocusedWindowId());
- ActivateWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
-
- ActivateWindowById(2);
-
- aura::Window* target = root_window()->GetChildById(1);
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(root_window());
-
- scoped_ptr<FocusShiftingActivationObserver> observer(
- new FocusShiftingActivationObserver(target));
- observer->set_shift_focus_to(target->GetChildById(11));
- client->AddObserver(observer.get());
-
- ActivateWindowById(1);
-
- // w1's ActivationChangeObserver shifted focus to this child, pre-empting
- // FocusController's default setting.
- EXPECT_EQ(11, GetFocusedWindowId());
-
- ActivateWindowById(2);
- EXPECT_EQ(2, GetFocusedWindowId());
-
- // Simulate a focus reset by the ActivationChangeObserver. This should
- // trigger the default setting in FocusController.
- observer->set_shift_focus_to(NULL);
- ActivateWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
-
- client->RemoveObserver(observer.get());
-
- ActivateWindowById(2);
- EXPECT_EQ(2, GetFocusedWindowId());
- ActivateWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
- }
- virtual void ShiftFocusOnActivationDueToHide() OVERRIDE {
- // Similar to ShiftFocusOnActivation except the activation change is
- // triggered by hiding the active window.
- ActivateWindowById(1);
- EXPECT_EQ(1, GetFocusedWindowId());
-
- // Removes window 3 as candidate for next activatable window.
- root_window()->GetChildById(3)->Hide();
- EXPECT_EQ(1, GetFocusedWindowId());
-
- aura::Window* target = root_window()->GetChildById(2);
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(root_window());
-
- scoped_ptr<FocusShiftingActivationObserver> observer(
- new FocusShiftingActivationObserver(target));
- observer->set_shift_focus_to(target->GetChildById(21));
- client->AddObserver(observer.get());
-
- // Hide the active window.
- root_window()->GetChildById(1)->Hide();
-
- EXPECT_EQ(21, GetFocusedWindowId());
-
- client->RemoveObserver(observer.get());
- }
- virtual void NoShiftActiveOnActivation() OVERRIDE {
- // When a window is activated, we need to prevent any change to activation
- // from being made in response to an activation change notification.
- }
-
- virtual void NoFocusChangeOnClickOnCaptureWindow() OVERRIDE {
- scoped_ptr<aura::client::DefaultCaptureClient> capture_client(
- new aura::client::DefaultCaptureClient(root_window()));
- // Clicking on a window which has capture should not cause a focus change
- // to the window. This test verifies whether that is indeed the case.
- ActivateWindowById(1);
-
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
-
- aura::Window* w2 = root_window()->GetChildById(2);
- aura::client::GetCaptureClient(root_window())->SetCapture(w2);
- aura::test::EventGenerator generator(root_window(), w2);
- generator.ClickLeftButton();
-
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
- aura::client::GetCaptureClient(root_window())->ReleaseCapture(w2);
- }
-
- // Verifies focus change is honored while capture held.
- virtual void ChangeFocusWhenNothingFocusedAndCaptured() OVERRIDE {
- scoped_ptr<aura::client::DefaultCaptureClient> capture_client(
- new aura::client::DefaultCaptureClient(root_window()));
- aura::Window* w1 = root_window()->GetChildById(1);
- aura::client::GetCaptureClient(root_window())->SetCapture(w1);
-
- EXPECT_EQ(-1, GetActiveWindowId());
- EXPECT_EQ(-1, GetFocusedWindowId());
-
- FocusWindowById(1);
-
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
-
- aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1);
- }
-
- // Verfies if a window that loses activation is deleted during observer
- // notification we don't pass the deleted window to other observers.
- virtual void DontPassDeletedWindow() OVERRIDE {
- FocusWindowById(1);
-
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
-
- DeleteOnLoseActivationChangeObserver observer1(
- root_window()->GetChildById(1));
- RecordingActivationChangeObserver observer2(root_window());
-
- FocusWindowById(2);
-
- EXPECT_EQ(2, GetActiveWindowId());
- EXPECT_EQ(2, GetFocusedWindowId());
-
- EXPECT_TRUE(observer1.did_delete());
- ASSERT_EQ(1u, observer2.lost().size());
- EXPECT_TRUE(observer2.lost()[0] == NULL);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase);
-};
-
-// Focus and Activation changes via aura::client::ActivationClient API.
-class FocusControllerApiTest : public FocusControllerDirectTestBase {
- public:
- FocusControllerApiTest() {}
-
- private:
- // Overridden from FocusControllerTestBase:
- virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
- FocusWindow(window);
- }
- virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
- ActivateWindow(window);
- }
- virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
- DeactivateWindow(window);
- }
- virtual bool IsInputEvent() OVERRIDE { return false; }
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest);
-};
-
-// Focus and Activation changes via input events.
-class FocusControllerMouseEventTest : public FocusControllerDirectTestBase {
- public:
- FocusControllerMouseEventTest() {}
-
- private:
- // Overridden from FocusControllerTestBase:
- virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
- aura::test::EventGenerator generator(root_window(), window);
- generator.ClickLeftButton();
- }
- virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
- aura::test::EventGenerator generator(root_window(), window);
- generator.ClickLeftButton();
- }
- virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
- aura::Window* next_activatable =
- test_focus_rules()->GetNextActivatableWindow(window);
- aura::test::EventGenerator generator(root_window(), next_activatable);
- generator.ClickLeftButton();
- }
- virtual bool IsInputEvent() OVERRIDE { return true; }
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest);
-};
-
-class FocusControllerGestureEventTest : public FocusControllerDirectTestBase {
- public:
- FocusControllerGestureEventTest() {}
-
- private:
- // Overridden from FocusControllerTestBase:
- virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
- aura::test::EventGenerator generator(root_window(), window);
- generator.GestureTapAt(window->bounds().CenterPoint());
- }
- virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
- aura::test::EventGenerator generator(root_window(), window);
- generator.GestureTapAt(window->bounds().CenterPoint());
- }
- virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
- aura::Window* next_activatable =
- test_focus_rules()->GetNextActivatableWindow(window);
- aura::test::EventGenerator generator(root_window(), next_activatable);
- generator.GestureTapAt(window->bounds().CenterPoint());
- }
- virtual bool IsInputEvent() OVERRIDE { return true; }
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerGestureEventTest);
-};
-
-// Test base for tests where focus is implicitly set to a window as the result
-// of a disposition change to the focused window or the hierarchy that contains
-// it.
-class FocusControllerImplicitTestBase : public FocusControllerTestBase {
- protected:
- explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {}
-
- aura::Window* GetDispositionWindow(aura::Window* window) {
- return parent_ ? window->parent() : window;
- }
-
- // Change the disposition of |window| in such a way as it will lose focus.
- virtual void ChangeWindowDisposition(aura::Window* window) = 0;
-
- // Allow each disposition change test to add additional post-disposition
- // change expectations.
- virtual void PostDispostionChangeExpectations() {}
-
- // Overridden from FocusControllerTestBase:
- virtual void BasicFocus() OVERRIDE {
- EXPECT_EQ(NULL, GetFocusedWindow());
-
- aura::Window* w211 = root_window()->GetChildById(211);
- FocusWindow(w211);
- EXPECT_EQ(211, GetFocusedWindowId());
-
- ChangeWindowDisposition(w211);
- // BasicFocusRules passes focus to the parent.
- EXPECT_EQ(parent_ ? 2 : 21, GetFocusedWindowId());
- }
- virtual void BasicActivation() OVERRIDE {
- DCHECK(!parent_) << "Activation tests don't support parent changes.";
-
- EXPECT_EQ(NULL, GetActiveWindow());
-
- aura::Window* w2 = root_window()->GetChildById(2);
- ActivateWindow(w2);
- EXPECT_EQ(2, GetActiveWindowId());
-
- ChangeWindowDisposition(w2);
- EXPECT_EQ(3, GetActiveWindowId());
- PostDispostionChangeExpectations();
- }
- virtual void FocusEvents() OVERRIDE {
- aura::Window* w211 = root_window()->GetChildById(211);
- FocusWindow(w211);
-
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer211(root_window(), 211);
- root_observer.ExpectCounts(0, 0);
- observer211.ExpectCounts(0, 0);
-
- ChangeWindowDisposition(w211);
- root_observer.ExpectCounts(0, 1);
- observer211.ExpectCounts(0, 1);
- }
- virtual void ActivationEvents() OVERRIDE {
- DCHECK(!parent_) << "Activation tests don't support parent changes.";
-
- aura::Window* w2 = root_window()->GetChildById(2);
- ActivateWindow(w2);
-
- ScopedFocusNotificationObserver root_observer(root_window());
- ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
- ScopedTargetFocusNotificationObserver observer3(root_window(), 3);
- root_observer.ExpectCounts(0, 0);
- observer2.ExpectCounts(0, 0);
- observer3.ExpectCounts(0, 0);
-
- ChangeWindowDisposition(w2);
- root_observer.ExpectCounts(1, 1);
- observer2.ExpectCounts(1, 1);
- observer3.ExpectCounts(1, 1);
- }
- virtual void FocusRulesOverride() OVERRIDE {
- EXPECT_EQ(NULL, GetFocusedWindow());
- aura::Window* w211 = root_window()->GetChildById(211);
- FocusWindow(w211);
- EXPECT_EQ(211, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(root_window()->GetChildById(11));
- ChangeWindowDisposition(w211);
- // Normally, focus would shift to the parent (w21) but the override shifts
- // it to 11.
- EXPECT_EQ(11, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(NULL);
- }
- virtual void ActivationRulesOverride() OVERRIDE {
- DCHECK(!parent_) << "Activation tests don't support parent changes.";
-
- aura::Window* w1 = root_window()->GetChildById(1);
- ActivateWindow(w1);
-
- EXPECT_EQ(1, GetActiveWindowId());
- EXPECT_EQ(1, GetFocusedWindowId());
-
- aura::Window* w3 = root_window()->GetChildById(3);
- test_focus_rules()->set_focus_restriction(w3);
-
- // Normally, activation/focus would move to w2, but since we have a focus
- // restriction, it should move to w3 instead.
- ChangeWindowDisposition(w1);
- EXPECT_EQ(3, GetActiveWindowId());
- EXPECT_EQ(3, GetFocusedWindowId());
-
- test_focus_rules()->set_focus_restriction(NULL);
- ActivateWindow(root_window()->GetChildById(2));
- EXPECT_EQ(2, GetActiveWindowId());
- EXPECT_EQ(2, GetFocusedWindowId());
- }
-
- private:
- // When true, the disposition change occurs to the parent of the window
- // instead of to the window. This verifies that changes occurring in the
- // hierarchy that contains the window affect the window's focus.
- bool parent_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase);
-};
-
-// Focus and Activation changes in response to window visibility changes.
-class FocusControllerHideTest : public FocusControllerImplicitTestBase {
- public:
- FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {}
-
- protected:
- FocusControllerHideTest(bool parent)
- : FocusControllerImplicitTestBase(parent) {}
-
- // Overridden from FocusControllerImplicitTestBase:
- virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
- GetDispositionWindow(window)->Hide();
- }
- virtual void PostDispostionChangeExpectations() OVERRIDE {
- // BasicActivation() starts with the stacking order: 1, 2, 3 (3 topmost)
- // and then activates 2. After 2 is hidden in ChangeWindowDisposition
- // above, 3 is activated, but code in
- // FocusController::OnWindowVisibilityChanging keeps 2's layer above 3's
- // until a hide animation completes (e.g. a fade-out transition).
- aura::Window* w2 = root_window()->GetChildById(2);
- aura::Window* w3 = root_window()->GetChildById(3);
-
- // W2 was hidden, but its layer should still be stacked above W3's.
- typedef std::vector<ui::Layer*> Layers;
- const Layers& children = w3->parent()->layer()->children();
- Layers::const_iterator w3_iter =
- std::find(children.begin(), children.end(), w3->layer());
- Layers::const_iterator w2_iter =
- std::find(children.begin(), children.end(), w2->layer());
- EXPECT_TRUE(w2_iter > w3_iter);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest);
-};
-
-// Focus and Activation changes in response to window parent visibility
-// changes.
-class FocusControllerParentHideTest : public FocusControllerHideTest {
- public:
- FocusControllerParentHideTest() : FocusControllerHideTest(true) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest);
-};
-
-// Focus and Activation changes in response to window destruction.
-class FocusControllerDestructionTest : public FocusControllerImplicitTestBase {
- public:
- FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {}
-
- protected:
- FocusControllerDestructionTest(bool parent)
- : FocusControllerImplicitTestBase(parent) {}
-
- // Overridden from FocusControllerImplicitTestBase:
- virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
- delete GetDispositionWindow(window);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest);
-};
-
-// Focus and Activation changes in response to window parent destruction.
-class FocusControllerParentDestructionTest
- : public FocusControllerDestructionTest {
- public:
- FocusControllerParentDestructionTest()
- : FocusControllerDestructionTest(true) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerParentDestructionTest);
-};
-
-// Focus and Activation changes in response to window removal.
-class FocusControllerRemovalTest : public FocusControllerImplicitTestBase {
- public:
- FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {}
-
- protected:
- FocusControllerRemovalTest(bool parent)
- : FocusControllerImplicitTestBase(parent) {}
-
- // Overridden from FocusControllerImplicitTestBase:
- virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
- aura::Window* disposition_window = GetDispositionWindow(window);
- disposition_window->parent()->RemoveChild(disposition_window);
- window_owner_.reset(disposition_window);
- }
- virtual void TearDown() OVERRIDE {
- window_owner_.reset();
- FocusControllerImplicitTestBase::TearDown();
- }
-
- private:
- scoped_ptr<aura::Window> window_owner_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest);
-};
-
-// Focus and Activation changes in response to window parent removal.
-class FocusControllerParentRemovalTest : public FocusControllerRemovalTest {
- public:
- FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest);
-};
-
-
-#define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \
- TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); }
-
-// Runs direct focus change tests (input events and API calls).
-#define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerGestureEventTest, TESTNAME)
-
-// Runs implicit focus change tests for disposition changes to target.
-#define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME)
-
-// Runs implicit focus change tests for disposition changes to target's parent
-// hierarchy.
-#define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \
- /* TODO(beng): parent destruction tests are not supported at
- present due to workspace manager issues. \
- FOCUS_CONTROLLER_TEST(FocusControllerParentDestructionTest, TESTNAME) */ \
- FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \
- FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME)
-
-// Runs all implicit focus change tests (changes to the target and target's
-// parent hierarchy)
-#define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \
- IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
- IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME)
-
-// Runs all possible focus change tests.
-#define ALL_FOCUS_TESTS(TESTNAME) \
- DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
- IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME)
-
-// Runs focus change tests that apply only to the target. For example,
-// implicit activation changes caused by window disposition changes do not
-// occur when changes to the containing hierarchy happen.
-#define TARGET_FOCUS_TESTS(TESTNAME) \
- DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
- IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME)
-
-// - Focuses a window, verifies that focus changed.
-ALL_FOCUS_TESTS(BasicFocus);
-
-// - Activates a window, verifies that activation changed.
-TARGET_FOCUS_TESTS(BasicActivation);
-
-// - Focuses a window, verifies that focus events were dispatched.
-ALL_FOCUS_TESTS(FocusEvents);
-
-// - Focuses or activates a window multiple times, verifies that events are only
-// dispatched when focus/activation actually changes.
-DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents);
-DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents);
-
-// - Activates a window, verifies that activation events were dispatched.
-TARGET_FOCUS_TESTS(ActivationEvents);
-
-// - Attempts to active a hidden window, verifies that current window is
-// attempted to be reactivated and the appropriate event dispatched.
-FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents);
-
-// - Input events/API calls shift focus between focusable windows within the
-// active window.
-DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow);
-
-// - Input events/API calls to a child window of an inactive window shifts
-// activation to the activatable parent and focuses the child.
-DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow);
-
-// - Input events/API calls to focus the parent of the focused window do not
-// shift focus away from the child.
-DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow);
-
-// - Verifies that FocusRules determine what can be focused.
-ALL_FOCUS_TESTS(FocusRulesOverride);
-
-// - Verifies that FocusRules determine what can be activated.
-TARGET_FOCUS_TESTS(ActivationRulesOverride);
-
-// - Verifies that attempts to change focus or activation from a focus or
-// activation change observer are ignored.
-DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation);
-DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide);
-DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation);
-
-// Clicking on a window which has capture should not result in a focus change.
-DIRECT_FOCUS_CHANGE_TESTS(NoFocusChangeOnClickOnCaptureWindow);
-
-FOCUS_CONTROLLER_TEST(FocusControllerApiTest,
- ChangeFocusWhenNothingFocusedAndCaptured);
-
-// See description above DontPassDeletedWindow() for details.
-FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDeletedWindow);
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/focus_rules.h b/chromium/ui/views/corewm/focus_rules.h
deleted file mode 100644
index 559a2385432..00000000000
--- a/chromium/ui/views/corewm/focus_rules.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_FOCUS_RULES_H_
-#define UI_VIEWS_COREWM_FOCUS_RULES_H_
-
-#include "ui/views/views_export.h"
-
-namespace aura {
-class Window;
-}
-
-namespace views {
-namespace corewm {
-
-// Implemented by an object that establishes the rules about what can be
-// focused or activated.
-class VIEWS_EXPORT FocusRules {
- public:
- virtual ~FocusRules() {}
-
- // Returns true if |window| is a toplevel window. Whether or not a window
- // is considered toplevel is determined by a similar set of rules that
- // govern activation and focus. Not all toplevel windows are activatable,
- // call CanActivateWindow() to determine if a window can be activated.
- virtual bool IsToplevelWindow(aura::Window* window) const = 0;
- // Returns true if |window| can be activated or focused.
- virtual bool CanActivateWindow(aura::Window* window) const = 0;
- // For CanFocusWindow(), NULL is supported, because NULL is a valid focusable
- // window (in the case of clearing focus).
- virtual bool CanFocusWindow(aura::Window* window) const = 0;
-
- // Returns the toplevel window containing |window|. Not all toplevel windows
- // are activatable, call GetActivatableWindow() instead to return the
- // activatable window, which might be in a different hierarchy.
- // Will return NULL if |window| is not contained by a window considered to be
- // a toplevel window.
- virtual aura::Window* GetToplevelWindow(aura::Window* window) const = 0;
- // Returns the activatable or focusable window given an attempt to activate or
- // focus |window|. Some possible scenarios (not intended to be exhaustive):
- // - |window| is a child of a non-focusable window and so focus must be set
- // according to rules defined by the delegate, e.g. to a parent.
- // - |window| is an activatable window that is the transient parent of a modal
- // window, so attempts to activate |window| should result in the modal
- // transient being activated instead.
- // These methods may return NULL if they are unable to find an activatable
- // or focusable window given |window|.
- virtual aura::Window* GetActivatableWindow(aura::Window* window) const = 0;
- virtual aura::Window* GetFocusableWindow(aura::Window* window) const = 0;
-
- // Returns the next window to activate in the event that |ignore| is no longer
- // activatable. This function is called when something is happening to
- // |ignore| that means it can no longer have focus or activation, including
- // but not limited to:
- // - it or its parent hierarchy is being hidden, or removed from the
- // RootWindow.
- // - it is being destroyed.
- // - it is being explicitly deactivated.
- // |ignore| cannot be NULL.
- virtual aura::Window* GetNextActivatableWindow(
- aura::Window* ignore) const = 0;
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_FOCUS_RULES_H_
diff --git a/chromium/ui/views/corewm/image_grid.cc b/chromium/ui/views/corewm/image_grid.cc
deleted file mode 100644
index 29c775773c7..00000000000
--- a/chromium/ui/views/corewm/image_grid.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/image_grid.h"
-
-#include <algorithm>
-
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkXfermode.h"
-#include "ui/compositor/dip_util.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/transform.h"
-
-using std::max;
-using std::min;
-
-namespace views {
-namespace corewm {
-
-gfx::RectF ImageGrid::TestAPI::GetTransformedLayerBounds(
- const ui::Layer& layer) {
- gfx::RectF bounds = layer.bounds();
- layer.transform().TransformRect(&bounds);
- return bounds;
-}
-
-ImageGrid::ImageGrid()
- : layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
- top_image_height_(0),
- bottom_image_height_(0),
- left_image_width_(0),
- right_image_width_(0),
- base_top_row_height_(0),
- base_bottom_row_height_(0),
- base_left_column_width_(0),
- base_right_column_width_(0) {
-}
-
-ImageGrid::~ImageGrid() {
-}
-
-void ImageGrid::SetImages(const gfx::Image* top_left_image,
- const gfx::Image* top_image,
- const gfx::Image* top_right_image,
- const gfx::Image* left_image,
- const gfx::Image* center_image,
- const gfx::Image* right_image,
- const gfx::Image* bottom_left_image,
- const gfx::Image* bottom_image,
- const gfx::Image* bottom_right_image) {
- SetImage(top_left_image, &top_left_layer_, &top_left_painter_);
- SetImage(top_image, &top_layer_, &top_painter_);
- SetImage(top_right_image, &top_right_layer_, &top_right_painter_);
- SetImage(left_image, &left_layer_, &left_painter_);
- SetImage(center_image, &center_layer_, &center_painter_);
- SetImage(right_image, &right_layer_, &right_painter_);
- SetImage(bottom_left_image, &bottom_left_layer_, &bottom_left_painter_);
- SetImage(bottom_image, &bottom_layer_, &bottom_painter_);
- SetImage(bottom_right_image, &bottom_right_layer_, &bottom_right_painter_);
-
- top_image_height_ = GetImageSize(top_image).height();
- bottom_image_height_ = GetImageSize(bottom_image).height();
- left_image_width_ = GetImageSize(left_image).width();
- right_image_width_ = GetImageSize(right_image).width();
-
- base_top_row_height_ = max(GetImageSize(top_left_image).height(),
- max(GetImageSize(top_image).height(),
- GetImageSize(top_right_image).height()));
- base_bottom_row_height_ = max(GetImageSize(bottom_left_image).height(),
- max(GetImageSize(bottom_image).height(),
- GetImageSize(bottom_right_image).height()));
- base_left_column_width_ = max(GetImageSize(top_left_image).width(),
- max(GetImageSize(left_image).width(),
- GetImageSize(bottom_left_image).width()));
- base_right_column_width_ = max(GetImageSize(top_right_image).width(),
- max(GetImageSize(right_image).width(),
- GetImageSize(bottom_right_image).width()));
-
- // Invalidate previous |size_| so calls to SetSize() will recompute it.
- size_.SetSize(0, 0);
-}
-
-void ImageGrid::SetSize(const gfx::Size& size) {
- if (size_ == size)
- return;
-
- size_ = size;
-
- gfx::Rect updated_bounds = layer_->bounds();
- updated_bounds.set_size(size);
- layer_->SetBounds(updated_bounds);
-
- // Calculate the available amount of space for corner images on all sides of
- // the grid. If the images don't fit, we need to clip them.
- const int left = min(base_left_column_width_, size_.width() / 2);
- const int right = min(base_right_column_width_, size_.width() - left);
- const int top = min(base_top_row_height_, size_.height() / 2);
- const int bottom = min(base_bottom_row_height_, size_.height() - top);
-
- // The remaining space goes to the center image.
- int center_width = std::max(size.width() - left - right, 0);
- int center_height = std::max(size.height() - top - bottom, 0);
-
- // At non-integer scale factors, the ratio of dimensions in DIP is not
- // necessarily the same as the ratio in physical pixels due to rounding. Set
- // the transform on each of the layers based on dimensions in pixels.
- gfx::Size center_size_in_pixels = gfx::ToFlooredSize(gfx::ScaleSize(
- gfx::Size(center_width, center_height), layer_->device_scale_factor()));
-
- if (top_layer_.get()) {
- if (center_width > 0) {
- gfx::Transform transform;
- transform.Translate(left, 0);
- ScaleWidth(center_size_in_pixels, top_layer_.get(), transform);
- top_layer_->SetTransform(transform);
- }
- top_layer_->SetVisible(center_width > 0);
- }
- if (bottom_layer_.get()) {
- if (center_width > 0) {
- gfx::Transform transform;
- transform.Translate(
- left, size.height() - bottom_layer_->bounds().height());
- ScaleWidth(center_size_in_pixels, bottom_layer_.get(), transform);
- bottom_layer_->SetTransform(transform);
- }
- bottom_layer_->SetVisible(center_width > 0);
- }
- if (left_layer_.get()) {
- if (center_height > 0) {
- gfx::Transform transform;
- transform.Translate(0, top);
- ScaleHeight(center_size_in_pixels, left_layer_.get(), transform);
- left_layer_->SetTransform(transform);
- }
- left_layer_->SetVisible(center_height > 0);
- }
- if (right_layer_.get()) {
- if (center_height > 0) {
- gfx::Transform transform;
- transform.Translate(
- size.width() - right_layer_->bounds().width(), top);
- ScaleHeight(center_size_in_pixels, right_layer_.get(), transform);
- right_layer_->SetTransform(transform);
- }
- right_layer_->SetVisible(center_height > 0);
- }
-
- if (top_left_layer_.get()) {
- // No transformation needed; it should be at (0, 0) and unscaled.
- top_left_painter_->SetClipRect(
- LayerExceedsSize(top_left_layer_.get(), gfx::Size(left, top)) ?
- gfx::Rect(gfx::Rect(0, 0, left, top)) :
- gfx::Rect(),
- top_left_layer_.get());
- }
- if (top_right_layer_.get()) {
- gfx::Transform transform;
- transform.Translate(size.width() - top_right_layer_->bounds().width(), 0.0);
- top_right_layer_->SetTransform(transform);
- top_right_painter_->SetClipRect(
- LayerExceedsSize(top_right_layer_.get(), gfx::Size(right, top)) ?
- gfx::Rect(top_right_layer_->bounds().width() - right, 0,
- right, top) :
- gfx::Rect(),
- top_right_layer_.get());
- }
- if (bottom_left_layer_.get()) {
- gfx::Transform transform;
- transform.Translate(
- 0.0, size.height() - bottom_left_layer_->bounds().height());
- bottom_left_layer_->SetTransform(transform);
- bottom_left_painter_->SetClipRect(
- LayerExceedsSize(bottom_left_layer_.get(), gfx::Size(left, bottom)) ?
- gfx::Rect(0, bottom_left_layer_->bounds().height() - bottom,
- left, bottom) :
- gfx::Rect(),
- bottom_left_layer_.get());
- }
- if (bottom_right_layer_.get()) {
- gfx::Transform transform;
- transform.Translate(
- size.width() - bottom_right_layer_->bounds().width(),
- size.height() - bottom_right_layer_->bounds().height());
- bottom_right_layer_->SetTransform(transform);
- bottom_right_painter_->SetClipRect(
- LayerExceedsSize(bottom_right_layer_.get(), gfx::Size(right, bottom)) ?
- gfx::Rect(bottom_right_layer_->bounds().width() - right,
- bottom_right_layer_->bounds().height() - bottom,
- right, bottom) :
- gfx::Rect(),
- bottom_right_layer_.get());
- }
-
- if (center_layer_.get()) {
- if (center_width > 0 && center_height > 0) {
- gfx::Transform transform;
- transform.Translate(left, top);
- transform.Scale(center_width / center_layer_->bounds().width(),
- center_height / center_layer_->bounds().height());
- center_layer_->SetTransform(transform);
- }
- center_layer_->SetVisible(center_width > 0 && center_height > 0);
- }
-}
-
-void ImageGrid::SetContentBounds(const gfx::Rect& content_bounds) {
-
- SetSize(gfx::Size(
- content_bounds.width() + left_image_width_ + right_image_width_,
- content_bounds.height() + top_image_height_ +
- bottom_image_height_));
- layer_->SetBounds(
- gfx::Rect(content_bounds.x() - left_image_width_,
- content_bounds.y() - top_image_height_,
- layer_->bounds().width(),
- layer_->bounds().height()));
-}
-
-void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect,
- ui::Layer* layer) {
- if (clip_rect != clip_rect_) {
- clip_rect_ = clip_rect;
- layer->SchedulePaint(layer->bounds());
- }
-}
-
-void ImageGrid::ImagePainter::OnPaintLayer(gfx::Canvas* canvas) {
- if (!clip_rect_.IsEmpty())
- canvas->ClipRect(clip_rect_);
- canvas->DrawImageInt(*(image_->ToImageSkia()), 0, 0);
-}
-
-void ImageGrid::ImagePainter::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- // Redrawing will take care of scale factor change.
-}
-
-base::Closure ImageGrid::ImagePainter::PrepareForLayerBoundsChange() {
- return base::Closure();
-}
-
-// static
-gfx::Size ImageGrid::GetImageSize(const gfx::Image* image) {
- return image ?
- gfx::Size(image->ToImageSkia()->width(), image->ToImageSkia()->height()) :
- gfx::Size();
-}
-
-// static
-bool ImageGrid::LayerExceedsSize(const ui::Layer* layer,
- const gfx::Size& size) {
- return layer->bounds().width() > size.width() ||
- layer->bounds().height() > size.height();
-}
-
-void ImageGrid::SetImage(const gfx::Image* image,
- scoped_ptr<ui::Layer>* layer_ptr,
- scoped_ptr<ImagePainter>* painter_ptr) {
- // Clean out old layers and painters.
- if (layer_ptr->get())
- layer_->Remove(layer_ptr->get());
- layer_ptr->reset();
- painter_ptr->reset();
-
- // If we're not using an image, we're done.
- if (!image)
- return;
-
- // Set up the new layer and painter.
- layer_ptr->reset(new ui::Layer(ui::LAYER_TEXTURED));
-
- const gfx::Size size = GetImageSize(image);
- layer_ptr->get()->SetBounds(gfx::Rect(0, 0, size.width(), size.height()));
-
- painter_ptr->reset(new ImagePainter(image));
- layer_ptr->get()->set_delegate(painter_ptr->get());
- layer_ptr->get()->SetFillsBoundsOpaquely(false);
- layer_ptr->get()->SetVisible(true);
- layer_->Add(layer_ptr->get());
-}
-
-void ImageGrid::ScaleWidth(gfx::Size center,
- ui::Layer* layer,
- gfx::Transform& transform) {
- int layer_width = ConvertSizeToPixel(layer,
- layer->bounds().size()).width();
- float scale = static_cast<float>(center.width()) / layer_width;
- transform.Scale(scale, 1.0);
-}
-
-void ImageGrid::ScaleHeight(gfx::Size center,
- ui::Layer* layer,
- gfx::Transform& transform) {
- int layer_height = ConvertSizeToPixel(layer,
- layer->bounds().size()).height();
- float scale = static_cast<float>(center.height()) / layer_height;
- transform.Scale(1.0, scale);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/image_grid.h b/chromium/ui/views/corewm/image_grid.h
deleted file mode 100644
index 51b1b56ee62..00000000000
--- a/chromium/ui/views/corewm/image_grid.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_IMAGE_GRID_H_
-#define UI_VIEWS_COREWM_IMAGE_GRID_H_
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_delegate.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
-#include "ui/views/views_export.h"
-
-namespace gfx {
-class Image;
-} // namespace gfx
-
-namespace views {
-namespace corewm {
-
-// An ImageGrid is a 3x3 array of ui::Layers, each containing an image.
-//
-// As the grid is resized, its images fill the requested space:
-// - corner images are not scaled
-// - top and bottom images are scaled horizontally
-// - left and right images are scaled vertically
-// - the center image is scaled in both directions
-//
-// If one of the non-center images is smaller than the largest images in its
-// row or column, it will be aligned with the outside of the grid. For
-// example, given 4x4 top-left and top-right images and a 1x2 top images:
-//
-// +--------+---------------------+--------+
-// | | top | |
-// | top- +---------------------+ top- +
-// | left | | right |
-// +----+---+ +---+----+
-// | | | |
-// ...
-//
-// This may seem odd at first, but it lets ImageGrid be used to draw shadows
-// with curved corners that extend inwards beyond a window's borders. In the
-// below example, the top-left corner image is overlaid on top of the window's
-// top-left corner:
-//
-// +---------+-----------------------
-// | ..xxx|XXXXXXXXXXXXXXXXXX
-// | .xXXXXX|XXXXXXXXXXXXXXXXXX_____
-// | .xXX | ^ window's top edge
-// | .xXX |
-// +---------+
-// | xXX|
-// | xXX|< window's left edge
-// | xXX|
-// ...
-//
-class VIEWS_EXPORT ImageGrid {
- public:
- // Helper class for use by tests.
- class VIEWS_EXPORT TestAPI {
- public:
- TestAPI(ImageGrid* grid) : grid_(grid) {}
-
- gfx::Rect top_left_clip_rect() const {
- return grid_->top_left_painter_->clip_rect_;
- }
- gfx::Rect top_right_clip_rect() const {
- return grid_->top_right_painter_->clip_rect_;
- }
- gfx::Rect bottom_left_clip_rect() const {
- return grid_->bottom_left_painter_->clip_rect_;
- }
- gfx::Rect bottom_right_clip_rect() const {
- return grid_->bottom_right_painter_->clip_rect_;
- }
-
- // Returns |layer|'s bounds after applying the layer's current transform.
- gfx::RectF GetTransformedLayerBounds(const ui::Layer& layer);
-
- private:
- ImageGrid* grid_; // not owned
-
- DISALLOW_COPY_AND_ASSIGN(TestAPI);
- };
-
- ImageGrid();
- ~ImageGrid();
-
- ui::Layer* layer() { return layer_.get(); }
- int top_image_height() const { return top_image_height_; }
- int bottom_image_height() const { return bottom_image_height_; }
- int left_image_width() const { return left_image_width_; }
- int right_image_width() const { return right_image_width_; }
-
- // Visible to allow independent layer animations and for testing.
- ui::Layer* top_left_layer() const { return top_left_layer_.get(); }
- ui::Layer* top_layer() const { return top_layer_.get(); }
- ui::Layer* top_right_layer() const { return top_right_layer_.get(); }
- ui::Layer* left_layer() const { return left_layer_.get(); }
- ui::Layer* center_layer() const { return center_layer_.get(); }
- ui::Layer* right_layer() const { return right_layer_.get(); }
- ui::Layer* bottom_left_layer() const { return bottom_left_layer_.get(); }
- ui::Layer* bottom_layer() const { return bottom_layer_.get(); }
- ui::Layer* bottom_right_layer() const { return bottom_right_layer_.get(); }
-
- // Sets the grid to display the passed-in images (any of which can be NULL).
- // Ownership of the images remains with the caller. May be called more than
- // once to switch images.
- void SetImages(const gfx::Image* top_left_image,
- const gfx::Image* top_image,
- const gfx::Image* top_right_image,
- const gfx::Image* left_image,
- const gfx::Image* center_image,
- const gfx::Image* right_image,
- const gfx::Image* bottom_left_image,
- const gfx::Image* bottom_image,
- const gfx::Image* bottom_right_image);
-
- void SetSize(const gfx::Size& size);
-
- // Sets the grid to a position and size such that the inner edges of the top,
- // bottom, left and right images will be flush with |content_bounds_in_dip|.
- void SetContentBounds(const gfx::Rect& content_bounds_in_dip);
-
- private:
- // Delegate responsible for painting a specific image on a layer.
- class ImagePainter : public ui::LayerDelegate {
- public:
- ImagePainter(const gfx::Image* image) : image_(image) {}
- virtual ~ImagePainter() {}
-
- // Clips |layer| to |clip_rect|. Triggers a repaint if the clipping
- // rectangle has changed. An empty rectangle disables clipping.
- void SetClipRect(const gfx::Rect& clip_rect, ui::Layer* layer);
-
- // ui::LayerDelegate implementation:
- virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE;
-
- private:
- friend class TestAPI;
-
- const gfx::Image* image_; // not owned
-
- gfx::Rect clip_rect_;
-
- DISALLOW_COPY_AND_ASSIGN(ImagePainter);
- };
-
- // Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise.
- static gfx::Size GetImageSize(const gfx::Image* image);
-
- // Returns true if |layer|'s bounds don't fit within |size|.
- static bool LayerExceedsSize(const ui::Layer* layer, const gfx::Size& size);
-
- // Sets |layer_ptr| and |painter_ptr| to display |image| and adds the
- // passed-in layer to |layer_|. If image is NULL resets |layer_ptr| and
- // |painter_ptr| and removes any existing layer from |layer_|.
- void SetImage(const gfx::Image* image,
- scoped_ptr<ui::Layer>* layer_ptr,
- scoped_ptr<ImagePainter>* painter_ptr);
-
- // Sets the scaling for the transform applied to a layer. The left, top,
- // right and bottom layers are stretched to the height or width of the
- // center image.
- void ScaleWidth(gfx::Size center,
- ui::Layer* layer,
- gfx::Transform& transform);
- void ScaleHeight(gfx::Size center,
- ui::Layer* layer,
- gfx::Transform& transform);
-
- // Layer that contains all of the image layers.
- scoped_ptr<ui::Layer> layer_;
-
- // The grid's dimensions.
- gfx::Size size_;
-
- // Heights and widths of the images displayed by |top_layer_|,
- // |bottom_layer_|, |left_layer_|, and |right_layer_|.
- int top_image_height_;
- int bottom_image_height_;
- int left_image_width_;
- int right_image_width_;
-
- // Heights of the tallest images in the top and bottom rows and the widest
- // images in the left and right columns. Note that we may have less actual
- // space than this available if the images are large and |size_| is small.
- int base_top_row_height_;
- int base_bottom_row_height_;
- int base_left_column_width_;
- int base_right_column_width_;
-
- // Layers used to display the various images. Children of |layer_|.
- // Positions for which no images were supplied are NULL.
- scoped_ptr<ui::Layer> top_left_layer_;
- scoped_ptr<ui::Layer> top_layer_;
- scoped_ptr<ui::Layer> top_right_layer_;
- scoped_ptr<ui::Layer> left_layer_;
- scoped_ptr<ui::Layer> center_layer_;
- scoped_ptr<ui::Layer> right_layer_;
- scoped_ptr<ui::Layer> bottom_left_layer_;
- scoped_ptr<ui::Layer> bottom_layer_;
- scoped_ptr<ui::Layer> bottom_right_layer_;
-
- // Delegates responsible for painting the above layers.
- // Positions for which no images were supplied are NULL.
- scoped_ptr<ImagePainter> top_left_painter_;
- scoped_ptr<ImagePainter> top_painter_;
- scoped_ptr<ImagePainter> top_right_painter_;
- scoped_ptr<ImagePainter> left_painter_;
- scoped_ptr<ImagePainter> center_painter_;
- scoped_ptr<ImagePainter> right_painter_;
- scoped_ptr<ImagePainter> bottom_left_painter_;
- scoped_ptr<ImagePainter> bottom_painter_;
- scoped_ptr<ImagePainter> bottom_right_painter_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageGrid);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_IMAGE_GRID_H_
diff --git a/chromium/ui/views/corewm/image_grid_unittest.cc b/chromium/ui/views/corewm/image_grid_unittest.cc
deleted file mode 100644
index 4b5508d733d..00000000000
--- a/chromium/ui/views/corewm/image_grid_unittest.cc
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/views/test/views_test_base.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia.h"
-#include "ui/views/corewm/image_grid.h"
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-// Creates a gfx::Image with the requested dimensions.
-gfx::Image* CreateImage(const gfx::Size& size) {
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- return new gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
-}
-
-} // namespace
-
-typedef ViewsTestBase ImageGridTest;
-
-// Test that an ImageGrid's layers are transformed correctly when SetSize() is
-// called.
-TEST_F(ImageGridTest, Basic) {
- // Size of the images around the grid's border.
- const int kBorder = 2;
-
- scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1)));
- scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder)));
- scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1)));
- scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder)));
-
- ImageGrid grid;
- grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(),
- image_Bx1.get(), image_1x1.get(), image_Bx1.get(),
- image_BxB.get(), image_1xB.get(), image_BxB.get());
-
- ImageGrid::TestAPI test_api(&grid);
- ASSERT_TRUE(grid.top_left_layer() != NULL);
- ASSERT_TRUE(grid.top_layer() != NULL);
- ASSERT_TRUE(grid.top_right_layer() != NULL);
- ASSERT_TRUE(grid.left_layer() != NULL);
- ASSERT_TRUE(grid.center_layer() != NULL);
- ASSERT_TRUE(grid.right_layer() != NULL);
- ASSERT_TRUE(grid.bottom_left_layer() != NULL);
- ASSERT_TRUE(grid.bottom_layer() != NULL);
- ASSERT_TRUE(grid.bottom_right_layer() != NULL);
-
- const gfx::Size size(20, 30);
- grid.SetSize(size);
-
- // The top-left layer should be flush with the top-left corner and unscaled.
- EXPECT_EQ(gfx::RectF(0, 0, kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.top_left_layer()).ToString());
-
- // The top layer should be flush with the top edge and stretched horizontally
- // between the two top corners.
- EXPECT_EQ(gfx::RectF(
- kBorder, 0, size.width() - 2 * kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.top_layer()).ToString());
-
- // The top-right layer should be flush with the top-right corner and unscaled.
- EXPECT_EQ(gfx::RectF(size.width() - kBorder, 0, kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.top_right_layer()).ToString());
-
- // The left layer should be flush with the left edge and stretched vertically
- // between the two left corners.
- EXPECT_EQ(gfx::RectF(
- 0, kBorder, kBorder, size.height() - 2 * kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.left_layer()).ToString());
-
- // The center layer should fill the space in the middle of the grid.
- EXPECT_EQ(gfx::RectF(
- kBorder, kBorder, size.width() - 2 * kBorder,
- size.height() - 2 * kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.center_layer()).ToString());
-
- // The right layer should be flush with the right edge and stretched
- // vertically between the two right corners.
- EXPECT_EQ(gfx::RectF(
- size.width() - kBorder, kBorder,
- kBorder, size.height() - 2 * kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.right_layer()).ToString());
-
- // The bottom-left layer should be flush with the bottom-left corner and
- // unscaled.
- EXPECT_EQ(gfx::RectF(0, size.height() - kBorder, kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.bottom_left_layer()).ToString());
-
- // The bottom layer should be flush with the bottom edge and stretched
- // horizontally between the two bottom corners.
- EXPECT_EQ(gfx::RectF(
- kBorder, size.height() - kBorder,
- size.width() - 2 * kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.bottom_layer()).ToString());
-
- // The bottom-right layer should be flush with the bottom-right corner and
- // unscaled.
- EXPECT_EQ(gfx::RectF(
- size.width() - kBorder, size.height() - kBorder,
- kBorder, kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.bottom_right_layer()).ToString());
-}
-
-// Test that an ImageGrid's layers are transformed correctly when
-// SetContentBounds() is called.
-TEST_F(ImageGridTest, SetContentBounds) {
- // Size of the images around the grid's border.
- const int kBorder = 2;
-
- scoped_ptr<gfx::Image> image_1x1(CreateImage(gfx::Size(1, 1)));
- scoped_ptr<gfx::Image> image_1xB(CreateImage(gfx::Size(1, kBorder)));
- scoped_ptr<gfx::Image> image_Bx1(CreateImage(gfx::Size(kBorder, 1)));
- scoped_ptr<gfx::Image> image_BxB(CreateImage(gfx::Size(kBorder, kBorder)));
-
- ImageGrid grid;
- grid.SetImages(image_BxB.get(), image_1xB.get(), image_BxB.get(),
- image_Bx1.get(), image_1x1.get(), image_Bx1.get(),
- image_BxB.get(), image_1xB.get(), image_BxB.get());
-
- ImageGrid::TestAPI test_api(&grid);
-
- const gfx::Point origin(5, 10);
- const gfx::Size size(20, 30);
- grid.SetContentBounds(gfx::Rect(origin, size));
-
- // The master layer is positioned above the top-left corner of the content
- // bounds and has height/width that contain the grid and bounds.
- EXPECT_EQ(gfx::RectF(origin.x() - kBorder,
- origin.y() - kBorder,
- size.width() + 2 * kBorder,
- size.height() + 2 * kBorder).ToString(),
- test_api.GetTransformedLayerBounds(*grid.layer()).ToString());
-}
-
-// Check that we don't crash if only a single image is supplied.
-TEST_F(ImageGridTest, SingleImage) {
- const int kBorder = 1;
- scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder)));
-
- ImageGrid grid;
- grid.SetImages(NULL, image.get(), NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL);
-
- ImageGrid::TestAPI test_api(&grid);
- EXPECT_TRUE(grid.top_left_layer() == NULL);
- ASSERT_TRUE(grid.top_layer() != NULL);
- EXPECT_TRUE(grid.top_right_layer() == NULL);
- EXPECT_TRUE(grid.left_layer() == NULL);
- EXPECT_TRUE(grid.center_layer() == NULL);
- EXPECT_TRUE(grid.right_layer() == NULL);
- EXPECT_TRUE(grid.bottom_left_layer() == NULL);
- EXPECT_TRUE(grid.bottom_layer() == NULL);
- EXPECT_TRUE(grid.bottom_right_layer() == NULL);
-
- const gfx::Size kSize(10, 10);
- grid.SetSize(kSize);
-
- // The top layer should be scaled horizontally across the entire width, but it
- // shouldn't be scaled vertically.
- EXPECT_EQ(gfx::RectF(0, 0, kSize.width(), kBorder).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.top_layer()).ToString());
-}
-
-// Check that we don't crash when we reset existing images to NULL and
-// reset NULL images to new ones.
-TEST_F(ImageGridTest, ResetImages) {
- const int kBorder = 1;
- scoped_ptr<gfx::Image> image(CreateImage(gfx::Size(kBorder, kBorder)));
-
- ImageGrid grid;
- grid.SetImages(NULL, image.get(), NULL,
- NULL, NULL, NULL,
- NULL, NULL, NULL);
-
- // Only the top edge has a layer.
- ImageGrid::TestAPI test_api(&grid);
- ASSERT_TRUE(grid.top_left_layer() == NULL);
- ASSERT_FALSE(grid.top_layer() == NULL);
- ASSERT_TRUE(grid.top_right_layer() == NULL);
- ASSERT_TRUE(grid.left_layer() == NULL);
- ASSERT_TRUE(grid.center_layer() == NULL);
- ASSERT_TRUE(grid.right_layer() == NULL);
- ASSERT_TRUE(grid.bottom_left_layer() == NULL);
- ASSERT_TRUE(grid.bottom_layer() == NULL);
- ASSERT_TRUE(grid.bottom_right_layer() == NULL);
-
- grid.SetImages(NULL, NULL, NULL,
- NULL, NULL, NULL,
- NULL, image.get(), NULL);
-
- // Now only the bottom edge has a layer.
- ASSERT_TRUE(grid.top_left_layer() == NULL);
- ASSERT_TRUE(grid.top_layer() == NULL);
- ASSERT_TRUE(grid.top_right_layer() == NULL);
- ASSERT_TRUE(grid.left_layer() == NULL);
- ASSERT_TRUE(grid.center_layer() == NULL);
- ASSERT_TRUE(grid.right_layer() == NULL);
- ASSERT_TRUE(grid.bottom_left_layer() == NULL);
- ASSERT_FALSE(grid.bottom_layer() == NULL);
- ASSERT_TRUE(grid.bottom_right_layer() == NULL);
-}
-
-// Test that side (top, left, right, bottom) layers that are narrower than their
-// adjacent corner layers stay pinned to the outside edges instead of getting
-// moved inwards or scaled. This exercises the scenario used for shadows.
-TEST_F(ImageGridTest, SmallerSides) {
- const int kCorner = 2;
- const int kEdge = 1;
-
- scoped_ptr<gfx::Image> top_left_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
- scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> top_right_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
- scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge)));
-
- ImageGrid grid;
- grid.SetImages(top_left_image.get(), top_image.get(), top_right_image.get(),
- left_image.get(), NULL, right_image.get(),
- NULL, NULL, NULL);
- ImageGrid::TestAPI test_api(&grid);
-
- const gfx::Size kSize(20, 30);
- grid.SetSize(kSize);
-
- // The top layer should be flush with the top edge and stretched horizontally
- // between the two top corners.
- EXPECT_EQ(gfx::RectF(
- kCorner, 0, kSize.width() - 2 * kCorner, kEdge).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.top_layer()).ToString());
-
- // The left layer should be flush with the left edge and stretched vertically
- // between the top left corner and the bottom.
- EXPECT_EQ(gfx::RectF(
- 0, kCorner, kEdge, kSize.height() - kCorner).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.left_layer()).ToString());
-
- // The right layer should be flush with the right edge and stretched
- // vertically between the top right corner and the bottom.
- EXPECT_EQ(gfx::RectF(
- kSize.width() - kEdge, kCorner,
- kEdge, kSize.height() - kCorner).ToString(),
- test_api.GetTransformedLayerBounds(
- *grid.right_layer()).ToString());
-}
-
-// Test that we hide or clip layers as needed when the grid is assigned a small
-// size.
-TEST_F(ImageGridTest, TooSmall) {
- const int kCorner = 5;
- const int kCenter = 3;
- const int kEdge = 3;
-
- scoped_ptr<gfx::Image> top_left_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
- scoped_ptr<gfx::Image> top_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> top_right_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
- scoped_ptr<gfx::Image> left_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> center_image(CreateImage(gfx::Size(kCenter, kCenter)));
- scoped_ptr<gfx::Image> right_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> bottom_left_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
- scoped_ptr<gfx::Image> bottom_image(CreateImage(gfx::Size(kEdge, kEdge)));
- scoped_ptr<gfx::Image> bottom_right_image(
- CreateImage(gfx::Size(kCorner, kCorner)));
-
- ImageGrid grid;
- grid.SetImages(
- top_left_image.get(), top_image.get(), top_right_image.get(),
- left_image.get(), center_image.get(), right_image.get(),
- bottom_left_image.get(), bottom_image.get(), bottom_right_image.get());
- ImageGrid::TestAPI test_api(&grid);
-
- // Set a size that's smaller than the combined (unscaled) corner images.
- const gfx::Size kSmallSize(kCorner + kCorner - 3, kCorner + kCorner - 5);
- grid.SetSize(kSmallSize);
-
- // The scalable images around the sides and in the center should be hidden.
- EXPECT_FALSE(grid.top_layer()->visible());
- EXPECT_FALSE(grid.bottom_layer()->visible());
- EXPECT_FALSE(grid.left_layer()->visible());
- EXPECT_FALSE(grid.right_layer()->visible());
- EXPECT_FALSE(grid.center_layer()->visible());
-
- // The corner images' clip rects should sum to the expected size.
- EXPECT_EQ(kSmallSize.width(),
- test_api.top_left_clip_rect().width() +
- test_api.top_right_clip_rect().width());
- EXPECT_EQ(kSmallSize.width(),
- test_api.bottom_left_clip_rect().width() +
- test_api.bottom_right_clip_rect().width());
- EXPECT_EQ(kSmallSize.height(),
- test_api.top_left_clip_rect().height() +
- test_api.bottom_left_clip_rect().height());
- EXPECT_EQ(kSmallSize.height(),
- test_api.top_right_clip_rect().height() +
- test_api.bottom_right_clip_rect().height());
-
- // Resize the grid to be large enough to show all images.
- const gfx::Size kLargeSize(kCorner + kCorner + kCenter,
- kCorner + kCorner + kCenter);
- grid.SetSize(kLargeSize);
-
- // The scalable images should be visible now.
- EXPECT_TRUE(grid.top_layer()->visible());
- EXPECT_TRUE(grid.bottom_layer()->visible());
- EXPECT_TRUE(grid.left_layer()->visible());
- EXPECT_TRUE(grid.right_layer()->visible());
- EXPECT_TRUE(grid.center_layer()->visible());
-
- // We shouldn't be clipping the corner images anymore.
- EXPECT_TRUE(test_api.top_left_clip_rect().IsEmpty());
- EXPECT_TRUE(test_api.top_right_clip_rect().IsEmpty());
- EXPECT_TRUE(test_api.bottom_left_clip_rect().IsEmpty());
- EXPECT_TRUE(test_api.bottom_right_clip_rect().IsEmpty());
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/input_method_event_filter.cc b/chromium/ui/views/corewm/input_method_event_filter.cc
deleted file mode 100644
index 8e9ead8e1d9..00000000000
--- a/chromium/ui/views/corewm/input_method_event_filter.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/input_method_event_filter.h"
-
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/root_window.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_factory.h"
-#include "ui/events/event.h"
-
-namespace views {
-namespace corewm {
-
-////////////////////////////////////////////////////////////////////////////////
-// InputMethodEventFilter, public:
-
-InputMethodEventFilter::InputMethodEventFilter(gfx::AcceleratedWidget widget)
- : input_method_(ui::CreateInputMethod(this, widget)),
- target_dispatcher_(NULL) {
- // TODO(yusukes): Check if the root window is currently focused and pass the
- // result to Init().
- input_method_->Init(true);
-}
-
-InputMethodEventFilter::~InputMethodEventFilter() {
-}
-
-void InputMethodEventFilter::SetInputMethodPropertyInRootWindow(
- aura::Window* root_window) {
- root_window->SetProperty(aura::client::kRootWindowInputMethodKey,
- input_method_.get());
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// InputMethodEventFilter, EventFilter implementation:
-
-void InputMethodEventFilter::OnKeyEvent(ui::KeyEvent* event) {
- const ui::EventType type = event->type();
- if (type == ui::ET_TRANSLATED_KEY_PRESS ||
- type == ui::ET_TRANSLATED_KEY_RELEASE) {
- // The |event| is already handled by this object, change the type of the
- // event to ui::ET_KEY_* and pass it to the next filter.
- static_cast<ui::TranslatedKeyEvent*>(event)->ConvertToKeyEvent();
- } else {
- // If the focused window is changed, all requests to IME will be
- // discarded so it's safe to update the target_dispatcher_ here.
- aura::Window* target = static_cast<aura::Window*>(event->target());
- target_dispatcher_ = target->GetRootWindow()->GetDispatcher();
- DCHECK(target_dispatcher_);
- if (input_method_->DispatchKeyEvent(*event))
- event->StopPropagation();
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// InputMethodEventFilter, ui::InputMethodDelegate implementation:
-
-bool InputMethodEventFilter::DispatchKeyEventPostIME(
- const base::NativeEvent& event) {
-#if defined(OS_WIN)
- DCHECK(event.message != WM_CHAR);
-#endif
- ui::TranslatedKeyEvent aura_event(event, false /* is_char */);
- return target_dispatcher_->AsRootWindowHostDelegate()->OnHostKeyEvent(
- &aura_event);
-}
-
-bool InputMethodEventFilter::DispatchFabricatedKeyEventPostIME(
- ui::EventType type,
- ui::KeyboardCode key_code,
- int flags) {
- ui::TranslatedKeyEvent aura_event(type == ui::ET_KEY_PRESSED, key_code,
- flags);
- return target_dispatcher_->AsRootWindowHostDelegate()->OnHostKeyEvent(
- &aura_event);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/input_method_event_filter.h b/chromium/ui/views/corewm/input_method_event_filter.h
deleted file mode 100644
index 902244c8865..00000000000
--- a/chromium/ui/views/corewm/input_method_event_filter.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_
-#define UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/aura/window.h"
-#include "ui/base/ime/input_method_delegate.h"
-#include "ui/events/event_handler.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/views/views_export.h"
-
-namespace ui {
-class InputMethod;
-}
-
-namespace views {
-namespace corewm {
-
-// An event filter that forwards a KeyEvent to a system IME, and dispatches a
-// TranslatedKeyEvent to the root window as needed.
-class VIEWS_EXPORT InputMethodEventFilter
- : public ui::EventHandler,
- public ui::internal::InputMethodDelegate {
- public:
- explicit InputMethodEventFilter(gfx::AcceleratedWidget widget);
- virtual ~InputMethodEventFilter();
-
- void SetInputMethodPropertyInRootWindow(aura::Window* root_window);
-
- ui::InputMethod* input_method() const { return input_method_.get(); }
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
-
- // Overridden from ui::internal::InputMethodDelegate.
- virtual bool DispatchKeyEventPostIME(const base::NativeEvent& event) OVERRIDE;
- virtual bool DispatchFabricatedKeyEventPostIME(ui::EventType type,
- ui::KeyboardCode key_code,
- int flags) OVERRIDE;
-
- scoped_ptr<ui::InputMethod> input_method_;
-
- // The target dispatcher that will receive translated key events from the IME.
- aura::WindowEventDispatcher* target_dispatcher_;
-
- DISALLOW_COPY_AND_ASSIGN(InputMethodEventFilter);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_INPUT_METHOD_EVENT_FILTER_H_
diff --git a/chromium/ui/views/corewm/input_method_event_filter_unittest.cc b/chromium/ui/views/corewm/input_method_event_filter_unittest.cc
deleted file mode 100644
index 2c95dc44e82..00000000000
--- a/chromium/ui/views/corewm/input_method_event_filter_unittest.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/input_method_event_filter.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/root_window.h"
-#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/test/test_event_handler.h"
-#include "ui/aura/test/test_windows.h"
-
-#if !defined(OS_WIN) && !defined(USE_X11)
-// On platforms except Windows and X11, aura::test::EventGenerator::PressKey
-// generates a key event without native_event(), which is not supported by
-// ui::MockInputMethod.
-#define TestInputMethodKeyEventPropagation \
-DISABLED_TestInputMethodKeyEventPropagation
-#endif
-
-namespace views {
-namespace corewm {
-
-typedef aura::test::AuraTestBase InputMethodEventFilterTest;
-
-TEST_F(InputMethodEventFilterTest, TestInputMethodProperty) {
- CompoundEventFilter* root_filter = new CompoundEventFilter;
- root_window()->SetEventFilter(root_filter);
-
- InputMethodEventFilter input_method_event_filter(
- dispatcher()->host()->GetAcceleratedWidget());
- root_filter->AddHandler(&input_method_event_filter);
-
- // Tests if InputMethodEventFilter adds a window property on its
- // construction.
- EXPECT_TRUE(root_window()->GetProperty(
- aura::client::kRootWindowInputMethodKey));
-
- root_filter->RemoveHandler(&input_method_event_filter);
-}
-
-// Tests if InputMethodEventFilter dispatches a ui::ET_TRANSLATED_KEY_* event to
-// the root window.
-TEST_F(InputMethodEventFilterTest, TestInputMethodKeyEventPropagation) {
- CompoundEventFilter* root_filter = new CompoundEventFilter;
- root_window()->SetEventFilter(root_filter);
-
- // Add the InputMethodEventFilter before the TestEventFilter.
- InputMethodEventFilter input_method_event_filter(
- dispatcher()->host()->GetAcceleratedWidget());
- root_filter->AddHandler(&input_method_event_filter);
-
- // Add TestEventFilter to the RootWindow.
- aura::test::TestEventHandler test_filter;
- root_filter->AddHandler(&test_filter);
-
- // We need an active window. Otherwise, the root window will not forward a key
- // event to event filters.
- aura::test::TestWindowDelegate test_delegate;
- scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate(
- &test_delegate,
- -1,
- gfx::Rect(),
- root_window()));
- aura::client::GetActivationClient(root_window())->ActivateWindow(
- window.get());
-
- // Send a fake key event to the root window. InputMethodEventFilter, which is
- // automatically set up by AshTestBase, consumes it and sends a new
- // ui::ET_TRANSLATED_KEY_* event to the root window, which will be consumed by
- // the test event filter.
- aura::test::EventGenerator generator(root_window());
- EXPECT_EQ(0, test_filter.num_key_events());
- generator.PressKey(ui::VKEY_SPACE, 0);
- EXPECT_EQ(1, test_filter.num_key_events());
- generator.ReleaseKey(ui::VKEY_SPACE, 0);
- EXPECT_EQ(2, test_filter.num_key_events());
-
- root_filter->RemoveHandler(&input_method_event_filter);
- root_filter->RemoveHandler(&test_filter);
-
- // Reset window before |test_delegate| gets deleted.
- window.reset();
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/native_cursor_manager.h b/chromium/ui/views/corewm/native_cursor_manager.h
deleted file mode 100644
index 75e4c8580a5..00000000000
--- a/chromium/ui/views/corewm/native_cursor_manager.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_
-#define UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_
-
-#include "base/strings/string16.h"
-#include "ui/views/corewm/native_cursor_manager_delegate.h"
-#include "ui/views/views_export.h"
-
-namespace gfx {
-class Display;
-}
-
-namespace views {
-namespace corewm {
-
-// Interface where platforms such as Ash or Desktop aura are notified of
-// requested changes to cursor state. When requested, implementer should tell
-// the CursorManager of any actual state changes performed through the
-// delegate.
-class VIEWS_EXPORT NativeCursorManager {
- public:
- virtual ~NativeCursorManager() {}
-
- // A request to set the screen DPI. Can cause changes in the current cursor.
- virtual void SetDisplay(
- const gfx::Display& display,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-
- // A request to set the cursor to |cursor|. At minimum, implementer should
- // call NativeCursorManagerDelegate::CommitCursor() with whatever cursor is
- // actually used.
- virtual void SetCursor(
- gfx::NativeCursor cursor,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-
- // A request to set the visibility of the cursor. At minimum, implementer
- // should call NativeCursorManagerDelegate::CommitVisibility() with whatever
- // the visibility is.
- virtual void SetVisibility(
- bool visible,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-
- // A request to set the scale of the cursor icon.
- virtual void SetScale(
- float scale,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-
- // A request to set the scale of the cursor icon.
- virtual void SetCursorSet(
- ui::CursorSetType cursor_set,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-
- // A request to set whether mouse events are disabled. At minimum,
- // implementer should call NativeCursorManagerDelegate::
- // CommitMouseEventsEnabled() with whether mouse events are actually enabled.
- virtual void SetMouseEventsEnabled(
- bool enabled,
- views::corewm::NativeCursorManagerDelegate* delegate) = 0;
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_H_
diff --git a/chromium/ui/views/corewm/native_cursor_manager_delegate.h b/chromium/ui/views/corewm/native_cursor_manager_delegate.h
deleted file mode 100644
index 491ab47b1b4..00000000000
--- a/chromium/ui/views/corewm/native_cursor_manager_delegate.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_
-#define UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_
-
-#include "ui/base/cursor/cursor.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-
-// The non-public interface that CursorManager exposes to its users. This
-// gives accessors to all the current state, and mutators to all the current
-// state.
-class VIEWS_EXPORT NativeCursorManagerDelegate {
- public:
- virtual ~NativeCursorManagerDelegate() {}
-
- // TODO(tdanderson): Possibly remove this interface.
- virtual gfx::NativeCursor GetCursor() const = 0;
- virtual bool IsCursorVisible() const = 0;
-
- virtual void CommitCursor(gfx::NativeCursor cursor) = 0;
- virtual void CommitVisibility(bool visible) = 0;
- virtual void CommitScale(float scale) = 0;
- virtual void CommitCursorSet(ui::CursorSetType cursor_set) = 0;
- virtual void CommitMouseEventsEnabled(bool enabled) = 0;
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_NATIVE_CURSOR_MANAGER_DELEGATE_H_
diff --git a/chromium/ui/views/corewm/shadow.cc b/chromium/ui/views/corewm/shadow.cc
deleted file mode 100644
index 4411c8d5637..00000000000
--- a/chromium/ui/views/corewm/shadow.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/shadow.h"
-
-#include "grit/ui_resources.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/views/corewm/image_grid.h"
-
-namespace {
-
-// Shadow opacity for different styles.
-const float kActiveShadowOpacity = 1.0f;
-const float kInactiveShadowOpacity = 0.2f;
-const float kSmallShadowOpacity = 1.0f;
-
-// Interior inset for different styles.
-const int kActiveInteriorInset = 0;
-const int kInactiveInteriorInset = 0;
-const int kSmallInteriorInset = 5;
-
-// Duration for opacity animation in milliseconds.
-const int kShadowAnimationDurationMs = 100;
-
-float GetOpacityForStyle(views::corewm::Shadow::Style style) {
- switch (style) {
- case views::corewm::Shadow::STYLE_ACTIVE:
- return kActiveShadowOpacity;
- case views::corewm::Shadow::STYLE_INACTIVE:
- return kInactiveShadowOpacity;
- case views::corewm::Shadow::STYLE_SMALL:
- return kSmallShadowOpacity;
- }
- return 1.0f;
-}
-
-int GetInteriorInsetForStyle(views::corewm::Shadow::Style style) {
- switch (style) {
- case views::corewm::Shadow::STYLE_ACTIVE:
- return kActiveInteriorInset;
- case views::corewm::Shadow::STYLE_INACTIVE:
- return kInactiveInteriorInset;
- case views::corewm::Shadow::STYLE_SMALL:
- return kSmallInteriorInset;
- }
- return 0;
-}
-
-} // namespace
-
-namespace views {
-namespace corewm {
-
-Shadow::Shadow() : style_(STYLE_ACTIVE), interior_inset_(0) {
-}
-
-Shadow::~Shadow() {
-}
-
-void Shadow::Init(Style style) {
- style_ = style;
- image_grid_.reset(new ImageGrid);
- UpdateImagesForStyle();
- image_grid_->layer()->set_name("Shadow");
- image_grid_->layer()->SetOpacity(GetOpacityForStyle(style_));
-}
-
-void Shadow::SetContentBounds(const gfx::Rect& content_bounds) {
- content_bounds_ = content_bounds;
- UpdateImageGridBounds();
-}
-
-ui::Layer* Shadow::layer() const {
- return image_grid_->layer();
-}
-
-void Shadow::SetStyle(Style style) {
- if (style_ == style)
- return;
-
- Style old_style = style_;
- style_ = style;
-
- // Stop waiting for any as yet unfinished implicit animations.
- StopObservingImplicitAnimations();
-
- // If we're switching to or from the small style, don't bother with
- // animations.
- if (style == STYLE_SMALL || old_style == STYLE_SMALL) {
- UpdateImagesForStyle();
- image_grid_->layer()->SetOpacity(GetOpacityForStyle(style));
- return;
- }
-
- // If we're becoming active, switch images now. Because the inactive image
- // has a very low opacity the switch isn't noticeable and this approach
- // allows us to use only a single set of shadow images at a time.
- if (style == STYLE_ACTIVE) {
- UpdateImagesForStyle();
- // Opacity was baked into inactive image, start opacity low to match.
- image_grid_->layer()->SetOpacity(kInactiveShadowOpacity);
- }
-
- {
- // Property sets within this scope will be implicitly animated.
- ui::ScopedLayerAnimationSettings settings(layer()->GetAnimator());
- settings.AddObserver(this);
- settings.SetTransitionDuration(
- base::TimeDelta::FromMilliseconds(kShadowAnimationDurationMs));
- switch (style_) {
- case STYLE_ACTIVE:
- image_grid_->layer()->SetOpacity(kActiveShadowOpacity);
- break;
- case STYLE_INACTIVE:
- image_grid_->layer()->SetOpacity(kInactiveShadowOpacity);
- break;
- default:
- NOTREACHED() << "Unhandled style " << style_;
- break;
- }
- }
-}
-
-void Shadow::OnImplicitAnimationsCompleted() {
- // If we just finished going inactive, switch images. This doesn't cause
- // a visual pop because the inactive image opacity is so low.
- if (style_ == STYLE_INACTIVE) {
- UpdateImagesForStyle();
- // Opacity is baked into inactive image, so set fully opaque.
- image_grid_->layer()->SetOpacity(1.0f);
- }
-}
-
-void Shadow::UpdateImagesForStyle() {
- ResourceBundle& res = ResourceBundle::GetSharedInstance();
- switch (style_) {
- case STYLE_ACTIVE:
- image_grid_->SetImages(
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_LEFT),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_TOP_RIGHT),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_LEFT),
- NULL,
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_RIGHT),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_LEFT),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM),
- &res.GetImageNamed(IDR_AURA_SHADOW_ACTIVE_BOTTOM_RIGHT));
- break;
- case STYLE_INACTIVE:
- image_grid_->SetImages(
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_LEFT),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_TOP_RIGHT),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_LEFT),
- NULL,
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_RIGHT),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_LEFT),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM),
- &res.GetImageNamed(IDR_AURA_SHADOW_INACTIVE_BOTTOM_RIGHT));
- break;
- case STYLE_SMALL:
- image_grid_->SetImages(
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_LEFT),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_TOP_RIGHT),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_LEFT),
- NULL,
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_RIGHT),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_LEFT),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM),
- &res.GetImageNamed(IDR_WINDOW_BUBBLE_SHADOW_SMALL_BOTTOM_RIGHT));
- break;
- default:
- NOTREACHED() << "Unhandled style " << style_;
- break;
- }
-
- // Update interior inset for style.
- interior_inset_ = GetInteriorInsetForStyle(style_);
-
- // Image sizes may have changed.
- UpdateImageGridBounds();
-}
-
-void Shadow::UpdateImageGridBounds() {
- // Update bounds based on content bounds and image sizes.
- gfx::Rect image_grid_bounds = content_bounds_;
- image_grid_bounds.Inset(interior_inset_, interior_inset_);
- image_grid_->SetContentBounds(image_grid_bounds);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/shadow.h b/chromium/ui/views/corewm/shadow.h
deleted file mode 100644
index 794ba3dbeaa..00000000000
--- a/chromium/ui/views/corewm/shadow.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_SHADOW_H_
-#define UI_VIEWS_COREWM_SHADOW_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/gfx/rect.h"
-#include "ui/views/views_export.h"
-
-namespace ui {
-class Layer;
-} // namespace ui
-
-namespace views {
-namespace corewm {
-
-class ImageGrid;
-
-// Simple class that draws a drop shadow around content at given bounds.
-class VIEWS_EXPORT Shadow : public ui::ImplicitAnimationObserver {
- public:
- enum Style {
- // Active windows have more opaque shadows, shifted down to make the window
- // appear "higher".
- STYLE_ACTIVE,
-
- // Inactive windows have less opaque shadows.
- STYLE_INACTIVE,
-
- // Small windows like tooltips and context menus have lighter, smaller
- // shadows.
- STYLE_SMALL,
- };
-
- Shadow();
- virtual ~Shadow();
-
- void Init(Style style);
-
- // Returns |image_grid_|'s ui::Layer. This is exposed so it can be added to
- // the same layer as the content and stacked below it. SetContentBounds()
- // should be used to adjust the shadow's size and position (rather than
- // applying transformations to this layer).
- ui::Layer* layer() const;
-
- const gfx::Rect& content_bounds() const { return content_bounds_; }
- Style style() const { return style_; }
-
- // Moves and resizes |image_grid_| to frame |content_bounds|.
- void SetContentBounds(const gfx::Rect& content_bounds);
-
- // Sets the shadow's style, animating opacity as necessary.
- void SetStyle(Style style);
-
- // ui::ImplicitAnimationObserver overrides:
- virtual void OnImplicitAnimationsCompleted() OVERRIDE;
-
- private:
- // Updates the |image_grid_| images to the current |style_|.
- void UpdateImagesForStyle();
-
- // Updates the |image_grid_| bounds based on its image sizes and the
- // current |content_bounds_|.
- void UpdateImageGridBounds();
-
- // The current style, set when the transition animation starts.
- Style style_;
-
- scoped_ptr<ImageGrid> image_grid_;
-
- // Bounds of the content that the shadow encloses.
- gfx::Rect content_bounds_;
-
- // The interior inset of the shadow images. The content bounds of the image
- // grid should be set to |content_bounds_| inset by this amount.
- int interior_inset_;
-
- DISALLOW_COPY_AND_ASSIGN(Shadow);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_SHADOW_H_
diff --git a/chromium/ui/views/corewm/shadow_controller.cc b/chromium/ui/views/corewm/shadow_controller.cc
deleted file mode 100644
index 49307d8e2d2..00000000000
--- a/chromium/ui/views/corewm/shadow_controller.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/shadow_controller.h"
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/linked_ptr.h"
-#include "base/scoped_observer.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/env_observer.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/compositor/layer.h"
-#include "ui/views/corewm/shadow.h"
-#include "ui/views/corewm/shadow_types.h"
-
-using std::make_pair;
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-ShadowType GetShadowTypeFromWindow(aura::Window* window) {
- switch (window->type()) {
- case aura::client::WINDOW_TYPE_NORMAL:
- case aura::client::WINDOW_TYPE_PANEL:
- case aura::client::WINDOW_TYPE_MENU:
- case aura::client::WINDOW_TYPE_TOOLTIP:
- return SHADOW_TYPE_RECTANGULAR;
- default:
- break;
- }
- return SHADOW_TYPE_NONE;
-}
-
-bool ShouldUseSmallShadowForWindow(aura::Window* window) {
- switch (window->type()) {
- case aura::client::WINDOW_TYPE_MENU:
- case aura::client::WINDOW_TYPE_TOOLTIP:
- return true;
- default:
- break;
- }
- return false;
-}
-
-// Returns the shadow style to be applied to |losing_active| when it is losing
-// active to |gaining_active|. |gaining_active| may be of a type that hides when
-// inactive, and as such we do not want to render |losing_active| as inactive.
-Shadow::Style GetShadowStyleForWindowLosingActive(
- aura::Window* losing_active,
- aura::Window* gaining_active) {
- if (gaining_active && aura::client::GetHideOnDeactivate(gaining_active)) {
- aura::Window::Windows::const_iterator it =
- std::find(losing_active->transient_children().begin(),
- losing_active->transient_children().end(),
- gaining_active);
- if (it != losing_active->transient_children().end())
- return Shadow::STYLE_ACTIVE;
- }
- return Shadow::STYLE_INACTIVE;
-}
-
-} // namespace
-
-// ShadowController::Impl ------------------------------------------------------
-
-// Real implementation of the ShadowController. ShadowController observes
-// ActivationChangeObserver, which are per ActivationClient, where as there is
-// only a single Impl (as it observes all window creation by way of an
-// EnvObserver).
-class ShadowController::Impl :
- public aura::EnvObserver,
- public aura::WindowObserver,
- public base::RefCounted<Impl> {
- public:
- // Returns the singleton instance, destroyed when there are no more refs.
- static Impl* GetInstance();
-
- // aura::EnvObserver override:
- virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
-
- // aura::WindowObserver overrides:
- virtual void OnWindowPropertyChanged(
- aura::Window* window, const void* key, intptr_t old) OVERRIDE;
- virtual void OnWindowBoundsChanged(
- aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
-
- private:
- friend class base::RefCounted<Impl>;
- friend class ShadowController;
- friend class ShadowController::TestApi;
-
- typedef std::map<aura::Window*, linked_ptr<Shadow> > WindowShadowMap;
-
- Impl();
- virtual ~Impl();
-
- // Forwarded from ShadowController.
- void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active);
-
- // Checks if |window| is visible and contains a property requesting a shadow.
- bool ShouldShowShadowForWindow(aura::Window* window) const;
-
- // Returns |window|'s shadow from |window_shadows_|, or NULL if no shadow
- // exists.
- Shadow* GetShadowForWindow(aura::Window* window);
-
- // Updates the shadow styles for windows when activation changes.
- void HandleWindowActivationChange(aura::Window* gaining_active,
- aura::Window* losing_active);
-
- // Shows or hides |window|'s shadow as needed (creating the shadow if
- // necessary).
- void HandlePossibleShadowVisibilityChange(aura::Window* window);
-
- // Creates a new shadow for |window| and stores it in |window_shadows_|. The
- // shadow's bounds are initialized and it is added to the window's layer.
- void CreateShadowForWindow(aura::Window* window);
-
- WindowShadowMap window_shadows_;
-
- ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
-
- static Impl* instance_;
-
- DISALLOW_COPY_AND_ASSIGN(Impl);
-};
-
-// static
-ShadowController::Impl* ShadowController::Impl::instance_ = NULL;
-
-// static
-ShadowController::Impl* ShadowController::Impl::GetInstance() {
- if (!instance_)
- instance_ = new Impl();
- return instance_;
-}
-
-void ShadowController::Impl::OnWindowInitialized(aura::Window* window) {
- observer_manager_.Add(window);
- SetShadowType(window, GetShadowTypeFromWindow(window));
- HandlePossibleShadowVisibilityChange(window);
-}
-
-void ShadowController::Impl::OnWindowPropertyChanged(aura::Window* window,
- const void* key,
- intptr_t old) {
- if (key == kShadowTypeKey) {
- HandlePossibleShadowVisibilityChange(window);
- return;
- }
-}
-
-void ShadowController::Impl::OnWindowBoundsChanged(
- aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) {
- Shadow* shadow = GetShadowForWindow(window);
- if (shadow)
- shadow->SetContentBounds(gfx::Rect(new_bounds.size()));
-}
-
-void ShadowController::Impl::OnWindowDestroyed(aura::Window* window) {
- window_shadows_.erase(window);
- observer_manager_.Remove(window);
-}
-
-void ShadowController::Impl::OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) {
- if (gained_active) {
- Shadow* shadow = GetShadowForWindow(gained_active);
- if (shadow && !ShouldUseSmallShadowForWindow(gained_active))
- shadow->SetStyle(Shadow::STYLE_ACTIVE);
- }
- if (lost_active) {
- Shadow* shadow = GetShadowForWindow(lost_active);
- if (shadow && !ShouldUseSmallShadowForWindow(lost_active)) {
- shadow->SetStyle(GetShadowStyleForWindowLosingActive(lost_active,
- gained_active));
- }
- }
-}
-
-bool ShadowController::Impl::ShouldShowShadowForWindow(
- aura::Window* window) const {
- const ShadowType type = GetShadowType(window);
- switch (type) {
- case SHADOW_TYPE_NONE:
- return false;
- case SHADOW_TYPE_RECTANGULAR:
- return true;
- default:
- NOTREACHED() << "Unknown shadow type " << type;
- return false;
- }
-}
-
-Shadow* ShadowController::Impl::GetShadowForWindow(aura::Window* window) {
- WindowShadowMap::const_iterator it = window_shadows_.find(window);
- return it != window_shadows_.end() ? it->second.get() : NULL;
-}
-
-void ShadowController::Impl::HandlePossibleShadowVisibilityChange(
- aura::Window* window) {
- const bool should_show = ShouldShowShadowForWindow(window);
- Shadow* shadow = GetShadowForWindow(window);
- if (shadow)
- shadow->layer()->SetVisible(should_show);
- else if (should_show && !shadow)
- CreateShadowForWindow(window);
-}
-
-void ShadowController::Impl::CreateShadowForWindow(aura::Window* window) {
- linked_ptr<Shadow> shadow(new Shadow());
- window_shadows_.insert(make_pair(window, shadow));
-
- shadow->Init(ShouldUseSmallShadowForWindow(window) ?
- Shadow::STYLE_SMALL : Shadow::STYLE_ACTIVE);
- shadow->SetContentBounds(gfx::Rect(window->bounds().size()));
- shadow->layer()->SetVisible(ShouldShowShadowForWindow(window));
- window->layer()->Add(shadow->layer());
-}
-
-ShadowController::Impl::Impl()
- : observer_manager_(this) {
- aura::Env::GetInstance()->AddObserver(this);
-}
-
-ShadowController::Impl::~Impl() {
- DCHECK_EQ(instance_, this);
- aura::Env::GetInstance()->RemoveObserver(this);
- instance_ = NULL;
-}
-
-// ShadowController ------------------------------------------------------------
-
-ShadowController::ShadowController(
- aura::client::ActivationClient* activation_client)
- : activation_client_(activation_client),
- impl_(Impl::GetInstance()) {
- // Watch for window activation changes.
- activation_client_->AddObserver(this);
-}
-
-ShadowController::~ShadowController() {
- activation_client_->RemoveObserver(this);
-}
-
-void ShadowController::OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) {
- impl_->OnWindowActivated(gained_active, lost_active);
-}
-
-// ShadowController::TestApi ---------------------------------------------------
-
-Shadow* ShadowController::TestApi::GetShadowForWindow(aura::Window* window) {
- return controller_->impl_->GetShadowForWindow(window);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/shadow_controller.h b/chromium/ui/views/corewm/shadow_controller.h
deleted file mode 100644
index 2a7e29c88e5..00000000000
--- a/chromium/ui/views/corewm/shadow_controller.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_
-#define UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/views/views_export.h"
-
-namespace aura {
-class Window;
-namespace client {
-class ActivationClient;
-}
-}
-namespace gfx {
-class Rect;
-}
-
-namespace views {
-namespace corewm {
-
-class Shadow;
-
-// ShadowController observes changes to windows and creates and updates drop
-// shadows as needed. ShadowController itself is light weight and per
-// ActivationClient. ShadowController delegates to its implementation class,
-// which observes all window creation.
-class VIEWS_EXPORT ShadowController :
- public aura::client::ActivationChangeObserver {
- public:
- class VIEWS_EXPORT TestApi {
- public:
- explicit TestApi(ShadowController* controller) : controller_(controller) {}
- ~TestApi() {}
-
- Shadow* GetShadowForWindow(aura::Window* window);
-
- private:
- ShadowController* controller_; // not owned
-
- DISALLOW_COPY_AND_ASSIGN(TestApi);
- };
-
- explicit ShadowController(aura::client::ActivationClient* activation_client);
- virtual ~ShadowController();
-
- // aura::client::ActivationChangeObserver overrides:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE;
-
- private:
- class Impl;
-
- aura::client::ActivationClient* activation_client_;
-
- scoped_refptr<Impl> impl_;
-
- DISALLOW_COPY_AND_ASSIGN(ShadowController);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_SHADOW_CONTROLLER_H_
diff --git a/chromium/ui/views/corewm/shadow_controller_unittest.cc b/chromium/ui/views/corewm/shadow_controller_unittest.cc
deleted file mode 100644
index 4140f7d83fb..00000000000
--- a/chromium/ui/views/corewm/shadow_controller_unittest.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/shadow_controller.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/views/corewm/shadow.h"
-#include "ui/views/corewm/shadow_types.h"
-
-namespace views {
-namespace corewm {
-
-class ShadowControllerTest : public aura::test::AuraTestBase {
- public:
- ShadowControllerTest() {}
- virtual ~ShadowControllerTest() {}
-
- virtual void SetUp() OVERRIDE {
- AuraTestBase::SetUp();
- aura::client::ActivationClient* activation_client =
- aura::client::GetActivationClient(root_window());
- shadow_controller_.reset(new ShadowController(activation_client));
- }
- virtual void TearDown() OVERRIDE {
- shadow_controller_.reset();
- AuraTestBase::TearDown();
- }
-
- protected:
- ShadowController* shadow_controller() { return shadow_controller_.get(); }
-
- void ActivateWindow(aura::Window* window) {
- DCHECK(window);
- DCHECK(window->GetRootWindow());
- aura::client::GetActivationClient(window->GetRootWindow())->ActivateWindow(
- window);
- }
-
- private:
- scoped_ptr<ShadowController> shadow_controller_;
-
- DISALLOW_COPY_AND_ASSIGN(ShadowControllerTest);
-};
-
-// Tests that various methods in Window update the Shadow object as expected.
-TEST_F(ShadowControllerTest, Shadow) {
- scoped_ptr<aura::Window> window(new aura::Window(NULL));
- window->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window->Init(ui::LAYER_TEXTURED);
- ParentWindow(window.get());
-
- // We should create the shadow before the window is visible (the shadow's
- // layer won't get drawn yet since it's a child of the window's layer).
- ShadowController::TestApi api(shadow_controller());
- const Shadow* shadow = api.GetShadowForWindow(window.get());
- ASSERT_TRUE(shadow != NULL);
- EXPECT_TRUE(shadow->layer()->visible());
-
- // The shadow should remain visible after window visibility changes.
- window->Show();
- EXPECT_TRUE(shadow->layer()->visible());
- window->Hide();
- EXPECT_TRUE(shadow->layer()->visible());
-
- // If the shadow is disabled, it should be hidden.
- SetShadowType(window.get(), SHADOW_TYPE_NONE);
- window->Show();
- EXPECT_FALSE(shadow->layer()->visible());
- SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR);
- EXPECT_TRUE(shadow->layer()->visible());
-
- // The shadow's layer should be a child of the window's layer.
- EXPECT_EQ(window->layer(), shadow->layer()->parent());
-
- window->parent()->RemoveChild(window.get());
- aura::Window* window_ptr = window.get();
- window.reset();
- EXPECT_TRUE(api.GetShadowForWindow(window_ptr) == NULL);
-}
-
-// Tests that the window's shadow's bounds are updated correctly.
-TEST_F(ShadowControllerTest, ShadowBounds) {
- scoped_ptr<aura::Window> window(new aura::Window(NULL));
- window->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window->Init(ui::LAYER_TEXTURED);
- ParentWindow(window.get());
- window->Show();
-
- const gfx::Rect kOldBounds(20, 30, 400, 300);
- window->SetBounds(kOldBounds);
-
- // When the shadow is first created, it should use the window's size (but
- // remain at the origin, since it's a child of the window's layer).
- SetShadowType(window.get(), SHADOW_TYPE_RECTANGULAR);
- ShadowController::TestApi api(shadow_controller());
- const Shadow* shadow = api.GetShadowForWindow(window.get());
- ASSERT_TRUE(shadow != NULL);
- EXPECT_EQ(gfx::Rect(kOldBounds.size()).ToString(),
- shadow->content_bounds().ToString());
-
- // When we change the window's bounds, the shadow's should be updated too.
- gfx::Rect kNewBounds(50, 60, 500, 400);
- window->SetBounds(kNewBounds);
- EXPECT_EQ(gfx::Rect(kNewBounds.size()).ToString(),
- shadow->content_bounds().ToString());
-}
-
-// Tests that activating a window changes the shadow style.
-TEST_F(ShadowControllerTest, ShadowStyle) {
- ShadowController::TestApi api(shadow_controller());
-
- scoped_ptr<aura::Window> window1(new aura::Window(NULL));
- window1->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window1->Init(ui::LAYER_TEXTURED);
- ParentWindow(window1.get());
- window1->SetBounds(gfx::Rect(10, 20, 300, 400));
- window1->Show();
- ActivateWindow(window1.get());
-
- // window1 is active, so style should have active appearance.
- Shadow* shadow1 = api.GetShadowForWindow(window1.get());
- ASSERT_TRUE(shadow1 != NULL);
- EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
-
- // Create another window and activate it.
- scoped_ptr<aura::Window> window2(new aura::Window(NULL));
- window2->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window2->Init(ui::LAYER_TEXTURED);
- ParentWindow(window2.get());
- window2->SetBounds(gfx::Rect(11, 21, 301, 401));
- window2->Show();
- ActivateWindow(window2.get());
-
- // window1 is now inactive, so shadow should go inactive.
- Shadow* shadow2 = api.GetShadowForWindow(window2.get());
- ASSERT_TRUE(shadow2 != NULL);
- EXPECT_EQ(Shadow::STYLE_INACTIVE, shadow1->style());
- EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow2->style());
-}
-
-// Tests that we use smaller shadows for tooltips and menus.
-TEST_F(ShadowControllerTest, SmallShadowsForTooltipsAndMenus) {
- ShadowController::TestApi api(shadow_controller());
-
- scoped_ptr<aura::Window> tooltip_window(new aura::Window(NULL));
- tooltip_window->SetType(aura::client::WINDOW_TYPE_TOOLTIP);
- tooltip_window->Init(ui::LAYER_TEXTURED);
- ParentWindow(tooltip_window.get());
- tooltip_window->SetBounds(gfx::Rect(10, 20, 300, 400));
- tooltip_window->Show();
-
- Shadow* tooltip_shadow = api.GetShadowForWindow(tooltip_window.get());
- ASSERT_TRUE(tooltip_shadow != NULL);
- EXPECT_EQ(Shadow::STYLE_SMALL, tooltip_shadow->style());
-
- scoped_ptr<aura::Window> menu_window(new aura::Window(NULL));
- menu_window->SetType(aura::client::WINDOW_TYPE_MENU);
- menu_window->Init(ui::LAYER_TEXTURED);
- ParentWindow(menu_window.get());
- menu_window->SetBounds(gfx::Rect(10, 20, 300, 400));
- menu_window->Show();
-
- Shadow* menu_shadow = api.GetShadowForWindow(tooltip_window.get());
- ASSERT_TRUE(menu_shadow != NULL);
- EXPECT_EQ(Shadow::STYLE_SMALL, menu_shadow->style());
-}
-
-// http://crbug.com/120210 - transient parents of certain types of transients
-// should not lose their shadow when they lose activation to the transient.
-TEST_F(ShadowControllerTest, TransientParentKeepsActiveShadow) {
- ShadowController::TestApi api(shadow_controller());
-
- scoped_ptr<aura::Window> window1(new aura::Window(NULL));
- window1->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window1->Init(ui::LAYER_TEXTURED);
- ParentWindow(window1.get());
- window1->SetBounds(gfx::Rect(10, 20, 300, 400));
- window1->Show();
- ActivateWindow(window1.get());
-
- // window1 is active, so style should have active appearance.
- Shadow* shadow1 = api.GetShadowForWindow(window1.get());
- ASSERT_TRUE(shadow1 != NULL);
- EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
-
- // Create a window that is transient to window1, and that has the 'hide on
- // deactivate' property set. Upon activation, window1 should still have an
- // active shadow.
- scoped_ptr<aura::Window> window2(new aura::Window(NULL));
- window2->SetType(aura::client::WINDOW_TYPE_NORMAL);
- window2->Init(ui::LAYER_TEXTURED);
- ParentWindow(window2.get());
- window2->SetBounds(gfx::Rect(11, 21, 301, 401));
- window1->AddTransientChild(window2.get());
- aura::client::SetHideOnDeactivate(window2.get(), true);
- window2->Show();
- ActivateWindow(window2.get());
-
- // window1 is now inactive, but its shadow should still appear active.
- EXPECT_EQ(Shadow::STYLE_ACTIVE, shadow1->style());
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/shadow_types.cc b/chromium/ui/views/corewm/shadow_types.cc
deleted file mode 100644
index 1e3a937028f..00000000000
--- a/chromium/ui/views/corewm/shadow_types.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/shadow_types.h"
-
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::ShadowType);
-
-namespace views {
-namespace corewm {
-
-void SetShadowType(aura::Window* window, ShadowType shadow_type) {
- window->SetProperty(kShadowTypeKey, shadow_type);
-}
-
-ShadowType GetShadowType(aura::Window* window) {
- return window->GetProperty(kShadowTypeKey);
-}
-
-DEFINE_WINDOW_PROPERTY_KEY(ShadowType, kShadowTypeKey, SHADOW_TYPE_NONE);
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/shadow_types.h b/chromium/ui/views/corewm/shadow_types.h
deleted file mode 100644
index 046ad705a3a..00000000000
--- a/chromium/ui/views/corewm/shadow_types.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_SHADOW_TYPES_H_
-#define UI_VIEWS_COREWM_SHADOW_TYPES_H_
-
-#include "ui/aura/window.h"
-#include "ui/views/views_export.h"
-
-namespace aura {
-class Window;
-}
-
-namespace views {
-namespace corewm {
-
-// Different types of drop shadows that can be drawn under a window by the
-// shell. Used as a value for the kShadowTypeKey property.
-enum ShadowType {
- // Starts at 0 due to the cast in GetShadowType().
- SHADOW_TYPE_NONE = 0,
- SHADOW_TYPE_RECTANGULAR,
-};
-
-VIEWS_EXPORT void SetShadowType(aura::Window* window, ShadowType shadow_type);
-VIEWS_EXPORT ShadowType GetShadowType(aura::Window* window);
-
-// A property key describing the drop shadow that should be displayed under the
-// window. If unset, no shadow is displayed.
-extern const aura::WindowProperty<ShadowType>* const kShadowTypeKey;
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_SHADOW_TYPES_H_
diff --git a/chromium/ui/views/corewm/tooltip.h b/chromium/ui/views/corewm/tooltip.h
index f714ac9a57c..7fb15bc32ca 100644
--- a/chromium/ui/views/corewm/tooltip.h
+++ b/chromium/ui/views/corewm/tooltip.h
@@ -27,7 +27,7 @@ class VIEWS_EXPORT Tooltip {
// Updates the text on the tooltip and resizes to fit.
virtual void SetText(aura::Window* window,
- const string16& tooltip_text,
+ const base::string16& tooltip_text,
const gfx::Point& location) = 0;
// Shows the tooltip at the specified location (in screen coordinates).
diff --git a/chromium/ui/views/corewm/tooltip_aura.cc b/chromium/ui/views/corewm/tooltip_aura.cc
index 7c11bd80bbc..f9f41b93722 100644
--- a/chromium/ui/views/corewm/tooltip_aura.cc
+++ b/chromium/ui/views/corewm/tooltip_aura.cc
@@ -4,23 +4,20 @@
#include "ui/views/corewm/tooltip_aura.h"
-#include "base/command_line.h"
#include "base/strings/string_split.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/text_elider.h"
+#include "ui/gfx/text_utils.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
-#include "ui/views/corewm/corewm_switches.h"
#include "ui/views/widget/widget.h"
namespace {
-const SkColor kTooltipBackground = 0xFFFFFFCC;
-const SkColor kTooltipBorder = 0xFF646450;
-const int kTooltipBorderWidth = 1;
const int kTooltipHorizontalPadding = 3;
// Max visual tooltip width. If a tooltip is greater than this width, it will
@@ -53,13 +50,6 @@ views::Widget* CreateTooltipWidget(aura::Window* tooltip_window) {
return widget;
}
-gfx::Font GetDefaultFont() {
- // TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
- // out a way to merge.
- return ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::BaseFont);
-}
-
} // namespace
namespace views {
@@ -69,13 +59,6 @@ TooltipAura::TooltipAura(gfx::ScreenType screen_type)
: screen_type_(screen_type),
widget_(NULL),
tooltip_window_(NULL) {
- label_.set_background(
- views::Background::CreateSolidBackground(kTooltipBackground));
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) {
- label_.set_border(
- views::Border::CreateSolidBorder(kTooltipBorderWidth,
- kTooltipBorder));
- }
label_.set_owned_by_client();
label_.SetMultiLine(true);
}
@@ -85,8 +68,9 @@ TooltipAura::~TooltipAura() {
}
// static
-void TooltipAura::TrimTooltipToFit(int max_width,
- string16* text,
+void TooltipAura::TrimTooltipToFit(const gfx::FontList& font_list,
+ int max_width,
+ base::string16* text,
int* width,
int* line_count) {
*width = 0;
@@ -95,27 +79,26 @@ void TooltipAura::TrimTooltipToFit(int max_width,
// Determine the available width for the tooltip.
int available_width = std::min(kTooltipMaxWidthPixels, max_width);
- std::vector<string16> lines;
+ std::vector<base::string16> lines;
base::SplitString(*text, '\n', &lines);
- std::vector<string16> result_lines;
+ std::vector<base::string16> result_lines;
// Format each line to fit.
- gfx::Font font = GetDefaultFont();
- for (std::vector<string16>::iterator l = lines.begin(); l != lines.end();
- ++l) {
+ for (std::vector<base::string16>::iterator l = lines.begin();
+ l != lines.end(); ++l) {
// We break the line at word boundaries, then stuff as many words as we can
// in the available width to the current line, and move the remaining words
// to a new line.
- std::vector<string16> words;
+ std::vector<base::string16> words;
base::SplitStringDontTrim(*l, ' ', &words);
int current_width = 0;
- string16 line;
- for (std::vector<string16>::iterator w = words.begin(); w != words.end();
- ++w) {
- string16 word = *w;
+ base::string16 line;
+ for (std::vector<base::string16>::iterator w = words.begin();
+ w != words.end(); ++w) {
+ base::string16 word = *w;
if (w + 1 != words.end())
word.push_back(' ');
- int word_width = font.GetStringWidth(word);
+ int word_width = gfx::GetStringWidth(word, font_list);
if (current_width + word_width > available_width) {
// Current width will exceed the available width. Must start a new line.
if (!line.empty())
@@ -139,19 +122,19 @@ void TooltipAura::TrimTooltipToFit(int max_width,
*line_count = result_lines.size();
// Flatten the result.
- string16 result;
- for (std::vector<string16>::iterator l = result_lines.begin();
+ base::string16 result;
+ for (std::vector<base::string16>::iterator l = result_lines.begin();
l != result_lines.end(); ++l) {
if (!result.empty())
result.push_back('\n');
- int line_width = font.GetStringWidth(*l);
+ int line_width = gfx::GetStringWidth(*l, font_list);
// Since we only break at word boundaries, it could happen that due to some
// very long word, line_width is greater than the available_width. In such
// case, we simply truncate at available_width and add ellipses at the end.
if (line_width > available_width) {
*width = available_width;
- result.append(gfx::ElideText(*l, font, available_width,
- gfx::ELIDE_AT_END));
+ result.append(gfx::ElideText(*l, font_list, available_width,
+ gfx::ELIDE_TAIL));
} else {
*width = std::max(*width, line_width);
result.append(*l);
@@ -163,25 +146,9 @@ void TooltipAura::TrimTooltipToFit(int max_width,
int TooltipAura::GetMaxWidth(const gfx::Point& location) const {
// TODO(varunjain): implementation duplicated in tooltip_manager_aura. Figure
// out a way to merge.
- gfx::Rect display_bounds = GetBoundsForTooltip(location);
- return (display_bounds.width() + 1) / 2;
-}
-
-gfx::Rect TooltipAura::GetBoundsForTooltip(
- const gfx::Point& origin) const {
- DCHECK(tooltip_window_);
- gfx::Rect widget_bounds;
- // For Desktop aura we constrain the tooltip to the bounds of the Widget
- // (which comes from the RootWindow).
- if (screen_type_ == gfx::SCREEN_TYPE_NATIVE &&
- gfx::SCREEN_TYPE_NATIVE != gfx::SCREEN_TYPE_ALTERNATE) {
- widget_bounds = tooltip_window_->GetDispatcher()->host()->GetBounds();
- }
gfx::Screen* screen = gfx::Screen::GetScreenByType(screen_type_);
- gfx::Rect bounds(screen->GetDisplayNearestPoint(origin).bounds());
- if (!widget_bounds.IsEmpty())
- bounds.Intersect(widget_bounds);
- return bounds;
+ gfx::Rect display_bounds(screen->GetDisplayNearestPoint(location).bounds());
+ return (display_bounds.width() + 1) / 2;
}
void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos,
@@ -191,7 +158,8 @@ void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos,
tooltip_height);
tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY);
- gfx::Rect display_bounds = GetBoundsForTooltip(mouse_pos);
+ gfx::Screen* screen = gfx::Screen::GetScreenByType(screen_type_);
+ gfx::Rect display_bounds(screen->GetDisplayNearestPoint(mouse_pos).bounds());
// If tooltip is out of bounds on the x axis, we simply shift it
// horizontally by the offset.
@@ -209,22 +177,6 @@ void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos,
widget_->SetBounds(tooltip_rect);
}
-void TooltipAura::CreateWidget() {
- if (widget_) {
- // If the window for which the tooltip is being displayed changes and if the
- // tooltip window and the tooltip widget belong to different rootwindows
- // then we need to recreate the tooltip widget under the active root window
- // hierarchy to get it to display.
- if (widget_->GetNativeWindow()->GetRootWindow() ==
- tooltip_window_->GetRootWindow())
- return;
- DestroyWidget();
- }
- widget_ = CreateTooltipWidget(tooltip_window_);
- widget_->SetContentsView(&label_);
- widget_->AddObserver(this);
-}
-
void TooltipAura::DestroyWidget() {
if (widget_) {
widget_->RemoveObserver(this);
@@ -234,29 +186,43 @@ void TooltipAura::DestroyWidget() {
}
void TooltipAura::SetText(aura::Window* window,
- const string16& tooltip_text,
+ const base::string16& tooltip_text,
const gfx::Point& location) {
tooltip_window_ = window;
int max_width, line_count;
- string16 trimmed_text(tooltip_text);
- TrimTooltipToFit(
- GetMaxWidth(location), &trimmed_text, &max_width, &line_count);
+ base::string16 trimmed_text(tooltip_text);
+ TrimTooltipToFit(label_.font_list(), GetMaxWidth(location), &trimmed_text,
+ &max_width, &line_count);
label_.SetText(trimmed_text);
int width = max_width + 2 * kTooltipHorizontalPadding;
int height = label_.GetHeightForWidth(max_width) +
2 * kTooltipVerticalPadding;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDropShadows)) {
- width += 2 * kTooltipBorderWidth;
- height += 2 * kTooltipBorderWidth;
+
+ if (!widget_) {
+ widget_ = CreateTooltipWidget(tooltip_window_);
+ widget_->SetContentsView(&label_);
+ widget_->AddObserver(this);
}
- CreateWidget();
+
SetTooltipBounds(location, width, height);
+
+ ui::NativeTheme* native_theme = widget_->GetNativeTheme();
+ label_.set_background(
+ views::Background::CreateSolidBackground(
+ native_theme->GetSystemColor(
+ ui::NativeTheme::kColorId_TooltipBackground)));
+
+ label_.SetAutoColorReadabilityEnabled(false);
+ label_.SetEnabledColor(native_theme->GetSystemColor(
+ ui::NativeTheme::kColorId_TooltipText));
}
void TooltipAura::Show() {
- if (widget_)
+ if (widget_) {
widget_->Show();
+ widget_->StackAtTop();
+ }
}
void TooltipAura::Hide() {
diff --git a/chromium/ui/views/corewm/tooltip_aura.h b/chromium/ui/views/corewm/tooltip_aura.h
index 97f3737aa8e..ead119f5d95 100644
--- a/chromium/ui/views/corewm/tooltip_aura.h
+++ b/chromium/ui/views/corewm/tooltip_aura.h
@@ -10,6 +10,10 @@
#include "ui/views/corewm/tooltip.h"
#include "ui/views/widget/widget_observer.h"
+namespace gfx {
+class FontList;
+} // namespace gfx
+
namespace views {
class Widget;
@@ -24,11 +28,11 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver {
// Trims the tooltip to fit in the width |max_width|, setting |text| to the
// clipped result, |width| to the width (in pixels) of the clipped text
- // and |line_count| to the number of lines of text in the tooltip. |x| and |y|
- // give the location of the tooltip in screen coordinates. |max_width| comes
- // from GetMaxWidth().
- static void TrimTooltipToFit(int max_width,
- string16* text,
+ // and |line_count| to the number of lines of text in the tooltip. |font_list|
+ // is used to layout |text|. |max_width| comes from GetMaxWidth().
+ static void TrimTooltipToFit(const gfx::FontList& font_list,
+ int max_width,
+ base::string16* text,
int* width,
int* line_count);
@@ -36,24 +40,18 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver {
// Returns the max width of the tooltip when shown at the specified location.
int GetMaxWidth(const gfx::Point& location) const;
- // Returns the bounds to fit the tooltip in.
- gfx::Rect GetBoundsForTooltip(const gfx::Point& origin) const;
-
// Adjusts the bounds given by the arguments to fit inside the desktop
// and applies the adjusted bounds to the label_.
void SetTooltipBounds(const gfx::Point& mouse_pos,
int tooltip_width,
int tooltip_height);
- // Makes sure |widget_| is valid, creating as necessary.
- void CreateWidget();
-
// Destroys |widget_|.
void DestroyWidget();
// Tooltip:
virtual void SetText(aura::Window* window,
- const string16& tooltip_text,
+ const base::string16& tooltip_text,
const gfx::Point& location) OVERRIDE;
virtual void Show() OVERRIDE;
virtual void Hide() OVERRIDE;
diff --git a/chromium/ui/views/corewm/tooltip_aura_unittest.cc b/chromium/ui/views/corewm/tooltip_aura_unittest.cc
index 75814abcad8..1e8981ad791 100644
--- a/chromium/ui/views/corewm/tooltip_aura_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_aura_unittest.cc
@@ -5,43 +5,44 @@
#include "ui/views/corewm/tooltip_aura.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/test/aura_test_base.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/text_elider.h"
-#include "ui/views/test/views_test_base.h"
+#include "ui/gfx/text_utils.h"
+
+using base::ASCIIToUTF16;
+using base::UTF8ToUTF16;
namespace views {
namespace corewm {
-typedef ViewsTestBase TooltipAuraTest;
-
-// TODO(sky): clean this up.
-gfx::Font GetDefaultFont() {
- return ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::BaseFont);
-}
+typedef aura::test::AuraTestBase TooltipAuraTest;
TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
+ const gfx::FontList font_list;
const int max_width = 4000;
- string16 tooltip;
+ base::string16 tooltip;
int width, line_count, expect_lines;
int max_pixel_width = 400; // copied from constants in tooltip_controller.cc
int max_lines = 10; // copied from constants in tooltip_controller.cc
- gfx::Font font = GetDefaultFont();
size_t tooltip_len;
// Error in computed size vs. expected size should not be greater than the
// size of the longest word.
- int error_in_pixel_width = font.GetStringWidth(ASCIIToUTF16("tooltip"));
+ int error_in_pixel_width = gfx::GetStringWidth(ASCIIToUTF16("tooltip"),
+ font_list);
// Long tooltips should wrap to next line
tooltip.clear();
width = line_count = -1;
expect_lines = 3;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
+ for (; gfx::GetStringWidth(tooltip, font_list) <=
+ (expect_lines - 1) * max_pixel_width;)
tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
tooltip_len = tooltip.length();
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
EXPECT_EQ(expect_lines, line_count);
EXPECT_EQ(tooltip_len + expect_lines - 1, tooltip.length());
@@ -50,9 +51,11 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
tooltip.clear();
width = line_count = -1;
expect_lines = 13;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 1) * max_pixel_width;)
+ for (; gfx::GetStringWidth(tooltip, font_list) <=
+ (expect_lines - 1) * max_pixel_width;)
tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
EXPECT_EQ(max_lines, line_count);
@@ -60,11 +63,13 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
tooltip.clear();
width = line_count = -1;
expect_lines = 4;
- for (; font.GetStringWidth(tooltip) <= (expect_lines - 2) * max_pixel_width;)
+ for (; gfx::GetStringWidth(tooltip, font_list) <=
+ (expect_lines - 2) * max_pixel_width;)
tooltip.append(ASCIIToUTF16("This is part of the tooltip"));
tooltip.insert(tooltip.length() / 2, ASCIIToUTF16("\n"));
tooltip_len = tooltip.length();
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
EXPECT_NEAR(max_pixel_width, width, error_in_pixel_width);
EXPECT_EQ(expect_lines, line_count);
// We may have inserted the line break above near a space which will get
@@ -76,19 +81,23 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
tooltip.clear();
width = line_count = -1;
tooltip = UTF8ToUTF16(std::string('a', max_pixel_width));
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
EXPECT_NEAR(max_pixel_width, width, 5);
EXPECT_EQ(1, line_count);
- EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)), font,
- max_pixel_width, gfx::ELIDE_AT_END), tooltip);
+ EXPECT_EQ(gfx::ElideText(UTF8ToUTF16(std::string('a', max_pixel_width)),
+ font_list, max_pixel_width, gfx::ELIDE_TAIL),
+ tooltip);
#endif
// Normal small tooltip should stay as is.
tooltip.clear();
width = line_count = -1;
tooltip = ASCIIToUTF16("Small Tooltip");
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
- EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tooltip")), width);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
+ EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tooltip"), font_list),
+ width);
EXPECT_EQ(1, line_count);
EXPECT_EQ(ASCIIToUTF16("Small Tooltip"), tooltip);
@@ -96,10 +105,13 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
tooltip.clear();
width = line_count = -1;
tooltip = ASCIIToUTF16("Multi line\nTooltip");
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
- int expected_width = font.GetStringWidth(ASCIIToUTF16("Multi line"));
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
+ int expected_width = gfx::GetStringWidth(ASCIIToUTF16("Multi line"),
+ font_list);
expected_width = std::max(expected_width,
- font.GetStringWidth(ASCIIToUTF16("Tooltip")));
+ gfx::GetStringWidth(ASCIIToUTF16("Tooltip"),
+ font_list));
EXPECT_EQ(expected_width, width);
EXPECT_EQ(2, line_count);
EXPECT_EQ(ASCIIToUTF16("Multi line\nTooltip"), tooltip);
@@ -108,8 +120,10 @@ TEST_F(TooltipAuraTest, TrimTooltipToFitTests) {
tooltip.clear();
width = line_count = -1;
tooltip = ASCIIToUTF16("Small Tool t\tip");
- TooltipAura::TrimTooltipToFit(max_width, &tooltip, &width, &line_count);
- EXPECT_EQ(font.GetStringWidth(ASCIIToUTF16("Small Tool t\tip")), width);
+ TooltipAura::TrimTooltipToFit(font_list, max_width, &tooltip, &width,
+ &line_count);
+ EXPECT_EQ(gfx::GetStringWidth(ASCIIToUTF16("Small Tool t\tip"), font_list),
+ width);
EXPECT_EQ(1, line_count);
EXPECT_EQ(ASCIIToUTF16("Small Tool t\tip"), tooltip);
}
diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc
index b411688397d..b1ffc1c7de8 100644
--- a/chromium/ui/views/corewm/tooltip_controller.cc
+++ b/chromium/ui/views/corewm/tooltip_controller.cc
@@ -10,7 +10,6 @@
#include "base/time/time.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
@@ -20,6 +19,7 @@
#include "ui/gfx/screen.h"
#include "ui/views/corewm/tooltip.h"
#include "ui/views/widget/tooltip_manager.h"
+#include "ui/wm/public/drag_drop_client.h"
namespace views {
namespace corewm {
@@ -115,6 +115,7 @@ aura::Window* GetTooltipTarget(const ui::MouseEvent& event,
TooltipController::TooltipController(scoped_ptr<Tooltip> tooltip)
: tooltip_window_(NULL),
+ tooltip_id_(NULL),
tooltip_window_at_mouse_press_(NULL),
tooltip_(tooltip.Pass()),
tooltips_enabled_(true) {
@@ -133,6 +134,18 @@ void TooltipController::UpdateTooltip(aura::Window* target) {
if (tooltip_window_ == target && tooltip_->IsVisible())
UpdateIfRequired();
+ // Reset |tooltip_window_at_mouse_press_| if the moving within the same window
+ // but over a region that has different tooltip text. By resetting
+ // |tooltip_window_at_mouse_press_| we ensure the next time the timer fires
+ // we'll requery for the tooltip text.
+ // This handles the case of clicking on a view, moving within the same window
+ // but over a different view, than back to the original.
+ if (tooltip_window_at_mouse_press_ &&
+ target == tooltip_window_at_mouse_press_ &&
+ aura::client::GetTooltipText(target) != tooltip_text_at_mouse_press_) {
+ tooltip_window_at_mouse_press_ = NULL;
+ }
+
// If we had stopped the tooltip timer for some reason, we must restart it if
// there is a change in the tooltip.
if (!tooltip_timer_.IsRunning()) {
@@ -174,14 +187,15 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_DRAGGED: {
curr_mouse_loc_ = event->location();
- aura::Window* target = GetTooltipTarget(*event, &curr_mouse_loc_);
- if (tooltip_window_ != target) {
- if (tooltip_window_)
- tooltip_window_->RemoveObserver(this);
- tooltip_window_ = target;
- if (tooltip_window_)
- tooltip_window_->AddObserver(this);
+ aura::Window* target = NULL;
+ // Avoid a call to gfx::Screen::GetWindowAtScreenPoint() since it can be
+ // very expensive on X11 in cases when the tooltip is hidden anyway.
+ if (tooltips_enabled_ &&
+ !aura::Env::GetInstance()->IsMouseButtonDown() &&
+ !IsDragDropInProgress()) {
+ target = GetTooltipTarget(*event, &curr_mouse_loc_);
}
+ SetTooltipWindow(target);
if (tooltip_timer_.IsRunning())
tooltip_timer_.Reset();
@@ -214,13 +228,12 @@ void TooltipController::OnTouchEvent(ui::TouchEvent* event) {
// touch events.
// Hide the tooltip for touch events.
tooltip_->Hide();
- if (tooltip_window_)
- tooltip_window_->RemoveObserver(this);
- tooltip_window_ = NULL;
+ SetTooltipWindow(NULL);
}
void TooltipController::OnCancelMode(ui::CancelModeEvent* event) {
tooltip_->Hide();
+ SetTooltipWindow(NULL);
}
void TooltipController::OnWindowDestroyed(aura::Window* window) {
@@ -255,7 +268,7 @@ void TooltipController::UpdateIfRequired() {
return;
}
- string16 tooltip_text;
+ base::string16 tooltip_text;
if (tooltip_window_)
tooltip_text = aura::client::GetTooltipText(tooltip_window_);
@@ -270,12 +283,19 @@ void TooltipController::UpdateIfRequired() {
tooltip_window_at_mouse_press_ = NULL;
}
+ // If the uniqueness indicator is different from the previously encountered
+ // one, we should force tooltip update
+ const void* tooltip_id = aura::client::GetTooltipId(tooltip_window_);
+ bool ids_differ = false;
+ ids_differ = tooltip_id_ != tooltip_id;
+ tooltip_id_ = tooltip_id;
+
// We add the !tooltip_->IsVisible() below because when we come here from
// TooltipTimerFired(), the tooltip_text may not have changed but we still
// want to update the tooltip because the timer has fired.
// If we come here from UpdateTooltip(), we have already checked for tooltip
// visibility and this check below will have no effect.
- if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible()) {
+ if (tooltip_text_ != tooltip_text || !tooltip_->IsVisible() || ids_differ) {
tooltip_shown_timer_.Stop();
tooltip_text_ = tooltip_text;
base::string16 trimmed_text(tooltip_text_);
@@ -283,13 +303,14 @@ void TooltipController::UpdateIfRequired() {
// If the string consists entirely of whitespace, then don't both showing it
// (an empty tooltip is useless).
base::string16 whitespace_removed_text;
- TrimWhitespace(trimmed_text, TRIM_ALL, &whitespace_removed_text);
+ base::TrimWhitespace(trimmed_text, base::TRIM_ALL,
+ &whitespace_removed_text);
if (whitespace_removed_text.empty()) {
tooltip_->Hide();
} else {
gfx::Point widget_loc = curr_mouse_loc_ +
tooltip_window_->GetBoundsInScreen().OffsetFromOrigin();
- tooltip_->SetText(tooltip_window_, trimmed_text, widget_loc);
+ tooltip_->SetText(tooltip_window_, whitespace_removed_text, widget_loc);
tooltip_->Show();
int timeout = GetTooltipShownTimeout();
if (timeout > 0) {
@@ -333,5 +354,15 @@ int TooltipController::GetTooltipShownTimeout() {
return it->second;
}
+void TooltipController::SetTooltipWindow(aura::Window* target) {
+ if (tooltip_window_ == target)
+ return;
+ if (tooltip_window_)
+ tooltip_window_->RemoveObserver(this);
+ tooltip_window_ = target;
+ if (tooltip_window_)
+ tooltip_window_->AddObserver(this);
+}
+
} // namespace corewm
} // namespace views
diff --git a/chromium/ui/views/corewm/tooltip_controller.h b/chromium/ui/views/corewm/tooltip_controller.h
index 66b6a3224c7..e0453341f00 100644
--- a/chromium/ui/views/corewm/tooltip_controller.h
+++ b/chromium/ui/views/corewm/tooltip_controller.h
@@ -10,11 +10,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/timer/timer.h"
-#include "ui/aura/client/tooltip_client.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/point.h"
#include "ui/views/views_export.h"
+#include "ui/wm/public/tooltip_client.h"
namespace aura {
class Window;
@@ -61,7 +61,7 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
void TooltipShownTimerFired();
// Updates the tooltip if required (if there is any change in the tooltip
- // text or the aura::Window.
+ // text, tooltip id or the aura::Window).
void UpdateIfRequired();
// Only used in tests.
@@ -74,8 +74,14 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
int GetTooltipShownTimeout();
+ // Sets tooltip window to |target| if it is different from existing window.
+ // Calls RemoveObserver on the existing window if it is not NULL.
+ // Calls AddObserver on the new window if it is not NULL.
+ void SetTooltipWindow(aura::Window* target);
+
aura::Window* tooltip_window_;
base::string16 tooltip_text_;
+ const void* tooltip_id_;
// These fields are for tracking state when the user presses a mouse button.
aura::Window* tooltip_window_at_mouse_press_;
diff --git a/chromium/ui/views/corewm/tooltip_controller_test_helper.cc b/chromium/ui/views/corewm/tooltip_controller_test_helper.cc
index 4794a6e73e4..f96b08dc50a 100644
--- a/chromium/ui/views/corewm/tooltip_controller_test_helper.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_test_helper.cc
@@ -19,7 +19,7 @@ TooltipControllerTestHelper::TooltipControllerTestHelper(
TooltipControllerTestHelper::~TooltipControllerTestHelper() {
}
-string16 TooltipControllerTestHelper::GetTooltipText() {
+base::string16 TooltipControllerTestHelper::GetTooltipText() {
return controller_->tooltip_text_;
}
@@ -55,7 +55,7 @@ TooltipTestView::~TooltipTestView() {
}
bool TooltipTestView::GetTooltipText(const gfx::Point& p,
- string16* tooltip) const {
+ base::string16* tooltip) const {
*tooltip = tooltip_text_;
return true;
}
diff --git a/chromium/ui/views/corewm/tooltip_controller_test_helper.h b/chromium/ui/views/corewm/tooltip_controller_test_helper.h
index 58386200000..4451ff35fec 100644
--- a/chromium/ui/views/corewm/tooltip_controller_test_helper.h
+++ b/chromium/ui/views/corewm/tooltip_controller_test_helper.h
@@ -31,7 +31,7 @@ class TooltipControllerTestHelper {
TooltipController* controller() { return controller_; }
// These are mostly cover methods for TooltipController private methods.
- string16 GetTooltipText();
+ base::string16 GetTooltipText();
aura::Window* GetTooltipWindow();
void FireTooltipTimer();
bool IsTooltipTimerRunning();
@@ -51,14 +51,16 @@ class TooltipTestView : public views::View {
TooltipTestView();
virtual ~TooltipTestView();
- void set_tooltip_text(string16 tooltip_text) { tooltip_text_ = tooltip_text; }
+ void set_tooltip_text(base::string16 tooltip_text) {
+ tooltip_text_ = tooltip_text;
+ }
// Overridden from views::View
virtual bool GetTooltipText(const gfx::Point& p,
- string16* tooltip) const OVERRIDE;
+ base::string16* tooltip) const OVERRIDE;
private:
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
DISALLOW_COPY_AND_ASSIGN(TooltipTestView);
};
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index 6ebf4b9f828..e3487ae854b 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -7,14 +7,13 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
-#include "ui/aura/client/window_types.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_screen.h"
+#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/font.h"
#include "ui/gfx/point.h"
@@ -23,9 +22,15 @@
#include "ui/gfx/text_elider.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/corewm/tooltip_controller_test_helper.h"
+#include "ui/views/test/desktop_test_views_delegate.h"
+#include "ui/views/test/test_views_delegate.h"
#include "ui/views/view.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/core/default_activation_client.h"
+#include "ui/wm/core/wm_state.h"
+#include "ui/wm/public/tooltip_client.h"
+#include "ui/wm/public/window_types.h"
#if defined(OS_WIN)
#include "ui/base/win/scoped_ole_initializer.h"
@@ -36,6 +41,8 @@
#include "ui/views/widget/desktop_aura/desktop_screen.h"
#endif
+using base::ASCIIToUTF16;
+
namespace views {
namespace corewm {
namespace test {
@@ -72,7 +79,14 @@ class TooltipControllerTest : public aura::test::AuraTestBase {
virtual ~TooltipControllerTest() {}
virtual void SetUp() OVERRIDE {
+#if defined(OS_CHROMEOS)
+ views_delegate_.reset(new TestViewsDelegate);
+#else
+ views_delegate_.reset(new DesktopTestViewsDelegate);
+#endif
+
aura::test::AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
#if defined(OS_CHROMEOS)
controller_.reset(new TooltipController(
scoped_ptr<views::corewm::Tooltip>(
@@ -100,6 +114,7 @@ class TooltipControllerTest : public aura::test::AuraTestBase {
helper_.reset();
widget_.reset();
aura::test::AuraTestBase::TearDown();
+ views_delegate_.reset();
}
protected:
@@ -126,6 +141,9 @@ class TooltipControllerTest : public aura::test::AuraTestBase {
private:
scoped_ptr<TooltipController> controller_;
+
+ scoped_ptr<views::TestViewsDelegate> views_delegate_;
+
#if defined(OS_WIN)
ui::ScopedOleInitializer ole_initializer_;
#endif
@@ -135,15 +153,15 @@ class TooltipControllerTest : public aura::test::AuraTestBase {
TEST_F(TooltipControllerTest, ViewTooltip) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
generator_->MoveMouseToCenterOf(GetWindow());
EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint(
generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
// Fire tooltip timer so tooltip becomes visible.
@@ -160,7 +178,7 @@ TEST_F(TooltipControllerTest, ViewTooltip) {
TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
PrepareSecondView();
@@ -176,7 +194,7 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
EXPECT_TRUE(helper_->IsTooltipVisible());
EXPECT_EQ(window, root_window->GetEventHandlerForPoint(
generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -186,7 +204,7 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
EXPECT_FALSE(helper_->IsTooltipVisible());
EXPECT_EQ(window, root_window->GetEventHandlerForPoint(
generator_->current_location()));
- string16 expected_tooltip; // = ""
+ base::string16 expected_tooltip; // = ""
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -195,11 +213,11 @@ TEST_F(TooltipControllerTest, TooltipsInMultipleViews) {
TEST_F(TooltipControllerTest, EnableOrDisableTooltips) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
// Fire tooltip timer so tooltip becomes visible.
helper_->FireTooltipTimer();
@@ -221,7 +239,7 @@ TEST_F(TooltipControllerTest, EnableOrDisableTooltips) {
// Verifies tooltip isn't shown if tooltip text consists entirely of whitespace.
TEST_F(TooltipControllerTest, DontShowEmptyTooltips) {
view_->set_tooltip_text(ASCIIToUTF16(" "));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
generator_->MoveMouseRelativeTo(GetWindow(), view_->bounds().CenterPoint());
@@ -232,7 +250,7 @@ TEST_F(TooltipControllerTest, DontShowEmptyTooltips) {
TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
TooltipTestView* view2 = PrepareSecondView();
@@ -261,7 +279,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
EXPECT_EQ(window,
GetRootWindow()->GetEventHandlerForPoint(
generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -273,7 +291,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
helper_->FireTooltipTimer();
EXPECT_TRUE(helper_->IsTooltipVisible());
EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -281,7 +299,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnKeyPressAndStaysHiddenUntilChange) {
TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text for view 1"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(NULL, helper_->GetTooltipWindow());
TooltipTestView* view2 = PrepareSecondView();
@@ -309,7 +327,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
EXPECT_FALSE(helper_->IsTooltipShownTimerRunning());
EXPECT_EQ(window, GetRootWindow()->GetEventHandlerForPoint(
generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 1");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -321,7 +339,7 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
helper_->FireTooltipTimer();
EXPECT_TRUE(helper_->IsTooltipVisible());
EXPECT_TRUE(helper_->IsTooltipShownTimerRunning());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text for view 2");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
EXPECT_EQ(window, helper_->GetTooltipWindow());
@@ -331,9 +349,9 @@ TEST_F(TooltipControllerTest, TooltipHidesOnTimeoutAndStaysHiddenUntilChange) {
TEST_F(TooltipControllerTest, HideOnExit) {
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
generator_->MoveMouseToCenterOf(GetWindow());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
// Fire tooltip timer so tooltip becomes visible.
@@ -344,6 +362,44 @@ TEST_F(TooltipControllerTest, HideOnExit) {
EXPECT_FALSE(helper_->IsTooltipVisible());
}
+TEST_F(TooltipControllerTest, ReshowOnClickAfterEnterExit) {
+ // Owned by |view_|.
+ TooltipTestView* v1 = new TooltipTestView;
+ TooltipTestView* v2 = new TooltipTestView;
+ view_->AddChildView(v1);
+ view_->AddChildView(v2);
+ gfx::Rect view_bounds(view_->GetLocalBounds());
+ view_bounds.set_height(view_bounds.height() / 2);
+ v1->SetBoundsRect(view_bounds);
+ view_bounds.set_y(view_bounds.height());
+ v2->SetBoundsRect(view_bounds);
+ const base::string16 v1_tt(ASCIIToUTF16("v1"));
+ const base::string16 v2_tt(ASCIIToUTF16("v2"));
+ v1->set_tooltip_text(v1_tt);
+ v2->set_tooltip_text(v2_tt);
+
+ gfx::Point v1_point(1, 1);
+ View::ConvertPointToWidget(v1, &v1_point);
+ generator_->MoveMouseRelativeTo(GetWindow(), v1_point);
+
+ // Fire tooltip timer so tooltip becomes visible.
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(v1_tt, helper_->GetTooltipText());
+
+ // Press the mouse, move to v2 and back to v1.
+ generator_->ClickLeftButton();
+
+ gfx::Point v2_point(1, 1);
+ View::ConvertPointToWidget(v2, &v2_point);
+ generator_->MoveMouseRelativeTo(GetWindow(), v2_point);
+ generator_->MoveMouseRelativeTo(GetWindow(), v1_point);
+
+ helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(v1_tt, helper_->GetTooltipText());
+}
+
namespace {
// Returns the index of |window| in its parent's children.
@@ -419,11 +475,12 @@ class TooltipControllerCaptureTest : public TooltipControllerTest {
// Verifies when capture is released the TooltipController resets state.
TEST_F(TooltipControllerCaptureTest, CloseOnCaptureLost) {
view_->GetWidget()->SetCapture(view_);
+ RunAllPendingInMessageLoop();
view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
generator_->MoveMouseToCenterOf(GetWindow());
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
+ base::string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
+ EXPECT_EQ(base::string16(), helper_->GetTooltipText());
EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
// Fire tooltip timer so tooltip becomes visible.
@@ -444,8 +501,8 @@ TEST_F(TooltipControllerCaptureTest, CloseOnCaptureLost) {
#endif
// Verifies the correct window is found for tooltips when there is a capture.
TEST_F(TooltipControllerCaptureTest, MAYBE_Capture) {
- const string16 tooltip_text(ASCIIToUTF16("1"));
- const string16 tooltip_text2(ASCIIToUTF16("2"));
+ const base::string16 tooltip_text(ASCIIToUTF16("1"));
+ const base::string16 tooltip_text2(ASCIIToUTF16("2"));
widget_->SetBounds(gfx::Rect(0, 0, 200, 200));
view_->set_tooltip_text(tooltip_text);
@@ -490,120 +547,285 @@ TEST_F(TooltipControllerCaptureTest, MAYBE_Capture) {
widget2.reset();
}
-#if !defined(OS_CHROMEOS)
-// This test creates two top level windows and verifies that the tooltip
-// displays correctly when mouse moves are dispatched to these windows.
-// Additionally it also verifies that the tooltip is reparented to the new
-// window when mouse moves are dispatched to it.
-TEST_F(TooltipControllerTest, TooltipsInMultipleRootWindows) {
- view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow1"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
- EXPECT_EQ(NULL, helper_->GetTooltipWindow());
+namespace {
- aura::Window* window = GetWindow();
- aura::Window* root_window = GetRootWindow();
+class TestTooltip : public Tooltip {
+ public:
+ TestTooltip() : is_visible_(false) {}
+ virtual ~TestTooltip() {}
- // Fire tooltip timer so tooltip becomes visible.
- generator_->MoveMouseRelativeTo(window, view_->bounds().CenterPoint());
- helper_->FireTooltipTimer();
- EXPECT_TRUE(helper_->IsTooltipVisible());
- for (int i = 0; i < 49; ++i) {
- generator_->MoveMouseBy(1, 0);
- EXPECT_TRUE(helper_->IsTooltipVisible());
- EXPECT_EQ(window, root_window->GetEventHandlerForPoint(
- generator_->current_location()));
- string16 expected_tooltip =
- ASCIIToUTF16("Tooltip Text For RootWindow1");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window));
- EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
- EXPECT_EQ(window, helper_->GetTooltipWindow());
+ const base::string16& tooltip_text() const { return tooltip_text_; }
+
+ // Tooltip:
+ virtual void SetText(aura::Window* window,
+ const base::string16& tooltip_text,
+ const gfx::Point& location) OVERRIDE {
+ tooltip_text_ = tooltip_text;
+ location_ = location;
+ }
+ virtual void Show() OVERRIDE {
+ is_visible_ = true;
}
+ virtual void Hide() OVERRIDE {
+ is_visible_ = false;
+ }
+ virtual bool IsVisible() OVERRIDE {
+ return is_visible_;
+ }
+ const gfx::Point& location() { return location_; }
+
+ private:
+ bool is_visible_;
+ base::string16 tooltip_text_;
+ gfx::Point location_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTooltip);
+};
+
+} // namespace
+
+// Use for tests that don't depend upon views.
+class TooltipControllerTest2 : public aura::test::AuraTestBase {
+ public:
+ TooltipControllerTest2() : test_tooltip_(new TestTooltip) {}
+ virtual ~TooltipControllerTest2() {}
+
+ virtual void SetUp() OVERRIDE {
+ wm_state_.reset(new wm::WMState);
+ aura::test::AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
+ controller_.reset(new TooltipController(
+ scoped_ptr<corewm::Tooltip>(test_tooltip_)));
+ root_window()->AddPreTargetHandler(controller_.get());
+ SetTooltipClient(root_window(), controller_.get());
+ helper_.reset(new TooltipControllerTestHelper(controller_.get()));
+ generator_.reset(new aura::test::EventGenerator(root_window()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ root_window()->RemovePreTargetHandler(controller_.get());
+ aura::client::SetTooltipClient(root_window(), NULL);
+ controller_.reset();
+ generator_.reset();
+ helper_.reset();
+ aura::test::AuraTestBase::TearDown();
+ wm_state_.reset();
+ }
+
+ protected:
+ // Owned by |controller_|.
+ TestTooltip* test_tooltip_;
+ scoped_ptr<TooltipControllerTestHelper> helper_;
+ scoped_ptr<aura::test::EventGenerator> generator_;
+
+ private:
+ scoped_ptr<TooltipController> controller_;
+ scoped_ptr<wm::WMState> wm_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest2);
+};
+
+TEST_F(TooltipControllerTest2, VerifyLeadingTrailingWhitespaceStripped) {
+ aura::test::TestWindowDelegate test_delegate;
+ scoped_ptr<aura::Window> window(
+ CreateNormalWindow(100, root_window(), &test_delegate));
+ window->SetBounds(gfx::Rect(0, 0, 300, 300));
+ base::string16 tooltip_text(ASCIIToUTF16(" \nx "));
+ aura::client::SetTooltipText(window.get(), &tooltip_text);
+ generator_->MoveMouseToCenterOf(window.get());
+ helper_->FireTooltipTimer();
+ EXPECT_EQ(ASCIIToUTF16("x"), test_tooltip_->tooltip_text());
+}
+
+// Verifies that tooltip is hidden and tooltip window closed upon cancel mode.
+TEST_F(TooltipControllerTest2, CloseOnCancelMode) {
+ aura::test::TestWindowDelegate test_delegate;
+ scoped_ptr<aura::Window> window(
+ CreateNormalWindow(100, root_window(), &test_delegate));
+ window->SetBounds(gfx::Rect(0, 0, 300, 300));
+ base::string16 tooltip_text(ASCIIToUTF16("Tooltip Text"));
+ aura::client::SetTooltipText(window.get(), &tooltip_text);
+ generator_->MoveMouseToCenterOf(window.get());
- views::Widget* widget2 = CreateWidget(NULL);
- widget2->SetContentsView(new View);
- TooltipTestView* view2 = new TooltipTestView;
- widget2->GetContentsView()->AddChildView(view2);
- view2->SetBoundsRect(widget2->GetContentsView()->GetLocalBounds());
- helper_.reset(new TooltipControllerTestHelper(
- GetController(widget2)));
- generator_.reset(new aura::test::EventGenerator(
- widget2->GetNativeWindow()->GetRootWindow()));
- view2->set_tooltip_text(ASCIIToUTF16("Tooltip Text For RootWindow2"));
-
- aura::Window* window2 = widget2->GetNativeWindow();
- aura::Window* root_window2 =
- widget2->GetNativeWindow()->GetRootWindow();
// Fire tooltip timer so tooltip becomes visible.
- generator_->MoveMouseRelativeTo(window2, view2->bounds().CenterPoint());
helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
- EXPECT_NE(root_window, root_window2);
- EXPECT_NE(window, window2);
+ // Send OnCancelMode event and verify that tooltip becomes invisible and
+ // the tooltip window is closed.
+ ui::CancelModeEvent event;
+ helper_->controller()->OnCancelMode(&event);
+ EXPECT_FALSE(helper_->IsTooltipVisible());
+ EXPECT_TRUE(helper_->GetTooltipWindow() == NULL);
+}
- for (int i = 0; i < 49; ++i) {
- generator_->MoveMouseBy(1, 0);
- EXPECT_TRUE(helper_->IsTooltipVisible());
- EXPECT_EQ(window2, root_window2->GetEventHandlerForPoint(
- generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text For RootWindow2");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(window2));
- EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
- EXPECT_EQ(window2, helper_->GetTooltipWindow());
+// Use for tests that need both views and a TestTooltip.
+class TooltipControllerTest3 : public aura::test::AuraTestBase {
+ public:
+ TooltipControllerTest3() : test_tooltip_(new TestTooltip) {}
+ virtual ~TooltipControllerTest3() {}
+
+ virtual void SetUp() OVERRIDE {
+ wm_state_.reset(new wm::WMState);
+ aura::test::AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
+
+ widget_.reset(CreateWidget(root_window()));
+ widget_->SetContentsView(new View);
+ view_ = new TooltipTestView;
+ widget_->GetContentsView()->AddChildView(view_);
+ view_->SetBoundsRect(widget_->GetContentsView()->GetLocalBounds());
+
+ generator_.reset(new aura::test::EventGenerator(GetRootWindow()));
+ controller_.reset(new TooltipController(
+ scoped_ptr<views::corewm::Tooltip>(test_tooltip_)));
+ GetRootWindow()->RemovePreTargetHandler(
+ static_cast<TooltipController*>(aura::client::GetTooltipClient(
+ widget_->GetNativeWindow()->GetRootWindow())));
+ GetRootWindow()->AddPreTargetHandler(controller_.get());
+ helper_.reset(new TooltipControllerTestHelper(controller_.get()));
+ SetTooltipClient(GetRootWindow(), controller_.get());
}
- bool tooltip_reparented = false;
- for (size_t i = 0; i < root_window2->children().size(); ++i) {
- if (root_window2->children()[i]->type() ==
- aura::client::WINDOW_TYPE_TOOLTIP) {
- tooltip_reparented = true;
- break;
- }
+ virtual void TearDown() OVERRIDE {
+ GetRootWindow()->RemovePreTargetHandler(controller_.get());
+ aura::client::SetTooltipClient(GetRootWindow(), NULL);
+
+ controller_.reset();
+ generator_.reset();
+ helper_.reset();
+ widget_.reset();
+ aura::test::AuraTestBase::TearDown();
+ wm_state_.reset();
}
- EXPECT_TRUE(tooltip_reparented);
- widget2->Close();
-}
-// This test validates whether the tooltip after becoming visible stays at the
-// top of the ZOrder in its root window after activation changes.
-TEST_F(TooltipControllerTest, TooltipAtTopOfZOrderAfterActivation) {
- view_->set_tooltip_text(ASCIIToUTF16("Tooltip Text"));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
- EXPECT_EQ(NULL, helper_->GetTooltipWindow());
- generator_->MoveMouseToCenterOf(GetWindow());
+ aura::Window* GetWindow() { return widget_->GetNativeWindow(); }
- EXPECT_EQ(GetWindow(), GetRootWindow()->GetEventHandlerForPoint(
- generator_->current_location()));
- string16 expected_tooltip = ASCIIToUTF16("Tooltip Text");
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
- EXPECT_EQ(string16(), helper_->GetTooltipText());
- EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
+ protected:
+ // Owned by |controller_|.
+ TestTooltip* test_tooltip_;
+ scoped_ptr<TooltipControllerTestHelper> helper_;
+ scoped_ptr<aura::test::EventGenerator> generator_;
+ scoped_ptr<views::Widget> widget_;
+ TooltipTestView* view_;
- // Fire tooltip timer so tooltip becomes visible.
+ private:
+ scoped_ptr<TooltipController> controller_;
+ scoped_ptr<wm::WMState> wm_state_;
+
+#if defined(OS_WIN)
+ ui::ScopedOleInitializer ole_initializer_;
+#endif
+
+ aura::Window* GetRootWindow() { return GetWindow()->GetRootWindow(); }
+
+ DISALLOW_COPY_AND_ASSIGN(TooltipControllerTest3);
+};
+
+TEST_F(TooltipControllerTest3, TooltipPositionChangesOnTwoViewsWithSameLabel) {
+ // Owned by |view_|.
+ // These two views have the same tooltip text
+ TooltipTestView* v1 = new TooltipTestView;
+ TooltipTestView* v2 = new TooltipTestView;
+ // v1_1 is a view inside v1 that has an identical tooltip text to that of v1
+ // and v2
+ TooltipTestView* v1_1 = new TooltipTestView;
+ // v2_1 is a view inside v2 that has an identical tooltip text to that of v1
+ // and v2
+ TooltipTestView* v2_1 = new TooltipTestView;
+ // v2_2 is a view inside v2 with the tooltip text different from all the
+ // others
+ TooltipTestView* v2_2 = new TooltipTestView;
+
+ // Setup all the views' relations
+ view_->AddChildView(v1);
+ view_->AddChildView(v2);
+ v1->AddChildView(v1_1);
+ v2->AddChildView(v2_1);
+ v2->AddChildView(v2_2);
+ const base::string16 reference_string(
+ base::ASCIIToUTF16("Identical Tooltip Text"));
+ const base::string16 alternative_string(
+ base::ASCIIToUTF16("Another Shrubbery"));
+ v1->set_tooltip_text(reference_string);
+ v2->set_tooltip_text(reference_string);
+ v1_1->set_tooltip_text(reference_string);
+ v2_1->set_tooltip_text(reference_string);
+ v2_2->set_tooltip_text(alternative_string);
+
+ // Set views' bounds
+ gfx::Rect view_bounds(view_->GetLocalBounds());
+ view_bounds.set_height(view_bounds.height() / 2);
+ v1->SetBoundsRect(view_bounds);
+ v1_1->SetBounds(0, 0, 3, 3);
+ view_bounds.set_y(view_bounds.height());
+ v2->SetBoundsRect(view_bounds);
+ v2_2->SetBounds(view_bounds.width() - 3, view_bounds.height() - 3, 3, 3);
+ v2_1->SetBounds(0, 0, 3, 3);
+
+ // Test whether a toolbar appears on v1
+ gfx::Point center = v1->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
helper_->FireTooltipTimer();
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+ gfx::Point tooltip_bounds1 = test_tooltip_->location();
+ // Test whether the toolbar changes position on mouse over v2
+ center = v2->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
EXPECT_TRUE(helper_->IsTooltipVisible());
- generator_->MoveMouseBy(1, 0);
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+ gfx::Point tooltip_bounds2 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds1, gfx::Point());
+ EXPECT_NE(tooltip_bounds2, gfx::Point());
+ EXPECT_NE(tooltip_bounds1, tooltip_bounds2);
+
+ // Test if the toolbar does not change position on encountering a contained
+ // view with the same tooltip text
+ center = v2_1->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v2_1, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds2_1 = test_tooltip_->location();
+ EXPECT_NE(tooltip_bounds2, tooltip_bounds2_1);
EXPECT_TRUE(helper_->IsTooltipVisible());
- EXPECT_EQ(expected_tooltip, aura::client::GetTooltipText(GetWindow()));
- EXPECT_EQ(expected_tooltip, helper_->GetTooltipText());
- EXPECT_EQ(GetWindow(), helper_->GetTooltipWindow());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+
+ // Test if the toolbar changes position on encountering a contained
+ // view with a different tooltip text
+ center = v2_2->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v2_2, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds2_2 = test_tooltip_->location();
- // Fake activation loss and gain in the native widget. This should cause a
- // ZOrder change which should not affect the position of the tooltip.
- DesktopNativeWidgetAura* native_widget =
- static_cast<DesktopNativeWidgetAura*>(widget_->native_widget());
- EXPECT_TRUE(native_widget != NULL);
+ EXPECT_NE(tooltip_bounds2_1, tooltip_bounds2_2);
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(alternative_string, helper_->GetTooltipText());
- native_widget->HandleActivationChanged(false);
- native_widget->HandleActivationChanged(true);
+ // Test if moving from a view that is contained by a larger view, both with
+ // the same tooltip text, does not change tooltip's position.
+ center = v1_1->GetLocalBounds().CenterPoint();
+ views::View::ConvertPointToTarget(v1_1, view_, &center);
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ gfx::Point tooltip_bounds1_1 = test_tooltip_->location();
- EXPECT_EQ(
- widget_->GetNativeWindow()->GetRootWindow()->children().back()->type(),
- aura::client::WINDOW_TYPE_TOOLTIP);
-}
+ EXPECT_TRUE(helper_->IsTooltipVisible());
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
-#endif
+ center = v1->bounds().CenterPoint();
+ generator_->MoveMouseRelativeTo(GetWindow(), center);
+ helper_->FireTooltipTimer();
+ tooltip_bounds1 = test_tooltip_->location();
+
+ EXPECT_NE(tooltip_bounds1_1, tooltip_bounds1);
+ EXPECT_EQ(reference_string, helper_->GetTooltipText());
+}
} // namespace test
} // namespace corewm
diff --git a/chromium/ui/views/corewm/tooltip_win.cc b/chromium/ui/views/corewm/tooltip_win.cc
index 10341d61635..4d2a4badb0e 100644
--- a/chromium/ui/views/corewm/tooltip_win.cc
+++ b/chromium/ui/views/corewm/tooltip_win.cc
@@ -12,6 +12,8 @@
#include "ui/base/l10n/l10n_util_win.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/win/dpi.h"
+#include "ui/views/corewm/cursor_height_provider_win.h"
namespace views {
namespace corewm {
@@ -63,7 +65,7 @@ bool TooltipWin::EnsureTooltipWindow() {
TOOLTIPS_CLASS, NULL, TTS_NOPREFIX | WS_POPUP, 0, 0, 0, 0,
parent_hwnd_, NULL, NULL, NULL);
if (!tooltip_hwnd_) {
- LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips";
+ PLOG(WARNING) << "tooltip creation failed, disabling tooltips";
return false;
}
@@ -76,20 +78,19 @@ bool TooltipWin::EnsureTooltipWindow() {
void TooltipWin::PositionTooltip() {
// This code only runs for non-metro, so GetNativeScreen() is fine.
- gfx::Display display(
- gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(location_));
+ gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_);
+ const int cursoroffset = GetCurrentCursorVisibleHeight();
+ screen_point.Offset(0, cursoroffset);
DWORD tooltip_size = SendMessage(tooltip_hwnd_, TTM_GETBUBBLESIZE, 0,
reinterpret_cast<LPARAM>(&toolinfo_));
- // 20 accounts for visible cursor size. I tried using SM_CYCURSOR but that's
- // way too big (32 on win7 default).
- // TODO(sky): figure out the right way to determine offset.
- const int initial_y = location_.y();
- gfx::Rect tooltip_bounds(location_.x(), initial_y + 20,
- LOWORD(tooltip_size), HIWORD(tooltip_size));
- tooltip_bounds.AdjustToFit(display.work_area());
- if (tooltip_bounds.y() < initial_y)
- tooltip_bounds.set_y(initial_y - tooltip_bounds.height() - 2);
+ const gfx::Size size(LOWORD(tooltip_size), HIWORD(tooltip_size));
+
+ const gfx::Display display(
+ gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));
+
+ gfx::Rect tooltip_bounds(screen_point, size);
+ tooltip_bounds.AdjustToFit(gfx::win::DIPToScreenRect(display.work_area()));
SetWindowPos(tooltip_hwnd_, NULL, tooltip_bounds.x(), tooltip_bounds.y(), 0,
0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
@@ -116,8 +117,9 @@ void TooltipWin::SetText(aura::Window* window,
reinterpret_cast<LPARAM>(&toolinfo_));
// This code only runs for non-metro, so GetNativeScreen() is fine.
+ const gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_);
gfx::Display display(
- gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(location_));
+ gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));
const gfx::Rect monitor_bounds = display.bounds();
int max_width = (monitor_bounds.width() + 1) / 2;
SendMessage(tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, max_width);
@@ -134,7 +136,7 @@ void TooltipWin::Show() {
}
void TooltipWin::Hide() {
- if (!EnsureTooltipWindow())
+ if (!tooltip_hwnd_)
return;
SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE, FALSE,
diff --git a/chromium/ui/views/corewm/tooltip_win.h b/chromium/ui/views/corewm/tooltip_win.h
index e454aac8773..b031a3204eb 100644
--- a/chromium/ui/views/corewm/tooltip_win.h
+++ b/chromium/ui/views/corewm/tooltip_win.h
@@ -24,7 +24,7 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
explicit TooltipWin(HWND parent);
virtual ~TooltipWin();
- // HandleNotify() is forwarded from DesktopRootWindowHostWin to keep the
+ // HandleNotify() is forwarded from DesktopWindowTreeHostWin to keep the
// native tooltip in sync.
bool HandleNotify(int w_param, NMHDR* l_param, LRESULT* l_result);
diff --git a/chromium/ui/views/corewm/transient_window_stacking_client.cc b/chromium/ui/views/corewm/transient_window_stacking_client.cc
deleted file mode 100644
index 6a4f8ab25cb..00000000000
--- a/chromium/ui/views/corewm/transient_window_stacking_client.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/transient_window_stacking_client.h"
-
-#include <algorithm>
-
-using aura::Window;
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-// Populates |ancestors| with all transient ancestors of |window| that are
-// siblings of |window|. Returns true if any ancestors were found, false if not.
-bool GetAllTransientAncestors(Window* window, Window::Windows* ancestors) {
- Window* parent = window->parent();
- for (; window; window = window->transient_parent()) {
- if (window->parent() == parent)
- ancestors->push_back(window);
- }
- return (!ancestors->empty());
-}
-
-// Replaces |window1| and |window2| with their possible transient ancestors that
-// are still siblings (have a common transient parent). |window1| and |window2|
-// are not modified if such ancestors cannot be found.
-void FindCommonTransientAncestor(Window** window1, Window** window2) {
- DCHECK(window1);
- DCHECK(window2);
- DCHECK(*window1);
- DCHECK(*window2);
- // Assemble chains of ancestors of both windows.
- Window::Windows ancestors1;
- Window::Windows ancestors2;
- if (!GetAllTransientAncestors(*window1, &ancestors1) ||
- !GetAllTransientAncestors(*window2, &ancestors2)) {
- return;
- }
- // Walk the two chains backwards and look for the first difference.
- Window::Windows::const_reverse_iterator it1 = ancestors1.rbegin();
- Window::Windows::const_reverse_iterator it2 = ancestors2.rbegin();
- for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) {
- if (*it1 != *it2) {
- *window1 = *it1;
- *window2 = *it2;
- break;
- }
- }
-}
-
-// Returns true if |window| has |ancestor| as a transient ancestor. A transient
-// ancestor is found by following the transient parent chain of the window.
-bool HasTransientAncestor(const Window* window, const Window* ancestor) {
- if (window->transient_parent() == ancestor)
- return true;
- return window->transient_parent() ?
- HasTransientAncestor(window->transient_parent(), ancestor) : false;
-}
-
-} // namespace
-
-TransientWindowStackingClient::TransientWindowStackingClient() {
-}
-
-TransientWindowStackingClient::~TransientWindowStackingClient() {
-}
-
-void TransientWindowStackingClient::AdjustStacking(
- Window** child,
- Window** target,
- Window::StackDirection* direction) {
- // For windows that have transient children stack the transient ancestors that
- // are siblings. This prevents one transient group from being inserted in the
- // middle of another.
- FindCommonTransientAncestor(child, target);
-
- // When stacking above skip to the topmost transient descendant of the target.
- if (*direction == Window::STACK_ABOVE &&
- !HasTransientAncestor(*child, *target)) {
- const Window::Windows& siblings((*child)->parent()->children());
- size_t target_i =
- std::find(siblings.begin(), siblings.end(), *target) - siblings.begin();
- while (target_i + 1 < siblings.size() &&
- HasTransientAncestor(siblings[target_i + 1], *target)) {
- ++target_i;
- }
- *target = siblings[target_i];
- }
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/transient_window_stacking_client.h b/chromium/ui/views/corewm/transient_window_stacking_client.h
deleted file mode 100644
index 19358362bcb..00000000000
--- a/chromium/ui/views/corewm/transient_window_stacking_client.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_
-#define UI_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_
-
-#include "ui/aura/client/window_stacking_client.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-
-class VIEWS_EXPORT TransientWindowStackingClient
- : public aura::client::WindowStackingClient {
- public:
- TransientWindowStackingClient();
- virtual ~TransientWindowStackingClient();
-
- // WindowStackingClient:
- virtual void AdjustStacking(aura::Window** child,
- aura::Window** target,
- aura::Window::StackDirection* direction) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClient);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_TRANSIENT_WINDOW_STACKING_CLIENT_H_
diff --git a/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc b/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc
deleted file mode 100644
index a84b832e596..00000000000
--- a/chromium/ui/views/corewm/transient_window_stacking_client_unittest.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/transient_window_stacking_client.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/test_windows.h"
-
-using aura::test::ChildWindowIDsAsString;
-using aura::test::CreateTestWindowWithId;
-using aura::Window;
-
-namespace views {
-namespace corewm {
-
-class TransientWindowStackingClientTest : public aura::test::AuraTestBase {
- public:
- TransientWindowStackingClientTest() {}
- virtual ~TransientWindowStackingClientTest() {}
-
- virtual void SetUp() OVERRIDE {
- AuraTestBase::SetUp();
- aura::client::SetWindowStackingClient(new TransientWindowStackingClient);
- }
-
- virtual void TearDown() OVERRIDE {
- aura::client::SetWindowStackingClient(NULL);
- AuraTestBase::TearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransientWindowStackingClientTest);
-};
-
-// Tests that transient children are stacked as a unit when using stack above.
-TEST_F(TransientWindowStackingClientTest, TransientChildrenGroupAbove) {
- scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
- scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
- Window* w11 = CreateTestWindowWithId(11, parent.get());
- scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get()));
- Window* w21 = CreateTestWindowWithId(21, parent.get());
- Window* w211 = CreateTestWindowWithId(211, parent.get());
- Window* w212 = CreateTestWindowWithId(212, parent.get());
- Window* w213 = CreateTestWindowWithId(213, parent.get());
- Window* w22 = CreateTestWindowWithId(22, parent.get());
- ASSERT_EQ(8u, parent->children().size());
-
- w1->AddTransientChild(w11); // w11 is now owned by w1.
- w2->AddTransientChild(w21); // w21 is now owned by w2.
- w2->AddTransientChild(w22); // w22 is now owned by w2.
- w21->AddTransientChild(w211); // w211 is now owned by w21.
- w21->AddTransientChild(w212); // w212 is now owned by w21.
- w21->AddTransientChild(w213); // w213 is now owned by w21.
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- // Stack w1 at the top (end), this should force w11 to be last (on top of w1).
- parent->StackChildAtTop(w1.get());
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
-
- // This tests that the order in children_ array rather than in
- // transient_children_ array is used when reinserting transient children.
- // If transient_children_ array was used '22' would be following '21'.
- parent->StackChildAtTop(w2.get());
- EXPECT_EQ(w22, parent->children().back());
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w11, w2.get());
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w21, w1.get());
- EXPECT_EQ(w22, parent->children().back());
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w21, w22);
- EXPECT_EQ(w213, parent->children().back());
- EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w11, w21);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w213, w21);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-
- // No change when stacking a transient parent above its transient child.
- parent->StackChildAbove(w21, w211);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-
- // This tests that the order in children_ array rather than in
- // transient_children_ array is used when reinserting transient children.
- // If transient_children_ array was used '22' would be following '21'.
- parent->StackChildAbove(w2.get(), w1.get());
- EXPECT_EQ(w212, parent->children().back());
- EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAbove(w11, w213);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-}
-
-// Tests that transient children are stacked as a unit when using stack below.
-TEST_F(TransientWindowStackingClientTest, TransientChildrenGroupBelow) {
- scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
- scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
- Window* w11 = CreateTestWindowWithId(11, parent.get());
- scoped_ptr<Window> w2(CreateTestWindowWithId(2, parent.get()));
- Window* w21 = CreateTestWindowWithId(21, parent.get());
- Window* w211 = CreateTestWindowWithId(211, parent.get());
- Window* w212 = CreateTestWindowWithId(212, parent.get());
- Window* w213 = CreateTestWindowWithId(213, parent.get());
- Window* w22 = CreateTestWindowWithId(22, parent.get());
- ASSERT_EQ(8u, parent->children().size());
-
- w1->AddTransientChild(w11); // w11 is now owned by w1.
- w2->AddTransientChild(w21); // w21 is now owned by w2.
- w2->AddTransientChild(w22); // w22 is now owned by w2.
- w21->AddTransientChild(w211); // w211 is now owned by w21.
- w21->AddTransientChild(w212); // w212 is now owned by w21.
- w21->AddTransientChild(w213); // w213 is now owned by w21.
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- // Stack w2 at the bottom, this should force w11 to be last (on top of w1).
- // This also tests that the order in children_ array rather than in
- // transient_children_ array is used when reinserting transient children.
- // If transient_children_ array was used '22' would be following '21'.
- parent->StackChildAtBottom(w2.get());
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildAtBottom(w1.get());
- EXPECT_EQ(w22, parent->children().back());
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w21, w1.get());
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 21 211 212 213 22 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w11, w2.get());
- EXPECT_EQ(w22, parent->children().back());
- EXPECT_EQ("1 11 2 21 211 212 213 22", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w22, w21);
- EXPECT_EQ(w213, parent->children().back());
- EXPECT_EQ("1 11 2 22 21 211 212 213", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w21, w11);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 211 212 213 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w213, w211);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-
- // No change when stacking a transient parent below its transient child.
- parent->StackChildBelow(w21, w211);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w1.get(), w2.get());
- EXPECT_EQ(w212, parent->children().back());
- EXPECT_EQ("1 11 2 22 21 213 211 212", ChildWindowIDsAsString(parent.get()));
-
- parent->StackChildBelow(w213, w11);
- EXPECT_EQ(w11, parent->children().back());
- EXPECT_EQ("2 22 21 213 211 212 1 11", ChildWindowIDsAsString(parent.get()));
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/visibility_controller.cc b/chromium/ui/views/corewm/visibility_controller.cc
deleted file mode 100644
index 4542f41c669..00000000000
--- a/chromium/ui/views/corewm/visibility_controller.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/visibility_controller.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-#include "ui/compositor/layer.h"
-#include "ui/views/corewm/window_animations.h"
-
-namespace views {
-namespace corewm {
-
-namespace {
-
-// Property set on all windows whose child windows' visibility changes are
-// animated.
-DEFINE_WINDOW_PROPERTY_KEY(
- bool, kChildWindowVisibilityChangesAnimatedKey, false);
-
-bool ShouldAnimateWindow(aura::Window* window) {
- return window->parent() && window->parent()->GetProperty(
- kChildWindowVisibilityChangesAnimatedKey);
-}
-
-} // namespace
-
-VisibilityController::VisibilityController() {
-}
-
-VisibilityController::~VisibilityController() {
-}
-
-bool VisibilityController::CallAnimateOnChildWindowVisibilityChanged(
- aura::Window* window,
- bool visible) {
- return AnimateOnChildWindowVisibilityChanged(window, visible);
-}
-
-void VisibilityController::UpdateLayerVisibility(aura::Window* window,
- bool visible) {
- bool animated = window->type() != aura::client::WINDOW_TYPE_CONTROL &&
- window->type() != aura::client::WINDOW_TYPE_UNKNOWN &&
- ShouldAnimateWindow(window);
- animated = animated &&
- CallAnimateOnChildWindowVisibilityChanged(window, visible);
-
- if (!visible) {
- // For window hiding animation, we want to check if the window is already
- // animating, and not do SetVisible(false) if it is.
- // TODO(vollick): remove this.
- animated = animated || (window->layer()->GetAnimator()->
- IsAnimatingProperty(ui::LayerAnimationElement::OPACITY) &&
- window->layer()->GetTargetOpacity() == 0.0f);
- }
-
- // When a window is made visible, we always make its layer visible
- // immediately. When a window is hidden, the layer must be left visible and
- // only made not visible once the animation is complete.
- if (!animated || visible)
- window->layer()->SetVisible(visible);
-}
-
-SuspendChildWindowVisibilityAnimations::SuspendChildWindowVisibilityAnimations(
- aura::Window* window)
- : window_(window),
- original_enabled_(window->GetProperty(
- kChildWindowVisibilityChangesAnimatedKey)) {
- window_->ClearProperty(kChildWindowVisibilityChangesAnimatedKey);
-}
-
-SuspendChildWindowVisibilityAnimations::
- ~SuspendChildWindowVisibilityAnimations() {
- if (original_enabled_)
- window_->SetProperty(kChildWindowVisibilityChangesAnimatedKey, true);
- else
- window_->ClearProperty(kChildWindowVisibilityChangesAnimatedKey);
-}
-
-void SetChildWindowVisibilityChangesAnimated(aura::Window* window) {
- window->SetProperty(kChildWindowVisibilityChangesAnimatedKey, true);
-}
-
-} // namespace corewm
-} // namespace views
-
diff --git a/chromium/ui/views/corewm/visibility_controller.h b/chromium/ui/views/corewm/visibility_controller.h
deleted file mode 100644
index ec489822f66..00000000000
--- a/chromium/ui/views/corewm/visibility_controller.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_
-#define UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "ui/aura/client/visibility_client.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-namespace corewm {
-
-class VIEWS_EXPORT VisibilityController
- : public aura::client::VisibilityClient {
- public:
- VisibilityController();
- virtual ~VisibilityController();
-
- protected:
- // Subclasses override if they want to call a different implementation of
- // this function.
- // TODO(beng): potentially replace by an actual window animator class in
- // window_animations.h.
- virtual bool CallAnimateOnChildWindowVisibilityChanged(aura::Window* window,
- bool visible);
-
- private:
- // Overridden from aura::client::VisibilityClient:
- virtual void UpdateLayerVisibility(aura::Window* window,
- bool visible) OVERRIDE;
-
- DISALLOW_COPY_AND_ASSIGN(VisibilityController);
-};
-
-// Suspends the animations for visibility changes during the lifetime of an
-// instance of this class.
-//
-// Example:
-//
-// void ViewName::UnanimatedAction() {
-// SuspendChildWindowVisibilityAnimations suspend(parent);
-// // Perform unanimated action here.
-// // ...
-// // When the method finishes, visibility animations will return to their
-// // previous state.
-// }
-//
-class VIEWS_EXPORT SuspendChildWindowVisibilityAnimations {
- public:
- // Suspend visibility animations of child windows.
- explicit SuspendChildWindowVisibilityAnimations(aura::Window* window);
-
- // Restore visibility animations to their original state.
- ~SuspendChildWindowVisibilityAnimations();
-
- private:
- // The window to manage.
- aura::Window* window_;
-
- // Whether the visibility animations on child windows were originally enabled.
- const bool original_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(SuspendChildWindowVisibilityAnimations);
-};
-
-// Tells |window| to animate visibility changes to its children.
-void VIEWS_EXPORT SetChildWindowVisibilityChangesAnimated(aura::Window* window);
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_VISIBILITY_CONTROLLER_H_
diff --git a/chromium/ui/views/corewm/visibility_controller_unittest.cc b/chromium/ui/views/corewm/visibility_controller_unittest.cc
deleted file mode 100644
index 222d7af61e8..00000000000
--- a/chromium/ui/views/corewm/visibility_controller_unittest.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/visibility_controller.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-
-namespace views {
-namespace corewm {
-
-typedef aura::test::AuraTestBase VisibilityControllerTest;
-
-// Hiding a window in an animatable container should not hide the window's layer
-// immediately.
-TEST_F(VisibilityControllerTest, AnimateHideDoesntHideWindowLayer) {
- // We cannot disable animations for this test.
- ui::ScopedAnimationDurationScaleMode normal_duration_mode(
- ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
-
- VisibilityController controller;
- aura::client::SetVisibilityClient(root_window(), &controller);
-
- SetChildWindowVisibilityChangesAnimated(root_window());
-
- aura::test::TestWindowDelegate d;
- scoped_ptr<aura::Window> animatable(
- aura::test::CreateTestWindowWithDelegate(
- &d, -2, gfx::Rect(0, 0, 50, 50), root_window()));
- scoped_ptr<aura::Window> non_animatable(
- aura::test::CreateTestWindowWithDelegateAndType(
- &d, aura::client::WINDOW_TYPE_CONTROL, -3, gfx::Rect(51, 51, 50, 50),
- root_window()));
- EXPECT_TRUE(animatable->IsVisible());
- EXPECT_TRUE(animatable->layer()->visible());
- animatable->Hide();
- EXPECT_FALSE(animatable->IsVisible());
- EXPECT_TRUE(animatable->layer()->visible());
-
- EXPECT_TRUE(non_animatable->IsVisible());
- EXPECT_TRUE(non_animatable->layer()->visible());
- non_animatable->Hide();
- EXPECT_FALSE(non_animatable->IsVisible());
- EXPECT_FALSE(non_animatable->layer()->visible());
-
- aura::client::SetVisibilityClient(root_window(), NULL);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/window_animations.cc b/chromium/ui/views/corewm/window_animations.cc
deleted file mode 100644
index 736f4bba822..00000000000
--- a/chromium/ui/views/corewm/window_animations.cc
+++ /dev/null
@@ -1,573 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/window_animations.h"
-
-#include <math.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "base/time/time.h"
-#include "ui/aura/client/animation_host.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_property.h"
-#include "ui/compositor/compositor_observer.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/compositor/layer_animation_sequence.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/interpolated_transform.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/vector2d.h"
-#include "ui/gfx/vector3d_f.h"
-#include "ui/views/corewm/corewm_switches.h"
-#include "ui/views/corewm/window_util.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(int)
-DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationType)
-DECLARE_WINDOW_PROPERTY_TYPE(views::corewm::WindowVisibilityAnimationTransition)
-DECLARE_WINDOW_PROPERTY_TYPE(float)
-DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT, bool)
-
-using aura::Window;
-using base::TimeDelta;
-using ui::Layer;
-
-namespace views {
-namespace corewm {
-namespace {
-const float kWindowAnimation_Vertical_TranslateY = 15.f;
-} // namespace
-
-DEFINE_WINDOW_PROPERTY_KEY(int,
- kWindowVisibilityAnimationTypeKey,
- WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
-DEFINE_WINDOW_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
-DEFINE_WINDOW_PROPERTY_KEY(WindowVisibilityAnimationTransition,
- kWindowVisibilityAnimationTransitionKey,
- ANIMATE_BOTH);
-DEFINE_WINDOW_PROPERTY_KEY(float,
- kWindowVisibilityAnimationVerticalPositionKey,
- kWindowAnimation_Vertical_TranslateY);
-
-namespace {
-
-const int kDefaultAnimationDurationForMenuMS = 150;
-
-const float kWindowAnimation_HideOpacity = 0.f;
-const float kWindowAnimation_ShowOpacity = 1.f;
-const float kWindowAnimation_TranslateFactor = 0.5f;
-const float kWindowAnimation_ScaleFactor = .95f;
-
-const int kWindowAnimation_Rotate_DurationMS = 180;
-const int kWindowAnimation_Rotate_OpacityDurationPercent = 90;
-const float kWindowAnimation_Rotate_TranslateY = -20.f;
-const float kWindowAnimation_Rotate_PerspectiveDepth = 500.f;
-const float kWindowAnimation_Rotate_DegreesX = 5.f;
-const float kWindowAnimation_Rotate_ScaleFactor = .99f;
-
-const float kWindowAnimation_Bounce_Scale = 1.02f;
-const int kWindowAnimation_Bounce_DurationMS = 180;
-const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40;
-
-base::TimeDelta GetWindowVisibilityAnimationDuration(aura::Window* window) {
- int duration =
- window->GetProperty(kWindowVisibilityAnimationDurationKey);
- if (duration == 0 && window->type() == aura::client::WINDOW_TYPE_MENU) {
- return base::TimeDelta::FromMilliseconds(
- kDefaultAnimationDurationForMenuMS);
- }
- return TimeDelta::FromInternalValue(duration);
-}
-
-// Gets/sets the WindowVisibilityAnimationType associated with a window.
-// TODO(beng): redundant/fold into method on public api?
-int GetWindowVisibilityAnimationType(aura::Window* window) {
- int type = window->GetProperty(kWindowVisibilityAnimationTypeKey);
- if (type == WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT) {
- return (window->type() == aura::client::WINDOW_TYPE_MENU ||
- window->type() == aura::client::WINDOW_TYPE_TOOLTIP) ?
- WINDOW_VISIBILITY_ANIMATION_TYPE_FADE :
- WINDOW_VISIBILITY_ANIMATION_TYPE_DROP;
- }
- return type;
-}
-
-// Observes a hide animation.
-// A window can be hidden for a variety of reasons. Sometimes, Hide() will be
-// called and life is simple. Sometimes, the window is actually bound to a
-// views::Widget and that Widget is closed, and life is a little more
-// complicated. When a Widget is closed the aura::Window* is actually not
-// destroyed immediately - it is actually just immediately hidden and then
-// destroyed when the stack unwinds. To handle this case, we start the hide
-// animation immediately when the window is hidden, then when the window is
-// subsequently destroyed this object acquires ownership of the window's layer,
-// so that it can continue animating it until the animation completes.
-// Regardless of whether or not the window is destroyed, this object deletes
-// itself when the animation completes.
-class HidingWindowAnimationObserver : public ui::ImplicitAnimationObserver,
- public aura::WindowObserver {
- public:
- explicit HidingWindowAnimationObserver(aura::Window* window)
- : window_(window) {
- window_->AddObserver(this);
- }
- virtual ~HidingWindowAnimationObserver() {
- STLDeleteElements(&layers_);
- }
-
- private:
- // Overridden from ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsCompleted() OVERRIDE {
- // Window may have been destroyed by this point.
- if (window_) {
- aura::client::AnimationHost* animation_host =
- aura::client::GetAnimationHost(window_);
- if (animation_host)
- animation_host->OnWindowHidingAnimationCompleted();
- window_->RemoveObserver(this);
- }
- delete this;
- }
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- DCHECK_EQ(window, window_);
- DCHECK(layers_.empty());
- AcquireAllLayers(window_);
-
- // If the Widget has views with layers, then it is necessary to take
- // ownership of those layers too.
- views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window_);
- const views::Widget* const_widget = widget;
- if (widget && const_widget->GetRootView() && widget->GetContentsView())
- AcquireAllViewLayers(widget->GetContentsView());
- window_->RemoveObserver(this);
- window_ = NULL;
- }
-
- void AcquireAllLayers(aura::Window* window) {
- ui::Layer* layer = window->AcquireLayer();
- DCHECK(layer);
- layers_.push_back(layer);
- for (aura::Window::Windows::const_iterator it = window->children().begin();
- it != window->children().end();
- ++it)
- AcquireAllLayers(*it);
- }
-
- void AcquireAllViewLayers(views::View* view) {
- for (int i = 0; i < view->child_count(); ++i)
- AcquireAllViewLayers(view->child_at(i));
- if (view->layer()) {
- ui::Layer* layer = view->RecreateLayer();
- if (layer) {
- layer->SuppressPaint();
- layers_.push_back(layer);
- }
- }
- }
-
- aura::Window* window_;
- std::vector<ui::Layer*> layers_;
-
- DISALLOW_COPY_AND_ASSIGN(HidingWindowAnimationObserver);
-};
-
-void GetTransformRelativeToRoot(ui::Layer* layer, gfx::Transform* transform) {
- const Layer* root = layer;
- while (root->parent())
- root = root->parent();
- layer->GetTargetTransformRelativeTo(root, transform);
-}
-
-gfx::Rect GetLayerWorldBoundsAfterTransform(ui::Layer* layer,
- const gfx::Transform& transform) {
- gfx::Transform in_world = transform;
- GetTransformRelativeToRoot(layer, &in_world);
-
- gfx::RectF transformed = layer->bounds();
- in_world.TransformRect(&transformed);
-
- return gfx::ToEnclosingRect(transformed);
-}
-
-// Augment the host window so that the enclosing bounds of the full
-// animation will fit inside of it.
-void AugmentWindowSize(aura::Window* window,
- const gfx::Transform& end_transform) {
- aura::client::AnimationHost* animation_host =
- aura::client::GetAnimationHost(window);
- if (!animation_host)
- return;
-
- const gfx::Rect& world_at_start = window->bounds();
- gfx::Rect world_at_end =
- GetLayerWorldBoundsAfterTransform(window->layer(), end_transform);
- gfx::Rect union_in_window_space =
- gfx::UnionRects(world_at_start, world_at_end);
-
- // Calculate the top left and bottom right deltas to be added to the window
- // bounds.
- gfx::Vector2d top_left_delta(world_at_start.x() - union_in_window_space.x(),
- world_at_start.y() - union_in_window_space.y());
-
- gfx::Vector2d bottom_right_delta(
- union_in_window_space.x() + union_in_window_space.width() -
- (world_at_start.x() + world_at_start.width()),
- union_in_window_space.y() + union_in_window_space.height() -
- (world_at_start.y() + world_at_start.height()));
-
- DCHECK(top_left_delta.x() >= 0 && top_left_delta.y() >= 0 &&
- bottom_right_delta.x() >= 0 && bottom_right_delta.y() >= 0);
-
- animation_host->SetHostTransitionOffsets(top_left_delta, bottom_right_delta);
-}
-
-// Shows a window using an animation, animating its opacity from 0.f to 1.f,
-// its visibility to true, and its transform from |start_transform| to
-// |end_transform|.
-void AnimateShowWindowCommon(aura::Window* window,
- const gfx::Transform& start_transform,
- const gfx::Transform& end_transform) {
- window->layer()->set_delegate(window);
-
- AugmentWindowSize(window, end_transform);
-
- window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
- window->layer()->SetTransform(start_transform);
- window->layer()->SetVisible(true);
-
- {
- // Property sets within this scope will be implicitly animated.
- ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
- base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window);
- if (duration.ToInternalValue() > 0)
- settings.SetTransitionDuration(duration);
-
- window->layer()->SetTransform(end_transform);
- window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
- }
-}
-
-// Hides a window using an animation, animating its opacity from 1.f to 0.f,
-// its visibility to false, and its transform to |end_transform|.
-void AnimateHideWindowCommon(aura::Window* window,
- const gfx::Transform& end_transform) {
- AugmentWindowSize(window, end_transform);
- window->layer()->set_delegate(NULL);
-
- // Property sets within this scope will be implicitly animated.
- ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
- settings.AddObserver(new HidingWindowAnimationObserver(window));
-
- base::TimeDelta duration = GetWindowVisibilityAnimationDuration(window);
- if (duration.ToInternalValue() > 0)
- settings.SetTransitionDuration(duration);
-
- window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
- window->layer()->SetTransform(end_transform);
- window->layer()->SetVisible(false);
-}
-
-static gfx::Transform GetScaleForWindow(aura::Window* window) {
- gfx::Rect bounds = window->bounds();
- gfx::Transform scale = gfx::GetScaleTransform(
- gfx::Point(kWindowAnimation_TranslateFactor * bounds.width(),
- kWindowAnimation_TranslateFactor * bounds.height()),
- kWindowAnimation_ScaleFactor);
- return scale;
-}
-
-// Show/Hide windows using a shrink animation.
-void AnimateShowWindow_Drop(aura::Window* window) {
- AnimateShowWindowCommon(window, GetScaleForWindow(window), gfx::Transform());
-}
-
-void AnimateHideWindow_Drop(aura::Window* window) {
- AnimateHideWindowCommon(window, GetScaleForWindow(window));
-}
-
-// Show/Hide windows using a vertical Glenimation.
-void AnimateShowWindow_Vertical(aura::Window* window) {
- gfx::Transform transform;
- transform.Translate(0, window->GetProperty(
- kWindowVisibilityAnimationVerticalPositionKey));
- AnimateShowWindowCommon(window, transform, gfx::Transform());
-}
-
-void AnimateHideWindow_Vertical(aura::Window* window) {
- gfx::Transform transform;
- transform.Translate(0, window->GetProperty(
- kWindowVisibilityAnimationVerticalPositionKey));
- AnimateHideWindowCommon(window, transform);
-}
-
-// Show/Hide windows using a fade.
-void AnimateShowWindow_Fade(aura::Window* window) {
- AnimateShowWindowCommon(window, gfx::Transform(), gfx::Transform());
-}
-
-void AnimateHideWindow_Fade(aura::Window* window) {
- AnimateHideWindowCommon(window, gfx::Transform());
-}
-
-ui::LayerAnimationElement* CreateGrowShrinkElement(
- aura::Window* window, bool grow) {
- scoped_ptr<ui::InterpolatedTransform> scale(new ui::InterpolatedScale(
- gfx::Point3F(kWindowAnimation_Bounce_Scale,
- kWindowAnimation_Bounce_Scale,
- 1),
- gfx::Point3F(1, 1, 1)));
- scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
- new ui::InterpolatedTransformAboutPivot(
- gfx::Point(window->bounds().width() * 0.5,
- window->bounds().height() * 0.5),
- scale.release()));
- scale_about_pivot->SetReversed(grow);
- scoped_ptr<ui::LayerAnimationElement> transition(
- ui::LayerAnimationElement::CreateInterpolatedTransformElement(
- scale_about_pivot.release(),
- base::TimeDelta::FromMilliseconds(
- kWindowAnimation_Bounce_DurationMS *
- kWindowAnimation_Bounce_GrowShrinkDurationPercent / 100)));
- transition->set_tween_type(grow ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
- return transition.release();
-}
-
-void AnimateBounce(aura::Window* window) {
- ui::ScopedLayerAnimationSettings scoped_settings(
- window->layer()->GetAnimator());
- scoped_settings.SetPreemptionStrategy(
- ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
- window->layer()->set_delegate(window);
- scoped_ptr<ui::LayerAnimationSequence> sequence(
- new ui::LayerAnimationSequence);
- sequence->AddElement(CreateGrowShrinkElement(window, true));
- ui::LayerAnimationElement::AnimatableProperties paused_properties;
- paused_properties.insert(ui::LayerAnimationElement::BOUNDS);
- sequence->AddElement(ui::LayerAnimationElement::CreatePauseElement(
- paused_properties,
- base::TimeDelta::FromMilliseconds(
- kWindowAnimation_Bounce_DurationMS *
- (100 - 2 * kWindowAnimation_Bounce_GrowShrinkDurationPercent) /
- 100)));
- sequence->AddElement(CreateGrowShrinkElement(window, false));
- window->layer()->GetAnimator()->StartAnimation(sequence.release());
-}
-
-void AddLayerAnimationsForRotate(aura::Window* window, bool show) {
- window->layer()->set_delegate(window);
- if (show)
- window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
-
- base::TimeDelta duration = base::TimeDelta::FromMilliseconds(
- kWindowAnimation_Rotate_DurationMS);
-
- if (!show) {
- new HidingWindowAnimationObserver(window);
- window->layer()->GetAnimator()->SchedulePauseForProperties(
- duration * (100 - kWindowAnimation_Rotate_OpacityDurationPercent) / 100,
- ui::LayerAnimationElement::OPACITY,
- -1);
- }
- scoped_ptr<ui::LayerAnimationElement> opacity(
- ui::LayerAnimationElement::CreateOpacityElement(
- show ? kWindowAnimation_ShowOpacity : kWindowAnimation_HideOpacity,
- duration * kWindowAnimation_Rotate_OpacityDurationPercent / 100));
- opacity->set_tween_type(gfx::Tween::EASE_IN_OUT);
- window->layer()->GetAnimator()->ScheduleAnimation(
- new ui::LayerAnimationSequence(opacity.release()));
-
- float xcenter = window->bounds().width() * 0.5;
-
- gfx::Transform transform;
- transform.Translate(xcenter, 0);
- transform.ApplyPerspectiveDepth(kWindowAnimation_Rotate_PerspectiveDepth);
- transform.Translate(-xcenter, 0);
- scoped_ptr<ui::InterpolatedTransform> perspective(
- new ui::InterpolatedConstantTransform(transform));
-
- scoped_ptr<ui::InterpolatedTransform> scale(
- new ui::InterpolatedScale(1, kWindowAnimation_Rotate_ScaleFactor));
- scoped_ptr<ui::InterpolatedTransform> scale_about_pivot(
- new ui::InterpolatedTransformAboutPivot(
- gfx::Point(xcenter, kWindowAnimation_Rotate_TranslateY),
- scale.release()));
-
- scoped_ptr<ui::InterpolatedTransform> translation(
- new ui::InterpolatedTranslation(gfx::Point(), gfx::Point(
- 0, kWindowAnimation_Rotate_TranslateY)));
-
- scoped_ptr<ui::InterpolatedTransform> rotation(
- new ui::InterpolatedAxisAngleRotation(
- gfx::Vector3dF(1, 0, 0), 0, kWindowAnimation_Rotate_DegreesX));
-
- scale_about_pivot->SetChild(perspective.release());
- translation->SetChild(scale_about_pivot.release());
- rotation->SetChild(translation.release());
- rotation->SetReversed(show);
-
- scoped_ptr<ui::LayerAnimationElement> transition(
- ui::LayerAnimationElement::CreateInterpolatedTransformElement(
- rotation.release(), duration));
-
- window->layer()->GetAnimator()->ScheduleAnimation(
- new ui::LayerAnimationSequence(transition.release()));
-}
-
-void AnimateShowWindow_Rotate(aura::Window* window) {
- AddLayerAnimationsForRotate(window, true);
-}
-
-void AnimateHideWindow_Rotate(aura::Window* window) {
- AddLayerAnimationsForRotate(window, false);
-}
-
-bool AnimateShowWindow(aura::Window* window) {
- if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
- if (HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
- // Since hide animation may have changed opacity and transform,
- // reset them to show the window.
- window->layer()->set_delegate(window);
- window->layer()->SetOpacity(kWindowAnimation_ShowOpacity);
- window->layer()->SetTransform(gfx::Transform());
- }
- return false;
- }
-
- switch (GetWindowVisibilityAnimationType(window)) {
- case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
- AnimateShowWindow_Drop(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
- AnimateShowWindow_Vertical(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
- AnimateShowWindow_Fade(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
- AnimateShowWindow_Rotate(window);
- return true;
- default:
- return false;
- }
-}
-
-bool AnimateHideWindow(aura::Window* window) {
- if (!HasWindowVisibilityAnimationTransition(window, ANIMATE_HIDE)) {
- if (HasWindowVisibilityAnimationTransition(window, ANIMATE_SHOW)) {
- // Since show animation may have changed opacity and transform,
- // reset them, though the change should be hidden.
- window->layer()->set_delegate(NULL);
- window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
- window->layer()->SetTransform(gfx::Transform());
- }
- return false;
- }
-
- switch (GetWindowVisibilityAnimationType(window)) {
- case WINDOW_VISIBILITY_ANIMATION_TYPE_DROP:
- AnimateHideWindow_Drop(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL:
- AnimateHideWindow_Vertical(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_FADE:
- AnimateHideWindow_Fade(window);
- return true;
- case WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE:
- AnimateHideWindow_Rotate(window);
- return true;
- default:
- return false;
- }
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// External interface
-
-void SetWindowVisibilityAnimationType(aura::Window* window, int type) {
- window->SetProperty(kWindowVisibilityAnimationTypeKey, type);
-}
-
-int GetWindowVisibilityAnimationType(aura::Window* window) {
- return window->GetProperty(kWindowVisibilityAnimationTypeKey);
-}
-
-void SetWindowVisibilityAnimationTransition(
- aura::Window* window,
- WindowVisibilityAnimationTransition transition) {
- window->SetProperty(kWindowVisibilityAnimationTransitionKey, transition);
-}
-
-bool HasWindowVisibilityAnimationTransition(
- aura::Window* window,
- WindowVisibilityAnimationTransition transition) {
- WindowVisibilityAnimationTransition prop = window->GetProperty(
- kWindowVisibilityAnimationTransitionKey);
- return (prop & transition) != 0;
-}
-
-void SetWindowVisibilityAnimationDuration(aura::Window* window,
- const TimeDelta& duration) {
- window->SetProperty(kWindowVisibilityAnimationDurationKey,
- static_cast<int>(duration.ToInternalValue()));
-}
-
-void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
- float position) {
- window->SetProperty(kWindowVisibilityAnimationVerticalPositionKey, position);
-}
-
-ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
- aura::Window* window) {
- return new HidingWindowAnimationObserver(window);
-}
-
-bool AnimateOnChildWindowVisibilityChanged(aura::Window* window, bool visible) {
- if (WindowAnimationsDisabled(window))
- return false;
- if (visible)
- return AnimateShowWindow(window);
- // Don't start hiding the window again if it's already being hidden.
- return window->layer()->GetTargetOpacity() != 0.0f &&
- AnimateHideWindow(window);
-}
-
-bool AnimateWindow(aura::Window* window, WindowAnimationType type) {
- switch (type) {
- case WINDOW_ANIMATION_TYPE_BOUNCE:
- AnimateBounce(window);
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool WindowAnimationsDisabled(aura::Window* window) {
- return (window &&
- window->GetProperty(aura::client::kAnimationsDisabledKey)) ||
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kWindowAnimationsDisabled);
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/window_animations.h b/chromium/ui/views/corewm/window_animations.h
deleted file mode 100644
index 996c215dc89..00000000000
--- a/chromium/ui/views/corewm/window_animations.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_
-#define UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_
-
-#include <vector>
-
-#include "ui/views/views_export.h"
-
-namespace aura {
-class Window;
-}
-namespace base {
-class TimeDelta;
-}
-namespace gfx {
-class Rect;
-}
-namespace ui {
-class ImplicitAnimationObserver;
-class Layer;
-class LayerAnimationSequence;
-}
-
-namespace views {
-namespace corewm {
-
-// A variety of canned animations for window transitions.
-enum WindowVisibilityAnimationType {
- WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT = 0, // Default. Lets the system
- // decide based on window
- // type.
- WINDOW_VISIBILITY_ANIMATION_TYPE_DROP, // Window shrinks in.
- WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL, // Vertical Glenimation.
- WINDOW_VISIBILITY_ANIMATION_TYPE_FADE, // Fades in/out.
- WINDOW_VISIBILITY_ANIMATION_TYPE_ROTATE, // Window rotates in.
-
- // Downstream library animations start above this point.
- WINDOW_VISIBILITY_ANIMATION_MAX
-};
-
-// Canned animations that take effect once but don't have a symmetric pair as
-// visibility animations do.
-enum WindowAnimationType {
- WINDOW_ANIMATION_TYPE_BOUNCE = 0, // Window scales up and down.
-};
-
-// Type of visibility change transition that a window should animate.
-// Default behavior is to animate both show and hide.
-enum WindowVisibilityAnimationTransition {
- ANIMATE_SHOW = 0x1,
- ANIMATE_HIDE = 0x2,
- ANIMATE_BOTH = ANIMATE_SHOW | ANIMATE_HIDE,
- ANIMATE_NONE = 0x4,
-};
-
-// These two methods use int for type rather than WindowVisibilityAnimationType
-// since downstream libraries can extend the set of animations.
-VIEWS_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window,
- int type);
-VIEWS_EXPORT int GetWindowVisibilityAnimationType(aura::Window* window);
-
-VIEWS_EXPORT void SetWindowVisibilityAnimationTransition(
- aura::Window* window,
- WindowVisibilityAnimationTransition transition);
-
-VIEWS_EXPORT bool HasWindowVisibilityAnimationTransition(
- aura::Window* window,
- WindowVisibilityAnimationTransition transition);
-
-VIEWS_EXPORT void SetWindowVisibilityAnimationDuration(
- aura::Window* window,
- const base::TimeDelta& duration);
-
-VIEWS_EXPORT void SetWindowVisibilityAnimationVerticalPosition(
- aura::Window* window,
- float position);
-
-// Creates an ImplicitAnimationObserver that takes ownership of the layers
-// associated with a Window so that the animation can continue after the Window
-// has been destroyed.
-// The returned object deletes itself when the animations are done.
-VIEWS_EXPORT ui::ImplicitAnimationObserver* CreateHidingWindowAnimationObserver(
- aura::Window* window);
-
-// Returns false if the |window| didn't animate.
-VIEWS_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window,
- bool visible);
-VIEWS_EXPORT bool AnimateWindow(aura::Window* window, WindowAnimationType type);
-
-// Returns true if window animations are disabled for |window|. Window
-// animations are enabled by default. If |window| is NULL, this just checks
-// if the global flag disabling window animations is present.
-VIEWS_EXPORT bool WindowAnimationsDisabled(aura::Window* window);
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_WINDOW_ANIMATIONS_H_
diff --git a/chromium/ui/views/corewm/window_animations_unittest.cc b/chromium/ui/views/corewm/window_animations_unittest.cc
deleted file mode 100644
index 89d48c6ce8d..00000000000
--- a/chromium/ui/views/corewm/window_animations_unittest.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/window_animations.h"
-
-#include "base/time/time.h"
-#include "ui/aura/client/animation_host.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/test_windows.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/gfx/animation/animation_container_element.h"
-#include "ui/gfx/vector2d.h"
-
-using aura::Window;
-using ui::Layer;
-
-namespace views {
-namespace corewm {
-
-class WindowAnimationsTest : public aura::test::AuraTestBase {
- public:
- WindowAnimationsTest() {}
-
- virtual void TearDown() OVERRIDE {
- AuraTestBase::TearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WindowAnimationsTest);
-};
-
-TEST_F(WindowAnimationsTest, LayerTargetVisibility) {
- scoped_ptr<aura::Window> window(
- aura::test::CreateTestWindowWithId(0, NULL));
-
- // Layer target visibility changes according to Show/Hide.
- window->Show();
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
- window->Hide();
- EXPECT_FALSE(window->layer()->GetTargetVisibility());
- window->Show();
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
-}
-
-TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateShow) {
- // Tests if opacity and transform are reset when only show animation is
- // enabled. See also LayerTargetVisibility_AnimateHide.
- // Since the window is not visible after Hide() is called, opacity and
- // transform shouldn't matter in case of ANIMATE_SHOW, but we reset them
- // to keep consistency.
-
- scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
- SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_SHOW);
-
- // Layer target visibility and opacity change according to Show/Hide.
- window->Show();
- AnimateOnChildWindowVisibilityChanged(window.get(), true);
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(1, window->layer()->opacity());
-
- window->Hide();
- AnimateOnChildWindowVisibilityChanged(window.get(), false);
- EXPECT_FALSE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(0, window->layer()->opacity());
- EXPECT_EQ(gfx::Transform(), window->layer()->transform());
-
- window->Show();
- AnimateOnChildWindowVisibilityChanged(window.get(), true);
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(1, window->layer()->opacity());
-}
-
-TEST_F(WindowAnimationsTest, LayerTargetVisibility_AnimateHide) {
- // Tests if opacity and transform are reset when only hide animation is
- // enabled. Hide animation changes opacity and transform in addition to
- // visibility, so we need to reset not only visibility but also opacity
- // and transform to show the window.
-
- scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
- SetWindowVisibilityAnimationTransition(window.get(), ANIMATE_HIDE);
-
- // Layer target visibility and opacity change according to Show/Hide.
- window->Show();
- AnimateOnChildWindowVisibilityChanged(window.get(), true);
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(1, window->layer()->opacity());
- EXPECT_EQ(gfx::Transform(), window->layer()->transform());
-
- window->Hide();
- AnimateOnChildWindowVisibilityChanged(window.get(), false);
- EXPECT_FALSE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(0, window->layer()->opacity());
-
- window->Show();
- AnimateOnChildWindowVisibilityChanged(window.get(), true);
- EXPECT_TRUE(window->layer()->GetTargetVisibility());
- EXPECT_EQ(1, window->layer()->opacity());
- EXPECT_EQ(gfx::Transform(), window->layer()->transform());
-}
-
-// A simple AnimationHost implementation for the NotifyHideCompleted test.
-class NotifyHideCompletedAnimationHost : public aura::client::AnimationHost {
- public:
- NotifyHideCompletedAnimationHost() : hide_completed_(false) {}
- virtual ~NotifyHideCompletedAnimationHost() {}
-
- // Overridden from TestWindowDelegate:
- virtual void OnWindowHidingAnimationCompleted() OVERRIDE {
- hide_completed_ = true;
- }
-
- virtual void SetHostTransitionOffsets(
- const gfx::Vector2d& top_left,
- const gfx::Vector2d& bottom_right) OVERRIDE {}
-
- bool hide_completed() const { return hide_completed_; }
-
- private:
- bool hide_completed_;
-
- DISALLOW_COPY_AND_ASSIGN(NotifyHideCompletedAnimationHost);
-};
-
-TEST_F(WindowAnimationsTest, NotifyHideCompleted) {
- NotifyHideCompletedAnimationHost animation_host;
- scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithId(0, NULL));
- aura::client::SetAnimationHost(window.get(), &animation_host);
- views::corewm::SetWindowVisibilityAnimationType(
- window.get(), WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
- AnimateOnChildWindowVisibilityChanged(window.get(), true);
- EXPECT_TRUE(window->layer()->visible());
-
- EXPECT_FALSE(animation_host.hide_completed());
- AnimateOnChildWindowVisibilityChanged(window.get(), false);
- EXPECT_TRUE(animation_host.hide_completed());
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/window_modality_controller.cc b/chromium/ui/views/corewm/window_modality_controller.cc
deleted file mode 100644
index b52a9d6ad8c..00000000000
--- a/chromium/ui/views/corewm/window_modality_controller.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/window_modality_controller.h"
-
-#include <algorithm>
-
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/capture_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-#include "ui/base/ui_base_types.h"
-#include "ui/events/event.h"
-#include "ui/events/event_target.h"
-#include "ui/events/gestures/gesture_recognizer.h"
-#include "ui/views/corewm/window_animations.h"
-#include "ui/views/corewm/window_util.h"
-
-namespace views {
-namespace corewm {
-
-// Transient child's modal parent.
-extern const aura::WindowProperty<aura::Window*>* const kModalParentKey;
-DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kModalParentKey, NULL);
-
-namespace {
-
-bool HasAncestor(aura::Window* window, aura::Window* ancestor) {
- if (!window)
- return false;
- if (window == ancestor)
- return true;
- return HasAncestor(window->parent(), ancestor);
-}
-
-bool TransientChildIsWindowModal(aura::Window* window) {
- return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW;
-}
-
-bool TransientChildIsSystemModal(aura::Window* window) {
- return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_SYSTEM;
-}
-
-bool TransientChildIsChildModal(aura::Window* window) {
- return window->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_CHILD;
-}
-
-aura::Window* GetModalParent(aura::Window* window) {
- return window->GetProperty(kModalParentKey);
-}
-
-bool IsModalTransientChild(aura::Window* transient, aura::Window* original) {
- return transient->IsVisible() &&
- (TransientChildIsWindowModal(transient) ||
- TransientChildIsSystemModal(transient) ||
- (TransientChildIsChildModal(transient) &&
- (HasAncestor(original, GetModalParent(transient)))));
-}
-
-aura::Window* GetModalTransientChild(
- aura::Window* activatable,
- aura::Window* original) {
- aura::Window::Windows::const_iterator it;
- for (it = activatable->transient_children().begin();
- it != activatable->transient_children().end();
- ++it) {
- aura::Window* transient = *it;
- if (IsModalTransientChild(transient, original)) {
- return transient->transient_children().empty() ?
- transient : GetModalTransientChild(transient, original);
- }
- }
- return NULL;
-}
-
-} // namespace
-
-void SetModalParent(aura::Window* child, aura::Window* parent) {
- child->SetProperty(kModalParentKey, parent);
-}
-
-aura::Window* GetModalTransient(aura::Window* window) {
- if (!window)
- return NULL;
-
- // We always want to check the for the transient child of the toplevel window.
- aura::Window* toplevel = GetToplevelWindow(window);
- if (!toplevel)
- return NULL;
-
- return GetModalTransientChild(toplevel, window);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WindowModalityController, public:
-
-WindowModalityController::WindowModalityController(
- ui::EventTarget* event_target)
- : event_target_(event_target) {
- aura::Env::GetInstance()->AddObserver(this);
- DCHECK(event_target->IsPreTargetListEmpty());
- event_target_->AddPreTargetHandler(this);
-}
-
-WindowModalityController::~WindowModalityController() {
- event_target_->RemovePreTargetHandler(this);
- aura::Env::GetInstance()->RemoveObserver(this);
- for (size_t i = 0; i < windows_.size(); ++i)
- windows_[i]->RemoveObserver(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WindowModalityController, aura::EventFilter implementation:
-
-void WindowModalityController::OnKeyEvent(ui::KeyEvent* event) {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (GetModalTransient(target))
- event->SetHandled();
-}
-
-void WindowModalityController::OnMouseEvent(ui::MouseEvent* event) {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (ProcessLocatedEvent(target, event))
- event->SetHandled();
-}
-
-void WindowModalityController::OnTouchEvent(ui::TouchEvent* event) {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- if (ProcessLocatedEvent(target, event))
- event->SetHandled();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WindowModalityController, aura::EnvObserver implementation:
-
-void WindowModalityController::OnWindowInitialized(aura::Window* window) {
- windows_.push_back(window);
- window->AddObserver(this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// WindowModalityController, aura::WindowObserver implementation:
-
-void WindowModalityController::OnWindowPropertyChanged(aura::Window* window,
- const void* key,
- intptr_t old) {
- // In tests, we sometimes create the modality relationship after a window is
- // visible.
- if (key == aura::client::kModalKey &&
- window->GetProperty(aura::client::kModalKey) != ui::MODAL_TYPE_NONE &&
- window->IsVisible()) {
- ActivateWindow(window);
- ui::GestureRecognizer::Get()->TransferEventsTo(
- window->transient_parent(), NULL);
- }
-}
-
-void WindowModalityController::OnWindowVisibilityChanged(
- aura::Window* window,
- bool visible) {
- if (visible && window->GetProperty(aura::client::kModalKey) !=
- ui::MODAL_TYPE_NONE) {
- ui::GestureRecognizer::Get()->TransferEventsTo(
- window->transient_parent(), NULL);
- // Make sure no other window has capture, otherwise |window| won't get mouse
- // events.
- aura::Window* capture_window = aura::client::GetCaptureWindow(window);
- if (capture_window)
- capture_window->ReleaseCapture();
- }
-}
-
-void WindowModalityController::OnWindowDestroyed(aura::Window* window) {
- windows_.erase(std::find(windows_.begin(), windows_.end(), window));
- window->RemoveObserver(this);
-}
-
-bool WindowModalityController::ProcessLocatedEvent(aura::Window* target,
- ui::LocatedEvent* event) {
- if (event->handled())
- return false;
- aura::Window* modal_transient_child = GetModalTransient(target);
- if (modal_transient_child && (event->type() == ui::ET_MOUSE_PRESSED ||
- event->type() == ui::ET_TOUCH_PRESSED)) {
- AnimateWindow(modal_transient_child, WINDOW_ANIMATION_TYPE_BOUNCE);
- }
- if (event->type() == ui::ET_TOUCH_CANCELLED)
- return false;
- return !!modal_transient_child;
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/window_modality_controller.h b/chromium/ui/views/corewm/window_modality_controller.h
deleted file mode 100644
index 88150a54253..00000000000
--- a/chromium/ui/views/corewm/window_modality_controller.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_
-#define UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "ui/aura/env_observer.h"
-#include "ui/aura/window_observer.h"
-#include "ui/events/event_handler.h"
-#include "ui/views/views_export.h"
-
-namespace ui {
-class EventTarget;
-class LocatedEvent;
-}
-
-namespace views {
-namespace corewm {
-
-// Sets the modal parent for the child.
-VIEWS_EXPORT void SetModalParent(aura::Window* child, aura::Window* parent);
-
-// Returns the modal transient child of |window|, or NULL if |window| does not
-// have any modal transient children.
-VIEWS_EXPORT aura::Window* GetModalTransient(aura::Window* window);
-
-// WindowModalityController is an event filter that consumes events sent to
-// windows that are the transient parents of window-modal windows. This filter
-// must be added to the CompoundEventFilter so that activation works properly.
-class VIEWS_EXPORT WindowModalityController : public ui::EventHandler,
- public aura::EnvObserver,
- public aura::WindowObserver {
- public:
- explicit WindowModalityController(ui::EventTarget* event_target);
- virtual ~WindowModalityController();
-
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
-
- // Overridden from aura::EnvObserver:
- virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
-
- // Overridden from aura::WindowObserver:
- virtual void OnWindowPropertyChanged(aura::Window* window,
- const void* key,
- intptr_t old) OVERRIDE;
- virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
-
- private:
- // Processes a mouse/touch event, and returns true if the event should be
- // consumed.
- bool ProcessLocatedEvent(aura::Window* target,
- ui::LocatedEvent* event);
-
- std::vector<aura::Window*> windows_;
-
- ui::EventTarget* event_target_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowModalityController);
-};
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_WINDOW_MODALITY_CONTROLLER_H_
diff --git a/chromium/ui/views/corewm/window_util.cc b/chromium/ui/views/corewm/window_util.cc
deleted file mode 100644
index eaee174d738..00000000000
--- a/chromium/ui/views/corewm/window_util.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/window_util.h"
-
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-namespace {
-
-// Helper method for RecreateWindowLayers() which adds all the existing layers
-// for |view| and its descendants to |parent_layer|. New layers are created for
-// |view| (if it previously had a layer) and any descendants which previously
-// had layers. The new layers are blank, so nothing has been painted to them
-// yet. Returns true if this method added at least one layer to |parent_layer|.
-bool RecreateViewLayers(ui::Layer* parent_layer, views::View* view) {
- bool recreated_layer = false;
- if (view->layer()) {
- ui::Layer* layer = view->RecreateLayer();
- if (layer) {
- layer->SuppressPaint();
- parent_layer->Add(layer);
- parent_layer = layer;
- recreated_layer = true;
- }
- }
- for (int i = 0; i < view->child_count(); ++i)
- recreated_layer |= RecreateViewLayers(parent_layer, view->child_at(i));
-
- return recreated_layer;
-}
-
-} // namespace
-
-namespace views {
-namespace corewm {
-
-void ActivateWindow(aura::Window* window) {
- DCHECK(window);
- DCHECK(window->GetRootWindow());
- aura::client::GetActivationClient(window->GetRootWindow())->ActivateWindow(
- window);
-}
-
-void DeactivateWindow(aura::Window* window) {
- DCHECK(window);
- DCHECK(window->GetRootWindow());
- aura::client::GetActivationClient(window->GetRootWindow())->DeactivateWindow(
- window);
-}
-
-bool IsActiveWindow(aura::Window* window) {
- DCHECK(window);
- if (!window->GetRootWindow())
- return false;
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(window->GetRootWindow());
- return client && client->GetActiveWindow() == window;
-}
-
-bool CanActivateWindow(aura::Window* window) {
- DCHECK(window);
- if (!window->GetRootWindow())
- return false;
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(window->GetRootWindow());
- return client && client->CanActivateWindow(window);
-}
-
-aura::Window* GetActivatableWindow(aura::Window* window) {
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(window->GetRootWindow());
- return client ? client->GetActivatableWindow(window) : NULL;
-}
-
-aura::Window* GetToplevelWindow(aura::Window* window) {
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(window->GetRootWindow());
- return client ? client->GetToplevelWindow(window) : NULL;
-}
-
-void DeepDeleteLayers(ui::Layer* layer) {
- std::vector<ui::Layer*> children = layer->children();
- for (std::vector<ui::Layer*>::const_iterator it = children.begin();
- it != children.end();
- ++it) {
- ui::Layer* child = *it;
- DeepDeleteLayers(child);
- }
- delete layer;
-}
-
-ui::Layer* RecreateWindowLayers(aura::Window* window, bool set_bounds) {
- const gfx::Rect bounds = window->bounds();
- ui::Layer* old_layer = window->RecreateLayer();
- DCHECK(old_layer);
-
- // Cache the order of |window|'s child layers. If |window| belongs to a widget
- // and the widget has both child windows and child views with layers,
- // |initial_layer_order| is used to determine the relative order.
- std::vector<ui::Layer*> initial_layer_order = window->layer()->children();
-
- // Recreate the layers for any child windows of |window|.
- for (aura::Window::Windows::const_iterator it = window->children().begin();
- it != window->children().end();
- ++it) {
- old_layer->Add(RecreateWindowLayers(*it, set_bounds));
- }
-
- // Recreate the layers for any child views of |widget|.
- bool has_view_layers = false;
- views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
- if (widget && widget->GetRootView())
- has_view_layers = RecreateViewLayers(old_layer, widget->GetRootView());
-
- if (has_view_layers && !window->children().empty()) {
- // RecreateViewLayers() added the view layers above the window layers in
- // z-order. The window layers and the view layers may have been originally
- // intermingled. Reorder |old_layer|'s children based on the initial
- // order.
- for (size_t i = 0; i < initial_layer_order.size(); ++i) {
- ui::Layer* layer = initial_layer_order[i];
- std::vector<ui::Layer*>::const_iterator it = std::find(
- old_layer->children().begin(), old_layer->children().end(), layer);
- if (it != old_layer->children().end())
- old_layer->StackAtTop(layer);
- }
- }
-
- if (set_bounds)
- window->SetBounds(bounds);
- return old_layer;
-}
-
-} // namespace corewm
-} // namespace views
diff --git a/chromium/ui/views/corewm/window_util.h b/chromium/ui/views/corewm/window_util.h
deleted file mode 100644
index 01a3ea43f06..00000000000
--- a/chromium/ui/views/corewm/window_util.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COREWM_WINDOW_UTIL_H_
-#define UI_VIEWS_COREWM_WINDOW_UTIL_H_
-
-#include "base/compiler_specific.h"
-#include "ui/views/views_export.h"
-
-namespace aura {
-class Window;
-}
-
-namespace ui {
-class Layer;
-}
-
-namespace views {
-namespace corewm {
-
-VIEWS_EXPORT void ActivateWindow(aura::Window* window);
-VIEWS_EXPORT void DeactivateWindow(aura::Window* window);
-VIEWS_EXPORT bool IsActiveWindow(aura::Window* window);
-VIEWS_EXPORT bool CanActivateWindow(aura::Window* window);
-
-// Retrieves the activatable window for |window|. The ActivationClient makes
-// this determination.
-VIEWS_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
-
-// Retrieves the toplevel window for |window|. The ActivationClient makes this
-// determination.
-VIEWS_EXPORT aura::Window* GetToplevelWindow(aura::Window* window);
-
-// Deletes |layer| and all its child layers.
-VIEWS_EXPORT void DeepDeleteLayers(ui::Layer* layer);
-
-// Returns the existing Layer for |window| (and all its descendants) and creates
-// a new layer for |window| and all its descendants. This is intended for
-// animations that want to animate between the existing visuals and a new window
-// state. The caller owns the return value.
-//
-// As a result of this |window| has freshly created layers, meaning the layers
-// are all empty (nothing has been painted to them) and are sized to 0x0. Soon
-// after this call you need to reset the bounds of the window. Or, you can pass
-// true as the second argument to let the function do that.
-VIEWS_EXPORT ui::Layer* RecreateWindowLayers(aura::Window* window,
- bool set_bounds) WARN_UNUSED_RESULT;
-
-} // namespace corewm
-} // namespace views
-
-#endif // UI_VIEWS_COREWM_WINDOW_UTIL_H_
diff --git a/chromium/ui/views/corewm/window_util_unittest.cc b/chromium/ui/views/corewm/window_util_unittest.cc
deleted file mode 100644
index fdf3a46fa2f..00000000000
--- a/chromium/ui/views/corewm/window_util_unittest.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/corewm/window_util.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/test/test_layers.h"
-#include "ui/views/view_constants_aura.h"
-#include "ui/views/widget/widget.h"
-
-class WindowUtilTest : public aura::test::AuraTestBase {
- public:
- WindowUtilTest() {
- }
-
- virtual ~WindowUtilTest() {
- }
-
- // Creates a widget of TYPE_CONTROL.
- // The caller takes ownership of the returned widget.
- views::Widget* CreateControlWidget(
- aura::Window* parent,
- const gfx::Rect& bounds) const WARN_UNUSED_RESULT {
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
- params.parent = parent;
- params.bounds = bounds;
- views::Widget* widget = new views::Widget();
- widget->Init(params);
- return widget;
- }
-
- // Returns a view with a layer with the passed in |bounds| and |layer_name|.
- // The caller takes ownership of the returned view.
- views::View* CreateViewWithLayer(
- const gfx::Rect& bounds,
- const char* layer_name) const WARN_UNUSED_RESULT {
- views::View* view = new views::View();
- view->SetBoundsRect(bounds);
- view->SetPaintToLayer(true);
- view->layer()->set_name(layer_name);
- return view;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WindowUtilTest);
-};
-
-// Test that RecreateWindowLayers() recreates the layers for all child windows
-// and all child views and that the z-order of the recreated layers matches that
-// of the original layers.
-// Test hierarchy:
-// w1
-// +-- v1
-// +-- v2 (no layer)
-// +-- v3 (no layer)
-// +-- v4
-// +-- w2
-// +-- v5
-// +-- v6
-// +-- v7
-TEST_F(WindowUtilTest, RecreateWindowLayers) {
- views::Widget* w1 = CreateControlWidget(root_window(),
- gfx::Rect(0, 0, 100, 100));
- w1->GetNativeView()->layer()->set_name("w1");
-
- views::View* v2 = new views::View();
- v2->SetBounds(0, 1, 100, 101);
- views::View* v3 = new views::View();
- v3->SetBounds(0, 2, 100, 102);
- views::View* w2_host_view = new views::View();
-
- w1->GetRootView()->AddChildView(CreateViewWithLayer(
- gfx::Rect(0, 3, 100, 103), "v1"));
- w1->GetRootView()->AddChildView(v2);
- v2->AddChildView(v3);
- v2->AddChildView(CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4"));
-
- w1->GetRootView()->AddChildView(w2_host_view);
- w1->GetRootView()->AddChildView(CreateViewWithLayer(
- gfx::Rect(0, 4, 100, 104), "v7"));
-
- views::Widget* w2 = CreateControlWidget(w1->GetNativeView(),
- gfx::Rect(0, 5, 100, 105));
- w2->GetNativeView()->layer()->set_name("w2");
- w2->GetNativeView()->SetProperty(views::kHostViewKey, w2_host_view);
-
- views::View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
- w2->GetRootView()->AddChildView(v5);
- v5->AddChildView(CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6"));
-
- // Test the initial order of the layers.
- ui::Layer* w1_layer = w1->GetNativeView()->layer();
- ASSERT_EQ("w1", w1_layer->name());
- ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
- ui::Layer* w2_layer = w1_layer->children()[2];
- ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
- ui::Layer* v5_layer = w2_layer->children()[0];
- ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
-
- w1_layer = views::corewm::RecreateWindowLayers(w1->GetNativeView(), false);
-
- // The order of the layers returned by RecreateWindowLayers() should match the
- // order of the layers prior to calling RecreateWindowLayers().
- ASSERT_EQ("w1", w1_layer->name());
- ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
- w2_layer = w1_layer->children()[2];
- ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
- v5_layer = w2_layer->children()[0];
- ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
-
- views::corewm::DeepDeleteLayers(w1_layer);
- // The views and the widgets are destroyed when AuraTestHelper::TearDown()
- // destroys root_window().
-}
diff --git a/chromium/ui/views/cull_set.cc b/chromium/ui/views/cull_set.cc
new file mode 100644
index 00000000000..65566e0b362
--- /dev/null
+++ b/chromium/ui/views/cull_set.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/cull_set.h"
+
+namespace views {
+
+CullSet::CullSet() {
+}
+
+CullSet::~CullSet() {
+}
+
+CullSet::CullSet(scoped_ptr<base::hash_set<intptr_t> > cull_set)
+ : cull_set_(cull_set.Pass()) {
+}
+
+bool CullSet::ShouldPaint(const View* view) const {
+ if (cull_set_)
+ return (cull_set_->count(reinterpret_cast<intptr_t>(view)) > 0);
+
+ return true;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/cull_set.h b/chromium/ui/views/cull_set.h
new file mode 100644
index 00000000000..03f7cff86ee
--- /dev/null
+++ b/chromium/ui/views/cull_set.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CULL_SET_H_
+#define UI_VIEWS_CULL_SET_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+// A CullSet defines a set of View pointers which have been possibly culled
+// from painting or other bounds-checking operations. It wraps a set of
+// pointers to views, or NULL if no such set is available.
+class VIEWS_EXPORT CullSet {
+ public:
+ // Default constructor builds a CullSet that will always return true for
+ // ShouldPaint().
+ CullSet();
+ ~CullSet();
+
+ // Wraps a set of pointers to Views, as might be provided by
+ // gfx::RTree::Query(), that intersect the damage rect and therefore need
+ // to be painted. CullSet takes ownership of the provided pointer.
+ CullSet(scoped_ptr<base::hash_set<intptr_t> > cull_set);
+
+ // Returns true if |view| needs to be painted.
+ bool ShouldPaint(const View* view) const;
+
+ private:
+ friend class BoundsTreeTestView;
+
+ // The set of Views that collided with the query rectangle provided to the
+ // RTree data structure, or NULL if one is not available.
+ scoped_ptr<base::hash_set<intptr_t> > cull_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(CullSet);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CULL_SET_H_
diff --git a/chromium/ui/views/debug_utils.cc b/chromium/ui/views/debug_utils.cc
index 536a6f6abf5..12b4759b33d 100644
--- a/chromium/ui/views/debug_utils.cc
+++ b/chromium/ui/views/debug_utils.cc
@@ -4,7 +4,7 @@
#include "ui/views/debug_utils.h"
-#include <iostream>
+#include <ostream>
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
@@ -18,7 +18,7 @@ void PrintViewHierarchyImp(const View* view,
int ind = indent;
while (ind-- > 0)
*out << L' ';
- *out << UTF8ToWide(view->GetClassName());
+ *out << base::UTF8ToWide(view->GetClassName());
*out << L' ';
*out << view->id();
*out << L' ';
@@ -38,7 +38,7 @@ void PrintFocusHierarchyImp(const View* view,
int ind = indent;
while (ind-- > 0)
*out << L' ';
- *out << UTF8ToWide(view->GetClassName());
+ *out << base::UTF8ToWide(view->GetClassName());
*out << L' ';
*out << view->id();
*out << L' ';
diff --git a/chromium/ui/views/drag_utils.cc b/chromium/ui/views/drag_utils.cc
index 0b9c31775a2..0fd5e5e91c8 100644
--- a/chromium/ui/views/drag_utils.cc
+++ b/chromium/ui/views/drag_utils.cc
@@ -5,26 +5,15 @@
#include "ui/views/drag_utils.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/size.h"
-
-#if defined(USE_AURA)
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
+#include "ui/gfx/size.h"
#include "ui/views/widget/widget.h"
-#elif defined(OS_WIN)
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/drag_source_win.h"
-#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
-#else
-#error
-#endif
+
+namespace {
float GetDeviceScaleForNativeView(views::Widget* widget) {
float device_scale = 1.0f;
-#if defined(USE_AURA)
// The following code should work on other platforms as well. But we do not
// yet care about device scale factor on other platforms. So to keep drag and
// drop behavior on other platforms un-touched, we wrap this in the #if guard.
@@ -34,34 +23,12 @@ float GetDeviceScaleForNativeView(views::Widget* widget) {
GetDisplayNearestWindow(view);
device_scale = display.device_scale_factor();
}
-#endif
return device_scale;
}
-namespace views {
+} // namespace
-void RunShellDrag(gfx::NativeView view,
- const ui::OSExchangeData& data,
- const gfx::Point& location,
- int operation,
- ui::DragDropTypes::DragEventSource source) {
-#if defined(USE_AURA)
- gfx::Point root_location(location);
- aura::Window* root_window = view->GetRootWindow();
- aura::Window::ConvertPointToTarget(view, root_window, &root_location);
- if (aura::client::GetDragDropClient(root_window)) {
- aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
- data, root_window, view, root_location, operation, source);
- }
-#elif defined(OS_WIN)
- scoped_refptr<ui::DragSourceWin> drag_source(new ui::DragSourceWin);
- DWORD effects;
- DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
- drag_source,
- ui::DragDropTypes::DragOperationToDropEffect(operation),
- &effects);
-#endif
-}
+namespace views {
gfx::Canvas* GetCanvasForDragImage(views::Widget* widget,
const gfx::Size& canvas_size) {
diff --git a/chromium/ui/views/drag_utils_aura.cc b/chromium/ui/views/drag_utils_aura.cc
new file mode 100644
index 00000000000..cb64199a2a6
--- /dev/null
+++ b/chromium/ui/views/drag_utils_aura.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/drag_utils.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/wm/public/drag_drop_client.h"
+
+namespace views {
+
+void RunShellDrag(gfx::NativeView view,
+ const ui::OSExchangeData& data,
+ const gfx::Point& location,
+ int operation,
+ ui::DragDropTypes::DragEventSource source) {
+ gfx::Point root_location(location);
+ aura::Window* root_window = view->GetRootWindow();
+ aura::Window::ConvertPointToTarget(view, root_window, &root_location);
+ if (aura::client::GetDragDropClient(root_window)) {
+ aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
+ data, root_window, view, root_location, operation, source);
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/event_utils.h b/chromium/ui/views/event_utils.h
deleted file mode 100644
index 095487b1525..00000000000
--- a/chromium/ui/views/event_utils.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_EVENT_UTILS_H_
-#define UI_VIEWS_EVENT_UTILS_H_
-
-#include "ui/gfx/native_widget_types.h"
-#include "ui/views/views_export.h"
-
-namespace ui {
-class LocatedEvent;
-}
-
-namespace views {
-
-// Reposts a located event natively. Returns false when |event| could not be
-// reposted. |event| should be in screen coordinates. |window| is the target
-// window that the event will be forwarded to. Only some events are supported.
-VIEWS_EXPORT bool RepostLocatedEvent(gfx::NativeWindow window,
- const ui::LocatedEvent& event);
-
-#if defined(OS_WIN) && defined(USE_AURA)
-// Reposts a located event to the HWND passed in.
-VIEWS_EXPORT bool RepostLocatedEventWin(HWND window,
- const ui::LocatedEvent& event);
-#endif
-
-} // namespace views
-
-#endif // UI_VIEWS_EVENT_UTILS_H_
diff --git a/chromium/ui/views/event_utils_aura.cc b/chromium/ui/views/event_utils_aura.cc
deleted file mode 100644
index e3d07d9f310..00000000000
--- a/chromium/ui/views/event_utils_aura.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/event_utils.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/events/event.h"
-#include "ui/gfx/point.h"
-#include "ui/views/views_delegate.h"
-
-using aura::client::ScreenPositionClient;
-
-namespace views {
-
-bool RepostLocatedEvent(gfx::NativeWindow window,
- const ui::LocatedEvent& event) {
- if (!window)
- return false;
-
-#if defined(OS_WIN)
- if (ViewsDelegate::views_delegate &&
- !ViewsDelegate::views_delegate->IsWindowInMetro(window)) {
- return RepostLocatedEventWin(
- window->GetDispatcher()->host()->GetAcceleratedWidget(), event);
- }
-#endif
- aura::Window* root_window = window->GetRootWindow();
-
- gfx::Point root_loc(event.location());
- ScreenPositionClient* spc =
- aura::client::GetScreenPositionClient(root_window);
- if (!spc)
- return false;
-
- spc->ConvertPointFromScreen(root_window, &root_loc);
-
- scoped_ptr<ui::LocatedEvent> relocated;
- if (event.IsMouseEvent()) {
- const ui::MouseEvent& orig = static_cast<const ui::MouseEvent&>(event);
- relocated.reset(new ui::MouseEvent(orig));
- } else if (event.IsGestureEvent()) {
- // TODO(rbyers): Gesture event repost is tricky to get right
- // crbug.com/170987.
- return false;
- } else {
- NOTREACHED();
- return false;
- }
- relocated->set_location(root_loc);
- relocated->set_root_location(root_loc);
-
- root_window->GetDispatcher()->RepostEvent(*relocated);
- return true;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/event_utils_win.cc b/chromium/ui/views/event_utils_win.cc
deleted file mode 100644
index 3e908889dfa..00000000000
--- a/chromium/ui/views/event_utils_win.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/event_utils.h"
-
-#include <windowsx.h>
-
-#include "base/logging.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/point.h"
-
-namespace views {
-
-#if defined(USE_AURA)
-bool RepostLocatedEventWin(HWND window,
- const ui::LocatedEvent& event) {
-#else
-bool RepostLocatedEvent(gfx::NativeWindow window
- const ui::LocatedEvent& event) {
-#endif
- if (!window)
- return false;
-
- // Determine whether the click was in the client area or not.
- // NOTE: WM_NCHITTEST coordinates are relative to the screen.
- const gfx::Point screen_loc = event.location();
- LRESULT nc_hit_result = SendMessage(window, WM_NCHITTEST, 0,
- MAKELPARAM(screen_loc.x(),
- screen_loc.y()));
- const bool in_client_area = nc_hit_result == HTCLIENT;
-
- // TODO(sky): this isn't right. The event to generate should correspond with
- // the event we just got. MouseEvent only tells us what is down, which may
- // differ. Need to add ability to get changed button from MouseEvent.
- int event_type;
- int flags = event.flags();
- if (flags & ui::EF_LEFT_MOUSE_BUTTON) {
- event_type = in_client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
- } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) {
- event_type = in_client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN;
- } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) {
- event_type = in_client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN;
- } else {
- NOTREACHED();
- return false;
- }
-
- int window_x = screen_loc.x();
- int window_y = screen_loc.y();
- if (in_client_area) {
- POINT pt = {window_x, window_y};
- ScreenToClient(window, &pt);
- window_x = pt.x;
- window_y = pt.y;
- }
-
- WPARAM target = in_client_area ? event.native_event().wParam : nc_hit_result;
- PostMessage(window, event_type, target, MAKELPARAM(window_x, window_y));
- return true;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/examples/DEPS b/chromium/ui/views/examples/DEPS
index 1108a456a1a..06e440bbb91 100644
--- a/chromium/ui/views/examples/DEPS
+++ b/chromium/ui/views/examples/DEPS
@@ -2,4 +2,6 @@ include_rules = [
"+content/public",
"+content/shell",
"+sandbox",
+ "+ui/gl/gl_surface.h", # To initialize GL bindings.
+ "+ui/views_content_client",
]
diff --git a/chromium/ui/views/examples/bubble_example.cc b/chromium/ui/views/examples/bubble_example.cc
index 6869b4634a1..49a60e59d9e 100644
--- a/chromium/ui/views/examples/bubble_example.cc
+++ b/chromium/ui/views/examples/bubble_example.cc
@@ -11,6 +11,8 @@
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -26,7 +28,7 @@ BubbleBorder::Arrow arrows[] = {
BubbleBorder::BOTTOM_LEFT, BubbleBorder::LEFT_BOTTOM,
BubbleBorder::LEFT_CENTER, BubbleBorder::LEFT_TOP };
-string16 GetArrowName(BubbleBorder::Arrow arrow) {
+base::string16 GetArrowName(BubbleBorder::Arrow arrow) {
switch (arrow) {
case BubbleBorder::TOP_LEFT: return ASCIIToUTF16("TOP_LEFT");
case BubbleBorder::TOP_RIGHT: return ASCIIToUTF16("TOP_RIGHT");
@@ -81,8 +83,6 @@ void BubbleExample::CreateExampleView(View* container) {
container->AddChildView(align_to_edge_);
persistent_ = new LabelButton(this, ASCIIToUTF16("Persistent"));
container->AddChildView(persistent_);
- fade_in_ = new LabelButton(this, ASCIIToUTF16("Fade In"));
- container->AddChildView(fade_in_);
}
void BubbleExample::ButtonPressed(Button* sender, const ui::Event& event) {
@@ -105,19 +105,14 @@ void BubbleExample::ButtonPressed(Button* sender, const ui::Event& event) {
else if (sender == small_shadow_)
bubble->set_shadow(BubbleBorder::SMALL_SHADOW);
- if (sender == persistent_) {
+ if (sender == persistent_)
bubble->set_close_on_deactivate(false);
- bubble->set_move_with_anchor(true);
- }
BubbleDelegateView::CreateBubble(bubble);
if (sender == align_to_edge_)
bubble->SetAlignment(BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE);
- if (sender == fade_in_)
- bubble->StartFade(true);
- else
- bubble->GetWidget()->Show();
+ bubble->GetWidget()->Show();
}
} // namespace examples
diff --git a/chromium/ui/views/examples/bubble_example.h b/chromium/ui/views/examples/bubble_example.h
index fd0008e6ed9..d9ad66de6b0 100644
--- a/chromium/ui/views/examples/bubble_example.h
+++ b/chromium/ui/views/examples/bubble_example.h
@@ -12,15 +12,17 @@ namespace views {
namespace examples {
// A Bubble example.
-class BubbleExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT BubbleExample : public ExampleBase,
+ public ButtonListener {
public:
BubbleExample();
virtual ~BubbleExample();
- // Overridden from ExampleBase.
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
Button* no_shadow_;
@@ -28,7 +30,6 @@ class BubbleExample : public ExampleBase, public ButtonListener {
Button* small_shadow_;
Button* align_to_edge_;
Button* persistent_;
- Button* fade_in_;
DISALLOW_COPY_AND_ASSIGN(BubbleExample);
};
diff --git a/chromium/ui/views/examples/button_example.cc b/chromium/ui/views/examples/button_example.cc
index a791559982a..f5ea950c887 100644
--- a/chromium/ui/views/examples/button_example.cc
+++ b/chromium/ui/views/examples/button_example.cc
@@ -16,6 +16,8 @@
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+
namespace {
const char kLabelButton[] = "Label Button";
const char kTextButton[] = "Text Button";
@@ -73,8 +75,6 @@ void ButtonExample::CreateExampleView(View* container) {
rb.GetImageNamed(IDR_CLOSE_H).ToImageSkia());
image_button_->SetImage(ImageButton::STATE_PRESSED,
rb.GetImageNamed(IDR_CLOSE_P).ToImageSkia());
- image_button_->SetOverlayImage(rb.GetImageNamed(
- IDR_MENU_CHECK).ToImageSkia());
container->AddChildView(image_button_);
}
@@ -124,10 +124,13 @@ void ButtonExample::TextButtonPressed(const ui::Event& event) {
text_button_->text().length() < 50 ? kLongText : kTextButton));
} else {
use_native_theme_border_ = !use_native_theme_border_;
- if (use_native_theme_border_)
- text_button_->set_border(new TextButtonNativeThemeBorder(text_button_));
- else
- text_button_->set_border(new TextButtonDefaultBorder());
+ if (use_native_theme_border_) {
+ text_button_->SetBorder(scoped_ptr<views::Border>(
+ new TextButtonNativeThemeBorder(text_button_)));
+ } else {
+ text_button_->SetBorder(
+ scoped_ptr<views::Border>(new TextButtonDefaultBorder()));
+ }
}
} else if (event.IsAltDown()) {
text_button_->SetIsDefault(!text_button_->is_default());
@@ -161,7 +164,7 @@ void ButtonExample::LabelButtonPressed(const ui::Event& event) {
}
} else if (event.IsShiftDown()) {
if (event.IsAltDown()) {
- label_button_->SetFocusable(!label_button_->focusable());
+ label_button_->SetFocusable(!label_button_->IsFocusable());
} else {
label_button_->SetStyle(static_cast<Button::ButtonStyle>(
(label_button_->style() + 1) % Button::STYLE_COUNT));
diff --git a/chromium/ui/views/examples/button_example.h b/chromium/ui/views/examples/button_example.h
index 6f23a0be1c1..d195faa6820 100644
--- a/chromium/ui/views/examples/button_example.h
+++ b/chromium/ui/views/examples/button_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_BUTTON_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_BUTTON_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/text_button.h"
#include "ui/views/examples/example_base.h"
@@ -18,19 +17,20 @@ class LabelButton;
namespace examples {
// ButtonExample simply counts the number of clicks.
-class ButtonExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT ButtonExample : public ExampleBase,
+ public ButtonListener {
public:
ButtonExample();
virtual ~ButtonExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
void TextButtonPressed(const ui::Event& event);
void LabelButtonPressed(const ui::Event& event);
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
// Example buttons.
diff --git a/chromium/ui/views/examples/checkbox_example.cc b/chromium/ui/views/examples/checkbox_example.cc
index cfe930fd0ca..b25dd8e8d86 100644
--- a/chromium/ui/views/examples/checkbox_example.cc
+++ b/chromium/ui/views/examples/checkbox_example.cc
@@ -20,7 +20,7 @@ CheckboxExample::~CheckboxExample() {
}
void CheckboxExample::CreateExampleView(View* container) {
- button_ = new Checkbox(ASCIIToUTF16("Checkbox"));
+ button_ = new Checkbox(base::ASCIIToUTF16("Checkbox"));
button_->set_listener(this);
container->SetLayoutManager(new FillLayout);
container->AddChildView(button_);
diff --git a/chromium/ui/views/examples/checkbox_example.h b/chromium/ui/views/examples/checkbox_example.h
index 1b0e52f5a3a..a5a8964513e 100644
--- a/chromium/ui/views/examples/checkbox_example.h
+++ b/chromium/ui/views/examples/checkbox_example.h
@@ -5,7 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_CHECKBOX_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_CHECKBOX_EXAMPLE_H_
-#include "base/basictypes.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
@@ -15,7 +15,8 @@ class Checkbox;
namespace examples {
// CheckboxExample exercises a Checkbox control.
-class CheckboxExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT CheckboxExample : public ExampleBase,
+ public ButtonListener {
public:
CheckboxExample();
virtual ~CheckboxExample();
diff --git a/chromium/ui/views/examples/combobox_example.cc b/chromium/ui/views/examples/combobox_example.cc
index 4c2a1b8cc26..ed07379b605 100644
--- a/chromium/ui/views/examples/combobox_example.cc
+++ b/chromium/ui/views/examples/combobox_example.cc
@@ -22,8 +22,8 @@ int ComboboxModelExample::GetItemCount() const {
return 10;
}
-string16 ComboboxModelExample::GetItemAt(int index) {
- return UTF8ToUTF16(base::StringPrintf("Item %d", index));
+base::string16 ComboboxModelExample::GetItemAt(int index) {
+ return base::UTF8ToUTF16(base::StringPrintf("Item %d", index));
}
ComboboxExample::ComboboxExample() : ExampleBase("Combo Box"), combobox_(NULL) {
@@ -44,9 +44,9 @@ void ComboboxExample::CreateExampleView(View* container) {
container->AddChildView(combobox_);
}
-void ComboboxExample::OnSelectedIndexChanged(Combobox* combobox) {
+void ComboboxExample::OnPerformAction(Combobox* combobox) {
DCHECK_EQ(combobox_, combobox);
- PrintStatus("Selected: %s", UTF16ToUTF8(combobox_model_.GetItemAt(
+ PrintStatus("Selected: %s", base::UTF16ToUTF8(combobox_model_.GetItemAt(
combobox->selected_index())).c_str());
}
diff --git a/chromium/ui/views/examples/combobox_example.h b/chromium/ui/views/examples/combobox_example.h
index 263782d54e3..89ccff2e986 100644
--- a/chromium/ui/views/examples/combobox_example.h
+++ b/chromium/ui/views/examples/combobox_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_COMBOBOX_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_COMBOBOX_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/base/models/combobox_model.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/examples/example_base.h"
@@ -15,30 +14,31 @@ namespace views {
namespace examples {
// A combobox model implementation that generates a list of "Item <index>".
-class ComboboxModelExample : public ui::ComboboxModel {
+class VIEWS_EXAMPLES_EXPORT ComboboxModelExample : public ui::ComboboxModel {
public:
ComboboxModelExample();
virtual ~ComboboxModelExample();
- // Overridden from ui::ComboboxModel:
+ // ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE;
- virtual string16 GetItemAt(int index) OVERRIDE;
+ virtual base::string16 GetItemAt(int index) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(ComboboxModelExample);
};
-class ComboboxExample : public ExampleBase, public ComboboxListener {
+class VIEWS_EXAMPLES_EXPORT ComboboxExample : public ExampleBase,
+ public ComboboxListener {
public:
ComboboxExample();
virtual ~ComboboxExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from ComboboxListener:
- virtual void OnSelectedIndexChanged(Combobox* combobox) OVERRIDE;
+ // ComboboxListener:
+ virtual void OnPerformAction(Combobox* combobox) OVERRIDE;
ComboboxModelExample combobox_model_;
Combobox* combobox_;
diff --git a/chromium/ui/views/examples/content_client/DEPS b/chromium/ui/views/examples/content_client/DEPS
deleted file mode 100644
index f71262e800a..00000000000
--- a/chromium/ui/views/examples/content_client/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+content/public",
- "+content/shell",
-]
diff --git a/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc b/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc
deleted file mode 100644
index e270d6fef12..00000000000
--- a/chromium/ui/views/examples/content_client/examples_browser_main_parts.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/examples/content_client/examples_browser_main_parts.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "content/public/common/content_switches.h"
-#include "content/shell/browser/shell_browser_context.h"
-#include "ui/base/ime/input_method_initializer.h"
-#include "ui/views/examples/examples_window_with_content.h"
-#include "ui/views/focus/accelerator_handler.h"
-#include "ui/views/test/desktop_test_views_delegate.h"
-#include "url/gurl.h"
-
-#if defined(USE_AURA)
-#include "ui/aura/env.h"
-#include "ui/gfx/screen.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
-#include "ui/views/widget/native_widget_aura.h"
-#endif
-
-#if defined(OS_CHROMEOS)
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/test_screen.h"
-#include "ui/aura/window.h"
-#include "ui/wm/test/wm_test_helper.h"
-#endif
-
-namespace views {
-namespace examples {
-
-ExamplesBrowserMainParts::ExamplesBrowserMainParts(
- const content::MainFunctionParams& parameters) {
-}
-
-ExamplesBrowserMainParts::~ExamplesBrowserMainParts() {
-}
-
-void ExamplesBrowserMainParts::PreMainMessageLoopRun() {
- ui::InitializeInputMethodForTesting();
- browser_context_.reset(new content::ShellBrowserContext(false, NULL));
-
- gfx::NativeView window_context = NULL;
-#if defined(OS_CHROMEOS)
- gfx::Screen::SetScreenInstance(
- gfx::SCREEN_TYPE_NATIVE, aura::TestScreen::Create());
- // Set up basic pieces of views::corewm.
- wm_test_helper_.reset(new wm::WMTestHelper(gfx::Size(800, 600)));
- // Ensure the X window gets mapped.
- wm_test_helper_->root_window()->host()->Show();
- // Ensure Aura knows where to open new windows.
- window_context = wm_test_helper_->root_window()->window();
-#elif defined(USE_AURA)
- aura::Env::CreateInstance();
- gfx::Screen::SetScreenInstance(
- gfx::SCREEN_TYPE_NATIVE, CreateDesktopScreen());
-#endif
- views_delegate_.reset(new DesktopTestViewsDelegate);
-
- ShowExamplesWindowWithContent(
- QUIT_ON_CLOSE, browser_context_.get(), window_context);
-}
-
-void ExamplesBrowserMainParts::PostMainMessageLoopRun() {
- browser_context_.reset();
-#if defined(OS_CHROMEOS)
- wm_test_helper_.reset();
-#endif
- views_delegate_.reset();
-#if defined(USE_AURA)
- aura::Env::DeleteInstance();
-#endif
-}
-
-bool ExamplesBrowserMainParts::MainMessageLoopRun(int* result_code) {
- // xxx: Hax here because this kills event handling.
-#if !defined(USE_AURA)
- AcceleratorHandler accelerator_handler;
- base::RunLoop run_loop(&accelerator_handler);
-#else
- base::RunLoop run_loop;
-#endif
- run_loop.Run();
- return true;
-}
-
-} // namespace examples
-} // namespace views
diff --git a/chromium/ui/views/examples/content_client/examples_browser_main_parts.h b/chromium/ui/views/examples/content_client/examples_browser_main_parts.h
deleted file mode 100644
index c3e3172c6d5..00000000000
--- a/chromium/ui/views/examples/content_client/examples_browser_main_parts.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_BROWSER_MAIN_PARTS_H_
-#define UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_BROWSER_MAIN_PARTS_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/public/browser/browser_main_parts.h"
-
-namespace content {
-class ShellBrowserContext;
-struct MainFunctionParams;
-}
-
-namespace wm {
-class WMTestHelper;
-}
-
-namespace views {
-class ViewsDelegate;
-
-namespace examples {
-
-class ExamplesBrowserMainParts : public content::BrowserMainParts {
- public:
- explicit ExamplesBrowserMainParts(
- const content::MainFunctionParams& parameters);
- virtual ~ExamplesBrowserMainParts();
-
- // Overridden from content::BrowserMainParts:
- virtual void PreMainMessageLoopRun() OVERRIDE;
- virtual bool MainMessageLoopRun(int* result_code) OVERRIDE;
- virtual void PostMainMessageLoopRun() OVERRIDE;
-
- content::ShellBrowserContext* browser_context() {
- return browser_context_.get();
- }
-
- private:
- scoped_ptr<content::ShellBrowserContext> browser_context_;
-
- scoped_ptr<ViewsDelegate> views_delegate_;
-
-#if defined(OS_CHROMEOS)
- // Enable a minimal set of views::corewm to be initialized.
- scoped_ptr<wm::WMTestHelper> wm_test_helper_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(ExamplesBrowserMainParts);
-};
-
-} // namespace examples
-} // namespace views
-
-#endif // UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_BROWSER_MAIN_PARTS_H_
diff --git a/chromium/ui/views/examples/content_client/examples_content_browser_client.cc b/chromium/ui/views/examples/content_client/examples_content_browser_client.cc
deleted file mode 100644
index 8a4ebc862e9..00000000000
--- a/chromium/ui/views/examples/content_client/examples_content_browser_client.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/examples/content_client/examples_content_browser_client.h"
-
-#include "content/shell/browser/shell_browser_context.h"
-#include "ui/views/examples/content_client/examples_browser_main_parts.h"
-
-namespace views {
-namespace examples {
-
-ExamplesContentBrowserClient::ExamplesContentBrowserClient()
- : examples_browser_main_parts_(NULL) {
-}
-
-ExamplesContentBrowserClient::~ExamplesContentBrowserClient() {
-}
-
-content::BrowserMainParts* ExamplesContentBrowserClient::CreateBrowserMainParts(
- const content::MainFunctionParams& parameters) {
- examples_browser_main_parts_ = new ExamplesBrowserMainParts(parameters);
- return examples_browser_main_parts_;
-}
-
-net::URLRequestContextGetter*
-ExamplesContentBrowserClient::CreateRequestContext(
- content::BrowserContext* content_browser_context,
- content::ProtocolHandlerMap* protocol_handlers) {
- content::ShellBrowserContext* shell_context =
- examples_browser_main_parts_->browser_context();
- return shell_context->CreateRequestContext(protocol_handlers);
-}
-
-} // namespace examples
-} // namespace views
diff --git a/chromium/ui/views/examples/content_client/examples_content_browser_client.h b/chromium/ui/views/examples/content_client/examples_content_browser_client.h
deleted file mode 100644
index b49d2c0528e..00000000000
--- a/chromium/ui/views/examples/content_client/examples_content_browser_client.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_CONTENT_BROWSER_CLIENT_H_
-#define UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_CONTENT_BROWSER_CLIENT_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/public/browser/content_browser_client.h"
-
-namespace content {
-class ShellBrowserContext;
-}
-
-namespace views {
-namespace examples {
-
-class ExamplesBrowserMainParts;
-
-class ExamplesContentBrowserClient : public content::ContentBrowserClient {
- public:
- ExamplesContentBrowserClient();
- virtual ~ExamplesContentBrowserClient();
-
- // Overridden from content::ContentBrowserClient:
- virtual content::BrowserMainParts* CreateBrowserMainParts(
- const content::MainFunctionParams& parameters) OVERRIDE;
- virtual net::URLRequestContextGetter* CreateRequestContext(
- content::BrowserContext* browser_context,
- content::ProtocolHandlerMap* protocol_handlers) OVERRIDE;
-
- private:
- ExamplesBrowserMainParts* examples_browser_main_parts_;
-
- DISALLOW_COPY_AND_ASSIGN(ExamplesContentBrowserClient);
-};
-
-} // namespace examples
-} // namespace views
-
-#endif // UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_CONTENT_BROWSER_CLIENT_H_
diff --git a/chromium/ui/views/examples/content_client/examples_main.cc b/chromium/ui/views/examples/content_client/examples_main.cc
deleted file mode 100644
index bb2b059b71e..00000000000
--- a/chromium/ui/views/examples/content_client/examples_main.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/app/content_main.h"
-#include "sandbox/win/src/sandbox_types.h"
-#include "ui/views/examples/content_client/examples_main_delegate.h"
-
-#if defined(OS_WIN)
-#include "content/public/app/startup_helper_win.h"
-#endif
-
-#if defined(OS_WIN)
-int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) {
- sandbox::SandboxInterfaceInfo sandbox_info = {0};
- content::InitializeSandboxInfo(&sandbox_info);
- views::examples::ExamplesMainDelegate delegate;
- return content::ContentMain(instance, &sandbox_info, &delegate);
-}
-#else
-int main(int argc, const char** argv) {
- views::examples::ExamplesMainDelegate delegate;
- return content::ContentMain(argc, argv, &delegate);
-}
-#endif
diff --git a/chromium/ui/views/examples/content_client/examples_main_delegate.cc b/chromium/ui/views/examples/content_client/examples_main_delegate.cc
deleted file mode 100644
index aabd289d868..00000000000
--- a/chromium/ui/views/examples/content_client/examples_main_delegate.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/examples/content_client/examples_main_delegate.h"
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "content/public/common/content_switches.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_paths.h"
-#include "ui/views/examples/content_client/examples_content_browser_client.h"
-
-#if defined(OS_WIN)
-#include "base/logging_win.h"
-#endif
-
-namespace views {
-namespace examples {
-namespace {
-
-#if defined(OS_WIN)
-// {83FAC8EE-7A0E-4dbb-A3F6-6F500D7CAB1A}
-const GUID kViewsExamplesProviderName =
- { 0x83fac8ee, 0x7a0e, 0x4dbb,
- { 0xa3, 0xf6, 0x6f, 0x50, 0xd, 0x7c, 0xab, 0x1a } };
-#endif
-
-} // namespace
-
-ExamplesMainDelegate::ExamplesMainDelegate() {
-}
-
-ExamplesMainDelegate::~ExamplesMainDelegate() {
-}
-
-bool ExamplesMainDelegate::BasicStartupComplete(int* exit_code) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
-
- content::SetContentClient(&content_client_);
-
- logging::LoggingSettings settings;
- settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
- bool success = logging::InitLogging(settings);
- CHECK(success);
-#if defined(OS_WIN)
- logging::LogEventProvider::Initialize(kViewsExamplesProviderName);
-#endif
-
- return false;
-}
-
-void ExamplesMainDelegate::PreSandboxStartup() {
- InitializeResourceBundle();
-}
-
-content::ContentBrowserClient*
- ExamplesMainDelegate::CreateContentBrowserClient() {
- browser_client_.reset(new ExamplesContentBrowserClient);
- return browser_client_.get();
-}
-
-void ExamplesMainDelegate::InitializeResourceBundle() {
- base::FilePath pak_dir;
- PathService::Get(base::DIR_MODULE, &pak_dir);
-
- base::FilePath pak_file;
- pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
-
- ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
-}
-
-} // namespace examples
-} // namespace views
diff --git a/chromium/ui/views/examples/content_client/examples_main_delegate.h b/chromium/ui/views/examples/content_client/examples_main_delegate.h
deleted file mode 100644
index e8cb493f613..00000000000
--- a/chromium/ui/views/examples/content_client/examples_main_delegate.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_MAIN_DELEGATE_H_
-#define UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_MAIN_DELEGATE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/public/app/content_main_delegate.h"
-#include "content/shell/common/shell_content_client.h"
-
-namespace views {
-namespace examples {
-
-class ExamplesContentBrowserClient;
-
-class ExamplesMainDelegate : public content::ContentMainDelegate {
- public:
- ExamplesMainDelegate();
- virtual ~ExamplesMainDelegate();
-
- // content::ContentMainDelegate implementation
- virtual bool BasicStartupComplete(int* exit_code) OVERRIDE;
- virtual void PreSandboxStartup() OVERRIDE;
- virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
-
- private:
- void InitializeResourceBundle();
-
- scoped_ptr<ExamplesContentBrowserClient> browser_client_;
- content::ShellContentClient content_client_;
-
- DISALLOW_COPY_AND_ASSIGN(ExamplesMainDelegate);
-};
-
-} // namespace examples
-} // namespace views
-
-#endif // UI_VIEWS_EXAMPLES_CONTENT_CLIENT_EXAMPLES_MAIN_DELEGATE_H_
diff --git a/chromium/ui/views/examples/double_split_view_example.cc b/chromium/ui/views/examples/double_split_view_example.cc
index fb1f099a1f9..8ff40df66a8 100644
--- a/chromium/ui/views/examples/double_split_view_example.cc
+++ b/chromium/ui/views/examples/double_split_view_example.cc
@@ -21,8 +21,8 @@ class SplittedView : public View {
void SetColor(SkColor from, SkColor to);
- // Overridden from View.
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ // View:
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(SplittedView);
@@ -39,7 +39,7 @@ void SplittedView::SetColor(SkColor from, SkColor to) {
set_background(Background::CreateVerticalGradientBackground(from, to));
}
-gfx::Size SplittedView::GetMinimumSize() {
+gfx::Size SplittedView::GetMinimumSize() const {
return gfx::Size(10, 10);
}
diff --git a/chromium/ui/views/examples/double_split_view_example.h b/chromium/ui/views/examples/double_split_view_example.h
index 7fbae46b212..fe37c792657 100644
--- a/chromium/ui/views/examples/double_split_view_example.h
+++ b/chromium/ui/views/examples/double_split_view_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_DOUBLE_SPLIT_VIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_DOUBLE_SPLIT_VIEW_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace views {
@@ -14,12 +13,12 @@ class SingleSplitView;
namespace examples {
-class DoubleSplitViewExample : public ExampleBase {
+class VIEWS_EXAMPLES_EXPORT DoubleSplitViewExample : public ExampleBase {
public:
DoubleSplitViewExample();
virtual ~DoubleSplitViewExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
diff --git a/chromium/ui/views/examples/example_base.cc b/chromium/ui/views/examples/example_base.cc
index 66a6c854c4a..a06fc1dcfea 100644
--- a/chromium/ui/views/examples/example_base.cc
+++ b/chromium/ui/views/examples/example_base.cc
@@ -6,7 +6,6 @@
#include <stdarg.h>
-#include "base/compiler_specific.h"
#include "base/strings/stringprintf.h"
#include "ui/views/view.h"
@@ -28,7 +27,7 @@ class ContainerView : public View {
}
private:
- // Overridden from View:
+ // View:
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE {
View::ViewHierarchyChanged(details);
diff --git a/chromium/ui/views/examples/example_base.h b/chromium/ui/views/examples/example_base.h
index a17cc0d0f91..f841eb920b1 100644
--- a/chromium/ui/views/examples/example_base.h
+++ b/chromium/ui/views/examples/example_base.h
@@ -7,14 +7,15 @@
#include <string>
-#include "base/basictypes.h"
+#include "base/macros.h"
+#include "ui/views/examples/views_examples_export.h"
namespace views {
class View;
namespace examples {
-class ExampleBase {
+class VIEWS_EXAMPLES_EXPORT ExampleBase {
public:
virtual ~ExampleBase();
diff --git a/chromium/ui/views/examples/example_combobox_model.cc b/chromium/ui/views/examples/example_combobox_model.cc
index 255ef15af96..a1160e7bb0e 100644
--- a/chromium/ui/views/examples/example_combobox_model.cc
+++ b/chromium/ui/views/examples/example_combobox_model.cc
@@ -20,8 +20,8 @@ int ExampleComboboxModel::GetItemCount() const {
return count_;
}
-string16 ExampleComboboxModel::GetItemAt(int index) {
- return ASCIIToUTF16(strings_[index]);
+base::string16 ExampleComboboxModel::GetItemAt(int index) {
+ return base::ASCIIToUTF16(strings_[index]);
}
} // namespace examples
diff --git a/chromium/ui/views/examples/example_combobox_model.h b/chromium/ui/views/examples/example_combobox_model.h
index 74262d8b90f..3b233323ef5 100644
--- a/chromium/ui/views/examples/example_combobox_model.h
+++ b/chromium/ui/views/examples/example_combobox_model.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_EXAMPLE_COMBOBOX_MODEL_H_
#define UI_VIEWS_EXAMPLES_EXAMPLE_COMBOBOX_MODEL_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/base/models/combobox_model.h"
namespace views {
@@ -17,9 +16,9 @@ class ExampleComboboxModel : public ui::ComboboxModel {
ExampleComboboxModel(const char** strings, int count);
virtual ~ExampleComboboxModel();
- // Overridden from ui::ComboboxModel:
+ // ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE;
- virtual string16 GetItemAt(int index) OVERRIDE;
+ virtual base::string16 GetItemAt(int index) OVERRIDE;
private:
const char** strings_;
diff --git a/chromium/ui/views/examples/examples.gyp b/chromium/ui/views/examples/examples.gyp
new file mode 100644
index 00000000000..4cf3a1bcf6b
--- /dev/null
+++ b/chromium/ui/views/examples/examples.gyp
@@ -0,0 +1,187 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ 'target_name': 'views_examples_lib',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../skia/skia.gyp:skia',
+ '../../../third_party/icu/icu.gyp:icui18n',
+ '../../../third_party/icu/icu.gyp:icuuc',
+ '../../base/ui_base.gyp:ui_base',
+ '../../events/events.gyp:events',
+ '../../gfx/gfx.gyp:gfx',
+ '../../gfx/gfx.gyp:gfx_geometry',
+ '../../resources/ui_resources.gyp:ui_resources',
+ '../../resources/ui_resources.gyp:ui_test_pak',
+ '../views.gyp:views',
+ ],
+ 'include_dirs': [
+ '../../..',
+ ],
+ 'defines': [
+ 'VIEWS_EXAMPLES_IMPLEMENTATION',
+ ],
+ 'sources': [
+ 'bubble_example.cc',
+ 'bubble_example.h',
+ 'button_example.cc',
+ 'button_example.h',
+ 'checkbox_example.cc',
+ 'checkbox_example.h',
+ 'combobox_example.cc',
+ 'combobox_example.h',
+ 'double_split_view_example.cc',
+ 'double_split_view_example.h',
+ 'example_base.cc',
+ 'example_base.h',
+ 'example_combobox_model.cc',
+ 'example_combobox_model.h',
+ 'examples_window.cc',
+ 'examples_window.h',
+ 'label_example.cc',
+ 'label_example.h',
+ 'link_example.cc',
+ 'link_example.h',
+ 'message_box_example.cc',
+ 'message_box_example.h',
+ 'menu_example.cc',
+ 'menu_example.h',
+ 'multiline_example.cc',
+ 'multiline_example.h',
+ 'progress_bar_example.cc',
+ 'progress_bar_example.h',
+ 'radio_button_example.cc',
+ 'radio_button_example.h',
+ 'scroll_view_example.cc',
+ 'scroll_view_example.h',
+ 'single_split_view_example.cc',
+ 'single_split_view_example.h',
+ 'slider_example.cc',
+ 'slider_example.h',
+ 'tabbed_pane_example.cc',
+ 'tabbed_pane_example.h',
+ 'table_example.cc',
+ 'table_example.h',
+ 'text_example.cc',
+ 'text_example.h',
+ 'textfield_example.cc',
+ 'textfield_example.h',
+ 'throbber_example.cc',
+ 'throbber_example.h',
+ 'tree_view_example.cc',
+ 'tree_view_example.h',
+ 'views_examples_export.h',
+ 'widget_example.cc',
+ 'widget_example.h',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'include_dirs': [
+ '../../../third_party/wtl/include',
+ ],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ }],
+ ['use_aura==1', {
+ 'dependencies': [
+ '../../aura/aura.gyp:aura',
+ ],
+ }],
+ ],
+ }, # target_name: views_examples_lib
+ {
+ 'target_name': 'views_examples_exe',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../base/base.gyp:base_i18n',
+ '../../base/ui_base.gyp:ui_base',
+ '../../compositor/compositor.gyp:compositor',
+ '../../compositor/compositor.gyp:compositor_test_support',
+ '../../gfx/gfx.gyp:gfx',
+ '../../resources/ui_resources.gyp:ui_test_pak',
+ '../views.gyp:views',
+ '../views.gyp:views_test_support',
+ 'views_examples_lib',
+ ],
+ 'sources': [
+ 'examples_main.cc',
+ ],
+ 'conditions': [
+ ['use_aura==1', {
+ 'dependencies': [
+ '../../aura/aura.gyp:aura',
+ ],
+ }],
+ ],
+ }, # target_name: views_examples_exe
+ {
+ 'target_name': 'views_examples_with_content_lib',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../content/content.gyp:content',
+ '../../../skia/skia.gyp:skia',
+ '../../../url/url.gyp:url_lib',
+ '../../events/events.gyp:events',
+ '../controls/webview/webview.gyp:webview',
+ '../views.gyp:views',
+ 'views_examples_lib',
+ ],
+ 'defines': [
+ 'VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION',
+ ],
+ 'sources': [
+ 'examples_window_with_content.cc',
+ 'examples_window_with_content.h',
+ 'views_examples_with_content_export.h',
+ 'webview_example.cc',
+ 'webview_example.h',
+ ],
+ }, # target_name: views_examples_with_content_lib
+ {
+ 'target_name': 'views_examples_with_content_exe',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../content/content.gyp:content',
+ '../../views_content_client/views_content_client.gyp:views_content_client',
+ 'views_examples_with_content_lib',
+ ],
+ 'sources': [
+ '../../../content/app/startup_helper_win.cc',
+ 'examples_with_content_main_exe.cc',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'link_settings': {
+ 'libraries': [
+ '-limm32.lib',
+ '-loleacc.lib',
+ ]
+ },
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'AdditionalManifestFiles': [
+ 'views_examples.exe.manifest',
+ ],
+ },
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ 'dependencies': [
+ '../../../sandbox/sandbox.gyp:sandbox',
+ ],
+ }],
+ ],
+ }, # target_name: views_examples_with_content_exe
+ ],
+}
diff --git a/chromium/ui/views/examples/examples_main.cc b/chromium/ui/views/examples/examples_main.cc
index 28864c477c8..4dc9fbec153 100644
--- a/chromium/ui/views/examples/examples_main.cc
+++ b/chromium/ui/views/examples/examples_main.cc
@@ -4,16 +4,94 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/i18n/icu_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
#include "base/run_loop.h"
+#include "ui/aura/env.h"
+#include "ui/base/ime/input_method_initializer.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_paths.h"
+#include "ui/compositor/test/in_process_context_factory.h"
+#include "ui/gfx/screen.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/views/examples/example_base.h"
+#include "ui/views/examples/examples_window.h"
+#include "ui/views/test/desktop_test_views_delegate.h"
+#include "ui/wm/core/wm_state.h"
+
+#if !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#endif
+
+#if defined(OS_WIN)
+#include "ui/base/win/scoped_ole_initializer.h"
+#endif
+
+#if defined(USE_X11)
+#include "ui/gfx/x/x11_connection.h"
+#endif
int main(int argc, char** argv) {
- base::AtExitManager at_exit;
+#if defined(OS_WIN)
+ ui::ScopedOleInitializer ole_initializer_;
+#endif
+
CommandLine::Init(argc, argv);
- base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
+ base::AtExitManager at_exit;
+
+#if defined(USE_X11)
+ // This demo uses InProcessContextFactory which uses X on a separate Gpu
+ // thread.
+ gfx::InitializeThreadedX11();
+#endif
+
+ gfx::GLSurface::InitializeOneOff();
+
+ // The ContextFactory must exist before any Compositors are created.
+ scoped_ptr<ui::InProcessContextFactory> context_factory(
+ new ui::InProcessContextFactory());
+
+ base::MessageLoopForUI message_loop;
+
+ base::i18n::InitializeICU();
+
+ ui::RegisterPathProvider();
+
+ base::FilePath ui_test_pak_path;
+ DCHECK(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
+
+ aura::Env::CreateInstance(true);
+ aura::Env::GetInstance()->set_context_factory(context_factory.get());
+
+ ui::InitializeInputMethodForTesting();
+
+ {
+ views::DesktopTestViewsDelegate views_delegate;
+ wm::WMState wm_state;
+
+#if !defined(OS_CHROMEOS)
+ scoped_ptr<gfx::Screen> desktop_screen(views::CreateDesktopScreen());
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
+ desktop_screen.get());
+#endif
+
+ views::examples::ShowExamplesWindow(
+ views::examples::QUIT_ON_CLOSE,
+ NULL,
+ scoped_ptr<ScopedVector<views::examples::ExampleBase> >());
+
+ base::RunLoop().Run();
+
+ ui::ResourceBundle::CleanupSharedInstance();
+ }
+
+ ui::ShutdownInputMethod();
- base::RunLoop().Run();
+ aura::Env::DeleteInstance();
return 0;
}
diff --git a/chromium/ui/views/examples/examples_window.cc b/chromium/ui/views/examples/examples_window.cc
index 041199286d1..55474440723 100644
--- a/chromium/ui/views/examples/examples_window.cc
+++ b/chromium/ui/views/examples/examples_window.cc
@@ -4,6 +4,7 @@
#include "ui/views/examples/examples_window.h"
+#include <algorithm>
#include <string>
#include "base/memory/scoped_vector.h"
@@ -43,26 +44,76 @@
namespace views {
namespace examples {
+typedef scoped_ptr<ScopedVector<ExampleBase> > ScopedExamples;
+
+namespace {
+
+// Creates the default set of examples. Caller owns the result.
+ScopedExamples CreateExamples() {
+ ScopedExamples examples(new ScopedVector<ExampleBase>);
+ examples->push_back(new BubbleExample);
+ examples->push_back(new ButtonExample);
+ examples->push_back(new CheckboxExample);
+ examples->push_back(new ComboboxExample);
+ examples->push_back(new DoubleSplitViewExample);
+ examples->push_back(new LabelExample);
+ examples->push_back(new LinkExample);
+ examples->push_back(new MenuExample);
+ examples->push_back(new MessageBoxExample);
+ examples->push_back(new MultilineExample);
+ examples->push_back(new ProgressBarExample);
+ examples->push_back(new RadioButtonExample);
+ examples->push_back(new ScrollViewExample);
+ examples->push_back(new SingleSplitViewExample);
+ examples->push_back(new SliderExample);
+ examples->push_back(new TabbedPaneExample);
+ examples->push_back(new TableExample);
+ examples->push_back(new TextExample);
+ examples->push_back(new TextfieldExample);
+ examples->push_back(new ThrobberExample);
+ examples->push_back(new TreeViewExample);
+ examples->push_back(new WidgetExample);
+ return examples.Pass();
+}
+
+struct ExampleTitleCompare {
+ bool operator() (ExampleBase* a, ExampleBase* b) {
+ return a->example_title() < b->example_title();
+ }
+};
+
+ScopedExamples GetExamplesToShow(ScopedExamples extra) {
+ ScopedExamples examples(CreateExamples());
+ if (extra.get()) {
+ examples->insert(examples->end(), extra->begin(), extra->end());
+ extra->weak_clear();
+ }
+ std::sort(examples->begin(), examples->end(), ExampleTitleCompare());
+ return examples.Pass();
+}
+
+} // namespace
+
// Model for the examples that are being added via AddExample().
class ComboboxModelExampleList : public ui::ComboboxModel {
public:
ComboboxModelExampleList() {}
virtual ~ComboboxModelExampleList() {}
- // Overridden from ui::ComboboxModel:
+ void SetExamples(ScopedExamples examples) {
+ example_list_.swap(*examples);
+ }
+
+ // ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE { return example_list_.size(); }
- virtual string16 GetItemAt(int index) OVERRIDE {
- return UTF8ToUTF16(example_list_[index]->example_title());
+ virtual base::string16 GetItemAt(int index) OVERRIDE {
+ return base::UTF8ToUTF16(example_list_[index]->example_title());
}
View* GetItemViewAt(int index) {
return example_list_[index]->example_view();
}
- void AddExample(ExampleBase* example) {
- example_list_.push_back(example);
- }
-
private:
ScopedVector<ExampleBase> example_list_;
@@ -72,14 +123,40 @@ class ComboboxModelExampleList : public ui::ComboboxModel {
class ExamplesWindowContents : public WidgetDelegateView,
public ComboboxListener {
public:
- ExamplesWindowContents(Operation operation)
+ ExamplesWindowContents(Operation operation, ScopedExamples examples)
: combobox_(new Combobox(&combobox_model_)),
example_shown_(new View),
status_label_(new Label),
operation_(operation) {
instance_ = this;
combobox_->set_listener(this);
+ combobox_model_.SetExamples(examples.Pass());
+ combobox_->ModelChanged();
+
+ set_background(Background::CreateStandardPanelBackground());
+ GridLayout* layout = new GridLayout(this);
+ SetLayoutManager(layout);
+ ColumnSet* column_set = layout->AddColumnSet(0);
+ column_set->AddPaddingColumn(0, 5);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, 5);
+ layout->AddPaddingRow(0, 5);
+ layout->StartRow(0 /* no expand */, 0);
+ layout->AddView(combobox_);
+
+ if (combobox_model_.GetItemCount() > 0) {
+ layout->StartRow(1, 0);
+ example_shown_->SetLayoutManager(new FillLayout());
+ example_shown_->AddChildView(combobox_model_.GetItemViewAt(0));
+ layout->AddView(example_shown_);
+ }
+
+ layout->StartRow(0 /* no expand */, 0);
+ layout->AddView(status_label_);
+ layout->AddPaddingRow(0, 5);
}
+
virtual ~ExamplesWindowContents() {
// Delete |combobox_| first as it references |combobox_model_|.
delete combobox_;
@@ -88,17 +165,17 @@ class ExamplesWindowContents : public WidgetDelegateView,
// Prints a message in the status area, at the bottom of the window.
void SetStatus(const std::string& status) {
- status_label_->SetText(UTF8ToUTF16(status));
+ status_label_->SetText(base::UTF8ToUTF16(status));
}
static ExamplesWindowContents* instance() { return instance_; }
private:
- // Overridden from WidgetDelegateView:
+ // WidgetDelegateView:
virtual bool CanResize() const OVERRIDE { return true; }
virtual bool CanMaximize() const OVERRIDE { return true; }
- virtual string16 GetWindowTitle() const OVERRIDE {
- return ASCIIToUTF16("Views Examples");
+ virtual base::string16 GetWindowTitle() const OVERRIDE {
+ return base::ASCIIToUTF16("Views Examples");
}
virtual View* GetContentsView() OVERRIDE { return this; }
virtual void WindowClosing() OVERRIDE {
@@ -107,15 +184,8 @@ class ExamplesWindowContents : public WidgetDelegateView,
base::MessageLoopForUI::current()->Quit();
}
- // Overridden from View:
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE {
- if (details.is_add && details.child == this)
- InitExamplesWindow();
- }
-
- // Overridden from ComboboxListener:
- virtual void OnSelectedIndexChanged(Combobox* combobox) OVERRIDE {
+ // ComboboxListener:
+ virtual void OnPerformAction(Combobox* combobox) OVERRIDE {
DCHECK_EQ(combobox, combobox_);
DCHECK(combobox->selected_index() < combobox_model_.GetItemCount());
example_shown_->RemoveAllChildViews(false);
@@ -126,61 +196,6 @@ class ExamplesWindowContents : public WidgetDelegateView,
Layout();
}
- // Creates the layout within the examples window.
- void InitExamplesWindow() {
- AddExamples();
-
- set_background(Background::CreateStandardPanelBackground());
- GridLayout* layout = new GridLayout(this);
- SetLayoutManager(layout);
- ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddPaddingColumn(0, 5);
- column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
- GridLayout::USE_PREF, 0, 0);
- column_set->AddPaddingColumn(0, 5);
- layout->AddPaddingRow(0, 5);
- layout->StartRow(0 /* no expand */, 0);
- layout->AddView(combobox_);
-
- if (combobox_model_.GetItemCount() > 0) {
- layout->StartRow(1, 0);
- example_shown_->SetLayoutManager(new FillLayout());
- example_shown_->AddChildView(combobox_model_.GetItemViewAt(0));
- layout->AddView(example_shown_);
- }
-
- layout->StartRow(0 /* no expand */, 0);
- layout->AddView(status_label_);
- layout->AddPaddingRow(0, 5);
- }
-
- // Adds all the individual examples to the combobox model.
- void AddExamples() {
- // Please keep this list in alphabetical order!
- combobox_model_.AddExample(new BubbleExample);
- combobox_model_.AddExample(new ButtonExample);
- combobox_model_.AddExample(new CheckboxExample);
- combobox_model_.AddExample(new ComboboxExample);
- combobox_model_.AddExample(new DoubleSplitViewExample);
- combobox_model_.AddExample(new LabelExample);
- combobox_model_.AddExample(new LinkExample);
- combobox_model_.AddExample(new MenuExample);
- combobox_model_.AddExample(new MessageBoxExample);
- combobox_model_.AddExample(new MultilineExample);
- combobox_model_.AddExample(new ProgressBarExample);
- combobox_model_.AddExample(new RadioButtonExample);
- combobox_model_.AddExample(new ScrollViewExample);
- combobox_model_.AddExample(new SingleSplitViewExample);
- combobox_model_.AddExample(new SliderExample);
- combobox_model_.AddExample(new TabbedPaneExample);
- combobox_model_.AddExample(new TableExample);
- combobox_model_.AddExample(new TextExample);
- combobox_model_.AddExample(new TextfieldExample);
- combobox_model_.AddExample(new ThrobberExample);
- combobox_model_.AddExample(new TreeViewExample);
- combobox_model_.AddExample(new WidgetExample);
- }
-
static ExamplesWindowContents* instance_;
ComboboxModelExampleList combobox_model_;
Combobox* combobox_;
@@ -194,12 +209,21 @@ class ExamplesWindowContents : public WidgetDelegateView,
// static
ExamplesWindowContents* ExamplesWindowContents::instance_ = NULL;
-void ShowExamplesWindow(Operation operation) {
+void ShowExamplesWindow(Operation operation,
+ gfx::NativeView window_context,
+ ScopedExamples extra_examples) {
if (ExamplesWindowContents::instance()) {
ExamplesWindowContents::instance()->GetWidget()->Activate();
} else {
- Widget::CreateWindowWithBounds(new ExamplesWindowContents(operation),
- gfx::Rect(0, 0, 850, 300))->Show();
+ ScopedExamples examples(GetExamplesToShow(extra_examples.Pass()));
+ Widget* widget = new Widget;
+ Widget::InitParams params;
+ params.delegate = new ExamplesWindowContents(operation, examples.Pass());
+ params.context = window_context;
+ params.bounds = gfx::Rect(0, 0, 850, 300);
+ params.remove_standard_frame = true;
+ widget->Init(params);
+ widget->Show();
}
}
diff --git a/chromium/ui/views/examples/examples_window.h b/chromium/ui/views/examples/examples_window.h
index 94139db4d09..89222ef84a0 100644
--- a/chromium/ui/views/examples/examples_window.h
+++ b/chromium/ui/views/examples/examples_window.h
@@ -5,18 +5,32 @@
#ifndef UI_VIEWS_EXAMPLES_EXAMPLES_WINDOW_H_
#define UI_VIEWS_EXAMPLES_EXAMPLES_WINDOW_H_
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/views/examples/views_examples_export.h"
+namespace aura {
+class Window;
+}
+
namespace views {
namespace examples {
+class ExampleBase;
+
enum Operation {
DO_NOTHING_ON_CLOSE = 0,
QUIT_ON_CLOSE,
};
-// Shows a window with the views examples in it.
-VIEWS_EXAMPLES_EXPORT void ShowExamplesWindow(Operation operation);
+// Shows a window with the views examples in it. |extra_examples| contains any
+// additional examples to add. |window_context| is used to determine where the
+// window should be created (see |Widget::InitParams::context| for details).
+VIEWS_EXAMPLES_EXPORT void ShowExamplesWindow(
+ Operation operation,
+ gfx::NativeView window_context,
+ scoped_ptr<ScopedVector<ExampleBase> > extra_examples);
} // namespace examples
} // namespace views
diff --git a/chromium/ui/views/examples/examples_window_with_content.cc b/chromium/ui/views/examples/examples_window_with_content.cc
index 3e4e4bd357f..66342ca0e5b 100644
--- a/chromium/ui/views/examples/examples_window_with_content.cc
+++ b/chromium/ui/views/examples/examples_window_with_content.cc
@@ -4,221 +4,19 @@
#include "ui/views/examples/examples_window_with_content.h"
-#include <string>
-
-#include "base/memory/scoped_vector.h"
-#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_context.h"
-#include "ui/base/models/combobox_model.h"
-#include "ui/base/ui_base_paths.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/combobox/combobox.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/examples/bubble_example.h"
-#include "ui/views/examples/button_example.h"
-#include "ui/views/examples/checkbox_example.h"
-#include "ui/views/examples/combobox_example.h"
-#include "ui/views/examples/double_split_view_example.h"
-#include "ui/views/examples/label_example.h"
-#include "ui/views/examples/link_example.h"
-#include "ui/views/examples/menu_example.h"
-#include "ui/views/examples/message_box_example.h"
-#include "ui/views/examples/multiline_example.h"
-#include "ui/views/examples/progress_bar_example.h"
-#include "ui/views/examples/radio_button_example.h"
-#include "ui/views/examples/scroll_view_example.h"
-#include "ui/views/examples/single_split_view_example.h"
-#include "ui/views/examples/slider_example.h"
-#include "ui/views/examples/tabbed_pane_example.h"
-#include "ui/views/examples/table_example.h"
-#include "ui/views/examples/text_example.h"
-#include "ui/views/examples/textfield_example.h"
-#include "ui/views/examples/throbber_example.h"
-#include "ui/views/examples/tree_view_example.h"
#include "ui/views/examples/webview_example.h"
-#include "ui/views/examples/widget_example.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/layout/grid_layout.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_delegate.h"
namespace views {
namespace examples {
-// Model for the examples that are being added via AddExample().
-class ComboboxModelExampleList : public ui::ComboboxModel {
- public:
- ComboboxModelExampleList() {}
- virtual ~ComboboxModelExampleList() {}
-
- // Overridden from ui::ComboboxModel:
- virtual int GetItemCount() const OVERRIDE { return example_list_.size(); }
- virtual string16 GetItemAt(int index) OVERRIDE {
- return UTF8ToUTF16(example_list_[index]->example_title());
- }
-
- View* GetItemViewAt(int index) {
- return example_list_[index]->example_view();
- }
-
- void AddExample(ExampleBase* example) {
- example_list_.push_back(example);
- }
-
- private:
- ScopedVector<ExampleBase> example_list_;
-
- DISALLOW_COPY_AND_ASSIGN(ComboboxModelExampleList);
-};
-
-class ExamplesWindowContents : public WidgetDelegateView,
- public ComboboxListener {
- public:
- ExamplesWindowContents(Operation operation,
- content::BrowserContext* browser_context)
- : combobox_(new Combobox(&combobox_model_)),
- example_shown_(new View),
- status_label_(new Label),
- operation_(operation),
- browser_context_(browser_context) {
- instance_ = this;
- combobox_->set_listener(this);
- }
- virtual ~ExamplesWindowContents() {
- // Delete |combobox_| first as it references |combobox_model_|.
- delete combobox_;
- combobox_ = NULL;
- }
-
- // Prints a message in the status area, at the bottom of the window.
- void SetStatus(const std::string& status) {
- status_label_->SetText(UTF8ToUTF16(status));
- }
-
- static ExamplesWindowContents* instance() { return instance_; }
-
- private:
- // Overridden from WidgetDelegateView:
- virtual bool CanResize() const OVERRIDE { return true; }
- virtual bool CanMaximize() const OVERRIDE { return true; }
- virtual string16 GetWindowTitle() const OVERRIDE {
- return ASCIIToUTF16("Views Examples");
- }
- virtual View* GetContentsView() OVERRIDE { return this; }
- virtual void WindowClosing() OVERRIDE {
- instance_ = NULL;
- if (operation_ == QUIT_ON_CLOSE)
- base::MessageLoopForUI::current()->Quit();
- }
-
- // Overridden from View:
- virtual void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) OVERRIDE {
- if (details.is_add && details.child == this)
- InitExamplesWindow();
- }
-
- // Overridden from ComboboxListener:
- virtual void OnSelectedIndexChanged(Combobox* combobox) OVERRIDE {
- DCHECK_EQ(combobox, combobox_);
- DCHECK(combobox->selected_index() < combobox_model_.GetItemCount());
- example_shown_->RemoveAllChildViews(false);
- example_shown_->AddChildView(combobox_model_.GetItemViewAt(
- combobox->selected_index()));
- SetStatus(std::string());
- Layout();
- SchedulePaint();
- }
-
- // Creates the layout within the examples window.
- void InitExamplesWindow() {
- AddExamples();
-
- set_background(Background::CreateStandardPanelBackground());
- GridLayout* layout = new GridLayout(this);
- SetLayoutManager(layout);
- ColumnSet* column_set = layout->AddColumnSet(0);
- column_set->AddPaddingColumn(0, 5);
- column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
- GridLayout::USE_PREF, 0, 0);
- column_set->AddPaddingColumn(0, 5);
- layout->AddPaddingRow(0, 5);
- layout->StartRow(0 /* no expand */, 0);
- layout->AddView(combobox_);
-
- if (combobox_model_.GetItemCount() > 0) {
- layout->StartRow(1, 0);
- example_shown_->SetLayoutManager(new FillLayout());
- example_shown_->AddChildView(combobox_model_.GetItemViewAt(0));
- layout->AddView(example_shown_);
- }
-
- layout->StartRow(0 /* no expand */, 0);
- layout->AddView(status_label_);
- layout->AddPaddingRow(0, 5);
- }
-
- // Adds all the individual examples to the combobox model.
- void AddExamples() {
- // Please keep this list in alphabetical order!
- combobox_model_.AddExample(new BubbleExample);
- combobox_model_.AddExample(new ButtonExample);
- combobox_model_.AddExample(new CheckboxExample);
- combobox_model_.AddExample(new ComboboxExample);
- combobox_model_.AddExample(new DoubleSplitViewExample);
- combobox_model_.AddExample(new LabelExample);
- combobox_model_.AddExample(new LinkExample);
- combobox_model_.AddExample(new MenuExample);
- combobox_model_.AddExample(new MessageBoxExample);
- combobox_model_.AddExample(new MultilineExample);
- combobox_model_.AddExample(new ProgressBarExample);
- combobox_model_.AddExample(new RadioButtonExample);
- combobox_model_.AddExample(new ScrollViewExample);
- combobox_model_.AddExample(new SingleSplitViewExample);
- combobox_model_.AddExample(new SliderExample);
- combobox_model_.AddExample(new TabbedPaneExample);
- combobox_model_.AddExample(new TableExample);
- combobox_model_.AddExample(new TextExample);
- combobox_model_.AddExample(new TextfieldExample);
- combobox_model_.AddExample(new ThrobberExample);
- combobox_model_.AddExample(new TreeViewExample);
- combobox_model_.AddExample(new WebViewExample(browser_context_));
- combobox_model_.AddExample(new WidgetExample);
- }
-
- static ExamplesWindowContents* instance_;
- ComboboxModelExampleList combobox_model_;
- Combobox* combobox_;
- View* example_shown_;
- Label* status_label_;
- const Operation operation_;
- content::BrowserContext* browser_context_;
-
- DISALLOW_COPY_AND_ASSIGN(ExamplesWindowContents);
-};
-
-// static
-ExamplesWindowContents* ExamplesWindowContents::instance_ = NULL;
-
void ShowExamplesWindowWithContent(Operation operation,
content::BrowserContext* browser_context,
gfx::NativeView window_context) {
- if (ExamplesWindowContents::instance()) {
- ExamplesWindowContents::instance()->GetWidget()->Activate();
- } else {
- Widget* widget = new Widget;
- Widget::InitParams params;
- params.delegate = new ExamplesWindowContents(operation, browser_context);
- params.context = window_context;
- params.bounds = gfx::Rect(0, 0, 850, 300);
- params.top_level = true;
- widget->Init(params);
- widget->Show();
- }
-}
-
-void LogStatus(const std::string& string) {
- ExamplesWindowContents::instance()->SetStatus(string);
+ scoped_ptr<ScopedVector<ExampleBase> > extra_examples(
+ new ScopedVector<ExampleBase>);
+ extra_examples->push_back(new WebViewExample(browser_context));
+ ShowExamplesWindow(operation, window_context, extra_examples.Pass());
}
} // namespace examples
diff --git a/chromium/ui/views/examples/examples_window_with_content.h b/chromium/ui/views/examples/examples_window_with_content.h
index 907d3075a28..407fd2eeb7e 100644
--- a/chromium/ui/views/examples/examples_window_with_content.h
+++ b/chromium/ui/views/examples/examples_window_with_content.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_EXAMPLES_EXAMPLES_WINDOW_WITH_CONTENT_H_
#include "ui/gfx/native_widget_types.h"
+#include "ui/views/examples/examples_window.h"
#include "ui/views/examples/views_examples_with_content_export.h"
namespace content {
@@ -15,11 +16,6 @@ class BrowserContext;
namespace views {
namespace examples {
-enum Operation {
- DO_NOTHING_ON_CLOSE = 0,
- QUIT_ON_CLOSE,
-};
-
// Shows a window with the views examples in it.
VIEWS_EXAMPLES_WITH_CONTENT_EXPORT void ShowExamplesWindowWithContent(
Operation operation,
diff --git a/chromium/ui/views/examples/examples_with_content_main_exe.cc b/chromium/ui/views/examples/examples_with_content_main_exe.cc
new file mode 100644
index 00000000000..8df1dec30ab
--- /dev/null
+++ b/chromium/ui/views/examples/examples_with_content_main_exe.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "content/public/browser/browser_context.h"
+#include "ui/views/examples/examples_window_with_content.h"
+#include "ui/views_content_client/views_content_client.h"
+
+#if defined(OS_WIN)
+#include "content/public/app/startup_helper_win.h"
+#include "sandbox/win/src/sandbox_types.h"
+#endif
+
+namespace {
+
+void ShowContentExampleWindow(content::BrowserContext* browser_context,
+ gfx::NativeView window_context) {
+ views::examples::ShowExamplesWindowWithContent(views::examples::QUIT_ON_CLOSE,
+ browser_context,
+ window_context);
+
+ // These lines serve no purpose other than to introduce an explicit content
+ // dependency. If the main executable doesn't have this dependency, the linker
+ // has more flexibility to reorder library dependencies in a shared component
+ // build. On linux, this can cause libc to appear before libcontent in the
+ // dlsym search path, which breaks (usually valid) assumptions made in
+ // sandbox::InitLibcUrandomOverrides(). See http://crbug.com/374712.
+ if (!browser_context) {
+ content::BrowserContext::SaveSessionState(NULL);
+ NOTREACHED();
+ }
+}
+
+} // namespace
+
+#if defined(OS_WIN)
+int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) {
+ sandbox::SandboxInterfaceInfo sandbox_info = {0};
+ content::InitializeSandboxInfo(&sandbox_info);
+ ui::ViewsContentClient views_content_client(instance, &sandbox_info);
+#else
+int main(int argc, const char** argv) {
+ ui::ViewsContentClient views_content_client(argc, argv);
+#endif
+
+ views_content_client.set_task(base::Bind(&ShowContentExampleWindow));
+ return views_content_client.RunMain();
+}
diff --git a/chromium/ui/views/examples/label_example.cc b/chromium/ui/views/examples/label_example.cc
index d970bf1a2d5..4dea806e4d4 100644
--- a/chromium/ui/views/examples/label_example.cc
+++ b/chromium/ui/views/examples/label_example.cc
@@ -10,6 +10,9 @@
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+using base::WideToUTF16;
+
namespace views {
namespace examples {
@@ -18,24 +21,20 @@ namespace {
// A Label with a constrained preferred size to demonstrate eliding or wrapping.
class PreferredSizeLabel : public Label {
public:
- PreferredSizeLabel();
- virtual ~PreferredSizeLabel();
+ PreferredSizeLabel() : Label() {
+ SetBorder(Border::CreateSolidBorder(2, SK_ColorCYAN));
+ }
+ virtual ~PreferredSizeLabel() {}
- // Overridden from Label:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ // Label:
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
+ return gfx::Size(100, 40);
+ }
private:
DISALLOW_COPY_AND_ASSIGN(PreferredSizeLabel);
};
-PreferredSizeLabel::PreferredSizeLabel() : Label() {
- set_border(Border::CreateSolidBorder(2, SK_ColorCYAN));
-}
-
-PreferredSizeLabel::~PreferredSizeLabel() {}
-
-gfx::Size PreferredSizeLabel::GetPreferredSize() { return gfx::Size(100, 40); }
-
} // namespace
LabelExample::LabelExample() : ExampleBase("Label") {}
@@ -63,10 +62,12 @@ void LabelExample::CreateExampleView(View* container) {
label->SetEnabledColor(SK_ColorBLUE);
container->AddChildView(label);
- label = new Label(ASCIIToUTF16("A Courier-18 label with a shadow."));
- label->SetFont(gfx::Font("Courier", 18));
- label->SetShadowColors(SK_ColorGRAY, SK_ColorLTGRAY);
- label->SetShadowOffset(1, 1);
+ label = new Label(ASCIIToUTF16("A Courier-18 label with shadows."));
+ label->SetFontList(gfx::FontList("Courier, 18px"));
+ gfx::ShadowValues shadows(1, gfx::ShadowValue(gfx::Point(), 1, SK_ColorRED));
+ gfx::ShadowValue shadow(gfx::Point(2, 2), 0, SK_ColorGRAY);
+ shadows.push_back(shadow);
+ label->set_shadows(shadows);
container->AddChildView(label);
label = new PreferredSizeLabel();
@@ -75,10 +76,20 @@ void LabelExample::CreateExampleView(View* container) {
container->AddChildView(label);
label = new PreferredSizeLabel();
+ label->SetElideBehavior(gfx::FADE_TAIL);
+ label->SetText(ASCIIToUTF16("Some long labels will fade, rather than elide, "
+ "if the text's width exceeds the label's available width."));
+ container->AddChildView(label);
+
+ label = new PreferredSizeLabel();
label->SetText(ASCIIToUTF16("A multi-line label will wrap onto subsequent "
"lines if the text's width exceeds the label's available width."));
label->SetMultiLine(true);
container->AddChildView(label);
+
+ label = new Label(WideToUTF16(L"Password!"));
+ label->SetObscured(true);
+ container->AddChildView(label);
}
} // namespace examples
diff --git a/chromium/ui/views/examples/label_example.h b/chromium/ui/views/examples/label_example.h
index 0f7eeae92f1..8b7cfe782f5 100644
--- a/chromium/ui/views/examples/label_example.h
+++ b/chromium/ui/views/examples/label_example.h
@@ -5,19 +5,18 @@
#ifndef UI_VIEWS_EXAMPLES_LABEL_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_LABEL_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace views {
namespace examples {
-class LabelExample : public ExampleBase {
+class VIEWS_EXAMPLES_EXPORT LabelExample : public ExampleBase {
public:
LabelExample();
virtual ~LabelExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
diff --git a/chromium/ui/views/examples/link_example.cc b/chromium/ui/views/examples/link_example.cc
index a28c5d579e5..3795c8c9832 100644
--- a/chromium/ui/views/examples/link_example.cc
+++ b/chromium/ui/views/examples/link_example.cc
@@ -19,7 +19,7 @@ LinkExample::~LinkExample() {
}
void LinkExample::CreateExampleView(View* container) {
- link_ = new Link(ASCIIToUTF16("Click me!"));
+ link_ = new Link(base::ASCIIToUTF16("Click me!"));
link_->set_listener(this);
container->SetLayoutManager(new FillLayout);
diff --git a/chromium/ui/views/examples/link_example.h b/chromium/ui/views/examples/link_example.h
index ac969c43a0c..fd6e9245318 100644
--- a/chromium/ui/views/examples/link_example.h
+++ b/chromium/ui/views/examples/link_example.h
@@ -5,24 +5,24 @@
#ifndef UI_VIEWS_EXAMPLES_LINK_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_LINK_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/link_listener.h"
#include "ui/views/examples/example_base.h"
namespace views {
namespace examples {
-class LinkExample : public ExampleBase, public LinkListener {
+class VIEWS_EXAMPLES_EXPORT LinkExample : public ExampleBase,
+ public LinkListener {
public:
LinkExample();
virtual ~LinkExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from LinkListener:
+ // LinkListener:
virtual void LinkClicked(Link* source, int event_flags) OVERRIDE;
Link* link_;
diff --git a/chromium/ui/views/examples/menu_example.cc b/chromium/ui/views/examples/menu_example.cc
index 307a6ca794e..742cfffa4b2 100644
--- a/chromium/ui/views/examples/menu_example.cc
+++ b/chromium/ui/views/examples/menu_example.cc
@@ -15,6 +15,8 @@
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -25,7 +27,7 @@ class ExampleMenuModel : public ui::SimpleMenuModel,
public:
ExampleMenuModel();
- // Overridden from ui::SimpleMenuModel::Delegate:
+ // ui::SimpleMenuModel::Delegate:
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
virtual bool GetAcceleratorForCommandId(
@@ -58,11 +60,11 @@ class ExampleMenuModel : public ui::SimpleMenuModel,
class ExampleMenuButton : public MenuButton, public MenuButtonListener {
public:
- explicit ExampleMenuButton(const string16& test);
+ explicit ExampleMenuButton(const base::string16& test);
virtual ~ExampleMenuButton();
private:
- // Overridden from MenuButtonListener:
+ // MenuButtonListener:
virtual void OnMenuButtonClicked(View* source,
const gfx::Point& point) OVERRIDE;
@@ -126,24 +128,24 @@ bool ExampleMenuModel::GetAcceleratorForCommandId(
void ExampleMenuModel::ExecuteCommand(int command_id, int event_flags) {
switch (command_id) {
case COMMAND_DO_SOMETHING: {
- LOG(INFO) << "Done something";
+ VLOG(0) << "Done something";
break;
}
// Radio items.
case COMMAND_SELECT_ASCII: {
current_encoding_command_id_ = COMMAND_SELECT_ASCII;
- LOG(INFO) << "Selected ASCII";
+ VLOG(0) << "Selected ASCII";
break;
}
case COMMAND_SELECT_UTF8: {
current_encoding_command_id_ = COMMAND_SELECT_UTF8;
- LOG(INFO) << "Selected UTF-8";
+ VLOG(0) << "Selected UTF-8";
break;
}
case COMMAND_SELECT_UTF16: {
current_encoding_command_id_ = COMMAND_SELECT_UTF16;
- LOG(INFO) << "Selected UTF-16";
+ VLOG(0) << "Selected UTF-16";
break;
}
@@ -176,7 +178,7 @@ void ExampleMenuModel::ExecuteCommand(int command_id, int event_flags) {
// ExampleMenuButton -----------------------------------------------------------
-ExampleMenuButton::ExampleMenuButton(const string16& test)
+ExampleMenuButton::ExampleMenuButton(const base::string16& test)
: MenuButton(NULL, test, this, true) {
}
@@ -187,11 +189,15 @@ void ExampleMenuButton::OnMenuButtonClicked(View* source,
const gfx::Point& point) {
menu_runner_.reset(new MenuRunner(GetMenuModel()));
- if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(), this,
- gfx::Rect(point, gfx::Size()), MenuItemView::TOPRIGHT,
- ui::MENU_SOURCE_NONE, MenuRunner::HAS_MNEMONICS) ==
- MenuRunner::MENU_DELETED)
+ if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(),
+ this,
+ gfx::Rect(point, gfx::Size()),
+ MENU_ANCHOR_TOPRIGHT,
+ ui::MENU_SOURCE_NONE,
+ MenuRunner::HAS_MNEMONICS) ==
+ MenuRunner::MENU_DELETED) {
return;
+ }
}
ui::SimpleMenuModel* ExampleMenuButton::GetMenuModel() {
diff --git a/chromium/ui/views/examples/menu_example.h b/chromium/ui/views/examples/menu_example.h
index 40c9b23d6e0..3ed5d37e7a4 100644
--- a/chromium/ui/views/examples/menu_example.h
+++ b/chromium/ui/views/examples/menu_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_MENU_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_MENU_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace views {
@@ -14,12 +13,12 @@ namespace examples {
// MenuExample demonstrates how to use the MenuModelAdapter and MenuRunner
// classes.
-class MenuExample : public ExampleBase {
+class VIEWS_EXAMPLES_EXPORT MenuExample : public ExampleBase {
public:
MenuExample();
virtual ~MenuExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
diff --git a/chromium/ui/views/examples/message_box_example.cc b/chromium/ui/views/examples/message_box_example.cc
index 2563525f325..cb9e924fbf6 100644
--- a/chromium/ui/views/examples/message_box_example.cc
+++ b/chromium/ui/views/examples/message_box_example.cc
@@ -10,6 +10,8 @@
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
diff --git a/chromium/ui/views/examples/message_box_example.h b/chromium/ui/views/examples/message_box_example.h
index 4d5277805eb..692ae22255a 100644
--- a/chromium/ui/views/examples/message_box_example.h
+++ b/chromium/ui/views/examples/message_box_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
@@ -18,16 +17,17 @@ class MessageBoxView;
namespace examples {
// A MessageBoxView example. This tests some of checkbox features as well.
-class MessageBoxExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT MessageBoxExample : public ExampleBase,
+ public ButtonListener {
public:
MessageBoxExample();
virtual ~MessageBoxExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
// The MessageBoxView to be tested.
diff --git a/chromium/ui/views/examples/multiline_example.cc b/chromium/ui/views/examples/multiline_example.cc
index b1923846386..e0a3b152b54 100644
--- a/chromium/ui/views/examples/multiline_example.cc
+++ b/chromium/ui/views/examples/multiline_example.cc
@@ -9,14 +9,27 @@
#include "ui/gfx/render_text.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
+#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
+namespace {
+
+gfx::Range ClampRange(gfx::Range range, size_t max) {
+ range.set_start(std::min(range.start(), max));
+ range.set_end(std::min(range.end(), max));
+ return range;
+}
+
+} // namespace
+
// A simple View that hosts a RenderText object.
class MultilineExample::RenderTextView : public View {
public:
@@ -24,7 +37,7 @@ class MultilineExample::RenderTextView : public View {
render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
render_text_->SetColor(SK_ColorBLACK);
render_text_->SetMultiline(true);
- set_border(Border::CreateSolidBorder(2, SK_ColorGRAY));
+ SetBorder(Border::CreateSolidBorder(2, SK_ColorGRAY));
}
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
@@ -32,7 +45,7 @@ class MultilineExample::RenderTextView : public View {
render_text_->Draw(canvas);
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
// Turn off multiline mode to get the single-line text size, which is the
// preferred size for this view.
render_text_->SetMultiline(false);
@@ -43,7 +56,7 @@ class MultilineExample::RenderTextView : public View {
return size;
}
- virtual int GetHeightForWidth(int w) OVERRIDE {
+ virtual int GetHeightForWidth(int w) const OVERRIDE {
// TODO(ckocagil): Why does this happen?
if (w == 0)
return View::GetHeightForWidth(w);
@@ -56,19 +69,22 @@ class MultilineExample::RenderTextView : public View {
return height;
}
- void SetText(const string16& new_contents) {
+ void SetText(const base::string16& new_contents) {
// Color and style the text inside |test_range| to test colors and styles.
- gfx::Range test_range(1, 21);
- test_range.set_start(std::min(test_range.start(), new_contents.length()));
- test_range.set_end(std::min(test_range.end(), new_contents.length()));
+ const size_t range_max = new_contents.length();
+ gfx::Range color_range = ClampRange(gfx::Range(1, 21), range_max);
+ gfx::Range bold_range = ClampRange(gfx::Range(4, 10), range_max);
+ gfx::Range italic_range = ClampRange(gfx::Range(7, 13), range_max);
render_text_->SetText(new_contents);
render_text_->SetColor(SK_ColorBLACK);
- render_text_->ApplyColor(0xFFFF0000, test_range);
+ render_text_->ApplyColor(0xFFFF0000, color_range);
render_text_->SetStyle(gfx::DIAGONAL_STRIKE, false);
- render_text_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, test_range);
+ render_text_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, color_range);
render_text_->SetStyle(gfx::UNDERLINE, false);
- render_text_->ApplyStyle(gfx::UNDERLINE, true, test_range);
+ render_text_->ApplyStyle(gfx::UNDERLINE, true, color_range);
+ render_text_->ApplyStyle(gfx::BOLD, true, bold_range);
+ render_text_->ApplyStyle(gfx::ITALIC, true, italic_range);
InvalidateLayout();
}
@@ -96,16 +112,17 @@ MultilineExample::~MultilineExample() {
}
void MultilineExample::CreateExampleView(View* container) {
- const char kTestString[] = "test string asdf 1234 test string asdf 1234 "
- "test string asdf 1234 test string asdf 1234";
+ const base::string16 kTestString = base::WideToUTF16(L"qwerty"
+ L"\x627\x644\x631\x626\x64A\x633\x64A\x629"
+ L"asdfgh");
render_text_view_ = new RenderTextView();
- render_text_view_->SetText(ASCIIToUTF16(kTestString));
+ render_text_view_->SetText(kTestString);
label_ = new Label();
- label_->SetText(ASCIIToUTF16(kTestString));
+ label_->SetText(kTestString);
label_->SetMultiLine(true);
- label_->set_border(Border::CreateSolidBorder(2, SK_ColorCYAN));
+ label_->SetBorder(Border::CreateSolidBorder(2, SK_ColorCYAN));
label_checkbox_ = new Checkbox(ASCIIToUTF16("views::Label:"));
label_checkbox_->SetChecked(true);
@@ -113,8 +130,8 @@ void MultilineExample::CreateExampleView(View* container) {
label_checkbox_->set_request_focus_on_press(false);
textfield_ = new Textfield();
- textfield_->SetController(this);
- textfield_->SetText(ASCIIToUTF16(kTestString));
+ textfield_->set_controller(this);
+ textfield_->SetText(kTestString);
GridLayout* layout = new GridLayout(container);
container->SetLayoutManager(layout);
@@ -139,7 +156,7 @@ void MultilineExample::CreateExampleView(View* container) {
}
void MultilineExample::ContentsChanged(Textfield* sender,
- const string16& new_contents) {
+ const base::string16& new_contents) {
render_text_view_->SetText(new_contents);
if (label_checkbox_->checked())
label_->SetText(new_contents);
@@ -154,7 +171,8 @@ bool MultilineExample::HandleKeyEvent(Textfield* sender,
void MultilineExample::ButtonPressed(Button* sender, const ui::Event& event) {
DCHECK_EQ(sender, label_checkbox_);
- label_->SetText(label_checkbox_->checked() ? textfield_->text() : string16());
+ label_->SetText(label_checkbox_->checked() ? textfield_->text() :
+ base::string16());
container()->Layout();
container()->SchedulePaint();
}
diff --git a/chromium/ui/views/examples/multiline_example.h b/chromium/ui/views/examples/multiline_example.h
index 2757c4ac933..7231c66bce7 100644
--- a/chromium/ui/views/examples/multiline_example.h
+++ b/chromium/ui/views/examples/multiline_example.h
@@ -5,22 +5,22 @@
#ifndef UI_VIEWS_EXAMPLES_MULTILINE_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_MULTILINE_EXAMPLE_H_
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
-#include "ui/views/controls/button/checkbox.h"
+#include "base/macros.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/examples/example_base.h"
namespace views {
+class Checkbox;
class Label;
namespace examples {
// An example that compares the multiline rendering of different controls.
-class MultilineExample : public ExampleBase,
- public TextfieldController,
- public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT MultilineExample : public ExampleBase,
+ public TextfieldController,
+ public ButtonListener {
public:
MultilineExample();
virtual ~MultilineExample();
@@ -36,7 +36,7 @@ class MultilineExample : public ExampleBase,
// TextfieldController:
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) OVERRIDE;
+ const base::string16& new_contents) OVERRIDE;
virtual bool HandleKeyEvent(Textfield* sender,
const ui::KeyEvent& key_event) OVERRIDE;
diff --git a/chromium/ui/views/examples/progress_bar_example.cc b/chromium/ui/views/examples/progress_bar_example.cc
index ce29ecd0fa2..8a860f212af 100644
--- a/chromium/ui/views/examples/progress_bar_example.cc
+++ b/chromium/ui/views/examples/progress_bar_example.cc
@@ -51,11 +51,11 @@ void ProgressBarExample::CreateExampleView(View* container) {
0, GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 0);
- minus_button_ = new LabelButton(this, ASCIIToUTF16("-"));
+ minus_button_ = new LabelButton(this, base::ASCIIToUTF16("-"));
layout->AddView(minus_button_);
progress_bar_ = new ProgressBar();
layout->AddView(progress_bar_);
- plus_button_ = new LabelButton(this, ASCIIToUTF16("+"));
+ plus_button_ = new LabelButton(this, base::ASCIIToUTF16("+"));
layout->AddView(plus_button_);
}
diff --git a/chromium/ui/views/examples/progress_bar_example.h b/chromium/ui/views/examples/progress_bar_example.h
index 92d0e9f1670..8533b7ac3cb 100644
--- a/chromium/ui/views/examples/progress_bar_example.h
+++ b/chromium/ui/views/examples/progress_bar_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_PROGRESS_BAR_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_PROGRESS_BAR_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
@@ -15,16 +14,17 @@ class ProgressBar;
namespace examples {
-class ProgressBarExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT ProgressBarExample : public ExampleBase,
+ public ButtonListener {
public:
ProgressBarExample();
virtual ~ProgressBarExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* button, const ui::Event& event) OVERRIDE;
Button* minus_button_;
diff --git a/chromium/ui/views/examples/radio_button_example.cc b/chromium/ui/views/examples/radio_button_example.cc
index 72a844e0f5f..5e3c7dd4a3c 100644
--- a/chromium/ui/views/examples/radio_button_example.cc
+++ b/chromium/ui/views/examples/radio_button_example.cc
@@ -23,13 +23,13 @@ RadioButtonExample::~RadioButtonExample() {
}
void RadioButtonExample::CreateExampleView(View* container) {
- select_ = new LabelButton(this, ASCIIToUTF16("Select"));
- status_ = new LabelButton(this, ASCIIToUTF16("Show Status"));
+ select_ = new LabelButton(this, base::ASCIIToUTF16("Select"));
+ status_ = new LabelButton(this, base::ASCIIToUTF16("Show Status"));
int group = 1;
for (size_t i = 0; i < arraysize(radio_buttons_); ++i) {
radio_buttons_[i] = new RadioButton(
- UTF8ToUTF16(base::StringPrintf(
+ base::UTF8ToUTF16(base::StringPrintf(
"Radio %d in group %d", static_cast<int>(i) + 1, group)),
group);
radio_buttons_[i]->set_listener(this);
diff --git a/chromium/ui/views/examples/radio_button_example.h b/chromium/ui/views/examples/radio_button_example.h
index ed8ddf4cf99..cc1452215e0 100644
--- a/chromium/ui/views/examples/radio_button_example.h
+++ b/chromium/ui/views/examples/radio_button_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
@@ -19,16 +18,17 @@ class RadioButton;
namespace examples {
-class RadioButtonExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT RadioButtonExample : public ExampleBase,
+ public ButtonListener {
public:
RadioButtonExample();
virtual ~RadioButtonExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
// Group of 3 radio buttons.
diff --git a/chromium/ui/views/examples/scroll_view_example.cc b/chromium/ui/views/examples/scroll_view_example.cc
index 38b18fc5e7f..127442fb7df 100644
--- a/chromium/ui/views/examples/scroll_view_example.cc
+++ b/chromium/ui/views/examples/scroll_view_example.cc
@@ -12,6 +12,8 @@
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -25,7 +27,7 @@ class ScrollViewExample::ScrollableView : public View {
AddChildView(new RadioButton(ASCIIToUTF16("Radio Button"), 0));
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return gfx::Size(width(), height());
}
diff --git a/chromium/ui/views/examples/scroll_view_example.h b/chromium/ui/views/examples/scroll_view_example.h
index e180bc0b4b5..d850b01df4e 100644
--- a/chromium/ui/views/examples/scroll_view_example.h
+++ b/chromium/ui/views/examples/scroll_view_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/examples/example_base.h"
@@ -19,16 +18,17 @@ class LabelButton;
namespace examples {
-class ScrollViewExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT ScrollViewExample : public ExampleBase,
+ public ButtonListener {
public:
ScrollViewExample();
virtual ~ScrollViewExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
// Control buttons to change the size of scrollable and jump to
diff --git a/chromium/ui/views/examples/single_split_view_example.cc b/chromium/ui/views/examples/single_split_view_example.cc
index 97fb36b7980..7e390b51064 100644
--- a/chromium/ui/views/examples/single_split_view_example.cc
+++ b/chromium/ui/views/examples/single_split_view_example.cc
@@ -21,9 +21,9 @@ class SplittedView : public View {
void SetColor(SkColor from, SkColor to);
private:
- // Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ // View:
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(SplittedView);
@@ -40,11 +40,11 @@ void SplittedView::SetColor(SkColor from, SkColor to) {
set_background(Background::CreateVerticalGradientBackground(from, to));
}
-gfx::Size SplittedView::GetPreferredSize() {
+gfx::Size SplittedView::GetPreferredSize() const {
return gfx::Size(width(), height());
}
-gfx::Size SplittedView::GetMinimumSize() {
+gfx::Size SplittedView::GetMinimumSize() const {
return gfx::Size(10, 10);
}
diff --git a/chromium/ui/views/examples/single_split_view_example.h b/chromium/ui/views/examples/single_split_view_example.h
index 0c157cc87b9..603482c2288 100644
--- a/chromium/ui/views/examples/single_split_view_example.h
+++ b/chromium/ui/views/examples/single_split_view_example.h
@@ -5,24 +5,25 @@
#ifndef UI_VIEWS_EXAMPLES_SINGLE_SPLIT_VIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_SINGLE_SPLIT_VIEW_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/single_split_view_listener.h"
#include "ui/views/examples/example_base.h"
namespace views {
namespace examples {
-class SingleSplitViewExample : public ExampleBase,
- public SingleSplitViewListener {
+class VIEWS_EXAMPLES_EXPORT SingleSplitViewExample
+ : public ExampleBase,
+ public SingleSplitViewListener {
public:
SingleSplitViewExample();
virtual ~SingleSplitViewExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
+ // SingleSplitViewListener:
virtual bool SplitHandleMoved(SingleSplitView* sender) OVERRIDE;
SingleSplitView* single_split_view_;
diff --git a/chromium/ui/views/examples/slider_example.cc b/chromium/ui/views/examples/slider_example.cc
index 8ae4d6bc423..89f78568e23 100644
--- a/chromium/ui/views/examples/slider_example.cc
+++ b/chromium/ui/views/examples/slider_example.cc
@@ -37,7 +37,7 @@ void SliderExample::SliderValueChanged(Slider* sender,
float value,
float old_value,
SliderChangeReason reason) {
- label_->SetText(ASCIIToUTF16(base::StringPrintf("%.3lf", value)));
+ label_->SetText(base::ASCIIToUTF16(base::StringPrintf("%.3lf", value)));
}
} // namespace examples
diff --git a/chromium/ui/views/examples/slider_example.h b/chromium/ui/views/examples/slider_example.h
index 8e909394467..32950f9ad36 100644
--- a/chromium/ui/views/examples/slider_example.h
+++ b/chromium/ui/views/examples/slider_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_SLIDER_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_SLIDER_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/slider.h"
#include "ui/views/examples/example_base.h"
@@ -15,16 +14,17 @@ class Label;
namespace examples {
-class SliderExample : public ExampleBase, public SliderListener {
+class VIEWS_EXAMPLES_EXPORT SliderExample : public ExampleBase,
+ public SliderListener {
public:
SliderExample();
virtual ~SliderExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
- // Overridden from SliderListener:
+ // SliderListener:
virtual void SliderValueChanged(Slider* sender,
float value,
float old_value,
diff --git a/chromium/ui/views/examples/tabbed_pane_example.cc b/chromium/ui/views/examples/tabbed_pane_example.cc
index f0f6691ef87..087c77bf0df 100644
--- a/chromium/ui/views/examples/tabbed_pane_example.cc
+++ b/chromium/ui/views/examples/tabbed_pane_example.cc
@@ -9,6 +9,8 @@
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
#include "ui/views/layout/grid_layout.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -57,7 +59,7 @@ void TabbedPaneExample::ButtonPressed(Button* sender, const ui::Event& event) {
if (sender == add_) {
AddButton("Added");
} else if (sender == add_at_) {
- const string16 label = ASCIIToUTF16("Added at 1");
+ const base::string16 label = ASCIIToUTF16("Added at 1");
tabbed_pane_->AddTabAtIndex(1, label, new LabelButton(NULL, label));
} else if (sender == select_at_) {
if (tabbed_pane_->GetTabCount() > 1)
diff --git a/chromium/ui/views/examples/tabbed_pane_example.h b/chromium/ui/views/examples/tabbed_pane_example.h
index 9a198269294..f23f6b34d7f 100644
--- a/chromium/ui/views/examples/tabbed_pane_example.h
+++ b/chromium/ui/views/examples/tabbed_pane_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
#include "ui/views/examples/example_base.h"
@@ -19,9 +18,9 @@ class TabbedPane;
namespace examples {
// A TabbedPane example tests adding and selecting tabs.
-class TabbedPaneExample : public ExampleBase,
- public ButtonListener,
- public TabbedPaneListener {
+class VIEWS_EXAMPLES_EXPORT TabbedPaneExample : public ExampleBase,
+ public ButtonListener,
+ public TabbedPaneListener {
public:
TabbedPaneExample();
virtual ~TabbedPaneExample();
diff --git a/chromium/ui/views/examples/table_example.cc b/chromium/ui/views/examples/table_example.cc
index 87032c7160a..5c9eebfd2ed 100644
--- a/chromium/ui/views/examples/table_example.cc
+++ b/chromium/ui/views/examples/table_example.cc
@@ -14,6 +14,8 @@
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/layout/grid_layout.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -107,9 +109,9 @@ int TableExample::RowCount() {
return 10;
}
-string16 TableExample::GetText(int row, int column_id) {
+base::string16 TableExample::GetText(int row, int column_id) {
if (row == -1)
- return string16();
+ return base::string16();
const char* const cells[5][4] = {
{ "Orange", "Orange", "South america", "$5" },
@@ -143,14 +145,14 @@ void TableExample::GetGroupRange(int model_index, GroupRange* range) {
void TableExample::OnSelectionChanged() {
PrintStatus("Selected: %s",
- UTF16ToASCII(GetText(table_->selection_model().active(),
- 0)).c_str());
+ base::UTF16ToASCII(GetText(table_->selection_model().active(),
+ 0)).c_str());
}
void TableExample::OnDoubleClick() {
PrintStatus("Double Click: %s",
- UTF16ToASCII(GetText(table_->selection_model().active(),
- 0)).c_str());
+ base::UTF16ToASCII(GetText(table_->selection_model().active(),
+ 0)).c_str());
}
void TableExample::OnMiddleClick() {}
diff --git a/chromium/ui/views/examples/table_example.h b/chromium/ui/views/examples/table_example.h
index d715a107a2b..06ac3c01a68 100644
--- a/chromium/ui/views/examples/table_example.h
+++ b/chromium/ui/views/examples/table_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/models/table_model.h"
#include "ui/views/controls/button/button.h"
@@ -27,11 +26,11 @@ class TableView;
namespace examples {
-class TableExample : public ExampleBase,
- public ui::TableModel,
- public TableGrouper,
- public TableViewObserver,
- public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT TableExample : public ExampleBase,
+ public ui::TableModel,
+ public TableGrouper,
+ public TableViewObserver,
+ public ButtonListener {
public:
TableExample();
virtual ~TableExample();
@@ -41,7 +40,7 @@ class TableExample : public ExampleBase,
// ui::TableModel:
virtual int RowCount() OVERRIDE;
- virtual string16 GetText(int row, int column_id) OVERRIDE;
+ virtual base::string16 GetText(int row, int column_id) OVERRIDE;
virtual gfx::ImageSkia GetIcon(int row) OVERRIDE;
virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
diff --git a/chromium/ui/views/examples/text_example.cc b/chromium/ui/views/examples/text_example.cc
index ec43ac15b99..2682e73bd14 100644
--- a/chromium/ui/views/examples/text_example.cc
+++ b/chromium/ui/views/examples/text_example.cc
@@ -24,48 +24,31 @@ namespace {
// Number of columns in the view layout.
const int kNumColumns = 10;
-const char kShortText[] = "Batman";
-const char kMediumText[] = "The quick brown fox jumps over the lazy dog.";
+const char kShortText[] = "The quick brown fox jumps over the lazy dog.";
const char kLongText[] =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
- "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
- "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
+ "commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate "
+ "velit esse cillum dolore eu fugiat nulla pariatur.\n\nExcepteur sint "
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
"mollit anim id est laborum.";
const char kAmpersandText[] =
"The quick && &brown fo&x jumps over the lazy dog.";
-const char kNewlineText[] =
- "The quick \nbrown fox jumps\n\n over the lazy dog.";
-
-const char* kTextExamples[] = {
- "Short",
- "Medium",
- "Long",
- "Ampersands",
- "Newlines",
-};
-
-const char* kElidingBehaviors[] = {
- "Ellipsis",
- "None",
- "Fade Tail",
- "Fade Head",
-};
-
-const char* kPrefixOptions[] = {
- "Default",
- "Show",
- "Hide",
-};
-
-const char* kHorizontalAligments[] = {
- "Default",
- "Left",
- "Center",
- "Right",
-};
+const wchar_t kRightToLeftText[] =
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
+ L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd!";
+
+const char* kTextExamples[] = { "Short", "Long", "Ampersands", "RTL Hebrew", };
+const char* kElideBehaviors[] = { "Elide", "Truncate", "Fade", };
+const char* kPrefixOptions[] = { "Default", "Show", "Hide", };
+const char* kHorizontalAligments[] = { "Default", "Left", "Center", "Right", };
// Toggles bit |flag| on |flags| based on state of |checkbox|.
void SetFlagFromCheckbox(Checkbox* checkbox, int* flags, int flag) {
@@ -77,91 +60,67 @@ void SetFlagFromCheckbox(Checkbox* checkbox, int* flags, int flag) {
} // namespace
-// TextExample's content view, which is responsible for drawing a string with
-// the specified style.
+// TextExample's content view, which draws stylized string.
class TextExample::TextExampleView : public View {
public:
TextExampleView()
- : text_(ASCIIToUTF16(kShortText)),
- text_flags_(0),
+ : text_(base::ASCIIToUTF16(kShortText)),
+ flags_(0),
halo_(false),
- fade_(false),
- fade_mode_(gfx::Canvas::TruncateFadeTail) {
+ elide_(gfx::TRUNCATE) {
}
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
View::OnPaint(canvas);
const gfx::Rect bounds = GetContentsBounds();
-
- if (fade_) {
- canvas->DrawFadeTruncatingStringRect(text_, fade_mode_, font_list_,
- SK_ColorDKGRAY, bounds);
+ const SkColor color = SK_ColorDKGRAY;
+ if (elide_ == gfx::FADE_TAIL) {
+ canvas->DrawFadedString(text_, font_list_, color, bounds, flags_);
} else if (halo_) {
- canvas->DrawStringRectWithHalo(text_, font_list_, SK_ColorDKGRAY,
- SK_ColorWHITE, bounds, text_flags_);
+ canvas->DrawStringRectWithHalo(text_, font_list_, color, SK_ColorYELLOW,
+ bounds, flags_);
} else {
- canvas->DrawStringRectWithFlags(text_, font_list_, SK_ColorDKGRAY, bounds,
- text_flags_);
+ canvas->DrawStringRectWithFlags(text_, font_list_, color, bounds, flags_);
}
}
- int text_flags() const { return text_flags_; }
- void set_text_flags(int text_flags) { text_flags_ = text_flags; }
-
- const string16& text() const { return text_; }
- void set_text(const string16& text) { text_ = text; }
-
- bool halo() const { return halo_; }
+ int flags() const { return flags_; }
+ void set_flags(int flags) { flags_ = flags; }
+ void set_text(const base::string16& text) { text_ = text; }
void set_halo(bool halo) { halo_ = halo; }
+ void set_elide(gfx::ElideBehavior elide) { elide_ = elide; }
- bool fade() const { return fade_; }
- void set_fade(bool fade) { fade_ = fade; }
-
- gfx::Canvas::TruncateFadeMode fade_mode() const { return fade_mode_; }
- void set_fade_mode(gfx::Canvas::TruncateFadeMode mode) { fade_mode_ = mode; }
-
- int GetFontStyle() const {
- return font_list_.GetFontStyle();
- }
- void SetFontStyle(int style) {
- font_list_ = font_list_.DeriveFontList(style);
- }
+ int GetStyle() const { return font_list_.GetFontStyle(); }
+ void SetStyle(int style) { font_list_ = font_list_.DeriveWithStyle(style); }
private:
// The font used for drawing the text.
gfx::FontList font_list_;
// The text to draw.
- string16 text_;
+ base::string16 text_;
- // Text flags for passing to |DrawStringInt()|.
- int text_flags_;
+ // Text flags for passing to |DrawStringRect()|.
+ int flags_;
- // If |true|, specifies to call |DrawStringWithHalo()| instead of
- // |DrawStringInt()|.
+ // A flag to draw a halo around the text.
bool halo_;
- // If |true|, specifies to call |DrawFadeTruncatingString()| instead of
- // |DrawStringInt()|.
- bool fade_;
-
- // If |fade_| is |true|, fade mode parameter to |DrawFadeTruncatingString()|.
- gfx::Canvas::TruncateFadeMode fade_mode_;
+ // The eliding, fading, or truncating behavior.
+ gfx::ElideBehavior elide_;
DISALLOW_COPY_AND_ASSIGN(TextExampleView);
};
-TextExample::TextExample() : ExampleBase("Text Styles") {
-}
+TextExample::TextExample() : ExampleBase("Text Styles") {}
TextExample::~TextExample() {
- // Remove all the views first as some reference models in
- // |example_combobox_model_|.
+ // Remove the views first as some reference combobox models.
container()->RemoveAllChildViews(true);
}
Checkbox* TextExample::AddCheckbox(GridLayout* layout, const char* name) {
- Checkbox* checkbox = new Checkbox(ASCIIToUTF16(name));
+ Checkbox* checkbox = new Checkbox(base::ASCIIToUTF16(name));
checkbox->set_listener(this);
layout->AddView(checkbox);
return checkbox;
@@ -172,11 +131,10 @@ Combobox* TextExample::AddCombobox(GridLayout* layout,
const char** strings,
int count) {
layout->StartRow(0, 0);
- layout->AddView(new Label(ASCIIToUTF16(name)));
- ExampleComboboxModel* combobox_model = new ExampleComboboxModel(strings,
- count);
- example_combobox_model_.push_back(combobox_model);
- Combobox* combobox = new Combobox(combobox_model);
+ layout->AddView(new Label(base::ASCIIToUTF16(name)));
+ ExampleComboboxModel* model = new ExampleComboboxModel(strings, count);
+ example_combobox_model_.push_back(model);
+ Combobox* combobox = new Combobox(model);
combobox->SetSelectedIndex(0);
combobox->set_listener(this);
layout->AddView(combobox, kNumColumns - 1, 1);
@@ -185,11 +143,9 @@ Combobox* TextExample::AddCombobox(GridLayout* layout,
void TextExample::CreateExampleView(View* container) {
text_view_ = new TextExampleView;
- text_view_->set_border(Border::CreateSolidBorder(1, SK_ColorGRAY));
-
+ text_view_->SetBorder(Border::CreateSolidBorder(1, SK_ColorGRAY));
GridLayout* layout = new GridLayout(container);
container->SetLayoutManager(layout);
-
layout->AddPaddingRow(0, 8);
ColumnSet* column_set = layout->AddColumnSet(0);
@@ -201,33 +157,24 @@ void TextExample::CreateExampleView(View* container) {
0.1f, GridLayout::USE_PREF, 0, 0);
column_set->AddPaddingColumn(0, 8);
- h_align_cb_ = AddCombobox(layout,
- "H-Align",
- kHorizontalAligments,
+ h_align_cb_ = AddCombobox(layout, "H-Align", kHorizontalAligments,
arraysize(kHorizontalAligments));
- eliding_cb_ = AddCombobox(layout,
- "Eliding",
- kElidingBehaviors,
- arraysize(kElidingBehaviors));
- prefix_cb_ = AddCombobox(layout,
- "Prefix",
- kPrefixOptions,
+ eliding_cb_ = AddCombobox(layout, "Eliding", kElideBehaviors,
+ arraysize(kElideBehaviors));
+ prefix_cb_ = AddCombobox(layout, "Prefix", kPrefixOptions,
arraysize(kPrefixOptions));
- text_cb_ = AddCombobox(layout,
- "Example Text",
- kTextExamples,
+ text_cb_ = AddCombobox(layout, "Example Text", kTextExamples,
arraysize(kTextExamples));
layout->StartRow(0, 0);
multiline_checkbox_ = AddCheckbox(layout, "Multiline");
break_checkbox_ = AddCheckbox(layout, "Character Break");
- halo_checkbox_ = AddCheckbox(layout, "Text Halo");
+ halo_checkbox_ = AddCheckbox(layout, "Halo");
bold_checkbox_ = AddCheckbox(layout, "Bold");
italic_checkbox_ = AddCheckbox(layout, "Italic");
underline_checkbox_ = AddCheckbox(layout, "Underline");
- layout->AddPaddingRow(0, 32);
-
+ layout->AddPaddingRow(0, 20);
column_set = layout->AddColumnSet(1);
column_set->AddPaddingColumn(0, 16);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
@@ -235,94 +182,83 @@ void TextExample::CreateExampleView(View* container) {
column_set->AddPaddingColumn(0, 16);
layout->StartRow(1, 1);
layout->AddView(text_view_);
-
layout->AddPaddingRow(0, 8);
}
void TextExample::ButtonPressed(Button* button, const ui::Event& event) {
- int flags = text_view_->text_flags();
- int style = text_view_->GetFontStyle();
+ int flags = text_view_->flags();
+ int style = text_view_->GetStyle();
SetFlagFromCheckbox(multiline_checkbox_, &flags, gfx::Canvas::MULTI_LINE);
SetFlagFromCheckbox(break_checkbox_, &flags, gfx::Canvas::CHARACTER_BREAK);
SetFlagFromCheckbox(bold_checkbox_, &style, gfx::Font::BOLD);
SetFlagFromCheckbox(italic_checkbox_, &style, gfx::Font::ITALIC);
SetFlagFromCheckbox(underline_checkbox_, &style, gfx::Font::UNDERLINE);
text_view_->set_halo(halo_checkbox_->checked());
- text_view_->set_text_flags(flags);
- text_view_->SetFontStyle(style);
+ text_view_->set_flags(flags);
+ text_view_->SetStyle(style);
text_view_->SchedulePaint();
}
-void TextExample::OnSelectedIndexChanged(Combobox* combobox) {
- int text_flags = text_view_->text_flags();
+void TextExample::OnPerformAction(Combobox* combobox) {
+ int flags = text_view_->flags();
if (combobox == h_align_cb_) {
- text_flags &= ~(gfx::Canvas::TEXT_ALIGN_LEFT |
- gfx::Canvas::TEXT_ALIGN_CENTER |
- gfx::Canvas::TEXT_ALIGN_RIGHT);
+ flags &= ~(gfx::Canvas::TEXT_ALIGN_LEFT |
+ gfx::Canvas::TEXT_ALIGN_CENTER |
+ gfx::Canvas::TEXT_ALIGN_RIGHT);
switch (combobox->selected_index()) {
case 0:
break;
case 1:
- text_flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
+ flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
break;
case 2:
- text_flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
+ flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
break;
case 3:
- text_flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
+ flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
break;
}
} else if (combobox == text_cb_) {
switch (combobox->selected_index()) {
case 0:
- text_view_->set_text(ASCIIToUTF16(kShortText));
+ text_view_->set_text(base::ASCIIToUTF16(kShortText));
break;
case 1:
- text_view_->set_text(ASCIIToUTF16(kMediumText));
+ text_view_->set_text(base::ASCIIToUTF16(kLongText));
break;
case 2:
- text_view_->set_text(ASCIIToUTF16(kLongText));
+ text_view_->set_text(base::ASCIIToUTF16(kAmpersandText));
break;
case 3:
- text_view_->set_text(ASCIIToUTF16(kAmpersandText));
- break;
- case 4:
- text_view_->set_text(ASCIIToUTF16(kNewlineText));
+ text_view_->set_text(base::WideToUTF16(kRightToLeftText));
break;
}
} else if (combobox == eliding_cb_) {
switch (combobox->selected_index()) {
case 0:
- text_flags &= ~gfx::Canvas::NO_ELLIPSIS;
- text_view_->set_fade(false);
+ text_view_->set_elide(gfx::ELIDE_TAIL);
break;
case 1:
- text_flags |= gfx::Canvas::NO_ELLIPSIS;
- text_view_->set_fade(false);
+ text_view_->set_elide(gfx::TRUNCATE);
break;
case 2:
- text_view_->set_fade_mode(gfx::Canvas::TruncateFadeTail);
- text_view_->set_fade(true);
- break;
- case 3:
- text_view_->set_fade_mode(gfx::Canvas::TruncateFadeHead);
- text_view_->set_fade(true);
+ text_view_->set_elide(gfx::FADE_TAIL);
break;
}
} else if (combobox == prefix_cb_) {
- text_flags &= ~(gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX);
+ flags &= ~(gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX);
switch (combobox->selected_index()) {
case 0:
break;
case 1:
- text_flags |= gfx::Canvas::SHOW_PREFIX;
+ flags |= gfx::Canvas::SHOW_PREFIX;
break;
case 2:
- text_flags |= gfx::Canvas::HIDE_PREFIX;
+ flags |= gfx::Canvas::HIDE_PREFIX;
break;
}
}
- text_view_->set_text_flags(text_flags);
+ text_view_->set_flags(flags);
text_view_->SchedulePaint();
}
diff --git a/chromium/ui/views/examples/text_example.h b/chromium/ui/views/examples/text_example.h
index 007f5194522..18ebaabdd74 100644
--- a/chromium/ui/views/examples/text_example.h
+++ b/chromium/ui/views/examples/text_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_TEXT_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
@@ -20,14 +19,14 @@ namespace examples {
class ExampleComboboxModel;
-class TextExample : public ExampleBase,
- public ButtonListener,
- public ComboboxListener {
+class VIEWS_EXAMPLES_EXPORT TextExample : public ExampleBase,
+ public ButtonListener,
+ public ComboboxListener {
public:
TextExample();
virtual ~TextExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
@@ -40,11 +39,11 @@ class TextExample : public ExampleBase,
const char** strings,
int count);
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* button, const ui::Event& event) OVERRIDE;
- // Overridden from ComboboxListener:
- virtual void OnSelectedIndexChanged(Combobox* combobox) OVERRIDE;
+ // ComboboxListener:
+ virtual void OnPerformAction(Combobox* combobox) OVERRIDE;
class TextExampleView;
// The content of the scroll view.
diff --git a/chromium/ui/views/examples/textfield_example.cc b/chromium/ui/views/examples/textfield_example.cc
index ec18cf74a5b..7dae434f353 100644
--- a/chromium/ui/views/examples/textfield_example.cc
+++ b/chromium/ui/views/examples/textfield_example.cc
@@ -14,6 +14,9 @@
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"
+using base::ASCIIToUTF16;
+using base::UTF16ToUTF8;
+
namespace views {
namespace examples {
@@ -34,7 +37,8 @@ TextfieldExample::~TextfieldExample() {
void TextfieldExample::CreateExampleView(View* container) {
name_ = new Textfield();
- password_ = new Textfield(Textfield::STYLE_OBSCURED);
+ password_ = new Textfield();
+ password_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
password_->set_placeholder_text(ASCIIToUTF16("password"));
read_only_ = new Textfield();
read_only_->SetReadOnly(true);
@@ -44,8 +48,8 @@ void TextfieldExample::CreateExampleView(View* container) {
append_ = new LabelButton(this, ASCIIToUTF16("Append"));
set_ = new LabelButton(this, ASCIIToUTF16("Set"));
set_style_ = new LabelButton(this, ASCIIToUTF16("Set Styles"));
- name_->SetController(this);
- password_->SetController(this);
+ name_->set_controller(this);
+ password_->set_controller(this);
GridLayout* layout = new GridLayout(container);
container->SetLayoutManager(layout);
@@ -77,7 +81,7 @@ void TextfieldExample::CreateExampleView(View* container) {
}
void TextfieldExample::ContentsChanged(Textfield* sender,
- const string16& new_contents) {
+ const base::string16& new_contents) {
if (sender == name_) {
PrintStatus("Name [%s]", UTF16ToUTF8(new_contents).c_str());
} else if (sender == password_) {
@@ -102,7 +106,7 @@ void TextfieldExample::ButtonPressed(Button* sender, const ui::Event& event) {
if (sender == show_password_) {
PrintStatus("Password [%s]", UTF16ToUTF8(password_->text()).c_str());
} else if (sender == clear_all_) {
- string16 empty;
+ base::string16 empty;
name_->SetText(empty);
password_->SetText(empty);
read_only_->SetText(empty);
diff --git a/chromium/ui/views/examples/textfield_example.h b/chromium/ui/views/examples/textfield_example.h
index b363c6ede7b..db5e1998299 100644
--- a/chromium/ui/views/examples/textfield_example.h
+++ b/chromium/ui/views/examples/textfield_example.h
@@ -7,9 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/examples/example_base.h"
@@ -21,9 +19,9 @@ class LabelButton;
namespace examples {
// TextfieldExample mimics login screen.
-class TextfieldExample : public ExampleBase,
- public TextfieldController,
- public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT TextfieldExample : public ExampleBase,
+ public TextfieldController,
+ public ButtonListener {
public:
TextfieldExample();
virtual ~TextfieldExample();
@@ -34,7 +32,7 @@ class TextfieldExample : public ExampleBase,
private:
// TextfieldController:
virtual void ContentsChanged(Textfield* sender,
- const string16& new_contents) OVERRIDE;
+ const base::string16& new_contents) OVERRIDE;
virtual bool HandleKeyEvent(Textfield* sender,
const ui::KeyEvent& key_event) OVERRIDE;
virtual bool HandleMouseEvent(Textfield* sender,
diff --git a/chromium/ui/views/examples/throbber_example.cc b/chromium/ui/views/examples/throbber_example.cc
index ccc3c794432..7bd18a246cb 100644
--- a/chromium/ui/views/examples/throbber_example.cc
+++ b/chromium/ui/views/examples/throbber_example.cc
@@ -25,7 +25,7 @@ class ThrobberView : public View {
throbber_->Start();
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return gfx::Size(width(), height());
}
diff --git a/chromium/ui/views/examples/throbber_example.h b/chromium/ui/views/examples/throbber_example.h
index 646ab691f79..3c4f9c0beb2 100644
--- a/chromium/ui/views/examples/throbber_example.h
+++ b/chromium/ui/views/examples/throbber_example.h
@@ -5,19 +5,18 @@
#ifndef UI_VIEWS_EXAMPLES_THROBBER_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_THROBBER_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace views {
namespace examples {
-class ThrobberExample : public ExampleBase {
+class VIEWS_EXAMPLES_EXPORT ThrobberExample : public ExampleBase {
public:
ThrobberExample();
virtual ~ThrobberExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
diff --git a/chromium/ui/views/examples/tree_view_example.cc b/chromium/ui/views/examples/tree_view_example.cc
index 6dfc5585974..2f6cc4cedf3 100644
--- a/chromium/ui/views/examples/tree_view_example.cc
+++ b/chromium/ui/views/examples/tree_view_example.cc
@@ -11,6 +11,8 @@
#include "ui/views/controls/tree/tree_view.h"
#include "ui/views/layout/grid_layout.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -130,10 +132,14 @@ void TreeViewExample::ShowContextMenuForView(View* source,
context_menu_model.AddItem(ID_REMOVE, ASCIIToUTF16("Remove"));
context_menu_model.AddItem(ID_ADD, ASCIIToUTF16("Add"));
context_menu_runner_.reset(new MenuRunner(&context_menu_model));
- if (context_menu_runner_->RunMenuAt(source->GetWidget(), NULL,
- gfx::Rect(point, gfx::Size()), MenuItemView::TOPLEFT, source_type, 0) ==
- MenuRunner::MENU_DELETED)
+ if (context_menu_runner_->RunMenuAt(source->GetWidget(),
+ NULL,
+ gfx::Rect(point, gfx::Size()),
+ MENU_ANCHOR_TOPLEFT,
+ source_type,
+ 0) == MenuRunner::MENU_DELETED) {
return;
+ }
}
bool TreeViewExample::IsCommandIdChecked(int command_id) const {
diff --git a/chromium/ui/views/examples/tree_view_example.h b/chromium/ui/views/examples/tree_view_example.h
index ffac4dd66fa..55af17f7d08 100644
--- a/chromium/ui/views/examples/tree_view_example.h
+++ b/chromium/ui/views/examples/tree_view_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_TREE_VIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_TREE_VIEW_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/models/tree_node_model.h"
#include "ui/views/context_menu_controller.h"
@@ -21,11 +20,12 @@ class TreeView;
namespace examples {
-class TreeViewExample : public ExampleBase,
- public ButtonListener,
- public TreeViewController,
- public ContextMenuController,
- public ui::SimpleMenuModel::Delegate {
+class VIEWS_EXAMPLES_EXPORT TreeViewExample
+ : public ExampleBase,
+ public ButtonListener,
+ public TreeViewController,
+ public ContextMenuController,
+ public ui::SimpleMenuModel::Delegate {
public:
TreeViewExample();
virtual ~TreeViewExample();
diff --git a/chromium/ui/views/examples/webview_example.cc b/chromium/ui/views/examples/webview_example.cc
index 5a2d89d3904..feae6b977f9 100644
--- a/chromium/ui/views/examples/webview_example.cc
+++ b/chromium/ui/views/examples/webview_example.cc
@@ -6,7 +6,6 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
@@ -28,7 +27,7 @@ void WebViewExample::CreateExampleView(View* container) {
container->AddChildView(webview_);
webview_->LoadInitialURL(GURL("http://www.google.com/"));
- webview_->web_contents()->GetView()->Focus();
+ webview_->web_contents()->Focus();
}
} // namespace examples
diff --git a/chromium/ui/views/examples/webview_example.h b/chromium/ui/views/examples/webview_example.h
index bc4e45918ef..3e35fe94a77 100644
--- a/chromium/ui/views/examples/webview_example.h
+++ b/chromium/ui/views/examples/webview_example.h
@@ -5,8 +5,7 @@
#ifndef UI_VIEWS_EXAMPLES_WEBVIEW_EXAMPLE_H_
#define UI_VIEWS_EXAMPLES_WEBVIEW_EXAMPLE_H_
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/examples/example_base.h"
namespace content {
@@ -23,7 +22,7 @@ class WebViewExample : public ExampleBase {
explicit WebViewExample(content::BrowserContext* browser_context);
virtual ~WebViewExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
diff --git a/chromium/ui/views/examples/widget_example.cc b/chromium/ui/views/examples/widget_example.cc
index 0d42a65ae6b..1109a5ad4c4 100644
--- a/chromium/ui/views/examples/widget_example.cc
+++ b/chromium/ui/views/examples/widget_example.cc
@@ -13,6 +13,8 @@
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace examples {
@@ -22,7 +24,7 @@ class DialogExample : public DialogDelegateView {
public:
DialogExample();
virtual ~DialogExample();
- virtual string16 GetWindowTitle() const OVERRIDE;
+ virtual base::string16 GetWindowTitle() const OVERRIDE;
virtual View* CreateExtraView() OVERRIDE;
virtual View* CreateTitlebarExtraView() OVERRIDE;
virtual View* CreateFootnoteView() OVERRIDE;
@@ -36,13 +38,13 @@ DialogExample::DialogExample() {
DialogExample::~DialogExample() {}
-string16 DialogExample::GetWindowTitle() const {
+base::string16 DialogExample::GetWindowTitle() const {
return ASCIIToUTF16("Dialog Widget Example");
}
View* DialogExample::CreateExtraView() {
LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Extra button!"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
return button;
}
diff --git a/chromium/ui/views/examples/widget_example.h b/chromium/ui/views/examples/widget_example.h
index 7c3085e02e8..ff08d70790f 100644
--- a/chromium/ui/views/examples/widget_example.h
+++ b/chromium/ui/views/examples/widget_example.h
@@ -7,8 +7,7 @@
#include <string>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/examples/example_base.h"
#include "ui/views/widget/widget.h"
@@ -17,12 +16,13 @@ namespace views {
namespace examples {
// WidgetExample demonstrates how to create a popup widget.
-class WidgetExample : public ExampleBase, public ButtonListener {
+class VIEWS_EXAMPLES_EXPORT WidgetExample : public ExampleBase,
+ public ButtonListener {
public:
WidgetExample();
virtual ~WidgetExample();
- // Overridden from ExampleBase:
+ // ExampleBase:
virtual void CreateExampleView(View* container) OVERRIDE;
private:
@@ -40,7 +40,7 @@ class WidgetExample : public ExampleBase, public ButtonListener {
// Construct a Widget for |sender|, initialize with |params|, and call Show().
void ShowWidget(View* sender, Widget::InitParams params);
- // Overridden from ButtonListener:
+ // ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(WidgetExample);
diff --git a/chromium/ui/views/focus/accelerator_handler.h b/chromium/ui/views/focus/accelerator_handler.h
deleted file mode 100644
index 29f353e697c..00000000000
--- a/chromium/ui/views/focus/accelerator_handler.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_
-#define UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_
-
-#include "build/build_config.h"
-
-#include <set>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-
-#if defined(USE_AURA) && defined(USE_X11)
-// Dispatch an XEvent to the RootView. Return true if the event was dispatched
-// and handled, false otherwise.
-bool VIEWS_EXPORT DispatchXEvent(XEvent* xevent);
-#endif // USE_AURA && USE_X11
-
-// This class delegates the key messages to the associated FocusManager class
-// for the window that is receiving these messages for accelerator processing.
-class VIEWS_EXPORT AcceleratorHandler : public base::MessageLoop::Dispatcher {
- public:
- AcceleratorHandler();
-
- // Dispatcher method. This returns true if an accelerator was processed by the
- // focus manager
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
-
- private:
-#if defined(OS_WIN)
- // The keys currently pressed and consumed by the FocusManager.
- std::set<WPARAM> pressed_keys_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(AcceleratorHandler);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_
diff --git a/chromium/ui/views/focus/accelerator_handler_aura.cc b/chromium/ui/views/focus/accelerator_handler_aura.cc
deleted file mode 100644
index 8daa0f394e9..00000000000
--- a/chromium/ui/views/focus/accelerator_handler_aura.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/focus/accelerator_handler.h"
-
-namespace views {
-
-AcceleratorHandler::AcceleratorHandler() {
-}
-
-bool AcceleratorHandler::Dispatch(const base::NativeEvent& event) {
-#if defined(OS_WIN)
- TranslateMessage(&event);
- DispatchMessage(&event);
-#endif // defined(OS_WIN)
- return true;
-}
-
-#if defined(USE_X11)
-bool DispatchXEvent(XEvent* xev) {
- return false;
-}
-#endif // defined(USE_X11)
-
-} // namespace views
diff --git a/chromium/ui/views/focus/accelerator_handler_win.cc b/chromium/ui/views/focus/accelerator_handler_win.cc
deleted file mode 100644
index ea82daed717..00000000000
--- a/chromium/ui/views/focus/accelerator_handler_win.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/focus/accelerator_handler.h"
-
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-AcceleratorHandler::AcceleratorHandler() {
-}
-
-bool AcceleratorHandler::Dispatch(const base::NativeEvent& msg) {
- if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) {
- Widget* widget = Widget::GetTopLevelWidgetForNativeView(msg.hwnd);
- FocusManager* focus_manager = widget ? widget->GetFocusManager() : NULL;
- if (focus_manager) {
- switch (msg.message) {
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN: {
- ui::KeyEvent event(msg, false);
- if (!focus_manager->OnKeyEvent(event)) {
- // Record that this key is pressed so we can remember not to
- // translate and dispatch the associated WM_KEYUP.
- pressed_keys_.insert(msg.wParam);
- return true;
- }
- break;
- }
- case WM_KEYUP:
- case WM_SYSKEYUP: {
- std::set<WPARAM>::iterator iter = pressed_keys_.find(msg.wParam);
- if (iter != pressed_keys_.end()) {
- // Don't translate/dispatch the KEYUP since we have eaten the
- // associated KEYDOWN.
- pressed_keys_.erase(iter);
- return true;
- }
- break;
- }
- }
- }
- }
-
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- return true;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/focus/focus_manager.cc b/chromium/ui/views/focus/focus_manager.cc
index f52712e6234..4808b4422cb 100644
--- a/chromium/ui/views/focus/focus_manager.cc
+++ b/chromium/ui/views/focus/focus_manager.cc
@@ -11,6 +11,10 @@
#include "base/logging.h"
#include "build/build_config.h"
#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/ime/input_method.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/base/ime/text_input_focus_manager.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/focus/focus_manager_delegate.h"
@@ -64,6 +68,7 @@ bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) {
modifiers |= ui::EF_ALT_DOWN;
ui::Accelerator accelerator(event.key_code(), modifiers);
accelerator.set_type(event.type());
+ accelerator.set_is_repeat(event.IsRepeat());
if (event.type() == ui::ET_KEY_PRESSED) {
// If the focused view wants to process the key event as is, let it be.
@@ -75,20 +80,10 @@ bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) {
// Note that we don't do focus traversal if the root window is not part of
// the active window hierarchy as this would mean we have no focused view
// and would focus the first focusable view.
-#if defined(OS_WIN) && !defined(USE_AURA)
- HWND top_window = widget_->GetNativeView();
- HWND active_window = ::GetActiveWindow();
- if ((active_window == top_window || ::IsChild(active_window, top_window)) &&
- IsTabTraversalKeyEvent(event)) {
- AdvanceFocus(event.IsShiftDown());
- return false;
- }
-#else
if (IsTabTraversalKeyEvent(event)) {
AdvanceFocus(event.IsShiftDown());
return false;
}
-#endif
if (arrow_key_traversal_enabled_ && ProcessArrowKeyTraversal(event))
return false;
@@ -319,8 +314,13 @@ View* FocusManager::GetNextFocusableView(View* original_starting_view,
void FocusManager::SetFocusedViewWithReason(
View* view, FocusChangeReason reason) {
- if (focused_view_ == view)
+ if (focused_view_ == view) {
+ // In the case that the widget lost the focus and gained it back without
+ // changing the focused view, we have to make the text input client focused.
+ // TODO(yukishiino): Remove this hack once we fix http://crbug.com/383236
+ FocusTextInputClient(focused_view_);
return;
+ }
base::AutoReset<bool> auto_changing_focus(&is_changing_focus_, true);
// Update the reason for the focus change (since this is checked by
@@ -331,14 +331,18 @@ void FocusManager::SetFocusedViewWithReason(
View* old_focused_view = focused_view_;
focused_view_ = view;
- if (old_focused_view)
+ if (old_focused_view) {
old_focused_view->Blur();
+ BlurTextInputClient(old_focused_view);
+ }
// Also make |focused_view_| the stored focus view. This way the stored focus
// view is remembered if focus changes are requested prior to a show or while
// hidden.
SetStoredFocusView(focused_view_);
- if (focused_view_)
+ if (focused_view_) {
+ FocusTextInputClient(focused_view_);
focused_view_->Focus();
+ }
FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
OnDidChangeFocus(old_focused_view, focused_view_));
@@ -437,6 +441,46 @@ void FocusManager::ClearStoredFocusedView() {
SetStoredFocusView(NULL);
}
+void FocusManager::OnTextInputClientChanged(View* view) {
+ if (view == focused_view_)
+ FocusTextInputClient(view);
+}
+
+void FocusManager::FocusTextInputClient(View* view) {
+ if (!switches::IsTextInputFocusManagerEnabled())
+ return;
+
+ // If the widget is not active, do not steal the text input focus.
+ if (!widget_->IsActive())
+ return;
+
+ ui::TextInputClient* text_input_client =
+ view ? view->GetTextInputClient() : NULL;
+ ui::TextInputFocusManager::GetInstance()->
+ FocusTextInputClient(text_input_client);
+ ui::InputMethod* input_method = widget_->GetHostInputMethod();
+ if (input_method) {
+ input_method->OnTextInputTypeChanged(text_input_client);
+ input_method->OnCaretBoundsChanged(text_input_client);
+ }
+}
+
+void FocusManager::BlurTextInputClient(View* view) {
+ if (!switches::IsTextInputFocusManagerEnabled())
+ return;
+
+ ui::TextInputClient* text_input_client =
+ view ? view->GetTextInputClient() : NULL;
+ if (text_input_client && text_input_client->HasCompositionText()) {
+ text_input_client->ConfirmCompositionText();
+ ui::InputMethod* input_method = widget_->GetHostInputMethod();
+ if (input_method && input_method->GetTextInputClient() == text_input_client)
+ input_method->CancelComposition(text_input_client);
+ }
+ ui::TextInputFocusManager::GetInstance()->
+ BlurTextInputClient(text_input_client);
+}
+
// Find the next (previous if reverse is true) focusable view for the specified
// FocusTraversable, starting at the specified view, traversing down the
// FocusTraversable hierarchy.
diff --git a/chromium/ui/views/focus/focus_manager.h b/chromium/ui/views/focus/focus_manager.h
index 7d7c7dc16e0..ebdc2a3d88e 100644
--- a/chromium/ui/views/focus/focus_manager.h
+++ b/chromium/ui/views/focus/focus_manager.h
@@ -72,8 +72,8 @@
// is FocusTraversable.
namespace ui {
-class AcceleratorTarget;
class AcceleratorManager;
+class AcceleratorTarget;
class EventHandler;
class KeyEvent;
}
@@ -213,6 +213,15 @@ class VIEWS_EXPORT FocusManager {
// Returns true if in the process of changing the focused view.
bool is_changing_focus() const { return is_changing_focus_; }
+ // Changes the text input focus to |view->GetTextInputClient()| iff |view|
+ // is focused. Views must call this method when their internal
+ // TextInputClient instance changes.
+ void OnTextInputClientChanged(View* view);
+
+ // Moves the text input focus into/out from |view|.
+ void FocusTextInputClient(View* view);
+ void BlurTextInputClient(View* view);
+
// Disable shortcut handling.
static void set_shortcut_handling_suspended(bool suspended) {
shortcut_handling_suspended_ = suspended;
diff --git a/chromium/ui/views/focus/focus_manager_test.cc b/chromium/ui/views/focus/focus_manager_test.cc
index 528f345ce63..6debc794dff 100644
--- a/chromium/ui/views/focus/focus_manager_test.cc
+++ b/chromium/ui/views/focus/focus_manager_test.cc
@@ -100,24 +100,6 @@ void FocusManagerTest::SetAccessiblePanes(const std::vector<View*>& panes) {
accessible_panes_ = panes;
}
-#if defined(OS_WIN) && !defined(USE_AURA)
-void FocusManagerTest::SimulateActivateWindow() {
- SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
-}
-
-void FocusManagerTest::SimulateDeactivateWindow() {
- SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
-}
-
-void FocusManagerTest::PostKeyDown(ui::KeyboardCode key_code) {
- PostMessage(GetWidget()->GetNativeView(), WM_KEYDOWN, key_code, 0);
-}
-
-void FocusManagerTest::PostKeyUp(ui::KeyboardCode key_code) {
- PostMessage(GetWidget()->GetNativeView(), WM_KEYUP, key_code, 0);
-}
-#endif
-
////////////////////////////////////////////////////////////////////////////////
// TestFocusChangeListener
diff --git a/chromium/ui/views/focus/focus_manager_test.h b/chromium/ui/views/focus/focus_manager_test.h
index 4afbf4f7758..e54138673b0 100644
--- a/chromium/ui/views/focus/focus_manager_test.h
+++ b/chromium/ui/views/focus/focus_manager_test.h
@@ -43,15 +43,6 @@ class FocusManagerTest : public ViewsTestBase, public WidgetDelegate {
// For testing FocusManager::RotatePaneFocus().
void SetAccessiblePanes(const std::vector<View*>& panes);
-#if defined(OS_WIN) && !defined(USE_AURA)
- // Mocks activating/deactivating the window.
- void SimulateActivateWindow();
- void SimulateDeactivateWindow();
-
- void PostKeyDown(ui::KeyboardCode key_code);
- void PostKeyUp(ui::KeyboardCode key_code);
-#endif
-
private:
View* contents_view_;
FocusChangeListener* focus_change_listener_;
diff --git a/chromium/ui/views/focus/focus_manager_unittest.cc b/chromium/ui/views/focus/focus_manager_unittest.cc
index fcb82b7f310..3513e2b70a7 100644
--- a/chromium/ui/views/focus/focus_manager_unittest.cc
+++ b/chromium/ui/views/focus/focus_manager_unittest.cc
@@ -2,38 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/focus/focus_manager.h"
+
#include <utility>
#include <vector>
+#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/window.h"
#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/base/ime/text_input_focus_manager.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/views/accessible_pane_view.h"
#include "ui/views/controls/button/label_button.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/focus/accelerator_handler.h"
#include "ui/views/focus/focus_manager_factory.h"
#include "ui/views/focus/focus_manager_test.h"
#include "ui/views/focus/widget_focus_manager.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/window.h"
-#endif
-
namespace views {
-void FocusNativeView(gfx::NativeView view) {
-#if defined(USE_AURA)
- aura::client::GetFocusClient(view)->FocusWindow(view);
-#elif defined(OS_WIN)
- SetFocus(view);
-#else
-#error
-#endif
-}
-
enum FocusTestEventType {
ON_FOCUS = 0,
ON_BLUR
@@ -67,6 +58,8 @@ class SimpleTestView : public View {
private:
std::vector<FocusTestEvent>* event_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleTestView);
};
// Tests that the appropriate Focus related methods are called when a View
@@ -149,14 +142,14 @@ TEST_F(FocusManagerTest, WidgetFocusChangeListener) {
widget_listener.ClearFocusChanges();
gfx::NativeView native_view1 = widget1->GetNativeView();
- FocusNativeView(native_view1);
+ aura::client::GetFocusClient(native_view1)->FocusWindow(native_view1);
ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
EXPECT_EQ(native_view1, widget_listener.focus_changes()[0].second);
EXPECT_EQ(native_view1, widget_listener.focus_changes()[1].second);
widget_listener.ClearFocusChanges();
gfx::NativeView native_view2 = widget2->GetNativeView();
- FocusNativeView(native_view2);
+ aura::client::GetFocusClient(native_view2)->FocusWindow(native_view2);
ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
EXPECT_EQ(NativeViewPair(native_view1, native_view2),
widget_listener.focus_changes()[0]);
@@ -164,26 +157,6 @@ TEST_F(FocusManagerTest, WidgetFocusChangeListener) {
widget_listener.focus_changes()[1]);
}
-#if !defined(USE_AURA)
-class TestTextfield : public Textfield {
- public:
- TestTextfield() {}
- virtual gfx::NativeView TestGetNativeControlView() {
- return native_wrapper_->GetTestingHandle();
- }
-};
-
-// Tests that NativeControls do set the focused View appropriately on the
-// FocusManager.
-TEST_F(FocusManagerTest, DISABLED_FocusNativeControls) {
- TestTextfield* textfield = new TestTextfield();
- GetContentsView()->AddChildView(textfield);
- // Simulate the native view getting the native focus (such as by user click).
- FocusNativeView(textfield->TestGetNativeControlView());
- EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
-}
-#endif
-
// Counts accelerator calls.
class TestAcceleratorTarget : public ui::AcceleratorTarget {
public:
@@ -537,10 +510,11 @@ class FocusManagerDtorTest : public FocusManagerTest {
class LabelButtonDtorTracked : public LabelButton {
public:
- LabelButtonDtorTracked(const string16& text, DtorTrackVector* dtor_tracker)
+ LabelButtonDtorTracked(const base::string16& text,
+ DtorTrackVector* dtor_tracker)
: LabelButton(NULL, text),
dtor_tracker_(dtor_tracker) {
- SetStyle(STYLE_NATIVE_TEXTBUTTON);
+ SetStyle(STYLE_BUTTON);
};
virtual ~LabelButtonDtorTracked() {
dtor_tracker_->push_back("LabelButtonDtorTracked");
@@ -586,25 +560,6 @@ class FocusManagerDtorTest : public FocusManagerTest {
DtorTrackVector dtor_tracker_;
};
-#if !defined(USE_AURA)
-TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
- // Setup views hierarchy.
- GetContentsView()->AddChildView(new TestTextfield());
- GetContentsView()->AddChildView(new LabelButtonDtorTracked(
- ASCIIToUTF16("button"), &dtor_tracker_));
-
- // Close the window.
- GetWidget()->Close();
- RunPendingMessages();
-
- // Test window, button and focus manager should all be destructed.
- ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size()));
-
- // Focus manager should be the last one to destruct.
- ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str());
-}
-#endif
-
namespace {
class FocusInAboutToRequestFocusFromTabTraversalView : public View {
@@ -819,16 +774,72 @@ TEST_F(FocusManagerTest, StoreFocusedView) {
View view;
GetFocusManager()->SetFocusedView(&view);
GetFocusManager()->StoreFocusedView(false);
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView());
// Repeat with |true|.
GetFocusManager()->SetFocusedView(&view);
GetFocusManager()->StoreFocusedView(true);
+ EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView());
}
+class TextInputTestView : public View {
+ public:
+ TextInputTestView() {}
+
+ virtual ui::TextInputClient* GetTextInputClient() OVERRIDE {
+ return &text_input_client_;
+ }
+
+ private:
+ ui::DummyTextInputClient text_input_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(TextInputTestView);
+};
+
+TEST_F(FocusManagerTest, TextInputClient) {
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager);
+
+ View* view = new TextInputTestView;
+ ui::TextInputClient* text_input_client = view->GetTextInputClient();
+ view->SetFocusable(true);
+ GetContentsView()->AddChildView(view);
+ ui::TextInputFocusManager* text_input_focus_manager =
+ ui::TextInputFocusManager::GetInstance();
+
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ GetFocusManager()->StoreFocusedView(false);
+ EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+
+ // Repeat with |true|.
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ GetFocusManager()->StoreFocusedView(true);
+ EXPECT_TRUE(GetFocusManager()->RestoreFocusedView());
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+
+ // Focus the view twice in a row.
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+ ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL);
+ GetFocusManager()->SetFocusedView(view);
+ EXPECT_EQ(text_input_client,
+ text_input_focus_manager->GetFocusedTextInputClient());
+}
+
namespace {
// Trivial WidgetDelegate implementation that allows setting return value of
diff --git a/chromium/ui/views/focus/focus_manager_unittest_win.cc b/chromium/ui/views/focus/focus_manager_unittest_win.cc
deleted file mode 100644
index 267a8b78df3..00000000000
--- a/chromium/ui/views/focus/focus_manager_unittest_win.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/focus/focus_manager.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "ui/events/event.h"
-#include "ui/views/controls/button/label_button.h"
-#include "ui/views/focus/accelerator_handler.h"
-#include "ui/views/focus/focus_manager_test.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-namespace {
-
-class MessageTrackingView : public View {
- public:
- MessageTrackingView() : accelerator_pressed_(false) {
- }
-
- void Reset() {
- accelerator_pressed_ = false;
- keys_pressed_.clear();
- keys_released_.clear();
- }
-
- const std::vector<ui::KeyboardCode>& keys_pressed() const {
- return keys_pressed_;
- }
-
- const std::vector<ui::KeyboardCode>& keys_released() const {
- return keys_released_;
- }
-
- bool accelerator_pressed() const {
- return accelerator_pressed_;
- }
-
- // Overridden from View:
- virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
- keys_pressed_.push_back(e.key_code());
- return true;
- }
- virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
- keys_released_.push_back(e.key_code());
- return true;
- }
- virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
- accelerator_pressed_ = true;
- return true;
- }
-
- private:
- bool accelerator_pressed_;
- std::vector<ui::KeyboardCode> keys_pressed_;
- std::vector<ui::KeyboardCode> keys_released_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
-};
-
-} // namespace
-
-// Test that when activating/deactivating the top window, the focus is stored/
-// restored properly.
-TEST_F(FocusManagerTest, FocusStoreRestore) {
- // Simulate an activate, otherwise the deactivate isn't going to do anything.
- SimulateActivateWindow();
-
- LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Press me"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
- View* view = new View();
- view->SetFocusable(true);
-
- GetContentsView()->AddChildView(button);
- button->SetBounds(10, 10, 200, 30);
- GetContentsView()->AddChildView(view);
- RunPendingMessages();
-
- TestFocusChangeListener listener;
- AddFocusChangeListener(&listener);
-
- view->RequestFocus();
- RunPendingMessages();
-
- // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
- views::View* null_view = NULL;
-
- // Deacivate the window, it should store its focus.
- SimulateDeactivateWindow();
- EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view));
- listener.ClearFocusChanges();
-
- // Reactivate, focus should come-back to the previously focused view.
- SimulateActivateWindow();
- EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
- listener.ClearFocusChanges();
-
- // Same test with a NativeControl.
- button->RequestFocus();
- SimulateDeactivateWindow();
- EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view));
- listener.ClearFocusChanges();
-
- SimulateActivateWindow();
- EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button));
- listener.ClearFocusChanges();
-
- /*
- // Now test that while the window is inactive we can change the focused view
- // (we do that in several places).
- SimulateDeactivateWindow();
- // TODO: would have to mock the window being inactive (with a TestWidgetWin
- // that would return false on IsActive()).
- GetFocusManager()->SetFocusedView(view);
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
-
- EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
- ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
- EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view));
- EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view));
- */
-}
-
-// Test that the focus manager is created successfully for the first view
-// window parented to a native dialog.
-TEST_F(FocusManagerTest, CreationForNativeRoot) {
- // Create a window class.
- WNDCLASSEX class_ex;
- memset(&class_ex, 0, sizeof(class_ex));
- class_ex.cbSize = sizeof(WNDCLASSEX);
- class_ex.lpfnWndProc = &DefWindowProc;
- class_ex.lpszClassName = L"TestWindow";
- ATOM atom = RegisterClassEx(&class_ex);
- ASSERT_TRUE(atom);
-
- // Create a native dialog window.
- HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
- WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
- NULL, NULL, NULL, NULL);
- ASSERT_TRUE(hwnd);
-
- // Create a view window parented to native dialog.
- scoped_ptr<Widget> widget1(new Widget);
- Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = hwnd;
- params.bounds = gfx::Rect(0, 0, 100, 100);
- params.top_level = true; // This is top level in views hierarchy.
- widget1->Init(params);
-
- // Get the focus manager directly from the first window. Should exist
- // because the first window is the root widget.
- views::FocusManager* focus_manager1 = widget1->GetFocusManager();
- EXPECT_TRUE(focus_manager1);
-
- // Create another view window parented to the first view window.
- scoped_ptr<Widget> widget2(new Widget);
- params.parent = widget1->GetNativeView();
- params.top_level = false; // This is child widget.
- widget2->Init(params);
-
- // Access the shared focus manager directly from the second window.
- views::FocusManager* focus_manager2 = widget2->GetFocusManager();
- EXPECT_EQ(focus_manager2, focus_manager1);
-
- // Access the shared focus manager indirectly from the first window handle.
- gfx::NativeWindow native_window = widget1->GetNativeWindow();
- views::Widget* widget =
- views::Widget::GetWidgetForNativeWindow(native_window);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the second window handle.
- native_window = widget2->GetNativeWindow();
- widget = views::Widget::GetWidgetForNativeWindow(native_window);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the first view handle.
- gfx::NativeView native_view = widget1->GetNativeView();
- widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- // Access the shared focus manager indirectly from the second view handle.
- native_view = widget2->GetNativeView();
- widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
- EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
-
- DestroyWindow(hwnd);
-}
-
-// Tests that the keyup messages are eaten for accelerators.
-// Windows-only, Windows is the only platform that handles accelerators in
-// AcceleratorHandler. NativeWidgetAura::OnKeyEvent handles them in other
-// configurations.
-TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
- FocusManager* focus_manager = GetFocusManager();
- MessageTrackingView* mtv = new MessageTrackingView();
- mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, ui::EF_NONE));
- mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, ui::EF_NONE));
- GetContentsView()->AddChildView(mtv);
- focus_manager->SetFocusedView(mtv);
-
- // First send a non-accelerator key sequence.
- PostKeyDown(ui::VKEY_9);
- PostKeyUp(ui::VKEY_9);
- AcceleratorHandler accelerator_handler;
- scoped_ptr<base::RunLoop> run_loop(new base::RunLoop(&accelerator_handler));
- run_loop->RunUntilIdle();
- // Make sure we get a key-up and key-down.
- ASSERT_EQ(1U, mtv->keys_pressed().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
- ASSERT_EQ(1U, mtv->keys_released().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
- EXPECT_FALSE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Same thing with repeat and more than one key at once.
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_8);
- PostKeyDown(ui::VKEY_9);
- PostKeyDown(ui::VKEY_7);
- PostKeyUp(ui::VKEY_9);
- PostKeyUp(ui::VKEY_7);
- PostKeyUp(ui::VKEY_8);
- run_loop.reset(new base::RunLoop(&accelerator_handler));
- run_loop->RunUntilIdle();
- // Make sure we get a key-up and key-down.
- ASSERT_EQ(5U, mtv->keys_pressed().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]);
- EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]);
- EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]);
- EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]);
- ASSERT_EQ(3U, mtv->keys_released().size());
- EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
- EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]);
- EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]);
- EXPECT_FALSE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Now send an accelerator key sequence.
- PostKeyDown(ui::VKEY_0);
- PostKeyUp(ui::VKEY_0);
- run_loop.reset(new base::RunLoop(&accelerator_handler));
- run_loop->RunUntilIdle();
- EXPECT_TRUE(mtv->keys_pressed().empty());
- EXPECT_TRUE(mtv->keys_released().empty());
- EXPECT_TRUE(mtv->accelerator_pressed());
- mtv->Reset();
-
- // Same thing with repeat and more than one key at once.
- PostKeyDown(ui::VKEY_0);
- PostKeyDown(ui::VKEY_1);
- PostKeyDown(ui::VKEY_1);
- PostKeyDown(ui::VKEY_0);
- PostKeyDown(ui::VKEY_0);
- PostKeyUp(ui::VKEY_1);
- PostKeyUp(ui::VKEY_0);
- run_loop.reset(new base::RunLoop(&accelerator_handler));
- run_loop->RunUntilIdle();
- EXPECT_TRUE(mtv->keys_pressed().empty());
- EXPECT_TRUE(mtv->keys_released().empty());
- EXPECT_TRUE(mtv->accelerator_pressed());
- mtv->Reset();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/focus/focus_traversal_unittest.cc b/chromium/ui/views/focus/focus_traversal_unittest.cc
index c3e8159a5fa..6f0ba34ecb2 100644
--- a/chromium/ui/views/focus/focus_traversal_unittest.cc
+++ b/chromium/ui/views/focus/focus_traversal_unittest.cc
@@ -20,11 +20,12 @@
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/focus/accelerator_handler.h"
#include "ui/views/focus/focus_manager_test.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
+using base::ASCIIToUTF16;
+
namespace views {
namespace {
@@ -89,7 +90,7 @@ class DummyComboboxModel : public ui::ComboboxModel {
public:
// Overridden from ui::ComboboxModel:
virtual int GetItemCount() const OVERRIDE { return 10; }
- virtual string16 GetItemAt(int index) OVERRIDE {
+ virtual base::string16 GetItemAt(int index) OVERRIDE {
return ASCIIToUTF16("Item ") + base::IntToString16(index);
}
};
@@ -157,11 +158,7 @@ class BorderView : public NativeViewHost {
if (!widget_) {
widget_ = new Widget;
Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
-#if defined(OS_WIN) || defined(USE_AURA)
params.parent = details.parent->GetWidget()->GetNativeView();
-#else
- NOTREACHED();
-#endif
widget_->Init(params);
widget_->SetFocusTraversableParentView(this);
widget_->SetContentsView(child_);
@@ -294,7 +291,7 @@ void FocusTraversalTest::InitContentView() {
cb->set_id(kTopCheckBoxID);
left_container_ = new PaneView();
- left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ left_container_->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK));
left_container_->set_background(
Background::CreateSolidBackground(240, 240, 240));
left_container_->set_id(kLeftContainerID);
@@ -361,7 +358,7 @@ void FocusTraversalTest::InitContentView() {
y += label_height + gap_between_labels;
LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Click me"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
button->SetBounds(label_x, y + 10, 80, 30);
button->set_id(kFruitButtonID);
left_container_->AddChildView(button);
@@ -379,7 +376,7 @@ void FocusTraversalTest::InitContentView() {
left_container_->AddChildView(combobox);
right_container_ = new PaneView();
- right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ right_container_->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK));
right_container_->set_background(
Background::CreateSolidBackground(240, 240, 240));
right_container_->set_id(kRightContainerID);
@@ -410,7 +407,7 @@ void FocusTraversalTest::InitContentView() {
y += radio_button_height + gap_between_radio_buttons;
View* inner_container = new View();
- inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
+ inner_container->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK));
inner_container->set_background(
Background::CreateSolidBackground(230, 230, 230));
inner_container->set_id(kInnerContainerID);
@@ -457,7 +454,7 @@ void FocusTraversalTest::InitContentView() {
y = 250;
int width = 60;
button = new LabelButton(NULL, ASCIIToUTF16("OK"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
button->set_id(kOKButtonID);
button->SetIsDefault(true);
@@ -465,13 +462,13 @@ void FocusTraversalTest::InitContentView() {
button->SetBounds(150, y, width, 30);
button = new LabelButton(NULL, ASCIIToUTF16("Cancel"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
button->set_id(kCancelButtonID);
GetContentsView()->AddChildView(button);
button->SetBounds(220, y, width, 30);
button = new LabelButton(NULL, ASCIIToUTF16("Help"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
button->set_id(kHelpButtonID);
GetContentsView()->AddChildView(button);
button->SetBounds(290, y, width, 30);
@@ -525,7 +522,7 @@ void FocusTraversalTest::InitContentView() {
text_field->set_id(kSearchTextfieldID);
button = new LabelButton(NULL, ASCIIToUTF16("Search"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
contents->AddChildView(button);
button->SetBounds(112, 5, 60, 30);
button->set_id(kSearchButtonID);
@@ -549,12 +546,12 @@ void FocusTraversalTest::InitContentView() {
contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
contents->set_id(kThumbnailContainerID);
button = new LabelButton(NULL, ASCIIToUTF16("Star"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
contents->AddChildView(button);
button->SetBounds(5, 5, 50, 30);
button->set_id(kThumbnailStarID);
button = new LabelButton(NULL, ASCIIToUTF16("SuperStar"));
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
contents->AddChildView(button);
button->SetBounds(60, 5, 100, 30);
button->set_id(kThumbnailSuperStarID);
@@ -579,9 +576,6 @@ TEST_F(FocusTraversalTest, NormalTraversal) {
kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
- // Uncomment the following line to manually test the UI of this test.
- // base::RunLoop(new AcceleratorHandler()).Run();
-
// Let's traverse the whole focus hierarchy (several times, to make sure it
// loops OK).
GetFocusManager()->ClearFocus();
@@ -631,9 +625,6 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
v->SetEnabled(false);
}
- // Uncomment the following line to manually test the UI of this test.
- // base::RunLoop(new AcceleratorHandler()).Run();
-
View* focused_view;
// Let's do one traversal (several times, to make sure it loops ok).
GetFocusManager()->ClearFocus();
@@ -682,9 +673,6 @@ TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
v->SetVisible(false);
}
- // Uncomment the following line to manually test the UI of this test.
- // base::RunLoop(new AcceleratorHandler()).Run();
-
View* focused_view;
// Let's do one traversal (several times, to make sure it loops ok).
GetFocusManager()->ClearFocus();
diff --git a/chromium/ui/views/focus/view_storage.h b/chromium/ui/views/focus/view_storage.h
index 629aec1cbb9..5e36f3c5e9b 100644
--- a/chromium/ui/views/focus/view_storage.h
+++ b/chromium/ui/views/focus/view_storage.h
@@ -17,7 +17,7 @@ template <typename T> struct DefaultSingletonTraits;
// used for example in the FocusManager to store/restore focused views when the
// main window becomes active/inactive.
// It automatically removes a view from the storage if the view is removed from
-// the tree hierarchy.
+// the tree hierarchy or when the view is destroyed, which ever comes first.
//
// To use it, you first need to create a view storage id that can then be used
// to store/retrieve views.
diff --git a/chromium/ui/views/ime/OWNERS b/chromium/ui/views/ime/OWNERS
index 60ba2b38ade..9f6409afd85 100644
--- a/chromium/ui/views/ime/OWNERS
+++ b/chromium/ui/views/ime/OWNERS
@@ -1,2 +1,6 @@
+# primary reviewer
+yukishiino@chromium.org
+
+# backup reviewers.
+mukai@chromium.org
nona@chromium.org
-penghuang@chromium.org
diff --git a/chromium/ui/views/ime/input_method.h b/chromium/ui/views/ime/input_method.h
index f4e8a482285..ffb5ae9c02f 100644
--- a/chromium/ui/views/ime/input_method.h
+++ b/chromium/ui/views/ime/input_method.h
@@ -34,7 +34,7 @@ class Widget;
// designed to be bound to top-level Widgets.
class VIEWS_EXPORT InputMethod {
public:
- // TODO(yukawa): Move these typedef into ime_constants.h or somewhere.
+
#if defined(OS_WIN)
typedef LRESULT NativeEventResult;
#else
@@ -94,10 +94,6 @@ class VIEWS_EXPORT InputMethod {
// tag, or an empty string if the input method cannot provide it.
virtual std::string GetInputLocale() = 0;
- // Returns the text direction of current keyboard layout or input method, or
- // base::i18n::UNKNOWN_DIRECTION if the input method cannot provide it.
- virtual base::i18n::TextDirection GetInputTextDirection() = 0;
-
// Returns true if the input method is ready to process keyboard events and
// generate composition or text results. It is not necessary to notify
// inactive input methods of caret bounds or text input type changes.
@@ -118,6 +114,9 @@ class VIEWS_EXPORT InputMethod {
// of IME popups is not supported.
virtual bool IsCandidatePopupOpen() const = 0;
+ // Displays an on screen keyboard if enabled.
+ virtual void ShowImeIfNeeded() = 0;
+
// Returns true if the input method is a mock instance used for testing.
virtual bool IsMock() const = 0;
diff --git a/chromium/ui/views/ime/input_method_bridge.cc b/chromium/ui/views/ime/input_method_bridge.cc
index f2e00ce03e1..97b040056ad 100644
--- a/chromium/ui/views/ime/input_method_bridge.cc
+++ b/chromium/ui/views/ime/input_method_bridge.cc
@@ -33,6 +33,7 @@ class InputMethodBridge::HostObserver : public ui::InputMethodObserver {
const ui::TextInputClient* client) OVERRIDE {}
virtual void OnInputMethodDestroyed(
const ui::InputMethod* input_method) OVERRIDE;
+ virtual void OnShowImeIfNeeded() OVERRIDE {}
private:
InputMethodBridge* bridge_;
@@ -159,12 +160,6 @@ std::string InputMethodBridge::GetInputLocale() {
return host_->GetInputLocale();
}
-base::i18n::TextDirection InputMethodBridge::GetInputTextDirection() {
- DCHECK(host_);
-
- return host_->GetInputTextDirection();
-}
-
bool InputMethodBridge::IsActive() {
DCHECK(host_);
@@ -177,8 +172,13 @@ bool InputMethodBridge::IsCandidatePopupOpen() const {
return host_->IsCandidatePopupOpen();
}
+void InputMethodBridge::ShowImeIfNeeded() {
+ DCHECK(host_);
+ host_->ShowImeIfNeeded();
+}
+
// Overridden from TextInputClient. Forward an event from the system-wide IME
-// to the text input |client|, which is e.g. views::NativeTextfieldViews.
+// to the text input |client|, which is e.g. views::Textfield.
void InputMethodBridge::SetCompositionText(
const ui::CompositionText& composition) {
TextInputClient* client = GetTextInputClient();
@@ -198,13 +198,13 @@ void InputMethodBridge::ClearCompositionText() {
client->ClearCompositionText();
}
-void InputMethodBridge::InsertText(const string16& text) {
+void InputMethodBridge::InsertText(const base::string16& text) {
TextInputClient* client = GetTextInputClient();
if (client)
client->InsertText(text);
}
-void InputMethodBridge::InsertChar(char16 ch, int flags) {
+void InputMethodBridge::InsertChar(base::char16 ch, int flags) {
TextInputClient* client = GetTextInputClient();
if (client)
client->InsertChar(ch, flags);
@@ -280,7 +280,7 @@ bool InputMethodBridge::DeleteRange(const gfx::Range& range) {
}
bool InputMethodBridge::GetTextFromRange(const gfx::Range& range,
- string16* text) const {
+ base::string16* text) const {
TextInputClient* client = GetTextInputClient();
return client ? client->GetTextFromRange(range, text) : false;
}
@@ -319,6 +319,13 @@ void InputMethodBridge::OnCandidateWindowUpdated() {
void InputMethodBridge::OnCandidateWindowHidden() {
}
+bool InputMethodBridge::IsEditingCommandEnabled(int command_id) {
+ return false;
+}
+
+void InputMethodBridge::ExecuteEditingCommand(int command_id) {
+}
+
// Overridden from FocusChangeListener.
void InputMethodBridge::OnWillChangeFocus(View* focused_before, View* focused) {
if (HasCompositionText()) {
diff --git a/chromium/ui/views/ime/input_method_bridge.h b/chromium/ui/views/ime/input_method_bridge.h
index 5e28a034b99..cdabecd7903 100644
--- a/chromium/ui/views/ime/input_method_bridge.h
+++ b/chromium/ui/views/ime/input_method_bridge.h
@@ -45,17 +45,17 @@ class InputMethodBridge : public InputMethodBase,
virtual void CancelComposition(View* view) OVERRIDE;
virtual void OnInputLocaleChanged() OVERRIDE;
virtual std::string GetInputLocale() OVERRIDE;
- virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE;
virtual bool IsActive() OVERRIDE;
virtual bool IsCandidatePopupOpen() const OVERRIDE;
+ virtual void ShowImeIfNeeded() OVERRIDE;
// Overridden from TextInputClient:
virtual void SetCompositionText(
const ui::CompositionText& composition) OVERRIDE;
virtual void ConfirmCompositionText() OVERRIDE;
virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const string16& text) OVERRIDE;
- virtual void InsertChar(char16 ch, int flags) OVERRIDE;
+ virtual void InsertText(const base::string16& text) OVERRIDE;
+ virtual void InsertChar(base::char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
@@ -70,7 +70,7 @@ class InputMethodBridge : public InputMethodBase,
virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
virtual bool GetTextFromRange(const gfx::Range& range,
- string16* text) const OVERRIDE;
+ base::string16* text) const OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) OVERRIDE;
@@ -79,6 +79,8 @@ class InputMethodBridge : public InputMethodBase,
virtual void OnCandidateWindowShown() OVERRIDE;
virtual void OnCandidateWindowUpdated() OVERRIDE;
virtual void OnCandidateWindowHidden() OVERRIDE;
+ virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE;
+ virtual void ExecuteEditingCommand(int command_id) OVERRIDE;
// Overridden from FocusChangeListener.
virtual void OnWillChangeFocus(View* focused_before, View* focused) OVERRIDE;
diff --git a/chromium/ui/views/ime/mock_input_method.cc b/chromium/ui/views/ime/mock_input_method.cc
index b04dafbfa63..ccc054db498 100644
--- a/chromium/ui/views/ime/mock_input_method.cc
+++ b/chromium/ui/views/ime/mock_input_method.cc
@@ -22,7 +22,6 @@ MockInputMethod::MockInputMethod()
cancel_composition_called_(false),
input_locale_changed_(false),
locale_("en-US"),
- direction_(base::i18n::LEFT_TO_RIGHT),
active_(true) {
}
@@ -35,7 +34,6 @@ MockInputMethod::MockInputMethod(internal::InputMethodDelegate* delegate)
cancel_composition_called_(false),
input_locale_changed_(false),
locale_("en-US"),
- direction_(base::i18n::LEFT_TO_RIGHT),
active_(true) {
SetDelegate(delegate);
}
@@ -90,7 +88,7 @@ void MockInputMethod::DispatchKeyEvent(const ui::KeyEvent& key) {
client->ClearCompositionText();
}
} else if (key.type() == ui::ET_KEY_PRESSED) {
- char16 ch = key.GetCharacter();
+ base::char16 ch = key.GetCharacter();
client->InsertChar(ch, key.flags());
}
}
@@ -124,10 +122,6 @@ std::string MockInputMethod::GetInputLocale() {
return locale_;
}
-base::i18n::TextDirection MockInputMethod::GetInputTextDirection() {
- return direction_;
-}
-
bool MockInputMethod::IsActive() {
return active_;
}
@@ -136,6 +130,9 @@ bool MockInputMethod::IsCandidatePopupOpen() const {
return false;
}
+void MockInputMethod::ShowImeIfNeeded() {
+}
+
bool MockInputMethod::IsMock() const {
return true;
}
@@ -159,7 +156,7 @@ void MockInputMethod::SetCompositionTextForNextKey(
composition_ = composition;
}
-void MockInputMethod::SetResultTextForNextKey(const string16& result) {
+void MockInputMethod::SetResultTextForNextKey(const base::string16& result) {
result_text_ = result;
}
@@ -170,14 +167,6 @@ void MockInputMethod::SetInputLocale(const std::string& locale) {
}
}
-void MockInputMethod::SetInputTextDirection(
- base::i18n::TextDirection direction) {
- if (direction_ != direction) {
- direction_ = direction;
- OnInputMethodChanged();
- }
-}
-
void MockInputMethod::SetActive(bool active) {
if (active_ != active) {
active_ = active;
diff --git a/chromium/ui/views/ime/mock_input_method.h b/chromium/ui/views/ime/mock_input_method.h
index fad5315d5fb..013742cff1c 100644
--- a/chromium/ui/views/ime/mock_input_method.h
+++ b/chromium/ui/views/ime/mock_input_method.h
@@ -34,9 +34,9 @@ class VIEWS_EXPORT MockInputMethod : public InputMethodBase {
virtual void CancelComposition(View* view) OVERRIDE;
virtual void OnInputLocaleChanged() OVERRIDE;
virtual std::string GetInputLocale() OVERRIDE;
- virtual base::i18n::TextDirection GetInputTextDirection() OVERRIDE;
virtual bool IsActive() OVERRIDE;
virtual bool IsCandidatePopupOpen() const OVERRIDE;
+ virtual void ShowImeIfNeeded() OVERRIDE;
virtual bool IsMock() const OVERRIDE;
bool focus_changed() const { return focus_changed_; }
@@ -52,10 +52,9 @@ class VIEWS_EXPORT MockInputMethod : public InputMethodBase {
void Clear();
void SetCompositionTextForNextKey(const ui::CompositionText& composition);
- void SetResultTextForNextKey(const string16& result);
+ void SetResultTextForNextKey(const base::string16& result);
void SetInputLocale(const std::string& locale);
- void SetInputTextDirection(base::i18n::TextDirection direction);
void SetActive(bool active);
private:
@@ -75,7 +74,7 @@ class VIEWS_EXPORT MockInputMethod : public InputMethodBase {
// Result text for the next key event. It'll be cleared automatically after
// dispatching the next key event.
- string16 result_text_;
+ base::string16 result_text_;
// Record call state of corresponding methods. They will be set to false
// automatically before dispatching a key event.
@@ -88,7 +87,6 @@ class VIEWS_EXPORT MockInputMethod : public InputMethodBase {
// To mock corresponding input method prooperties.
std::string locale_;
- base::i18n::TextDirection direction_;
bool active_;
DISALLOW_COPY_AND_ASSIGN(MockInputMethod);
diff --git a/chromium/ui/views/ime/null_input_method.cc b/chromium/ui/views/ime/null_input_method.cc
new file mode 100644
index 00000000000..666d6cfba39
--- /dev/null
+++ b/chromium/ui/views/ime/null_input_method.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/ime/null_input_method.h"
+
+namespace views {
+
+NullInputMethod::NullInputMethod() {}
+
+void NullInputMethod::SetDelegate(
+ internal::InputMethodDelegate* /* delegate */) {}
+
+void NullInputMethod::Init(Widget* /* widget */) {}
+
+void NullInputMethod::OnFocus() {}
+
+void NullInputMethod::OnBlur() {}
+
+bool NullInputMethod::OnUntranslatedIMEMessage(
+ const base::NativeEvent& /* event */,
+ NativeEventResult* /* result */) {
+ return false;
+}
+
+void NullInputMethod::DispatchKeyEvent(const ui::KeyEvent& /* key */) {}
+
+void NullInputMethod::OnTextInputTypeChanged(View* /* view */) {}
+
+void NullInputMethod::OnCaretBoundsChanged(View* /* view */) {}
+
+void NullInputMethod::CancelComposition(View* /* view */) {}
+
+void NullInputMethod::OnInputLocaleChanged() {}
+
+std::string NullInputMethod::GetInputLocale() {
+ return std::string();
+}
+
+bool NullInputMethod::IsActive() {
+ return false;
+}
+
+ui::TextInputClient* NullInputMethod::GetTextInputClient() const {
+ return NULL;
+}
+
+ui::TextInputType NullInputMethod::GetTextInputType() const {
+ return ui::TEXT_INPUT_TYPE_NONE;
+}
+
+bool NullInputMethod::IsCandidatePopupOpen() const {
+ return false;
+}
+
+void NullInputMethod::ShowImeIfNeeded() {}
+
+bool NullInputMethod::IsMock() const {
+ return false;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/ime/null_input_method.h b/chromium/ui/views/ime/null_input_method.h
new file mode 100644
index 00000000000..49234d3d551
--- /dev/null
+++ b/chromium/ui/views/ime/null_input_method.h
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_IME_NULL_INPUT_METHOD_H_
+#define UI_VIEWS_IME_NULL_INPUT_METHOD_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "ui/views/ime/input_method.h"
+
+namespace views {
+
+// An implementation of views::InputMethod which does nothing.
+//
+// We're working on removing views::InputMethod{,Base,Bridge} and going to use
+// only ui::InputMethod. Use this class instead of views::InputMethodBridge
+// with ui::TextInputFocusManager to effectively eliminate the
+// views::InputMethod layer.
+class NullInputMethod : public InputMethod {
+ public:
+ NullInputMethod();
+
+ // Overridden from InputMethod:
+ virtual void SetDelegate(internal::InputMethodDelegate* delegate) OVERRIDE;
+ virtual void Init(Widget* widget) OVERRIDE;
+ virtual void OnFocus() OVERRIDE;
+ virtual void OnBlur() OVERRIDE;
+ virtual bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
+ NativeEventResult* result) OVERRIDE;
+ virtual void DispatchKeyEvent(const ui::KeyEvent& key) OVERRIDE;
+ virtual void OnTextInputTypeChanged(View* view) OVERRIDE;
+ virtual void OnCaretBoundsChanged(View* view) OVERRIDE;
+ virtual void CancelComposition(View* view) OVERRIDE;
+ virtual void OnInputLocaleChanged() OVERRIDE;
+ virtual std::string GetInputLocale() OVERRIDE;
+ virtual bool IsActive() OVERRIDE;
+ virtual ui::TextInputClient* GetTextInputClient() const OVERRIDE;
+ virtual ui::TextInputType GetTextInputType() const OVERRIDE;
+ virtual bool IsCandidatePopupOpen() const OVERRIDE;
+ virtual void ShowImeIfNeeded() OVERRIDE;
+ virtual bool IsMock() const OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NullInputMethod);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_IME_NULL_INPUT_METHOD_H_
diff --git a/chromium/ui/views/layout/box_layout.cc b/chromium/ui/views/layout/box_layout.cc
index c11479678a9..c33264c5eeb 100644
--- a/chromium/ui/views/layout/box_layout.cc
+++ b/chromium/ui/views/layout/box_layout.cc
@@ -19,7 +19,7 @@ BoxLayout::BoxLayout(BoxLayout::Orientation orientation,
inside_border_vertical_spacing,
inside_border_horizontal_spacing),
between_child_spacing_(between_child_spacing),
- spread_blank_space_(false) {
+ main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START) {
}
BoxLayout::~BoxLayout() {
@@ -29,38 +29,55 @@ void BoxLayout::Layout(View* host) {
gfx::Rect child_area(host->GetLocalBounds());
child_area.Inset(host->GetInsets());
child_area.Inset(inside_border_insets_);
- int x = child_area.x();
- int y = child_area.y();
int padding = 0;
- if (spread_blank_space_) {
- int total = 0;
- int visible = 0;
+ if (main_axis_alignment_ != MAIN_AXIS_ALIGNMENT_START) {
+ int total_main_axis_size = 0;
+ int num_visible = 0;
for (int i = 0; i < host->child_count(); ++i) {
View* child = host->child_at(i);
if (!child->visible())
continue;
if (orientation_ == kHorizontal) {
- total += child->GetPreferredSize().width() + between_child_spacing_;
+ total_main_axis_size +=
+ child->GetPreferredSize().width() + between_child_spacing_;
} else {
- total += child->GetHeightForWidth(child_area.width()) +
- between_child_spacing_;
+ total_main_axis_size += child->GetHeightForWidth(child_area.width()) +
+ between_child_spacing_;
}
- ++visible;
+ ++num_visible;
}
- if (visible) {
- total -= between_child_spacing_;
- if (orientation_ == kHorizontal)
- padding = (child_area.width() - total) / visible;
- else
- padding = (child_area.height() - total) / visible;
-
- if (padding < 0)
- padding = 0;
+ if (num_visible) {
+ total_main_axis_size -= between_child_spacing_;
+ int free_space = MainAxisSize(child_area) - total_main_axis_size;
+ int position = MainAxisPosition(child_area);
+ int size = MainAxisSize(child_area);
+ switch (main_axis_alignment_) {
+ case MAIN_AXIS_ALIGNMENT_FILL:
+ padding = std::max(free_space / num_visible, 0);
+ break;
+ case MAIN_AXIS_ALIGNMENT_CENTER:
+ position += free_space / 2;
+ size = total_main_axis_size;
+ break;
+ case MAIN_AXIS_ALIGNMENT_END:
+ position += free_space;
+ size = total_main_axis_size;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ gfx::Rect new_child_area(child_area);
+ SetMainAxisPosition(position, &new_child_area);
+ SetMainAxisSize(size, &new_child_area);
+ child_area.Intersect(new_child_area);
}
}
+ int x = child_area.x();
+ int y = child_area.y();
for (int i = 0; i < host->child_count(); ++i) {
View* child = host->child_at(i);
if (child->visible()) {
@@ -81,12 +98,12 @@ void BoxLayout::Layout(View* host) {
}
}
-gfx::Size BoxLayout::GetPreferredSize(View* host) {
+gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
// Calculate the child views' preferred width.
int width = 0;
if (orientation_ == kVertical) {
for (int i = 0; i < host->child_count(); ++i) {
- View* child = host->child_at(i);
+ const View* child = host->child_at(i);
if (!child->visible())
continue;
@@ -97,13 +114,35 @@ gfx::Size BoxLayout::GetPreferredSize(View* host) {
return GetPreferredSizeForChildWidth(host, width);
}
-int BoxLayout::GetPreferredHeightForWidth(View* host, int width) {
+int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const {
int child_width = width - NonChildSize(host).width();
return GetPreferredSizeForChildWidth(host, child_width).height();
}
-gfx::Size BoxLayout::GetPreferredSizeForChildWidth(View* host,
- int child_area_width) {
+int BoxLayout::MainAxisSize(const gfx::Rect& child_area) const {
+ return orientation_ == kHorizontal ? child_area.width() : child_area.height();
+}
+
+int BoxLayout::MainAxisPosition(const gfx::Rect& child_area) const {
+ return orientation_ == kHorizontal ? child_area.x() : child_area.y();
+}
+
+void BoxLayout::SetMainAxisSize(int size, gfx::Rect* child_area) const {
+ if (orientation_ == kHorizontal)
+ child_area->set_width(size);
+ else
+ child_area->set_height(size);
+}
+
+void BoxLayout::SetMainAxisPosition(int position, gfx::Rect* child_area) const {
+ if (orientation_ == kHorizontal)
+ child_area->set_x(position);
+ else
+ child_area->set_y(position);
+}
+
+gfx::Size BoxLayout::GetPreferredSizeForChildWidth(const View* host,
+ int child_area_width) const {
gfx::Rect child_area_bounds;
if (orientation_ == kHorizontal) {
@@ -112,7 +151,7 @@ gfx::Size BoxLayout::GetPreferredSizeForChildWidth(View* host,
// TODO(estade): fix this if it ever becomes a problem.
int position = 0;
for (int i = 0; i < host->child_count(); ++i) {
- View* child = host->child_at(i);
+ const View* child = host->child_at(i);
if (!child->visible())
continue;
@@ -127,7 +166,7 @@ gfx::Size BoxLayout::GetPreferredSizeForChildWidth(View* host,
} else {
int height = 0;
for (int i = 0; i < host->child_count(); ++i) {
- View* child = host->child_at(i);
+ const View* child = host->child_at(i);
if (!child->visible())
continue;
@@ -147,7 +186,7 @@ gfx::Size BoxLayout::GetPreferredSizeForChildWidth(View* host,
child_area_bounds.height() + non_child_size.height());
}
-gfx::Size BoxLayout::NonChildSize(View* host) {
+gfx::Size BoxLayout::NonChildSize(const View* host) const {
gfx::Insets insets(host->GetInsets());
return gfx::Size(insets.width() + inside_border_insets_.width(),
insets.height() + inside_border_insets_.height());
diff --git a/chromium/ui/views/layout/box_layout.h b/chromium/ui/views/layout/box_layout.h
index 7670d8cb05e..e1d22ac91a2 100644
--- a/chromium/ui/views/layout/box_layout.h
+++ b/chromium/ui/views/layout/box_layout.h
@@ -11,6 +11,7 @@
#include "ui/views/layout/layout_manager.h"
namespace gfx {
+class Rect;
class Size;
}
@@ -30,6 +31,25 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
kVertical,
};
+ // This specifies where along the main axis the children should be laid out.
+ // e.g. a horizontal layout of MAIN_AXIS_ALIGNMENT_END will result in the
+ // child views being right-aligned.
+ enum MainAxisAlignment {
+ MAIN_AXIS_ALIGNMENT_START,
+ MAIN_AXIS_ALIGNMENT_CENTER,
+ MAIN_AXIS_ALIGNMENT_END,
+
+ // This distributes extra space among the child views. This increases the
+ // size of child views along the main axis rather than the space between
+ // them.
+ MAIN_AXIS_ALIGNMENT_FILL,
+ // TODO(calamity): Add MAIN_AXIS_ALIGNMENT_JUSTIFY which spreads blank space
+ // in-between the child views.
+ };
+
+ // TODO(calamity): Add CrossAxisAlignment property to allow cross axis
+ // alignment.
+
// Use |inside_border_horizontal_spacing| and
// |inside_border_vertical_spacing| to add additional space between the child
// view area and the host view border. |between_child_spacing| controls the
@@ -40,22 +60,36 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
int between_child_spacing);
virtual ~BoxLayout();
- void set_spread_blank_space(bool spread) {
- spread_blank_space_ = spread;
+ void set_main_axis_alignment(MainAxisAlignment main_axis_alignment) {
+ main_axis_alignment_ = main_axis_alignment;
+ }
+
+ void set_inside_border_insets(const gfx::Insets& insets) {
+ inside_border_insets_ = insets;
}
// Overridden from views::LayoutManager:
virtual void Layout(View* host) OVERRIDE;
- virtual gfx::Size GetPreferredSize(View* host) OVERRIDE;
- virtual int GetPreferredHeightForWidth(View* host, int width) OVERRIDE;
+ virtual gfx::Size GetPreferredSize(const View* host) const OVERRIDE;
+ virtual int GetPreferredHeightForWidth(const View* host,
+ int width) const OVERRIDE;
private:
+ // Returns the size and position along the main axis of |child_area|.
+ int MainAxisSize(const gfx::Rect& child_area) const;
+ int MainAxisPosition(const gfx::Rect& child_area) const;
+
+ // Sets the size and position along the main axis of |child_area|.
+ void SetMainAxisSize(int size, gfx::Rect* child_area) const;
+ void SetMainAxisPosition(int position, gfx::Rect* child_area) const;
+
// The preferred size for the dialog given the width of the child area.
- gfx::Size GetPreferredSizeForChildWidth(View* host, int child_area_width);
+ gfx::Size GetPreferredSizeForChildWidth(const View* host,
+ int child_area_width) const;
// The amount of space the layout requires in addition to any space for the
// child views.
- gfx::Size NonChildSize(View* host);
+ gfx::Size NonChildSize(const View* host) const;
const Orientation orientation_;
@@ -65,9 +99,9 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// Spacing to put in between child views.
const int between_child_spacing_;
- // Whether the available extra space should be distributed among the child
- // views.
- bool spread_blank_space_;
+ // The alignment of children in the main axis. This is
+ // MAIN_AXIS_ALIGNMENT_START by default.
+ MainAxisAlignment main_axis_alignment_;
DISALLOW_IMPLICIT_CONSTRUCTORS(BoxLayout);
};
diff --git a/chromium/ui/views/layout/box_layout_unittest.cc b/chromium/ui/views/layout/box_layout_unittest.cc
index 2c12090685e..42f8f4272c6 100644
--- a/chromium/ui/views/layout/box_layout_unittest.cc
+++ b/chromium/ui/views/layout/box_layout_unittest.cc
@@ -55,6 +55,27 @@ TEST_F(BoxLayoutTest, AlignmentVertical) {
EXPECT_EQ(gfx::Rect(0, 10, 20, 10), v2->bounds());
}
+TEST_F(BoxLayoutTest, SetInsideBorderInsets) {
+ layout_.reset(new BoxLayout(BoxLayout::kHorizontal, 10, 20, 0));
+ View* v1 = new StaticSizedView(gfx::Size(10, 20));
+ host_->AddChildView(v1);
+ View* v2 = new StaticSizedView(gfx::Size(10, 10));
+ host_->AddChildView(v2);
+ EXPECT_EQ(gfx::Size(40, 60), layout_->GetPreferredSize(host_.get()));
+ host_->SetBounds(0, 0, 40, 60);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 20, 10, 20), v1->bounds());
+ EXPECT_EQ(gfx::Rect(20, 20, 10, 20), v2->bounds());
+
+ layout_->set_inside_border_insets(
+ gfx::Insets(5, 10, 15, 20));
+ EXPECT_EQ(gfx::Size(50, 40), layout_->GetPreferredSize(host_.get()));
+ host_->SetBounds(0, 0, 50, 40);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 5, 10, 20), v1->bounds());
+ EXPECT_EQ(gfx::Rect(20, 5, 10, 20), v2->bounds());
+}
+
TEST_F(BoxLayoutTest, Spacing) {
layout_.reset(new BoxLayout(BoxLayout::kHorizontal, 7, 7, 8));
View* v1 = new StaticSizedView(gfx::Size(10, 20));
@@ -75,6 +96,25 @@ TEST_F(BoxLayoutTest, Overflow) {
View* v2 = new StaticSizedView(gfx::Size(10, 20));
host_->AddChildView(v2);
host_->SetBounds(0, 0, 10, 10);
+
+ // Overflows by positioning views at the start and truncating anything that
+ // doesn't fit.
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
+
+ // All values of main axis alignment should overflow in the same manner.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
+
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
+
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_END);
layout_->Layout(host_.get());
EXPECT_EQ(gfx::Rect(0, 0, 10, 10), v1->bounds());
EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
@@ -102,9 +142,9 @@ TEST_F(BoxLayoutTest, InvisibleChild) {
EXPECT_EQ(gfx::Rect(10, 10, 10, 10), v2->bounds());
}
-TEST_F(BoxLayoutTest, DistributeEmptySpace) {
+TEST_F(BoxLayoutTest, MainAxisAlignmentFill) {
layout_.reset(new BoxLayout(BoxLayout::kHorizontal, 10, 10, 10));
- layout_->set_spread_blank_space(true);
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_FILL);
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -156,4 +196,74 @@ TEST_F(BoxLayoutTest, EmptyPreferredSize) {
}
}
+TEST_F(BoxLayoutTest, MainAxisAlignmentHorizontal) {
+ layout_.reset(new BoxLayout(BoxLayout::kHorizontal, 10, 10, 10));
+
+ View* v1 = new StaticSizedView(gfx::Size(20, 20));
+ host_->AddChildView(v1);
+ View* v2 = new StaticSizedView(gfx::Size(10, 10));
+ host_->AddChildView(v2);
+
+ host_->SetBounds(0, 0, 100, 40);
+
+ // Align children to the horizontal start by default.
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(40, 10, 10, 20).ToString(), v2->bounds().ToString());
+
+ // Ensure same results for MAIN_AXIS_ALIGNMENT_START.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(40, 10, 10, 20).ToString(), v2->bounds().ToString());
+
+ // Aligns children to the center horizontally.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(30, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(60, 10, 10, 20).ToString(), v2->bounds().ToString());
+
+ // Aligns children to the end of the host horizontally, accounting for the
+ // inside border spacing.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_END);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(50, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(80, 10, 10, 20).ToString(), v2->bounds().ToString());
+}
+
+TEST_F(BoxLayoutTest, MainAxisAlignmentVertical) {
+ layout_.reset(new BoxLayout(BoxLayout::kVertical, 10, 10, 10));
+
+ View* v1 = new StaticSizedView(gfx::Size(20, 20));
+ host_->AddChildView(v1);
+ View* v2 = new StaticSizedView(gfx::Size(10, 10));
+ host_->AddChildView(v2);
+
+ host_->SetBounds(0, 0, 40, 100);
+
+ // Align children to the vertical start by default.
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(10, 40, 20, 10).ToString(), v2->bounds().ToString());
+
+ // Ensure same results for MAIN_AXIS_ALIGNMENT_START.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(10, 40, 20, 10).ToString(), v2->bounds().ToString());
+
+ // Aligns children to the center vertically.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 30, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(10, 60, 20, 10).ToString(), v2->bounds().ToString());
+
+ // Aligns children to the end of the host vertically, accounting for the
+ // inside border spacing.
+ layout_->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_END);
+ layout_->Layout(host_.get());
+ EXPECT_EQ(gfx::Rect(10, 50, 20, 20).ToString(), v1->bounds().ToString());
+ EXPECT_EQ(gfx::Rect(10, 80, 20, 10).ToString(), v2->bounds().ToString());
+}
+
} // namespace views
diff --git a/chromium/ui/views/layout/fill_layout.cc b/chromium/ui/views/layout/fill_layout.cc
index 54893671f58..21375461210 100644
--- a/chromium/ui/views/layout/fill_layout.cc
+++ b/chromium/ui/views/layout/fill_layout.cc
@@ -20,7 +20,7 @@ void FillLayout::Layout(View* host) {
frame_view->SetBoundsRect(host->GetContentsBounds());
}
-gfx::Size FillLayout::GetPreferredSize(View* host) {
+gfx::Size FillLayout::GetPreferredSize(const View* host) const {
if (!host->has_children())
return gfx::Size();
DCHECK_EQ(1, host->child_count());
@@ -29,7 +29,7 @@ gfx::Size FillLayout::GetPreferredSize(View* host) {
return rect.size();
}
-int FillLayout::GetPreferredHeightForWidth(View* host, int width) {
+int FillLayout::GetPreferredHeightForWidth(const View* host, int width) const {
if (!host->has_children())
return 0;
DCHECK_EQ(1, host->child_count());
diff --git a/chromium/ui/views/layout/fill_layout.h b/chromium/ui/views/layout/fill_layout.h
index 67c7f831457..f50bde0c6c7 100644
--- a/chromium/ui/views/layout/fill_layout.h
+++ b/chromium/ui/views/layout/fill_layout.h
@@ -25,8 +25,9 @@ class VIEWS_EXPORT FillLayout : public LayoutManager {
// Overridden from LayoutManager:
virtual void Layout(View* host) OVERRIDE;
- virtual gfx::Size GetPreferredSize(View* host) OVERRIDE;
- virtual int GetPreferredHeightForWidth(View* host, int width) OVERRIDE;
+ virtual gfx::Size GetPreferredSize(const View* host) const OVERRIDE;
+ virtual int GetPreferredHeightForWidth(const View* host,
+ int width) const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(FillLayout);
diff --git a/chromium/ui/views/layout/grid_layout.cc b/chromium/ui/views/layout/grid_layout.cc
index e4bf19d47c8..7ab81083c34 100644
--- a/chromium/ui/views/layout/grid_layout.cc
+++ b/chromium/ui/views/layout/grid_layout.cc
@@ -57,7 +57,8 @@ class LayoutElement {
for (typename std::vector<T*>::iterator i = elements->begin();
i != elements->end(); ++i) {
total_percent += (*i)->ResizePercent();
- resize_count++;
+ if ((*i)->ResizePercent() > 0)
+ resize_count++;
}
if (total_percent == 0) {
// None of the elements are resizable, return.
@@ -161,7 +162,6 @@ class Column : public LayoutElement {
GridLayout::SizeType size_type,
int fixed_width,
int min_width,
- size_t index,
bool is_padding)
: LayoutElement(resize_percent),
h_align_(h_align),
@@ -170,7 +170,6 @@ class Column : public LayoutElement {
same_size_column_(-1),
fixed_width_(fixed_width),
min_width_(min_width),
- index_(index),
is_padding_(is_padding),
master_column_(NULL) {}
@@ -200,9 +199,6 @@ class Column : public LayoutElement {
const int fixed_width_;
const int min_width_;
- // Index of this column in the ColumnSet.
- const size_t index_;
-
const bool is_padding_;
// If multiple columns have their sizes linked, one is the
@@ -263,10 +259,8 @@ void Column::AdjustSize(int size) {
class Row : public LayoutElement {
public:
- Row(bool fixed_height, int height, float resize_percent,
- ColumnSet* column_set)
+ Row(int height, float resize_percent, ColumnSet* column_set)
: LayoutElement(resize_percent),
- fixed_height_(fixed_height),
height_(height),
column_set_(column_set),
max_ascent_(0),
@@ -300,7 +294,6 @@ class Row : public LayoutElement {
}
private:
- const bool fixed_height_;
const int height_;
// The column set used for this row; null for padding rows.
ColumnSet* column_set_;
@@ -421,17 +414,16 @@ void ColumnSet::AddColumn(GridLayout::Alignment h_align,
int min_width,
bool is_padding) {
Column* column = new Column(h_align, v_align, resize_percent, size_type,
- fixed_width, min_width, columns_.size(),
- is_padding);
+ fixed_width, min_width, is_padding);
columns_.push_back(column);
}
void ColumnSet::AddViewState(ViewState* view_state) {
// view_states are ordered by column_span (in ascending order).
- std::vector<ViewState*>::iterator i = lower_bound(view_states_.begin(),
- view_states_.end(),
- view_state,
- CompareByColumnSpan);
+ std::vector<ViewState*>::iterator i = std::lower_bound(view_states_.begin(),
+ view_states_.end(),
+ view_state,
+ CompareByColumnSpan);
view_states_.insert(i, view_state);
}
@@ -503,8 +495,8 @@ void ColumnSet::AccumulateMasterColumns() {
Column* column = *i;
Column* master_column = column->GetLastMasterColumn();
if (master_column &&
- find(master_columns_.begin(), master_columns_.end(),
- master_column) == master_columns_.end()) {
+ std::find(master_columns_.begin(), master_columns_.end(),
+ master_column) == master_columns_.end()) {
master_columns_.push_back(master_column);
}
// At this point, GetLastMasterColumn may not == master_column
@@ -717,11 +709,11 @@ void GridLayout::StartRowWithPadding(float vertical_resize, int column_set_id,
void GridLayout::StartRow(float vertical_resize, int column_set_id) {
ColumnSet* column_set = GetColumnSet(column_set_id);
DCHECK(column_set);
- AddRow(new Row(false, 0, vertical_resize, column_set));
+ AddRow(new Row(0, vertical_resize, column_set));
}
void GridLayout::AddPaddingRow(float vertical_resize, int pixel_count) {
- AddRow(new Row(true, pixel_count, vertical_resize, NULL));
+ AddRow(new Row(pixel_count, vertical_resize, NULL));
}
void GridLayout::SkipColumns(int col_count) {
@@ -836,7 +828,7 @@ void GridLayout::Layout(View* host) {
}
}
-gfx::Size GridLayout::GetPreferredSize(View* host) {
+gfx::Size GridLayout::GetPreferredSize(const View* host) const {
DCHECK(host_ == host);
gfx::Size out;
SizeRowsAndColumns(false, 0, 0, &out);
@@ -845,7 +837,7 @@ gfx::Size GridLayout::GetPreferredSize(View* host) {
return out;
}
-int GridLayout::GetPreferredHeightForWidth(View* host, int width) {
+int GridLayout::GetPreferredHeightForWidth(const View* host, int width) const {
DCHECK(host_ == host);
gfx::Size pref;
SizeRowsAndColumns(false, width, 0, &pref);
@@ -853,7 +845,7 @@ int GridLayout::GetPreferredHeightForWidth(View* host, int width) {
}
void GridLayout::SizeRowsAndColumns(bool layout, int width, int height,
- gfx::Size* pref) {
+ gfx::Size* pref) const {
// Make sure the master columns have been calculated.
CalculateMasterColumnsIfNecessary();
pref->SetSize(0, 0);
@@ -958,7 +950,7 @@ void GridLayout::SizeRowsAndColumns(bool layout, int width, int height,
}
}
-void GridLayout::CalculateMasterColumnsIfNecessary() {
+void GridLayout::CalculateMasterColumnsIfNecessary() const {
if (!calculated_master_columns_) {
calculated_master_columns_ = true;
for (std::vector<ColumnSet*>::iterator i = column_sets_.begin();
@@ -980,10 +972,10 @@ void GridLayout::AddViewState(ViewState* view_state) {
next_column_ += view_state->col_span;
current_row_col_set_->AddViewState(view_state);
// view_states are ordered by row_span (in ascending order).
- std::vector<ViewState*>::iterator i = lower_bound(view_states_.begin(),
- view_states_.end(),
- view_state,
- CompareByRowSpan);
+ std::vector<ViewState*>::iterator i = std::lower_bound(view_states_.begin(),
+ view_states_.end(),
+ view_state,
+ CompareByRowSpan);
view_states_.insert(i, view_state);
SkipPaddingColumns();
}
@@ -1003,14 +995,14 @@ void GridLayout::AddRow(Row* row) {
SkipPaddingColumns();
}
-void GridLayout::UpdateRemainingHeightFromRows(ViewState* view_state) {
+void GridLayout::UpdateRemainingHeightFromRows(ViewState* view_state) const {
for (int i = 0, start_row = view_state->start_row;
i < view_state->row_span; ++i) {
view_state->remaining_height -= rows_[i + start_row]->Size();
}
}
-void GridLayout::DistributeRemainingHeight(ViewState* view_state) {
+void GridLayout::DistributeRemainingHeight(ViewState* view_state) const {
int height = view_state->remaining_height;
if (height <= 0)
return;
diff --git a/chromium/ui/views/layout/grid_layout.h b/chromium/ui/views/layout/grid_layout.h
index f026eb7915f..ea578c8ad57 100644
--- a/chromium/ui/views/layout/grid_layout.h
+++ b/chromium/ui/views/layout/grid_layout.h
@@ -178,9 +178,10 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
virtual void Layout(View* host) OVERRIDE;
// Returns the preferred size for the GridLayout.
- virtual gfx::Size GetPreferredSize(View* host) OVERRIDE;
+ virtual gfx::Size GetPreferredSize(const View* host) const OVERRIDE;
- virtual int GetPreferredHeightForWidth(View* host, int width) OVERRIDE;
+ virtual int GetPreferredHeightForWidth(const View* host,
+ int width) const OVERRIDE;
void set_minimum_size(const gfx::Size& size) { minimum_size_ = size; }
@@ -189,11 +190,14 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
// they both call into this method. This sizes the Columns/Rows as
// appropriate. If layout is true, width/height give the width/height the
// of the host, otherwise they are ignored.
- void SizeRowsAndColumns(bool layout, int width, int height, gfx::Size* pref);
+ void SizeRowsAndColumns(bool layout,
+ int width,
+ int height,
+ gfx::Size* pref) const;
// Calculates the master columns of all the column sets. See Column for
// a description of what a master column is.
- void CalculateMasterColumnsIfNecessary();
+ 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_.
@@ -205,12 +209,12 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
// As the name says, updates the remaining_height of the ViewState for
// all Rows the supplied ViewState touches.
- void UpdateRemainingHeightFromRows(ViewState* state);
+ void UpdateRemainingHeightFromRows(ViewState* state) const;
// If the view state's remaining height is > 0, it is distributed among
// the rows the view state touches. This is used during layout to make
// sure the Rows can accommodate a view.
- void DistributeRemainingHeight(ViewState* state);
+ void DistributeRemainingHeight(ViewState* state) const;
// Advances next_column_ past any padding columns.
void SkipPaddingColumns();
@@ -222,7 +226,7 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
View* const host_;
// Whether or not we've calculated the master/linked columns.
- bool calculated_master_columns_;
+ mutable bool calculated_master_columns_;
// Used to verify a view isn't added with a row span that expands into
// another column structure.
@@ -244,13 +248,13 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
bool adding_view_;
// ViewStates. This is ordered by row_span in ascending order.
- std::vector<ViewState*> view_states_;
+ mutable std::vector<ViewState*> view_states_;
// ColumnSets.
- std::vector<ColumnSet*> column_sets_;
+ mutable std::vector<ColumnSet*> column_sets_;
// Rows.
- std::vector<Row*> rows_;
+ mutable std::vector<Row*> rows_;
// Minimum preferred size.
gfx::Size minimum_size_;
@@ -267,10 +271,11 @@ class VIEWS_EXPORT ColumnSet {
// Adds a column for padding. When adding views, padding columns are
// automatically skipped. For example, if you create a column set with
- // two columns separated by a padding column, the first AddView automatically
+ // two columns separated by a padding column, the second AddView automatically
// skips past the padding column. That is, to add two views, do:
// layout->AddView(v1); layout->AddView(v2);, not:
// layout->AddView(v1); layout->SkipColumns(1); layout->AddView(v2);
+ // See class description for details on |resize_percent|.
void AddPaddingColumn(float resize_percent, int width);
// Adds a column. The alignment gives the default alignment for views added
@@ -282,6 +287,7 @@ class VIEWS_EXPORT ColumnSet {
// made as wide as the widest views in each column, even if extra space is
// provided. In other words, GridLayout does not automatically resize views
// unless the column is marked as resizable.
+ // See class description for details on |resize_percent|.
void AddColumn(GridLayout::Alignment h_align,
GridLayout::Alignment v_align,
float resize_percent,
diff --git a/chromium/ui/views/layout/grid_layout_unittest.cc b/chromium/ui/views/layout/grid_layout_unittest.cc
index 71988d870b6..ea7d231f04b 100644
--- a/chromium/ui/views/layout/grid_layout_unittest.cc
+++ b/chromium/ui/views/layout/grid_layout_unittest.cc
@@ -24,7 +24,7 @@ class SettableSizeView : public View {
pref_ = pref;
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return pref_;
}
@@ -39,11 +39,11 @@ class FlexibleView : public View {
circumference_ = circumference;
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
return gfx::Size(0, circumference_ / 2);
}
- virtual int GetHeightForWidth(int width) OVERRIDE {
+ virtual int GetHeightForWidth(int width) const OVERRIDE {
return std::max(0, circumference_ / 2 - width);
}
@@ -346,6 +346,33 @@ TEST_F(GridLayoutTest, HorizontalResizeTest2) {
RemoveAll();
}
+// Tests that space leftover due to rounding is distributed to the last
+// resizable column.
+TEST_F(GridLayoutTest, HorizontalResizeTest3) {
+ SettableSizeView v1(gfx::Size(10, 10));
+ SettableSizeView v2(gfx::Size(10, 10));
+ SettableSizeView v3(gfx::Size(10, 10));
+ ColumnSet* c1 = layout.AddColumnSet(0);
+ c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
+ 1, GridLayout::USE_PREF, 0, 0);
+ c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
+ 1, GridLayout::USE_PREF, 0, 0);
+ 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);
+
+ RemoveAll();
+}
+
TEST_F(GridLayoutTest, TestVerticalResize1) {
SettableSizeView v1(gfx::Size(50, 20));
SettableSizeView v2(gfx::Size(10, 10));
diff --git a/chromium/ui/views/layout/layout_manager.cc b/chromium/ui/views/layout/layout_manager.cc
index 188cc6f14fc..9a79ce75832 100644
--- a/chromium/ui/views/layout/layout_manager.cc
+++ b/chromium/ui/views/layout/layout_manager.cc
@@ -17,7 +17,8 @@ void LayoutManager::Installed(View* host) {
void LayoutManager::Uninstalled(View* host) {
}
-int LayoutManager::GetPreferredHeightForWidth(View* host, int width) {
+int LayoutManager::GetPreferredHeightForWidth(const View* host,
+ int width) const {
return GetPreferredSize(host).height();
}
diff --git a/chromium/ui/views/layout/layout_manager.h b/chromium/ui/views/layout/layout_manager.h
index f678e721179..d10e09ed381 100644
--- a/chromium/ui/views/layout/layout_manager.h
+++ b/chromium/ui/views/layout/layout_manager.h
@@ -42,11 +42,11 @@ class VIEWS_EXPORT LayoutManager {
// Return the preferred size which is the size required to give each
// children their respective preferred size.
- virtual gfx::Size GetPreferredSize(View* host) = 0;
+ virtual gfx::Size GetPreferredSize(const View* host) const = 0;
// Returns the preferred height for the specified width. The default
// implementation returns the value from GetPreferredSize.
- virtual int GetPreferredHeightForWidth(View* host, int width);
+ virtual int GetPreferredHeightForWidth(const View* host, int width) const;
// Notification that a view has been added.
virtual void ViewAdded(View* host, View* view);
diff --git a/chromium/ui/views/linux_ui/linux_ui.cc b/chromium/ui/views/linux_ui/linux_ui.cc
index 6a35040f4f8..63c74020c19 100644
--- a/chromium/ui/views/linux_ui/linux_ui.cc
+++ b/chromium/ui/views/linux_ui/linux_ui.cc
@@ -5,6 +5,7 @@
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
+#include "ui/gfx/linux_font_delegate.h"
#include "ui/shell_dialogs/linux_shell_dialog.h"
namespace {
@@ -19,7 +20,9 @@ void LinuxUI::SetInstance(LinuxUI* instance) {
delete g_linux_ui;
g_linux_ui = instance;
LinuxInputMethodContextFactory::SetInstance(instance);
+ LinuxFontDelegate::SetInstance(instance);
LinuxShellDialog::SetInstance(instance);
+ ui::SetTextEditKeyBindingsDelegate(instance);
}
LinuxUI* LinuxUI::instance() {
diff --git a/chromium/ui/views/linux_ui/linux_ui.gyp b/chromium/ui/views/linux_ui/linux_ui.gyp
index 1f87a1a01ee..5ba78e52baf 100644
--- a/chromium/ui/views/linux_ui/linux_ui.gyp
+++ b/chromium/ui/views/linux_ui/linux_ui.gyp
@@ -14,9 +14,9 @@
'../../base/base.gyp:base',
'../../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../../skia/skia.gyp:skia',
+ '../base/ui_base.gyp:ui_base',
'../native_theme/native_theme.gyp:native_theme',
'../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
],
'defines': [
'LINUX_UI_IMPLEMENTATION',
diff --git a/chromium/ui/views/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h
index 152b364282d..b5466f57ef5 100644
--- a/chromium/ui/views/linux_ui/linux_ui.h
+++ b/chromium/ui/views/linux_ui/linux_ui.h
@@ -5,15 +5,25 @@
#ifndef UI_VIEWS_LINUX_UI_LINUX_UI_H_
#define UI_VIEWS_LINUX_UI_LINUX_UI_H_
+#include <string>
+
+#include "base/callback.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
+#include "ui/events/linux/text_edit_key_bindings_delegate_auralinux.h"
+#include "ui/gfx/linux_font_delegate.h"
#include "ui/shell_dialogs/linux_shell_dialog.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/linux_ui/status_icon_linux.h"
#include "ui/views/views_export.h"
// The main entrypoint into Linux toolkit specific code. GTK code should only
// be executed behind this interface.
+namespace aura {
+class Window;
+}
+
namespace gfx {
class Image;
}
@@ -23,6 +33,10 @@ class NativeTheme;
}
namespace views {
+class Border;
+class LabelButton;
+class LabelButtonBorder;
+class View;
class WindowButtonOrderObserver;
// Adapter class with targets to render like different toolkits. Set by any
@@ -33,8 +47,22 @@ class WindowButtonOrderObserver;
// complex method that pokes around with dlopen against a libuigtk2.so, a
// liuigtk3.so, etc.
class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
- public ui::LinuxShellDialog {
+ public gfx::LinuxFontDelegate,
+ public ui::LinuxShellDialog,
+ public ui::TextEditKeyBindingsDelegateAuraLinux {
public:
+ // Describes the window management actions that could be taken in response to
+ // a middle click in the non client area.
+ enum NonClientMiddleClickAction {
+ MIDDLE_CLICK_ACTION_NONE,
+ MIDDLE_CLICK_ACTION_LOWER,
+ MIDDLE_CLICK_ACTION_MINIMIZE,
+ MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE
+ };
+
+ typedef base::Callback<ui::NativeTheme*(aura::Window* window)>
+ NativeThemeGetter;
+
virtual ~LinuxUI() {}
// Sets the dynamically loaded singleton that draws the desktop native UI.
@@ -67,9 +95,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
// Returns a NativeTheme that will provide system colors and draw system
// style widgets.
- virtual ui::NativeTheme* GetNativeTheme() const = 0;
+ virtual ui::NativeTheme* GetNativeTheme(aura::Window* window) const = 0;
- virtual void SetUseSystemTheme(bool use_system_theme) = 0;
+ // Used to set an override NativeTheme.
+ virtual void SetNativeThemeOverride(const NativeThemeGetter& callback) = 0;
// Returns whether we should be using the native theme provided by this
// object by default.
@@ -86,7 +115,7 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
// Create a native status icon.
virtual scoped_ptr<StatusIconLinux> CreateLinuxStatusIcon(
const gfx::ImageSkia& image,
- const string16& tool_tip) const = 0;
+ const base::string16& tool_tip) const = 0;
// Returns the icon for a given content type from the icon theme.
// TODO(davidben): Add an observer for the theme changing, so we can drop the
@@ -94,6 +123,11 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
virtual gfx::Image GetIconForContentType(
const std::string& content_type, int size) const = 0;
+ // Builds a Border which paints the native button style.
+ virtual scoped_ptr<Border> CreateNativeBorder(
+ views::LabelButton* owning_button,
+ scoped_ptr<views::LabelButtonBorder> border) = 0;
+
// Notifies the observer about changes about how window buttons should be
// laid out. If the order is anything other than the default min,max,close on
// the right, will immediately send a button change event to the observer.
@@ -106,6 +140,16 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
// Determines whether the user's window manager is Unity.
virtual bool UnityIsRunning() = 0;
+
+ // What action we should take when the user middle clicks on non-client
+ // area. The default is lowering the window.
+ virtual NonClientMiddleClickAction GetNonClientMiddleClickAction() = 0;
+
+ // Notifies the window manager that start up has completed.
+ // Normally Chromium opens a new window on startup and GTK does this
+ // automatically. In case Chromium does not open a new window on startup,
+ // e.g. an existing browser window already exists, this should be called.
+ virtual void NotifyWindowManagerStartupComplete() = 0;
};
} // 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 5ed8be21a7e..b7ed3c72295 100644
--- a/chromium/ui/views/linux_ui/status_icon_linux.h
+++ b/chromium/ui/views/linux_ui/status_icon_linux.h
@@ -38,7 +38,7 @@ class VIEWS_EXPORT StatusIconLinux {
virtual void SetImage(const gfx::ImageSkia& image) = 0;
virtual void SetPressedImage(const gfx::ImageSkia& image) = 0;
- virtual void SetToolTip(const string16& tool_tip) = 0;
+ virtual void SetToolTip(const base::string16& tool_tip) = 0;
// Invoked after a call to SetContextMenu() to let the platform-specific
// subclass update the native context menu based on the new model. The
diff --git a/chromium/ui/views/linux_ui/window_button_order_provider.cc b/chromium/ui/views/linux_ui/window_button_order_provider.cc
new file mode 100644
index 00000000000..903247883b8
--- /dev/null
+++ b/chromium/ui/views/linux_ui/window_button_order_provider.cc
@@ -0,0 +1,83 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/window/window_button_order_provider.h"
+
+#include "ui/views/linux_ui/linux_ui.h"
+#include "ui/views/linux_ui/window_button_order_observer.h"
+
+namespace views {
+
+namespace {
+
+class WindowButtonOrderObserverDelegate : public WindowButtonOrderProvider,
+ public WindowButtonOrderObserver {
+ public:
+ WindowButtonOrderObserverDelegate();
+ virtual ~WindowButtonOrderObserverDelegate();
+
+ // WindowButtonOrderObserver:
+ virtual void OnWindowButtonOrderingChange(
+ const std::vector<views::FrameButton>& leading_buttons,
+ const std::vector<views::FrameButton>& trailing_buttons) OVERRIDE;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowButtonOrderObserverDelegate);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowButtonOrderObserverDelegate, public:
+
+WindowButtonOrderObserverDelegate::WindowButtonOrderObserverDelegate() {
+ views::LinuxUI* ui = views::LinuxUI::instance();
+ if (ui)
+ ui->AddWindowButtonOrderObserver(this);
+}
+
+WindowButtonOrderObserverDelegate::~WindowButtonOrderObserverDelegate() {
+ views::LinuxUI* ui = views::LinuxUI::instance();
+ if (ui)
+ ui->RemoveWindowButtonOrderObserver(this);
+}
+
+void WindowButtonOrderObserverDelegate::OnWindowButtonOrderingChange(
+ const std::vector<views::FrameButton>& leading_buttons,
+ const std::vector<views::FrameButton>& trailing_buttons) {
+ SetWindowButtonOrder(leading_buttons, trailing_buttons);
+}
+
+} // namespace
+
+// static
+WindowButtonOrderProvider* WindowButtonOrderProvider::instance_ = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowButtonOrderProvider, public:
+
+// static
+WindowButtonOrderProvider* WindowButtonOrderProvider::GetInstance() {
+ if (!instance_)
+ instance_ = new WindowButtonOrderObserverDelegate;
+ return instance_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowButtonOrderProvider, protected:
+
+WindowButtonOrderProvider::WindowButtonOrderProvider() {
+ trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE);
+ trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE);
+ trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE);
+}
+
+WindowButtonOrderProvider::~WindowButtonOrderProvider() {
+}
+
+void WindowButtonOrderProvider::SetWindowButtonOrder(
+ const std::vector<views::FrameButton>& leading_buttons,
+ const std::vector<views::FrameButton>& trailing_buttons) {
+ leading_buttons_ = leading_buttons;
+ trailing_buttons_ = trailing_buttons;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/masked_view_targeter.cc b/chromium/ui/views/masked_view_targeter.cc
new file mode 100644
index 00000000000..112df676808
--- /dev/null
+++ b/chromium/ui/views/masked_view_targeter.cc
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/masked_view_targeter.h"
+
+#include "ui/gfx/path.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+MaskedViewTargeter::MaskedViewTargeter(View* masked_view)
+ : masked_view_(masked_view) {
+}
+
+MaskedViewTargeter::~MaskedViewTargeter() {
+}
+
+bool MaskedViewTargeter::EventLocationInsideBounds(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const {
+ View* view = static_cast<View*>(target);
+ if (view == masked_view_) {
+ gfx::Path mask;
+ if (!GetHitTestMask(view, &mask))
+ return ViewTargeter::EventLocationInsideBounds(view, event);
+
+ gfx::Size size = view->bounds().size();
+ SkRegion clip_region;
+ clip_region.setRect(0, 0, size.width(), size.height());
+
+ gfx::RectF bounds_f = ViewTargeter::BoundsForEvent(event);
+ if (view->parent())
+ View::ConvertRectToTarget(view->parent(), view, &bounds_f);
+ gfx::Rect bounds = gfx::ToEnclosingRect(bounds_f);
+
+ SkRegion mask_region;
+ return mask_region.setPath(mask, clip_region) &&
+ mask_region.intersects(RectToSkIRect(bounds));
+ }
+
+ return ViewTargeter::EventLocationInsideBounds(view, event);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/masked_view_targeter.h b/chromium/ui/views/masked_view_targeter.h
new file mode 100644
index 00000000000..df155b915de
--- /dev/null
+++ b/chromium/ui/views/masked_view_targeter.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_MASKED_VIEW_TARGETER_H_
+#define UI_VIEWS_MASKED_VIEW_TARGETER_H_
+
+#include "ui/views/view_targeter.h"
+#include "ui/views/views_export.h"
+
+namespace gfx {
+class Path;
+}
+
+namespace views {
+
+// Derived classes of MaskedViewTargeter are used to define custom-shaped
+// hit test regions for a View used in event targeting.
+// TODO(tdanderson|sadrul): Some refactoring opportunities may be possible
+// between this class and MaskedWindowTargeter.
+class VIEWS_EXPORT MaskedViewTargeter : public ViewTargeter {
+ public:
+ explicit MaskedViewTargeter(View* masked_view);
+ virtual ~MaskedViewTargeter();
+
+ // Sets the hit-test mask for |view| in |mask| (in |view|'s local
+ // coordinate system). Returns whether a valid mask has been set in |mask|.
+ virtual bool GetHitTestMask(const View* view, gfx::Path* mask) const = 0;
+
+ protected:
+ const View* masked_view() const { return masked_view_; }
+
+ // ui::EventTargeter:
+ virtual bool EventLocationInsideBounds(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const OVERRIDE;
+
+ private:
+ View* masked_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(MaskedViewTargeter);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_MASKED_VIEW_TARGETER_H_
diff --git a/chromium/ui/views/metrics_aura.cc b/chromium/ui/views/metrics_aura.cc
index 03aa832f01e..046baa892ca 100644
--- a/chromium/ui/views/metrics_aura.cc
+++ b/chromium/ui/views/metrics_aura.cc
@@ -11,7 +11,6 @@
namespace {
// Default double click interval in milliseconds.
-// Same as what gtk uses.
const int kDefaultDoubleClickInterval = 500;
} // namespace
diff --git a/chromium/ui/views/metrics_mac.cc b/chromium/ui/views/metrics_mac.cc
new file mode 100644
index 00000000000..3a399d19463
--- /dev/null
+++ b/chromium/ui/views/metrics_mac.cc
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/metrics.h"
+
+namespace {
+
+// Default double click interval in milliseconds.
+// Same as what gtk uses.
+const int kDefaultDoubleClickInterval = 500;
+
+} // namespace
+
+namespace views {
+
+int GetDoubleClickInterval() {
+ return kDefaultDoubleClickInterval;
+}
+
+int GetMenuShowDelay() {
+ return 0;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/metrics_win.cc b/chromium/ui/views/metrics_win.cc
deleted file mode 100644
index 3e04446b3eb..00000000000
--- a/chromium/ui/views/metrics_win.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/metrics.h"
-
-#include <windows.h>
-
-namespace views {
-
-int GetDoubleClickInterval() {
- return ::GetDoubleClickTime();
-}
-
-int GetMenuShowDelay() {
- static DWORD delay = 0;
- if (!delay && !SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &delay, 0))
- delay = kDefaultMenuShowDelay;
- return delay;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/mouse_watcher.cc b/chromium/ui/views/mouse_watcher_aura.cc
index bee59848dba..3793f0e9671 100644
--- a/chromium/ui/views/mouse_watcher.cc
+++ b/chromium/ui/views/mouse_watcher_aura.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,16 +9,13 @@
#include "base/event_types.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/event_utils.h"
-#include "ui/gfx/screen.h"
-
-#if defined(USE_AURA)
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
#include "ui/events/event_handler.h"
-#endif
+#include "ui/events/event_utils.h"
+#include "ui/gfx/screen.h"
namespace views {
@@ -26,90 +23,6 @@ namespace views {
// the listener is notified.
const int kNotifyListenerTimeMs = 300;
-#if defined(OS_WIN) && !defined(USE_AURA)
-class MouseWatcher::Observer : public base::MessageLoopForUI::Observer {
- public:
- explicit Observer(MouseWatcher* mouse_watcher)
- : mouse_watcher_(mouse_watcher),
- notify_listener_factory_(this) {
- base::MessageLoopForUI::current()->AddObserver(this);
- }
-
- virtual ~Observer() {
- base::MessageLoopForUI::current()->RemoveObserver(this);
- }
-
- // MessageLoop::Observer implementation:
- virtual base::EventStatus WillProcessEvent(
- const base::NativeEvent& event) OVERRIDE {
- return base::EVENT_CONTINUE;
- }
-
- virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
- // We spy on three different Windows messages here to see if the mouse has
- // moved out of the bounds of the current view. The messages are:
- //
- // WM_MOUSEMOVE:
- // For when the mouse moves from the view into the rest of the browser UI,
- // i.e. within the bounds of the same windows HWND.
- // WM_MOUSELEAVE:
- // For when the mouse moves out of the bounds of the view's HWND.
- // WM_NCMOUSELEAVE:
- // For notification when the mouse leaves the _non-client_ area.
- //
- switch (event.message) {
- case WM_MOUSEMOVE:
- HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_MOVE);
- break;
- case WM_MOUSELEAVE:
- case WM_NCMOUSELEAVE:
- HandleGlobalMouseMoveEvent(MouseWatcherHost::MOUSE_EXIT);
- break;
- }
- }
-
- private:
- MouseWatcherHost* host() const { return mouse_watcher_->host_.get(); }
-
- // Called from the message loop observer when a mouse movement has occurred.
- void HandleGlobalMouseMoveEvent(MouseWatcherHost::MouseEventType event_type) {
- bool contained = host()->Contains(
- // TODO(scottmg): Native is wrong http://crbug.com/133312
- gfx::Screen::GetNativeScreen()->GetCursorScreenPoint(),
- event_type);
- if (!contained) {
- // Mouse moved outside the host's zone, start a timer to notify the
- // listener.
- if (!notify_listener_factory_.HasWeakPtrs()) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&Observer::NotifyListener,
- notify_listener_factory_.GetWeakPtr()),
- event_type == MouseWatcherHost::MOUSE_MOVE
- ? base::TimeDelta::FromMilliseconds(kNotifyListenerTimeMs)
- : mouse_watcher_->notify_on_exit_time_);
- }
- } else {
- // Mouse moved quickly out of the host and then into it again, so cancel
- // the timer.
- notify_listener_factory_.InvalidateWeakPtrs();
- }
- }
-
- void NotifyListener() {
- mouse_watcher_->NotifyListener();
- // WARNING: we've been deleted.
- }
-
- private:
- MouseWatcher* mouse_watcher_;
-
- // A factory that is used to construct a delayed callback to the listener.
- base::WeakPtrFactory<Observer> notify_listener_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(Observer);
-};
-#else
class MouseWatcher::Observer : public ui::EventHandler {
public:
explicit Observer(MouseWatcher* mouse_watcher)
@@ -177,7 +90,6 @@ class MouseWatcher::Observer : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(Observer);
};
-#endif
MouseWatcherListener::~MouseWatcherListener() {
}
diff --git a/chromium/ui/views/native_cursor.h b/chromium/ui/views/native_cursor.h
new file mode 100644
index 00000000000..81f6e213ae2
--- /dev/null
+++ b/chromium/ui/views/native_cursor.h
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_NATIVE_CURSOR_H_
+#define UI_VIEWS_NATIVE_CURSOR_H_
+
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+VIEWS_EXPORT gfx::NativeCursor GetNativeIBeamCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeHandCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeColumnResizeCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeEastWestResizeCursor();
+VIEWS_EXPORT gfx::NativeCursor GetNativeNorthSouthResizeCursor();
+
+} // namespace views
+
+#endif // UI_VIEWS_NATIVE_CURSOR_H_
diff --git a/chromium/ui/views/native_cursor_aura.cc b/chromium/ui/views/native_cursor_aura.cc
new file mode 100644
index 00000000000..cafe684aa0b
--- /dev/null
+++ b/chromium/ui/views/native_cursor_aura.cc
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/native_cursor.h"
+
+#include "ui/base/cursor/cursor.h"
+
+namespace views {
+
+gfx::NativeCursor GetNativeIBeamCursor() {
+ return ui::kCursorIBeam;
+}
+
+gfx::NativeCursor GetNativeHandCursor() {
+ return ui::kCursorHand;
+}
+
+gfx::NativeCursor GetNativeColumnResizeCursor() {
+ return ui::kCursorColumnResize;
+}
+
+gfx::NativeCursor GetNativeEastWestResizeCursor() {
+ return ui::kCursorEastWestResize;
+}
+
+gfx::NativeCursor GetNativeNorthSouthResizeCursor() {
+ return ui::kCursorNorthSouthResize;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/native_cursor_mac.mm b/chromium/ui/views/native_cursor_mac.mm
new file mode 100644
index 00000000000..967484deb72
--- /dev/null
+++ b/chromium/ui/views/native_cursor_mac.mm
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/native_cursor.h"
+
+#include <Cocoa/Cocoa.h>
+
+namespace views {
+
+gfx::NativeCursor GetNativeIBeamCursor() {
+ return [NSCursor IBeamCursor];
+}
+
+gfx::NativeCursor GetNativeArrowCursor() {
+ return [NSCursor arrowCursor];
+}
+
+gfx::NativeCursor GetNativeHandCursor() {
+ return [NSCursor pointingHandCursor];
+}
+
+gfx::NativeCursor GetNativeColumnResizeCursor() {
+ return [NSCursor resizeLeftRightCursor];
+}
+
+gfx::NativeCursor GetNativeEastWestResizeCursor() {
+ NOTIMPLEMENTED();
+ // TODO(tapted): This is the wrong cursor. Fetch the right one from WebCursor
+ // or ResourceBundle or CoreCursor private API.
+ return [NSCursor resizeLeftRightCursor];
+}
+
+gfx::NativeCursor GetNativeNorthSouthResizeCursor() {
+ NOTIMPLEMENTED();
+ return [NSCursor resizeUpDownCursor];
+}
+
+} // namespace views
diff --git a/chromium/ui/views/painter.cc b/chromium/ui/views/painter.cc
index b6a2e7d4c6f..ed0e65f7f85 100644
--- a/chromium/ui/views/painter.cc
+++ b/chromium/ui/views/painter.cc
@@ -13,6 +13,7 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/insets.h"
+#include "ui/gfx/nine_image_painter.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/views/view.h"
@@ -150,7 +151,7 @@ void GradientPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
p[1].iset(0, size.height());
skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
- p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode, NULL));
+ p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode));
paint.setStyle(SkPaint::kFill_Style);
paint.setShader(s.get());
@@ -173,117 +174,34 @@ class VIEWS_EXPORT ImagePainter : public Painter {
virtual ~ImagePainter();
- // Returns true if the images are empty.
- bool IsEmpty() const;
-
// Painter:
virtual gfx::Size GetMinimumSize() const OVERRIDE;
virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE;
private:
- // Stretches the given image over the specified canvas area.
- static void Fill(gfx::Canvas* c,
- const gfx::ImageSkia& i,
- int x,
- int y,
- int w,
- int h);
-
- // Images are numbered as depicted below.
- // ____________________
- // |__i0__|__i1__|__i2__|
- // |__i3__|__i4__|__i5__|
- // |__i6__|__i7__|__i8__|
- gfx::ImageSkia images_[9];
+ scoped_ptr<gfx::NineImagePainter> nine_painter_;
DISALLOW_COPY_AND_ASSIGN(ImagePainter);
};
-ImagePainter::ImagePainter(const int image_ids[]) {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- for (size_t i = 0; i < 9; ++i)
- if (image_ids[i] != 0)
- images_[i] = *rb.GetImageSkiaNamed(image_ids[i]);
+ImagePainter::ImagePainter(const int image_ids[])
+ : nine_painter_(ui::CreateNineImagePainter(image_ids)) {
}
ImagePainter::ImagePainter(const gfx::ImageSkia& image,
- const gfx::Insets& insets) {
- DCHECK_GE(image.width(), insets.width());
- DCHECK_GE(image.height(), insets.height());
-
- // Extract subsets of the original image to match the |images_| format.
- const int x[] =
- { 0, insets.left(), image.width() - insets.right(), image.width() };
- const int y[] =
- { 0, insets.top(), image.height() - insets.bottom(), image.height() };
-
- for (size_t j = 0; j < 3; ++j) {
- for (size_t i = 0; i < 3; ++i) {
- images_[i + j * 3] = gfx::ImageSkiaOperations::ExtractSubset(image,
- gfx::Rect(x[i], y[j], x[i + 1] - x[i], y[j + 1] - y[j]));
- }
- }
+ const gfx::Insets& insets)
+ : nine_painter_(new gfx::NineImagePainter(image, insets)) {
}
ImagePainter::~ImagePainter() {
}
-bool ImagePainter::IsEmpty() const {
- return images_[0].isNull();
-}
-
gfx::Size ImagePainter::GetMinimumSize() const {
- return IsEmpty() ? gfx::Size() : gfx::Size(
- images_[0].width() + images_[1].width() + images_[2].width(),
- images_[0].height() + images_[3].height() + images_[6].height());
+ return nine_painter_->GetMinimumSize();
}
void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
- if (IsEmpty())
- return;
-
- // In case the corners and edges don't all have the same width/height, we draw
- // the center first, and extend it out in all directions to the edges of the
- // images with the smallest widths/heights. This way there will be no
- // unpainted areas, though some corners or edges might overlap the center.
- int w = size.width();
- int i0w = images_[0].width();
- int i2w = images_[2].width();
- int i3w = images_[3].width();
- int i5w = images_[5].width();
- int i6w = images_[6].width();
- int i8w = images_[8].width();
- int i4x = std::min(std::min(i0w, i3w), i6w);
- int i4w = w - i4x - std::min(std::min(i2w, i5w), i8w);
- int h = size.height();
- int i0h = images_[0].height();
- int i1h = images_[1].height();
- int i2h = images_[2].height();
- int i6h = images_[6].height();
- int i7h = images_[7].height();
- int i8h = images_[8].height();
- int i4y = std::min(std::min(i0h, i1h), i2h);
- int i4h = h - i4y - std::min(std::min(i6h, i7h), i8h);
- if (!images_[4].isNull())
- Fill(canvas, images_[4], i4x, i4y, i4w, i4h);
- canvas->DrawImageInt(images_[0], 0, 0);
- Fill(canvas, images_[1], i0w, 0, w - i0w - i2w, i1h);
- canvas->DrawImageInt(images_[2], w - i2w, 0);
- Fill(canvas, images_[3], 0, i0h, i3w, h - i0h - i6h);
- Fill(canvas, images_[5], w - i5w, i2h, i5w, h - i2h - i8h);
- canvas->DrawImageInt(images_[6], 0, h - i6h);
- Fill(canvas, images_[7], i6w, h - i7h, w - i6w - i8w, i7h);
- canvas->DrawImageInt(images_[8], w - i8w, h - i8h);
-}
-
-// static
-void ImagePainter::Fill(gfx::Canvas* c,
- const gfx::ImageSkia& i,
- int x,
- int y,
- int w,
- int h) {
- c->DrawImageInt(i, 0, 0, i.width(), i.height(), x, y, w, h, false);
+ nine_painter_->Paint(canvas, gfx::Rect(size));
}
} // namespace
diff --git a/chromium/ui/views/painter.h b/chromium/ui/views/painter.h
index 3799e91e86c..6efd281f11a 100644
--- a/chromium/ui/views/painter.h
+++ b/chromium/ui/views/painter.h
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/nine_image_painter_factory.h"
#include "ui/views/views_export.h"
namespace gfx {
@@ -19,11 +20,6 @@ class Rect;
class Size;
}
-// A macro to define arrays of IDR constants used with CreateImageGridPainter.
-#define IMAGE_GRID(x) { x ## _TOP_LEFT, x ## _TOP, x ## _TOP_RIGHT, \
- x ## _LEFT, x ## _CENTER, x ## _RIGHT, \
- x ## _BOTTOM_LEFT, x ## _BOTTOM, x ## _BOTTOM_RIGHT, }
-
namespace views {
class View;
diff --git a/chromium/ui/views/run_all_unittests.cc b/chromium/ui/views/run_all_unittests.cc
index 499d339c5f9..e5d7b9d61f0 100644
--- a/chromium/ui/views/run_all_unittests.cc
+++ b/chromium/ui/views/run_all_unittests.cc
@@ -8,8 +8,10 @@
#include "base/path_service.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
+#include "ui/gl/gl_surface.h"
class ViewTestSuite : public base::TestSuite {
public:
@@ -18,15 +20,12 @@ class ViewTestSuite : public base::TestSuite {
protected:
virtual void Initialize() OVERRIDE {
base::TestSuite::Initialize();
+ gfx::GLSurface::InitializeOneOffForTests();
ui::RegisterPathProvider();
- base::FilePath pak_dir;
- PathService::Get(base::DIR_MODULE, &pak_dir);
-
- base::FilePath pak_file;
- pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
-
- ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+ base::FilePath ui_test_pak_path;
+ ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
}
virtual void Shutdown() OVERRIDE {
diff --git a/chromium/ui/views/touchui/touch_editing_menu.cc b/chromium/ui/views/touchui/touch_editing_menu.cc
index dec91139093..b17039c9727 100644
--- a/chromium/ui/views/touchui/touch_editing_menu.cc
+++ b/chromium/ui/views/touchui/touch_editing_menu.cc
@@ -9,6 +9,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/bubble/bubble_border.h"
@@ -38,11 +39,11 @@ namespace views {
TouchEditingMenuView::TouchEditingMenuView(
TouchEditingMenuController* controller,
- gfx::Rect anchor_rect,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
gfx::NativeView context)
: BubbleDelegateView(NULL, views::BubbleBorder::BOTTOM_CENTER),
controller_(controller) {
- SetAnchorRect(anchor_rect);
set_shadow(views::BubbleBorder::SMALL_SHADOW);
set_parent_window(context);
set_margins(gfx::Insets(kMenuMargin, kMenuMargin, kMenuMargin, kMenuMargin));
@@ -52,6 +53,16 @@ TouchEditingMenuView::TouchEditingMenuView(
SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, 0, 0,
kSpacingBetweenButtons));
CreateButtons();
+
+ // After buttons are created, check if there is enough room between handles to
+ // show the menu and adjust anchor rect properly if needed, just in case the
+ // menu is needed to be shown under the selection.
+ gfx::Rect adjusted_anchor_rect(anchor_rect);
+ int menu_width = GetPreferredSize().width();
+ if (menu_width > anchor_rect.width() - handle_image_size.width())
+ adjusted_anchor_rect.Inset(0, 0, 0, -handle_image_size.height());
+ SetAnchorRect(adjusted_anchor_rect);
+
views::BubbleDelegateView::CreateBubble(this);
GetWidget()->Show();
}
@@ -62,12 +73,15 @@ TouchEditingMenuView::~TouchEditingMenuView() {
// static
TouchEditingMenuView* TouchEditingMenuView::Create(
TouchEditingMenuController* controller,
- gfx::Rect anchor_rect,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
gfx::NativeView context) {
if (controller) {
for (size_t i = 0; i < arraysize(kMenuCommands); i++) {
- if (controller->IsCommandIdEnabled(kMenuCommands[i]))
- return new TouchEditingMenuView(controller, anchor_rect, context);
+ if (controller->IsCommandIdEnabled(kMenuCommands[i])) {
+ return new TouchEditingMenuView(controller, anchor_rect,
+ handle_image_size, context);
+ }
}
}
return NULL;
@@ -121,25 +135,27 @@ void TouchEditingMenuView::CreateButtons() {
// Finally, add ellipses button.
AddChildView(CreateButton(
- UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag));
+ base::UTF8ToUTF16(kEllipsesButtonText), kEllipsesButtonTag));
Layout();
}
-Button* TouchEditingMenuView::CreateButton(const string16& title, int tag) {
- string16 label = gfx::RemoveAcceleratorChar(title, '&', NULL, NULL);
+Button* TouchEditingMenuView::CreateButton(const base::string16& title,
+ int tag) {
+ base::string16 label = gfx::RemoveAcceleratorChar(title, '&', NULL, NULL);
LabelButton* button = new LabelButton(this, label);
button->SetFocusable(true);
button->set_request_focus_on_press(false);
- gfx::Font font = ui::ResourceBundle::GetSharedInstance().GetFont(
- ui::ResourceBundle::SmallFont);
+ const gfx::FontList& font_list =
+ ui::ResourceBundle::GetSharedInstance().GetFontList(
+ ui::ResourceBundle::SmallFont);
scoped_ptr<LabelButtonBorder> button_border(
new LabelButtonBorder(button->style()));
- int v_border = (kMenuButtonHeight - font.GetHeight()) / 2;
- int h_border = (kMenuButtonWidth - font.GetStringWidth(label)) / 2;
+ int v_border = (kMenuButtonHeight - font_list.GetHeight()) / 2;
+ int h_border = (kMenuButtonWidth - gfx::GetStringWidth(label, font_list)) / 2;
button_border->set_insets(
gfx::Insets(v_border, h_border, v_border, h_border));
- button->set_border(button_border.release());
- button->SetFont(font);
+ button->SetBorder(button_border.PassAs<Border>());
+ button->SetFontList(font_list);
button->set_tag(tag);
return button;
}
diff --git a/chromium/ui/views/touchui/touch_editing_menu.h b/chromium/ui/views/touchui/touch_editing_menu.h
index 5dfeaef373a..19f0d34a664 100644
--- a/chromium/ui/views/touchui/touch_editing_menu.h
+++ b/chromium/ui/views/touchui/touch_editing_menu.h
@@ -45,14 +45,16 @@ class VIEWS_EXPORT TouchEditingMenuView : public BubbleDelegateView,
// If there are no actions available for the menu, returns NULL. Otherwise,
// returns a new instance of TouchEditingMenuView.
static TouchEditingMenuView* Create(TouchEditingMenuController* controller,
- gfx::Rect anchor_rect,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
gfx::NativeView context);
void Close();
private:
TouchEditingMenuView(TouchEditingMenuController* controller,
- gfx::Rect anchor_rect,
+ const gfx::Rect& anchor_rect,
+ const gfx::Size& handle_image_size,
gfx::NativeView context);
// views::WidgetDelegate overrides:
@@ -69,7 +71,7 @@ class VIEWS_EXPORT TouchEditingMenuView : public BubbleDelegateView,
void CreateButtons();
// Helper method to create a single button.
- Button* CreateButton(const string16& title, int tag);
+ Button* CreateButton(const base::string16& title, int tag);
TouchEditingMenuController* controller_;
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
index 41720be7033..3e005a64ea6 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
@@ -7,16 +7,19 @@
#include "base/time/time.h"
#include "grit/ui_resources.h"
#include "grit/ui_strings.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_switches_util.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size.h"
-#include "ui/views/corewm/shadow_types.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/core/masked_window_targeter.h"
+#include "ui/wm/core/window_animations.h"
namespace {
@@ -56,21 +59,27 @@ const int kSelectionHandleVertPadding = 20;
const int kContextMenuTimoutMs = 200;
+const int kSelectionHandleQuickFadeDurationMs = 50;
+
+// Minimum height for selection handle bar. If the bar height is going to be
+// less than this value, handle will not be shown.
+const int kSelectionHandleBarMinHeight = 5;
+// Maximum amount that selection handle bar can stick out of client view's
+// boundaries.
+const int kSelectionHandleBarBottomAllowance = 3;
+
// Creates a widget to host SelectionHandleView.
views::Widget* CreateTouchSelectionPopupWidget(
gfx::NativeView context,
views::WidgetDelegate* widget_delegate) {
views::Widget* widget = new views::Widget;
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_TOOLTIP);
- params.can_activate = false;
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+ params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.context = context;
+ params.parent = context;
params.delegate = widget_delegate;
widget->Init(params);
-#if defined(USE_AURA)
- SetShadowType(widget->GetNativeView(), views::corewm::SHADOW_TYPE_NONE);
-#endif
return widget;
}
@@ -97,8 +106,8 @@ gfx::Rect Union(const gfx::Rect& r1, const gfx::Rect& r2) {
return gfx::Rect(rx, ry, rr - rx, rb - ry);
}
-// Convenience method to convert a |rect| from screen to the |client|'s
-// coordinate system.
+// Convenience methods to convert a |rect| from screen to the |client|'s
+// coordinate system and vice versa.
// Note that this is not quite correct because it does not take into account
// transforms such as rotation and scaling. This should be in TouchEditable.
// TODO(varunjain): Fix this.
@@ -107,29 +116,57 @@ gfx::Rect ConvertFromScreen(ui::TouchEditable* client, const gfx::Rect& rect) {
client->ConvertPointFromScreen(&origin);
return gfx::Rect(origin, rect.size());
}
+gfx::Rect ConvertToScreen(ui::TouchEditable* client, const gfx::Rect& rect) {
+ gfx::Point origin = rect.origin();
+ client->ConvertPointToScreen(&origin);
+ return gfx::Rect(origin, rect.size());
+}
} // namespace
namespace views {
+typedef TouchSelectionControllerImpl::EditingHandleView EditingHandleView;
+
+class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter {
+ public:
+ TouchHandleWindowTargeter(aura::Window* window,
+ EditingHandleView* handle_view);
+
+ virtual ~TouchHandleWindowTargeter() {}
+
+ private:
+ // wm::MaskedWindowTargeter:
+ virtual bool GetHitTestMask(aura::Window* window,
+ gfx::Path* mask) const OVERRIDE;
+
+ EditingHandleView* handle_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter);
+};
+
// A View that displays the text selection handle.
class TouchSelectionControllerImpl::EditingHandleView
: public views::WidgetDelegateView {
public:
- explicit EditingHandleView(TouchSelectionControllerImpl* controller,
- gfx::NativeView context)
+ EditingHandleView(TouchSelectionControllerImpl* controller,
+ gfx::NativeView context)
: controller_(controller),
drag_offset_(0),
draw_invisible_(false) {
widget_.reset(CreateTouchSelectionPopupWidget(context, this));
widget_->SetContentsView(this);
- widget_->SetAlwaysOnTop(true);
+
+ aura::Window* window = widget_->GetNativeWindow();
+ window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
+ new TouchHandleWindowTargeter(window, this)));
// We are owned by the TouchSelectionController.
set_owned_by_client();
}
virtual ~EditingHandleView() {
+ SetWidgetVisible(false, false);
}
// Overridden from views::WidgetDelegateView:
@@ -193,7 +230,7 @@ class TouchSelectionControllerImpl::EditingHandleView
}
}
- virtual gfx::Size GetPreferredSize() OVERRIDE {
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
gfx::Size image_size = GetHandleImageSize();
return gfx::Size(image_size.width() + 2 * kSelectionHandleHorizPadding,
image_size.height() + selection_rect_.height() +
@@ -204,9 +241,13 @@ class TouchSelectionControllerImpl::EditingHandleView
return widget_->IsVisible();
}
- void SetWidgetVisible(bool visible) {
+ void SetWidgetVisible(bool visible, bool quick) {
if (widget_->IsVisible() == visible)
return;
+ wm::SetWindowVisibilityAnimationDuration(
+ widget_->GetNativeView(),
+ base::TimeDelta::FromMilliseconds(
+ quick ? kSelectionHandleQuickFadeDurationMs : 0));
if (visible)
widget_->Show();
else
@@ -235,6 +276,8 @@ class TouchSelectionControllerImpl::EditingHandleView
SchedulePaint();
}
+ const gfx::Rect& selection_rect() const { return selection_rect_; }
+
private:
scoped_ptr<Widget> widget_;
TouchSelectionControllerImpl* controller_;
@@ -254,6 +297,24 @@ class TouchSelectionControllerImpl::EditingHandleView
DISALLOW_COPY_AND_ASSIGN(EditingHandleView);
};
+TouchHandleWindowTargeter::TouchHandleWindowTargeter(
+ aura::Window* window,
+ EditingHandleView* handle_view)
+ : wm::MaskedWindowTargeter(window),
+ handle_view_(handle_view) {
+}
+
+bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window,
+ gfx::Path* mask) const {
+ const gfx::Rect& selection_rect = handle_view_->selection_rect();
+ gfx::Size image_size = GetHandleImageSize();
+ mask->addRect(SkIntToScalar(0), SkIntToScalar(selection_rect.height()),
+ SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
+ SkIntToScalar(selection_rect.height() + image_size.height() +
+ kSelectionHandleVertPadding));
+ return true;
+}
+
TouchSelectionControllerImpl::TouchSelectionControllerImpl(
ui::TouchEditable* client_view)
: client_view_(client_view),
@@ -270,10 +331,12 @@ TouchSelectionControllerImpl::TouchSelectionControllerImpl(
client_view_->GetNativeView());
if (client_widget_)
client_widget_->AddObserver(this);
+ aura::Env::GetInstance()->AddPreTargetHandler(this);
}
TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
HideContextMenu();
+ aura::Env::GetInstance()->RemovePreTargetHandler(this);
if (client_widget_)
client_widget_->RemoveObserver(this);
}
@@ -281,21 +344,26 @@ TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
void TouchSelectionControllerImpl::SelectionChanged() {
gfx::Rect r1, r2;
client_view_->GetSelectionEndPoints(&r1, &r2);
- gfx::Point screen_pos_1(r1.origin());
- client_view_->ConvertPointToScreen(&screen_pos_1);
- gfx::Point screen_pos_2(r2.origin());
- client_view_->ConvertPointToScreen(&screen_pos_2);
- gfx::Rect screen_rect_1(screen_pos_1, r1.size());
- gfx::Rect screen_rect_2(screen_pos_2, r2.size());
- if (screen_rect_1 == selection_end_point_1_ &&
- screen_rect_2 == selection_end_point_2_)
+ gfx::Rect screen_rect_1 = ConvertToScreen(client_view_, r1);
+ gfx::Rect screen_rect_2 = ConvertToScreen(client_view_, r2);
+ gfx::Rect client_bounds = client_view_->GetBounds();
+ if (r1.y() < client_bounds.y())
+ r1.Inset(0, client_bounds.y() - r1.y(), 0, 0);
+ if (r2.y() < client_bounds.y())
+ r2.Inset(0, client_bounds.y() - r2.y(), 0, 0);
+ gfx::Rect screen_rect_1_clipped = ConvertToScreen(client_view_, r1);
+ gfx::Rect screen_rect_2_clipped = ConvertToScreen(client_view_, r2);
+ if (screen_rect_1_clipped == selection_end_point_1_clipped_ &&
+ screen_rect_2_clipped == selection_end_point_2_clipped_)
return;
selection_end_point_1_ = screen_rect_1;
selection_end_point_2_ = screen_rect_2;
+ selection_end_point_1_clipped_ = screen_rect_1_clipped;
+ selection_end_point_2_clipped_ = screen_rect_2_clipped;
if (client_view_->DrawsHandles()) {
- UpdateContextMenu(r1.origin(), r2.origin());
+ UpdateContextMenu();
return;
}
if (dragging_handle_) {
@@ -306,14 +374,14 @@ void TouchSelectionControllerImpl::SelectionChanged() {
// If the new location of this handle is out of client view, its widget
// should not get hidden, since it should still receive touch events.
// Hence, we are not using |SetHandleSelectionRect()| method here.
- dragging_handle_->SetSelectionRectInScreen(screen_rect_2);
+ dragging_handle_->SetSelectionRectInScreen(screen_rect_2_clipped);
// Temporary fix for selection handle going outside a window. On a webpage,
// the page should scroll if the selection handle is dragged outside the
// window. That does not happen currently. So we just hide the handle for
// now.
// TODO(varunjain): Fix this: crbug.com/269003
- dragging_handle_->SetDrawInvisible(!client_view_->GetBounds().Contains(r2));
+ dragging_handle_->SetDrawInvisible(!ShouldShowHandleFor(r2));
if (dragging_handle_ != cursor_handle_.get()) {
// The non-dragging-handle might have recently become visible.
@@ -324,23 +392,27 @@ void TouchSelectionControllerImpl::SelectionChanged() {
// selection and the other handle to the start of selection.
selection_end_point_1_ = screen_rect_2;
selection_end_point_2_ = screen_rect_1;
+ selection_end_point_1_clipped_ = screen_rect_2_clipped;
+ selection_end_point_2_clipped_ = screen_rect_1_clipped;
}
- SetHandleSelectionRect(non_dragging_handle, r1, screen_rect_1);
+ SetHandleSelectionRect(non_dragging_handle, r1, screen_rect_1_clipped);
}
} else {
- UpdateContextMenu(r1.origin(), r2.origin());
+ UpdateContextMenu();
// Check if there is any selection at all.
- if (screen_pos_1 == screen_pos_2) {
- selection_handle_1_->SetWidgetVisible(false);
- selection_handle_2_->SetWidgetVisible(false);
- SetHandleSelectionRect(cursor_handle_.get(), r1, screen_rect_1);
+ if (screen_rect_1.origin() == screen_rect_2.origin()) {
+ selection_handle_1_->SetWidgetVisible(false, false);
+ selection_handle_2_->SetWidgetVisible(false, false);
+ SetHandleSelectionRect(cursor_handle_.get(), r1, screen_rect_1_clipped);
return;
}
- cursor_handle_->SetWidgetVisible(false);
- SetHandleSelectionRect(selection_handle_1_.get(), r1, screen_rect_1);
- SetHandleSelectionRect(selection_handle_2_.get(), r2, screen_rect_2);
+ cursor_handle_->SetWidgetVisible(false, false);
+ SetHandleSelectionRect(selection_handle_1_.get(), r1,
+ screen_rect_1_clipped);
+ SetHandleSelectionRect(selection_handle_2_.get(), r2,
+ screen_rect_2_clipped);
}
}
@@ -348,6 +420,12 @@ bool TouchSelectionControllerImpl::IsHandleDragInProgress() {
return !!dragging_handle_;
}
+void TouchSelectionControllerImpl::HideHandles(bool quick) {
+ selection_handle_1_->SetWidgetVisible(false, quick);
+ selection_handle_2_->SetWidgetVisible(false, quick);
+ cursor_handle_->SetWidgetVisible(false, quick);
+}
+
void TouchSelectionControllerImpl::SetDraggingHandle(
EditingHandleView* handle) {
dragging_handle_ = handle;
@@ -397,11 +475,20 @@ void TouchSelectionControllerImpl::SetHandleSelectionRect(
EditingHandleView* handle,
const gfx::Rect& rect,
const gfx::Rect& rect_in_screen) {
- handle->SetWidgetVisible(client_view_->GetBounds().Contains(rect));
+ handle->SetWidgetVisible(ShouldShowHandleFor(rect), false);
if (handle->IsWidgetVisible())
handle->SetSelectionRectInScreen(rect_in_screen);
}
+bool TouchSelectionControllerImpl::ShouldShowHandleFor(
+ const gfx::Rect& rect) const {
+ if (rect.height() < kSelectionHandleBarMinHeight)
+ return false;
+ gfx::Rect bounds = client_view_->GetBounds();
+ bounds.Inset(0, 0, 0, -kSelectionHandleBarBottomAllowance);
+ return bounds.Contains(rect);
+}
+
bool TouchSelectionControllerImpl::IsCommandIdEnabled(int command_id) const {
return client_view_->IsCommandIdEnabled(command_id);
}
@@ -438,16 +525,31 @@ void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
SelectionChanged();
}
+void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) {
+ client_view_->DestroyTouchSelection();
+}
+
+void TouchSelectionControllerImpl::OnMouseEvent(ui::MouseEvent* event) {
+ aura::client::CursorClient* cursor_client = aura::client::GetCursorClient(
+ client_view_->GetNativeView()->GetRootWindow());
+ if (!cursor_client || cursor_client->IsMouseEventsEnabled())
+ client_view_->DestroyTouchSelection();
+}
+
+void TouchSelectionControllerImpl::OnScrollEvent(ui::ScrollEvent* event) {
+ client_view_->DestroyTouchSelection();
+}
+
void TouchSelectionControllerImpl::ContextMenuTimerFired() {
// Get selection end points in client_view's space.
gfx::Rect end_rect_1_in_screen;
gfx::Rect end_rect_2_in_screen;
if (cursor_handle_->IsWidgetVisible()) {
- end_rect_1_in_screen = selection_end_point_1_;
+ end_rect_1_in_screen = selection_end_point_1_clipped_;
end_rect_2_in_screen = end_rect_1_in_screen;
} else {
- end_rect_1_in_screen = selection_end_point_1_;
- end_rect_2_in_screen = selection_end_point_2_;
+ end_rect_1_in_screen = selection_end_point_1_clipped_;
+ end_rect_2_in_screen = selection_end_point_2_clipped_;
}
// Convert from screen to client.
@@ -458,19 +560,19 @@ void TouchSelectionControllerImpl::ContextMenuTimerFired() {
// in the middle of the end points on the top. Else, we show it above the
// visible handle. If no handle is visible, we do not show the menu.
gfx::Rect menu_anchor;
- gfx::Rect client_bounds = client_view_->GetBounds();
- if (client_bounds.Contains(end_rect_1) &&
- client_bounds.Contains(end_rect_2))
+ if (ShouldShowHandleFor(end_rect_1) &&
+ ShouldShowHandleFor(end_rect_2))
menu_anchor = Union(end_rect_1_in_screen,end_rect_2_in_screen);
- else if (client_bounds.Contains(end_rect_1))
+ else if (ShouldShowHandleFor(end_rect_1))
menu_anchor = end_rect_1_in_screen;
- else if (client_bounds.Contains(end_rect_2))
+ else if (ShouldShowHandleFor(end_rect_2))
menu_anchor = end_rect_2_in_screen;
else
return;
DCHECK(!context_menu_);
context_menu_ = TouchEditingMenuView::Create(this, menu_anchor,
+ GetHandleImageSize(),
client_view_->GetNativeView());
}
@@ -484,8 +586,7 @@ void TouchSelectionControllerImpl::StartContextMenuTimer() {
&TouchSelectionControllerImpl::ContextMenuTimerFired);
}
-void TouchSelectionControllerImpl::UpdateContextMenu(const gfx::Point& p1,
- const gfx::Point& p2) {
+void TouchSelectionControllerImpl::UpdateContextMenu() {
// Hide context menu to be shown when the timer fires.
HideContextMenu();
StartContextMenuTimer();
@@ -498,6 +599,10 @@ void TouchSelectionControllerImpl::HideContextMenu() {
context_menu_timer_.Stop();
}
+gfx::NativeView TouchSelectionControllerImpl::GetCursorHandleNativeView() {
+ return cursor_handle_->GetWidget()->GetNativeView();
+}
+
gfx::Point TouchSelectionControllerImpl::GetSelectionHandle1Position() {
return selection_handle_1_->GetScreenPosition();
}
@@ -522,14 +627,4 @@ bool TouchSelectionControllerImpl::IsCursorHandleVisible() {
return cursor_handle_->IsWidgetVisible();
}
-ViewsTouchSelectionControllerFactory::ViewsTouchSelectionControllerFactory() {
-}
-
-ui::TouchSelectionController* ViewsTouchSelectionControllerFactory::create(
- ui::TouchEditable* client_view) {
- if (switches::IsTouchEditingEnabled())
- return new views::TouchSelectionControllerImpl(client_view);
- return NULL;
-}
-
} // namespace views
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.h b/chromium/ui/views/touchui/touch_selection_controller_impl.h
index dc9babe9d34..04076af2e8f 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.h
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.h
@@ -14,13 +14,20 @@
namespace views {
+namespace test {
+class WidgetTestInteractive;
+}
+
// Touch specific implementation of TouchSelectionController. Responsible for
// displaying selection handles and menu elements relevant in a touch interface.
class VIEWS_EXPORT TouchSelectionControllerImpl
: public ui::TouchSelectionController,
public TouchEditingMenuController,
- public WidgetObserver {
+ public WidgetObserver,
+ public ui::EventHandler {
public:
+ class EditingHandleView;
+
// Use TextSelectionController::create().
explicit TouchSelectionControllerImpl(
ui::TouchEditable* client_view);
@@ -30,10 +37,11 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
// TextSelectionController.
virtual void SelectionChanged() OVERRIDE;
virtual bool IsHandleDragInProgress() OVERRIDE;
+ virtual void HideHandles(bool quick) OVERRIDE;
private:
friend class TouchSelectionControllerImplTest;
- class EditingHandleView;
+ friend class test::WidgetTestInteractive;
void SetDraggingHandle(EditingHandleView* handle);
@@ -50,6 +58,10 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
void SetHandleSelectionRect(EditingHandleView* handle, const gfx::Rect& rect,
const gfx::Rect& rect_in_screen);
+ // Checks if handle should be shown for a selection end-point at |rect|.
+ // |rect| should be the clipped version of the selection end-point.
+ bool ShouldShowHandleFor(const gfx::Rect& rect) const;
+
// Overridden from TouchEditingMenuController.
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
@@ -63,18 +75,24 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
virtual void OnWidgetBoundsChanged(Widget* widget,
const gfx::Rect& new_bounds) OVERRIDE;
+ // Overriden from ui::EventHandler.
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+ virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
+
// Time to show context menu.
void ContextMenuTimerFired();
void StartContextMenuTimer();
// Convenience method to update the position/visibility of the context menu.
- void UpdateContextMenu(const gfx::Point& p1, const gfx::Point& p2);
+ void UpdateContextMenu();
// Convenience method for hiding context menu.
void HideContextMenu();
// Convenience methods for testing.
+ gfx::NativeView GetCursorHandleNativeView();
gfx::Point GetSelectionHandle1Position();
gfx::Point GetSelectionHandle2Position();
gfx::Point GetCursorHandlePosition();
@@ -104,20 +122,13 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
// position of handles which might be invalid when handles are hidden.
gfx::Rect selection_end_point_1_;
gfx::Rect selection_end_point_2_;
+ // Selection end points, clipped to client view's boundaries.
+ gfx::Rect selection_end_point_1_clipped_;
+ gfx::Rect selection_end_point_2_clipped_;
DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerImpl);
};
-class VIEWS_EXPORT ViewsTouchSelectionControllerFactory
- : public ui::TouchSelectionControllerFactory {
- public:
- ViewsTouchSelectionControllerFactory();
-
- // Overridden from ui::TouchSelectionControllerFactory.
- virtual ui::TouchSelectionController* create(
- ui::TouchEditable* client_view) OVERRIDE;
-};
-
} // namespace views
#endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc
index 54c997223c2..8f21e3729bc 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -5,27 +5,44 @@
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/touch/touch_editing_controller.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/canvas.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/render_text.h"
-#include "ui/views/controls/textfield/native_textfield_views.h"
#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/touchui/touch_selection_controller_impl.h"
+#include "ui/views/views_touch_selection_controller_factory.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/aura/test/event_generator.h"
-#include "ui/aura/window.h"
-#endif
+using base::ASCIIToUTF16;
+using base::UTF16ToUTF8;
+using base::WideToUTF16;
namespace {
// Should match kSelectionHandlePadding in touch_selection_controller.
const int kPadding = 10;
+// Should match kSelectionHandleBarMinHeight in touch_selection_controller.
+const int kBarMinHeight = 5;
+
+// Should match kSelectionHandleBarBottomAllowance in
+// touch_selection_controller.
+const int kBarBottomAllowance = 3;
+
+// Should match kMenuButtonWidth in touch_editing_menu.
+const int kMenuButtonWidth = 63;
+
+// Should match size of kMenuCommands array in touch_editing_menu.
+const int kMenuCommandCount = 3;
+
gfx::Image* GetHandleImage() {
static gfx::Image* handle_image = NULL;
if (!handle_image) {
@@ -45,9 +62,9 @@ namespace views {
class TouchSelectionControllerImplTest : public ViewsTestBase {
public:
TouchSelectionControllerImplTest()
- : widget_(NULL),
+ : textfield_widget_(NULL),
+ widget_(NULL),
textfield_(NULL),
- textfield_view_(NULL),
views_tsc_factory_(new ViewsTouchSelectionControllerFactory) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableTouchEditing);
@@ -59,42 +76,68 @@ class TouchSelectionControllerImplTest : public ViewsTestBase {
}
virtual void TearDown() {
- if (widget_)
+ if (textfield_widget_ && !textfield_widget_->IsClosed())
+ textfield_widget_->Close();
+ if (widget_ && !widget_->IsClosed())
widget_->Close();
ViewsTestBase::TearDown();
}
void CreateTextfield() {
textfield_ = new Textfield();
- widget_ = new Widget;
+ textfield_widget_ = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.bounds = gfx::Rect(0, 0, 200, 200);
- widget_->Init(params);
+ textfield_widget_->Init(params);
View* container = new View();
- widget_->SetContentsView(container);
+ textfield_widget_->SetContentsView(container);
container->AddChildView(textfield_);
- textfield_view_ = static_cast<NativeTextfieldViews*>(
- textfield_->GetNativeWrapperForTesting());
- textfield_->SetBoundsRect(params.bounds);
- textfield_view_->SetBoundsRect(params.bounds);
+ textfield_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
textfield_->set_id(1);
- widget_->Show();
+ textfield_widget_->Show();
- DCHECK(textfield_view_);
textfield_->RequestFocus();
+
+ textfield_test_api_.reset(new TextfieldTestApi(textfield_));
+ }
+
+ void CreateWidget() {
+ widget_ = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ widget_->Init(params);
+ widget_->Show();
}
protected:
+ static bool IsCursorHandleVisibleFor(
+ ui::TouchSelectionController* controller) {
+ TouchSelectionControllerImpl* impl =
+ static_cast<TouchSelectionControllerImpl*>(controller);
+ return impl->IsCursorHandleVisible();
+ }
+
+ gfx::Rect GetCursorRect(const gfx::SelectionModel& sel) {
+ return textfield_test_api_->GetRenderText()->GetCursorBounds(sel, true);
+ }
+
gfx::Point GetCursorPosition(const gfx::SelectionModel& sel) {
- gfx::RenderText* render_text = textfield_view_->GetRenderText();
- gfx::Rect cursor_bounds = render_text->GetCursorBounds(sel, true);
+ gfx::Rect cursor_bounds = GetCursorRect(sel);
return gfx::Point(cursor_bounds.x(), cursor_bounds.y());
}
TouchSelectionControllerImpl* GetSelectionController() {
return static_cast<TouchSelectionControllerImpl*>(
- textfield_view_->touch_selection_controller_.get());
+ textfield_test_api_->touch_selection_controller());
+ }
+
+ void StartTouchEditing() {
+ textfield_test_api_->CreateTouchSelectionControllerAndNotifyIt();
+ }
+
+ void EndTouchEditing() {
+ textfield_test_api_->ResetTouchSelectionController();
}
void SimulateSelectionHandleDrag(gfx::Point p, int selection_handle) {
@@ -114,6 +157,10 @@ class TouchSelectionControllerImplTest : public ViewsTestBase {
controller->dragging_handle_ = NULL;
}
+ gfx::NativeView GetCursorHandleNativeView() {
+ return GetSelectionController()->GetCursorHandleNativeView();
+ }
+
gfx::Point GetSelectionHandle1Position() {
return GetSelectionController()->GetSelectionHandle1Position();
}
@@ -139,13 +186,23 @@ class TouchSelectionControllerImplTest : public ViewsTestBase {
}
gfx::RenderText* GetRenderText() {
- return textfield_view_->GetRenderText();
+ return textfield_test_api_->GetRenderText();
}
+ gfx::Point GetCursorHandleDragPoint() {
+ gfx::Point point = GetCursorHandlePosition();
+ const gfx::SelectionModel& sel = textfield_->GetSelectionModel();
+ int cursor_height = GetCursorRect(sel).height();
+ point.Offset(GetHandleImageSize().width() / 2 + kPadding,
+ GetHandleImageSize().height() / 2 + cursor_height);
+ return point;
+ }
+
+ Widget* textfield_widget_;
Widget* widget_;
Textfield* textfield_;
- NativeTextfieldViews* textfield_view_;
+ scoped_ptr<TextfieldTestApi> textfield_test_api_;
scoped_ptr<ViewsTouchSelectionControllerFactory> views_tsc_factory_;
private:
@@ -158,7 +215,7 @@ class TouchSelectionControllerImplTest : public ViewsTestBase {
// handle 1's position is matched against the start of selection or the end.
#define VERIFY_HANDLE_POSITIONS(cursor_at_selection_handle_1) \
{ \
- gfx::SelectionModel sel = textfield_view_->GetSelectionModel(); \
+ gfx::SelectionModel sel = textfield_->GetSelectionModel(); \
if (textfield_->HasSelection()) { \
EXPECT_TRUE(IsSelectionHandle1Visible()); \
EXPECT_TRUE(IsSelectionHandle2Visible()); \
@@ -197,7 +254,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInTextfieldTest) {
// Tap the textfield to invoke touch selection.
ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0);
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
// Test selecting a range.
textfield_->SelectRange(gfx::Range(3, 7));
@@ -212,13 +269,13 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInTextfieldTest) {
VERIFY_HANDLE_POSITIONS(false);
// Test with lost focus.
- widget_->GetFocusManager()->ClearFocus();
+ textfield_widget_->GetFocusManager()->ClearFocus();
EXPECT_FALSE(GetSelectionController());
// Test with focus re-gained.
- widget_->GetFocusManager()->SetFocusedView(textfield_);
+ textfield_widget_->GetFocusManager()->SetFocusedView(textfield_);
EXPECT_FALSE(GetSelectionController());
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
VERIFY_HANDLE_POSITIONS(false);
}
@@ -229,7 +286,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectionInBidiTextfieldTest) {
// Tap the textfield to invoke touch selection.
ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0);
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
// Test cursor at run boundary and with empty selection.
textfield_->SelectSelectionModel(
@@ -277,15 +334,15 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) {
// Tap the textfield to invoke touch selection.
ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0);
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
textfield_->SelectRange(gfx::Range(3, 7));
EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfie");
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 2 to right by 3 chars.
- const gfx::Font& font = textfield_->GetPrimaryFont();
- int x = font.GetStringWidth(ASCIIToUTF16("ld "));
+ const gfx::FontList& font_list = textfield_->GetFontList();
+ int x = gfx::Canvas::GetStringWidth(ASCIIToUTF16("ld "), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "tfield ");
VERIFY_HANDLE_POSITIONS(false);
@@ -297,13 +354,13 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectCallbackTest) {
VERIFY_HANDLE_POSITIONS(true);
// Drag selection handle 1 across selection handle 2.
- x = font.GetStringWidth(ASCIIToUTF16("textfield with "));
+ x = gfx::Canvas::GetStringWidth(ASCIIToUTF16("textfield with "), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "with ");
VERIFY_HANDLE_POSITIONS(true);
// Drag selection handle 2 across selection handle 1.
- x = font.GetStringWidth(ASCIIToUTF16("with selected "));
+ x = gfx::Canvas::GetStringWidth(ASCIIToUTF16("with selected "), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
EXPECT_EQ(UTF16ToUTF8(textfield_->GetSelectedText()), "selected ");
VERIFY_HANDLE_POSITIONS(false);
@@ -315,7 +372,7 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
// Tap the textfield to invoke touch selection.
ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0);
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
// Select [c] from left to right.
textfield_->SelectRange(gfx::Range(2, 3));
@@ -323,14 +380,14 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 2 to right by 1 char.
- const gfx::Font& font = textfield_->GetPrimaryFont();
- int x = font.GetStringWidth(WideToUTF16(L"\x05e3"));
+ const gfx::FontList& font_list = textfield_->GetFontList();
+ int x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e3"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 1 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"b"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"b"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
EXPECT_EQ(WideToUTF16(L"bc\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
@@ -341,13 +398,13 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 1 to right by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"\x05e3"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e3"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
// Drag selection handle 2 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"b"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"b"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
EXPECT_EQ(WideToUTF16(L"bc\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
@@ -366,14 +423,14 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
Need further investigation on whether this is a bug in Pango and how to
work around it.
// Drag selection handle 2 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"\x05e2"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e2"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
EXPECT_EQ(WideToUTF16(L"\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
*/
// Drag selection handle 1 to right by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"d"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"d"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
EXPECT_EQ(WideToUTF16(L"\x05e2\x05e3" L"d"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
@@ -385,14 +442,14 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
/* TODO(xji): see detail of above commented out test case.
// Drag selection handle 1 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"\x05e2"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e2"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
EXPECT_EQ(WideToUTF16(L"\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
*/
// Drag selection handle 2 to right by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"d"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"d"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
EXPECT_EQ(WideToUTF16(L"\x05e2\x05e3" L"d"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
@@ -403,13 +460,13 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 2 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"c"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"c"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 2);
EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 1 to right by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"\x05e2"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e2"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 1);
EXPECT_EQ(WideToUTF16(L"c\x05e1"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
@@ -420,13 +477,13 @@ TEST_F(TouchSelectionControllerImplTest, SelectRectInBidiCallbackTest) {
VERIFY_HANDLE_POSITIONS(false);
// Drag selection handle 1 to left by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"c"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"c"), font_list);
SimulateSelectionHandleDrag(gfx::Point(-x, 0), 1);
EXPECT_EQ(WideToUTF16(L"c\x05e1\x05e2"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(true);
// Drag selection handle 2 to right by 1 char.
- x = font.GetStringWidth(WideToUTF16(L"\x05e2"));
+ x = gfx::Canvas::GetStringWidth(WideToUTF16(L"\x05e2"), font_list);
SimulateSelectionHandleDrag(gfx::Point(x, 0), 2);
EXPECT_EQ(WideToUTF16(L"c\x05e1"), textfield_->GetSelectedText());
VERIFY_HANDLE_POSITIONS(false);
@@ -444,7 +501,7 @@ TEST_F(TouchSelectionControllerImplTest,
// Tap the textfield to invoke selection.
ui::GestureEvent tap(ui::ET_GESTURE_TAP, 0, 0, 0, base::TimeDelta(),
ui::GestureEventDetails(ui::ET_GESTURE_TAP, 1.0f, 0.0f), 0);
- textfield_view_->OnGestureEvent(&tap);
+ textfield_->OnGestureEvent(&tap);
// Select some text such that one handle is hidden.
textfield_->SelectRange(gfx::Range(10, textfield_text.length()));
@@ -467,9 +524,8 @@ TEST_F(TouchSelectionControllerImplTest,
}
}
-#if defined(USE_AURA)
TEST_F(TouchSelectionControllerImplTest,
- DoubleTapInTextfieldWithCursorHandleShouldSelectWord) {
+ DoubleTapInTextfieldWithCursorHandleShouldSelectText) {
CreateTextfield();
textfield_->SetText(ASCIIToUTF16("some text"));
aura::test::EventGenerator generator(
@@ -490,8 +546,302 @@ TEST_F(TouchSelectionControllerImplTest,
generator.GestureTapAt(cursor_pos);
generator.GestureTapAt(cursor_pos);
EXPECT_TRUE(textfield_->HasSelection());
- VERIFY_HANDLE_POSITIONS(false);
}
-#endif
+
+// A simple implementation of TouchEditable that allows faking cursor position
+// inside its boundaries.
+class TestTouchEditable : public ui::TouchEditable {
+ public:
+ explicit TestTouchEditable(aura::Window* window)
+ : window_(window) {
+ DCHECK(window);
+ }
+
+ void set_bounds(const gfx::Rect& bounds) {
+ bounds_ = bounds;
+ }
+
+ void set_cursor_rect(const gfx::Rect& cursor_rect) {
+ cursor_rect_ = cursor_rect;
+ }
+
+ virtual ~TestTouchEditable() {}
+
+ private:
+ // Overridden from ui::TouchEditable.
+ virtual void SelectRect(
+ const gfx::Point& start, const gfx::Point& end) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE {
+ *p1 = *p2 = cursor_rect_;
+ }
+ virtual gfx::Rect GetBounds() OVERRIDE {
+ return gfx::Rect(bounds_.size());
+ }
+ virtual gfx::NativeView GetNativeView() const OVERRIDE {
+ return window_;
+ }
+ virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(window_->GetRootWindow());
+ if (screen_position_client)
+ screen_position_client->ConvertPointToScreen(window_, point);
+ }
+ virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE {
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(window_->GetRootWindow());
+ if (screen_position_client)
+ screen_position_client->ConvertPointFromScreen(window_, point);
+ }
+ virtual bool DrawsHandles() OVERRIDE {
+ return false;
+ }
+ virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void DestroyTouchSelection() OVERRIDE {
+ NOTREACHED();
+ }
+
+ // Overridden from ui::SimpleMenuModel::Delegate.
+ virtual bool IsCommandIdChecked(int command_id) const OVERRIDE {
+ NOTREACHED();
+ return false;
+ }
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
+ NOTREACHED();
+ return false;
+ }
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) OVERRIDE {
+ NOTREACHED();
+ return false;
+ }
+ virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE {
+ NOTREACHED();
+ }
+
+ aura::Window* window_;
+
+ // Boundaries of the client view.
+ gfx::Rect bounds_;
+
+ // Cursor position inside the client view.
+ gfx::Rect cursor_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestTouchEditable);
+};
+
+// Tests if the touch editing handle is shown or hidden properly according to
+// the cursor position relative to the client boundaries.
+TEST_F(TouchSelectionControllerImplTest,
+ VisibilityOfHandleRegardingClientBounds) {
+ CreateWidget();
+
+ TestTouchEditable touch_editable(widget_->GetNativeView());
+ scoped_ptr<ui::TouchSelectionController> touch_selection_controller(
+ ui::TouchSelectionController::create(&touch_editable));
+
+ touch_editable.set_bounds(gfx::Rect(0, 0, 100, 20));
+
+ // Put the cursor completely inside the client bounds. Handle should be
+ // visible.
+ touch_editable.set_cursor_rect(gfx::Rect(2, 0, 1, 20));
+ touch_selection_controller->SelectionChanged();
+ EXPECT_TRUE(IsCursorHandleVisibleFor(touch_selection_controller.get()));
+
+ // Move the cursor up such that |kBarMinHeight| pixels are still in the client
+ // bounds. Handle should still be visible.
+ touch_editable.set_cursor_rect(gfx::Rect(2, kBarMinHeight - 20, 1, 20));
+ touch_selection_controller->SelectionChanged();
+ EXPECT_TRUE(IsCursorHandleVisibleFor(touch_selection_controller.get()));
+
+ // Move the cursor up such that less than |kBarMinHeight| pixels are in the
+ // client bounds. Handle should be hidden.
+ touch_editable.set_cursor_rect(gfx::Rect(2, kBarMinHeight - 20 - 1, 1, 20));
+ touch_selection_controller->SelectionChanged();
+ EXPECT_FALSE(IsCursorHandleVisibleFor(touch_selection_controller.get()));
+
+ // Move the Cursor down such that |kBarBottomAllowance| pixels are out of the
+ // client bounds. Handle should be visible.
+ touch_editable.set_cursor_rect(gfx::Rect(2, kBarBottomAllowance, 1, 20));
+ touch_selection_controller->SelectionChanged();
+ EXPECT_TRUE(IsCursorHandleVisibleFor(touch_selection_controller.get()));
+
+ // Move the cursor down such that more than |kBarBottomAllowance| pixels are
+ // out of the client bounds. Handle should be hidden.
+ touch_editable.set_cursor_rect(gfx::Rect(2, kBarBottomAllowance + 1, 1, 20));
+ touch_selection_controller->SelectionChanged();
+ EXPECT_FALSE(IsCursorHandleVisibleFor(touch_selection_controller.get()));
+
+ touch_selection_controller.reset();
+}
+
+TEST_F(TouchSelectionControllerImplTest, HandlesStackAboveParent) {
+ ui::EventTarget* root = GetContext();
+ ui::EventTargeter* targeter = root->GetEventTargeter();
+
+ // Create the first window containing a Views::Textfield.
+ CreateTextfield();
+ aura::Window* window1 = textfield_widget_->GetNativeView();
+
+ // Start touch editing, check that the handle is above the first window, and
+ // end touch editing.
+ StartTouchEditing();
+ gfx::Point test_point = GetCursorHandleDragPoint();
+ ui::MouseEvent test_event1(ui::ET_MOUSE_MOVED, test_point, test_point,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(GetCursorHandleNativeView(),
+ targeter->FindTargetForEvent(root, &test_event1));
+ EndTouchEditing();
+
+ // Create the second (empty) window over the first one.
+ CreateWidget();
+ aura::Window* window2 = widget_->GetNativeView();
+
+ // Start touch editing (in the first window) and check that the handle is not
+ // above the second window.
+ StartTouchEditing();
+ ui::MouseEvent test_event2(ui::ET_MOUSE_MOVED, test_point, test_point,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(window2, targeter->FindTargetForEvent(root, &test_event2));
+
+ // Move the first window to top and check that the handle is kept above the
+ // first window.
+ window1->GetRootWindow()->StackChildAtTop(window1);
+ ui::MouseEvent test_event3(ui::ET_MOUSE_MOVED, test_point, test_point,
+ ui::EF_NONE, ui::EF_NONE);
+ EXPECT_EQ(GetCursorHandleNativeView(),
+ targeter->FindTargetForEvent(root, &test_event3));
+}
+
+// A simple implementation of TouchEditingMenuController that enables all
+// available commands.
+class TestTouchEditingMenuController : public TouchEditingMenuController {
+ public:
+ TestTouchEditingMenuController() {}
+ virtual ~TestTouchEditingMenuController() {}
+
+ // Overriden from TouchEditingMenuController.
+ virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
+ // Return true, since we want the menu to have all |kMenuCommandCount|
+ // available commands.
+ return true;
+ }
+ virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void OpenContextMenu() OVERRIDE {
+ NOTREACHED();
+ }
+ virtual void OnMenuClosed(TouchEditingMenuView* menu) OVERRIDE {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestTouchEditingMenuController);
+};
+
+// Tests if anchor rect for touch editing quick menu is adjusted correctly based
+// on the distance of handles.
+TEST_F(TouchSelectionControllerImplTest, QuickMenuAdjustsAnchorRect) {
+ CreateWidget();
+ aura::Window* window = widget_->GetNativeView();
+
+ scoped_ptr<TestTouchEditingMenuController> quick_menu_controller(
+ new TestTouchEditingMenuController());
+
+ // Some arbitrary size for touch editing handle image.
+ gfx::Size handle_image_size(10, 10);
+
+ // Calculate the width of quick menu. In addition to |kMenuCommandCount|
+ // commands, there is an item for ellipsis.
+ int quick_menu_width = (kMenuCommandCount + 1) * kMenuButtonWidth +
+ kMenuCommandCount;
+
+ // Set anchor rect's width a bit smaller than the quick menu width plus handle
+ // image width and check that anchor rect's height is adjusted.
+ gfx::Rect anchor_rect(
+ 0, 0, quick_menu_width + handle_image_size.width() - 10, 20);
+ TouchEditingMenuView* quick_menu(TouchEditingMenuView::Create(
+ quick_menu_controller.get(), anchor_rect, handle_image_size, window));
+ anchor_rect.Inset(0, 0, 0, -handle_image_size.height());
+ EXPECT_EQ(anchor_rect.ToString(), quick_menu->GetAnchorRect().ToString());
+
+ // Set anchor rect's width a bit greater than the quick menu width plus handle
+ // image width and check that anchor rect's height is not adjusted.
+ anchor_rect =
+ gfx::Rect(0, 0, quick_menu_width + handle_image_size.width() + 10, 20);
+ quick_menu = TouchEditingMenuView::Create(
+ quick_menu_controller.get(), anchor_rect, handle_image_size, window);
+ EXPECT_EQ(anchor_rect.ToString(), quick_menu->GetAnchorRect().ToString());
+
+ // Close the widget, hence quick menus, before quick menu controller goes out
+ // of scope.
+ widget_->CloseNow();
+ widget_ = NULL;
+}
+
+TEST_F(TouchSelectionControllerImplTest, MouseEventDeactivatesTouchSelection) {
+ CreateTextfield();
+ EXPECT_FALSE(GetSelectionController());
+
+ aura::test::EventGenerator generator(
+ textfield_widget_->GetNativeView()->GetRootWindow());
+
+ generator.set_current_location(gfx::Point(5, 5));
+ RunPendingMessages();
+
+ // Start touch editing; then move mouse over the textfield and ensure it
+ // deactivates touch selection.
+ StartTouchEditing();
+ EXPECT_TRUE(GetSelectionController());
+ generator.MoveMouseTo(gfx::Point(5, 10));
+ RunPendingMessages();
+ EXPECT_FALSE(GetSelectionController());
+
+ generator.MoveMouseTo(gfx::Point(5, 50));
+ RunPendingMessages();
+
+ // Start touch editing; then move mouse out of the textfield, but inside the
+ // winow and ensure it deactivates touch selection.
+ StartTouchEditing();
+ EXPECT_TRUE(GetSelectionController());
+ generator.MoveMouseTo(gfx::Point(5, 55));
+ RunPendingMessages();
+ EXPECT_FALSE(GetSelectionController());
+
+ generator.MoveMouseTo(gfx::Point(5, 500));
+ RunPendingMessages();
+
+ // Start touch editing; then move mouse out of the textfield and window and
+ // ensure it deactivates touch selection.
+ StartTouchEditing();
+ EXPECT_TRUE(GetSelectionController());
+ generator.MoveMouseTo(5, 505);
+ RunPendingMessages();
+ EXPECT_FALSE(GetSelectionController());
+}
+
+TEST_F(TouchSelectionControllerImplTest, KeyEventDeactivatesTouchSelection) {
+ CreateTextfield();
+ EXPECT_FALSE(GetSelectionController());
+
+ aura::test::EventGenerator generator(
+ textfield_widget_->GetNativeView()->GetRootWindow());
+
+ RunPendingMessages();
+
+ // Start touch editing; then press a key and ensure it deactivates touch
+ // selection.
+ StartTouchEditing();
+ EXPECT_TRUE(GetSelectionController());
+ generator.PressKey(ui::VKEY_A, 0);
+ RunPendingMessages();
+ EXPECT_FALSE(GetSelectionController());
+}
} // namespace views
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index 40ad7cce2d9..c8ebd0abb67 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -16,9 +16,9 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkRect.h"
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
@@ -39,6 +39,7 @@
#include "ui/views/border.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/drag_controller.h"
+#include "ui/views/focus/view_storage.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/rect_based_targeting_utils.h"
#include "ui/views/views_delegate.h"
@@ -47,24 +48,12 @@
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
-
#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
#endif
namespace {
-// Whether to use accelerated compositing when necessary (e.g. when a view has a
-// transformation).
-#if defined(USE_AURA)
-bool use_acceleration_when_possible = true;
-#else
-bool use_acceleration_when_possible = false;
-#endif
-
#if defined(OS_WIN)
const bool kContextMenuOnMousePress = false;
#else
@@ -76,6 +65,14 @@ const bool kContextMenuOnMousePress = true;
// rect-based targeting algorithm.
static const float kRectTargetOverlap = 0.6f;
+// Default horizontal drag threshold in pixels.
+// Same as what gtk uses.
+const int kDefaultHorizontalDragThreshold = 8;
+
+// Default vertical drag threshold in pixels.
+// Same as what gtk uses.
+const int kDefaultVerticalDragThreshold = 8;
+
// Returns the top view in |view|'s hierarchy.
const views::View* GetHierarchyRoot(const views::View* view) {
const views::View* root = view;
@@ -90,54 +87,6 @@ namespace views {
namespace internal {
-// This event handler receives events in the post-target phase and takes care of
-// the following:
-// - Generates context menu, or initiates drag-and-drop, from gesture events.
-class PostEventDispatchHandler : public ui::EventHandler {
- public:
- explicit PostEventDispatchHandler(View* owner)
- : owner_(owner),
- touch_dnd_enabled_(switches::IsTouchDragDropEnabled()) {
- }
- virtual ~PostEventDispatchHandler() {}
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
- DCHECK_EQ(ui::EP_POSTTARGET, event->phase());
- if (event->handled())
- return;
-
- if (touch_dnd_enabled_) {
- if (event->type() == ui::ET_GESTURE_LONG_PRESS &&
- (!owner_->drag_controller() ||
- owner_->drag_controller()->CanStartDragForView(
- owner_, event->location(), event->location()))) {
- if (owner_->DoDrag(*event, event->location(),
- ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH)) {
- event->StopPropagation();
- return;
- }
- }
- }
-
- if (owner_->context_menu_controller() &&
- (event->type() == ui::ET_GESTURE_LONG_PRESS ||
- event->type() == ui::ET_GESTURE_LONG_TAP ||
- event->type() == ui::ET_GESTURE_TWO_FINGER_TAP)) {
- gfx::Point location(event->location());
- View::ConvertPointToScreen(owner_, &location);
- owner_->ShowContextMenu(location, ui::MENU_SOURCE_TOUCH);
- event->StopPropagation();
- }
- }
-
- View* owner_;
- bool touch_dnd_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler);
-};
-
} // namespace internal
// static
@@ -160,6 +109,7 @@ View::View()
enabled_(true),
notify_enter_exit_on_child_(false),
registered_for_visible_bounds_notification_(false),
+ root_bounds_dirty_(true),
clip_insets_(0, 0, 0, 0),
needs_layout_(true),
flip_canvas_on_paint_for_rtl_ui_(false),
@@ -172,15 +122,15 @@ View::View()
accessibility_focusable_(false),
context_menu_controller_(NULL),
drag_controller_(NULL),
- post_dispatch_handler_(new internal::PostEventDispatchHandler(this)),
native_view_accessibility_(NULL) {
- AddPostTargetHandler(post_dispatch_handler_.get());
}
View::~View() {
if (parent_)
parent_->RemoveChildView(this);
+ ViewStorage::GetInstance()->ViewRemoved(this);
+
for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) {
(*i)->parent_ = NULL;
if (!(*i)->owned_by_client_)
@@ -217,8 +167,9 @@ void View::AddChildViewAt(View* view, int index) {
// If |view| has a parent, remove it from its parent.
View* parent = view->parent_;
- const ui::NativeTheme* old_theme = view->GetNativeTheme();
+ ui::NativeTheme* old_theme = NULL;
if (parent) {
+ old_theme = view->GetNativeTheme();
if (parent == this) {
ReorderChildView(view, index);
return;
@@ -233,6 +184,16 @@ void View::AddChildViewAt(View* view, int index) {
view->parent_ = this;
children_.insert(children_.begin() + index, view);
+ // Instruct the view to recompute its root bounds on next Paint().
+ view->SetRootBoundsDirty(true);
+
+ views::Widget* widget = GetWidget();
+ if (widget) {
+ const ui::NativeTheme* new_theme = view->GetNativeTheme();
+ if (new_theme != old_theme)
+ view->PropagateNativeThemeChanged(new_theme);
+ }
+
ViewHierarchyChangedDetails details(true, this, view, parent);
for (View* v = this; v; v = v->parent_)
@@ -240,19 +201,16 @@ void View::AddChildViewAt(View* view, int index) {
view->PropagateAddNotifications(details);
UpdateTooltip();
- views::Widget* widget = GetWidget();
if (widget) {
RegisterChildrenForVisibleBoundsNotification(view);
- const ui::NativeTheme* new_theme = widget->GetNativeTheme();
- if (new_theme != old_theme)
- PropagateNativeThemeChanged(new_theme);
+ if (view->visible())
+ view->SchedulePaint();
}
if (layout_manager_.get())
layout_manager_->ViewAdded(this, view);
- if (use_acceleration_when_possible)
- ReorderLayers();
+ ReorderLayers();
// Make sure the visibility of the child layers are correct.
// If any of the parent View is hidden, then the layers of the subtree
@@ -286,8 +244,7 @@ void View::ReorderChildView(View* view, int index) {
InitFocusSiblings(view, index);
children_.insert(children_.begin() + index, view);
- if (use_acceleration_when_possible)
- ReorderLayers();
+ ReorderLayers();
}
void View::RemoveChildView(View* view) {
@@ -416,7 +373,7 @@ gfx::Rect View::GetBoundsInScreen() const {
return gfx::Rect(origin, size());
}
-gfx::Size View::GetPreferredSize() {
+gfx::Size View::GetPreferredSize() const {
if (layout_manager_.get())
return layout_manager_->GetPreferredSize(this);
return gfx::Size();
@@ -432,15 +389,15 @@ void View::SizeToPreferredSize() {
SetBounds(x(), y(), prefsize.width(), prefsize.height());
}
-gfx::Size View::GetMinimumSize() {
+gfx::Size View::GetMinimumSize() const {
return GetPreferredSize();
}
-gfx::Size View::GetMaximumSize() {
+gfx::Size View::GetMaximumSize() const {
return gfx::Size();
}
-int View::GetHeightForWidth(int w) {
+int View::GetHeightForWidth(int w) const {
if (layout_manager_.get())
return layout_manager_->GetPreferredHeightForWidth(this, w);
return GetPreferredSize().height();
@@ -508,6 +465,31 @@ void View::SetTransform(const gfx::Transform& transform) {
}
void View::SetPaintToLayer(bool paint_to_layer) {
+ if (paint_to_layer_ == paint_to_layer)
+ return;
+
+ // If this is a change in state we will also need to update bounds trees.
+ if (paint_to_layer) {
+ // Gaining a layer means becoming a paint root. We must remove ourselves
+ // from our old paint root, if we had one. Traverse up view tree to find old
+ // paint root.
+ View* old_paint_root = parent_;
+ while (old_paint_root && !old_paint_root->IsPaintRoot())
+ old_paint_root = old_paint_root->parent_;
+
+ // Remove our and our children's bounds from the old tree. This will also
+ // mark all of our bounds as dirty.
+ if (old_paint_root && old_paint_root->bounds_tree_)
+ RemoveRootBounds(old_paint_root->bounds_tree_.get());
+
+ } else {
+ // Losing a layer means we are no longer a paint root, so delete our
+ // bounds tree and mark ourselves as dirty for future insertion into our
+ // new paint root's bounds tree.
+ bounds_tree_.reset();
+ SetRootBoundsDirty(true);
+ }
+
paint_to_layer_ = paint_to_layer;
if (paint_to_layer_ && !layer()) {
CreateLayer();
@@ -516,16 +498,6 @@ void View::SetPaintToLayer(bool paint_to_layer) {
}
}
-ui::Layer* View::RecreateLayer() {
- ui::Layer* layer = AcquireLayer();
- if (!layer)
- return NULL;
-
- CreateLayer();
- layer_->set_scale_content(layer->scale_content());
- return layer;
-}
-
// RTL positioning -------------------------------------------------------------
gfx::Rect View::GetMirroredBounds() const {
@@ -606,14 +578,19 @@ const char* View::GetClassName() const {
return kViewClassName;
}
-View* View::GetAncestorWithClassName(const std::string& name) {
- for (View* view = this; view; view = view->parent_) {
+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()))
return view;
}
return NULL;
}
+View* View::GetAncestorWithClassName(const std::string& name) {
+ return const_cast<View*>(const_cast<const View*>(this)->
+ GetAncestorWithClassName(name));
+}
+
const View* View::GetViewByID(int id) const {
if (id == id_)
return const_cast<View*>(this);
@@ -773,40 +750,73 @@ void View::SchedulePaintInRect(const gfx::Rect& rect) {
}
}
-void View::Paint(gfx::Canvas* canvas) {
- TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
+void View::Paint(gfx::Canvas* canvas, const CullSet& cull_set) {
+ // The cull_set may allow us to skip painting without canvas construction or
+ // even canvas rect intersection.
+ if (cull_set.ShouldPaint(this)) {
+ TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
- gfx::ScopedCanvas scoped_canvas(canvas);
+ gfx::ScopedCanvas scoped_canvas(canvas);
- // Paint this View and its children, setting the clip rect to the bounds
- // of this View and translating the origin to the local bounds' top left
- // point.
- //
- // Note that the X (or left) position we pass to ClipRectInt takes into
- // consideration whether or not the view uses a right-to-left layout so that
- // we paint our view in its mirrored position if need be.
- gfx::Rect clip_rect = bounds();
- clip_rect.Inset(clip_insets_);
- if (parent_)
- clip_rect.set_x(parent_->GetMirroredXForRect(clip_rect));
- if (!canvas->ClipRect(clip_rect))
- return;
+ // Paint this View and its children, setting the clip rect to the bounds
+ // of this View and translating the origin to the local bounds' top left
+ // point.
+ //
+ // Note that the X (or left) position we pass to ClipRectInt takes into
+ // consideration whether or not the view uses a right-to-left layout so that
+ // we paint our view in its mirrored position if need be.
+ gfx::Rect clip_rect = bounds();
+ clip_rect.Inset(clip_insets_);
+ if (parent_)
+ clip_rect.set_x(parent_->GetMirroredXForRect(clip_rect));
+ canvas->ClipRect(clip_rect);
+ if (canvas->IsClipEmpty())
+ return;
+
+ // Non-empty clip, translate the graphics such that 0,0 corresponds to where
+ // this view is located (related to its parent).
+ canvas->Translate(GetMirroredPosition().OffsetFromOrigin());
+ canvas->Transform(GetTransform());
- // Non-empty clip, translate the graphics such that 0,0 corresponds to
- // where this view is located (related to its parent).
- canvas->Translate(GetMirroredPosition().OffsetFromOrigin());
- canvas->Transform(GetTransform());
+ // If we are a paint root, we need to construct our own CullSet object for
+ // propagation to our children.
+ if (IsPaintRoot()) {
+ if (!bounds_tree_)
+ bounds_tree_.reset(new BoundsTree(2, 5));
- PaintCommon(canvas);
+ // Recompute our bounds tree as needed.
+ UpdateRootBounds(bounds_tree_.get(), gfx::Vector2d());
+
+ // Grab the clip rect from the supplied canvas to use as the query rect.
+ gfx::Rect canvas_bounds;
+ if (!canvas->GetClipBounds(&canvas_bounds)) {
+ NOTREACHED() << "Failed to get clip bounds from the canvas!";
+ return;
+ }
+
+ // Now query our bounds_tree_ for a set of damaged views that intersect
+ // our canvas bounds.
+ scoped_ptr<base::hash_set<intptr_t> > damaged_views(
+ new base::hash_set<intptr_t>());
+ bounds_tree_->AppendIntersectingRecords(
+ canvas_bounds, damaged_views.get());
+ // Construct a CullSet to wrap the damaged views set, it will delete it
+ // for us on scope exit.
+ CullSet paint_root_cull_set(damaged_views.Pass());
+ // Paint all descendents using our new cull set.
+ PaintCommon(canvas, paint_root_cull_set);
+ } else {
+ // Not a paint root, so we can proceed as normal.
+ PaintCommon(canvas, cull_set);
+ }
+ }
}
void View::set_background(Background* b) {
background_.reset(b);
}
-void View::set_border(Border* b) {
- border_.reset(b);
-}
+void View::SetBorder(scoped_ptr<Border> b) { border_ = b.Pass(); }
ui::ThemeProvider* View::GetThemeProvider() const {
const Widget* widget = GetWidget();
@@ -818,18 +828,6 @@ const ui::NativeTheme* View::GetNativeTheme() const {
return widget ? widget->GetNativeTheme() : ui::NativeTheme::instance();
}
-// Accelerated Painting --------------------------------------------------------
-
-// static
-void View::set_use_acceleration_when_possible(bool use) {
- use_acceleration_when_possible = use;
-}
-
-// static
-bool View::get_use_acceleration_when_possible() {
- return use_acceleration_when_possible;
-}
-
// Input -----------------------------------------------------------------------
View* View::GetEventHandlerForPoint(const gfx::Point& point) {
@@ -852,6 +850,9 @@ View* View::GetEventHandlerForRect(const gfx::Rect& rect) {
for (int i = child_count() - 1; i >= 0; --i) {
View* child = child_at(i);
+ if (!child->CanProcessEventsWithinSubtree())
+ continue;
+
// Ignore any children which are invisible or do not intersect |rect|.
if (!child->visible())
continue;
@@ -907,8 +908,12 @@ View* View::GetEventHandlerForRect(const gfx::Rect& rect) {
return rect_view ? rect_view : point_view;
}
+bool View::CanProcessEventsWithinSubtree() const {
+ return true;
+}
+
View* View::GetTooltipHandlerForPoint(const gfx::Point& point) {
- if (!HitTestPoint(point))
+ if (!HitTestPoint(point) || !CanProcessEventsWithinSubtree())
return NULL;
// Walk the child Views recursively looking for the View that most
@@ -929,16 +934,11 @@ View* View::GetTooltipHandlerForPoint(const gfx::Point& point) {
gfx::NativeCursor View::GetCursor(const ui::MouseEvent& event) {
#if defined(OS_WIN)
-#if defined(USE_AURA)
static ui::Cursor arrow;
if (!arrow.platform())
arrow.SetPlatformCursor(LoadCursor(NULL, IDC_ARROW));
return arrow;
#else
- static HCURSOR arrow = LoadCursor(NULL, IDC_ARROW);
- return arrow;
-#endif
-#else
return gfx::kNullCursor;
#endif
}
@@ -955,18 +955,11 @@ bool View::HitTestRect(const gfx::Rect& rect) const {
if (!views::UsePointBasedTargeting(rect))
source = HIT_TEST_SOURCE_TOUCH;
GetHitTestMask(source, &mask);
-#if defined(USE_AURA)
- // TODO: should we use this every where?
SkRegion clip_region;
clip_region.setRect(0, 0, width(), height());
SkRegion mask_region;
return mask_region.setPath(mask, clip_region) &&
mask_region.intersects(RectToSkIRect(rect));
-#elif defined(OS_WIN)
- base::win::ScopedRegion rgn(mask.CreateNativeRegion());
- const RECT r(rect.ToRECT());
- return RectInRegion(rgn, &r) != 0;
-#endif
}
// No mask, but inside our bounds.
return true;
@@ -1070,6 +1063,8 @@ void View::OnMouseEvent(ui::MouseEvent* event) {
break;
case ui::ET_MOUSE_ENTERED:
+ if (event->flags() & ui::EF_TOUCH_ACCESSIBILITY)
+ NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
OnMouseEntered(*event);
break;
@@ -1086,6 +1081,7 @@ void View::OnScrollEvent(ui::ScrollEvent* event) {
}
void View::OnTouchEvent(ui::TouchEvent* event) {
+ NOTREACHED() << "Views should not receive touch events.";
}
void View::OnGestureEvent(ui::GestureEvent* event) {
@@ -1105,6 +1101,13 @@ const InputMethod* View::GetInputMethod() const {
return widget ? widget->GetInputMethod() : NULL;
}
+scoped_ptr<ui::EventTargeter>
+View::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) {
+ scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass();
+ targeter_ = targeter.Pass();
+ return old_targeter.Pass();
+}
+
bool View::CanAcceptEvent(const ui::Event& event) {
return IsDrawn();
}
@@ -1119,7 +1122,16 @@ scoped_ptr<ui::EventTargetIterator> View::GetChildIterator() const {
}
ui::EventTargeter* View::GetEventTargeter() {
- return NULL;
+ return targeter_.get();
+}
+
+const ui::EventTargeter* View::GetEventTargeter() const {
+ return targeter_.get();
+}
+
+void View::ConvertEventToTarget(ui::EventTarget* target,
+ ui::LocatedEvent* event) {
+ event->ConvertLocationToTarget(this, static_cast<View*>(target));
}
// Accelerators ----------------------------------------------------------------
@@ -1252,7 +1264,7 @@ FocusTraversable* View::GetPaneFocusTraversable() {
// Tooltips --------------------------------------------------------------------
-bool View::GetTooltipText(const gfx::Point& p, string16* tooltip) const {
+bool View::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
return false;
}
@@ -1326,12 +1338,12 @@ gfx::NativeViewAccessible View::GetNativeViewAccessible() {
}
void View::NotifyAccessibilityEvent(
- ui::AccessibilityTypes::Event event_type,
+ ui::AXEvent event_type,
bool send_native_event) {
if (ViewsDelegate::views_delegate)
ViewsDelegate::views_delegate->NotifyAccessibilityEvent(this, event_type);
- if (send_native_event) {
+ if (send_native_event && GetWidget()) {
if (!native_view_accessibility_)
native_view_accessibility_ = NativeViewAccessibility::Create(this);
if (native_view_accessibility_)
@@ -1402,11 +1414,11 @@ void View::NativeViewHierarchyChanged() {
// Painting --------------------------------------------------------------------
-void View::PaintChildren(gfx::Canvas* canvas) {
+void View::PaintChildren(gfx::Canvas* canvas, const CullSet& cull_set) {
TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName());
for (int i = 0, count = child_count(); i < count; ++i)
if (!child_at(i)->layer())
- child_at(i)->Paint(canvas);
+ child_at(i)->Paint(canvas, cull_set);
}
void View::OnPaint(gfx::Canvas* canvas) {
@@ -1433,6 +1445,10 @@ void View::OnPaintBorder(gfx::Canvas* canvas) {
}
}
+bool View::IsPaintRoot() {
+ return paint_to_layer_ || !parent_;
+}
+
// Accelerated Painting --------------------------------------------------------
void View::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
@@ -1484,8 +1500,6 @@ void View::MoveLayerToParent(ui::Layer* parent_layer,
}
void View::UpdateLayerVisibility() {
- if (!use_acceleration_when_possible)
- return;
bool visible = visible_;
for (const View* v = parent_; visible && v && !v->layer(); v = v->parent_)
visible = v->visible();
@@ -1517,7 +1531,7 @@ void View::UpdateChildLayerBounds(const gfx::Vector2d& offset) {
void View::OnPaintLayer(gfx::Canvas* canvas) {
if (!layer() || !layer()->fills_bounds_opaquely())
canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode);
- PaintCommon(canvas);
+ PaintCommon(canvas, CullSet());
}
void View::OnDeviceScaleFactorChanged(float device_scale_factor) {
@@ -1562,7 +1576,7 @@ void View::ReorderChildLayers(ui::Layer* parent_layer) {
// Iterate backwards through the children so that a child with a layer
// which is further to the back is stacked above one which is further to
// the front.
- for (Views::const_reverse_iterator it(children_.rbegin());
+ for (Views::reverse_iterator it(children_.rbegin());
it != children_.rend(); ++it) {
(*it)->ReorderChildLayers(parent_layer);
}
@@ -1597,7 +1611,7 @@ void View::OnFocus() {
// TODO(beng): Investigate whether it's possible for us to move this to
// Focus().
// Notify assistive technologies of the focus change.
- NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
}
void View::OnBlur() {
@@ -1648,6 +1662,18 @@ bool View::InDrag() {
return widget ? widget->dragged_view() == this : false;
}
+int View::GetHorizontalDragThreshold() {
+ // TODO(jennyz): This value may need to be adjusted for different platforms
+ // and for different display density.
+ return kDefaultHorizontalDragThreshold;
+}
+
+int View::GetVerticalDragThreshold() {
+ // TODO(jennyz): This value may need to be adjusted for different platforms
+ // and for different display density.
+ return kDefaultVerticalDragThreshold;
+}
+
// Debugging -------------------------------------------------------------------
#if !defined(NDEBUG)
@@ -1722,7 +1748,7 @@ std::string View::DoPrintViewGraph(bool first, View* view_with_children) {
if (!parent_)
result.append(", shape=box");
if (layer()) {
- if (layer()->texture())
+ if (layer()->has_external_content())
result.append(", color=green");
else
result.append(", color=red");
@@ -1753,7 +1779,6 @@ std::string View::DoPrintViewGraph(bool first, View* view_with_children) {
return result;
}
-
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -1790,7 +1815,7 @@ void View::SchedulePaintBoundsChanged(SchedulePaintType type) {
}
}
-void View::PaintCommon(gfx::Canvas* canvas) {
+void View::PaintCommon(gfx::Canvas* canvas, const CullSet& cull_set) {
if (!visible_)
return;
@@ -1809,7 +1834,7 @@ void View::PaintCommon(gfx::Canvas* canvas) {
OnPaint(canvas);
}
- PaintChildren(canvas);
+ PaintChildren(canvas, cull_set);
}
// Tree operations -------------------------------------------------------------
@@ -1820,6 +1845,7 @@ void View::DoRemoveChildView(View* view,
bool delete_removed_view,
View* new_parent) {
DCHECK(view);
+
const Views::iterator i(std::find(children_.begin(), children_.end(), view));
scoped_ptr<View> view_to_be_deleted;
if (i != children_.end()) {
@@ -1833,8 +1859,19 @@ void View::DoRemoveChildView(View* view,
next_focusable->previous_focusable_view_ = prev_focusable;
}
- if (GetWidget())
+ if (GetWidget()) {
UnregisterChildrenForVisibleBoundsNotification(view);
+ if (view->visible())
+ view->SchedulePaint();
+ GetWidget()->NotifyWillRemoveView(view);
+ }
+
+ // Remove the bounds of this child and any of its descendants from our
+ // paint root bounds tree.
+ BoundsTree* bounds_tree = GetBoundsTreeFromPaintRoot();
+ if (bounds_tree)
+ view->RemoveRootBounds(bounds_tree);
+
view->PropagateRemoveNotifications(this, new_parent);
view->parent_ = NULL;
view->UpdateLayerVisibility();
@@ -1898,11 +1935,9 @@ void View::ViewHierarchyChangedImpl(
// Make sure the layers belonging to the subtree rooted at |child| get
// removed from layers that do not belong in the same subtree.
OrphanLayers();
- if (use_acceleration_when_possible) {
- Widget* widget = GetWidget();
- if (widget)
- widget->UpdateRootLayers();
- }
+ Widget* widget = GetWidget();
+ if (widget)
+ widget->UpdateRootLayers();
}
ViewHierarchyChanged(details);
@@ -1928,6 +1963,12 @@ void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
}
void View::BoundsChanged(const gfx::Rect& previous_bounds) {
+ // Mark our bounds as dirty for the paint root, also see if we need to
+ // recompute our children's bounds due to origin change.
+ bool origin_changed =
+ previous_bounds.OffsetFromOrigin() != bounds_.OffsetFromOrigin();
+ SetRootBoundsDirty(origin_changed);
+
if (visible_) {
// Paint the new bounds.
SchedulePaintBoundsChanged(
@@ -1935,28 +1976,18 @@ void View::BoundsChanged(const gfx::Rect& previous_bounds) {
SCHEDULE_PAINT_SIZE_CHANGED);
}
- if (use_acceleration_when_possible) {
- if (layer()) {
- if (parent_) {
- SetLayerBounds(GetLocalBounds() +
- gfx::Vector2d(GetMirroredX(), y()) +
- parent_->CalculateOffsetToAncestorWithLayer(NULL));
- } else {
- SetLayerBounds(bounds_);
- }
- // TODO(beng): this seems redundant with the SchedulePaint at the top of
- // this function. explore collapsing.
- if (previous_bounds.size() != bounds_.size() &&
- !layer()->layer_updated_externally()) {
- // If our bounds have changed then we need to update the complete
- // texture.
- layer()->SchedulePaint(GetLocalBounds());
- }
+ if (layer()) {
+ if (parent_) {
+ SetLayerBounds(GetLocalBounds() +
+ gfx::Vector2d(GetMirroredX(), y()) +
+ parent_->CalculateOffsetToAncestorWithLayer(NULL));
} else {
- // If our bounds have changed, then any descendant layer bounds may
- // have changed. Update them accordingly.
- UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL));
+ SetLayerBounds(bounds_);
}
+ } else {
+ // If our bounds have changed, then any descendant layer bounds may have
+ // changed. Update them accordingly.
+ UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL));
}
OnBoundsChanged(previous_bounds);
@@ -2034,6 +2065,69 @@ void View::SetLayerBounds(const gfx::Rect& bounds) {
layer()->SetBounds(bounds);
}
+void View::SetRootBoundsDirty(bool origin_changed) {
+ root_bounds_dirty_ = true;
+
+ if (origin_changed) {
+ // Inform our children that their root bounds are dirty, as their relative
+ // coordinates in paint root space have changed since ours have changed.
+ for (Views::const_iterator i(children_.begin()); i != children_.end();
+ ++i) {
+ if (!(*i)->IsPaintRoot())
+ (*i)->SetRootBoundsDirty(origin_changed);
+ }
+ }
+}
+
+void View::UpdateRootBounds(BoundsTree* tree, const gfx::Vector2d& offset) {
+ // No need to recompute bounds if we haven't flagged ours as dirty.
+ TRACE_EVENT1("views", "View::UpdateRootBounds", "class", GetClassName());
+
+ // Add our own offset to the provided offset, for our own bounds update and
+ // for propagation to our children if needed.
+ gfx::Vector2d view_offset = offset + GetMirroredBounds().OffsetFromOrigin();
+
+ // If our bounds have changed we must re-insert our new bounds to the tree.
+ if (root_bounds_dirty_) {
+ root_bounds_dirty_ = false;
+ gfx::Rect bounds(
+ view_offset.x(), view_offset.y(), bounds_.width(), bounds_.height());
+ tree->Insert(bounds, reinterpret_cast<intptr_t>(this));
+ }
+
+ // Update our children's bounds if needed.
+ for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) {
+ // We don't descend in to layer views for bounds recomputation, as they
+ // manage their own RTree as paint roots.
+ if (!(*i)->IsPaintRoot())
+ (*i)->UpdateRootBounds(tree, view_offset);
+ }
+}
+
+void View::RemoveRootBounds(BoundsTree* tree) {
+ tree->Remove(reinterpret_cast<intptr_t>(this));
+
+ root_bounds_dirty_ = true;
+
+ for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) {
+ if (!(*i)->IsPaintRoot())
+ (*i)->RemoveRootBounds(tree);
+ }
+}
+
+View::BoundsTree* View::GetBoundsTreeFromPaintRoot() {
+ BoundsTree* bounds_tree = bounds_tree_.get();
+ View* paint_root = this;
+ while (!bounds_tree && !paint_root->IsPaintRoot()) {
+ // Assumption is that if IsPaintRoot() is false then parent_ is valid.
+ DCHECK(paint_root);
+ paint_root = paint_root->parent_;
+ bounds_tree = paint_root->bounds_tree_.get();
+ }
+
+ return bounds_tree;
+}
+
// Transformations -------------------------------------------------------------
bool View::GetTransformRelativeTo(const View* ancestor,
@@ -2101,11 +2195,10 @@ void View::CreateLayer() {
for (int i = 0, count = child_count(); i < count; ++i)
child_at(i)->UpdateChildLayerVisibility(true);
- layer_ = new ui::Layer();
- layer_owner_.reset(layer_);
- layer_->set_delegate(this);
+ SetLayer(new ui::Layer());
+ layer()->set_delegate(this);
#if !defined(NDEBUG)
- layer_->set_name(GetClassName());
+ layer()->set_name(GetClassName());
#endif
UpdateParentLayers();
@@ -2146,11 +2239,11 @@ void View::OrphanLayers() {
}
void View::ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer) {
- layer_->SetBounds(GetLocalBounds() + offset);
+ layer()->SetBounds(GetLocalBounds() + offset);
DCHECK_NE(layer(), parent_layer);
if (parent_layer)
parent_layer->Add(layer());
- layer_->SchedulePaint(GetLocalBounds());
+ layer()->SchedulePaint(GetLocalBounds());
MoveLayerToParent(layer(), gfx::Point());
}
@@ -2163,8 +2256,7 @@ void View::DestroyLayer() {
new_parent->Add(children[i]);
}
- layer_ = NULL;
- layer_owner_.reset();
+ LayerOwner::DestroyLayer();
if (new_parent)
ReorderLayers();
@@ -2189,6 +2281,15 @@ bool View::ProcessMousePressed(const ui::MouseEvent& event) {
context_menu_controller_ : 0;
View::DragInfo* drag_info = GetDragInfo();
+ // TODO(sky): for debugging 360238.
+ int storage_id = 0;
+ if (event.IsOnlyRightMouseButton() && context_menu_controller &&
+ kContextMenuOnMousePress && HitTestPoint(event.location())) {
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ storage_id = view_storage->CreateStorageID();
+ view_storage->StoreView(storage_id, this);
+ }
+
const bool enabled = enabled_;
const bool result = OnMousePressed(event);
@@ -2201,6 +2302,8 @@ bool View::ProcessMousePressed(const ui::MouseEvent& event) {
// from mouse pressed.
gfx::Point location(event.location());
if (HitTestPoint(location)) {
+ if (storage_id != 0)
+ CHECK_EQ(this, ViewStorage::GetInstance()->RetrieveView(storage_id));
ConvertPointToScreen(this, &location);
ShowContextMenu(location, ui::MENU_SOURCE_MOUSE);
return true;
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index dd298edc0a7..93cbd481ddb 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -16,8 +16,8 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/accessibility/accessibility_types.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@@ -26,10 +26,13 @@
#include "ui/compositor/layer_owner.h"
#include "ui/events/event.h"
#include "ui/events/event_target.h"
+#include "ui/events/event_targeter.h"
+#include "ui/gfx/geometry/r_tree.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d.h"
+#include "ui/views/cull_set.h"
#include "ui/views/views_export.h"
#if defined(OS_WIN)
@@ -46,7 +49,7 @@ class Transform;
}
namespace ui {
-struct AccessibleViewState;
+struct AXViewState;
class Compositor;
class Layer;
class NativeTheme;
@@ -70,6 +73,7 @@ class ScrollView;
class Widget;
namespace internal {
+class PreEventDispatchHandler;
class PostEventDispatchHandler;
class RootView;
}
@@ -106,8 +110,9 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
public:
typedef std::vector<View*> Views;
- // TODO(tdanderson,sadrul): Becomes obsolete with the refactoring of the
- // event targeting logic for views and windows.
+ // TODO(tdanderson): Becomes obsolete with the refactoring of the event
+ // targeting logic for views and windows. See
+ // crbug.com/355425.
// Specifies the source of the region used in a hit test.
// HIT_TEST_SOURCE_MOUSE indicates the hit test is being performed with a
// single point and HIT_TEST_SOURCE_TOUCH indicates the hit test is being
@@ -260,24 +265,24 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
virtual int GetBaseline() const;
// Get the size the View would like to be, if enough space were available.
- virtual gfx::Size GetPreferredSize();
+ virtual gfx::Size GetPreferredSize() const;
// Convenience method that sizes this view to its preferred size.
void SizeToPreferredSize();
// Gets the minimum size of the view. View's implementation invokes
// GetPreferredSize.
- virtual gfx::Size GetMinimumSize();
+ virtual gfx::Size GetMinimumSize() const;
// Gets the maximum size of the view. Currently only used for sizing shell
// windows.
- virtual gfx::Size GetMaximumSize();
+ virtual gfx::Size GetMaximumSize() const;
// Return the height necessary to display this view with the provided width.
// View's implementation returns the value from getPreferredSize.cy.
// Override if your View's preferred height depends upon the width (such
// as with Labels).
- virtual int GetHeightForWidth(int w);
+ virtual int GetHeightForWidth(int w) const;
// Set whether this view is visible. Painting is scheduled as needed.
virtual void SetVisible(bool visible);
@@ -323,13 +328,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Compositor.
void SetPaintToLayer(bool paint_to_layer);
- // Recreates a layer for the view and returns the old layer. After this call,
- // the View no longer has a pointer to the old layer (so it won't be able to
- // update the old layer or destroy it). The caller must free the returned
- // layer.
- // Returns NULL and does not recreate layer if view does not own its layer.
- ui::Layer* RecreateLayer() WARN_UNUSED_RESULT;
-
// RTL positioning -----------------------------------------------------------
// Methods for accessing the bounds and position of the view, relative to its
@@ -408,6 +406,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// 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;
View* GetAncestorWithClassName(const std::string& name);
// Recursively descends the view tree starting at this view, and returns
@@ -505,7 +504,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// for View coordinates and language direction as required, allows the View
// to paint itself via the various OnPaint*() event handlers and then paints
// the hierarchy beneath it.
- virtual void Paint(gfx::Canvas* canvas);
+ virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set);
// The background object is owned by this object and may be NULL.
void set_background(Background* b);
@@ -513,12 +512,12 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
Background* background() { return background_.get(); }
// The border object is owned by this object and may be NULL.
- void set_border(Border* b);
+ virtual void SetBorder(scoped_ptr<Border> b);
const Border* border() const { return border_.get(); }
Border* border() { return border_.get(); }
// Get the theme provider from the parent widget.
- virtual ui::ThemeProvider* GetThemeProvider() const;
+ ui::ThemeProvider* GetThemeProvider() const;
// Returns the NativeTheme to use for this View. This calls through to
// GetNativeTheme() on the Widget this View is in. If this View is not in a
@@ -557,16 +556,15 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
flip_canvas_on_paint_for_rtl_ui_ = enable;
}
- // Accelerated painting ------------------------------------------------------
-
- // Enable/Disable accelerated compositing.
- static void set_use_acceleration_when_possible(bool use);
- static bool get_use_acceleration_when_possible();
-
// Input ---------------------------------------------------------------------
// The points, rects, mouse locations, and touch locations in the following
// functions are in the view's coordinates, except for a RootView.
+ // TODO(tdanderson): GetEventHandlerForPoint() and GetEventHandlerForRect()
+ // will be removed once their logic is moved into
+ // ViewTargeter and its derived classes. See
+ // crbug.com/355425.
+
// Convenience functions which calls into GetEventHandler() with
// a 1x1 rect centered at |point|.
View* GetEventHandlerForPoint(const gfx::Point& point);
@@ -592,6 +590,10 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// the cursor is a shared resource.
virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event);
+ // TODO(tdanderson): HitTestPoint() and HitTestRect() will be removed once
+ // their logic is moved into ViewTargeter and its
+ // derived classes. See crbug.com/355425.
+
// A convenience function which calls HitTestRect() with a rect of size
// 1x1 and an origin of |point|.
bool HitTestPoint(const gfx::Point& point) const;
@@ -599,6 +601,10 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Tests whether |rect| intersects this view's bounds.
virtual bool HitTestRect(const gfx::Rect& rect) const;
+ // Returns true if this view or any of its descendants are permitted to
+ // be the target of an event.
+ virtual bool CanProcessEventsWithinSubtree() const;
+
// Returns true if the mouse cursor is over |view| and mouse events are
// enabled.
bool IsMouseHovered();
@@ -713,17 +719,26 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
virtual InputMethod* GetInputMethod();
virtual const InputMethod* GetInputMethod() const;
+ // Sets a new event-targeter for the view, and returns the previous
+ // event-targeter.
+ scoped_ptr<ui::EventTargeter> SetEventTargeter(
+ scoped_ptr<ui::EventTargeter> targeter);
+
// Overridden from ui::EventTarget:
virtual bool CanAcceptEvent(const ui::Event& event) OVERRIDE;
virtual ui::EventTarget* GetParentTarget() OVERRIDE;
virtual scoped_ptr<ui::EventTargetIterator> GetChildIterator() const OVERRIDE;
virtual ui::EventTargeter* GetEventTargeter() OVERRIDE;
+ virtual void ConvertEventToTarget(ui::EventTarget* target,
+ ui::LocatedEvent* event) OVERRIDE;
+
+ const ui::EventTargeter* GetEventTargeter() const;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE FINAL;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Accelerators --------------------------------------------------------------
@@ -773,9 +788,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// not get the focus.
void SetFocusable(bool focusable);
- // Returns true if this view is capable of taking focus.
- bool focusable() const { return focusable_ && enabled_ && visible_; }
-
// Returns true if this view is |focusable_|, |enabled_| and drawn.
virtual bool IsFocusable() const;
@@ -833,7 +845,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Any time the tooltip text that a View is displaying changes, it must
// invoke TooltipTextChanged.
// |p| provides the coordinates of the mouse (relative to this view).
- virtual bool GetTooltipText(const gfx::Point& p, string16* tooltip) const;
+ virtual bool GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const;
// Returns the location (relative to this View) for the text on the tooltip
// to display. If false is returned (the default), the tooltip is placed at
@@ -936,7 +949,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Accessibility -------------------------------------------------------------
// Modifies |state| to reflect the current accessible state of this view.
- virtual void GetAccessibleState(ui::AccessibleViewState* state) { }
+ virtual void GetAccessibleState(ui::AXViewState* state) { }
// Returns an instance of the native accessibility interface for this view.
virtual gfx::NativeViewAccessible GetNativeViewAccessible();
@@ -947,7 +960,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// cases where the view is a native control that's already sending a
// native accessibility event and the duplicate event would cause
// problems.
- void NotifyAccessibilityEvent(ui::AccessibilityTypes::Event event_type,
+ void NotifyAccessibilityEvent(ui::AXEvent event_type,
bool send_native_event);
// Scrolling -----------------------------------------------------------------
@@ -1036,6 +1049,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// changed. The default implementation calls SchedulePaint() on this View.
virtual void OnEnabledChanged();
+ bool needs_layout() const { return needs_layout_; }
+
// Tree operations -----------------------------------------------------------
// This method is invoked when the tree changes.
@@ -1069,7 +1084,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Responsible for calling Paint() on child Views. Override to control the
// order child Views are painted.
- virtual void PaintChildren(gfx::Canvas* canvas);
+ virtual void PaintChildren(gfx::Canvas* canvas, const CullSet& cull_set);
// Override to provide rendering in any part of the View's bounds. Typically
// this is the "contents" of the view. If you override this method you will
@@ -1084,6 +1099,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Override to paint a border not specified by SetBorder().
virtual void OnPaintBorder(gfx::Canvas* canvas);
+ // Returns true if this View is the root for paint events, and should
+ // therefore maintain a |bounds_tree_| member and use it for paint damage rect
+ // calculations.
+ virtual bool IsPaintRoot();
+
// Accelerated painting ------------------------------------------------------
// Returns the offset from this view to the nearest ancestor with a layer. If
@@ -1141,6 +1161,10 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Focus ---------------------------------------------------------------------
+ // Returns last value passed to SetFocusable(). Use IsFocusable() to determine
+ // if a view can take focus right now.
+ bool focusable() const { return focusable_; }
+
// Override to be notified when focus has changed either to or from this View.
virtual void OnFocus();
virtual void OnBlur();
@@ -1218,11 +1242,14 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
#endif
private:
+ friend class internal::PreEventDispatchHandler;
friend class internal::PostEventDispatchHandler;
friend class internal::RootView;
friend class FocusManager;
friend class Widget;
+ typedef gfx::RTree<intptr_t> BoundsTree;
+
// Painting -----------------------------------------------------------------
enum SchedulePaintType {
@@ -1239,7 +1266,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Common Paint() code shared by accelerated and non-accelerated code paths to
// invoke OnPaint() on the View.
- void PaintCommon(gfx::Canvas* canvas);
+ void PaintCommon(gfx::Canvas* canvas, const CullSet& cull_set);
// Tree operations -----------------------------------------------------------
@@ -1308,6 +1335,25 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Sets the layer's bounds given in DIP coordinates.
void SetLayerBounds(const gfx::Rect& bounds_in_dip);
+ // Sets the bit indicating that the cached bounds for this object within the
+ // root view bounds tree are no longer valid. If |origin_changed| is true sets
+ // the same bit for all of our children as well.
+ void SetRootBoundsDirty(bool origin_changed);
+
+ // If needed, updates the bounds rectangle in paint root coordinate space
+ // in the supplied RTree. Recurses to children for recomputation as well.
+ void UpdateRootBounds(BoundsTree* bounds_tree, const gfx::Vector2d& offset);
+
+ // Remove self and all children from the supplied bounds tree. This is used,
+ // for example, when a view gets a layer and therefore becomes paint root. It
+ // needs to remove all references to itself and its children from any previous
+ // paint root that may have been tracking it.
+ void RemoveRootBounds(BoundsTree* bounds_tree);
+
+ // Traverse up the View hierarchy to the first ancestor that is a paint root
+ // and return a pointer to its |bounds_tree_| or NULL if no tree is found.
+ BoundsTree* GetBoundsTreeFromPaintRoot();
+
// Transformations -----------------------------------------------------------
// Returns in |transform| the transform to get from coordinates of |ancestor|
@@ -1480,6 +1526,15 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// List of descendants wanting notification when their visible bounds change.
scoped_ptr<Views> descendants_to_notify_;
+ // True if the bounds on this object have changed since the last time the
+ // paint root view constructed the spatial database.
+ bool root_bounds_dirty_;
+
+ // If this View IsPaintRoot() then this will be a pointer to a spatial data
+ // structure where we will keep the bounding boxes of all our children, for
+ // efficient paint damage rectangle intersection.
+ scoped_ptr<BoundsTree> bounds_tree_;
+
// Transformations -----------------------------------------------------------
// Clipping parameters. skia transformation matrix does not give us clipping.
@@ -1551,7 +1606,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Input --------------------------------------------------------------------
- scoped_ptr<internal::PostEventDispatchHandler> post_dispatch_handler_;
+ scoped_ptr<ui::EventTargeter> targeter_;
// Accessibility -------------------------------------------------------------
diff --git a/chromium/ui/views/view_aura.cc b/chromium/ui/views/view_aura.cc
deleted file mode 100644
index 006f1da2840..00000000000
--- a/chromium/ui/views/view_aura.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/view.h"
-
-namespace {
-
-// Default horizontal drag threshold in pixels.
-// Same as what gtk uses.
-const int kDefaultHorizontalDragThreshold = 8;
-
-// Default vertical drag threshold in pixels.
-// Same as what gtk uses.
-const int kDefaultVerticalDragThreshold = 8;
-
-} // namespace
-
-namespace views {
-
-int View::GetHorizontalDragThreshold() {
- // TODO(jennyz): This value may need to be adjusted for different platforms
- // and for different display density.
- return kDefaultHorizontalDragThreshold;
-}
-
-int View::GetVerticalDragThreshold() {
- // TODO(jennyz): This value may need to be adjusted for different platforms
- // and for different display density.
- return kDefaultVerticalDragThreshold;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/view_constants_aura.cc b/chromium/ui/views/view_constants_aura.cc
index 977050fb4e8..caf964a3119 100644
--- a/chromium/ui/views/view_constants_aura.cc
+++ b/chromium/ui/views/view_constants_aura.cc
@@ -13,4 +13,6 @@ namespace views {
DEFINE_WINDOW_PROPERTY_KEY(views::View*, kHostViewKey, NULL);
+DEFINE_WINDOW_PROPERTY_KEY(bool, kDesktopRootWindow, false);
+
} // namespace views
diff --git a/chromium/ui/views/view_constants_aura.h b/chromium/ui/views/view_constants_aura.h
index e0d718d2e85..1ca28207617 100644
--- a/chromium/ui/views/view_constants_aura.h
+++ b/chromium/ui/views/view_constants_aura.h
@@ -17,6 +17,10 @@ class View;
// have the same parent widget as the window on which the property is set.
VIEWS_EXPORT extern const aura::WindowProperty<View*>* const kHostViewKey;
+// A property key to indicate if a window is a desktop root window or not.
+// This property is currently set during creation of desktop root window.
+VIEWS_EXPORT extern const aura::WindowProperty<bool>* const kDesktopRootWindow;
+
} // namespace views
#endif // UI_VIEWS_VIEW_CONSTANTS_AURA_H_
diff --git a/chromium/ui/views/view_model.cc b/chromium/ui/views/view_model.cc
index 5f492f5380d..a0a75496450 100644
--- a/chromium/ui/views/view_model.cc
+++ b/chromium/ui/views/view_model.cc
@@ -33,6 +33,11 @@ void ViewModel::Remove(int index) {
}
void ViewModel::Move(int index, int target_index) {
+ DCHECK_LT(index, static_cast<int>(entries_.size()));
+ DCHECK_GE(index, 0);
+ DCHECK_LT(target_index, static_cast<int>(entries_.size()));
+ DCHECK_GE(target_index, 0);
+
if (index == target_index)
return;
Entry entry(entries_[index]);
diff --git a/chromium/ui/views/view_targeter.cc b/chromium/ui/views/view_targeter.cc
new file mode 100644
index 00000000000..31babfb88c0
--- /dev/null
+++ b/chromium/ui/views/view_targeter.cc
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/view_targeter.h"
+
+#include "ui/events/event_target.h"
+#include "ui/views/focus/focus_manager.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+ViewTargeter::ViewTargeter() {}
+ViewTargeter::~ViewTargeter() {}
+
+gfx::RectF ViewTargeter::BoundsForEvent(const ui::LocatedEvent& event) const {
+ gfx::RectF event_bounds(event.location_f(), gfx::SizeF(1, 1));
+ if (event.IsGestureEvent()) {
+ const ui::GestureEvent& gesture =
+ static_cast<const ui::GestureEvent&>(event);
+ event_bounds = gesture.details().bounding_box_f();
+ }
+
+ return event_bounds;
+}
+
+ui::EventTarget* ViewTargeter::FindTargetForEvent(ui::EventTarget* root,
+ ui::Event* event) {
+ View* view = static_cast<View*>(root);
+ if (event->IsKeyEvent())
+ return FindTargetForKeyEvent(view, *static_cast<ui::KeyEvent*>(event));
+ else if (event->IsScrollEvent())
+ return EventTargeter::FindTargetForEvent(root, event);
+
+ NOTREACHED() << "ViewTargeter does not yet support this event type.";
+ return NULL;
+}
+
+ui::EventTarget* ViewTargeter::FindNextBestTarget(
+ ui::EventTarget* previous_target,
+ ui::Event* event) {
+ return previous_target->GetParentTarget();
+}
+
+bool ViewTargeter::SubtreeCanAcceptEvent(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const {
+ views::View* view = static_cast<views::View*>(target);
+ if (!view->visible())
+ return false;
+
+ if (!view->CanProcessEventsWithinSubtree())
+ return false;
+
+ return true;
+}
+
+bool ViewTargeter::EventLocationInsideBounds(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const {
+ views::View* view = static_cast<views::View*>(target);
+ gfx::Rect rect(event.location(), gfx::Size(1, 1));
+ gfx::RectF rect_in_view_coords_f(rect);
+ if (view->parent())
+ View::ConvertRectToTarget(view->parent(), view, &rect_in_view_coords_f);
+ gfx::Rect rect_in_view_coords = gfx::ToEnclosingRect(rect_in_view_coords_f);
+
+ // TODO(tdanderson): Don't call into HitTestRect() directly here.
+ // See crbug.com/370579.
+ return view->HitTestRect(rect_in_view_coords);
+}
+
+View* ViewTargeter::FindTargetForKeyEvent(View* view, const ui::KeyEvent& key) {
+ if (view->GetFocusManager())
+ return view->GetFocusManager()->GetFocusedView();
+ return NULL;
+}
+
+} // namespace aura
diff --git a/chromium/ui/views/view_targeter.h b/chromium/ui/views/view_targeter.h
new file mode 100644
index 00000000000..8273a8aabc4
--- /dev/null
+++ b/chromium/ui/views/view_targeter.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_VIEW_TARGETER_H_
+#define UI_VIEWS_VIEW_TARGETER_H_
+
+#include "ui/events/event_targeter.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+// Contains the logic used to determine the View to which an
+// event should be dispatched. A ViewTargeter (or one of its
+// derived classes) is installed on a View to specify the
+// targeting behaviour to be used for the subtree rooted at
+// that View.
+class VIEWS_EXPORT ViewTargeter : public ui::EventTargeter {
+ public:
+ ViewTargeter();
+ virtual ~ViewTargeter();
+
+ protected:
+ // Returns the location of |event| represented as a rect. If |event| is
+ // a gesture event, its bounding box is returned. Otherwise, a 1x1 rect
+ // having its origin at the location of |event| is returned.
+ gfx::RectF BoundsForEvent(const ui::LocatedEvent& event) const;
+
+ // ui::EventTargeter:
+ virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
+ ui::Event* event) OVERRIDE;
+ virtual ui::EventTarget* FindNextBestTarget(ui::EventTarget* previous_target,
+ ui::Event* event) OVERRIDE;
+ virtual bool SubtreeCanAcceptEvent(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const OVERRIDE;
+ virtual bool EventLocationInsideBounds(
+ ui::EventTarget* target,
+ const ui::LocatedEvent& event) const OVERRIDE;
+
+ private:
+ View* FindTargetForKeyEvent(View* view, const ui::KeyEvent& key);
+
+ DISALLOW_COPY_AND_ASSIGN(ViewTargeter);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_VIEW_TARGETER_H_
diff --git a/chromium/ui/views/view_targeter_unittest.cc b/chromium/ui/views/view_targeter_unittest.cc
new file mode 100644
index 00000000000..54a28b13a32
--- /dev/null
+++ b/chromium/ui/views/view_targeter_unittest.cc
@@ -0,0 +1,386 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/view_targeter.h"
+
+#include "ui/events/event_targeter.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/path.h"
+#include "ui/views/masked_view_targeter.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/root_view.h"
+
+namespace views {
+
+// A class used to define a triangular-shaped hit test mask on a View.
+class TestMaskedViewTargeter : public MaskedViewTargeter {
+ public:
+ explicit TestMaskedViewTargeter(View* masked_view)
+ : MaskedViewTargeter(masked_view) {}
+ virtual ~TestMaskedViewTargeter() {}
+
+ private:
+ virtual bool GetHitTestMask(const View* view,
+ gfx::Path* mask) const OVERRIDE {
+ SkScalar w = SkIntToScalar(view->width());
+ SkScalar h = SkIntToScalar(view->height());
+
+ // Create a triangular mask within the bounds of |view|.
+ mask->moveTo(w / 2, 0);
+ mask->lineTo(w, h);
+ mask->lineTo(0, h);
+ mask->close();
+
+ return true;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestMaskedViewTargeter);
+};
+
+// A derived class of View used for testing purposes.
+class TestingView : public View {
+ public:
+ TestingView() : can_process_events_within_subtree_(true) {}
+ virtual ~TestingView() {}
+
+ // Reset all test state.
+ void Reset() { can_process_events_within_subtree_ = true; }
+
+ void set_can_process_events_within_subtree(bool can_process) {
+ can_process_events_within_subtree_ = can_process;
+ }
+
+ // View:
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE {
+ return can_process_events_within_subtree_;
+ }
+
+ private:
+ // Value to return from CanProcessEventsWithinSubtree().
+ bool can_process_events_within_subtree_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestingView);
+};
+
+namespace test {
+
+typedef ViewsTestBase ViewTargeterTest;
+
+// Verifies that the the functions ViewTargeter::FindTargetForEvent()
+// and ViewTargeter::FindNextBestTarget() are implemented correctly
+// for key events.
+TEST_F(ViewTargeterTest, ViewTargeterForKeyEvents) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(init_params);
+
+ View* content = new View;
+ View* child = new View;
+ View* grandchild = new View;
+
+ widget.SetContentsView(content);
+ content->AddChildView(child);
+ child->AddChildView(grandchild);
+
+ grandchild->SetFocusable(true);
+ grandchild->RequestFocus();
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
+ ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
+
+ // The focused view should be the initial target of the event.
+ ui::EventTarget* current_target = targeter->FindTargetForEvent(root_view,
+ &key_event);
+ EXPECT_EQ(grandchild, static_cast<View*>(current_target));
+
+ // Verify that FindNextBestTarget() will return the parent view of the
+ // argument (and NULL if the argument has no parent view).
+ current_target = targeter->FindNextBestTarget(grandchild, &key_event);
+ EXPECT_EQ(child, static_cast<View*>(current_target));
+ current_target = targeter->FindNextBestTarget(child, &key_event);
+ EXPECT_EQ(content, static_cast<View*>(current_target));
+ current_target = targeter->FindNextBestTarget(content, &key_event);
+ EXPECT_EQ(widget.GetRootView(), static_cast<View*>(current_target));
+ current_target = targeter->FindNextBestTarget(widget.GetRootView(),
+ &key_event);
+ EXPECT_EQ(NULL, static_cast<View*>(current_target));
+}
+
+// Verifies that the the functions ViewTargeter::FindTargetForEvent()
+// and ViewTargeter::FindNextBestTarget() are implemented correctly
+// for scroll events.
+TEST_F(ViewTargeterTest, ViewTargeterForScrollEvents) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.bounds = gfx::Rect(0, 0, 200, 200);
+ widget.Init(init_params);
+
+ // The coordinates used for SetBounds() are in the parent coordinate space.
+ View* content = new View;
+ content->SetBounds(0, 0, 100, 100);
+ View* child = new View;
+ child->SetBounds(50, 50, 20, 20);
+ View* grandchild = new View;
+ grandchild->SetBounds(0, 0, 5, 5);
+
+ widget.SetContentsView(content);
+ content->AddChildView(child);
+ child->AddChildView(grandchild);
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
+ // The event falls within the bounds of |child| and |content| but not
+ // |grandchild|, so |child| should be the initial target for the event.
+ ui::ScrollEvent scroll(ui::ET_SCROLL,
+ gfx::Point(60, 60),
+ ui::EventTimeForNow(),
+ 0,
+ 0, 3,
+ 0, 3,
+ 2);
+ ui::EventTarget* current_target = targeter->FindTargetForEvent(root_view,
+ &scroll);
+ EXPECT_EQ(child, static_cast<View*>(current_target));
+
+ // Verify that FindNextBestTarget() will return the parent view of the
+ // argument (and NULL if the argument has no parent view).
+ current_target = targeter->FindNextBestTarget(child, &scroll);
+ EXPECT_EQ(content, static_cast<View*>(current_target));
+ current_target = targeter->FindNextBestTarget(content, &scroll);
+ EXPECT_EQ(widget.GetRootView(), static_cast<View*>(current_target));
+ current_target = targeter->FindNextBestTarget(widget.GetRootView(),
+ &scroll);
+ EXPECT_EQ(NULL, static_cast<View*>(current_target));
+
+ // The event falls outside of the original specified bounds of |content|,
+ // |child|, and |grandchild|. But since |content| is the contents view,
+ // and contents views are resized to fill the entire area of the root
+ // view, the event's initial target should still be |content|.
+ scroll = ui::ScrollEvent(ui::ET_SCROLL,
+ gfx::Point(150, 150),
+ ui::EventTimeForNow(),
+ 0,
+ 0, 3,
+ 0, 3,
+ 2);
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(content, static_cast<View*>(current_target));
+}
+
+// Tests the basic functionality of the method
+// ViewTargeter::SubtreeShouldBeExploredForEvent().
+TEST_F(ViewTargeterTest, SubtreeShouldBeExploredForEvent) {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget.Init(params);
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
+ // The coordinates used for SetBounds() are in the parent coordinate space.
+ View v1, v2, v3;
+ v1.SetBounds(0, 0, 300, 300);
+ v2.SetBounds(100, 100, 100, 100);
+ v3.SetBounds(0, 0, 10, 10);
+ v3.SetVisible(false);
+ root_view->AddChildView(&v1);
+ v1.AddChildView(&v2);
+ v2.AddChildView(&v3);
+
+ // Note that the coordinates used below are in |v1|'s coordinate space,
+ // and that SubtreeShouldBeExploredForEvent() expects the event location
+ // to be in the coordinate space of the target's parent. |v1| and
+ // its parent share a common coordinate space.
+
+ // Event located within |v1| only.
+ gfx::Point point(10, 10);
+ ui::MouseEvent event(ui::ET_MOUSE_PRESSED, point, point,
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ EXPECT_TRUE(targeter->SubtreeShouldBeExploredForEvent(&v1, event));
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v2, event));
+ v1.ConvertEventToTarget(&v2, &event);
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event));
+
+ // Event located within |v1| and |v2| only.
+ event.set_location(gfx::Point(150, 150));
+ EXPECT_TRUE(targeter->SubtreeShouldBeExploredForEvent(&v1, event));
+ EXPECT_TRUE(targeter->SubtreeShouldBeExploredForEvent(&v2, event));
+ v1.ConvertEventToTarget(&v2, &event);
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event));
+
+ // Event located within |v1|, |v2|, and |v3|. Note that |v3| is not
+ // visible, so it cannot handle the event.
+ event.set_location(gfx::Point(105, 105));
+ EXPECT_TRUE(targeter->SubtreeShouldBeExploredForEvent(&v1, event));
+ EXPECT_TRUE(targeter->SubtreeShouldBeExploredForEvent(&v2, event));
+ v1.ConvertEventToTarget(&v2, &event);
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event));
+
+ // Event located outside the bounds of all views.
+ event.set_location(gfx::Point(400, 400));
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v1, event));
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v2, event));
+ v1.ConvertEventToTarget(&v2, &event);
+ EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event));
+
+ // TODO(tdanderson): Move the hit-testing unit tests out of view_unittest
+ // and into here. See crbug.com/355425.
+}
+
+// Tests that FindTargetForEvent() returns the correct target when some
+// views in the view tree return false when CanProcessEventsWithinSubtree()
+// is called on them.
+TEST_F(ViewTargeterTest, CanProcessEventsWithinSubtree) {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget.Init(params);
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
+ // The coordinates used for SetBounds() are in the parent coordinate space.
+ TestingView v1, v2, v3;
+ v1.SetBounds(0, 0, 300, 300);
+ v2.SetBounds(100, 100, 100, 100);
+ v3.SetBounds(0, 0, 10, 10);
+ root_view->AddChildView(&v1);
+ v1.AddChildView(&v2);
+ v2.AddChildView(&v3);
+
+ // Note that the coordinates used below are in the coordinate space of
+ // the root view.
+
+ // Define |scroll| to be (105, 105) (in the coordinate space of the root
+ // view). This is located within all of |v1|, |v2|, and |v3|.
+ gfx::Point scroll_point(105, 105);
+ ui::ScrollEvent scroll(
+ ui::ET_SCROLL, scroll_point, ui::EventTimeForNow(), 0, 0, 3, 0, 3, 2);
+
+ // If CanProcessEventsWithinSubtree() returns true for each view,
+ // |scroll| should be targeted at the deepest view in the hierarchy,
+ // which is |v3|.
+ ui::EventTarget* current_target =
+ targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&v3, current_target);
+
+ // If CanProcessEventsWithinSubtree() returns |false| when called
+ // on |v3|, then |v3| cannot be the target of |scroll| (this should
+ // instead be |v2|). Note we need to reset the location of |scroll|
+ // because it may have been mutated by the previous call to
+ // FindTargetForEvent().
+ scroll.set_location(scroll_point);
+ v3.set_can_process_events_within_subtree(false);
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&v2, current_target);
+
+ // If CanProcessEventsWithinSubtree() returns |false| when called
+ // on |v2|, then neither |v2| nor |v3| can be the target of |scroll|
+ // (this should instead be |v1|).
+ scroll.set_location(scroll_point);
+ v3.Reset();
+ v2.set_can_process_events_within_subtree(false);
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&v1, current_target);
+
+ // If CanProcessEventsWithinSubtree() returns |false| when called
+ // on |v1|, then none of |v1|, |v2| or |v3| can be the target of |scroll|
+ // (this should instead be the root view itself).
+ scroll.set_location(scroll_point);
+ v2.Reset();
+ v1.set_can_process_events_within_subtree(false);
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(root_view, current_target);
+
+ // TODO(tdanderson): We should also test that targeting works correctly
+ // with gestures. See crbug.com/375822.
+}
+
+// Tests that FindTargetForEvent() returns the correct target when some
+// views in the view tree have a MaskedViewTargeter installed, i.e.,
+// they have a custom-shaped hit test mask.
+TEST_F(ViewTargeterTest, MaskedViewTargeter) {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget.Init(params);
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
+ // The coordinates used for SetBounds() are in the parent coordinate space.
+ View masked_view, unmasked_view, masked_child;
+ masked_view.SetBounds(0, 0, 200, 200);
+ unmasked_view.SetBounds(300, 0, 300, 300);
+ masked_child.SetBounds(0, 0, 100, 100);
+ root_view->AddChildView(&masked_view);
+ root_view->AddChildView(&unmasked_view);
+ unmasked_view.AddChildView(&masked_child);
+
+ // Install event targeters of type TestMaskedViewTargeter on the two masked
+ // views to define their hit test masks.
+ ui::EventTargeter* masked_targeter = new TestMaskedViewTargeter(&masked_view);
+ masked_view.SetEventTargeter(make_scoped_ptr(masked_targeter));
+ masked_targeter = new TestMaskedViewTargeter(&masked_child);
+ masked_child.SetEventTargeter(make_scoped_ptr(masked_targeter));
+
+ // Note that the coordinates used below are in the coordinate space of
+ // the root view.
+
+ // Event located within the hit test mask of |masked_view|.
+ ui::ScrollEvent scroll(ui::ET_SCROLL,
+ gfx::Point(100, 190),
+ ui::EventTimeForNow(),
+ 0,
+ 0,
+ 3,
+ 0,
+ 3,
+ 2);
+ ui::EventTarget* current_target =
+ targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&masked_view, static_cast<View*>(current_target));
+
+ // Event located outside the hit test mask of |masked_view|.
+ scroll.set_location(gfx::Point(10, 10));
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(root_view, static_cast<View*>(current_target));
+
+ // Event located within the hit test mask of |masked_child|.
+ scroll.set_location(gfx::Point(350, 3));
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&masked_child, static_cast<View*>(current_target));
+
+ // Event located within the hit test mask of |masked_child|.
+ scroll.set_location(gfx::Point(300, 12));
+ current_target = targeter->FindTargetForEvent(root_view, &scroll);
+ EXPECT_EQ(&unmasked_view, static_cast<View*>(current_target));
+
+ // TODO(tdanderson): We should also test that targeting of masked views
+ // works correctly with gestures. See crbug.com/375822.
+}
+
+} // namespace test
+} // namespace views
diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc
index 77601b20eef..a8639bcdd0d 100644
--- a/chromium/ui/views/view_unittest.cc
+++ b/chromium/ui/views/view_unittest.cc
@@ -9,14 +9,15 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_strings.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/test/draw_waiter_for_test.h"
#include "ui/events/event.h"
+#include "ui/events/gestures/gesture_recognizer.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/path.h"
@@ -25,7 +26,6 @@
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/focus/accelerator_handler.h"
#include "ui/views/focus/view_storage.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
@@ -35,15 +35,7 @@
#include "ui/views/window/dialog_client_view.h"
#include "ui/views/window/dialog_delegate.h"
-#if defined(OS_WIN)
-#include "ui/views/test/test_views_delegate.h"
-#endif
-#if defined(USE_AURA)
-#include "ui/aura/root_window.h"
-#include "ui/events/gestures/gesture_recognizer.h"
-#endif
-
-using ::testing::_;
+using base::ASCIIToUTF16;
namespace {
@@ -205,7 +197,11 @@ typedef ViewsTestBase ViewTest;
// A derived class for testing purpose.
class TestView : public View {
public:
- TestView() : View(), delete_on_pressed_(false), in_touch_sequence_(false) {}
+ TestView()
+ : View(),
+ delete_on_pressed_(false),
+ native_theme_(NULL),
+ can_process_events_within_subtree_(true) {}
virtual ~TestView() {}
// Reset all test state
@@ -215,12 +211,11 @@ class TestView : public View {
location_.SetPoint(0, 0);
received_mouse_enter_ = false;
received_mouse_exit_ = false;
- last_touch_event_type_ = 0;
- last_touch_event_was_handled_ = false;
last_gesture_event_type_ = 0;
last_gesture_event_was_handled_ = false;
last_clip_.setEmpty();
accelerator_count_map_.clear();
+ can_process_events_within_subtree_ = true;
}
// Exposed as public for testing.
@@ -232,6 +227,16 @@ class TestView : public View {
views::View::Blur();
}
+ bool focusable() const { return View::focusable(); }
+
+ void set_can_process_events_within_subtree(bool can_process) {
+ can_process_events_within_subtree_ = can_process;
+ }
+
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE {
+ return can_process_events_within_subtree_;
+ }
+
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
@@ -239,14 +244,16 @@ class TestView : public View {
virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
// Ignores GestureEvent by default.
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
+ virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE;
virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
+ virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme)
+ OVERRIDE;
+
// OnBoundsChanged.
bool did_change_bounds_;
gfx::Rect new_bounds_;
@@ -265,26 +272,17 @@ class TestView : public View {
int last_gesture_event_type_;
bool last_gesture_event_was_handled_;
- // TouchEvent.
- int last_touch_event_type_;
- bool last_touch_event_was_handled_;
- bool in_touch_sequence_;
-
// Painting.
SkRect last_clip_;
// Accelerators.
std::map<ui::Accelerator, int> accelerator_count_map_;
-};
-// A view subclass that ignores all touch events for testing purposes.
-class TestViewIgnoreTouch : public TestView {
- public:
- TestViewIgnoreTouch() : TestView() {}
- virtual ~TestViewIgnoreTouch() {}
+ // Native theme.
+ const ui::NativeTheme* native_theme_;
- private:
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ // Value to return from CanProcessEventsWithinSubtree().
+ bool can_process_events_within_subtree_;
};
// A view subclass that consumes all Gesture events for testing purposes.
@@ -412,7 +410,7 @@ TEST_F(ViewTest, MouseEvent) {
gfx::Point p1(110, 120);
ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(pressed);
EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_PRESSED);
EXPECT_EQ(v2->location_.x(), 10);
@@ -425,7 +423,7 @@ TEST_F(ViewTest, MouseEvent) {
v2->Reset();
gfx::Point p2(50, 40);
ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, p2, p2,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
root->OnMouseDragged(dragged);
EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_DRAGGED);
EXPECT_EQ(v2->location_.x(), -50);
@@ -436,7 +434,8 @@ TEST_F(ViewTest, MouseEvent) {
// Releasted event out of bounds. Should still go to v2
v1->Reset();
v2->Reset();
- ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
+ ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0,
+ 0);
root->OnMouseDragged(released);
EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_RELEASED);
EXPECT_EQ(v2->location_.x(), -100);
@@ -471,7 +470,7 @@ TEST_F(ViewTest, DeleteOnPressed) {
v2->delete_on_pressed_ = true;
gfx::Point point(110, 120);
ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(pressed);
EXPECT_EQ(0, v1->child_count());
@@ -479,129 +478,8 @@ TEST_F(ViewTest, DeleteOnPressed) {
}
////////////////////////////////////////////////////////////////////////////////
-// TouchEvent
+// GestureEvent
////////////////////////////////////////////////////////////////////////////////
-void TestView::OnTouchEvent(ui::TouchEvent* event) {
- last_touch_event_type_ = event->type();
- location_.SetPoint(event->x(), event->y());
- if (!in_touch_sequence_) {
- if (event->type() == ui::ET_TOUCH_PRESSED) {
- in_touch_sequence_ = true;
- event->StopPropagation();
- return;
- }
- } else {
- if (event->type() == ui::ET_TOUCH_RELEASED) {
- in_touch_sequence_ = false;
- event->SetHandled();
- return;
- }
- event->StopPropagation();
- return;
- }
-
- if (last_touch_event_was_handled_)
- event->StopPropagation();
-}
-
-void TestViewIgnoreTouch::OnTouchEvent(ui::TouchEvent* event) {
-}
-
-TEST_F(ViewTest, TouchEvent) {
- TestView* v1 = new TestView();
- v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
-
- TestView* v2 = new TestView();
- v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
-
- TestView* v3 = new TestViewIgnoreTouch();
- v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
-
- scoped_ptr<Widget> widget(new Widget());
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.bounds = gfx::Rect(50, 50, 650, 650);
- widget->Init(params);
- internal::RootView* root =
- static_cast<internal::RootView*>(widget->GetRootView());
-
- root->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
-
- // |v3| completely obscures |v2|, but all the touch events on |v3| should
- // reach |v2| because |v3| doesn't process any touch events.
-
- // Make sure if none of the views handle the touch event, the gesture manager
- // does.
- v1->Reset();
- v2->Reset();
-
- ui::TouchEvent unhandled(ui::ET_TOUCH_MOVED,
- gfx::Point(400, 400),
- 0, /* no flags */
- 0, /* first finger touch */
- base::TimeDelta(),
- 1.0, 0.0, 1.0, 0.0);
- root->DispatchTouchEvent(&unhandled);
-
- EXPECT_EQ(v1->last_touch_event_type_, 0);
- EXPECT_EQ(v2->last_touch_event_type_, 0);
-
- // Test press, drag, release touch sequence.
- v1->Reset();
- v2->Reset();
-
- ui::TouchEvent pressed(ui::ET_TOUCH_PRESSED,
- gfx::Point(110, 120),
- 0, /* no flags */
- 0, /* first finger touch */
- base::TimeDelta(),
- 1.0, 0.0, 1.0, 0.0);
- v2->last_touch_event_was_handled_ = true;
- root->DispatchTouchEvent(&pressed);
-
- EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_PRESSED);
- EXPECT_EQ(v2->location_.x(), 10);
- EXPECT_EQ(v2->location_.y(), 20);
- // Make sure v1 did not receive the event
- EXPECT_EQ(v1->last_touch_event_type_, 0);
-
- // Drag event out of bounds. Should still go to v2
- v1->Reset();
- v2->Reset();
- ui::TouchEvent dragged(ui::ET_TOUCH_MOVED,
- gfx::Point(50, 40),
- 0, /* no flags */
- 0, /* first finger touch */
- base::TimeDelta(),
- 1.0, 0.0, 1.0, 0.0);
-
- root->DispatchTouchEvent(&dragged);
- EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_MOVED);
- EXPECT_EQ(v2->location_.x(), -50);
- EXPECT_EQ(v2->location_.y(), -60);
- // Make sure v1 did not receive the event
- EXPECT_EQ(v1->last_touch_event_type_, 0);
-
- // Released event out of bounds. Should still go to v2
- v1->Reset();
- v2->Reset();
- ui::TouchEvent released(ui::ET_TOUCH_RELEASED, gfx::Point(),
- 0, /* no flags */
- 0, /* first finger */
- base::TimeDelta(),
- 1.0, 0.0, 1.0, 0.0);
- v2->last_touch_event_was_handled_ = true;
- root->DispatchTouchEvent(&released);
- EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_RELEASED);
- EXPECT_EQ(v2->location_.x(), -100);
- EXPECT_EQ(v2->location_.y(), -100);
- // Make sure v1 did not receive the event
- EXPECT_EQ(v1->last_touch_event_type_, 0);
-
- widget->CloseNow();
-}
void TestView::OnGestureEvent(ui::GestureEvent* event) {
}
@@ -624,6 +502,7 @@ TEST_F(ViewTest, GestureEvent) {
widget->Init(params);
internal::RootView* root =
static_cast<internal::RootView*>(widget->GetRootView());
+ ui::EventDispatchDetails details;
root->AddChildView(v1);
v1->AddChildView(v2);
@@ -640,14 +519,19 @@ TEST_F(ViewTest, GestureEvent) {
// Gesture on |v3|
GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
- root->DispatchGestureEvent(&g1);
+ details = root->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
EXPECT_EQ(gfx::Point(10, 10), v2->location_);
EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
// Simulate an up so that RootView is no longer targetting |v3|.
GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
- root->DispatchGestureEvent(&g1_up);
+ details = root->OnEventFromSource(&g1_up);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
v1->Reset();
v2->Reset();
@@ -655,7 +539,10 @@ TEST_F(ViewTest, GestureEvent) {
// Gesture on |v1|
GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
- root->DispatchGestureEvent(&g2);
+ details = root->OnEventFromSource(&g2);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
EXPECT_EQ(gfx::Point(80, 80), v1->location_);
EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
@@ -664,7 +551,10 @@ TEST_F(ViewTest, GestureEvent) {
// to |v1| as that is the view the touch was initially down on.
v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
- root->DispatchGestureEvent(&g1);
+ details = root->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
EXPECT_EQ("110,110", v1->location_.ToString());
@@ -690,6 +580,7 @@ TEST_F(ViewTest, ScrollGestureEvent) {
widget->Init(params);
internal::RootView* root =
static_cast<internal::RootView*>(widget->GetRootView());
+ ui::EventDispatchDetails details;
root->AddChildView(v1);
v1->AddChildView(v2);
@@ -706,7 +597,10 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// Gesture on |v3|
GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
- root->DispatchGestureEvent(&g1);
+ details = root->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
EXPECT_EQ(gfx::Point(10, 10), v2->location_);
EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
@@ -717,7 +611,10 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// since it does not process scroll-gesture events, these events should reach
// |v1|.
GestureEventForTest gscroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 115, 115, 0);
- root->DispatchGestureEvent(&gscroll_begin);
+ details = root->OnEventFromSource(&gscroll_begin);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
EXPECT_EQ(ui::ET_GESTURE_SCROLL_BEGIN, v1->last_gesture_event_type_);
v1->Reset();
@@ -726,19 +623,28 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// default gesture handler, and not |v1| (even though it is the view under the
// point, and is the scroll event handler).
GestureEventForTest second_tap(ui::ET_GESTURE_TAP, 70, 70, 0);
- root->DispatchGestureEvent(&second_tap);
+ details = root->OnEventFromSource(&second_tap);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
v2->Reset();
GestureEventForTest gscroll_end(ui::ET_GESTURE_SCROLL_END, 50, 50, 0);
- root->DispatchGestureEvent(&gscroll_end);
+ details = root->OnEventFromSource(&gscroll_end);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_SCROLL_END, v1->last_gesture_event_type_);
v1->Reset();
// Simulate an up so that RootView is no longer targetting |v3|.
GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
- root->DispatchGestureEvent(&g1_up);
+ details = root->OnEventFromSource(&g1_up);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_END, v2->last_gesture_event_type_);
v1->Reset();
@@ -747,7 +653,10 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// Gesture on |v1|
GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
- root->DispatchGestureEvent(&g2);
+ details = root->OnEventFromSource(&g2);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
EXPECT_EQ(gfx::Point(80, 80), v1->location_);
EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
@@ -756,7 +665,10 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// to |v1| as that is the view the touch was initially down on.
v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
- root->DispatchGestureEvent(&g1);
+ details = root->OnEventFromSource(&g1);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_FALSE(details.target_destroyed);
+
EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
EXPECT_EQ("110,110", v1->location_.ToString());
@@ -768,7 +680,7 @@ TEST_F(ViewTest, ScrollGestureEvent) {
// Painting
////////////////////////////////////////////////////////////////////////////////
-void TestView::Paint(gfx::Canvas* canvas) {
+void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) {
canvas->sk_canvas()->getClipBounds(&last_clip_);
}
@@ -784,66 +696,6 @@ void CheckRect(const SkRect& check_rect, const SkRect& target_rect) {
EXPECT_EQ(target_rect.fBottom, check_rect.fBottom);
}
-/* This test is disabled because it is flakey on some systems.
-TEST_F(ViewTest, DISABLED_Painting) {
- // Determine if InvalidateRect generates an empty paint rectangle.
- EmptyWindow paint_window(CRect(50, 50, 650, 650));
- paint_window.RedrawWindow(CRect(0, 0, 600, 600), NULL,
- RDW_UPDATENOW | RDW_INVALIDATE | RDW_ALLCHILDREN);
- bool empty_paint = paint_window.empty_paint();
-
- NativeWidgetWin window;
- window.set_delete_on_destroy(false);
- window.set_window_style(WS_OVERLAPPEDWINDOW);
- window.Init(NULL, gfx::Rect(50, 50, 650, 650), NULL);
- View* root = window.GetRootView();
-
- TestView* v1 = new TestView();
- v1->SetBoundsRect(gfx::Rect(0, 0, 650, 650));
- root->AddChildView(v1);
-
- TestView* v2 = new TestView();
- v2->SetBoundsRect(gfx::Rect(10, 10, 80, 80));
- v1->AddChildView(v2);
-
- TestView* v3 = new TestView();
- v3->SetBoundsRect(gfx::Rect(10, 10, 60, 60));
- v2->AddChildView(v3);
-
- TestView* v4 = new TestView();
- v4->SetBoundsRect(gfx::Rect(10, 200, 100, 100));
- v1->AddChildView(v4);
-
- // Make sure to paint current rects
- PaintRootView(root, empty_paint);
-
-
- v1->Reset();
- v2->Reset();
- v3->Reset();
- v4->Reset();
- v3->SchedulePaintInRect(gfx::Rect(10, 10, 10, 10));
- PaintRootView(root, empty_paint);
-
- SkRect tmp_rect;
-
- tmp_rect.iset(10, 10, 20, 20);
- CheckRect(v3->last_clip_, tmp_rect);
-
- tmp_rect.iset(20, 20, 30, 30);
- CheckRect(v2->last_clip_, tmp_rect);
-
- tmp_rect.iset(30, 30, 40, 40);
- CheckRect(v1->last_clip_, tmp_rect);
-
- // Make sure v4 was not painted
- tmp_rect.setEmpty();
- CheckRect(v4->last_clip_, tmp_rect);
-
- window.DestroyWindow();
-}
-*/
-
TEST_F(ViewTest, RemoveNotification) {
ViewStorage* vs = ViewStorage::GetInstance();
Widget* widget = new Widget;
@@ -1370,6 +1222,163 @@ TEST_F(ViewTest, GetEventHandlerForRect) {
widget->CloseNow();
}
+// Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave
+// as expected when different views in the view hierarchy return false
+// when CanProcessEventsWithinSubtree() is called.
+TEST_F(ViewTest, CanProcessEventsWithinSubtree) {
+ Widget* widget = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ widget->Init(params);
+ View* root_view = widget->GetRootView();
+ root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
+
+ // Have this hierarchy of views (the coords here are in the coordinate
+ // space of the root view):
+ // v (0, 0, 100, 100)
+ // - v_child (0, 0, 20, 30)
+ // - v_grandchild (5, 5, 5, 15)
+
+ TestView* v = new TestView;
+ v->SetBounds(0, 0, 100, 100);
+ root_view->AddChildView(v);
+ v->set_notify_enter_exit_on_child(true);
+
+ TestView* v_child = new TestView;
+ v_child->SetBounds(0, 0, 20, 30);
+ v->AddChildView(v_child);
+
+ TestView* v_grandchild = new TestView;
+ v_grandchild->SetBounds(5, 5, 5, 15);
+ v_child->AddChildView(v_grandchild);
+
+ v->Reset();
+ v_child->Reset();
+ v_grandchild->Reset();
+
+ // Define rects and points within the views in the hierarchy.
+ gfx::Rect rect_in_v_grandchild(7, 7, 3, 3);
+ gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin());
+ gfx::Rect rect_in_v_child(12, 3, 5, 5);
+ gfx::Point point_in_v_child(rect_in_v_child.origin());
+ gfx::Rect rect_in_v(50, 50, 25, 30);
+ gfx::Point point_in_v(rect_in_v.origin());
+
+ // When all three views return true when CanProcessEventsWithinSubtree()
+ // is called, targeting should behave as expected.
+
+ View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+ EXPECT_EQ(v_grandchild, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+ EXPECT_EQ(v_grandchild, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+
+ // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
+ // is called, then |v_grandchild| cannot be returned as a target.
+
+ v_grandchild->set_can_process_events_within_subtree(false);
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+ EXPECT_EQ(v_child, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+ EXPECT_EQ(v, result_view);
+
+ // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
+ // is called, then NULL should be returned as a target if we call
+ // GetTooltipHandlerForPoint() with |v_grandchild| as the root of the
+ // views tree. Note that the location must be in the coordinate space
+ // of the root view (|v_grandchild| in this case), so use (1, 1).
+
+ result_view = v_grandchild;
+ result_view = v_grandchild->GetTooltipHandlerForPoint(gfx::Point(1, 1));
+ EXPECT_EQ(NULL, result_view);
+ result_view = NULL;
+
+ // When |v_child| returns false when CanProcessEventsWithinSubtree()
+ // is called, then neither |v_child| nor |v_grandchild| can be returned
+ // as a target (|v| should be returned as the target for each case).
+
+ v_grandchild->Reset();
+ v_child->set_can_process_events_within_subtree(false);
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+ EXPECT_EQ(v, result_view);
+ result_view = NULL;
+
+ // When |v| returns false when CanProcessEventsWithinSubtree()
+ // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned
+ // as a target (|root_view| should be returned as the target for each case).
+
+ v_child->Reset();
+ v->set_can_process_events_within_subtree(false);
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+ EXPECT_EQ(root_view, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+ EXPECT_EQ(root_view, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+ EXPECT_EQ(root_view, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+ EXPECT_EQ(root_view, result_view);
+ result_view = NULL;
+
+ result_view = root_view->GetEventHandlerForRect(rect_in_v);
+ EXPECT_EQ(root_view, result_view);
+ result_view = NULL;
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+ EXPECT_EQ(root_view, result_view);
+}
+
TEST_F(ViewTest, NotifyEnterExitOnChild) {
Widget* widget = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -1425,7 +1434,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Move the mouse in v111.
gfx::Point p1(6, 6);
- ui::MouseEvent move1(ui::ET_MOUSE_MOVED, p1, p1, 0);
+ ui::MouseEvent move1(ui::ET_MOUSE_MOVED, p1, p1, 0, 0);
root_view->OnMouseMoved(move1);
EXPECT_TRUE(v111->received_mouse_enter_);
EXPECT_FALSE(v11->last_mouse_event_type_);
@@ -1436,7 +1445,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Now, move into v121.
gfx::Point p2(65, 21);
- ui::MouseEvent move2(ui::ET_MOUSE_MOVED, p2, p2, 0);
+ ui::MouseEvent move2(ui::ET_MOUSE_MOVED, p2, p2, 0, 0);
root_view->OnMouseMoved(move2);
EXPECT_TRUE(v111->received_mouse_exit_);
EXPECT_TRUE(v121->received_mouse_enter_);
@@ -1447,7 +1456,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Now, move into v11.
gfx::Point p3(1, 1);
- ui::MouseEvent move3(ui::ET_MOUSE_MOVED, p3, p3, 0);
+ ui::MouseEvent move3(ui::ET_MOUSE_MOVED, p3, p3, 0, 0);
root_view->OnMouseMoved(move3);
EXPECT_TRUE(v121->received_mouse_exit_);
EXPECT_TRUE(v11->received_mouse_enter_);
@@ -1458,7 +1467,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Move to v21.
gfx::Point p4(121, 15);
- ui::MouseEvent move4(ui::ET_MOUSE_MOVED, p4, p4, 0);
+ ui::MouseEvent move4(ui::ET_MOUSE_MOVED, p4, p4, 0, 0);
root_view->OnMouseMoved(move4);
EXPECT_TRUE(v21->received_mouse_enter_);
EXPECT_FALSE(v2->last_mouse_event_type_);
@@ -1471,7 +1480,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Move to v1.
gfx::Point p5(21, 0);
- ui::MouseEvent move5(ui::ET_MOUSE_MOVED, p5, p5, 0);
+ ui::MouseEvent move5(ui::ET_MOUSE_MOVED, p5, p5, 0, 0);
root_view->OnMouseMoved(move5);
EXPECT_TRUE(v21->received_mouse_exit_);
EXPECT_TRUE(v1->received_mouse_enter_);
@@ -1481,7 +1490,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// Now, move into v11.
gfx::Point p6(15, 15);
- ui::MouseEvent mouse6(ui::ET_MOUSE_MOVED, p6, p6, 0);
+ ui::MouseEvent mouse6(ui::ET_MOUSE_MOVED, p6, p6, 0, 0);
root_view->OnMouseMoved(mouse6);
EXPECT_TRUE(v11->received_mouse_enter_);
EXPECT_FALSE(v1->last_mouse_event_type_);
@@ -1493,7 +1502,7 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
// and the mouse remains inside |v1| the whole time, it receives another ENTER
// when the mouse leaves v11.
gfx::Point p7(21, 0);
- ui::MouseEvent mouse7(ui::ET_MOUSE_MOVED, p7, p7, 0);
+ ui::MouseEvent mouse7(ui::ET_MOUSE_MOVED, p7, p7, 0, 0);
root_view->OnMouseMoved(mouse7);
EXPECT_TRUE(v11->received_mouse_exit_);
EXPECT_FALSE(v1->received_mouse_enter_);
@@ -1502,10 +1511,10 @@ TEST_F(ViewTest, NotifyEnterExitOnChild) {
}
TEST_F(ViewTest, Textfield) {
- const string16 kText = ASCIIToUTF16("Reality is that which, when you stop "
- "believing it, doesn't go away.");
- const string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!");
- const string16 kEmptyString;
+ const base::string16 kText = ASCIIToUTF16(
+ "Reality is that which, when you stop believing it, doesn't go away.");
+ const base::string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!");
+ const base::string16 kEmptyString;
Widget* widget = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -1521,7 +1530,7 @@ TEST_F(ViewTest, Textfield) {
EXPECT_EQ(kText, textfield->text());
textfield->AppendText(kExtraText);
EXPECT_EQ(kText + kExtraText, textfield->text());
- textfield->SetText(string16());
+ textfield->SetText(base::string16());
EXPECT_EQ(kEmptyString, textfield->text());
// Test selection related methods.
@@ -1537,9 +1546,10 @@ TEST_F(ViewTest, Textfield) {
// Tests that the Textfield view respond appropiately to cut/copy/paste.
TEST_F(ViewTest, TextfieldCutCopyPaste) {
- const string16 kNormalText = ASCIIToUTF16("Normal");
- const string16 kReadOnlyText = ASCIIToUTF16("Read only");
- const string16 kPasswordText = ASCIIToUTF16("Password! ** Secret stuff **");
+ const base::string16 kNormalText = ASCIIToUTF16("Normal");
+ const base::string16 kReadOnlyText = ASCIIToUTF16("Read only");
+ const base::string16 kPasswordText =
+ ASCIIToUTF16("Password! ** Secret stuff **");
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
@@ -1552,7 +1562,8 @@ TEST_F(ViewTest, TextfieldCutCopyPaste) {
Textfield* normal = new Textfield();
Textfield* read_only = new Textfield();
read_only->SetReadOnly(true);
- Textfield* password = new Textfield(Textfield::STYLE_OBSCURED);
+ Textfield* password = new Textfield();
+ password->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
root_view->AddChildView(normal);
root_view->AddChildView(read_only);
@@ -1568,7 +1579,7 @@ TEST_F(ViewTest, TextfieldCutCopyPaste) {
normal->SelectAll(false);
normal->ExecuteCommand(IDS_APP_CUT);
- string16 result;
+ base::string16 result;
clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
EXPECT_EQ(kNormalText, result);
normal->SetText(kNormalText); // Let's revert to the original content.
@@ -1641,7 +1652,9 @@ bool TestView::AcceleratorPressed(const ui::Accelerator& accelerator) {
return true;
}
-#if defined(OS_WIN) && !defined(USE_AURA)
+// TODO: these tests were initially commented out when getting aura to
+// run. Figure out if still valuable and either nuke or fix.
+#if 0
TEST_F(ViewTest, ActivateAccelerator) {
// Register a keyboard accelerator before the view is added to a window.
ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
@@ -1706,9 +1719,7 @@ TEST_F(ViewTest, ActivateAccelerator) {
widget->CloseNow();
}
-#endif
-#if defined(OS_WIN) && !defined(USE_AURA)
TEST_F(ViewTest, HiddenViewWithAccelerator) {
ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
TestView* view = new TestView();
@@ -1736,9 +1747,7 @@ TEST_F(ViewTest, HiddenViewWithAccelerator) {
widget->CloseNow();
}
-#endif
-#if defined(OS_WIN) && !defined(USE_AURA)
TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) {
ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
TestView* view = new TestView();
@@ -1770,9 +1779,7 @@ TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) {
widget->CloseNow();
}
-#endif
-#if defined(OS_WIN) && !defined(USE_AURA)
////////////////////////////////////////////////////////////////////////////////
// Mouse-wheel message rerouting
////////////////////////////////////////////////////////////////////////////////
@@ -1849,20 +1856,10 @@ TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) {
WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250));
EXPECT_EQ(20, scroll_view->GetVisibleRect().y());
- // Then the text-field.
- ::SendMessage(view_with_controls->text_field_->GetTestingHandle(),
- WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250));
- EXPECT_EQ(80, scroll_view->GetVisibleRect().y());
-
- // Ensure we don't scroll when the mouse is not over that window.
- ::SendMessage(view_with_controls->text_field_->GetTestingHandle(),
- WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(50, 50));
- EXPECT_EQ(80, scroll_view->GetVisibleRect().y());
-
window1->CloseNow();
window2->CloseNow();
}
-#endif
+#endif // 0
////////////////////////////////////////////////////////////////////////////////
// Native view hierachy
@@ -2030,14 +2027,15 @@ TEST_F(ViewTest, TransformEvent) {
gfx::Point p1(110, 210);
ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(pressed);
EXPECT_EQ(0, v1->last_mouse_event_type_);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
EXPECT_EQ(190, v2->location_.x());
EXPECT_EQ(10, v2->location_.y());
- ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0);
+ ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0,
+ 0);
root->OnMouseReleased(released);
// Now rotate |v2| inside |v1| clockwise.
@@ -2054,7 +2052,7 @@ TEST_F(ViewTest, TransformEvent) {
gfx::Point point2(110, 320);
ui::MouseEvent p2(ui::ET_MOUSE_PRESSED, point2, point2,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(p2);
EXPECT_EQ(0, v1->last_mouse_event_type_);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
@@ -2090,7 +2088,7 @@ TEST_F(ViewTest, TransformEvent) {
gfx::Point point(112, 110);
ui::MouseEvent p3(ui::ET_MOUSE_PRESSED, point, point,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(p3);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
@@ -2129,7 +2127,7 @@ TEST_F(ViewTest, TransformEvent) {
gfx::Point point3(124, 125);
ui::MouseEvent p4(ui::ET_MOUSE_PRESSED, point3, point3,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
root->OnMousePressed(p4);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
@@ -2299,6 +2297,39 @@ TEST_F(ViewTest, SetBoundsSameBoundsDoesntSchedulePaint) {
EXPECT_TRUE(view.scheduled_paint_rects_.empty());
}
+// Verifies AddChildView() and RemoveChildView() schedule appropriate paints.
+TEST_F(ViewTest, AddAndRemoveSchedulePaints) {
+ gfx::Rect viewport_bounds(0, 0, 100, 100);
+
+ // We have to put the View hierarchy into a Widget or no paints will be
+ // scheduled.
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = viewport_bounds;
+ widget->Init(params);
+ widget->GetRootView()->SetBoundsRect(viewport_bounds);
+
+ TestView* parent_view = new TestView;
+ widget->SetContentsView(parent_view);
+ parent_view->SetBoundsRect(viewport_bounds);
+ parent_view->scheduled_paint_rects_.clear();
+
+ View* child_view = new View;
+ child_view->SetBoundsRect(gfx::Rect(0, 0, 20, 20));
+ parent_view->AddChildView(child_view);
+ ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
+ EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
+
+ parent_view->scheduled_paint_rects_.clear();
+ parent_view->RemoveChildView(child_view);
+ scoped_ptr<View> child_deleter(child_view);
+ ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
+ EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
+
+ widget->CloseNow();
+}
+
// Tests conversion methods with a transform.
TEST_F(ViewTest, ConversionsWithTransform) {
TestView top_view;
@@ -2992,8 +3023,6 @@ TEST_F(ViewTest, AddExistingChild) {
// Layers
////////////////////////////////////////////////////////////////////////////////
-#if defined(USE_AURA)
-
namespace {
// Test implementation of LayerAnimator.
@@ -3027,7 +3056,7 @@ void TestLayerAnimator::SetBounds(const gfx::Rect& bounds) {
class ViewLayerTest : public ViewsTestBase {
public:
- ViewLayerTest() : widget_(NULL), old_use_acceleration_(false) {}
+ ViewLayerTest() : widget_(NULL) {}
virtual ~ViewLayerTest() {
}
@@ -3039,9 +3068,6 @@ class ViewLayerTest : public ViewsTestBase {
virtual void SetUp() OVERRIDE {
ViewTest::SetUp();
- old_use_acceleration_ = View::get_use_acceleration_when_possible();
- View::set_use_acceleration_when_possible(true);
-
widget_ = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.bounds = gfx::Rect(50, 50, 200, 200);
@@ -3051,7 +3077,6 @@ class ViewLayerTest : public ViewsTestBase {
}
virtual void TearDown() OVERRIDE {
- View::set_use_acceleration_when_possible(old_use_acceleration_);
widget_->CloseNow();
ViewsTestBase::TearDown();
}
@@ -3060,7 +3085,6 @@ class ViewLayerTest : public ViewsTestBase {
private:
Widget* widget_;
- bool old_use_acceleration_;
};
@@ -3506,17 +3530,6 @@ TEST_F(ViewLayerTest, AcquireLayer) {
c1.reset();
}
-// Verify that new layer scales content only if the old layer does.
-TEST_F(ViewLayerTest, RecreateLayerScaling) {
- scoped_ptr<View> v(new View());
- v->SetPaintToLayer(true);
- // Set to non default value.
- v->layer()->set_scale_content(false);
- scoped_ptr<ui::Layer> old_layer(v->RecreateLayer());
- ui::Layer* new_layer = v->layer();
- EXPECT_FALSE(new_layer->scale_content());
-}
-
// Verify the z-order of the layers as a result of calling RecreateLayer().
TEST_F(ViewLayerTest, RecreateLayerZOrder) {
scoped_ptr<View> v(new View());
@@ -3537,13 +3550,13 @@ TEST_F(ViewLayerTest, RecreateLayerZOrder) {
scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
- // Test the new layer order. |v1_old_layer| should be above the layers
+ // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
// for |v1| and |v2|.
const std::vector<ui::Layer*>& child_layers_post = v->layer()->children();
ASSERT_EQ(3u, child_layers_post.size());
EXPECT_EQ(v1->layer(), child_layers_post[0]);
- EXPECT_EQ(v2->layer(), child_layers_post[1]);
- EXPECT_EQ(v1_old_layer, child_layers_post[2]);
+ EXPECT_EQ(v1_old_layer, child_layers_post[1]);
+ EXPECT_EQ(v2->layer(), child_layers_post[2]);
}
// Verify the z-order of the layers as a result of calling RecreateLayer when
@@ -3569,15 +3582,393 @@ TEST_F(ViewLayerTest, RecreateLayerZOrderWidgetParent) {
scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
- // Test the new layer order. |v1_old_layer| should be above the layers
- // for |v1| and |v2|.
+ // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
const std::vector<ui::Layer*>& child_layers_post = root_layer->children();
ASSERT_EQ(3u, child_layers_post.size());
EXPECT_EQ(v1->layer(), child_layers_post[0]);
- EXPECT_EQ(v2->layer(), child_layers_post[1]);
- EXPECT_EQ(v1_old_layer, child_layers_post[2]);
+ EXPECT_EQ(v1_old_layer, child_layers_post[1]);
+ EXPECT_EQ(v2->layer(), child_layers_post[2]);
+}
+
+// Verifies RecreateLayer() moves all Layers over, even those that don't have
+// a View.
+TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) {
+ View v;
+ v.SetPaintToLayer(true);
+ View child;
+ child.SetPaintToLayer(true);
+ v.AddChildView(&child);
+ ASSERT_TRUE(v.layer() != NULL);
+ ASSERT_EQ(1u, v.layer()->children().size());
+ EXPECT_EQ(v.layer()->children()[0], child.layer());
+
+ ui::Layer layer(ui::LAYER_NOT_DRAWN);
+ v.layer()->Add(&layer);
+ v.layer()->StackAtBottom(&layer);
+
+ scoped_ptr<ui::Layer> old_layer(v.RecreateLayer());
+
+ // All children should be moved from old layer to new layer.
+ ASSERT_TRUE(old_layer.get() != NULL);
+ EXPECT_TRUE(old_layer->children().empty());
+
+ // And new layer should have the two children.
+ ASSERT_TRUE(v.layer() != NULL);
+ ASSERT_EQ(2u, v.layer()->children().size());
+ EXPECT_EQ(v.layer()->children()[0], &layer);
+ EXPECT_EQ(v.layer()->children()[1], child.layer());
+}
+
+class BoundsTreeTestView : public View {
+ public:
+ BoundsTreeTestView() {}
+
+ virtual void PaintChildren(gfx::Canvas* canvas,
+ const CullSet& cull_set) OVERRIDE {
+ // Save out a copy of the cull_set before calling the base implementation.
+ last_cull_set_.clear();
+ if (cull_set.cull_set_) {
+ for (base::hash_set<intptr_t>::iterator it = cull_set.cull_set_->begin();
+ it != cull_set.cull_set_->end();
+ ++it) {
+ last_cull_set_.insert(reinterpret_cast<View*>(*it));
+ }
+ }
+ View::PaintChildren(canvas, cull_set);
+ }
+
+ std::set<View*> last_cull_set_;
+};
+
+TEST_F(ViewLayerTest, BoundsTreePaintUpdatesCullSet) {
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ View* v1 = new View();
+ v1->SetBoundsRect(gfx::Rect(10, 15, 150, 151));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View();
+ v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
+ v1->AddChildView(v2);
+
+ // Schedule a full-view paint to get everyone's rectangles updated.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Now we have test_view - v1 - v2. Damage to only test_view should only
+ // return root_view and test_view.
+ test_view->SchedulePaintInRect(gfx::Rect(0, 0, 1, 1));
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(2U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+
+ // Damage to v1 only should only return root_view, test_view, and v1.
+ test_view->SchedulePaintInRect(gfx::Rect(11, 16, 1, 1));
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(3U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+
+ // A Damage rect inside v2 should get all 3 views back in the |last_cull_set_|
+ // on call to TestView::Paint(), along with the widget root view.
+ test_view->SchedulePaintInRect(gfx::Rect(31, 49, 1, 1));
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(4U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
}
-#endif // USE_AURA
+TEST_F(ViewLayerTest, BoundsTreeWithRTL) {
+ std::string locale = l10n_util::GetApplicationLocale(std::string());
+ base::i18n::SetICUDefaultLocale("ar");
+
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ // Add child views, which should be in RTL coordinate space of parent view.
+ View* v1 = new View;
+ v1->SetBoundsRect(gfx::Rect(10, 12, 25, 26));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View;
+ v2->SetBoundsRect(gfx::Rect(5, 6, 7, 8));
+ v1->AddChildView(v2);
+
+ // Schedule a full-view paint to get everyone's rectangles updated.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Damage to the right side of the parent view should touch both child views.
+ gfx::Rect rtl_damage(test_view->bounds().width() - 16, 18, 1, 1);
+ test_view->SchedulePaintInRect(rtl_damage);
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(4U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+
+ // Damage to the left side of the parent view should only touch the
+ // container views.
+ gfx::Rect ltr_damage(16, 18, 1, 1);
+ test_view->SchedulePaintInRect(ltr_damage);
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(2U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+
+ // Reset locale.
+ base::i18n::SetICUDefaultLocale(locale);
+}
+
+TEST_F(ViewLayerTest, BoundsTreeSetBoundsChangesCullSet) {
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ View* v1 = new View;
+ v1->SetBoundsRect(gfx::Rect(5, 6, 100, 101));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View;
+ v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
+ v1->AddChildView(v2);
+
+ // Schedule a full-view paint to get everyone's rectangles updated.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Move v1 to a new origin out of the way of our next query.
+ v1->SetBoundsRect(gfx::Rect(50, 60, 100, 101));
+ // The move will force a repaint.
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Schedule a paint with damage rect where v1 used to be.
+ test_view->SchedulePaintInRect(gfx::Rect(5, 6, 10, 11));
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Should only have picked up root_view and test_view.
+ EXPECT_EQ(2U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+}
+
+TEST_F(ViewLayerTest, BoundsTreeLayerChangeMakesNewTree) {
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ View* v1 = new View;
+ v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View;
+ v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+ v1->AddChildView(v2);
+
+ // Schedule a full-view paint to get everyone's rectangles updated.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Set v1 to paint to its own layer, it should remove itself from the
+ // test_view heiarchy and no longer intersect with damage rects in that cull
+ // set.
+ v1->SetPaintToLayer(true);
+
+ // Schedule another full-view paint.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ // v1 and v2 should no longer be present in the test_view cull_set.
+ EXPECT_EQ(2U, test_view->last_cull_set_.size());
+ EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
+
+ // Now set v1 back to not painting to a layer.
+ v1->SetPaintToLayer(false);
+ // Schedule another full-view paint.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ // We should be back to the full cull set including v1 and v2.
+ EXPECT_EQ(4U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+}
+
+TEST_F(ViewLayerTest, BoundsTreeRemoveChildRemovesBounds) {
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ View* v1 = new View;
+ v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View;
+ v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+ v1->AddChildView(v2);
+
+ // Schedule a full-view paint to get everyone's rectangles updated.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Now remove v1 from the root view.
+ test_view->RemoveChildView(v1);
+
+ // Schedule another full-view paint.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ // v1 and v2 should no longer be present in the test_view cull_set.
+ EXPECT_EQ(2U, test_view->last_cull_set_.size());
+ EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
+
+ // View v1 and v2 are no longer part of view hierarchy and therefore won't be
+ // deleted with that hierarchy.
+ delete v1;
+}
+
+TEST_F(ViewLayerTest, BoundsTreeMoveViewMovesBounds) {
+ BoundsTreeTestView* test_view = new BoundsTreeTestView;
+ widget()->SetContentsView(test_view);
+
+ // Build hierarchy v1 - v2 - v3.
+ View* v1 = new View;
+ v1->SetBoundsRect(gfx::Rect(20, 30, 150, 160));
+ test_view->AddChildView(v1);
+
+ View* v2 = new View;
+ v2->SetBoundsRect(gfx::Rect(5, 10, 40, 50));
+ v1->AddChildView(v2);
+
+ View* v3 = new View;
+ v3->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+ v2->AddChildView(v3);
+
+ // Schedule a full-view paint and ensure all views are present in the cull.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+ EXPECT_EQ(5U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v3));
+
+ // Build an unrelated view hierarchy and move v2 in to it.
+ scoped_ptr<Widget> test_widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.bounds = gfx::Rect(10, 10, 500, 500);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ test_widget->Init(params);
+ test_widget->Show();
+ BoundsTreeTestView* widget_view = new BoundsTreeTestView;
+ test_widget->SetContentsView(widget_view);
+ widget_view->AddChildView(v2);
+
+ // Now schedule full-view paints in both widgets.
+ test_view->SchedulePaintInRect(test_view->bounds());
+ widget_view->SchedulePaintInRect(widget_view->bounds());
+ GetRootLayer()->GetCompositor()->ScheduleDraw();
+ ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+ // Only v1 should be present in the first cull set.
+ EXPECT_EQ(3U, test_view->last_cull_set_.size());
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+ EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+
+ // We should find v2 and v3 in the widget_view cull_set.
+ EXPECT_EQ(4U, widget_view->last_cull_set_.size());
+ EXPECT_EQ(1U, widget_view->last_cull_set_.count(test_widget->GetRootView()));
+ EXPECT_EQ(1U, widget_view->last_cull_set_.count(widget_view));
+ EXPECT_EQ(1U, widget_view->last_cull_set_.count(v2));
+ EXPECT_EQ(1U, widget_view->last_cull_set_.count(v3));
+}
+
+TEST_F(ViewTest, FocusableAssertions) {
+ // View subclasses may change insets based on whether they are focusable,
+ // which effects the preferred size. To avoid preferred size changing around
+ // these Views need to key off the last value set to SetFocusable(), not
+ // whether the View is focusable right now. For this reason it's important
+ // that focusable() return the last value passed to SetFocusable and not
+ // whether the View is focusable right now.
+ TestView view;
+ view.SetFocusable(true);
+ EXPECT_TRUE(view.focusable());
+ view.SetEnabled(false);
+ EXPECT_TRUE(view.focusable());
+ view.SetFocusable(false);
+ EXPECT_FALSE(view.focusable());
+}
+
+// Verifies when a view is deleted it is removed from ViewStorage.
+TEST_F(ViewTest, UpdateViewStorageOnDelete) {
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ const int storage_id = view_storage->CreateStorageID();
+ {
+ View view;
+ view_storage->StoreView(storage_id, &view);
+ }
+ EXPECT_TRUE(view_storage->RetrieveView(storage_id) == NULL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeTheme
+////////////////////////////////////////////////////////////////////////////////
+
+void TestView::OnNativeThemeChanged(const ui::NativeTheme* native_theme) {
+ native_theme_ = native_theme;
+}
+
+TEST_F(ViewTest, OnNativeThemeChanged) {
+ TestView* test_view = new TestView();
+ EXPECT_FALSE(test_view->native_theme_);
+ TestView* test_view_child = new TestView();
+ EXPECT_FALSE(test_view_child->native_theme_);
+
+ // Child view added before the widget hierarchy exists should get the
+ // new native theme notification.
+ test_view->AddChildView(test_view_child);
+
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget->Init(params);
+
+ widget->GetRootView()->AddChildView(test_view);
+ EXPECT_TRUE(test_view->native_theme_);
+ EXPECT_EQ(widget->GetNativeTheme(), test_view->native_theme_);
+ EXPECT_TRUE(test_view_child->native_theme_);
+ EXPECT_EQ(widget->GetNativeTheme(), test_view_child->native_theme_);
+
+ // Child view added after the widget hierarchy exists should also get the
+ // notification.
+ TestView* test_view_child_2 = new TestView();
+ test_view->AddChildView(test_view_child_2);
+ EXPECT_TRUE(test_view_child_2->native_theme_);
+ EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_);
+
+ widget->CloseNow();
+}
} // namespace views
diff --git a/chromium/ui/views/view_unittest_aura.cc b/chromium/ui/views/view_unittest_aura.cc
new file mode 100644
index 00000000000..5b649101050
--- /dev/null
+++ b/chromium/ui/views/view_unittest_aura.cc
@@ -0,0 +1,160 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/view.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_tree_owner.h"
+#include "ui/compositor/test/test_layers.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/view_constants_aura.h"
+#include "ui/views/widget/widget.h"
+#include "ui/wm/core/window_util.h"
+
+namespace views {
+
+namespace {
+
+// Creates a widget of TYPE_CONTROL.
+// The caller takes ownership of the returned widget.
+Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) {
+ Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
+ params.parent = parent;
+ params.bounds = bounds;
+ Widget* widget = new Widget();
+ widget->Init(params);
+ return widget;
+}
+
+// Returns a view with a layer with the passed in |bounds| and |layer_name|.
+// The caller takes ownership of the returned view.
+View* CreateViewWithLayer(const gfx::Rect& bounds, const char* layer_name) {
+ View* view = new View();
+ view->SetBoundsRect(bounds);
+ view->SetPaintToLayer(true);
+ view->layer()->set_name(layer_name);
+ return view;
+}
+
+} // namespace
+
+typedef ViewsTestBase ViewAuraTest;
+
+// Test that wm::RecreateLayers() recreates the layers for all child windows and
+// all child views and that the z-order of the recreated layers matches that of
+// the original layers.
+// Test hierarchy:
+// w1
+// +-- v1
+// +-- v2 (no layer)
+// +-- v3 (no layer)
+// +-- v4
+// +-- w2
+// +-- v5
+// +-- v6
+// +-- v7
+// +-- v8
+// +-- v9
+TEST_F(ViewAuraTest, RecreateLayersWithWindows) {
+ Widget* w1 = CreateControlWidget(GetContext(), gfx::Rect(0, 0, 100, 100));
+ w1->GetNativeView()->layer()->set_name("w1");
+
+ View* v2 = new View();
+ v2->SetBounds(0, 1, 100, 101);
+ View* v3 = new View();
+ v3->SetBounds(0, 2, 100, 102);
+ View* w2_host_view = new View();
+
+ View* v1 = CreateViewWithLayer(gfx::Rect(0, 3, 100, 103), "v1");
+ ui::Layer* v1_layer = v1->layer();
+ w1->GetRootView()->AddChildView(v1);
+ w1->GetRootView()->AddChildView(v2);
+ v2->AddChildView(v3);
+ View* v4 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4");
+ ui::Layer* v4_layer = v4->layer();
+ v2->AddChildView(v4);
+
+ w1->GetRootView()->AddChildView(w2_host_view);
+ View* v7 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v7");
+ ui::Layer* v7_layer = v7->layer();
+ w1->GetRootView()->AddChildView(v7);
+
+ View* v8 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v8");
+ ui::Layer* v8_layer = v8->layer();
+ v7->AddChildView(v8);
+
+ View* v9 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v9");
+ ui::Layer* v9_layer = v9->layer();
+ v7->AddChildView(v9);
+
+ Widget* w2 =
+ CreateControlWidget(w1->GetNativeView(), gfx::Rect(0, 5, 100, 105));
+ w2->GetNativeView()->layer()->set_name("w2");
+ w2->GetNativeView()->SetProperty(kHostViewKey, w2_host_view);
+
+ View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
+ w2->GetRootView()->AddChildView(v5);
+ View* v6 = CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6");
+ ui::Layer* v6_layer = v6->layer();
+ v5->AddChildView(v6);
+
+ // Test the initial order of the layers.
+ ui::Layer* w1_layer = w1->GetNativeView()->layer();
+ ASSERT_EQ("w1", w1_layer->name());
+ ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
+ ui::Layer* w2_layer = w1_layer->children()[2];
+ ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
+ ui::Layer* v5_layer = w2_layer->children()[0];
+ ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
+
+ {
+ scoped_ptr<ui::LayerTreeOwner> cloned_owner(
+ wm::RecreateLayers(w1->GetNativeView()));
+ EXPECT_EQ(w1_layer, cloned_owner->root());
+ EXPECT_NE(w1_layer, w1->GetNativeView()->layer());
+
+ // The old layers should still exist and have the same hierarchy.
+ ASSERT_EQ("w1", w1_layer->name());
+ ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
+ ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
+ ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
+ EXPECT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_layer));
+
+ ASSERT_EQ(4u, w1_layer->children().size());
+ EXPECT_EQ(v1_layer, w1_layer->children()[0]);
+ EXPECT_EQ(v4_layer, w1_layer->children()[1]);
+ EXPECT_EQ(w2_layer, w1_layer->children()[2]);
+ EXPECT_EQ(v7_layer, w1_layer->children()[3]);
+
+ ASSERT_EQ(1u, w2_layer->children().size());
+ EXPECT_EQ(v5_layer, w2_layer->children()[0]);
+
+ ASSERT_EQ(1u, v5_layer->children().size());
+ EXPECT_EQ(v6_layer, v5_layer->children()[0]);
+
+ ASSERT_EQ(0u, v6_layer->children().size());
+
+ EXPECT_EQ(2u, v7_layer->children().size());
+ EXPECT_EQ(v8_layer, v7_layer->children()[0]);
+ EXPECT_EQ(v9_layer, v7_layer->children()[1]);
+
+ // The cloned layers should have the same hierarchy as old.
+ ui::Layer* w1_new_layer = w1->GetNativeView()->layer();
+ EXPECT_EQ("w1", w1_new_layer->name());
+ ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_new_layer));
+ ui::Layer* w2_new_layer = w1_new_layer->children()[2];
+ ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_new_layer));
+ ui::Layer* v5_new_layer = w2_new_layer->children()[0];
+ ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_new_layer));
+ ui::Layer* v7_new_layer = w1_new_layer->children()[3];
+ ASSERT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_new_layer));
+ }
+ // The views and the widgets are destroyed when AuraTestHelper::TearDown()
+ // destroys root_window().
+}
+
+} // namespace views
diff --git a/chromium/ui/views/view_win.cc b/chromium/ui/views/view_win.cc
deleted file mode 100644
index 183a7758cc3..00000000000
--- a/chromium/ui/views/view_win.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/view.h"
-
-// Necessary to define oleacc GUID's.
-#include <windows.h>
-#include <initguid.h>
-#include <oleacc.h>
-
-namespace views {
-
-int View::GetHorizontalDragThreshold() {
- static int threshold = -1;
- if (threshold == -1)
- threshold = GetSystemMetrics(SM_CXDRAG) / 2;
- return threshold;
-}
-
-int View::GetVerticalDragThreshold() {
- static int threshold = -1;
- if (threshold == -1)
- threshold = GetSystemMetrics(SM_CYDRAG) / 2;
- return threshold;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/views.gyp b/chromium/ui/views/views.gyp
index af835c22b96..646bb2fcb20 100644
--- a/chromium/ui/views/views.gyp
+++ b/chromium/ui/views/views.gyp
@@ -8,11 +8,16 @@
'target_defaults': {
'conditions': [
['use_aura==1', {
- 'sources/': [ ['exclude', '_win\\.(h|cc)$'] ],
- 'dependencies': [ '../aura/aura.gyp:aura', ],
- }],
- ['OS!="linux" or chromeos==1', {
- 'sources/': [ ['exclude', '_linux\\.(h|cc)$'] ],
+ 'dependencies': [
+ '../aura/aura.gyp:aura',
+ '../wm/wm.gyp:wm',
+ ],
+ }, { # use_aura==0
+ 'sources/': [
+ ['exclude', '^corewm/'],
+ ['exclude', '^touchui/'],
+ ['exclude', '^widget/desktop_aura/']
+ ]
}],
],
},
@@ -28,20 +33,36 @@
'../../third_party/icu/icu.gyp:icui18n',
'../../third_party/icu/icu.gyp:icuuc',
'../../url/url.gyp:url_lib',
- '../base/strings/ui_strings.gyp:ui_strings',
+ '../accessibility/accessibility.gyp:accessibility',
+ '../accessibility/accessibility.gyp:ax_gen',
+ '../base/ui_base.gyp:ui_base',
'../compositor/compositor.gyp:compositor',
'../events/events.gyp:events',
'../events/events.gyp:events_base',
+ '../events/platform/events_platform.gyp:events_platform',
'../gfx/gfx.gyp:gfx',
+ '../gfx/gfx.gyp:gfx_geometry',
'../native_theme/native_theme.gyp:native_theme',
'../resources/ui_resources.gyp:ui_resources',
- '../ui.gyp:ui',
+ '../strings/ui_strings.gyp:ui_strings',
+ ],
+ 'export_dependent_settings': [
+ '../accessibility/accessibility.gyp:ax_gen',
],
'defines': [
'VIEWS_IMPLEMENTATION',
],
'sources': [
# All .cc, .h under views, except unittests
+ 'accessibility/ax_aura_obj_cache.cc',
+ 'accessibility/ax_aura_obj_cache.h',
+ 'accessibility/ax_aura_obj_wrapper.h',
+ 'accessibility/ax_view_obj_wrapper.cc',
+ 'accessibility/ax_view_obj_wrapper.h',
+ 'accessibility/ax_widget_obj_wrapper.cc',
+ 'accessibility/ax_widget_obj_wrapper.h',
+ 'accessibility/ax_window_obj_wrapper.cc',
+ 'accessibility/ax_window_obj_wrapper.h',
'accessibility/native_view_accessibility.cc',
'accessibility/native_view_accessibility.h',
'accessibility/native_view_accessibility_win.cc',
@@ -62,10 +83,16 @@
'bubble/bubble_delegate.h',
'bubble/bubble_frame_view.cc',
'bubble/bubble_frame_view.h',
+ 'bubble/bubble_window_targeter.cc',
+ 'bubble/bubble_window_targeter.h',
'bubble/tray_bubble_view.cc',
'bubble/tray_bubble_view.h',
'button_drag_utils.cc',
'button_drag_utils.h',
+ 'cocoa/bridged_content_view.h',
+ 'cocoa/bridged_content_view.mm',
+ 'cocoa/bridged_native_widget.h',
+ 'cocoa/bridged_native_widget.mm',
'color_chooser/color_chooser_listener.h',
'color_chooser/color_chooser_view.cc',
'color_chooser/color_chooser_view.h',
@@ -108,21 +135,30 @@
'controls/link.h',
'controls/link_listener.h',
'controls/menu/display_change_listener_aura.cc',
+ 'controls/menu/display_change_listener_mac.cc',
'controls/menu/menu.cc',
'controls/menu/menu.h',
'controls/menu/menu_2.cc',
'controls/menu/menu_2.h',
'controls/menu/menu_config.cc',
'controls/menu/menu_config.h',
- 'controls/menu/menu_config_views.cc',
+ 'controls/menu/menu_config_aura.cc',
+ 'controls/menu/menu_config_mac.cc',
'controls/menu/menu_config_win.cc',
'controls/menu/menu_controller.cc',
'controls/menu/menu_controller.h',
- 'controls/menu/menu_controller_aura.cc',
'controls/menu/menu_controller_delegate.h',
- 'controls/menu/menu_controller_win.cc',
+ 'controls/menu/menu_event_dispatcher_linux.cc',
+ 'controls/menu/menu_event_dispatcher_linux.h',
'controls/menu/menu_delegate.cc',
'controls/menu/menu_delegate.h',
+ 'controls/menu/menu_message_pump_dispatcher_win.cc',
+ 'controls/menu/menu_message_pump_dispatcher_win.h',
+ 'controls/menu/menu_message_loop.h',
+ 'controls/menu/menu_message_loop_aura.cc',
+ 'controls/menu/menu_message_loop_aura.h',
+ 'controls/menu/menu_message_loop_mac.cc',
+ 'controls/menu/menu_message_loop_mac.h',
'controls/menu/menu_host.cc',
'controls/menu/menu_host.h',
'controls/menu/menu_host_root_view.cc',
@@ -142,8 +178,7 @@
'controls/menu/menu_separator.h',
'controls/menu/menu_separator_views.cc',
'controls/menu/menu_separator_win.cc',
- 'controls/menu/menu_win.cc',
- 'controls/menu/menu_win.h',
+ 'controls/menu/menu_types.h',
'controls/menu/menu_wrapper.h',
'controls/menu/native_menu_win.cc',
'controls/menu/native_menu_win.h',
@@ -153,16 +188,11 @@
'controls/menu/submenu_view.h',
'controls/message_box_view.cc',
'controls/message_box_view.h',
- 'controls/native_control.cc',
- 'controls/native_control.h',
- 'controls/native_control_win.cc',
- 'controls/native_control_win.h',
'controls/native/native_view_host.cc',
'controls/native/native_view_host.h',
'controls/native/native_view_host_aura.cc',
'controls/native/native_view_host_aura.h',
- 'controls/native/native_view_host_win.cc',
- 'controls/native/native_view_host_win.h',
+ 'controls/native/native_view_host_mac.cc',
'controls/prefix_delegate.h',
'controls/prefix_selector.cc',
'controls/prefix_selector.h',
@@ -179,8 +209,6 @@
'controls/scrollbar/base_scroll_bar_button.h',
'controls/scrollbar/base_scroll_bar_thumb.cc',
'controls/scrollbar/base_scroll_bar_thumb.h',
- 'controls/scrollbar/bitmap_scroll_bar.cc',
- 'controls/scrollbar/bitmap_scroll_bar.h',
'controls/scrollbar/kennedy_scroll_bar.cc',
'controls/scrollbar/kennedy_scroll_bar.h',
'controls/scrollbar/native_scroll_bar_views.cc',
@@ -215,46 +243,20 @@
'controls/table/table_view.h',
'controls/table/table_view_observer.h',
'controls/table/table_view_row_background_painter.h',
- 'controls/textfield/native_textfield_views.cc',
- 'controls/textfield/native_textfield_views.h',
- 'controls/textfield/native_textfield_wrapper.h',
'controls/textfield/textfield.cc',
'controls/textfield/textfield.h',
'controls/textfield/textfield_controller.cc',
'controls/textfield/textfield_controller.h',
- 'controls/textfield/textfield_views_model.cc',
- 'controls/textfield/textfield_views_model.h',
+ 'controls/textfield/textfield_model.cc',
+ 'controls/textfield/textfield_model.h',
'controls/throbber.cc',
'controls/throbber.h',
'controls/tree/tree_view.cc',
'controls/tree/tree_view.h',
'controls/tree/tree_view_controller.cc',
'controls/tree/tree_view_controller.h',
- 'corewm/base_focus_rules.cc',
- 'corewm/base_focus_rules.h',
- 'corewm/capture_controller.cc',
- 'corewm/capture_controller.h',
- 'corewm/compound_event_filter.cc',
- 'corewm/compound_event_filter.h',
- 'corewm/corewm_switches.cc',
- 'corewm/corewm_switches.h',
- 'corewm/cursor_manager.cc',
- 'corewm/cursor_manager.h',
- 'corewm/focus_controller.cc',
- 'corewm/focus_controller.h',
- 'corewm/focus_rules.h',
- 'corewm/image_grid.cc',
- 'corewm/image_grid.h',
- 'corewm/input_method_event_filter.cc',
- 'corewm/input_method_event_filter.h',
- 'corewm/native_cursor_manager.h',
- 'corewm/native_cursor_manager_delegate.h',
- 'corewm/shadow.cc',
- 'corewm/shadow.h',
- 'corewm/shadow_controller.cc',
- 'corewm/shadow_controller.h',
- 'corewm/shadow_types.cc',
- 'corewm/shadow_types.h',
+ 'corewm/cursor_height_provider_win.cc',
+ 'corewm/cursor_height_provider_win.h',
'corewm/tooltip.h',
'corewm/tooltip_aura.cc',
'corewm/tooltip_aura.h',
@@ -262,27 +264,14 @@
'corewm/tooltip_controller.h',
'corewm/tooltip_win.cc',
'corewm/tooltip_win.h',
- 'corewm/transient_window_stacking_client.cc',
- 'corewm/transient_window_stacking_client.h',
- 'corewm/visibility_controller.cc',
- 'corewm/visibility_controller.h',
- 'corewm/window_animations.cc',
- 'corewm/window_animations.h',
- 'corewm/window_modality_controller.cc',
- 'corewm/window_modality_controller.h',
- 'corewm/window_util.cc',
- 'corewm/window_util.h',
+ 'cull_set.cc',
+ 'cull_set.h',
'debug_utils.cc',
'debug_utils.h',
'drag_controller.h',
'drag_utils.cc',
'drag_utils.h',
- 'event_utils.h',
- 'event_utils_aura.cc',
- 'event_utils_win.cc',
- 'focus/accelerator_handler.h',
- 'focus/accelerator_handler_aura.cc',
- 'focus/accelerator_handler_win.cc',
+ 'drag_utils_aura.cc',
'focus/external_focus_tracker.cc',
'focus/external_focus_tracker.h',
'focus/focus_manager.cc',
@@ -296,14 +285,16 @@
'focus/view_storage.h',
'focus/widget_focus_manager.cc',
'focus/widget_focus_manager.h',
+ 'ime/input_method.h',
'ime/input_method_base.cc',
'ime/input_method_base.h',
'ime/input_method_bridge.cc',
'ime/input_method_bridge.h',
'ime/input_method_delegate.h',
- 'ime/input_method.h',
'ime/mock_input_method.cc',
'ime/mock_input_method.h',
+ 'ime/null_input_method.cc',
+ 'ime/null_input_method.h',
'layout/box_layout.cc',
'layout/box_layout.h',
'layout/fill_layout.cc',
@@ -318,15 +309,21 @@
'linux_ui/status_icon_linux.h',
'linux_ui/status_icon_linux.cc',
'linux_ui/window_button_order_observer.h',
+ 'linux_ui/window_button_order_provider.cc',
+ 'masked_view_targeter.cc',
+ 'masked_view_targeter.h',
'metrics.cc',
'metrics.h',
'metrics_aura.cc',
- 'metrics_win.cc',
+ 'metrics_mac.cc',
'mouse_constants.h',
- 'mouse_watcher.cc',
'mouse_watcher.h',
+ 'mouse_watcher_aura.cc',
'mouse_watcher_view_host.cc',
'mouse_watcher_view_host.h',
+ 'native_cursor.h',
+ 'native_cursor_aura.cc',
+ 'native_cursor_mac.mm',
'native_theme_delegate.h',
'painter.cc',
'painter.h',
@@ -344,7 +341,6 @@
'touchui/touch_selection_controller_impl.h',
'view.cc',
'view.h',
- 'view_aura.cc',
'view_constants.cc',
'view_constants.h',
'view_constants_aura.cc',
@@ -353,15 +349,15 @@
'view_model.h',
'view_model_utils.cc',
'view_model_utils.h',
- 'view_win.cc',
+ 'view_targeter.cc',
+ 'view_targeter.h',
'views_switches.cc',
'views_switches.h',
'views_delegate.cc',
'views_delegate.h',
- 'widget/aero_tooltip_manager.cc',
- 'widget/aero_tooltip_manager.h',
- 'widget/child_window_message_processor.cc',
- 'widget/child_window_message_processor.h',
+ 'views_touch_selection_controller_factory.h',
+ 'views_touch_selection_controller_factory_aura.cc',
+ 'views_touch_selection_controller_factory_mac.cc',
'widget/desktop_aura/desktop_capture_client.cc',
'widget/desktop_aura/desktop_capture_client.h',
'widget/desktop_aura/desktop_cursor_loader_updater.h',
@@ -386,12 +382,12 @@
'widget/desktop_aura/desktop_native_cursor_manager.h',
'widget/desktop_aura/desktop_native_widget_aura.cc',
'widget/desktop_aura/desktop_native_widget_aura.h',
- 'widget/desktop_aura/desktop_root_window_host.h',
- 'widget/desktop_aura/desktop_root_window_host_ozone.cc',
- 'widget/desktop_aura/desktop_root_window_host_win.cc',
- 'widget/desktop_aura/desktop_root_window_host_win.h',
- 'widget/desktop_aura/desktop_root_window_host_x11.cc',
- 'widget/desktop_aura/desktop_root_window_host_x11.h',
+ 'widget/desktop_aura/desktop_window_tree_host.h',
+ 'widget/desktop_aura/desktop_window_tree_host_ozone.cc',
+ 'widget/desktop_aura/desktop_window_tree_host_win.cc',
+ 'widget/desktop_aura/desktop_window_tree_host_win.h',
+ 'widget/desktop_aura/desktop_window_tree_host_x11.cc',
+ 'widget/desktop_aura/desktop_window_tree_host_x11.h',
'widget/desktop_aura/desktop_screen.h',
'widget/desktop_aura/desktop_screen_ozone.cc',
'widget/desktop_aura/desktop_screen_position_client.cc',
@@ -404,6 +400,10 @@
'widget/desktop_aura/x11_desktop_handler.h',
'widget/desktop_aura/x11_desktop_window_move_client.cc',
'widget/desktop_aura/x11_desktop_window_move_client.h',
+ 'widget/desktop_aura/x11_scoped_capture.cc',
+ 'widget/desktop_aura/x11_scoped_capture.h',
+ 'widget/desktop_aura/x11_topmost_window_finder.cc',
+ 'widget/desktop_aura/x11_topmost_window_finder.h',
'widget/desktop_aura/x11_whole_screen_move_loop.cc',
'widget/desktop_aura/x11_whole_screen_move_loop.h',
'widget/desktop_aura/x11_whole_screen_move_loop_delegate.h',
@@ -411,8 +411,6 @@
'widget/desktop_aura/x11_window_event_filter.h',
'widget/drop_helper.cc',
'widget/drop_helper.h',
- 'widget/drop_target_win.cc',
- 'widget/drop_target_win.h',
'widget/root_view.cc',
'widget/root_view.h',
'widget/monitor_win.cc',
@@ -421,13 +419,11 @@
'widget/native_widget_aura.cc',
'widget/native_widget_aura.h',
'widget/native_widget_delegate.h',
+ 'widget/native_widget_mac.h',
+ 'widget/native_widget_mac.mm',
'widget/native_widget_private.h',
- 'widget/native_widget_win.cc',
- 'widget/native_widget_win.h',
'widget/tooltip_manager_aura.cc',
'widget/tooltip_manager_aura.h',
- 'widget/tooltip_manager_win.cc',
- 'widget/tooltip_manager_win.h',
'widget/tooltip_manager.cc',
'widget/tooltip_manager.h',
'widget/widget.cc',
@@ -441,10 +437,9 @@
'widget/widget_hwnd_utils.cc',
'widget/widget_hwnd_utils.h',
'widget/widget_observer.h',
+ 'widget/widget_removals_observer.h',
'widget/window_reorderer.cc',
'widget/window_reorderer.h',
- 'win/appbar.cc',
- 'win/appbar.h',
'win/fullscreen_handler.cc',
'win/fullscreen_handler.h',
'win/hwnd_message_handler.cc',
@@ -452,7 +447,6 @@
'win/hwnd_message_handler_delegate.h',
'win/hwnd_util.h',
'win/hwnd_util_aurawin.cc',
- 'win/hwnd_util_win.cc',
'win/scoped_fullscreen_visibility.cc',
'win/scoped_fullscreen_visibility.h',
'window/client_view.cc',
@@ -470,6 +464,8 @@
'window/native_frame_view.h',
'window/non_client_view.cc',
'window/non_client_view.h',
+ 'window/window_button_order_provider.cc',
+ 'window/window_button_order_provider.h',
'window/window_resources.h',
'window/window_shape.cc',
'window/window_shape.h',
@@ -478,53 +474,6 @@
'../../third_party/wtl/include',
],
'conditions': [
- ['use_aura==1', {
- 'sources!': [
- 'controls/native_control.cc',
- 'controls/native_control.h',
- 'controls/scrollbar/bitmap_scroll_bar.cc',
- 'controls/scrollbar/bitmap_scroll_bar.h',
- 'controls/table/table_view_observer.h',
- 'widget/aero_tooltip_manager.cc',
- 'widget/aero_tooltip_manager.h',
- 'widget/child_window_message_processor.cc',
- 'widget/child_window_message_processor.h',
- 'widget/tooltip_manager_win.cc',
- 'widget/tooltip_manager_win.h',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'sources/': [
- ['include', 'controls/menu/menu_insertion_delegate_win.h'],
- ['include', 'controls/menu/native_menu_win.cc'],
- ['include', 'controls/menu/native_menu_win.h'],
- ['include', 'corewm/tooltip_win.cc'],
- ['include', 'corewm/tooltip_win.h'],
- ['include', 'event_utils_win.cc'],
- ['include', 'widget/desktop_aura/desktop_screen_win.cc'],
- ['include', 'widget/desktop_aura/desktop_drag_drop_client_win.cc'],
- ['include', 'widget/desktop_aura/desktop_drop_target_win.cc'],
- ['include', 'widget/desktop_aura/desktop_root_window_host_win.cc'],
- ['include', 'widget/monitor_win.cc'],
- ['include', 'widget/monitor_win.h'],
- ['include', 'win/appbar.cc'],
- ['include', 'win/appbar.h'],
- ],
- }],
- ],
- }],
- ['use_aura==0', {
- 'sources/': [
- ['exclude', 'corewm'],
- ['exclude', 'widget/desktop_aura'],
- ['exclude', 'widget/window_reorderer.h'],
- ['exclude', 'widget/window_reorderer.cc'],
- ],
- 'sources!': [
- 'widget/widget_aura_utils.cc',
- 'widget/widget_aura_utils.h',
- ],
- }],
['chromeos==1', {
'sources/': [
['exclude', 'widget/desktop_aura'],
@@ -536,24 +485,18 @@
'bubble/tray_bubble_view.h',
],
}],
- ['use_aura==0 and OS=="win"', {
- 'sources!': [
- 'controls/menu/menu_config_views.cc',
- 'controls/menu/menu_separator_views.cc',
- ],
- }],
- ['use_aura==1 and OS=="win"', {
- 'sources/': [
- ['include', 'controls/menu/menu_config_win.cc'],
- ['include', 'controls/menu/menu_separator_win.cc'],
- ['include', 'accessibility/native_view_accessibility_win.cc'],
- ['include', 'accessibility/native_view_accessibility_win.h'],
+ ['chromeos==0 and use_x11==1', {
+ 'dependencies': [
+ '../display/display.gyp:display_util',
],
}],
['OS=="linux" and chromeos==0', {
'dependencies': [
'../shell_dialogs/shell_dialogs.gyp:shell_dialogs',
],
+ 'sources!': [
+ 'window/window_button_order_provider.cc',
+ ],
}, { # OS=="linux" and chromeos==0
'sources/': [
['exclude', 'linux_ui'],
@@ -604,6 +547,34 @@
'../ozone/ozone.gyp:ozone',
],
}],
+ ['use_x11==1', {
+ 'dependencies': [
+ '../../build/linux/system.gyp:x11',
+ '../../build/linux/system.gyp:xrandr',
+ '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
+ ],
+ }],
+ ['use_aura==0', {
+ 'sources!': [
+ 'accessibility/ax_aura_obj_cache.cc',
+ 'accessibility/ax_aura_obj_cache.h',
+ 'accessibility/ax_aura_obj_wrapper.h',
+ 'accessibility/ax_view_obj_wrapper.cc',
+ 'accessibility/ax_view_obj_wrapper.h',
+ 'accessibility/ax_widget_obj_wrapper.cc',
+ 'accessibility/ax_widget_obj_wrapper.h',
+ 'accessibility/ax_window_obj_wrapper.cc',
+ 'accessibility/ax_window_obj_wrapper.h',
+ 'bubble/bubble_window_targeter.cc',
+ 'bubble/bubble_window_targeter.h',
+ 'bubble/tray_bubble_view.cc',
+ 'bubble/tray_bubble_view.h',
+ 'mouse_watcher_view_host.cc',
+ 'mouse_watcher_view_host.h',
+ 'widget/window_reorderer.cc',
+ 'widget/window_reorderer.h',
+ ],
+ }],
],
}, # target_name: views
{
@@ -614,38 +585,52 @@
'../../ipc/ipc.gyp:test_support_ipc',
'../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
+ '../base/ui_base.gyp:ui_base',
+ '../compositor/compositor.gyp:compositor',
'../events/events.gyp:events',
+ '../events/platform/events_platform.gyp:events_platform',
'../gfx/gfx.gyp:gfx',
- '../ui.gyp:ui',
+ '../gfx/gfx.gyp:gfx_geometry',
'views',
],
'include_dirs': [
'..',
],
'sources': [
+ 'controls/textfield/textfield_test_api.cc',
+ 'controls/textfield/textfield_test_api.h',
'corewm/tooltip_controller_test_helper.cc',
'corewm/tooltip_controller_test_helper.h',
'test/capture_tracking_view.cc',
'test/capture_tracking_view.h',
- 'test/child_modal_window.cc',
- 'test/child_modal_window.h',
- 'test/desktop_test_views_delegate.cc',
'test/desktop_test_views_delegate.h',
+ 'test/desktop_test_views_delegate_aura.cc',
+ 'test/desktop_test_views_delegate_mac.mm',
'test/menu_runner_test_api.cc',
'test/menu_runner_test_api.h',
+ 'test/slider_test_api.cc',
+ 'test/slider_test_api.h',
'test/test_views.cc',
'test/test_views.h',
- 'test/test_views_delegate.cc',
'test/test_views_delegate.h',
+ 'test/test_views_delegate_aura.cc',
+ 'test/test_views_delegate_mac.mm',
'test/test_widget_observer.cc',
'test/test_widget_observer.h',
'test/ui_controls_factory_desktop_aurax11.cc',
'test/ui_controls_factory_desktop_aurax11.h',
'test/views_test_base.cc',
'test/views_test_base.h',
+ 'test/views_test_helper.cc',
+ 'test/views_test_helper.h',
+ 'test/views_test_helper_aura.cc',
+ 'test/views_test_helper_aura.h',
'test/widget_test.cc',
'test/widget_test.h',
- 'widget/root_view_test_helper.h',
+ 'test/widget_test_aura.cc',
+ 'test/widget_test_mac.mm',
+ 'test/x11_property_change_waiter.cc',
+ 'test/x11_property_change_waiter.h',
],
'conditions': [
['chromeos==1', {
@@ -657,44 +642,11 @@
['use_aura==1', {
'dependencies': [
'../aura/aura.gyp:aura_test_support',
- '../compositor/compositor.gyp:compositor',
- ],
- }, { # use_aura==0
- 'sources!': [
- 'corewm/tooltip_controller_test_helper.cc',
- 'corewm/tooltip_controller_test_helper.h',
- 'test/child_modal_window.cc',
- 'test/child_modal_window.h',
],
}],
],
}, # target_name: views_test_support
{
- 'target_name': 'views_with_content_test_support',
- 'type': 'static_library',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../content/content.gyp:content',
- '../../content/content_shell_and_tests.gyp:test_support_content',
- '../../ipc/ipc.gyp:test_support_ipc',
- '../../skia/skia.gyp:skia',
- '../../testing/gtest.gyp:gtest',
- '../events/events.gyp:events',
- '../gfx/gfx.gyp:gfx',
- '../ui.gyp:ui',
- 'controls/webview/webview.gyp:webview',
- 'views_test_support',
- 'views',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'test/webview_test_helper.cc',
- 'test/webview_test_helper.h',
- ],
- }, # target_name: views_with_content_test_support
- {
'target_name': 'views_unittests',
'type': 'executable',
'dependencies': [
@@ -702,20 +654,22 @@
'../../base/base.gyp:base_i18n',
'../../base/base.gyp:test_support_base',
'../../skia/skia.gyp:skia',
- '../../testing/gmock.gyp:gmock',
'../../testing/gtest.gyp:gtest',
'../../third_party/icu/icu.gyp:icui18n',
'../../third_party/icu/icu.gyp:icuuc',
'../../url/url.gyp:url_lib',
- '../base/strings/ui_strings.gyp:ui_strings',
+ '../accessibility/accessibility.gyp:accessibility',
+ '../base/ui_base.gyp:ui_base',
+ '../base/ui_base.gyp:ui_base_test_support',
'../compositor/compositor.gyp:compositor',
'../compositor/compositor.gyp:compositor_test_support',
'../events/events.gyp:events',
+ '../events/events.gyp:events_base',
'../gfx/gfx.gyp:gfx',
+ '../gfx/gfx.gyp:gfx_geometry',
'../resources/ui_resources.gyp:ui_resources',
'../resources/ui_resources.gyp:ui_test_pak',
- '../ui.gyp:ui',
- '../ui_unittests.gyp:ui_test_support',
+ '../strings/ui_strings.gyp:ui_strings',
'views',
'views_test_support',
],
@@ -729,12 +683,17 @@
'bubble/bubble_border_unittest.cc',
'bubble/bubble_delegate_unittest.cc',
'bubble/bubble_frame_view_unittest.cc',
+ 'bubble/bubble_window_targeter_unittest.cc',
+ 'cocoa/bridged_native_widget_unittest.mm',
+ 'controls/button/blue_button_unittest.cc',
'controls/button/custom_button_unittest.cc',
'controls/button/image_button_unittest.cc',
'controls/button/label_button_unittest.cc',
+ 'controls/button/menu_button_unittest.cc',
'controls/combobox/combobox_unittest.cc',
'controls/label_unittest.cc',
'controls/menu/menu_model_adapter_unittest.cc',
+ 'controls/menu/menu_controller_unittest.cc',
'controls/native/native_view_host_aura_unittest.cc',
'controls/native/native_view_host_unittest.cc',
'controls/prefix_selector_unittest.cc',
@@ -749,26 +708,15 @@
'controls/table/table_view_unittest.cc',
'controls/table/test_table_model.cc',
'controls/table/test_table_model.h',
- 'controls/textfield/native_textfield_views_unittest.cc',
- 'controls/textfield/textfield_views_model_unittest.cc',
+ 'controls/textfield/textfield_unittest.cc',
+ 'controls/textfield/textfield_model_unittest.cc',
'controls/tree/tree_view_unittest.cc',
'corewm/capture_controller_unittest.cc',
- 'corewm/compound_event_filter_unittest.cc',
- 'corewm/cursor_manager_unittest.cc',
- 'corewm/focus_controller_unittest.cc',
- 'corewm/image_grid_unittest.cc',
- 'corewm/input_method_event_filter_unittest.cc',
- 'corewm/shadow_controller_unittest.cc',
'corewm/tooltip_aura_unittest.cc',
'corewm/tooltip_controller_unittest.cc',
- 'corewm/transient_window_stacking_client_unittest.cc',
- 'corewm/visibility_controller_unittest.cc',
- 'corewm/window_animations_unittest.cc',
- 'corewm/window_util_unittest.cc',
'focus/focus_manager_test.h',
'focus/focus_manager_test.cc',
'focus/focus_manager_unittest.cc',
- 'focus/focus_manager_unittest_win.cc',
'focus/focus_traversal_unittest.cc',
'ime/input_method_bridge_unittest.cc',
'layout/box_layout_unittest.cc',
@@ -778,32 +726,36 @@
'touchui/touch_selection_controller_impl_unittest.cc',
'view_model_unittest.cc',
'view_model_utils_unittest.cc',
+ 'view_targeter_unittest.cc',
'view_unittest.cc',
+ 'view_unittest_aura.cc',
+ 'widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc',
+ 'widget/desktop_aura/desktop_focus_rules_unittest.cc',
'widget/desktop_aura/desktop_native_widget_aura_unittest.cc',
- 'widget/desktop_aura/desktop_root_window_host_win_unittest.cc',
'widget/desktop_aura/desktop_screen_x11_unittest.cc',
'widget/desktop_aura/desktop_screen_position_client_unittest.cc',
+ 'widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc',
+ 'widget/desktop_aura/x11_topmost_window_finder_unittest.cc',
'widget/native_widget_aura_unittest.cc',
'widget/native_widget_unittest.cc',
- 'widget/native_widget_win_unittest.cc',
'widget/root_view_unittest.cc',
'widget/widget_unittest.cc',
'widget/window_reorderer_unittest.cc',
+ 'window/custom_frame_view_unittest.cc',
'window/dialog_client_view_unittest.cc',
'window/dialog_delegate_unittest.cc',
],
'conditions': [
- ['chromeos==0', {
- 'sources!': [
- 'touchui/touch_selection_controller_impl_unittest.cc',
- ],
- }, { # use_chromeos==1
+ ['chromeos==1', {
'sources/': [
['exclude', 'ime/input_method_bridge_unittest.cc'],
['exclude', 'widget/desktop_aura'],
],
}],
['OS=="win"', {
+ 'dependencies': [
+ '../../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
+ ],
'link_settings': {
'libraries': [
'-limm32.lib',
@@ -814,35 +766,30 @@
'include_dirs': [
'../third_party/wtl/include',
],
+ 'msvs_settings': {
+ 'VCManifestTool': {
+ 'AdditionalManifestFiles': [
+ '$(ProjectDir)\\test\\views_unittest.manifest',
+ ],
+ },
+ },
}],
['OS=="win" and win_use_allocator_shim==1', {
'dependencies': [
'../../base/allocator/allocator.gyp:allocator',
],
}],
- ['OS=="linux" and linux_use_tcmalloc==1', {
+ ['OS=="linux" and use_allocator!="none"', {
# See http://crbug.com/162998#c4 for why this is needed.
'dependencies': [
'../../base/allocator/allocator.gyp:allocator',
],
}],
- [ 'use_aura==1', {
+ ['use_x11==1', {
'dependencies': [
- '../aura/aura.gyp:aura_test_support',
- ],
- 'sources!': [
- 'widget/native_widget_win_unittest.cc',
- ],
- }, { # use_aura==0
- 'sources!': [
- 'controls/native/native_view_host_aura_unittest.cc',
- 'widget/native_widget_aura_unittest.cc',
- ],
- 'sources/': [
- ['exclude', 'corewm'],
- ['exclude', 'ime/input_method_bridge_unittest.cc'],
- ['exclude', 'widget/desktop_aura'],
- ['exclude', 'widget/window_reorderer_unittest.cc']
+ '../../build/linux/system.gyp:x11',
+ '../../build/linux/system.gyp:xext',
+ '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
],
}],
['use_ozone==1', {
@@ -850,268 +797,31 @@
'corewm/capture_controller_unittest.cc',
],
}],
- # Native tooltip class doesn't run well from unit tests.
- ['use_aura==1 and OS=="win"', {
- 'sources!': [
- 'corewm/tooltip_controller_unittest.cc',
- ],
- }],
- ],
- }, # target_name: views_unittests
- {
- 'target_name': 'views_examples_lib',
- 'type': '<(component)',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../skia/skia.gyp:skia',
- '../../third_party/icu/icu.gyp:icui18n',
- '../../third_party/icu/icu.gyp:icuuc',
- '../events/events.gyp:events',
- '../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../resources/ui_resources.gyp:ui_test_pak',
- '../ui.gyp:ui',
- 'views',
- ],
- 'include_dirs': [
- '..',
- ],
- 'defines': [
- 'VIEWS_EXAMPLES_IMPLEMENTATION',
- ],
- 'sources': [
- 'examples/bubble_example.cc',
- 'examples/bubble_example.h',
- 'examples/button_example.cc',
- 'examples/button_example.h',
- 'examples/checkbox_example.cc',
- 'examples/checkbox_example.h',
- 'examples/combobox_example.cc',
- 'examples/combobox_example.h',
- 'examples/double_split_view_example.cc',
- 'examples/double_split_view_example.h',
- 'examples/example_base.cc',
- 'examples/example_base.h',
- 'examples/example_combobox_model.cc',
- 'examples/example_combobox_model.h',
- 'examples/examples_window.cc',
- 'examples/examples_window.h',
- 'examples/label_example.cc',
- 'examples/label_example.h',
- 'examples/link_example.cc',
- 'examples/link_example.h',
- 'examples/message_box_example.cc',
- 'examples/message_box_example.h',
- 'examples/menu_example.cc',
- 'examples/menu_example.h',
- 'examples/multiline_example.cc',
- 'examples/multiline_example.h',
- 'examples/progress_bar_example.cc',
- 'examples/progress_bar_example.h',
- 'examples/radio_button_example.cc',
- 'examples/radio_button_example.h',
- 'examples/scroll_view_example.cc',
- 'examples/scroll_view_example.h',
- 'examples/single_split_view_example.cc',
- 'examples/single_split_view_example.h',
- 'examples/slider_example.cc',
- 'examples/slider_example.h',
- 'examples/tabbed_pane_example.cc',
- 'examples/tabbed_pane_example.h',
- 'examples/table_example.cc',
- 'examples/table_example.h',
- 'examples/text_example.cc',
- 'examples/text_example.h',
- 'examples/textfield_example.cc',
- 'examples/textfield_example.h',
- 'examples/throbber_example.cc',
- 'examples/throbber_example.h',
- 'examples/tree_view_example.cc',
- 'examples/tree_view_example.h',
- 'examples/views_examples_export.h',
- 'examples/widget_example.cc',
- 'examples/widget_example.h',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'include_dirs': [
- '../third_party/wtl/include',
- ],
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- }],
- ],
- }, # target_name: views_examples_lib
- {
- 'target_name': 'views_examples_exe',
- 'type': 'executable',
- 'dependencies': [
- '../../base/base.gyp:base',
- ],
- 'sources': [
- 'examples/examples_main.cc',
- ],
- }, # target_name: views_examples_exe
- {
- 'target_name': 'views_examples_with_content_lib',
- 'type': '<(component)',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../base/base.gyp:base_i18n',
- '../../content/content.gyp:content',
- '../../skia/skia.gyp:skia',
- '../../third_party/icu/icu.gyp:icui18n',
- '../../third_party/icu/icu.gyp:icuuc',
- '../../url/url.gyp:url_lib',
- '../events/events.gyp:events',
- '../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../resources/ui_resources.gyp:ui_test_pak',
- '../ui.gyp:ui',
- 'controls/webview/webview.gyp:webview',
- 'views',
- ],
- 'include_dirs': [
- '..',
- ],
- 'defines': [
- 'VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION',
- ],
- 'sources': [
- 'examples/bubble_example.cc',
- 'examples/bubble_example.h',
- 'examples/button_example.cc',
- 'examples/button_example.h',
- 'examples/checkbox_example.cc',
- 'examples/checkbox_example.h',
- 'examples/combobox_example.cc',
- 'examples/combobox_example.h',
- 'examples/double_split_view_example.cc',
- 'examples/double_split_view_example.h',
- 'examples/example_base.cc',
- 'examples/example_base.h',
- 'examples/example_combobox_model.cc',
- 'examples/example_combobox_model.h',
- 'examples/examples_window_with_content.cc',
- 'examples/examples_window_with_content.h',
- 'examples/label_example.cc',
- 'examples/label_example.h',
- 'examples/link_example.cc',
- 'examples/link_example.h',
- 'examples/message_box_example.cc',
- 'examples/message_box_example.h',
- 'examples/menu_example.cc',
- 'examples/menu_example.h',
- 'examples/multiline_example.cc',
- 'examples/multiline_example.h',
- 'examples/progress_bar_example.cc',
- 'examples/progress_bar_example.h',
- 'examples/radio_button_example.cc',
- 'examples/radio_button_example.h',
- 'examples/scroll_view_example.cc',
- 'examples/scroll_view_example.h',
- 'examples/single_split_view_example.cc',
- 'examples/single_split_view_example.h',
- 'examples/slider_example.cc',
- 'examples/slider_example.h',
- 'examples/tabbed_pane_example.cc',
- 'examples/tabbed_pane_example.h',
- 'examples/table_example.cc',
- 'examples/table_example.h',
- 'examples/text_example.cc',
- 'examples/text_example.h',
- 'examples/textfield_example.cc',
- 'examples/textfield_example.h',
- 'examples/throbber_example.cc',
- 'examples/throbber_example.h',
- 'examples/tree_view_example.cc',
- 'examples/tree_view_example.h',
- 'examples/views_examples_with_content_export.h',
- 'examples/webview_example.cc',
- 'examples/webview_example.h',
- 'examples/widget_example.cc',
- 'examples/widget_example.h',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'include_dirs': [
- '../third_party/wtl/include',
- ],
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- }],
- ],
- }, # target_name: views_examples_with_content_lib
- {
- 'target_name': 'views_examples_with_content_exe',
- 'type': 'executable',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../base/base.gyp:base_i18n',
- '../../content/content.gyp:content',
- '../../content/content_shell_and_tests.gyp:content_shell_lib',
- '../../content/content_shell_and_tests.gyp:test_support_content',
- '../../skia/skia.gyp:skia',
- '../../third_party/icu/icu.gyp:icui18n',
- '../../third_party/icu/icu.gyp:icuuc',
- '../events/events.gyp:events',
- '../gfx/gfx.gyp:gfx',
- '../resources/ui_resources.gyp:ui_resources',
- '../resources/ui_resources.gyp:ui_test_pak',
- '../ui.gyp:ui',
- '../wm/wm.gyp:wm_test_support',
- 'views',
- 'views_examples_with_content_lib',
- 'views_test_support'
- ],
- 'include_dirs': [
- '../..',
- ],
- 'sources': [
- '../../content/app/startup_helper_win.cc',
- 'examples/content_client/examples_browser_main_parts.cc',
- 'examples/content_client/examples_browser_main_parts.h',
- 'examples/content_client/examples_content_browser_client.cc',
- 'examples/content_client/examples_content_browser_client.h',
- 'examples/content_client/examples_main_delegate.cc',
- 'examples/content_client/examples_main_delegate.h',
- 'examples/content_client/examples_main.cc',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'link_settings': {
- 'libraries': [
- '-limm32.lib',
- '-loleacc.lib',
- ]
- },
- 'msvs_settings': {
- 'VCManifestTool': {
- 'AdditionalManifestFiles': [
- 'examples\\views_examples.exe.manifest',
- ],
- },
- 'VCLinkerTool': {
- 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
- },
- },
+ ['use_aura==1', {
'dependencies': [
- '../../sandbox/sandbox.gyp:sandbox',
+ '../aura/aura.gyp:aura_test_support',
],
}],
- ['use_aura==1', {
+ ['use_x11==1', {
'dependencies': [
- '../compositor/compositor.gyp:compositor',
+ '../events/platform/x11/x11_events_platform.gyp:x11_events_platform',
],
}],
- ['OS=="win"', {
- 'sources/': [
- # This is needed because the aura rule strips it from the default
- # sources list.
- ['include', '^../../content/app/startup_helper_win.cc'],
- ],
+ ['OS=="mac"', {
+ # views_unittests not yet compiling on Mac. http://crbug.com/378134
+ 'sources!': [
+ 'bubble/bubble_window_targeter_unittest.cc',
+ 'controls/button/custom_button_unittest.cc',
+ 'controls/button/menu_button_unittest.cc',
+ 'controls/native/native_view_host_unittest.cc',
+ 'controls/menu/menu_controller_unittest.cc',
+ 'ime/input_method_bridge_unittest.cc',
+ 'focus/focus_manager_unittest.cc',
+ 'widget/window_reorderer_unittest.cc',
+ 'widget/widget_unittest.cc',
+ ]
}],
],
- }, # target_name: views_examples_with_content_exe
+ }, # target_name: views_unittests
],
}
diff --git a/chromium/ui/views/views_delegate.cc b/chromium/ui/views/views_delegate.cc
index 20cb88f9359..c1c7ca6bd44 100644
--- a/chromium/ui/views/views_delegate.cc
+++ b/chromium/ui/views/views_delegate.cc
@@ -4,12 +4,12 @@
#include "ui/views/views_delegate.h"
-#include "ui/views/touchui/touch_selection_controller_impl.h"
+#include "ui/views/views_touch_selection_controller_factory.h"
namespace views {
ViewsDelegate::ViewsDelegate()
- : views_tsc_factory_(new views::ViewsTouchSelectionControllerFactory) {
+ : views_tsc_factory_(new ViewsTouchSelectionControllerFactory) {
ui::TouchSelectionControllerFactory::SetInstance(views_tsc_factory_.get());
}
@@ -17,4 +17,81 @@ ViewsDelegate::~ViewsDelegate() {
ui::TouchSelectionControllerFactory::SetInstance(NULL);
}
+void ViewsDelegate::SaveWindowPlacement(const Widget* widget,
+ const std::string& window_name,
+ const gfx::Rect& bounds,
+ ui::WindowShowState show_state) {
+}
+
+bool ViewsDelegate::GetSavedWindowPlacement(
+ const Widget* widget,
+ const std::string& window_name,
+ gfx::Rect* bounds,
+ ui::WindowShowState* show_state) const {
+ return false;
+}
+
+void ViewsDelegate::NotifyAccessibilityEvent(View* view,
+ ui::AXEvent event_type) {
+}
+
+void ViewsDelegate::NotifyMenuItemFocused(const base::string16& menu_name,
+ const base::string16& menu_item_name,
+ int item_index,
+ int item_count,
+ bool has_submenu) {
+}
+
+#if defined(OS_WIN)
+HICON ViewsDelegate::GetDefaultWindowIcon() const {
+ return NULL;
+}
+
+bool ViewsDelegate::IsWindowInMetro(gfx::NativeWindow window) const {
+ return false;
+}
+#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
+gfx::ImageSkia* ViewsDelegate::GetDefaultWindowIcon() const {
+ return NULL;
+}
+#endif
+
+NonClientFrameView* ViewsDelegate::CreateDefaultNonClientFrameView(
+ Widget* widget) {
+ return NULL;
+}
+
+void ViewsDelegate::AddRef() {
+}
+
+void ViewsDelegate::ReleaseRef() {
+}
+
+content::WebContents* ViewsDelegate::CreateWebContents(
+ content::BrowserContext* browser_context,
+ content::SiteInstance* site_instance) {
+ return NULL;
+}
+
+base::TimeDelta ViewsDelegate::GetDefaultTextfieldObscuredRevealDuration() {
+ return base::TimeDelta();
+}
+
+bool ViewsDelegate::WindowManagerProvidesTitleBar(bool maximized) {
+ return false;
+}
+
+#if defined(USE_AURA)
+ui::ContextFactory* ViewsDelegate::GetContextFactory() {
+ return NULL;
+}
+#endif
+
+#if defined(OS_WIN)
+int ViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor,
+ const base::Closure& callback) {
+ return EDGE_BOTTOM;
+}
+#endif
+
} // namespace views
diff --git a/chromium/ui/views/views_delegate.h b/chromium/ui/views/views_delegate.h
index 85fa50b5aa5..0175c8ba201 100644
--- a/chromium/ui/views/views_delegate.h
+++ b/chromium/ui/views/views_delegate.h
@@ -12,7 +12,7 @@
#endif
#include "base/strings/string16.h"
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
@@ -33,6 +33,10 @@ class ImageSkia;
class Rect;
}
+namespace ui {
+class ContextFactory;
+}
+
namespace views {
class NativeWidget;
@@ -52,11 +56,16 @@ class NativeWidgetDelegate;
// implementation.
class VIEWS_EXPORT ViewsDelegate {
public:
- // The active ViewsDelegate used by the views system.
- static ViewsDelegate* views_delegate;
+#if defined(OS_WIN)
+ enum AppbarAutohideEdge {
+ EDGE_TOP = 1 << 0,
+ EDGE_LEFT = 1 << 1,
+ EDGE_BOTTOM = 1 << 2,
+ EDGE_RIGHT = 1 << 3,
+ };
+#endif
ViewsDelegate();
-
virtual ~ViewsDelegate();
// Saves the position, size and "show" state for the window with the
@@ -64,68 +73,86 @@ class VIEWS_EXPORT ViewsDelegate {
virtual void SaveWindowPlacement(const Widget* widget,
const std::string& window_name,
const gfx::Rect& bounds,
- ui::WindowShowState show_state) = 0;
+ ui::WindowShowState show_state);
// Retrieves the saved position and size and "show" state for the window with
// the specified name.
- virtual bool GetSavedWindowPlacement(
- const Widget* widget,
- const std::string& window_name,
- gfx::Rect* bounds,
- ui::WindowShowState* show_state) const = 0;
+ virtual bool GetSavedWindowPlacement(const Widget* widget,
+ const std::string& window_name,
+ gfx::Rect* bounds,
+ ui::WindowShowState* show_state) const;
- virtual void NotifyAccessibilityEvent(
- View* view,
- ui::AccessibilityTypes::Event event_type) = 0;
+ virtual void NotifyAccessibilityEvent(View* view, ui::AXEvent event_type);
// For accessibility, notify the delegate that a menu item was focused
// so that alternate feedback (speech / magnified text) can be provided.
- virtual void NotifyMenuItemFocused(const string16& menu_name,
- const string16& menu_item_name,
+ virtual void NotifyMenuItemFocused(const base::string16& menu_name,
+ const base::string16& menu_item_name,
int item_index,
int item_count,
- bool has_submenu) = 0;
+ bool has_submenu);
#if defined(OS_WIN)
// Retrieves the default window icon to use for windows if none is specified.
- virtual HICON GetDefaultWindowIcon() const = 0;
+ virtual HICON GetDefaultWindowIcon() const;
// Returns true if the window passed in is in the Windows 8 metro
// environment.
- virtual bool IsWindowInMetro(gfx::NativeWindow window) const = 0;
+ virtual bool IsWindowInMetro(gfx::NativeWindow window) const;
#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
- virtual gfx::ImageSkia* GetDefaultWindowIcon() const = 0;
+ virtual gfx::ImageSkia* GetDefaultWindowIcon() const;
#endif
// Creates a default NonClientFrameView to be used for windows that don't
// specify their own. If this function returns NULL, the
// views::CustomFrameView type will be used.
- virtual NonClientFrameView* CreateDefaultNonClientFrameView(
- Widget* widget) = 0;
-
- // Returns whether the embedding app wants windows to be created with the
- // views::Widget marked as transparent. For example, an app may wish to
- // apply transparent window frames in the NonClientFrameView.
- virtual bool UseTransparentWindows() const = 0;
+ virtual NonClientFrameView* CreateDefaultNonClientFrameView(Widget* widget);
// AddRef/ReleaseRef are invoked while a menu is visible. They are used to
// ensure we don't attempt to exit while a menu is showing.
- virtual void AddRef() = 0;
- virtual void ReleaseRef() = 0;
+ virtual void AddRef();
+ virtual void ReleaseRef();
// Creates a web contents. This will return NULL unless overriden.
virtual content::WebContents* CreateWebContents(
content::BrowserContext* browser_context,
- content::SiteInstance* site_instance) = 0;
+ content::SiteInstance* site_instance);
// Gives the platform a chance to modify the properties of a Widget.
virtual void OnBeforeWidgetInit(Widget::InitParams* params,
internal::NativeWidgetDelegate* delegate) = 0;
// Returns the default obscured text reveal duration.
- virtual base::TimeDelta GetDefaultTextfieldObscuredRevealDuration() = 0;
+ virtual base::TimeDelta GetDefaultTextfieldObscuredRevealDuration();
+
+ // Returns true if the operating system's window manager will always provide a
+ // title bar with caption buttons (ignoring the setting to
+ // |remove_standard_frame| in InitParams). If |maximized|, this applies to
+ // maximized windows; otherwise to restored windows.
+ virtual bool WindowManagerProvidesTitleBar(bool maximized);
+
+#if defined(USE_AURA)
+ // Returns the context factory for new windows.
+ virtual ui::ContextFactory* GetContextFactory();
+#endif
+
+#if defined(OS_WIN)
+ // Starts a query for the appbar autohide edges of the specified monitor and
+ // returns the current value. If the query finds the edges have changed from
+ // the current value, |callback| is subsequently invoked. If the edges have
+ // not changed, |callback| is never run.
+ //
+ // The return value is a bitmask of AppbarAutohideEdge.
+ virtual int GetAppbarAutohideEdges(HMONITOR monitor,
+ const base::Closure& callback);
+#endif
+
+ // The active ViewsDelegate used by the views system.
+ static ViewsDelegate* views_delegate;
private:
scoped_ptr<ViewsTouchSelectionControllerFactory> views_tsc_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewsDelegate);
};
} // namespace views
diff --git a/chromium/ui/views/views_switches.cc b/chromium/ui/views/views_switches.cc
index c62e83d1d8b..342deeec600 100644
--- a/chromium/ui/views/views_switches.cc
+++ b/chromium/ui/views/views_switches.cc
@@ -16,6 +16,15 @@ namespace switches {
const char kDisableViewsRectBasedTargeting[] =
"disable-views-rect-based-targeting";
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+// When enabled, tries to get a transparent X11 visual so that we can have
+// per-pixel alpha in windows.
+//
+// TODO(erg): Remove this switch once we've stabilized the code
+// path. http://crbug.com/369209
+const char kEnableTransparentVisuals[] = "enable-transparent-visuals";
+#endif
+
bool IsRectBasedTargetingEnabled() {
#if defined(OS_CHROMEOS) || defined(OS_WIN)
return !CommandLine::ForCurrentProcess()->
diff --git a/chromium/ui/views/views_switches.h b/chromium/ui/views/views_switches.h
index 9e5029476ef..0fb09db6632 100644
--- a/chromium/ui/views/views_switches.h
+++ b/chromium/ui/views/views_switches.h
@@ -15,6 +15,10 @@ namespace switches {
// Please keep alphabetized.
VIEWS_EXPORT extern const char kDisableViewsRectBasedTargeting[];
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+VIEWS_EXPORT extern const char kEnableTransparentVisuals[];
+#endif
+
// Returns true if rect-based targeting in views should be used.
VIEWS_EXPORT bool IsRectBasedTargetingEnabled();
diff --git a/chromium/ui/views/views_touch_selection_controller_factory.h b/chromium/ui/views/views_touch_selection_controller_factory.h
new file mode 100644
index 00000000000..6b02c1e8d42
--- /dev/null
+++ b/chromium/ui/views/views_touch_selection_controller_factory.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_UI_VIEWS_VIEWS_TOUCH_SELECTION_CONTROLLER_FACTORY_H_
+#define UI_UI_VIEWS_VIEWS_TOUCH_SELECTION_CONTROLLER_FACTORY_H_
+
+#include "ui/base/touch/touch_editing_controller.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class VIEWS_EXPORT ViewsTouchSelectionControllerFactory
+ : public ui::TouchSelectionControllerFactory {
+ public:
+ ViewsTouchSelectionControllerFactory();
+
+ // Overridden from ui::TouchSelectionControllerFactory.
+ virtual ui::TouchSelectionController* create(
+ ui::TouchEditable* client_view) OVERRIDE;
+};
+
+} // namespace views
+
+#endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
diff --git a/chromium/ui/views/views_touch_selection_controller_factory_aura.cc b/chromium/ui/views/views_touch_selection_controller_factory_aura.cc
new file mode 100644
index 00000000000..a28da03a2e4
--- /dev/null
+++ b/chromium/ui/views/views_touch_selection_controller_factory_aura.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/views_touch_selection_controller_factory.h"
+
+#include "ui/base/ui_base_switches_util.h"
+#include "ui/views/touchui/touch_selection_controller_impl.h"
+
+namespace views {
+
+ViewsTouchSelectionControllerFactory::ViewsTouchSelectionControllerFactory() {
+}
+
+ui::TouchSelectionController* ViewsTouchSelectionControllerFactory::create(
+ ui::TouchEditable* client_view) {
+ if (switches::IsTouchEditingEnabled())
+ return new views::TouchSelectionControllerImpl(client_view);
+ return NULL;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/views_touch_selection_controller_factory_mac.cc b/chromium/ui/views/views_touch_selection_controller_factory_mac.cc
new file mode 100644
index 00000000000..b4866154e11
--- /dev/null
+++ b/chromium/ui/views/views_touch_selection_controller_factory_mac.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/views_touch_selection_controller_factory.h"
+
+namespace views {
+
+ViewsTouchSelectionControllerFactory::ViewsTouchSelectionControllerFactory() {
+}
+
+ui::TouchSelectionController* ViewsTouchSelectionControllerFactory::create(
+ ui::TouchEditable* client_view) {
+ return NULL;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/widget/aero_tooltip_manager.cc b/chromium/ui/views/widget/aero_tooltip_manager.cc
deleted file mode 100644
index 8e1f600b0d5..00000000000
--- a/chromium/ui/views/widget/aero_tooltip_manager.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/aero_tooltip_manager.h"
-
-#include <windows.h>
-#include <commctrl.h>
-#include <shlobj.h>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/gfx/point.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/hwnd_util.h"
-
-namespace views {
-
-///////////////////////////////////////////////////////////////////////////////
-// AeroTooltipManager, public:
-
-AeroTooltipManager::AeroTooltipManager(Widget* widget)
- : TooltipManagerWin(widget),
- initial_delay_(0) {
-}
-
-AeroTooltipManager::~AeroTooltipManager() {
- if (initial_timer_)
- initial_timer_->Disown();
-}
-
-void AeroTooltipManager::OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param) {
- if (u_msg == WM_MOUSELEAVE) {
- last_mouse_pos_.SetPoint(-1, -1);
- UpdateTooltip();
- return;
- }
-
- if (initial_timer_)
- initial_timer_->Disown();
-
- if (u_msg == WM_MOUSEMOVE || u_msg == WM_NCMOUSEMOVE) {
- gfx::Point mouse_pos_in_pixels(l_param);
- gfx::Point mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels);
- if (u_msg == WM_NCMOUSEMOVE) {
- // NC message coordinates are in screen coordinates.
- POINT temp = mouse_pos_in_pixels.ToPOINT();
- ::MapWindowPoints(HWND_DESKTOP, GetParent(), &temp, 1);
- mouse_pos_in_pixels.SetPoint(temp.x, temp.y);
- mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels);
- }
- if (last_mouse_pos_ != mouse_pos) {
- last_mouse_pos_ = mouse_pos;
- UpdateTooltip(mouse_pos);
- }
-
- // Delay opening of the tooltip just in case the user moves their
- // mouse to another control. We defer this from Init because we get
- // zero if we query it too soon.
- if (!initial_delay_) {
- initial_delay_ = static_cast<int>(
- ::SendMessage(tooltip_hwnd_, TTM_GETDELAYTIME, TTDT_INITIAL, 0));
- }
- initial_timer_ = new InitialTimer(this);
- initial_timer_->Start(initial_delay_);
- } else {
- // Hide the tooltip and cancel any timers.
- ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
- ::SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE, false, (LPARAM)&toolinfo_);
- return;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// AeroTooltipManager, private:
-
-void AeroTooltipManager::OnTimer() {
- initial_timer_ = NULL;
-
- POINT pt = last_mouse_pos_.ToPOINT();
- ::ClientToScreen(GetParent(), &pt);
-
- // Set the position and visibility.
- if (!tooltip_showing_) {
- ::SendMessage(tooltip_hwnd_, TTM_POPUP, 0, 0);
- ::SendMessage(tooltip_hwnd_, TTM_TRACKPOSITION, 0, MAKELPARAM(pt.x, pt.y));
- ::SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE, true, (LPARAM)&toolinfo_);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// AeroTooltipManager::InitialTimer
-
-AeroTooltipManager::InitialTimer::InitialTimer(AeroTooltipManager* manager)
- : manager_(manager) {
-}
-
-void AeroTooltipManager::InitialTimer::Start(int time) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&InitialTimer::Execute, this),
- base::TimeDelta::FromMilliseconds(time));
-}
-
-void AeroTooltipManager::InitialTimer::Disown() {
- manager_ = NULL;
-}
-
-void AeroTooltipManager::InitialTimer::Execute() {
- if (manager_)
- manager_->OnTimer();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/aero_tooltip_manager.h b/chromium/ui/views/widget/aero_tooltip_manager.h
deleted file mode 100644
index 0f9db20faa4..00000000000
--- a/chromium/ui/views/widget/aero_tooltip_manager.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_AERO_TOOLTIP_MANAGER_H_
-#define UI_VIEWS_WIDGET_AERO_TOOLTIP_MANAGER_H_
-
-#include "base/memory/ref_counted.h"
-#include "ui/views/widget/tooltip_manager_win.h"
-
-namespace views {
-
-///////////////////////////////////////////////////////////////////////////////
-// AeroTooltipManager
-//
-// Default Windows tooltips are broken when using our custom window frame
-// - as soon as the tooltip receives a WM_MOUSEMOVE event, it starts spewing
-// NCHITTEST messages at its parent window (us). These messages have random
-// x/y coordinates and can't be ignored, as the DwmDefWindowProc uses
-// NCHITTEST messages to determine how to highlight the caption buttons
-// (the buttons then flicker as the hit tests sent by the user's mouse
-// trigger different effects to those sent by the tooltip).
-//
-// So instead, we have to partially implement tooltips ourselves using
-// TTF_TRACKed tooltips.
-//
-// TODO(glen): Resolve this with Microsoft.
-class AeroTooltipManager : public TooltipManagerWin {
- public:
- explicit AeroTooltipManager(Widget* widget);
- virtual ~AeroTooltipManager();
-
- virtual void OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param);
-
- private:
- void OnTimer();
-
- class InitialTimer : public base::RefCounted<InitialTimer> {
- public:
- explicit InitialTimer(AeroTooltipManager* manager);
- void Start(int time);
- void Disown();
- void Execute();
-
- private:
- friend class base::RefCounted<InitialTimer>;
-
- ~InitialTimer() {}
-
- AeroTooltipManager* manager_;
- };
-
- int initial_delay_;
- scoped_refptr<InitialTimer> initial_timer_;
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_AERO_TOOLTIP_MANAGER_H_
diff --git a/chromium/ui/views/widget/child_window_message_processor.cc b/chromium/ui/views/widget/child_window_message_processor.cc
deleted file mode 100644
index dc497560093..00000000000
--- a/chromium/ui/views/widget/child_window_message_processor.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/child_window_message_processor.h"
-
-#include "base/logging.h"
-#include "ui/base/view_prop.h"
-
-namespace views {
-
-static const char* const kChildWindowKey = "__CHILD_WINDOW_MESSAGE_PROCESSOR__";
-
-// static
-ui::ViewProp* ChildWindowMessageProcessor::Register(
- HWND hwnd,
- ChildWindowMessageProcessor* processor) {
- DCHECK(processor);
- return new ui::ViewProp(hwnd, kChildWindowKey, processor);
-}
-
-// static
-ChildWindowMessageProcessor* ChildWindowMessageProcessor::Get(HWND hwnd) {
- return reinterpret_cast<ChildWindowMessageProcessor*>(
- ui::ViewProp::GetValue(hwnd, kChildWindowKey));
-}
-
-} // namespace
diff --git a/chromium/ui/views/widget/child_window_message_processor.h b/chromium/ui/views/widget/child_window_message_processor.h
deleted file mode 100644
index 112d9d835d4..00000000000
--- a/chromium/ui/views/widget/child_window_message_processor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_CHILD_WINDOW_MESSAGE_PROCESSOR_H_
-#define UI_VIEWS_WIDGET_CHILD_WINDOW_MESSAGE_PROCESSOR_H_
-
-#include <windows.h>
-
-namespace ui {
-class ViewProp;
-}
-
-namespace views {
-
-// Windows sends a handful of messages to the parent window rather than the
-// window itself. For example, selection changes of a rich edit (EN_SELCHANGE)
-// are sent to the parent, not the window. Typically such message are best
-// dealt with by the window rather than the parent. NativeWidgetWin allows for
-// registering a ChildWindowMessageProcessor to handle such messages.
-class ChildWindowMessageProcessor {
- public:
- // Registers |processor| for |hwnd|. The caller takes ownership of the
- // returned object.
- static ui::ViewProp* Register(HWND hwnd,
- ChildWindowMessageProcessor* processor);
-
- // Returns the ChildWindowMessageProcessor for |hwnd|, NULL if there isn't
- // one.
- static ChildWindowMessageProcessor* Get(HWND hwnd);
-
- // Invoked for any messages that are sent to the parent and originated from
- // the HWND this ChildWindowMessageProcessor was registered for. Returns true
- // if the message was handled with a valid result in |result|. Returns false
- // if the message was not handled.
- virtual bool ProcessMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) = 0;
-
- protected:
- virtual ~ChildWindowMessageProcessor() {}
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_CHILD_WINDOW_MESSAGE_PROCESSOR_H_
diff --git a/chromium/ui/views/widget/desktop_aura/OWNERS b/chromium/ui/views/widget/desktop_aura/OWNERS
index 89630b157dd..c216dcda9de 100644
--- a/chromium/ui/views/widget/desktop_aura/OWNERS
+++ b/chromium/ui/views/widget/desktop_aura/OWNERS
@@ -1,5 +1,2 @@
# Elliot is the owner of all the X11 stuff.
-per-file *x11.cc=erg@chromium.org
-per-file *x11.h=erg@chromium.org
-per-file x11*=erg@chromium.org
-per-file x11*=erg@chromium.org
+per-file *x11*=erg@chromium.org
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
index 33054fe006d..fe9090d24a2 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -4,8 +4,9 @@
#include "ui/views/widget/desktop_aura/desktop_capture_client.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
namespace views {
@@ -52,7 +53,7 @@ void DesktopCaptureClient::SetCapture(aura::Window* new_capture_window) {
capture_window_ = new_capture_window;
- aura::client::CaptureDelegate* delegate = root_->GetDispatcher();
+ aura::client::CaptureDelegate* delegate = root_->GetHost()->dispatcher();
delegate->UpdateCapture(old_capture_window, new_capture_window);
// Initiate native capture updating.
@@ -67,7 +68,8 @@ void DesktopCaptureClient::SetCapture(aura::Window* new_capture_window) {
for (CaptureClients::iterator i = capture_clients.begin();
i != capture_clients.end(); ++i) {
if (*i != this) {
- aura::client::CaptureDelegate* delegate = (*i)->root_->GetDispatcher();
+ aura::client::CaptureDelegate* delegate =
+ (*i)->root_->GetHost()->dispatcher();
delegate->OnOtherRootGotCapture();
}
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h
index 599b625b26f..ff116bc81a0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h
@@ -33,7 +33,7 @@ class VIEWS_EXPORT DesktopCursorLoaderUpdater {
static scoped_ptr<DesktopCursorLoaderUpdater> Create();
// Called when a CursorLoader is created.
- virtual void OnCreate(aura::RootWindow* window,
+ virtual void OnCreate(float device_scale_factor,
ui::CursorLoader* loader) = 0;
// Called when the display has changed (as we may need to reload the cursor
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.cc b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.cc
index 80d99d1094b..63290b31343 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.cc
@@ -4,7 +4,7 @@
#include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/cursor/cursor_loader.h"
#include "ui/base/cursor/cursors_aura.h"
#include "ui/gfx/display.h"
@@ -53,9 +53,9 @@ DesktopCursorLoaderUpdaterAuraLinux::DesktopCursorLoaderUpdaterAuraLinux() {}
DesktopCursorLoaderUpdaterAuraLinux::~DesktopCursorLoaderUpdaterAuraLinux() {}
void DesktopCursorLoaderUpdaterAuraLinux::OnCreate(
- aura::RootWindow* window,
+ float device_scale_factor,
ui::CursorLoader* loader) {
- LoadImageCursors(window->compositor()->device_scale_factor(), loader);
+ LoadImageCursors(device_scale_factor, loader);
}
void DesktopCursorLoaderUpdaterAuraLinux::OnDisplayUpdated(
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h
index 02db2b2773e..c367518ca08 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_cursor_loader_updater_auralinux.h
@@ -17,7 +17,7 @@ class DesktopCursorLoaderUpdaterAuraLinux : public DesktopCursorLoaderUpdater {
virtual ~DesktopCursorLoaderUpdaterAuraLinux();
// Overridden from DesktopCursorLoaderUpdater:
- virtual void OnCreate(aura::RootWindow* window,
+ virtual void OnCreate(float device_scale_factor,
ui::CursorLoader* loader) OVERRIDE;
virtual void OnDisplayUpdated(const gfx::Display& display,
ui::CursorLoader* loader) OVERRIDE;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc
index bd4ba0229aa..4b8ca2db08d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc
@@ -4,31 +4,30 @@
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
+#include "base/auto_reset.h"
+#include "base/bind.h"
#include "base/run_loop.h"
namespace views {
-DesktopDispatcherClient::DesktopDispatcherClient() {}
-
-DesktopDispatcherClient::~DesktopDispatcherClient() {}
+DesktopDispatcherClient::DesktopDispatcherClient() {
+}
-void DesktopDispatcherClient::RunWithDispatcher(
- base::MessageLoop::Dispatcher* nested_dispatcher,
- aura::Window* associated_window,
- bool nestable_tasks_allowed) {
- // TODO(erg): This class has been copypastad from
- // ash/accelerators/nested_dispatcher_controller.cc. I have left my changes
- // commented out because I don't entirely understand the implications of the
- // change.
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- bool did_allow_task_nesting = loop->NestableTasksAllowed();
- loop->SetNestableTasksAllowed(nestable_tasks_allowed);
+DesktopDispatcherClient::~DesktopDispatcherClient() {
+}
- // DefaultAcceleratorDispatcher dispatcher(nested_dispatcher,
- // associated_window);
- base::RunLoop run_loop(nested_dispatcher);
- run_loop.Run();
- loop->SetNestableTasksAllowed(did_allow_task_nesting);
+void DesktopDispatcherClient::PrepareNestedLoopClosures(
+ base::MessagePumpDispatcher* dispatcher,
+ base::Closure* run_closure,
+ base::Closure* quit_closure) {
+#if defined(OS_WIN)
+ scoped_ptr<base::RunLoop> run_loop(new base::RunLoop(dispatcher));
+#else
+ scoped_ptr<base::RunLoop> run_loop(new base::RunLoop());
+#endif
+ *quit_closure = run_loop->QuitClosure();
+ *run_closure =
+ base::Bind(&base::RunLoop::Run, base::Owned(run_loop.release()));
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
index 5e7a517cc71..284e81cacda 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
@@ -6,8 +6,9 @@
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_
#include "base/basictypes.h"
-#include "ui/aura/client/dispatcher_client.h"
+#include "base/callback.h"
#include "ui/views/views_export.h"
+#include "ui/wm/public/dispatcher_client.h"
namespace views {
@@ -18,9 +19,10 @@ class VIEWS_EXPORT DesktopDispatcherClient
DesktopDispatcherClient();
virtual ~DesktopDispatcherClient();
- virtual void RunWithDispatcher(base::MessageLoop::Dispatcher* dispatcher,
- aura::Window* associated_window,
- bool nestable_tasks_allowed) OVERRIDE;
+ virtual void PrepareNestedLoopClosures(
+ base::MessagePumpDispatcher* dispatcher,
+ base::Closure* run_closure,
+ base::Closure* quit_closure) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(DesktopDispatcherClient);
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 59e46f93245..d8a76e66559 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
@@ -9,18 +9,20 @@
#include "base/event_types.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/clipboard/clipboard.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#include "ui/base/x/selection_utils.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/event.h"
+#include "ui/events/platform/platform_event_source.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
+#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/drag_drop_delegate.h"
using aura::client::DragDropDelegate;
using ui::OSExchangeData;
@@ -35,19 +37,23 @@ const int kWantFurtherPosEvents = 2;
const char kXdndActionCopy[] = "XdndActionCopy";
const char kXdndActionMove[] = "XdndActionMove";
const char kXdndActionLink[] = "XdndActionLink";
+const char kXdndActionDirectSave[] = "XdndActionDirectSave";
const char kChromiumDragReciever[] = "_CHROMIUM_DRAG_RECEIVER";
const char kXdndSelection[] = "XdndSelection";
+const char kXdndDirectSave0[] = "XdndDirectSave0";
const char* kAtomsToCache[] = {
kChromiumDragReciever,
"XdndActionAsk",
kXdndActionCopy,
+ kXdndActionDirectSave,
kXdndActionLink,
"XdndActionList",
kXdndActionMove,
"XdndActionPrivate",
"XdndAware",
+ kXdndDirectSave0,
"XdndDrop",
"XdndEnter",
"XdndFinished",
@@ -57,88 +63,32 @@ const char* kAtomsToCache[] = {
kXdndSelection,
"XdndStatus",
"XdndTypeList",
+ ui::Clipboard::kMimeTypeText,
NULL
};
+// The time to wait for the target to respond after the user has released the
+// mouse button before ending the move loop.
+const int kEndMoveLoopTimeoutMs = 1000;
+
+// The time to wait since sending the last XdndPosition message before
+// reprocessing the most recent mouse move event in case that the window
+// stacking order has changed and |source_current_window_| needs to be updated.
+const int kRepeatMouseMoveTimeoutMs = 350;
+
static base::LazyInstance<
std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky
g_live_client_map = LAZY_INSTANCE_INITIALIZER;
-// Helper class to FindWindowFor which looks for a drag target under the
-// cursor.
-class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate {
- public:
- DragTargetWindowFinder(XID ignored_icon_window,
- gfx::Point screen_loc)
- : ignored_icon_window_(ignored_icon_window),
- output_window_(None),
- screen_loc_(screen_loc) {
- ui::EnumerateTopLevelWindows(this);
- }
-
- virtual ~DragTargetWindowFinder() {}
-
- XID window() const { return output_window_; }
-
- protected:
- virtual bool ShouldStopIterating(XID window) OVERRIDE {
- if (window == ignored_icon_window_)
- return false;
-
- if (!ui::IsWindowVisible(window))
- return false;
-
- if (!ui::WindowContainsPoint(window, screen_loc_))
- return false;
-
- if (ui::PropertyExists(window, "WM_STATE")) {
- output_window_ = window;
- return true;
- }
-
- return false;
- }
-
- private:
- XID ignored_icon_window_;
- XID output_window_;
- gfx::Point screen_loc_;
-
- DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder);
-};
-
-// Returns the topmost X11 window at |screen_point| if it is advertising that
-// is supports the Xdnd protocol. Will return the window under the pointer as
-// |mouse_window|. If there's a Xdnd aware window, it will be returned in
-// |dest_window|.
-void FindWindowFor(const gfx::Point& screen_point,
- ::Window* mouse_window, ::Window* dest_window) {
- DragTargetWindowFinder finder(None, screen_point);
- *mouse_window = finder.window();
- *dest_window = None;
-
- if (finder.window() == None)
- return;
-
- // Figure out which window we should test as XdndAware. If mouse_window has
- // XdndProxy, it will set that proxy on target, and if not, |target|'s
- // original value will remain.
- XID target = *mouse_window;
- ui::GetXIDProperty(*mouse_window, "XdndProxy", &target);
-
- int version;
- if (ui::GetIntProperty(target, "XdndAware", &version) &&
- version >= kMinXdndVersion) {
- *dest_window = target;
- }
-}
-
} // namespace
namespace views {
-class DesktopDragDropClientAuraX11::X11DragContext :
- public base::MessageLoop::Dispatcher {
+DesktopDragDropClientAuraX11*
+DesktopDragDropClientAuraX11::g_current_drag_drop_client = NULL;
+
+class DesktopDragDropClientAuraX11::X11DragContext
+ : public ui::PlatformEventDispatcher {
public:
X11DragContext(ui::X11AtomCache* atom_cache,
::Window local_window,
@@ -150,6 +100,7 @@ class DesktopDragDropClientAuraX11::X11DragContext :
// message. If we have that data already, dispatch immediately. Otherwise,
// delay dispatching until we do.
void OnStartXdndPositionMessage(DesktopDragDropClientAuraX11* client,
+ ::Atom suggested_action,
::Window source_window,
const gfx::Point& screen_point);
@@ -173,8 +124,13 @@ class DesktopDragDropClientAuraX11::X11DragContext :
int GetDragOperation() const;
private:
- // Overridden from MessageLoop::Dispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
+ // Masks the X11 atom |xdnd_operation|'s views representation onto
+ // |drag_operation|.
+ void MaskOpeartion(::Atom xdnd_operation, int* drag_operation) const;
+
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
// The atom cache owned by our parent.
ui::X11AtomCache* atom_cache_;
@@ -202,6 +158,10 @@ class DesktopDragDropClientAuraX11::X11DragContext :
// haven't fetched and put in |fetched_targets_| yet.
std::vector<Atom> unfetched_targets_;
+ // XdndPosition messages have a suggested action. Qt applications exclusively
+ // use this, instead of the XdndActionList which is backed by |actions_|.
+ Atom suggested_action_;
+
// Possible actions.
std::vector<Atom> actions_;
@@ -216,7 +176,8 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
local_window_(local_window),
source_window_(event.data.l[0]),
drag_drop_client_(NULL),
- waiting_to_handle_position_(false) {
+ waiting_to_handle_position_(false),
+ suggested_action_(None) {
bool get_types = ((event.data.l[1] & 1) != 0);
if (get_types) {
@@ -239,8 +200,7 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
if (!client) {
// The window doesn't have a DesktopDragDropClientAuraX11, that means it's
// created by some other process. Listen for messages on it.
- base::MessagePumpX11::Current()->AddDispatcherForWindow(
- this, source_window_);
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
XSelectInput(gfx::GetXDisplay(), source_window_, PropertyChangeMask);
// We must perform a full sync here because we could be racing
@@ -258,20 +218,17 @@ DesktopDragDropClientAuraX11::X11DragContext::X11DragContext(
}
DesktopDragDropClientAuraX11::X11DragContext::~X11DragContext() {
- DesktopDragDropClientAuraX11* client =
- DesktopDragDropClientAuraX11::GetForWindow(source_window_);
- if (!client) {
- // Unsubscribe from message events.
- base::MessagePumpX11::Current()->RemoveDispatcherForWindow(
- source_window_);
- }
+ // Unsubscribe from message events.
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
}
void DesktopDragDropClientAuraX11::X11DragContext::OnStartXdndPositionMessage(
DesktopDragDropClientAuraX11* client,
+ ::Atom suggested_action,
::Window source_window,
const gfx::Point& screen_point) {
DCHECK_EQ(source_window_, source_window);
+ suggested_action_ = suggested_action;
if (!unfetched_targets_.empty()) {
// We have unfetched targets. That means we need to pause the handling of
@@ -301,7 +258,11 @@ void DesktopDragDropClientAuraX11::X11DragContext::RequestNextTarget() {
void DesktopDragDropClientAuraX11::X11DragContext::OnSelectionNotify(
const XSelectionEvent& event) {
- DCHECK(waiting_to_handle_position_);
+ if (!waiting_to_handle_position_) {
+ // A misbehaved window may send SelectionNotify without us requesting data
+ // via XConvertSelection().
+ return;
+ }
DCHECK(drag_drop_client_);
DCHECK_EQ(event.property, atom_cache_->GetAtom(kChromiumDragReciever));
@@ -345,24 +306,38 @@ int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const {
int drag_operation = ui::DragDropTypes::DRAG_NONE;
for (std::vector<Atom>::const_iterator it = actions_.begin();
it != actions_.end(); ++it) {
- if (*it == atom_cache_->GetAtom(kXdndActionCopy))
- drag_operation |= ui::DragDropTypes::DRAG_COPY;
- else if (*it == atom_cache_->GetAtom(kXdndActionMove))
- drag_operation |= ui::DragDropTypes::DRAG_MOVE;
- else if (*it == atom_cache_->GetAtom(kXdndActionLink))
- drag_operation |= ui::DragDropTypes::DRAG_LINK;
+ MaskOpeartion(*it, &drag_operation);
}
+ MaskOpeartion(suggested_action_, &drag_operation);
+
return drag_operation;
}
-bool DesktopDragDropClientAuraX11::X11DragContext::Dispatch(
- const base::NativeEvent& event) {
+void DesktopDragDropClientAuraX11::X11DragContext::MaskOpeartion(
+ ::Atom xdnd_operation,
+ int* drag_operation) const {
+ if (xdnd_operation == atom_cache_->GetAtom(kXdndActionCopy))
+ *drag_operation |= ui::DragDropTypes::DRAG_COPY;
+ else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionMove))
+ *drag_operation |= ui::DragDropTypes::DRAG_MOVE;
+ else if (xdnd_operation == atom_cache_->GetAtom(kXdndActionLink))
+ *drag_operation |= ui::DragDropTypes::DRAG_LINK;
+}
+
+bool DesktopDragDropClientAuraX11::X11DragContext::CanDispatchEvent(
+ const ui::PlatformEvent& event) {
+ return event->xany.window == source_window_;
+}
+
+uint32_t DesktopDragDropClientAuraX11::X11DragContext::DispatchEvent(
+ const ui::PlatformEvent& event) {
if (event->type == PropertyNotify &&
event->xproperty.atom == atom_cache_->GetAtom("XdndActionList")) {
ReadActions();
+ return ui::POST_DISPATCH_STOP_PROPAGATION;
}
- return true;
+ return ui::POST_DISPATCH_NONE;
}
///////////////////////////////////////////////////////////////////////////////
@@ -378,17 +353,20 @@ DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
xwindow_(xwindow),
atom_cache_(xdisplay_, kAtomsToCache),
target_window_(NULL),
+ waiting_on_status_(false),
+ status_received_since_enter_(false),
source_provider_(NULL),
source_current_window_(None),
- drag_drop_in_progress_(false),
+ source_state_(SOURCE_STATE_OTHER),
drag_operation_(0),
- resulting_operation_(0),
+ negotiated_operation_(ui::DragDropTypes::DRAG_NONE),
grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)),
copy_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorCopy)),
- move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)) {
- DCHECK(g_live_client_map.Get().find(xwindow) ==
- g_live_client_map.Get().end());
- g_live_client_map.Get().insert(std::make_pair(xwindow, this));
+ move_grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorMove)),
+ weak_ptr_factory_(this) {
+ // Some tests change the DesktopDragDropClientAuraX11 associated with an
+ // |xwindow|.
+ g_live_client_map.Get()[xwindow] = this;
// Mark that we are aware of drag and drop concepts.
unsigned long xdnd_version = kMinXdndVersion;
@@ -399,6 +377,10 @@ DesktopDragDropClientAuraX11::DesktopDragDropClientAuraX11(
DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() {
g_live_client_map.Get().erase(xwindow_);
+ // Make sure that all observers are unregistered from source and target
+ // windows. This may be necessary when the parent native widget gets destroyed
+ // while a drag operation is in progress.
+ NotifyDragLeave();
}
// static
@@ -446,6 +428,7 @@ void DesktopDragDropClientAuraX11::OnXdndPosition(
unsigned long source_window = event.data.l[0];
int x_root_window = event.data.l[2] >> 16;
int y_root_window = event.data.l[2] & 0xffff;
+ ::Atom suggested_action = event.data.l[4];
if (!target_current_context_.get()) {
NOTREACHED();
@@ -455,7 +438,8 @@ void DesktopDragDropClientAuraX11::OnXdndPosition(
// If we already have all the data from this drag, we complete it
// immediately.
target_current_context_->OnStartXdndPositionMessage(
- this, source_window, gfx::Point(x_root_window, y_root_window));
+ this, suggested_action, source_window,
+ gfx::Point(x_root_window, y_root_window));
}
void DesktopDragDropClientAuraX11::OnXdndStatus(
@@ -463,14 +447,37 @@ void DesktopDragDropClientAuraX11::OnXdndStatus(
DVLOG(1) << "XdndStatus";
unsigned long source_window = event.data.l[0];
- int drag_operation = ui::DragDropTypes::DRAG_NONE;
+
+ if (source_window != source_current_window_)
+ return;
+
+ if (source_state_ != SOURCE_STATE_PENDING_DROP &&
+ source_state_ != SOURCE_STATE_OTHER) {
+ return;
+ }
+
+ waiting_on_status_ = false;
+ status_received_since_enter_ = true;
+
if (event.data.l[1] & 1) {
::Atom atom_operation = event.data.l[4];
- negotiated_operation_[source_window] = atom_operation;
- drag_operation = AtomToDragOperation(atom_operation);
+ negotiated_operation_ = AtomToDragOperation(atom_operation);
+ } else {
+ negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
+ }
+
+ if (source_state_ == SOURCE_STATE_PENDING_DROP) {
+ // We were waiting on the status message so we could send the XdndDrop.
+ if (negotiated_operation_ == ui::DragDropTypes::DRAG_NONE) {
+ move_loop_.EndMoveLoop();
+ return;
+ }
+ source_state_ = SOURCE_STATE_DROPPED;
+ SendXdndDrop(source_window);
+ return;
}
- switch (drag_operation) {
+ switch (negotiated_operation_) {
case ui::DragDropTypes::DRAG_COPY:
move_loop_.UpdateCursor(copy_grab_cursor_);
break;
@@ -488,31 +495,31 @@ void DesktopDragDropClientAuraX11::OnXdndStatus(
// the spec) the other side must handle further position messages within
// it. GTK+ doesn't bother with this, so neither should we.
- waiting_on_status_.erase(source_window);
-
- if (ContainsKey(pending_drop_, source_window)) {
- // We were waiting on the status message so we could send the XdndDrop.
- SendXdndDrop(source_window);
- return;
- }
-
- NextPositionMap::iterator it = next_position_message_.find(source_window);
- if (it != next_position_message_.end()) {
+ if (next_position_message_.get()) {
// We were waiting on the status message so we could send off the next
// position message we queued up.
- gfx::Point p = it->second.first;
- unsigned long time = it->second.second;
- next_position_message_.erase(it);
+ gfx::Point p = next_position_message_->first;
+ unsigned long event_time = next_position_message_->second;
+ next_position_message_.reset();
- SendXdndPosition(source_window, p, time);
+ SendXdndPosition(source_window, p, event_time);
}
}
void DesktopDragDropClientAuraX11::OnXdndFinished(
const XClientMessageEvent& event) {
DVLOG(1) << "XdndFinished";
- resulting_operation_ = AtomToDragOperation(
- negotiated_operation_[event.data.l[0]]);
+ unsigned long source_window = event.data.l[0];
+ if (source_current_window_ != source_window)
+ return;
+
+ // Clear |negotiated_operation_| if the drag was rejected.
+ if ((event.data.l[1] & 1) == 0)
+ negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
+
+ // Clear |source_current_window_| to avoid sending XdndLeave upon ending the
+ // move loop.
+ source_current_window_ = None;
move_loop_.EndMoveLoop();
}
@@ -555,12 +562,12 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
void DesktopDragDropClientAuraX11::OnSelectionNotify(
const XSelectionEvent& xselection) {
- if (!target_current_context_) {
- NOTIMPLEMENTED();
- return;
- }
+ if (target_current_context_)
+ target_current_context_->OnSelectionNotify(xselection);
- target_current_context_->OnSelectionNotify(xselection);
+ // ICCCM requires us to delete the property passed into SelectionNotify.
+ if (xselection.property != None)
+ XDeleteProperty(xdisplay_, xwindow_, xselection.property);
}
int DesktopDragDropClientAuraX11::StartDragAndDrop(
@@ -571,9 +578,14 @@ int DesktopDragDropClientAuraX11::StartDragAndDrop(
int operation,
ui::DragDropTypes::DragEventSource source) {
source_current_window_ = None;
- drag_drop_in_progress_ = true;
+ DCHECK(!g_current_drag_drop_client);
+ g_current_drag_drop_client = this;
+ waiting_on_status_ = false;
+ next_position_message_.reset();
+ status_received_since_enter_ = false;
+ source_state_ = SOURCE_STATE_OTHER;
drag_operation_ = operation;
- resulting_operation_ = ui::DragDropTypes::DRAG_NONE;
+ negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
const ui::OSExchangeData::Provider* provider = &data.provider();
source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>(
@@ -582,22 +594,41 @@ int DesktopDragDropClientAuraX11::StartDragAndDrop(
source_provider_->TakeOwnershipOfSelection();
std::vector< ::Atom> actions = GetOfferedDragOperations();
+ if (!source_provider_->file_contents_name().empty()) {
+ actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave));
+ ui::SetStringProperty(
+ xwindow_,
+ atom_cache_.GetAtom(kXdndDirectSave0),
+ atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText),
+ source_provider_->file_contents_name().AsUTF8Unsafe());
+ }
ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
+ // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
+ // move loop, which would also destroy this drag-client. So keep track of
+ // whether it is alive after the drag ends.
+ base::WeakPtr<DesktopDragDropClientAuraX11> alive(
+ weak_ptr_factory_.GetWeakPtr());
+
// Windows has a specific method, DoDragDrop(), which performs the entire
// drag. We have to emulate this, so we spin off a nested runloop which will
// track all cursor movement and reroute events to a specific handler.
move_loop_.SetDragImage(source_provider_->GetDragImage(),
source_provider_->GetDragImageOffset());
move_loop_.RunMoveLoop(source_window, grab_cursor_);
- move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
- source_provider_ = NULL;
- drag_drop_in_progress_ = false;
- drag_operation_ = 0;
- XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
+ if (alive) {
+ move_loop_.SetDragImage(gfx::ImageSkia(), gfx::Vector2dF());
+
+ source_provider_ = NULL;
+ g_current_drag_drop_client = NULL;
+ drag_operation_ = 0;
+ XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
+ XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
- return resulting_operation_;
+ return negotiated_operation_;
+ }
+ return ui::DragDropTypes::DRAG_NONE;
}
void DesktopDragDropClientAuraX11::DragUpdate(aura::Window* target,
@@ -615,7 +646,7 @@ void DesktopDragDropClientAuraX11::DragCancel() {
}
bool DesktopDragDropClientAuraX11::IsDragDropInProgress() {
- return drag_drop_in_progress_;
+ return !!g_current_drag_drop_client;
}
void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
@@ -624,61 +655,170 @@ void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
}
void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
- gfx::Point screen_point(event->x_root, event->y_root);
-
- // Find the current window the cursor is over.
- ::Window mouse_window = None;
- ::Window dest_window = None;
- FindWindowFor(screen_point, &mouse_window, &dest_window);
-
- if (source_current_window_ != dest_window) {
- if (source_current_window_ != None)
- SendXdndLeave(source_current_window_);
+ repeat_mouse_move_timer_.Stop();
+ ProcessMouseMove(gfx::Point(event->x_root, event->y_root), event->time);
+}
- source_current_window_ = dest_window;
+void DesktopDragDropClientAuraX11::OnMouseReleased() {
+ repeat_mouse_move_timer_.Stop();
- if (source_current_window_ != None) {
- negotiated_operation_.erase(source_current_window_);
- SendXdndEnter(source_current_window_);
- }
+ if (source_state_ != SOURCE_STATE_OTHER) {
+ // The user has previously released the mouse and is clicking in
+ // frustration.
+ move_loop_.EndMoveLoop();
+ return;
}
if (source_current_window_ != None) {
- if (ContainsKey(waiting_on_status_, dest_window)) {
- next_position_message_[dest_window] =
- std::make_pair(screen_point, event->time);
- } else {
- SendXdndPosition(dest_window, screen_point, event->time);
- }
- }
-}
+ if (waiting_on_status_) {
+ if (status_received_since_enter_) {
+ // If we are waiting for an XdndStatus message, we need to wait for it
+ // to complete.
+ source_state_ = SOURCE_STATE_PENDING_DROP;
+
+ // Start timer to end the move loop if the target takes too long to send
+ // the XdndStatus and XdndFinished messages.
+ StartEndMoveLoopTimer();
+ return;
+ }
-void DesktopDragDropClientAuraX11::OnMouseReleased() {
- if (source_current_window_ != None) {
- if (ContainsKey(waiting_on_status_, source_current_window_)) {
- // If we are waiting for an XdndStatus message, we need to wait for it to
- // complete.
- pending_drop_.insert(source_current_window_);
+ move_loop_.EndMoveLoop();
return;
}
- std::map< ::Window, ::Atom>::iterator it =
- negotiated_operation_.find(source_current_window_);
- if (it != negotiated_operation_.end() && it->second != None) {
+ if (negotiated_operation_ != ui::DragDropTypes::DRAG_NONE) {
+ // Start timer to end the move loop if the target takes too long to send
+ // an XdndFinished message. It is important that StartEndMoveLoopTimer()
+ // is called before SendXdndDrop() because SendXdndDrop()
+ // sends XdndFinished synchronously if the drop target is a Chrome
+ // window.
+ StartEndMoveLoopTimer();
+
// We have negotiated an action with the other end.
+ source_state_ = SOURCE_STATE_DROPPED;
SendXdndDrop(source_current_window_);
return;
}
-
- SendXdndLeave(source_current_window_);
- source_current_window_ = None;
}
move_loop_.EndMoveLoop();
}
void DesktopDragDropClientAuraX11::OnMoveLoopEnded() {
+ if (source_current_window_ != None) {
+ SendXdndLeave(source_current_window_);
+ source_current_window_ = None;
+ }
target_current_context_.reset();
+ repeat_mouse_move_timer_.Stop();
+ end_move_loop_timer_.Stop();
+}
+
+XID DesktopDragDropClientAuraX11::FindWindowFor(
+ const gfx::Point& screen_point) {
+ views::X11TopmostWindowFinder finder;
+ ::Window target = finder.FindWindowAt(screen_point);
+
+ if (target == None)
+ return None;
+
+ // Figure out which window we should test as XdndAware. If |target| has
+ // XdndProxy, it will set that proxy on target, and if not, |target|'s
+ // original value will remain.
+ ui::GetXIDProperty(target, "XdndProxy", &target);
+
+ int version;
+ if (ui::GetIntProperty(target, "XdndAware", &version) &&
+ version >= kMinXdndVersion) {
+ return target;
+ }
+ return None;
+}
+
+void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
+ XEvent* xev) {
+ DCHECK_EQ(ClientMessage, xev->type);
+
+ // Don't send messages to the X11 message queue if we can help it.
+ DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
+ if (short_circuit) {
+ Atom message_type = xev->xclient.message_type;
+ if (message_type == atom_cache_.GetAtom("XdndEnter")) {
+ short_circuit->OnXdndEnter(xev->xclient);
+ return;
+ } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
+ short_circuit->OnXdndLeave(xev->xclient);
+ return;
+ } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
+ short_circuit->OnXdndPosition(xev->xclient);
+ return;
+ } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
+ short_circuit->OnXdndStatus(xev->xclient);
+ return;
+ } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
+ short_circuit->OnXdndFinished(xev->xclient);
+ return;
+ } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
+ short_circuit->OnXdndDrop(xev->xclient);
+ return;
+ }
+ }
+
+ // I don't understand why the GTK+ code is doing what it's doing here. It
+ // goes out of its way to send the XEvent so that it receives a callback on
+ // success or failure, and when it fails, it then sends an internal
+ // GdkEvent about the failed drag. (And sending this message doesn't appear
+ // to go through normal xlib machinery, but instead passes through the low
+ // level xProto (the x11 wire format) that I don't understand.
+ //
+ // I'm unsure if I have to jump through those hoops, or if XSendEvent is
+ // sufficient.
+ XSendEvent(xdisplay_, xid, False, 0, xev);
+}
+
+void DesktopDragDropClientAuraX11::ProcessMouseMove(
+ const gfx::Point& screen_point,
+ unsigned long event_time) {
+ if (source_state_ != SOURCE_STATE_OTHER)
+ return;
+
+ // Find the current window the cursor is over.
+ ::Window dest_window = FindWindowFor(screen_point);
+
+ if (source_current_window_ != dest_window) {
+ if (source_current_window_ != None)
+ SendXdndLeave(source_current_window_);
+
+ source_current_window_ = dest_window;
+ waiting_on_status_ = false;
+ next_position_message_.reset();
+ status_received_since_enter_ = false;
+ negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
+
+ if (source_current_window_ != None)
+ SendXdndEnter(source_current_window_);
+ }
+
+ if (source_current_window_ != None) {
+ if (waiting_on_status_) {
+ next_position_message_.reset(
+ new std::pair<gfx::Point, unsigned long>(screen_point, event_time));
+ } else {
+ SendXdndPosition(dest_window, screen_point, event_time);
+ }
+ }
+}
+
+void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() {
+ end_move_loop_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(
+ kEndMoveLoopTimeoutMs),
+ this,
+ &DesktopDragDropClientAuraX11::EndMoveLoop);
+}
+
+void DesktopDragDropClientAuraX11::EndMoveLoop() {
+ move_loop_.EndMoveLoop();
}
void DesktopDragDropClientAuraX11::DragTranslate(
@@ -687,8 +827,7 @@ void DesktopDragDropClientAuraX11::DragTranslate(
scoped_ptr<ui::DropTargetEvent>* event,
aura::client::DragDropDelegate** delegate) {
gfx::Point root_location = root_window_location;
- root_window_->GetDispatcher()->host()->ConvertPointFromNativeScreen(
- &root_location);
+ root_window_->GetHost()->ConvertPointFromNativeScreen(&root_location);
aura::Window* target_window =
root_window_->GetEventHandlerForPoint(root_location);
bool target_window_changed = false;
@@ -747,7 +886,8 @@ void DesktopDragDropClientAuraX11::NotifyDragLeave() {
return None;
}
-int DesktopDragDropClientAuraX11::AtomToDragOperation(::Atom atom) {
+ui::DragDropTypes::DragOperation
+DesktopDragDropClientAuraX11::AtomToDragOperation(::Atom atom) {
if (atom == atom_cache_.GetAtom(kXdndActionCopy))
return ui::DragDropTypes::DRAG_COPY;
if (atom == atom_cache_.GetAtom(kXdndActionMove))
@@ -834,12 +974,6 @@ void DesktopDragDropClientAuraX11::SendXdndEnter(::Window dest_window) {
}
void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) {
- // If we're sending a leave message, don't wait for status messages anymore.
- waiting_on_status_.erase(dest_window);
- NextPositionMap::iterator it = next_position_message_.find(dest_window);
- if (it != next_position_message_.end())
- next_position_message_.erase(it);
-
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.message_type = atom_cache_.GetAtom("XdndLeave");
@@ -856,8 +990,8 @@ void DesktopDragDropClientAuraX11::SendXdndLeave(::Window dest_window) {
void DesktopDragDropClientAuraX11::SendXdndPosition(
::Window dest_window,
const gfx::Point& screen_point,
- unsigned long time) {
- waiting_on_status_.insert(dest_window);
+ unsigned long event_time) {
+ waiting_on_status_ = true;
XEvent xev;
xev.xclient.type = ClientMessage;
@@ -867,9 +1001,20 @@ void DesktopDragDropClientAuraX11::SendXdndPosition(
xev.xclient.data.l[0] = xwindow_;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y();
- xev.xclient.data.l[3] = time;
+ xev.xclient.data.l[3] = event_time;
xev.xclient.data.l[4] = DragOperationToAtom(drag_operation_);
SendXClientEvent(dest_window, &xev);
+
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and
+ // the Xdnd protocol both recommend that drag events should be sent
+ // periodically.
+ repeat_mouse_move_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kRepeatMouseMoveTimeoutMs),
+ base::Bind(&DesktopDragDropClientAuraX11::ProcessMouseMove,
+ base::Unretained(this),
+ screen_point,
+ event_time));
}
void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) {
@@ -886,45 +1031,4 @@ void DesktopDragDropClientAuraX11::SendXdndDrop(::Window dest_window) {
SendXClientEvent(dest_window, &xev);
}
-void DesktopDragDropClientAuraX11::SendXClientEvent(::Window xid,
- XEvent* xev) {
- DCHECK_EQ(ClientMessage, xev->type);
-
- // Don't send messages to the X11 message queue if we can help it.
- DesktopDragDropClientAuraX11* short_circuit = GetForWindow(xid);
- if (short_circuit) {
- Atom message_type = xev->xclient.message_type;
- if (message_type == atom_cache_.GetAtom("XdndEnter")) {
- short_circuit->OnXdndEnter(xev->xclient);
- return;
- } else if (message_type == atom_cache_.GetAtom("XdndLeave")) {
- short_circuit->OnXdndLeave(xev->xclient);
- return;
- } else if (message_type == atom_cache_.GetAtom("XdndPosition")) {
- short_circuit->OnXdndPosition(xev->xclient);
- return;
- } else if (message_type == atom_cache_.GetAtom("XdndStatus")) {
- short_circuit->OnXdndStatus(xev->xclient);
- return;
- } else if (message_type == atom_cache_.GetAtom("XdndFinished")) {
- short_circuit->OnXdndFinished(xev->xclient);
- return;
- } else if (message_type == atom_cache_.GetAtom("XdndDrop")) {
- short_circuit->OnXdndDrop(xev->xclient);
- return;
- }
- }
-
- // I don't understand why the GTK+ code is doing what it's doing here. It
- // goes out of its way to send the XEvent so that it receives a callback on
- // success or failure, and when it fails, it then sends an internal
- // GdkEvent about the failed drag. (And sending this message doesn't appear
- // to go through normal xlib machinery, but instead passes through the low
- // level xProto (the x11 wire format) that I don't understand.
- //
- // I'm unsure if I have to jump through those hoops, or if XSendEvent is
- // sufficient.
- XSendEvent(xdisplay_, xid, False, 0, xev);
-}
-
} // namespace views
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 8e8711e5fa3..30f3aa022e1 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
@@ -9,16 +9,18 @@
#include <X11/Xlib.h>
#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/drag_drop_client.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/gfx/point.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop_delegate.h"
+#include "ui/wm/public/drag_drop_client.h"
namespace aura {
namespace client {
@@ -42,7 +44,7 @@ namespace views {
class DesktopNativeCursorManager;
// Implements drag and drop on X11 for aura. On one side, this class takes raw
-// X11 events forwarded from DesktopRootWindowHostLinux, while on the other, it
+// X11 events forwarded from DesktopWindowTreeHostLinux, while on the other, it
// handles the views drag events.
class VIEWS_EXPORT DesktopDragDropClientAuraX11
: public aura::client::DragDropClient,
@@ -95,9 +97,43 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
virtual void OnMouseReleased() OVERRIDE;
virtual void OnMoveLoopEnded() OVERRIDE;
+ protected:
+ // The following methods are virtual for the sake of testing.
+
+ // Finds the topmost X11 window at |screen_point| and returns it if it is
+ // Xdnd aware. Returns NULL otherwise.
+ virtual ::Window FindWindowFor(const gfx::Point& screen_point);
+
+ // Sends |xev| to |xid|, optionally short circuiting the round trip to the X
+ // server.
+ virtual void SendXClientEvent(::Window xid, XEvent* xev);
+
private:
- typedef std::map< ::Window, std::pair<gfx::Point, unsigned long> >
- NextPositionMap;
+ enum SourceState {
+ // |source_current_window_| will receive a drop once we receive an
+ // XdndStatus from it.
+ SOURCE_STATE_PENDING_DROP,
+
+ // The move looped will be ended once we receive XdndFinished from
+ // |source_current_window_|. We should not send XdndPosition to
+ // |source_current_window_| while in this state.
+ SOURCE_STATE_DROPPED,
+
+ // There is no drag in progress or there is a drag in progress and the
+ // user has not yet released the mouse.
+ SOURCE_STATE_OTHER,
+ };
+
+ // Processes a mouse move at |screen_point|.
+ void ProcessMouseMove(const gfx::Point& screen_point,
+ unsigned long event_time);
+
+ // Start timer to end the move loop if the target is too slow to respond after
+ // the mouse is released.
+ void StartEndMoveLoopTimer();
+
+ // Ends the move loop.
+ void EndMoveLoop();
// When we receive an position x11 message, we need to translate that into
// the underlying aura::Window representation, as moves internal to the X11
@@ -116,7 +152,7 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
::Atom DragOperationToAtom(int drag_operation);
// Converts a single action atom to a drag operation.
- int AtomToDragOperation(::Atom atom);
+ ui::DragDropTypes::DragOperation AtomToDragOperation(::Atom atom);
// During the blocking StartDragAndDrop() call, this converts the views-style
// |drag_operation_| bitfield into a vector of Atoms to offer to other
@@ -138,13 +174,9 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
void SendXdndLeave(::Window dest_window);
void SendXdndPosition(::Window dest_window,
const gfx::Point& screen_point,
- unsigned long time);
+ unsigned long event_time);
void SendXdndDrop(::Window dest_window);
- // Sends |xev| to |xid|, optionally short circuiting the round trip to the X
- // server.
- void SendXClientEvent(::Window xid, XEvent* xev);
-
// A nested message loop that notifies this object of events through the
// X11WholeScreenMoveLoopDelegate interface.
X11WholeScreenMoveLoop move_loop_;
@@ -175,46 +207,53 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
// In the Xdnd protocol, we aren't supposed to send another XdndPosition
// message until we have received a confirming XdndStatus message.
- std::set< ::Window> waiting_on_status_;
+ bool waiting_on_status_;
// If we would send an XdndPosition message while we're waiting for an
// XdndStatus response, we need to cache the latest details we'd send.
- NextPositionMap next_position_message_;
+ scoped_ptr<std::pair<gfx::Point, unsigned long> > next_position_message_;
+
+ // Reprocesses the most recent mouse move event if the mouse has not moved
+ // in a while in case the window stacking order has changed and
+ // |source_current_window_| needs to be updated.
+ base::OneShotTimer<DesktopDragDropClientAuraX11> repeat_mouse_move_timer_;
+
+ // When the mouse is released, we need to wait for the last XdndStatus message
+ // only if we have previously received a status message from
+ // |source_current_window_|.
+ bool status_received_since_enter_;
// Source side information.
ui::OSExchangeDataProviderAuraX11 const* source_provider_;
::Window source_current_window_;
+ SourceState source_state_;
- bool drag_drop_in_progress_;
+ // The current drag-drop client that has an active operation. Since we have
+ // multiple root windows and multiple DesktopDragDropClientAuraX11 instances
+ // it is important to maintain only one drag and drop operation at any time.
+ static DesktopDragDropClientAuraX11* g_current_drag_drop_client;
// The operation bitfield as requested by StartDragAndDrop.
int drag_operation_;
- // The operation performed. Is initialized to None at the start of
- // StartDragAndDrop(), and is set only during the asynchronous XdndFinished
- // message.
- int resulting_operation_;
-
- // This window will be receiving a drop as soon as we receive an XdndStatus
- // from it.
- std::set< ::Window> pending_drop_;
-
// We offer the other window a list of possible operations,
// XdndActionsList. This is the requested action from the other window. This
- // is None if we haven't sent out an XdndPosition message yet, haven't yet
- // received an XdndStatus or if the other window has told us that there's no
- // action that we can agree on.
- //
- // This is a map instead of a simple variable because of the case where we
- // put an XdndLeave in the queue at roughly the same time that the other
- // window responds to an XdndStatus.
- std::map< ::Window, ::Atom> negotiated_operation_;
+ // is DRAG_NONE if we haven't sent out an XdndPosition message yet, haven't
+ // yet received an XdndStatus or if the other window has told us that there's
+ // no action that we can agree on.
+ ui::DragDropTypes::DragOperation negotiated_operation_;
+
+ // Ends the move loop if the target is too slow to respond after the mouse is
+ // released.
+ base::OneShotTimer<DesktopDragDropClientAuraX11> end_move_loop_timer_;
// We use these cursors while dragging.
gfx::NativeCursor grab_cursor_;
gfx::NativeCursor copy_grab_cursor_;
gfx::NativeCursor move_grab_cursor_;
+ base::WeakPtrFactory<DesktopDragDropClientAuraX11> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientAuraX11);
};
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
new file mode 100644
index 00000000000..4286d1873a5
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
@@ -0,0 +1,679 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <map>
+#include <vector>
+
+// Include views_test_base.h first because the definition of None in X.h
+// conflicts with the definition of None in gtest-type-util.h
+#include "ui/views/test/views_test_base.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
+#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
+#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/widget.h"
+
+#include <X11/Xlib.h>
+
+namespace views {
+
+namespace {
+
+const char* kAtomsToCache[] = {
+ "XdndActionCopy",
+ "XdndDrop",
+ "XdndEnter",
+ "XdndFinished",
+ "XdndLeave",
+ "XdndPosition",
+ "XdndStatus",
+ "XdndTypeList",
+ NULL
+};
+
+class TestDragDropClient;
+
+// Collects messages which would otherwise be sent to |xid_| via
+// SendXClientEvent().
+class ClientMessageEventCollector {
+ public:
+ ClientMessageEventCollector(::Window xid, TestDragDropClient* client);
+ virtual ~ClientMessageEventCollector();
+
+ // Returns true if |events_| is non-empty.
+ bool HasEvents() const {
+ return !events_.empty();
+ }
+
+ // Pops all of |events_| and returns the popped events in the order that they
+ // were on the stack
+ std::vector<XClientMessageEvent> PopAllEvents();
+
+ // Adds |event| to the stack.
+ void RecordEvent(const XClientMessageEvent& event);
+
+ private:
+ ::Window xid_;
+
+ // Not owned.
+ TestDragDropClient* client_;
+
+ std::vector<XClientMessageEvent> events_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientMessageEventCollector);
+};
+
+// Implementation of DesktopDragDropClientAuraX11 which works with a fake
+// |DesktopDragDropClientAuraX11::source_current_window_|.
+class TestDragDropClient : public DesktopDragDropClientAuraX11 {
+ public:
+ // The location in screen coordinates used for the synthetic mouse moves
+ // generated in SetTopmostXWindowAndMoveMouse().
+ static const int kMouseMoveX;
+ static const int kMouseMoveY;
+
+ TestDragDropClient(aura::Window* window,
+ DesktopNativeCursorManager* cursor_manager);
+ virtual ~TestDragDropClient();
+
+ // Returns the XID of the window which initiated the drag.
+ ::Window source_xwindow() {
+ return source_xid_;
+ }
+
+ // Returns the Atom with |name|.
+ Atom GetAtom(const char* name);
+
+ // Returns true if the event's message has |type|.
+ bool MessageHasType(const XClientMessageEvent& event,
+ const char* type);
+
+ // Sets |collector| to collect XClientMessageEvents which would otherwise
+ // have been sent to the drop target window.
+ void SetEventCollectorFor(::Window xid,
+ ClientMessageEventCollector* collector);
+
+ // Builds an XdndStatus message and sends it to
+ // DesktopDragDropClientAuraX11.
+ void OnStatus(XID target_window,
+ bool will_accept_drop,
+ ::Atom accepted_action);
+
+ // Builds an XdndFinished message and sends it to
+ // DesktopDragDropClientAuraX11.
+ void OnFinished(XID target_window,
+ bool accepted_drop,
+ ::Atom performed_action);
+
+ // Sets |xid| as the topmost window at the current mouse position and
+ // generates a synthetic mouse move.
+ void SetTopmostXWindowAndMoveMouse(::Window xid);
+
+ // Returns true if the move loop is running.
+ bool IsMoveLoopRunning();
+
+ // DesktopDragDropClientAuraX11:
+ virtual int StartDragAndDrop(
+ const ui::OSExchangeData& data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& root_location,
+ int operation,
+ ui::DragDropTypes::DragEventSource source) OVERRIDE;
+ virtual void OnMoveLoopEnded() OVERRIDE;
+
+ private:
+ // DesktopDragDropClientAuraX11:
+ virtual ::Window FindWindowFor(const gfx::Point& screen_point) OVERRIDE;
+ virtual void SendXClientEvent(::Window xid, XEvent* event) OVERRIDE;
+
+ // The XID of the window which initiated the drag.
+ ::Window source_xid_;
+
+ // The XID of the window which is simulated to be the topmost window at the
+ // current mouse position.
+ ::Window target_xid_;
+
+ // Whether the move loop is running.
+ bool move_loop_running_;
+
+ // Map of ::Windows to the collector which intercepts XClientMessageEvents
+ // for that window.
+ std::map< ::Window, ClientMessageEventCollector*> collectors_;
+
+ ui::X11AtomCache atom_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDragDropClient);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ClientMessageEventCollector
+
+ClientMessageEventCollector::ClientMessageEventCollector(
+ ::Window xid,
+ TestDragDropClient* client)
+ : xid_(xid),
+ client_(client) {
+ client->SetEventCollectorFor(xid, this);
+}
+
+ClientMessageEventCollector::~ClientMessageEventCollector() {
+ client_->SetEventCollectorFor(xid_, NULL);
+}
+
+std::vector<XClientMessageEvent> ClientMessageEventCollector::PopAllEvents() {
+ std::vector<XClientMessageEvent> to_return;
+ to_return.swap(events_);
+ return to_return;
+}
+
+void ClientMessageEventCollector::RecordEvent(
+ const XClientMessageEvent& event) {
+ events_.push_back(event);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TestDragDropClient
+
+// static
+const int TestDragDropClient::kMouseMoveX = 100;
+
+// static
+const int TestDragDropClient::kMouseMoveY = 200;
+
+TestDragDropClient::TestDragDropClient(
+ aura::Window* window,
+ DesktopNativeCursorManager* cursor_manager)
+ : DesktopDragDropClientAuraX11(window,
+ cursor_manager,
+ gfx::GetXDisplay(),
+ window->GetHost()->GetAcceleratedWidget()),
+ source_xid_(window->GetHost()->GetAcceleratedWidget()),
+ target_xid_(None),
+ move_loop_running_(false),
+ atom_cache_(gfx::GetXDisplay(), kAtomsToCache) {
+}
+
+TestDragDropClient::~TestDragDropClient() {
+}
+
+Atom TestDragDropClient::GetAtom(const char* name) {
+ return atom_cache_.GetAtom(name);
+}
+
+bool TestDragDropClient::MessageHasType(const XClientMessageEvent& event,
+ const char* type) {
+ return event.message_type == atom_cache_.GetAtom(type);
+}
+
+void TestDragDropClient::SetEventCollectorFor(
+ ::Window xid,
+ ClientMessageEventCollector* collector) {
+ if (collector)
+ collectors_[xid] = collector;
+ else
+ collectors_.erase(xid);
+}
+
+void TestDragDropClient::OnStatus(XID target_window,
+ bool will_accept_drop,
+ ::Atom accepted_action) {
+ XClientMessageEvent event;
+ event.message_type = atom_cache_.GetAtom("XdndStatus");
+ event.format = 32;
+ event.window = source_xid_;
+ event.data.l[0] = target_window;
+ event.data.l[1] = will_accept_drop ? 1 : 0;
+ event.data.l[2] = 0;
+ event.data.l[3] = 0;
+ event.data.l[4] = accepted_action;
+ OnXdndStatus(event);
+}
+
+void TestDragDropClient::OnFinished(XID target_window,
+ bool accepted_drop,
+ ::Atom performed_action) {
+ XClientMessageEvent event;
+ event.message_type = atom_cache_.GetAtom("XdndFinished");
+ event.format = 32;
+ event.window = source_xid_;
+ event.data.l[0] = target_window;
+ event.data.l[1] = accepted_drop ? 1 : 0;
+ event.data.l[2] = performed_action;
+ event.data.l[3] = 0;
+ event.data.l[4] = 0;
+ OnXdndFinished(event);
+}
+
+void TestDragDropClient::SetTopmostXWindowAndMoveMouse(::Window xid) {
+ target_xid_ = xid;
+
+ XMotionEvent event;
+ event.time = CurrentTime;
+ event.x_root = kMouseMoveX;
+ event.y_root = kMouseMoveY;
+ OnMouseMovement(&event);
+}
+
+bool TestDragDropClient::IsMoveLoopRunning() {
+ return move_loop_running_;
+}
+
+int TestDragDropClient::StartDragAndDrop(
+ const ui::OSExchangeData& data,
+ aura::Window* root_window,
+ aura::Window* source_window,
+ const gfx::Point& root_location,
+ int operation,
+ ui::DragDropTypes::DragEventSource source) {
+ move_loop_running_ = true;
+ return DesktopDragDropClientAuraX11::StartDragAndDrop(data, root_window,
+ source_window, root_location, operation, source);
+}
+
+void TestDragDropClient::OnMoveLoopEnded() {
+ DesktopDragDropClientAuraX11::OnMoveLoopEnded();
+ move_loop_running_ = false;
+}
+
+::Window TestDragDropClient::FindWindowFor(const gfx::Point& screen_point) {
+ return target_xid_;
+}
+
+void TestDragDropClient::SendXClientEvent(::Window xid, XEvent* event) {
+ std::map< ::Window, ClientMessageEventCollector*>::iterator it =
+ collectors_.find(xid);
+ if (it != collectors_.end())
+ it->second->RecordEvent(event->xclient);
+}
+
+} // namespace
+
+class DesktopDragDropClientAuraX11Test : public ViewsTestBase {
+ public:
+ DesktopDragDropClientAuraX11Test() {
+ }
+
+ virtual ~DesktopDragDropClientAuraX11Test() {
+ }
+
+ int StartDragAndDrop() {
+ ui::OSExchangeData data;
+ data.SetString(base::ASCIIToUTF16("Test"));
+
+ return client_->StartDragAndDrop(
+ data,
+ widget_->GetNativeWindow()->GetRootWindow(),
+ widget_->GetNativeWindow(),
+ gfx::Point(),
+ ui::DragDropTypes::DRAG_COPY,
+ ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+ }
+
+ // ViewsTestBase:
+ virtual void SetUp() OVERRIDE {
+ ViewsTestBase::SetUp();
+
+ // Create widget to initiate the drags.
+ widget_.reset(new Widget);
+ Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(widget_.get());
+ params.bounds = gfx::Rect(100, 100);
+ widget_->Init(params);
+ widget_->Show();
+
+ cursor_manager_.reset(new DesktopNativeCursorManager(
+ DesktopCursorLoaderUpdater::Create()));
+
+ client_.reset(new TestDragDropClient(widget_->GetNativeWindow(),
+ cursor_manager_.get()));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ client_.reset();
+ cursor_manager_.reset();
+ widget_.reset();
+ ViewsTestBase::TearDown();
+ }
+
+ TestDragDropClient* client() {
+ return client_.get();
+ }
+
+ private:
+ scoped_ptr<TestDragDropClient> client_;
+ scoped_ptr<DesktopNativeCursorManager> cursor_manager_;
+
+ // The widget used to initiate drags.
+ scoped_ptr<Widget> widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientAuraX11Test);
+};
+
+namespace {
+
+void BasicStep2(TestDragDropClient* client, XID toplevel) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ // XdndEnter should have been sent to |toplevel| before the XdndPosition
+ // message.
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_EQ(client->source_xwindow(),
+ static_cast<XID>(events[0].data.l[0]));
+ EXPECT_EQ(1, events[0].data.l[1] & 1);
+ std::vector<Atom> targets;
+ ui::GetAtomArrayProperty(client->source_xwindow(), "XdndTypeList", &targets);
+ EXPECT_FALSE(targets.empty());
+
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+ EXPECT_EQ(client->source_xwindow(),
+ static_cast<XID>(events[0].data.l[0]));
+ const long kCoords =
+ TestDragDropClient::kMouseMoveX << 16 | TestDragDropClient::kMouseMoveY;
+ EXPECT_EQ(kCoords, events[1].data.l[2]);
+ EXPECT_EQ(client->GetAtom("XdndActionCopy"),
+ static_cast<Atom>(events[1].data.l[4]));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+
+ // Because there is no unprocessed XdndPosition, the drag drop client should
+ // send XdndDrop immediately after the mouse is released.
+ client->OnMouseReleased();
+
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
+ EXPECT_EQ(client->source_xwindow(),
+ static_cast<XID>(events[0].data.l[0]));
+
+ // Send XdndFinished to indicate that the drag drop client can cleanup any
+ // data related to this drag. The move loop should end only after the
+ // XdndFinished message was received.
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+ client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+void BasicStep3(TestDragDropClient* client, XID toplevel) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
+
+ // We have not received an XdndStatus ack for the second XdndPosition message.
+ // Test that sending XdndDrop is delayed till the XdndStatus ack is received.
+ client->OnMouseReleased();
+ EXPECT_FALSE(collector.HasEvents());
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
+
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+ client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+} // namespace
+
+TEST_F(DesktopDragDropClientAuraX11Test, Basic) {
+ XID toplevel = 1;
+
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&BasicStep2,
+ client(),
+ toplevel));
+ int result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+
+ // Do another drag and drop to test that the data is properly cleaned up as a
+ // result of the XdndFinished message.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&BasicStep3,
+ client(),
+ toplevel));
+ result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+}
+
+namespace {
+
+void TargetDoesNotRespondStep2(TestDragDropClient* client) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ XID toplevel = 1;
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+
+ client->OnMouseReleased();
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndLeave"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+} // namespace
+
+// Test that we do not wait for the target to send XdndStatus if we have not
+// received any XdndStatus messages at all from the target. The Unity
+// DNDCollectionWindow is an example of an XdndAware target which does not
+// respond to XdndPosition messages at all.
+TEST_F(DesktopDragDropClientAuraX11Test, TargetDoesNotRespond) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&TargetDoesNotRespondStep2, client()));
+ int result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+}
+
+namespace {
+
+void QueuePositionStep2(TestDragDropClient* client) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ XID toplevel = 1;
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(collector.HasEvents());
+
+ client->OnMouseReleased();
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
+
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+ client->OnFinished(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+} // namespace
+
+// Test that XdndPosition messages are queued till the pending XdndPosition
+// message is acked via an XdndStatus message.
+TEST_F(DesktopDragDropClientAuraX11Test, QueuePosition) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&QueuePositionStep2, client()));
+ int result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+}
+
+namespace {
+
+void TargetChangesStep2(TestDragDropClient* client) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ XID toplevel1 = 1;
+ ClientMessageEventCollector collector1(toplevel1, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel1);
+
+ std::vector<XClientMessageEvent> events1 = collector1.PopAllEvents();
+ ASSERT_EQ(2u, events1.size());
+ EXPECT_TRUE(client->MessageHasType(events1[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events1[1], "XdndPosition"));
+
+ XID toplevel2 = 2;
+ ClientMessageEventCollector collector2(toplevel2, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel2);
+
+ // It is possible for |toplevel1| to send XdndStatus after the source has sent
+ // XdndLeave but before |toplevel1| has received the XdndLeave message. The
+ // XdndStatus message should be ignored.
+ client->OnStatus(toplevel1, true, client->GetAtom("XdndActionCopy"));
+ events1 = collector1.PopAllEvents();
+ ASSERT_EQ(1u, events1.size());
+ EXPECT_TRUE(client->MessageHasType(events1[0], "XdndLeave"));
+
+ std::vector<XClientMessageEvent> events2 = collector2.PopAllEvents();
+ ASSERT_EQ(2u, events2.size());
+ EXPECT_TRUE(client->MessageHasType(events2[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events2[1], "XdndPosition"));
+
+ client->OnStatus(toplevel2, true, client->GetAtom("XdndActionCopy"));
+ client->OnMouseReleased();
+ events2 = collector2.PopAllEvents();
+ ASSERT_EQ(1u, events2.size());
+ EXPECT_TRUE(client->MessageHasType(events2[0], "XdndDrop"));
+
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+ client->OnFinished(toplevel2, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+} // namespace
+
+// Test the behavior when the target changes during a drag.
+TEST_F(DesktopDragDropClientAuraX11Test, TargetChanges) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&TargetChangesStep2, client()));
+ int result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_COPY, result);
+}
+
+namespace {
+
+void RejectAfterMouseReleaseStep2(TestDragDropClient* client) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ XID toplevel = 1;
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(collector.HasEvents());
+
+ // Send another mouse move such that there is a pending XdndPosition.
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndPosition"));
+
+ client->OnMouseReleased();
+ // Reject the drop.
+ client->OnStatus(toplevel, false, None);
+
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndLeave"));
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+void RejectAfterMouseReleaseStep3(TestDragDropClient* client) {
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+
+ XID toplevel = 2;
+ ClientMessageEventCollector collector(toplevel, client);
+ client->SetTopmostXWindowAndMoveMouse(toplevel);
+
+ std::vector<XClientMessageEvent> events = collector.PopAllEvents();
+ ASSERT_EQ(2u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndEnter"));
+ EXPECT_TRUE(client->MessageHasType(events[1], "XdndPosition"));
+
+ client->OnStatus(toplevel, true, client->GetAtom("XdndActionCopy"));
+ EXPECT_FALSE(collector.HasEvents());
+
+ client->OnMouseReleased();
+ events = collector.PopAllEvents();
+ ASSERT_EQ(1u, events.size());
+ EXPECT_TRUE(client->MessageHasType(events[0], "XdndDrop"));
+
+ EXPECT_TRUE(client->IsMoveLoopRunning());
+ client->OnFinished(toplevel, false, None);
+ EXPECT_FALSE(client->IsMoveLoopRunning());
+}
+
+} // namespace
+
+// Test that the source sends XdndLeave instead of XdndDrop if the drag
+// operation is rejected after the mouse is released.
+TEST_F(DesktopDragDropClientAuraX11Test, RejectAfterMouseRelease) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&RejectAfterMouseReleaseStep2, client()));
+ int result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+
+ // Repeat the test but reject the drop in the XdndFinished message instead.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&RejectAfterMouseReleaseStep3, client()));
+ result = StartDragAndDrop();
+ EXPECT_EQ(ui::DragDropTypes::DRAG_NONE, result);
+}
+
+} // namespace views
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 5669f31a1fb..26431c1159f 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
@@ -9,8 +9,7 @@
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
#include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
-#include "ui/views/widget/drop_target_win.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
namespace views {
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 042a5a8a3c3..a8051ca8693 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
@@ -7,15 +7,14 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
-#include "ui/aura/client/drag_drop_client.h"
#include "ui/views/views_export.h"
+#include "ui/wm/public/drag_drop_client.h"
namespace ui {
class DragSourceWin;
}
namespace views {
-class DesktopDragDragSourceWin;
class DesktopDropTargetWin;
class VIEWS_EXPORT DesktopDragDropClientWin
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 57c81d58628..1369b62eb79 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
@@ -5,14 +5,14 @@
#include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
#include "base/win/win_util.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
#include "ui/events/event_constants.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/drag_drop_delegate.h"
using aura::client::DragDropDelegate;
using ui::OSExchangeData;
@@ -96,7 +96,7 @@ void DesktopDropTargetWin::Translate(
DragDropDelegate** delegate) {
gfx::Point location(position.x, position.y);
gfx::Point root_location = location;
- root_window_->GetDispatcher()->host()->ConvertPointFromNativeScreen(
+ root_window_->GetHost()->ConvertPointFromNativeScreen(
&root_location);
aura::Window* target_window =
root_window_->GetEventHandlerForPoint(root_location);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.h b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.h
index 113fd75ce23..9e11ff68cf1 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.h
@@ -23,7 +23,7 @@ class OSExchangeData;
namespace views {
// DesktopDropTargetWin takes care of managing drag and drop for
-// DesktopRootWindowHostWin. It converts Windows OLE drop messages into
+// DesktopWindowTreeHostWin. It converts Windows OLE drop messages into
// aura::client::DragDropDelegate calls.
class DesktopDropTargetWin : public ui::DropTargetWin,
public aura::WindowObserver {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h
index e557d3bdb7a..2af191b445f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_factory_ozone.h
@@ -9,11 +9,12 @@
namespace gfx {
class Rect;
+class Screen;
}
namespace views {
class DesktopNativeWidgetAura;
-class DesktopRootWindowHost;
+class DesktopWindowTreeHost;
namespace internal {
class NativeWidgetDelegate;
@@ -30,12 +31,16 @@ class VIEWS_EXPORT DesktopFactoryOzone {
// Sets the implementation delegate. Ownership is retained by the caller.
static void SetInstance(DesktopFactoryOzone* impl);
- // Delegates implementation of DesktopRootWindowHost::Create externally to
+ // Delegates implementation of DesktopWindowTreeHost::Create externally to
// Ozone implementation.
- virtual DesktopRootWindowHost* CreateRootWindowHost(
+ virtual DesktopWindowTreeHost* CreateWindowTreeHost(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura) = 0;
+ // Delegates implementation of DesktopScreen externally to
+ // Ozone implementation.
+ virtual gfx::Screen* CreateDesktopScreen() = 0;
+
private:
static DesktopFactoryOzone* impl_; // not owned
};
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 475facf10cf..1d7d40c5e3d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc
@@ -4,8 +4,8 @@
#include "ui/views/widget/desktop_aura/desktop_focus_rules.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
namespace views {
@@ -14,6 +14,14 @@ DesktopFocusRules::DesktopFocusRules(aura::Window* content_window)
DesktopFocusRules::~DesktopFocusRules() {}
+bool DesktopFocusRules::CanActivateWindow(aura::Window* window) const {
+ if (!BaseFocusRules::CanActivateWindow(window))
+ return false;
+ // Never activate a window that is not a child of the root window. Transients
+ // spanning different DesktopNativeWidgetAuras may trigger this.
+ return !window || content_window_->GetRootWindow()->Contains(window);
+}
+
bool DesktopFocusRules::SupportsChildActivation(aura::Window* window) const {
// In Desktop-Aura, only the content_window or children of the RootWindow are
// activatable.
@@ -32,7 +40,7 @@ bool DesktopFocusRules::IsWindowConsideredVisibleForActivation(
aura::Window* DesktopFocusRules::GetToplevelWindow(
aura::Window* window) const {
aura::Window* top_level_window =
- corewm::BaseFocusRules::GetToplevelWindow(window);
+ wm::BaseFocusRules::GetToplevelWindow(window);
// In Desktop-Aura, only the content_window or children of the RootWindow are
// considered as top level windows.
if (top_level_window == content_window_->parent())
@@ -43,7 +51,7 @@ aura::Window* DesktopFocusRules::GetToplevelWindow(
aura::Window* DesktopFocusRules::GetNextActivatableWindow(
aura::Window* window) const {
aura::Window* next_activatable_window =
- corewm::BaseFocusRules::GetNextActivatableWindow(window);
+ wm::BaseFocusRules::GetNextActivatableWindow(window);
// In Desktop-Aura the content_window_'s parent is a dummy window and thus
// should never be activated. We should return the content_window_ if it
// can be activated in this case.
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h
index fff8116b18e..e096e80998d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.h
@@ -5,17 +5,18 @@
#ifndef UI_VIEWS_WIDGET_DESKTOP_FOCUS_RULES_H_
#define UI_VIEWS_WIDGET_DESKTOP_FOCUS_RULES_H_
-#include "ui/views/corewm/base_focus_rules.h"
+#include "ui/wm/core/base_focus_rules.h"
namespace views {
-class DesktopFocusRules : public corewm::BaseFocusRules {
+class DesktopFocusRules : public wm::BaseFocusRules {
public:
explicit DesktopFocusRules(aura::Window* content_window);
virtual ~DesktopFocusRules();
private:
- // Overridden from corewm::BaseFocusRules:
+ // Overridden from wm::BaseFocusRules:
+ virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE;
virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE;
virtual bool IsWindowConsideredVisibleForActivation(
aura::Window* window) const OVERRIDE;
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
new file mode 100644
index 00000000000..39eda7dcb47
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/desktop_aura/desktop_focus_rules.h"
+
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/test/test_window_delegate.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_layer_type.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/widget.h"
+#include "ui/wm/core/window_util.h"
+
+namespace views {
+
+namespace {
+
+scoped_ptr<Widget> CreateDesktopWidget() {
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = Widget::InitParams(
+ Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(widget.get());
+ widget->Init(params);
+ return widget.Pass();
+}
+
+} // namespace
+
+typedef ViewsTestBase DesktopFocusRulesTest;
+
+// Verifies we don't attempt to activate a window in another widget.
+TEST_F(DesktopFocusRulesTest, DontFocusWindowsInOtherHierarchies) {
+ // Two widgets (each with a DesktopNativeWidgetAura). |w2| has a child Window
+ // |w2_child| that is not focusable. |w2_child|'s has a transient parent in
+ // |w1|.
+ scoped_ptr<views::Widget> w1(CreateDesktopWidget());
+ scoped_ptr<views::Widget> w2(CreateDesktopWidget());
+ aura::test::TestWindowDelegate w2_child_delegate;
+ w2_child_delegate.set_can_focus(false);
+ aura::Window* w2_child = new aura::Window(&w2_child_delegate);
+ w2_child->Init(aura::WINDOW_LAYER_SOLID_COLOR);
+ w2->GetNativeView()->AddChild(w2_child);
+ wm::AddTransientChild(w1->GetNativeView(), w2_child);
+ aura::client::GetFocusClient(w2->GetNativeView())->FocusWindow(w2_child);
+ aura::Window* focused =
+ aura::client::GetFocusClient(w2->GetNativeView())->GetFocusedWindow();
+ EXPECT_TRUE((focused == NULL) || w2->GetNativeView()->Contains(focused));
+ wm::RemoveTransientChild(w1->GetNativeView(), w2_child);
+ w1.reset();
+ w2.reset();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
index 911f7753361..187aa6e612f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
@@ -4,20 +4,19 @@
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor_loader.h"
#include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
namespace views {
DesktopNativeCursorManager::DesktopNativeCursorManager(
- aura::RootWindow* window,
scoped_ptr<DesktopCursorLoaderUpdater> cursor_loader_updater)
- : root_window_(window),
- cursor_loader_updater_(cursor_loader_updater.Pass()),
+ : cursor_loader_updater_(cursor_loader_updater.Pass()),
cursor_loader_(ui::CursorLoader::Create()) {
if (cursor_loader_updater_.get())
- cursor_loader_updater_->OnCreate(root_window_, cursor_loader_.get());
+ cursor_loader_updater_->OnCreate(1.0f, cursor_loader_.get());
}
DesktopNativeCursorManager::~DesktopNativeCursorManager() {
@@ -29,11 +28,20 @@ gfx::NativeCursor DesktopNativeCursorManager::GetInitializedCursor(int type) {
return cursor;
}
+void DesktopNativeCursorManager::AddHost(aura::WindowTreeHost* host) {
+ hosts_.insert(host);
+}
+
+void DesktopNativeCursorManager::RemoveHost(aura::WindowTreeHost* host) {
+ hosts_.erase(host);
+}
+
void DesktopNativeCursorManager::SetDisplay(
const gfx::Display& display,
- views::corewm::NativeCursorManagerDelegate* delegate) {
+ wm::NativeCursorManagerDelegate* delegate) {
cursor_loader_->UnloadAll();
- cursor_loader_->set_display(display);
+ cursor_loader_->set_rotation(display.rotation());
+ cursor_loader_->set_scale(display.device_scale_factor());
if (cursor_loader_updater_.get())
cursor_loader_updater_->OnDisplayUpdated(display, cursor_loader_.get());
@@ -43,18 +51,20 @@ void DesktopNativeCursorManager::SetDisplay(
void DesktopNativeCursorManager::SetCursor(
gfx::NativeCursor cursor,
- views::corewm::NativeCursorManagerDelegate* delegate) {
+ wm::NativeCursorManagerDelegate* delegate) {
gfx::NativeCursor new_cursor = cursor;
cursor_loader_->SetPlatformCursor(&new_cursor);
delegate->CommitCursor(new_cursor);
- if (delegate->IsCursorVisible())
- root_window_->SetCursor(new_cursor);
+ if (delegate->IsCursorVisible()) {
+ for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ (*i)->SetCursor(new_cursor);
+ }
}
void DesktopNativeCursorManager::SetVisibility(
bool visible,
- views::corewm::NativeCursorManagerDelegate* delegate) {
+ wm::NativeCursorManagerDelegate* delegate) {
delegate->CommitVisibility(visible);
if (visible) {
@@ -62,27 +72,23 @@ void DesktopNativeCursorManager::SetVisibility(
} else {
gfx::NativeCursor invisible_cursor(ui::kCursorNone);
cursor_loader_->SetPlatformCursor(&invisible_cursor);
- root_window_->SetCursor(invisible_cursor);
+ for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ (*i)->SetCursor(invisible_cursor);
}
- root_window_->OnCursorVisibilityChanged(visible);
+ for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ (*i)->OnCursorVisibilityChanged(visible);
}
void DesktopNativeCursorManager::SetCursorSet(
ui::CursorSetType cursor_set,
- views::corewm::NativeCursorManagerDelegate* delegate) {
- NOTIMPLEMENTED();
-}
-
-void DesktopNativeCursorManager::SetScale(
- float scale,
- views::corewm::NativeCursorManagerDelegate* delegate) {
+ wm::NativeCursorManagerDelegate* delegate) {
NOTIMPLEMENTED();
}
void DesktopNativeCursorManager::SetMouseEventsEnabled(
bool enabled,
- views::corewm::NativeCursorManagerDelegate* delegate) {
+ wm::NativeCursorManagerDelegate* delegate) {
delegate->CommitMouseEventsEnabled(enabled);
// TODO(erg): In the ash version, we set the last mouse location on Env. I'm
@@ -90,7 +96,8 @@ void DesktopNativeCursorManager::SetMouseEventsEnabled(
SetVisibility(delegate->IsCursorVisible(), delegate);
- root_window_->OnMouseEventsEnableStateChanged(enabled);
+ for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ (*i)->dispatcher()->OnMouseEventsEnableStateChanged(enabled);
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
index 563131d92cc..ee156348774 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h
@@ -5,61 +5,69 @@
#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_NATIVE_CURSOR_MANAGER_H_
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_NATIVE_CURSOR_MANAGER_H_
+#include <set>
+
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "ui/views/corewm/native_cursor_manager.h"
#include "ui/views/views_export.h"
+#include "ui/wm/core/native_cursor_manager.h"
namespace aura {
-class RootWindow;
+class WindowTreeHost;
}
namespace ui {
class CursorLoader;
}
-namespace views {
-class DesktopCursorLoaderUpdater;
-
-namespace corewm {
+namespace wm {
class NativeCursorManagerDelegate;
}
-// A NativeCursorManager that interacts with only one RootWindow. (Unlike the
-// one in ash, which interacts with all the RootWindows that ash knows about.)
+namespace views {
+class DesktopCursorLoaderUpdater;
+
+// A NativeCursorManager that performs the desktop-specific setting of cursor
+// state. Similar to AshNativeCursorManager, it also communicates these changes
+// to all root windows.
class VIEWS_EXPORT DesktopNativeCursorManager
- : public views::corewm::NativeCursorManager {
+ : public wm::NativeCursorManager {
public:
DesktopNativeCursorManager(
- aura::RootWindow* window,
scoped_ptr<DesktopCursorLoaderUpdater> cursor_loader_updater);
virtual ~DesktopNativeCursorManager();
// Builds a cursor and sets the internal platform representation.
gfx::NativeCursor GetInitializedCursor(int type);
+ // Adds |host| to the set |hosts_|.
+ void AddHost(aura::WindowTreeHost* host);
+
+ // Removes |host| from the set |hosts_|.
+ void RemoveHost(aura::WindowTreeHost* host);
+
private:
- // Overridden from views::corewm::NativeCursorManager:
+ // Overridden from wm::NativeCursorManager:
virtual void SetDisplay(
const gfx::Display& display,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE;
virtual void SetCursor(
gfx::NativeCursor cursor,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE;
virtual void SetVisibility(
bool visible,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE;
virtual void SetCursorSet(
ui::CursorSetType cursor_set,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
- virtual void SetScale(
- float scale,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE;
virtual void SetMouseEventsEnabled(
bool enabled,
- views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+ wm::NativeCursorManagerDelegate* delegate) OVERRIDE;
+
+ // The set of hosts to notify of changes in cursor state.
+ typedef std::set<aura::WindowTreeHost*> Hosts;
+ Hosts hosts_;
- aura::RootWindow* root_window_;
scoped_ptr<DesktopCursorLoaderUpdater> cursor_loader_updater_;
scoped_ptr<ui::CursorLoader> cursor_loader_;
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 6ae83df66bb..e461fd9e7f2 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
@@ -6,18 +6,16 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
-#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/aura/window_property.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/display.h"
@@ -25,29 +23,20 @@
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/views/corewm/corewm_switches.h"
-#include "ui/views/corewm/cursor_manager.h"
-#include "ui/views/corewm/focus_controller.h"
-#include "ui/views/corewm/input_method_event_filter.h"
-#include "ui/views/corewm/native_cursor_manager.h"
-#include "ui/views/corewm/shadow_controller.h"
-#include "ui/views/corewm/shadow_types.h"
#include "ui/views/corewm/tooltip.h"
#include "ui/views/corewm/tooltip_controller.h"
-#include "ui/views/corewm/visibility_controller.h"
-#include "ui/views/corewm/window_modality_controller.h"
#include "ui/views/drag_utils.h"
-#include "ui/views/ime/input_method.h"
#include "ui/views/ime/input_method_bridge.h"
+#include "ui/views/ime/null_input_method.h"
+#include "ui/views/view_constants_aura.h"
#include "ui/views/widget/desktop_aura/desktop_capture_client.h"
#include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
#include "ui/views/widget/desktop_aura/desktop_event_client.h"
#include "ui/views/widget/desktop_aura/desktop_focus_rules.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/native_widget_aura.h"
#include "ui/views/widget/root_view.h"
@@ -56,8 +45,21 @@
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/window_reorderer.h"
+#include "ui/views/window/native_frame_view.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/cursor_manager.h"
+#include "ui/wm/core/focus_controller.h"
+#include "ui/wm/core/input_method_event_filter.h"
+#include "ui/wm/core/native_cursor_manager.h"
+#include "ui/wm/core/shadow_controller.h"
+#include "ui/wm/core/shadow_types.h"
+#include "ui/wm/core/visibility_controller.h"
+#include "ui/wm/core/window_modality_controller.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/drag_drop_client.h"
#if defined(OS_WIN)
+#include "ui/base/win/shell.h"
#include "ui/gfx/win/dpi.h"
#endif
@@ -79,7 +81,8 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
// becomes the parent of the child window passed in.
static aura::Window* CreateParentWindow(aura::Window* child_window,
const gfx::Rect& bounds,
- bool full_screen) {
+ bool full_screen,
+ bool root_is_always_on_top) {
// This instance will get deleted when the widget is destroyed.
DesktopNativeWidgetTopLevelHandler* top_level_handler =
new DesktopNativeWidgetTopLevelHandler;
@@ -91,8 +94,12 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
Widget::InitParams::TYPE_POPUP;
init_params.bounds = bounds;
init_params.ownership = Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
- init_params.layer_type = ui::LAYER_NOT_DRAWN;
- init_params.can_activate = full_screen;
+ init_params.layer_type = aura::WINDOW_LAYER_NOT_DRAWN;
+ init_params.activatable = full_screen ?
+ Widget::InitParams::ACTIVATABLE_YES :
+ Widget::InitParams::ACTIVATABLE_NO;
+ init_params.keep_on_top = root_is_always_on_top;
+
// This widget instance will get deleted when the window is
// destroyed.
top_level_handler->top_level_widget_ = new Widget();
@@ -171,10 +178,17 @@ class DesktopNativeWidgetAuraWindowTreeClient :
const gfx::Rect& bounds) OVERRIDE {
bool is_fullscreen = window->GetProperty(aura::client::kShowStateKey) ==
ui::SHOW_STATE_FULLSCREEN;
- bool is_menu = window->type() == aura::client::WINDOW_TYPE_MENU;
+ bool is_menu = window->type() == ui::wm::WINDOW_TYPE_MENU;
+
if (is_fullscreen || is_menu) {
+ bool root_is_always_on_top = false;
+ internal::NativeWidgetPrivate* native_widget =
+ DesktopNativeWidgetAura::ForWindow(root_window_);
+ if (native_widget)
+ root_is_always_on_top = native_widget->IsAlwaysOnTop();
+
return DesktopNativeWidgetTopLevelHandler::CreateParentWindow(
- window, bounds, is_fullscreen);
+ window, bounds, is_fullscreen, root_is_always_on_top);
}
return root_window_;
}
@@ -207,15 +221,38 @@ class FocusManagerEventHandler : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(FocusManagerEventHandler);
};
+class RootWindowDestructionObserver : public aura::WindowObserver {
+ public:
+ explicit RootWindowDestructionObserver(DesktopNativeWidgetAura* parent)
+ : parent_(parent) {}
+ virtual ~RootWindowDestructionObserver() {}
+
+ private:
+ // Overridden from aura::WindowObserver:
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
+ parent_->RootWindowDestroyed();
+ window->RemoveObserver(this);
+ delete this;
+ }
+
+ DesktopNativeWidgetAura* parent_;
+
+ DISALLOW_COPY_AND_ASSIGN(RootWindowDestructionObserver);
+};
+
////////////////////////////////////////////////////////////////////////////////
// DesktopNativeWidgetAura, public:
+int DesktopNativeWidgetAura::cursor_reference_count_ = 0;
+DesktopNativeCursorManager* DesktopNativeWidgetAura::native_cursor_manager_ =
+ NULL;
+wm::CursorManager* DesktopNativeWidgetAura::cursor_manager_ = NULL;
+
DesktopNativeWidgetAura::DesktopNativeWidgetAura(
internal::NativeWidgetDelegate* delegate)
- : ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
+ : desktop_window_tree_host_(NULL),
+ ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
close_widget_factory_(this),
- can_activate_(true),
- desktop_root_window_host_(NULL),
content_window_container_(NULL),
content_window_(new aura::Window(this)),
native_widget_delegate_(delegate),
@@ -223,7 +260,6 @@ DesktopNativeWidgetAura::DesktopNativeWidgetAura(
restore_focus_on_activate_(false),
cursor_(gfx::kNullCursor),
widget_type_(Widget::InitParams::TYPE_WINDOW) {
- content_window_->SetProperty(kDesktopNativeWidgetAuraKey, this);
aura::client::SetFocusChangeObserver(content_window_, this);
aura::client::SetActivationChangeObserver(content_window_, this);
}
@@ -243,48 +279,50 @@ DesktopNativeWidgetAura* DesktopNativeWidgetAura::ForWindow(
void DesktopNativeWidgetAura::OnHostClosed() {
// Don't invoke Widget::OnNativeWidgetDestroying(), its done by
- // DesktopRootWindowHost.
+ // DesktopWindowTreeHost.
// The WindowModalityController is at the front of the event pretarget
// handler list. We destroy it first to preserve order symantics.
if (window_modality_controller_)
window_modality_controller_.reset();
- // Make sure we don't have capture. Otherwise CaptureController and RootWindow
- // are left referencing a deleted Window.
+ // Make sure we don't have capture. Otherwise CaptureController and
+ // WindowEventDispatcher are left referencing a deleted Window.
{
aura::Window* capture_window = capture_client_->GetCaptureWindow();
- if (capture_window && root_window_->window()->Contains(capture_window))
+ if (capture_window && host_->window()->Contains(capture_window))
capture_window->ReleaseCapture();
}
- // DesktopRootWindowHost owns the ActivationController which ShadowController
+ // DesktopWindowTreeHost owns the ActivationController which ShadowController
// references. Make sure we destroy ShadowController early on.
shadow_controller_.reset();
tooltip_manager_.reset();
- root_window_->window()->RemovePreTargetHandler(tooltip_controller_.get());
- aura::client::SetTooltipClient(root_window_->window(), NULL);
- tooltip_controller_.reset();
+ if (tooltip_controller_.get()) {
+ host_->window()->RemovePreTargetHandler(tooltip_controller_.get());
+ aura::client::SetTooltipClient(host_->window(), NULL);
+ tooltip_controller_.reset();
+ }
root_window_event_filter_->RemoveHandler(input_method_event_filter_.get());
- window_tree_client_.reset(); // Uses root_window_ at destruction.
+ window_tree_client_.reset(); // Uses host_->dispatcher() at destruction.
- capture_client_.reset(); // Uses root_window_ at destruction.
+ capture_client_.reset(); // Uses host_->dispatcher() at destruction.
// FocusController uses |content_window_|. Destroy it now so that we don't
// have to worry about the possibility of FocusController attempting to use
// |content_window_| after it's been destroyed but before all child windows
// have been destroyed.
- root_window_->window()->RemovePreTargetHandler(focus_client_.get());
- aura::client::SetFocusClient(root_window_->window(), NULL);
- aura::client::SetActivationClient(root_window_->window(), NULL);
+ host_->window()->RemovePreTargetHandler(focus_client_.get());
+ aura::client::SetFocusClient(host_->window(), NULL);
+ aura::client::SetActivationClient(host_->window(), NULL);
focus_client_.reset();
- root_window_->RemoveRootWindowObserver(this);
- root_window_.reset(); // Uses input_method_event_filter_ at destruction.
- // RootWindow owns |desktop_root_window_host_|.
- desktop_root_window_host_ = NULL;
+ host_->RemoveObserver(this);
+ host_.reset(); // Uses input_method_event_filter_ at destruction.
+ // WindowEventDispatcher owns |desktop_window_tree_host_|.
+ desktop_window_tree_host_ = NULL;
content_window_ = NULL;
native_widget_delegate_->OnNativeWidgetDestroyed();
@@ -292,30 +330,36 @@ void DesktopNativeWidgetAura::OnHostClosed() {
delete this;
}
-void DesktopNativeWidgetAura::OnDesktopRootWindowHostDestroyed(
- aura::RootWindow* root) {
- // |root_window_| is still valid, but DesktopRootWindowHost is nearly
- // destroyed. Do cleanup here of members DesktopRootWindowHost may also use.
- aura::client::SetDispatcherClient(root->window(), NULL);
+void DesktopNativeWidgetAura::OnDesktopWindowTreeHostDestroyed(
+ aura::WindowTreeHost* host) {
+ // |dispatcher_| is still valid, but DesktopWindowTreeHost is nearly
+ // destroyed. Do cleanup here of members DesktopWindowTreeHost may also use.
+ aura::client::SetDispatcherClient(host->window(), NULL);
dispatcher_client_.reset();
- aura::client::SetCursorClient(root->window(), NULL);
- cursor_client_.reset();
+ // We explicitly do NOT clear the cursor client property. Since the cursor
+ // manager is a singleton, it can outlive any window hierarchy, and it's
+ // important that objects attached to this destroying window hierarchy have
+ // an opportunity to deregister their observers from the cursor manager.
+ // They may want to do this when they are notified that they're being
+ // removed from the window hierarchy, which happens soon after this
+ // function when DesktopWindowTreeHost* calls DestroyDispatcher().
+ native_cursor_manager_->RemoveHost(host);
- aura::client::SetScreenPositionClient(root->window(), NULL);
+ aura::client::SetScreenPositionClient(host->window(), NULL);
position_client_.reset();
- aura::client::SetDragDropClient(root->window(), NULL);
+ aura::client::SetDragDropClient(host->window(), NULL);
drag_drop_client_.reset();
- aura::client::SetEventClient(root->window(), NULL);
+ aura::client::SetEventClient(host->window(), NULL);
event_client_.reset();
}
void DesktopNativeWidgetAura::HandleActivationChanged(bool active) {
native_widget_delegate_->OnNativeWidgetActivationChanged(active);
aura::client::ActivationClient* activation_client =
- aura::client::GetActivationClient(root_window_->window());
+ aura::client::GetActivationClient(host_->window());
if (!activation_client)
return;
if (active) {
@@ -361,142 +405,155 @@ void DesktopNativeWidgetAura::InitNativeWidget(
}
content_window_->SetType(GetAuraWindowTypeForWidgetType(params.type));
content_window_->Init(params.layer_type);
- corewm::SetShadowType(content_window_, corewm::SHADOW_TYPE_NONE);
+ wm::SetShadowType(content_window_, wm::SHADOW_TYPE_NONE);
content_window_container_ = new aura::Window(NULL);
- content_window_container_->Init(ui::LAYER_NOT_DRAWN);
+ content_window_container_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
content_window_container_->Show();
content_window_container_->AddChild(content_window_);
- desktop_root_window_host_ = params.desktop_root_window_host ?
- params.desktop_root_window_host :
- DesktopRootWindowHost::Create(native_widget_delegate_, this);
- aura::RootWindow::CreateParams rw_params(params.bounds);
- desktop_root_window_host_->Init(content_window_, params, &rw_params);
+ desktop_window_tree_host_ = params.desktop_window_tree_host ?
+ params.desktop_window_tree_host :
+ DesktopWindowTreeHost::Create(native_widget_delegate_, this);
+ host_.reset(desktop_window_tree_host_->AsWindowTreeHost());
+ desktop_window_tree_host_->Init(content_window_, params);
+
+ // Mark this window as Desktop root window.
+ host_->window()->SetProperty(views::kDesktopRootWindow, true);
+
+ host_->InitHost();
+ host_->window()->AddChild(content_window_container_);
+ host_->window()->SetProperty(kDesktopNativeWidgetAuraKey, this);
- root_window_.reset(new aura::RootWindow(rw_params));
- root_window_->Init();
- root_window_->window()->AddChild(content_window_container_);
+ host_->window()->AddObserver(new RootWindowDestructionObserver(this));
// The WindowsModalityController event filter should be at the head of the
// pre target handlers list. This ensures that it handles input events first
// when modal windows are at the top of the Zorder.
if (widget_type_ == Widget::InitParams::TYPE_WINDOW)
window_modality_controller_.reset(
- new views::corewm::WindowModalityController(root_window_->window()));
+ new wm::WindowModalityController(host_->window()));
// |root_window_event_filter_| must be created before
- // OnRootWindowHostCreated() is invoked.
+ // OnWindowTreeHostCreated() is invoked.
// CEF sets focus to the window the user clicks down on.
// TODO(beng): see if we can't do this some other way. CEF seems a heavy-
// handed way of accomplishing focus.
- // No event filter for aura::Env. Create CompoundEvnetFilter per RootWindow.
- root_window_event_filter_ = new corewm::CompoundEventFilter;
- // Pass ownership of the filter to the root_window.
- root_window_->window()->SetEventFilter(root_window_event_filter_);
+ // No event filter for aura::Env. Create CompoundEventFilter per
+ // WindowEventDispatcher.
+ root_window_event_filter_.reset(new wm::CompoundEventFilter);
+ host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
+
+ // The host's dispatcher must be added to |native_cursor_manager_| before
+ // OnNativeWidgetCreated() is called.
+ cursor_reference_count_++;
+ if (!native_cursor_manager_) {
+ native_cursor_manager_ = new DesktopNativeCursorManager(
+ DesktopCursorLoaderUpdater::Create());
+ }
+ if (!cursor_manager_) {
+ cursor_manager_ = new wm::CursorManager(
+ scoped_ptr<wm::NativeCursorManager>(native_cursor_manager_));
+ }
+ native_cursor_manager_->AddHost(host());
+ aura::client::SetCursorClient(host_->window(), cursor_manager_);
- desktop_root_window_host_->OnRootWindowCreated(root_window_.get(), params);
+ desktop_window_tree_host_->OnNativeWidgetCreated(params);
UpdateWindowTransparency();
- capture_client_.reset(new DesktopCaptureClient(root_window_->window()));
+ capture_client_.reset(new DesktopCaptureClient(host_->window()));
- corewm::FocusController* focus_controller =
- new corewm::FocusController(new DesktopFocusRules(content_window_));
+ wm::FocusController* focus_controller =
+ new wm::FocusController(new DesktopFocusRules(content_window_));
focus_client_.reset(focus_controller);
- aura::client::SetFocusClient(root_window_->window(), focus_controller);
- aura::client::SetActivationClient(root_window_->window(), focus_controller);
- root_window_->window()->AddPreTargetHandler(focus_controller);
+ aura::client::SetFocusClient(host_->window(), focus_controller);
+ aura::client::SetActivationClient(host_->window(), focus_controller);
+ host_->window()->AddPreTargetHandler(focus_controller);
dispatcher_client_.reset(new DesktopDispatcherClient);
- aura::client::SetDispatcherClient(root_window_->window(),
+ aura::client::SetDispatcherClient(host_->window(),
dispatcher_client_.get());
- DesktopNativeCursorManager* desktop_native_cursor_manager =
- new views::DesktopNativeCursorManager(
- root_window_.get(),
- DesktopCursorLoaderUpdater::Create());
- cursor_client_.reset(
- new views::corewm::CursorManager(
- scoped_ptr<corewm::NativeCursorManager>(
- desktop_native_cursor_manager)));
- aura::client::SetCursorClient(root_window_->window(), cursor_client_.get());
-
- position_client_.reset(new DesktopScreenPositionClient());
- aura::client::SetScreenPositionClient(root_window_->window(),
- position_client_.get());
+ position_client_.reset(new DesktopScreenPositionClient(host_->window()));
InstallInputMethodEventFilter();
- drag_drop_client_ = desktop_root_window_host_->CreateDragDropClient(
- desktop_native_cursor_manager);
- aura::client::SetDragDropClient(root_window_->window(),
+ drag_drop_client_ = desktop_window_tree_host_->CreateDragDropClient(
+ native_cursor_manager_);
+ aura::client::SetDragDropClient(host_->window(),
drag_drop_client_.get());
static_cast<aura::client::FocusClient*>(focus_client_.get())->
FocusWindow(content_window_);
- OnRootWindowHostResized(root_window_.get());
+ OnHostResized(host());
- root_window_->AddRootWindowObserver(this);
+ host_->AddObserver(this);
window_tree_client_.reset(
- new DesktopNativeWidgetAuraWindowTreeClient(root_window_->window()));
- drop_helper_.reset(new DropHelper(
- static_cast<internal::RootView*>(GetWidget()->GetRootView())));
+ new DesktopNativeWidgetAuraWindowTreeClient(host_->window()));
+ drop_helper_.reset(new DropHelper(GetWidget()->GetRootView()));
aura::client::SetDragDropDelegate(content_window_, this);
- tooltip_manager_.reset(new TooltipManagerAura(GetWidget()));
-
- tooltip_controller_.reset(
- new corewm::TooltipController(
- desktop_root_window_host_->CreateTooltip()));
- aura::client::SetTooltipClient(root_window_->window(),
- tooltip_controller_.get());
- root_window_->window()->AddPreTargetHandler(tooltip_controller_.get());
+ if (params.type != Widget::InitParams::TYPE_TOOLTIP) {
+ tooltip_manager_.reset(new TooltipManagerAura(GetWidget()));
+ tooltip_controller_.reset(
+ new corewm::TooltipController(
+ desktop_window_tree_host_->CreateTooltip()));
+ aura::client::SetTooltipClient(host_->window(),
+ tooltip_controller_.get());
+ host_->window()->AddPreTargetHandler(tooltip_controller_.get());
+ }
if (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW) {
- visibility_controller_.reset(new views::corewm::VisibilityController);
- aura::client::SetVisibilityClient(root_window_->window(),
+ visibility_controller_.reset(new wm::VisibilityController);
+ aura::client::SetVisibilityClient(host_->window(),
visibility_controller_.get());
- views::corewm::SetChildWindowVisibilityChangesAnimated(
- root_window_->window());
- views::corewm::SetChildWindowVisibilityChangesAnimated(
+ wm::SetChildWindowVisibilityChangesAnimated(host_->window());
+ wm::SetChildWindowVisibilityChangesAnimated(
content_window_container_);
}
if (params.type == Widget::InitParams::TYPE_WINDOW) {
focus_manager_event_handler_.reset(new FocusManagerEventHandler(this));
- root_window_->window()->AddPreTargetHandler(
- focus_manager_event_handler_.get());
+ host_->window()->AddPreTargetHandler(focus_manager_event_handler_.get());
}
event_client_.reset(new DesktopEventClient);
- aura::client::SetEventClient(root_window_->window(), event_client_.get());
+ aura::client::SetEventClient(host_->window(), event_client_.get());
aura::client::GetFocusClient(content_window_)->FocusWindow(content_window_);
aura::client::SetActivationDelegate(content_window_, this);
- shadow_controller_.reset(
- new corewm::ShadowController(
- aura::client::GetActivationClient(root_window_->window())));
+ shadow_controller_.reset(new wm::ShadowController(
+ aura::client::GetActivationClient(host_->window())));
+
+ content_window_->SetProperty(aura::client::kCanMaximizeKey,
+ GetWidget()->widget_delegate()->CanMaximize());
+ content_window_->SetProperty(aura::client::kCanResizeKey,
+ GetWidget()->widget_delegate()->CanResize());
window_reorderer_.reset(new WindowReorderer(content_window_,
GetWidget()->GetRootView()));
}
NonClientFrameView* DesktopNativeWidgetAura::CreateNonClientFrameView() {
- return desktop_root_window_host_->CreateNonClientFrameView();
+ return ShouldUseNativeFrame() ? new NativeFrameView(GetWidget()) : NULL;
}
bool DesktopNativeWidgetAura::ShouldUseNativeFrame() const {
- return desktop_root_window_host_->ShouldUseNativeFrame();
+ return desktop_window_tree_host_->ShouldUseNativeFrame();
+}
+
+bool DesktopNativeWidgetAura::ShouldWindowContentsBeTransparent() const {
+ return desktop_window_tree_host_->ShouldWindowContentsBeTransparent();
}
void DesktopNativeWidgetAura::FrameTypeChanged() {
- desktop_root_window_host_->FrameTypeChanged();
+ desktop_window_tree_host_->FrameTypeChanged();
UpdateWindowTransparency();
}
@@ -538,6 +595,8 @@ void DesktopNativeWidgetAura::ReorderNativeViews() {
}
void DesktopNativeWidgetAura::ViewRemoved(View* view) {
+ DCHECK(drop_helper_.get() != NULL);
+ drop_helper_->ResetTargetViewIfEquals(view);
}
void DesktopNativeWidgetAura::SetNativeWindowProperty(const char* name,
@@ -571,10 +630,13 @@ void DesktopNativeWidgetAura::ReleaseCapture() {
bool DesktopNativeWidgetAura::HasCapture() const {
return content_window_ && content_window_->HasCapture() &&
- desktop_root_window_host_->HasCapture();
+ desktop_window_tree_host_->HasCapture();
}
InputMethod* DesktopNativeWidgetAura::CreateInputMethod() {
+ if (switches::IsTextInputFocusManagerEnabled())
+ return new NullInputMethod();
+
ui::InputMethod* host = input_method_event_filter_->input_method();
return new InputMethodBridge(this, host, false);
}
@@ -584,50 +646,54 @@ internal::InputMethodDelegate*
return this;
}
+ui::InputMethod* DesktopNativeWidgetAura::GetHostInputMethod() {
+ return input_method_event_filter_->input_method();
+}
+
void DesktopNativeWidgetAura::CenterWindow(const gfx::Size& size) {
if (content_window_)
- desktop_root_window_host_->CenterWindow(size);
+ desktop_window_tree_host_->CenterWindow(size);
}
void DesktopNativeWidgetAura::GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* maximized) const {
if (content_window_)
- desktop_root_window_host_->GetWindowPlacement(bounds, maximized);
+ desktop_window_tree_host_->GetWindowPlacement(bounds, maximized);
}
-bool DesktopNativeWidgetAura::SetWindowTitle(const string16& title) {
+bool DesktopNativeWidgetAura::SetWindowTitle(const base::string16& title) {
if (!content_window_)
return false;
- return desktop_root_window_host_->SetWindowTitle(title);
+ return desktop_window_tree_host_->SetWindowTitle(title);
}
void DesktopNativeWidgetAura::SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) {
if (content_window_)
- desktop_root_window_host_->SetWindowIcons(window_icon, app_icon);
+ desktop_window_tree_host_->SetWindowIcons(window_icon, app_icon);
}
void DesktopNativeWidgetAura::InitModalType(ui::ModalType modal_type) {
// 99% of the time, we should not be asked to create a
// DesktopNativeWidgetAura that is modal. We only support window modal
// dialogs on the same lines as non AURA.
- desktop_root_window_host_->InitModalType(modal_type);
+ desktop_window_tree_host_->InitModalType(modal_type);
}
gfx::Rect DesktopNativeWidgetAura::GetWindowBoundsInScreen() const {
return content_window_ ?
- desktop_root_window_host_->GetWindowBoundsInScreen() : gfx::Rect();
+ desktop_window_tree_host_->GetWindowBoundsInScreen() : gfx::Rect();
}
gfx::Rect DesktopNativeWidgetAura::GetClientAreaBoundsInScreen() const {
return content_window_ ?
- desktop_root_window_host_->GetClientAreaBoundsInScreen() : gfx::Rect();
+ desktop_window_tree_host_->GetClientAreaBoundsInScreen() : gfx::Rect();
}
gfx::Rect DesktopNativeWidgetAura::GetRestoredBounds() const {
return content_window_ ?
- desktop_root_window_host_->GetRestoredBounds() : gfx::Rect();
+ desktop_window_tree_host_->GetRestoredBounds() : gfx::Rect();
}
void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
@@ -636,9 +702,9 @@ void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
// TODO(ananta)
// This code by default scales the bounds rectangle by 1.
// We could probably get rid of this and similar logic from
- // the DesktopNativeWidgetAura::OnRootWindowHostResized function.
+ // the DesktopNativeWidgetAura::OnWindowTreeHostResized function.
float scale = 1;
- aura::Window* root = root_window_->window();
+ aura::Window* root = host_->window();
if (root) {
scale = gfx::Screen::GetScreenFor(root)->
GetDisplayNearestWindow(root).device_scale_factor();
@@ -646,12 +712,12 @@ void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
gfx::Rect bounds_in_pixels(
gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)),
gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale)));
- desktop_root_window_host_->AsRootWindowHost()->SetBounds(bounds_in_pixels);
+ desktop_window_tree_host_->AsWindowTreeHost()->SetBounds(bounds_in_pixels);
}
void DesktopNativeWidgetAura::SetSize(const gfx::Size& size) {
if (content_window_)
- desktop_root_window_host_->SetSize(size);
+ desktop_window_tree_host_->SetSize(size);
}
void DesktopNativeWidgetAura::StackAbove(gfx::NativeView native_view) {
@@ -659,7 +725,7 @@ void DesktopNativeWidgetAura::StackAbove(gfx::NativeView native_view) {
void DesktopNativeWidgetAura::StackAtTop() {
if (content_window_)
- desktop_root_window_host_->StackAtTop();
+ desktop_window_tree_host_->StackAtTop();
}
void DesktopNativeWidgetAura::StackBelow(gfx::NativeView native_view) {
@@ -667,7 +733,7 @@ void DesktopNativeWidgetAura::StackBelow(gfx::NativeView native_view) {
void DesktopNativeWidgetAura::SetShape(gfx::NativeRegion shape) {
if (content_window_)
- desktop_root_window_host_->SetShape(shape);
+ desktop_window_tree_host_->SetShape(shape);
}
void DesktopNativeWidgetAura::Close() {
@@ -677,25 +743,25 @@ void DesktopNativeWidgetAura::Close() {
content_window_->SuppressPaint();
content_window_->Hide();
- desktop_root_window_host_->Close();
+ desktop_window_tree_host_->Close();
}
void DesktopNativeWidgetAura::CloseNow() {
if (content_window_)
- desktop_root_window_host_->CloseNow();
+ desktop_window_tree_host_->CloseNow();
}
void DesktopNativeWidgetAura::Show() {
if (!content_window_)
return;
- desktop_root_window_host_->AsRootWindowHost()->Show();
+ desktop_window_tree_host_->AsWindowTreeHost()->Show();
content_window_->Show();
}
void DesktopNativeWidgetAura::Hide() {
if (!content_window_)
return;
- desktop_root_window_host_->AsRootWindowHost()->Hide();
+ desktop_window_tree_host_->AsWindowTreeHost()->Hide();
content_window_->Hide();
}
@@ -703,79 +769,84 @@ void DesktopNativeWidgetAura::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
if (!content_window_)
return;
- desktop_root_window_host_->ShowMaximizedWithBounds(restored_bounds);
+ desktop_window_tree_host_->ShowMaximizedWithBounds(restored_bounds);
content_window_->Show();
}
void DesktopNativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
if (!content_window_)
return;
- desktop_root_window_host_->ShowWindowWithState(state);
+ desktop_window_tree_host_->ShowWindowWithState(state);
content_window_->Show();
}
bool DesktopNativeWidgetAura::IsVisible() const {
- return content_window_ && desktop_root_window_host_->IsVisible();
+ return content_window_ && desktop_window_tree_host_->IsVisible();
}
void DesktopNativeWidgetAura::Activate() {
if (content_window_)
- desktop_root_window_host_->Activate();
+ desktop_window_tree_host_->Activate();
}
void DesktopNativeWidgetAura::Deactivate() {
if (content_window_)
- desktop_root_window_host_->Deactivate();
+ desktop_window_tree_host_->Deactivate();
}
bool DesktopNativeWidgetAura::IsActive() const {
- return content_window_ && desktop_root_window_host_->IsActive();
+ return content_window_ && desktop_window_tree_host_->IsActive();
}
void DesktopNativeWidgetAura::SetAlwaysOnTop(bool always_on_top) {
if (content_window_)
- desktop_root_window_host_->SetAlwaysOnTop(always_on_top);
+ desktop_window_tree_host_->SetAlwaysOnTop(always_on_top);
}
bool DesktopNativeWidgetAura::IsAlwaysOnTop() const {
- return content_window_ && desktop_root_window_host_->IsAlwaysOnTop();
+ return content_window_ && desktop_window_tree_host_->IsAlwaysOnTop();
+}
+
+void DesktopNativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
+ if (content_window_)
+ desktop_window_tree_host_->SetVisibleOnAllWorkspaces(always_visible);
}
void DesktopNativeWidgetAura::Maximize() {
if (content_window_)
- desktop_root_window_host_->Maximize();
+ desktop_window_tree_host_->Maximize();
}
void DesktopNativeWidgetAura::Minimize() {
if (content_window_)
- desktop_root_window_host_->Minimize();
+ desktop_window_tree_host_->Minimize();
}
bool DesktopNativeWidgetAura::IsMaximized() const {
- return content_window_ && desktop_root_window_host_->IsMaximized();
+ return content_window_ && desktop_window_tree_host_->IsMaximized();
}
bool DesktopNativeWidgetAura::IsMinimized() const {
- return content_window_ && desktop_root_window_host_->IsMinimized();
+ return content_window_ && desktop_window_tree_host_->IsMinimized();
}
void DesktopNativeWidgetAura::Restore() {
if (content_window_)
- desktop_root_window_host_->Restore();
+ desktop_window_tree_host_->Restore();
}
void DesktopNativeWidgetAura::SetFullscreen(bool fullscreen) {
if (content_window_)
- desktop_root_window_host_->SetFullscreen(fullscreen);
+ desktop_window_tree_host_->SetFullscreen(fullscreen);
}
bool DesktopNativeWidgetAura::IsFullscreen() const {
- return content_window_ && desktop_root_window_host_->IsFullscreen();
+ return content_window_ && desktop_window_tree_host_->IsFullscreen();
}
void DesktopNativeWidgetAura::SetOpacity(unsigned char opacity) {
if (content_window_)
- desktop_root_window_host_->SetOpacity(opacity);
+ desktop_window_tree_host_->SetOpacity(opacity);
}
void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
@@ -783,7 +854,7 @@ void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) {
if (content_window_)
- desktop_root_window_host_->FlashFrame(flash_frame);
+ desktop_window_tree_host_->FlashFrame(flash_frame);
}
void DesktopNativeWidgetAura::RunShellDrag(
@@ -803,7 +874,7 @@ void DesktopNativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) {
void DesktopNativeWidgetAura::SetCursor(gfx::NativeCursor cursor) {
cursor_ = cursor;
aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window_->window());
+ aura::client::GetCursorClient(host_->window());
if (cursor_client)
cursor_client->SetCursor(cursor);
}
@@ -812,12 +883,12 @@ bool DesktopNativeWidgetAura::IsMouseEventsEnabled() const {
if (!content_window_)
return false;
aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window_->window());
+ aura::client::GetCursorClient(host_->window());
return cursor_client ? cursor_client->IsMouseEventsEnabled() : true;
}
void DesktopNativeWidgetAura::ClearNativeFocus() {
- desktop_root_window_host_->ClearNativeFocus();
+ desktop_window_tree_host_->ClearNativeFocus();
if (ShouldActivate()) {
aura::client::GetFocusClient(content_window_)->
@@ -826,8 +897,8 @@ void DesktopNativeWidgetAura::ClearNativeFocus() {
}
gfx::Rect DesktopNativeWidgetAura::GetWorkAreaBoundsInScreen() const {
- return desktop_root_window_host_ ?
- desktop_root_window_host_->GetWorkAreaBoundsInScreen() : gfx::Rect();
+ return desktop_window_tree_host_ ?
+ desktop_window_tree_host_->GetWorkAreaBoundsInScreen() : gfx::Rect();
}
Widget::MoveLoopResult DesktopNativeWidgetAura::RunMoveLoop(
@@ -836,28 +907,37 @@ Widget::MoveLoopResult DesktopNativeWidgetAura::RunMoveLoop(
Widget::MoveLoopEscapeBehavior escape_behavior) {
if (!content_window_)
return Widget::MOVE_LOOP_CANCELED;
- return desktop_root_window_host_->RunMoveLoop(drag_offset, source,
+ return desktop_window_tree_host_->RunMoveLoop(drag_offset, source,
escape_behavior);
}
void DesktopNativeWidgetAura::EndMoveLoop() {
if (content_window_)
- desktop_root_window_host_->EndMoveLoop();
+ desktop_window_tree_host_->EndMoveLoop();
}
void DesktopNativeWidgetAura::SetVisibilityChangedAnimationsEnabled(
bool value) {
if (content_window_)
- desktop_root_window_host_->SetVisibilityChangedAnimationsEnabled(value);
+ desktop_window_tree_host_->SetVisibilityChangedAnimationsEnabled(value);
}
ui::NativeTheme* DesktopNativeWidgetAura::GetNativeTheme() const {
- return DesktopRootWindowHost::GetNativeTheme(content_window_);
+ return DesktopWindowTreeHost::GetNativeTheme(content_window_);
}
void DesktopNativeWidgetAura::OnRootViewLayout() const {
if (content_window_)
- desktop_root_window_host_->OnRootViewLayout();
+ desktop_window_tree_host_->OnRootViewLayout();
+}
+
+bool DesktopNativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+ return content_window_ &&
+ desktop_window_tree_host_->IsTranslucentWindowOpacitySupported();
+}
+
+void DesktopNativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
+ OnEvent(native_event);
}
////////////////////////////////////////////////////////////////////////////////
@@ -904,13 +984,13 @@ void DesktopNativeWidgetAura::OnDeviceScaleFactorChanged(
float device_scale_factor) {
}
-void DesktopNativeWidgetAura::OnWindowDestroying() {
+void DesktopNativeWidgetAura::OnWindowDestroying(aura::Window* window) {
// Cleanup happens in OnHostClosed().
}
-void DesktopNativeWidgetAura::OnWindowDestroyed() {
+void DesktopNativeWidgetAura::OnWindowDestroyed(aura::Window* window) {
// Cleanup happens in OnHostClosed(). We own |content_window_| (indirectly by
- // way of |root_window_|) so there should be no need to do any processing
+ // way of |dispatcher_|) so there should be no need to do any processing
// here.
}
@@ -925,9 +1005,6 @@ void DesktopNativeWidgetAura::GetHitTestMask(gfx::Path* mask) const {
native_widget_delegate_->GetHitTestMask(mask);
}
-void DesktopNativeWidgetAura::DidRecreateLayer(ui::Layer* old_layer,
- ui::Layer* new_layer) {}
-
////////////////////////////////////////////////////////////////////////////////
// DesktopNativeWidgetAura, ui::EventHandler implementation:
@@ -978,10 +1055,6 @@ void DesktopNativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) {
}
}
-void DesktopNativeWidgetAura::OnTouchEvent(ui::TouchEvent* event) {
- native_widget_delegate_->OnTouchEvent(event);
-}
-
void DesktopNativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) {
native_widget_delegate_->OnGestureEvent(event);
}
@@ -990,7 +1063,7 @@ void DesktopNativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) {
// DesktopNativeWidgetAura, aura::client::ActivationDelegate implementation:
bool DesktopNativeWidgetAura::ShouldActivate() const {
- return can_activate_ && native_widget_delegate_->CanActivate();
+ return native_widget_delegate_->CanActivate();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1000,10 +1073,6 @@ bool DesktopNativeWidgetAura::ShouldActivate() const {
void DesktopNativeWidgetAura::OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) {
DCHECK(content_window_ == gained_active || content_window_ == lost_active);
- if ((content_window_ == gained_active || content_window_ == lost_active) &&
- IsVisible() && GetWidget()->non_client_view()) {
- GetWidget()->non_client_view()->SchedulePaint();
- }
if (gained_active == content_window_ && restore_focus_on_activate_) {
restore_focus_on_activate_ = false;
GetWidget()->GetFocusManager()->RestoreFocusedView();
@@ -1021,19 +1090,18 @@ void DesktopNativeWidgetAura::OnWindowActivated(aura::Window* gained_active,
void DesktopNativeWidgetAura::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
if (content_window_ == gained_focus) {
- desktop_root_window_host_->OnNativeWidgetFocus();
+ desktop_window_tree_host_->OnNativeWidgetFocus();
native_widget_delegate_->OnNativeFocus(lost_focus);
// If focus is moving from a descendant Window to |content_window_| then
- // native activation hasn't changed. We still need to inform the InputMethod
- // we've been focused though.
+ // native activation hasn't changed. Still, the InputMethod must be informed
+ // of the Window focus change.
InputMethod* input_method = GetWidget()->GetInputMethod();
if (input_method)
input_method->OnFocus();
} else if (content_window_ == lost_focus) {
- desktop_root_window_host_->OnNativeWidgetBlur();
- native_widget_delegate_->OnNativeBlur(
- aura::client::GetFocusClient(content_window_)->GetFocusedWindow());
+ desktop_window_tree_host_->OnNativeWidgetBlur();
+ native_widget_delegate_->OnNativeBlur(gained_focus);
}
}
@@ -1078,22 +1146,21 @@ int DesktopNativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) {
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopNativeWidgetAura, aura::RootWindowObserver implementation:
+// DesktopNativeWidgetAura, aura::WindowTreeHostObserver implementation:
-void DesktopNativeWidgetAura::OnRootWindowHostCloseRequested(
- const aura::RootWindow* root) {
- Close();
+void DesktopNativeWidgetAura::OnHostCloseRequested(
+ const aura::WindowTreeHost* host) {
+ GetWidget()->Close();
}
-void DesktopNativeWidgetAura::OnRootWindowHostResized(
- const aura::RootWindow* root) {
+void DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost* host) {
// Don't update the bounds of the child layers when animating closed. If we
// did it would force a paint, which we don't want. We don't want the paint
// as we can't assume any of the children are valid.
- if (desktop_root_window_host_->IsAnimatingClosed())
+ if (desktop_window_tree_host_->IsAnimatingClosed())
return;
- gfx::Rect new_bounds = gfx::Rect(root->window()->bounds().size());
+ gfx::Rect new_bounds = gfx::Rect(host->window()->bounds().size());
content_window_->SetBounds(new_bounds);
// Can be NULL at start.
if (content_window_container_)
@@ -1101,34 +1168,45 @@ void DesktopNativeWidgetAura::OnRootWindowHostResized(
native_widget_delegate_->OnNativeWidgetSizeChanged(new_bounds.size());
}
-void DesktopNativeWidgetAura::OnRootWindowHostMoved(
- const aura::RootWindow* root,
- const gfx::Point& new_origin) {
- TRACE_EVENT1("views", "DesktopNativeWidgetAura::OnRootWindowHostMoved",
+void DesktopNativeWidgetAura::OnHostMoved(const aura::WindowTreeHost* host,
+ const gfx::Point& new_origin) {
+ TRACE_EVENT1("views", "DesktopNativeWidgetAura::OnHostMoved",
"new_origin", new_origin.ToString());
native_widget_delegate_->OnNativeWidgetMove();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopNativeWidgetAura, NativeWidget implementation:
-
-ui::EventHandler* DesktopNativeWidgetAura::GetEventHandler() {
- return this;
-}
+// DesktopNativeWidgetAura, private:
void DesktopNativeWidgetAura::InstallInputMethodEventFilter() {
DCHECK(!input_method_event_filter_.get());
- input_method_event_filter_.reset(new corewm::InputMethodEventFilter(
- root_window_->host()->GetAcceleratedWidget()));
+ input_method_event_filter_.reset(new wm::InputMethodEventFilter(
+ host_->GetAcceleratedWidget()));
input_method_event_filter_->SetInputMethodPropertyInRootWindow(
- root_window_->window());
+ host_->window());
root_window_event_filter_->AddHandler(input_method_event_filter_.get());
}
void DesktopNativeWidgetAura::UpdateWindowTransparency() {
- content_window_->SetTransparent(ShouldUseNativeFrame());
+ content_window_->SetTransparent(
+ desktop_window_tree_host_->ShouldWindowContentsBeTransparent());
+ // Regardless of transparency or not, this root content window will always
+ // fill its bounds completely, so set this flag to true to avoid an
+ // unecessary clear before update.
+ content_window_->SetFillsBoundsCompletely(true);
+}
+
+void DesktopNativeWidgetAura::RootWindowDestroyed() {
+ cursor_reference_count_--;
+ if (cursor_reference_count_ == 0) {
+ // We are the last DesktopNativeWidgetAura instance, and we are responsible
+ // for cleaning up |cursor_manager_|.
+ delete cursor_manager_;
+ native_cursor_manager_ = NULL;
+ cursor_manager_ = NULL;
+ }
}
} // namespace views
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 639210f3f4f..16a56d951bc 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
@@ -6,18 +6,20 @@
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_NATIVE_WIDGET_AURA_H_
#include "base/memory/weak_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/focus_change_observer.h"
-#include "ui/aura/root_window_observer.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/cursor/cursor.h"
#include "ui/views/ime/input_method_delegate.h"
#include "ui/views/widget/native_widget_private.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
+#include "ui/wm/public/drag_drop_delegate.h"
namespace aura {
-class RootWindow;
+class WindowEventDispatcher;
+class WindowTreeHost;
namespace client {
class DragDropClient;
class FocusClient;
@@ -26,23 +28,25 @@ class WindowTreeClient;
}
}
-namespace views {
-
-namespace corewm {
+namespace wm {
class CompoundEventFilter;
class CursorManager;
class FocusController;
class InputMethodEventFilter;
class ShadowController;
-class TooltipController;
class VisibilityController;
class WindowModalityController;
}
+namespace views {
+namespace corewm {
+class TooltipController;
+}
class DesktopCaptureClient;
class DesktopDispatcherClient;
class DesktopEventClient;
-class DesktopRootWindowHost;
+class DesktopNativeCursorManager;
+class DesktopWindowTreeHost;
class DropHelper;
class FocusManagerEventHandler;
class TooltipManagerAura;
@@ -56,31 +60,34 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
public aura::client::FocusChangeObserver,
public views::internal::InputMethodDelegate,
public aura::client::DragDropDelegate,
- public aura::RootWindowObserver {
+ public aura::WindowTreeHostObserver {
public:
explicit DesktopNativeWidgetAura(internal::NativeWidgetDelegate* delegate);
virtual ~DesktopNativeWidgetAura();
- // Maps from window to DesktopNativeWidgetAura.
+ // Maps from window to DesktopNativeWidgetAura. |window| must be a root
+ // window.
static DesktopNativeWidgetAura* ForWindow(aura::Window* window);
- // Called by our DesktopRootWindowHost after it has deleted native resources;
+ // Called by our DesktopWindowTreeHost after it has deleted native resources;
// this is the signal that we should start our shutdown.
virtual void OnHostClosed();
- // Called from ~DesktopRootWindowHost. This takes the RootWindow as by the
- // time we get here |root_window_| is NULL.
- virtual void OnDesktopRootWindowHostDestroyed(aura::RootWindow* root);
+ // TODO(beng): remove this method and replace with an implementation of
+ // WindowDestroying() that takes the window being destroyed.
+ // Called from ~DesktopWindowTreeHost. This takes the WindowEventDispatcher
+ // as by the time we get here |dispatcher_| is NULL.
+ virtual void OnDesktopWindowTreeHostDestroyed(aura::WindowTreeHost* host);
- corewm::InputMethodEventFilter* input_method_event_filter() {
+ wm::InputMethodEventFilter* input_method_event_filter() {
return input_method_event_filter_.get();
}
- corewm::CompoundEventFilter* root_window_event_filter() {
- return root_window_event_filter_;
+ wm::CompoundEventFilter* root_window_event_filter() {
+ return root_window_event_filter_.get();
+ }
+ aura::WindowTreeHost* host() {
+ return host_.get();
}
-
- // Overridden from NativeWidget:
- virtual ui::EventHandler* GetEventHandler() OVERRIDE;
// Ensures that the correct window is activated/deactivated based on whether
// we are being activated/deactivated.
@@ -91,6 +98,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE;
virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
virtual bool ShouldUseNativeFrame() const OVERRIDE;
+ virtual bool ShouldWindowContentsBeTransparent() const OVERRIDE;
virtual void FrameTypeChanged() OVERRIDE;
virtual Widget* GetWidget() OVERRIDE;
virtual const Widget* GetWidget() const OVERRIDE;
@@ -110,11 +118,12 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual bool HasCapture() const OVERRIDE;
virtual InputMethod* CreateInputMethod() OVERRIDE;
virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
+ virtual ui::InputMethod* GetHostInputMethod() OVERRIDE;
virtual void CenterWindow(const gfx::Size& size) OVERRIDE;
virtual void GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* maximized) const OVERRIDE;
- virtual bool SetWindowTitle(const string16& title) OVERRIDE;
+ virtual bool SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) OVERRIDE;
virtual void InitModalType(ui::ModalType modal_type) OVERRIDE;
@@ -140,6 +149,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual bool IsActive() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
virtual bool IsAlwaysOnTop() const OVERRIDE;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) OVERRIDE;
virtual void Maximize() OVERRIDE;
virtual void Minimize() OVERRIDE;
virtual bool IsMaximized() const OVERRIDE;
@@ -168,6 +178,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
+ virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
// Overridden from aura::WindowDelegate:
virtual gfx::Size GetMinimumSize() const OVERRIDE;
@@ -183,19 +195,16 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual void OnCaptureLost() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void OnWindowDestroying() OVERRIDE;
- virtual void OnWindowDestroyed() OVERRIDE;
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual void DidRecreateLayer(ui::Layer* old_layer,
- ui::Layer* new_layer) OVERRIDE;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Overridden from aura::client::ActivationDelegate:
@@ -218,15 +227,15 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
virtual void OnDragExited() OVERRIDE;
virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
- // Overridden from aura::RootWindowObserver:
- virtual void OnRootWindowHostCloseRequested(
- const aura::RootWindow* root) OVERRIDE;
- virtual void OnRootWindowHostResized(const aura::RootWindow* root) OVERRIDE;
- virtual void OnRootWindowHostMoved(const aura::RootWindow* root,
- const gfx::Point& new_origin) OVERRIDE;
+ // Overridden from aura::WindowTreeHostObserver:
+ virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE;
+ virtual void OnHostResized(const aura::WindowTreeHost* host) OVERRIDE;
+ virtual void OnHostMoved(const aura::WindowTreeHost* host,
+ const gfx::Point& new_origin) OVERRIDE;
private:
friend class FocusManagerEventHandler;
+ friend class RootWindowDestructionObserver;
// Installs the input method filter.
void InstallInputMethodEventFilter();
@@ -235,25 +244,20 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
// window is only set as transparent when the glass frame is in use.
void UpdateWindowTransparency();
+ void RootWindowDestroyed();
+
+ scoped_ptr<aura::WindowTreeHost> host_;
+ DesktopWindowTreeHost* desktop_window_tree_host_;
+
// See class documentation for Widget in widget.h for a note about ownership.
Widget::InitParams::Ownership ownership_;
scoped_ptr<DesktopCaptureClient> capture_client_;
- // The NativeWidget owns the RootWindow. Required because the RootWindow owns
- // its RootWindowHost, so DesktopRootWindowHost can't own it.
- scoped_ptr<aura::RootWindow> root_window_;
-
// The following factory is used for calls to close the NativeWidgetAura
// instance.
base::WeakPtrFactory<DesktopNativeWidgetAura> close_widget_factory_;
- // Can we be made active?
- bool can_activate_;
-
- // Ownership passed to RootWindow on Init.
- DesktopRootWindowHost* desktop_root_window_host_;
-
// Child of the root, contains |content_window_|.
aura::Window* content_window_container_;
@@ -264,9 +268,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
internal::NativeWidgetDelegate* native_widget_delegate_;
- scoped_ptr<corewm::FocusController> focus_client_;
+ scoped_ptr<wm::FocusController> focus_client_;
scoped_ptr<DesktopDispatcherClient> dispatcher_client_;
- scoped_ptr<views::corewm::CursorManager> cursor_client_;
scoped_ptr<aura::client::ScreenPositionClient> position_client_;
scoped_ptr<aura::client::DragDropClient> drag_drop_client_;
scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
@@ -274,9 +277,9 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
scoped_ptr<FocusManagerEventHandler> focus_manager_event_handler_;
// Toplevel event filter which dispatches to other event filters.
- corewm::CompoundEventFilter* root_window_event_filter_;
+ scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_;
- scoped_ptr<corewm::InputMethodEventFilter> input_method_event_filter_;
+ scoped_ptr<wm::InputMethodEventFilter> input_method_event_filter_;
scoped_ptr<DropHelper> drop_helper_;
int last_drop_operation_;
@@ -284,17 +287,25 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
scoped_ptr<corewm::TooltipController> tooltip_controller_;
scoped_ptr<TooltipManagerAura> tooltip_manager_;
- scoped_ptr<views::corewm::VisibilityController> visibility_controller_;
+ scoped_ptr<wm::VisibilityController> visibility_controller_;
- scoped_ptr<views::corewm::WindowModalityController>
+ scoped_ptr<wm::WindowModalityController>
window_modality_controller_;
- // See comments in OnLostActive().
bool restore_focus_on_activate_;
gfx::NativeCursor cursor_;
-
- scoped_ptr<corewm::ShadowController> shadow_controller_;
+ // We must manually reference count the number of users of |cursor_manager_|
+ // because the cursors created by |cursor_manager_| are shared among the
+ // DNWAs. We can't just stuff this in a LazyInstance because we need to
+ // destroy this as the last DNWA happens; we can't put it off until
+ // (potentially) after we tear down the X11 connection because that's a
+ // crash.
+ static int cursor_reference_count_;
+ static wm::CursorManager* cursor_manager_;
+ static views::DesktopNativeCursorManager* native_cursor_manager_;
+
+ scoped_ptr<wm::ShadowController> shadow_controller_;
// Reorders child windows of |window_| associated with a view based on the
// order of the associated views in the widget's view hierarchy.
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index 6a011cab955..f52fe91a7b6 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -4,13 +4,21 @@
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/aura/root_window.h"
+#include "base/bind.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/client/cursor_client.h"
+#include "ui/aura/client/window_tree_client.h"
+#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/views/test/views_test_base.h"
+#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/public/dispatcher_client.h"
namespace views {
+namespace test {
typedef ViewsTestBase DesktopNativeWidgetAuraTest;
@@ -27,12 +35,21 @@ TEST_F(DesktopNativeWidgetAuraTest, CreateWithParentNotInRootWindow) {
widget.Init(params);
}
-// Verifies that the AURA windows making up a widget instance have the correct
+// Verifies that the Aura windows making up a widget instance have the correct
// bounds after the widget is resized.
TEST_F(DesktopNativeWidgetAuraTest, DesktopAuraWindowSizeTest) {
Widget widget;
+
+ // On Linux we test this with popup windows because the WM may ignore the size
+ // suggestion for normal windows.
+#if defined(OS_LINUX)
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+#else
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+#endif
+
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
init_params.native_widget = new DesktopNativeWidgetAura(&widget);
widget.Init(init_params);
@@ -68,6 +85,97 @@ TEST_F(DesktopNativeWidgetAuraTest, NativeViewInitiallyHidden) {
EXPECT_FALSE(widget.GetNativeView()->IsVisible());
}
+// Verify that the cursor state is shared between two native widgets.
+TEST_F(DesktopNativeWidgetAuraTest, GlobalCursorState) {
+ // Create two native widgets, each owning different root windows.
+ Widget widget_a;
+ Widget::InitParams init_params_a =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ init_params_a.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ DesktopNativeWidgetAura* desktop_native_widget_aura_a =
+ new DesktopNativeWidgetAura(&widget_a);
+ init_params_a.native_widget = desktop_native_widget_aura_a;
+ widget_a.Init(init_params_a);
+
+ Widget widget_b;
+ Widget::InitParams init_params_b =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ init_params_b.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ DesktopNativeWidgetAura* desktop_native_widget_aura_b =
+ new DesktopNativeWidgetAura(&widget_b);
+ init_params_b.native_widget = desktop_native_widget_aura_b;
+ widget_b.Init(init_params_b);
+
+ aura::client::CursorClient* cursor_client_a = aura::client::GetCursorClient(
+ desktop_native_widget_aura_a->host()->window());
+ aura::client::CursorClient* cursor_client_b = aura::client::GetCursorClient(
+ desktop_native_widget_aura_b->host()->window());
+
+ // Verify the cursor can be locked using one client and unlocked using
+ // another.
+ EXPECT_FALSE(cursor_client_a->IsCursorLocked());
+ EXPECT_FALSE(cursor_client_b->IsCursorLocked());
+
+ cursor_client_a->LockCursor();
+ EXPECT_TRUE(cursor_client_a->IsCursorLocked());
+ EXPECT_TRUE(cursor_client_b->IsCursorLocked());
+
+ cursor_client_b->UnlockCursor();
+ EXPECT_FALSE(cursor_client_a->IsCursorLocked());
+ EXPECT_FALSE(cursor_client_b->IsCursorLocked());
+
+ // Verify that mouse events can be disabled using one client and then
+ // re-enabled using another. Note that disabling mouse events should also
+ // have the side effect of making the cursor invisible.
+ EXPECT_TRUE(cursor_client_a->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_b->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_a->IsMouseEventsEnabled());
+ EXPECT_TRUE(cursor_client_b->IsMouseEventsEnabled());
+
+ cursor_client_b->DisableMouseEvents();
+ EXPECT_FALSE(cursor_client_a->IsCursorVisible());
+ EXPECT_FALSE(cursor_client_b->IsCursorVisible());
+ EXPECT_FALSE(cursor_client_a->IsMouseEventsEnabled());
+ EXPECT_FALSE(cursor_client_b->IsMouseEventsEnabled());
+
+ cursor_client_a->EnableMouseEvents();
+ EXPECT_TRUE(cursor_client_a->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_b->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_a->IsMouseEventsEnabled());
+ EXPECT_TRUE(cursor_client_b->IsMouseEventsEnabled());
+
+ // Verify that setting the cursor using one cursor client
+ // will set it for all root windows.
+ EXPECT_EQ(ui::kCursorNone, cursor_client_a->GetCursor().native_type());
+ EXPECT_EQ(ui::kCursorNone, cursor_client_b->GetCursor().native_type());
+
+ cursor_client_b->SetCursor(ui::kCursorPointer);
+ EXPECT_EQ(ui::kCursorPointer, cursor_client_a->GetCursor().native_type());
+ EXPECT_EQ(ui::kCursorPointer, cursor_client_b->GetCursor().native_type());
+
+ // Verify that hiding the cursor using one cursor client will
+ // hide it for all root windows. Note that hiding the cursor
+ // should not disable mouse events.
+ cursor_client_a->HideCursor();
+ EXPECT_FALSE(cursor_client_a->IsCursorVisible());
+ EXPECT_FALSE(cursor_client_b->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_a->IsMouseEventsEnabled());
+ EXPECT_TRUE(cursor_client_b->IsMouseEventsEnabled());
+
+ // Verify that the visibility state cannot be changed using one
+ // cursor client when the cursor was locked using another.
+ cursor_client_b->LockCursor();
+ cursor_client_a->ShowCursor();
+ EXPECT_FALSE(cursor_client_a->IsCursorVisible());
+ EXPECT_FALSE(cursor_client_b->IsCursorVisible());
+
+ // Verify the cursor becomes visible on unlock (since a request
+ // to make it visible was queued up while the cursor was locked).
+ cursor_client_b->UnlockCursor();
+ EXPECT_TRUE(cursor_client_a->IsCursorVisible());
+ EXPECT_TRUE(cursor_client_b->IsCursorVisible());
+}
+
// Verifies FocusController doesn't attempt to access |content_window_| during
// destruction. Previously the FocusController was destroyed after the window.
// This could be problematic as FocusController references |content_window_| and
@@ -94,4 +202,198 @@ TEST_F(DesktopNativeWidgetAuraTest, DontAccessContentWindowDuringDestruction) {
}
}
+void QuitNestedLoopAndCloseWidget(scoped_ptr<Widget> widget,
+ base::Closure* quit_runloop) {
+ quit_runloop->Run();
+}
+
+// Verifies that a widget can be destroyed when running a nested message-loop.
+TEST_F(DesktopNativeWidgetAuraTest, WidgetCanBeDestroyedFromNestedLoop) {
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(0, 0, 200, 200);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(widget.get());
+ widget->Init(params);
+ widget->Show();
+
+ aura::Window* window = widget->GetNativeView();
+ aura::Window* root = window->GetRootWindow();
+ aura::client::DispatcherClient* client =
+ aura::client::GetDispatcherClient(root);
+
+ // Post a task that terminates the nested loop and destroyes the widget. This
+ // task will be executed from the nested loop initiated with the call to
+ // |RunWithDispatcher()| below.
+ aura::client::DispatcherRunLoop run_loop(client, NULL);
+ base::Closure quit_runloop = run_loop.QuitClosure();
+ message_loop()->PostTask(FROM_HERE,
+ base::Bind(&QuitNestedLoopAndCloseWidget,
+ base::Passed(&widget),
+ base::Unretained(&quit_runloop)));
+ run_loop.Run();
+}
+
+// This class provides functionality to create fullscreen and top level popup
+// windows. It additionally tests whether the destruction of these windows
+// occurs correctly in desktop AURA without crashing.
+// It provides facilities to test the following cases:-
+// 1. Child window destroyed which should lead to the destruction of the
+// parent.
+// 2. Parent window destroyed which should lead to the child being destroyed.
+class DesktopAuraTopLevelWindowTest
+ : public views::TestViewsDelegate,
+ public aura::WindowObserver {
+ public:
+ DesktopAuraTopLevelWindowTest()
+ : top_level_widget_(NULL),
+ owned_window_(NULL),
+ owner_destroyed_(false),
+ owned_window_destroyed_(false) {}
+
+ virtual ~DesktopAuraTopLevelWindowTest() {
+ EXPECT_TRUE(owner_destroyed_);
+ EXPECT_TRUE(owned_window_destroyed_);
+ top_level_widget_ = NULL;
+ owned_window_ = NULL;
+ }
+
+ // views::TestViewsDelegate overrides.
+ virtual void OnBeforeWidgetInit(
+ Widget::InitParams* params,
+ internal::NativeWidgetDelegate* delegate) OVERRIDE {
+ if (!params->native_widget)
+ params->native_widget = new views::DesktopNativeWidgetAura(delegate);
+ }
+
+ void CreateTopLevelWindow(const gfx::Rect& bounds, bool fullscreen) {
+ Widget::InitParams init_params;
+ init_params.type = Widget::InitParams::TYPE_WINDOW;
+ init_params.bounds = bounds;
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.layer_type = aura::WINDOW_LAYER_NOT_DRAWN;
+ init_params.accept_events = fullscreen;
+
+ widget_.Init(init_params);
+
+ owned_window_ = new aura::Window(&child_window_delegate_);
+ owned_window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
+ owned_window_->SetName("TestTopLevelWindow");
+ if (fullscreen) {
+ owned_window_->SetProperty(aura::client::kShowStateKey,
+ ui::SHOW_STATE_FULLSCREEN);
+ } else {
+ owned_window_->SetType(ui::wm::WINDOW_TYPE_MENU);
+ }
+ owned_window_->Init(aura::WINDOW_LAYER_TEXTURED);
+ aura::client::ParentWindowWithContext(
+ owned_window_,
+ widget_.GetNativeView()->GetRootWindow(),
+ gfx::Rect(0, 0, 1900, 1600));
+ owned_window_->Show();
+ owned_window_->AddObserver(this);
+
+ ASSERT_TRUE(owned_window_->parent() != NULL);
+ owned_window_->parent()->AddObserver(this);
+
+ top_level_widget_ =
+ views::Widget::GetWidgetForNativeView(owned_window_->parent());
+ ASSERT_TRUE(top_level_widget_ != NULL);
+ }
+
+ void DestroyOwnedWindow() {
+ ASSERT_TRUE(owned_window_ != NULL);
+ delete owned_window_;
+ }
+
+ void DestroyOwnerWindow() {
+ ASSERT_TRUE(top_level_widget_ != NULL);
+ top_level_widget_->CloseNow();
+ }
+
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ window->RemoveObserver(this);
+ if (window == owned_window_) {
+ owned_window_destroyed_ = true;
+ } else if (window == top_level_widget_->GetNativeView()) {
+ owner_destroyed_ = true;
+ } else {
+ ADD_FAILURE() << "Unexpected window destroyed callback: " << window;
+ }
+ }
+
+ aura::Window* owned_window() {
+ return owned_window_;
+ }
+
+ views::Widget* top_level_widget() {
+ return top_level_widget_;
+ }
+
+ private:
+ views::Widget widget_;
+ views::Widget* top_level_widget_;
+ aura::Window* owned_window_;
+ bool owner_destroyed_;
+ bool owned_window_destroyed_;
+ aura::test::TestWindowDelegate child_window_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopAuraTopLevelWindowTest);
+};
+
+typedef WidgetTest DesktopAuraWidgetTest;
+
+TEST_F(DesktopAuraWidgetTest, FullscreenWindowDestroyedBeforeOwnerTest) {
+ ViewsDelegate::views_delegate = NULL;
+ DesktopAuraTopLevelWindowTest fullscreen_window;
+ ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
+ gfx::Rect(0, 0, 200, 200), true));
+
+ RunPendingMessages();
+ ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnedWindow());
+ RunPendingMessages();
+}
+
+TEST_F(DesktopAuraWidgetTest, FullscreenWindowOwnerDestroyed) {
+ ViewsDelegate::views_delegate = NULL;
+
+ DesktopAuraTopLevelWindowTest fullscreen_window;
+ ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
+ gfx::Rect(0, 0, 200, 200), true));
+
+ RunPendingMessages();
+ ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnerWindow());
+ RunPendingMessages();
+}
+
+TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupTest) {
+ ViewsDelegate::views_delegate = NULL;
+ DesktopAuraTopLevelWindowTest popup_window;
+ ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow(
+ gfx::Rect(0, 0, 200, 200), false));
+
+ RunPendingMessages();
+ ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow());
+ RunPendingMessages();
+}
+
+// This test validates that when a top level owned popup Aura window is
+// resized, the widget is resized as well.
+TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupResizeTest) {
+ ViewsDelegate::views_delegate = NULL;
+ DesktopAuraTopLevelWindowTest popup_window;
+ ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow(
+ gfx::Rect(0, 0, 200, 200), false));
+
+ gfx::Rect new_size(0, 0, 400, 400);
+ popup_window.owned_window()->SetBounds(new_size);
+
+ EXPECT_EQ(popup_window.top_level_widget()->GetNativeView()->bounds().size(),
+ new_size.size());
+ RunPendingMessages();
+ ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow());
+ RunPendingMessages();
+}
+
+} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win_unittest.cc
deleted file mode 100644
index a002f10fdf2..00000000000
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win_unittest.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
-
-#include "ui/aura/root_window.h"
-#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-typedef ViewsTestBase DesktopRootWindowHostWinTest;
-
-namespace {
-
-// See description above SaveFocusOnDeactivateFromHandleCreate.
-class TestDesktopRootWindowHostWin : public DesktopRootWindowHostWin {
- public:
- TestDesktopRootWindowHostWin(
- internal::NativeWidgetDelegate* native_widget_delegate,
- DesktopNativeWidgetAura* desktop_native_widget_aura)
- : DesktopRootWindowHostWin(native_widget_delegate,
- desktop_native_widget_aura) {}
- virtual ~TestDesktopRootWindowHostWin() {}
-
- // DesktopRootWindowHostWin overrides:
- virtual void HandleCreate() OVERRIDE {
- DesktopRootWindowHostWin::HandleCreate();
- SaveFocusOnDeactivate();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestDesktopRootWindowHostWin);
-};
-
-} // namespace
-
-// Verifies if SaveFocusOnDeactivate() is invoked from
-// DesktopRootWindowHostWin::HandleCreate we don't crash.
-TEST_F(DesktopRootWindowHostWinTest, SaveFocusOnDeactivateFromHandleCreate) {
- Widget widget;
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
- params.bounds = gfx::Rect(0, 0, 200, 200);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- DesktopNativeWidgetAura* desktop_native_widget_aura =
- new DesktopNativeWidgetAura(&widget);
- params.native_widget = desktop_native_widget_aura;
- params.desktop_root_window_host = new TestDesktopRootWindowHostWin(
- &widget, desktop_native_widget_aura);
- widget.Init(params);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen.h b/chromium/ui/views/widget/desktop_aura/desktop_screen.h
index ad66bd41575..2db961d2d95 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen.h
@@ -14,7 +14,7 @@ class Screen;
namespace views {
// Creates a Screen that represents the screen of the environment that hosts
-// a RootWindowHost. Caller owns the result.
+// a WindowTreeHost. Caller owns the result.
VIEWS_EXPORT gfx::Screen* CreateDesktopScreen();
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
index 4d7f9a1b739..9708ad88bfc 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
@@ -4,14 +4,12 @@
#include "ui/views/widget/desktop_aura/desktop_screen.h"
-#include "ui/gfx/ozone/surface_factory_ozone.h"
-#include "ui/ozone/ozone_platform.h"
+#include "ui/views/widget/desktop_aura/desktop_factory_ozone.h"
namespace views {
gfx::Screen* CreateDesktopScreen() {
- ui::OzonePlatform::Initialize();
- return gfx::SurfaceFactoryOzone::GetInstance()->CreateDesktopScreen();
+ return DesktopFactoryOzone::GetInstance()->CreateDesktopScreen();
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
index a16b24b6427..96deaf4205c 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.cc
@@ -4,7 +4,7 @@
#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/gfx/display.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/screen.h"
@@ -15,20 +15,17 @@ namespace views {
namespace {
gfx::Point GetOrigin(const aura::Window* root_window) {
- gfx::Point origin_in_pixels =
- root_window->GetDispatcher()->host()->GetBounds().origin();
+ gfx::Point origin_in_pixels = root_window->GetHost()->GetBounds().origin();
aura::Window* window = const_cast<aura::Window*>(root_window);
float scale = gfx::Screen::GetScreenFor(window)->
GetDisplayNearestWindow(window).device_scale_factor();
- return gfx::ToFlooredPoint(
- gfx::ScalePoint(origin_in_pixels, 1 / scale));
+ return gfx::ToFlooredPoint(gfx::ScalePoint(origin_in_pixels, 1 / scale));
}
// Returns true if bounds passed to window are treated as though they are in
// screen coordinates.
bool PositionWindowInScreenCoordinates(aura::Window* window) {
- if (window->type() == aura::client::WINDOW_TYPE_POPUP ||
- window->type() == aura::client::WINDOW_TYPE_TOOLTIP)
+ if (window->type() == ui::wm::WINDOW_TYPE_POPUP)
return true;
Widget* widget = Widget::GetWidgetForNativeView(window);
@@ -37,14 +34,19 @@ bool PositionWindowInScreenCoordinates(aura::Window* window) {
} // namespace
-DesktopScreenPositionClient::DesktopScreenPositionClient() {
+DesktopScreenPositionClient::DesktopScreenPositionClient(
+ aura::Window* root_window)
+ : root_window_(root_window) {
+ aura::client::SetScreenPositionClient(root_window_, this);
}
DesktopScreenPositionClient::~DesktopScreenPositionClient() {
+ aura::client::SetScreenPositionClient(root_window_, NULL);
}
void DesktopScreenPositionClient::ConvertPointToScreen(
- const aura::Window* window, gfx::Point* point) {
+ const aura::Window* window,
+ gfx::Point* point) {
const aura::Window* root_window = window->GetRootWindow();
aura::Window::ConvertPointToTarget(window, root_window, point);
gfx::Point origin = GetOrigin(root_window);
@@ -52,26 +54,33 @@ void DesktopScreenPositionClient::ConvertPointToScreen(
}
void DesktopScreenPositionClient::ConvertPointFromScreen(
- const aura::Window* window, gfx::Point* point) {
+ const aura::Window* window,
+ gfx::Point* point) {
const aura::Window* root_window = window->GetRootWindow();
gfx::Point origin = GetOrigin(root_window);
point->Offset(-origin.x(), -origin.y());
aura::Window::ConvertPointToTarget(root_window, window, point);
}
-void DesktopScreenPositionClient::ConvertHostPointToScreen(
- aura::Window* window, gfx::Point* point) {
+void DesktopScreenPositionClient::ConvertHostPointToScreen(aura::Window* window,
+ gfx::Point* point) {
aura::Window* root_window = window->GetRootWindow();
ConvertPointToScreen(root_window, point);
}
-void DesktopScreenPositionClient::SetBounds(
- aura::Window* window,
- const gfx::Rect& bounds,
- const gfx::Display& display) {
+void DesktopScreenPositionClient::SetBounds(aura::Window* window,
+ const gfx::Rect& bounds,
+ const gfx::Display& display) {
// TODO: Use the 3rd parameter, |display|.
aura::Window* root = window->GetRootWindow();
+ // This method assumes that |window| does not have an associated
+ // DesktopNativeWidgetAura.
+ internal::NativeWidgetPrivate* desktop_native_widget =
+ DesktopNativeWidgetAura::ForWindow(root);
+ DCHECK(!desktop_native_widget ||
+ desktop_native_widget->GetNativeView() != window);
+
if (PositionWindowInScreenCoordinates(window)) {
// The caller expects windows we consider "embedded" to be placed in the
// screen coordinate system. So we need to offset the root window's
@@ -86,14 +95,7 @@ void DesktopScreenPositionClient::SetBounds(
return;
}
- DesktopNativeWidgetAura* desktop_native_widget =
- DesktopNativeWidgetAura::ForWindow(window);
- if (desktop_native_widget) {
- root->GetDispatcher()->SetHostBounds(bounds);
- // Setting bounds of root resizes |window|.
- } else {
- window->SetBounds(bounds);
- }
+ window->SetBounds(bounds);
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.h
index da8ad402ea7..222c2a1a4ea 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client.h
@@ -15,7 +15,7 @@ namespace views {
class VIEWS_EXPORT DesktopScreenPositionClient
: public aura::client::ScreenPositionClient {
public:
- DesktopScreenPositionClient();
+ explicit DesktopScreenPositionClient(aura::Window* root_window);
virtual ~DesktopScreenPositionClient();
// aura::client::ScreenPositionClient overrides:
@@ -28,6 +28,11 @@ class VIEWS_EXPORT DesktopScreenPositionClient
virtual void SetBounds(aura::Window* window,
const gfx::Rect& bounds,
const gfx::Display& display) OVERRIDE;
+
+ private:
+ aura::Window* root_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopScreenPositionClient);
};
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client_unittest.cc
index bb1cd8b08ac..ac30d1ee700 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_position_client_unittest.cc
@@ -15,21 +15,17 @@ typedef ViewsTestBase DesktopScreenPositionClientTest;
// DesktopNativeWidgetAura is positioned correctly.
TEST_F(DesktopScreenPositionClientTest, PositionDialog) {
Widget parent_widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.bounds = gfx::Rect(10, 11, 200, 200);
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&parent_widget);
- parent_widget.Init(init_params);
- // parent_widget.Show();
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.bounds = gfx::Rect(10, 11, 200, 200);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(&parent_widget);
+ parent_widget.Init(params);
// Owned by |dialog|.
DialogDelegateView* dialog_delegate_view = new DialogDelegateView;
// Owned by |parent_widget|.
Widget* dialog = DialogDelegate::CreateDialogWidget(
- dialog_delegate_view,
- NULL,
- parent_widget.GetNativeView());
+ dialog_delegate_view, NULL, parent_widget.GetNativeView());
dialog->SetBounds(gfx::Rect(11, 12, 200, 200));
EXPECT_EQ("11,12", dialog->GetWindowBoundsInScreen().origin().ToString());
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
index 86823a04d3a..c5edf76c687 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
@@ -5,12 +5,12 @@
#include "ui/views/widget/desktop_aura/desktop_screen_win.h"
#include "base/logging.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/gfx/display.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
namespace {
@@ -54,13 +54,13 @@ gfx::Display DesktopScreenWin::GetDisplayMatching(
}
HWND DesktopScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const {
- aura::WindowEventDispatcher* dispatcher = window->GetDispatcher();
- return dispatcher ? dispatcher->host()->GetAcceleratedWidget() : NULL;
+ aura::WindowTreeHost* host = window->GetHost();
+ return host ? host->GetAcceleratedWidget() : NULL;
}
gfx::NativeWindow DesktopScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
return (::IsWindow(hwnd)) ?
- DesktopRootWindowHostWin::GetContentWindowForHWND(hwnd) : NULL;
+ DesktopWindowTreeHostWin::GetContentWindowForHWND(hwnd) : NULL;
}
////////////////////////////////////////////////////////////////////////////////
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 332b81c59ce..76db7948117 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -12,19 +12,21 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
-#include "base/x11/edid_parser_x11.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/layout.h"
-#include "ui/base/x/x11_util.h"
+#include "ui/display/util/display_util.h"
+#include "ui/display/util/x11/edid_parser_x11.h"
+#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/display.h"
#include "ui/gfx/display_observer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/x/x11_types.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
namespace {
@@ -32,6 +34,7 @@ namespace {
// in |Dispatch()|.
const int64 kConfigureDelayMs = 500;
+// TODO(oshima): Consider using gtk-xft-dpi instead.
float GetDeviceScaleFactor(int screen_pixels, int screen_mm) {
const int kCSSDefaultDPI = 96;
const float kInchInMm = 25.4f;
@@ -40,7 +43,7 @@ float GetDeviceScaleFactor(int screen_pixels, int screen_mm) {
float screen_dpi = screen_pixels / screen_inches;
float scale = screen_dpi / kCSSDefaultDPI;
- return ui::GetImageScale(ui::GetSupportedScaleFactor(scale));
+ return ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale));
}
std::vector<gfx::Display> GetFallbackDisplayList() {
@@ -48,14 +51,14 @@ std::vector<gfx::Display> GetFallbackDisplayList() {
::Screen* screen = DefaultScreenOfDisplay(display);
int width = WidthOfScreen(screen);
int height = HeightOfScreen(screen);
- int mm_width = WidthMMOfScreen(screen);
- int mm_height = HeightMMOfScreen(screen);
+ gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen));
gfx::Rect bounds_in_pixels(0, 0, width, height);
gfx::Display gfx_display(0, bounds_in_pixels);
if (!gfx::Display::HasForceDeviceScaleFactor() &&
- !ui::IsXDisplaySizeBlackListed(mm_width, mm_height)) {
- float device_scale_factor = GetDeviceScaleFactor(width, mm_width);
+ !ui::IsDisplaySizeBlackListed(physical_size)) {
+ float device_scale_factor = GetDeviceScaleFactor(
+ width, physical_size.width());
DCHECK_LE(1.0f, device_scale_factor);
gfx_display.SetScaleAndBounds(device_scale_factor, bounds_in_pixels);
}
@@ -71,7 +74,7 @@ namespace views {
// DesktopScreenX11, public:
DesktopScreenX11::DesktopScreenX11()
- : xdisplay_(base::MessagePumpX11::GetDefaultXDisplay()),
+ : xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
has_xrandr_(false),
xrandr_event_base_(0) {
@@ -88,10 +91,13 @@ DesktopScreenX11::DesktopScreenX11()
int error_base_ignored = 0;
XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
- base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
XRRSelectInput(xdisplay_,
x_root_window_,
- RRScreenChangeNotifyMask | RROutputChangeNotifyMask);
+ RRScreenChangeNotifyMask |
+ RROutputChangeNotifyMask |
+ RRCrtcChangeNotifyMask);
displays_ = BuildDisplaysFromXRandRInfo();
} else {
@@ -100,18 +106,22 @@ DesktopScreenX11::DesktopScreenX11()
}
DesktopScreenX11::~DesktopScreenX11() {
- if (has_xrandr_)
- base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this);
+ if (has_xrandr_ && ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
}
void DesktopScreenX11::ProcessDisplayChange(
const std::vector<gfx::Display>& incoming) {
- std::vector<gfx::Display>::const_iterator cur_it = displays_.begin();
- for (; cur_it != displays_.end(); ++cur_it) {
+ std::vector<gfx::Display> old_displays = displays_;
+ displays_ = incoming;
+
+ typedef std::vector<gfx::Display>::const_iterator DisplayIt;
+ std::vector<gfx::Display>::const_iterator old_it = old_displays.begin();
+ for (; old_it != old_displays.end(); ++old_it) {
bool found = false;
- for (std::vector<gfx::Display>::const_iterator incoming_it =
- incoming.begin(); incoming_it != incoming.end(); ++incoming_it) {
- if (cur_it->id() == incoming_it->id()) {
+ for (std::vector<gfx::Display>::const_iterator new_it =
+ displays_.begin(); new_it != displays_.end(); ++new_it) {
+ if (old_it->id() == new_it->id()) {
found = true;
break;
}
@@ -119,33 +129,47 @@ void DesktopScreenX11::ProcessDisplayChange(
if (!found) {
FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
- OnDisplayRemoved(*cur_it));
+ OnDisplayRemoved(*old_it));
}
}
- std::vector<gfx::Display>::const_iterator incoming_it = incoming.begin();
- for (; incoming_it != incoming.end(); ++incoming_it) {
+ std::vector<gfx::Display>::const_iterator new_it = displays_.begin();
+ for (; new_it != displays_.end(); ++new_it) {
bool found = false;
- for (std::vector<gfx::Display>::const_iterator cur_it = displays_.begin();
- cur_it != displays_.end(); ++cur_it) {
- if (incoming_it->id() == cur_it->id()) {
- if (incoming_it->bounds() != cur_it->bounds()) {
- FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
- OnDisplayBoundsChanged(*incoming_it));
- }
+ for (std::vector<gfx::Display>::const_iterator old_it =
+ old_displays.begin(); old_it != old_displays.end(); ++old_it) {
+ if (new_it->id() != old_it->id())
+ continue;
- found = true;
- break;
+ uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE;
+
+ if (new_it->bounds() != old_it->bounds())
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS;
+
+ if (new_it->rotation() != old_it->rotation())
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
+
+ if (new_it->work_area() != old_it->work_area())
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+
+ if (new_it->device_scale_factor() != old_it->device_scale_factor())
+ metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+
+ if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) {
+ FOR_EACH_OBSERVER(gfx::DisplayObserver,
+ observer_list_,
+ OnDisplayMetricsChanged(*new_it, metrics));
}
+
+ found = true;
+ break;
}
if (!found) {
FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_,
- OnDisplayAdded(*incoming_it));
+ OnDisplayAdded(*new_it));
}
}
-
- displays_ = incoming;
}
////////////////////////////////////////////////////////////////////////////////
@@ -182,16 +206,8 @@ gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() {
gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
const gfx::Point& point) {
- std::vector<aura::Window*> windows =
- DesktopRootWindowHostX11::GetAllOpenWindows();
-
- for (std::vector<aura::Window*>::const_iterator it = windows.begin();
- it != windows.end(); ++it) {
- if ((*it)->GetBoundsInScreen().Contains(point))
- return *it;
- }
-
- return NULL;
+ X11TopmostWindowFinder finder;
+ return finder.FindLocalProcessWindowAt(point, std::set<aura::Window*>());
}
int DesktopScreenX11::GetNumDisplays() const {
@@ -207,16 +223,16 @@ gfx::Display DesktopScreenX11::GetDisplayNearestWindow(
// Getting screen bounds here safely is hard.
//
// You'd think we'd be able to just call window->GetBoundsInScreen(), but we
- // can't because |window| (and the associated RootWindow*) can be partially
- // initialized at this point; RootWindow initializations call through into
- // GetDisplayNearestWindow(). But the X11 resources are created before we
- // create the aura::RootWindow. So we ask what the DRWHX11 believes the
- // window bounds are instead of going through the aura::Window's screen
- // bounds.
- aura::WindowEventDispatcher* dispatcher = window->GetDispatcher();
- if (dispatcher) {
- DesktopRootWindowHostX11* rwh = DesktopRootWindowHostX11::GetHostForXID(
- dispatcher->host()->GetAcceleratedWidget());
+ // can't because |window| (and the associated WindowEventDispatcher*) can be
+ // partially initialized at this point; WindowEventDispatcher initializations
+ // call through into GetDisplayNearestWindow(). But the X11 resources are
+ // created before we create the aura::WindowEventDispatcher. So we ask what
+ // the DRWHX11 believes the window bounds are instead of going through the
+ // aura::Window's screen bounds.
+ aura::WindowTreeHost* host = window->GetHost();
+ if (host) {
+ DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID(
+ host->GetAcceleratedWidget());
if (rwh)
return GetDisplayMatching(rwh->GetX11RootWindowBounds());
}
@@ -264,7 +280,12 @@ void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) {
observer_list_.RemoveObserver(observer);
}
-bool DesktopScreenX11::Dispatch(const base::NativeEvent& event) {
+bool DesktopScreenX11::CanDispatchEvent(const ui::PlatformEvent& event) {
+ return event->type - xrandr_event_base_ == RRScreenChangeNotify ||
+ event->type - xrandr_event_base_ == RRNotify;
+}
+
+uint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) {
if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
// Pass the event through to xlib.
XRRUpdateConfiguration(event);
@@ -281,9 +302,11 @@ bool DesktopScreenX11::Dispatch(const base::NativeEvent& event) {
this,
&DesktopScreenX11::ConfigureTimerFired);
}
+ } else {
+ NOTREACHED();
}
- return true;
+ return ui::POST_DISPATCH_NONE;
}
////////////////////////////////////////////////////////////////////////////////
@@ -291,7 +314,7 @@ bool DesktopScreenX11::Dispatch(const base::NativeEvent& event) {
DesktopScreenX11::DesktopScreenX11(
const std::vector<gfx::Display>& test_displays)
- : xdisplay_(base::MessagePumpX11::GetDefaultXDisplay()),
+ : xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
has_xrandr_(false),
xrandr_event_base_(0),
@@ -334,7 +357,7 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
output_info->crtc);
int64 display_id = -1;
- if (!base::GetDisplayId(output_id, i, &display_id)) {
+ if (!ui::GetDisplayId(output_id, static_cast<uint8>(i), &display_id)) {
// It isn't ideal, but if we can't parse the EDID data, fallback on the
// display number.
display_id = i;
@@ -344,8 +367,8 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
gfx::Display display(display_id, crtc_bounds);
if (!gfx::Display::HasForceDeviceScaleFactor()) {
- if (i == 0 && !ui::IsXDisplaySizeBlackListed(output_info->mm_width,
- output_info->mm_height)) {
+ if (i == 0 && !ui::IsDisplaySizeBlackListed(
+ gfx::Size(output_info->mm_width, output_info->mm_height))) {
// As per display scale factor is not supported right now,
// the primary display's scale factor is always used.
device_scale_factor = GetDeviceScaleFactor(crtc->width,
@@ -361,6 +384,21 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
display.set_work_area(intersection);
}
+ switch (crtc->rotation) {
+ case RR_Rotate_0:
+ display.set_rotation(gfx::Display::ROTATE_0);
+ break;
+ case RR_Rotate_90:
+ display.set_rotation(gfx::Display::ROTATE_90);
+ break;
+ case RR_Rotate_180:
+ display.set_rotation(gfx::Display::ROTATE_180);
+ break;
+ case RR_Rotate_270:
+ display.set_rotation(gfx::Display::ROTATE_270);
+ break;
+ }
+
displays.push_back(display);
XRRFreeCrtcInfo(crtc);
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 1b9a8320a36..a5b2a17dd83 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
@@ -5,9 +5,9 @@
#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_X11_H_
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_X11_H_
-#include "base/message_loop/message_pump_dispatcher.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/screen.h"
#include "ui/views/views_export.h"
@@ -24,7 +24,7 @@ class DesktopScreenX11Test;
// Our singleton screen implementation that talks to xrandr.
class VIEWS_EXPORT DesktopScreenX11 : public gfx::Screen,
- public base::MessagePumpDispatcher {
+ public ui::PlatformEventDispatcher {
public:
DesktopScreenX11();
@@ -52,8 +52,9 @@ class VIEWS_EXPORT DesktopScreenX11 : public gfx::Screen,
virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE;
virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE;
- // Overridden from MessagePumpDispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
private:
friend class DesktopScreenX11Test;
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 55ce07069fb..c9e7159a53f 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
@@ -4,12 +4,47 @@
#include "ui/views/widget/desktop_aura/desktop_screen_x11.h"
-#include "base/message_loop/message_loop.h"
+#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/test/event_generator.h"
+#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/gfx/display_observer.h"
+#include "ui/gfx/x/x11_types.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+
+namespace {
+
+// Class which allows for the designation of non-client component targets of
+// hit tests.
+class TestDesktopNativeWidgetAura : public views::DesktopNativeWidgetAura {
+ public:
+ explicit TestDesktopNativeWidgetAura(
+ views::internal::NativeWidgetDelegate* delegate)
+ : views::DesktopNativeWidgetAura(delegate) {}
+ virtual ~TestDesktopNativeWidgetAura() {}
+
+ void set_window_component(int window_component) {
+ window_component_ = window_component;
+ }
+
+ // DesktopNativeWidgetAura:
+ virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
+ return window_component_;
+ }
+
+ private:
+ int window_component_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDesktopNativeWidgetAura);
+};
+
+} // namespace
namespace views {
@@ -50,23 +85,26 @@ class DesktopScreenX11Test : public views::ViewsTestBase,
removed_display_.clear();
}
- Widget* BuildTopLevelDesktopWidget(const gfx::Rect& bounds) {
+ Widget* BuildTopLevelDesktopWidget(const gfx::Rect& bounds,
+ bool use_test_native_widget) {
Widget* toplevel = new Widget;
Widget::InitParams toplevel_params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
- toplevel_params.native_widget =
- new views::DesktopNativeWidgetAura(toplevel);
+ if (use_test_native_widget) {
+ toplevel_params.native_widget =
+ new TestDesktopNativeWidgetAura(toplevel);
+ } else {
+ toplevel_params.native_widget =
+ new views::DesktopNativeWidgetAura(toplevel);
+ }
toplevel_params.bounds = bounds;
+ toplevel_params.remove_standard_frame = true;
toplevel->Init(toplevel_params);
return toplevel;
}
private:
// Overridden from gfx::DisplayObserver:
- virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE {
- changed_display_.push_back(display);
- }
-
virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE {
added_display_.push_back(new_display);
}
@@ -75,6 +113,11 @@ class DesktopScreenX11Test : public views::ViewsTestBase,
removed_display_.push_back(old_display);
}
+ virtual void OnDisplayMetricsChanged(const gfx::Display& display,
+ uint32_t metrics) OVERRIDE {
+ changed_display_.push_back(display);
+ }
+
scoped_ptr<DesktopScreenX11> screen_;
DISALLOW_COPY_AND_ASSIGN(DesktopScreenX11Test);
@@ -198,32 +241,6 @@ TEST_F(DesktopScreenX11Test, GetPrimaryDisplay) {
EXPECT_EQ(kFirstDisplay, screen()->GetPrimaryDisplay().id());
}
-TEST_F(DesktopScreenX11Test, GetWindowAtScreenPoint) {
- Widget* window_one = BuildTopLevelDesktopWidget(gfx::Rect(10, 10, 10, 10));
- Widget* window_two = BuildTopLevelDesktopWidget(gfx::Rect(50, 50, 10, 10));
- Widget* window_three = BuildTopLevelDesktopWidget(gfx::Rect(15, 15, 20, 20));
-
- // Make sure the internal state of DesktopRootWindowHostX11 is set up
- // correctly.
- ASSERT_EQ(3u, DesktopRootWindowHostX11::GetAllOpenWindows().size());
-
- EXPECT_EQ(window_one->GetNativeWindow(),
- screen()->GetWindowAtScreenPoint(gfx::Point(15, 15)));
- EXPECT_EQ(window_two->GetNativeWindow(),
- screen()->GetWindowAtScreenPoint(gfx::Point(55, 55)));
- EXPECT_EQ(NULL,
- screen()->GetWindowAtScreenPoint(gfx::Point(100, 100)));
-
- // Bring the third window in front. It overlaps with the first window.
- // Hit-testing on the intersecting region should give the third window.
- window_three->Activate();
- EXPECT_EQ(window_three->GetNativeWindow(),
- screen()->GetWindowAtScreenPoint(gfx::Point(15, 15)));
-
- window_one->CloseNow();
- window_two->CloseNow();
-}
-
TEST_F(DesktopScreenX11Test, GetDisplayNearestWindow) {
// Set up a two monitor situation.
std::vector<gfx::Display> displays;
@@ -232,8 +249,10 @@ TEST_F(DesktopScreenX11Test, GetDisplayNearestWindow) {
gfx::Rect(640, 0, 1024, 768)));
screen()->ProcessDisplayChange(displays);
- Widget* window_one = BuildTopLevelDesktopWidget(gfx::Rect(10, 10, 10, 10));
- Widget* window_two = BuildTopLevelDesktopWidget(gfx::Rect(650, 50, 10, 10));
+ Widget* window_one = BuildTopLevelDesktopWidget(gfx::Rect(10, 10, 10, 10),
+ false);
+ Widget* window_two = BuildTopLevelDesktopWidget(gfx::Rect(650, 50, 10, 10),
+ false);
EXPECT_EQ(
kFirstDisplay,
@@ -246,4 +265,183 @@ TEST_F(DesktopScreenX11Test, GetDisplayNearestWindow) {
window_two->CloseNow();
}
+// Tests that the window is maximized in response to a double click event.
+TEST_F(DesktopScreenX11Test, DoubleClickHeaderMaximizes) {
+ if (!ui::WmSupportsHint(ui::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")))
+ return;
+
+ Widget* widget = BuildTopLevelDesktopWidget(gfx::Rect(0, 0, 100, 100), true);
+ widget->Show();
+ TestDesktopNativeWidgetAura* native_widget =
+ static_cast<TestDesktopNativeWidgetAura*>(widget->native_widget());
+ native_widget->set_window_component(HTCAPTION);
+
+ aura::Window* window = widget->GetNativeWindow();
+ window->SetProperty(aura::client::kCanMaximizeKey, true);
+
+ // Cast to superclass as DesktopWindowTreeHostX11 hide IsMaximized
+ DesktopWindowTreeHost* rwh =
+ DesktopWindowTreeHostX11::GetHostForXID(window->GetHost()->
+ GetAcceleratedWidget());
+
+ aura::test::EventGenerator generator(window);
+ generator.ClickLeftButton();
+ generator.DoubleClickLeftButton();
+ RunPendingMessages();
+ EXPECT_TRUE(rwh->IsMaximized());
+
+ widget->CloseNow();
+}
+
+// Tests that the window does not maximize in response to a double click event,
+// if the first click was to a different target component than that of the
+// second click.
+TEST_F(DesktopScreenX11Test, DoubleClickTwoDifferentTargetsDoesntMaximizes) {
+ Widget* widget = BuildTopLevelDesktopWidget(gfx::Rect(0, 0, 100, 100), true);
+ widget->Show();
+ TestDesktopNativeWidgetAura* native_widget =
+ static_cast<TestDesktopNativeWidgetAura*>(widget->native_widget());
+
+ aura::Window* window = widget->GetNativeWindow();
+ window->SetProperty(aura::client::kCanMaximizeKey, true);
+
+ // Cast to superclass as DesktopWindowTreeHostX11 hide IsMaximized
+ DesktopWindowTreeHost* rwh =
+ DesktopWindowTreeHostX11::GetHostForXID(window->GetHost()->
+ GetAcceleratedWidget());
+
+ aura::test::EventGenerator generator(window);
+ native_widget->set_window_component(HTCLIENT);
+ generator.ClickLeftButton();
+ native_widget->set_window_component(HTCAPTION);
+ generator.DoubleClickLeftButton();
+ RunPendingMessages();
+ EXPECT_FALSE(rwh->IsMaximized());
+
+ widget->CloseNow();
+}
+
+// Tests that the window does not maximize in response to a double click event,
+// if the double click was interrupted by a right click.
+TEST_F(DesktopScreenX11Test, RightClickDuringDoubleClickDoesntMaximize) {
+ Widget* widget = BuildTopLevelDesktopWidget(gfx::Rect(0, 0, 100, 100), true);
+ widget->Show();
+ TestDesktopNativeWidgetAura* native_widget =
+ static_cast<TestDesktopNativeWidgetAura*>(widget->native_widget());
+
+ aura::Window* window = widget->GetNativeWindow();
+ window->SetProperty(aura::client::kCanMaximizeKey, true);
+
+ // Cast to superclass as DesktopWindowTreeHostX11 hide IsMaximized
+ DesktopWindowTreeHost* rwh = static_cast<DesktopWindowTreeHost*>(
+ DesktopWindowTreeHostX11::GetHostForXID(window->GetHost()->
+ GetAcceleratedWidget()));
+
+ aura::test::EventGenerator generator(window);
+ native_widget->set_window_component(HTCLIENT);
+ generator.ClickLeftButton();
+ native_widget->set_window_component(HTCAPTION);
+ generator.PressRightButton();
+ generator.ReleaseRightButton();
+ EXPECT_FALSE(rwh->IsMaximized());
+ generator.DoubleClickLeftButton();
+ RunPendingMessages();
+ EXPECT_FALSE(rwh->IsMaximized());
+
+ widget->CloseNow();
+}
+
+// Test that rotating the displays notifies the DisplayObservers.
+TEST_F(DesktopScreenX11Test, RotationChange) {
+ std::vector<gfx::Display> displays;
+ displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
+ displays.push_back(
+ gfx::Display(kSecondDisplay, gfx::Rect(640, 0, 1024, 768)));
+ screen()->ProcessDisplayChange(displays);
+ ResetDisplayChanges();
+
+ displays[0].set_rotation(gfx::Display::ROTATE_90);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(1u, changed_display_.size());
+
+ displays[1].set_rotation(gfx::Display::ROTATE_90);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[0].set_rotation(gfx::Display::ROTATE_270);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(3u, changed_display_.size());
+
+ displays[0].set_rotation(gfx::Display::ROTATE_270);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(3u, changed_display_.size());
+
+ displays[0].set_rotation(gfx::Display::ROTATE_0);
+ displays[1].set_rotation(gfx::Display::ROTATE_0);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(5u, changed_display_.size());
+}
+
+// Test that changing the displays workarea notifies the DisplayObservers.
+TEST_F(DesktopScreenX11Test, WorkareaChange) {
+ std::vector<gfx::Display> displays;
+ displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
+ displays.push_back(
+ gfx::Display(kSecondDisplay, gfx::Rect(640, 0, 1024, 768)));
+ screen()->ProcessDisplayChange(displays);
+ ResetDisplayChanges();
+
+ displays[0].set_work_area(gfx::Rect(0, 0, 300, 300));
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(1u, changed_display_.size());
+
+ displays[1].set_work_area(gfx::Rect(0, 0, 300, 300));
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[0].set_work_area(gfx::Rect(0, 0, 300, 300));
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[1].set_work_area(gfx::Rect(0, 0, 300, 300));
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[0].set_work_area(gfx::Rect(0, 0, 640, 480));
+ displays[1].set_work_area(gfx::Rect(640, 0, 1024, 768));
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(4u, changed_display_.size());
+}
+
+// Test that changing the device scale factor notifies the DisplayObservers.
+TEST_F(DesktopScreenX11Test, DeviceScaleFactorChange) {
+ std::vector<gfx::Display> displays;
+ displays.push_back(gfx::Display(kFirstDisplay, gfx::Rect(0, 0, 640, 480)));
+ displays.push_back(
+ gfx::Display(kSecondDisplay, gfx::Rect(640, 0, 1024, 768)));
+ screen()->ProcessDisplayChange(displays);
+ ResetDisplayChanges();
+
+ displays[0].set_device_scale_factor(2.5f);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(1u, changed_display_.size());
+
+ displays[1].set_device_scale_factor(2.5f);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[0].set_device_scale_factor(2.5f);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[1].set_device_scale_factor(2.5f);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(2u, changed_display_.size());
+
+ displays[0].set_device_scale_factor(1.f);
+ displays[1].set_device_scale_factor(1.f);
+ screen()->ProcessDisplayChange(displays);
+ EXPECT_EQ(4u, changed_display_.size());
+}
+
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index c66cee9254c..9ccb67225a1 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_H_
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_H_
#include "base/memory/scoped_ptr.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget.h"
namespace aura {
-class RootWindowHost;
+class WindowTreeHost;
class Window;
namespace client {
@@ -31,7 +31,6 @@ class NativeTheme;
namespace views {
namespace corewm {
-
class Tooltip;
}
@@ -42,41 +41,39 @@ class NativeWidgetDelegate;
class DesktopNativeCursorManager;
class DesktopNativeWidgetAura;
-class VIEWS_EXPORT DesktopRootWindowHost {
+class VIEWS_EXPORT DesktopWindowTreeHost {
public:
- virtual ~DesktopRootWindowHost() {}
+ virtual ~DesktopWindowTreeHost() {}
- static DesktopRootWindowHost* Create(
+ static DesktopWindowTreeHost* Create(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura);
// Return the NativeTheme to use for |window|. WARNING: |window| may be NULL.
static ui::NativeTheme* GetNativeTheme(aura::Window* window);
- // Sets up resources needed before the RootWindow has been created.
+ // Sets up resources needed before the WindowEventDispatcher has been created.
virtual void Init(aura::Window* content_window,
- const Widget::InitParams& params,
- aura::RootWindow::CreateParams* rw_create_params) = 0;
+ const Widget::InitParams& params) = 0;
- // Invoked once the RootWindow has been created. Caller owns the RootWindow.
- virtual void OnRootWindowCreated(aura::RootWindow* root,
- const Widget::InitParams& params) = 0;
+ // Invoked once the DesktopNativeWidgetAura has been created.
+ virtual void OnNativeWidgetCreated(const Widget::InitParams& params) = 0;
// Creates and returns the Tooltip implementation to use. Return value is
// owned by DesktopNativeWidgetAura and lives as long as
- // DesktopRootWindowHost.
+ // DesktopWindowTreeHost.
virtual scoped_ptr<corewm::Tooltip> CreateTooltip() = 0;
// Creates and returns the DragDropClient implementation to use. Return value
// is owned by DesktopNativeWidgetAura and lives as long as
- // DesktopRootWindowHost.
+ // DesktopWindowTreeHost.
virtual scoped_ptr<aura::client::DragDropClient> CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) = 0;
virtual void Close() = 0;
virtual void CloseNow() = 0;
- virtual aura::RootWindowHost* AsRootWindowHost() = 0;
+ virtual aura::WindowTreeHost* AsWindowTreeHost() = 0;
virtual void ShowWindowWithState(ui::WindowShowState show_state) = 0;
virtual void ShowMaximizedWithBounds(const gfx::Rect& restored_bounds) = 0;
@@ -112,8 +109,10 @@ class VIEWS_EXPORT DesktopRootWindowHost {
virtual void SetAlwaysOnTop(bool always_on_top) = 0;
virtual bool IsAlwaysOnTop() const = 0;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
+
// Returns true if the title changed.
- virtual bool SetWindowTitle(const string16& title) = 0;
+ virtual bool SetWindowTitle(const base::string16& title) = 0;
virtual void ClearNativeFocus() = 0;
@@ -125,9 +124,12 @@ class VIEWS_EXPORT DesktopRootWindowHost {
virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0;
- virtual bool ShouldUseNativeFrame() = 0;
+ // Determines whether the window should use native title bar and borders.
+ virtual bool ShouldUseNativeFrame() const = 0;
+ // Determines whether the window contents should be rendered transparently
+ // (for example, so that they can overhang onto the window title bar).
+ virtual bool ShouldWindowContentsBeTransparent() const = 0;
virtual void FrameTypeChanged() = 0;
- virtual NonClientFrameView* CreateNonClientFrameView() = 0;
virtual void SetFullscreen(bool fullscreen) = 0;
virtual bool IsFullscreen() const = 0;
@@ -151,8 +153,11 @@ class VIEWS_EXPORT DesktopRootWindowHost {
// Returns true if the Widget was closed but is still showing because of
// animations.
virtual bool IsAnimatingClosed() const = 0;
+
+ // Returns true if the Widget supports translucency.
+ virtual bool IsTranslucentWindowOpacitySupported() const = 0;
};
} // namespace views
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_H_
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_H_
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h
index f430b38c20d..544f20527aa 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_OBSERVER_X11_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_OBSERVER_X11_H_
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_OBSERVER_X11_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_OBSERVER_X11_H_
#include "ui/views/views_export.h"
namespace views {
// Allows for the observation of lower level window events.
-class VIEWS_EXPORT DesktopRootWindowHostObserverX11 {
+class VIEWS_EXPORT DesktopWindowTreeHostObserverX11 {
public:
- virtual ~DesktopRootWindowHostObserverX11() {}
+ virtual ~DesktopWindowTreeHostObserverX11() {}
// Called after we receive a MapNotify event (the X11 server has allocated
// resources for it).
@@ -25,5 +25,5 @@ class VIEWS_EXPORT DesktopRootWindowHostObserverX11 {
} // namespace views
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_OBSERVER_X11_H_
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_OBSERVER_X11_H_
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_ozone.cc
index ffca2a6337c..1a78a9ab57e 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_ozone.cc
@@ -3,17 +3,17 @@
// found in the LICENSE file.
#include "ui/aura/window_tree_host.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
#include "ui/views/widget/desktop_aura/desktop_factory_ozone.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
namespace views {
-DesktopRootWindowHost* DesktopRootWindowHost::Create(
+DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura) {
DesktopFactoryOzone* d_factory = DesktopFactoryOzone::GetInstance();
- return d_factory->CreateRootWindowHost(native_widget_delegate,
+ return d_factory->CreateWindowTreeHost(native_widget_delegate,
desktop_native_widget_aura);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 938a05b2c4b..63475267815 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#include "base/win/metro.h"
#include "third_party/skia/include/core/SkPath.h"
@@ -10,11 +10,10 @@
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
#include "ui/base/cursor/cursor_loader_win.h"
#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/win/tsf_bridge.h"
#include "ui/base/win/shell.h"
#include "ui/compositor/compositor_constants.h"
#include "ui/gfx/insets.h"
@@ -25,11 +24,7 @@
#include "ui/gfx/win/dpi.h"
#include "ui/native_theme/native_theme_aura.h"
#include "ui/native_theme/native_theme_win.h"
-#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/views/corewm/corewm_switches.h"
-#include "ui/views/corewm/input_method_event_filter.h"
#include "ui/views/corewm/tooltip_win.h"
-#include "ui/views/corewm/window_animations.h"
#include "ui/views/ime/input_method_bridge.h"
#include "ui/views/widget/desktop_aura/desktop_cursor_loader_updater.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h"
@@ -40,7 +35,10 @@
#include "ui/views/widget/widget_hwnd_utils.h"
#include "ui/views/win/fullscreen_handler.h"
#include "ui/views/win/hwnd_message_handler.h"
-#include "ui/views/window/native_frame_view.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/input_method_event_filter.h"
+#include "ui/wm/core/window_animations.h"
+#include "ui/wm/public/scoped_tooltip_disabler.h"
namespace views {
@@ -64,18 +62,20 @@ void InsetBottomRight(gfx::Rect* rect, gfx::Vector2d vector) {
DEFINE_WINDOW_PROPERTY_KEY(aura::Window*, kContentWindowForRootWindow, NULL);
-// Identifies the DesktopRootWindowHostWin associated with the RootWindow.
-DEFINE_WINDOW_PROPERTY_KEY(DesktopRootWindowHostWin*, kDesktopRootWindowHostKey,
+// Identifies the DesktopWindowTreeHostWin associated with the
+// WindowEventDispatcher.
+DEFINE_WINDOW_PROPERTY_KEY(DesktopWindowTreeHostWin*, kDesktopWindowTreeHostKey,
NULL);
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, public:
+// DesktopWindowTreeHostWin, public:
-DesktopRootWindowHostWin::DesktopRootWindowHostWin(
+bool DesktopWindowTreeHostWin::is_cursor_visible_ = true;
+
+DesktopWindowTreeHostWin::DesktopWindowTreeHostWin(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura)
- : root_window_(NULL),
- message_handler_(new HWNDMessageHandler(this)),
+ : message_handler_(new HWNDMessageHandler(this)),
native_widget_delegate_(native_widget_delegate),
desktop_native_widget_aura_(desktop_native_widget_aura),
content_window_(NULL),
@@ -83,32 +83,31 @@ DesktopRootWindowHostWin::DesktopRootWindowHostWin(
should_animate_window_close_(false),
pending_close_(false),
has_non_client_view_(false),
- tooltip_(NULL),
- is_cursor_visible_(true) {
+ tooltip_(NULL) {
}
-DesktopRootWindowHostWin::~DesktopRootWindowHostWin() {
+DesktopWindowTreeHostWin::~DesktopWindowTreeHostWin() {
// WARNING: |content_window_| has been destroyed by the time we get here.
- desktop_native_widget_aura_->OnDesktopRootWindowHostDestroyed(
- root_window_);
+ desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
+ DestroyDispatcher();
}
// static
-aura::Window* DesktopRootWindowHostWin::GetContentWindowForHWND(HWND hwnd) {
- aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(hwnd);
- return root ? root->window()->GetProperty(kContentWindowForRootWindow) : NULL;
+aura::Window* DesktopWindowTreeHostWin::GetContentWindowForHWND(HWND hwnd) {
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(hwnd);
+ return host ? host->window()->GetProperty(kContentWindowForRootWindow) : NULL;
}
// static
-ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) {
+ui::NativeTheme* DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
// Use NativeThemeWin for windows shown on the desktop, those not on the
// desktop come from Ash and get NativeThemeAura.
- aura::WindowEventDispatcher* dispatcher =
- window ? window->GetDispatcher() : NULL;
- if (dispatcher) {
- HWND host_hwnd = dispatcher->host()->GetAcceleratedWidget();
+ aura::WindowTreeHost* host = window ? window->GetHost() : NULL;
+ if (host) {
+ HWND host_hwnd = host->GetAcceleratedWidget();
if (host_hwnd &&
- DesktopRootWindowHostWin::GetContentWindowForHWND(host_hwnd)) {
+ DesktopWindowTreeHostWin::GetContentWindowForHWND(host_hwnd)) {
return ui::NativeThemeWin::instance();
}
}
@@ -116,12 +115,10 @@ ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) {
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, DesktopRootWindowHost implementation:
+// DesktopWindowTreeHostWin, DesktopWindowTreeHost implementation:
-void DesktopRootWindowHostWin::Init(
- aura::Window* content_window,
- const Widget::InitParams& params,
- aura::RootWindow::CreateParams* rw_create_params) {
+void DesktopWindowTreeHostWin::Init(aura::Window* content_window,
+ const Widget::InitParams& params) {
// TODO(beng): SetInitParams().
content_window_ = content_window;
@@ -132,59 +129,56 @@ void DesktopRootWindowHostWin::Init(
native_widget_delegate_);
HWND parent_hwnd = NULL;
- if (params.parent && params.parent->GetDispatcher()) {
- parent_hwnd =
- params.parent->GetDispatcher()->host()->GetAcceleratedWidget();
- }
+ if (params.parent && params.parent->GetHost())
+ parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
message_handler_->set_remove_standard_frame(params.remove_standard_frame);
has_non_client_view_ = Widget::RequiresNonClientView(params.type);
+ gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
+ message_handler_->Init(parent_hwnd, pixel_bounds);
if (params.type == Widget::InitParams::TYPE_MENU) {
::SetProp(GetAcceleratedWidget(),
kForceSoftwareCompositor,
reinterpret_cast<HANDLE>(true));
}
-
- gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
- message_handler_->Init(parent_hwnd, pixel_bounds);
-
- rw_create_params->host = this;
+ CreateCompositor(GetAcceleratedWidget());
}
-void DesktopRootWindowHostWin::OnRootWindowCreated(
- aura::RootWindow* root,
+void DesktopWindowTreeHostWin::OnNativeWidgetCreated(
const Widget::InitParams& params) {
- root_window_ = root;
+ // The cursor is not necessarily visible when the root window is created.
+ aura::client::CursorClient* cursor_client =
+ aura::client::GetCursorClient(window());
+ if (cursor_client)
+ is_cursor_visible_ = cursor_client->IsCursorVisible();
- root_window_->window()->SetProperty(kContentWindowForRootWindow,
- content_window_);
- root_window_->window()->SetProperty(kDesktopRootWindowHostKey, this);
+ window()->SetProperty(kContentWindowForRootWindow, content_window_);
+ window()->SetProperty(kDesktopWindowTreeHostKey, this);
should_animate_window_close_ =
- content_window_->type() != aura::client::WINDOW_TYPE_NORMAL &&
- !views::corewm::WindowAnimationsDisabled(content_window_);
+ content_window_->type() != ui::wm::WINDOW_TYPE_NORMAL &&
+ !wm::WindowAnimationsDisabled(content_window_);
// TODO this is not invoked *after* Init(), but should be ok.
SetWindowTransparency();
}
-scoped_ptr<corewm::Tooltip> DesktopRootWindowHostWin::CreateTooltip() {
+scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostWin::CreateTooltip() {
DCHECK(!tooltip_);
tooltip_ = new corewm::TooltipWin(GetAcceleratedWidget());
return scoped_ptr<corewm::Tooltip>(tooltip_);
}
scoped_ptr<aura::client::DragDropClient>
-DesktopRootWindowHostWin::CreateDragDropClient(
+DesktopWindowTreeHostWin::CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) {
- drag_drop_client_ = new DesktopDragDropClientWin(root_window_->window(),
- GetHWND());
+ drag_drop_client_ = new DesktopDragDropClientWin(window(), GetHWND());
return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
}
-void DesktopRootWindowHostWin::Close() {
+void DesktopWindowTreeHostWin::Close() {
// TODO(beng): Move this entire branch to DNWA so it can be shared with X11.
if (should_animate_window_close_) {
pending_close_ = true;
@@ -200,30 +194,30 @@ void DesktopRootWindowHostWin::Close() {
}
}
-void DesktopRootWindowHostWin::CloseNow() {
+void DesktopWindowTreeHostWin::CloseNow() {
message_handler_->CloseNow();
}
-aura::RootWindowHost* DesktopRootWindowHostWin::AsRootWindowHost() {
+aura::WindowTreeHost* DesktopWindowTreeHostWin::AsWindowTreeHost() {
return this;
}
-void DesktopRootWindowHostWin::ShowWindowWithState(
+void DesktopWindowTreeHostWin::ShowWindowWithState(
ui::WindowShowState show_state) {
message_handler_->ShowWindowWithState(show_state);
}
-void DesktopRootWindowHostWin::ShowMaximizedWithBounds(
+void DesktopWindowTreeHostWin::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds);
message_handler_->ShowMaximizedWithBounds(pixel_bounds);
}
-bool DesktopRootWindowHostWin::IsVisible() const {
+bool DesktopWindowTreeHostWin::IsVisible() const {
return message_handler_->IsVisible();
}
-void DesktopRootWindowHostWin::SetSize(const gfx::Size& size) {
+void DesktopWindowTreeHostWin::SetSize(const gfx::Size& size) {
gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
gfx::Size expanded = GetExpandedWindowSize(
message_handler_->window_ex_style(), size_in_pixels);
@@ -233,11 +227,11 @@ void DesktopRootWindowHostWin::SetSize(const gfx::Size& size) {
message_handler_->SetSize(expanded);
}
-void DesktopRootWindowHostWin::StackAtTop() {
+void DesktopWindowTreeHostWin::StackAtTop() {
message_handler_->StackAtTop();
}
-void DesktopRootWindowHostWin::CenterWindow(const gfx::Size& size) {
+void DesktopWindowTreeHostWin::CenterWindow(const gfx::Size& size) {
gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
gfx::Size expanded_size;
expanded_size = GetExpandedWindowSize(message_handler_->window_ex_style(),
@@ -248,7 +242,7 @@ void DesktopRootWindowHostWin::CenterWindow(const gfx::Size& size) {
message_handler_->CenterWindow(expanded_size);
}
-void DesktopRootWindowHostWin::GetWindowPlacement(
+void DesktopWindowTreeHostWin::GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
message_handler_->GetWindowPlacement(bounds, show_state);
@@ -256,25 +250,25 @@ void DesktopRootWindowHostWin::GetWindowPlacement(
*bounds = gfx::win::ScreenToDIPRect(*bounds);
}
-gfx::Rect DesktopRootWindowHostWin::GetWindowBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostWin::GetWindowBoundsInScreen() const {
gfx::Rect pixel_bounds = message_handler_->GetWindowBoundsInScreen();
InsetBottomRight(&pixel_bounds, window_enlargement_);
return gfx::win::ScreenToDIPRect(pixel_bounds);
}
-gfx::Rect DesktopRootWindowHostWin::GetClientAreaBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() const {
gfx::Rect pixel_bounds = message_handler_->GetClientAreaBoundsInScreen();
InsetBottomRight(&pixel_bounds, window_enlargement_);
return gfx::win::ScreenToDIPRect(pixel_bounds);
}
-gfx::Rect DesktopRootWindowHostWin::GetRestoredBounds() const {
+gfx::Rect DesktopWindowTreeHostWin::GetRestoredBounds() const {
gfx::Rect pixel_bounds = message_handler_->GetRestoredBounds();
InsetBottomRight(&pixel_bounds, window_enlargement_);
return gfx::win::ScreenToDIPRect(pixel_bounds);
}
-gfx::Rect DesktopRootWindowHostWin::GetWorkAreaBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostWin::GetWorkAreaBoundsInScreen() const {
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(MonitorFromWindow(message_handler_->hwnd(),
@@ -284,7 +278,7 @@ gfx::Rect DesktopRootWindowHostWin::GetWorkAreaBoundsInScreen() const {
return gfx::win::ScreenToDIPRect(pixel_bounds);
}
-void DesktopRootWindowHostWin::SetShape(gfx::NativeRegion native_region) {
+void DesktopWindowTreeHostWin::SetShape(gfx::NativeRegion native_region) {
if (native_region) {
message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(*native_region));
} else {
@@ -294,59 +288,63 @@ void DesktopRootWindowHostWin::SetShape(gfx::NativeRegion native_region) {
delete native_region;
}
-void DesktopRootWindowHostWin::Activate() {
+void DesktopWindowTreeHostWin::Activate() {
message_handler_->Activate();
}
-void DesktopRootWindowHostWin::Deactivate() {
+void DesktopWindowTreeHostWin::Deactivate() {
message_handler_->Deactivate();
}
-bool DesktopRootWindowHostWin::IsActive() const {
+bool DesktopWindowTreeHostWin::IsActive() const {
return message_handler_->IsActive();
}
-void DesktopRootWindowHostWin::Maximize() {
+void DesktopWindowTreeHostWin::Maximize() {
message_handler_->Maximize();
}
-void DesktopRootWindowHostWin::Minimize() {
+void DesktopWindowTreeHostWin::Minimize() {
message_handler_->Minimize();
}
-void DesktopRootWindowHostWin::Restore() {
+void DesktopWindowTreeHostWin::Restore() {
message_handler_->Restore();
}
-bool DesktopRootWindowHostWin::IsMaximized() const {
+bool DesktopWindowTreeHostWin::IsMaximized() const {
return message_handler_->IsMaximized();
}
-bool DesktopRootWindowHostWin::IsMinimized() const {
+bool DesktopWindowTreeHostWin::IsMinimized() const {
return message_handler_->IsMinimized();
}
-bool DesktopRootWindowHostWin::HasCapture() const {
+bool DesktopWindowTreeHostWin::HasCapture() const {
return message_handler_->HasCapture();
}
-void DesktopRootWindowHostWin::SetAlwaysOnTop(bool always_on_top) {
+void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
message_handler_->SetAlwaysOnTop(always_on_top);
}
-bool DesktopRootWindowHostWin::IsAlwaysOnTop() const {
+bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
return message_handler_->IsAlwaysOnTop();
}
-bool DesktopRootWindowHostWin::SetWindowTitle(const string16& title) {
+void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
+ // Windows does not have the concept of workspaces.
+}
+
+bool DesktopWindowTreeHostWin::SetWindowTitle(const base::string16& title) {
return message_handler_->SetTitle(title);
}
-void DesktopRootWindowHostWin::ClearNativeFocus() {
+void DesktopWindowTreeHostWin::ClearNativeFocus() {
message_handler_->ClearNativeFocus();
}
-Widget::MoveLoopResult DesktopRootWindowHostWin::RunMoveLoop(
+Widget::MoveLoopResult DesktopWindowTreeHostWin::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source,
Widget::MoveLoopEscapeBehavior escape_behavior) {
@@ -356,31 +354,34 @@ Widget::MoveLoopResult DesktopRootWindowHostWin::RunMoveLoop(
Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
}
-void DesktopRootWindowHostWin::EndMoveLoop() {
+void DesktopWindowTreeHostWin::EndMoveLoop() {
message_handler_->EndMoveLoop();
}
-void DesktopRootWindowHostWin::SetVisibilityChangedAnimationsEnabled(
+void DesktopWindowTreeHostWin::SetVisibilityChangedAnimationsEnabled(
bool value) {
message_handler_->SetVisibilityChangedAnimationsEnabled(value);
content_window_->SetProperty(aura::client::kAnimationsDisabledKey, !value);
}
-bool DesktopRootWindowHostWin::ShouldUseNativeFrame() {
- return ui::win::IsAeroGlassEnabled();
+bool DesktopWindowTreeHostWin::ShouldUseNativeFrame() const {
+ return IsTranslucentWindowOpacitySupported();
}
-void DesktopRootWindowHostWin::FrameTypeChanged() {
- message_handler_->FrameTypeChanged();
- SetWindowTransparency();
+bool DesktopWindowTreeHostWin::ShouldWindowContentsBeTransparent() const {
+ // If the window has a native frame, we assume it is an Aero Glass window, and
+ // is therefore transparent. Note: This is not equivalent to calling
+ // IsAeroGlassEnabled, because ShouldUseNativeFrame is overridden in a
+ // subclass.
+ return ShouldUseNativeFrame();
}
-NonClientFrameView* DesktopRootWindowHostWin::CreateNonClientFrameView() {
- return GetWidget()->ShouldUseNativeFrame() ?
- new NativeFrameView(GetWidget()) : NULL;
+void DesktopWindowTreeHostWin::FrameTypeChanged() {
+ message_handler_->FrameTypeChanged();
+ SetWindowTransparency();
}
-void DesktopRootWindowHostWin::SetFullscreen(bool fullscreen) {
+void DesktopWindowTreeHostWin::SetFullscreen(bool fullscreen) {
message_handler_->fullscreen_handler()->SetFullscreen(fullscreen);
// TODO(sky): workaround for ScopedFullscreenVisibility showing window
// directly. Instead of this should listen for visibility changes and then
@@ -390,70 +391,70 @@ void DesktopRootWindowHostWin::SetFullscreen(bool fullscreen) {
SetWindowTransparency();
}
-bool DesktopRootWindowHostWin::IsFullscreen() const {
+bool DesktopWindowTreeHostWin::IsFullscreen() const {
return message_handler_->fullscreen_handler()->fullscreen();
}
-void DesktopRootWindowHostWin::SetOpacity(unsigned char opacity) {
+void DesktopWindowTreeHostWin::SetOpacity(unsigned char opacity) {
message_handler_->SetOpacity(static_cast<BYTE>(opacity));
content_window_->layer()->SetOpacity(opacity / 255.0);
}
-void DesktopRootWindowHostWin::SetWindowIcons(
+void DesktopWindowTreeHostWin::SetWindowIcons(
const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
message_handler_->SetWindowIcons(window_icon, app_icon);
}
-void DesktopRootWindowHostWin::InitModalType(ui::ModalType modal_type) {
+void DesktopWindowTreeHostWin::InitModalType(ui::ModalType modal_type) {
message_handler_->InitModalType(modal_type);
}
-void DesktopRootWindowHostWin::FlashFrame(bool flash_frame) {
+void DesktopWindowTreeHostWin::FlashFrame(bool flash_frame) {
message_handler_->FlashFrame(flash_frame);
}
-void DesktopRootWindowHostWin::OnRootViewLayout() const {
+void DesktopWindowTreeHostWin::OnRootViewLayout() const {
}
-void DesktopRootWindowHostWin::OnNativeWidgetFocus() {
+void DesktopWindowTreeHostWin::OnNativeWidgetFocus() {
// HWNDMessageHandler will perform the proper updating on its own.
}
-void DesktopRootWindowHostWin::OnNativeWidgetBlur() {
+void DesktopWindowTreeHostWin::OnNativeWidgetBlur() {
}
-bool DesktopRootWindowHostWin::IsAnimatingClosed() const {
+bool DesktopWindowTreeHostWin::IsAnimatingClosed() const {
return pending_close_;
}
+bool DesktopWindowTreeHostWin::IsTranslucentWindowOpacitySupported() const {
+ return ui::win::IsAeroGlassEnabled();
+}
+
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, RootWindowHost implementation:
+// DesktopWindowTreeHostWin, WindowTreeHost implementation:
-aura::RootWindow* DesktopRootWindowHostWin::GetRootWindow() {
- return root_window_;
+ui::EventSource* DesktopWindowTreeHostWin::GetEventSource() {
+ return this;
}
-gfx::AcceleratedWidget DesktopRootWindowHostWin::GetAcceleratedWidget() {
+gfx::AcceleratedWidget DesktopWindowTreeHostWin::GetAcceleratedWidget() {
return message_handler_->hwnd();
}
-void DesktopRootWindowHostWin::Show() {
+void DesktopWindowTreeHostWin::Show() {
message_handler_->Show();
}
-void DesktopRootWindowHostWin::Hide() {
+void DesktopWindowTreeHostWin::Hide() {
if (!pending_close_)
message_handler_->Hide();
}
-void DesktopRootWindowHostWin::ToggleFullScreen() {
- SetWindowTransparency();
-}
-
// GetBounds and SetBounds work in pixel coordinates, whereas other get/set
// methods work in DIP.
-gfx::Rect DesktopRootWindowHostWin::GetBounds() const {
+gfx::Rect DesktopWindowTreeHostWin::GetBounds() const {
gfx::Rect bounds(message_handler_->GetClientAreaBounds());
// If the window bounds were expanded we need to return the original bounds
// To achieve this we do the reverse of the expansion, i.e. add the
@@ -469,7 +470,7 @@ gfx::Rect DesktopRootWindowHostWin::GetBounds() const {
return without_expansion;
}
-void DesktopRootWindowHostWin::SetBounds(const gfx::Rect& bounds) {
+void DesktopWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
// If the window bounds have to be expanded we need to subtract the
// window_expansion_top_left_delta_ from the origin and add the
// window_expansion_bottom_right_delta_ to the width and height
@@ -489,92 +490,60 @@ void DesktopRootWindowHostWin::SetBounds(const gfx::Rect& bounds) {
window_enlargement_ =
gfx::Vector2d(new_expanded.width() - expanded.width(),
new_expanded.height() - expanded.height());
- message_handler_->SetBounds(new_expanded);
-
- // The client area size may have changed even though the window bounds have
- // not, if the window bounds were expanded to 64 pixels both times.
- if (old_hwnd_size == new_expanded.size() && old_content_size != bounds.size())
- HandleClientSizeChanged(new_expanded.size());
-}
-
-gfx::Insets DesktopRootWindowHostWin::GetInsets() const {
- return gfx::Insets();
-}
-
-void DesktopRootWindowHostWin::SetInsets(const gfx::Insets& insets) {
+ message_handler_->SetBounds(new_expanded, old_content_size != bounds.size());
}
-gfx::Point DesktopRootWindowHostWin::GetLocationOnNativeScreen() const {
+gfx::Point DesktopWindowTreeHostWin::GetLocationOnNativeScreen() const {
return GetBounds().origin();
}
-void DesktopRootWindowHostWin::SetCapture() {
+void DesktopWindowTreeHostWin::SetCapture() {
message_handler_->SetCapture();
}
-void DesktopRootWindowHostWin::ReleaseCapture() {
+void DesktopWindowTreeHostWin::ReleaseCapture() {
message_handler_->ReleaseCapture();
}
-void DesktopRootWindowHostWin::SetCursor(gfx::NativeCursor cursor) {
- ui::CursorLoaderWin cursor_loader;
- cursor_loader.SetPlatformCursor(&cursor);
-
- message_handler_->SetCursor(cursor.platform());
+void DesktopWindowTreeHostWin::PostNativeEvent(
+ const base::NativeEvent& native_event) {
}
-bool DesktopRootWindowHostWin::QueryMouseLocation(gfx::Point* location_return) {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root_window_->window());
- if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
- *location_return = gfx::Point(0, 0);
- return false;
- }
- POINT pt = {0};
- ::GetCursorPos(&pt);
- *location_return =
- gfx::Point(static_cast<int>(pt.x), static_cast<int>(pt.y));
- return true;
+void DesktopWindowTreeHostWin::OnDeviceScaleFactorChanged(
+ float device_scale_factor) {
}
-bool DesktopRootWindowHostWin::ConfineCursorToRootWindow() {
- RECT window_rect = root_window_->window()->GetBoundsInScreen().ToRECT();
- ::ClipCursor(&window_rect);
- return true;
-}
+void DesktopWindowTreeHostWin::SetCursorNative(gfx::NativeCursor cursor) {
+ ui::CursorLoaderWin cursor_loader;
+ cursor_loader.SetPlatformCursor(&cursor);
-void DesktopRootWindowHostWin::UnConfineCursor() {
- ::ClipCursor(NULL);
+ message_handler_->SetCursor(cursor.platform());
}
-void DesktopRootWindowHostWin::OnCursorVisibilityChanged(bool show) {
+void DesktopWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
if (is_cursor_visible_ == show)
return;
is_cursor_visible_ = show;
::ShowCursor(!!show);
}
-void DesktopRootWindowHostWin::MoveCursorTo(const gfx::Point& location) {
+void DesktopWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
POINT cursor_location = location.ToPOINT();
::ClientToScreen(GetHWND(), &cursor_location);
::SetCursorPos(cursor_location.x, cursor_location.y);
}
-void DesktopRootWindowHostWin::PostNativeEvent(
- const base::NativeEvent& native_event) {
-}
-
-void DesktopRootWindowHostWin::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
-}
+////////////////////////////////////////////////////////////////////////////////
+// DesktopWindowTreeHostWin, ui::EventSource implementation:
-void DesktopRootWindowHostWin::PrepareForShutdown() {
+ui::EventProcessor* DesktopWindowTreeHostWin::GetEventProcessor() {
+ return dispatcher();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, aura::AnimationHost implementation:
+// DesktopWindowTreeHostWin, aura::AnimationHost implementation:
-void DesktopRootWindowHostWin::SetHostTransitionOffsets(
+void DesktopWindowTreeHostWin::SetHostTransitionOffsets(
const gfx::Vector2d& top_left_delta,
const gfx::Vector2d& bottom_right_delta) {
gfx::Rect bounds_without_expansion = GetBounds();
@@ -583,88 +552,72 @@ void DesktopRootWindowHostWin::SetHostTransitionOffsets(
SetBounds(bounds_without_expansion);
}
-void DesktopRootWindowHostWin::OnWindowHidingAnimationCompleted() {
+void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() {
if (pending_close_)
message_handler_->Close();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, HWNDMessageHandlerDelegate implementation:
+// DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation:
-bool DesktopRootWindowHostWin::IsWidgetWindow() const {
+bool DesktopWindowTreeHostWin::IsWidgetWindow() const {
return has_non_client_view_;
}
-bool DesktopRootWindowHostWin::IsUsingCustomFrame() const {
+bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const {
return !GetWidget()->ShouldUseNativeFrame();
}
-void DesktopRootWindowHostWin::SchedulePaint() {
+void DesktopWindowTreeHostWin::SchedulePaint() {
GetWidget()->GetRootView()->SchedulePaint();
}
-void DesktopRootWindowHostWin::EnableInactiveRendering() {
+void DesktopWindowTreeHostWin::EnableInactiveRendering() {
native_widget_delegate_->EnableInactiveRendering();
}
-bool DesktopRootWindowHostWin::IsInactiveRenderingDisabled() {
+bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() {
return native_widget_delegate_->IsInactiveRenderingDisabled();
}
-bool DesktopRootWindowHostWin::CanResize() const {
+bool DesktopWindowTreeHostWin::CanResize() const {
return GetWidget()->widget_delegate()->CanResize();
}
-bool DesktopRootWindowHostWin::CanMaximize() const {
+bool DesktopWindowTreeHostWin::CanMaximize() const {
return GetWidget()->widget_delegate()->CanMaximize();
}
-bool DesktopRootWindowHostWin::CanActivate() const {
+bool DesktopWindowTreeHostWin::CanActivate() const {
if (IsModalWindowActive())
return true;
return native_widget_delegate_->CanActivate();
}
-bool DesktopRootWindowHostWin::WidgetSizeIsClientSize() const {
+bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const {
const Widget* widget = GetWidget()->GetTopLevelWidget();
return IsMaximized() || (widget && widget->ShouldUseNativeFrame());
}
-bool DesktopRootWindowHostWin::CanSaveFocus() const {
- return GetWidget()->is_top_level();
-}
-
-void DesktopRootWindowHostWin::SaveFocusOnDeactivate() {
- GetWidget()->GetFocusManager()->StoreFocusedView(true);
-}
-
-void DesktopRootWindowHostWin::RestoreFocusOnActivate() {
- RestoreFocusOnEnable();
-}
-
-void DesktopRootWindowHostWin::RestoreFocusOnEnable() {
- GetWidget()->GetFocusManager()->RestoreFocusedView();
-}
-
-bool DesktopRootWindowHostWin::IsModal() const {
+bool DesktopWindowTreeHostWin::IsModal() const {
return native_widget_delegate_->IsModal();
}
-int DesktopRootWindowHostWin::GetInitialShowState() const {
- return SW_SHOWNORMAL;
+int DesktopWindowTreeHostWin::GetInitialShowState() const {
+ return CanActivate() ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE;
}
-bool DesktopRootWindowHostWin::WillProcessWorkAreaChange() const {
+bool DesktopWindowTreeHostWin::WillProcessWorkAreaChange() const {
return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
}
-int DesktopRootWindowHostWin::GetNonClientComponent(
+int DesktopWindowTreeHostWin::GetNonClientComponent(
const gfx::Point& point) const {
gfx::Point dip_position = gfx::win::ScreenToDIPPoint(point);
return native_widget_delegate_->GetNonClientComponent(dip_position);
}
-void DesktopRootWindowHostWin::GetWindowMask(const gfx::Size& size,
+void DesktopWindowTreeHostWin::GetWindowMask(const gfx::Size& size,
gfx::Path* path) {
if (GetWidget()->non_client_view()) {
GetWidget()->non_client_view()->GetWindowMask(size, path);
@@ -677,193 +630,192 @@ void DesktopRootWindowHostWin::GetWindowMask(const gfx::Size& size,
}
}
-bool DesktopRootWindowHostWin::GetClientAreaInsets(gfx::Insets* insets) const {
+bool DesktopWindowTreeHostWin::GetClientAreaInsets(gfx::Insets* insets) const {
return false;
}
-void DesktopRootWindowHostWin::GetMinMaxSize(gfx::Size* min_size,
+void DesktopWindowTreeHostWin::GetMinMaxSize(gfx::Size* min_size,
gfx::Size* max_size) const {
*min_size = native_widget_delegate_->GetMinimumSize();
*max_size = native_widget_delegate_->GetMaximumSize();
}
-gfx::Size DesktopRootWindowHostWin::GetRootViewSize() const {
+gfx::Size DesktopWindowTreeHostWin::GetRootViewSize() const {
return GetWidget()->GetRootView()->size();
}
-void DesktopRootWindowHostWin::ResetWindowControls() {
+void DesktopWindowTreeHostWin::ResetWindowControls() {
GetWidget()->non_client_view()->ResetWindowControls();
}
-void DesktopRootWindowHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
- GetWidget()->GetRootView()->Paint(canvas);
+void DesktopWindowTreeHostWin::PaintLayeredWindow(gfx::Canvas* canvas) {
+ GetWidget()->GetRootView()->Paint(canvas, views::CullSet());
}
-gfx::NativeViewAccessible DesktopRootWindowHostWin::GetNativeViewAccessible() {
+gfx::NativeViewAccessible DesktopWindowTreeHostWin::GetNativeViewAccessible() {
return GetWidget()->GetRootView()->GetNativeViewAccessible();
}
-InputMethod* DesktopRootWindowHostWin::GetInputMethod() {
+InputMethod* DesktopWindowTreeHostWin::GetInputMethod() {
return GetWidget()->GetInputMethodDirect();
}
-bool DesktopRootWindowHostWin::ShouldHandleSystemCommands() const {
+bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const {
return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
}
-void DesktopRootWindowHostWin::HandleAppDeactivated() {
+void DesktopWindowTreeHostWin::HandleAppDeactivated() {
native_widget_delegate_->EnableInactiveRendering();
}
-void DesktopRootWindowHostWin::HandleActivationChanged(bool active) {
+void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) {
// This can be invoked from HWNDMessageHandler::Init(), at which point we're
// not in a good state and need to ignore it.
- if (!delegate_)
+ // TODO(beng): Do we need this still now the host owns the dispatcher?
+ if (!dispatcher())
return;
if (active)
- delegate_->OnHostActivated();
+ OnHostActivated();
desktop_native_widget_aura_->HandleActivationChanged(active);
}
-bool DesktopRootWindowHostWin::HandleAppCommand(short command) {
+bool DesktopWindowTreeHostWin::HandleAppCommand(short command) {
// We treat APPCOMMAND ids as an extension of our command namespace, and just
// let the delegate figure out what to do...
return GetWidget()->widget_delegate() &&
GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
}
-void DesktopRootWindowHostWin::HandleCancelMode() {
- delegate_->OnHostCancelMode();
+void DesktopWindowTreeHostWin::HandleCancelMode() {
+ dispatcher()->DispatchCancelModeEvent();
}
-void DesktopRootWindowHostWin::HandleCaptureLost() {
- delegate_->OnHostLostWindowCapture();
+void DesktopWindowTreeHostWin::HandleCaptureLost() {
+ OnHostLostWindowCapture();
native_widget_delegate_->OnMouseCaptureLost();
}
-void DesktopRootWindowHostWin::HandleClose() {
+void DesktopWindowTreeHostWin::HandleClose() {
GetWidget()->Close();
}
-bool DesktopRootWindowHostWin::HandleCommand(int command) {
+bool DesktopWindowTreeHostWin::HandleCommand(int command) {
return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
}
-void DesktopRootWindowHostWin::HandleAccelerator(
+void DesktopWindowTreeHostWin::HandleAccelerator(
const ui::Accelerator& accelerator) {
GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
}
-void DesktopRootWindowHostWin::HandleCreate() {
- // TODO(beng): moar
- NOTIMPLEMENTED();
-
+void DesktopWindowTreeHostWin::HandleCreate() {
native_widget_delegate_->OnNativeWidgetCreated(true);
-
- // 1. Window property association
- // 2. MouseWheel.
}
-void DesktopRootWindowHostWin::HandleDestroying() {
+void DesktopWindowTreeHostWin::HandleDestroying() {
drag_drop_client_->OnNativeWidgetDestroying(GetHWND());
native_widget_delegate_->OnNativeWidgetDestroying();
+
+ // Destroy the compositor before destroying the HWND since shutdown
+ // may try to swap to the window.
+ DestroyCompositor();
}
-void DesktopRootWindowHostWin::HandleDestroyed() {
+void DesktopWindowTreeHostWin::HandleDestroyed() {
desktop_native_widget_aura_->OnHostClosed();
}
-bool DesktopRootWindowHostWin::HandleInitialFocus() {
- return GetWidget()->SetInitialFocus();
+bool DesktopWindowTreeHostWin::HandleInitialFocus(
+ ui::WindowShowState show_state) {
+ return GetWidget()->SetInitialFocus(show_state);
}
-void DesktopRootWindowHostWin::HandleDisplayChange() {
+void DesktopWindowTreeHostWin::HandleDisplayChange() {
GetWidget()->widget_delegate()->OnDisplayChanged();
}
-void DesktopRootWindowHostWin::HandleBeginWMSizeMove() {
+void DesktopWindowTreeHostWin::HandleBeginWMSizeMove() {
native_widget_delegate_->OnNativeWidgetBeginUserBoundsChange();
}
-void DesktopRootWindowHostWin::HandleEndWMSizeMove() {
+void DesktopWindowTreeHostWin::HandleEndWMSizeMove() {
native_widget_delegate_->OnNativeWidgetEndUserBoundsChange();
}
-void DesktopRootWindowHostWin::HandleMove() {
+void DesktopWindowTreeHostWin::HandleMove() {
native_widget_delegate_->OnNativeWidgetMove();
- if (delegate_)
- delegate_->OnHostMoved(GetBounds().origin());
+ OnHostMoved(GetBounds().origin());
}
-void DesktopRootWindowHostWin::HandleWorkAreaChanged() {
+void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
GetWidget()->widget_delegate()->OnWorkAreaChanged();
}
-void DesktopRootWindowHostWin::HandleVisibilityChanging(bool visible) {
+void DesktopWindowTreeHostWin::HandleVisibilityChanging(bool visible) {
native_widget_delegate_->OnNativeWidgetVisibilityChanging(visible);
}
-void DesktopRootWindowHostWin::HandleVisibilityChanged(bool visible) {
+void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
}
-void DesktopRootWindowHostWin::HandleClientSizeChanged(
+void DesktopWindowTreeHostWin::HandleClientSizeChanged(
const gfx::Size& new_size) {
- if (delegate_)
- delegate_->OnHostResized(new_size);
+ if (dispatcher())
+ OnHostResized(new_size);
}
-void DesktopRootWindowHostWin::HandleFrameChanged() {
+void DesktopWindowTreeHostWin::HandleFrameChanged() {
SetWindowTransparency();
// Replace the frame and layout the contents.
GetWidget()->non_client_view()->UpdateFrame();
}
-void DesktopRootWindowHostWin::HandleNativeFocus(HWND last_focused_window) {
+void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
// TODO(beng): inform the native_widget_delegate_.
InputMethod* input_method = GetInputMethod();
if (input_method)
input_method->OnFocus();
}
-void DesktopRootWindowHostWin::HandleNativeBlur(HWND focused_window) {
+void DesktopWindowTreeHostWin::HandleNativeBlur(HWND focused_window) {
// TODO(beng): inform the native_widget_delegate_.
InputMethod* input_method = GetInputMethod();
if (input_method)
input_method->OnBlur();
}
-bool DesktopRootWindowHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
- if (base::win::IsTSFAwareRequired() && event.IsAnyButton())
- ui::TSFBridge::GetInstance()->CancelComposition();
- return delegate_->OnHostMouseEvent(const_cast<ui::MouseEvent*>(&event));
+bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
+ SendEventToProcessor(const_cast<ui::MouseEvent*>(&event));
+ return event.handled();
}
-bool DesktopRootWindowHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
+bool DesktopWindowTreeHostWin::HandleKeyEvent(const ui::KeyEvent& event) {
return false;
}
-bool DesktopRootWindowHostWin::HandleUntranslatedKeyEvent(
+bool DesktopWindowTreeHostWin::HandleUntranslatedKeyEvent(
const ui::KeyEvent& event) {
ui::KeyEvent duplicate_event(event);
- return delegate_->OnHostKeyEvent(&duplicate_event);
+ SendEventToProcessor(&duplicate_event);
+ return duplicate_event.handled();
}
-void DesktopRootWindowHostWin::HandleTouchEvent(
+void DesktopWindowTreeHostWin::HandleTouchEvent(
const ui::TouchEvent& event) {
// HWNDMessageHandler asynchronously processes touch events. Because of this
- // it's possible for the aura::RootWindow to have been destroyed by the time
- // we attempt to process them.
+ // it's possible for the aura::WindowEventDispatcher to have been destroyed
+ // by the time we attempt to process them.
if (!GetWidget()->GetNativeView())
return;
// Currently we assume the window that has capture gets touch events too.
- aura::RootWindow* root =
- aura::RootWindow::GetForAcceleratedWidget(GetCapture());
- if (root) {
- DesktopRootWindowHostWin* target =
- root->window()->GetProperty(kDesktopRootWindowHostKey);
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(GetCapture());
+ if (host) {
+ DesktopWindowTreeHostWin* target =
+ host->window()->GetProperty(kDesktopWindowTreeHostKey);
if (target && target->HasCapture() && target != this) {
POINT target_location(event.location().ToPOINT());
ClientToScreen(GetHWND(), &target_location);
@@ -872,15 +824,14 @@ void DesktopRootWindowHostWin::HandleTouchEvent(
static_cast<View*>(NULL));
target_event.set_location(gfx::Point(target_location));
target_event.set_root_location(target_event.location());
- target->delegate_->OnHostTouchEvent(&target_event);
+ target->SendEventToProcessor(&target_event);
return;
}
}
- delegate_->OnHostTouchEvent(
- const_cast<ui::TouchEvent*>(&event));
+ SendEventToProcessor(const_cast<ui::TouchEvent*>(&event));
}
-bool DesktopRootWindowHostWin::HandleIMEMessage(UINT message,
+bool DesktopWindowTreeHostWin::HandleIMEMessage(UINT message,
WPARAM w_param,
LPARAM l_param,
LRESULT* result) {
@@ -893,83 +844,100 @@ bool DesktopRootWindowHostWin::HandleIMEMessage(UINT message,
input_method()->OnUntranslatedIMEMessage(msg, result);
}
-void DesktopRootWindowHostWin::HandleInputLanguageChange(
+void DesktopWindowTreeHostWin::HandleInputLanguageChange(
DWORD character_set,
HKL input_language_id) {
desktop_native_widget_aura_->input_method_event_filter()->
input_method()->OnInputLocaleChanged();
}
-bool DesktopRootWindowHostWin::HandlePaintAccelerated(
+bool DesktopWindowTreeHostWin::HandlePaintAccelerated(
const gfx::Rect& invalid_rect) {
return native_widget_delegate_->OnNativeWidgetPaintAccelerated(invalid_rect);
}
-void DesktopRootWindowHostWin::HandlePaint(gfx::Canvas* canvas) {
- delegate_->OnHostPaint(gfx::Rect());
+void DesktopWindowTreeHostWin::HandlePaint(gfx::Canvas* canvas) {
+ // It appears possible to get WM_PAINT after WM_DESTROY.
+ if (compositor())
+ compositor()->ScheduleRedrawRect(gfx::Rect());
}
-bool DesktopRootWindowHostWin::HandleTooltipNotify(int w_param,
+bool DesktopWindowTreeHostWin::HandleTooltipNotify(int w_param,
NMHDR* l_param,
LRESULT* l_result) {
return tooltip_ && tooltip_->HandleNotify(w_param, l_param, l_result);
}
-void DesktopRootWindowHostWin::HandleTooltipMouseMove(UINT message,
+void DesktopWindowTreeHostWin::HandleTooltipMouseMove(UINT message,
WPARAM w_param,
LPARAM l_param) {
// TooltipWin implementation doesn't need this.
// TODO(sky): remove from HWNDMessageHandler once non-aura path nuked.
}
-bool DesktopRootWindowHostWin::PreHandleMSG(UINT message,
+void DesktopWindowTreeHostWin::HandleMenuLoop(bool in_menu_loop) {
+ if (in_menu_loop) {
+ tooltip_disabler_.reset(
+ new aura::client::ScopedTooltipDisabler(window()));
+ } else {
+ tooltip_disabler_.reset();
+ }
+}
+
+bool DesktopWindowTreeHostWin::PreHandleMSG(UINT message,
WPARAM w_param,
LPARAM l_param,
LRESULT* result) {
return false;
}
-void DesktopRootWindowHostWin::PostHandleMSG(UINT message,
+void DesktopWindowTreeHostWin::PostHandleMSG(UINT message,
WPARAM w_param,
LPARAM l_param) {
}
-bool DesktopRootWindowHostWin::HandleScrollEvent(
+bool DesktopWindowTreeHostWin::HandleScrollEvent(
const ui::ScrollEvent& event) {
- return delegate_->OnHostScrollEvent(const_cast<ui::ScrollEvent*>(&event));
+ SendEventToProcessor(const_cast<ui::ScrollEvent*>(&event));
+ return event.handled();
+}
+
+void DesktopWindowTreeHostWin::HandleWindowSizeChanging() {
+ if (compositor())
+ compositor()->FinishAllRendering();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostWin, private:
+// DesktopWindowTreeHostWin, private:
-Widget* DesktopRootWindowHostWin::GetWidget() {
+Widget* DesktopWindowTreeHostWin::GetWidget() {
return native_widget_delegate_->AsWidget();
}
-const Widget* DesktopRootWindowHostWin::GetWidget() const {
+const Widget* DesktopWindowTreeHostWin::GetWidget() const {
return native_widget_delegate_->AsWidget();
}
-HWND DesktopRootWindowHostWin::GetHWND() const {
+HWND DesktopWindowTreeHostWin::GetHWND() const {
return message_handler_->hwnd();
}
-void DesktopRootWindowHostWin::SetWindowTransparency() {
+void DesktopWindowTreeHostWin::SetWindowTransparency() {
bool transparent = ShouldUseNativeFrame() && !IsFullscreen();
- root_window_->compositor()->SetHostHasTransparentBackground(transparent);
- root_window_->window()->SetTransparent(transparent);
+ compositor()->SetHostHasTransparentBackground(transparent);
+ window()->SetTransparent(transparent);
content_window_->SetTransparent(transparent);
}
-bool DesktopRootWindowHostWin::IsModalWindowActive() const {
+bool DesktopWindowTreeHostWin::IsModalWindowActive() const {
// This function can get called during window creation which occurs before
- // root_window_ has been created.
- if (!root_window_)
+ // dispatcher() has been created.
+ if (!dispatcher())
return false;
aura::Window::Windows::const_iterator index;
- for (index = root_window_->window()->children().begin();
- index != root_window_->window()->children().end();
+ for (index = window()->children().begin();
+ index != window()->children().end();
++index) {
if ((*index)->GetProperty(aura::client::kModalKey) !=
ui:: MODAL_TYPE_NONE && (*index)->TargetVisibility())
@@ -979,13 +947,13 @@ bool DesktopRootWindowHostWin::IsModalWindowActive() const {
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHost, public:
+// DesktopWindowTreeHost, public:
// static
-DesktopRootWindowHost* DesktopRootWindowHost::Create(
+DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura) {
- return new DesktopRootWindowHostWin(native_widget_delegate,
+ return new DesktopWindowTreeHostWin(native_widget_delegate,
desktop_native_widget_aura);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index e4ed8eaeb8f..225365f5b14 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_WIN_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_WIN_H_
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_WIN_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_WIN_H_
-#include "ui/aura/client/animation_host.h"
#include "ui/aura/window_tree_host.h"
#include "ui/views/views_export.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/win/hwnd_message_handler_delegate.h"
+#include "ui/wm/public/animation_host.h"
namespace aura {
namespace client {
class DragDropClient;
class FocusClient;
+class ScopedTooltipDisabler;
}
}
@@ -27,33 +28,32 @@ namespace corewm {
class TooltipWin;
}
-class VIEWS_EXPORT DesktopRootWindowHostWin
- : public DesktopRootWindowHost,
+class VIEWS_EXPORT DesktopWindowTreeHostWin
+ : public DesktopWindowTreeHost,
public aura::client::AnimationHost,
- public aura::RootWindowHost,
+ public aura::WindowTreeHost,
+ public ui::EventSource,
public HWNDMessageHandlerDelegate {
public:
- DesktopRootWindowHostWin(
+ DesktopWindowTreeHostWin(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura);
- virtual ~DesktopRootWindowHostWin();
+ virtual ~DesktopWindowTreeHostWin();
// A way of converting an HWND into a content window.
static aura::Window* GetContentWindowForHWND(HWND hwnd);
protected:
- // Overridden from DesktopRootWindowHost:
+ // Overridden from DesktopWindowTreeHost:
virtual void Init(aura::Window* content_window,
- const Widget::InitParams& params,
- aura::RootWindow::CreateParams* rw_create_params) OVERRIDE;
- virtual void OnRootWindowCreated(aura::RootWindow* root,
- const Widget::InitParams& params) OVERRIDE;
+ const Widget::InitParams& params) OVERRIDE;
+ virtual void OnNativeWidgetCreated(const Widget::InitParams& params) OVERRIDE;
virtual scoped_ptr<corewm::Tooltip> CreateTooltip() OVERRIDE;
virtual scoped_ptr<aura::client::DragDropClient>
CreateDragDropClient(DesktopNativeCursorManager* cursor_manager) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void CloseNow() OVERRIDE;
- virtual aura::RootWindowHost* AsRootWindowHost() OVERRIDE;
+ virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE;
virtual void ShowWindowWithState(ui::WindowShowState show_state) OVERRIDE;
virtual void ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) OVERRIDE;
@@ -80,7 +80,8 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual bool HasCapture() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
virtual bool IsAlwaysOnTop() const OVERRIDE;
- virtual bool SetWindowTitle(const string16& title) OVERRIDE;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) OVERRIDE;
+ virtual bool SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void ClearNativeFocus() OVERRIDE;
virtual Widget::MoveLoopResult RunMoveLoop(
const gfx::Vector2d& drag_offset,
@@ -88,9 +89,9 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
Widget::MoveLoopEscapeBehavior escape_behavior) OVERRIDE;
virtual void EndMoveLoop() OVERRIDE;
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
- virtual bool ShouldUseNativeFrame() OVERRIDE;
+ virtual bool ShouldUseNativeFrame() const OVERRIDE;
+ virtual bool ShouldWindowContentsBeTransparent() const OVERRIDE;
virtual void FrameTypeChanged() OVERRIDE;
- virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
virtual void SetFullscreen(bool fullscreen) OVERRIDE;
virtual bool IsFullscreen() const OVERRIDE;
virtual void SetOpacity(unsigned char opacity) OVERRIDE;
@@ -102,29 +103,26 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual void OnNativeWidgetFocus() OVERRIDE;
virtual void OnNativeWidgetBlur() OVERRIDE;
virtual bool IsAnimatingClosed() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
- // Overridden from aura::RootWindowHost:
- virtual aura::RootWindow* GetRootWindow() OVERRIDE;
+ // Overridden from aura::WindowTreeHost:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
virtual void Show() OVERRIDE;
virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
virtual gfx::Rect GetBounds() const OVERRIDE;
virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
virtual void SetCapture() OVERRIDE;
virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+
+ // Overridden frm ui::EventSource
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
// Overridden from aura::client::AnimationHost
virtual void SetHostTransitionOffsets(
@@ -142,10 +140,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual bool CanMaximize() const OVERRIDE;
virtual bool CanActivate() const OVERRIDE;
virtual bool WidgetSizeIsClientSize() const OVERRIDE;
- virtual bool CanSaveFocus() const OVERRIDE;
- virtual void SaveFocusOnDeactivate() OVERRIDE;
- virtual void RestoreFocusOnActivate() OVERRIDE;
- virtual void RestoreFocusOnEnable() OVERRIDE;
virtual bool IsModal() const OVERRIDE;
virtual int GetInitialShowState() const OVERRIDE;
virtual bool WillProcessWorkAreaChange() const OVERRIDE;
@@ -171,7 +165,7 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual void HandleCreate() OVERRIDE;
virtual void HandleDestroying() OVERRIDE;
virtual void HandleDestroyed() OVERRIDE;
- virtual bool HandleInitialFocus() OVERRIDE;
+ virtual bool HandleInitialFocus(ui::WindowShowState show_state) OVERRIDE;
virtual void HandleDisplayChange() OVERRIDE;
virtual void HandleBeginWMSizeMove() OVERRIDE;
virtual void HandleEndWMSizeMove() OVERRIDE;
@@ -201,6 +195,7 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
virtual void HandleTooltipMouseMove(UINT message,
WPARAM w_param,
LPARAM l_param) OVERRIDE;
+ virtual void HandleMenuLoop(bool in_menu_loop) OVERRIDE;
virtual bool PreHandleMSG(UINT message,
WPARAM w_param,
LPARAM l_param,
@@ -209,6 +204,7 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
WPARAM w_param,
LPARAM l_param) OVERRIDE;
virtual bool HandleScrollEvent(const ui::ScrollEvent& event) OVERRIDE;
+ virtual void HandleWindowSizeChanging() OVERRIDE;
Widget* GetWidget();
const Widget* GetWidget() const;
@@ -220,9 +216,6 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
// Returns true if a modal window is active in the current root window chain.
bool IsModalWindowActive() const;
- // We are owned by the RootWindow, but we have to have a back pointer to it.
- aura::RootWindow* root_window_;
-
scoped_ptr<HWNDMessageHandler> message_handler_;
scoped_ptr<aura::client::FocusClient> focus_client_;
@@ -267,12 +260,17 @@ class VIEWS_EXPORT DesktopRootWindowHostWin
// a reference.
corewm::TooltipWin* tooltip_;
- // State of the cursor.
- bool is_cursor_visible_;
+ // Visibility of the cursor. On Windows we can have multiple root windows and
+ // the implementation of ::ShowCursor() is based on a counter, so making this
+ // member static ensures that ::ShowCursor() is always called exactly once
+ // whenever the cursor visibility state changes.
+ static bool is_cursor_visible_;
+
+ scoped_ptr<aura::client::ScopedTooltipDisabler> tooltip_disabler_;
- DISALLOW_COPY_AND_ASSIGN(DesktopRootWindowHostWin);
+ DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostWin);
};
} // namespace views
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_WIN_H_
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_WIN_H_
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 545e0cde550..9a96e53c283 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/XInput2.h>
@@ -11,20 +11,22 @@
#include <X11/Xutil.h>
#include "base/basictypes.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#include "base/message_loop/message_pump_x11.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/user_action_client.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_property.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
+#include "ui/base/hit_test.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/event_utils.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/events/x/device_data_manager.h"
#include "ui/events/x/device_list_cache_x.h"
#include "ui/events/x/touch_factory_x11.h"
@@ -33,49 +35,54 @@
#include "ui/gfx/insets.h"
#include "ui/gfx/path.h"
#include "ui/gfx/path_x11.h"
+#include "ui/gfx/screen.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/corewm/compound_event_filter.h"
-#include "ui/views/corewm/corewm_switches.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/ime/input_method.h"
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/views_delegate.h"
+#include "ui/views/views_switches.h"
#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_observer_x11.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_observer_x11.h"
#include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
#include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h"
+#include "ui/views/widget/desktop_aura/x11_scoped_capture.h"
#include "ui/views/widget/desktop_aura/x11_window_event_filter.h"
+#include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/core/window_util.h"
namespace views {
-DesktopRootWindowHostX11* DesktopRootWindowHostX11::g_current_capture =
+DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::g_current_capture =
NULL;
-std::list<XID>* DesktopRootWindowHostX11::open_windows_ = NULL;
+std::list<XID>* DesktopWindowTreeHostX11::open_windows_ = NULL;
DEFINE_WINDOW_PROPERTY_KEY(
aura::Window*, kViewsWindowForRootWindow, NULL);
DEFINE_WINDOW_PROPERTY_KEY(
- DesktopRootWindowHostX11*, kHostForRootWindow, NULL);
+ DesktopWindowTreeHostX11*, kHostForRootWindow, NULL);
namespace {
-// Standard Linux mouse buttons for going back and forward.
-const int kBackMouseButton = 8;
-const int kForwardMouseButton = 9;
-
// Constants that are part of EWMH.
const int k_NET_WM_STATE_ADD = 1;
const int k_NET_WM_STATE_REMOVE = 0;
+// Special value of the _NET_WM_DESKTOP property which indicates that the window
+// should appear on all desktops.
+const int kAllDesktops = 0xFFFFFFFF;
+
const char* kAtomsToCache[] = {
"UTF8_STRING",
"WM_DELETE_WINDOW",
"WM_PROTOCOLS",
- "WM_S0",
+ "_NET_FRAME_EXTENTS",
+ "_NET_WM_CM_S0",
+ "_NET_WM_DESKTOP",
"_NET_WM_ICON",
"_NET_WM_NAME",
"_NET_WM_PID",
@@ -87,6 +94,8 @@ const char* kAtomsToCache[] = {
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_SKIP_TASKBAR",
+ "_NET_WM_STATE_STICKY",
+ "_NET_WM_USER_TIME",
"_NET_WM_WINDOW_OPACITY",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_DND",
@@ -116,9 +125,9 @@ const char* kAtomsToCache[] = {
} // namespace
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostX11, public:
+// DesktopWindowTreeHostX11, public:
-DesktopRootWindowHostX11::DesktopRootWindowHostX11(
+DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura)
: close_widget_factory_(this),
@@ -129,38 +138,44 @@ DesktopRootWindowHostX11::DesktopRootWindowHostX11(
window_mapped_(false),
is_fullscreen_(false),
is_always_on_top_(false),
- root_window_(NULL),
+ use_native_frame_(false),
+ use_argb_visual_(false),
drag_drop_client_(NULL),
current_cursor_(ui::kCursorNull),
native_widget_delegate_(native_widget_delegate),
desktop_native_widget_aura_(desktop_native_widget_aura),
content_window_(NULL),
window_parent_(NULL),
- custom_window_shape_(NULL) {
+ window_shape_(NULL),
+ custom_window_shape_(false),
+ urgency_hint_set_(false) {
}
-DesktopRootWindowHostX11::~DesktopRootWindowHostX11() {
- root_window_->window()->ClearProperty(kHostForRootWindow);
- aura::client::SetWindowMoveClient(root_window_->window(), NULL);
- desktop_native_widget_aura_->OnDesktopRootWindowHostDestroyed(root_window_);
- if (custom_window_shape_)
- XDestroyRegion(custom_window_shape_);
+DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
+ window()->ClearProperty(kHostForRootWindow);
+ aura::client::SetWindowMoveClient(window(), NULL);
+ desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
+ if (window_shape_)
+ XDestroyRegion(window_shape_);
+ DestroyDispatcher();
}
// static
-aura::Window* DesktopRootWindowHostX11::GetContentWindowForXID(XID xid) {
- aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid);
- return root ? root->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
+aura::Window* DesktopWindowTreeHostX11::GetContentWindowForXID(XID xid) {
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(xid);
+ return host ? host->window()->GetProperty(kViewsWindowForRootWindow) : NULL;
}
// static
-DesktopRootWindowHostX11* DesktopRootWindowHostX11::GetHostForXID(XID xid) {
- aura::RootWindow* root = aura::RootWindow::GetForAcceleratedWidget(xid);
- return root ? root->window()->GetProperty(kHostForRootWindow) : NULL;
+DesktopWindowTreeHostX11* DesktopWindowTreeHostX11::GetHostForXID(XID xid) {
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(xid);
+ return host ? host->window()->GetProperty(kHostForRootWindow) : NULL;
}
// static
-std::vector<aura::Window*> DesktopRootWindowHostX11::GetAllOpenWindows() {
+std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() {
std::vector<aura::Window*> windows(open_windows().size());
std::transform(open_windows().begin(),
open_windows().end(),
@@ -169,14 +184,25 @@ std::vector<aura::Window*> DesktopRootWindowHostX11::GetAllOpenWindows() {
return windows;
}
-gfx::Rect DesktopRootWindowHostX11::GetX11RootWindowBounds() const {
+gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const {
return bounds_;
}
-void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged(
+gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const {
+ gfx::Rect outer_bounds(bounds_);
+ outer_bounds.Inset(-native_window_frame_borders_);
+ return outer_bounds;
+}
+
+::Region DesktopWindowTreeHostX11::GetWindowShape() const {
+ return window_shape_;
+}
+
+void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged(
bool active) {
if (active) {
- delegate_->OnHostActivated();
+ FlashFrame(false);
+ OnHostActivated();
open_windows().remove(xwindow_);
open_windows().insert(open_windows().begin(), xwindow_);
}
@@ -186,31 +212,39 @@ void DesktopRootWindowHostX11::HandleNativeWidgetActivationChanged(
native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
}
-void DesktopRootWindowHostX11::AddObserver(
- views::DesktopRootWindowHostObserverX11* observer) {
+void DesktopWindowTreeHostX11::AddObserver(
+ views::DesktopWindowTreeHostObserverX11* observer) {
observer_list_.AddObserver(observer);
}
-void DesktopRootWindowHostX11::RemoveObserver(
- views::DesktopRootWindowHostObserverX11* observer) {
+void DesktopWindowTreeHostX11::RemoveObserver(
+ views::DesktopWindowTreeHostObserverX11* observer) {
observer_list_.RemoveObserver(observer);
}
-void DesktopRootWindowHostX11::CleanUpWindowList() {
+void DesktopWindowTreeHostX11::SwapNonClientEventHandler(
+ scoped_ptr<ui::EventHandler> handler) {
+ wm::CompoundEventFilter* compound_event_filter =
+ desktop_native_widget_aura_->root_window_event_filter();
+ if (x11_non_client_event_filter_)
+ compound_event_filter->RemoveHandler(x11_non_client_event_filter_.get());
+ compound_event_filter->AddHandler(handler.get());
+ x11_non_client_event_filter_ = handler.Pass();
+}
+
+void DesktopWindowTreeHostX11::CleanUpWindowList() {
delete open_windows_;
open_windows_ = NULL;
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostX11, DesktopRootWindowHost implementation:
+// DesktopWindowTreeHostX11, DesktopWindowTreeHost implementation:
-void DesktopRootWindowHostX11::Init(
- aura::Window* content_window,
- const Widget::InitParams& params,
- aura::RootWindow::CreateParams* rw_create_params) {
+void DesktopWindowTreeHostX11::Init(aura::Window* content_window,
+ const Widget::InitParams& params) {
content_window_ = content_window;
- // TODO(erg): Check whether we *should* be building a RootWindowHost here, or
+ // 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
@@ -222,59 +256,47 @@ void DesktopRootWindowHostX11::Init(
sanitized_params.bounds.set_height(100);
InitX11Window(sanitized_params);
-
- rw_create_params->initial_bounds = bounds_;
- rw_create_params->host = this;
}
-void DesktopRootWindowHostX11::OnRootWindowCreated(
- aura::RootWindow* root,
+void DesktopWindowTreeHostX11::OnNativeWidgetCreated(
const Widget::InitParams& params) {
- root_window_ = root;
-
- root_window_->window()->SetProperty(kViewsWindowForRootWindow,
- content_window_);
- root_window_->window()->SetProperty(kHostForRootWindow, this);
- delegate_ = root_window_;
-
- // If we're given a parent, we need to mark ourselves as transient to another
- // window. Otherwise activation gets screwy.
- gfx::NativeView parent = params.parent;
- if (!params.child && params.parent)
- parent->AddTransientChild(content_window_);
+ window()->SetProperty(kViewsWindowForRootWindow, content_window_);
+ window()->SetProperty(kHostForRootWindow, this);
// Ensure that the X11DesktopHandler exists so that it dispatches activation
// messages to us.
X11DesktopHandler::get();
// TODO(erg): Unify this code once the other consumer goes away.
- x11_window_event_filter_.reset(new X11WindowEventFilter(root_window_, this));
- x11_window_event_filter_->SetUseHostWindowBorders(false);
- desktop_native_widget_aura_->root_window_event_filter()->AddHandler(
- x11_window_event_filter_.get());
+ SwapNonClientEventHandler(
+ scoped_ptr<ui::EventHandler>(new X11WindowEventFilter(this)).Pass());
+ SetUseNativeFrame(params.type == Widget::InitParams::TYPE_WINDOW &&
+ !params.remove_standard_frame);
x11_window_move_client_.reset(new X11DesktopWindowMoveClient);
- aura::client::SetWindowMoveClient(root_window_->window(),
- x11_window_move_client_.get());
+ aura::client::SetWindowMoveClient(window(), x11_window_move_client_.get());
+
+ SetWindowTransparency();
native_widget_delegate_->OnNativeWidgetCreated(true);
}
-scoped_ptr<corewm::Tooltip> DesktopRootWindowHostX11::CreateTooltip() {
+scoped_ptr<corewm::Tooltip> DesktopWindowTreeHostX11::CreateTooltip() {
return scoped_ptr<corewm::Tooltip>(
new corewm::TooltipAura(gfx::SCREEN_TYPE_NATIVE));
}
scoped_ptr<aura::client::DragDropClient>
-DesktopRootWindowHostX11::CreateDragDropClient(
+DesktopWindowTreeHostX11::CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) {
drag_drop_client_ = new DesktopDragDropClientAuraX11(
- root_window_->window(), cursor_manager, xdisplay_, xwindow_);
+ window(), cursor_manager, xdisplay_, xwindow_);
return scoped_ptr<aura::client::DragDropClient>(drag_drop_client_).Pass();
}
-void DesktopRootWindowHostX11::Close() {
+void DesktopWindowTreeHostX11::Close() {
// TODO(erg): Might need to do additional hiding tasks here.
+ delayed_resize_task_.Cancel();
if (!close_widget_factory_.HasWeakPtrs()) {
// And we delay the close so that if we are called from an ATL callback,
@@ -283,21 +305,22 @@ void DesktopRootWindowHostX11::Close() {
// dereference us when the callback returns).
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&DesktopRootWindowHostX11::CloseNow,
+ base::Bind(&DesktopWindowTreeHostX11::CloseNow,
close_widget_factory_.GetWeakPtr()));
}
}
-void DesktopRootWindowHostX11::CloseNow() {
+void DesktopWindowTreeHostX11::CloseNow() {
if (xwindow_ == None)
return;
+ x11_capture_.reset();
native_widget_delegate_->OnNativeWidgetDestroying();
// If we have children, close them. Use a copy for iteration because they'll
// remove themselves.
- std::set<DesktopRootWindowHostX11*> window_children_copy = window_children_;
- for (std::set<DesktopRootWindowHostX11*>::iterator it =
+ std::set<DesktopWindowTreeHostX11*> window_children_copy = window_children_;
+ for (std::set<DesktopWindowTreeHostX11*>::iterator it =
window_children_copy.begin(); it != window_children_copy.end();
++it) {
(*it)->CloseNow();
@@ -311,62 +334,79 @@ void DesktopRootWindowHostX11::CloseNow() {
}
// Remove the event listeners we've installed. We need to remove these
- // because otherwise we get assert during ~RootWindow().
+ // because otherwise we get assert during ~WindowEventDispatcher().
desktop_native_widget_aura_->root_window_event_filter()->RemoveHandler(
- x11_window_event_filter_.get());
+ x11_non_client_event_filter_.get());
+ x11_non_client_event_filter_.reset();
+
+ // Destroy the compositor before destroying the |xwindow_| since shutdown
+ // may try to swap, and the swap without a window causes an X error, which
+ // causes a crash with in-process renderer.
+ DestroyCompositor();
open_windows().remove(xwindow_);
// Actually free our native resources.
- base::MessagePumpX11::Current()->RemoveDispatcherForWindow(xwindow_);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
XDestroyWindow(xdisplay_, xwindow_);
xwindow_ = None;
desktop_native_widget_aura_->OnHostClosed();
}
-aura::RootWindowHost* DesktopRootWindowHostX11::AsRootWindowHost() {
+aura::WindowTreeHost* DesktopWindowTreeHostX11::AsWindowTreeHost() {
return this;
}
-void DesktopRootWindowHostX11::ShowWindowWithState(
+void DesktopWindowTreeHostX11::ShowWindowWithState(
ui::WindowShowState show_state) {
- if (show_state != ui::SHOW_STATE_DEFAULT &&
- show_state != ui::SHOW_STATE_NORMAL) {
- // Only forwarding to Show().
- NOTIMPLEMENTED();
+ if (!window_mapped_)
+ MapWindow(show_state);
+
+ if (show_state == ui::SHOW_STATE_NORMAL ||
+ show_state == ui::SHOW_STATE_MAXIMIZED) {
+ // Note: XFCE ignores a maximize hint given before mapping the window.
+ if (show_state == ui::SHOW_STATE_MAXIMIZED)
+ Maximize();
+ Activate();
}
- Show();
+ native_widget_delegate_->AsWidget()->SetInitialFocus(show_state);
}
-void DesktopRootWindowHostX11::ShowMaximizedWithBounds(
+void DesktopWindowTreeHostX11::ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) {
+ ShowWindowWithState(ui::SHOW_STATE_MAXIMIZED);
+ // Enforce |restored_bounds_| since calling Maximize() could have reset it.
restored_bounds_ = restored_bounds;
- Maximize();
- Show();
}
-bool DesktopRootWindowHostX11::IsVisible() const {
+bool DesktopWindowTreeHostX11::IsVisible() const {
return window_mapped_;
}
-void DesktopRootWindowHostX11::SetSize(const gfx::Size& size) {
- // TODO(erg):
- NOTIMPLEMENTED();
+void DesktopWindowTreeHostX11::SetSize(const gfx::Size& size) {
+ bool size_changed = bounds_.size() != size;
+ XResizeWindow(xdisplay_, xwindow_, size.width(), size.height());
+ bounds_.set_size(size);
+ if (size_changed) {
+ OnHostResized(size);
+ ResetWindowRegion();
+ }
}
-void DesktopRootWindowHostX11::StackAtTop() {
+void DesktopWindowTreeHostX11::StackAtTop() {
XRaiseWindow(xdisplay_, xwindow_);
}
-void DesktopRootWindowHostX11::CenterWindow(const gfx::Size& size) {
+void DesktopWindowTreeHostX11::CenterWindow(const gfx::Size& size) {
gfx::Rect parent_bounds = GetWorkAreaBoundsInScreen();
// If |window_|'s transient parent bounds are big enough to contain |size|,
// use them instead.
- if (content_window_->transient_parent()) {
+ if (wm::GetTransientParent(content_window_)) {
gfx::Rect transient_parent_rect =
- content_window_->transient_parent()->GetBoundsInScreen();
+ wm::GetTransientParent(content_window_)->GetBoundsInScreen();
if (transient_parent_rect.height() >= size.height() &&
transient_parent_rect.width() >= size.width()) {
parent_bounds = transient_parent_rect;
@@ -385,10 +425,10 @@ void DesktopRootWindowHostX11::CenterWindow(const gfx::Size& size) {
SetBounds(window_bounds);
}
-void DesktopRootWindowHostX11::GetWindowPlacement(
+void DesktopWindowTreeHostX11::GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
- *bounds = bounds_;
+ *bounds = GetRestoredBounds();
if (IsFullscreen()) {
*show_state = ui::SHOW_STATE_FULLSCREEN;
@@ -403,14 +443,14 @@ void DesktopRootWindowHostX11::GetWindowPlacement(
}
}
-gfx::Rect DesktopRootWindowHostX11::GetWindowBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
return bounds_;
}
-gfx::Rect DesktopRootWindowHostX11::GetClientAreaBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostX11::GetClientAreaBoundsInScreen() const {
// TODO(erg): The NativeWidgetAura version returns |bounds_|, claiming its
// needed for View::ConvertPointToScreen() to work
- // correctly. DesktopRootWindowHostWin::GetClientAreaBoundsInScreen() just
+ // correctly. DesktopWindowTreeHostWin::GetClientAreaBoundsInScreen() just
// asks windows what it thinks the client rect is.
//
// Attempts to calculate the rect by asking the NonClientFrameView what it
@@ -419,7 +459,7 @@ gfx::Rect DesktopRootWindowHostX11::GetClientAreaBoundsInScreen() const {
return bounds_;
}
-gfx::Rect DesktopRootWindowHostX11::GetRestoredBounds() const {
+gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const {
// We can't reliably track the restored bounds of a window, but we can get
// the 90% case down. When *chrome* is the process that requests maximizing
// or restoring bounds, we can record the current bounds before we request
@@ -430,7 +470,7 @@ gfx::Rect DesktopRootWindowHostX11::GetRestoredBounds() const {
return GetWindowBoundsInScreen();
}
-gfx::Rect DesktopRootWindowHostX11::GetWorkAreaBoundsInScreen() const {
+gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
std::vector<int> value;
if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) &&
value.size() >= 4) {
@@ -451,79 +491,118 @@ gfx::Rect DesktopRootWindowHostX11::GetWorkAreaBoundsInScreen() const {
return gfx::Rect(x, y, width, height);
}
-void DesktopRootWindowHostX11::SetShape(gfx::NativeRegion native_region) {
- if (custom_window_shape_)
- XDestroyRegion(custom_window_shape_);
- custom_window_shape_ = gfx::CreateRegionFromSkRegion(*native_region);
+void DesktopWindowTreeHostX11::SetShape(gfx::NativeRegion native_region) {
+ if (window_shape_)
+ XDestroyRegion(window_shape_);
+ custom_window_shape_ = true;
+ window_shape_ = gfx::CreateRegionFromSkRegion(*native_region);
ResetWindowRegion();
delete native_region;
}
-void DesktopRootWindowHostX11::Activate() {
+void DesktopWindowTreeHostX11::Activate() {
+ if (!window_mapped_)
+ return;
+
X11DesktopHandler::get()->ActivateWindow(xwindow_);
- native_widget_delegate_->AsWidget()->SetInitialFocus();
}
-void DesktopRootWindowHostX11::Deactivate() {
- // Deactivating a window means activating nothing.
- X11DesktopHandler::get()->ActivateWindow(None);
+void DesktopWindowTreeHostX11::Deactivate() {
+ if (!IsActive())
+ return;
+
+ x11_capture_.reset();
+ XLowerWindow(xdisplay_, xwindow_);
}
-bool DesktopRootWindowHostX11::IsActive() const {
+bool DesktopWindowTreeHostX11::IsActive() const {
return X11DesktopHandler::get()->IsActiveWindow(xwindow_);
}
-void DesktopRootWindowHostX11::Maximize() {
- // When we're the process requesting the maximizing, we can accurately keep
- // track of our restored bounds instead of relying on the heuristics that are
- // in the PropertyNotify and ConfigureNotify handlers.
+void DesktopWindowTreeHostX11::Maximize() {
+ // 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_ = bounds_;
SetWMSpecState(true,
atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
+ if (IsMinimized())
+ ShowWindowWithState(ui::SHOW_STATE_NORMAL);
}
-void DesktopRootWindowHostX11::Minimize() {
+void DesktopWindowTreeHostX11::Minimize() {
+ x11_capture_.reset();
XIconifyWindow(xdisplay_, xwindow_, 0);
}
-void DesktopRootWindowHostX11::Restore() {
+void DesktopWindowTreeHostX11::Restore() {
SetWMSpecState(false,
atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
atom_cache_.GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
+ if (IsMinimized())
+ ShowWindowWithState(ui::SHOW_STATE_NORMAL);
}
-bool DesktopRootWindowHostX11::IsMaximized() const {
+bool DesktopWindowTreeHostX11::IsMaximized() const {
return (HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_VERT") &&
HasWMSpecProperty("_NET_WM_STATE_MAXIMIZED_HORZ"));
}
-bool DesktopRootWindowHostX11::IsMinimized() const {
+bool DesktopWindowTreeHostX11::IsMinimized() const {
return HasWMSpecProperty("_NET_WM_STATE_HIDDEN");
}
-
-bool DesktopRootWindowHostX11::HasCapture() const {
+bool DesktopWindowTreeHostX11::HasCapture() const {
return g_current_capture == this;
}
-void DesktopRootWindowHostX11::SetAlwaysOnTop(bool always_on_top) {
+void DesktopWindowTreeHostX11::SetAlwaysOnTop(bool always_on_top) {
is_always_on_top_ = always_on_top;
SetWMSpecState(always_on_top,
atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"),
None);
}
-bool DesktopRootWindowHostX11::IsAlwaysOnTop() const {
+bool DesktopWindowTreeHostX11::IsAlwaysOnTop() const {
return is_always_on_top_;
}
-bool DesktopRootWindowHostX11::SetWindowTitle(const string16& title) {
+void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) {
+ SetWMSpecState(always_visible,
+ atom_cache_.GetAtom("_NET_WM_STATE_STICKY"),
+ None);
+
+ int new_desktop = 0;
+ if (always_visible) {
+ new_desktop = kAllDesktops;
+ } else {
+ if (!ui::GetCurrentDesktop(&new_desktop))
+ return;
+ }
+
+ XEvent xevent;
+ memset (&xevent, 0, sizeof (xevent));
+ xevent.type = ClientMessage;
+ xevent.xclient.window = xwindow_;
+ xevent.xclient.message_type = atom_cache_.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_, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xevent);
+}
+
+bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) {
if (window_title_ == title)
return false;
window_title_ = title;
- std::string utf8str = UTF16ToUTF8(title);
+ std::string utf8str = base::UTF16ToUTF8(title);
XChangeProperty(xdisplay_,
xwindow_,
atom_cache_.GetAtom("_NET_WM_NAME"),
@@ -540,7 +619,7 @@ bool DesktopRootWindowHostX11::SetWindowTitle(const string16& title) {
return true;
}
-void DesktopRootWindowHostX11::ClearNativeFocus() {
+void DesktopWindowTreeHostX11::ClearNativeFocus() {
// This method is weird and misnamed. Instead of clearing the native focus,
// it sets the focus to our |content_window_|, which will trigger a cascade
// of focus changes into views.
@@ -551,7 +630,7 @@ void DesktopRootWindowHostX11::ClearNativeFocus() {
}
}
-Widget::MoveLoopResult DesktopRootWindowHostX11::RunMoveLoop(
+Widget::MoveLoopResult DesktopWindowTreeHostX11::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source,
Widget::MoveLoopEscapeBehavior escape_behavior) {
@@ -566,42 +645,75 @@ Widget::MoveLoopResult DesktopRootWindowHostX11::RunMoveLoop(
return Widget::MOVE_LOOP_CANCELED;
}
-void DesktopRootWindowHostX11::EndMoveLoop() {
+void DesktopWindowTreeHostX11::EndMoveLoop() {
x11_window_move_client_->EndMoveLoop();
}
-void DesktopRootWindowHostX11::SetVisibilityChangedAnimationsEnabled(
+void DesktopWindowTreeHostX11::SetVisibilityChangedAnimationsEnabled(
bool value) {
// Much like the previous NativeWidgetGtk, we don't have anything to do here.
}
-bool DesktopRootWindowHostX11::ShouldUseNativeFrame() {
+bool DesktopWindowTreeHostX11::ShouldUseNativeFrame() const {
+ return use_native_frame_;
+}
+
+bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const {
return false;
}
-void DesktopRootWindowHostX11::FrameTypeChanged() {
+void DesktopWindowTreeHostX11::FrameTypeChanged() {
+ Widget::FrameType new_type =
+ native_widget_delegate_->AsWidget()->frame_type();
+ if (new_type == Widget::FRAME_TYPE_DEFAULT) {
+ // The default is determined by Widget::InitParams::remove_standard_frame
+ // and does not change.
+ return;
+ }
+
+ SetUseNativeFrame(new_type == Widget::FRAME_TYPE_FORCE_NATIVE);
// Replace the frame and layout the contents. Even though we don't have a
// swapable glass frame like on Windows, we still replace the frame because
// the button assets don't update otherwise.
native_widget_delegate_->AsWidget()->non_client_view()->UpdateFrame();
}
-NonClientFrameView* DesktopRootWindowHostX11::CreateNonClientFrameView() {
- return NULL;
-}
-
-void DesktopRootWindowHostX11::SetFullscreen(bool fullscreen) {
+void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
+ if (is_fullscreen_ == fullscreen)
+ return;
is_fullscreen_ = fullscreen;
SetWMSpecState(fullscreen,
atom_cache_.GetAtom("_NET_WM_STATE_FULLSCREEN"),
None);
+ // Try to guess the size we will have after the switch to/from fullscreen:
+ // - (may) avoid transient states
+ // - works around Flash content which expects to have the size updated
+ // synchronously.
+ // See https://crbug.com/361408
+ if (fullscreen) {
+ restored_bounds_ = bounds_;
+ const gfx::Display display =
+ gfx::Screen::GetScreenFor(NULL)->GetDisplayNearestWindow(window());
+ bounds_ = display.bounds();
+ } else {
+ bounds_ = restored_bounds_;
+ }
+ OnHostMoved(bounds_.origin());
+ OnHostResized(bounds_.size());
+
+ if (HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN") == fullscreen) {
+ Relayout();
+ ResetWindowRegion();
+ }
+ // Else: the widget will be relaid out either when the window bounds change or
+ // when |xwindow_|'s fullscreen state changes.
}
-bool DesktopRootWindowHostX11::IsFullscreen() const {
+bool DesktopWindowTreeHostX11::IsFullscreen() const {
return is_fullscreen_;
}
-void DesktopRootWindowHostX11::SetOpacity(unsigned char opacity) {
+void DesktopWindowTreeHostX11::SetOpacity(unsigned char 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.
@@ -619,7 +731,7 @@ void DesktopRootWindowHostX11::SetOpacity(unsigned char opacity) {
}
}
-void DesktopRootWindowHostX11::SetWindowIcons(
+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
@@ -643,7 +755,7 @@ void DesktopRootWindowHostX11::SetWindowIcons(
ui::SetAtomArrayProperty(xwindow_, "_NET_WM_ICON", "CARDINAL", data);
}
-void DesktopRootWindowHostX11::InitModalType(ui::ModalType modal_type) {
+void DesktopWindowTreeHostX11::InitModalType(ui::ModalType modal_type) {
switch (modal_type) {
case ui::MODAL_TYPE_NONE:
break;
@@ -655,12 +767,28 @@ void DesktopRootWindowHostX11::InitModalType(ui::ModalType modal_type) {
}
}
-void DesktopRootWindowHostX11::FlashFrame(bool flash_frame) {
- // TODO(erg):
- NOTIMPLEMENTED();
+void DesktopWindowTreeHostX11::FlashFrame(bool flash_frame) {
+ if (urgency_hint_set_ == flash_frame)
+ return;
+
+ XWMHints* hints = XGetWMHints(xdisplay_, xwindow_);
+ if (!hints) {
+ // The window hasn't had its hints set yet.
+ hints = XAllocWMHints();
+ }
+
+ if (flash_frame)
+ hints->flags |= XUrgencyHint;
+ else
+ hints->flags &= ~XUrgencyHint;
+
+ XSetWMHints(xdisplay_, xwindow_, hints);
+ XFree(hints);
+
+ urgency_hint_set_ = flash_frame;
}
-void DesktopRootWindowHostX11::OnRootViewLayout() const {
+void DesktopWindowTreeHostX11::OnRootViewLayout() const {
if (!window_mapped_)
return;
@@ -689,68 +817,54 @@ void DesktopRootWindowHostX11::OnRootViewLayout() const {
XSetWMNormalHints(xdisplay_, xwindow_, &hints);
}
-void DesktopRootWindowHostX11::OnNativeWidgetFocus() {
+void DesktopWindowTreeHostX11::OnNativeWidgetFocus() {
native_widget_delegate_->AsWidget()->GetInputMethod()->OnFocus();
}
-void DesktopRootWindowHostX11::OnNativeWidgetBlur() {
- if (xwindow_)
+void DesktopWindowTreeHostX11::OnNativeWidgetBlur() {
+ if (xwindow_) {
+ x11_capture_.reset();
native_widget_delegate_->AsWidget()->GetInputMethod()->OnBlur();
+ }
}
-bool DesktopRootWindowHostX11::IsAnimatingClosed() const {
+bool DesktopWindowTreeHostX11::IsAnimatingClosed() const {
+ return false;
+}
+
+bool DesktopWindowTreeHostX11::IsTranslucentWindowOpacitySupported() const {
return false;
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostX11, aura::RootWindowHost implementation:
+// DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
-aura::RootWindow* DesktopRootWindowHostX11::GetRootWindow() {
- return root_window_;
+ui::EventSource* DesktopWindowTreeHostX11::GetEventSource() {
+ return this;
}
-gfx::AcceleratedWidget DesktopRootWindowHostX11::GetAcceleratedWidget() {
+gfx::AcceleratedWidget DesktopWindowTreeHostX11::GetAcceleratedWidget() {
return xwindow_;
}
-void DesktopRootWindowHostX11::Show() {
- if (!window_mapped_) {
- // Before we map the window, set size hints. Otherwise, some window managers
- // will ignore toplevel XMoveWindow commands.
- XSizeHints size_hints;
- size_hints.flags = PPosition;
- size_hints.x = bounds_.x();
- size_hints.y = bounds_.y();
- XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
-
- XMapWindow(xdisplay_, xwindow_);
-
- // We now block until our window is mapped. Some X11 APIs will crash and
- // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
- // asynchronous.
- base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_);
- window_mapped_ = true;
- }
-
- native_widget_delegate_->AsWidget()->SetInitialFocus();
+void DesktopWindowTreeHostX11::Show() {
+ ShowWindowWithState(ui::SHOW_STATE_NORMAL);
+ native_widget_delegate_->OnNativeWidgetVisibilityChanged(true);
}
-void DesktopRootWindowHostX11::Hide() {
+void DesktopWindowTreeHostX11::Hide() {
if (window_mapped_) {
XWithdrawWindow(xdisplay_, xwindow_, 0);
window_mapped_ = false;
}
+ native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);
}
-void DesktopRootWindowHostX11::ToggleFullScreen() {
- NOTIMPLEMENTED();
-}
-
-gfx::Rect DesktopRootWindowHostX11::GetBounds() const {
+gfx::Rect DesktopWindowTreeHostX11::GetBounds() const {
return bounds_;
}
-void DesktopRootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
+void DesktopWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
bool origin_changed = bounds_.origin() != bounds.origin();
bool size_changed = bounds_.size() != bounds.size();
XWindowChanges changes = {0};
@@ -783,24 +897,17 @@ void DesktopRootWindowHostX11::SetBounds(const gfx::Rect& bounds) {
if (origin_changed)
native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
- if (size_changed)
- delegate_->OnHostResized(bounds.size());
- else
- delegate_->OnHostPaint(gfx::Rect(bounds.size()));
-}
-
-gfx::Insets DesktopRootWindowHostX11::GetInsets() const {
- return gfx::Insets();
-}
-
-void DesktopRootWindowHostX11::SetInsets(const gfx::Insets& insets) {
+ if (size_changed) {
+ OnHostResized(bounds.size());
+ ResetWindowRegion();
+ }
}
-gfx::Point DesktopRootWindowHostX11::GetLocationOnNativeScreen() const {
+gfx::Point DesktopWindowTreeHostX11::GetLocationOnNativeScreen() const {
return bounds_.origin();
}
-void DesktopRootWindowHostX11::SetCapture() {
+void DesktopWindowTreeHostX11::SetCapture() {
// This is vaguely based on the old NativeWidgetGtk implementation.
//
// X11's XPointerGrab() shouldn't be used for everything; it doesn't map
@@ -813,70 +920,29 @@ void DesktopRootWindowHostX11::SetCapture() {
g_current_capture->OnCaptureReleased();
g_current_capture = this;
-
- // TODO(erg): In addition to the above, NativeWidgetGtk performs a full X
- // pointer grab when our NativeWidget is of type Menu. However, things work
- // without it. Clicking inside a chrome window causes a release capture, and
- // clicking outside causes an activation change. Since previous attempts at
- // using XPointerGrab() to implement this have locked my X server, I'm going
- // to skip this for now.
+ x11_capture_.reset(new X11ScopedCapture(xwindow_));
}
-void DesktopRootWindowHostX11::ReleaseCapture() {
- if (g_current_capture)
+void DesktopWindowTreeHostX11::ReleaseCapture() {
+ if (g_current_capture == this)
g_current_capture->OnCaptureReleased();
}
-void DesktopRootWindowHostX11::SetCursor(gfx::NativeCursor cursor) {
+void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
XDefineCursor(xdisplay_, xwindow_, cursor.platform());
}
-bool DesktopRootWindowHostX11::QueryMouseLocation(
- gfx::Point* location_return) {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(GetRootWindow()->window());
- if (cursor_client && !cursor_client->IsMouseEventsEnabled()) {
- *location_return = gfx::Point(0, 0);
- return false;
- }
-
- ::Window root_return, child_return;
- int root_x_return, root_y_return, win_x_return, win_y_return;
- unsigned int mask_return;
- XQueryPointer(xdisplay_,
- xwindow_,
- &root_return,
- &child_return,
- &root_x_return, &root_y_return,
- &win_x_return, &win_y_return,
- &mask_return);
- *location_return = gfx::Point(
- std::max(0, std::min(bounds_.width(), win_x_return)),
- std::max(0, std::min(bounds_.height(), win_y_return)));
- return (win_x_return >= 0 && win_x_return < bounds_.width() &&
- win_y_return >= 0 && win_y_return < bounds_.height());
-}
-
-bool DesktopRootWindowHostX11::ConfineCursorToRootWindow() {
- NOTIMPLEMENTED();
- return false;
-}
-
-void DesktopRootWindowHostX11::UnConfineCursor() {
- NOTIMPLEMENTED();
+void DesktopWindowTreeHostX11::MoveCursorToNative(const gfx::Point& location) {
+ XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
+ bounds_.x() + location.x(), bounds_.y() + location.y());
}
-void DesktopRootWindowHostX11::OnCursorVisibilityChanged(bool show) {
+void DesktopWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
// TODO(erg): Conditional on us enabling touch on desktop linux builds, do
// the same tap-to-click disabling here that chromeos does.
}
-void DesktopRootWindowHostX11::MoveCursorTo(const gfx::Point& location) {
- XWarpPointer(xdisplay_, None, x_root_window_, 0, 0, 0, 0,
- bounds_.x() + location.x(), bounds_.y() + location.y());
-}
-
-void DesktopRootWindowHostX11::PostNativeEvent(
+void DesktopWindowTreeHostX11::PostNativeEvent(
const base::NativeEvent& native_event) {
DCHECK(xwindow_);
DCHECK(xdisplay_);
@@ -909,17 +975,21 @@ void DesktopRootWindowHostX11::PostNativeEvent(
XSendEvent(xdisplay_, xwindow_, False, 0, &xevent);
}
-void DesktopRootWindowHostX11::OnDeviceScaleFactorChanged(
+void DesktopWindowTreeHostX11::OnDeviceScaleFactorChanged(
float device_scale_factor) {
}
-void DesktopRootWindowHostX11::PrepareForShutdown() {
+////////////////////////////////////////////////////////////////////////////////
+// DesktopWindowTreeHostX11, ui::EventSource implementation:
+
+ui::EventProcessor* DesktopWindowTreeHostX11::GetEventProcessor() {
+ return dispatcher();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostX11, private:
+// DesktopWindowTreeHostX11, private:
-void DesktopRootWindowHostX11::InitX11Window(
+void DesktopWindowTreeHostX11::InitX11Window(
const Widget::InitParams& params) {
unsigned long attribute_mask = CWBackPixmap;
XSetWindowAttributes swa;
@@ -933,6 +1003,7 @@ void DesktopRootWindowHostX11::InitX11Window(
window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU");
break;
case Widget::InitParams::TYPE_TOOLTIP:
+ swa.override_redirect = True;
window_type = atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP");
break;
case Widget::InitParams::TYPE_POPUP:
@@ -950,18 +1021,45 @@ void DesktopRootWindowHostX11::InitX11Window(
if (swa.override_redirect)
attribute_mask |= CWOverrideRedirect;
+ // Detect whether we're running inside a compositing manager. If so, try to
+ // use the ARGB visual. Otherwise, just use our parent's visual.
+ Visual* visual = CopyFromParent;
+ int depth = CopyFromParent;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableTransparentVisuals) &&
+ XGetSelectionOwner(xdisplay_,
+ atom_cache_.GetAtom("_NET_WM_CM_S0")) != None) {
+ Visual* rgba_visual = GetARGBVisual();
+ if (rgba_visual) {
+ visual = rgba_visual;
+ depth = 32;
+
+ attribute_mask |= CWColormap;
+ swa.colormap = XCreateColormap(xdisplay_, x_root_window_, visual,
+ AllocNone);
+
+ // 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;
+
+ use_argb_visual_ = true;
+ }
+ }
+
bounds_ = params.bounds;
xwindow_ = XCreateWindow(
xdisplay_, x_root_window_,
bounds_.x(), bounds_.y(),
bounds_.width(), bounds_.height(),
0, // border width
- CopyFromParent, // depth
+ depth,
InputOutput,
- CopyFromParent, // visual
+ visual,
attribute_mask,
&swa);
- base::MessagePumpX11::Current()->AddDispatcherForWindow(this, xwindow_);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
open_windows().push_back(xwindow_);
// TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL().
@@ -1014,9 +1112,10 @@ void DesktopRootWindowHostX11::InitX11Window(
// List of window state properties (_NET_WM_STATE) to set, if any.
std::vector< ::Atom> state_atom_list;
- // Remove popup windows from taskbar.
- if (params.type == Widget::InitParams::TYPE_POPUP ||
- params.type == Widget::InitParams::TYPE_BUBBLE) {
+ // 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) {
state_atom_list.push_back(
atom_cache_.GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
}
@@ -1027,6 +1126,11 @@ void DesktopRootWindowHostX11::InitX11Window(
if (is_always_on_top_)
state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_ABOVE"));
+ if (params.visible_on_all_workspaces) {
+ state_atom_list.push_back(atom_cache_.GetAtom("_NET_WM_STATE_STICKY"));
+ ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", kAllDesktops);
+ }
+
// Setting _NET_WM_STATE by sending a message to the root_window (with
// SetWMSpecState) has no effect here since the window has not yet been
// mapped. So we manually change the state.
@@ -1048,12 +1152,19 @@ void DesktopRootWindowHostX11::InitX11Window(
std::string(kX11WindowRolePopup) : params.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 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->GetDispatcher()) {
+ if (params.parent && params.parent->GetHost()) {
XID parent_xid =
- params.parent->GetDispatcher()->host()->GetAcceleratedWidget();
+ params.parent->GetHost()->GetAcceleratedWidget();
window_parent_ = GetHostForXID(parent_xid);
DCHECK(window_parent_);
window_parent_->window_children_.insert(this);
@@ -1066,16 +1177,105 @@ void DesktopRootWindowHostX11::InitX11Window(
if (window_icon) {
SetWindowIcons(gfx::ImageSkia(), *window_icon);
}
+ CreateCompositor(GetAcceleratedWidget());
+}
+
+void DesktopWindowTreeHostX11::OnWMStateUpdated() {
+ std::vector< ::Atom> atom_list;
+ if (!ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list))
+ return;
+
+ bool was_minimized = IsMinimized();
+
+ window_properties_.clear();
+ std::copy(atom_list.begin(), atom_list.end(),
+ inserter(window_properties_, window_properties_.begin()));
+
+ // Propagate the window minimization information to the content window, so
+ // the render side can update its visibility properly. OnWMStateUpdated() is
+ // called by PropertyNofify event from DispatchEvent() when the browser is
+ // minimized or shown from minimized state. On Windows, this is realized by
+ // calling OnHostResized() with an empty size. In particular,
+ // HWNDMessageHandler::GetClientAreaBounds() returns an empty size when the
+ // window is minimized. On Linux, returning empty size in GetBounds() or
+ // SetBounds() does not work.
+ bool is_minimized = IsMinimized();
+ if (is_minimized != was_minimized) {
+ if (is_minimized)
+ content_window_->Hide();
+ else
+ content_window_->Show();
+ }
+
+ if (restored_bounds_.IsEmpty()) {
+ DCHECK(!IsFullscreen());
+ if (IsMaximized()) {
+ // The request that we become maximized originated from a different
+ // process. |bounds_| already contains our maximized bounds. Do 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_ = previous_bounds_;
+ }
+ } else if (!IsMaximized() && !IsFullscreen()) {
+ // If we have restored bounds, but WM_STATE no longer claims to be
+ // maximized or fullscreen, we should clear our restored bounds.
+ restored_bounds_ = 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_ = HasWMSpecProperty("_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.)
+ Relayout();
+ 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_ = gfx::Insets(
+ insets[2],
+ insets[0],
+ insets[3],
+ insets[1]);
+ } else {
+ native_window_frame_borders_ = gfx::Insets();
+ }
}
-bool DesktopRootWindowHostX11::IsWindowManagerPresent() {
- // Per ICCCM 2.8, "Manager Selections", window managers should take ownership
- // of WM_Sn selections (where n is a screen number).
- return XGetSelectionOwner(
- xdisplay_, atom_cache_.GetAtom("WM_S0")) != None;
+void DesktopWindowTreeHostX11::UpdateWMUserTime(
+ const ui::PlatformEvent& event) {
+ if (!IsActive())
+ return;
+
+ 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).InMilliseconds());
+ XChangeProperty(xdisplay_,
+ xwindow_,
+ atom_cache_.GetAtom("_NET_WM_USER_TIME"),
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char *>(&wm_user_time_ms),
+ 1);
+ X11DesktopHandler::get()->set_wm_user_time_ms(wm_user_time_ms);
+ }
}
-void DesktopRootWindowHostX11::SetWMSpecState(bool enabled,
+void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled,
::Atom state1,
::Atom state2) {
XEvent xclient;
@@ -1096,49 +1296,88 @@ void DesktopRootWindowHostX11::SetWMSpecState(bool enabled,
&xclient);
}
-bool DesktopRootWindowHostX11::HasWMSpecProperty(const char* property) const {
+bool DesktopWindowTreeHostX11::HasWMSpecProperty(const char* property) const {
return window_properties_.find(atom_cache_.GetAtom(property)) !=
window_properties_.end();
}
-void DesktopRootWindowHostX11::OnCaptureReleased() {
+void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
+ use_native_frame_ = use_native_frame;
+ ui::SetUseOSWindowFrame(xwindow_, use_native_frame);
+ ResetWindowRegion();
+}
+
+void DesktopWindowTreeHostX11::OnCaptureReleased() {
+ x11_capture_.reset();
g_current_capture = NULL;
- delegate_->OnHostLostWindowCapture();
+ OnHostLostWindowCapture();
native_widget_delegate_->OnMouseCaptureLost();
}
-void DesktopRootWindowHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
+void DesktopWindowTreeHostX11::DispatchMouseEvent(ui::MouseEvent* event) {
+ // In Windows, the native events sent to chrome are separated into client
+ // and non-client versions of events, which we record on our LocatedEvent
+ // structures. On X11, we emulate the concept of non-client. Before we pass
+ // this event to the cross platform event handling framework, we need to
+ // make sure it is appropriately marked as non-client if it's in the non
+ // client area, or otherwise, we can get into a state where the a window is
+ // set as the |mouse_pressed_handler_| in window_event_dispatcher.cc
+ // despite the mouse button being released.
+ //
+ // We can't do this later in the dispatch process because we share that
+ // with ash, and ash gets confused about event IS_NON_CLIENT-ness on
+ // events, since ash doesn't expect this bit to be set, because it's never
+ // been set before. (This works on ash on Windows because none of the mouse
+ // events on the ash desktop are clicking in what Windows considers to be a
+ // non client area.) Likewise, we won't want to do the following in any
+ // WindowTreeHost that hosts ash.
+ if (content_window_ && content_window_->delegate()) {
+ int flags = event->flags();
+ int hit_test_code =
+ content_window_->delegate()->GetNonClientComponent(event->location());
+ if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE)
+ flags |= ui::EF_IS_NON_CLIENT;
+ event->set_flags(flags);
+ }
+
+ // While we unset the urgency hint when we gain focus, we also must remove it
+ // on mouse clicks because we can call FlashFrame() on an active window.
+ if (event->IsAnyButton() || event->IsMouseWheelEvent())
+ FlashFrame(false);
+
if (!g_current_capture || g_current_capture == this) {
- delegate_->OnHostMouseEvent(event);
+ SendEventToProcessor(event);
} else {
- // Another DesktopRootWindowHostX11 has installed itself as
+ // Another DesktopWindowTreeHostX11 has installed itself as
// capture. Translate the event's location and dispatch to the other.
- event->ConvertLocationToTarget(root_window_->window(),
- g_current_capture->root_window_->window());
- g_current_capture->delegate_->OnHostMouseEvent(event);
+ event->ConvertLocationToTarget(window(), g_current_capture->window());
+ g_current_capture->SendEventToProcessor(event);
}
}
-void DesktopRootWindowHostX11::DispatchTouchEvent(ui::TouchEvent* event) {
+void DesktopWindowTreeHostX11::DispatchTouchEvent(ui::TouchEvent* event) {
if (g_current_capture && g_current_capture != this &&
event->type() == ui::ET_TOUCH_PRESSED) {
- event->ConvertLocationToTarget(root_window_->window(),
- g_current_capture->root_window_->window());
- g_current_capture->delegate_->OnHostTouchEvent(event);
+ event->ConvertLocationToTarget(window(), g_current_capture->window());
+ g_current_capture->SendEventToProcessor(event);
} else {
- delegate_->OnHostTouchEvent(event);
+ SendEventToProcessor(event);
}
}
-void DesktopRootWindowHostX11::ResetWindowRegion() {
+void DesktopWindowTreeHostX11::ResetWindowRegion() {
// If a custom window shape was supplied then apply it.
if (custom_window_shape_) {
XShapeCombineRegion(
- xdisplay_, xwindow_, ShapeBounding, 0, 0, custom_window_shape_, false);
+ xdisplay_, xwindow_, ShapeBounding, 0, 0, window_shape_, false);
return;
}
- if (!IsMaximized()) {
+ if (window_shape_)
+ XDestroyRegion(window_shape_);
+ window_shape_ = NULL;
+
+ if (!IsMaximized() && !IsFullscreen()) {
gfx::Path window_mask;
views::Widget* widget = native_widget_delegate_->AsWidget();
if (widget->non_client_view()) {
@@ -1146,24 +1385,36 @@ void DesktopRootWindowHostX11::ResetWindowRegion() {
// so, use it to define the window shape. If not, fall through.
widget->non_client_view()->GetWindowMask(bounds_.size(), &window_mask);
if (window_mask.countPoints() > 0) {
- Region region = gfx::CreateRegionFromSkPath(window_mask);
+ window_shape_ = gfx::CreateRegionFromSkPath(window_mask);
XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding,
- 0, 0, region, false);
- XDestroyRegion(region);
+ 0, 0, window_shape_, false);
return;
}
}
}
- // If we didn't set the shape for any reason, reset the shaping information
- // by ShapeSet-ing with our bounds rect.
- XRectangle r = { 0, 0, static_cast<unsigned short>(bounds_.width()),
- static_cast<unsigned short>(bounds_.height()) };
- XShapeCombineRectangles(xdisplay_, xwindow_, ShapeBounding,
- 0, 0, &r, 1, ShapeSet, YXBanded);
+ // 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, 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_.width()),
+ static_cast<unsigned short>(bounds_.height())};
+ XShapeCombineRectangles(
+ xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, ShapeSet, YXBanded);
+ }
}
-void DesktopRootWindowHostX11::SerializeImageRepresentation(
+void DesktopWindowTreeHostX11::SerializeImageRepresentation(
const gfx::ImageSkiaRep& rep,
std::vector<unsigned long>* data) {
int width = rep.GetWidth();
@@ -1180,28 +1431,135 @@ void DesktopRootWindowHostX11::SerializeImageRepresentation(
data->push_back(bitmap.getColor(x, y));
}
-std::list<XID>& DesktopRootWindowHostX11::open_windows() {
+Visual* DesktopWindowTreeHostX11::GetARGBVisual() {
+ XVisualInfo visual_template;
+ visual_template.screen = 0;
+ Visual* to_return = NULL;
+
+ int visuals_len;
+ XVisualInfo* visual_list = XGetVisualInfo(xdisplay_,
+ VisualScreenMask,
+ &visual_template, &visuals_len);
+ for (int i = 0; i < visuals_len; ++i) {
+ // Why support only 8888 ARGB? Because it's all that GTK+ supports. In
+ // gdkvisual-x11.cc, they look for this specific visual and use it for all
+ // their alpha channel using needs.
+ //
+ // TODO(erg): While the following does find a valid visual, some GL drivers
+ // don't believe that this has an alpha channel. According to marcheu@,
+ // this should work on open source driver though. (It doesn't work with
+ // NVidia's binaries currently.) http://crbug.com/369209
+ if (visual_list[i].depth == 32 &&
+ visual_list[i].visual->red_mask == 0xff0000 &&
+ visual_list[i].visual->green_mask == 0x00ff00 &&
+ visual_list[i].visual->blue_mask == 0x0000ff) {
+ to_return = visual_list[i].visual;
+ break;
+ }
+ }
+
+ if (visual_list)
+ XFree(visual_list);
+
+ return to_return;
+}
+
+std::list<XID>& DesktopWindowTreeHostX11::open_windows() {
if (!open_windows_)
open_windows_ = new std::list<XID>();
return *open_windows_;
}
+void DesktopWindowTreeHostX11::MapWindow(ui::WindowShowState show_state) {
+ if (show_state != ui::SHOW_STATE_DEFAULT &&
+ show_state != ui::SHOW_STATE_NORMAL &&
+ show_state != ui::SHOW_STATE_INACTIVE) {
+ // It will behave like SHOW_STATE_NORMAL.
+ NOTIMPLEMENTED();
+ }
+
+ // Before we map the window, set size hints. Otherwise, some window managers
+ // will ignore toplevel XMoveWindow commands.
+ XSizeHints size_hints;
+ size_hints.flags = PPosition;
+ size_hints.x = bounds_.x();
+ size_hints.y = bounds_.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
+ unsigned long wm_user_time_ms = (show_state == ui::SHOW_STATE_INACTIVE) ?
+ 0 : X11DesktopHandler::get()->wm_user_time_ms();
+ if (show_state == ui::SHOW_STATE_INACTIVE || wm_user_time_ms != 0) {
+ XChangeProperty(xdisplay_,
+ xwindow_,
+ atom_cache_.GetAtom("_NET_WM_USER_TIME"),
+ XA_CARDINAL,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char *>(&wm_user_time_ms),
+ 1);
+ }
+
+ XMapWindow(xdisplay_, xwindow_);
+
+ // We now block until our window is mapped. Some X11 APIs will crash and
+ // burn if passed |xwindow_| before the window is mapped, and XMapWindow is
+ // asynchronous.
+ if (ui::X11EventSource::GetInstance())
+ ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
+ window_mapped_ = true;
+}
+
+void DesktopWindowTreeHostX11::SetWindowTransparency() {
+ compositor()->SetHostHasTransparentBackground(use_argb_visual_);
+ window()->SetTransparent(use_argb_visual_);
+ content_window_->SetTransparent(use_argb_visual_);
+}
+
+void DesktopWindowTreeHostX11::Relayout() {
+ Widget* widget = native_widget_delegate_->AsWidget();
+ NonClientView* non_client_view = widget->non_client_view();
+ // non_client_view may be NULL, especially during creation.
+ if (non_client_view) {
+ non_client_view->client_view()->InvalidateLayout();
+ non_client_view->InvalidateLayout();
+ }
+ widget->GetRootView()->Layout();
+}
+
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostX11, MessageLoop::Dispatcher implementation:
+// DesktopWindowTreeHostX11, ui::PlatformEventDispatcher implementation:
+
+bool DesktopWindowTreeHostX11::CanDispatchEvent(
+ const ui::PlatformEvent& event) {
+ return event->xany.window == xwindow_ ||
+ (event->type == GenericEvent &&
+ static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_);
+}
-bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
+uint32_t DesktopWindowTreeHostX11::DispatchEvent(
+ const ui::PlatformEvent& event) {
XEvent* xev = event;
- TRACE_EVENT1("views", "DesktopRootWindowHostX11::Dispatch",
+ 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: {
- if (!g_current_capture)
- X11DesktopHandler::get()->ProcessXEvent(xev);
+ // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
+ // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
+ // TODO(pkotwicz|tdanderson): Figure out whether the suppression is
+ // necessary. crbug.com/385716
+ if (xev->xcrossing.detail == NotifyInferior)
+ break;
+
ui::MouseEvent mouse_event(xev);
DispatchMouseEvent(&mouse_event);
break;
@@ -1209,33 +1567,20 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
case Expose: {
gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y,
xev->xexpose.width, xev->xexpose.height);
- delegate_->OnHostPaint(damage_rect);
+ compositor()->ScheduleRedrawRect(damage_rect);
break;
}
case KeyPress: {
ui::KeyEvent keydown_event(xev, false);
- delegate_->OnHostKeyEvent(&keydown_event);
+ SendEventToProcessor(&keydown_event);
break;
}
case KeyRelease: {
ui::KeyEvent keyup_event(xev, false);
- delegate_->OnHostKeyEvent(&keyup_event);
+ SendEventToProcessor(&keyup_event);
break;
}
- case ButtonPress: {
- if (static_cast<int>(xev->xbutton.button) == kBackMouseButton ||
- static_cast<int>(xev->xbutton.button) == kForwardMouseButton) {
- aura::client::UserActionClient* gesture_client =
- aura::client::GetUserActionClient(root_window_->window());
- if (gesture_client) {
- gesture_client->OnUserAction(
- static_cast<int>(xev->xbutton.button) == kBackMouseButton ?
- aura::client::UserActionClient::BACK :
- aura::client::UserActionClient::FORWARD);
- }
- break;
- }
- } // fallthrough
+ case ButtonPress:
case ButtonRelease: {
ui::EventType event_type = ui::EventTypeFromNative(xev);
switch (event_type) {
@@ -1261,11 +1606,15 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
case FocusOut:
if (xev->xfocus.mode != NotifyGrab) {
ReleaseCapture();
- delegate_->OnHostLostWindowCapture();
+ OnHostLostWindowCapture();
+ X11DesktopHandler::get()->ProcessXEvent(xev);
} else {
- delegate_->OnHostLostMouseGrab();
+ dispatcher()->OnHostLostMouseGrab();
}
break;
+ case FocusIn:
+ X11DesktopHandler::get()->ProcessXEvent(xev);
+ break;
case ConfigureNotify: {
DCHECK_EQ(xwindow_, xev->xconfigure.window);
DCHECK_EQ(xwindow_, xev->xconfigure.event);
@@ -1285,11 +1634,18 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
bool origin_changed = bounds_.origin() != bounds.origin();
previous_bounds_ = bounds_;
bounds_ = bounds;
- if (size_changed)
- delegate_->OnHostResized(bounds.size());
+
if (origin_changed)
- delegate_->OnHostMoved(bounds_.origin());
- ResetWindowRegion();
+ OnHostMoved(bounds_.origin());
+
+ if (size_changed) {
+ delayed_resize_task_.Reset(base::Bind(
+ &DesktopWindowTreeHostX11::DelayedResize,
+ close_widget_factory_.GetWeakPtr(),
+ bounds.size()));
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, delayed_resize_task_.callback());
+ }
break;
}
case GenericEvent: {
@@ -1325,34 +1681,6 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
if (num_coalesced > 0)
xev = &last_event;
- } else if (type == ui::ET_MOUSE_PRESSED) {
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(xev->xcookie.data);
- int button = xievent->detail;
- if (button == kBackMouseButton || button == kForwardMouseButton) {
- aura::client::UserActionClient* gesture_client =
- aura::client::GetUserActionClient(
- delegate_->AsRootWindow()->window());
- if (gesture_client) {
- bool reverse_direction =
- ui::IsTouchpadEvent(xev) && ui::IsNaturalScrollEnabled();
- gesture_client->OnUserAction(
- (button == kBackMouseButton && !reverse_direction) ||
- (button == kForwardMouseButton && reverse_direction) ?
- aura::client::UserActionClient::BACK :
- aura::client::UserActionClient::FORWARD);
- }
- break;
- }
- } else if (type == ui::ET_MOUSE_RELEASED) {
- XIDeviceEvent* xievent =
- static_cast<XIDeviceEvent*>(xev->xcookie.data);
- int button = xievent->detail;
- if (button == kBackMouseButton || button == kForwardMouseButton) {
- // We've already passed the back/forward mouse down to the user
- // action client; we want to swallow the corresponding release.
- break;
- }
}
ui::MouseEvent mouseev(xev);
DispatchMouseEvent(&mouseev);
@@ -1367,7 +1695,7 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
case ui::ET_SCROLL_FLING_CANCEL:
case ui::ET_SCROLL: {
ui::ScrollEvent scrollev(xev);
- delegate_->OnHostScrollEvent(&scrollev);
+ SendEventToProcessor(&scrollev);
break;
}
case ui::ET_UNKNOWN:
@@ -1382,13 +1710,13 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
break;
}
case MapNotify: {
- FOR_EACH_OBSERVER(DesktopRootWindowHostObserverX11,
+ FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
observer_list_,
OnWindowMapped(xwindow_));
break;
}
case UnmapNotify: {
- FOR_EACH_OBSERVER(DesktopRootWindowHostObserverX11,
+ FOR_EACH_OBSERVER(DesktopWindowTreeHostObserverX11,
observer_list_,
OnWindowUnmapped(xwindow_));
break;
@@ -1399,7 +1727,7 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
if (protocol == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
// We have received a close message from the window manager.
- root_window_->OnRootWindowHostCloseRequested();
+ OnHostCloseRequested();
} else if (protocol == atom_cache_.GetAtom("_NET_WM_PING")) {
XEvent reply_event = *xev;
reply_event.xclient.window = x_root_window_;
@@ -1430,7 +1758,6 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
case MappingModifier:
case MappingKeyboard:
XRefreshKeyboardMapping(&xev->xmapping);
- root_window_->OnKeyboardMappingChanged();
break;
case MappingPointer:
ui::DeviceDataManager::GetInstance()->UpdateButtonMap();
@@ -1464,50 +1791,11 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
break;
}
case PropertyNotify: {
- // Get our new window property state if the WM has told us its changed.
- ::Atom state = atom_cache_.GetAtom("_NET_WM_STATE");
-
- std::vector< ::Atom> atom_list;
- if (xev->xproperty.atom == state &&
- ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list)) {
- window_properties_.clear();
- std::copy(atom_list.begin(), atom_list.end(),
- inserter(window_properties_, window_properties_.begin()));
-
- if (!restored_bounds_.IsEmpty() && !IsMaximized()) {
- // If we have restored bounds, but WM_STATE no longer claims to be
- // maximized, we should clear our restored bounds.
- restored_bounds_ = gfx::Rect();
- } else if (IsMaximized() && restored_bounds_.IsEmpty()) {
- // The request that we become maximized originated from a different
- // process. |bounds_| already contains our maximized bounds. Do 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_ = previous_bounds_;
- }
-
- is_fullscreen_ = HasWMSpecProperty("_NET_WM_STATE_FULLSCREEN");
- is_always_on_top_ = HasWMSpecProperty("_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.)
- //
- // TODO(erg): While this does work, there's a quick flash showing the
- // tabstrip/toolbar/etc. when going into fullscreen mode before hiding
- // those parts of the UI because we receive the sizing event from the
- // window manager before we receive the event that changes the
- // fullscreen state. Unsure what to do about that.
- Widget* widget = native_widget_delegate_->AsWidget();
- NonClientView* non_client_view = widget->non_client_view();
- // non_client_view may be NULL, especially during creation.
- if (non_client_view) {
- non_client_view->client_view()->InvalidateLayout();
- non_client_view->InvalidateLayout();
- }
- widget->GetRootView()->Layout();
- }
+ ::Atom changed_atom = xev->xproperty.atom;
+ if (changed_atom == atom_cache_.GetAtom("_NET_WM_STATE"))
+ OnWMStateUpdated();
+ else if (changed_atom == atom_cache_.GetAtom("_NET_FRAME_EXTENTS"))
+ OnFrameExtentsUpdated();
break;
}
case SelectionNotify: {
@@ -1515,25 +1803,31 @@ bool DesktopRootWindowHostX11::Dispatch(const base::NativeEvent& event) {
break;
}
}
- return true;
+ return ui::POST_DISPATCH_STOP_PROPAGATION;
+}
+
+void DesktopWindowTreeHostX11::DelayedResize(const gfx::Size& size) {
+ OnHostResized(size);
+ ResetWindowRegion();
+ delayed_resize_task_.Cancel();
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHost, public:
+// DesktopWindowTreeHost, public:
// static
-DesktopRootWindowHost* DesktopRootWindowHost::Create(
+DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura) {
- return new DesktopRootWindowHostX11(native_widget_delegate,
+ return new DesktopWindowTreeHostX11(native_widget_delegate,
desktop_native_widget_aura);
}
// static
-ui::NativeTheme* DesktopRootWindowHost::GetNativeTheme(aura::Window* window) {
+ui::NativeTheme* DesktopWindowTreeHost::GetNativeTheme(aura::Window* window) {
const views::LinuxUI* linux_ui = views::LinuxUI::instance();
if (linux_ui) {
- ui::NativeTheme* native_theme = linux_ui->GetNativeTheme();
+ ui::NativeTheme* native_theme = linux_ui->GetNativeTheme(window);
if (native_theme)
return native_theme;
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 76a0821a6de..a67a1516820 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_root_window_host_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -2,52 +2,59 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_X11_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_X11_H_
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_X11_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_X11_H_
#include <X11/extensions/shape.h>
#include <X11/Xlib.h>
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
-#undef RootWindow
-
#include "base/basictypes.h"
+#include "base/cancelable_callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor_loader_x11.h"
+#include "ui/events/event_source.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/gfx/insets.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/views/views_export.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
namespace gfx {
class ImageSkia;
class ImageSkiaRep;
}
+namespace ui {
+class EventHandler;
+}
+
namespace views {
class DesktopDragDropClientAuraX11;
class DesktopDispatcherClient;
-class DesktopRootWindowHostObserverX11;
+class DesktopWindowTreeHostObserverX11;
class X11DesktopWindowMoveClient;
+class X11ScopedCapture;
class X11WindowEventFilter;
-class VIEWS_EXPORT DesktopRootWindowHostX11 :
- public DesktopRootWindowHost,
- public aura::RootWindowHost,
- public base::MessageLoop::Dispatcher {
+class VIEWS_EXPORT DesktopWindowTreeHostX11
+ : public DesktopWindowTreeHost,
+ public aura::WindowTreeHost,
+ public ui::EventSource,
+ public ui::PlatformEventDispatcher {
public:
- DesktopRootWindowHostX11(
+ DesktopWindowTreeHostX11(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura);
- virtual ~DesktopRootWindowHostX11();
+ virtual ~DesktopWindowTreeHostX11();
// A way of converting an X11 |xid| host window into a |content_window_|.
static aura::Window* GetContentWindowForXID(XID xid);
// A way of converting an X11 |xid| host window into this object.
- static DesktopRootWindowHostX11* GetHostForXID(XID xid);
+ static DesktopWindowTreeHostX11* GetHostForXID(XID xid);
// Get all open top-level windows. This includes windows that may not be
// visible. This list is sorted in their stacking order, i.e. the first window
@@ -57,29 +64,38 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 :
// Returns the current bounds in terms of the X11 Root Window.
gfx::Rect GetX11RootWindowBounds() const;
+ // Returns the current bounds in terms of the X11 Root Window including the
+ // borders provided by the window manager (if any).
+ gfx::Rect GetX11RootWindowOuterBounds() const;
+
+ // Returns the window shape if the window is not rectangular. Returns NULL
+ // otherwise.
+ ::Region GetWindowShape() const;
+
// Called by X11DesktopHandler to notify us that the native windowing system
// has changed our activation.
void HandleNativeWidgetActivationChanged(bool active);
- void AddObserver(views::DesktopRootWindowHostObserverX11* observer);
- void RemoveObserver(views::DesktopRootWindowHostObserverX11* observer);
+ void AddObserver(views::DesktopWindowTreeHostObserverX11* observer);
+ void RemoveObserver(views::DesktopWindowTreeHostObserverX11* observer);
+
+ // Swaps the current handler for events in the non client view with |handler|.
+ void SwapNonClientEventHandler(scoped_ptr<ui::EventHandler> handler);
// Deallocates the internal list of open windows.
static void CleanUpWindowList();
protected:
- // Overridden from DesktopRootWindowHost:
+ // Overridden from DesktopWindowTreeHost:
virtual void Init(aura::Window* content_window,
- const Widget::InitParams& params,
- aura::RootWindow::CreateParams* rw_create_params) OVERRIDE;
- virtual void OnRootWindowCreated(aura::RootWindow* root,
- const Widget::InitParams& params) OVERRIDE;
+ const Widget::InitParams& params) OVERRIDE;
+ virtual void OnNativeWidgetCreated(const Widget::InitParams& params) OVERRIDE;
virtual scoped_ptr<corewm::Tooltip> CreateTooltip() OVERRIDE;
virtual scoped_ptr<aura::client::DragDropClient>
CreateDragDropClient(DesktopNativeCursorManager* cursor_manager) OVERRIDE;
virtual void Close() OVERRIDE;
virtual void CloseNow() OVERRIDE;
- virtual aura::RootWindowHost* AsRootWindowHost() OVERRIDE;
+ virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE;
virtual void ShowWindowWithState(ui::WindowShowState show_state) OVERRIDE;
virtual void ShowMaximizedWithBounds(
const gfx::Rect& restored_bounds) OVERRIDE;
@@ -106,7 +122,8 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 :
virtual bool HasCapture() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
virtual bool IsAlwaysOnTop() const OVERRIDE;
- virtual bool SetWindowTitle(const string16& title) OVERRIDE;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) OVERRIDE;
+ virtual bool SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void ClearNativeFocus() OVERRIDE;
virtual Widget::MoveLoopResult RunMoveLoop(
const gfx::Vector2d& drag_offset,
@@ -114,9 +131,9 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 :
Widget::MoveLoopEscapeBehavior escape_behavior) OVERRIDE;
virtual void EndMoveLoop() OVERRIDE;
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
- virtual bool ShouldUseNativeFrame() OVERRIDE;
+ virtual bool ShouldUseNativeFrame() const OVERRIDE;
+ virtual bool ShouldWindowContentsBeTransparent() const OVERRIDE;
virtual void FrameTypeChanged() OVERRIDE;
- virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
virtual void SetFullscreen(bool fullscreen) OVERRIDE;
virtual bool IsFullscreen() const OVERRIDE;
virtual void SetOpacity(unsigned char opacity) OVERRIDE;
@@ -128,43 +145,44 @@ class VIEWS_EXPORT DesktopRootWindowHostX11 :
virtual void OnNativeWidgetFocus() OVERRIDE;
virtual void OnNativeWidgetBlur() OVERRIDE;
virtual bool IsAnimatingClosed() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
- // Overridden from aura::RootWindowHost:
- virtual aura::RootWindow* GetRootWindow() OVERRIDE;
+ // Overridden from aura::WindowTreeHost:
+ virtual ui::EventSource* GetEventSource() OVERRIDE;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE;
virtual void Show() OVERRIDE;
virtual void Hide() OVERRIDE;
- virtual void ToggleFullScreen() OVERRIDE;
virtual gfx::Rect GetBounds() const OVERRIDE;
virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual gfx::Insets GetInsets() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
virtual gfx::Point GetLocationOnNativeScreen() const OVERRIDE;
virtual void SetCapture() OVERRIDE;
virtual void ReleaseCapture() OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual bool QueryMouseLocation(gfx::Point* location_return) OVERRIDE;
- virtual bool ConfineCursorToRootWindow() OVERRIDE;
- virtual void UnConfineCursor() OVERRIDE;
- virtual void OnCursorVisibilityChanged(bool show) OVERRIDE;
- virtual void MoveCursorTo(const gfx::Point& location) OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void PrepareForShutdown() OVERRIDE;
+ virtual void SetCursorNative(gfx::NativeCursor cursor) OVERRIDE;
+ virtual void MoveCursorToNative(const gfx::Point& location) OVERRIDE;
+ virtual void OnCursorVisibilityChangedNative(bool show) OVERRIDE;
-private:
+ // Overridden frm ui::EventSource
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
+
+ private:
// Initializes our X11 surface to draw on. This method performs all
// initialization related to talking to the X11 server.
void InitX11Window(const Widget::InitParams& params);
- // Creates an aura::RootWindow to contain the |content_window|, along with
- // all aura client objects that direct behavior.
- aura::RootWindow* InitRootWindow(const Widget::InitParams& params);
+ // Creates an aura::WindowEventDispatcher to contain the |content_window|,
+ // along with all aura client objects that direct behavior.
+ aura::WindowEventDispatcher* InitDispatcher(const Widget::InitParams& params);
+
+ // Called when |xwindow_|'s _NET_WM_STATE property is updated.
+ void OnWMStateUpdated();
+
+ // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated.
+ void OnFrameExtentsUpdated();
- // Returns true if there's an X window manager present... in most cases. Some
- // window managers (notably, ion3) don't implement enough of ICCCM for us to
- // detect that they're there.
- bool IsWindowManagerPresent();
+ // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active.
+ void UpdateWMUserTime(const ui::PlatformEvent& event);
// Sends a message to the x11 window manager, enabling or disabling the
// states |state1| and |state2|.
@@ -173,6 +191,9 @@ private:
// Checks if the window manager has set a specific state.
bool HasWMSpecProperty(const char* property) const;
+ // Sets whether the window's borders are provided by the window manager.
+ void SetUseNativeFrame(bool use_native_frame);
+
// Called when another DRWHL takes capture, or when capture is released
// entirely.
void OnCaptureReleased();
@@ -194,13 +215,28 @@ private:
void SerializeImageRepresentation(const gfx::ImageSkiaRep& rep,
std::vector<unsigned long>* data);
+ // Returns an 8888 ARGB visual. Can return NULL if there is no matching
+ // visual on this display.
+ Visual* GetARGBVisual();
+
// See comment for variable open_windows_.
static std::list<XID>& open_windows();
- // Overridden from Dispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
+ // Map the window (shows it) taking into account the given |show_state|.
+ void MapWindow(ui::WindowShowState show_state);
- base::WeakPtrFactory<DesktopRootWindowHostX11> close_widget_factory_;
+ void SetWindowTransparency();
+
+ // Relayout the widget's client and non-client views.
+ void Relayout();
+
+ // ui::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+
+ void DelayedResize(const gfx::Size& size);
+
+ base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_;
// X11 things
// The display and the native X window hosting the root window.
@@ -232,15 +268,17 @@ private:
// The window manager state bits.
std::set< ::Atom> window_properties_;
- // Local flag for fullscreen state to avoid a state mismatch between
- // server and local window_properties_ during app-initiated fullscreen.
+ // Whether |xwindow_| was requested to be fullscreen via SetFullscreen().
bool is_fullscreen_;
// True if the window should stay on top of most other windows.
bool is_always_on_top_;
- // We are owned by the RootWindow, but we have to have a back pointer to it.
- aura::RootWindow* root_window_;
+ // True if the window has title-bar / borders provided by the window manager.
+ bool use_native_frame_;
+
+ // Whether we used an ARGB visual for our window.
+ bool use_argb_visual_;
scoped_ptr<DesktopDispatcherClient> dispatcher_client_;
@@ -249,7 +287,7 @@ private:
// Current Aura cursor.
gfx::NativeCursor current_cursor_;
- scoped_ptr<X11WindowEventFilter> x11_window_event_filter_;
+ scoped_ptr<ui::EventHandler> x11_non_client_event_filter_;
scoped_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
// TODO(beng): Consider providing an interface to DesktopNativeWidgetAura
@@ -262,30 +300,46 @@ private:
// We can optionally have a parent which can order us to close, or own
// children who we're responsible for closing when we CloseNow().
- DesktopRootWindowHostX11* window_parent_;
- std::set<DesktopRootWindowHostX11*> window_children_;
+ DesktopWindowTreeHostX11* window_parent_;
+ std::set<DesktopWindowTreeHostX11*> window_children_;
- ObserverList<DesktopRootWindowHostObserverX11> observer_list_;
+ ObserverList<DesktopWindowTreeHostObserverX11> observer_list_;
- // Copy of custom window shape specified via SetShape(), if any.
- ::Region custom_window_shape_;
+ // The window shape if the window is non-rectangular.
+ ::Region window_shape_;
+
+ // Whether |window_shape_| was set via SetShape().
+ bool custom_window_shape_;
+
+ // The size of the window manager provided borders (if any).
+ gfx::Insets native_window_frame_borders_;
// The current root window host that has capture. While X11 has something
// like Windows SetCapture()/ReleaseCapture(), it is entirely implicit and
// there are no notifications when this changes. We need to track this so we
// can notify widgets when they have lost capture, which controls a bunch of
// things in views like hiding menus.
- static DesktopRootWindowHostX11* g_current_capture;
+ static DesktopWindowTreeHostX11* g_current_capture;
// A list of all (top-level) windows that have been created but not yet
// destroyed.
static std::list<XID>* open_windows_;
- string16 window_title_;
+ scoped_ptr<X11ScopedCapture> x11_capture_;
+
+ 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_;
+
+ base::CancelableCallback<void()> delayed_resize_task_;
- DISALLOW_COPY_AND_ASSIGN(DesktopRootWindowHostX11);
+ DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11);
};
} // namespace views
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_ROOT_WINDOW_HOST_X11_H_
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_X11_H_
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
new file mode 100644
index 00000000000..8a66c6e0327
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -0,0 +1,448 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include <X11/extensions/shape.h>
+#include <X11/Xlib.h>
+
+// Get rid of X11 macros which conflict with gtest.
+#undef Bool
+#undef None
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/hit_test.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/point.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/test/x11_property_change_waiter.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/non_client_view.h"
+
+namespace views {
+
+namespace {
+
+// Blocks till the window state hint, |hint|, is set or unset.
+class WMStateWaiter : public X11PropertyChangeWaiter {
+ public:
+ WMStateWaiter(XID window,
+ const char* hint,
+ bool wait_till_set)
+ : X11PropertyChangeWaiter(window, "_NET_WM_STATE"),
+ hint_(hint),
+ wait_till_set_(wait_till_set) {
+
+ const char* kAtomsToCache[] = {
+ hint,
+ NULL
+ };
+ atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache));
+ }
+
+ virtual ~WMStateWaiter() {
+ }
+
+ private:
+ // X11PropertyChangeWaiter:
+ virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE {
+ std::vector<Atom> hints;
+ if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) {
+ std::vector<Atom>::iterator it = std::find(
+ hints.begin(),
+ hints.end(),
+ atom_cache_->GetAtom(hint_));
+ bool hint_set = (it != hints.end());
+ return hint_set != wait_till_set_;
+ }
+ return true;
+ }
+
+ scoped_ptr<ui::X11AtomCache> atom_cache_;
+
+ // The name of the hint to wait to get set or unset.
+ const char* hint_;
+
+ // Whether we are waiting for |hint| to be set or unset.
+ bool wait_till_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(WMStateWaiter);
+};
+
+// A NonClientFrameView with a window mask with the bottom right corner cut out.
+class ShapedNonClientFrameView : public NonClientFrameView {
+ public:
+ explicit ShapedNonClientFrameView() {
+ }
+
+ virtual ~ShapedNonClientFrameView() {
+ }
+
+ // NonClientFrameView:
+ virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
+ return bounds();
+ }
+ virtual gfx::Rect GetWindowBoundsForClientBounds(
+ const gfx::Rect& client_bounds) const OVERRIDE {
+ return client_bounds;
+ }
+ virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
+ return HTNOWHERE;
+ }
+ virtual void GetWindowMask(const gfx::Size& size,
+ gfx::Path* window_mask) OVERRIDE {
+ int right = size.width();
+ int bottom = size.height();
+
+ window_mask->moveTo(0, 0);
+ window_mask->lineTo(0, bottom);
+ window_mask->lineTo(right, bottom);
+ window_mask->lineTo(right, 10);
+ window_mask->lineTo(right - 10, 10);
+ window_mask->lineTo(right - 10, 0);
+ window_mask->close();
+ }
+ virtual void ResetWindowControls() OVERRIDE {
+ }
+ virtual void UpdateWindowIcon() OVERRIDE {
+ }
+ virtual void UpdateWindowTitle() OVERRIDE {
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShapedNonClientFrameView);
+};
+
+class ShapedWidgetDelegate : public WidgetDelegateView {
+ public:
+ ShapedWidgetDelegate() {
+ }
+
+ virtual ~ShapedWidgetDelegate() {
+ }
+
+ // WidgetDelegateView:
+ virtual NonClientFrameView* CreateNonClientFrameView(
+ Widget* widget) OVERRIDE {
+ return new ShapedNonClientFrameView;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShapedWidgetDelegate);
+};
+
+// Creates a widget of size 100x100.
+scoped_ptr<Widget> CreateWidget(WidgetDelegate* delegate) {
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
+ params.delegate = delegate;
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.remove_standard_frame = true;
+ params.native_widget = new DesktopNativeWidgetAura(widget.get());
+ params.bounds = gfx::Rect(100, 100, 100, 100);
+ widget->Init(params);
+ return widget.Pass();
+}
+
+// Returns the list of rectangles which describe |xid|'s bounding region via the
+// X shape extension.
+std::vector<gfx::Rect> GetShapeRects(XID xid) {
+ int dummy;
+ int shape_rects_size;
+ XRectangle* shape_rects = XShapeGetRectangles(gfx::GetXDisplay(),
+ xid,
+ ShapeBounding,
+ &shape_rects_size,
+ &dummy);
+
+ std::vector<gfx::Rect> shape_vector;
+ for (int i = 0; i < shape_rects_size; ++i) {
+ shape_vector.push_back(gfx::Rect(
+ shape_rects[i].x,
+ shape_rects[i].y,
+ shape_rects[i].width,
+ shape_rects[i].height));
+ }
+ XFree(shape_rects);
+ return shape_vector;
+}
+
+// Returns true if one of |rects| contains point (x,y).
+bool ShapeRectContainsPoint(const std::vector<gfx::Rect>& shape_rects,
+ int x,
+ int y) {
+ gfx::Point point(x, y);
+ for (size_t i = 0; i < shape_rects.size(); ++i) {
+ if (shape_rects[i].Contains(point))
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+class DesktopWindowTreeHostX11Test : public ViewsTestBase {
+ public:
+ DesktopWindowTreeHostX11Test() {
+ }
+ virtual ~DesktopWindowTreeHostX11Test() {
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ViewsTestBase::SetUp();
+
+ // Make X11 synchronous for our display connection. This does not force the
+ // window manager to behave synchronously.
+ XSynchronize(gfx::GetXDisplay(), True);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ XSynchronize(gfx::GetXDisplay(), False);
+ ViewsTestBase::TearDown();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11Test);
+};
+
+// Tests that the shape is properly set on the x window.
+TEST_F(DesktopWindowTreeHostX11Test, Shape) {
+ if (!ui::IsShapeExtensionAvailable())
+ return;
+
+ // 1) Test setting the window shape via the NonClientFrameView. This technique
+ // is used to get rounded corners on Chrome windows when not using the native
+ // window frame.
+ scoped_ptr<Widget> widget1 = CreateWidget(new ShapedWidgetDelegate());
+ widget1->Show();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+ std::vector<gfx::Rect> shape_rects = GetShapeRects(xid1);
+ ASSERT_FALSE(shape_rects.empty());
+
+ // The widget was supposed to be 100x100, but the WM might have ignored this
+ // suggestion.
+ int widget_width = widget1->GetWindowBoundsInScreen().width();
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, widget_width - 15, 5));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, widget_width - 5, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, widget_width - 5, 15));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, widget_width + 5, 15));
+
+ // Changing widget's size should update the shape.
+ widget1->SetBounds(gfx::Rect(100, 100, 200, 200));
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ if (widget1->GetWindowBoundsInScreen().width() == 200) {
+ shape_rects = GetShapeRects(xid1);
+ ASSERT_FALSE(shape_rects.empty());
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 85, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 185, 5));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 195, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 195, 15));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 205, 15));
+ }
+
+ if (ui::WmSupportsHint(ui::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"))) {
+ // The shape should be changed to a rectangle which fills the entire screen
+ // when |widget1| is maximized.
+ {
+ WMStateWaiter waiter(xid1, "_NET_WM_STATE_MAXIMIZED_VERT", true);
+ widget1->Maximize();
+ waiter.Wait();
+ }
+
+ // xvfb does not support Xrandr so we cannot check the maximized window's
+ // bounds.
+ gfx::Rect maximized_bounds;
+ ui::GetWindowRect(xid1, &maximized_bounds);
+
+ shape_rects = GetShapeRects(xid1);
+ ASSERT_FALSE(shape_rects.empty());
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects,
+ maximized_bounds.width() - 1,
+ 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects,
+ maximized_bounds.width() - 1,
+ 15));
+ }
+
+ // 2) Test setting the window shape via Widget::SetShape().
+ gfx::Path shape2;
+ shape2.moveTo(10, 0);
+ shape2.lineTo(10, 10);
+ shape2.lineTo(0, 10);
+ shape2.lineTo(0, 100);
+ shape2.lineTo(100, 100);
+ shape2.lineTo(100, 0);
+ shape2.close();
+
+ scoped_ptr<Widget> widget2(CreateWidget(NULL));
+ widget2->Show();
+ widget2->SetShape(shape2.CreateNativeRegion());
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ XID xid2 = widget2->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+ shape_rects = GetShapeRects(xid2);
+ ASSERT_FALSE(shape_rects.empty());
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 5, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 15, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 15));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 105, 15));
+
+ // Changing the widget's size should not affect the shape.
+ widget2->SetBounds(gfx::Rect(100, 100, 200, 200));
+ shape_rects = GetShapeRects(xid2);
+ ASSERT_FALSE(shape_rects.empty());
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 5, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 15, 5));
+ EXPECT_TRUE(ShapeRectContainsPoint(shape_rects, 95, 15));
+ EXPECT_FALSE(ShapeRectContainsPoint(shape_rects, 105, 15));
+}
+
+// Test that the widget ignores changes in fullscreen state initiated by the
+// window manager (e.g. via a window manager accelerator key).
+TEST_F(DesktopWindowTreeHostX11Test, WindowManagerTogglesFullscreen) {
+ if (!ui::WmSupportsHint(ui::GetAtom("_NET_WM_STATE_FULLSCREEN")))
+ return;
+
+ scoped_ptr<Widget> widget = CreateWidget(new ShapedWidgetDelegate());
+ XID xid = widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+ widget->Show();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ gfx::Rect initial_bounds = widget->GetWindowBoundsInScreen();
+ {
+ WMStateWaiter waiter(xid, "_NET_WM_STATE_FULLSCREEN", true);
+ widget->SetFullscreen(true);
+ waiter.Wait();
+ }
+ EXPECT_TRUE(widget->IsFullscreen());
+
+ // Emulate the window manager exiting fullscreen via a window manager
+ // accelerator key. It should not affect the widget's fullscreen state.
+ {
+ const char* kAtomsToCache[] = {
+ "_NET_WM_STATE",
+ "_NET_WM_STATE_FULLSCREEN",
+ NULL
+ };
+ Display* display = gfx::GetXDisplay();
+ ui::X11AtomCache atom_cache(display, kAtomsToCache);
+
+ XEvent xclient;
+ memset(&xclient, 0, sizeof(xclient));
+ xclient.type = ClientMessage;
+ xclient.xclient.window = xid;
+ xclient.xclient.message_type = atom_cache.GetAtom("_NET_WM_STATE");
+ xclient.xclient.format = 32;
+ xclient.xclient.data.l[0] = 0;
+ xclient.xclient.data.l[1] = atom_cache.GetAtom("_NET_WM_STATE_FULLSCREEN");
+ xclient.xclient.data.l[2] = 0;
+ xclient.xclient.data.l[3] = 1;
+ xclient.xclient.data.l[4] = 0;
+ XSendEvent(display, DefaultRootWindow(display), False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xclient);
+
+ WMStateWaiter waiter(xid, "_NET_WM_STATE_FULLSCREEN", false);
+ waiter.Wait();
+ }
+ EXPECT_TRUE(widget->IsFullscreen());
+
+ // Calling Widget::SetFullscreen(false) should clear the widget's fullscreen
+ // state and clean things up.
+ widget->SetFullscreen(false);
+ EXPECT_FALSE(widget->IsFullscreen());
+ EXPECT_EQ(initial_bounds.ToString(),
+ widget->GetWindowBoundsInScreen().ToString());
+}
+
+// Tests that the minimization information is propagated to the content window.
+TEST_F(DesktopWindowTreeHostX11Test, ToggleMinimizePropogateToContentWindow) {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(&widget);
+ widget.Init(params);
+ widget.Show();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ XID xid = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+ Display* display = gfx::GetXDisplay();
+
+ // Minimize by sending _NET_WM_STATE_HIDDEN
+ {
+ const char* kAtomsToCache[] = {
+ "_NET_WM_STATE",
+ "_NET_WM_STATE_HIDDEN",
+ NULL
+ };
+
+ ui::X11AtomCache atom_cache(display, kAtomsToCache);
+
+ std::vector< ::Atom> atom_list;
+ atom_list.push_back(atom_cache.GetAtom("_NET_WM_STATE_HIDDEN"));
+ ui::SetAtomArrayProperty(xid, "_NET_WM_STATE", "ATOM", atom_list);
+
+ XEvent xevent;
+ memset(&xevent, 0, sizeof(xevent));
+ xevent.type = PropertyNotify;
+ xevent.xproperty.type = PropertyNotify;
+ xevent.xproperty.send_event = 1;
+ xevent.xproperty.display = display;
+ xevent.xproperty.window = xid;
+ xevent.xproperty.atom = atom_cache.GetAtom("_NET_WM_STATE");
+ xevent.xproperty.state = 0;
+ XSendEvent(display, DefaultRootWindow(display), False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xevent);
+
+ WMStateWaiter waiter(xid, "_NET_WM_STATE_HIDDEN", true);
+ waiter.Wait();
+ }
+ EXPECT_FALSE(widget.GetNativeWindow()->IsVisible());
+
+ // Show from minimized by sending _NET_WM_STATE_FOCUSED
+ {
+ const char* kAtomsToCache[] = {
+ "_NET_WM_STATE",
+ "_NET_WM_STATE_FOCUSED",
+ NULL
+ };
+
+ ui::X11AtomCache atom_cache(display, kAtomsToCache);
+
+ std::vector< ::Atom> atom_list;
+ atom_list.push_back(atom_cache.GetAtom("_NET_WM_STATE_FOCUSED"));
+ ui::SetAtomArrayProperty(xid, "_NET_WM_STATE", "ATOM", atom_list);
+
+ XEvent xevent;
+ memset(&xevent, 0, sizeof(xevent));
+ xevent.type = PropertyNotify;
+ xevent.xproperty.type = PropertyNotify;
+ xevent.xproperty.send_event = 1;
+ xevent.xproperty.display = display;
+ xevent.xproperty.window = xid;
+ xevent.xproperty.atom = atom_cache.GetAtom("_NET_WM_STATE");
+ xevent.xproperty.state = 0;
+ XSendEvent(display, DefaultRootWindow(display), False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xevent);
+
+ WMStateWaiter waiter(xid, "_NET_WM_STATE_FOCUSED", true);
+ waiter.Wait();
+ }
+ EXPECT_TRUE(widget.GetNativeWindow()->IsVisible());
+}
+
+} // namespace views
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 0cfe040cbdf..d43b853093b 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc
@@ -9,19 +9,18 @@
#include "base/message_loop/message_loop.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/x/x11_menu_list.h"
#include "ui/base/x/x11_util.h"
-
-#if !defined(OS_CHROMEOS)
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/x/x11_error_tracker.h"
#include "ui/views/ime/input_method.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
-#endif
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
namespace {
const char* kAtomsToCache[] = {
"_NET_ACTIVE_WINDOW",
- "_NET_SUPPORTED",
NULL
};
@@ -43,10 +42,12 @@ X11DesktopHandler* X11DesktopHandler::get() {
X11DesktopHandler::X11DesktopHandler()
: xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
+ wm_user_time_ms_(0),
current_window_(None),
atom_cache_(xdisplay_, kAtomsToCache),
wm_supports_active_window_(false) {
- base::MessagePumpX11::Current()->AddDispatcherForRootWindow(this);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
aura::Env::GetInstance()->AddObserver(this);
XWindowAttributes attr;
@@ -55,22 +56,16 @@ X11DesktopHandler::X11DesktopHandler()
attr.your_event_mask | PropertyChangeMask |
StructureNotifyMask | SubstructureNotifyMask);
- std::vector<Atom> atoms;
- if (ui::GetAtomArrayProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &atoms)) {
- Atom active_window = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW");
- for (std::vector<Atom>::iterator iter = atoms.begin(); iter != atoms.end();
- ++iter) {
- if (*(iter) == active_window) {
- wm_supports_active_window_ = true;
- break;
- }
- }
- }
+ ::Window active_window;
+ wm_supports_active_window_ =
+ ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &active_window) &&
+ active_window;
}
X11DesktopHandler::~X11DesktopHandler() {
aura::Env::GetInstance()->RemoveObserver(this);
- base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow(this);
+ if (ui::PlatformEventSource::GetInstance())
+ ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
}
void X11DesktopHandler::ActivateWindow(::Window window) {
@@ -84,7 +79,7 @@ void X11DesktopHandler::ActivateWindow(::Window window) {
xclient.xclient.message_type = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW");
xclient.xclient.format = 32;
xclient.xclient.data.l[0] = 1; // Specified we are an app.
- xclient.xclient.data.l[1] = CurrentTime;
+ xclient.xclient.data.l[1] = wm_user_time_ms_;
xclient.xclient.data.l[2] = None;
xclient.xclient.data.l[3] = 0;
xclient.xclient.data.l[4] = 0;
@@ -94,6 +89,12 @@ void X11DesktopHandler::ActivateWindow(::Window window) {
&xclient);
} else {
XRaiseWindow(xdisplay_, window);
+
+ // XRaiseWindow will not give input focus to the window. We now need to ask
+ // the X server to do that. Note that the call will raise an X error if the
+ // window is not mapped.
+ XSetInputFocus(xdisplay_, window, RevertToParent, CurrentTime);
+
OnActiveWindowChanged(window);
}
}
@@ -102,16 +103,14 @@ bool X11DesktopHandler::IsActiveWindow(::Window window) const {
return window == current_window_;
}
-void X11DesktopHandler::ProcessXEvent(const base::NativeEvent& event) {
+void X11DesktopHandler::ProcessXEvent(XEvent* event) {
switch (event->type) {
- case EnterNotify:
- if (event->xcrossing.focus == True &&
- current_window_ != event->xcrossing.window)
- OnActiveWindowChanged(event->xcrossing.window);
+ case FocusIn:
+ if (current_window_ != event->xfocus.window)
+ OnActiveWindowChanged(event->xfocus.window);
break;
- case LeaveNotify:
- if (event->xcrossing.focus == False &&
- current_window_ == event->xcrossing.window)
+ case FocusOut:
+ if (current_window_ == event->xfocus.window)
OnActiveWindowChanged(None);
break;
default:
@@ -119,25 +118,53 @@ void X11DesktopHandler::ProcessXEvent(const base::NativeEvent& event) {
}
}
-bool X11DesktopHandler::Dispatch(const base::NativeEvent& event) {
- // Check for a change to the active window.
+bool X11DesktopHandler::CanDispatchEvent(const ui::PlatformEvent& event) {
+ return event->type == CreateNotify || event->type == DestroyNotify ||
+ (event->type == PropertyNotify &&
+ event->xproperty.window == x_root_window_);
+}
+
+uint32_t X11DesktopHandler::DispatchEvent(const ui::PlatformEvent& event) {
switch (event->type) {
case PropertyNotify: {
- ::Atom active_window = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW");
-
- if (event->xproperty.window == x_root_window_ &&
- event->xproperty.atom == active_window) {
- int window;
- if (ui::GetIntProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) &&
+ // Check for a change to the active window.
+ CHECK_EQ(x_root_window_, event->xproperty.window);
+ ::Atom active_window_atom = atom_cache_.GetAtom("_NET_ACTIVE_WINDOW");
+ if (event->xproperty.atom == active_window_atom) {
+ ::Window window;
+ if (ui::GetXIDProperty(x_root_window_, "_NET_ACTIVE_WINDOW", &window) &&
window) {
- OnActiveWindowChanged(static_cast< ::Window>(window));
+ OnActiveWindowChanged(window);
}
}
break;
}
+
+ // Menus created by Chrome can be drag and drop targets. Since they are
+ // direct children of the screen root window and have override_redirect
+ // we cannot use regular _NET_CLIENT_LIST_STACKING property to find them
+ // and use a separate cache to keep track of them.
+ // TODO(varkha): Implement caching of all top level X windows and their
+ // coordinates and stacking order to eliminate repeated calls to X server
+ // during mouse movement, drag and shaping events.
+ case CreateNotify: {
+ // The window might be destroyed if the message pump haven't gotten a
+ // chance to run but we can safely ignore the X error.
+ gfx::X11ErrorTracker error_tracker;
+ XCreateWindowEvent *xcwe = &event->xcreatewindow;
+ ui::XMenuList::GetInstance()->MaybeRegisterMenu(xcwe->window);
+ break;
+ }
+ case DestroyNotify: {
+ XDestroyWindowEvent *xdwe = &event->xdestroywindow;
+ ui::XMenuList::GetInstance()->MaybeUnregisterMenu(xdwe->window);
+ break;
+ }
+ default:
+ NOTREACHED();
}
- return true;
+ return ui::POST_DISPATCH_NONE;
}
void X11DesktopHandler::OnWindowInitialized(aura::Window* window) {
@@ -151,17 +178,18 @@ void X11DesktopHandler::OnWillDestroyEnv() {
void X11DesktopHandler::OnActiveWindowChanged(::Window xid) {
if (current_window_ == xid)
return;
- DesktopRootWindowHostX11* old_host =
- views::DesktopRootWindowHostX11::GetHostForXID(current_window_);
+ DesktopWindowTreeHostX11* old_host =
+ views::DesktopWindowTreeHostX11::GetHostForXID(current_window_);
if (old_host)
old_host->HandleNativeWidgetActivationChanged(false);
- DesktopRootWindowHostX11* new_host =
- views::DesktopRootWindowHostX11::GetHostForXID(xid);
+ // Update the current window ID to effectively change the active widget.
+ current_window_ = xid;
+
+ DesktopWindowTreeHostX11* new_host =
+ views::DesktopWindowTreeHostX11::GetHostForXID(xid);
if (new_host)
new_host->HandleNativeWidgetActivationChanged(true);
-
- current_window_ = xid;
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h
index 3399b401cf1..56b2084e7a5 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h
+++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.h
@@ -9,8 +9,10 @@
// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
#undef RootWindow
-#include "base/message_loop/message_loop.h"
+#include <vector>
+
#include "ui/aura/env_observer.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/views/views_export.h"
@@ -22,13 +24,23 @@ namespace views {
// A singleton that owns global objects related to the desktop and listens for
// X11 events on the X11 root window. Destroys itself when aura::Env is
// deleted.
-class VIEWS_EXPORT X11DesktopHandler : public base::MessageLoop::Dispatcher,
+class VIEWS_EXPORT X11DesktopHandler : public ui::PlatformEventDispatcher,
public aura::EnvObserver {
public:
// Returns the singleton handler.
static X11DesktopHandler* get();
+ // Gets/sets the X11 server time of the most recent mouse click, touch or
+ // key press on a Chrome window.
+ int wm_user_time_ms() const {
+ return wm_user_time_ms_;
+ }
+ void set_wm_user_time_ms(unsigned long time_ms) {
+ wm_user_time_ms_ = time_ms;
+ }
+
// Sends a request to the window manager to activate |window|.
+ // This method should only be called if the window is already mapped.
void ActivateWindow(::Window window);
// Checks if the current active window is |window|.
@@ -37,10 +49,11 @@ class VIEWS_EXPORT X11DesktopHandler : public base::MessageLoop::Dispatcher,
// Processes activation/focus related events. Some of these events are
// dispatched to the X11 window dispatcher, and not to the X11 root-window
// dispatcher. The window dispatcher sends these events to here.
- void ProcessXEvent(const base::NativeEvent& event);
+ void ProcessXEvent(XEvent* event);
- // Overridden from MessageLoop::Dispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
+ // ui::PlatformEventDispatcher
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
// Overridden from aura::EnvObserver:
virtual void OnWindowInitialized(aura::Window* window) OVERRIDE;
@@ -59,6 +72,10 @@ class VIEWS_EXPORT X11DesktopHandler : public base::MessageLoop::Dispatcher,
// The native root window.
::Window x_root_window_;
+ // The X11 server time of the most recent mouse click, touch, or key press
+ // on a Chrome window.
+ unsigned long wm_user_time_ms_;
+
// The activated window.
::Window current_window_;
diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc
index a79d365ebc7..195d102a587 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc
@@ -5,45 +5,22 @@
#include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h"
#include <X11/Xlib.h>
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
-#undef RootWindow
#include "base/debug/stack_trace.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_x11.h"
#include "base/run_loop.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/event.h"
#include "ui/gfx/screen.h"
-namespace {
-
-// Delay moving the window.
-//
-// When we receive a mouse move event, we have to have it processed in a
-// different run through the message pump because moving the window will
-// otherwise prevent tasks from running.
-//
-// This constant was derived with playing with builds of chrome; it has no
-// theoretical justification.
-//
-// TODO(erg): This helps with the performance of dragging windows, but it
-// doesn't really solve the hard problems, which is that various calls to X11,
-// such as XQueryPointer, ui::IsWindowVisible() and ui::WindowContainsPoint()
-// take a while to get replies and block in the process. I've seen all of the
-// above take as long as 20ms to respond.
-const int kMoveDelay = 3;
-
-} // namespace
-
namespace views {
X11DesktopWindowMoveClient::X11DesktopWindowMoveClient()
: move_loop_(this),
- root_window_(NULL) {
+ host_(NULL) {
}
X11DesktopWindowMoveClient::~X11DesktopWindowMoveClient() {}
@@ -51,15 +28,7 @@ X11DesktopWindowMoveClient::~X11DesktopWindowMoveClient() {}
void X11DesktopWindowMoveClient::OnMouseMovement(XMotionEvent* event) {
gfx::Point cursor_point(event->x_root, event->y_root);
gfx::Point system_loc = cursor_point - window_offset_;
-
- gfx::Rect target_rect(system_loc, root_window_->host()->GetBounds().size());
-
- window_move_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kMoveDelay),
- base::Bind(&X11DesktopWindowMoveClient::SetHostBounds,
- base::Unretained(this),
- target_rect));
+ host_->SetBounds(gfx::Rect(system_loc, host_->GetBounds().size()));
}
void X11DesktopWindowMoveClient::OnMouseReleased() {
@@ -67,33 +36,25 @@ void X11DesktopWindowMoveClient::OnMouseReleased() {
}
void X11DesktopWindowMoveClient::OnMoveLoopEnded() {
- root_window_ = NULL;
+ host_ = NULL;
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostLinux, aura::client::WindowMoveClient implementation:
+// DesktopWindowTreeHostLinux, aura::client::WindowMoveClient implementation:
aura::client::WindowMoveResult X11DesktopWindowMoveClient::RunMoveLoop(
aura::Window* source,
const gfx::Vector2d& drag_offset,
aura::client::WindowMoveSource move_source) {
window_offset_ = drag_offset;
- root_window_ = source->GetDispatcher();
+ host_ = source->GetHost();
- bool success = move_loop_.RunMoveLoop(source, root_window_->last_cursor());
+ bool success = move_loop_.RunMoveLoop(source, host_->last_cursor());
return success ? aura::client::MOVE_SUCCESSFUL : aura::client::MOVE_CANCELED;
}
void X11DesktopWindowMoveClient::EndMoveLoop() {
- window_move_timer_.Stop();
move_loop_.EndMoveLoop();
}
-////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostLinux, private:
-
-void X11DesktopWindowMoveClient::SetHostBounds(const gfx::Rect& rect) {
- root_window_->SetHostBounds(rect);
-}
-
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
index 3be6a63c325..44bdd91ff70 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
+++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
@@ -7,25 +7,17 @@
#include <X11/Xlib.h>
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
-#undef RootWindow
-
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
-#include "base/timer/timer.h"
-#include "ui/aura/client/window_move_client.h"
#include "ui/gfx/point.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
#include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop_delegate.h"
+#include "ui/wm/public/window_move_client.h"
namespace aura {
-class RootWindow;
-}
-
-namespace gfx {
-class Rect;
+class WindowTreeHost;
}
namespace views {
@@ -51,21 +43,16 @@ class VIEWS_EXPORT X11DesktopWindowMoveClient :
virtual void EndMoveLoop() OVERRIDE;
private:
- // Callback from |window_move_timer_|.
- void SetHostBounds(const gfx::Rect& rect);
-
X11WholeScreenMoveLoop move_loop_;
// We need to keep track of this so we can actually move it when reacting to
// mouse events.
- aura::RootWindow* root_window_;
+ aura::WindowTreeHost* host_;
// Our cursor offset from the top left window origin when the drag
// started. Used to calculate the window's new bounds relative to the current
// location of the cursor.
gfx::Vector2d window_offset_;
-
- base::OneShotTimer<X11DesktopWindowMoveClient> window_move_timer_;
};
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.cc b/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.cc
new file mode 100644
index 00000000000..b48bb5005ba
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.cc
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/desktop_aura/x11_scoped_capture.h"
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+
+#include "ui/gfx/x/x11_types.h"
+
+namespace views {
+
+X11ScopedCapture::X11ScopedCapture(XID window)
+ : captured_(false) {
+ // TODO(sad): Use XI2 API instead.
+ unsigned int event_mask = PointerMotionMask | ButtonReleaseMask |
+ ButtonPressMask;
+ int status = XGrabPointer(gfx::GetXDisplay(), window, True, event_mask,
+ GrabModeAsync, GrabModeAsync, None, None,
+ CurrentTime);
+ captured_ = status == GrabSuccess;
+}
+
+X11ScopedCapture::~X11ScopedCapture() {
+ if (captured_) {
+ XUngrabPointer(gfx::GetXDisplay(), CurrentTime);
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.h b/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.h
new file mode 100644
index 00000000000..cd744c86451
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/x11_scoped_capture.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_X11_SCOPED_CAPTURE_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_X11_SCOPED_CAPTURE_H_
+
+#include "base/basictypes.h"
+
+typedef unsigned long XID;
+
+namespace views {
+
+// Grabs X11 input on a window., i.e. all subsequent mouse events are dispatched
+// to the window, while the capture is active.
+class X11ScopedCapture {
+ public:
+ explicit X11ScopedCapture(XID window);
+ virtual ~X11ScopedCapture();
+
+ private:
+ bool captured_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11ScopedCapture);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_X11_SCOPED_CAPTURE_H_
diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.cc b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.cc
new file mode 100644
index 00000000000..d59b46cf379
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
+
+#include <X11/Xutil.h>
+
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/aura/window.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+
+namespace views {
+
+X11TopmostWindowFinder::X11TopmostWindowFinder() : toplevel_(None) {
+}
+
+X11TopmostWindowFinder::~X11TopmostWindowFinder() {
+}
+
+aura::Window* X11TopmostWindowFinder::FindLocalProcessWindowAt(
+ const gfx::Point& screen_loc,
+ const std::set<aura::Window*>& ignore) {
+ screen_loc_ = screen_loc;
+ ignore_ = ignore;
+
+ std::vector<aura::Window*> local_process_windows =
+ DesktopWindowTreeHostX11::GetAllOpenWindows();
+ bool found_local_process_window = false;
+ for (size_t i = 0; i < local_process_windows.size(); ++i) {
+ if (ShouldStopIteratingAtLocalProcessWindow(local_process_windows[i])) {
+ found_local_process_window = true;
+ break;
+ }
+ }
+ if (!found_local_process_window)
+ return NULL;
+
+ ui::EnumerateTopLevelWindows(this);
+ return DesktopWindowTreeHostX11::GetContentWindowForXID(toplevel_);
+}
+
+XID X11TopmostWindowFinder::FindWindowAt(const gfx::Point& screen_loc) {
+ screen_loc_ = screen_loc;
+ ui::EnumerateTopLevelWindows(this);
+ return toplevel_;
+}
+
+bool X11TopmostWindowFinder::ShouldStopIterating(XID xid) {
+ if (!ui::IsWindowVisible(xid))
+ return false;
+
+ aura::Window* window =
+ views::DesktopWindowTreeHostX11::GetContentWindowForXID(xid);
+ if (window) {
+ if (ShouldStopIteratingAtLocalProcessWindow(window)) {
+ toplevel_ = xid;
+ return true;
+ }
+ return false;
+ }
+
+ if (ui::WindowContainsPoint(xid, screen_loc_)) {
+ toplevel_ = xid;
+ return true;
+ }
+ return false;
+}
+
+bool X11TopmostWindowFinder::ShouldStopIteratingAtLocalProcessWindow(
+ aura::Window* window) {
+ if (ignore_.find(window) != ignore_.end())
+ return false;
+
+ // Currently |window|->IsVisible() always returns true.
+ // TODO(pkotwicz): Fix this. crbug.com/353038
+ if (!window->IsVisible())
+ return false;
+
+ DesktopWindowTreeHostX11* host =
+ DesktopWindowTreeHostX11::GetHostForXID(
+ window->GetHost()->GetAcceleratedWidget());
+ if (!host->GetX11RootWindowOuterBounds().Contains(screen_loc_))
+ return false;
+
+ ::Region shape = host->GetWindowShape();
+ if (!shape)
+ return true;
+
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(window->GetRootWindow());
+ gfx::Point window_loc(screen_loc_);
+ screen_position_client->ConvertPointFromScreen(window, &window_loc);
+ return XPointInRegion(shape, window_loc.x(), window_loc.y()) == True;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.h b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.h
new file mode 100644
index 00000000000..cf8498abe50
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder.h
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_X11_TOPMOST_WINDOW_FINDER_H_
+#define UI_VIEWS_WIDGET_DESKTOP_AURA_X11_TOPMOST_WINDOW_FINDER_H_
+
+#include <set>
+
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/point.h"
+#include "ui/views/views_export.h"
+
+namespace aura {
+class Window;
+}
+
+namespace views {
+
+// Utility class for finding the topmost window at a given screen position.
+class VIEWS_EXPORT X11TopmostWindowFinder
+ : public ui::EnumerateWindowsDelegate {
+ public:
+ X11TopmostWindowFinder();
+ virtual ~X11TopmostWindowFinder();
+
+ // Returns the topmost window at |screen_loc|, ignoring the windows in
+ // |ignore|. Returns NULL if the topmost window at |screen_loc| does not
+ // belong to Chrome.
+ aura::Window* FindLocalProcessWindowAt(const gfx::Point& screen_loc,
+ const std::set<aura::Window*>& ignore);
+
+ // Returns the topmost window at |screen_loc|.
+ XID FindWindowAt(const gfx::Point& screen_loc);
+
+ private:
+ // ui::EnumerateWindowsDelegate:
+ virtual bool ShouldStopIterating(XID xid) OVERRIDE;
+
+ // Returns true if |window| does not not belong to |ignore|, is visible and
+ // contains |screen_loc_|.
+ bool ShouldStopIteratingAtLocalProcessWindow(aura::Window* window);
+
+ gfx::Point screen_loc_;
+ std::set<aura::Window*> ignore_;
+ XID toplevel_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinder);
+};
+
+} // namespace
+
+#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_X11_TOPMOST_WINDOW_FINDER_H_
diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_unittest.cc b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_unittest.cc
new file mode 100644
index 00000000000..ea9544528f8
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_unittest.cc
@@ -0,0 +1,389 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
+
+#include <algorithm>
+#include <vector>
+#include <X11/extensions/shape.h>
+#include <X11/Xlib.h>
+#include <X11/Xregion.h>
+
+// Get rid of X11 macros which conflict with gtest.
+#undef Bool
+#undef None
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/path.h"
+#include "ui/gfx/path_x11.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/test/x11_property_change_waiter.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+namespace {
+
+// Waits till |window| is minimized.
+class MinimizeWaiter : public X11PropertyChangeWaiter {
+ public:
+ explicit MinimizeWaiter(XID window)
+ : X11PropertyChangeWaiter(window, "_NET_WM_STATE") {
+ const char* kAtomsToCache[] = { "_NET_WM_STATE_HIDDEN", NULL };
+ atom_cache_.reset(new ui::X11AtomCache(gfx::GetXDisplay(), kAtomsToCache));
+ }
+
+ virtual ~MinimizeWaiter() {
+ }
+
+ private:
+ // X11PropertyChangeWaiter:
+ virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE {
+ std::vector<Atom> wm_states;
+ if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) {
+ std::vector<Atom>::iterator it = std::find(
+ wm_states.begin(),
+ wm_states.end(),
+ atom_cache_->GetAtom("_NET_WM_STATE_HIDDEN"));
+ return it == wm_states.end();
+ }
+ return true;
+ }
+
+ scoped_ptr<ui::X11AtomCache> atom_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinimizeWaiter);
+};
+
+// Waits till |_NET_CLIENT_LIST_STACKING| is updated to include
+// |expected_windows|.
+class StackingClientListWaiter : public X11PropertyChangeWaiter {
+ public:
+ StackingClientListWaiter(XID* expected_windows, size_t count)
+ : X11PropertyChangeWaiter(ui::GetX11RootWindow(),
+ "_NET_CLIENT_LIST_STACKING"),
+ expected_windows_(expected_windows, expected_windows + count) {
+ }
+
+ virtual ~StackingClientListWaiter() {
+ }
+
+ // X11PropertyChangeWaiter:
+ virtual void Wait() OVERRIDE {
+ // StackingClientListWaiter may be created after
+ // _NET_CLIENT_LIST_STACKING already contains |expected_windows|.
+ if (!ShouldKeepOnWaiting(NULL))
+ return;
+
+ X11PropertyChangeWaiter::Wait();
+ }
+
+ private:
+ // X11PropertyChangeWaiter:
+ virtual bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) OVERRIDE {
+ std::vector<XID> stack;
+ ui::GetXWindowStack(ui::GetX11RootWindow(), &stack);
+ for (size_t i = 0; i < expected_windows_.size(); ++i) {
+ std::vector<XID>::iterator it = std::find(
+ stack.begin(), stack.end(), expected_windows_[i]);
+ if (it == stack.end())
+ return true;
+ }
+ return false;
+ }
+
+ std::vector<XID> expected_windows_;
+
+ DISALLOW_COPY_AND_ASSIGN(StackingClientListWaiter);
+};
+
+} // namespace
+
+class X11TopmostWindowFinderTest : public ViewsTestBase {
+ public:
+ X11TopmostWindowFinderTest() {
+ }
+
+ virtual ~X11TopmostWindowFinderTest() {
+ }
+
+ // Creates and shows a Widget with |bounds|. The caller takes ownership of
+ // the returned widget.
+ scoped_ptr<Widget> CreateAndShowWidget(const gfx::Rect& bounds) {
+ scoped_ptr<Widget> toplevel(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.native_widget = new DesktopNativeWidgetAura(toplevel.get());
+ params.bounds = bounds;
+ params.remove_standard_frame = true;
+ toplevel->Init(params);
+ toplevel->Show();
+ return toplevel.Pass();
+ }
+
+ // Creates and shows an X window with |bounds|.
+ XID CreateAndShowXWindow(const gfx::Rect& bounds) {
+ XID root = DefaultRootWindow(xdisplay());
+ XID xid = XCreateSimpleWindow(xdisplay(),
+ root,
+ 0, 0, 1, 1,
+ 0, // border_width
+ 0, // border
+ 0); // background
+
+ ui::SetUseOSWindowFrame(xid, false);
+ ShowAndSetXWindowBounds(xid, bounds);
+ return xid;
+ }
+
+ // Shows |xid| and sets its bounds.
+ void ShowAndSetXWindowBounds(XID xid, const gfx::Rect& bounds) {
+ XMapWindow(xdisplay(), xid);
+
+ XWindowChanges changes = {0};
+ changes.x = bounds.x();
+ changes.y = bounds.y();
+ changes.width = bounds.width();
+ changes.height = bounds.height();
+ XConfigureWindow(xdisplay(),
+ xid,
+ CWX | CWY | CWWidth | CWHeight,
+ &changes);
+ }
+
+ Display* xdisplay() {
+ return gfx::GetXDisplay();
+ }
+
+ // Returns the topmost X window at the passed in screen position.
+ XID FindTopmostXWindowAt(int screen_x, int screen_y) {
+ X11TopmostWindowFinder finder;
+ return finder.FindWindowAt(gfx::Point(screen_x, screen_y));
+ }
+
+ // Returns the topmost aura::Window at the passed in screen position. Returns
+ // NULL if the topmost window does not have an associated aura::Window.
+ aura::Window* FindTopmostLocalProcessWindowAt(int screen_x, int screen_y) {
+ X11TopmostWindowFinder finder;
+ return finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y),
+ std::set<aura::Window*>());
+ }
+
+ // Returns the topmost aura::Window at the passed in screen position ignoring
+ // |ignore_window|. Returns NULL if the topmost window does not have an
+ // associated aura::Window.
+ aura::Window* FindTopmostLocalProcessWindowWithIgnore(
+ int screen_x,
+ int screen_y,
+ aura::Window* ignore_window) {
+ std::set<aura::Window*> ignore;
+ ignore.insert(ignore_window);
+ X11TopmostWindowFinder finder;
+ return finder.FindLocalProcessWindowAt(gfx::Point(screen_x, screen_y),
+ ignore);
+ }
+
+ // ViewsTestBase:
+ virtual void SetUp() OVERRIDE {
+ ViewsTestBase::SetUp();
+
+ // Make X11 synchronous for our display connection. This does not force the
+ // window manager to behave synchronously.
+ XSynchronize(xdisplay(), True);
+
+ // Ensure that the X11DesktopHandler exists. The X11DesktopHandler is
+ // necessary to properly track menu windows.
+ X11DesktopHandler::get();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ XSynchronize(xdisplay(), False);
+ ViewsTestBase::TearDown();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(X11TopmostWindowFinderTest);
+};
+
+TEST_F(X11TopmostWindowFinderTest, Basic) {
+ // Avoid positioning test windows at 0x0 because window managers often have a
+ // panel/launcher along one of the screen edges and do not allow windows to
+ // position themselves to overlap the panel/launcher.
+ scoped_ptr<Widget> widget1(
+ CreateAndShowWidget(gfx::Rect(100, 100, 200, 100)));
+ aura::Window* window1 = widget1->GetNativeWindow();
+ XID xid1 = window1->GetHost()->GetAcceleratedWidget();
+
+ XID xid2 = CreateAndShowXWindow(gfx::Rect(200, 100, 100, 200));
+
+ scoped_ptr<Widget> widget3(
+ CreateAndShowWidget(gfx::Rect(100, 190, 200, 110)));
+ aura::Window* window3 = widget3->GetNativeWindow();
+ XID xid3 = window3->GetHost()->GetAcceleratedWidget();
+
+ XID xids[] = { xid1, xid2, xid3 };
+ StackingClientListWaiter waiter(xids, arraysize(xids));
+ waiter.Wait();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150));
+ EXPECT_EQ(window1, FindTopmostLocalProcessWindowAt(150, 150));
+
+ EXPECT_EQ(xid2, FindTopmostXWindowAt(250, 150));
+ EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(250, 150));
+
+ EXPECT_EQ(xid3, FindTopmostXWindowAt(250, 250));
+ EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(250, 250));
+
+ EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 250));
+ EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 250));
+
+ EXPECT_EQ(xid3, FindTopmostXWindowAt(150, 195));
+ EXPECT_EQ(window3, FindTopmostLocalProcessWindowAt(150, 195));
+
+ EXPECT_NE(xid1, FindTopmostXWindowAt(1000, 1000));
+ EXPECT_NE(xid2, FindTopmostXWindowAt(1000, 1000));
+ EXPECT_NE(xid3, FindTopmostXWindowAt(1000, 1000));
+ EXPECT_EQ(NULL, FindTopmostLocalProcessWindowAt(1000, 1000));
+
+ EXPECT_EQ(window1,
+ FindTopmostLocalProcessWindowWithIgnore(150, 150, window3));
+ EXPECT_EQ(NULL,
+ FindTopmostLocalProcessWindowWithIgnore(250, 250, window3));
+ EXPECT_EQ(NULL,
+ FindTopmostLocalProcessWindowWithIgnore(150, 250, window3));
+ EXPECT_EQ(window1,
+ FindTopmostLocalProcessWindowWithIgnore(150, 195, window3));
+
+ XDestroyWindow(xdisplay(), xid2);
+}
+
+// Test that the minimized state is properly handled.
+TEST_F(X11TopmostWindowFinderTest, Minimized) {
+ scoped_ptr<Widget> widget1(
+ CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
+ aura::Window* window1 = widget1->GetNativeWindow();
+ XID xid1 = window1->GetHost()->GetAcceleratedWidget();
+ XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
+
+ XID xids[] = { xid1, xid2 };
+ StackingClientListWaiter stack_waiter(xids, arraysize(xids));
+ stack_waiter.Wait();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ EXPECT_EQ(xid1, FindTopmostXWindowAt(150, 150));
+ {
+ MinimizeWaiter minimize_waiter(xid1);
+ XIconifyWindow(xdisplay(), xid1, 0);
+ minimize_waiter.Wait();
+ }
+ EXPECT_NE(xid1, FindTopmostXWindowAt(150, 150));
+ EXPECT_NE(xid2, FindTopmostXWindowAt(150, 150));
+
+ // Repeat test for an X window which does not belong to a views::Widget
+ // because the code path is different.
+ EXPECT_EQ(xid2, FindTopmostXWindowAt(350, 150));
+ {
+ MinimizeWaiter minimize_waiter(xid2);
+ XIconifyWindow(xdisplay(), xid2, 0);
+ minimize_waiter.Wait();
+ }
+ EXPECT_NE(xid1, FindTopmostXWindowAt(350, 150));
+ EXPECT_NE(xid2, FindTopmostXWindowAt(350, 150));
+
+ XDestroyWindow(xdisplay(), xid2);
+}
+
+// Test that non-rectangular windows are properly handled.
+TEST_F(X11TopmostWindowFinderTest, NonRectangular) {
+ if (!ui::IsShapeExtensionAvailable())
+ return;
+
+ scoped_ptr<Widget> widget1(
+ CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
+ XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+ SkRegion* skregion1 = new SkRegion;
+ skregion1->op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
+ skregion1->op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
+ // Widget takes ownership of |skregion1|.
+ widget1->SetShape(skregion1);
+
+ SkRegion skregion2;
+ skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
+ skregion2.op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
+ XID xid2 = CreateAndShowXWindow(gfx::Rect(300, 100, 100, 100));
+ REGION* region2 = gfx::CreateRegionFromSkRegion(skregion2);
+ XShapeCombineRegion(xdisplay(), xid2, ShapeBounding, 0, 0, region2,
+ false);
+ XDestroyRegion(region2);
+
+ XID xids[] = { xid1, xid2 };
+ StackingClientListWaiter stack_waiter(xids, arraysize(xids));
+ stack_waiter.Wait();
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ EXPECT_EQ(xid1, FindTopmostXWindowAt(105, 120));
+ EXPECT_NE(xid1, FindTopmostXWindowAt(105, 105));
+ EXPECT_NE(xid2, FindTopmostXWindowAt(105, 105));
+
+ // Repeat test for an X window which does not belong to a views::Widget
+ // because the code path is different.
+ EXPECT_EQ(xid2, FindTopmostXWindowAt(305, 120));
+ EXPECT_NE(xid1, FindTopmostXWindowAt(305, 105));
+ EXPECT_NE(xid2, FindTopmostXWindowAt(305, 105));
+
+ XDestroyWindow(xdisplay(), xid2);
+}
+
+// Test that the TopmostWindowFinder finds windows which belong to menus
+// (which may or may not belong to Chrome).
+TEST_F(X11TopmostWindowFinderTest, Menu) {
+ XID xid = CreateAndShowXWindow(gfx::Rect(100, 100, 100, 100));
+
+ XID root = DefaultRootWindow(xdisplay());
+ XSetWindowAttributes swa;
+ swa.override_redirect = True;
+ XID menu_xid = XCreateWindow(xdisplay(),
+ root,
+ 0, 0, 1, 1,
+ 0, // border width
+ CopyFromParent, // depth
+ InputOutput,
+ CopyFromParent, // visual
+ CWOverrideRedirect,
+ &swa);
+ {
+ const char* kAtomsToCache[] = { "_NET_WM_WINDOW_TYPE_MENU", NULL };
+ ui::X11AtomCache atom_cache(gfx::GetXDisplay(), kAtomsToCache);
+ ui::SetAtomProperty(menu_xid,
+ "_NET_WM_WINDOW_TYPE",
+ "ATOM",
+ atom_cache.GetAtom("_NET_WM_WINDOW_TYPE_MENU"));
+ }
+ ui::SetUseOSWindowFrame(menu_xid, false);
+ ShowAndSetXWindowBounds(menu_xid, gfx::Rect(140, 110, 100, 100));
+ ui::X11EventSource::GetInstance()->DispatchXEvents();
+
+ // |menu_xid| is never added to _NET_CLIENT_LIST_STACKING.
+ XID xids[] = { xid };
+ StackingClientListWaiter stack_waiter(xids, arraysize(xids));
+ stack_waiter.Wait();
+
+ EXPECT_EQ(xid, FindTopmostXWindowAt(110, 110));
+ EXPECT_EQ(menu_xid, FindTopmostXWindowAt(150, 120));
+ EXPECT_EQ(menu_xid, FindTopmostXWindowAt(210, 120));
+
+ XDestroyWindow(xdisplay(), xid);
+ XDestroyWindow(xdisplay(), menu_xid);
+}
+
+} // namespace views
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 20c061bd670..6c0b3c6b9e7 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
@@ -8,16 +8,20 @@
// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
#undef RootWindow
-#include "base/debug/stack_trace.h"
+#include "base/bind.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_x11.h"
#include "base/run_loop.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/x/x11_util.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/scoped_event_dispatcher.h"
+#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/image_view.h"
@@ -27,9 +31,14 @@ namespace views {
namespace {
+// The minimum alpha before we declare a pixel transparent when searching in
+// our source image.
+const uint32 kMinAlpha = 32;
+const unsigned char kDragWidgetOpacity = 0xc0;
+
class ScopedCapturer {
public:
- explicit ScopedCapturer(aura::RootWindowHost* host)
+ explicit ScopedCapturer(aura::WindowTreeHost* host)
: host_(host) {
host_->SetCapture();
}
@@ -39,7 +48,7 @@ class ScopedCapturer {
}
private:
- aura::RootWindowHost* host_;
+ aura::WindowTreeHost* host_;
DISALLOW_COPY_AND_ASSIGN(ScopedCapturer);
};
@@ -50,15 +59,42 @@ X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(
X11WholeScreenMoveLoopDelegate* delegate)
: delegate_(delegate),
in_move_loop_(false),
- grab_input_window_(None) {
+ should_reset_mouse_flags_(false),
+ grab_input_window_(None),
+ canceled_(false),
+ has_grab_(false),
+ weak_factory_(this) {
+ last_xmotion_.type = LASTEvent;
}
X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
+void X11WholeScreenMoveLoop::DispatchMouseMovement() {
+ if (!weak_factory_.HasWeakPtrs())
+ return;
+ weak_factory_.InvalidateWeakPtrs();
+ DCHECK_EQ(MotionNotify, last_xmotion_.type);
+ delegate_->OnMouseMovement(&last_xmotion_);
+ last_xmotion_.type = LASTEvent;
+}
+
////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostLinux, MessageLoop::Dispatcher implementation:
+// DesktopWindowTreeHostLinux, ui::PlatformEventDispatcher implementation:
+
+bool X11WholeScreenMoveLoop::CanDispatchEvent(const ui::PlatformEvent& event) {
+ return in_move_loop_;
+}
-bool X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) {
+uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) {
+ // This method processes all events for the grab_input_window_ as well as
+ // mouse events for all windows while the move loop is active - even before
+ // the grab is granted by X. This allows mouse notification events that were
+ // sent after the capture was requested but before the capture was granted
+ // to be dispatched. It is especially important to process the mouse release
+ // event that should have stopped the drag even if that mouse release happened
+ // before the grab was granted.
+ if (!in_move_loop_)
+ return ui::POST_DISPATCH_PERFORM_DEFAULT;
XEvent* xev = event;
// Note: the escape key is handled in the tab drag controller, which has
@@ -70,70 +106,152 @@ bool X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) {
gfx::Point location = gfx::ToFlooredPoint(
screen->GetCursorScreenPoint() - drag_offset_);
drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size()));
+ drag_widget_->StackAtTop();
}
- delegate_->OnMouseMovement(&xev->xmotion);
- break;
+ last_xmotion_ = xev->xmotion;
+ if (!weak_factory_.HasWeakPtrs()) {
+ // Post a task to dispatch mouse movement event when control returns to
+ // the message loop. This allows smoother dragging since the events are
+ // dispatched without waiting for the drag widget updates.
+ base::MessageLoopForUI::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&X11WholeScreenMoveLoop::DispatchMouseMovement,
+ weak_factory_.GetWeakPtr()));
+ }
+ return ui::POST_DISPATCH_NONE;
}
case ButtonRelease: {
if (xev->xbutton.button == Button1) {
// Assume that drags are being done with the left mouse button. Only
// break the drag if the left mouse button was released.
+ DispatchMouseMovement();
delegate_->OnMouseReleased();
}
+ return ui::POST_DISPATCH_NONE;
+ }
+ case KeyPress: {
+ if (ui::KeyboardCodeFromXKeyEvent(xev) == ui::VKEY_ESCAPE) {
+ canceled_ = true;
+ EndMoveLoop();
+ return ui::POST_DISPATCH_NONE;
+ }
break;
}
+ case FocusOut: {
+ if (xev->xfocus.mode != NotifyGrab)
+ has_grab_ = false;
+ break;
+ }
+ case GenericEvent: {
+ ui::EventType type = ui::EventTypeFromNative(xev);
+ switch (type) {
+ case ui::ET_MOUSE_MOVED:
+ case ui::ET_MOUSE_DRAGGED:
+ case ui::ET_MOUSE_RELEASED: {
+ XEvent xevent = {0};
+ if (type == ui::ET_MOUSE_RELEASED) {
+ xevent.type = ButtonRelease;
+ xevent.xbutton.button = ui::EventButtonFromNative(xev);
+ } else {
+ xevent.type = MotionNotify;
+ }
+ xevent.xany.display = xev->xgeneric.display;
+ xevent.xany.window = grab_input_window_;
+ // The fields used below are in the same place for all of events
+ // above. Using xmotion from XEvent's unions to avoid repeating
+ // the code.
+ xevent.xmotion.root = DefaultRootWindow(xev->xgeneric.display);
+ xevent.xmotion.time = ui::EventTimeFromNative(xev).InMilliseconds();
+ gfx::Point point(ui::EventSystemLocationFromNative(xev));
+ xevent.xmotion.x_root = point.x();
+ xevent.xmotion.y_root = point.y();
+ DispatchEvent(&xevent);
+ return ui::POST_DISPATCH_NONE;
+ }
+ default:
+ break;
+ }
+ }
}
- return true;
+ return (event->xany.window == grab_input_window_) ?
+ ui::POST_DISPATCH_NONE : ui::POST_DISPATCH_PERFORM_DEFAULT;
}
-////////////////////////////////////////////////////////////////////////////////
-// DesktopRootWindowHostLinux, aura::client::WindowMoveClient implementation:
-
bool X11WholeScreenMoveLoop::RunMoveLoop(aura::Window* source,
gfx::NativeCursor cursor) {
- // Start a capture on the host, so that it continues to receive events during
- // the drag.
- ScopedCapturer capturer(source->GetDispatcher()->host());
-
DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
- in_move_loop_ = true;
- XDisplay* display = gfx::GetXDisplay();
+ // Start a capture on the host, so that it continues to receive events during
+ // the drag. This may be second time we are capturing the mouse events - the
+ // first being when a mouse is first pressed. That first capture needs to be
+ // released before the call to GrabPointerAndKeyboard below, otherwise it may
+ // get released while we still need the pointer grab, which is why we restrict
+ // the scope here.
+ {
+ ScopedCapturer capturer(source->GetHost());
+
+ grab_input_window_ = CreateDragInputWindow(gfx::GetXDisplay());
+ // Releasing ScopedCapturer ensures that any other instance of
+ // X11ScopedCapture will not prematurely release grab that will be acquired
+ // below.
+ }
+ // TODO(varkha): Consider integrating GrabPointerAndKeyboard with
+ // ScopedCapturer to avoid possibility of logically keeping multiple grabs.
+ if (!GrabPointerAndKeyboard(cursor)) {
+ XDestroyWindow(gfx::GetXDisplay(), grab_input_window_);
+ return false;
+ }
- grab_input_window_ = CreateDragInputWindow(display);
- if (!drag_image_.isNull())
+ scoped_ptr<ui::ScopedEventDispatcher> old_dispatcher =
+ nested_dispatcher_.Pass();
+ nested_dispatcher_ =
+ ui::PlatformEventSource::GetInstance()->OverrideDispatcher(this);
+ if (!drag_image_.isNull() && CheckIfIconValid())
CreateDragImageWindow();
- base::MessagePumpX11::Current()->AddDispatcherForWindow(
- this, grab_input_window_);
-
- if (!GrabPointerWithCursor(cursor))
- return false;
// We are handling a mouse drag outside of the aura::RootWindow system. We
// must manually make aura think that the mouse button is pressed so that we
// don't draw extraneous tooltips.
- aura::Env::GetInstance()->set_mouse_button_flags(ui::EF_LEFT_MOUSE_BUTTON);
+ aura::Env* env = aura::Env::GetInstance();
+ if (!env->IsMouseButtonDown()) {
+ env->set_mouse_button_flags(ui::EF_LEFT_MOUSE_BUTTON);
+ should_reset_mouse_flags_ = true;
+ }
+ in_move_loop_ = true;
+ canceled_ = false;
base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
- base::RunLoop run_loop(aura::Env::GetInstance()->GetDispatcher());
+ base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
- return true;
+ nested_dispatcher_ = old_dispatcher.Pass();
+ return !canceled_;
}
void X11WholeScreenMoveLoop::UpdateCursor(gfx::NativeCursor cursor) {
- DCHECK(in_move_loop_);
- GrabPointerWithCursor(cursor);
+ if (in_move_loop_) {
+ // If we're still in the move loop, regrab the pointer with the updated
+ // cursor. Note: we can be called from handling an XdndStatus message after
+ // EndMoveLoop() was called, but before we return from the nested RunLoop.
+ GrabPointerAndKeyboard(cursor);
+ }
}
void X11WholeScreenMoveLoop::EndMoveLoop() {
if (!in_move_loop_)
return;
+ // Prevent DispatchMouseMovement from dispatching any posted motion event.
+ weak_factory_.InvalidateWeakPtrs();
+ last_xmotion_.type = LASTEvent;
+
// We undo our emulated mouse click from RunMoveLoop();
- aura::Env::GetInstance()->set_mouse_button_flags(0);
+ if (should_reset_mouse_flags_) {
+ aura::Env::GetInstance()->set_mouse_button_flags(0);
+ should_reset_mouse_flags_ = false;
+ }
// TODO(erg): Is this ungrab the cause of having to click to give input focus
// on drawn out windows? Not ungrabbing here screws the X server until I kill
@@ -141,13 +259,18 @@ void X11WholeScreenMoveLoop::EndMoveLoop() {
// Ungrab before we let go of the window.
XDisplay* display = gfx::GetXDisplay();
- XUngrabPointer(display, CurrentTime);
+ // Only ungrab pointer if capture was not switched to another window.
+ if (has_grab_) {
+ XUngrabPointer(display, CurrentTime);
+ XUngrabKeyboard(display, CurrentTime);
+ }
- base::MessagePumpX11::Current()->RemoveDispatcherForWindow(
- grab_input_window_);
+ // Restore the previous dispatcher.
+ nested_dispatcher_.reset();
drag_widget_.reset();
delegate_->OnMoveLoopEnded();
XDestroyWindow(display, grab_input_window_);
+ grab_input_window_ = None;
in_move_loop_ = false;
quit_closure_.Run();
@@ -162,9 +285,10 @@ void X11WholeScreenMoveLoop::SetDragImage(const gfx::ImageSkia& image,
drag_offset_.set_y(0.f);
}
-bool X11WholeScreenMoveLoop::GrabPointerWithCursor(gfx::NativeCursor cursor) {
+bool X11WholeScreenMoveLoop::GrabPointerAndKeyboard(gfx::NativeCursor cursor) {
XDisplay* display = gfx::GetXDisplay();
XGrabServer(display);
+
XUngrabPointer(display, CurrentTime);
int ret = XGrabPointer(
display,
@@ -176,14 +300,28 @@ bool X11WholeScreenMoveLoop::GrabPointerWithCursor(gfx::NativeCursor cursor) {
None,
cursor.platform(),
CurrentTime);
- XUngrabServer(display);
if (ret != GrabSuccess) {
- DLOG(ERROR) << "Grabbing new tab for dragging failed: "
+ DLOG(ERROR) << "Grabbing pointer for dragging failed: "
<< ui::GetX11ErrorString(display, ret);
- return false;
+ } else {
+ has_grab_ = true;
+ XUngrabKeyboard(display, CurrentTime);
+ ret = XGrabKeyboard(
+ display,
+ grab_input_window_,
+ False,
+ GrabModeAsync,
+ GrabModeAsync,
+ CurrentTime);
+ if (ret != GrabSuccess) {
+ DLOG(ERROR) << "Grabbing keyboard for dragging failed: "
+ << ui::GetX11ErrorString(display, ret);
+ }
}
- return true;
+ XUngrabServer(display);
+ XFlush(display);
+ return ret == GrabSuccess;
}
Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) {
@@ -196,7 +334,7 @@ Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) {
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
- StructureNotifyMask;
+ KeyPressMask | KeyReleaseMask | StructureNotifyMask;
swa.override_redirect = True;
Window window = XCreateWindow(display,
DefaultRootWindow(display),
@@ -204,7 +342,7 @@ Window X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) {
0, CopyFromParent, InputOnly, CopyFromParent,
attribute_mask, &swa);
XMapRaised(display, window);
- base::MessagePumpX11::Current()->BlockUntilWindowMapped(window);
+ ui::X11EventSource::GetInstance()->BlockUntilWindowMapped(window);
return window;
}
@@ -221,17 +359,35 @@ void X11WholeScreenMoveLoop::CreateDragImageWindow() {
widget->set_focus_on_creation(false);
widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
widget->Init(params);
+ widget->SetOpacity(kDragWidgetOpacity);
widget->GetNativeWindow()->SetName("DragWindow");
ImageView* image = new ImageView();
image->SetImage(drag_image_);
image->SetBounds(0, 0, drag_image_.width(), drag_image_.height());
widget->SetContentsView(image);
-
widget->Show();
widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
drag_widget_.reset(widget);
}
+bool X11WholeScreenMoveLoop::CheckIfIconValid() {
+ // Because we need a GL context per window, we do a quick check so that we
+ // don't make another context if the window would just be displaying a mostly
+ // transparent image.
+ const SkBitmap* in_bitmap = drag_image_.bitmap();
+ SkAutoLockPixels in_lock(*in_bitmap);
+ for (int y = 0; y < in_bitmap->height(); ++y) {
+ uint32* in_row = in_bitmap->getAddr32(0, y);
+
+ for (int x = 0; x < in_bitmap->width(); ++x) {
+ if (SkColorGetA(in_row[x]) > kMinAlpha)
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace views
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 c0c25466647..cf3665ecac6 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
@@ -5,8 +5,10 @@
#ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_X11_WHOLE_SCREEN_MOVE_LOOP_H_
#define UI_VIEWS_WIDGET_DESKTOP_AURA_X11_WHOLE_SCREEN_MOVE_LOOP_H_
+#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/message_loop/message_loop.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/vector2d_f.h"
@@ -18,23 +20,29 @@ namespace aura {
class Window;
}
+namespace ui {
+class ScopedEventDispatcher;
+}
+
namespace views {
class Widget;
// Runs a nested message loop and grabs the mouse. This is used to implement
// dragging.
-class X11WholeScreenMoveLoop : public base::MessageLoop::Dispatcher {
+class X11WholeScreenMoveLoop : public ui::PlatformEventDispatcher {
public:
explicit X11WholeScreenMoveLoop(X11WholeScreenMoveLoopDelegate* delegate);
virtual ~X11WholeScreenMoveLoop();
- // Overridden from base::MessageLoop::Dispatcher:
- virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
+ // ui:::PlatformEventDispatcher:
+ virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
+ virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE;
// Runs the nested message loop. While the mouse is grabbed, use |cursor| as
- // the mouse cursor. Returns true if there we were able to grab the pointer
- // and run the move loop.
+ // the mouse cursor. Returns true if the move-loop is completed successfully.
+ // If the pointer-grab fails, or the move-loop is canceled by the user (e.g.
+ // by pressing escape), then returns false.
bool RunMoveLoop(aura::Window* window, gfx::NativeCursor cursor);
// Updates the cursor while the move loop is running.
@@ -47,9 +55,9 @@ class X11WholeScreenMoveLoop : public base::MessageLoop::Dispatcher {
void SetDragImage(const gfx::ImageSkia& image, gfx::Vector2dF offset);
private:
- // Grabs the pointer, setting the mouse cursor to |cursor|. Returns true if
- // the grab was successful.
- bool GrabPointerWithCursor(gfx::NativeCursor cursor);
+ // Grabs the pointer and keyboard, setting the mouse cursor to |cursor|.
+ // Returns true if the grab was successful.
+ bool GrabPointerAndKeyboard(gfx::NativeCursor cursor);
// Creates an input-only window to be used during the drag.
Window CreateDragInputWindow(XDisplay* display);
@@ -57,10 +65,20 @@ class X11WholeScreenMoveLoop : public base::MessageLoop::Dispatcher {
// Creates a window to show the drag image during the drag.
void CreateDragImageWindow();
+ // Checks to see if |in_image| is an image that has any visible regions
+ // (defined as having a pixel with alpha > 32). If so, return true.
+ bool CheckIfIconValid();
+
+ // Dispatch mouse movement event to |delegate_| in a posted task.
+ void DispatchMouseMovement();
+
X11WholeScreenMoveLoopDelegate* delegate_;
// Are we running a nested message loop from RunMoveLoop()?
bool in_move_loop_;
+ scoped_ptr<ui::ScopedEventDispatcher> nested_dispatcher_;
+
+ bool should_reset_mouse_flags_;
// An invisible InputOnly window . We create this window so we can track the
// cursor wherever it goes on screen during a drag, since normal windows
@@ -69,11 +87,20 @@ class X11WholeScreenMoveLoop : public base::MessageLoop::Dispatcher {
base::Closure quit_closure_;
+ // Keeps track of whether the move-loop is cancled by the user (e.g. by
+ // pressing escape).
+ bool canceled_;
+
+ // Keeps track of whether we still have a pointer grab at the end of the loop.
+ bool has_grab_;
+
// A Widget is created during the drag if there is an image available to be
// used during the drag.
scoped_ptr<Widget> drag_widget_;
gfx::ImageSkia drag_image_;
gfx::Vector2dF drag_offset_;
+ XMotionEvent last_xmotion_;
+ base::WeakPtrFactory<X11WholeScreenMoveLoop> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(X11WholeScreenMoveLoop);
};
diff --git a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc
index 3f415f0050d..ab992c66806 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc
@@ -9,15 +9,20 @@
#include <X11/Xatom.h>
#include <X11/Xlib.h>
-#include "ui/aura/root_window.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
#include "ui/gfx/x/x11_types.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
+#include "ui/views/linux_ui/linux_ui.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/widget/native_widget_aura.h"
+#include "ui/views/widget/widget.h"
namespace {
@@ -33,24 +38,7 @@ const int k_NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT = 6;
const int k_NET_WM_MOVERESIZE_SIZE_LEFT = 7;
const int k_NET_WM_MOVERESIZE_MOVE = 8;
-// This data structure represents additional hints that we send to the window
-// manager and has a direct lineage back to Motif, which defined this de facto
-// standard. This struct doesn't seem 64-bit safe though, but it's what GDK
-// does.
-typedef struct {
- unsigned long flags;
- unsigned long functions;
- unsigned long decorations;
- long input_mode;
- unsigned long status;
-} MotifWmHints;
-
-// The bitflag in |flags| in MotifWmHints that signals that the reader should
-// pay attention to the value in |decorations|.
-const unsigned long kHintsDecorations = (1L << 1);
-
const char* kAtomsToCache[] = {
- "_MOTIF_WM_HINTS",
"_NET_WM_MOVERESIZE",
NULL
};
@@ -60,70 +48,134 @@ const char* kAtomsToCache[] = {
namespace views {
X11WindowEventFilter::X11WindowEventFilter(
- aura::RootWindow* root_window,
- DesktopRootWindowHost* root_window_host)
+ DesktopWindowTreeHost* window_tree_host)
: xdisplay_(gfx::GetXDisplay()),
- xwindow_(root_window->host()->GetAcceleratedWidget()),
+ xwindow_(window_tree_host->AsWindowTreeHost()->GetAcceleratedWidget()),
x_root_window_(DefaultRootWindow(xdisplay_)),
atom_cache_(xdisplay_, kAtomsToCache),
- root_window_host_(root_window_host),
- is_active_(false) {
+ window_tree_host_(window_tree_host),
+ is_active_(false),
+ click_component_(HTNOWHERE) {
}
X11WindowEventFilter::~X11WindowEventFilter() {
}
-void X11WindowEventFilter::SetUseHostWindowBorders(bool use_os_border) {
- MotifWmHints motif_hints;
- memset(&motif_hints, 0, sizeof(motif_hints));
- motif_hints.flags = kHintsDecorations;
- motif_hints.decorations = use_os_border ? 1 : 0;
-
- ::Atom hint_atom = atom_cache_.GetAtom("_MOTIF_WM_HINTS");
- XChangeProperty(gfx::GetXDisplay(),
- xwindow_,
- hint_atom,
- hint_atom,
- 32,
- PropModeReplace,
- reinterpret_cast<unsigned char*>(&motif_hints),
- sizeof(MotifWmHints)/sizeof(long));
-}
-
void X11WindowEventFilter::OnMouseEvent(ui::MouseEvent* event) {
if (event->type() != ui::ET_MOUSE_PRESSED)
return;
- if (!event->IsLeftMouseButton())
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ if (!target->delegate())
return;
- aura::Window* target = static_cast<aura::Window*>(event->target());
+ int previous_click_component = HTNOWHERE;
int component =
target->delegate()->GetNonClientComponent(event->location());
- if (component == HTCLIENT)
- return;
+ if (event->IsLeftMouseButton()) {
+ previous_click_component = click_component_;
+ click_component_ = component;
+ }
+
+ if (component == HTCAPTION) {
+ OnClickedCaption(event, previous_click_component);
+ } else if (component == HTMAXBUTTON) {
+ OnClickedMaximizeButton(event);
+ } else {
+ // Get the |x_root_window_| location out of the native event.
+ if (event->IsLeftMouseButton() && event->native_event()) {
+ const gfx::Point x_root_location =
+ ui::EventSystemLocationFromNative(event->native_event());
+ if (target->GetProperty(aura::client::kCanResizeKey) &&
+ DispatchHostWindowDragMovement(component, x_root_location)) {
+ event->StopPropagation();
+ }
+ }
+ }
+}
+
+void X11WindowEventFilter::OnClickedCaption(ui::MouseEvent* event,
+ int previous_click_component) {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+
+ if (event->IsMiddleMouseButton()) {
+ LinuxUI::NonClientMiddleClickAction action =
+ LinuxUI::MIDDLE_CLICK_ACTION_LOWER;
+ LinuxUI* linux_ui = LinuxUI::instance();
+ if (linux_ui)
+ action = linux_ui->GetNonClientMiddleClickAction();
+
+ switch (action) {
+ case LinuxUI::MIDDLE_CLICK_ACTION_NONE:
+ break;
+ case LinuxUI::MIDDLE_CLICK_ACTION_LOWER:
+ XLowerWindow(xdisplay_, xwindow_);
+ break;
+ case LinuxUI::MIDDLE_CLICK_ACTION_MINIMIZE:
+ window_tree_host_->Minimize();
+ break;
+ case LinuxUI::MIDDLE_CLICK_ACTION_TOGGLE_MAXIMIZE:
+ if (target->GetProperty(aura::client::kCanMaximizeKey))
+ ToggleMaximizedState();
+ break;
+ }
- if (event->flags() & ui::EF_IS_DOUBLE_CLICK && component == HTCAPTION) {
- // Our event is a double click in the caption area. We are responsible for
- // dispatching this as a minimize/maximize on X11 (Windows converts this to
- // min/max events for us).
- if (root_window_host_->IsMaximized())
- root_window_host_->Restore();
- else
- root_window_host_->Maximize();
event->SetHandled();
return;
}
+ if (event->IsLeftMouseButton() && event->flags() & ui::EF_IS_DOUBLE_CLICK) {
+ click_component_ = HTNOWHERE;
+ if (target->GetProperty(aura::client::kCanMaximizeKey) &&
+ previous_click_component == HTCAPTION) {
+ // Our event is a double click in the caption area in a window that can be
+ // maximized. We are responsible for dispatching this as a minimize/
+ // maximize on X11 (Windows converts this to min/max events for us).
+ ToggleMaximizedState();
+ event->SetHandled();
+ return;
+ }
+ }
+
// Get the |x_root_window_| location out of the native event.
- if (event->native_event()) {
+ if (event->IsLeftMouseButton() && event->native_event()) {
const gfx::Point x_root_location =
ui::EventSystemLocationFromNative(event->native_event());
- if (DispatchHostWindowDragMovement(component, x_root_location))
+ if (DispatchHostWindowDragMovement(HTCAPTION, x_root_location))
event->StopPropagation();
}
}
+void X11WindowEventFilter::OnClickedMaximizeButton(ui::MouseEvent* event) {
+ aura::Window* target = static_cast<aura::Window*>(event->target());
+ views::Widget* widget = views::Widget::GetWidgetForNativeView(target);
+ if (!widget)
+ return;
+
+ gfx::Screen* screen = gfx::Screen::GetNativeScreen();
+ gfx::Rect display_work_area =
+ screen->GetDisplayNearestWindow(target).work_area();
+ gfx::Rect bounds = widget->GetWindowBoundsInScreen();
+ if (event->IsMiddleMouseButton()) {
+ bounds.set_y(display_work_area.y());
+ bounds.set_height(display_work_area.height());
+ widget->SetBounds(bounds);
+ event->StopPropagation();
+ } else if (event->IsRightMouseButton()) {
+ bounds.set_x(display_work_area.x());
+ bounds.set_width(display_work_area.width());
+ widget->SetBounds(bounds);
+ event->StopPropagation();
+ }
+}
+
+void X11WindowEventFilter::ToggleMaximizedState() {
+ if (window_tree_host_->IsMaximized())
+ window_tree_host_->Restore();
+ else
+ window_tree_host_->Maximize();
+}
+
bool X11WindowEventFilter::DispatchHostWindowDragMovement(
int hittest,
const gfx::Point& screen_location) {
diff --git a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h
index d172958cc8f..920733f154f 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h
+++ b/chromium/ui/views/widget/desktop_aura/x11_window_event_filter.h
@@ -6,8 +6,6 @@
#define UI_VIEWS_WIDGET_DESKTOP_AURA_X11_WINDOW_EVENT_FILTER_H_
#include <X11/Xlib.h>
-// Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
-#undef RootWindow
#include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
@@ -17,7 +15,6 @@
#include "ui/views/views_export.h"
namespace aura {
-class RootWindow;
class Window;
}
@@ -26,23 +23,28 @@ class Point;
}
namespace views {
-class DesktopRootWindowHost;
+class DesktopWindowTreeHost;
class NativeWidgetAura;
// An EventFilter that sets properties on X11 windows.
class VIEWS_EXPORT X11WindowEventFilter : public ui::EventHandler {
public:
- X11WindowEventFilter(aura::RootWindow* root_window,
- DesktopRootWindowHost* root_window_host);
+ explicit X11WindowEventFilter(DesktopWindowTreeHost* window_tree_host);
virtual ~X11WindowEventFilter();
- // Changes whether borders are shown on this |root_window|.
- void SetUseHostWindowBorders(bool use_os_border);
-
// Overridden from ui::EventHandler:
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
private:
+ // Called when the user clicked the caption area.
+ void OnClickedCaption(ui::MouseEvent* event,
+ int previous_click_component);
+
+ // Called when the user clicked the maximize button.
+ void OnClickedMaximizeButton(ui::MouseEvent* event);
+
+ void ToggleMaximizedState();
+
// Dispatches a _NET_WM_MOVERESIZE message to the window manager to tell it
// to act as if a border or titlebar drag occurred.
bool DispatchHostWindowDragMovement(int hittest,
@@ -57,11 +59,18 @@ class VIEWS_EXPORT X11WindowEventFilter : public ui::EventHandler {
ui::X11AtomCache atom_cache_;
- DesktopRootWindowHost* root_window_host_;
+ DesktopWindowTreeHost* window_tree_host_;
// True if |xwindow_| is the current _NET_ACTIVE_WINDOW.
bool is_active_;
+ // The non-client component for the target of a MouseEvent. Mouse events can
+ // be destructive to the window tree, which can cause the component of a
+ // ui::EF_IS_DOUBLE_CLICK event to no longer be the same as that of the
+ // initial click. Acting on a double click should only occur for matching
+ // components.
+ int click_component_;
+
DISALLOW_COPY_AND_ASSIGN(X11WindowEventFilter);
};
diff --git a/chromium/ui/views/widget/drop_target_win.cc b/chromium/ui/views/widget/drop_target_win.cc
deleted file mode 100644
index 56b0be1aef1..00000000000
--- a/chromium/ui/views/widget/drop_target_win.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/drop_target_win.h"
-
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
-#include "ui/gfx/point.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/widget.h"
-
-using ui::OSExchangeData;
-using ui::OSExchangeDataProviderWin;
-
-namespace views {
-
-DropTargetWin::DropTargetWin(internal::RootView* root_view)
- : ui::DropTargetWin(root_view->GetWidget()->GetNativeView()),
- helper_(root_view) {
-}
-
-DropTargetWin::~DropTargetWin() {
-}
-
-void DropTargetWin::ResetTargetViewIfEquals(View* view) {
- helper_.ResetTargetViewIfEquals(view);
-}
-
-DWORD DropTargetWin::OnDragOver(IDataObject* data_object,
- DWORD key_state,
- POINT cursor_position,
- DWORD effect) {
- gfx::Point root_view_location(cursor_position.x, cursor_position.y);
- View::ConvertPointFromScreen(helper_.root_view(), &root_view_location);
- OSExchangeData data(new OSExchangeDataProviderWin(data_object));
- int drop_operation =
- helper_.OnDragOver(data, root_view_location,
- ui::DragDropTypes::DropEffectToDragOperation(effect));
- return ui::DragDropTypes::DragOperationToDropEffect(drop_operation);
-}
-
-void DropTargetWin::OnDragLeave(IDataObject* data_object) {
- helper_.OnDragExit();
-}
-
-DWORD DropTargetWin::OnDrop(IDataObject* data_object,
- DWORD key_state,
- POINT cursor_position,
- DWORD effect) {
- gfx::Point root_view_location(cursor_position.x, cursor_position.y);
- View::ConvertPointFromScreen(helper_.root_view(), &root_view_location);
-
- OSExchangeData data(new OSExchangeDataProviderWin(data_object));
- int drop_operation = ui::DragDropTypes::DropEffectToDragOperation(effect);
- drop_operation = helper_.OnDragOver(data, root_view_location,
- drop_operation);
- drop_operation = helper_.OnDrop(data, root_view_location, drop_operation);
- return ui::DragDropTypes::DragOperationToDropEffect(drop_operation);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/drop_target_win.h b/chromium/ui/views/widget/drop_target_win.h
deleted file mode 100644
index 742675122df..00000000000
--- a/chromium/ui/views/widget/drop_target_win.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_DROP_TARGET_WIN_H_
-#define UI_VIEWS_WIDGET_DROP_TARGET_WIN_H_
-
-#include "ui/base/dragdrop/drop_target_win.h"
-#include "ui/views/widget/drop_helper.h"
-
-namespace views {
-
-class View;
-namespace internal {
-class RootView;
-}
-
-// DropTargetWin takes care of managing drag and drop for NativeWidgetWin. It
-// converts Windows OLE drop messages into Views drop messages.
-//
-// DropTargetWin uses DropHelper to manage the appropriate view to target
-// drop messages at.
-class DropTargetWin : public ui::DropTargetWin {
- public:
- explicit DropTargetWin(internal::RootView* root_view);
- virtual ~DropTargetWin();
-
- // If a drag and drop is underway and view is the current drop target, the
- // drop target is set to null.
- // This is invoked when a View is removed from the RootView to make sure
- // we don't target a view that was removed during dnd.
- void ResetTargetViewIfEquals(View* view);
-
- protected:
- virtual DWORD OnDragOver(IDataObject* data_object,
- DWORD key_state,
- POINT cursor_position,
- DWORD effect);
-
- virtual void OnDragLeave(IDataObject* data_object);
-
- virtual DWORD OnDrop(IDataObject* data_object,
- DWORD key_state,
- POINT cursor_position,
- DWORD effect);
-
- private:
- views::DropHelper helper_;
-
- DISALLOW_COPY_AND_ASSIGN(DropTargetWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_DROP_TARGET_WIN_H_
diff --git a/chromium/ui/views/widget/monitor_win.cc b/chromium/ui/views/widget/monitor_win.cc
index 1292692d9f3..1220671beb8 100644
--- a/chromium/ui/views/widget/monitor_win.cc
+++ b/chromium/ui/views/widget/monitor_win.cc
@@ -4,10 +4,9 @@
#include "ui/views/widget/monitor_win.h"
-#include <shellapi.h>
+#include <windows.h>
#include "base/logging.h"
-#include "base/win/win_util.h"
#include "ui/gfx/rect.h"
namespace views {
@@ -16,24 +15,12 @@ gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect) {
RECT p_rect = rect.ToRECT();
HMONITOR monitor = MonitorFromRect(&p_rect, MONITOR_DEFAULTTONEAREST);
if (monitor) {
- MONITORINFO mi = {0};
- mi.cbSize = sizeof(mi);
- base::win::GetMonitorInfoWrapper(monitor, &mi);
+ MONITORINFO mi = { sizeof(MONITORINFO) };
+ GetMonitorInfo(monitor, &mi);
return gfx::Rect(mi.rcWork);
}
NOTREACHED();
return gfx::Rect();
}
-HWND GetTopmostAutoHideTaskbarForEdge(UINT edge, HMONITOR monitor) {
- // NOTE: this may be invoked on a background thread.
- APPBARDATA taskbar_data = { sizeof(APPBARDATA), NULL, 0, edge };
- HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
- &taskbar_data));
- return (::IsWindow(taskbar) && (monitor != NULL) &&
- (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
- (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST)) ?
- taskbar : NULL;
-}
-
} // namespace views
diff --git a/chromium/ui/views/widget/monitor_win.h b/chromium/ui/views/widget/monitor_win.h
index 87bdc4e00c2..ef4d3dde613 100644
--- a/chromium/ui/views/widget/monitor_win.h
+++ b/chromium/ui/views/widget/monitor_win.h
@@ -5,8 +5,6 @@
#ifndef UI_VIEWS_WIDGET_MONITOR_WIN_H_
#define UI_VIEWS_WIDGET_MONITOR_WIN_H_
-#include <windows.h>
-
#include "ui/views/views_export.h"
namespace gfx {
@@ -19,14 +17,6 @@ namespace views {
// intersection with the specified rectangle.
VIEWS_EXPORT gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect);
-// Returns the always-on-top auto-hiding taskbar for edge |edge| (one of
-// ABE_LEFT, TOP, RIGHT, or BOTTOM) of monitor |monitor|. NULL is returned
-// if nothing is found.
-//
-// WARNING: this function spawns a nested message loop. Use Appbar instead if
-// possible.
-VIEWS_EXPORT HWND GetTopmostAutoHideTaskbarForEdge(UINT edge, HMONITOR monitor);
-
} // namespace views
#endif // UI_VIEWS_WIDGET_MONITOR_WIN_H_
diff --git a/chromium/ui/views/widget/native_widget.h b/chromium/ui/views/widget/native_widget.h
index 39255ffc9c1..d01265f81f8 100644
--- a/chromium/ui/views/widget/native_widget.h
+++ b/chromium/ui/views/widget/native_widget.h
@@ -7,10 +7,6 @@
#include "ui/views/widget/widget.h"
-namespace ui {
-class EventHandler;
-}
-
namespace views {
namespace internal {
class NativeWidgetPrivate;
@@ -30,9 +26,6 @@ class VIEWS_EXPORT NativeWidget {
public:
virtual ~NativeWidget() {}
- // Retrieves the event handler
- virtual ui::EventHandler* GetEventHandler() = 0;
-
private:
friend class Widget;
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index ffedac5c15a..150a1a42527 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -7,32 +7,28 @@
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/aura/client/activation_client.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_move_client.h"
#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/client/window_types.h"
#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_observer.h"
#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/screen.h"
#include "ui/native_theme/native_theme_aura.h"
-#include "ui/views/corewm/window_util.h"
#include "ui/views/drag_utils.h"
#include "ui/views/ime/input_method_bridge.h"
+#include "ui/views/ime/null_input_method.h"
#include "ui/views/views_delegate.h"
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/native_widget_delegate.h"
#include "ui/views/widget/root_view.h"
@@ -40,20 +36,27 @@
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/window_reorderer.h"
+#include "ui/wm/core/shadow_types.h"
+#include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/window_move_client.h"
+#include "ui/wm/public/window_types.h"
#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
#include "base/win/win_util.h"
#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_win.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#endif
#if defined(USE_X11) && !defined(OS_CHROMEOS)
-#include "ui/views/widget/desktop_aura/desktop_root_window_host_x11.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#endif
#if !defined(OS_CHROMEOS)
-#include "ui/views/widget/desktop_aura/desktop_root_window_host.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#endif
namespace views {
@@ -74,7 +77,6 @@ NativeWidgetAura::NativeWidgetAura(internal::NativeWidgetDelegate* delegate)
window_(new aura::Window(this)),
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
close_widget_factory_(this),
- can_activate_(true),
destroying_(false),
cursor_(gfx::kNullCursor),
saved_window_state_(ui::SHOW_STATE_DEFAULT) {
@@ -83,19 +85,6 @@ NativeWidgetAura::NativeWidgetAura(internal::NativeWidgetDelegate* delegate)
}
// static
-gfx::Font NativeWidgetAura::GetWindowTitleFont() {
-#if defined(OS_WIN)
- NONCLIENTMETRICS ncm;
- base::win::GetNonClientMetrics(&ncm);
- l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
- base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
- return gfx::Font(caption_font);
-#else
- return gfx::Font();
-#endif
-}
-
-// static
void NativeWidgetAura::RegisterNativeWidgetForWindow(
internal::NativeWidgetPrivate* native_widget,
aura::Window* window) {
@@ -120,6 +109,10 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
window_->SetTransparent(
params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW);
window_->Init(params.layer_type);
+ if (params.shadow_type == Widget::InitParams::SHADOW_TYPE_NONE)
+ SetShadowType(window_, wm::SHADOW_TYPE_NONE);
+ else if (params.shadow_type == Widget::InitParams::SHADOW_TYPE_DROP)
+ SetShadowType(window_, wm::SHADOW_TYPE_RECTANGULAR);
if (params.type == Widget::InitParams::TYPE_CONTROL)
window_->Show();
@@ -131,8 +124,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
if (!params.child) {
// Set up the transient child before the window is added. This way the
// LayoutManager knows the window has a transient parent.
- if (parent && parent->type() != aura::client::WINDOW_TYPE_UNKNOWN) {
- parent->AddTransientChild(window_);
+ if (parent && parent->type() != ui::wm::WINDOW_TYPE_UNKNOWN) {
+ wm::AddTransientChild(parent, window_);
if (!context)
context = parent;
parent = NULL;
@@ -150,6 +143,13 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
}
}
+ // Set properties before addeing to the parent so that its layout manager
+ // sees the correct values.
+ window_->SetProperty(aura::client::kCanMaximizeKey,
+ GetWidget()->widget_delegate()->CanMaximize());
+ window_->SetProperty(aura::client::kCanResizeKey,
+ GetWidget()->widget_delegate()->CanResize());
+
if (parent) {
parent->AddChild(window_);
} else {
@@ -165,9 +165,6 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
else
SetBounds(window_bounds);
window_->set_ignore_events(!params.accept_events);
- can_activate_ = params.can_activate &&
- params.type != Widget::InitParams::TYPE_CONTROL &&
- params.type != Widget::InitParams::TYPE_TOOLTIP;
DCHECK(GetWidget()->GetRootView());
if (params.type != Widget::InitParams::TYPE_TOOLTIP)
tooltip_manager_.reset(new views::TooltipManagerAura(GetWidget()));
@@ -180,11 +177,6 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
aura::client::SetActivationDelegate(window_, this);
- window_->SetProperty(aura::client::kCanMaximizeKey,
- GetWidget()->widget_delegate()->CanMaximize());
- window_->SetProperty(aura::client::kCanResizeKey,
- GetWidget()->widget_delegate()->CanResize());
-
window_reorderer_.reset(new WindowReorderer(window_,
GetWidget()->GetRootView()));
}
@@ -198,6 +190,10 @@ bool NativeWidgetAura::ShouldUseNativeFrame() const {
return false;
}
+bool NativeWidgetAura::ShouldWindowContentsBeTransparent() const {
+ return false;
+}
+
void NativeWidgetAura::FrameTypeChanged() {
// This is called when the Theme has changed; forward the event to the root
// widget.
@@ -277,6 +273,10 @@ bool NativeWidgetAura::HasCapture() const {
InputMethod* NativeWidgetAura::CreateInputMethod() {
if (!window_)
return NULL;
+
+ if (switches::IsTextInputFocusManagerEnabled())
+ return new NullInputMethod();
+
aura::Window* root_window = window_->GetRootWindow();
ui::InputMethod* host =
root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
@@ -287,6 +287,11 @@ internal::InputMethodDelegate* NativeWidgetAura::GetInputMethodDelegate() {
return this;
}
+ui::InputMethod* NativeWidgetAura::GetHostInputMethod() {
+ aura::Window* root_window = window_->GetRootWindow();
+ return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
+}
+
void NativeWidgetAura::CenterWindow(const gfx::Size& size) {
if (!window_)
return;
@@ -311,9 +316,9 @@ void NativeWidgetAura::CenterWindow(const gfx::Size& size) {
// If |window_|'s transient parent's bounds are big enough to fit it, then we
// center it with respect to the transient parent.
- if (window_->transient_parent()) {
- gfx::Rect transient_parent_rect = window_->transient_parent()->
- GetBoundsInRootWindow();
+ if (wm::GetTransientParent(window_)) {
+ gfx::Rect transient_parent_rect =
+ wm::GetTransientParent(window_)->GetBoundsInRootWindow();
transient_parent_rect.Intersect(work_area);
if (transient_parent_rect.height() >= size.height() &&
transient_parent_rect.width() >= size.width())
@@ -346,7 +351,7 @@ void NativeWidgetAura::GetWindowPlacement(
ui::SHOW_STATE_DEFAULT;
}
-bool NativeWidgetAura::SetWindowTitle(const string16& title) {
+bool NativeWidgetAura::SetWindowTitle(const base::string16& title) {
if (!window_)
return false;
if (window_->title() == title)
@@ -462,7 +467,7 @@ void NativeWidgetAura::CloseNow() {
}
void NativeWidgetAura::Show() {
- ShowWithWindowState(ui::SHOW_STATE_INACTIVE);
+ ShowWithWindowState(ui::SHOW_STATE_NORMAL);
}
void NativeWidgetAura::Hide() {
@@ -483,17 +488,13 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
if (state == ui::SHOW_STATE_MAXIMIZED || state == ui::SHOW_STATE_FULLSCREEN)
window_->SetProperty(aura::client::kShowStateKey, state);
window_->Show();
- if (can_activate_) {
+ if (delegate_->CanActivate()) {
if (state != ui::SHOW_STATE_INACTIVE)
Activate();
// SetInitialFocus() should be always be called, even for
- // SHOW_STATE_INACTIVE. When a frameless modal dialog is created by
- // a widget of TYPE_WINDOW_FRAMELESS, Widget::Show() will call into
- // this function with the window state SHOW_STATE_INACTIVE,
- // SetInitialFoucs() has to be called so that the dialog can get focus.
- // This also matches NativeWidgetWin which invokes SetInitialFocus
- // regardless of show state.
- SetInitialFocus();
+ // SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
+ // do the right thing.
+ SetInitialFocus(state);
}
}
@@ -523,7 +524,7 @@ void NativeWidgetAura::Deactivate() {
}
bool NativeWidgetAura::IsActive() const {
- return window_ && corewm::IsActiveWindow(window_);
+ return window_ && wm::IsActiveWindow(window_);
}
void NativeWidgetAura::SetAlwaysOnTop(bool on_top) {
@@ -535,6 +536,10 @@ bool NativeWidgetAura::IsAlwaysOnTop() const {
return window_ && window_->GetProperty(aura::client::kAlwaysOnTopKey);
}
+void NativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
+ // Not implemented on chromeos or for child widgets.
+}
+
void NativeWidgetAura::Maximize() {
if (window_)
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
@@ -642,27 +647,32 @@ Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop(
Widget::MoveLoopEscapeBehavior escape_behavior) {
// |escape_behavior| is only needed on windows when running the native message
// loop.
- if (window_ && window_->parent() &&
- aura::client::GetWindowMoveClient(window_->parent())) {
- SetCapture();
- aura::client::WindowMoveSource window_move_source =
- source == Widget::MOVE_LOOP_SOURCE_MOUSE ?
- aura::client::WINDOW_MOVE_SOURCE_MOUSE :
- aura::client::WINDOW_MOVE_SOURCE_TOUCH;
- if (aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop(
- window_, drag_offset, window_move_source) ==
- aura::client::MOVE_SUCCESSFUL) {
- return Widget::MOVE_LOOP_SUCCESSFUL;
- }
+ if (!window_ || !window_->GetRootWindow())
+ return Widget::MOVE_LOOP_CANCELED;
+ aura::client::WindowMoveClient* move_client =
+ aura::client::GetWindowMoveClient(window_->GetRootWindow());
+ if (!move_client)
+ return Widget::MOVE_LOOP_CANCELED;
+
+ SetCapture();
+ aura::client::WindowMoveSource window_move_source =
+ source == Widget::MOVE_LOOP_SOURCE_MOUSE ?
+ aura::client::WINDOW_MOVE_SOURCE_MOUSE :
+ aura::client::WINDOW_MOVE_SOURCE_TOUCH;
+ if (move_client->RunMoveLoop(window_, drag_offset, window_move_source) ==
+ aura::client::MOVE_SUCCESSFUL) {
+ return Widget::MOVE_LOOP_SUCCESSFUL;
}
return Widget::MOVE_LOOP_CANCELED;
}
void NativeWidgetAura::EndMoveLoop() {
- if (window_ && window_->parent() &&
- aura::client::GetWindowMoveClient(window_->parent())) {
- aura::client::GetWindowMoveClient(window_->parent())->EndMoveLoop();
- }
+ if (!window_ || !window_->GetRootWindow())
+ return;
+ aura::client::WindowMoveClient* move_client =
+ aura::client::GetWindowMoveClient(window_->GetRootWindow());
+ if (move_client)
+ move_client->EndMoveLoop();
}
void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) {
@@ -672,7 +682,7 @@ void NativeWidgetAura::SetVisibilityChangedAnimationsEnabled(bool value) {
ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const {
#if !defined(OS_CHROMEOS)
- return DesktopRootWindowHost::GetNativeTheme(window_);
+ return DesktopWindowTreeHost::GetNativeTheme(window_);
#else
return ui::NativeThemeAura::instance();
#endif
@@ -681,6 +691,14 @@ ui::NativeTheme* NativeWidgetAura::GetNativeTheme() const {
void NativeWidgetAura::OnRootViewLayout() const {
}
+bool NativeWidgetAura::IsTranslucentWindowOpacitySupported() const {
+ return true;
+}
+
+void NativeWidgetAura::RepostNativeEvent(gfx::NativeEvent native_event) {
+ OnEvent(native_event);
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetAura, views::InputMethodDelegate implementation:
@@ -700,13 +718,22 @@ gfx::Size NativeWidgetAura::GetMinimumSize() const {
}
gfx::Size NativeWidgetAura::GetMaximumSize() const {
+ // If a window have a maximum size, the window should not be
+ // maximizable.
+ DCHECK(delegate_->GetMaximumSize().IsEmpty() ||
+ !window_->GetProperty(aura::client::kCanMaximizeKey));
return delegate_->GetMaximumSize();
}
void NativeWidgetAura::OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
- if (old_bounds.origin() != new_bounds.origin())
+ // Assume that if the old bounds was completely empty a move happened. This
+ // handles the case of a maximize animation acquiring the layer (acquiring a
+ // layer results in clearing the bounds).
+ if (old_bounds.origin() != new_bounds.origin() ||
+ (old_bounds == gfx::Rect(0, 0, 0, 0) && !new_bounds.IsEmpty())) {
delegate_->OnNativeWidgetMove();
+ }
if (old_bounds.size() != new_bounds.size())
delegate_->OnNativeWidgetSizeChanged(new_bounds.size());
}
@@ -755,7 +782,7 @@ bool NativeWidgetAura::ShouldDescendIntoChildForEventHandling(
}
bool NativeWidgetAura::CanFocus() {
- return can_activate_;
+ return ShouldActivate();
}
void NativeWidgetAura::OnCaptureLost() {
@@ -770,14 +797,14 @@ void NativeWidgetAura::OnDeviceScaleFactorChanged(float device_scale_factor) {
// Repainting with new scale factor will paint the content at the right scale.
}
-void NativeWidgetAura::OnWindowDestroying() {
+void NativeWidgetAura::OnWindowDestroying(aura::Window* window) {
delegate_->OnNativeWidgetDestroying();
// If the aura::Window is destroyed, we can no longer show tooltips.
tooltip_manager_.reset();
}
-void NativeWidgetAura::OnWindowDestroyed() {
+void NativeWidgetAura::OnWindowDestroyed(aura::Window* window) {
window_ = NULL;
delegate_->OnNativeWidgetDestroyed();
if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
@@ -797,10 +824,6 @@ void NativeWidgetAura::GetHitTestMask(gfx::Path* mask) const {
delegate_->GetHitTestMask(mask);
}
-void NativeWidgetAura::DidRecreateLayer(ui::Layer *old_layer,
- ui::Layer *new_layer) {
-}
-
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetAura, ui::EventHandler implementation:
@@ -818,6 +841,12 @@ void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
if (!window_->IsVisible())
return;
GetWidget()->GetInputMethod()->DispatchKeyEvent(*event);
+ if (switches::IsTextInputFocusManagerEnabled()) {
+ FocusManager* focus_manager = GetWidget()->GetFocusManager();
+ delegate_->OnKeyEvent(event);
+ if (!event->handled() && focus_manager)
+ focus_manager->OnKeyEvent(*event);
+ }
event->SetHandled();
}
@@ -840,12 +869,6 @@ void NativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) {
delegate_->OnScrollEvent(event);
}
-void NativeWidgetAura::OnTouchEvent(ui::TouchEvent* event) {
- DCHECK(window_);
- DCHECK(window_->IsVisible() || event->IsEndingEvent());
- delegate_->OnTouchEvent(event);
-}
-
void NativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) {
DCHECK(window_);
DCHECK(window_->IsVisible() || event->IsEndingEvent());
@@ -856,7 +879,7 @@ void NativeWidgetAura::OnGestureEvent(ui::GestureEvent* event) {
// NativeWidgetAura, aura::client::ActivationDelegate implementation:
bool NativeWidgetAura::ShouldActivate() const {
- return can_activate_ && delegate_->CanActivate();
+ return delegate_->CanActivate();
}
////////////////////////////////////////////////////////////////////////////////
@@ -872,8 +895,6 @@ void NativeWidgetAura::OnWindowActivated(aura::Window* gained_active,
GetWidget()->GetFocusManager()->StoreFocusedView(true);
}
delegate_->OnNativeWidgetActivationChanged(window_ == gained_active);
- if (IsVisible() && GetWidget()->non_client_view())
- GetWidget()->non_client_view()->SchedulePaint();
}
////////////////////////////////////////////////////////////////////////////////
@@ -902,9 +923,7 @@ void NativeWidgetAura::OnWindowFocused(aura::Window* gained_focus,
DCHECK_EQ(ownership_, Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET);
}
- aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
- if (client) // NULL during destruction of aura::Window.
- delegate_->OnNativeBlur(client->GetFocusedWindow());
+ delegate_->OnNativeBlur(gained_focus);
}
}
@@ -936,13 +955,6 @@ int NativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) {
}
////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAura, NativeWidget implementation:
-
-ui::EventHandler* NativeWidgetAura::GetEventHandler() {
- return this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
// NativeWidgetAura, protected:
NativeWidgetAura::~NativeWidgetAura() {
@@ -956,20 +968,15 @@ NativeWidgetAura::~NativeWidgetAura() {
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetAura, private:
-void NativeWidgetAura::SetInitialFocus() {
+void NativeWidgetAura::SetInitialFocus(ui::WindowShowState show_state) {
// The window does not get keyboard messages unless we focus it.
- if (!GetWidget()->SetInitialFocus())
+ if (!GetWidget()->SetInitialFocus(show_state))
window_->Focus();
}
////////////////////////////////////////////////////////////////////////////////
// Widget, public:
-// static
-void Widget::NotifyLocaleChanged() {
- // Deliberately not implemented.
-}
-
namespace {
#if defined(OS_WIN) || (defined(USE_X11) && !defined(OS_CHROMEOS))
void CloseWindow(aura::Window* window) {
@@ -988,7 +995,7 @@ void CloseWindow(aura::Window* window) {
#if defined(OS_WIN)
BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) {
aura::Window* root_window =
- DesktopRootWindowHostWin::GetContentWindowForHWND(hwnd);
+ DesktopWindowTreeHostWin::GetContentWindowForHWND(hwnd);
CloseWindow(root_window);
return TRUE;
}
@@ -1003,9 +1010,9 @@ void Widget::CloseAllSecondaryWidgets() {
#if defined(USE_X11) && !defined(OS_CHROMEOS)
std::vector<aura::Window*> open_windows =
- DesktopRootWindowHostX11::GetAllOpenWindows();
+ DesktopWindowTreeHostX11::GetAllOpenWindows();
std::for_each(open_windows.begin(), open_windows.end(), CloseWindow);
- DesktopRootWindowHostX11::CleanUpWindowList();
+ DesktopWindowTreeHostX11::CleanUpWindowList();
#endif
}
@@ -1076,7 +1083,7 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
Widget::Widgets* owned) {
const aura::Window::Windows& transient_children =
- native_view->transient_children();
+ wm::GetTransientChildren(native_view);
for (aura::Window::Windows::const_iterator i = transient_children.begin();
i != transient_children.end(); ++i) {
NativeWidgetPrivate* native_widget = static_cast<NativeWidgetPrivate*>(
@@ -1142,5 +1149,18 @@ bool NativeWidgetPrivate::IsTouchDown() {
return aura::Env::GetInstance()->is_touch_down();
}
+// static
+gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
+#if defined(OS_WIN)
+ NONCLIENTMETRICS ncm;
+ base::win::GetNonClientMetrics(&ncm);
+ l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
+ base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
+ return gfx::FontList(gfx::Font(caption_font));
+#else
+ return gfx::FontList();
+#endif
+}
+
} // namespace internal
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index c79c003f995..dd6fafe8381 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -7,9 +7,6 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/cursor/cursor.h"
@@ -17,12 +14,15 @@
#include "ui/views/ime/input_method_delegate.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/native_widget_private.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
+#include "ui/wm/public/drag_drop_delegate.h"
namespace aura {
class Window;
}
namespace gfx {
-class Font;
+class FontList;
}
namespace views {
@@ -42,10 +42,6 @@ class VIEWS_EXPORT NativeWidgetAura
public:
explicit NativeWidgetAura(internal::NativeWidgetDelegate* delegate);
- // TODO(beng): Find a better place for this, and the similar method on
- // NativeWidgetWin.
- static gfx::Font GetWindowTitleFont();
-
// Called internally by NativeWidgetAura and DesktopNativeWidgetAura to
// associate |native_widget| with |window|.
static void RegisterNativeWidgetForWindow(
@@ -56,6 +52,7 @@ class VIEWS_EXPORT NativeWidgetAura
virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE;
virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
virtual bool ShouldUseNativeFrame() const OVERRIDE;
+ virtual bool ShouldWindowContentsBeTransparent() const OVERRIDE;
virtual void FrameTypeChanged() OVERRIDE;
virtual Widget* GetWidget() OVERRIDE;
virtual const Widget* GetWidget() const OVERRIDE;
@@ -75,11 +72,12 @@ class VIEWS_EXPORT NativeWidgetAura
virtual bool HasCapture() const OVERRIDE;
virtual InputMethod* CreateInputMethod() OVERRIDE;
virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
+ virtual ui::InputMethod* GetHostInputMethod() OVERRIDE;
virtual void CenterWindow(const gfx::Size& size) OVERRIDE;
virtual void GetWindowPlacement(
gfx::Rect* bounds,
ui::WindowShowState* maximized) const OVERRIDE;
- virtual bool SetWindowTitle(const string16& title) OVERRIDE;
+ virtual bool SetWindowTitle(const base::string16& title) OVERRIDE;
virtual void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) OVERRIDE;
virtual void InitModalType(ui::ModalType modal_type) OVERRIDE;
@@ -105,6 +103,7 @@ class VIEWS_EXPORT NativeWidgetAura
virtual bool IsActive() const OVERRIDE;
virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
virtual bool IsAlwaysOnTop() const OVERRIDE;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) OVERRIDE;
virtual void Maximize() OVERRIDE;
virtual void Minimize() OVERRIDE;
virtual bool IsMaximized() const OVERRIDE;
@@ -133,6 +132,8 @@ class VIEWS_EXPORT NativeWidgetAura
virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
+ virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
// Overridden from views::InputMethodDelegate:
virtual void DispatchKeyEventPostIME(const ui::KeyEvent& key) OVERRIDE;
@@ -151,19 +152,16 @@ class VIEWS_EXPORT NativeWidgetAura
virtual void OnCaptureLost() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void OnWindowDestroying() OVERRIDE;
- virtual void OnWindowDestroyed() OVERRIDE;
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
+ virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
virtual bool HasHitTestMask() const OVERRIDE;
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
- virtual void DidRecreateLayer(ui::Layer* old_layer,
- ui::Layer* new_layer) OVERRIDE;
// Overridden from ui::EventHandler:
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Overridden from aura::client::ActivationDelegate:
@@ -183,9 +181,6 @@ class VIEWS_EXPORT NativeWidgetAura
virtual void OnDragExited() OVERRIDE;
virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
- // Overridden from NativeWidget:
- virtual ui::EventHandler* GetEventHandler() OVERRIDE;
-
protected:
virtual ~NativeWidgetAura();
@@ -194,7 +189,7 @@ class VIEWS_EXPORT NativeWidgetAura
private:
class ActiveWindowObserver;
- void SetInitialFocus();
+ void SetInitialFocus(ui::WindowShowState show_state);
internal::NativeWidgetDelegate* delegate_;
@@ -210,9 +205,6 @@ class VIEWS_EXPORT NativeWidgetAura
// instance.
base::WeakPtrFactory<NativeWidgetAura> close_widget_factory_;
- // Can we be made active?
- bool can_activate_;
-
// Are we in the destructor?
bool destroying_;
diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc
index f0f34c76cbd..3c6d3cc49ad 100644
--- a/chromium/ui/views/widget/native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc
@@ -12,14 +12,16 @@
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/aura_test_helper.h"
+#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
#include "ui/gfx/screen.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/core/default_activation_client.h"
namespace views {
namespace {
@@ -32,40 +34,29 @@ NativeWidgetAura* Init(aura::Window* parent, Widget* widget) {
return static_cast<NativeWidgetAura*>(widget->native_widget());
}
-class NativeWidgetAuraTest : public testing::Test {
+class NativeWidgetAuraTest : public aura::test::AuraTestBase {
public:
NativeWidgetAuraTest() {}
virtual ~NativeWidgetAuraTest() {}
// testing::Test overrides:
virtual void SetUp() OVERRIDE {
- aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
- aura_test_helper_->SetUp();
- root_window()->SetBounds(gfx::Rect(0, 0, 640, 480));
- dispatcher()->SetHostSize(gfx::Size(640, 480));
+ AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
+ host()->SetBounds(gfx::Rect(640, 480));
}
- virtual void TearDown() OVERRIDE {
- message_loop_.RunUntilIdle();
- aura_test_helper_->TearDown();
- }
-
- protected:
- aura::Window* root_window() { return aura_test_helper_->root_window(); }
- aura::RootWindow* dispatcher() { return aura_test_helper_->dispatcher(); }
private:
- base::MessageLoopForUI message_loop_;
- scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
-
DISALLOW_COPY_AND_ASSIGN(NativeWidgetAuraTest);
};
TEST_F(NativeWidgetAuraTest, CenterWindowLargeParent) {
- // Make a parent window larger than the host represented by rootwindow.
+ // Make a parent window larger than the host represented by
+ // WindowEventDispatcher.
scoped_ptr<aura::Window> parent(new aura::Window(NULL));
- parent->Init(ui::LAYER_NOT_DRAWN);
+ parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->SetBounds(gfx::Rect(0, 0, 1024, 800));
- scoped_ptr<Widget> widget(new Widget());
+ scoped_ptr<Widget> widget(new Widget());
NativeWidgetAura* window = Init(parent.get(), widget.get());
window->CenterWindow(gfx::Size(100, 100));
@@ -77,9 +68,10 @@ TEST_F(NativeWidgetAuraTest, CenterWindowLargeParent) {
}
TEST_F(NativeWidgetAuraTest, CenterWindowSmallParent) {
- // Make a parent window smaller than the host represented by rootwindow.
+ // Make a parent window smaller than the host represented by
+ // WindowEventDispatcher.
scoped_ptr<aura::Window> parent(new aura::Window(NULL));
- parent->Init(ui::LAYER_NOT_DRAWN);
+ parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->SetBounds(gfx::Rect(0, 0, 480, 320));
scoped_ptr<Widget> widget(new Widget());
NativeWidgetAura* window = Init(parent.get(), widget.get());
@@ -94,10 +86,10 @@ TEST_F(NativeWidgetAuraTest, CenterWindowSmallParent) {
// Verifies CenterWindow() constrains to parent size.
TEST_F(NativeWidgetAuraTest, CenterWindowSmallParentNotAtOrigin) {
- // Make a parent window smaller than the host represented by rootwindow and
- // offset it slightly from the origin.
+ // Make a parent window smaller than the host represented by
+ // WindowEventDispatcher and offset it slightly from the origin.
scoped_ptr<aura::Window> parent(new aura::Window(NULL));
- parent->Init(ui::LAYER_NOT_DRAWN);
+ parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->SetBounds(gfx::Rect(20, 40, 480, 320));
scoped_ptr<Widget> widget(new Widget());
NativeWidgetAura* window = Init(parent.get(), widget.get());
@@ -108,30 +100,39 @@ TEST_F(NativeWidgetAuraTest, CenterWindowSmallParentNotAtOrigin) {
widget->CloseNow();
}
+class TestLayoutManagerBase : public aura::LayoutManager {
+ public:
+ TestLayoutManagerBase() {}
+ virtual ~TestLayoutManagerBase() {}
+
+ // aura::LayoutManager:
+ virtual void OnWindowResized() OVERRIDE {}
+ virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {}
+ virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
+ virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
+ virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) OVERRIDE {}
+ virtual void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) OVERRIDE {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestLayoutManagerBase);
+};
+
// Used by ShowMaximizedDoesntBounceAround. See it for details.
-class TestLayoutManager : public aura::LayoutManager {
+class MaximizeLayoutManager : public TestLayoutManagerBase {
public:
- TestLayoutManager() {}
+ MaximizeLayoutManager() {}
+ virtual ~MaximizeLayoutManager() {}
- virtual void OnWindowResized() OVERRIDE {
- }
+ private:
+ // aura::LayoutManager:
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
// This simulates what happens when adding a maximized window.
SetChildBoundsDirect(child, gfx::Rect(0, 0, 300, 300));
}
- virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {
- }
- virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {
- }
- virtual void OnChildWindowVisibilityChanged(aura::Window* child,
- bool visible) OVERRIDE {
- }
- virtual void SetChildBounds(aura::Window* child,
- const gfx::Rect& requested_bounds) OVERRIDE {
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(TestLayoutManager);
+ DISALLOW_COPY_AND_ASSIGN(MaximizeLayoutManager);
};
// This simulates BrowserView, which creates a custom RootView so that
@@ -168,7 +169,7 @@ class TestWidget : public views::Widget {
// leads to noticable flashes.
TEST_F(NativeWidgetAuraTest, ShowMaximizedDoesntBounceAround) {
root_window()->SetBounds(gfx::Rect(0, 0, 640, 480));
- root_window()->SetLayoutManager(new TestLayoutManager);
+ root_window()->SetLayoutManager(new MaximizeLayoutManager);
scoped_ptr<TestWidget> widget(new TestWidget());
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
@@ -181,6 +182,70 @@ TEST_F(NativeWidgetAuraTest, ShowMaximizedDoesntBounceAround) {
widget->CloseNow();
}
+class PropertyTestLayoutManager : public TestLayoutManagerBase {
+ public:
+ PropertyTestLayoutManager() : added_(false) {}
+ virtual ~PropertyTestLayoutManager() {}
+
+ bool added() const { return added_; }
+
+ private:
+ // aura::LayoutManager:
+ virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
+ EXPECT_TRUE(child->GetProperty(aura::client::kCanMaximizeKey));
+ EXPECT_TRUE(child->GetProperty(aura::client::kCanResizeKey));
+ added_ = true;
+ }
+
+ bool added_;
+
+ DISALLOW_COPY_AND_ASSIGN(PropertyTestLayoutManager);
+};
+
+class PropertyTestWidgetDelegate : public views::WidgetDelegate {
+ public:
+ explicit PropertyTestWidgetDelegate(Widget* widget) : widget_(widget) {}
+ virtual ~PropertyTestWidgetDelegate() {}
+
+ private:
+ // views::WidgetDelegate:
+ virtual bool CanMaximize() const OVERRIDE {
+ return true;
+ }
+ virtual bool CanResize() const OVERRIDE {
+ return true;
+ }
+ virtual void DeleteDelegate() OVERRIDE {
+ delete this;
+ }
+ virtual Widget* GetWidget() OVERRIDE {
+ return widget_;
+ }
+ virtual const Widget* GetWidget() const OVERRIDE {
+ return widget_;
+ }
+
+ Widget* widget_;
+ DISALLOW_COPY_AND_ASSIGN(PropertyTestWidgetDelegate);
+};
+
+// Verifies that the kCanMaximizeKey/kCanReizeKey have the correct
+// value when added to the layout manager.
+TEST_F(NativeWidgetAuraTest, TestPropertiesWhenAddedToLayout) {
+ root_window()->SetBounds(gfx::Rect(0, 0, 640, 480));
+ PropertyTestLayoutManager* layout_manager = new PropertyTestLayoutManager();
+ root_window()->SetLayoutManager(layout_manager);
+ scoped_ptr<TestWidget> widget(new TestWidget());
+ Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.delegate = new PropertyTestWidgetDelegate(widget.get());
+ params.parent = NULL;
+ params.context = root_window();
+ widget->Init(params);
+ EXPECT_TRUE(layout_manager->added());
+ widget->CloseNow();
+}
+
TEST_F(NativeWidgetAuraTest, GetClientAreaScreenBounds) {
// Create a widget.
Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
@@ -198,8 +263,6 @@ TEST_F(NativeWidgetAuraTest, GetClientAreaScreenBounds) {
EXPECT_EQ(400, client_bounds.height());
}
-namespace {
-
// View subclass that tracks whether it has gotten a gesture event.
class GestureTrackingView : public views::View {
public:
@@ -235,8 +298,6 @@ class GestureTrackingView : public views::View {
DISALLOW_COPY_AND_ASSIGN(GestureTrackingView);
};
-} // namespace
-
// Verifies a capture isn't set on touch press and that the view that gets
// the press gets the release.
TEST_F(NativeWidgetAuraTest, DontCaptureOnGesture) {
@@ -256,9 +317,11 @@ TEST_F(NativeWidgetAuraTest, DontCaptureOnGesture) {
widget->SetContentsView(view);
widget->Show();
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(41, 51), 1,
- base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED, gfx::Point(41, 51), 1, ui::EventTimeForNow());
+ ui::EventDispatchDetails details =
+ event_processor()->OnEventFromSource(&press);
+ ASSERT_FALSE(details.dispatcher_destroyed);
// Both views should get the press.
EXPECT_TRUE(view->got_gesture_event());
EXPECT_TRUE(child->got_gesture_event());
@@ -269,9 +332,10 @@ TEST_F(NativeWidgetAuraTest, DontCaptureOnGesture) {
// Release touch. Only |view| should get the release since that it consumed
// the press.
- ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(250, 251), 1,
- base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
+ ui::TouchEvent release(
+ ui::ET_TOUCH_RELEASED, gfx::Point(250, 251), 1, ui::EventTimeForNow());
+ details = event_processor()->OnEventFromSource(&release);
+ ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(view->got_gesture_event());
EXPECT_FALSE(child->got_gesture_event());
view->clear_got_gesture_event();
@@ -281,39 +345,6 @@ TEST_F(NativeWidgetAuraTest, DontCaptureOnGesture) {
widget->Close();
}
-TEST_F(NativeWidgetAuraTest, ReleaseCaptureOnTouchRelease) {
- GestureTrackingView* view = new GestureTrackingView();
- scoped_ptr<TestWidget> widget(new TestWidget());
- Widget::InitParams params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.context = root_window();
- params.bounds = gfx::Rect(0, 0, 100, 200);
- widget->Init(params);
- widget->SetContentsView(view);
- widget->Show();
-
- ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(41, 51), 1,
- base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
- EXPECT_TRUE(view->got_gesture_event());
- view->clear_got_gesture_event();
- // Set the capture.
- widget->SetCapture(view);
- EXPECT_TRUE(widget->HasCapture());
-
- // Generate a release, this should trigger releasing capture.
- ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(41, 51), 1,
- base::TimeDelta());
- dispatcher()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
- EXPECT_TRUE(view->got_gesture_event());
- view->clear_got_gesture_event();
- EXPECT_FALSE(widget->HasCapture());
-
- // Work around for bug in NativeWidgetAura.
- // TODO: fix bug and remove this.
- widget->Close();
-}
-
// Verifies views with layers are targeted for events properly.
TEST_F(NativeWidgetAuraTest, PreferViewLayersToChildWindows) {
// Create two widgets: |parent| and |child|. |child| is a child of |parent|.
@@ -399,15 +430,53 @@ TEST_F(NativeWidgetAuraTest, FlashFrame) {
TEST_F(NativeWidgetAuraTest, NoCrashOnThemeAfterClose) {
scoped_ptr<aura::Window> parent(new aura::Window(NULL));
- parent->Init(ui::LAYER_NOT_DRAWN);
+ parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
parent->SetBounds(gfx::Rect(0, 0, 480, 320));
scoped_ptr<Widget> widget(new Widget());
- NativeWidgetAura* window = Init(parent.get(), widget.get());
- window->Show();
- window->Close();
+ Init(parent.get(), widget.get());
+ widget->Show();
+ widget->Close();
base::MessageLoop::current()->RunUntilIdle();
widget->GetNativeTheme(); // Shouldn't crash.
}
+// Used to track calls to WidgetDelegate::OnWidgetMove().
+class MoveTestWidgetDelegate : public WidgetDelegateView {
+ public:
+ MoveTestWidgetDelegate() : got_move_(false) {}
+ virtual ~MoveTestWidgetDelegate() {}
+
+ void ClearGotMove() { got_move_ = false; }
+ bool got_move() const { return got_move_; }
+
+ // WidgetDelegate overrides:
+ virtual void OnWidgetMove() OVERRIDE { got_move_ = true; }
+
+ private:
+ bool got_move_;
+
+ DISALLOW_COPY_AND_ASSIGN(MoveTestWidgetDelegate);
+};
+
+// This test simulates what happens when a window is normally maximized. That
+// is, it's layer is acquired for animation then the window is maximized.
+// Acquiring the layer resets the bounds of the window. This test verifies the
+// Widget is still notified correctly of a move in this case.
+TEST_F(NativeWidgetAuraTest, OnWidgetMovedInvokedAfterAcquireLayer) {
+ // |delegate| deletes itself when the widget is destroyed.
+ MoveTestWidgetDelegate* delegate = new MoveTestWidgetDelegate;
+ Widget* widget =
+ Widget::CreateWindowWithContextAndBounds(delegate,
+ root_window(),
+ gfx::Rect(10, 10, 100, 200));
+ widget->Show();
+ delegate->ClearGotMove();
+ // Simulate a maximize with animation.
+ delete widget->GetNativeView()->RecreateLayer().release();
+ widget->SetBounds(gfx::Rect(0, 0, 500, 500));
+ EXPECT_TRUE(delegate->got_move());
+ widget->CloseNow();
+}
+
} // namespace
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_delegate.h b/chromium/ui/views/widget/native_widget_delegate.h
index 914b575f30d..c18b5fc8015 100644
--- a/chromium/ui/views/widget/native_widget_delegate.h
+++ b/chromium/ui/views/widget/native_widget_delegate.h
@@ -80,10 +80,10 @@ class VIEWS_EXPORT NativeWidgetDelegate {
virtual void OnNativeWidgetDestroyed() = 0;
// Returns the smallest size the window can be resized to by the user.
- virtual gfx::Size GetMinimumSize() = 0;
+ virtual gfx::Size GetMinimumSize() const = 0;
// Returns the largest size the window can be resized to by the user.
- virtual gfx::Size GetMaximumSize() = 0;
+ virtual gfx::Size GetMaximumSize() const = 0;
// Called when the NativeWidget changed position.
virtual void OnNativeWidgetMove() = 0;
@@ -116,7 +116,6 @@ class VIEWS_EXPORT NativeWidgetDelegate {
virtual void OnMouseEvent(ui::MouseEvent* event) = 0;
virtual void OnMouseCaptureLost() = 0;
- virtual void OnTouchEvent(ui::TouchEvent* event) = 0;
virtual void OnScrollEvent(ui::ScrollEvent* event) = 0;
virtual void OnGestureEvent(ui::GestureEvent* event) = 0;
@@ -140,6 +139,14 @@ class VIEWS_EXPORT NativeWidgetDelegate {
//
virtual Widget* AsWidget() = 0;
virtual const Widget* AsWidget() const = 0;
+
+ // Sets-up the focus manager with the view that should have focus when the
+ // window is shown the first time. It takes the intended |show_state| of the
+ // window in order to decide whether the window should be focused now or
+ // later. Returns true if the initial focus has been set or the window should
+ // not set the initial focus, or false if the caller should set the initial
+ // focus (if any).
+ virtual bool SetInitialFocus(ui::WindowShowState show_state) = 0;
};
} // namespace internal
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
new file mode 100644
index 00000000000..64cb9a3bea8
--- /dev/null
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -0,0 +1,117 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_
+#define UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_
+
+#include "ui/gfx/native_widget_types.h"
+#include "ui/views/widget/native_widget_private.h"
+
+namespace views {
+
+class BridgedNativeWidget;
+
+class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
+ public:
+ NativeWidgetMac(internal::NativeWidgetDelegate* delegate);
+ virtual ~NativeWidgetMac();
+
+ protected:
+ // internal::NativeWidgetPrivate:
+ virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE;
+ virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
+ virtual bool ShouldUseNativeFrame() const OVERRIDE;
+ virtual bool ShouldWindowContentsBeTransparent() const OVERRIDE;
+ virtual void FrameTypeChanged() OVERRIDE;
+ virtual Widget* GetWidget() OVERRIDE;
+ virtual const Widget* GetWidget() const OVERRIDE;
+ virtual gfx::NativeView GetNativeView() const OVERRIDE;
+ virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE;
+ virtual Widget* GetTopLevelWidget() OVERRIDE;
+ virtual const ui::Compositor* GetCompositor() const OVERRIDE;
+ virtual ui::Compositor* GetCompositor() OVERRIDE;
+ virtual ui::Layer* GetLayer() OVERRIDE;
+ virtual void ReorderNativeViews() OVERRIDE;
+ virtual void ViewRemoved(View* view) OVERRIDE;
+ virtual void SetNativeWindowProperty(const char* name, void* value) OVERRIDE;
+ virtual void* GetNativeWindowProperty(const char* name) const OVERRIDE;
+ virtual TooltipManager* GetTooltipManager() const OVERRIDE;
+ virtual void SetCapture() OVERRIDE;
+ virtual void ReleaseCapture() OVERRIDE;
+ virtual bool HasCapture() const OVERRIDE;
+ virtual InputMethod* CreateInputMethod() OVERRIDE;
+ virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
+ virtual ui::InputMethod* GetHostInputMethod() OVERRIDE;
+ virtual void CenterWindow(const gfx::Size& size) OVERRIDE;
+ virtual void GetWindowPlacement(
+ gfx::Rect* bounds,
+ ui::WindowShowState* maximized) const OVERRIDE;
+ virtual bool SetWindowTitle(const base::string16& title) OVERRIDE;
+ virtual void SetWindowIcons(const gfx::ImageSkia& window_icon,
+ const gfx::ImageSkia& app_icon) OVERRIDE;
+ virtual void InitModalType(ui::ModalType modal_type) OVERRIDE;
+ virtual gfx::Rect GetWindowBoundsInScreen() const OVERRIDE;
+ virtual gfx::Rect GetClientAreaBoundsInScreen() const OVERRIDE;
+ virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+ virtual void SetSize(const gfx::Size& size) OVERRIDE;
+ virtual void StackAbove(gfx::NativeView native_view) OVERRIDE;
+ virtual void StackAtTop() OVERRIDE;
+ virtual void StackBelow(gfx::NativeView native_view) OVERRIDE;
+ virtual void SetShape(gfx::NativeRegion shape) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual void CloseNow() OVERRIDE;
+ virtual void Show() OVERRIDE;
+ virtual void Hide() OVERRIDE;
+ virtual void ShowMaximizedWithBounds(
+ const gfx::Rect& restored_bounds) OVERRIDE;
+ virtual void ShowWithWindowState(ui::WindowShowState state) OVERRIDE;
+ virtual bool IsVisible() const OVERRIDE;
+ virtual void Activate() OVERRIDE;
+ virtual void Deactivate() OVERRIDE;
+ virtual bool IsActive() const OVERRIDE;
+ virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
+ virtual bool IsAlwaysOnTop() const OVERRIDE;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) OVERRIDE;
+ virtual void Maximize() OVERRIDE;
+ virtual void Minimize() OVERRIDE;
+ virtual bool IsMaximized() const OVERRIDE;
+ virtual bool IsMinimized() const OVERRIDE;
+ virtual void Restore() OVERRIDE;
+ virtual void SetFullscreen(bool fullscreen) OVERRIDE;
+ virtual bool IsFullscreen() const OVERRIDE;
+ virtual void SetOpacity(unsigned char opacity) OVERRIDE;
+ virtual void SetUseDragFrame(bool use_drag_frame) OVERRIDE;
+ virtual void FlashFrame(bool flash_frame) OVERRIDE;
+ virtual void RunShellDrag(View* view,
+ const ui::OSExchangeData& data,
+ const gfx::Point& location,
+ int operation,
+ ui::DragDropTypes::DragEventSource source) OVERRIDE;
+ virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
+ virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
+ virtual bool IsMouseEventsEnabled() const OVERRIDE;
+ virtual void ClearNativeFocus() OVERRIDE;
+ virtual gfx::Rect GetWorkAreaBoundsInScreen() const OVERRIDE;
+ virtual Widget::MoveLoopResult RunMoveLoop(
+ const gfx::Vector2d& drag_offset,
+ Widget::MoveLoopSource source,
+ Widget::MoveLoopEscapeBehavior escape_behavior) OVERRIDE;
+ virtual void EndMoveLoop() OVERRIDE;
+ virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
+ virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
+ virtual void OnRootViewLayout() const OVERRIDE;
+ virtual bool IsTranslucentWindowOpacitySupported() const OVERRIDE;
+ virtual void RepostNativeEvent(gfx::NativeEvent native_event) OVERRIDE;
+
+ private:
+ internal::NativeWidgetDelegate* delegate_;
+ scoped_ptr<BridgedNativeWidget> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeWidgetMac);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
new file mode 100644
index 00000000000..37545b974cf
--- /dev/null
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -0,0 +1,448 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/native_widget_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_nsobject.h"
+#include "ui/gfx/font_list.h"
+#include "ui/native_theme/native_theme.h"
+#import "ui/views/cocoa/bridged_content_view.h"
+#import "ui/views/cocoa/bridged_native_widget.h"
+
+namespace views {
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetMac, public:
+
+NativeWidgetMac::NativeWidgetMac(internal::NativeWidgetDelegate* delegate)
+ : delegate_(delegate), bridge_(new BridgedNativeWidget) {
+}
+
+NativeWidgetMac::~NativeWidgetMac() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeWidgetMac, internal::NativeWidgetPrivate implementation:
+
+void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
+ // TODO(tapted): Convert position into Cocoa's flipped coordinate space.
+ NSRect content_rect =
+ NSMakeRect(0, 0, params.bounds.width(), params.bounds.height());
+ // TODO(tapted): Determine a good initial style mask from |params|.
+ NSInteger style_mask = NSTitledWindowMask | NSClosableWindowMask |
+ NSMiniaturizableWindowMask | NSResizableWindowMask;
+ base::scoped_nsobject<NSWindow> window(
+ [[NSWindow alloc] initWithContentRect:content_rect
+ styleMask:style_mask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ bridge_->Init(window);
+}
+
+NonClientFrameView* NativeWidgetMac::CreateNonClientFrameView() {
+ return NULL;
+}
+
+bool NativeWidgetMac::ShouldUseNativeFrame() const {
+ return false;
+}
+
+bool NativeWidgetMac::ShouldWindowContentsBeTransparent() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NativeWidgetMac::FrameTypeChanged() {
+ NOTIMPLEMENTED();
+}
+
+Widget* NativeWidgetMac::GetWidget() {
+ return delegate_->AsWidget();
+}
+
+const Widget* NativeWidgetMac::GetWidget() const {
+ return delegate_->AsWidget();
+}
+
+gfx::NativeView NativeWidgetMac::GetNativeView() const {
+ return bridge_->ns_view();
+}
+
+gfx::NativeWindow NativeWidgetMac::GetNativeWindow() const {
+ return bridge_->ns_window();
+}
+
+Widget* NativeWidgetMac::GetTopLevelWidget() {
+ NOTIMPLEMENTED();
+ return GetWidget();
+}
+
+const ui::Compositor* NativeWidgetMac::GetCompositor() const {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+ui::Compositor* NativeWidgetMac::GetCompositor() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+ui::Layer* NativeWidgetMac::GetLayer() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void NativeWidgetMac::ReorderNativeViews() {
+ bridge_->SetRootView(GetWidget()->GetRootView());
+}
+
+void NativeWidgetMac::ViewRemoved(View* view) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetNativeWindowProperty(const char* name, void* value) {
+ NOTIMPLEMENTED();
+}
+
+void* NativeWidgetMac::GetNativeWindowProperty(const char* name) const {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+TooltipManager* NativeWidgetMac::GetTooltipManager() const {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void NativeWidgetMac::SetCapture() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::ReleaseCapture() {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::HasCapture() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+InputMethod* NativeWidgetMac::CreateInputMethod() {
+ return bridge_->CreateInputMethod();
+}
+
+internal::InputMethodDelegate* NativeWidgetMac::GetInputMethodDelegate() {
+ return bridge_.get();
+}
+
+ui::InputMethod* NativeWidgetMac::GetHostInputMethod() {
+ return bridge_->GetHostInputMethod();
+}
+
+void NativeWidgetMac::CenterWindow(const gfx::Size& size) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::GetWindowPlacement(gfx::Rect* bounds,
+ ui::WindowShowState* maximized) const {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::SetWindowTitle(const base::string16& title) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NativeWidgetMac::SetWindowIcons(const gfx::ImageSkia& window_icon,
+ const gfx::ImageSkia& app_icon) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
+ NOTIMPLEMENTED();
+}
+
+gfx::Rect NativeWidgetMac::GetWindowBoundsInScreen() const {
+ NOTIMPLEMENTED();
+ return gfx::Rect();
+}
+
+gfx::Rect NativeWidgetMac::GetClientAreaBoundsInScreen() const {
+ NOTIMPLEMENTED();
+ return gfx::Rect();
+}
+
+gfx::Rect NativeWidgetMac::GetRestoredBounds() const {
+ NOTIMPLEMENTED();
+ return gfx::Rect();
+}
+
+void NativeWidgetMac::SetBounds(const gfx::Rect& bounds) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetSize(const gfx::Size& size) {
+ [bridge_->ns_window() setContentSize:NSMakeSize(size.width(), size.height())];
+}
+
+void NativeWidgetMac::StackAbove(gfx::NativeView native_view) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::StackAtTop() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::StackBelow(gfx::NativeView native_view) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetShape(gfx::NativeRegion shape) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Close() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::CloseNow() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Show() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Hide() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::ShowMaximizedWithBounds(
+ const gfx::Rect& restored_bounds) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::ShowWithWindowState(ui::WindowShowState state) {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsVisible() const {
+ NOTIMPLEMENTED();
+ return true;
+}
+
+void NativeWidgetMac::Activate() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Deactivate() {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsActive() const {
+ NOTIMPLEMENTED();
+ return true;
+}
+
+void NativeWidgetMac::SetAlwaysOnTop(bool always_on_top) {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsAlwaysOnTop() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NativeWidgetMac::SetVisibleOnAllWorkspaces(bool always_visible) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Maximize() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::Minimize() {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsMaximized() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool NativeWidgetMac::IsMinimized() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NativeWidgetMac::Restore() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetFullscreen(bool fullscreen) {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsFullscreen() const {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NativeWidgetMac::SetOpacity(unsigned char opacity) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetUseDragFrame(bool use_drag_frame) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::FlashFrame(bool flash_frame) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::RunShellDrag(View* view,
+ const ui::OSExchangeData& data,
+ const gfx::Point& location,
+ int operation,
+ ui::DragDropTypes::DragEventSource source) {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
+ // TODO(tapted): This should use setNeedsDisplayInRect:, once the coordinate
+ // system of |rect| has been converted.
+ [bridge_->ns_view() setNeedsDisplay:YES];
+}
+
+void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsMouseEventsEnabled() const {
+ NOTIMPLEMENTED();
+ return true;
+}
+
+void NativeWidgetMac::ClearNativeFocus() {
+ NOTIMPLEMENTED();
+}
+
+gfx::Rect NativeWidgetMac::GetWorkAreaBoundsInScreen() const {
+ NOTIMPLEMENTED();
+ return gfx::Rect();
+}
+
+Widget::MoveLoopResult NativeWidgetMac::RunMoveLoop(
+ const gfx::Vector2d& drag_offset,
+ Widget::MoveLoopSource source,
+ Widget::MoveLoopEscapeBehavior escape_behavior) {
+ NOTIMPLEMENTED();
+ return Widget::MOVE_LOOP_CANCELED;
+}
+
+void NativeWidgetMac::EndMoveLoop() {
+ NOTIMPLEMENTED();
+}
+
+void NativeWidgetMac::SetVisibilityChangedAnimationsEnabled(bool value) {
+ NOTIMPLEMENTED();
+}
+
+ui::NativeTheme* NativeWidgetMac::GetNativeTheme() const {
+ return ui::NativeTheme::instance();
+}
+
+void NativeWidgetMac::OnRootViewLayout() const {
+ NOTIMPLEMENTED();
+}
+
+bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
+ return false;
+}
+
+void NativeWidgetMac::RepostNativeEvent(gfx::NativeEvent native_event) {
+ NOTIMPLEMENTED();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget, public:
+
+bool Widget::ConvertRect(const Widget* source,
+ const Widget* target,
+ gfx::Rect* rect) {
+ return false;
+}
+
+namespace internal {
+
+////////////////////////////////////////////////////////////////////////////////
+// internal::NativeWidgetPrivate, public:
+
+// static
+NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
+ internal::NativeWidgetDelegate* delegate) {
+ return new NativeWidgetMac(delegate);
+}
+
+// static
+NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
+ gfx::NativeView native_view) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+// static
+NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
+ gfx::NativeWindow native_window) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+// static
+NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
+ gfx::NativeView native_view) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+// static
+void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
+ Widget::Widgets* children) {
+ NOTIMPLEMENTED();
+}
+
+// static
+void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
+ Widget::Widgets* owned) {
+ NOTIMPLEMENTED();
+}
+
+// static
+void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
+ gfx::NativeView new_parent) {
+ NOTIMPLEMENTED();
+}
+
+// static
+bool NativeWidgetPrivate::IsMouseButtonDown() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+// static
+bool NativeWidgetPrivate::IsTouchDown() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+// static
+gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
+ NOTIMPLEMENTED();
+ return gfx::FontList();
+}
+
+} // 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 2cee9533a6b..8c9233a3ff8 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -8,15 +8,16 @@
#include "base/strings/string16.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/views/ime/input_method_delegate.h"
#include "ui/views/widget/native_widget.h"
namespace gfx {
+class FontList;
class ImageSkia;
class Rect;
}
namespace ui {
+class InputMethod;
class NativeTheme;
class OSExchangeData;
}
@@ -25,6 +26,7 @@ namespace views {
class InputMethod;
class TooltipManager;
namespace internal {
+class InputMethodDelegate;
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetPrivate interface
@@ -72,6 +74,8 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
// Returns true if any touch device is currently down.
static bool IsTouchDown();
+ static gfx::FontList GetWindowTitleFontList();
+
// Initializes the NativeWidget.
virtual void InitNativeWidget(const Widget::InitParams& params) = 0;
@@ -80,6 +84,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual NonClientFrameView* CreateNonClientFrameView() = 0;
virtual bool ShouldUseNativeFrame() const = 0;
+ virtual bool ShouldWindowContentsBeTransparent() const = 0;
virtual void FrameTypeChanged() = 0;
// Returns the Widget associated with this NativeWidget. This function is
@@ -141,6 +146,10 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
// Returns the InputMethodDelegate for this native widget.
virtual InputMethodDelegate* GetInputMethodDelegate() = 0;
+ // Returns the ui::InputMethod for this native widget.
+ // TODO(yukishiino): Rename this method to GetInputMethod once we remove
+ // views::InputMethod.
+ virtual ui::InputMethod* GetHostInputMethod() = 0;
// Centers the window and sizes it to the specified size.
virtual void CenterWindow(const gfx::Size& size) = 0;
@@ -152,7 +161,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
ui::WindowShowState* show_state) const = 0;
// Sets the NativeWindow title. Returns true if the title changed.
- virtual bool SetWindowTitle(const string16& title) = 0;
+ virtual bool SetWindowTitle(const base::string16& title) = 0;
// Sets the Window icons. |window_icon| is a 16x16 icon suitable for use in
// a title bar. |app_icon| is a larger size for use in the host environment
@@ -189,6 +198,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual bool IsActive() const = 0;
virtual void SetAlwaysOnTop(bool always_on_top) = 0;
virtual bool IsAlwaysOnTop() const = 0;
+ virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
virtual void Maximize() = 0;
virtual void Minimize() = 0;
virtual bool IsMaximized() const = 0;
@@ -217,10 +227,13 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual void SetVisibilityChangedAnimationsEnabled(bool value) = 0;
virtual ui::NativeTheme* GetNativeTheme() const = 0;
virtual void OnRootViewLayout() const = 0;
+ virtual bool IsTranslucentWindowOpacitySupported() const = 0;
+
+ // Repost an unhandled event to the native widget for default OS processing.
+ virtual void RepostNativeEvent(gfx::NativeEvent native_event) = 0;
// Overridden from NativeWidget:
virtual internal::NativeWidgetPrivate* AsNativeWidgetPrivate() OVERRIDE;
- virtual ui::EventHandler* GetEventHandler() = 0;
};
} // namespace internal
diff --git a/chromium/ui/views/widget/native_widget_unittest.cc b/chromium/ui/views/widget/native_widget_unittest.cc
index 133f8be04a5..9002e9da8f1 100644
--- a/chromium/ui/views/widget/native_widget_unittest.cc
+++ b/chromium/ui/views/widget/native_widget_unittest.cc
@@ -42,7 +42,6 @@ class NativeWidgetTest : public ViewsTestBase {
Widget* widget = new Widget;
Widget::InitParams params = CreateParams(type);
params.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
- params.child = false; // Implicitly set to true by ctor with TYPE_CONTROL.
params.bounds = gfx::Rect(10, 10, 200, 200);
widget->Init(params);
return widget->native_widget_private();
diff --git a/chromium/ui/views/widget/native_widget_win.cc b/chromium/ui/views/widget/native_widget_win.cc
deleted file mode 100644
index 3f992e8d894..00000000000
--- a/chromium/ui/views/widget/native_widget_win.cc
+++ /dev/null
@@ -1,1068 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/native_widget_win.h"
-
-#include <dwmapi.h>
-#include <shellapi.h>
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/strings/string_util.h"
-#include "base/win/scoped_gdi_object.h"
-#include "base/win/win_util.h"
-#include "base/win/windows_version.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/base/dragdrop/drag_source_win.h"
-#include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
-#include "ui/base/ime/input_method_factory.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/base/theme_provider.h"
-#include "ui/base/view_prop.h"
-#include "ui/base/win/mouse_wheel_util.h"
-#include "ui/base/win/shell.h"
-#include "ui/events/event.h"
-#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/canvas_skia_paint.h"
-#include "ui/gfx/path.h"
-#include "ui/gfx/point_conversions.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/views/controls/native_control_win.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/drag_utils.h"
-#include "ui/views/focus/accelerator_handler.h"
-#include "ui/views/focus/view_storage.h"
-#include "ui/views/focus/widget_focus_manager.h"
-#include "ui/views/ime/input_method_bridge.h"
-#include "ui/views/widget/aero_tooltip_manager.h"
-#include "ui/views/widget/drop_target_win.h"
-#include "ui/views/widget/monitor_win.h"
-#include "ui/views/widget/native_widget_delegate.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/widget_delegate.h"
-#include "ui/views/widget/widget_hwnd_utils.h"
-#include "ui/views/win/fullscreen_handler.h"
-#include "ui/views/win/hwnd_message_handler.h"
-#include "ui/views/window/native_frame_view.h"
-
-#pragma comment(lib, "dwmapi.lib")
-
-using ui::ViewProp;
-
-namespace views {
-
-namespace {
-
-// Enumeration callback for NativeWidget::GetAllChildWidgets() and
-// NativeWidget::GetAllOwnedWidgets. Adds any HWNDs that correspond to
-// Widgets to a set.
-BOOL CALLBACK EnumerateNativeWidgets(HWND hwnd, LPARAM l_param) {
- Widget* widget = Widget::GetWidgetForNativeView(hwnd);
- if (widget) {
- Widget::Widgets* widgets = reinterpret_cast<Widget::Widgets*>(l_param);
- widgets->insert(widget);
- }
- return TRUE;
-}
-
-// Links the HWND to its NativeWidget.
-const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
-
-const int kDragFrameWindowAlpha = 200;
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, public:
-
-NativeWidgetWin::NativeWidgetWin(internal::NativeWidgetDelegate* delegate)
- : delegate_(delegate),
- ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
- drag_frame_saved_window_style_(0),
- drag_frame_saved_window_ex_style_(0),
- has_non_client_view_(false),
- message_handler_(new HWNDMessageHandler(this)) {
-}
-
-NativeWidgetWin::~NativeWidgetWin() {
- if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
- delete delegate_;
- else
- CloseNow();
- message_handler_.reset();
-}
-
-// static
-gfx::Font NativeWidgetWin::GetWindowTitleFont() {
- NONCLIENTMETRICS ncm;
- base::win::GetNonClientMetrics(&ncm);
- l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
- base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
- return gfx::Font(caption_font);
-}
-
-void NativeWidgetWin::Show(int show_state) {
- message_handler_->Show(show_state);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, NativeWidget implementation:
-
-void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) {
- gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
- Widget::InitParams params_in_pixel(params);
- params_in_pixel.bounds = pixel_bounds;
- SetInitParams(params_in_pixel);
- message_handler_->Init(params.parent, pixel_bounds);
-}
-
-NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() {
- return GetWidget()->ShouldUseNativeFrame() ?
- new NativeFrameView(GetWidget()) : NULL;
-}
-
-bool NativeWidgetWin::ShouldUseNativeFrame() const {
- return ui::win::IsAeroGlassEnabled();
-}
-
-void NativeWidgetWin::FrameTypeChanged() {
- message_handler_->FrameTypeChanged();
-}
-
-Widget* NativeWidgetWin::GetWidget() {
- return delegate_->AsWidget();
-}
-
-const Widget* NativeWidgetWin::GetWidget() const {
- return delegate_->AsWidget();
-}
-
-gfx::NativeView NativeWidgetWin::GetNativeView() const {
- return message_handler_->hwnd();
-}
-
-gfx::NativeWindow NativeWidgetWin::GetNativeWindow() const {
- return message_handler_->hwnd();
-}
-
-Widget* NativeWidgetWin::GetTopLevelWidget() {
- NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView());
- return native_widget ? native_widget->GetWidget() : NULL;
-}
-
-const ui::Compositor* NativeWidgetWin::GetCompositor() const {
- return NULL;
-}
-
-ui::Compositor* NativeWidgetWin::GetCompositor() {
- return NULL;
-}
-
-ui::Layer* NativeWidgetWin::GetLayer() {
- return NULL;
-}
-
-void NativeWidgetWin::ReorderNativeViews() {
-}
-
-void NativeWidgetWin::ViewRemoved(View* view) {
- if (drop_target_.get())
- drop_target_->ResetTargetViewIfEquals(view);
-}
-
-void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) {
- // Remove the existing property (if any).
- for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) {
- if ((*i)->Key() == name) {
- props_.erase(i);
- break;
- }
- }
-
- if (value)
- props_.push_back(new ViewProp(GetNativeView(), name, value));
-}
-
-void* NativeWidgetWin::GetNativeWindowProperty(const char* name) const {
- return ViewProp::GetValue(GetNativeView(), name);
-}
-
-TooltipManager* NativeWidgetWin::GetTooltipManager() const {
- return tooltip_manager_.get();
-}
-
-void NativeWidgetWin::SetCapture() {
- message_handler_->SetCapture();
-}
-
-void NativeWidgetWin::ReleaseCapture() {
- message_handler_->ReleaseCapture();
-}
-
-bool NativeWidgetWin::HasCapture() const {
- return message_handler_->HasCapture();
-}
-
-InputMethod* NativeWidgetWin::CreateInputMethod() {
- return new InputMethodBridge(GetMessageHandler(), ui::GetSharedInputMethod(),
- true);
-}
-
-internal::InputMethodDelegate* NativeWidgetWin::GetInputMethodDelegate() {
- return message_handler_.get();
-}
-
-void NativeWidgetWin::CenterWindow(const gfx::Size& size) {
- gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
- message_handler_->CenterWindow(size_in_pixels);
-}
-
-void NativeWidgetWin::GetWindowPlacement(
- gfx::Rect* bounds,
- ui::WindowShowState* show_state) const {
- message_handler_->GetWindowPlacement(bounds, show_state);
- *bounds = gfx::win::ScreenToDIPRect(*bounds);
-}
-
-bool NativeWidgetWin::SetWindowTitle(const string16& title) {
- return message_handler_->SetTitle(title);
-}
-
-void NativeWidgetWin::SetWindowIcons(const gfx::ImageSkia& window_icon,
- const gfx::ImageSkia& app_icon) {
- message_handler_->SetWindowIcons(window_icon, app_icon);
-}
-
-void NativeWidgetWin::InitModalType(ui::ModalType modal_type) {
- message_handler_->InitModalType(modal_type);
-}
-
-gfx::Rect NativeWidgetWin::GetWindowBoundsInScreen() const {
- gfx::Rect bounds_in_pixels = message_handler_->GetWindowBoundsInScreen();
- return gfx::win::ScreenToDIPRect(bounds_in_pixels);
-}
-
-gfx::Rect NativeWidgetWin::GetClientAreaBoundsInScreen() const {
- gfx::Rect bounds_in_pixels = message_handler_->GetClientAreaBoundsInScreen();
- return gfx::win::ScreenToDIPRect(bounds_in_pixels);
-}
-
-gfx::Rect NativeWidgetWin::GetRestoredBounds() const {
- gfx::Rect bounds_in_pixels = message_handler_->GetRestoredBounds();
- return gfx::win::ScreenToDIPRect(bounds_in_pixels);
-}
-
-void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) {
- float scale = gfx::win::GetDeviceScaleFactor();
- gfx::Rect bounds_in_pixels(
- gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)),
- gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale)));
- message_handler_->SetBounds(bounds_in_pixels);
-}
-
-void NativeWidgetWin::SetSize(const gfx::Size& size) {
- message_handler_->SetSize(size);
-}
-
-void NativeWidgetWin::StackAbove(gfx::NativeView native_view) {
- message_handler_->StackAbove(native_view);
-}
-
-void NativeWidgetWin::StackAtTop() {
- message_handler_->StackAtTop();
-}
-
-void NativeWidgetWin::StackBelow(gfx::NativeView native_view) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetWin::SetShape(gfx::NativeRegion region) {
- message_handler_->SetRegion(region);
-}
-
-void NativeWidgetWin::Close() {
- message_handler_->Close();
-}
-
-void NativeWidgetWin::CloseNow() {
- message_handler_->CloseNow();
-}
-
-void NativeWidgetWin::Show() {
- message_handler_->Show();
-}
-
-void NativeWidgetWin::Hide() {
- message_handler_->Hide();
-}
-
-void NativeWidgetWin::ShowMaximizedWithBounds(
- const gfx::Rect& restored_bounds) {
- gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds);
- message_handler_->ShowMaximizedWithBounds(pixel_bounds);
-}
-
-void NativeWidgetWin::ShowWithWindowState(ui::WindowShowState show_state) {
- message_handler_->ShowWindowWithState(show_state);
-}
-
-bool NativeWidgetWin::IsVisible() const {
- return message_handler_->IsVisible();
-}
-
-void NativeWidgetWin::Activate() {
- message_handler_->Activate();
-}
-
-void NativeWidgetWin::Deactivate() {
- message_handler_->Deactivate();
-}
-
-bool NativeWidgetWin::IsActive() const {
- return message_handler_->IsActive();
-}
-
-void NativeWidgetWin::SetAlwaysOnTop(bool on_top) {
- message_handler_->SetAlwaysOnTop(on_top);
-}
-
-bool NativeWidgetWin::IsAlwaysOnTop() const {
- return message_handler_->IsAlwaysOnTop();
-}
-
-void NativeWidgetWin::Maximize() {
- message_handler_->Maximize();
-}
-
-void NativeWidgetWin::Minimize() {
- message_handler_->Minimize();
-}
-
-bool NativeWidgetWin::IsMaximized() const {
- return message_handler_->IsMaximized();
-}
-
-bool NativeWidgetWin::IsMinimized() const {
- return message_handler_->IsMinimized();
-}
-
-void NativeWidgetWin::Restore() {
- message_handler_->Restore();
-}
-
-void NativeWidgetWin::SetFullscreen(bool fullscreen) {
- message_handler_->fullscreen_handler()->SetFullscreen(fullscreen);
-}
-
-void NativeWidgetWin::SetMetroSnapFullscreen(bool metro_snap) {
- message_handler_->fullscreen_handler()->SetMetroSnap(metro_snap);
-}
-
-bool NativeWidgetWin::IsFullscreen() const {
- return message_handler_->fullscreen_handler()->fullscreen();
-}
-
-bool NativeWidgetWin::IsInMetroSnapMode() const {
- return message_handler_->fullscreen_handler()->metro_snap();
-}
-
-void NativeWidgetWin::SetCanUpdateLayeredWindow(bool can_update) {
- message_handler_->set_can_update_layered_window(can_update);
-}
-
-void NativeWidgetWin::SetOpacity(unsigned char opacity) {
- message_handler_->SetOpacity(static_cast<BYTE>(opacity));
- GetWidget()->GetRootView()->SchedulePaint();
-}
-
-void NativeWidgetWin::SetUseDragFrame(bool use_drag_frame) {
- if (use_drag_frame) {
- // Make the frame slightly transparent during the drag operation.
- drag_frame_saved_window_style_ = GetWindowLong(GetNativeView(), GWL_STYLE);
- drag_frame_saved_window_ex_style_ =
- GetWindowLong(GetNativeView(), GWL_EXSTYLE);
- SetWindowLong(GetNativeView(), GWL_EXSTYLE,
- drag_frame_saved_window_ex_style_ | WS_EX_LAYERED);
- // Remove the captions tyle so the window doesn't have window controls for a
- // more "transparent" look.
- SetWindowLong(GetNativeView(), GWL_STYLE,
- drag_frame_saved_window_style_ & ~WS_CAPTION);
- SetLayeredWindowAttributes(GetNativeView(), RGB(0xFF, 0xFF, 0xFF),
- kDragFrameWindowAlpha, LWA_ALPHA);
- } else {
- SetWindowLong(GetNativeView(), GWL_STYLE, drag_frame_saved_window_style_);
- SetWindowLong(GetNativeView(), GWL_EXSTYLE,
- drag_frame_saved_window_ex_style_);
- }
-}
-
-void NativeWidgetWin::FlashFrame(bool flash) {
- message_handler_->FlashFrame(flash);
-}
-
-void NativeWidgetWin::RunShellDrag(View* view,
- const ui::OSExchangeData& data,
- const gfx::Point& location,
- int operation,
- ui::DragDropTypes::DragEventSource source) {
- views::RunShellDrag(NULL, data, location, operation, source);
-}
-
-void NativeWidgetWin::SchedulePaintInRect(const gfx::Rect& rect) {
- gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(rect);
- message_handler_->SchedulePaintInRect(pixel_rect);
-}
-
-void NativeWidgetWin::SetCursor(gfx::NativeCursor cursor) {
- message_handler_->SetCursor(cursor);
-}
-
-bool NativeWidgetWin::IsMouseEventsEnabled() const {
- return true;
-}
-
-void NativeWidgetWin::ClearNativeFocus() {
- message_handler_->ClearNativeFocus();
-}
-
-gfx::Rect NativeWidgetWin::GetWorkAreaBoundsInScreen() const {
- return gfx::win::ScreenToDIPRect(
- gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
- GetNativeView()).work_area());
-}
-
-Widget::MoveLoopResult NativeWidgetWin::RunMoveLoop(
- const gfx::Vector2d& drag_offset,
- Widget::MoveLoopSource source,
- Widget::MoveLoopEscapeBehavior escape_behavior) {
- const bool hide_on_escape =
- escape_behavior == Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE;
- return message_handler_->RunMoveLoop(drag_offset, hide_on_escape) ?
- Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
-}
-
-void NativeWidgetWin::EndMoveLoop() {
- message_handler_->EndMoveLoop();
-}
-
-void NativeWidgetWin::SetVisibilityChangedAnimationsEnabled(bool value) {
- message_handler_->SetVisibilityChangedAnimationsEnabled(value);
-}
-
-ui::NativeTheme* NativeWidgetWin::GetNativeTheme() const {
- return ui::NativeTheme::instance();
-}
-
-void NativeWidgetWin::OnRootViewLayout() const {
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, NativeWidget implementation:
-
-ui::EventHandler* NativeWidgetWin::GetEventHandler() {
- NOTIMPLEMENTED();
- return NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, protected:
-
-void NativeWidgetWin::OnFinalMessage(HWND window) {
- // We don't destroy props in WM_DESTROY as we may still get messages after
- // WM_DESTROY that assume the properties are still valid (such as WM_CLOSE).
- props_.clear();
- delegate_->OnNativeWidgetDestroyed();
- if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
- delete this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, protected:
-
-HWNDMessageHandler* NativeWidgetWin::GetMessageHandler() {
- return message_handler_.get();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, HWNDMessageHandlerDelegate implementation:
-
-bool NativeWidgetWin::IsWidgetWindow() const {
- // We don't NULL check GetWidget()->non_client_view() here because this
- // function can be called before the widget is fully constructed.
- return has_non_client_view_;
-}
-
-bool NativeWidgetWin::IsUsingCustomFrame() const {
- return !GetWidget()->ShouldUseNativeFrame();
-}
-
-void NativeWidgetWin::SchedulePaint() {
- GetWidget()->GetRootView()->SchedulePaint();
-}
-
-void NativeWidgetWin::EnableInactiveRendering() {
- delegate_->EnableInactiveRendering();
-}
-
-bool NativeWidgetWin::IsInactiveRenderingDisabled() {
- return delegate_->IsInactiveRenderingDisabled();
-}
-
-bool NativeWidgetWin::CanResize() const {
- return GetWidget()->widget_delegate()->CanResize();
-}
-
-bool NativeWidgetWin::CanMaximize() const {
- return GetWidget()->widget_delegate()->CanMaximize();
-}
-
-bool NativeWidgetWin::CanActivate() const {
- return delegate_->CanActivate();
-}
-
-bool NativeWidgetWin::WidgetSizeIsClientSize() const {
- const Widget* widget = GetWidget()->GetTopLevelWidget();
- return IsZoomed(GetNativeView()) ||
- (widget && widget->ShouldUseNativeFrame());
-}
-
-bool NativeWidgetWin::CanSaveFocus() const {
- return GetWidget()->is_top_level();
-}
-
-void NativeWidgetWin::SaveFocusOnDeactivate() {
- GetWidget()->GetFocusManager()->StoreFocusedView(true);
-}
-
-void NativeWidgetWin::RestoreFocusOnActivate() {
- // Mysteriously, this only appears to be needed support restoration of focus
- // to a child hwnd when restoring its top level window from the minimized
- // state. If we don't do this, then ::SetFocus() to that child HWND returns
- // ERROR_INVALID_PARAMETER, despite both HWNDs being of the same thread.
- // See http://crbug.com/125976 and
- // chrome/browser/ui/views/native_widget_win_interactive_uitest.cc .
- {
- // Since this is a synthetic reset, we don't need to tell anyone about it.
- AutoNativeNotificationDisabler disabler;
- GetWidget()->GetFocusManager()->ClearFocus();
- }
- RestoreFocusOnEnable();
-}
-
-void NativeWidgetWin::RestoreFocusOnEnable() {
- GetWidget()->GetFocusManager()->RestoreFocusedView();
-}
-
-bool NativeWidgetWin::IsModal() const {
- return delegate_->IsModal();
-}
-
-int NativeWidgetWin::GetInitialShowState() const {
- return SW_SHOWNORMAL;
-}
-
-bool NativeWidgetWin::WillProcessWorkAreaChange() const {
- return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
-}
-
-int NativeWidgetWin::GetNonClientComponent(const gfx::Point& point) const {
- gfx::Point point_in_dip = gfx::win::ScreenToDIPPoint(point);
- return delegate_->GetNonClientComponent(point_in_dip);
-}
-
-void NativeWidgetWin::GetWindowMask(const gfx::Size& size, gfx::Path* path) {
- if (GetWidget()->non_client_view())
- GetWidget()->non_client_view()->GetWindowMask(size, path);
-}
-
-bool NativeWidgetWin::GetClientAreaInsets(gfx::Insets* insets) const {
- return false;
-}
-
-void NativeWidgetWin::GetMinMaxSize(gfx::Size* min_size,
- gfx::Size* max_size) const {
- *min_size = gfx::win::ScreenToDIPSize(delegate_->GetMinimumSize());
- *max_size = gfx::win::ScreenToDIPSize(delegate_->GetMaximumSize());
-}
-
-gfx::Size NativeWidgetWin::GetRootViewSize() const {
- gfx::Size pixel_size = GetWidget()->GetRootView()->size();
- return gfx::win::ScreenToDIPSize(pixel_size);
-}
-
-void NativeWidgetWin::ResetWindowControls() {
- GetWidget()->non_client_view()->ResetWindowControls();
-}
-
-void NativeWidgetWin::PaintLayeredWindow(gfx::Canvas* canvas) {
- GetWidget()->GetRootView()->Paint(canvas);
-}
-
-InputMethod* NativeWidgetWin::GetInputMethod() {
- return GetWidget()->GetInputMethodDirect();
-}
-
-gfx::NativeViewAccessible NativeWidgetWin::GetNativeViewAccessible() {
- return GetWidget()->GetRootView()->GetNativeViewAccessible();
-}
-
-bool NativeWidgetWin::ShouldHandleSystemCommands() const {
- return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
-}
-
-void NativeWidgetWin::HandleAppDeactivated() {
- if (IsInactiveRenderingDisabled()) {
- delegate_->EnableInactiveRendering();
- } else {
- // TODO(pkotwicz): Remove need for SchedulePaint(). crbug.com/165841
- View* non_client_view = GetWidget()->non_client_view();
- if (non_client_view)
- non_client_view->SchedulePaint();
- }
-}
-
-void NativeWidgetWin::HandleActivationChanged(bool active) {
- delegate_->OnNativeWidgetActivationChanged(active);
-}
-
-bool NativeWidgetWin::HandleAppCommand(short command) {
- // We treat APPCOMMAND ids as an extension of our command namespace, and just
- // let the delegate figure out what to do...
- return GetWidget()->widget_delegate() &&
- GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
-}
-
-void NativeWidgetWin::HandleCancelMode() {
-}
-
-void NativeWidgetWin::HandleCaptureLost() {
- delegate_->OnMouseCaptureLost();
-}
-
-void NativeWidgetWin::HandleClose() {
- GetWidget()->Close();
-}
-
-bool NativeWidgetWin::HandleCommand(int command) {
- return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
-}
-
-void NativeWidgetWin::HandleAccelerator(const ui::Accelerator& accelerator) {
- GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
-}
-
-void NativeWidgetWin::HandleCreate() {
- // TODO(beng): much of this could/should maybe move to HWNDMessageHandler.
-
- SetNativeWindowProperty(kNativeWidgetKey, this);
- CHECK_EQ(this, GetNativeWidgetForNativeView(GetNativeView()));
-
- props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(GetNativeView()));
-
- drop_target_ = new DropTargetWin(
- static_cast<internal::RootView*>(GetWidget()->GetRootView()));
-
- // Windows special DWM window frame requires a special tooltip manager so
- // that window controls in Chrome windows don't flicker when you move your
- // mouse over them. See comment in aero_tooltip_manager.h.
- Widget* widget = GetWidget()->GetTopLevelWidget();
- if (widget && widget->ShouldUseNativeFrame()) {
- tooltip_manager_.reset(new AeroTooltipManager(GetWidget()));
- } else {
- tooltip_manager_.reset(new TooltipManagerWin(GetWidget()));
- }
- if (!tooltip_manager_->Init()) {
- // There was a problem creating the TooltipManager. Common error is 127.
- // See 82193 for details.
- LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips";
- tooltip_manager_.reset();
- }
-
- delegate_->OnNativeWidgetCreated(true);
-}
-
-void NativeWidgetWin::HandleDestroying() {
- delegate_->OnNativeWidgetDestroying();
- if (drop_target_.get()) {
- RevokeDragDrop(GetNativeView());
- drop_target_ = NULL;
- }
-}
-
-void NativeWidgetWin::HandleDestroyed() {
- OnFinalMessage(GetNativeView());
-}
-
-bool NativeWidgetWin::HandleInitialFocus() {
- return GetWidget()->SetInitialFocus();
-}
-
-void NativeWidgetWin::HandleDisplayChange() {
- GetWidget()->widget_delegate()->OnDisplayChanged();
-}
-
-void NativeWidgetWin::HandleBeginWMSizeMove() {
- delegate_->OnNativeWidgetBeginUserBoundsChange();
-}
-
-void NativeWidgetWin::HandleEndWMSizeMove() {
- delegate_->OnNativeWidgetEndUserBoundsChange();
-}
-
-void NativeWidgetWin::HandleMove() {
- delegate_->OnNativeWidgetMove();
-}
-
-void NativeWidgetWin::HandleWorkAreaChanged() {
- GetWidget()->widget_delegate()->OnWorkAreaChanged();
-}
-
-void NativeWidgetWin::HandleVisibilityChanging(bool visible) {
- delegate_->OnNativeWidgetVisibilityChanging(visible);
-}
-
-void NativeWidgetWin::HandleVisibilityChanged(bool visible) {
- delegate_->OnNativeWidgetVisibilityChanged(visible);
-}
-
-void NativeWidgetWin::HandleClientSizeChanged(const gfx::Size& new_size) {
- gfx::Size size_in_dip = gfx::win::ScreenToDIPSize(new_size);
- delegate_->OnNativeWidgetSizeChanged(size_in_dip);
-}
-
-void NativeWidgetWin::HandleFrameChanged() {
- // Replace the frame and layout the contents.
- GetWidget()->non_client_view()->UpdateFrame();
-}
-
-void NativeWidgetWin::HandleNativeFocus(HWND last_focused_window) {
- delegate_->OnNativeFocus(last_focused_window);
- InputMethod* input_method = GetInputMethod();
- if (input_method)
- input_method->OnFocus();
-}
-
-void NativeWidgetWin::HandleNativeBlur(HWND focused_window) {
- delegate_->OnNativeBlur(focused_window);
- InputMethod* input_method = GetInputMethod();
- if (input_method)
- input_method->OnBlur();
-}
-
-bool NativeWidgetWin::HandleMouseEvent(const ui::MouseEvent& event) {
- static gfx::Transform scale_transform(
- 1/gfx::win::GetDeviceScaleFactor(), 0.0,
- 0.0, 1/gfx::win::GetDeviceScaleFactor(),
- 0.0, 0.0);
- if (event.IsMouseWheelEvent()) {
- ui::MouseWheelEvent dpi_event(
- static_cast<const ui::MouseWheelEvent&>(event));
- dpi_event.UpdateForRootTransform(scale_transform);
- delegate_->OnMouseEvent(&dpi_event);
- return dpi_event.handled();
- } else if (event.IsMouseEvent()) {
- ui::MouseEvent dpi_event(event);
- if (!(dpi_event.flags() & ui::EF_IS_NON_CLIENT))
- dpi_event.UpdateForRootTransform(scale_transform);
- delegate_->OnMouseEvent(&dpi_event);
- return dpi_event.handled();
- }
- NOTREACHED();
- return false;
-}
-
-bool NativeWidgetWin::HandleKeyEvent(const ui::KeyEvent& event) {
- delegate_->OnKeyEvent(const_cast<ui::KeyEvent*>(&event));
- return event.handled();
-}
-
-bool NativeWidgetWin::HandleUntranslatedKeyEvent(const ui::KeyEvent& event) {
- InputMethod* input_method = GetInputMethod();
- if (input_method)
- input_method->DispatchKeyEvent(event);
- return !!input_method;
-}
-
-void NativeWidgetWin::HandleTouchEvent(const ui::TouchEvent& event) {
- NOTREACHED() << "Touch events are not supported";
-}
-
-bool NativeWidgetWin::HandleIMEMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) {
- InputMethod* input_method = GetInputMethod();
- if (!input_method || input_method->IsMock()) {
- *result = 0;
- return false;
- }
-
- MSG msg = {};
- msg.hwnd = message_handler_->hwnd();
- msg.message = message;
- msg.wParam = w_param;
- msg.lParam = l_param;
- return input_method->OnUntranslatedIMEMessage(msg, result);
-}
-
-void NativeWidgetWin::HandleInputLanguageChange(DWORD character_set,
- HKL input_language_id) {
- InputMethod* input_method = GetInputMethod();
- if (input_method && !input_method->IsMock()) {
- input_method->OnInputLocaleChanged();
- }
-}
-
-bool NativeWidgetWin::HandlePaintAccelerated(const gfx::Rect& invalid_rect) {
- gfx::Rect dpi_rect = gfx::win::ScreenToDIPRect(invalid_rect);
- return delegate_->OnNativeWidgetPaintAccelerated(dpi_rect);
-}
-
-void NativeWidgetWin::HandlePaint(gfx::Canvas* canvas) {
- delegate_->OnNativeWidgetPaint(canvas);
-}
-
-bool NativeWidgetWin::HandleTooltipNotify(int w_param,
- NMHDR* l_param,
- LRESULT* l_result) {
- // We can be sent this message before the tooltip manager is created, if a
- // subclass overrides OnCreate and creates some kind of Windows control there
- // that sends WM_NOTIFY messages.
- if (tooltip_manager_.get()) {
- bool handled;
- *l_result = tooltip_manager_->OnNotify(w_param, l_param, &handled);
- return handled;
- }
- return false;
-}
-
-void NativeWidgetWin::HandleTooltipMouseMove(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- if (tooltip_manager_.get())
- tooltip_manager_->OnMouse(message, w_param, l_param);
-}
-
-bool NativeWidgetWin::PreHandleMSG(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) {
- return false;
-}
-
-void NativeWidgetWin::PostHandleMSG(UINT message,
- WPARAM w_param,
- LPARAM l_param) {
-}
-
-bool NativeWidgetWin::HandleScrollEvent(const ui::ScrollEvent& event) {
- delegate_->OnScrollEvent(const_cast<ui::ScrollEvent*>(&event));
- return event.handled();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetWin, private:
-
-void NativeWidgetWin::SetInitParams(const Widget::InitParams& params) {
- // Set non-style attributes.
- ownership_ = params.ownership;
-
- ConfigureWindowStyles(message_handler_.get(), params,
- GetWidget()->widget_delegate(), delegate_);
-
- has_non_client_view_ = Widget::RequiresNonClientView(params.type);
- message_handler_->set_remove_standard_frame(params.remove_standard_frame);
- message_handler_->set_use_system_default_icon(params.use_system_default_icon);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Widget, public:
-
-// static
-void Widget::NotifyLocaleChanged() {
- NOTIMPLEMENTED();
-}
-
-namespace {
-BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) {
- Widget* widget = Widget::GetWidgetForNativeView(hwnd);
- if (widget && widget->is_secondary_widget())
- widget->Close();
- return TRUE;
-}
-} // namespace
-
-// static
-void Widget::CloseAllSecondaryWidgets() {
- EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0);
-}
-
-bool Widget::ConvertRect(const Widget* source,
- const Widget* target,
- gfx::Rect* rect) {
- DCHECK(source);
- DCHECK(target);
- DCHECK(rect);
-
- HWND source_hwnd = source->GetNativeView();
- HWND target_hwnd = target->GetNativeView();
- if (source_hwnd == target_hwnd)
- return true;
-
- RECT win_rect = gfx::win::DIPToScreenRect(*rect).ToRECT();
- if (::MapWindowPoints(source_hwnd, target_hwnd,
- reinterpret_cast<LPPOINT>(&win_rect),
- sizeof(RECT)/sizeof(POINT))) {
- *rect = gfx::win::ScreenToDIPRect(gfx::Rect(win_rect));
- return true;
- }
- return false;
-}
-
-namespace internal {
-
-////////////////////////////////////////////////////////////////////////////////
-// internal::NativeWidgetPrivate, public:
-
-// static
-NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
- internal::NativeWidgetDelegate* delegate) {
- return new NativeWidgetWin(delegate);
-}
-
-// static
-NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
- gfx::NativeView native_view) {
- return reinterpret_cast<NativeWidgetWin*>(
- ViewProp::GetValue(native_view, kNativeWidgetKey));
-}
-
-// static
-NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
- gfx::NativeWindow native_window) {
- return GetNativeWidgetForNativeView(native_window);
-}
-
-// static
-NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
- gfx::NativeView native_view) {
- if (!native_view)
- return NULL;
-
- // First, check if the top-level window is a Widget.
- HWND root = ::GetAncestor(native_view, GA_ROOT);
- if (!root)
- return NULL;
-
- NativeWidgetPrivate* widget = GetNativeWidgetForNativeView(root);
- if (widget)
- return widget;
-
- // Second, try to locate the last Widget window in the parent hierarchy.
- HWND parent_hwnd = native_view;
- // If we fail to find the native widget pointer for the root then it probably
- // means that the root belongs to a different process in which case we walk up
- // the native view chain looking for a parent window which corresponds to a
- // valid native widget. We only do this if we fail to find the native widget
- // for the current native view which means it is being destroyed.
- if (!widget && !GetNativeWidgetForNativeView(native_view)) {
- parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT);
- if (!parent_hwnd)
- return NULL;
- }
- NativeWidgetPrivate* parent_widget;
- do {
- parent_widget = GetNativeWidgetForNativeView(parent_hwnd);
- if (parent_widget) {
- widget = parent_widget;
- parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT);
- }
- } while (parent_hwnd != NULL && parent_widget != NULL);
-
- return widget;
-}
-
-// static
-void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
- Widget::Widgets* children) {
- if (!native_view)
- return;
-
- Widget* widget = Widget::GetWidgetForNativeView(native_view);
- if (widget)
- children->insert(widget);
- EnumChildWindows(native_view, EnumerateNativeWidgets,
- reinterpret_cast<LPARAM>(children));
-}
-
-// static
-void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
- Widget::Widgets* owned) {
- if (!native_view)
- return;
-
- Widget::Widgets all;
- EnumWindows(EnumerateNativeWidgets, reinterpret_cast<LPARAM>(&all));
- for (Widget::Widgets::const_iterator iter = all.begin();
- iter != all.end(); ++iter) {
- if (native_view == GetWindow((*iter)->GetNativeView(), GW_OWNER))
- owned->insert(*iter);
- }
-}
-
-// static
-void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
- gfx::NativeView new_parent) {
- if (!native_view)
- return;
-
- HWND previous_parent = ::GetParent(native_view);
- if (previous_parent == new_parent)
- return;
-
- Widget::Widgets widgets;
- GetAllChildWidgets(native_view, &widgets);
-
- // First notify all the widgets that they are being disassociated
- // from their previous parent.
- for (Widget::Widgets::iterator it = widgets.begin();
- it != widgets.end(); ++it) {
- (*it)->NotifyNativeViewHierarchyWillChange();
- }
-
- ::SetParent(native_view, new_parent);
-
- // And now, notify them that they have a brand new parent.
- for (Widget::Widgets::iterator it = widgets.begin();
- it != widgets.end(); ++it) {
- (*it)->NotifyNativeViewHierarchyChanged();
- }
-}
-
-// static
-bool NativeWidgetPrivate::IsMouseButtonDown() {
- return (GetKeyState(VK_LBUTTON) & 0x80) ||
- (GetKeyState(VK_RBUTTON) & 0x80) ||
- (GetKeyState(VK_MBUTTON) & 0x80) ||
- (GetKeyState(VK_XBUTTON1) & 0x80) ||
- (GetKeyState(VK_XBUTTON2) & 0x80);
-}
-
-// static
-bool NativeWidgetPrivate::IsTouchDown() {
- // This currently isn't necessary because we're not generating touch events on
- // windows. When we do, this will need to be updated.
- return false;
-}
-
-} // namespace internal
-
-} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_win.h b/chromium/ui/views/widget/native_widget_win.h
deleted file mode 100644
index 31bee8b8828..00000000000
--- a/chromium/ui/views/widget/native_widget_win.h
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
-#define UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
-
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/win/scoped_comptr.h"
-#include "base/win/win_util.h"
-#include "ui/gfx/win/window_impl.h"
-#include "ui/views/widget/native_widget_private.h"
-#include "ui/views/win/hwnd_message_handler_delegate.h"
-
-namespace ui {
-class Compositor;
-class ViewProp;
-}
-
-namespace gfx {
-class Canvas;
-class Font;
-class Rect;
-}
-
-namespace views {
-
-class DropTargetWin;
-class HWNDMessageHandler;
-class InputMethodDelegate;
-class RootView;
-class TooltipManagerWin;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// NativeWidgetWin
-// A Widget for a views hierarchy used to represent anything that can be
-// contained within an HWND, e.g. a control, a window, etc. Specializations
-// suitable for specific tasks, e.g. top level window, are derived from this.
-//
-// This Widget contains a RootView which owns the hierarchy of views within it.
-// As long as views are part of this tree, they will be deleted automatically
-// when the RootView is destroyed. If you remove a view from the tree, you are
-// then responsible for cleaning up after it.
-//
-///////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT NativeWidgetWin : public internal::NativeWidgetPrivate,
- public HWNDMessageHandlerDelegate {
- public:
- explicit NativeWidgetWin(internal::NativeWidgetDelegate* delegate);
- virtual ~NativeWidgetWin();
-
- // Returns the system set window title font.
- static gfx::Font GetWindowTitleFont();
-
- // Show the window with the specified show command.
- void Show(int show_state);
-
- // Places the window in a pseudo-fullscreen mode where it looks and acts as
- // like a fullscreen window except that it remains within the boundaries
- // of the metro snap divider.
- void SetMetroSnapFullscreen(bool metro_snap);
- bool IsInMetroSnapMode() const;
-
- void SetCanUpdateLayeredWindow(bool can_update);
-
- // Overridden from internal::NativeWidgetPrivate:
- virtual void InitNativeWidget(const Widget::InitParams& params) OVERRIDE;
- virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
- virtual bool ShouldUseNativeFrame() const OVERRIDE;
- virtual void FrameTypeChanged() OVERRIDE;
- virtual Widget* GetWidget() OVERRIDE;
- virtual const Widget* GetWidget() const OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeWindow GetNativeWindow() const OVERRIDE;
- virtual Widget* GetTopLevelWidget() OVERRIDE;
- virtual const ui::Compositor* GetCompositor() const OVERRIDE;
- virtual ui::Compositor* GetCompositor() OVERRIDE;
- virtual ui::Layer* GetLayer() OVERRIDE;
- virtual void ReorderNativeViews() OVERRIDE;
- virtual void ViewRemoved(View* view) OVERRIDE;
- virtual void SetNativeWindowProperty(const char* name, void* value) OVERRIDE;
- virtual void* GetNativeWindowProperty(const char* name) const OVERRIDE;
- virtual TooltipManager* GetTooltipManager() const OVERRIDE;
- virtual void SetCapture() OVERRIDE;
- virtual void ReleaseCapture() OVERRIDE;
- virtual bool HasCapture() const OVERRIDE;
- virtual InputMethod* CreateInputMethod() OVERRIDE;
- virtual internal::InputMethodDelegate* GetInputMethodDelegate() OVERRIDE;
- virtual void CenterWindow(const gfx::Size& size) OVERRIDE;
- virtual void GetWindowPlacement(
- gfx::Rect* bounds,
- ui::WindowShowState* show_state) const OVERRIDE;
- virtual bool SetWindowTitle(const string16& title) OVERRIDE;
- virtual void SetWindowIcons(const gfx::ImageSkia& window_icon,
- const gfx::ImageSkia& app_icon) OVERRIDE;
- virtual void InitModalType(ui::ModalType modal_type) OVERRIDE;
- virtual gfx::Rect GetWindowBoundsInScreen() const OVERRIDE;
- virtual gfx::Rect GetClientAreaBoundsInScreen() const OVERRIDE;
- virtual gfx::Rect GetRestoredBounds() const OVERRIDE;
- virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void StackAbove(gfx::NativeView native_view) OVERRIDE;
- virtual void StackAtTop() OVERRIDE;
- virtual void StackBelow(gfx::NativeView native_view) OVERRIDE;
- virtual void SetShape(gfx::NativeRegion shape) OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void CloseNow() OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void ShowMaximizedWithBounds(
- const gfx::Rect& restored_bounds) OVERRIDE;
- virtual void ShowWithWindowState(ui::WindowShowState show_state) OVERRIDE;
- virtual bool IsVisible() const OVERRIDE;
- virtual void Activate() OVERRIDE;
- virtual void Deactivate() OVERRIDE;
- virtual bool IsActive() const OVERRIDE;
- virtual void SetAlwaysOnTop(bool always_on_top) OVERRIDE;
- virtual bool IsAlwaysOnTop() const OVERRIDE;
- virtual void Maximize() OVERRIDE;
- virtual void Minimize() OVERRIDE;
- virtual bool IsMaximized() const OVERRIDE;
- virtual bool IsMinimized() const OVERRIDE;
- virtual void Restore() OVERRIDE;
- virtual void SetFullscreen(bool fullscreen) OVERRIDE;
- virtual bool IsFullscreen() const OVERRIDE;
- virtual void SetOpacity(unsigned char opacity) OVERRIDE;
- virtual void SetUseDragFrame(bool use_drag_frame) OVERRIDE;
- virtual void FlashFrame(bool flash) OVERRIDE;
- virtual void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
- const gfx::Point& location,
- int operation,
- ui::DragDropTypes::DragEventSource source) OVERRIDE;
- virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
- virtual void SetCursor(gfx::NativeCursor cursor) OVERRIDE;
- virtual bool IsMouseEventsEnabled() const OVERRIDE;
- virtual void ClearNativeFocus() OVERRIDE;
- virtual gfx::Rect GetWorkAreaBoundsInScreen() const OVERRIDE;
- virtual Widget::MoveLoopResult RunMoveLoop(
- const gfx::Vector2d& drag_offset,
- Widget::MoveLoopSource source,
- Widget::MoveLoopEscapeBehavior escape_behavior) OVERRIDE;
- virtual void EndMoveLoop() OVERRIDE;
- virtual void SetVisibilityChangedAnimationsEnabled(bool value) OVERRIDE;
- virtual ui::NativeTheme* GetNativeTheme() const OVERRIDE;
- virtual void OnRootViewLayout() const OVERRIDE;
-
- // Overridden from NativeWidget:
- virtual ui::EventHandler* GetEventHandler() OVERRIDE;
-
- protected:
- // Deletes this window as it is destroyed, override to provide different
- // behavior.
- virtual void OnFinalMessage(HWND window);
-
- HWNDMessageHandler* GetMessageHandler();
-
- // Overridden from HWNDMessageHandlerDelegate:
- virtual bool IsWidgetWindow() const OVERRIDE;
- virtual bool IsUsingCustomFrame() const OVERRIDE;
- virtual void SchedulePaint() OVERRIDE;
- virtual void EnableInactiveRendering() OVERRIDE;
- virtual bool IsInactiveRenderingDisabled() OVERRIDE;
- virtual bool CanResize() const OVERRIDE;
- virtual bool CanMaximize() const OVERRIDE;
- virtual bool CanActivate() const OVERRIDE;
- virtual bool WidgetSizeIsClientSize() const OVERRIDE;
- virtual bool CanSaveFocus() const OVERRIDE;
- virtual void SaveFocusOnDeactivate() OVERRIDE;
- virtual void RestoreFocusOnActivate() OVERRIDE;
- virtual void RestoreFocusOnEnable() OVERRIDE;
- virtual bool IsModal() const OVERRIDE;
- virtual int GetInitialShowState() const OVERRIDE;
- virtual bool WillProcessWorkAreaChange() const OVERRIDE;
- virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE;
- virtual void GetWindowMask(const gfx::Size& size, gfx::Path* path) OVERRIDE;
- virtual bool GetClientAreaInsets(gfx::Insets* insets) const OVERRIDE;
- virtual void GetMinMaxSize(gfx::Size* min_size,
- gfx::Size* max_size) const OVERRIDE;
- virtual gfx::Size GetRootViewSize() const OVERRIDE;
- virtual void ResetWindowControls() OVERRIDE;
- virtual void PaintLayeredWindow(gfx::Canvas* canvas) OVERRIDE;
- virtual InputMethod* GetInputMethod() OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual bool ShouldHandleSystemCommands() const OVERRIDE;
- virtual void HandleAppDeactivated() OVERRIDE;
- virtual void HandleActivationChanged(bool active) OVERRIDE;
- virtual bool HandleAppCommand(short command) OVERRIDE;
- virtual void HandleCancelMode() OVERRIDE;
- virtual void HandleCaptureLost() OVERRIDE;
- virtual void HandleClose() OVERRIDE;
- virtual bool HandleCommand(int command) OVERRIDE;
- virtual void HandleAccelerator(const ui::Accelerator& accelerator) OVERRIDE;
- virtual void HandleCreate() OVERRIDE;
- virtual void HandleDestroying() OVERRIDE;
- virtual void HandleDestroyed() OVERRIDE;
- virtual bool HandleInitialFocus() OVERRIDE;
- virtual void HandleDisplayChange() OVERRIDE;
- virtual void HandleBeginWMSizeMove() OVERRIDE;
- virtual void HandleEndWMSizeMove() OVERRIDE;
- virtual void HandleMove() OVERRIDE;
- virtual void HandleWorkAreaChanged() OVERRIDE;
- virtual void HandleVisibilityChanging(bool visible) OVERRIDE;
- virtual void HandleVisibilityChanged(bool visible) OVERRIDE;
- virtual void HandleClientSizeChanged(const gfx::Size& new_size) OVERRIDE;
- virtual void HandleFrameChanged() OVERRIDE;
- virtual void HandleNativeFocus(HWND last_focused_window) OVERRIDE;
- virtual void HandleNativeBlur(HWND focused_window) OVERRIDE;
- virtual bool HandleMouseEvent(const ui::MouseEvent& event) OVERRIDE;
- virtual bool HandleKeyEvent(const ui::KeyEvent& event) OVERRIDE;
- virtual bool HandleUntranslatedKeyEvent(const ui::KeyEvent& event) OVERRIDE;
- virtual void HandleTouchEvent(const ui::TouchEvent& event) OVERRIDE;
- virtual bool HandleIMEMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) OVERRIDE;
- virtual void HandleInputLanguageChange(DWORD character_set,
- HKL input_language_id) OVERRIDE;
- virtual bool HandlePaintAccelerated(const gfx::Rect& invalid_rect) OVERRIDE;
- virtual void HandlePaint(gfx::Canvas* canvas) OVERRIDE;
- virtual bool HandleTooltipNotify(int w_param,
- NMHDR* l_param,
- LRESULT* l_result) OVERRIDE;
- virtual void HandleTooltipMouseMove(UINT message,
- WPARAM w_param,
- LPARAM l_param) OVERRIDE;
- virtual bool PreHandleMSG(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* result) OVERRIDE;
- virtual void PostHandleMSG(UINT message,
- WPARAM w_param,
- LPARAM l_param) OVERRIDE;
- virtual bool HandleScrollEvent(const ui::ScrollEvent& event) OVERRIDE;
-
- // The TooltipManager. This is NULL if there is a problem creating the
- // underlying tooltip window.
- // WARNING: RootView's destructor calls into the TooltipManager. As such, this
- // must be destroyed AFTER root_view_.
- scoped_ptr<TooltipManagerWin> tooltip_manager_;
-
- scoped_refptr<DropTargetWin> drop_target_;
-
- private:
- typedef ScopedVector<ui::ViewProp> ViewProps;
-
- void SetInitParams(const Widget::InitParams& params);
-
- // A delegate implementation that handles events received here.
- // See class documentation for Widget in widget.h for a note about ownership.
- internal::NativeWidgetDelegate* delegate_;
-
- // See class documentation for Widget in widget.h for a note about ownership.
- Widget::InitParams::Ownership ownership_;
-
- ViewProps props_;
-
- // The window styles before we modified them for the drag frame appearance.
- DWORD drag_frame_saved_window_style_;
- DWORD drag_frame_saved_window_ex_style_;
-
- // True if the widget is going to have a non_client_view. We cache this value
- // rather than asking the Widget for the non_client_view so that we know at
- // Init time, before the Widget has created the NonClientView.
- bool has_non_client_view_;
-
- scoped_ptr<HWNDMessageHandler> message_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeWidgetWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_NATIVE_WIDGET_WIN_H_
diff --git a/chromium/ui/views/widget/native_widget_win_unittest.cc b/chromium/ui/views/widget/native_widget_win_unittest.cc
deleted file mode 100644
index 6a84ca06d70..00000000000
--- a/chromium/ui/views/widget/native_widget_win_unittest.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/native_widget_win.h"
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/win/scoped_ole_initializer.h"
-
-namespace views {
-namespace {
-
-class NativeWidgetWinTest : public testing::Test {
- public:
- NativeWidgetWinTest() {}
- ~NativeWidgetWinTest() {}
-
- virtual void TearDown() {
- // Flush the message loop because we have pending release tasks
- // and these tasks if un-executed would upset Valgrind.
- RunPendingMessages();
- }
-
- // Create a simple widget win. The caller is responsible for taking ownership
- // of the returned value.
- NativeWidgetWin* CreateNativeWidgetWin();
-
- void RunPendingMessages() {
- message_loop_.RunUntilIdle();
- }
-
- private:
- base::MessageLoopForUI message_loop_;
- ui::ScopedOleInitializer ole_initializer_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeWidgetWinTest);
-};
-
-NativeWidgetWin* NativeWidgetWinTest::CreateNativeWidgetWin() {
- scoped_ptr<Widget> widget(new Widget);
- Widget::InitParams params(Widget::InitParams::TYPE_POPUP);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.bounds = gfx::Rect(50, 50, 650, 650);
- widget->Init(params);
- return static_cast<NativeWidgetWin*>(widget.release()->native_widget());
-}
-
-TEST_F(NativeWidgetWinTest, ZoomWindow) {
- scoped_ptr<NativeWidgetWin> window(CreateNativeWidgetWin());
- ShowWindow(window->GetNativeView(), SW_HIDE);
- EXPECT_FALSE(window->IsActive());
- ShowWindow(window->GetNativeView(), SW_MAXIMIZE);
- EXPECT_TRUE(IsZoomed(window->GetNativeView()));
- window->CloseNow();
-}
-
-TEST_F(NativeWidgetWinTest, SetBoundsForZoomedWindow) {
- scoped_ptr<NativeWidgetWin> window(CreateNativeWidgetWin());
- ShowWindow(window->GetNativeView(), SW_MAXIMIZE);
- EXPECT_TRUE(IsZoomed(window->GetNativeView()));
-
- // Create another window, so that it will be active.
- scoped_ptr<NativeWidgetWin> window2(CreateNativeWidgetWin());
- ShowWindow(window2->GetNativeView(), SW_MAXIMIZE);
- EXPECT_TRUE(window2->IsActive());
- EXPECT_FALSE(window->IsActive());
-
- // Verify that setting the bounds of a zoomed window will unzoom it and not
- // cause it to be activated.
- window->SetBounds(gfx::Rect(50, 50, 650, 650));
- EXPECT_FALSE(IsZoomed(window->GetNativeView()));
- EXPECT_FALSE(window->IsActive());
-
- // Cleanup.
- window->CloseNow();
- window2->CloseNow();
-}
-
-} // namespace
-} // namespace views
diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc
index c825998d914..b41e16cb1b9 100644
--- a/chromium/ui/views/widget/root_view.cc
+++ b/chromium/ui/views/widget/root_view.cc
@@ -8,22 +8,23 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
+#include "ui/views/drag_controller.h"
#include "ui/views/focus/view_storage.h"
#include "ui/views/layout/fill_layout.h"
+#include "ui/views/view_targeter.h"
#include "ui/views/views_switches.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
-#include "ui/views/widget/widget_deletion_observer.h"
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
+typedef ui::EventDispatchDetails DispatchDetails;
namespace views {
namespace internal {
@@ -51,6 +52,95 @@ class MouseEnterExitEvent : public ui::MouseEvent {
} // namespace
+// This event handler receives events in the pre-target phase and takes care of
+// the following:
+// - Shows keyboard-triggered context menus.
+class PreEventDispatchHandler : public ui::EventHandler {
+ public:
+ explicit PreEventDispatchHandler(View* owner)
+ : owner_(owner) {
+ }
+ virtual ~PreEventDispatchHandler() {}
+
+ private:
+ // ui::EventHandler:
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
+ CHECK_EQ(ui::EP_PRETARGET, event->phase());
+ if (event->handled())
+ return;
+
+ View* v = NULL;
+ if (owner_->GetFocusManager()) // Can be NULL in unittests.
+ v = owner_->GetFocusManager()->GetFocusedView();
+
+ // Special case to handle keyboard-triggered context menus.
+ if (v && v->enabled() && ((event->key_code() == ui::VKEY_APPS) ||
+ (event->key_code() == ui::VKEY_F10 && event->IsShiftDown()))) {
+ // Clamp the menu location within the visible bounds of each ancestor view
+ // to avoid showing the menu over a completely different view or window.
+ gfx::Point location = v->GetKeyboardContextMenuLocation();
+ for (View* parent = v->parent(); parent; parent = parent->parent()) {
+ const gfx::Rect& parent_bounds = parent->GetBoundsInScreen();
+ location.SetToMax(parent_bounds.origin());
+ location.SetToMin(parent_bounds.bottom_right());
+ }
+ v->ShowContextMenu(location, ui::MENU_SOURCE_KEYBOARD);
+ event->StopPropagation();
+ }
+ }
+
+ View* owner_;
+
+ DISALLOW_COPY_AND_ASSIGN(PreEventDispatchHandler);
+};
+
+// This event handler receives events in the post-target phase and takes care of
+// the following:
+// - Generates context menu, or initiates drag-and-drop, from gesture events.
+class PostEventDispatchHandler : public ui::EventHandler {
+ public:
+ PostEventDispatchHandler()
+ : touch_dnd_enabled_(::switches::IsTouchDragDropEnabled()) {
+ }
+ virtual ~PostEventDispatchHandler() {}
+
+ private:
+ // Overridden from ui::EventHandler:
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ DCHECK_EQ(ui::EP_POSTTARGET, event->phase());
+ if (event->handled())
+ return;
+
+ View* target = static_cast<View*>(event->target());
+ gfx::Point location = event->location();
+ if (touch_dnd_enabled_ &&
+ event->type() == ui::ET_GESTURE_LONG_PRESS &&
+ (!target->drag_controller() ||
+ target->drag_controller()->CanStartDragForView(
+ target, location, location))) {
+ if (target->DoDrag(*event, location,
+ ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH)) {
+ event->StopPropagation();
+ return;
+ }
+ }
+
+ if (target->context_menu_controller() &&
+ (event->type() == ui::ET_GESTURE_LONG_PRESS ||
+ event->type() == ui::ET_GESTURE_LONG_TAP ||
+ event->type() == ui::ET_GESTURE_TWO_FINGER_TAP)) {
+ gfx::Point screen_location(location);
+ View::ConvertPointToScreen(target, &screen_location);
+ target->ShowContextMenu(screen_location, ui::MENU_SOURCE_TOUCH);
+ event->StopPropagation();
+ }
+ }
+
+ bool touch_dnd_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler);
+};
+
// static
const char RootView::kViewClassName[] = "RootView";
@@ -68,13 +158,18 @@ RootView::RootView(Widget* widget)
last_mouse_event_flags_(0),
last_mouse_event_x_(-1),
last_mouse_event_y_(-1),
- touch_pressed_handler_(NULL),
gesture_handler_(NULL),
scroll_gesture_handler_(NULL),
+ pre_dispatch_handler_(new internal::PreEventDispatchHandler(this)),
+ post_dispatch_handler_(new internal::PostEventDispatchHandler),
focus_search_(this, false, false),
focus_traversable_parent_(NULL),
focus_traversable_parent_view_(NULL),
- event_dispatch_target_(NULL) {
+ event_dispatch_target_(NULL),
+ old_dispatch_target_(NULL) {
+ AddPreTargetHandler(pre_dispatch_handler_.get());
+ AddPostTargetHandler(post_dispatch_handler_.get());
+ SetEventTargeter(scoped_ptr<ui::EventTargeter>(new ViewTargeter()));
}
RootView::~RootView() {
@@ -111,232 +206,6 @@ void RootView::NotifyNativeViewHierarchyChanged() {
PropagateNativeViewHierarchyChanged();
}
-// Input -----------------------------------------------------------------------
-
-void RootView::DispatchKeyEvent(ui::KeyEvent* event) {
- View* v = NULL;
- if (GetFocusManager()) // NULL in unittests.
- v = GetFocusManager()->GetFocusedView();
- // Special case to handle right-click context menus triggered by the
- // keyboard.
- if (v && v->enabled() && ((event->key_code() == ui::VKEY_APPS) ||
- (event->key_code() == ui::VKEY_F10 && event->IsShiftDown()))) {
- // Showing the context menu outside the visible bounds may result in a
- // context menu appearing over a completely different window. Constrain
- // location to visible bounds so this doesn't happen.
- gfx::Rect visible_bounds(v->ConvertRectToWidget(v->GetVisibleBounds()));
- visible_bounds.Offset(
- widget_->GetClientAreaBoundsInScreen().OffsetFromOrigin());
- gfx::Rect keyboard_loc(v->GetKeyboardContextMenuLocation(),
- gfx::Size(1, 1));
- keyboard_loc.AdjustToFit(visible_bounds);
- v->ShowContextMenu(keyboard_loc.origin(), ui::MENU_SOURCE_KEYBOARD);
- event->StopPropagation();
- return;
- }
-
- DispatchKeyEventStartAt(v, event);
-}
-
-void RootView::DispatchScrollEvent(ui::ScrollEvent* event) {
- for (View* v = GetEventHandlerForPoint(event->location());
- v && v != this && !event->stopped_propagation(); v = v->parent()) {
- DispatchEventToTarget(v, event);
- }
-
- if (event->handled() || event->type() != ui::ET_SCROLL)
- return;
-
- // Convert unprocessed scroll events into mouse-wheel events.
- ui::MouseWheelEvent wheel(*event);
- if (OnMouseWheel(wheel))
- event->SetHandled();
-}
-
-void RootView::DispatchTouchEvent(ui::TouchEvent* event) {
- // TODO: this looks all wrong. On a TOUCH_PRESSED we should figure out the
- // view and target that view with all touches with the same id until the
- // release (or keep it if captured).
-
- // If touch_pressed_handler_ is non null, we are currently processing
- // a touch down on the screen situation. In that case we send the
- // event to touch_pressed_handler_
-
- if (touch_pressed_handler_) {
- ui::TouchEvent touch_event(*event, static_cast<View*>(this),
- touch_pressed_handler_);
- DispatchEventToTarget(touch_pressed_handler_, &touch_event);
- if (touch_event.handled())
- event->SetHandled();
- if (touch_event.stopped_propagation())
- event->StopPropagation();
- return;
- }
-
- // Walk up the tree until we find a view that wants the touch event.
- for (touch_pressed_handler_ = GetEventHandlerForPoint(event->location());
- touch_pressed_handler_ && (touch_pressed_handler_ != this);
- touch_pressed_handler_ = touch_pressed_handler_->parent()) {
- if (!touch_pressed_handler_->enabled()) {
- // Disabled views eat events but are treated as not handled.
- break;
- }
-
- // See if this view wants to handle the touch
- ui::TouchEvent touch_event(*event, static_cast<View*>(this),
- touch_pressed_handler_);
- DispatchEventToTarget(touch_pressed_handler_, &touch_event);
- if (touch_event.handled())
- event->SetHandled();
- if (touch_event.stopped_propagation())
- event->StopPropagation();
-
- // The view could have removed itself from the tree when handling
- // OnTouchEvent(). So handle as per OnMousePressed. NB: we
- // assume that the RootView itself cannot be so removed.
- if (!touch_pressed_handler_)
- break;
-
- // The touch event wasn't processed. Go up the view hierarchy and dispatch
- // the touch event.
- if (!event->handled())
- continue;
-
- // If a View consumed the event, that means future touch-events should go to
- // that View. If the event wasn't consumed, then reset the handler.
- if (!event->stopped_propagation())
- touch_pressed_handler_ = NULL;
-
- return;
- }
-
- // Reset touch_pressed_handler_ to indicate that no processing is occurring.
- touch_pressed_handler_ = NULL;
-
- return;
-}
-
-void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
- if (gesture_handler_) {
- // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during
- // processing.
- View* handler = scroll_gesture_handler_ &&
- (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ?
- scroll_gesture_handler_ : gesture_handler_;
- ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler);
- DispatchEventToTarget(handler, &handler_event);
-
- if (event->type() == ui::ET_GESTURE_END &&
- event->details().touch_points() <= 1) {
- // In case a drag was in progress, reset all the handlers. Otherwise, just
- // reset the gesture handler.
- if (gesture_handler_ == mouse_pressed_handler_)
- SetMouseHandler(NULL);
- else
- gesture_handler_ = NULL;
- }
-
- if (scroll_gesture_handler_ &&
- (event->type() == ui::ET_GESTURE_SCROLL_END ||
- event->type() == ui::ET_SCROLL_FLING_START)) {
- scroll_gesture_handler_ = NULL;
- }
-
- if (handler_event.stopped_propagation()) {
- event->StopPropagation();
- return;
- } else if (handler_event.handled()) {
- event->SetHandled();
- return;
- }
-
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN &&
- !scroll_gesture_handler_) {
- // Some view started processing gesture events, however it does not
- // process scroll-gesture events. In such case, we allow the event to
- // bubble up, and install a different scroll-gesture handler different
- // from the default gesture handler.
- for (scroll_gesture_handler_ = gesture_handler_->parent();
- scroll_gesture_handler_ && scroll_gesture_handler_ != this;
- scroll_gesture_handler_ = scroll_gesture_handler_->parent()) {
- ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
- scroll_gesture_handler_);
- DispatchEventToTarget(scroll_gesture_handler_, &gesture_event);
- if (gesture_event.stopped_propagation()) {
- event->StopPropagation();
- return;
- } else if (gesture_event.handled()) {
- event->SetHandled();
- return;
- }
- }
- scroll_gesture_handler_ = NULL;
- }
-
- return;
- }
-
- // If there was no handler for a SCROLL_BEGIN event, then subsequent scroll
- // events are not dispatched to any views.
- switch (event->type()) {
- case ui::ET_GESTURE_SCROLL_UPDATE:
- case ui::ET_GESTURE_SCROLL_END:
- case ui::ET_SCROLL_FLING_START:
- return;
- default:
- break;
- }
-
- View* gesture_handler = NULL;
- if (views::switches::IsRectBasedTargetingEnabled() &&
- !event->details().bounding_box().IsEmpty()) {
- // TODO(tdanderson): Pass in the bounding box to GetEventHandlerForRect()
- // once crbug.com/313392 is resolved.
- gfx::Rect touch_rect(event->details().bounding_box());
- touch_rect.set_origin(event->location());
- touch_rect.Offset(-touch_rect.width() / 2, -touch_rect.height() / 2);
- gesture_handler = GetEventHandlerForRect(touch_rect);
- } else {
- gesture_handler = GetEventHandlerForPoint(event->location());
- }
-
- // Walk up the tree until we find a view that wants the gesture event.
- for (gesture_handler_ = gesture_handler;
- gesture_handler_ && (gesture_handler_ != this);
- gesture_handler_ = gesture_handler_->parent()) {
- if (!gesture_handler_->enabled()) {
- // Disabled views eat events but are treated as not handled.
- return;
- }
-
- // See if this view wants to handle the Gesture.
- ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
- gesture_handler_);
- DispatchEventToTarget(gesture_handler_, &gesture_event);
-
- // The view could have removed itself from the tree when handling
- // OnGestureEvent(). So handle as per OnMousePressed. NB: we
- // assume that the RootView itself cannot be so removed.
- if (!gesture_handler_)
- return;
-
- if (gesture_event.handled()) {
- if (gesture_event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
- scroll_gesture_handler_ = gesture_handler_;
- if (gesture_event.stopped_propagation())
- event->StopPropagation();
- else
- event->SetHandled();
- return;
- }
-
- // The gesture event wasn't processed. Go up the view hierarchy and
- // dispatch the gesture event.
- }
-
- gesture_handler_ = NULL;
-}
-
// Focus -----------------------------------------------------------------------
void RootView::SetFocusTraversableParent(FocusTraversable* focus_traversable) {
@@ -374,6 +243,35 @@ View* RootView::GetFocusTraversableParentView() {
}
////////////////////////////////////////////////////////////////////////////////
+// RootView, ui::EventProcessor overrides:
+
+ui::EventTarget* RootView::GetRootTarget() {
+ return this;
+}
+
+ui::EventDispatchDetails RootView::OnEventFromSource(ui::Event* event) {
+ // TODO(tdanderson): Replace the calls to Dispatch*Event() with calls to
+ // EventProcessor::OnEventFromSource() once the code for
+ // that event type has been refactored, and then
+ // eventually remove this function altogether. See
+ // crbug.com/348083.
+ if (event->IsKeyEvent())
+ return EventProcessor::OnEventFromSource(event);
+ else if (event->IsScrollEvent())
+ return EventProcessor::OnEventFromSource(event);
+ else if (event->IsTouchEvent())
+ NOTREACHED() << "Touch events should not be sent to RootView.";
+ else if (event->IsGestureEvent())
+ DispatchGestureEvent(static_cast<ui::GestureEvent*>(event));
+ else if (event->IsMouseEvent())
+ NOTREACHED() << "Should not be called with a MouseEvent.";
+ else
+ NOTREACHED() << "Invalid event type.";
+
+ return DispatchDetails();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// RootView, View overrides:
const Widget* RootView::GetWidget() const {
@@ -419,7 +317,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) {
ui::MouseEvent mouse_pressed_event(event, static_cast<View*>(this),
mouse_pressed_handler_);
drag_info_.Reset();
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return true;
return true;
}
DCHECK(!explicit_mouse_handler_);
@@ -447,12 +348,10 @@ bool RootView::OnMousePressed(const ui::MouseEvent& event) {
mouse_pressed_event.set_flags(event.flags() & ~ui::EF_IS_DOUBLE_CLICK);
drag_info_.Reset();
- {
- WidgetDeletionObserver widget_deletion_observer(widget_);
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_pressed_event);
- if (!widget_deletion_observer.IsWidgetAlive())
- return mouse_pressed_event.handled();
- }
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_pressed_handler_, &mouse_pressed_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return mouse_pressed_event.handled();
// The view could have removed itself from the tree when handling
// OnMousePressed(). In this case, the removal notification will have
@@ -495,7 +394,10 @@ bool RootView::OnMouseDragged(const ui::MouseEvent& event) {
ui::MouseEvent mouse_event(event, static_cast<View*>(this),
mouse_pressed_handler_);
- DispatchEventToTarget(mouse_pressed_handler_, &mouse_event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_pressed_handler_, &mouse_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return false;
}
return false;
}
@@ -510,8 +412,10 @@ void RootView::OnMouseReleased(const ui::MouseEvent& event) {
// configure state such that we're done first, then call View.
View* mouse_pressed_handler = mouse_pressed_handler_;
SetMouseHandler(NULL);
- DispatchEventToTarget(mouse_pressed_handler, &mouse_released);
- // WARNING: we may have been deleted.
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_pressed_handler, &mouse_released);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
}
}
@@ -524,7 +428,8 @@ void RootView::OnMouseCaptureLost() {
gfx::Point last_point(last_mouse_event_x_, last_mouse_event_y_);
ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED,
last_point, last_point,
- last_mouse_event_flags_);
+ last_mouse_event_flags_,
+ 0);
UpdateCursor(release_event);
}
// We allow the view to delete us from OnMouseCaptureLost. As such,
@@ -554,7 +459,12 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
(!mouse_move_handler_->notify_enter_exit_on_child() ||
!mouse_move_handler_->Contains(v))) {
MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exit);
+ exit.ConvertLocationToTarget(static_cast<View*>(this),
+ mouse_move_handler_);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_move_handler_, &exit);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, v);
}
@@ -565,19 +475,28 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED);
entered.ConvertLocationToTarget(static_cast<View*>(this),
mouse_move_handler_);
- DispatchEventToTarget(mouse_move_handler_, &entered);
- NotifyEnterExitOfDescendant(entered, ui::ET_MOUSE_ENTERED, v,
- old_handler);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_move_handler_, &entered);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
+ NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_ENTERED,
+ mouse_move_handler_, old_handler);
}
}
ui::MouseEvent moved_event(event, static_cast<View*>(this),
mouse_move_handler_);
mouse_move_handler_->OnMouseMoved(moved_event);
+ // TODO(tdanderson): It may be possible to avoid setting the cursor twice
+ // (once here and once from CompoundEventFilter) on a
+ // mousemove. See crbug.com/351469.
if (!(moved_event.flags() & ui::EF_IS_NON_CLIENT))
widget_->SetCursor(mouse_move_handler_->GetCursor(moved_event));
} else if (mouse_move_handler_ != NULL) {
MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exited);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_move_handler_, &exited);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, v);
// On Aura the non-client area extends slightly outside the root view for
@@ -592,7 +511,10 @@ void RootView::OnMouseMoved(const ui::MouseEvent& event) {
void RootView::OnMouseExited(const ui::MouseEvent& event) {
if (mouse_move_handler_ != NULL) {
MouseEnterExitEvent exited(event, ui::ET_MOUSE_EXITED);
- DispatchEventToTarget(mouse_move_handler_, &exited);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(mouse_move_handler_, &exited);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
NotifyEnterExitOfDescendant(event, ui::ET_MOUSE_EXITED,
mouse_move_handler_, NULL);
mouse_move_handler_ = NULL;
@@ -601,8 +523,14 @@ void RootView::OnMouseExited(const ui::MouseEvent& event) {
bool RootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
for (View* v = GetEventHandlerForPoint(event.location());
- v && v != this && !event.handled(); v = v->parent())
- DispatchEventToTarget(v, const_cast<ui::MouseWheelEvent*>(&event));
+ v && v != this && !event.handled(); v = v->parent()) {
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(v, const_cast<ui::MouseWheelEvent*>(&event));
+ if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
+ return event.handled();
+ }
+ }
return event.handled();
}
@@ -615,7 +543,7 @@ void RootView::SetMouseHandler(View* new_mh) {
drag_info_.Reset();
}
-void RootView::GetAccessibleState(ui::AccessibleViewState* state) {
+void RootView::GetAccessibleState(ui::AXViewState* state) {
state->name = widget_->widget_delegate()->GetAccessibleWindowTitle();
state->role = widget_->widget_delegate()->GetAccessibleWindowRole();
}
@@ -628,6 +556,142 @@ void RootView::UpdateParentLayer() {
////////////////////////////////////////////////////////////////////////////////
// RootView, protected:
+void RootView::DispatchGestureEvent(ui::GestureEvent* event) {
+ if (gesture_handler_) {
+ // |gesture_handler_| (or |scroll_gesture_handler_|) can be deleted during
+ // processing.
+ View* handler = scroll_gesture_handler_ &&
+ (event->IsScrollGestureEvent() || event->IsFlingScrollEvent()) ?
+ scroll_gesture_handler_ : gesture_handler_;
+ ui::GestureEvent handler_event(*event, static_cast<View*>(this), handler);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(handler, &handler_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
+
+ if (event->type() == ui::ET_GESTURE_END &&
+ event->details().touch_points() <= 1) {
+ // In case a drag was in progress, reset all the handlers. Otherwise, just
+ // reset the gesture handler.
+ if (gesture_handler_ == mouse_pressed_handler_)
+ SetMouseHandler(NULL);
+ else
+ gesture_handler_ = NULL;
+ }
+
+ if (scroll_gesture_handler_ &&
+ (event->type() == ui::ET_GESTURE_SCROLL_END ||
+ event->type() == ui::ET_SCROLL_FLING_START)) {
+ scroll_gesture_handler_ = NULL;
+ }
+
+ if (handler_event.stopped_propagation()) {
+ event->StopPropagation();
+ return;
+ } else if (handler_event.handled()) {
+ event->SetHandled();
+ return;
+ }
+
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN &&
+ !scroll_gesture_handler_) {
+ // Some view started processing gesture events, however it does not
+ // process scroll-gesture events. In such case, we allow the event to
+ // bubble up, and install a different scroll-gesture handler different
+ // from the default gesture handler.
+ for (scroll_gesture_handler_ = gesture_handler_->parent();
+ scroll_gesture_handler_ && scroll_gesture_handler_ != this;
+ scroll_gesture_handler_ = scroll_gesture_handler_->parent()) {
+ ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
+ scroll_gesture_handler_);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(scroll_gesture_handler_, &gesture_event);
+ if (gesture_event.stopped_propagation()) {
+ event->StopPropagation();
+ return;
+ } else if (gesture_event.handled()) {
+ event->SetHandled();
+ return;
+ } else if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
+ return;
+ }
+ }
+ scroll_gesture_handler_ = NULL;
+ }
+
+ return;
+ }
+
+ // If there was no handler for a SCROLL_BEGIN event, then subsequent scroll
+ // events are not dispatched to any views.
+ switch (event->type()) {
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ case ui::ET_GESTURE_SCROLL_END:
+ case ui::ET_SCROLL_FLING_START:
+ return;
+ default:
+ break;
+ }
+
+ View* gesture_handler = NULL;
+ if (views::switches::IsRectBasedTargetingEnabled() &&
+ !event->details().bounding_box().IsEmpty()) {
+ // TODO(tdanderson): Pass in the bounding box to GetEventHandlerForRect()
+ // once crbug.com/313392 is resolved.
+ gfx::Rect touch_rect(event->details().bounding_box());
+ touch_rect.set_origin(event->location());
+ touch_rect.Offset(-touch_rect.width() / 2, -touch_rect.height() / 2);
+ gesture_handler = GetEventHandlerForRect(touch_rect);
+ } else {
+ gesture_handler = GetEventHandlerForPoint(event->location());
+ }
+
+ // Walk up the tree until we find a view that wants the gesture event.
+ for (gesture_handler_ = gesture_handler;
+ gesture_handler_ && (gesture_handler_ != this);
+ gesture_handler_ = gesture_handler_->parent()) {
+ if (!gesture_handler_->enabled()) {
+ // Disabled views eat events but are treated as not handled.
+ return;
+ }
+
+ // See if this view wants to handle the Gesture.
+ ui::GestureEvent gesture_event(*event, static_cast<View*>(this),
+ gesture_handler_);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchEvent(gesture_handler_, &gesture_event);
+ if (dispatch_details.dispatcher_destroyed)
+ return;
+
+ // The view could have removed itself from the tree when handling
+ // OnGestureEvent(). So handle as per OnMousePressed. NB: we
+ // assume that the RootView itself cannot be so removed.
+ if (!gesture_handler_)
+ return;
+
+ if (gesture_event.handled()) {
+ if (gesture_event.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ scroll_gesture_handler_ = gesture_handler_;
+ if (gesture_event.stopped_propagation())
+ event->StopPropagation();
+ else
+ event->SetHandled();
+ // Last ui::ET_GESTURE_END should not set the gesture_handler_.
+ if (gesture_event.type() == ui::ET_GESTURE_END &&
+ event->details().touch_points() <= 1) {
+ gesture_handler_ = NULL;
+ }
+ return;
+ }
+
+ // The gesture event wasn't processed. Go up the view hierarchy and
+ // dispatch the gesture event.
+ }
+
+ gesture_handler_ = NULL;
+}
+
void RootView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
widget_->ViewHierarchyChanged(details);
@@ -637,14 +701,14 @@ void RootView::ViewHierarchyChanged(
mouse_pressed_handler_ = NULL;
if (mouse_move_handler_ == details.child)
mouse_move_handler_ = NULL;
- if (touch_pressed_handler_ == details.child)
- touch_pressed_handler_ = NULL;
if (gesture_handler_ == details.child)
gesture_handler_ = NULL;
if (scroll_gesture_handler_ == details.child)
scroll_gesture_handler_ = NULL;
if (event_dispatch_target_ == details.child)
event_dispatch_target_ = NULL;
+ if (old_dispatch_target_ == details.child)
+ old_dispatch_target_ = NULL;
}
}
@@ -656,10 +720,10 @@ void RootView::VisibilityChanged(View* /*starting_from*/, bool is_visible) {
explicit_mouse_handler_ = false;
mouse_pressed_handler_ = NULL;
mouse_move_handler_ = NULL;
- touch_pressed_handler_ = NULL;
gesture_handler_ = NULL;
scroll_gesture_handler_ = NULL;
event_dispatch_target_ = NULL;
+ old_dispatch_target_ = NULL;
}
}
@@ -701,14 +765,6 @@ void RootView::SetMouseLocationAndFlags(const ui::MouseEvent& event) {
last_mouse_event_y_ = event.y();
}
-void RootView::DispatchEventToTarget(View* target, ui::Event* event) {
- View* old_target = event_dispatch_target_;
- event_dispatch_target_ = target;
- ui::EventDispatchDetails details = DispatchEvent(target, event);
- if (!details.dispatcher_destroyed)
- event_dispatch_target_ = old_target;
-}
-
void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
ui::EventType type,
View* view,
@@ -722,20 +778,11 @@ void RootView::NotifyEnterExitOfDescendant(const ui::MouseEvent& event,
// of the callbacks can mark the event as handled, and that would cause
// incorrect event dispatch.
MouseEnterExitEvent notify_event(event, type);
- DispatchEventToTarget(p, &notify_event);
- }
-}
-
-
-void RootView::DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) {
- if (event->handled() || !view)
- return;
-
- for (; view && view != this; view = view->parent()) {
- DispatchEventToTarget(view, event);
- // Do this check here rather than in the if as |view| may have been deleted.
- if (event->handled())
+ ui::EventDispatchDetails dispatch_details = DispatchEvent(p, &notify_event);
+ if (dispatch_details.dispatcher_destroyed ||
+ dispatch_details.target_destroyed) {
return;
+ }
}
}
@@ -743,5 +790,28 @@ bool RootView::CanDispatchToTarget(ui::EventTarget* target) {
return event_dispatch_target_ == target;
}
+ui::EventDispatchDetails RootView::PreDispatchEvent(ui::EventTarget* target,
+ ui::Event* event) {
+ old_dispatch_target_ = event_dispatch_target_;
+ event_dispatch_target_ = static_cast<View*>(target);
+ return DispatchDetails();
+}
+
+ui::EventDispatchDetails RootView::PostDispatchEvent(ui::EventTarget* target,
+ const ui::Event& event) {
+ DispatchDetails details;
+ if (target != event_dispatch_target_)
+ details.target_destroyed = true;
+
+ event_dispatch_target_ = old_dispatch_target_;
+ old_dispatch_target_ = NULL;
+
+#ifndef NDEBUG
+ DCHECK(!event_dispatch_target_ || Contains(event_dispatch_target_));
+#endif
+
+ return details;
+}
+
} // namespace internal
} // namespace views
diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h
index 6ab367bd992..75788234b9b 100644
--- a/chromium/ui/views/widget/root_view.h
+++ b/chromium/ui/views/widget/root_view.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "ui/events/event_dispatcher.h"
+#include "ui/events/event_processor.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/focus/focus_search.h"
#include "ui/views/view.h"
@@ -16,7 +16,6 @@
namespace views {
namespace test {
-class RootViewTestHelper;
class WidgetTest;
}
@@ -25,6 +24,7 @@ class Widget;
// This is a views-internal API and should not be used externally.
// Widget exposes this object as a View*.
namespace internal {
+class PreEventDispatchHandler;
////////////////////////////////////////////////////////////////////////////////
// RootView class
@@ -45,7 +45,7 @@ namespace internal {
//
class VIEWS_EXPORT RootView : public View,
public FocusTraversable,
- public ui::EventDispatcherDelegate {
+ public ui::EventProcessor {
public:
static const char kViewClassName[];
@@ -63,16 +63,6 @@ class VIEWS_EXPORT RootView : public View,
// Called when parent of the host changed.
void NotifyNativeViewHierarchyChanged();
- // Input ---------------------------------------------------------------------
-
- // Process a key event. Send the event to the focused view and up the focus
- // path, and finally to the default keyboard handler, until someone consumes
- // it. Returns whether anyone consumed the event.
- void DispatchKeyEvent(ui::KeyEvent* event);
- void DispatchScrollEvent(ui::ScrollEvent* event);
- void DispatchTouchEvent(ui::TouchEvent* event);
- virtual void DispatchGestureEvent(ui::GestureEvent* event);
-
// Focus ---------------------------------------------------------------------
// Used to set the FocusTraversable parent after the view has been created
@@ -97,6 +87,10 @@ class VIEWS_EXPORT RootView : public View,
virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE;
virtual View* GetFocusTraversableParentView() OVERRIDE;
+ // Overridden from ui::EventProcessor:
+ virtual ui::EventTarget* GetRootTarget() OVERRIDE;
+ virtual ui::EventDispatchDetails OnEventFromSource(ui::Event* event) OVERRIDE;
+
// Overridden from View:
virtual const Widget* GetWidget() const OVERRIDE;
virtual Widget* GetWidget() OVERRIDE;
@@ -112,10 +106,15 @@ class VIEWS_EXPORT RootView : public View,
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE;
virtual void SetMouseHandler(View* new_mouse_handler) OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual void UpdateParentLayer() OVERRIDE;
protected:
+ // TODO(tdanderson): Remove RootView::DispatchGestureEvent() once
+ // its targeting and dispatch logic has been moved
+ // elsewhere. See crbug.com/348083.
+ virtual void DispatchGestureEvent(ui::GestureEvent* event);
+
// Overridden from View:
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
@@ -128,7 +127,6 @@ class VIEWS_EXPORT RootView : public View,
private:
friend class ::views::View;
friend class ::views::Widget;
- friend class ::views::test::RootViewTestHelper;
friend class ::views::test::WidgetTest;
// Input ---------------------------------------------------------------------
@@ -145,8 +143,6 @@ class VIEWS_EXPORT RootView : public View,
// be applied to the point prior to calling this).
void SetMouseLocationAndFlags(const ui::MouseEvent& event);
- void DispatchEventToTarget(View* target, ui::Event* event);
-
// |view| is the view receiving |event|. This function sends the event to all
// the Views up the hierarchy that has |notify_enter_exit_on_child_| flag
// turned on, but does not contain |sibling|.
@@ -155,15 +151,14 @@ class VIEWS_EXPORT RootView : public View,
View* view,
View* sibling);
- // Dispatches the KeyEvent to |view| and ancestors until the event is
- // handled.
- void DispatchKeyEventStartAt(View* view, ui::KeyEvent* event);
-
// Overridden from ui::EventDispatcherDelegate:
virtual bool CanDispatchToTarget(ui::EventTarget* target) OVERRIDE;
+ virtual ui::EventDispatchDetails PreDispatchEvent(ui::EventTarget* target,
+ ui::Event* event) OVERRIDE;
+ virtual ui::EventDispatchDetails PostDispatchEvent(
+ ui::EventTarget* target, const ui::Event& event) OVERRIDE;
//////////////////////////////////////////////////////////////////////////////
-
// Tree operations -----------------------------------------------------------
// The host Widget
@@ -190,9 +185,6 @@ class VIEWS_EXPORT RootView : public View,
int last_mouse_event_x_;
int last_mouse_event_y_;
- // The view currently handling touch events.
- View* touch_pressed_handler_;
-
// The view currently handling gesture events. When set, this handler receives
// all gesture events, except when there is an event handler for the specific
// gesture (e.g. scroll).
@@ -201,6 +193,9 @@ class VIEWS_EXPORT RootView : public View,
// The view currently handling scroll gesture events.
View* scroll_gesture_handler_;
+ scoped_ptr<internal::PreEventDispatchHandler> pre_dispatch_handler_;
+ scoped_ptr<internal::PostEventDispatchHandler> post_dispatch_handler_;
+
// Focus ---------------------------------------------------------------------
// The focus search algorithm.
@@ -217,6 +212,7 @@ class VIEWS_EXPORT RootView : public View,
View* focus_traversable_parent_view_;
View* event_dispatch_target_;
+ View* old_dispatch_target_;
// Drag and drop -------------------------------------------------------------
diff --git a/chromium/ui/views/widget/root_view_test_helper.h b/chromium/ui/views/widget/root_view_test_helper.h
deleted file mode 100644
index a26396730b2..00000000000
--- a/chromium/ui/views/widget/root_view_test_helper.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_
-#define UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_
-
-#include "ui/views/widget/root_view.h"
-
-namespace views {
-namespace test {
-
-class RootViewTestHelper {
- public:
- explicit RootViewTestHelper(internal::RootView* root_view)
- : root_view_(root_view) {
- }
- ~RootViewTestHelper() {}
-
- void DispatchKeyEventStartAt(View* view, ui::KeyEvent* event) {
- root_view_->DispatchKeyEventStartAt(view, event);
- }
-
- private:
- internal::RootView* root_view_;
-
- DISALLOW_COPY_AND_ASSIGN(RootViewTestHelper);
-};
-
-} // namespace test
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_ROOT_VIEW_TEST_HELPER_H_
diff --git a/chromium/ui/views/widget/root_view_unittest.cc b/chromium/ui/views/widget/root_view_unittest.cc
index ebe20d65346..9def7726fdd 100644
--- a/chromium/ui/views/widget/root_view_unittest.cc
+++ b/chromium/ui/views/widget/root_view_unittest.cc
@@ -2,8 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/widget/root_view.h"
+
+#include "ui/events/event_targeter.h"
+#include "ui/views/context_menu_controller.h"
#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/root_view_test_helper.h"
+#include "ui/views/view_targeter.h"
+#include "ui/views/widget/root_view.h"
namespace views {
namespace test {
@@ -28,7 +33,8 @@ class DeleteOnKeyEventView : public View {
DISALLOW_COPY_AND_ASSIGN(DeleteOnKeyEventView);
};
-// Verifies deleting a View in OnKeyPressed() doesn't crash.
+// Verifies deleting a View in OnKeyPressed() doesn't crash and that the
+// target is marked as destroyed in the returned EventDispatchDetails.
TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) {
Widget widget;
Widget::InitParams init_params =
@@ -44,12 +50,194 @@ TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) {
View* child = new DeleteOnKeyEventView(&got_key_event);
content->AddChildView(child);
+ // Give focus to |child| so that it will be the target of the key event.
+ child->SetFocusable(true);
+ child->RequestFocus();
+
+ ui::EventTargeter* targeter = new ViewTargeter();
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+ root_view->SetEventTargeter(make_scoped_ptr(targeter));
+
ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0, false);
- RootViewTestHelper test_helper(
- static_cast<internal::RootView*>(widget.GetRootView()));
- test_helper.DispatchKeyEventStartAt(child, &key_event);
+ ui::EventDispatchDetails details = root_view->OnEventFromSource(&key_event);
+ EXPECT_TRUE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(got_key_event);
}
+// Tracks whether a context menu is shown.
+class TestContextMenuController : public ContextMenuController {
+ public:
+ TestContextMenuController()
+ : show_context_menu_calls_(0),
+ menu_source_view_(NULL),
+ menu_source_type_(ui::MENU_SOURCE_NONE) {
+ }
+ virtual ~TestContextMenuController() {}
+
+ int show_context_menu_calls() const { return show_context_menu_calls_; }
+ View* menu_source_view() const { return menu_source_view_; }
+ ui::MenuSourceType menu_source_type() const { return menu_source_type_; }
+
+ void Reset() {
+ show_context_menu_calls_ = 0;
+ menu_source_view_ = NULL;
+ menu_source_type_ = ui::MENU_SOURCE_NONE;
+ }
+
+ // ContextMenuController:
+ virtual void ShowContextMenuForView(
+ View* source,
+ const gfx::Point& point,
+ ui::MenuSourceType source_type) OVERRIDE {
+ show_context_menu_calls_++;
+ menu_source_view_ = source;
+ menu_source_type_ = source_type;
+ }
+
+ private:
+ int show_context_menu_calls_;
+ View* menu_source_view_;
+ ui::MenuSourceType menu_source_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
+};
+
+// Tests that context menus are shown for certain key events (Shift+F10
+// and VKEY_APPS) by the pre-target handler installed on RootView.
+TEST_F(RootViewTest, ContextMenuFromKeyEvent) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(init_params);
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+
+ TestContextMenuController controller;
+ View* focused_view = new View;
+ focused_view->set_context_menu_controller(&controller);
+ widget.SetContentsView(focused_view);
+ focused_view->SetFocusable(true);
+ focused_view->RequestFocus();
+
+ // No context menu should be shown for a keypress of 'A'.
+ ui::KeyEvent nomenu_key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
+ ui::EventDispatchDetails details =
+ root_view->OnEventFromSource(&nomenu_key_event);
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_EQ(0, controller.show_context_menu_calls());
+ EXPECT_EQ(NULL, controller.menu_source_view());
+ EXPECT_EQ(ui::MENU_SOURCE_NONE, controller.menu_source_type());
+ controller.Reset();
+
+ // A context menu should be shown for a keypress of Shift+F10.
+ ui::KeyEvent menu_key_event(
+ ui::ET_KEY_PRESSED, ui::VKEY_F10, ui::EF_SHIFT_DOWN, false);
+ details = root_view->OnEventFromSource(&menu_key_event);
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_EQ(1, controller.show_context_menu_calls());
+ EXPECT_EQ(focused_view, controller.menu_source_view());
+ EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
+ controller.Reset();
+
+ // A context menu should be shown for a keypress of VKEY_APPS.
+ ui::KeyEvent menu_key_event2(ui::ET_KEY_PRESSED, ui::VKEY_APPS, 0, false);
+ details = root_view->OnEventFromSource(&menu_key_event2);
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_EQ(1, controller.show_context_menu_calls());
+ EXPECT_EQ(focused_view, controller.menu_source_view());
+ EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
+ controller.Reset();
+}
+
+// View which handles all gesture events.
+class GestureHandlingView : public View {
+ public:
+ GestureHandlingView() {
+ }
+
+ virtual ~GestureHandlingView() {
+ }
+
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ event->SetHandled();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GestureHandlingView);
+};
+
+// Tests that context menus are shown for long press by the post-target handler
+// installed on the RootView only if the event is targetted at a view which can
+// show a context menu.
+TEST_F(RootViewTest, ContextMenuFromLongPress) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.bounds = gfx::Rect(100,100);
+ widget.Init(init_params);
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget.GetRootView());
+
+ // Create a view capable of showing the context menu with two children one of
+ // which handles all gesture events (e.g. a button).
+ TestContextMenuController controller;
+ View* parent_view = new View;
+ parent_view->set_context_menu_controller(&controller);
+ widget.SetContentsView(parent_view);
+
+ View* gesture_handling_child_view = new GestureHandlingView;
+ gesture_handling_child_view->SetBoundsRect(gfx::Rect(10,10));
+ parent_view->AddChildView(gesture_handling_child_view);
+
+ View* other_child_view = new View;
+ other_child_view->SetBoundsRect(gfx::Rect(20, 0, 10,10));
+ parent_view->AddChildView(other_child_view);
+
+ // |parent_view| should not show a context menu as a result of a long press on
+ // |gesture_handling_child_view|.
+ ui::GestureEvent begin1(ui::ET_GESTURE_BEGIN, 5, 5, 0, base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1);
+ ui::EventDispatchDetails details = root_view->OnEventFromSource(&begin1);
+
+ ui::GestureEvent long_press1(ui::ET_GESTURE_LONG_PRESS, 5, 5, 0,
+ base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 0, 0), 1);
+ details = root_view->OnEventFromSource(&long_press1);
+
+ ui::GestureEvent end1(ui::ET_GESTURE_END, 5, 5, 0, base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
+ details = root_view->OnEventFromSource(&end1);
+
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_EQ(0, controller.show_context_menu_calls());
+
+ // |parent_view| should show a context menu as a result of a long press on
+ // |other_child_view|.
+ ui::GestureEvent begin2(ui::ET_GESTURE_BEGIN, 25, 5, 0, base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1);
+ details = root_view->OnEventFromSource(&begin2);
+
+ ui::GestureEvent long_press2(ui::ET_GESTURE_LONG_PRESS, 25, 5, 0,
+ base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 0, 0), 1);
+ details = root_view->OnEventFromSource(&long_press2);
+
+ ui::GestureEvent end2(ui::ET_GESTURE_END, 25, 5, 0, base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
+ details = root_view->OnEventFromSource(&end2);
+
+ EXPECT_FALSE(details.target_destroyed);
+ EXPECT_FALSE(details.dispatcher_destroyed);
+ EXPECT_EQ(1, controller.show_context_menu_calls());
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/tooltip_manager_aura.cc b/chromium/ui/views/widget/tooltip_manager_aura.cc
index 173597939c9..99ae9e6be57 100644
--- a/chromium/ui/views/widget/tooltip_manager_aura.cc
+++ b/chromium/ui/views/widget/tooltip_manager_aura.cc
@@ -6,12 +6,13 @@
#include "base/logging.h"
#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
-#include "ui/aura/root_window.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/public/tooltip_client.h"
namespace views {
@@ -49,7 +50,7 @@ void TooltipManagerAura::UpdateTooltipManagerForCapture(Widget* source) {
return;
gfx::Point screen_loc(
- root_window->GetDispatcher()->GetLastMouseLocationInRoot());
+ root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(root_window);
if (!screen_position_client)
@@ -91,7 +92,7 @@ void TooltipManagerAura::UpdateTooltip() {
aura::Window* root_window = GetWindow()->GetRootWindow();
if (aura::client::GetTooltipClient(root_window)) {
gfx::Point view_point =
- root_window->GetDispatcher()->GetLastMouseLocationInRoot();
+ root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot();
aura::Window::ConvertPointToTarget(root_window, GetWindow(), &view_point);
View* view = GetViewUnderPoint(view_point);
UpdateTooltipForTarget(view, view_point, root_window);
@@ -102,7 +103,7 @@ void TooltipManagerAura::TooltipTextChanged(View* view) {
aura::Window* root_window = GetWindow()->GetRootWindow();
if (aura::client::GetTooltipClient(root_window)) {
gfx::Point view_point =
- root_window->GetDispatcher()->GetLastMouseLocationInRoot();
+ root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot();
aura::Window::ConvertPointToTarget(root_window, GetWindow(), &view_point);
View* target = GetViewUnderPoint(view_point);
if (target != view)
@@ -124,7 +125,7 @@ void TooltipManagerAura::UpdateTooltipForTarget(View* target,
if (target) {
gfx::Point view_point = point;
View::ConvertPointFromWidget(target, &view_point);
- string16 new_tooltip_text;
+ base::string16 new_tooltip_text;
if (!target->GetTooltipText(view_point, &new_tooltip_text))
tooltip_text_.clear();
else
@@ -132,6 +133,9 @@ void TooltipManagerAura::UpdateTooltipForTarget(View* target,
} else {
tooltip_text_.clear();
}
+
+ aura::client::SetTooltipId(GetWindow(), target);
+
aura::client::GetTooltipClient(root_window)->UpdateTooltip(GetWindow());
}
diff --git a/chromium/ui/views/widget/tooltip_manager_aura.h b/chromium/ui/views/widget/tooltip_manager_aura.h
index ed69c6d79b9..e723299060b 100644
--- a/chromium/ui/views/widget/tooltip_manager_aura.h
+++ b/chromium/ui/views/widget/tooltip_manager_aura.h
@@ -52,7 +52,7 @@ class TooltipManagerAura : public TooltipManager {
aura::Window* GetWindow();
Widget* widget_;
- string16 tooltip_text_;
+ base::string16 tooltip_text_;
DISALLOW_COPY_AND_ASSIGN(TooltipManagerAura);
};
diff --git a/chromium/ui/views/widget/tooltip_manager_win.cc b/chromium/ui/views/widget/tooltip_manager_win.cc
deleted file mode 100644
index f9965f9cc37..00000000000
--- a/chromium/ui/views/widget/tooltip_manager_win.cc
+++ /dev/null
@@ -1,357 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/tooltip_manager_win.h"
-
-#include <windowsx.h>
-
-#include <limits>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/i18n/rtl.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/win/scoped_hdc.h"
-#include "base/win/scoped_select_object.h"
-#include "ui/base/l10n/l10n_util_win.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/text_elider.h"
-#include "ui/gfx/text_utils.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/gfx/win/scoped_set_map_mode.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/monitor_win.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-namespace {
-
-static int tooltip_height_ = 0;
-
-// Maximum number of lines we allow in the tooltip.
-const size_t kMaxLines = 6;
-
-// Trims the tooltip to fit, setting |text| to the clipped result, |max_width|
-// to the width (in pixels) of the clipped text and |line_count| to the number
-// of lines of text in the tooltip. |available_width| gives the space available
-// for the tooltip.
-void TrimTooltipToFit(const gfx::FontList& font_list,
- int available_width,
- base::string16* text,
- int* max_width,
- int* line_count) {
- *max_width = 0;
- *line_count = 0;
-
- TooltipManager::TrimTooltipText(text);
-
- // Split the string into at most kMaxLines lines.
- std::vector<base::string16> lines;
- base::SplitString(*text, '\n', &lines);
- if (lines.size() > kMaxLines)
- lines.resize(kMaxLines);
- *line_count = static_cast<int>(lines.size());
-
- // Format each line to fit.
- base::string16 result;
- for (std::vector<base::string16>::iterator i = lines.begin();
- i != lines.end(); ++i) {
- base::string16 elided_text =
- gfx::ElideText(*i, font_list, available_width, gfx::ELIDE_AT_END);
- *max_width = std::max(*max_width,
- gfx::GetStringWidth(elided_text, font_list));
- if (!result.empty())
- result.push_back('\n');
- result.append(elided_text);
- }
- *text = result;
-}
-
-} // namespace
-
-// static
-int TooltipManager::GetTooltipHeight() {
- DCHECK_GT(tooltip_height_, 0);
- return tooltip_height_;
-}
-
-static gfx::Font DetermineDefaultFont() {
- HWND window = CreateWindowEx(
- WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(),
- TOOLTIPS_CLASS, NULL, 0 , 0, 0, 0, 0, NULL, NULL, NULL, NULL);
- if (!window)
- return gfx::Font();
- HFONT hfont = reinterpret_cast<HFONT>(SendMessage(window, WM_GETFONT, 0, 0));
- gfx::Font font = hfont ? gfx::Font(hfont) : gfx::Font();
- DestroyWindow(window);
- return font;
-}
-
-TooltipManagerWin::TooltipManagerWin(Widget* widget)
- : widget_(widget),
- tooltip_hwnd_(NULL),
- last_mouse_pos_(-1, -1),
- tooltip_showing_(false),
- last_tooltip_view_(NULL),
- last_view_out_of_sync_(false),
- tooltip_width_(0) {
- DCHECK(widget);
- DCHECK(widget->GetNativeView());
-}
-
-TooltipManagerWin::~TooltipManagerWin() {
- if (tooltip_hwnd_)
- DestroyWindow(tooltip_hwnd_);
-}
-
-bool TooltipManagerWin::Init() {
- DCHECK(!tooltip_hwnd_);
- // Create the tooltip control.
- tooltip_hwnd_ = CreateWindowEx(
- WS_EX_TRANSPARENT | l10n_util::GetExtendedTooltipStyles(),
- TOOLTIPS_CLASS, NULL, TTS_NOPREFIX, 0, 0, 0, 0,
- GetParent(), NULL, NULL, NULL);
- if (!tooltip_hwnd_)
- return false;
-
- l10n_util::AdjustUIFontForWindow(tooltip_hwnd_);
-
- // This effectively turns off clipping of tooltips. We need this otherwise
- // multi-line text (\r\n) won't work right. The size doesn't really matter
- // (just as long as its bigger than the monitor's width) as we clip to the
- // screen size before rendering.
- SendMessage(tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0,
- std::numeric_limits<int16>::max());
-
- // Add one tool that is used for all tooltips.
- toolinfo_.cbSize = sizeof(toolinfo_);
- toolinfo_.uFlags = TTF_TRANSPARENT | TTF_IDISHWND;
- toolinfo_.hwnd = GetParent();
- toolinfo_.uId = reinterpret_cast<UINT_PTR>(GetParent());
- // Setting this tells windows to call GetParent() back (using a WM_NOTIFY
- // message) for the actual tooltip contents.
- toolinfo_.lpszText = LPSTR_TEXTCALLBACK;
- toolinfo_.lpReserved = NULL;
- SetRectEmpty(&toolinfo_.rect);
- SendMessage(tooltip_hwnd_, TTM_ADDTOOL, 0, (LPARAM)&toolinfo_);
- return true;
-}
-
-gfx::NativeView TooltipManagerWin::GetParent() {
- return widget_->GetNativeView();
-}
-
-const gfx::FontList& TooltipManagerWin::GetFontList() const {
- static gfx::FontList* font_list = NULL;
- if (!font_list)
- font_list = new gfx::FontList(DetermineDefaultFont());
- return *font_list;
-}
-
-void TooltipManagerWin::UpdateTooltip() {
- // Set last_view_out_of_sync_ to indicate the view is currently out of sync.
- // This doesn't update the view under the mouse immediately as it may cause
- // timing problems.
- last_view_out_of_sync_ = true;
- last_tooltip_view_ = NULL;
- // Hide the tooltip.
- SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
-}
-
-void TooltipManagerWin::TooltipTextChanged(View* view) {
- if (view == last_tooltip_view_)
- UpdateTooltip(last_mouse_pos_);
-}
-
-LRESULT TooltipManagerWin::OnNotify(int w_param,
- NMHDR* l_param,
- bool* handled) {
- *handled = false;
- if (l_param->hwndFrom != tooltip_hwnd_)
- return 0;
-
- switch (l_param->code) {
- case TTN_GETDISPINFO: {
- if (last_view_out_of_sync_) {
- // View under the mouse is out of sync, determine it now.
- View* root_view = widget_->GetRootView();
- last_tooltip_view_ =
- root_view->GetTooltipHandlerForPoint(last_mouse_pos_);
- last_view_out_of_sync_ = false;
- }
- // Tooltip control is asking for the tooltip to display.
- NMTTDISPINFOW* tooltip_info =
- reinterpret_cast<NMTTDISPINFOW*>(l_param);
- // Initialize the string, if we have a valid tooltip the string will
- // get reset below.
- tooltip_info->szText[0] = TEXT('\0');
- tooltip_text_.clear();
- tooltip_info->lpszText = NULL;
- clipped_text_.clear();
- if (last_tooltip_view_ != NULL) {
- tooltip_text_.clear();
- // Mouse is over a View, ask the View for its tooltip.
- gfx::Point view_loc = last_mouse_pos_;
- View::ConvertPointToTarget(widget_->GetRootView(),
- last_tooltip_view_, &view_loc);
- if (last_tooltip_view_->GetTooltipText(view_loc, &tooltip_text_) &&
- !tooltip_text_.empty()) {
- // View has a valid tip, copy it into TOOLTIPINFO.
- clipped_text_ = tooltip_text_;
- gfx::Point screen_loc = last_mouse_pos_;
- View::ConvertPointToScreen(widget_->GetRootView(), &screen_loc);
- TrimTooltipToFit(
- GetFontList(),
- GetMaxWidth(screen_loc.x(), screen_loc.y(),
- widget_->GetNativeView()),
- &clipped_text_, &tooltip_width_, &line_count_);
- // Adjust the clipped tooltip text for locale direction.
- base::i18n::AdjustStringForLocaleDirection(&clipped_text_);
- tooltip_info->lpszText = const_cast<WCHAR*>(clipped_text_.c_str());
- } else {
- tooltip_text_.clear();
- }
- }
- *handled = true;
- return 0;
- }
- case TTN_POP:
- tooltip_showing_ = false;
- *handled = true;
- return 0;
- case TTN_SHOW: {
- *handled = true;
- tooltip_showing_ = true;
- // The tooltip is about to show, allow the view to position it
- gfx::Point text_origin;
- if (tooltip_height_ == 0)
- tooltip_height_ = CalcTooltipHeight();
- gfx::Point view_loc = last_mouse_pos_;
- View::ConvertPointToTarget(widget_->GetRootView(),
- last_tooltip_view_, &view_loc);
- if (last_tooltip_view_->GetTooltipTextOrigin(view_loc, &text_origin) &&
- SetTooltipPosition(text_origin.x(), text_origin.y())) {
- // Return true, otherwise the rectangle we specified is ignored.
- return TRUE;
- }
- return 0;
- }
- default:
- // Fall through.
- break;
- }
- return 0;
-}
-
-bool TooltipManagerWin::SetTooltipPosition(int text_x, int text_y) {
- // NOTE: this really only tests that the y location fits on screen, but that
- // is good enough for our usage.
-
- // Calculate the bounds the tooltip will get.
- gfx::Point view_loc;
- View::ConvertPointToScreen(last_tooltip_view_, &view_loc);
- view_loc = gfx::win::DIPToScreenPoint(view_loc);
- RECT bounds = { view_loc.x() + text_x,
- view_loc.y() + text_y,
- view_loc.x() + text_x + tooltip_width_,
- view_loc.y() + line_count_ * GetTooltipHeight() };
- SendMessage(tooltip_hwnd_, TTM_ADJUSTRECT, TRUE, (LPARAM)&bounds);
-
- // Make sure the rectangle completely fits on the current monitor. If it
- // doesn't, return false so that windows positions the tooltip at the
- // default location.
- gfx::Rect monitor_bounds =
- views::GetMonitorBoundsForRect(gfx::Rect(bounds.left, bounds.right,
- 0, 0));
- if (!monitor_bounds.Contains(gfx::Rect(bounds))) {
- return false;
- }
-
- ::SetWindowPos(tooltip_hwnd_, NULL, bounds.left, bounds.top, 0, 0,
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
- return true;
-}
-
-int TooltipManagerWin::CalcTooltipHeight() {
- // Ask the tooltip for its font.
- int height;
- HFONT hfont = reinterpret_cast<HFONT>(
- SendMessage(tooltip_hwnd_, WM_GETFONT, 0, 0));
- if (hfont != NULL) {
- base::win::ScopedGetDC dc(tooltip_hwnd_);
- base::win::ScopedSelectObject font(dc, hfont);
- gfx::ScopedSetMapMode mode(dc, MM_TEXT);
- TEXTMETRIC font_metrics;
- GetTextMetrics(dc, &font_metrics);
- height = font_metrics.tmHeight;
- } else {
- // Tooltip is using the system font. Use gfx::Font, which should pick
- // up the system font.
- height = gfx::Font().GetHeight();
- }
- // Get the margins from the tooltip
- RECT tooltip_margin;
- SendMessage(tooltip_hwnd_, TTM_GETMARGIN, 0, (LPARAM)&tooltip_margin);
- return height + tooltip_margin.top + tooltip_margin.bottom;
-}
-
-void TooltipManagerWin::UpdateTooltip(const gfx::Point& mouse_pos) {
- View* root_view = widget_->GetRootView();
- View* view = root_view->GetTooltipHandlerForPoint(mouse_pos);
- if (view != last_tooltip_view_) {
- // NOTE: This *must* be sent regardless of the visibility of the tooltip.
- // It triggers Windows to ask for the tooltip again.
- SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
- last_tooltip_view_ = view;
- } else if (last_tooltip_view_ != NULL) {
- // Tooltip is showing, and mouse is over the same view. See if the tooltip
- // text has changed.
- gfx::Point view_point = mouse_pos;
- View::ConvertPointToTarget(root_view, last_tooltip_view_, &view_point);
- string16 new_tooltip_text;
- bool has_tooltip_text =
- last_tooltip_view_->GetTooltipText(view_point, &new_tooltip_text);
- if (!has_tooltip_text || (new_tooltip_text != tooltip_text_)) {
- // The text has changed, hide the popup.
- SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
- if (has_tooltip_text && !new_tooltip_text.empty() && tooltip_showing_) {
- // New text is valid, show the popup.
- SendMessage(tooltip_hwnd_, TTM_POPUP, 0, 0);
- }
- }
- }
-}
-
-void TooltipManagerWin::OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param) {
- gfx::Point mouse_pos_in_pixels(l_param);
- gfx::Point mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels);
-
- if (u_msg >= WM_NCMOUSEMOVE && u_msg <= WM_NCXBUTTONDBLCLK) {
- // NC message coordinates are in screen coordinates.
- POINT temp = mouse_pos_in_pixels.ToPOINT();
- ::MapWindowPoints(HWND_DESKTOP, GetParent(), &temp, 1);
- mouse_pos_in_pixels.SetPoint(temp.x, temp.y);
- mouse_pos = gfx::win::ScreenToDIPPoint(mouse_pos_in_pixels);
- }
-
- if (u_msg != WM_MOUSEMOVE || last_mouse_pos_ != mouse_pos) {
- last_mouse_pos_ = mouse_pos;
- UpdateTooltip(mouse_pos);
- }
- // Forward the message onto the tooltip.
- MSG msg;
- msg.hwnd = GetParent();
- msg.message = u_msg;
- msg.wParam = w_param;
- msg.lParam = l_param;
- SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, 0, (LPARAM)&msg);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/tooltip_manager_win.h b/chromium/ui/views/widget/tooltip_manager_win.h
deleted file mode 100644
index e12dfbb2859..00000000000
--- a/chromium/ui/views/widget/tooltip_manager_win.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_TOOLTIP_MANAGER_WIN_H_
-#define UI_VIEWS_WIDGET_TOOLTIP_MANAGER_WIN_H_
-
-#include <windows.h>
-#include <commctrl.h>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/strings/string16.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/point.h"
-#include "ui/views/widget/tooltip_manager.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace views {
-
-class View;
-class Widget;
-
-// TooltipManager implementation for Windows.
-//
-// This class is intended to be used by NativeWidgetWin. To use this, you must
-// do the following:
-// Add the following to your MSG_MAP:
-//
-// MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
-// MESSAGE_RANGE_HANDLER(WM_NCMOUSEMOVE, WM_NCMOUSEMOVE, OnMouseRange)
-// MSG_WM_NOTIFY(OnNotify)
-//
-// With the following implementations:
-// LRESULT XXX::OnMouseRange(UINT u_msg, WPARAM w_param, LPARAM l_param,
-// BOOL& handled) {
-// tooltip_manager_->OnMouse(u_msg, w_param, l_param);
-// handled = FALSE;
-// return 0;
-// }
-//
-// LRESULT XXX::OnNotify(int w_param, NMHDR* l_param) {
-// bool handled;
-// LRESULT result = tooltip_manager_->OnNotify(w_param, l_param, &handled);
-// SetMsgHandled(handled);
-// return result;
-// }
-//
-// And of course you'll need to create the TooltipManager!
-//
-// Lastly, you'll need to override GetTooltipManager.
-//
-// See NativeWidgetWin for an example of this in action.
-class TooltipManagerWin : public TooltipManager {
- public:
- // Creates a TooltipManager for the specified Widget and parent window.
- explicit TooltipManagerWin(Widget* widget);
- virtual ~TooltipManagerWin();
-
- // Initializes the TooltipManager returning whether initialization was
- // successful. If this returns false the TooltipManager should be destroyed
- // and not used.
- bool Init();
-
- // TooltipManager:
- virtual const gfx::FontList& TooltipManagerWin::GetFontList() const OVERRIDE;
- virtual void UpdateTooltip() OVERRIDE;
- virtual void TooltipTextChanged(View* view) OVERRIDE;
-
- // Message handlers. These forward to the tooltip control.
- virtual void OnMouse(UINT u_msg, WPARAM w_param, LPARAM l_param);
- LRESULT OnNotify(int w_param, NMHDR* l_param, bool* handled);
-
- protected:
- // Returns the Widget we're showing tooltips for.
- gfx::NativeView GetParent();
-
- // Updates the tooltip for the specified location.
- void UpdateTooltip(const gfx::Point& location);
-
- // Tooltip control window.
- HWND tooltip_hwnd_;
-
- // Tooltip information.
- TOOLINFO toolinfo_;
-
- // Last location of the mouse. This is in the coordinates of the rootview.
- gfx::Point last_mouse_pos_;
-
- // Whether or not the tooltip is showing.
- bool tooltip_showing_;
-
- private:
- // Sets the tooltip position based on the x/y position of the text. If the
- // tooltip fits, true is returned.
- bool SetTooltipPosition(int text_x, int text_y);
-
- // Calculates the preferred height for tooltips. This always returns a
- // positive value.
- int CalcTooltipHeight();
-
- // Hosting Widget.
- Widget* widget_;
-
- // The View the mouse is under. This is null if the mouse isn't under a
- // View.
- View* last_tooltip_view_;
-
- // Whether or not the view under the mouse needs to be refreshed. If this
- // is true, when the tooltip is asked for the view under the mouse is
- // refreshed.
- bool last_view_out_of_sync_;
-
- // Text for tooltip from the view.
- string16 tooltip_text_;
-
- // The clipped tooltip.
- string16 clipped_text_;
-
- // Number of lines in the tooltip.
- int line_count_;
-
- // Width of the last tooltip.
- int tooltip_width_;
-
- DISALLOW_COPY_AND_ASSIGN(TooltipManagerWin);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_TOOLTIP_MANAGER_WIN_H_
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index b050ae60ef4..3f4a1707fbc 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/base/cursor/cursor.h"
#include "ui/base/default_theme_provider.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_font_util.h"
@@ -15,6 +16,7 @@
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/focus/focus_manager.h"
@@ -29,13 +31,10 @@
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_deletion_observer.h"
#include "ui/views/widget/widget_observer.h"
+#include "ui/views/widget/widget_removals_observer.h"
#include "ui/views/window/custom_frame_view.h"
#include "ui/views/window/dialog_delegate.h"
-#if defined(USE_AURA)
-#include "ui/base/cursor/cursor.h"
-#endif
-
namespace views {
namespace {
@@ -70,11 +69,7 @@ NativeWidget* CreateNativeWidget(NativeWidget* native_widget,
// WidgetDelegate is supplied.
class DefaultWidgetDelegate : public WidgetDelegate {
public:
- DefaultWidgetDelegate(Widget* widget, const Widget::InitParams& params)
- : widget_(widget),
- can_activate_(!params.child &&
- params.type != Widget::InitParams::TYPE_POPUP &&
- params.type != Widget::InitParams::TYPE_DRAG) {
+ explicit DefaultWidgetDelegate(Widget* widget) : widget_(widget) {
}
virtual ~DefaultWidgetDelegate() {}
@@ -88,9 +83,6 @@ class DefaultWidgetDelegate : public WidgetDelegate {
virtual const Widget* GetWidget() const OVERRIDE {
return widget_;
}
- virtual bool CanActivate() const OVERRIDE {
- return can_activate_;
- }
virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
// In most situations where a Widget is used without a delegate the Widget
// is used as a container, so that we want focus to advance to the top-level
@@ -100,7 +92,6 @@ class DefaultWidgetDelegate : public WidgetDelegate {
private:
Widget* widget_;
- bool can_activate_;
DISALLOW_COPY_AND_ASSIGN(DefaultWidgetDelegate);
};
@@ -112,52 +103,48 @@ Widget::InitParams::InitParams()
: type(TYPE_WINDOW),
delegate(NULL),
child(false),
- opacity((ViewsDelegate::views_delegate &&
- ViewsDelegate::views_delegate->UseTransparentWindows()) ?
- TRANSLUCENT_WINDOW : INFER_OPACITY),
+ opacity(INFER_OPACITY),
accept_events(true),
- can_activate(true),
+ activatable(ACTIVATABLE_DEFAULT),
keep_on_top(false),
+ visible_on_all_workspaces(false),
ownership(NATIVE_WIDGET_OWNS_WIDGET),
mirror_origin_in_rtl(false),
- has_dropshadow(false),
+ shadow_type(SHADOW_TYPE_DEFAULT),
remove_standard_frame(false),
use_system_default_icon(false),
show_state(ui::SHOW_STATE_DEFAULT),
double_buffer(false),
parent(NULL),
native_widget(NULL),
- desktop_root_window_host(NULL),
- top_level(false),
- layer_type(ui::LAYER_TEXTURED),
- context(NULL) {
+ desktop_window_tree_host(NULL),
+ layer_type(aura::WINDOW_LAYER_TEXTURED),
+ context(NULL),
+ force_show_in_taskbar(false) {
}
Widget::InitParams::InitParams(Type type)
: type(type),
delegate(NULL),
- child(type == TYPE_CONTROL),
- opacity(((type == TYPE_WINDOW || type == TYPE_PANEL) &&
- ViewsDelegate::views_delegate &&
- ViewsDelegate::views_delegate->UseTransparentWindows()) ?
- TRANSLUCENT_WINDOW : INFER_OPACITY),
+ child(false),
+ opacity(INFER_OPACITY),
accept_events(true),
- can_activate(type != TYPE_POPUP && type != TYPE_MENU &&
- type != TYPE_DRAG),
+ 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),
- has_dropshadow(false),
+ shadow_type(SHADOW_TYPE_DEFAULT),
remove_standard_frame(false),
use_system_default_icon(false),
show_state(ui::SHOW_STATE_DEFAULT),
double_buffer(false),
parent(NULL),
native_widget(NULL),
- desktop_root_window_host(NULL),
- top_level(false),
- layer_type(ui::LAYER_TEXTURED),
- context(NULL) {
+ desktop_window_tree_host(NULL),
+ layer_type(aura::WINDOW_LAYER_TEXTURED),
+ context(NULL),
+ force_show_in_taskbar(false) {
}
Widget::InitParams::~InitParams() {
@@ -186,7 +173,8 @@ Widget::Widget()
last_mouse_event_was_move_(false),
auto_release_capture_(true),
root_layers_dirty_(false),
- movement_disabled_(false) {
+ movement_disabled_(false),
+ observer_manager_(this) {
}
Widget::~Widget() {
@@ -212,20 +200,19 @@ Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate,
Widget::InitParams params;
params.bounds = bounds;
params.delegate = delegate;
- params.top_level = true;
widget->Init(params);
return widget;
}
// static
Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate,
- gfx::NativeWindow parent) {
+ gfx::NativeView parent) {
return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect());
}
// static
Widget* Widget::CreateWindowWithParentAndBounds(WidgetDelegate* delegate,
- gfx::NativeWindow parent,
+ gfx::NativeView parent,
const gfx::Rect& bounds) {
Widget* widget = new Widget;
Widget::InitParams params;
@@ -256,24 +243,6 @@ Widget* Widget::CreateWindowWithContextAndBounds(WidgetDelegate* delegate,
}
// static
-Widget* Widget::CreateWindowAsFramelessChild(WidgetDelegate* widget_delegate,
- gfx::NativeView parent) {
- views::Widget* widget = new views::Widget;
-
- views::Widget::InitParams params;
- params.delegate = widget_delegate;
- params.child = true;
- params.parent = parent;
- params.remove_standard_frame = true;
-#if defined(USE_AURA)
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
-#endif
-
- widget->Init(params);
- return widget;
-}
-
-// static
Widget* Widget::GetWidgetForNativeView(gfx::NativeView native_view) {
internal::NativeWidgetPrivate* native_widget =
internal::NativeWidgetPrivate::GetNativeWidgetForNativeView(native_view);
@@ -344,29 +313,39 @@ void Widget::Init(const InitParams& in_params) {
TRACE_EVENT0("views", "Widget::Init");
InitParams params = in_params;
- is_top_level_ = params.top_level ||
- (!params.child &&
- params.type != InitParams::TYPE_CONTROL &&
- params.type != InitParams::TYPE_TOOLTIP);
- params.top_level = is_top_level_;
- if (params.opacity == InitParams::INFER_OPACITY) {
-#if defined(OS_WIN) && defined(USE_AURA)
- // By default, make all top-level windows but the main window transparent
- // initially so that they can be made to fade in.
- if (is_top_level_ && params.type != InitParams::TYPE_WINDOW)
- params.opacity = InitParams::TRANSLUCENT_WINDOW;
- else
- params.opacity = InitParams::OPAQUE_WINDOW;
-#else
- params.opacity = InitParams::OPAQUE_WINDOW;
-#endif
- }
+ params.child |= (params.type == InitParams::TYPE_CONTROL);
+ is_top_level_ = !params.child;
+
+ if (params.opacity == views::Widget::InitParams::INFER_OPACITY &&
+ params.type != views::Widget::InitParams::TYPE_WINDOW &&
+ params.type != views::Widget::InitParams::TYPE_PANEL)
+ params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
if (ViewsDelegate::views_delegate)
ViewsDelegate::views_delegate->OnBeforeWidgetInit(&params, this);
+ if (params.opacity == views::Widget::InitParams::INFER_OPACITY)
+ params.opacity = views::Widget::InitParams::OPAQUE_WINDOW;
+
+ bool can_activate = false;
+ if (params.activatable != InitParams::ACTIVATABLE_DEFAULT) {
+ can_activate = (params.activatable == InitParams::ACTIVATABLE_YES);
+ } else if (params.type != InitParams::TYPE_CONTROL &&
+ params.type != InitParams::TYPE_POPUP &&
+ params.type != InitParams::TYPE_MENU &&
+ params.type != InitParams::TYPE_TOOLTIP &&
+ params.type != InitParams::TYPE_DRAG) {
+ can_activate = true;
+ params.activatable = InitParams::ACTIVATABLE_YES;
+ } else {
+ can_activate = false;
+ params.activatable = InitParams::ACTIVATABLE_NO;
+ }
+
widget_delegate_ = params.delegate ?
- params.delegate : new DefaultWidgetDelegate(this, params);
+ params.delegate : new DefaultWidgetDelegate(this);
+ widget_delegate_->set_can_activate(can_activate);
+
ownership_ = params.ownership;
native_widget_ = CreateNativeWidget(params.native_widget, this)->
AsNativeWidgetPrivate();
@@ -388,6 +367,7 @@ void Widget::Init(const InitParams& in_params) {
// Initialize the window's title before setting the window's initial bounds;
// the frame view's preferred height may depend on the presence of a title.
UpdateWindowTitle();
+ non_client_view_->ResetWindowControls();
SetInitialBounds(params.bounds);
if (params.show_state == ui::SHOW_STATE_MAXIMIZED)
Maximize();
@@ -397,6 +377,9 @@ void Widget::Init(const InitParams& in_params) {
SetContentsView(params.delegate->GetContentsView());
SetInitialBoundsForFramelessWindow(params.bounds);
}
+ // This must come after SetContentsView() or it might not be able to find
+ // the correct NativeTheme (on Linux). See http://crbug.com/384492
+ observer_manager_.Add(GetNativeTheme());
native_widget_initialized_ = true;
}
@@ -422,7 +405,19 @@ bool Widget::HasObserver(WidgetObserver* observer) {
return observers_.HasObserver(observer);
}
-bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) {
+void Widget::AddRemovalsObserver(WidgetRemovalsObserver* observer) {
+ removals_observers_.AddObserver(observer);
+}
+
+void Widget::RemoveRemovalsObserver(WidgetRemovalsObserver* observer) {
+ removals_observers_.RemoveObserver(observer);
+}
+
+bool Widget::HasRemovalsObserver(WidgetRemovalsObserver* observer) {
+ return removals_observers_.HasObserver(observer);
+}
+
+bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) const {
return false;
}
@@ -451,6 +446,12 @@ void Widget::NotifyNativeViewHierarchyChanged() {
root_view_->NotifyNativeViewHierarchyChanged();
}
+void Widget::NotifyWillRemoveView(View* view) {
+ FOR_EACH_OBSERVER(WidgetRemovalsObserver,
+ removals_observers_,
+ OnWillRemoveView(this, view));
+}
+
// Converted methods (see header) ----------------------------------------------
Widget* Widget::GetTopLevelWidget() {
@@ -616,7 +617,9 @@ void Widget::Show() {
// it is subsequently shown after being hidden.
saved_show_state_ = ui::SHOW_STATE_NORMAL;
} else {
- native_widget_->Show();
+ CanActivate()
+ ? native_widget_->Show()
+ : native_widget_->ShowWithWindowState(ui::SHOW_STATE_INACTIVE);
}
}
@@ -661,6 +664,10 @@ bool Widget::IsAlwaysOnTop() const {
return native_widget_->IsAlwaysOnTop();
}
+void Widget::SetVisibleOnAllWorkspaces(bool always_visible) {
+ native_widget_->SetVisibleOnAllWorkspaces(always_visible);
+}
+
void Widget::Maximize() {
native_widget_->Maximize();
}
@@ -770,6 +777,10 @@ const InputMethod* Widget::GetInputMethod() const {
}
}
+ui::InputMethod* Widget::GetHostInputMethod() {
+ return native_widget_private()->GetHostInputMethod();
+}
+
void Widget::RunShellDrag(View* view,
const ui::OSExchangeData& data,
const gfx::Point& location,
@@ -811,7 +822,7 @@ void Widget::UpdateWindowTitle() {
// Update the native frame's text. We do this regardless of whether or not
// the native frame is being used, since this also updates the taskbar, etc.
- string16 window_title = widget_delegate_->GetWindowTitle();
+ base::string16 window_title = widget_delegate_->GetWindowTitle();
base::i18n::AdjustStringForLocaleDirection(&window_title);
if (!native_widget_->SetWindowTitle(window_title))
return;
@@ -876,6 +887,10 @@ bool Widget::ShouldUseNativeFrame() const {
return native_widget_->ShouldUseNativeFrame();
}
+bool Widget::ShouldWindowContentsBeTransparent() const {
+ return native_widget_->ShouldWindowContentsBeTransparent();
+}
+
void Widget::DebugToggleFrameType() {
if (frame_type_ == FRAME_TYPE_DEFAULT) {
frame_type_ = ShouldUseNativeFrame() ? FRAME_TYPE_FORCE_CUSTOM :
@@ -949,20 +964,6 @@ const TooltipManager* Widget::GetTooltipManager() const {
return native_widget_->GetTooltipManager();
}
-bool Widget::SetInitialFocus() {
- View* v = widget_delegate_->GetInitiallyFocusedView();
- if (!focus_on_creation_) {
- // If not focusing the window now, tell the focus manager which view to
- // focus when the window is restored.
- if (v)
- focus_manager_->SetStoredFocusView(v);
- return true;
- }
- if (v)
- v->RequestFocus();
- return !!v;
-}
-
gfx::Rect Widget::GetWorkAreaBoundsInScreen() const {
return native_widget_->GetWorkAreaBoundsInScreen();
}
@@ -972,7 +973,7 @@ void Widget::SynthesizeMouseMoveEvent() {
ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED,
last_mouse_event_position_,
last_mouse_event_position_,
- ui::EF_IS_SYNTHESIZED);
+ ui::EF_IS_SYNTHESIZED, 0);
root_view_->OnMouseMoved(mouse_event);
}
@@ -980,6 +981,10 @@ void Widget::OnRootViewLayout() {
native_widget_->OnRootViewLayout();
}
+bool Widget::IsTranslucentWindowOpacitySupported() const {
+ return native_widget_->IsTranslucentWindowOpacitySupported();
+}
+
void Widget::OnOwnerClosing() {
}
@@ -1015,6 +1020,22 @@ void Widget::OnNativeWidgetActivationChanged(bool active) {
FOR_EACH_OBSERVER(WidgetObserver, observers_,
OnWidgetActivationChanged(this, active));
+
+ // During window creation, the widget gets focused without activation, and in
+ // that case, the focus manager cannot set the appropriate text input client
+ // because the widget is not active. Thus we have to notify the focus manager
+ // not only when the focus changes but also when the widget gets activated.
+ // See crbug.com/377479 for details.
+ views::FocusManager* focus_manager = GetFocusManager();
+ if (focus_manager) {
+ if (active)
+ focus_manager->FocusTextInputClient(focus_manager->GetFocusedView());
+ else
+ focus_manager->BlurTextInputClient(focus_manager->GetFocusedView());
+ }
+
+ if (IsVisible() && non_client_view())
+ non_client_view()->frame_view()->SchedulePaint();
}
void Widget::OnNativeFocus(gfx::NativeView old_focused_view) {
@@ -1069,24 +1090,37 @@ void Widget::OnNativeWidgetDestroyed() {
native_widget_destroyed_ = true;
}
-gfx::Size Widget::GetMinimumSize() {
+gfx::Size Widget::GetMinimumSize() const {
return non_client_view_ ? non_client_view_->GetMinimumSize() : gfx::Size();
}
-gfx::Size Widget::GetMaximumSize() {
+gfx::Size Widget::GetMaximumSize() const {
return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size();
}
void Widget::OnNativeWidgetMove() {
widget_delegate_->OnWidgetMove();
+ View* root = GetRootView();
+ if (root && root->GetFocusManager()) {
+ View* focused_view = root->GetFocusManager()->GetFocusedView();
+ if (focused_view && focused_view->GetInputMethod())
+ focused_view->GetInputMethod()->OnCaretBoundsChanged(focused_view);
+ }
FOR_EACH_OBSERVER(WidgetObserver, observers_, OnWidgetBoundsChanged(
this,
GetWindowBoundsInScreen()));
}
void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) {
- root_view_->SetSize(new_size);
-
+ View* root = GetRootView();
+ if (root) {
+ root->SetSize(new_size);
+ if (root->GetFocusManager()) {
+ View* focused_view = GetRootView()->GetFocusManager()->GetFocusedView();
+ if (focused_view && focused_view->GetInputMethod())
+ focused_view->GetInputMethod()->OnCaretBoundsChanged(focused_view);
+ }
+ }
// Size changed notifications can fire prior to full initialization
// i.e. during session restore. Avoid saving session state during these
// startup procedures.
@@ -1123,7 +1157,7 @@ void Widget::OnNativeWidgetPaint(gfx::Canvas* canvas) {
// On Linux Aura, we can get here during Init() because of the
// SetInitialBounds call.
if (native_widget_initialized_)
- GetRootView()->Paint(canvas);
+ GetRootView()->Paint(canvas, CullSet());
}
int Widget::GetNonClientComponent(const gfx::Point& point) {
@@ -1138,10 +1172,12 @@ int Widget::GetNonClientComponent(const gfx::Point& point) {
}
void Widget::OnKeyEvent(ui::KeyEvent* event) {
- static_cast<internal::RootView*>(GetRootView())->
- DispatchKeyEvent(event);
+ SendEventToProcessor(event);
}
+// TODO(tdanderson): We should not be calling the OnMouse*() functions on
+// RootView from anywhere in Widget. Use
+// SendEventToProcessor() instead. See crbug.com/348087.
void Widget::OnMouseEvent(ui::MouseEvent* event) {
View* root_view = GetRootView();
switch (event->type()) {
@@ -1172,6 +1208,7 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
}
return;
}
+
case ui::ET_MOUSE_RELEASED:
last_mouse_event_was_move_ = false;
is_mouse_button_pressed_ = false;
@@ -1183,6 +1220,7 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
if ((event->flags() & ui::EF_IS_NON_CLIENT) == 0)
event->SetHandled();
return;
+
case ui::ET_MOUSE_MOVED:
case ui::ET_MOUSE_DRAGGED:
if (native_widget_->HasCapture() && is_mouse_button_pressed_) {
@@ -1197,20 +1235,22 @@ void Widget::OnMouseEvent(ui::MouseEvent* event) {
root_view->OnMouseMoved(*event);
}
return;
+
case ui::ET_MOUSE_EXITED:
last_mouse_event_was_move_ = false;
if (root_view)
root_view->OnMouseExited(*event);
return;
+
case ui::ET_MOUSEWHEEL:
if (root_view && root_view->OnMouseWheel(
static_cast<const ui::MouseWheelEvent&>(*event)))
event->SetHandled();
return;
+
default:
return;
}
- event->SetHandled();
}
void Widget::OnMouseCaptureLost() {
@@ -1223,14 +1263,15 @@ void Widget::OnMouseCaptureLost() {
is_mouse_button_pressed_ = false;
}
-void Widget::OnTouchEvent(ui::TouchEvent* event) {
- static_cast<internal::RootView*>(GetRootView())->
- DispatchTouchEvent(event);
-}
-
void Widget::OnScrollEvent(ui::ScrollEvent* event) {
- static_cast<internal::RootView*>(GetRootView())->
- DispatchScrollEvent(event);
+ ui::ScrollEvent event_copy(*event);
+ SendEventToProcessor(&event_copy);
+
+ // Convert unhandled ui::ET_SCROLL events into ui::ET_MOUSEWHEEL events.
+ if (!event_copy.handled() && event_copy.type() == ui::ET_SCROLL) {
+ ui::MouseWheelEvent wheel(*event);
+ OnMouseEvent(&wheel);
+ }
}
void Widget::OnGestureEvent(ui::GestureEvent* event) {
@@ -1243,17 +1284,14 @@ void Widget::OnGestureEvent(ui::GestureEvent* event) {
break;
case ui::ET_GESTURE_END:
- if (event->details().touch_points() == 1) {
+ if (event->details().touch_points() == 1)
is_touch_down_ = false;
- if (auto_release_capture_)
- ReleaseCapture();
- }
break;
default:
break;
}
- static_cast<internal::RootView*>(GetRootView())->DispatchGestureEvent(event);
+ SendEventToProcessor(event);
}
bool Widget::ExecuteCommand(int command_id) {
@@ -1290,6 +1328,27 @@ const Widget* Widget::AsWidget() const {
return this;
}
+bool Widget::SetInitialFocus(ui::WindowShowState show_state) {
+ View* v = widget_delegate_->GetInitiallyFocusedView();
+ if (!focus_on_creation_ || show_state == ui::SHOW_STATE_INACTIVE ||
+ show_state == ui::SHOW_STATE_MINIMIZED) {
+ // If not focusing the window now, tell the focus manager which view to
+ // focus when the window is restored.
+ if (v)
+ focus_manager_->SetStoredFocusView(v);
+ return true;
+ }
+ if (v)
+ v->RequestFocus();
+ return !!v;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Widget, ui::EventSource implementation:
+ui::EventProcessor* Widget::GetEventProcessor() {
+ return root_view_.get();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, FocusTraversable implementation:
@@ -1312,6 +1371,21 @@ View* Widget::GetFocusTraversableParentView() {
}
////////////////////////////////////////////////////////////////////////////////
+// Widget, ui::NativeThemeObserver implementation:
+
+void Widget::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
+ DCHECK(observer_manager_.IsObserving(observed_theme));
+
+ ui::NativeTheme* current_native_theme = GetNativeTheme();
+ if (!observer_manager_.IsObserving(current_native_theme)) {
+ observer_manager_.RemoveAll();
+ observer_manager_.Add(current_native_theme);
+ }
+
+ root_view_->PropagateNativeThemeChanged(current_native_theme);
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Widget, protected:
internal::RootView* Widget::CreateRootView() {
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index ce14d7c5bff..c76633b282f 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -12,10 +12,13 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
+#include "base/scoped_observer.h"
+#include "ui/aura/window_layer_type.h"
#include "ui/base/ui_base_types.h"
-#include "ui/compositor/layer_type.h"
+#include "ui/events/event_source.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
+#include "ui/native_theme/native_theme_observer.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/native_widget_delegate.h"
#include "ui/views/window/client_view.h"
@@ -44,6 +47,7 @@ namespace ui {
class Accelerator;
class Compositor;
class DefaultThemeProvider;
+class InputMethod;
class Layer;
class NativeTheme;
class OSExchangeData;
@@ -52,7 +56,7 @@ class ThemeProvider;
namespace views {
-class DesktopRootWindowHost;
+class DesktopWindowTreeHost;
class InputMethod;
class NativeWidget;
class NonClientFrameView;
@@ -60,6 +64,7 @@ class TooltipManager;
class View;
class WidgetDelegate;
class WidgetObserver;
+class WidgetRemovalsObserver;
namespace internal {
class NativeWidgetPrivate;
@@ -92,7 +97,9 @@ class RootView;
// destructor).
//
class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
- public FocusTraversable {
+ public ui::EventSource,
+ public FocusTraversable,
+ public ui::NativeThemeObserver {
public:
typedef std::set<Widget*> Widgets;
@@ -155,6 +162,14 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
TRANSLUCENT_WINDOW,
};
+ enum Activatable {
+ // Infer whether the window should be activatable from the window type.
+ ACTIVATABLE_DEFAULT,
+
+ ACTIVATABLE_YES,
+ ACTIVATABLE_NO
+ };
+
enum Ownership {
// Default. Creator is not responsible for managing the lifetime of the
// Widget, it is destroyed when the corresponding NativeWidget is
@@ -165,33 +180,42 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
WIDGET_OWNS_NATIVE_WIDGET
};
+ enum ShadowType {
+ SHADOW_TYPE_DEFAULT, // Use default shadow setting. It will be one of
+ // the settings below depending on InitParams::type
+ // and the native widget's type.
+ SHADOW_TYPE_NONE, // Don't draw any shadow.
+ SHADOW_TYPE_DROP, // Draw a drop shadow that emphasizes Z-order
+ // relationship to other windows.
+ };
+
InitParams();
explicit InitParams(Type type);
~InitParams();
- // Will return the first of the following that isn't NULL: the native view,
- // |parent|, |context|.
- gfx::NativeView GetContext() const;
-
Type type;
// If NULL, a default implementation will be constructed.
WidgetDelegate* delegate;
bool child;
// If TRANSLUCENT_WINDOW, the widget may be fully or partially transparent.
+ // Translucent windows may not always be supported. Use
+ // IsTranslucentWindowOpacitySupported to determine if translucent windows
+ // are supported.
// If OPAQUE_WINDOW, we can perform optimizations based on the widget being
// fully opaque. Defaults to TRANSLUCENT_WINDOW if
// ViewsDelegate::UseTransparentWindows(). Defaults to OPAQUE_WINDOW for
// non-window widgets.
WindowOpacity opacity;
bool accept_events;
- bool can_activate;
+ Activatable activatable;
bool keep_on_top;
+ bool visible_on_all_workspaces;
Ownership ownership;
bool mirror_origin_in_rtl;
- bool has_dropshadow;
- // Only used by Windows. Specifies that the system default caption and icon
- // should not be rendered, and that the client area should be equivalent to
- // the window area.
+ ShadowType shadow_type;
+ // Specifies that the system default caption and icon should not be
+ // rendered, and that the client area should be equivalent to the window
+ // area. Only used on some platforms (Windows and Linux).
bool remove_standard_frame;
// Only used by ShellWindow on Windows. Specifies that the default icon of
// packaged app should be the system default icon.
@@ -209,18 +233,14 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// When set, this value is used as the Widget's NativeWidget implementation.
// The Widget will not construct a default one. Default is NULL.
NativeWidget* native_widget;
- // Aura-only. Provides a DesktopRootWindowHost implementation to use instead
+ // Aura-only. Provides a DesktopWindowTreeHost implementation to use instead
// of the default one.
// TODO(beng): Figure out if there's a better way to expose this, e.g. get
// rid of NW subclasses and do this all via message handling.
- DesktopRootWindowHost* desktop_root_window_host;
- // Whether this window is intended to be a toplevel window with no
- // attachment to any other window. (This may be a transient window if
- // |parent| is set.)
- bool top_level;
+ DesktopWindowTreeHost* desktop_window_tree_host;
// Only used by NativeWidgetAura. Specifies the type of layer for the
- // aura::Window. Default is LAYER_TEXTURED.
- ui::LayerType layer_type;
+ // aura::Window. Default is WINDOW_LAYER_TEXTURED.
+ aura::WindowLayerType layer_type;
// Only used by Aura. Provides a context window whose RootWindow is
// consulted during widget creation to determine where in the Window
// hierarchy this widget should be placed. (This is separate from |parent|;
@@ -229,6 +249,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// where it wants your window placed.) NULL is not allowed if you are using
// aura.
gfx::NativeView context;
+ // If true, forces the window to be shown in the taskbar, even for window
+ // types that do not appear in the taskbar by default (popup and bubble).
+ bool force_show_in_taskbar;
// Only used by X11, for root level windows. Specifies the res_name and
// res_class fields, respectively, of the WM_CLASS window property. Controls
// window grouping and desktop file matching in Linux window managers.
@@ -253,9 +276,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Creates a decorated window Widget with the specified properties.
static Widget* CreateWindowWithParent(WidgetDelegate* delegate,
- gfx::NativeWindow parent);
+ gfx::NativeView parent);
static Widget* CreateWindowWithParentAndBounds(WidgetDelegate* delegate,
- gfx::NativeWindow parent,
+ gfx::NativeView parent,
const gfx::Rect& bounds);
// Creates a decorated window Widget in the same desktop context as |context|.
@@ -265,15 +288,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
gfx::NativeView context,
const gfx::Rect& bounds);
- // Creates an undecorated child window Widget parented to |parent|.
- static Widget* CreateWindowAsFramelessChild(WidgetDelegate* widget_delegate,
- gfx::NativeView parent);
-
- // Enumerates all windows pertaining to us and notifies their
- // view hierarchies that the locale has changed.
- // TODO(beng): remove post-Aurafication of ChromeOS.
- static void NotifyLocaleChanged();
-
// Closes all Widgets that aren't identified as "secondary widgets". Called
// during application shutdown when the last non-secondary widget is closed.
static void CloseAllSecondaryWidgets();
@@ -341,9 +355,14 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
void RemoveObserver(WidgetObserver* observer);
bool HasObserver(WidgetObserver* observer);
+ // Add/remove removals observer.
+ void AddRemovalsObserver(WidgetRemovalsObserver* observer);
+ void RemoveRemovalsObserver(WidgetRemovalsObserver* observer);
+ bool HasRemovalsObserver(WidgetRemovalsObserver* observer);
+
// Returns the accelerator given a command id. Returns false if there is
// no accelerator associated with a given id, which is a common condition.
- virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator);
+ virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator) const;
// Forwarded from the RootView so that the widget can do any cleanup.
void ViewHierarchyChanged(const View::ViewHierarchyChangedDetails& details);
@@ -356,6 +375,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// about the change.
void NotifyNativeViewHierarchyChanged();
+ // Called immediately before removing |view| from this widget.
+ void NotifyWillRemoveView(View* view);
+
// Returns the top level widget in a hierarchy (see is_top_level() for
// the definition of top level widget.) Will return NULL if called
// before the widget is attached to the top level widget's hierarchy.
@@ -434,8 +456,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// set to true after Close() has been invoked on the NativeWidget.
bool IsClosed() const;
- // Shows or hides the widget, without changing activation state.
+ // Shows the widget. The widget is activated if during initialization the
+ // can_activate flag in the InitParams structure is set to true.
virtual void Show();
+ // Hides the widget.
void Hide();
// Like Show(), but does not activate the window.
@@ -464,6 +488,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// in the windowing system.
bool IsAlwaysOnTop() const;
+ // Sets the widget to be visible on all work spaces.
+ void SetVisibleOnAllWorkspaces(bool always_visible);
+
// Maximizes/minimizes/restores the window.
void Maximize();
void Minimize();
@@ -527,6 +554,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
InputMethod* GetInputMethod();
const InputMethod* GetInputMethod() const;
+ // Returns the ui::InputMethod for this widget.
+ // TODO(yukishiino): Rename this method to GetInputMethod once we remove
+ // views::InputMethod.
+ ui::InputMethod* GetHostInputMethod();
+
// Starts a drag operation for the specified view. This blocks until the drag
// operation completes. |view| can be NULL.
// If the view is non-NULL it can be accessed during the drag by calling
@@ -595,6 +627,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Whether we should be using a native frame.
bool ShouldUseNativeFrame() const;
+ // Determines whether the window contents should be rendered transparently
+ // (for example, so that they can overhang onto the window title bar).
+ bool ShouldWindowContentsBeTransparent() const;
+
// Forces the frame into the alternate frame type (custom or native) depending
// on its current state.
void DebugToggleFrameType();
@@ -668,12 +704,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
TooltipManager* GetTooltipManager();
const TooltipManager* GetTooltipManager() const;
- // Sets-up the focus manager with the view that should have focus when the
- // window is shown the first time. Returns true if the initial focus has been
- // set or the widget should not set the initial focus, or false if the caller
- // should set the initial focus (if any).
- bool SetInitialFocus();
-
void set_focus_on_creation(bool focus_on_creation) {
focus_on_creation_ = focus_on_creation;
}
@@ -699,6 +729,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// window sizing information to the window server on some platforms.
void OnRootViewLayout();
+ // Whether the widget supports translucency.
+ bool IsTranslucentWindowOpacitySupported() const;
+
// 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
@@ -719,8 +752,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
virtual void OnNativeWidgetCreated(bool desktop_widget) OVERRIDE;
virtual void OnNativeWidgetDestroying() OVERRIDE;
virtual void OnNativeWidgetDestroyed() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
virtual void OnNativeWidgetMove() OVERRIDE;
virtual void OnNativeWidgetSizeChanged(const gfx::Size& new_size) OVERRIDE;
virtual void OnNativeWidgetBeginUserBoundsChange() OVERRIDE;
@@ -733,7 +766,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
virtual void OnMouseCaptureLost() OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool ExecuteCommand(int command_id) OVERRIDE;
@@ -743,12 +775,19 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
virtual Widget* AsWidget() OVERRIDE;
virtual const Widget* AsWidget() const OVERRIDE;
+ virtual bool SetInitialFocus(ui::WindowShowState show_state) OVERRIDE;
+
+ // Overridden from ui::EventSource:
+ virtual ui::EventProcessor* GetEventProcessor() OVERRIDE;
// Overridden from FocusTraversable:
virtual FocusSearch* GetFocusSearch() OVERRIDE;
virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE;
virtual View* GetFocusTraversableParentView() OVERRIDE;
+ // Overridden from ui::NativeThemeObserver:
+ virtual void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) OVERRIDE;
+
protected:
// Creates the RootView to be used within this Widget. Subclasses may override
// to create custom RootViews that do specialized event processing.
@@ -762,7 +801,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
private:
friend class ComboboxTest;
- friend class NativeTextfieldViewsTest;
+ friend class TextfieldTest;
// Sets the value of |disable_inactive_rendering_|. If the value changes,
// both the NonClientView and WidgetDelegate are notified.
@@ -795,6 +834,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
ObserverList<WidgetObserver> observers_;
+ ObserverList<WidgetRemovalsObserver> removals_observers_;
+
// Non-owned pointer to the Widget's delegate. If a NULL delegate is supplied
// to Init() a default WidgetDelegate is created.
WidgetDelegate* widget_delegate_;
@@ -892,6 +933,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// disabled.
bool movement_disabled_;
+ ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> observer_manager_;
+
DISALLOW_COPY_AND_ASSIGN(Widget);
};
diff --git a/chromium/ui/views/widget/widget_aura_utils.cc b/chromium/ui/views/widget/widget_aura_utils.cc
index 348f828ff8f..be284a8af81 100644
--- a/chromium/ui/views/widget/widget_aura_utils.cc
+++ b/chromium/ui/views/widget/widget_aura_utils.cc
@@ -8,27 +8,27 @@
namespace views {
-aura::client::WindowType GetAuraWindowTypeForWidgetType(
+ui::wm::WindowType GetAuraWindowTypeForWidgetType(
Widget::InitParams::Type type) {
switch (type) {
case Widget::InitParams::TYPE_WINDOW:
- return aura::client::WINDOW_TYPE_NORMAL;
+ return ui::wm::WINDOW_TYPE_NORMAL;
case Widget::InitParams::TYPE_PANEL:
- return aura::client::WINDOW_TYPE_PANEL;
+ return ui::wm::WINDOW_TYPE_PANEL;
case Widget::InitParams::TYPE_CONTROL:
- return aura::client::WINDOW_TYPE_CONTROL;
+ return ui::wm::WINDOW_TYPE_CONTROL;
case Widget::InitParams::TYPE_WINDOW_FRAMELESS:
case Widget::InitParams::TYPE_POPUP:
case Widget::InitParams::TYPE_BUBBLE:
case Widget::InitParams::TYPE_DRAG:
- return aura::client::WINDOW_TYPE_POPUP;
+ return ui::wm::WINDOW_TYPE_POPUP;
case Widget::InitParams::TYPE_MENU:
- return aura::client::WINDOW_TYPE_MENU;
+ return ui::wm::WINDOW_TYPE_MENU;
case Widget::InitParams::TYPE_TOOLTIP:
- return aura::client::WINDOW_TYPE_TOOLTIP;
+ return ui::wm::WINDOW_TYPE_TOOLTIP;
default:
NOTREACHED() << "Unhandled widget type " << type;
- return aura::client::WINDOW_TYPE_UNKNOWN;
+ return ui::wm::WINDOW_TYPE_UNKNOWN;
}
}
diff --git a/chromium/ui/views/widget/widget_aura_utils.h b/chromium/ui/views/widget/widget_aura_utils.h
index 8f0bfcc0358..4b16de48cab 100644
--- a/chromium/ui/views/widget/widget_aura_utils.h
+++ b/chromium/ui/views/widget/widget_aura_utils.h
@@ -5,14 +5,14 @@
#ifndef UI_VIEWS_WIDGET_WIDGET_AURA_UTILS_H_
#define UI_VIEWS_WIDGET_WIDGET_AURA_UTILS_H_
-#include "ui/aura/client/window_types.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/public/window_types.h"
// Functions shared by native_widget_aura.cc and desktop_native_widget_aura.cc:
namespace views {
-aura::client::WindowType GetAuraWindowTypeForWidgetType(
+ui::wm::WindowType GetAuraWindowTypeForWidgetType(
Widget::InitParams::Type type);
} // namespace views
diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc
index fbace27c316..7e1f67e19c3 100644
--- a/chromium/ui/views/widget/widget_delegate.cc
+++ b/chromium/ui/views/widget/widget_delegate.cc
@@ -17,7 +17,9 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// WidgetDelegate:
-WidgetDelegate::WidgetDelegate() : default_contents_view_(NULL) {
+WidgetDelegate::WidgetDelegate()
+ : default_contents_view_(NULL),
+ can_activate_(true) {
}
void WidgetDelegate::OnWidgetMove() {
@@ -50,23 +52,23 @@ bool WidgetDelegate::CanMaximize() const {
}
bool WidgetDelegate::CanActivate() const {
- return true;
+ return can_activate_;
}
ui::ModalType WidgetDelegate::GetModalType() const {
return ui::MODAL_TYPE_NONE;
}
-ui::AccessibilityTypes::Role WidgetDelegate::GetAccessibleWindowRole() const {
- return ui::AccessibilityTypes::ROLE_WINDOW;
+ui::AXRole WidgetDelegate::GetAccessibleWindowRole() const {
+ return ui::AX_ROLE_WINDOW;
}
-string16 WidgetDelegate::GetAccessibleWindowTitle() const {
+base::string16 WidgetDelegate::GetAccessibleWindowTitle() const {
return GetWindowTitle();
}
-string16 WidgetDelegate::GetWindowTitle() const {
- return string16();
+base::string16 WidgetDelegate::GetWindowTitle() const {
+ return base::string16();
}
bool WidgetDelegate::ShouldShowWindowTitle() const {
diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h
index 16e29a8b338..b9903096c14 100644
--- a/chromium/ui/views/widget/widget_delegate.h
+++ b/chromium/ui/views/widget/widget_delegate.h
@@ -8,7 +8,7 @@
#include <string>
#include <vector>
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/view.h"
@@ -30,6 +30,11 @@ class VIEWS_EXPORT WidgetDelegate {
public:
WidgetDelegate();
+ // Sets the return value of CanActivate(). Default is true.
+ void set_can_activate(bool can_activate) {
+ can_activate_ = can_activate;
+ }
+
// Called whenever the widget's position changes.
virtual void OnWidgetMove();
@@ -60,13 +65,13 @@ class VIEWS_EXPORT WidgetDelegate {
// ui::MODAL_TYPE_NONE (not modal).
virtual ui::ModalType GetModalType() const;
- virtual ui::AccessibilityTypes::Role GetAccessibleWindowRole() const;
+ virtual ui::AXRole GetAccessibleWindowRole() const;
// Returns the title to be read with screen readers.
- virtual string16 GetAccessibleWindowTitle() const;
+ virtual base::string16 GetAccessibleWindowTitle() const;
// Returns the text to be displayed in the window title.
- virtual string16 GetWindowTitle() const;
+ virtual base::string16 GetWindowTitle() const;
// Returns true if the window should show a title in the title bar.
virtual bool ShouldShowWindowTitle() const;
@@ -181,6 +186,8 @@ class VIEWS_EXPORT WidgetDelegate {
private:
View* default_contents_view_;
+ bool can_activate_;
+
DISALLOW_COPY_AND_ASSIGN(WidgetDelegate);
};
diff --git a/chromium/ui/views/widget/widget_hwnd_utils.cc b/chromium/ui/views/widget/widget_hwnd_utils.cc
index 53588c25e5e..ac313bb74c8 100644
--- a/chromium/ui/views/widget/widget_hwnd_utils.cc
+++ b/chromium/ui/views/widget/widget_hwnd_utils.cc
@@ -41,7 +41,8 @@ void CalculateWindowStylesFromInitParams(
*style |= WS_MINIMIZE;
if (!params.accept_events)
*ex_style |= WS_EX_TRANSPARENT;
- if (!params.can_activate)
+ 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)
*ex_style |= WS_EX_TOPMOST;
@@ -62,14 +63,10 @@ void CalculateWindowStylesFromInitParams(
// 5- When the window is created but before it is presented, call
// DwmExtendFrameIntoClientArea passing -1 as the margins.
if (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW) {
-#if defined(USE_AURA)
if (ui::win::IsAeroGlassEnabled())
*ex_style |= WS_EX_COMPOSITED;
-#else
- *ex_style |= WS_EX_LAYERED;
-#endif
}
- if (params.has_dropshadow) {
+ if (params.shadow_type == Widget::InitParams::SHADOW_TYPE_DROP) {
*class_style |= (base::win::GetVersion() < base::win::VERSION_XP) ?
0 : CS_DROPSHADOW;
}
@@ -122,10 +119,13 @@ void CalculateWindowStylesFromInitParams(
case Widget::InitParams::TYPE_BUBBLE:
*style |= WS_POPUP;
*style |= WS_CLIPCHILDREN;
+ if (!params.force_show_in_taskbar)
+ *ex_style |= WS_EX_TOOLWINDOW;
break;
case Widget::InitParams::TYPE_POPUP:
*style |= WS_POPUP;
- *ex_style |= WS_EX_TOOLWINDOW;
+ if (!params.force_show_in_taskbar)
+ *ex_style |= WS_EX_TOOLWINDOW;
break;
case Widget::InitParams::TYPE_MENU:
*style |= WS_POPUP;
diff --git a/chromium/ui/views/widget/widget_hwnd_utils.h b/chromium/ui/views/widget/widget_hwnd_utils.h
index 2808bab0d48..09ee0abe138 100644
--- a/chromium/ui/views/widget/widget_hwnd_utils.h
+++ b/chromium/ui/views/widget/widget_hwnd_utils.h
@@ -9,7 +9,8 @@
#include "ui/views/widget/widget.h"
-// Functions shared by native_widget_win.cc and desktop_root_window_host_win.cc:
+// Functions shared by hwnd_message_handler.cc and
+// desktop_window_tree_host_win.cc:
namespace views {
class HWNDMessageHandler;
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index 30d44a3c9d7..45026a9eb1e 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -4,21 +4,31 @@
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/path_service.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/aura/client/focus_client.h"
+#include "ui/aura/env.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_paths.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/events/event_processor.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/test/widget_test.h"
+#include "ui/views/touchui/touch_selection_controller_impl.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
+#include "ui/wm/public/activation_client.h"
-#if defined(USE_AURA)
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#endif
-
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#endif
@@ -134,9 +144,6 @@ class NestedLoopCaptureView : public View {
base::MessageLoop::ScopedNestableTaskAllower allow(loop);
base::RunLoop run_loop;
-#if defined(USE_AURA)
- run_loop.set_dispatcher(aura::Env::GetInstance()->GetDispatcher());
-#endif
run_loop.Run();
return true;
}
@@ -148,8 +155,39 @@ class NestedLoopCaptureView : public View {
} // namespace
-#if defined(OS_WIN) && defined(USE_AURA)
-// Tests whether activation and focus change works correctly in Windows AURA.
+class WidgetTestInteractive : public WidgetTest {
+ public:
+ WidgetTestInteractive() {}
+ virtual ~WidgetTestInteractive() {}
+
+ virtual void SetUp() OVERRIDE {
+ gfx::GLSurface::InitializeOneOffForTests();
+ base::FilePath pak_dir;
+ PathService::Get(base::DIR_MODULE, &pak_dir);
+ base::FilePath pak_file;
+ pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+ WidgetTest::SetUp();
+ }
+
+ protected:
+ static void ShowQuickMenuImmediately(
+ TouchSelectionControllerImpl* controller) {
+ DCHECK(controller);
+ if (controller->context_menu_timer_.IsRunning()) {
+ controller->context_menu_timer_.Stop();
+ controller->ContextMenuTimerFired();
+ }
+ }
+
+ static bool IsQuickMenuVisible(TouchSelectionControllerImpl* controller) {
+ DCHECK(controller);
+ return controller->context_menu_ && controller->context_menu_->visible();
+ }
+};
+
+#if defined(OS_WIN)
+// Tests whether activation and focus change works correctly in Windows.
// We test the following:-
// 1. If the active aura window is correctly set when a top level widget is
// created.
@@ -157,9 +195,8 @@ class NestedLoopCaptureView : public View {
// another top level widget is created and focused.
// 3. On focusing the native platform window for widget 1, the active aura
// window for widget 1 should be set and that for widget 2 should reset.
-// TODO(ananta)
-// Discuss with erg on how to write this test for linux x11 aura.
-TEST_F(WidgetTest, DesktopNativeWidgetAuraActivationAndFocusTest) {
+// TODO(ananta): Discuss with erg on how to write this test for linux x11 aura.
+TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) {
// Create widget 1 and expect the active window to be its window.
View* contents_view1 = new View;
contents_view1->SetFocusable(true);
@@ -195,7 +232,7 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraActivationAndFocusTest) {
aura::Window* root_window2 = widget2.GetNativeView()->GetRootWindow();
contents_view2->RequestFocus();
::SetActiveWindow(
- root_window2->GetDispatcher()->host()->GetAcceleratedWidget());
+ root_window2->GetHost()->GetAcceleratedWidget());
aura::client::ActivationClient* activation_client2 =
aura::client::GetActivationClient(root_window2);
@@ -208,14 +245,14 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraActivationAndFocusTest) {
// window.
contents_view1->RequestFocus();
::SetActiveWindow(
- root_window1->GetDispatcher()->host()->GetAcceleratedWidget());
+ root_window1->GetHost()->GetAcceleratedWidget());
EXPECT_EQ(activation_client2->GetActiveWindow(),
reinterpret_cast<aura::Window*>(NULL));
EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView());
}
#endif
-TEST_F(WidgetTest, CaptureAutoReset) {
+TEST_F(WidgetTestInteractive, CaptureAutoReset) {
Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
View* container = new View;
toplevel->SetContentsView(container);
@@ -227,7 +264,7 @@ TEST_F(WidgetTest, CaptureAutoReset) {
// By default, mouse release removes capture.
gfx::Point click_location(45, 15);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
toplevel->OnMouseEvent(&release);
EXPECT_FALSE(toplevel->HasCapture());
@@ -244,7 +281,7 @@ TEST_F(WidgetTest, CaptureAutoReset) {
RunPendingMessages();
}
-TEST_F(WidgetTest, ResetCaptureOnGestureEnd) {
+TEST_F(WidgetTestInteractive, ResetCaptureOnGestureEnd) {
Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
View* container = new View;
toplevel->SetContentsView(container);
@@ -274,9 +311,9 @@ TEST_F(WidgetTest, ResetCaptureOnGestureEnd) {
gfx::Point click_location(45, 15);
ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
EXPECT_TRUE(toplevel->HasCapture());
@@ -300,7 +337,7 @@ TEST_F(WidgetTest, ResetCaptureOnGestureEnd) {
// Checks that if a mouse-press triggers a capture on a different widget (which
// consumes the mouse-release event), then the target of the press does not have
// capture.
-TEST_F(WidgetTest, DisableCaptureWidgetFromMousePress) {
+TEST_F(WidgetTestInteractive, DisableCaptureWidgetFromMousePress) {
// The test creates two widgets: |first| and |second|.
// The View in |first| makes |second| visible, sets capture on it, and starts
// a nested loop (like a menu does). The View in |second| terminates the
@@ -327,9 +364,10 @@ TEST_F(WidgetTest, DisableCaptureWidgetFromMousePress) {
base::Owned(new ui::MouseEvent(ui::ET_MOUSE_RELEASED,
location,
location,
+ ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON))));
ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
first->OnMouseEvent(&press);
EXPECT_FALSE(first->HasCapture());
first->Close();
@@ -338,7 +376,7 @@ TEST_F(WidgetTest, DisableCaptureWidgetFromMousePress) {
// Tests some grab/ungrab events.
// TODO(estade): can this be enabled now that this is an interactive ui test?
-TEST_F(WidgetTest, DISABLED_GrabUngrab) {
+TEST_F(WidgetTestInteractive, DISABLED_GrabUngrab) {
Widget* toplevel = CreateTopLevelPlatformWidget();
Widget* child1 = CreateChildNativeWidgetWithParent(toplevel);
Widget* child2 = CreateChildNativeWidgetWithParent(toplevel);
@@ -361,7 +399,7 @@ TEST_F(WidgetTest, DISABLED_GrabUngrab) {
// Click on child1
gfx::Point p1(45, 45);
ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
toplevel->OnMouseEvent(&pressed);
EXPECT_TRUE(toplevel->HasCapture());
@@ -369,7 +407,7 @@ TEST_F(WidgetTest, DISABLED_GrabUngrab) {
EXPECT_FALSE(child2->HasCapture());
ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
toplevel->OnMouseEvent(&released);
EXPECT_FALSE(toplevel->HasCapture());
@@ -381,7 +419,7 @@ TEST_F(WidgetTest, DISABLED_GrabUngrab) {
// Click on child2
gfx::Point p2(315, 45);
ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
toplevel->OnMouseEvent(&pressed2);
EXPECT_TRUE(pressed2.handled());
EXPECT_TRUE(toplevel->HasCapture());
@@ -389,7 +427,7 @@ TEST_F(WidgetTest, DISABLED_GrabUngrab) {
EXPECT_FALSE(child1->HasCapture());
ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
toplevel->OnMouseEvent(&released2);
EXPECT_FALSE(toplevel->HasCapture());
EXPECT_FALSE(child1->HasCapture());
@@ -400,7 +438,7 @@ TEST_F(WidgetTest, DISABLED_GrabUngrab) {
// Tests mouse move outside of the window into the "resize controller" and back
// will still generate an OnMouseEntered and OnMouseExited event..
-TEST_F(WidgetTest, CheckResizeControllerEvents) {
+TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) {
Widget* toplevel = CreateTopLevelPlatformWidget();
toplevel->SetBounds(gfx::Rect(0, 0, 100, 100));
@@ -414,21 +452,24 @@ TEST_F(WidgetTest, CheckResizeControllerEvents) {
// Move to an outside position.
gfx::Point p1(200, 200);
- ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE);
+ ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE,
+ ui::EF_NONE);
toplevel->OnMouseEvent(&moved_out);
EXPECT_EQ(0, view->EnteredCalls());
EXPECT_EQ(0, view->ExitedCalls());
// Move onto the active view.
gfx::Point p2(95, 95);
- ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE);
+ ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE,
+ ui::EF_NONE);
toplevel->OnMouseEvent(&moved_over);
EXPECT_EQ(1, view->EnteredCalls());
EXPECT_EQ(0, view->ExitedCalls());
// Move onto the outer resizing border.
gfx::Point p3(102, 95);
- ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE);
+ ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE,
+ ui::EF_NONE);
toplevel->OnMouseEvent(&moved_resizer);
EXPECT_EQ(0, view->EnteredCalls());
EXPECT_EQ(1, view->ExitedCalls());
@@ -443,8 +484,92 @@ TEST_F(WidgetTest, CheckResizeControllerEvents) {
toplevel->CloseNow();
}
+// Test view focus restoration when a widget is deactivated and re-activated.
+TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) {
+ Widget* widget1 = CreateTopLevelPlatformWidget();
+ View* view1 = new View;
+ view1->SetFocusable(true);
+ widget1->GetContentsView()->AddChildView(view1);
+
+ Widget* widget2 = CreateTopLevelPlatformWidget();
+ View* view2a = new View;
+ View* view2b = new View;
+ view2a->SetFocusable(true);
+ view2b->SetFocusable(true);
+ widget2->GetContentsView()->AddChildView(view2a);
+ widget2->GetContentsView()->AddChildView(view2b);
+
+ widget1->Show();
+ EXPECT_TRUE(widget1->IsActive());
+ view1->RequestFocus();
+ EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
+
+ widget2->Show();
+ EXPECT_TRUE(widget2->IsActive());
+ EXPECT_FALSE(widget1->IsActive());
+ EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
+ view2a->RequestFocus();
+ EXPECT_EQ(view2a, widget2->GetFocusManager()->GetFocusedView());
+ view2b->RequestFocus();
+ EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
+
+ widget1->Activate();
+ EXPECT_TRUE(widget1->IsActive());
+ EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
+ EXPECT_FALSE(widget2->IsActive());
+ EXPECT_EQ(NULL, widget2->GetFocusManager()->GetFocusedView());
+
+ widget2->Activate();
+ EXPECT_TRUE(widget2->IsActive());
+ EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
+ EXPECT_FALSE(widget1->IsActive());
+ EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
+
+ widget1->CloseNow();
+ widget2->CloseNow();
+}
+
#if defined(OS_WIN)
+// Test view focus retention when a widget's HWND is disabled and re-enabled.
+TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
+ Widget* widget = CreateTopLevelFramelessPlatformWidget();
+ widget->SetContentsView(new View);
+ for (size_t i = 0; i < 2; ++i) {
+ widget->GetContentsView()->AddChildView(new View);
+ widget->GetContentsView()->child_at(i)->SetFocusable(true);
+ }
+
+ widget->Show();
+ const HWND hwnd = HWNDForWidget(widget);
+ EXPECT_TRUE(::IsWindow(hwnd));
+ EXPECT_TRUE(::IsWindowEnabled(hwnd));
+ EXPECT_EQ(hwnd, ::GetActiveWindow());
+
+ for (int i = 0; i < widget->GetContentsView()->child_count(); ++i) {
+ SCOPED_TRACE(base::StringPrintf("Child view %d", i));
+ View* view = widget->GetContentsView()->child_at(i);
+
+ view->RequestFocus();
+ EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
+ EXPECT_FALSE(::EnableWindow(hwnd, FALSE));
+ EXPECT_FALSE(::IsWindowEnabled(hwnd));
+
+ // Oddly, disabling the HWND leaves it active with the focus unchanged.
+ EXPECT_EQ(hwnd, ::GetActiveWindow());
+ EXPECT_TRUE(widget->IsActive());
+ EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
+
+ EXPECT_TRUE(::EnableWindow(hwnd, TRUE));
+ EXPECT_TRUE(::IsWindowEnabled(hwnd));
+ EXPECT_EQ(hwnd, ::GetActiveWindow());
+ EXPECT_TRUE(widget->IsActive());
+ EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
+ }
+
+ widget->CloseNow();
+}
+
// This class subclasses the Widget class to listen for activation change
// notifications and provides accessors to return information as to whether
// the widget is active. We need this to ensure that users of the widget
@@ -473,23 +598,19 @@ class WidgetActivationTest : public Widget {
// Tests whether the widget only becomes active when the underlying window
// is really active.
-TEST_F(WidgetTest, WidgetNotActivatedOnFakeActivationMessages) {
+TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
WidgetActivationTest widget1;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-#if defined(USE_AURA)
init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
-#endif
init_params.bounds = gfx::Rect(0, 0, 200, 200);
widget1.Init(init_params);
widget1.Show();
EXPECT_EQ(true, widget1.active());
WidgetActivationTest widget2;
-#if defined(USE_AURA)
init_params.native_widget = new DesktopNativeWidgetAura(&widget2);
-#endif
widget2.Init(init_params);
widget2.Show();
EXPECT_EQ(true, widget2.active());
@@ -508,7 +629,7 @@ TEST_F(WidgetTest, WidgetNotActivatedOnFakeActivationMessages) {
}
#endif
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
// Provides functionality to create a window modal dialog.
class ModalDialogDelegate : public DialogDelegateView {
public:
@@ -527,9 +648,8 @@ class ModalDialogDelegate : public DialogDelegateView {
};
// Tests whether the focused window is set correctly when a modal window is
-// created and destroyed. When it is destroyed it should focus the owner
-// window.
-TEST_F(WidgetTest, WindowModalWindowDestroyedActivationTest) {
+// created and destroyed. When it is destroyed it should focus the owner window.
+TEST_F(WidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
// Create a top level widget.
Widget top_level_widget;
Widget::InitParams init_params =
@@ -566,7 +686,7 @@ TEST_F(WidgetTest, WindowModalWindowDestroyedActivationTest) {
}
// Test that when opening a system-modal window, capture is released.
-TEST_F(WidgetTest, SystemModalWindowReleasesCapture) {
+TEST_F(WidgetTestInteractive, SystemModalWindowReleasesCapture) {
// Create a top level widget.
Widget top_level_widget;
Widget::InitParams init_params =
@@ -604,6 +724,59 @@ TEST_F(WidgetTest, SystemModalWindowReleasesCapture) {
#endif
+TEST_F(WidgetTestInteractive, CanActivateFlagIsHonored) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ init_params.bounds = gfx::Rect(0, 0, 200, 200);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.activatable = Widget::InitParams::ACTIVATABLE_NO;
+#if !defined(OS_CHROMEOS)
+ init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+#endif // !defined(OS_CHROMEOS)
+ widget.Init(init_params);
+
+ widget.Show();
+ EXPECT_FALSE(widget.IsActive());
+}
+
+// Test that touch selection quick menu is not activated when opened.
+TEST_F(WidgetTestInteractive, TouchSelectionQuickMenuIsNotActivated) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
+#if defined(OS_WIN)
+ views_delegate().set_use_desktop_native_widgets(true);
+#endif // !defined(OS_WIN)
+
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ init_params.bounds = gfx::Rect(0, 0, 200, 200);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(init_params);
+
+ Textfield* textfield = new Textfield;
+ textfield->SetBounds(0, 0, 200, 20);
+ textfield->SetText(base::ASCIIToUTF16("some text"));
+ widget.GetRootView()->AddChildView(textfield);
+
+ widget.Show();
+ textfield->RequestFocus();
+ textfield->SelectAll(true);
+ TextfieldTestApi textfield_test_api(textfield);
+
+ RunPendingMessages();
+
+ aura::test::EventGenerator generator(widget.GetNativeView()->GetRootWindow());
+ generator.GestureTapAt(gfx::Point(10, 10));
+ ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>(
+ textfield_test_api.touch_selection_controller()));
+
+ EXPECT_TRUE(textfield->HasFocus());
+ EXPECT_TRUE(widget.IsActive());
+ EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>(
+ textfield_test_api.touch_selection_controller())));
+}
+
namespace {
// Used to veirfy OnMouseCaptureLost() has been invoked.
@@ -640,6 +813,16 @@ class WidgetCaptureTest : public ViewsTestBase {
virtual ~WidgetCaptureTest() {
}
+ virtual void SetUp() OVERRIDE {
+ gfx::GLSurface::InitializeOneOffForTests();
+ base::FilePath pak_dir;
+ PathService::Get(base::DIR_MODULE, &pak_dir);
+ base::FilePath pak_file;
+ pak_file = pak_dir.Append(FILE_PATH_LITERAL("ui_test.pak"));
+ ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file);
+ ViewsTestBase::SetUp();
+ }
+
// Verifies Widget::SetCapture() results in updating native capture along with
// invoking the right Widget function.
void TestCapture(bool use_desktop_native_widget) {
@@ -686,7 +869,7 @@ class WidgetCaptureTest : public ViewsTestBase {
private:
NativeWidget* CreateNativeWidget(bool create_desktop_native_widget,
Widget* widget) {
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
if (create_desktop_native_widget)
return new DesktopNativeWidgetAura(widget);
#endif
@@ -701,14 +884,14 @@ TEST_F(WidgetCaptureTest, Capture) {
TestCapture(false);
}
-#if defined(USE_AURA) && !defined(OS_LINUX)
+#if !defined(OS_LINUX)
// See description in TestCapture(). Creates DesktopNativeWidget.
TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) {
TestCapture(true);
}
#endif
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
namespace {
// Used to veirfy OnMouseEvent() has been invoked.
@@ -737,7 +920,7 @@ class MouseEventTrackingWidget : public Widget {
} // namespace
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// TODO(erg): linux_aura bringup: http://crbug.com/163931
#define MAYBE_MouseEventDispatchedToRightWindow \
DISABLED_MouseEventDispatchedToRightWindow
@@ -775,9 +958,10 @@ TEST_F(WidgetCaptureTest, MAYBE_MouseEventDispatchedToRightWindow) {
// Send a mouse event to the RootWindow associated with |widget1|. Even though
// |widget2| has capture, |widget1| should still get the event.
ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
- ui::EF_NONE);
- widget1.GetNativeWindow()->GetDispatcher()->AsRootWindowHostDelegate()->
- OnHostMouseEvent(&mouse_event);
+ ui::EF_NONE, ui::EF_NONE);
+ ui::EventDispatchDetails details = widget1.GetNativeWindow()->
+ GetHost()->event_processor()->OnEventFromSource(&mouse_event);
+ ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(widget1.GetAndClearGotMouseEvent());
EXPECT_FALSE(widget2.GetAndClearGotMouseEvent());
}
diff --git a/chromium/ui/views/widget/widget_observer.h b/chromium/ui/views/widget/widget_observer.h
index fc13afae682..2cad7142e25 100644
--- a/chromium/ui/views/widget/widget_observer.h
+++ b/chromium/ui/views/widget/widget_observer.h
@@ -14,6 +14,7 @@ class Rect;
namespace views {
class Widget;
+class View;
// Observers can listen to various events on the Widgets.
class VIEWS_EXPORT WidgetObserver {
diff --git a/chromium/ui/views/widget/widget_removals_observer.h b/chromium/ui/views/widget/widget_removals_observer.h
new file mode 100644
index 00000000000..e62acab36a4
--- /dev/null
+++ b/chromium/ui/views/widget/widget_removals_observer.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WIDGET_WIDGET_REMOVALS_OBSERVER_H_
+#define UI_VIEWS_WIDGET_WIDGET_REMOVALS_OBSERVER_H_
+
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class Widget;
+class View;
+
+// |WidgetRemovalsObserver| complements |WidgetObserver| with additional
+// notifications. These include events occurring during tear down like view
+// removal. For this reason, it is recommended that subclasses not also inherit
+// from |View|.
+class VIEWS_EXPORT WidgetRemovalsObserver {
+ public:
+ // Called immediately before a descendant view of |widget| is removed.
+ virtual void OnWillRemoveView(Widget* widget, View* view) {}
+
+ protected:
+ virtual ~WidgetRemovalsObserver() {}
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_WIDGET_WIDGET_REMOVALS_OBSERVER_H_
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index a243eb5f2ac..d6062067a33 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -12,7 +12,12 @@
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/point.h"
@@ -23,23 +28,10 @@
#include "ui/views/views_delegate.h"
#include "ui/views/widget/native_widget_delegate.h"
#include "ui/views/widget/root_view.h"
+#include "ui/views/widget/widget_deletion_observer.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/window/native_frame_view.h"
-#if defined(USE_AURA)
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/test/test_window_delegate.h"
-#include "ui/aura/window.h"
-#include "ui/views/widget/native_widget_aura.h"
-#if !defined(OS_CHROMEOS)
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
-#endif
-#elif defined(OS_WIN)
-#include "ui/views/widget/native_widget_win.h"
-#endif
-
#if defined(OS_WIN)
#include "ui/views/win/hwnd_util.h"
#endif
@@ -72,9 +64,6 @@ class EventCountView : public View {
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
RecordEvent(*event);
}
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
- RecordEvent(*event);
- }
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
RecordEvent(*event);
}
@@ -90,7 +79,7 @@ class EventCountView : public View {
};
// A view that keeps track of the events it receives, and consumes all scroll
-// gesture events.
+// gesture events and ui::ET_SCROLL events.
class ScrollableEventCountView : public EventCountView {
public:
ScrollableEventCountView() {}
@@ -112,6 +101,12 @@ class ScrollableEventCountView : public EventCountView {
}
}
+ virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
+ EventCountView::OnScrollEvent(event);
+ if (event->type() == ui::ET_SCROLL)
+ event->SetHandled();
+ }
+
DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView);
};
@@ -123,7 +118,7 @@ class MinimumSizeFrameView : public NativeFrameView {
private:
// Overridden from View:
- virtual gfx::Size GetMinimumSize() OVERRIDE {
+ virtual gfx::Size GetMinimumSize() const OVERRIDE {
return gfx::Size(300, 400);
}
@@ -162,34 +157,47 @@ class EventCountHandler : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
};
+// Class that closes the widget (which ends up deleting it immediately) when the
+// appropriate event is received.
+class CloseWidgetView : public View {
+ public:
+ explicit CloseWidgetView(ui::EventType event_type)
+ : event_type_(event_type) {
+ }
+
+ // ui::EventHandler override:
+ virtual void OnEvent(ui::Event* event) OVERRIDE {
+ if (event->type() == event_type_) {
+ // Go through NativeWidgetPrivate to simulate what happens if the OS
+ // deletes the NativeWindow out from under us.
+ GetWidget()->native_widget_private()->CloseNow();
+ } else {
+ View::OnEvent(event);
+ if (!event->IsTouchEvent())
+ event->SetHandled();
+ }
+ }
+
+ private:
+ const ui::EventType event_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
+};
+
ui::WindowShowState GetWidgetShowState(const Widget* widget) {
// Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
// because the former is implemented on all platforms but the latter is not.
return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN :
widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED :
widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED :
- ui::SHOW_STATE_NORMAL;
+ widget->IsActive() ? ui::SHOW_STATE_NORMAL :
+ ui::SHOW_STATE_INACTIVE;
}
TEST_F(WidgetTest, WidgetInitParams) {
- ASSERT_FALSE(views_delegate().UseTransparentWindows());
-
// Widgets are not transparent by default.
Widget::InitParams init1;
EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
-
- // Non-window widgets are not transparent either.
- Widget::InitParams init2(Widget::InitParams::TYPE_MENU);
- EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init2.opacity);
-
- // A ViewsDelegate can set windows transparent by default.
- views_delegate().SetUseTransparentWindows(true);
- Widget::InitParams init3;
- EXPECT_EQ(Widget::InitParams::TRANSLUCENT_WINDOW, init3.opacity);
-
- // Non-window widgets stay opaque.
- Widget::InitParams init4(Widget::InitParams::TYPE_MENU);
- EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init4.opacity);
}
////////////////////////////////////////////////////////////////////////////////
@@ -259,32 +267,6 @@ TEST_F(WidgetTest, Visibility) {
// |child| should be automatically destroyed with |toplevel|.
}
-#if defined(OS_WIN) && !defined(USE_AURA)
-// On Windows, it is possible to have child window that are TYPE_POPUP. Unlike
-// regular child windows, these should be created as hidden and must be shown
-// explicitly.
-TEST_F(WidgetTest, Visibility_ChildPopup) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
- Widget* child_popup = CreateChildPopupPlatformWidget(
- toplevel->GetNativeView());
-
- EXPECT_FALSE(toplevel->IsVisible());
- EXPECT_FALSE(child_popup->IsVisible());
-
- toplevel->Show();
-
- EXPECT_TRUE(toplevel->IsVisible());
- EXPECT_FALSE(child_popup->IsVisible());
-
- child_popup->Show();
-
- EXPECT_TRUE(child_popup->IsVisible());
-
- toplevel->CloseNow();
- // |child_popup| should be automatically destroyed with |toplevel|.
-}
-#endif
-
////////////////////////////////////////////////////////////////////////////////
// Widget ownership tests.
//
@@ -323,11 +305,11 @@ struct OwnershipTestState {
// A platform NativeWidget subclass that updates a bag of state when it is
// destroyed.
-class OwnershipTestNativeWidget : public NativeWidgetPlatform {
+class OwnershipTestNativeWidget : public PlatformNativeWidget {
public:
OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
OwnershipTestState* state)
- : NativeWidgetPlatform(delegate),
+ : PlatformNativeWidget(delegate),
state_(state) {
}
virtual ~OwnershipTestNativeWidget() {
@@ -342,21 +324,21 @@ class OwnershipTestNativeWidget : public NativeWidgetPlatform {
// A views NativeWidget subclass that updates a bag of state when it is
// destroyed.
-class OwnershipTestNativeWidgetPlatform : public NativeWidgetPlatformForTest {
+class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
public:
- OwnershipTestNativeWidgetPlatform(internal::NativeWidgetDelegate* delegate,
- OwnershipTestState* state)
- : NativeWidgetPlatformForTest(delegate),
+ OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
+ OwnershipTestState* state)
+ : NativeWidgetCapture(delegate),
state_(state) {
}
- virtual ~OwnershipTestNativeWidgetPlatform() {
+ virtual ~OwnershipTestNativeWidgetAura() {
state_->native_widget_deleted = true;
}
private:
OwnershipTestState* state_;
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetPlatform);
+ DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura);
};
// A Widget subclass that updates a bag of state when it is destroyed.
@@ -381,7 +363,7 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
+ new OwnershipTestNativeWidgetAura(widget.get(), &state);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -402,7 +384,7 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
+ new OwnershipTestNativeWidgetAura(widget.get(), &state);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -427,7 +409,7 @@ TEST_F(WidgetOwnershipTest,
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
+ new OwnershipTestNativeWidgetAura(widget.get(), &state);
params.parent = toplevel->GetNativeView();
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -457,7 +439,7 @@ TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget, &state);
+ new OwnershipTestNativeWidgetAura(widget, &state);
widget->Init(params);
// Now destroy the native widget.
@@ -476,7 +458,7 @@ TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget, &state);
+ new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
widget->Init(params);
@@ -500,15 +482,11 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget, &state);
+ new OwnershipTestNativeWidgetAura(widget, &state);
widget->Init(params);
// Now simulate a destroy of the platform native widget from the OS:
-#if defined(USE_AURA)
- delete widget->GetNativeView();
-#elif defined(OS_WIN)
- DestroyWindow(widget->GetNativeView());
-#endif
+ SimulateNativeDestroy(widget);
EXPECT_TRUE(state.widget_deleted);
EXPECT_TRUE(state.native_widget_deleted);
@@ -525,7 +503,7 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget, &state);
+ new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
widget->Init(params);
@@ -551,7 +529,7 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget, &state);
+ new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
widget->Init(params);
@@ -577,7 +555,7 @@ TEST_F(WidgetOwnershipTest,
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
params.native_widget =
- new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
+ new OwnershipTestNativeWidgetAura(widget.get(), &state);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.delegate = delegate_view;
widget->Init(params);
@@ -614,7 +592,6 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
widget->StackAtTop();
widget->IsClosed();
widget->Close();
- widget->Show();
widget->Hide();
widget->Activate();
widget->Deactivate();
@@ -646,11 +623,7 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
widget->ReleaseCapture();
widget->HasCapture();
widget->GetWorkAreaBoundsInScreen();
- // These three crash with NativeWidgetWin, so I'm assuming we don't need
- // them to work for the other NativeWidget impls.
- // widget->CenterWindow(gfx::Size(50, 60));
- // widget->GetRestoredBounds();
- // widget->ShowInactive();
+ widget->IsTranslucentWindowOpacitySupported();
}
private:
@@ -668,11 +641,11 @@ TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
widget.native_widget_private()->CloseNow();
InvokeWidgetMethods(&widget);
}
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
{
Widget widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new DesktopNativeWidgetAura(&widget);
+ params.native_widget = new PlatformDesktopNativeWidget(&widget);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(params);
widget.Show();
@@ -852,7 +825,7 @@ TEST_F(WidgetObserverTest, WidgetBoundsChanged) {
EXPECT_EQ(child2, widget_bounds_changed());
}
-#if !defined(USE_AURA) && defined(OS_WIN)
+#if defined(false)
// Aura needs shell to maximize/fullscreen window.
// NativeWidgetGtk doesn't implement GetRestoredBounds.
TEST_F(WidgetTest, GetRestoredBounds) {
@@ -892,26 +865,21 @@ TEST_F(WidgetTest, ExitFullscreenRestoreState) {
EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
toplevel->SetFullscreen(true);
- while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_FULLSCREEN)
- RunPendingMessages();
+ EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
toplevel->SetFullscreen(false);
- while (GetWidgetShowState(toplevel) == ui::SHOW_STATE_FULLSCREEN)
- RunPendingMessages();
+ EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
// And it should still be in normal state after getting out of full screen.
EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
// Now, make it maximized.
toplevel->Maximize();
- while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_MAXIMIZED)
- RunPendingMessages();
+ EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
toplevel->SetFullscreen(true);
- while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_FULLSCREEN)
- RunPendingMessages();
+ EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
toplevel->SetFullscreen(false);
- while (GetWidgetShowState(toplevel) == ui::SHOW_STATE_FULLSCREEN)
- RunPendingMessages();
+ EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
// And it stays maximized after getting out of full screen.
EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
@@ -921,7 +889,6 @@ TEST_F(WidgetTest, ExitFullscreenRestoreState) {
RunPendingMessages();
}
-#if defined(USE_AURA)
// The key-event propagation from Widget happens differently on aura and
// non-aura systems because of the difference in IME. So this test works only on
// aura.
@@ -930,7 +897,7 @@ TEST_F(WidgetTest, KeyboardInputEvent) {
View* container = toplevel->client_view();
Textfield* textfield = new Textfield();
- textfield->SetText(ASCIIToUTF16("some text"));
+ textfield->SetText(base::ASCIIToUTF16("some text"));
container->AddChildView(textfield);
toplevel->Show();
textfield->RequestFocus();
@@ -959,7 +926,7 @@ TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
#if !defined(OS_CHROMEOS)
- init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
#endif
widget.Init(init_params);
widget.SetContentsView(contents_view);
@@ -985,6 +952,36 @@ TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
EXPECT_TRUE(contents_view->HasFocus());
}
+class TestBubbleDelegateView : public BubbleDelegateView {
+ public:
+ TestBubbleDelegateView(View* anchor)
+ : BubbleDelegateView(anchor, BubbleBorder::NONE),
+ reset_controls_called_(false) {}
+ virtual ~TestBubbleDelegateView() {}
+
+ virtual bool ShouldShowCloseButton() const OVERRIDE {
+ reset_controls_called_ = true;
+ return true;
+ }
+
+ mutable bool reset_controls_called_;
+};
+
+TEST_F(WidgetTest, BubbleControlsResetOnInit) {
+ Widget* anchor = CreateTopLevelPlatformWidget();
+ anchor->Show();
+
+ TestBubbleDelegateView* bubble_delegate =
+ new TestBubbleDelegateView(anchor->client_view());
+ Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
+ EXPECT_TRUE(bubble_delegate->reset_controls_called_);
+ bubble_widget->Show();
+ bubble_widget->CloseNow();
+
+ anchor->Hide();
+ anchor->CloseNow();
+}
+
// Desktop native widget Aura tests are for non Chrome OS platforms.
#if !defined(OS_CHROMEOS)
// Test to ensure that after minimize, view width is set to zero.
@@ -997,7 +994,7 @@ TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
gfx::Rect initial_bounds(0, 0, 300, 400);
init_params.bounds = initial_bounds;
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
widget.Init(init_params);
NonClientView* non_client_view = widget.non_client_view();
NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
@@ -1051,7 +1048,7 @@ class DesktopAuraTestValidPaintWidget : public views::Widget {
bool received_paint_while_hidden_;
};
-TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterCloseTest) {
+TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
View* contents_view = new View;
contents_view->SetFocusable(true);
DesktopAuraTestValidPaintWidget widget;
@@ -1059,7 +1056,7 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterCloseTest) {
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
widget.Init(init_params);
widget.SetContentsView(contents_view);
widget.Show();
@@ -1071,7 +1068,7 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterCloseTest) {
EXPECT_FALSE(widget.received_paint_while_hidden());
}
-TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterHideTest) {
+TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) {
View* contents_view = new View;
contents_view->SetFocusable(true);
DesktopAuraTestValidPaintWidget widget;
@@ -1079,7 +1076,7 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterHideTest) {
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
widget.Init(init_params);
widget.SetContentsView(contents_view);
widget.Show();
@@ -1092,170 +1089,6 @@ TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterHideTest) {
widget.Close();
}
-// This class provides functionality to create fullscreen and top level popup
-// windows. It additionally tests whether the destruction of these windows
-// occurs correctly in desktop AURA without crashing.
-// It provides facilities to test the following cases:-
-// 1. Child window destroyed which should lead to the destruction of the
-// parent.
-// 2. Parent window destroyed which should lead to the child being destroyed.
-class DesktopAuraTopLevelWindowTest
- : public views::TestViewsDelegate,
- public aura::WindowObserver {
- public:
- DesktopAuraTopLevelWindowTest()
- : top_level_widget_(NULL),
- owned_window_(NULL),
- owner_destroyed_(false),
- owned_window_destroyed_(false) {}
-
- virtual ~DesktopAuraTopLevelWindowTest() {
- EXPECT_TRUE(owner_destroyed_);
- EXPECT_TRUE(owned_window_destroyed_);
- top_level_widget_ = NULL;
- owned_window_ = NULL;
- }
-
- // views::TestViewsDelegate overrides.
- virtual void OnBeforeWidgetInit(
- Widget::InitParams* params,
- internal::NativeWidgetDelegate* delegate) OVERRIDE {
- if (!params->native_widget)
- params->native_widget = new views::DesktopNativeWidgetAura(delegate);
- }
-
- void CreateTopLevelWindow(const gfx::Rect& bounds, bool fullscreen) {
- Widget::InitParams init_params;
- init_params.type = Widget::InitParams::TYPE_WINDOW;
- init_params.bounds = bounds;
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.layer_type = ui::LAYER_NOT_DRAWN;
- init_params.accept_events = fullscreen;
-
- widget_.Init(init_params);
-
- owned_window_ = new aura::Window(&child_window_delegate_);
- owned_window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
- owned_window_->SetName("TestTopLevelWindow");
- if (fullscreen) {
- owned_window_->SetProperty(aura::client::kShowStateKey,
- ui::SHOW_STATE_FULLSCREEN);
- } else {
- owned_window_->SetType(aura::client::WINDOW_TYPE_MENU);
- }
- owned_window_->Init(ui::LAYER_TEXTURED);
- aura::client::ParentWindowWithContext(
- owned_window_,
- widget_.GetNativeView()->GetRootWindow(),
- gfx::Rect(0, 0, 1900, 1600));
- owned_window_->Show();
- owned_window_->AddObserver(this);
-
- ASSERT_TRUE(owned_window_->parent() != NULL);
- owned_window_->parent()->AddObserver(this);
-
- top_level_widget_ =
- views::Widget::GetWidgetForNativeView(owned_window_->parent());
- ASSERT_TRUE(top_level_widget_ != NULL);
- }
-
- void DestroyOwnedWindow() {
- ASSERT_TRUE(owned_window_ != NULL);
- delete owned_window_;
- }
-
- void DestroyOwnerWindow() {
- ASSERT_TRUE(top_level_widget_ != NULL);
- top_level_widget_->CloseNow();
- }
-
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- window->RemoveObserver(this);
- if (window == owned_window_) {
- owned_window_destroyed_ = true;
- } else if (window == top_level_widget_->GetNativeView()) {
- owner_destroyed_ = true;
- } else {
- ADD_FAILURE() << "Unexpected window destroyed callback: " << window;
- }
- }
-
- aura::Window* owned_window() {
- return owned_window_;
- }
-
- views::Widget* top_level_widget() {
- return top_level_widget_;
- }
-
- private:
- views::Widget widget_;
- views::Widget* top_level_widget_;
- aura::Window* owned_window_;
- bool owner_destroyed_;
- bool owned_window_destroyed_;
- aura::test::TestWindowDelegate child_window_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(DesktopAuraTopLevelWindowTest);
-};
-
-TEST_F(WidgetTest, DesktopAuraFullscreenWindowDestroyedBeforeOwnerTest) {
- ViewsDelegate::views_delegate = NULL;
- DesktopAuraTopLevelWindowTest fullscreen_window;
- ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
- gfx::Rect(0, 0, 200, 200), true));
-
- RunPendingMessages();
- ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnedWindow());
- RunPendingMessages();
-}
-
-TEST_F(WidgetTest, DesktopAuraFullscreenWindowOwnerDestroyed) {
- ViewsDelegate::views_delegate = NULL;
-
- DesktopAuraTopLevelWindowTest fullscreen_window;
- ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
- gfx::Rect(0, 0, 200, 200), true));
-
- RunPendingMessages();
- ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnerWindow());
- RunPendingMessages();
-}
-
-TEST_F(WidgetTest, DesktopAuraTopLevelOwnedPopupTest) {
- ViewsDelegate::views_delegate = NULL;
- DesktopAuraTopLevelWindowTest popup_window;
- ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow(
- gfx::Rect(0, 0, 200, 200), false));
-
- RunPendingMessages();
- ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow());
- RunPendingMessages();
-}
-
-#if defined(OS_WIN)
-// TODO(ananta)
-// Fix this test to work on Linux Aura. Need to implement the
-// views::DesktopRootWindowHostX11::SetSize function
-// This test validates that when a top level owned popup Aura window is
-// resized, the widget is resized as well.
-TEST_F(WidgetTest, DesktopAuraTopLevelOwnedPopupResizeTest) {
- ViewsDelegate::views_delegate = NULL;
- DesktopAuraTopLevelWindowTest popup_window;
- ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow(
- gfx::Rect(0, 0, 200, 200), false));
-
- gfx::Rect new_size(0, 0, 400, 400);
- popup_window.owned_window()->SetBounds(new_size);
-
- EXPECT_EQ(popup_window.top_level_widget()->GetNativeView()->bounds().size(),
- new_size.size());
- RunPendingMessages();
- ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow());
- RunPendingMessages();
-}
-#endif
-
// Test to ensure that the aura Window's visiblity state is set to visible if
// the underlying widget is hidden and then shown.
TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
@@ -1267,16 +1100,16 @@ TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
gfx::Rect initial_bounds(0, 0, 300, 400);
init_params.bounds = initial_bounds;
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
widget.Init(init_params);
NonClientView* non_client_view = widget.non_client_view();
NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
non_client_view->SetFrameView(frame_view);
widget.Hide();
- EXPECT_FALSE(widget.GetNativeView()->IsVisible());
+ EXPECT_FALSE(IsNativeWindowVisible(widget.GetNativeWindow()));
widget.Show();
- EXPECT_TRUE(widget.GetNativeView()->IsVisible());
+ EXPECT_TRUE(IsNativeWindowVisible(widget.GetNativeWindow()));
}
// The following code verifies we can correctly destroy a Widget from a mouse
@@ -1284,84 +1117,38 @@ TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
// nested message loops from such events, nor has the code ever really dealt
// with this situation.
-// Class that closes the widget (which ends up deleting it immediately) when the
-// appropriate event is received.
-class CloseWidgetView : public View {
- public:
- explicit CloseWidgetView(ui::EventType event_type)
- : event_type_(event_type) {
- }
-
- // View overrides:
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
- if (!CloseWidget(event))
- View::OnMousePressed(event);
- return true;
- }
- virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE {
- if (!CloseWidget(event))
- View::OnMouseDragged(event);
- return true;
- }
- virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE {
- if (!CloseWidget(event))
- View::OnMouseReleased(event);
- }
- virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE {
- if (!CloseWidget(event))
- View::OnMouseMoved(event);
- }
- virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
- if (!CloseWidget(event))
- View::OnMouseEntered(event);
- }
-
- private:
- bool CloseWidget(const ui::LocatedEvent& event) {
- if (event.type() == event_type_) {
- // Go through NativeWidgetPrivate to simulate what happens if the OS
- // deletes the NativeWindow out from under us.
- GetWidget()->native_widget_private()->CloseNow();
- return true;
- }
- return false;
- }
-
- const ui::EventType event_type_;
-
- DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
-};
-
// Generates two moves (first generates enter, second real move), a press, drag
// and release stopping at |last_event_type|.
void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) {
const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen());
ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(),
- screen_bounds.CenterPoint(), 0);
- aura::RootWindowHostDelegate* rwhd =
- widget->GetNativeWindow()->GetDispatcher()->AsRootWindowHostDelegate();
- rwhd->OnHostMouseEvent(&move_event);
- if (last_event_type == ui::ET_MOUSE_ENTERED)
+ screen_bounds.CenterPoint(), 0, 0);
+ ui::EventProcessor* dispatcher = WidgetTest::GetEventProcessor(widget);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move_event);
+ if (last_event_type == ui::ET_MOUSE_ENTERED || details.dispatcher_destroyed)
return;
- rwhd->OnHostMouseEvent(&move_event);
- if (last_event_type == ui::ET_MOUSE_MOVED)
+ details = dispatcher->OnEventFromSource(&move_event);
+ if (last_event_type == ui::ET_MOUSE_MOVED || details.dispatcher_destroyed)
return;
ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(),
- screen_bounds.CenterPoint(), 0);
- rwhd->OnHostMouseEvent(&press_event);
- if (last_event_type == ui::ET_MOUSE_PRESSED)
+ screen_bounds.CenterPoint(), 0, 0);
+ details = dispatcher->OnEventFromSource(&press_event);
+ if (last_event_type == ui::ET_MOUSE_PRESSED || details.dispatcher_destroyed)
return;
gfx::Point end_point(screen_bounds.CenterPoint());
end_point.Offset(1, 1);
- ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0);
- rwhd->OnHostMouseEvent(&drag_event);
- if (last_event_type == ui::ET_MOUSE_DRAGGED)
+ ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0, 0);
+ details = dispatcher->OnEventFromSource(&drag_event);
+ if (last_event_type == ui::ET_MOUSE_DRAGGED || details.dispatcher_destroyed)
return;
- ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0);
- rwhd->OnHostMouseEvent(&release_event);
+ ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0,
+ 0);
+ details = dispatcher->OnEventFromSource(&release_event);
+ if (details.dispatcher_destroyed)
+ return;
}
// Creates a widget and invokes GenerateMouseEvents() with |last_event_type|.
@@ -1371,7 +1158,7 @@ void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
Widget* widget = new Widget;
Widget::InitParams params =
test->CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new DesktopNativeWidgetAura(widget);
+ params.native_widget = new PlatformDesktopNativeWidget(widget);
params.bounds = gfx::Rect(0, 0, 50, 100);
widget->Init(params);
widget->SetContentsView(new CloseWidgetView(last_event_type));
@@ -1430,8 +1217,6 @@ TEST_F(WidgetTest, WheelEventsFromScrollEventTarget) {
widget->CloseNow();
}
-#endif // defined(USE_AURA)
-
// Tests that if a scroll-begin gesture is not handled, then subsequent scroll
// events are not dispatched to any view.
TEST_F(WidgetTest, GestureScrollEventDispatching) {
@@ -1493,13 +1278,15 @@ TEST_F(WidgetTest, GestureScrollEventDispatching) {
}
// Tests that event-handlers installed on the RootView get triggered correctly.
+// TODO(tdanderson): Clean up this test as part of crbug.com/355680.
TEST_F(WidgetTest, EventHandlersOnRootView) {
Widget* widget = CreateTopLevelNativeWidget();
View* root_view = widget->GetRootView();
- EventCountView* view = new EventCountView;
+ scoped_ptr<EventCountView> view(new EventCountView());
+ view->set_owned_by_client();
view->SetBounds(0, 0, 20, 20);
- root_view->AddChildView(view);
+ root_view->AddChildView(view.get());
EventCountHandler h1;
root_view->AddPreTargetHandler(&h1);
@@ -1510,16 +1297,6 @@ TEST_F(WidgetTest, EventHandlersOnRootView) {
widget->SetBounds(gfx::Rect(0, 0, 100, 100));
widget->Show();
- ui::TouchEvent pressed(ui::ET_TOUCH_PRESSED,
- gfx::Point(10, 10),
- 0, 0,
- ui::EventTimeForNow(),
- 1.0, 0.0, 1.0, 0.0);
- widget->OnTouchEvent(&pressed);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_TOUCH_PRESSED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_TOUCH_PRESSED));
- EXPECT_EQ(1, h2.GetEventCount(ui::ET_TOUCH_PRESSED));
-
ui::GestureEvent begin(ui::ET_GESTURE_BEGIN,
5, 5, 0, ui::EventTimeForNow(),
ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1);
@@ -1531,16 +1308,6 @@ TEST_F(WidgetTest, EventHandlersOnRootView) {
EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_BEGIN));
EXPECT_EQ(1, h2.GetEventCount(ui::ET_GESTURE_BEGIN));
- ui::TouchEvent released(ui::ET_TOUCH_RELEASED,
- gfx::Point(10, 10),
- 0, 0,
- ui::EventTimeForNow(),
- 1.0, 0.0, 1.0, 0.0);
- widget->OnTouchEvent(&released);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_TOUCH_RELEASED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_TOUCH_RELEASED));
- EXPECT_EQ(1, h2.GetEventCount(ui::ET_TOUCH_RELEASED));
-
widget->OnGestureEvent(&end);
EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_END));
EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_END));
@@ -1554,9 +1321,67 @@ TEST_F(WidgetTest, EventHandlersOnRootView) {
0, 20,
2);
widget->OnScrollEvent(&scroll);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
+ EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL));
EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(1, h2.GetEventCount(ui::ET_SCROLL));
+ EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL));
+
+ // Unhandled scroll events are turned into wheel events and re-dispatched.
+ EXPECT_EQ(1, h1.GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(1, h2.GetEventCount(ui::ET_MOUSEWHEEL));
+
+ h1.ResetCounts();
+ view->ResetCounts();
+ h2.ResetCounts();
+
+ ui::ScrollEvent fling(ui::ET_SCROLL_FLING_START,
+ gfx::Point(5, 5),
+ ui::EventTimeForNow(),
+ 0,
+ 0, 20,
+ 0, 20,
+ 2);
+ widget->OnScrollEvent(&fling);
+ EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL_FLING_START));
+ EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL_FLING_START));
+ EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL_FLING_START));
+
+ // Unhandled scroll events which are not of type ui::ET_SCROLL should not
+ // be turned into wheel events and re-dispatched.
+ EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
+
+ h1.ResetCounts();
+ view->ResetCounts();
+ h2.ResetCounts();
+
+ // Replace the child of |root_view| with a ScrollableEventCountView so that
+ // ui::ET_SCROLL events are marked as handled at the target phase.
+ root_view->RemoveChildView(view.get());
+ ScrollableEventCountView* scroll_view = new ScrollableEventCountView;
+ scroll_view->SetBounds(0, 0, 20, 20);
+ root_view->AddChildView(scroll_view);
+
+ ui::ScrollEvent consumed_scroll(ui::ET_SCROLL,
+ gfx::Point(5, 5),
+ ui::EventTimeForNow(),
+ 0,
+ 0, 20,
+ 0, 20,
+ 2);
+ widget->OnScrollEvent(&consumed_scroll);
+
+ // The event is handled at the target phase and should not reach the
+ // post-target handler.
+ EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
+ EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_SCROLL));
+ EXPECT_EQ(0, h2.GetEventCount(ui::ET_SCROLL));
+
+ // Handled scroll events are not turned into wheel events and re-dispatched.
+ EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(0, scroll_view->GetEventCount(ui::ET_MOUSEWHEEL));
+ EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
widget->CloseNow();
}
@@ -1574,7 +1399,7 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
gfx::Point cursor_location(5, 5);
ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location,
- ui::EF_NONE);
+ ui::EF_NONE, ui::EF_NONE);
widget->OnMouseEvent(&move);
EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED));
@@ -1621,8 +1446,8 @@ TEST_F(WidgetTest, SingleWindowClosing) {
CreateParams(Widget::InitParams::TYPE_WINDOW);
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.delegate = delegate.get();
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
- init_params.native_widget = new DesktopNativeWidgetAura(widget);
+#if !defined(OS_CHROMEOS)
+ init_params.native_widget = new PlatformDesktopNativeWidget(widget);
#endif
widget->Init(init_params);
EXPECT_EQ(0, delegate->count());
@@ -1638,9 +1463,9 @@ class WidgetWindowTitleTest : public WidgetTest {
CreateParams(Widget::InitParams::TYPE_WINDOW);
widget->Init(init_params);
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
if (desktop_native_widget)
- init_params.native_widget = new DesktopNativeWidgetAura(widget);
+ init_params.native_widget = new PlatformDesktopNativeWidget(widget);
#else
DCHECK(!desktop_native_widget)
<< "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
@@ -1649,10 +1474,10 @@ class WidgetWindowTitleTest : public WidgetTest {
internal::NativeWidgetPrivate* native_widget =
widget->native_widget_private();
- string16 empty;
- string16 s1(UTF8ToUTF16("Title1"));
- string16 s2(UTF8ToUTF16("Title2"));
- string16 s3(UTF8ToUTF16("TitleLong"));
+ base::string16 empty;
+ base::string16 s1(base::UTF8ToUTF16("Title1"));
+ base::string16 s2(base::UTF8ToUTF16("Title2"));
+ base::string16 s3(base::UTF8ToUTF16("TitleLong"));
// The widget starts with no title, setting empty should not change
// anything.
@@ -1679,85 +1504,50 @@ TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_NativeWidget) {
}
// DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
// Override to use a DesktopNativeWidget.
bool desktop_native_widget = true;
RunTest(desktop_native_widget);
}
-#endif // USE_AURA && !OS_CHROMEOS
+#endif // !OS_CHROMEOS
-// Used by SetTopLevelCorrectly to track calls to OnBeforeWidgetInit().
-class VerifyTopLevelDelegate : public TestViewsDelegate {
- public:
- VerifyTopLevelDelegate()
- : on_before_init_called_(false),
- is_top_level_(false) {
- }
-
- bool on_before_init_called() const { return on_before_init_called_; }
- bool is_top_level() const { return is_top_level_; }
-
- virtual void OnBeforeWidgetInit(
- Widget::InitParams* params,
- internal::NativeWidgetDelegate* delegate) OVERRIDE {
- on_before_init_called_ = true;
- is_top_level_ = params->top_level;
- }
-
- private:
- bool on_before_init_called_;
- bool is_top_level_;
-
- DISALLOW_COPY_AND_ASSIGN(VerifyTopLevelDelegate);
-};
-
-// Verifies |top_level| is correctly passed to
-// ViewsDelegate::OnBeforeWidgetInit().
-TEST_F(WidgetTest, SetTopLevelCorrectly) {
- set_views_delegate(NULL);
- VerifyTopLevelDelegate* delegate = new VerifyTopLevelDelegate;
- set_views_delegate(delegate); // ViewsTestBase takes ownership.
- scoped_ptr<Widget> widget(new Widget);
+TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
+ Widget* widget = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
- EXPECT_TRUE(delegate->on_before_init_called());
- EXPECT_TRUE(delegate->is_top_level());
-}
-// A scumbag View that deletes its owning widget OnMousePressed.
-class WidgetDeleterView : public View {
- public:
- WidgetDeleterView() : View() {}
+ widget->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED));
- // Overridden from View.
- virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
- delete GetWidget();
- return true;
- }
+ widget->SetSize(gfx::Size(100, 100));
+ widget->Show();
- private:
- DISALLOW_COPY_AND_ASSIGN(WidgetDeleterView);
-};
+ aura::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
-TEST_F(WidgetTest, TestWidgetDeletedInOnMousePressed) {
+ WidgetDeletionObserver deletion_observer(widget);
+ generator.ClickLeftButton();
+ EXPECT_FALSE(deletion_observer.IsWidgetAlive());
+
+ // Yay we did not crash!
+}
+
+TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
Widget* widget = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
- widget->SetContentsView(new WidgetDeleterView);
+ widget->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN));
widget->SetSize(gfx::Size(100, 100));
widget->Show();
- gfx::Point click_location(45, 15);
- ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON);
- widget->OnMouseEvent(&press);
+ aura::test::EventGenerator generator(GetContext());
+
+ WidgetDeletionObserver deletion_observer(widget);
+ generator.GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
+ EXPECT_FALSE(deletion_observer.IsWidgetAlive());
// Yay we did not crash!
}
@@ -1794,9 +1584,9 @@ bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
Widget::InitParams params(in_params);
// Deletes itself when the Widget is destroyed.
params.delegate = new GetNativeThemeFromDestructorView;
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
if (is_first_run) {
- params.native_widget = new DesktopNativeWidgetAura(widget);
+ params.native_widget = new PlatformDesktopNativeWidget(widget);
needs_second_run = true;
}
#endif
@@ -1843,8 +1633,8 @@ TEST_F(WidgetTest, CloseDestroys) {
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_MENU);
params.opacity = Widget::InitParams::OPAQUE_WINDOW;
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
- params.native_widget = new DesktopNativeWidgetAura(widget);
+#if !defined(OS_CHROMEOS)
+ params.native_widget = new PlatformDesktopNativeWidget(widget);
#endif
widget->Init(params);
widget->Show();
@@ -1860,6 +1650,24 @@ TEST_F(WidgetTest, CloseDestroys) {
}
}
+// Tests that killing a widget while animating it does not crash.
+TEST_F(WidgetTest, CloseWidgetWhileAnimating) {
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget->Init(params);
+
+ // Normal animations for tests have ZERO_DURATION, make sure we are actually
+ // animating the movement.
+ ui::ScopedAnimationDurationScaleMode animation_scale_mode(
+ ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+ ui::ScopedLayerAnimationSettings animation_settings(
+ widget->GetLayer()->GetAnimator());
+ widget->Show();
+ // Animate the bounds change.
+ widget->SetBounds(gfx::Rect(0, 0, 200, 200));
+}
+
// A view that consumes mouse-pressed event and gesture-tap-down events.
class RootViewTestView : public View {
public:
@@ -1899,7 +1707,7 @@ TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
gfx::Point click_location(45, 15);
ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON);
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
widget->OnMouseEvent(&press);
EXPECT_EQ(view, GetMousePressedHandler(root_view));
widget->Hide();
@@ -1909,7 +1717,7 @@ TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
widget->Show();
EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
gfx::Point move_location(45, 15);
- ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0);
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0, 0);
widget->OnMouseEvent(&move);
EXPECT_EQ(view, GetMouseMoveHandler(root_view));
widget->Hide();
@@ -1934,6 +1742,33 @@ TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
widget->Close();
}
+class GestureEndConsumerView : public View {
+ private:
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ if (event->type() == ui::ET_GESTURE_END)
+ event->SetHandled();
+ }
+};
+
+TEST_F(WidgetTest, GestureHandlerNotSetOnGestureEnd) {
+ Widget* widget = CreateTopLevelNativeWidget();
+ widget->SetBounds(gfx::Rect(0, 0, 300, 300));
+ View* view = new GestureEndConsumerView();
+ view->SetBounds(0, 0, 300, 300);
+ internal::RootView* root_view =
+ static_cast<internal::RootView*>(widget->GetRootView());
+ root_view->AddChildView(view);
+
+ widget->Show();
+ EXPECT_EQ(NULL, GetGestureHandler(root_view));
+ ui::GestureEvent end(ui::ET_GESTURE_END, 15, 15, 0, base::TimeDelta(),
+ ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
+ widget->OnGestureEvent(&end);
+ EXPECT_EQ(NULL, GetGestureHandler(root_view));
+
+ widget->Close();
+}
+
// Test the result of Widget::GetAllChildWidgets().
TEST_F(WidgetTest, GetAllChildWidgets) {
// Create the following widget hierarchy:
@@ -2001,9 +1836,9 @@ class WidgetChildDestructionTest : public WidgetTest {
Widget* top_level = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
if (top_level_has_desktop_native_widget_aura)
- params.native_widget = new DesktopNativeWidgetAura(top_level);
+ params.native_widget = new PlatformDesktopNativeWidget(top_level);
#endif
top_level->Init(params);
top_level->GetRootView()->AddChildView(
@@ -2014,9 +1849,9 @@ class WidgetChildDestructionTest : public WidgetTest {
Widget::InitParams child_params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
child_params.parent = top_level->GetNativeView();
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
if (child_has_desktop_native_widget_aura)
- child_params.native_widget = new DesktopNativeWidgetAura(child);
+ child_params.native_widget = new PlatformDesktopNativeWidget(child);
#endif
child->Init(child_params);
child->GetRootView()->AddChildView(
@@ -2036,7 +1871,7 @@ class WidgetChildDestructionTest : public WidgetTest {
DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest);
};
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
// See description of RunDestroyChildWidgetsTest(). Parent uses
// DesktopNativeWidgetAura.
TEST_F(WidgetChildDestructionTest,
@@ -2050,14 +1885,14 @@ TEST_F(WidgetChildDestructionTest,
DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
RunDestroyChildWidgetsTest(true, true);
}
-#endif
+#endif // !defined(OS_CHROMEOS)
// See description of RunDestroyChildWidgetsTest().
TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
RunDestroyChildWidgetsTest(false, false);
}
-#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+#if !defined(OS_CHROMEOS)
// Provides functionality to create a window modal dialog.
class ModalDialogDelegate : public DialogDelegateView {
public:
@@ -2084,7 +1919,8 @@ TEST_F(WidgetTest, WindowMouseModalityTest) {
gfx::Rect initial_bounds(0, 0, 500, 500);
init_params.bounds = initial_bounds;
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
+ init_params.native_widget =
+ new PlatformDesktopNativeWidget(&top_level_widget);
top_level_widget.Init(init_params);
top_level_widget.Show();
EXPECT_TRUE(top_level_widget.IsVisible());
@@ -2098,9 +1934,11 @@ TEST_F(WidgetTest, WindowMouseModalityTest) {
ui::MouseEvent move_main(ui::ET_MOUSE_MOVED,
cursor_location_main,
cursor_location_main,
+ ui::EF_NONE,
ui::EF_NONE);
- top_level_widget.GetNativeView()->GetDispatcher()->
- AsRootWindowHostDelegate()->OnHostMouseEvent(&move_main);
+ ui::EventDispatchDetails details =
+ GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main);
+ ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED));
widget_view->ResetCounts();
@@ -2112,7 +1950,7 @@ TEST_F(WidgetTest, WindowMouseModalityTest) {
ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
- dialog_delegate, NULL, top_level_widget.GetNativeWindow());
+ dialog_delegate, NULL, top_level_widget.GetNativeView());
modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
EventCountView* dialog_widget_view = new EventCountView();
dialog_widget_view->SetBounds(0, 0, 50, 50);
@@ -2124,9 +1962,11 @@ TEST_F(WidgetTest, WindowMouseModalityTest) {
ui::MouseEvent mouse_down_dialog(ui::ET_MOUSE_PRESSED,
cursor_location_dialog,
cursor_location_dialog,
+ ui::EF_NONE,
ui::EF_NONE);
- top_level_widget.GetNativeView()->GetDispatcher()->
- AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_down_dialog);
+ details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
+ &mouse_down_dialog);
+ ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED));
// Send a mouse move message to the main window. It should not be received by
@@ -2135,16 +1975,17 @@ TEST_F(WidgetTest, WindowMouseModalityTest) {
ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED,
cursor_location_main2,
cursor_location_main2,
+ ui::EF_NONE,
ui::EF_NONE);
- top_level_widget.GetNativeView()->GetDispatcher()->
- AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_down_main);
+ details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
+ &mouse_down_main);
+ ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED));
modal_dialog_widget->CloseNow();
top_level_widget.CloseNow();
}
-#if defined(USE_AURA)
// Verifies nativeview visbility matches that of Widget visibility when
// SetFullscreen is invoked.
TEST_F(WidgetTest, FullscreenStatePropagated) {
@@ -2159,23 +2000,23 @@ TEST_F(WidgetTest, FullscreenStatePropagated) {
top_level_widget.Init(init_params);
top_level_widget.SetFullscreen(true);
EXPECT_EQ(top_level_widget.IsVisible(),
- top_level_widget.GetNativeView()->IsVisible());
+ IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
top_level_widget.CloseNow();
}
#if !defined(OS_CHROMEOS)
{
Widget top_level_widget;
- init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
+ init_params.native_widget =
+ new PlatformDesktopNativeWidget(&top_level_widget);
top_level_widget.Init(init_params);
top_level_widget.SetFullscreen(true);
EXPECT_EQ(top_level_widget.IsVisible(),
- top_level_widget.GetNativeView()->IsVisible());
+ IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
top_level_widget.CloseNow();
}
#endif
}
-#endif
#if defined(OS_WIN)
@@ -2268,8 +2109,67 @@ TEST_F(WidgetTest, WindowModalityActivationTest) {
modal_dialog_widget->CloseNow();
top_level_widget.CloseNow();
}
-#endif
-#endif
+#endif // defined(OS_WIN)
+#endif // !defined(OS_CHROMEOS)
+
+TEST_F(WidgetTest, ShowCreatesActiveWindow) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+
+ widget->Show();
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
+
+ widget->CloseNow();
+}
+
+TEST_F(WidgetTest, ShowInactive) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+
+ widget->ShowInactive();
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_INACTIVE);
+
+ widget->CloseNow();
+}
+
+TEST_F(WidgetTest, ShowInactiveAfterShow) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+
+ widget->Show();
+ widget->ShowInactive();
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
+
+ widget->CloseNow();
+}
+
+TEST_F(WidgetTest, ShowAfterShowInactive) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+
+ widget->ShowInactive();
+ widget->Show();
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
+
+ widget->CloseNow();
+}
+
+#if !defined(OS_CHROMEOS)
+TEST_F(WidgetTest, InactiveWidgetDoesNotGrabActivation) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+ widget->Show();
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
+
+ Widget widget2;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.native_widget = new PlatformDesktopNativeWidget(&widget2);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget2.Init(params);
+ widget2.Show();
+
+ EXPECT_EQ(GetWidgetShowState(&widget2), ui::SHOW_STATE_INACTIVE);
+ EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
+
+ widget->CloseNow();
+ widget2.CloseNow();
+}
+#endif // !defined(OS_CHROMEOS)
namespace {
@@ -2359,7 +2259,7 @@ TEST_F(WidgetTest, IsActiveFromDestroy) {
Widget parent_widget;
Widget::InitParams parent_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
- parent_params.native_widget = new DesktopNativeWidgetAura(&parent_widget);
+ parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget);
parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
parent_widget.Init(parent_params);
parent_widget.Show();
@@ -2375,7 +2275,7 @@ TEST_F(WidgetTest, IsActiveFromDestroy) {
parent_widget.CloseNow();
}
-#endif
+#endif // !defined(OS_CHROMEOS)
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/window_reorderer_unittest.cc b/chromium/ui/views/widget/window_reorderer_unittest.cc
index 1d9566c916e..67cf246e73a 100644
--- a/chromium/ui/views/widget/window_reorderer_unittest.cc
+++ b/chromium/ui/views/widget/window_reorderer_unittest.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_event_dispatcher.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/test/test_layers.h"
#include "ui/views/view.h"
diff --git a/chromium/ui/views/win/DEPS b/chromium/ui/views/win/DEPS
index 2365859be11..8cab1708ab1 100644
--- a/chromium/ui/views/win/DEPS
+++ b/chromium/ui/views/win/DEPS
@@ -19,9 +19,7 @@ include_rules = [
"+ui/views/ime/input_method_delegate.h",
"+ui/views/views_delegate.h",
"+ui/views/views_export.h",
- "+ui/views/widget/child_window_message_processor.h",
"+ui/views/widget/monitor_win.h",
- "+ui/views/widget/native_widget_win.h",
"+ui/views/widget/widget_hwnd_utils.h",
"+ui/views/win",
]
diff --git a/chromium/ui/views/win/appbar.cc b/chromium/ui/views/win/appbar.cc
deleted file mode 100644
index 92151d47756..00000000000
--- a/chromium/ui/views/win/appbar.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/win/appbar.h"
-
-#include <shellapi.h>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/threading/worker_pool.h"
-#include "base/win/scoped_com_initializer.h"
-#include "ui/views/widget/monitor_win.h"
-
-namespace views {
-
-namespace {
-
-void GetEdgesOnWorkerThread(HMONITOR monitor, int* edge) {
- base::win::ScopedCOMInitializer com_initializer;
- *edge = 0;
- if (GetTopmostAutoHideTaskbarForEdge(ABE_LEFT, monitor))
- *edge = Appbar::EDGE_LEFT;
- if (GetTopmostAutoHideTaskbarForEdge(ABE_TOP, monitor))
- *edge = Appbar::EDGE_TOP;
- if (GetTopmostAutoHideTaskbarForEdge(ABE_RIGHT, monitor))
- *edge = Appbar::EDGE_RIGHT;
- if (GetTopmostAutoHideTaskbarForEdge(ABE_BOTTOM, monitor))
- *edge = Appbar::EDGE_BOTTOM;
-}
-
-}
-
-// static
-Appbar* Appbar::instance() {
- static Appbar* appbar = NULL;
- if (!appbar)
- appbar = new Appbar();
- return appbar;
-}
-
-int Appbar::GetAutohideEdges(HMONITOR monitor, const base::Closure& callback) {
- // Initialize the map with EDGE_BOTTOM. This is important, as if we return an
- // initial value of 0 (no auto-hide edges) then we'll go fullscreen and
- // windows will automatically remove WS_EX_TOPMOST from the appbar resulting
- // in us thinking there is no auto-hide edges. By returning at least one edge
- // we don't initially go fullscreen until we figure out the real auto-hide
- // edges.
- if (edge_map_.find(monitor) == edge_map_.end())
- edge_map_[monitor] = Appbar::EDGE_BOTTOM;
- if (!in_callback_) {
- int* edge = new int;
- base::WorkerPool::PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GetEdgesOnWorkerThread,
- monitor,
- base::Unretained(edge)),
- base::Bind(&Appbar::OnGotEdges,
- weak_factory_.GetWeakPtr(),
- callback,
- monitor,
- edge_map_[monitor],
- base::Owned(edge)),
- false);
- }
- return edge_map_[monitor];
-}
-
-Appbar::Appbar() : weak_factory_(this), in_callback_(false) {
-}
-
-Appbar::~Appbar() {
-}
-
-void Appbar::OnGotEdges(const base::Closure& callback,
- HMONITOR monitor,
- int returned_edges,
- int* edges) {
- edge_map_[monitor] = *edges;
- if (returned_edges == *edges)
- return;
-
- base::AutoReset<bool> in_callback_setter(&in_callback_, true);
- callback.Run();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/win/appbar.h b/chromium/ui/views/win/appbar.h
deleted file mode 100644
index 4c24c192548..00000000000
--- a/chromium/ui/views/win/appbar.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIN_APPBAR_H_
-#define UI_VIEWS_WIN_APPBAR_H_
-
-#include <map>
-
-#include <windows.h>
-
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
-#include "base/memory/weak_ptr.h"
-
-namespace views {
-
-// Appbar provides an API to query for the edges of the monitor that have an
-// autohide bar.
-// NOTE: querying is done on a separate thread as it spawns a nested message
-// loop. The nested message loop is particularly problematic here as it's
-// possible for the nested message loop to run during window creation and
-// startup time (WM_NCCALCSIZE is called at creation time).
-class Appbar {
- public:
- enum Edge {
- EDGE_TOP = 1 << 0,
- EDGE_LEFT = 1 << 1,
- EDGE_BOTTOM = 1 << 2,
- EDGE_RIGHT = 1 << 3,
- };
-
- // Returns the singleton instance.
- static Appbar* instance();
-
- // Starts a query for the autohide edges of the specified monitor and returns
- // the current value. If the edges have changed |callback| is subsequently
- // invoked. If the edges have not changed |callback| is never run.
- //
- // Return value is a bitmask of Edges.
- int GetAutohideEdges(HMONITOR monitor, const base::Closure& callback);
-
- private:
- typedef std::map<HMONITOR, int> EdgeMap;
-
- Appbar();
- ~Appbar();
-
- // Callback on main thread with the edges. |returned_edges| is the value that
- // was returned from the call to GetAutohideEdges() that initiated the lookup.
- void OnGotEdges(const base::Closure& callback,
- HMONITOR monitor,
- int returned_edges,
- int* edges);
-
- EdgeMap edge_map_;
-
- base::WeakPtrFactory<Appbar> weak_factory_;
-
- // If true we're in the process of notifying a callback. When true we do not
- // start a new query.
- bool in_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(Appbar);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIN_APPBAR_H_
-
diff --git a/chromium/ui/views/win/fullscreen_handler.cc b/chromium/ui/views/win/fullscreen_handler.cc
index 2fe8ceaf2b5..a6f51567856 100644
--- a/chromium/ui/views/win/fullscreen_handler.cc
+++ b/chromium/ui/views/win/fullscreen_handler.cc
@@ -76,8 +76,8 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
if (!for_metro) {
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
- base::win::GetMonitorInfoWrapper(
- MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST), &monitor_info);
+ GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
+ &monitor_info);
gfx::Rect window_rect(monitor_info.rcMonitor);
SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
window_rect.width(), window_rect.height(),
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index ab43f1224ff..adbe4fabe69 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -5,6 +5,7 @@
#include "ui/views/win/hwnd_message_handler.h"
#include <dwmapi.h>
+#include <oleacc.h>
#include <shellapi.h>
#include <wtsapi32.h>
#pragma comment(lib, "wtsapi32.lib")
@@ -14,6 +15,8 @@
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "ui/base/touch/touch_enabled.h"
+#include "ui/base/view_prop.h"
+#include "ui/base/win/internal_constants.h"
#include "ui/base/win/lock_state.h"
#include "ui/base/win/mouse_wheel_util.h"
#include "ui/base/win/shell.h"
@@ -34,18 +37,11 @@
#include "ui/native_theme/native_theme_win.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/monitor_win.h"
-#include "ui/views/widget/native_widget_win.h"
#include "ui/views/widget/widget_hwnd_utils.h"
-#include "ui/views/win/appbar.h"
#include "ui/views/win/fullscreen_handler.h"
#include "ui/views/win/hwnd_message_handler_delegate.h"
#include "ui/views/win/scoped_fullscreen_visibility.h"
-#if !defined(USE_AURA)
-#include "ui/views/accessibility/native_view_accessibility_win.h"
-#include "ui/views/widget/child_window_message_processor.h"
-#endif
-
namespace views {
namespace {
@@ -186,7 +182,7 @@ bool GetMonitorAndRects(const RECT& rect,
return false;
MONITORINFO monitor_info = { 0 };
monitor_info.cbSize = sizeof(monitor_info);
- base::win::GetMonitorInfoWrapper(*monitor, &monitor_info);
+ GetMonitorInfo(*monitor, &monitor_info);
*monitor_rect = gfx::Rect(monitor_info.rcMonitor);
*work_area = gfx::Rect(monitor_info.rcWork);
return true;
@@ -197,19 +193,6 @@ struct FindOwnedWindowsData {
std::vector<Widget*> owned_widgets;
};
-BOOL CALLBACK FindOwnedWindowsCallback(HWND hwnd, LPARAM param) {
- // TODO(beng): resolve wrt aura.
-#if !defined(USE_AURA)
- FindOwnedWindowsData* data = reinterpret_cast<FindOwnedWindowsData*>(param);
- if (GetWindow(hwnd, GW_OWNER) == data->window) {
- Widget* widget = Widget::GetWidgetForNativeView(hwnd);
- if (widget)
- data->owned_widgets.push_back(widget);
- }
-#endif
- return TRUE;
-}
-
// Enables or disables the menu item for the specified command and menu.
void EnableMenuItemByCommand(HMENU menu, UINT command, bool enabled) {
UINT flags = MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_DISABLED | MF_GRAYED);
@@ -251,54 +234,6 @@ static BOOL CALLBACK ClipDCToChild(HWND window, LPARAM param) {
return TRUE;
}
-#if !defined(USE_AURA)
-
-// Get the source HWND of the specified message. Depending on the message, the
-// source HWND is encoded in either the WPARAM or the LPARAM value.
-HWND GetControlHWNDForMessage(UINT message, WPARAM w_param, LPARAM l_param) {
- // Each of the following messages can be sent by a child HWND and must be
- // forwarded to its associated NativeControlWin for handling.
- switch (message) {
- case WM_NOTIFY:
- return reinterpret_cast<NMHDR*>(l_param)->hwndFrom;
- case WM_COMMAND:
- return reinterpret_cast<HWND>(l_param);
- case WM_CONTEXTMENU:
- return reinterpret_cast<HWND>(w_param);
- case WM_CTLCOLORBTN:
- case WM_CTLCOLORSTATIC:
- return reinterpret_cast<HWND>(l_param);
- }
- return NULL;
-}
-
-// Some messages may be sent to us by a child HWND. If this is the case, this
-// function will forward those messages on to the object associated with the
-// source HWND and return true, in which case the window procedure must not do
-// any further processing of the message. If there is no associated
-// ChildWindowMessageProcessor, the return value will be false and the WndProc
-// can continue processing the message normally. |l_result| contains the result
-// of the message processing by the control and must be returned by the WndProc
-// if the return value is true.
-bool ProcessChildWindowMessage(UINT message,
- WPARAM w_param,
- LPARAM l_param,
- LRESULT* l_result) {
- *l_result = 0;
-
- HWND control_hwnd = GetControlHWNDForMessage(message, w_param, l_param);
- if (IsWindow(control_hwnd)) {
- ChildWindowMessageProcessor* processor =
- ChildWindowMessageProcessor::Get(control_hwnd);
- if (processor)
- return processor->ProcessMessage(message, w_param, l_param, l_result);
- }
-
- return false;
-}
-
-#endif
-
// The thickness of an auto-hide taskbar in pixels.
const int kAutoHideTaskbarThicknessPx = 2;
@@ -318,6 +253,15 @@ void AddScrollStylesToWindow(HWND window) {
}
}
+const int kTouchDownContextResetTimeout = 500;
+
+// Windows does not flag synthesized mouse messages from touch in all cases.
+// This causes us grief as we don't want to process touch and mouse messages
+// concurrently. Hack as per msdn is to check if the time difference between
+// the touch message and the mouse move is within 500 ms and at the same
+// location as the cursor.
+const int kSynthesizedMouseTouchMessagesTimeDifference = 500;
+
} // namespace
// A scoping class that prevents a window from being able to redraw in response
@@ -387,6 +331,8 @@ class HWNDMessageHandler::ScopedRedrawLock {
////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, public:
+long HWNDMessageHandler::last_touch_message_time_ = 0;
+
HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
: delegate_(delegate),
fullscreen_handler_(new FullscreenHandler),
@@ -394,7 +340,6 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
waiting_for_close_now_(false),
remove_standard_frame_(false),
use_system_default_icon_(false),
- restore_focus_when_enabled_(false),
restored_enabled_(false),
current_cursor_(NULL),
previous_cursor_(NULL),
@@ -407,10 +352,14 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
layered_alpha_(255),
waiting_for_redraw_layered_window_contents_(false),
is_first_nccalc_(true),
+ menu_depth_(0),
autohide_factory_(this),
id_generator_(0),
needs_scroll_styles_(false),
- in_size_loop_(false) {
+ in_size_loop_(false),
+ touch_down_contexts_(0),
+ last_mouse_hwheel_time_(0),
+ msg_handled_(FALSE) {
}
HWNDMessageHandler::~HWNDMessageHandler() {
@@ -427,8 +376,9 @@ void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) {
// Create the window.
WindowImpl::Init(parent, bounds);
-
-#if defined(USE_AURA)
+ // TODO(ananta)
+ // Remove the scrolling hack code once we have scrolling working well.
+#if defined(ENABLE_SCROLL_HACK)
// Certain trackpad drivers on Windows have bugs where in they don't generate
// WM_MOUSEWHEEL messages for the trackpoint and trackpad scrolling gestures
// unless there is an entry for Chrome with the class name of the Window.
@@ -448,6 +398,10 @@ void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) {
}
}
#endif
+
+ prop_window_target_.reset(new ui::ViewProp(hwnd(),
+ ui::WindowEventTarget::kWin32InputEventTarget,
+ static_cast<ui::WindowEventTarget*>(this)));
}
void HWNDMessageHandler::InitModalType(ui::ModalType modal_type) {
@@ -549,7 +503,7 @@ void HWNDMessageHandler::GetWindowPlacement(
} else {
MONITORINFO mi;
mi.cbSize = sizeof(mi);
- const bool succeeded = base::win::GetMonitorInfoWrapper(
+ const bool succeeded = GetMonitorInfo(
MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST), &mi) != 0;
DCHECK(succeeded);
@@ -571,13 +525,24 @@ void HWNDMessageHandler::GetWindowPlacement(
}
}
-void HWNDMessageHandler::SetBounds(const gfx::Rect& bounds_in_pixels) {
+void HWNDMessageHandler::SetBounds(const gfx::Rect& bounds_in_pixels,
+ bool force_size_changed) {
LONG style = GetWindowLong(hwnd(), GWL_STYLE);
if (style & WS_MAXIMIZE)
SetWindowLong(hwnd(), GWL_STYLE, style & ~WS_MAXIMIZE);
+
+ gfx::Size old_size = GetClientAreaBounds().size();
SetWindowPos(hwnd(), NULL, bounds_in_pixels.x(), bounds_in_pixels.y(),
bounds_in_pixels.width(), bounds_in_pixels.height(),
SWP_NOACTIVATE | SWP_NOZORDER);
+
+ // If HWND size is not changed, we will not receive standard size change
+ // notifications. If |force_size_changed| is |true|, we should pretend size is
+ // changed.
+ if (old_size == bounds_in_pixels.size() && force_size_changed) {
+ delegate_->HandleClientSizeChanged(GetClientAreaBounds().size());
+ ResetWindowRegion(false, true);
+ }
}
void HWNDMessageHandler::SetSize(const gfx::Size& size) {
@@ -609,8 +574,14 @@ void HWNDMessageHandler::StackAtTop() {
}
void HWNDMessageHandler::Show() {
- if (IsWindow(hwnd()))
- ShowWindowWithState(ui::SHOW_STATE_INACTIVE);
+ if (IsWindow(hwnd())) {
+ if (!(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TRANSPARENT) &&
+ !(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)) {
+ ShowWindowWithState(ui::SHOW_STATE_NORMAL);
+ } else {
+ ShowWindowWithState(ui::SHOW_STATE_INACTIVE);
+ }
+ }
}
void HWNDMessageHandler::ShowWindowWithState(ui::WindowShowState show_state) {
@@ -630,30 +601,28 @@ void HWNDMessageHandler::ShowWindowWithState(ui::WindowShowState show_state) {
native_show_state = delegate_->GetInitialShowState();
break;
}
- Show(native_show_state);
-}
-void HWNDMessageHandler::Show(int show_state) {
- ShowWindow(hwnd(), show_state);
+ ShowWindow(hwnd(), native_show_state);
// When launched from certain programs like bash and Windows Live Messenger,
// show_state is set to SW_HIDE, so we need to correct that condition. We
// don't just change show_state to SW_SHOWNORMAL because MSDN says we must
// always first call ShowWindow with the specified value from STARTUPINFO,
// otherwise all future ShowWindow calls will be ignored (!!#@@#!). Instead,
// we call ShowWindow again in this case.
- if (show_state == SW_HIDE) {
- show_state = SW_SHOWNORMAL;
- ShowWindow(hwnd(), show_state);
+ if (native_show_state == SW_HIDE) {
+ native_show_state = SW_SHOWNORMAL;
+ ShowWindow(hwnd(), native_show_state);
}
// We need to explicitly activate the window if we've been shown with a state
// that should activate, because if we're opened from a desktop shortcut while
// an existing window is already running it doesn't seem to be enough to use
// one of these flags to activate the window.
- if (show_state == SW_SHOWNORMAL || show_state == SW_SHOWMAXIMIZED)
+ if (native_show_state == SW_SHOWNORMAL ||
+ native_show_state == SW_SHOWMAXIMIZED)
Activate();
- if (!delegate_->HandleInitialFocus())
+ if (!delegate_->HandleInitialFocus(show_state))
SetInitialFocus();
}
@@ -674,9 +643,6 @@ void HWNDMessageHandler::Hide() {
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0,
SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
-
- if (!GetParent(hwnd()))
- NotifyOwnedWindowsParentClosing();
}
}
@@ -740,12 +706,11 @@ bool HWNDMessageHandler::RunMoveLoop(const gfx::Vector2d& drag_offset,
bool hide_on_escape) {
ReleaseCapture();
MoveLoopMouseWatcher watcher(this, hide_on_escape);
-#if defined(USE_AURA)
// In Aura, we handle touch events asynchronously. So we need to allow nested
// tasks while in windows move loop.
base::MessageLoop::ScopedNestableTaskAllower allow_nested(
base::MessageLoop::current());
-#endif
+
SendMessage(hwnd(), WM_SYSCOMMAND, SC_MOVE | 0x0002, GetMessagePos());
// Windows doesn't appear to offer a way to determine whether the user
// canceled the move or not. We assume if the user released the mouse it was
@@ -804,8 +769,8 @@ void HWNDMessageHandler::SetVisibilityChangedAnimationsEnabled(bool enabled) {
}
}
-bool HWNDMessageHandler::SetTitle(const string16& title) {
- string16 current_title;
+bool HWNDMessageHandler::SetTitle(const base::string16& title) {
+ base::string16 current_title;
size_t len_with_null = GetWindowTextLength(hwnd()) + 1;
if (len_with_null == 1 && title.length() == 0)
return false;
@@ -831,6 +796,7 @@ void HWNDMessageHandler::SetCursor(HCURSOR cursor) {
void HWNDMessageHandler::FrameTypeChanged() {
// Called when the frame type could possibly be changing (theme change or
// DWM composition change).
+ UpdateDwmNcRenderingPolicy();
// Don't redraw the window here, because we need to hide and show the window
// which will also trigger a redraw.
@@ -849,8 +815,9 @@ void HWNDMessageHandler::FrameTypeChanged() {
UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_HIDEWINDOW);
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0, flags | SWP_SHOWWINDOW);
-
- UpdateWindow(hwnd());
+ // Invalidate the window to force a paint. There may be child windows which
+ // could resize in this context. Don't paint right away.
+ ::InvalidateRect(hwnd(), NULL, FALSE);
}
// WM_DWMCOMPOSITIONCHANGED is only sent to top level windows, however we want
@@ -937,14 +904,6 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message,
if (delegate_ && delegate_->PreHandleMSG(message, w_param, l_param, &result))
return result;
-#if !defined(USE_AURA)
- // First allow messages sent by child controls to be processed directly by
- // their associated views. If such a view is present, it will handle the
- // message *instead of* this NativeWidgetWin.
- if (ProcessChildWindowMessage(message, w_param, l_param, &result))
- return result;
-#endif
-
// Otherwise we handle everything else.
// NOTE: We inline ProcessWindowMessage() as 'this' may be destroyed during
// dispatch and ProcessWindowMessage() doesn't deal with that well.
@@ -963,40 +922,48 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message,
if (!::IsWindow(window))
return result;
- if (delegate_)
+ if (delegate_) {
delegate_->PostHandleMSG(message, w_param, l_param);
- if (message == WM_NCDESTROY) {
-#if !defined(USE_AURA)
- base::MessageLoopForUI::current()->RemoveObserver(this);
-#endif
- if (delegate_)
+ if (message == WM_NCDESTROY)
delegate_->HandleDestroyed();
}
- // Only top level widget should store/restore focus.
- if (message == WM_ACTIVATE && delegate_->CanSaveFocus())
+ if (message == WM_ACTIVATE && IsTopLevelWindow(window))
PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param));
-
- if (message == WM_ENABLE && restore_focus_when_enabled_) {
- // This path should be executed only for top level as
- // restore_focus_when_enabled_ is set in PostProcessActivateMessage.
- DCHECK(delegate_->CanSaveFocus());
- restore_focus_when_enabled_ = false;
- delegate_->RestoreFocusOnEnable();
- }
return result;
}
-////////////////////////////////////////////////////////////////////////////////
-// HWNDMessageHandler, MessageLoopForUI::Observer implementation:
+LRESULT HWNDMessageHandler::HandleMouseMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ // Don't track forwarded mouse messages. We expect the caller to track the
+ // mouse.
+ return HandleMouseEventInternal(message, w_param, l_param, false);
+}
+
+LRESULT HWNDMessageHandler::HandleTouchMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return OnTouchEvent(message, w_param, l_param);
+}
+
+LRESULT HWNDMessageHandler::HandleKeyboardMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return OnKeyEvent(message, w_param, l_param);
+}
-base::EventStatus HWNDMessageHandler::WillProcessEvent(
- const base::NativeEvent& event) {
- return base::EVENT_CONTINUE;
+LRESULT HWNDMessageHandler::HandleScrollMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return OnScrollMessage(message, w_param, l_param);
}
-void HWNDMessageHandler::DidProcessEvent(const base::NativeEvent& event) {
- RedrawInvalidRect();
+LRESULT HWNDMessageHandler::HandleNcHitTestMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return OnNCHitTest(
+ gfx::Point(CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param)));
}
////////////////////////////////////////////////////////////////////////////////
@@ -1004,10 +971,12 @@ void HWNDMessageHandler::DidProcessEvent(const base::NativeEvent& event) {
int HWNDMessageHandler::GetAppbarAutohideEdges(HMONITOR monitor) {
autohide_factory_.InvalidateWeakPtrs();
- return Appbar::instance()->GetAutohideEdges(
- monitor,
- base::Bind(&HWNDMessageHandler::OnAppbarAutohideEdgesChanged,
- autohide_factory_.GetWeakPtr()));
+ return ViewsDelegate::views_delegate ?
+ ViewsDelegate::views_delegate->GetAppbarAutohideEdges(
+ monitor,
+ base::Bind(&HWNDMessageHandler::OnAppbarAutohideEdgesChanged,
+ autohide_factory_.GetWeakPtr())) :
+ ViewsDelegate::EDGE_BOTTOM;
}
void HWNDMessageHandler::OnAppbarAutohideEdgesChanged() {
@@ -1029,33 +998,10 @@ void HWNDMessageHandler::SetInitialFocus() {
void HWNDMessageHandler::PostProcessActivateMessage(int activation_state,
bool minimized) {
- DCHECK(delegate_->CanSaveFocus());
-
- bool active = activation_state != WA_INACTIVE && !minimized;
+ DCHECK(IsTopLevelWindow(hwnd()));
+ const bool active = activation_state != WA_INACTIVE && !minimized;
if (delegate_->CanActivate())
delegate_->HandleActivationChanged(active);
-
- if (!active) {
- // We might get activated/inactivated without being enabled, so we need to
- // clear restore_focus_when_enabled_.
- restore_focus_when_enabled_ = false;
- delegate_->SaveFocusOnDeactivate();
- } else {
- // We must restore the focus after the message has been DefProc'ed as it
- // does set the focus to the last focused HWND.
- // Note that if the window is not enabled, we cannot restore the focus as
- // calling ::SetFocus on a child of the non-enabled top-window would fail.
- // This is the case when showing a modal dialog (such as 'open file',
- // 'print'...) from a different thread.
- // In that case we delay the focus restoration to when the window is enabled
- // again.
- if (!IsWindowEnabled(hwnd())) {
- DCHECK(!restore_focus_when_enabled_);
- restore_focus_when_enabled_ = true;
- return;
- }
- delegate_->RestoreFocusOnActivate();
- }
}
void HWNDMessageHandler::RestoreEnabledIfNecessary() {
@@ -1153,7 +1099,7 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
HRGN current_rgn = CreateRectRgn(0, 0, 0, 0);
int current_rgn_result = GetWindowRgn(hwnd(), current_rgn);
- CRect window_rect;
+ RECT window_rect;
GetWindowRect(hwnd(), &window_rect);
HRGN new_region;
if (custom_window_region_) {
@@ -1163,14 +1109,15 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
HMONITOR monitor = MonitorFromWindow(hwnd(), MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
mi.cbSize = sizeof mi;
- base::win::GetMonitorInfoWrapper(monitor, &mi);
- CRect work_rect = mi.rcWork;
- work_rect.OffsetRect(-window_rect.left, -window_rect.top);
+ GetMonitorInfo(monitor, &mi);
+ RECT work_rect = mi.rcWork;
+ OffsetRect(&work_rect, -window_rect.left, -window_rect.top);
new_region = CreateRectRgnIndirect(&work_rect);
} else {
gfx::Path window_mask;
- delegate_->GetWindowMask(
- gfx::Size(window_rect.Width(), window_rect.Height()), &window_mask);
+ delegate_->GetWindowMask(gfx::Size(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top),
+ &window_mask);
new_region = gfx::CreateHRGNFromSkPath(window_mask);
}
@@ -1187,8 +1134,11 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return;
- DWMNCRENDERINGPOLICY policy = custom_window_region_ ? DWMNCRP_DISABLED
- : DWMNCRP_USEWINDOWSTYLE;
+
+ DWMNCRENDERINGPOLICY policy =
+ custom_window_region_ || delegate_->IsUsingCustomFrame() ?
+ DWMNCRP_DISABLED : DWMNCRP_ENABLED;
+
DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY,
&policy, sizeof(DWMNCRENDERINGPOLICY));
}
@@ -1206,15 +1156,6 @@ LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
return result;
}
-void HWNDMessageHandler::NotifyOwnedWindowsParentClosing() {
- FindOwnedWindowsData data;
- data.window = hwnd();
- EnumThreadWindows(GetCurrentThreadId(), FindOwnedWindowsCallback,
- reinterpret_cast<LPARAM>(&data));
- for (size_t i = 0; i < data.owned_widgets.size(); ++i)
- data.owned_widgets[i]->OnOwnerClosing();
-}
-
void HWNDMessageHandler::LockUpdates(bool force) {
// We skip locked updates when Aero is on for two reasons:
// 1. Because it isn't necessary
@@ -1236,28 +1177,13 @@ void HWNDMessageHandler::UnlockUpdates(bool force) {
}
}
-void HWNDMessageHandler::RedrawInvalidRect() {
-// TODO(cpu): Remove the caller and this class as a message loop observer
-// because we don't need agressive repaints via RDW_UPDATENOW in Aura. The
-// general tracking bug for repaint issues is 177115.
-#if !defined(USE_AURA)
- if (!use_layered_buffer_) {
- RECT r = { 0, 0, 0, 0 };
- if (GetUpdateRect(hwnd(), &r, FALSE) && !IsRectEmpty(&r)) {
- RedrawWindow(hwnd(), &r, NULL,
- RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
- }
- }
-#endif
-}
-
void HWNDMessageHandler::RedrawLayeredWindowContents() {
waiting_for_redraw_layered_window_contents_ = false;
if (invalid_rect_.IsEmpty())
return;
// We need to clip to the dirty rect ourselves.
- layered_window_contents_->sk_canvas()->save(SkCanvas::kClip_SaveFlag);
+ layered_window_contents_->sk_canvas()->save();
double scale = gfx::win::GetDeviceScaleFactor();
layered_window_contents_->sk_canvas()->scale(
SkScalar(scale),SkScalar(scale));
@@ -1347,7 +1273,6 @@ void HWNDMessageHandler::OnCommand(UINT notification_code,
LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
use_layered_buffer_ = !!(window_ex_style() & WS_EX_LAYERED);
-#if defined(USE_AURA)
if (window_ex_style() & WS_EX_COMPOSITED) {
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
// This is part of the magic to emulate layered windows with Aura
@@ -1356,7 +1281,6 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
DwmExtendFrameIntoClientArea(hwnd(), &margins);
}
}
-#endif
fullscreen_handler_->set_hwnd(hwnd());
@@ -1385,14 +1309,6 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
// creation time.
ClientAreaSizeChanged();
-#if !defined(USE_AURA)
- // We need to add ourselves as a message loop observer so that we can repaint
- // aggressively if the contents of our window become invalid. Unfortunately
- // WM_PAINT messages are starved and we get flickery redrawing when resizing
- // if we do not do this.
- base::MessageLoopForUI::current()->AddObserver(this);
-#endif
-
delegate_->HandleCreate();
WTSRegisterSessionNotification(hwnd(), NOTIFY_FOR_THIS_SESSION);
@@ -1407,7 +1323,7 @@ void HWNDMessageHandler::OnDestroy() {
}
void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
- const CSize& screen_size) {
+ const gfx::Size& screen_size) {
delegate_->HandleDisplayChange();
}
@@ -1423,6 +1339,11 @@ LRESULT HWNDMessageHandler::OnDwmCompositionChanged(UINT msg,
return 0;
}
+void HWNDMessageHandler::OnEnterMenuLoop(BOOL from_track_popup_menu) {
+ if (menu_depth_++ == 0)
+ delegate_->HandleMenuLoop(true);
+}
+
void HWNDMessageHandler::OnEnterSizeMove() {
// Please refer to the comments in the OnSize function about the scrollbar
// hack.
@@ -1440,6 +1361,12 @@ LRESULT HWNDMessageHandler::OnEraseBkgnd(HDC dc) {
return 1;
}
+void HWNDMessageHandler::OnExitMenuLoop(BOOL is_shortcut_menu) {
+ if (--menu_depth_ == 0)
+ delegate_->HandleMenuLoop(false);
+ DCHECK_GE(0, menu_depth_);
+}
+
void HWNDMessageHandler::OnExitSizeMove() {
delegate_->HandleEndWMSizeMove();
SetMsgHandled(FALSE);
@@ -1460,13 +1387,16 @@ void HWNDMessageHandler::OnGetMinMaxInfo(MINMAXINFO* minmax_info) {
// Add the native frame border size to the minimum and maximum size if the
// view reports its size as the client size.
if (delegate_->WidgetSizeIsClientSize()) {
- CRect client_rect, window_rect;
+ RECT client_rect, window_rect;
GetClientRect(hwnd(), &client_rect);
GetWindowRect(hwnd(), &window_rect);
- window_rect -= client_rect;
- min_window_size.Enlarge(window_rect.Width(), window_rect.Height());
- if (!max_window_size.IsEmpty())
- max_window_size.Enlarge(window_rect.Width(), window_rect.Height());
+ CR_DEFLATE_RECT(&window_rect, &client_rect);
+ min_window_size.Enlarge(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top);
+ if (!max_window_size.IsEmpty()) {
+ max_window_size.Enlarge(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top);
+ }
}
minmax_info->ptMinTrackSize.x = min_window_size.width();
minmax_info->ptMinTrackSize.y = min_window_size.height();
@@ -1486,8 +1416,12 @@ LRESULT HWNDMessageHandler::OnGetObject(UINT message,
LPARAM l_param) {
LRESULT reference_result = static_cast<LRESULT>(0L);
+ // Only the lower 32 bits of l_param are valid when checking the object id
+ // because it sometimes gets sign-extended incorrectly (but not always).
+ DWORD obj_id = static_cast<DWORD>(static_cast<DWORD_PTR>(l_param));
+
// Accessibility readers will send an OBJID_CLIENT message
- if (OBJID_CLIENT == l_param) {
+ if (OBJID_CLIENT == obj_id) {
// Retrieve MSAA dispatch object for the root view.
base::win::ScopedComPtr<IAccessible> root(
delegate_->GetNativeViewAccessible());
@@ -1516,13 +1450,21 @@ void HWNDMessageHandler::OnInitMenu(HMENU menu) {
bool is_restored = !is_fullscreen && !is_minimized && !is_maximized;
ScopedRedrawLock lock(this);
- EnableMenuItemByCommand(menu, SC_RESTORE, is_minimized || is_maximized);
+ EnableMenuItemByCommand(menu, SC_RESTORE, delegate_->CanResize() &&
+ (is_minimized || is_maximized));
EnableMenuItemByCommand(menu, SC_MOVE, is_restored);
EnableMenuItemByCommand(menu, SC_SIZE, delegate_->CanResize() && is_restored);
EnableMenuItemByCommand(menu, SC_MAXIMIZE, delegate_->CanMaximize() &&
!is_fullscreen && !is_maximized);
+ // TODO: unfortunately, WidgetDelegate does not declare CanMinimize() and some
+ // code depends on this check, see http://crbug.com/341010.
EnableMenuItemByCommand(menu, SC_MINIMIZE, delegate_->CanMaximize() &&
!is_minimized);
+
+ if (is_maximized && delegate_->CanResize())
+ ::SetMenuDefaultItem(menu, SC_RESTORE, FALSE);
+ else if (!is_maximized && delegate_->CanMaximize())
+ ::SetMenuDefaultItem(menu, SC_MAXIMIZE, FALSE);
}
void HWNDMessageHandler::OnInputLangChange(DWORD character_set,
@@ -1548,7 +1490,11 @@ void HWNDMessageHandler::OnKillFocus(HWND focused_window) {
LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
WPARAM w_param,
LPARAM l_param) {
-#if defined(USE_AURA)
+ // Please refer to the comments in the header for the touch_down_contexts_
+ // member for the if statement below.
+ if (touch_down_contexts_)
+ return MA_NOACTIVATE;
+
// On Windows, if we select the menu item by touch and if the window at the
// location is another window on the same thread, that window gets a
// WM_MOUSEACTIVATE message and ends up activating itself, which is not
@@ -1556,8 +1502,8 @@ LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
// current cursor location. We check for this property in our
// WM_MOUSEACTIVATE handler and don't activate the window if the property is
// set.
- if (::GetProp(hwnd(), kIgnoreTouchMouseActivateForWindow)) {
- ::RemoveProp(hwnd(), kIgnoreTouchMouseActivateForWindow);
+ if (::GetProp(hwnd(), ui::kIgnoreTouchMouseActivateForWindow)) {
+ ::RemoveProp(hwnd(), ui::kIgnoreTouchMouseActivateForWindow);
return MA_NOACTIVATE;
}
// A child window activation should be treated as if we lost activation.
@@ -1567,7 +1513,7 @@ LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
HWND child = ::RealChildWindowFromPoint(hwnd(), cursor_pos);
if (::IsWindow(child) && child != hwnd() && ::IsWindowVisible(child))
PostProcessActivateMessage(WA_INACTIVE, false);
-#endif
+
// TODO(beng): resolve this with the GetWindowLong() check on the subsequent
// line.
if (delegate_->IsWidgetWindow())
@@ -1581,120 +1527,10 @@ LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
LRESULT HWNDMessageHandler::OnMouseRange(UINT message,
WPARAM w_param,
LPARAM l_param) {
-#if defined(USE_AURA)
- if (!touch_ids_.empty())
- return 0;
- // We handle touch events on Windows Aura. Windows generates synthesized
- // mouse messages in response to touch which we should ignore. However touch
- // messages are only received for the client area. We need to ignore the
- // synthesized mouse messages for all points in the client area and places
- // which return HTNOWHERE.
- if (ui::IsMouseEventFromTouch(message)) {
- LPARAM l_param_ht = l_param;
- // For mouse events (except wheel events), location is in window coordinates
- // and should be converted to screen coordinates for WM_NCHITTEST.
- if (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) {
- CPoint screen_point(l_param_ht);
- MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
- l_param_ht = MAKELPARAM(screen_point.x, screen_point.y);
- }
- LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht);
- if (hittest == HTCLIENT || hittest == HTNOWHERE)
- return 0;
- }
-#endif
- if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
- is_right_mouse_pressed_on_caption_ = false;
- ReleaseCapture();
- // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
- // expect screen coordinates.
- CPoint screen_point(l_param);
- MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
- 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));
- return 0;
- }
- } else if (message == WM_NCLBUTTONDOWN && delegate_->IsUsingCustomFrame()) {
- switch (w_param) {
- case HTCLOSE:
- case HTMINBUTTON:
- case HTMAXBUTTON: {
- // When the mouse is pressed down in these specific non-client areas,
- // we need to tell the RootView to send the mouse pressed event (which
- // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
- // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
- // sent by the applicable button's ButtonListener. We _have_ to do this
- // way rather than letting Windows just send the syscommand itself (as
- // would happen if we never did this dance) because for some insane
- // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
- // window control button appearance, in the Windows classic style, over
- // our view! Ick! By handling this message we prevent Windows from
- // doing this undesirable thing, but that means we need to roll the
- // sys-command handling ourselves.
- // Combine |w_param| with common key state message flags.
- w_param |= base::win::IsCtrlPressed() ? MK_CONTROL : 0;
- w_param |= base::win::IsShiftPressed() ? MK_SHIFT : 0;
- }
- }
- } else if (message == WM_NCRBUTTONDOWN &&
- (w_param == HTCAPTION || w_param == HTSYSMENU)) {
- is_right_mouse_pressed_on_caption_ = true;
- // We SetCapture() to ensure we only show the menu when the button
- // down and up are both on the caption. Note: this causes the button up to
- // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
- SetCapture();
- }
-
- MSG msg = { hwnd(), message, w_param, l_param, GetMessageTime(),
- { GET_X_LPARAM(l_param), GET_Y_LPARAM(l_param) } };
- ui::MouseEvent event(msg);
- if (!touch_ids_.empty() || ui::IsMouseEventFromTouch(message))
- event.set_flags(event.flags() | ui::EF_FROM_TOUCH);
-
- if (!(event.flags() & ui::EF_IS_NON_CLIENT))
- delegate_->HandleTooltipMouseMove(message, w_param, l_param);
-
- if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture()) {
- // Windows only fires WM_MOUSELEAVE events if the application begins
- // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
- // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
- TrackMouseEvents((message == WM_NCMOUSEMOVE) ?
- TME_NONCLIENT | TME_LEAVE : TME_LEAVE);
- } else if (event.type() == ui::ET_MOUSE_EXITED) {
- // Reset our tracking flags so future mouse movement over this
- // NativeWidgetWin results in a new tracking session. Fall through for
- // OnMouseEvent.
- active_mouse_tracking_flags_ = 0;
- } else if (event.type() == ui::ET_MOUSEWHEEL) {
- // Reroute the mouse wheel to the window under the pointer if applicable.
- return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
- delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1;
- }
-
- // There are cases where the code handling the message destroys the window,
- // so use the weak ptr to check if destruction occured or not.
- base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
- bool handled = delegate_->HandleMouseEvent(event);
- if (!ref.get())
- return 0;
- if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU &&
- delegate_->IsUsingCustomFrame()) {
- // TODO(msw): Eliminate undesired painting, or re-evaluate this workaround.
- // DefWindowProc for WM_NCLBUTTONDOWN does weird non-client painting, so we
- // need to call it inside a ScopedRedrawLock. This may cause other negative
- // side-effects (ex/ stifling non-client mouse releases).
- DefWindowProcWithRedrawLock(message, w_param, l_param);
- handled = true;
- }
-
- if (ref.get())
- SetMsgHandled(handled);
- return 0;
+ return HandleMouseEventInternal(message, w_param, l_param, true);
}
-void HWNDMessageHandler::OnMove(const CPoint& point) {
+void HWNDMessageHandler::OnMove(const gfx::Point& point) {
delegate_->HandleMove();
SetMsgHandled(FALSE);
}
@@ -1814,9 +1650,9 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
}
}
const int autohide_edges = GetAppbarAutohideEdges(monitor);
- if (autohide_edges & Appbar::EDGE_LEFT)
+ if (autohide_edges & ViewsDelegate::EDGE_LEFT)
client_rect->left += kAutoHideTaskbarThicknessPx;
- if (autohide_edges & Appbar::EDGE_TOP) {
+ if (autohide_edges & ViewsDelegate::EDGE_TOP) {
if (!delegate_->IsUsingCustomFrame()) {
// Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
// WM_NCHITTEST, having any nonclient area atop the window causes the
@@ -1832,9 +1668,9 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
client_rect->top += kAutoHideTaskbarThicknessPx;
}
}
- if (autohide_edges & Appbar::EDGE_RIGHT)
+ if (autohide_edges & ViewsDelegate::EDGE_RIGHT)
client_rect->right -= kAutoHideTaskbarThicknessPx;
- if (autohide_edges & Appbar::EDGE_BOTTOM)
+ if (autohide_edges & ViewsDelegate::EDGE_BOTTOM)
client_rect->bottom -= kAutoHideTaskbarThicknessPx;
// We cannot return WVR_REDRAW when there is nonclient area, or Windows
@@ -1855,7 +1691,7 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
return mode ? WVR_REDRAW : 0;
}
-LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
+LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) {
if (!delegate_->IsWidgetWindow()) {
SetMsgHandled(FALSE);
return 0;
@@ -1866,14 +1702,14 @@ LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame()) {
LRESULT result;
if (DwmDefWindowProc(hwnd(), WM_NCHITTEST, 0,
- MAKELPARAM(point.x, point.y), &result)) {
+ MAKELPARAM(point.x(), point.y()), &result)) {
return result;
}
}
// First, give the NonClientView a chance to test the point to see if it
// provides any of the non-client area.
- POINT temp = point;
+ POINT temp = { point.x(), point.y() };
MapWindowPoints(HWND_DESKTOP, hwnd(), &temp, 1);
int component = delegate_->GetNonClientComponent(gfx::Point(temp));
if (component != HTNOWHERE)
@@ -1881,9 +1717,8 @@ LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
// Otherwise, we let Windows do all the native frame non-client handling for
// us.
-#if defined(USE_AURA)
LRESULT hit_test_code = DefWindowProc(hwnd(), WM_NCHITTEST, 0,
- MAKELPARAM(point.x, point.y));
+ MAKELPARAM(point.x(), point.y()));
if (needs_scroll_styles_) {
switch (hit_test_code) {
// If we faked the WS_VSCROLL and WS_HSCROLL styles for this window, then
@@ -1916,8 +1751,8 @@ LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
window_rect.left = window_rect.right - scroll_width;
window_rect.top = window_rect.bottom - scroll_height;
POINT pt;
- pt.x = point.x;
- pt.y = point.y;
+ pt.x = point.x();
+ pt.y = point.y();
if (::PtInRect(&window_rect, pt))
hit_test_code = HTCLIENT;
break;
@@ -1928,9 +1763,6 @@ LRESULT HWNDMessageHandler::OnNCHitTest(const CPoint& point) {
}
}
return hit_test_code;
-#else
- SetMsgHandled(FALSE);
-#endif
}
void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
@@ -1945,11 +1777,12 @@ void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
// We have an NC region and need to paint it. We expand the NC region to
// include the dirty region of the root view. This is done to minimize
// paints.
- CRect window_rect;
+ RECT window_rect;
GetWindowRect(hwnd(), &window_rect);
gfx::Size root_view_size = delegate_->GetRootViewSize();
- if (gfx::Size(window_rect.Width(), window_rect.Height()) != root_view_size) {
+ if (gfx::Size(window_rect.right - window_rect.left,
+ window_rect.bottom - window_rect.top) != root_view_size) {
// If the size of the window differs from the size of the root view it
// means we're being asked to paint before we've gotten a WM_SIZE. This can
// happen when the user is interactively resizing the window. To avoid
@@ -1959,10 +1792,13 @@ void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
return;
}
- CRect dirty_region;
+ RECT dirty_region;
// A value of 1 indicates paint all.
if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
- dirty_region = CRect(0, 0, window_rect.Width(), window_rect.Height());
+ dirty_region.left = 0;
+ dirty_region.top = 0;
+ dirty_region.right = window_rect.right - window_rect.left;
+ dirty_region.bottom = window_rect.bottom - window_rect.top;
} else {
RECT rgn_bounding_box;
GetRgnBox(rgn, &rgn_bounding_box);
@@ -1991,8 +1827,8 @@ void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
// The root view has a region that needs to be painted. Include it in the
// region we're going to paint.
- CRect old_paint_region_crect = old_paint_region.ToRECT();
- CRect tmp = dirty_region;
+ RECT old_paint_region_crect = old_paint_region.ToRECT();
+ RECT tmp = dirty_region;
UnionRect(&dirty_region, &tmp, &old_paint_region_crect);
}
@@ -2002,9 +1838,12 @@ void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
// the following in a block to force paint to occur so that we can release
// the dc.
if (!delegate_->HandlePaintAccelerated(gfx::Rect(dirty_region))) {
- gfx::CanvasSkiaPaint canvas(dc, true, dirty_region.left,
- dirty_region.top, dirty_region.Width(),
- dirty_region.Height());
+ gfx::CanvasSkiaPaint canvas(dc,
+ true,
+ dirty_region.left,
+ dirty_region.top,
+ dirty_region.right - dirty_region.left,
+ dirty_region.bottom - dirty_region.top);
delegate_->HandlePaint(&canvas);
}
@@ -2050,13 +1889,7 @@ void HWNDMessageHandler::OnPaint(HDC dc) {
// Try to paint accelerated first.
if (!IsRectEmpty(&ps.rcPaint) &&
!delegate_->HandlePaintAccelerated(gfx::Rect(ps.rcPaint))) {
-#if defined(USE_AURA)
delegate_->HandlePaint(NULL);
-#else
- scoped_ptr<gfx::CanvasSkiaPaint> canvas(
- new gfx::CanvasSkiaPaint(hwnd(), display_dc, ps));
- delegate_->HandlePaint(canvas.get());
-#endif
}
EndPaint(hwnd(), &ps);
@@ -2120,6 +1953,9 @@ LRESULT HWNDMessageHandler::OnSetCursor(UINT message,
case HTCLIENT:
SetCursor(current_cursor_);
return 1;
+ case LOWORD(HTERROR): // Use HTERROR's LOWORD value for valid comparison.
+ SetMsgHandled(FALSE);
+ break;
default:
// Use the default value, IDC_ARROW.
break;
@@ -2160,13 +1996,12 @@ void HWNDMessageHandler::OnSettingChange(UINT flags, const wchar_t* section) {
}
}
-void HWNDMessageHandler::OnSize(UINT param, const CSize& size) {
+void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) {
RedrawWindow(hwnd(), NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
// ResetWindowRegion is going to trigger WM_NCPAINT. By doing it after we've
// invoked OnSize we ensure the RootView has been laid out.
ResetWindowRegion(false, true);
-#if defined(USE_AURA)
// We add the WS_VSCROLL and WS_HSCROLL styles to top level windows to ensure
// that legacy trackpad/trackpoint drivers generate the WM_VSCROLL and
// WM_HSCROLL messages and scrolling works.
@@ -2179,11 +2014,10 @@ void HWNDMessageHandler::OnSize(UINT param, const CSize& size) {
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&AddScrollStylesToWindow, hwnd()));
}
-#endif
}
void HWNDMessageHandler::OnSysCommand(UINT notification_code,
- const CPoint& point) {
+ const gfx::Point& point) {
if (!delegate_->ShouldHandleSystemCommands())
return;
@@ -2214,7 +2048,7 @@ void HWNDMessageHandler::OnSysCommand(UINT notification_code,
// Handle SC_KEYMENU, which means that the user has pressed the ALT
// key and released it, so we should focus the menu bar.
- if ((notification_code & sc_mask) == SC_KEYMENU && point.x == 0) {
+ if ((notification_code & sc_mask) == SC_KEYMENU && point.x() == 0) {
int modifiers = ui::EF_NONE;
if (base::win::IsShiftPressed())
modifiers |= ui::EF_SHIFT_DOWN;
@@ -2234,8 +2068,11 @@ void HWNDMessageHandler::OnSysCommand(UINT notification_code,
// with the mouse/touch/keyboard, we flag as being in a size loop.
if ((notification_code & sc_mask) == SC_SIZE)
in_size_loop_ = true;
+ base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
DefWindowProc(hwnd(), WM_SYSCOMMAND, notification_code,
- MAKELPARAM(point.x, point.y));
+ MAKELPARAM(point.x(), point.y()));
+ if (!ref.get())
+ return;
in_size_loop_ = false;
}
}
@@ -2248,22 +2085,44 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
WPARAM w_param,
LPARAM l_param) {
// Handle touch events only on Aura for now.
-#if !defined(USE_AURA)
- SetMsgHandled(FALSE);
- return 0;
-#endif
int num_points = LOWORD(w_param);
scoped_ptr<TOUCHINPUT[]> input(new TOUCHINPUT[num_points]);
if (ui::GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(l_param),
num_points, input.get(),
sizeof(TOUCHINPUT))) {
+ int flags = ui::GetModifiersFromKeyState();
TouchEvents touch_events;
for (int i = 0; i < num_points; ++i) {
+ POINT point;
+ point.x = TOUCH_COORD_TO_PIXEL(input[i].x);
+ point.y = TOUCH_COORD_TO_PIXEL(input[i].y);
+
+ if (base::win::GetVersion() == base::win::VERSION_WIN7) {
+ // Windows 7 sends touch events for touches in the non-client area,
+ // whereas Windows 8 does not. In order to unify the behaviour, always
+ // ignore touch events in the non-client area.
+ LPARAM l_param_ht = MAKELPARAM(point.x, point.y);
+ LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht);
+
+ if (hittest != HTCLIENT)
+ return 0;
+ }
+
+ ScreenToClient(hwnd(), &point);
+
+ last_touch_message_time_ = ::GetMessageTime();
+
ui::EventType touch_event_type = ui::ET_UNKNOWN;
if (input[i].dwFlags & TOUCHEVENTF_DOWN) {
touch_ids_.insert(input[i].dwID);
touch_event_type = ui::ET_TOUCH_PRESSED;
+ touch_down_contexts_++;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&HWNDMessageHandler::ResetTouchDownContext,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kTouchDownContextResetTimeout));
} else if (input[i].dwFlags & TOUCHEVENTF_UP) {
touch_ids_.erase(input[i].dwID);
touch_event_type = ui::ET_TOUCH_RELEASED;
@@ -2271,19 +2130,27 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
touch_event_type = ui::ET_TOUCH_MOVED;
}
if (touch_event_type != ui::ET_UNKNOWN) {
- POINT point;
- point.x = TOUCH_COORD_TO_PIXEL(input[i].x) /
- gfx::win::GetUndocumentedDPITouchScale();
- point.y = TOUCH_COORD_TO_PIXEL(input[i].y) /
- gfx::win::GetUndocumentedDPITouchScale();
-
- ScreenToClient(hwnd(), &point);
-
- ui::TouchEvent event(
- touch_event_type,
- gfx::Point(point.x, point.y),
- id_generator_.GetGeneratedID(input[i].dwID),
- base::TimeDelta::FromMilliseconds(input[i].dwTime));
+ base::TimeTicks now;
+ // input[i].dwTime doesn't necessarily relate to the system time at all,
+ // so use base::TimeTicks::HighResNow() if possible, or
+ // base::TimeTicks::Now() otherwise.
+ if (base::TimeTicks::IsHighResNowFastAndReliable())
+ now = base::TimeTicks::HighResNow();
+ else
+ now = base::TimeTicks::Now();
+ ui::TouchEvent event(touch_event_type,
+ gfx::Point(point.x, point.y),
+ id_generator_.GetGeneratedID(input[i].dwID),
+ now - base::TimeTicks());
+ event.set_flags(flags);
+ event.latency()->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
+ 0,
+ 0,
+ base::TimeTicks::FromInternalValue(
+ event.time_stamp().ToInternalValue()),
+ 1);
+
touch_events.push_back(event);
if (touch_event_type == ui::ET_TOUCH_RELEASED)
id_generator_.ReleaseNumber(input[i].dwID);
@@ -2314,7 +2181,7 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
window_pos->flags &= ~(SWP_SHOWWINDOW | SWP_HIDEWINDOW);
}
} else if (!GetParent(hwnd())) {
- CRect window_rect;
+ RECT window_rect;
HMONITOR monitor;
gfx::Rect monitor_rect, work_area;
if (GetWindowRect(hwnd(), &window_rect) &&
@@ -2368,6 +2235,9 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
}
}
+ if (DidClientAreaSizeChange(window_pos))
+ delegate_->HandleWindowSizeChanging();
+
if (ScopedFullscreenVisibility::IsHiddenForFullscreen(hwnd())) {
// Prevent the window from being made visible if we've been asked to do so.
// See comment in header as to why we might want this.
@@ -2404,4 +2274,158 @@ void HWNDMessageHandler::HandleTouchEvents(const TouchEvents& touch_events) {
delegate_->HandleTouchEvent(touch_events[i]);
}
+void HWNDMessageHandler::ResetTouchDownContext() {
+ touch_down_contexts_--;
+}
+
+LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ bool track_mouse) {
+ if (!touch_ids_.empty())
+ return 0;
+ // We handle touch events on Windows Aura. Windows generates synthesized
+ // mouse messages in response to touch which we should ignore. However touch
+ // messages are only received for the client area. We need to ignore the
+ // synthesized mouse messages for all points in the client area and places
+ // which return HTNOWHERE.
+ if (ui::IsMouseEventFromTouch(message)) {
+ LPARAM l_param_ht = l_param;
+ // For mouse events (except wheel events), location is in window coordinates
+ // and should be converted to screen coordinates for WM_NCHITTEST.
+ if (message != WM_MOUSEWHEEL && message != WM_MOUSEHWHEEL) {
+ POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param_ht);
+ MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
+ l_param_ht = MAKELPARAM(screen_point.x, screen_point.y);
+ }
+ LRESULT hittest = SendMessage(hwnd(), WM_NCHITTEST, 0, l_param_ht);
+ if (hittest == HTCLIENT || hittest == HTNOWHERE)
+ return 0;
+ }
+
+ // Certain logitech drivers send the WM_MOUSEHWHEEL message to the parent
+ // followed by WM_MOUSEWHEEL messages to the child window causing a vertical
+ // scroll. We treat these WM_MOUSEWHEEL messages as WM_MOUSEHWHEEL
+ // messages.
+ if (message == WM_MOUSEHWHEEL)
+ last_mouse_hwheel_time_ = ::GetMessageTime();
+
+ if (message == WM_MOUSEWHEEL &&
+ ::GetMessageTime() == last_mouse_hwheel_time_) {
+ message = WM_MOUSEHWHEEL;
+ }
+
+ if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
+ is_right_mouse_pressed_on_caption_ = false;
+ ReleaseCapture();
+ // |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
+ // expect screen coordinates.
+ POINT screen_point = CR_POINT_INITIALIZER_FROM_LPARAM(l_param);
+ MapWindowPoints(hwnd(), HWND_DESKTOP, &screen_point, 1);
+ 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));
+ return 0;
+ }
+ } else if (message == WM_NCLBUTTONDOWN && delegate_->IsUsingCustomFrame()) {
+ switch (w_param) {
+ case HTCLOSE:
+ case HTMINBUTTON:
+ case HTMAXBUTTON: {
+ // When the mouse is pressed down in these specific non-client areas,
+ // we need to tell the RootView to send the mouse pressed event (which
+ // sets capture, allowing subsequent WM_LBUTTONUP (note, _not_
+ // WM_NCLBUTTONUP) to fire so that the appropriate WM_SYSCOMMAND can be
+ // sent by the applicable button's ButtonListener. We _have_ to do this
+ // way rather than letting Windows just send the syscommand itself (as
+ // would happen if we never did this dance) because for some insane
+ // reason DefWindowProc for WM_NCLBUTTONDOWN also renders the pressed
+ // window control button appearance, in the Windows classic style, over
+ // our view! Ick! By handling this message we prevent Windows from
+ // doing this undesirable thing, but that means we need to roll the
+ // sys-command handling ourselves.
+ // Combine |w_param| with common key state message flags.
+ w_param |= base::win::IsCtrlPressed() ? MK_CONTROL : 0;
+ w_param |= base::win::IsShiftPressed() ? MK_SHIFT : 0;
+ }
+ }
+ } else if (message == WM_NCRBUTTONDOWN &&
+ (w_param == HTCAPTION || w_param == HTSYSMENU)) {
+ is_right_mouse_pressed_on_caption_ = true;
+ // We SetCapture() to ensure we only show the menu when the button
+ // down and up are both on the caption. Note: this causes the button up to
+ // be WM_RBUTTONUP instead of WM_NCRBUTTONUP.
+ SetCapture();
+ }
+ long message_time = GetMessageTime();
+ MSG msg = { hwnd(), message, w_param, l_param, message_time,
+ { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
+ ui::MouseEvent event(msg);
+ if (IsSynthesizedMouseMessage(message, message_time, l_param))
+ event.set_flags(event.flags() | ui::EF_FROM_TOUCH);
+
+ if (!(event.flags() & ui::EF_IS_NON_CLIENT))
+ delegate_->HandleTooltipMouseMove(message, w_param, l_param);
+
+ if (event.type() == ui::ET_MOUSE_MOVED && !HasCapture() && track_mouse) {
+ // Windows only fires WM_MOUSELEAVE events if the application begins
+ // "tracking" mouse events for a given HWND during WM_MOUSEMOVE events.
+ // We need to call |TrackMouseEvents| to listen for WM_MOUSELEAVE.
+ TrackMouseEvents((message == WM_NCMOUSEMOVE) ?
+ TME_NONCLIENT | TME_LEAVE : TME_LEAVE);
+ } else if (event.type() == ui::ET_MOUSE_EXITED) {
+ // Reset our tracking flags so future mouse movement over this
+ // NativeWidget results in a new tracking session. Fall through for
+ // OnMouseEvent.
+ active_mouse_tracking_flags_ = 0;
+ } else if (event.type() == ui::ET_MOUSEWHEEL) {
+ // Reroute the mouse wheel to the window under the pointer if applicable.
+ return (ui::RerouteMouseWheel(hwnd(), w_param, l_param) ||
+ delegate_->HandleMouseEvent(ui::MouseWheelEvent(msg))) ? 0 : 1;
+ }
+
+ // There are cases where the code handling the message destroys the window,
+ // so use the weak ptr to check if destruction occured or not.
+ base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
+ bool handled = delegate_->HandleMouseEvent(event);
+ if (!ref.get())
+ return 0;
+ if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU &&
+ delegate_->IsUsingCustomFrame()) {
+ // TODO(msw): Eliminate undesired painting, or re-evaluate this workaround.
+ // DefWindowProc for WM_NCLBUTTONDOWN does weird non-client painting, so we
+ // need to call it inside a ScopedRedrawLock. This may cause other negative
+ // side-effects (ex/ stifling non-client mouse releases).
+ DefWindowProcWithRedrawLock(message, w_param, l_param);
+ handled = true;
+ }
+
+ if (ref.get())
+ SetMsgHandled(handled);
+ return 0;
+}
+
+bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
+ int message_time,
+ LPARAM l_param) {
+ if (ui::IsMouseEventFromTouch(message))
+ return true;
+ // Ignore mouse messages which occur at the same location as the current
+ // cursor position and within a time difference of 500 ms from the last
+ // touch message.
+ if (last_touch_message_time_ && message_time >= last_touch_message_time_ &&
+ ((message_time - last_touch_message_time_) <=
+ kSynthesizedMouseTouchMessagesTimeDifference)) {
+ POINT mouse_location = CR_POINT_INITIALIZER_FROM_LPARAM(l_param);
+ ::ClientToScreen(hwnd(), &mouse_location);
+ POINT cursor_pos = {0};
+ ::GetCursorPos(&cursor_pos);
+ if (memcmp(&cursor_pos, &mouse_location, sizeof(POINT)))
+ return false;
+ return true;
+ }
+ return false;
+}
+
} // namespace views
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index 5aacd7819d8..fbc05813ca0 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -6,9 +6,6 @@
#define UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_
#include <windows.h>
-#include <atlbase.h>
-#include <atlapp.h>
-#include <atlmisc.h>
#include <set>
#include <vector>
@@ -17,12 +14,12 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/string16.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/win_util.h"
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/base/ui_base_types.h"
+#include "ui/base/win/window_event_target.h"
#include "ui/events/event.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/sequential_id_generator.h"
@@ -36,6 +33,10 @@ class ImageSkia;
class Insets;
}
+namespace ui {
+class ViewProp;
+}
+
namespace views {
class FullscreenHandler;
@@ -77,10 +78,12 @@ const int WM_NCUAHDRAWFRAME = 0xAF;
LPARAM l_param, \
LRESULT& l_result, \
DWORD msg_map_id = 0) { \
+ base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr()); \
BOOL old_msg_handled = msg_handled_; \
BOOL ret = _ProcessWindowMessage(hwnd, msg, w_param, l_param, l_result, \
msg_map_id); \
- msg_handled_ = old_msg_handled; \
+ if (ref.get()) \
+ msg_handled_ = old_msg_handled; \
return ret; \
} \
BOOL _ProcessWindowMessage(HWND hWnd, \
@@ -103,13 +106,13 @@ const int WM_NCUAHDRAWFRAME = 0xAF;
// An object that handles messages for a HWND that implements the views
// "Custom Frame" look. The purpose of this class is to isolate the windows-
// specific message handling from the code that wraps it. It is intended to be
-// used by both a views::NativeWidget and an aura::RootWindowHost
+// used by both a views::NativeWidget and an aura::WindowTreeHost
// implementation.
// TODO(beng): This object should eventually *become* the WindowImpl.
class VIEWS_EXPORT HWNDMessageHandler :
public gfx::WindowImpl,
public internal::InputMethodDelegate,
- public base::MessageLoopForUI::Observer {
+ public ui::WindowEventTarget {
public:
explicit HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate);
~HWNDMessageHandler();
@@ -129,7 +132,10 @@ class VIEWS_EXPORT HWNDMessageHandler :
void GetWindowPlacement(gfx::Rect* bounds,
ui::WindowShowState* show_state) const;
- void SetBounds(const gfx::Rect& bounds_in_pixels);
+ // Sets the bounds of the HWND to |bounds_in_pixels|. If the HWND size is not
+ // changed, |force_size_changed| determines if we should pretend it is.
+ void SetBounds(const gfx::Rect& bounds_in_pixels, bool force_size_changed);
+
void SetSize(const gfx::Size& size);
void CenterWindow(const gfx::Size& size);
@@ -140,8 +146,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
void Show();
void ShowWindowWithState(ui::WindowShowState show_state);
- // TODO(beng): distinguish from ShowWindowWithState().
- void Show(int show_state);
void ShowMaximizedWithBounds(const gfx::Rect& bounds);
void Hide();
@@ -179,7 +183,7 @@ class VIEWS_EXPORT HWNDMessageHandler :
void SetVisibilityChangedAnimationsEnabled(bool enabled);
// Returns true if the title changed.
- bool SetTitle(const string16& title);
+ bool SetTitle(const base::string16& title);
void SetCursor(HCURSOR cursor);
@@ -211,16 +215,32 @@ class VIEWS_EXPORT HWNDMessageHandler :
WPARAM w_param,
LPARAM l_param) OVERRIDE;
- // Overridden from MessageLoopForUI::Observer:
- virtual base::EventStatus WillProcessEvent(
- const base::NativeEvent& event) OVERRIDE;
- virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
+ // Overridden from WindowEventTarget
+ virtual LRESULT HandleMouseMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) OVERRIDE;
+ virtual LRESULT HandleKeyboardMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) OVERRIDE;
+ virtual LRESULT HandleTouchMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) OVERRIDE;
+
+ virtual LRESULT HandleScrollMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) OVERRIDE;
+
+ virtual LRESULT HandleNcHitTestMessage(unsigned int message,
+ WPARAM w_param,
+ LPARAM l_param) OVERRIDE;
- // Returns the auto-hide edges of the appbar. See Appbar::GetAutohideEdges()
- // for details. If the edges change OnAppbarAutohideEdgesChanged() is called.
+ // Returns the auto-hide edges of the appbar. See
+ // ViewsDelegate::GetAppbarAutohideEdges() for details. If the edges change,
+ // OnAppbarAutohideEdgesChanged() is called.
int GetAppbarAutohideEdges(HMONITOR monitor);
- // Callback if the autohide edges have changed. See Appbar for details.
+ // Callback if the autohide edges have changed. See
+ // ViewsDelegate::GetAppbarAutohideEdges() for details.
void OnAppbarAutohideEdgesChanged();
// Can be called after the delegate has had the opportunity to set focus and
@@ -267,9 +287,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
WPARAM w_param,
LPARAM l_param);
- // Notifies any owned windows that we're closing.
- void NotifyOwnedWindowsParentClosing();
-
// Lock or unlock the window from being able to redraw itself in response to
// updates to its invalid region.
class ScopedRedrawLock;
@@ -279,9 +296,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Stops ignoring SetWindowPos() requests (see below).
void StopIgnoringPosChanges() { ignore_window_pos_changes_ = false; }
- // Synchronously paints the invalid contents of the Widget.
- void RedrawInvalidRect();
-
// Synchronously updates the invalid contents of the Widget. Valid for
// layered windows only.
void RedrawLayeredWindowContents();
@@ -294,90 +308,92 @@ class VIEWS_EXPORT HWNDMessageHandler :
BEGIN_SAFE_MSG_MAP_EX(HWNDMessageHandler)
// Range handlers must go first!
- MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
- MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange)
+ CR_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
+ CR_MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE,
+ WM_NCXBUTTONDBLCLK,
+ OnMouseRange)
// CustomFrameWindow hacks
- MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
- MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
+ CR_MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
+ CR_MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
// Vista and newer
- MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
+ CR_MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
// Non-atlcrack.h handlers
- MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
+ CR_MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
// Mouse events.
- MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate)
- MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseRange)
- MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseRange)
- MESSAGE_HANDLER_EX(WM_SETCURSOR, OnSetCursor);
+ CR_MESSAGE_HANDLER_EX(WM_MOUSEACTIVATE, OnMouseActivate)
+ CR_MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseRange)
+ CR_MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseRange)
+ CR_MESSAGE_HANDLER_EX(WM_SETCURSOR, OnSetCursor);
// Key events.
- MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
- MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent)
+ CR_MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent)
// IME Events.
- MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_IME_ENDCOMPOSITION, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_IME_REQUEST, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_CHAR, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_SYSCHAR, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_DEADCHAR, OnImeMessages)
- MESSAGE_HANDLER_EX(WM_SYSDEADCHAR, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_SETCONTEXT, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_STARTCOMPOSITION, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_ENDCOMPOSITION, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_REQUEST, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_IME_NOTIFY, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_CHAR, OnImeMessages)
+ CR_MESSAGE_HANDLER_EX(WM_SYSCHAR, OnImeMessages)
// Scroll events
- MESSAGE_HANDLER_EX(WM_VSCROLL, OnScrollMessage)
- MESSAGE_HANDLER_EX(WM_HSCROLL, OnScrollMessage)
+ CR_MESSAGE_HANDLER_EX(WM_VSCROLL, OnScrollMessage)
+ CR_MESSAGE_HANDLER_EX(WM_HSCROLL, OnScrollMessage)
// Touch Events.
- MESSAGE_HANDLER_EX(WM_TOUCH, OnTouchEvent)
+ CR_MESSAGE_HANDLER_EX(WM_TOUCH, OnTouchEvent)
// Uses the general handler macro since the specific handler macro
// MSG_WM_NCACTIVATE would convert WPARAM type to BOOL type. The high
// word of WPARAM could be set when the window is minimized or restored.
- MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
+ CR_MESSAGE_HANDLER_EX(WM_NCACTIVATE, OnNCActivate)
// This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
- MSG_WM_ACTIVATEAPP(OnActivateApp)
- MSG_WM_APPCOMMAND(OnAppCommand)
- MSG_WM_CANCELMODE(OnCancelMode)
- MSG_WM_CAPTURECHANGED(OnCaptureChanged)
- MSG_WM_CLOSE(OnClose)
- MSG_WM_COMMAND(OnCommand)
- MSG_WM_CREATE(OnCreate)
- MSG_WM_DESTROY(OnDestroy)
- MSG_WM_DISPLAYCHANGE(OnDisplayChange)
- MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
- MSG_WM_ERASEBKGND(OnEraseBkgnd)
- MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
- MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
- MSG_WM_INITMENU(OnInitMenu)
- MSG_WM_INPUTLANGCHANGE(OnInputLangChange)
- MSG_WM_KILLFOCUS(OnKillFocus)
- MSG_WM_MOVE(OnMove)
- MSG_WM_MOVING(OnMoving)
- MSG_WM_NCCALCSIZE(OnNCCalcSize)
- MSG_WM_NCHITTEST(OnNCHitTest)
- MSG_WM_NCPAINT(OnNCPaint)
- MSG_WM_NOTIFY(OnNotify)
- MSG_WM_PAINT(OnPaint)
- MSG_WM_SETFOCUS(OnSetFocus)
- MSG_WM_SETICON(OnSetIcon)
- MSG_WM_SETTEXT(OnSetText)
- MSG_WM_SETTINGCHANGE(OnSettingChange)
- MSG_WM_SIZE(OnSize)
- MSG_WM_SYSCOMMAND(OnSysCommand)
- MSG_WM_THEMECHANGED(OnThemeChanged)
- MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
- MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
- MSG_WM_WTSSESSION_CHANGE(OnSessionChange)
- END_MSG_MAP()
+ CR_MSG_WM_ACTIVATEAPP(OnActivateApp)
+ CR_MSG_WM_APPCOMMAND(OnAppCommand)
+ CR_MSG_WM_CANCELMODE(OnCancelMode)
+ CR_MSG_WM_CAPTURECHANGED(OnCaptureChanged)
+ CR_MSG_WM_CLOSE(OnClose)
+ CR_MSG_WM_COMMAND(OnCommand)
+ CR_MSG_WM_CREATE(OnCreate)
+ CR_MSG_WM_DESTROY(OnDestroy)
+ CR_MSG_WM_DISPLAYCHANGE(OnDisplayChange)
+ CR_MSG_WM_ENTERMENULOOP(OnEnterMenuLoop)
+ CR_MSG_WM_EXITMENULOOP(OnExitMenuLoop)
+ CR_MSG_WM_ENTERSIZEMOVE(OnEnterSizeMove)
+ CR_MSG_WM_ERASEBKGND(OnEraseBkgnd)
+ CR_MSG_WM_EXITSIZEMOVE(OnExitSizeMove)
+ CR_MSG_WM_GETMINMAXINFO(OnGetMinMaxInfo)
+ CR_MSG_WM_INITMENU(OnInitMenu)
+ CR_MSG_WM_INPUTLANGCHANGE(OnInputLangChange)
+ CR_MSG_WM_KILLFOCUS(OnKillFocus)
+ CR_MSG_WM_MOVE(OnMove)
+ CR_MSG_WM_MOVING(OnMoving)
+ CR_MSG_WM_NCCALCSIZE(OnNCCalcSize)
+ CR_MSG_WM_NCHITTEST(OnNCHitTest)
+ CR_MSG_WM_NCPAINT(OnNCPaint)
+ CR_MSG_WM_NOTIFY(OnNotify)
+ CR_MSG_WM_PAINT(OnPaint)
+ CR_MSG_WM_SETFOCUS(OnSetFocus)
+ CR_MSG_WM_SETICON(OnSetIcon)
+ CR_MSG_WM_SETTEXT(OnSetText)
+ CR_MSG_WM_SETTINGCHANGE(OnSettingChange)
+ CR_MSG_WM_SIZE(OnSize)
+ CR_MSG_WM_SYSCOMMAND(OnSysCommand)
+ CR_MSG_WM_THEMECHANGED(OnThemeChanged)
+ CR_MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
+ CR_MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
+ CR_MSG_WM_WTSSESSION_CHANGE(OnSessionChange)
+ CR_END_MSG_MAP()
// Message Handlers.
// This list is in _ALPHABETICAL_ order!
@@ -393,10 +409,12 @@ class VIEWS_EXPORT HWNDMessageHandler :
void OnCommand(UINT notification_code, int command, HWND window);
LRESULT OnCreate(CREATESTRUCT* create_struct);
void OnDestroy();
- void OnDisplayChange(UINT bits_per_pixel, const CSize& screen_size);
+ void OnDisplayChange(UINT bits_per_pixel, const gfx::Size& screen_size);
LRESULT OnDwmCompositionChanged(UINT msg, WPARAM w_param, LPARAM l_param);
+ void OnEnterMenuLoop(BOOL from_track_popup_menu);
void OnEnterSizeMove();
LRESULT OnEraseBkgnd(HDC dc);
+ void OnExitMenuLoop(BOOL is_shortcut_menu);
void OnExitSizeMove();
void OnGetMinMaxInfo(MINMAXINFO* minmax_info);
LRESULT OnGetObject(UINT message, WPARAM w_param, LPARAM l_param);
@@ -407,11 +425,11 @@ class VIEWS_EXPORT HWNDMessageHandler :
void OnKillFocus(HWND focused_window);
LRESULT OnMouseActivate(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param);
- void OnMove(const CPoint& point);
+ void OnMove(const gfx::Point& point);
void OnMoving(UINT param, const RECT* new_bounds);
LRESULT OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnNCCalcSize(BOOL mode, LPARAM l_param);
- LRESULT OnNCHitTest(const CPoint& point);
+ LRESULT OnNCHitTest(const gfx::Point& point);
void OnNCPaint(HRGN rgn);
LRESULT OnNCUAHDrawCaption(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnNCUAHDrawFrame(UINT message, WPARAM w_param, LPARAM l_param);
@@ -425,8 +443,8 @@ class VIEWS_EXPORT HWNDMessageHandler :
LRESULT OnSetIcon(UINT size_type, HICON new_icon);
LRESULT OnSetText(const wchar_t* text);
void OnSettingChange(UINT flags, const wchar_t* section);
- void OnSize(UINT param, const CSize& size);
- void OnSysCommand(UINT notification_code, const CPoint& point);
+ void OnSize(UINT param, const gfx::Size& size);
+ void OnSysCommand(UINT notification_code, const gfx::Point& point);
void OnThemeChanged();
LRESULT OnTouchEvent(UINT message, WPARAM w_param, LPARAM l_param);
void OnWindowPosChanging(WINDOWPOS* window_pos);
@@ -438,6 +456,28 @@ class VIEWS_EXPORT HWNDMessageHandler :
// of a touch event.
void HandleTouchEvents(const TouchEvents& touch_events);
+ // Resets the flag which indicates that we are in the context of a touch down
+ // event.
+ void ResetTouchDownContext();
+
+ // Helper to handle mouse events.
+ // The |message|, |w_param|, |l_param| parameters identify the Windows mouse
+ // message and its parameters respectively.
+ // The |track_mouse| parameter indicates if we should track the mouse.
+ LRESULT HandleMouseEventInternal(UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ bool track_mouse);
+
+ // Returns true if the mouse message passed in is an OS synthesized mouse
+ // message.
+ // |message| identifies the mouse message.
+ // |message_time| is the time when the message occurred.
+ // |l_param| indicates the location of the mouse message.
+ bool IsSynthesizedMouseMessage(unsigned int message,
+ int message_time,
+ LPARAM l_param);
+
HWNDMessageHandlerDelegate* delegate_;
scoped_ptr<FullscreenHandler> fullscreen_handler_;
@@ -449,10 +489,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
bool use_system_default_icon_;
- // Whether the focus should be restored next time we get enabled. Needed to
- // restore focus correctly when Windows modal dialogs are displayed.
- bool restore_focus_when_enabled_;
-
// Whether all ancestors have been enabled. This is only used if is_modal_ is
// true.
bool restored_enabled_;
@@ -535,6 +571,9 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Copy of custom window region specified via SetRegion(), if any.
base::win::ScopedRegion custom_window_region_;
+ // If > 0 indicates a menu is running (we're showing a native menu).
+ int menu_depth_;
+
// A factory used to lookup appbar autohide edges.
base::WeakPtrFactory<HWNDMessageHandler> autohide_factory_;
@@ -547,14 +586,30 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Set to true if we are in the context of a sizing operation.
bool in_size_loop_;
+ // Stores a pointer to the WindowEventTarget interface implemented by this
+ // class. Allows callers to retrieve the interface pointer.
+ scoped_ptr<ui::ViewProp> prop_window_target_;
+
+ // Number of active touch down contexts. This is incremented on touch down
+ // events and decremented later using a delayed task.
+ // We need this to ignore WM_MOUSEACTIVATE messages generated in response to
+ // touch input. This is fine because activation still works correctly via
+ // native SetFocus calls invoked in the views code.
+ int touch_down_contexts_;
+
+ // Time the last touch message was received. Used to flag mouse messages
+ // synthesized by Windows for touch which are not flagged by the OS as
+ // synthesized mouse messages. For more information please refer to
+ // the IsMouseEventFromTouch function.
+ static long last_touch_message_time_;
+
+ // Time the last WM_MOUSEHWHEEL message is received. Please refer to the
+ // HandleMouseEventInternal function as to why this is needed.
+ long last_mouse_hwheel_time_;
+
DISALLOW_COPY_AND_ASSIGN(HWNDMessageHandler);
};
-// This window property if set on the window does not activate the window for a
-// touch based WM_MOUSEACTIVATE message.
-const wchar_t kIgnoreTouchMouseActivateForWindow[] =
- L"Chrome.IgnoreMouseActivate";
-
} // namespace views
#endif // UI_VIEWS_WIN_HWND_MESSAGE_HANDLER_H_
diff --git a/chromium/ui/views/win/hwnd_message_handler_delegate.h b/chromium/ui/views/win/hwnd_message_handler_delegate.h
index e932d30c5e8..e17bf78eaa6 100644
--- a/chromium/ui/views/win/hwnd_message_handler_delegate.h
+++ b/chromium/ui/views/win/hwnd_message_handler_delegate.h
@@ -25,7 +25,6 @@ class TouchEvent;
namespace views {
class InputMethod;
-class NativeWidgetWin;
// Implemented by the object that uses the HWNDMessageHandler to handle
// notifications from the underlying HWND and service requests for data.
@@ -47,13 +46,6 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
virtual bool WidgetSizeIsClientSize() const = 0;
- // Returns true if the delegate has a focus saving mechanism that should be
- // used when the window is activated and deactivated.
- virtual bool CanSaveFocus() const = 0;
- virtual void SaveFocusOnDeactivate() = 0;
- virtual void RestoreFocusOnActivate() = 0;
- virtual void RestoreFocusOnEnable() = 0;
-
// Returns true if the delegate represents a modal window.
virtual bool IsModal() const = 0;
@@ -137,7 +129,7 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
// Called when the HWND is to be focused for the first time. This is called
// when the window is shown for the first time. Returns true if the delegate
// set focus and no default processing should be done by the message handler.
- virtual bool HandleInitialFocus() = 0;
+ virtual bool HandleInitialFocus(ui::WindowShowState show_state) = 0;
// Called when display settings are adjusted on the system.
virtual void HandleDisplayChange() = 0;
@@ -217,6 +209,9 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
WPARAM w_param,
LPARAM l_param) = 0;
+ // Invoked on entering/exiting a menu loop.
+ virtual void HandleMenuLoop(bool in_menu_loop) = 0;
+
// Catch-all message handling and filtering. Called before
// HWNDMessageHandler's built-in handling, which may pre-empt some
// expectations in Views/Aura if messages are consumed. Returns true if the
@@ -238,6 +233,9 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
// handled by the delegate.
virtual bool HandleScrollEvent(const ui::ScrollEvent& event) = 0;
+ // Called when the window size is about to change.
+ virtual void HandleWindowSizeChanging() = 0;
+
protected:
virtual ~HWNDMessageHandlerDelegate() {}
};
diff --git a/chromium/ui/views/win/hwnd_util_aurawin.cc b/chromium/ui/views/win/hwnd_util_aurawin.cc
index 9fc6f10d816..37dca58f774 100644
--- a/chromium/ui/views/win/hwnd_util_aurawin.cc
+++ b/chromium/ui/views/win/hwnd_util_aurawin.cc
@@ -4,8 +4,8 @@
#include "ui/views/win/hwnd_util.h"
-#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_tree_host.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -20,21 +20,20 @@ HWND HWNDForWidget(const Widget* widget) {
HWND HWNDForNativeView(const gfx::NativeView view) {
return view && view->GetRootWindow() ?
- view->GetDispatcher()->host()->GetAcceleratedWidget() : NULL;
+ view->GetHost()->GetAcceleratedWidget() : NULL;
}
HWND HWNDForNativeWindow(const gfx::NativeWindow window) {
return window && window->GetRootWindow() ?
- window->GetDispatcher()->host()->GetAcceleratedWidget() : NULL;
+ window->GetHost()->GetAcceleratedWidget() : NULL;
}
gfx::Rect GetWindowBoundsForClientBounds(View* view,
const gfx::Rect& client_bounds) {
DCHECK(view);
- aura::WindowEventDispatcher* dispatcher =
- view->GetWidget()->GetNativeWindow()->GetDispatcher();
- if (dispatcher) {
- HWND hwnd = dispatcher->host()->GetAcceleratedWidget();
+ aura::WindowTreeHost* host = view->GetWidget()->GetNativeWindow()->GetHost();
+ if (host) {
+ HWND hwnd = host->GetAcceleratedWidget();
RECT rect = client_bounds.ToRECT();
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
diff --git a/chromium/ui/views/win/hwnd_util_win.cc b/chromium/ui/views/win/hwnd_util_win.cc
deleted file mode 100644
index abc05f8ec84..00000000000
--- a/chromium/ui/views/win/hwnd_util_win.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/win/hwnd_util.h"
-
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-HWND HWNDForView(const View* view) {
- return view->GetWidget() ? HWNDForWidget(view->GetWidget()) : NULL;
-}
-
-// Returns the HWND associated with the specified widget.
-HWND HWNDForWidget(const Widget* widget) {
- return widget->GetNativeView();
-}
-
-HWND HWNDForNativeView(const gfx::NativeView view) {
- return view;
-}
-
-HWND HWNDForNativeWindow(const gfx::NativeWindow window) {
- return window;
-}
-
-gfx::Rect GetWindowBoundsForClientBounds(View* view,
- const gfx::Rect& client_bounds) {
- DCHECK(view);
- HWND hwnd = view->GetWidget()->GetNativeWindow();
- RECT rect = client_bounds.ToRECT();
- DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
- DWORD ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
- AdjustWindowRectEx(&rect, style, FALSE, ex_style);
- return gfx::Rect(rect);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/window/client_view.cc b/chromium/ui/views/window/client_view.cc
index 7edc5f4d5b9..fb7d89fed18 100644
--- a/chromium/ui/views/window/client_view.cc
+++ b/chromium/ui/views/window/client_view.cc
@@ -5,7 +5,7 @@
#include "ui/views/window/client_view.h"
#include "base/logging.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/hit_test.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -45,19 +45,19 @@ void ClientView::WidgetClosing() {
///////////////////////////////////////////////////////////////////////////////
// ClientView, View overrides:
-gfx::Size ClientView::GetPreferredSize() {
+gfx::Size ClientView::GetPreferredSize() const {
// |contents_view_| is allowed to be NULL up until the point where this view
// is attached to a Container.
return contents_view_ ? contents_view_->GetPreferredSize() : gfx::Size();
}
-gfx::Size ClientView::GetMaximumSize() {
+gfx::Size ClientView::GetMaximumSize() const {
// |contents_view_| is allowed to be NULL up until the point where this view
// is attached to a Container.
return contents_view_ ? contents_view_->GetMaximumSize() : gfx::Size();
}
-gfx::Size ClientView::GetMinimumSize() {
+gfx::Size ClientView::GetMinimumSize() const {
// |contents_view_| is allowed to be NULL up until the point where this view
// is attached to a Container.
return contents_view_ ? contents_view_->GetMinimumSize() : gfx::Size();
@@ -74,8 +74,8 @@ const char* ClientView::GetClassName() const {
return kViewClassName;
}
-void ClientView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_CLIENT;
+void ClientView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_CLIENT;
}
void ClientView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
diff --git a/chromium/ui/views/window/client_view.h b/chromium/ui/views/window/client_view.h
index 8c890d70b7c..5a329aad567 100644
--- a/chromium/ui/views/window/client_view.h
+++ b/chromium/ui/views/window/client_view.h
@@ -57,15 +57,15 @@ class VIEWS_EXPORT ClientView : public View {
virtual int NonClientHitTest(const gfx::Point& point);
// Overridden from View:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
protected:
// Overridden from View:
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index bb27dc60ca5..a3fb3f7c96c 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -5,6 +5,7 @@
#include "ui/views/window/custom_frame_view.h"
#include <algorithm>
+#include <vector>
#include "base/strings/utf_string_conversions.h"
#include "grit/ui_resources.h"
@@ -16,21 +17,19 @@
#include "ui/gfx/font.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
+#include "ui/gfx/rect.h"
#include "ui/views/color_constants.h"
#include "ui/views/controls/button/image_button.h"
+#include "ui/views/views_delegate.h"
+#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"
#include "ui/views/window/frame_background.h"
+#include "ui/views/window/window_button_order_provider.h"
#include "ui/views/window/window_resources.h"
#include "ui/views/window/window_shape.h"
-#if defined(USE_AURA)
-#include "ui/views/widget/native_widget_aura.h"
-#elif defined(OS_WIN)
-#include "ui/views/widget/native_widget_win.h"
-#endif
-
namespace views {
namespace {
@@ -65,19 +64,17 @@ const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201);
const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
#endif
-const gfx::Font& GetTitleFont() {
- static gfx::Font* title_font = NULL;
- if (!title_font) {
-#if defined(USE_AURA)
- title_font = new gfx::Font(NativeWidgetAura::GetWindowTitleFont());
-#elif defined(OS_WIN)
- title_font = new gfx::Font(NativeWidgetWin::GetWindowTitleFont());
-#elif defined(OS_LINUX)
- // TODO(ben): need to resolve what font this is.
- title_font = new gfx::Font();
-#endif
- }
- return *title_font;
+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->SetImageAlignment(ImageButton::ALIGN_LEFT,
+ ImageButton::ALIGN_BOTTOM);
+ button->SetBoundsRect(bounds);
}
} // namespace
@@ -93,7 +90,9 @@ CustomFrameView::CustomFrameView()
restore_button_(NULL),
close_button_(NULL),
should_show_maximize_button_(false),
- frame_background_(new FrameBackground()) {
+ frame_background_(new FrameBackground()),
+ minimum_title_bar_x_(0),
+ maximum_title_bar_x_(-1) {
}
CustomFrameView::~CustomFrameView() {
@@ -102,19 +101,12 @@ CustomFrameView::~CustomFrameView() {
void CustomFrameView::Init(Widget* frame) {
frame_ = frame;
- close_button_ = new ImageButton(this);
- close_button_->SetAccessibleName(
- l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
-
- // Close button images will be set in LayoutWindowControls().
- AddChildView(close_button_);
-
+ close_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_CLOSE,
+ IDR_CLOSE, IDR_CLOSE_H, IDR_CLOSE_P);
minimize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MINIMIZE,
IDR_MINIMIZE, IDR_MINIMIZE_H, IDR_MINIMIZE_P);
-
maximize_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_MAXIMIZE,
IDR_MAXIMIZE, IDR_MAXIMIZE_H, IDR_MAXIMIZE_P);
-
restore_button_ = InitWindowCaptionButton(IDS_APP_ACCNAME_RESTORE,
IDR_RESTORE, IDR_RESTORE_H, IDR_RESTORE_P);
@@ -137,8 +129,8 @@ gfx::Rect CustomFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
int top_height = NonClientTopBorderHeight();
int border_thickness = NonClientBorderThickness();
- return gfx::Rect(std::max(0, client_bounds.x() - border_thickness),
- std::max(0, client_bounds.y() - top_height),
+ return gfx::Rect(client_bounds.x() - border_thickness,
+ client_bounds.y() - top_height,
client_bounds.width() + (2 * border_thickness),
client_bounds.height() + top_height + border_thickness);
}
@@ -186,7 +178,7 @@ int CustomFrameView::NonClientHitTest(const gfx::Point& point) {
void CustomFrameView::GetWindowMask(const gfx::Size& size,
gfx::Path* window_mask) {
DCHECK(window_mask);
- if (frame_->IsMaximized())
+ if (frame_->IsMaximized() || !ShouldShowTitleBarAndBorder())
return;
GetDefaultWindowMask(size, window_mask);
@@ -205,13 +197,17 @@ void CustomFrameView::UpdateWindowIcon() {
}
void CustomFrameView::UpdateWindowTitle() {
- SchedulePaintInRect(title_bounds_);
+ if (frame_->widget_delegate()->ShouldShowWindowTitle())
+ SchedulePaintInRect(title_bounds_);
}
///////////////////////////////////////////////////////////////////////////////
// CustomFrameView, View overrides:
void CustomFrameView::OnPaint(gfx::Canvas* canvas) {
+ if (!ShouldShowTitleBarAndBorder())
+ return;
+
if (frame_->IsMaximized())
PaintMaximizedFrameBorder(canvas);
else
@@ -222,22 +218,25 @@ void CustomFrameView::OnPaint(gfx::Canvas* canvas) {
}
void CustomFrameView::Layout() {
- LayoutWindowControls();
- LayoutTitleBar();
+ if (ShouldShowTitleBarAndBorder()) {
+ LayoutWindowControls();
+ LayoutTitleBar();
+ }
+
LayoutClientView();
}
-gfx::Size CustomFrameView::GetPreferredSize() {
+gfx::Size CustomFrameView::GetPreferredSize() const {
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
gfx::Rect(frame_->client_view()->GetPreferredSize())).size();
}
-gfx::Size CustomFrameView::GetMinimumSize() {
+gfx::Size CustomFrameView::GetMinimumSize() const {
return frame_->non_client_view()->GetWindowBoundsForClientBounds(
gfx::Rect(frame_->client_view()->GetMinimumSize())).size();
}
-gfx::Size CustomFrameView::GetMaximumSize() {
+gfx::Size CustomFrameView::GetMaximumSize() const {
gfx::Size max_size = frame_->client_view()->GetMaximumSize();
gfx::Size converted_size =
frame_->non_client_view()->GetWindowBoundsForClientBounds(
@@ -282,7 +281,11 @@ int CustomFrameView::NonClientTopBorderHeight() const {
int CustomFrameView::CaptionButtonY() const {
// Maximized buttons start at window top so that even if their images aren't
// drawn flush with the screen edge, they still obey Fitts' Law.
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ return FrameBorderThickness();
+#else
return frame_->IsMaximized() ? FrameBorderThickness() : kFrameShadowThickness;
+#endif
}
int CustomFrameView::TitlebarBottomThickness() const {
@@ -296,7 +299,7 @@ int CustomFrameView::IconSize() const {
// size are increased.
return GetSystemMetrics(SM_CYSMICON);
#else
- return std::max(GetTitleFont().GetHeight(), kIconMinimumSize);
+ return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize);
#endif
}
@@ -320,11 +323,24 @@ gfx::Rect CustomFrameView::IconBounds() const {
// 3D edge (or nothing at all, for maximized windows) above; hence the +1.
int y = unavailable_px_at_top + (NonClientTopBorderHeight() -
unavailable_px_at_top - size - TitlebarBottomThickness() + 1) / 2;
- return gfx::Rect(frame_thickness + kIconLeftSpacing, y, size, size);
+ return gfx::Rect(frame_thickness + kIconLeftSpacing + minimum_title_bar_x_,
+ y, size, size);
+}
+
+bool CustomFrameView::ShouldShowTitleBarAndBorder() const {
+ if (frame_->IsFullscreen())
+ return false;
+
+ if (ViewsDelegate::views_delegate) {
+ return !ViewsDelegate::views_delegate->WindowManagerProvidesTitleBar(
+ frame_->IsMaximized());
+ }
+
+ return true;
}
bool CustomFrameView::ShouldShowClientEdge() const {
- return !frame_->IsMaximized();
+ return !frame_->IsMaximized() && ShouldShowTitleBarAndBorder();
}
void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
@@ -374,13 +390,13 @@ void CustomFrameView::PaintTitleBar(gfx::Canvas* canvas) {
// It seems like in some conditions we can be asked to paint after the window
// that contains us is WM_DESTROYed. At this point, our delegate is NULL. The
// correct long term fix may be to shut down the RootView in WM_DESTROY.
- if (!delegate)
+ if (!delegate || !delegate->ShouldShowWindowTitle())
return;
- canvas->DrawStringInt(delegate->GetWindowTitle(), GetTitleFont(),
- SK_ColorWHITE, GetMirroredXForRect(title_bounds_),
- title_bounds_.y(), title_bounds_.width(),
- title_bounds_.height());
+ gfx::Rect rect = title_bounds_;
+ rect.set_x(GetMirroredXForRect(title_bounds_));
+ canvas->DrawStringRect(delegate->GetWindowTitle(), GetTitleFontList(),
+ SK_ColorWHITE, rect);
}
void CustomFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
@@ -462,70 +478,68 @@ const gfx::ImageSkia* CustomFrameView::GetFrameImage() const {
}
void CustomFrameView::LayoutWindowControls() {
- close_button_->SetImageAlignment(ImageButton::ALIGN_LEFT,
- ImageButton::ALIGN_BOTTOM);
+ minimum_title_bar_x_ = 0;
+ maximum_title_bar_x_ = width();
+
+ if (bounds().IsEmpty())
+ return;
+
int caption_y = CaptionButtonY();
bool is_maximized = frame_->IsMaximized();
// There should always be the same number of non-shadow pixels visible to the
- // side of the caption buttons. In maximized mode we extend the rightmost
- // button to the screen corner to obey Fitts' Law.
- int right_extra_width = is_maximized ?
+ // side of the caption buttons. In maximized mode we extend the edge button
+ // to the screen corner to obey Fitts' Law.
+ int extra_width = is_maximized ?
(kFrameBorderThickness - kFrameShadowThickness) : 0;
- gfx::Size close_button_size = close_button_->GetPreferredSize();
- close_button_->SetBounds(width() - FrameBorderThickness() -
- right_extra_width - close_button_size.width(), caption_y,
- close_button_size.width() + right_extra_width,
- close_button_size.height());
-
- // When the window is restored, we show a maximized button; otherwise, we show
- // a restore button.
+ int next_button_x = FrameBorderThickness();
+
bool is_restored = !is_maximized && !frame_->IsMinimized();
ImageButton* invisible_button = is_restored ? restore_button_
: maximize_button_;
invisible_button->SetVisible(false);
- ImageButton* visible_button = is_restored ? maximize_button_
- : restore_button_;
- FramePartImage normal_part, hot_part, pushed_part;
- int next_button_x;
- if (should_show_maximize_button_) {
- visible_button->SetVisible(true);
- visible_button->SetImageAlignment(ImageButton::ALIGN_LEFT,
- ImageButton::ALIGN_BOTTOM);
- gfx::Size visible_button_size = visible_button->GetPreferredSize();
- visible_button->SetBounds(close_button_->x() - visible_button_size.width(),
- caption_y, visible_button_size.width(),
- visible_button_size.height());
- next_button_x = visible_button->x();
- } else {
- visible_button->SetVisible(false);
- next_button_x = close_button_->x();
+ WindowButtonOrderProvider* button_order =
+ WindowButtonOrderProvider::GetInstance();
+ const std::vector<views::FrameButton>& leading_buttons =
+ button_order->leading_buttons();
+ const std::vector<views::FrameButton>& trailing_buttons =
+ button_order->trailing_buttons();
+
+ ImageButton* button = NULL;
+ for (std::vector<views::FrameButton>::const_iterator it =
+ leading_buttons.begin(); it != leading_buttons.end(); ++it) {
+ button = GetImageButton(*it);
+ if (!button)
+ continue;
+ gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y),
+ button->GetPreferredSize());
+ if (it == leading_buttons.begin())
+ target_bounds.set_width(target_bounds.width() + extra_width);
+ LayoutButton(button, target_bounds);
+ next_button_x += button->width();
+ minimum_title_bar_x_ = std::min(width(), next_button_x);
}
- minimize_button_->SetVisible(true);
- minimize_button_->SetImageAlignment(ImageButton::ALIGN_LEFT,
- ImageButton::ALIGN_BOTTOM);
- gfx::Size minimize_button_size = minimize_button_->GetPreferredSize();
- minimize_button_->SetBounds(
- next_button_x - minimize_button_size.width(), caption_y,
- minimize_button_size.width(),
- minimize_button_size.height());
-
- normal_part = IDR_CLOSE;
- hot_part = IDR_CLOSE_H;
- pushed_part = IDR_CLOSE_P;
-
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-
- close_button_->SetImage(CustomButton::STATE_NORMAL,
- rb.GetImageNamed(normal_part).ToImageSkia());
- close_button_->SetImage(CustomButton::STATE_HOVERED,
- rb.GetImageNamed(hot_part).ToImageSkia());
- close_button_->SetImage(CustomButton::STATE_PRESSED,
- rb.GetImageNamed(pushed_part).ToImageSkia());
+ // Trailing buttions are laid out in a RTL fashion
+ next_button_x = width() - FrameBorderThickness();
+ for (std::vector<views::FrameButton>::const_reverse_iterator it =
+ trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) {
+ button = GetImageButton(*it);
+ if (!button)
+ continue;
+ gfx::Rect target_bounds(gfx::Point(next_button_x, caption_y),
+ button->GetPreferredSize());
+ if (it == trailing_buttons.rbegin())
+ target_bounds.set_width(target_bounds.width() + extra_width);
+ target_bounds.Offset(-target_bounds.width(), 0);
+ LayoutButton(button, target_bounds);
+ next_button_x = button->x();
+ maximum_title_bar_x_ = std::max(minimum_title_bar_x_, next_button_x);
+ }
}
void CustomFrameView::LayoutTitleBar() {
+ DCHECK_GE(maximum_title_bar_x_, 0);
// The window title position is calculated based on the icon position, even
// when there is no icon.
gfx::Rect icon_bounds(IconBounds());
@@ -533,10 +547,13 @@ void CustomFrameView::LayoutTitleBar() {
if (show_window_icon)
window_icon_->SetBoundsRect(icon_bounds);
+ if (!frame_->widget_delegate()->ShouldShowWindowTitle())
+ return;
+
// 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 = GetTitleFont().GetHeight();
+ int title_height = GetTitleFontList().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
@@ -544,11 +561,16 @@ void CustomFrameView::LayoutTitleBar() {
// title from overlapping the 3D edge at the bottom of the titlebar.
title_bounds_.SetRect(title_x,
icon_bounds.y() + ((icon_bounds.height() - title_height - 1) / 2),
- std::max(0, minimize_button_->x() - kTitleCaptionSpacing -
+ std::max(0, maximum_title_bar_x_ - kTitleCaptionSpacing -
title_x), title_height);
}
void CustomFrameView::LayoutClientView() {
+ if (!ShouldShowTitleBarAndBorder()) {
+ client_view_bounds_ = bounds();
+ return;
+ }
+
int top_height = NonClientTopBorderHeight();
int border_thickness = NonClientBorderThickness();
client_view_bounds_.SetRect(border_thickness, top_height,
@@ -574,4 +596,31 @@ ImageButton* CustomFrameView::InitWindowCaptionButton(
return button;
}
+ImageButton* CustomFrameView::GetImageButton(views::FrameButton frame_button) {
+ ImageButton* button = NULL;
+ switch (frame_button) {
+ case views::FRAME_BUTTON_MINIMIZE: {
+ button = minimize_button_;
+ break;
+ }
+ case views::FRAME_BUTTON_MAXIMIZE: {
+ bool is_restored = !frame_->IsMaximized() && !frame_->IsMinimized();
+ button = is_restored ? maximize_button_ : restore_button_;
+ if (!should_show_maximize_button_) {
+ // If we should not show the maximize/restore button, then we return
+ // NULL as we don't want this button to become visible and to be laid
+ // out.
+ button->SetVisible(false);
+ return NULL;
+ }
+ break;
+ }
+ case views::FRAME_BUTTON_CLOSE: {
+ button = close_button_;
+ break;
+ }
+ }
+ return button;
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/custom_frame_view.h b/chromium/ui/views/window/custom_frame_view.h
index 8c96df7fc9f..fe5a3e4c7bd 100644
--- a/chromium/ui/views/window/custom_frame_view.h
+++ b/chromium/ui/views/window/custom_frame_view.h
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "ui/views/controls/button/button.h"
+#include "ui/views/window/frame_buttons.h"
#include "ui/views/window/non_client_view.h"
namespace gfx {
@@ -29,8 +30,8 @@ class Widget;
// rendering the non-standard window caption, border, and controls.
//
////////////////////////////////////////////////////////////////////////////////
-class CustomFrameView : public NonClientFrameView,
- public ButtonListener {
+class VIEWS_EXPORT CustomFrameView : public NonClientFrameView,
+ public ButtonListener {
public:
CustomFrameView();
virtual ~CustomFrameView();
@@ -51,14 +52,16 @@ class CustomFrameView : public NonClientFrameView,
// Overridden from View:
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void Layout() OVERRIDE;
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
// Overridden from ButtonListener:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
private:
+ friend class CustomFrameViewTest;
+
// Returns the thickness of the border that makes up the window frame edges.
// This does not include any client edge.
int FrameBorderThickness() const;
@@ -86,6 +89,10 @@ class CustomFrameView : public NonClientFrameView,
// there was one).
gfx::Rect IconBounds() const;
+ // Returns true if the title bar, caption buttons, and frame border should be
+ // drawn. If false, the client view occupies the full area of this view.
+ bool ShouldShowTitleBarAndBorder() const;
+
// Returns true if the client edge should be drawn. This is true if
// the window is not maximized.
bool ShouldShowClientEdge() const;
@@ -100,8 +107,13 @@ class CustomFrameView : public NonClientFrameView,
SkColor GetFrameColor() const;
const gfx::ImageSkia* GetFrameImage() const;
- // Layout various sub-components of this view.
+ // Performs the layout for the window control buttons based on the
+ // configuration specified in WindowButtonOrderProvider. The sizing and
+ // positions of the buttons affects LayoutTitleBar, call this beforehand.
void LayoutWindowControls();
+
+ // Calculations depend on the positions of the window controls. Always call
+ // LayoutWindowControls beforehand.
void LayoutTitleBar();
void LayoutClientView();
@@ -112,6 +124,10 @@ class CustomFrameView : public NonClientFrameView,
int hot_image_id,
int pushed_image_id);
+ // Returns the window caption button for the given FrameButton type, if it
+ // should be visible. Otherwise NULL.
+ ImageButton* GetImageButton(views::FrameButton button);
+
// The bounds of the client view, in this view's coordinates.
gfx::Rect client_view_bounds_;
@@ -136,6 +152,11 @@ class CustomFrameView : public NonClientFrameView,
// Background painter for the window frame.
scoped_ptr<FrameBackground> frame_background_;
+ // The horizontal boundaries for the title bar to layout within. Restricted
+ // by the space used by the leading and trailing buttons.
+ int minimum_title_bar_x_;
+ int maximum_title_bar_x_;
+
DISALLOW_COPY_AND_ASSIGN(CustomFrameView);
};
diff --git a/chromium/ui/views/window/custom_frame_view_unittest.cc b/chromium/ui/views/window/custom_frame_view_unittest.cc
new file mode 100644
index 00000000000..26711190214
--- /dev/null
+++ b/chromium/ui/views/window/custom_frame_view_unittest.cc
@@ -0,0 +1,252 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/window/custom_frame_view.h"
+
+#include <vector>
+
+#include "ui/views/controls/button/image_button.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/window_button_order_provider.h"
+
+namespace views {
+
+namespace {
+
+// Allows for the control of whether or not the widget can maximize or not.
+// This can be set after initial setup in order to allow testing of both forms
+// of delegates. By default this can maximize.
+class MaximizeStateControlDelegate : public WidgetDelegateView {
+ public:
+ MaximizeStateControlDelegate() : can_maximize_(true) {}
+ virtual ~MaximizeStateControlDelegate() {}
+
+ void set_can_maximize(bool can_maximize) {
+ can_maximize_ = can_maximize;
+ }
+
+ // WidgetDelegate:
+ virtual bool CanMaximize() const OVERRIDE { return can_maximize_; }
+
+ private:
+ bool can_maximize_;
+
+ DISALLOW_COPY_AND_ASSIGN(MaximizeStateControlDelegate);
+};
+
+} // namespace
+
+class CustomFrameViewTest : public ViewsTestBase {
+ public:
+ CustomFrameViewTest() {}
+ virtual ~CustomFrameViewTest() {}
+
+ CustomFrameView* custom_frame_view() {
+ return custom_frame_view_;
+ }
+
+ MaximizeStateControlDelegate* maximize_state_control_delegate() {
+ return maximize_state_control_delegate_;
+ }
+
+ Widget* widget() {
+ return widget_;
+ }
+
+ // ViewsTestBase:
+ virtual void SetUp() OVERRIDE;
+ virtual void TearDown() OVERRIDE;
+
+ protected:
+ const std::vector<views::FrameButton>& leading_buttons() {
+ return WindowButtonOrderProvider::GetInstance()->leading_buttons();
+ }
+
+ const std::vector<views::FrameButton>& trailing_buttons() {
+ return WindowButtonOrderProvider::GetInstance()->trailing_buttons();
+ }
+
+ ImageButton* minimize_button() {
+ return custom_frame_view_->minimize_button_;
+ }
+
+ ImageButton* maximize_button() {
+ return custom_frame_view_->maximize_button_;
+ }
+
+ ImageButton* restore_button() {
+ return custom_frame_view_->restore_button_;
+ }
+
+ ImageButton* close_button() {
+ return custom_frame_view_->close_button_;
+ }
+
+ gfx::Rect title_bounds() {
+ return custom_frame_view_->title_bounds_;
+ }
+
+ void SetWindowButtonOrder(
+ const std::vector<views::FrameButton> leading_buttons,
+ const std::vector<views::FrameButton> trailing_buttons);
+
+ private:
+ // Parent container for |custom_frame_view_|
+ Widget* widget_;
+
+ // Owned by |widget_|
+ CustomFrameView* custom_frame_view_;
+
+ // Delegate of |widget_| which controls maximizing
+ MaximizeStateControlDelegate* maximize_state_control_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomFrameViewTest);
+};
+
+void CustomFrameViewTest::SetUp() {
+ ViewsTestBase::SetUp();
+
+ maximize_state_control_delegate_ = new MaximizeStateControlDelegate;
+ widget_ = new Widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.delegate = maximize_state_control_delegate_;
+ params.remove_standard_frame = true;
+ widget_->Init(params);
+
+ custom_frame_view_ = new CustomFrameView;
+ widget_->non_client_view()->SetFrameView(custom_frame_view_);
+}
+
+void CustomFrameViewTest::TearDown() {
+ widget_->CloseNow();
+
+ ViewsTestBase::TearDown();
+}
+
+void CustomFrameViewTest::SetWindowButtonOrder(
+ const std::vector<views::FrameButton> leading_buttons,
+ const std::vector<views::FrameButton> trailing_buttons) {
+ WindowButtonOrderProvider::GetInstance()->
+ SetWindowButtonOrder(leading_buttons, trailing_buttons);
+}
+
+// Tests that there is a default button ordering before initialization causes
+// a configuration file check.
+TEST_F(CustomFrameViewTest, DefaultButtons) {
+ const std::vector<views::FrameButton>& trailing = trailing_buttons();
+ EXPECT_EQ(trailing.size(), 3u);
+ EXPECT_TRUE(leading_buttons().empty());
+ EXPECT_EQ(trailing[0], FRAME_BUTTON_MINIMIZE);
+ EXPECT_EQ(trailing[1], FRAME_BUTTON_MAXIMIZE);
+ EXPECT_EQ(trailing[2], FRAME_BUTTON_CLOSE);
+}
+
+// Tests that layout places the buttons in order, that the restore button is
+// hidden and the buttons are placed after the title.
+TEST_F(CustomFrameViewTest, DefaultButtonLayout) {
+ Widget* parent = widget();
+ CustomFrameView* view = custom_frame_view();
+ view->Init(parent);
+ parent->SetBounds(gfx::Rect(0, 0, 300, 100));
+ parent->Show();
+
+ EXPECT_LT(minimize_button()->x(), maximize_button()->x());
+ EXPECT_LT(maximize_button()->x(), close_button()->x());
+ EXPECT_FALSE(restore_button()->visible());
+
+ EXPECT_GT(minimize_button()->x(),
+ title_bounds().x() + title_bounds().width());
+}
+
+// Tests that setting the buttons to leading places them before the title.
+TEST_F(CustomFrameViewTest, LeadingButtonLayout) {
+ Widget* parent = widget();
+ CustomFrameView* view = custom_frame_view();
+
+ std::vector<views::FrameButton> leading;
+ leading.push_back(views::FRAME_BUTTON_CLOSE);
+ leading.push_back(views::FRAME_BUTTON_MINIMIZE);
+ leading.push_back(views::FRAME_BUTTON_MAXIMIZE);
+
+ std::vector<views::FrameButton> trailing;
+
+ SetWindowButtonOrder(leading, trailing);
+
+ view->Init(parent);
+ parent->SetBounds(gfx::Rect(0, 0, 300, 100));
+ parent->Show();
+ EXPECT_LT(close_button()->x(), minimize_button()->x());
+ EXPECT_LT(minimize_button()->x(), maximize_button()->x());
+ EXPECT_FALSE(restore_button()->visible());
+ EXPECT_LT(maximize_button()->x() + maximize_button()->width(),
+ title_bounds().x());
+}
+
+// Tests that layouts occuring while maximized swap the maximize button for the
+// restore button
+TEST_F(CustomFrameViewTest, MaximizeRevealsRestoreButton) {
+ Widget* parent = widget();
+ CustomFrameView* view = custom_frame_view();
+ view->Init(parent);
+ parent->SetBounds(gfx::Rect(0, 0, 300, 100));
+ parent->Show();
+
+ ASSERT_FALSE(restore_button()->visible());
+ ASSERT_TRUE(maximize_button()->visible());
+
+ parent->Maximize();
+ view->Layout();
+
+ EXPECT_TRUE(restore_button()->visible());
+ EXPECT_FALSE(maximize_button()->visible());
+}
+
+// Tests that when the parent cannot maximize that the maximize button is not
+// visible
+TEST_F(CustomFrameViewTest, CannotMaximizeHidesButton) {
+ Widget* parent = widget();
+ CustomFrameView* view = custom_frame_view();
+ MaximizeStateControlDelegate* delegate = maximize_state_control_delegate();
+ delegate->set_can_maximize(false);
+
+ view->Init(parent);
+ parent->SetBounds(gfx::Rect(0, 0, 300, 100));
+ parent->Show();
+
+ EXPECT_FALSE(restore_button()->visible());
+ EXPECT_FALSE(maximize_button()->visible());
+}
+
+// Tests that when maximized that the edge button has an increased width.
+TEST_F(CustomFrameViewTest, LargerEdgeButtonsWhenMaximized) {
+ Widget* parent = widget();
+ CustomFrameView* view = custom_frame_view();
+
+ // Custom ordering to have a button on each edge.
+ std::vector<views::FrameButton> leading;
+ leading.push_back(views::FRAME_BUTTON_CLOSE);
+ leading.push_back(views::FRAME_BUTTON_MAXIMIZE);
+ std::vector<views::FrameButton> trailing;
+ trailing.push_back(views::FRAME_BUTTON_MINIMIZE);
+ SetWindowButtonOrder(leading, trailing);
+
+ view->Init(parent);
+ parent->SetBounds(gfx::Rect(0, 0, 300, 100));
+ parent->Show();
+
+ gfx::Rect close_button_initial_bounds = close_button()->bounds();
+ gfx::Rect minimize_button_initial_bounds = minimize_button()->bounds();
+
+ parent->Maximize();
+ view->Layout();
+
+ EXPECT_GT(close_button()->bounds().width(),
+ close_button_initial_bounds.width());
+ EXPECT_GT(minimize_button()->bounds().width(),
+ minimize_button_initial_bounds.width());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index bfb870ed50b..172ca0fde3d 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -22,12 +22,30 @@ namespace {
// conflict with other groups that could be in the dialog content.
const int kButtonGroup = 6666;
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+const bool kIsOkButtonOnLeftSide = true;
+#else
+const bool kIsOkButtonOnLeftSide = false;
+#endif
+
// Returns true if the given view should be shown (i.e. exists and is
// visible).
bool ShouldShow(View* view) {
return view && view->visible();
}
+// Do the layout for a button.
+void LayoutButton(LabelButton* button, gfx::Rect* row_bounds) {
+ if (!button)
+ return;
+
+ const gfx::Size size = button->GetPreferredSize();
+ row_bounds->set_width(row_bounds->width() - size.width());
+ button->SetBounds(row_bounds->right(), row_bounds->y(),
+ size.width(), row_bounds->height());
+ row_bounds->set_width(row_bounds->width() - kRelatedButtonHSpacing);
+}
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
@@ -157,7 +175,7 @@ void DialogClientView::OnDidChangeFocus(View* focused_before,
////////////////////////////////////////////////////////////////////////////////
// DialogClientView, View overrides:
-gfx::Size DialogClientView::GetPreferredSize() {
+gfx::Size DialogClientView::GetPreferredSize() const {
// Initialize the size to fit the buttons and extra view row.
gfx::Size size(
(ok_button_ ? ok_button_->GetPreferredSize().width() : 0) +
@@ -213,19 +231,12 @@ void DialogClientView::Layout() {
const int height = GetButtonsAndExtraViewRowHeight();
gfx::Rect row_bounds(bounds.x(), bounds.bottom() - height,
bounds.width(), height);
- if (cancel_button_) {
- const gfx::Size size = cancel_button_->GetPreferredSize();
- row_bounds.set_width(row_bounds.width() - size.width());
- cancel_button_->SetBounds(row_bounds.right(), row_bounds.y(),
- size.width(), height);
- row_bounds.set_width(row_bounds.width() - kRelatedButtonHSpacing);
- }
- if (ok_button_) {
- const gfx::Size size = ok_button_->GetPreferredSize();
- row_bounds.set_width(row_bounds.width() - size.width());
- ok_button_->SetBounds(row_bounds.right(), row_bounds.y(),
- size.width(), height);
- row_bounds.set_width(row_bounds.width() - kRelatedButtonHSpacing);
+ if (kIsOkButtonOnLeftSide) {
+ LayoutButton(cancel_button_, &row_bounds);
+ LayoutButton(ok_button_, &row_bounds);
+ } else {
+ LayoutButton(ok_button_, &row_bounds);
+ LayoutButton(cancel_button_, &row_bounds);
}
if (extra_view_) {
row_bounds.set_width(std::min(row_bounds.width(),
@@ -254,13 +265,6 @@ void DialogClientView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
ClientView::ViewHierarchyChanged(details);
if (details.is_add && details.child == this) {
- // The old dialog style needs an explicit background color, while the new
- // dialog style simply inherits the bubble's frame view color.
- const DialogDelegate* dialog = GetDialogDelegate();
- if (dialog && !dialog->UseNewStyleForThisDialog())
- set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
- GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
-
focus_manager_ = GetFocusManager();
if (focus_manager_)
GetFocusManager()->AddFocusChangeListener(this);
@@ -293,6 +297,17 @@ void DialogClientView::NativeViewHierarchyChanged() {
}
}
+void DialogClientView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
+ // The old dialog style needs an explicit background color, while the new
+ // dialog style simply inherits the bubble's frame view color.
+ const DialogDelegate* dialog = GetDialogDelegate();
+
+ if (dialog && !dialog->UseNewStyleForThisDialog()) {
+ set_background(views::Background::CreateSolidBackground(GetNativeTheme()->
+ GetSystemColor(ui::NativeTheme::kColorId_DialogBackground)));
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// DialogClientView, ButtonListener implementation:
@@ -359,7 +374,7 @@ void DialogClientView::ChildVisibilityChanged(View* child) {
// DialogClientView, private:
LabelButton* DialogClientView::CreateDialogButton(ui::DialogButton type) {
- const string16 title = GetDialogDelegate()->GetDialogButtonLabel(type);
+ const base::string16 title = GetDialogDelegate()->GetDialogButtonLabel(type);
LabelButton* button = NULL;
if (GetDialogDelegate()->UseNewStyleForThisDialog() &&
GetDialogDelegate()->GetDefaultDialogButton() == type &&
@@ -367,7 +382,7 @@ LabelButton* DialogClientView::CreateDialogButton(ui::DialogButton type) {
button = new BlueButton(this, title);
} else {
button = new LabelButton(this, title);
- button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
+ button->SetStyle(Button::STYLE_BUTTON);
}
button->SetFocusable(true);
diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h
index d780806094c..1e8ced11c77 100644
--- a/chromium/ui/views/window/dialog_client_view.h
+++ b/chromium/ui/views/window/dialog_client_view.h
@@ -57,12 +57,13 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
View* focused_now) OVERRIDE;
// View implementation:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
virtual void NativeViewHierarchyChanged() OVERRIDE;
+ virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
// ButtonListener implementation:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE;
diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc
index cb5374acf55..5ec29a216a9 100644
--- a/chromium/ui/views/window/dialog_delegate.cc
+++ b/chromium/ui/views/window/dialog_delegate.cc
@@ -14,8 +14,8 @@
#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/dialog_client_view.h"
-#if defined(USE_AURA)
-#include "ui/views/corewm/shadow_types.h"
+#if defined(OS_WIN)
+#include "ui/base/win/shell.h"
#endif
namespace views {
@@ -23,23 +23,42 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// DialogDelegate:
+DialogDelegate::DialogDelegate() : supports_new_style_(true) {
+}
+
DialogDelegate::~DialogDelegate() {
}
// static
-Widget* DialogDelegate::CreateDialogWidget(DialogDelegate* dialog,
- gfx::NativeWindow context,
- gfx::NativeWindow parent) {
+Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
+ gfx::NativeView context,
+ gfx::NativeView parent) {
views::Widget* widget = new views::Widget;
views::Widget::InitParams params;
- params.delegate = dialog;
+ params.delegate = delegate;
+ DialogDelegate* dialog = delegate->AsDialogDelegate();
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // The new style doesn't support unparented dialogs on Linux desktop.
+ if (dialog)
+ dialog->supports_new_style_ &= parent != NULL;
+#elif defined(OS_WIN)
+ // The new style doesn't support unparented dialogs on Windows Classic themes.
+ if (dialog && !ui::win::IsAeroGlassEnabled())
+ dialog->supports_new_style_ &= parent != NULL;
+#endif
+
if (!dialog || dialog->UseNewStyleForThisDialog()) {
params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
params.remove_standard_frame = true;
+ // The bubble frame includes its own shadow; remove any native shadowing.
+ params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
}
params.context = context;
params.parent = parent;
- params.top_level = true;
+ // Web-modal (ui::MODAL_TYPE_CHILD) dialogs with parents are marked as child
+ // widgets to prevent top-level window behavior (independent movement, etc).
+ params.child = parent && (delegate->GetModalType() == ui::MODAL_TYPE_CHILD);
widget->Init(params);
return widget;
}
@@ -154,43 +173,22 @@ NonClientFrameView* DialogDelegate::CreateNonClientFrameView(Widget* widget) {
// static
NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) {
- return CreateDialogFrameView(widget, false);
-}
-
-// static
-NonClientFrameView* DialogDelegate::CreateDialogFrameView(
- Widget* widget,
- bool force_opaque_border) {
BubbleFrameView* frame = new BubbleFrameView(gfx::Insets());
- const SkColor color = widget->GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_DialogBackground);
- if (force_opaque_border) {
- frame->SetBubbleBorder(new BubbleBorder(
- BubbleBorder::NONE,
- BubbleBorder::NO_SHADOW_OPAQUE_BORDER,
- color));
- } else {
- frame->SetBubbleBorder(new BubbleBorder(BubbleBorder::FLOAT,
- BubbleBorder::SMALL_SHADOW,
- color));
- }
+ scoped_ptr<BubbleBorder> border(new BubbleBorder(
+ BubbleBorder::FLOAT, BubbleBorder::SMALL_SHADOW, SK_ColorRED));
+ border->set_use_theme_background_color(true);
+ frame->SetBubbleBorder(border.Pass());
DialogDelegate* delegate = widget->widget_delegate()->AsDialogDelegate();
if (delegate) {
View* titlebar_view = delegate->CreateTitlebarExtraView();
if (titlebar_view)
frame->SetTitlebarExtraView(titlebar_view);
}
- if (force_opaque_border)
- widget->set_frame_type(views::Widget::FRAME_TYPE_FORCE_CUSTOM);
-#if defined(USE_AURA)
- // TODO(msw): Add a matching shadow type and remove the bubble frame border?
- corewm::SetShadowType(widget->GetNativeWindow(), corewm::SHADOW_TYPE_NONE);
-#endif
return frame;
}
bool DialogDelegate::UseNewStyleForThisDialog() const {
- return true;
+ return supports_new_style_;
}
const DialogClientView* DialogDelegate::GetDialogClientView() const {
@@ -201,8 +199,8 @@ DialogClientView* DialogDelegate::GetDialogClientView() {
return GetWidget()->client_view()->AsDialogClientView();
}
-ui::AccessibilityTypes::Role DialogDelegate::GetAccessibleWindowRole() const {
- return ui::AccessibilityTypes::ROLE_DIALOG;
+ui::AXRole DialogDelegate::GetAccessibleWindowRole() const {
+ return ui::AX_ROLE_DIALOG;
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h
index 8e8948de427..91fff1e51fb 100644
--- a/chromium/ui/views/window/dialog_delegate.h
+++ b/chromium/ui/views/window/dialog_delegate.h
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/strings/string16.h"
-#include "ui/base/accessibility/accessibility_types.h"
+#include "ui/accessibility/ax_enums.h"
#include "ui/base/models/dialog_model.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/widget/widget_delegate.h"
@@ -29,12 +29,13 @@ class DialogClientView;
class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
public WidgetDelegate {
public:
+ DialogDelegate();
virtual ~DialogDelegate();
- // Create a |dialog| window Widget with the specified |context| or |parent|.
- static Widget* CreateDialogWidget(DialogDelegate* dialog,
- gfx::NativeWindow context,
- gfx::NativeWindow parent);
+ // Create a dialog widget with the specified |context| or |parent|.
+ static Widget* CreateDialogWidget(WidgetDelegate* delegate,
+ gfx::NativeView context,
+ gfx::NativeView parent);
// 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.
@@ -91,14 +92,6 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// Create a frame view using the new dialog style.
static NonClientFrameView* CreateDialogFrameView(Widget* widget);
- // The semi-transparent border and shadow of the new style frame view does not
- // work on child windows under Views/Win32. This is a kludge to get a
- // reasonable-looking opaque border for the dialog. Note that this does not
- // support arrows.
- //
- // TODO(wittman): Remove once WinAura is in place.
- static NonClientFrameView* CreateDialogFrameView(Widget* widget,
- bool force_opaque_border);
// Returns whether this particular dialog should use the new dialog style.
virtual bool UseNewStyleForThisDialog() const;
@@ -113,7 +106,11 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
protected:
// Overridden from WidgetDelegate:
- virtual ui::AccessibilityTypes::Role GetAccessibleWindowRole() const OVERRIDE;
+ virtual ui::AXRole GetAccessibleWindowRole() const OVERRIDE;
+
+ private:
+ // A flag indicating whether this dialog supports the new style.
+ bool supports_new_style_;
};
// A DialogDelegate implementation that is-a View. Used to override GetWidget()
diff --git a/chromium/ui/views/window/dialog_delegate_unittest.cc b/chromium/ui/views/window/dialog_delegate_unittest.cc
index f56073affac..fedb6983eb2 100644
--- a/chromium/ui/views/window/dialog_delegate_unittest.cc
+++ b/chromium/ui/views/window/dialog_delegate_unittest.cc
@@ -37,8 +37,11 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
}
// DialogDelegateView overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE { return gfx::Size(200, 200); }
- virtual string16 GetWindowTitle() const OVERRIDE { return title_; }
+ virtual gfx::Size GetPreferredSize() const OVERRIDE {
+ return gfx::Size(200, 200);
+ }
+ virtual base::string16 GetWindowTitle() const OVERRIDE { return title_; }
+ virtual bool UseNewStyleForThisDialog() const OVERRIDE { return true; }
// ButtonListener override:
virtual void ButtonPressed(Button* sender, const ui::Event& event) OVERRIDE {
@@ -73,7 +76,7 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
GetWidget()->Close();
}
- void set_title(const string16& title) { title_ = title; }
+ void set_title(const base::string16& title) { title_ = title; }
private:
bool canceled_;
@@ -81,7 +84,7 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
// Prevent the dialog from closing, for repeated ok and cancel button clicks.
bool closeable_;
Button* last_pressed_button_;
- string16 title_;
+ base::string16 title_;
DISALLOW_COPY_AND_ASSIGN(TestDialog);
};
@@ -121,21 +124,21 @@ TEST_F(DialogTest, DefaultButtons) {
dialog()->PressEnterAndCheckStates(ok_button);
// Focus another button in the dialog, it should become the default.
- LabelButton* button_1 = new LabelButton(dialog(), string16());
+ LabelButton* button_1 = new LabelButton(dialog(), base::string16());
client_view->AddChildView(button_1);
client_view->OnWillChangeFocus(ok_button, button_1);
EXPECT_TRUE(button_1->is_default());
dialog()->PressEnterAndCheckStates(button_1);
// Focus a Checkbox (not a push button), OK should become the default again.
- Checkbox* checkbox = new Checkbox(string16());
+ Checkbox* checkbox = new Checkbox(base::string16());
client_view->AddChildView(checkbox);
client_view->OnWillChangeFocus(button_1, checkbox);
EXPECT_FALSE(button_1->is_default());
dialog()->PressEnterAndCheckStates(ok_button);
// Focus yet another button in the dialog, it should become the default.
- LabelButton* button_2 = new LabelButton(dialog(), string16());
+ LabelButton* button_2 = new LabelButton(dialog(), base::string16());
client_view->AddChildView(button_2);
client_view->OnWillChangeFocus(checkbox, button_2);
EXPECT_FALSE(button_1->is_default());
@@ -205,21 +208,22 @@ TEST_F(DialogTest, HitTest) {
}
}
-TEST_F(DialogTest, InitialBoundsAccommodateTitle) {
- TestDialog* titled_dialog(new TestDialog());
- titled_dialog->set_title(ASCIIToUTF16("Title"));
- DialogDelegate::CreateDialogWidget(titled_dialog, GetContext(), NULL);
+TEST_F(DialogTest, BoundsAccommodateTitle) {
+ TestDialog* dialog2(new TestDialog());
+ dialog2->set_title(base::ASCIIToUTF16("Title"));
+ DialogDelegate::CreateDialogWidget(dialog2, GetContext(), NULL);
// Titled dialogs have taller initial frame bounds than untitled dialogs.
- EXPECT_GT(titled_dialog->GetWidget()->GetWindowBoundsInScreen().height(),
- dialog()->GetWidget()->GetWindowBoundsInScreen().height());
+ View* frame1 = dialog()->GetWidget()->non_client_view()->frame_view();
+ View* frame2 = dialog2->GetWidget()->non_client_view()->frame_view();
+ EXPECT_LT(frame1->GetPreferredSize().height(),
+ frame2->GetPreferredSize().height());
- // Giving the default test dialog a title will make the bounds the same.
- dialog()->set_title(ASCIIToUTF16("Title"));
+ // Giving the default test dialog a title will yield the same bounds.
+ dialog()->set_title(base::ASCIIToUTF16("Title"));
dialog()->GetWidget()->UpdateWindowTitle();
- View* frame = dialog()->GetWidget()->non_client_view()->frame_view();
- EXPECT_EQ(titled_dialog->GetWidget()->GetWindowBoundsInScreen().height(),
- frame->GetPreferredSize().height());
+ EXPECT_EQ(frame1->GetPreferredSize().height(),
+ frame2->GetPreferredSize().height());
}
} // namespace views
diff --git a/chromium/ui/views/window/frame_background.cc b/chromium/ui/views/window/frame_background.cc
index 111ac257814..f9e8293c0db 100644
--- a/chromium/ui/views/window/frame_background.cc
+++ b/chromium/ui/views/window/frame_background.cc
@@ -26,10 +26,7 @@ FrameBackground::FrameBackground()
top_right_corner_(NULL),
bottom_left_corner_(NULL),
bottom_right_corner_(NULL),
- maximized_top_left_(NULL),
- maximized_top_right_(NULL),
- maximized_top_offset_(0),
- theme_background_y_(0) {
+ maximized_top_inset_(0) {
}
FrameBackground::~FrameBackground() {
@@ -124,41 +121,25 @@ void FrameBackground::PaintRestored(gfx::Canvas* canvas, View* view) const {
}
void FrameBackground::PaintMaximized(gfx::Canvas* canvas, View* view) const {
- // We will be painting from top_offset to top_offset + theme_frame_height. If
- // this is less than top_area_height_, we need to paint the frame color
- // to fill in the area beneath the image.
- // TODO(jamescook): I'm not sure this is correct, as it doesn't seem to fully
- // account for the top_offset, but this is how it worked before.
- int theme_frame_bottom = maximized_top_offset_ + theme_image_->height();
+ // We will be painting from -|maximized_top_inset_| to
+ // -|maximized_top_inset_| + |theme_image_|->height(). If this is less than
+ // |top_area_height_|, we need to paint the frame color to fill in the area
+ // beneath the image.
+ int theme_frame_bottom = -maximized_top_inset_ + theme_image_->height();
if (top_area_height_ > theme_frame_bottom) {
canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_),
frame_color_);
}
- int left_offset = 0;
- int right_offset = 0;
-
- // Draw top-left and top-right corners to give maximized ChromeOS windows
- // a rounded appearance.
- if (maximized_top_left_ || maximized_top_right_) {
- // If we have either a left or right we should have both.
- DCHECK(maximized_top_left_ && maximized_top_right_);
- left_offset = maximized_top_left_->width();
- right_offset = maximized_top_right_->width();
- canvas->DrawImageInt(*maximized_top_left_, 0, 0);
- canvas->DrawImageInt(*maximized_top_right_,
- view->width() - right_offset, 0);
- }
-
// Draw the theme frame.
canvas->TileImageInt(*theme_image_,
- left_offset,
- maximized_top_offset_,
- view->width() - (left_offset + right_offset),
+ 0,
+ -maximized_top_inset_,
+ view->width(),
theme_image_->height());
// Draw the theme frame overlay, if available.
if (theme_overlay_image_)
- canvas->DrawImageInt(*theme_overlay_image_, 0, theme_background_y_);
+ canvas->DrawImageInt(*theme_overlay_image_, 0, -maximized_top_inset_);
}
void FrameBackground::PaintFrameColor(gfx::Canvas* canvas, View* view) const {
diff --git a/chromium/ui/views/window/frame_background.h b/chromium/ui/views/window/frame_background.h
index b8684f61399..bdabf51f72e 100644
--- a/chromium/ui/views/window/frame_background.h
+++ b/chromium/ui/views/window/frame_background.h
@@ -44,11 +44,8 @@ class VIEWS_EXPORT FrameBackground {
// which must extend behind the tab strip.
void set_top_area_height(int height) { top_area_height_ = height; }
- // Only used if we have an overlay image for the theme.
- void set_theme_background_y(int y) { theme_background_y_ = y; }
-
- // Vertical offset for theme image when drawing maximized.
- void set_maximized_top_offset(int offset) { maximized_top_offset_ = offset; }
+ // Vertical inset for theme image when drawing maximized.
+ void set_maximized_top_inset(int inset) { maximized_top_inset_ = inset; }
// Sets images used when drawing the sides of the frame.
// Caller owns the memory.
@@ -94,12 +91,8 @@ class VIEWS_EXPORT FrameBackground {
const gfx::ImageSkia* bottom_left_corner_;
const gfx::ImageSkia* bottom_right_corner_;
- // Attributes for maximized window painting.
- // TODO(jamescook): Remove all these.
- gfx::ImageSkia* maximized_top_left_;
- gfx::ImageSkia* maximized_top_right_;
- int maximized_top_offset_;
- int theme_background_y_;
+ // Vertical inset for theme image when drawing maximized.
+ int maximized_top_inset_;
DISALLOW_COPY_AND_ASSIGN(FrameBackground);
};
diff --git a/chromium/ui/views/window/native_frame_view.cc b/chromium/ui/views/window/native_frame_view.cc
index 1cbafabe57b..1ffbcdbb02b 100644
--- a/chromium/ui/views/window/native_frame_view.cc
+++ b/chromium/ui/views/window/native_frame_view.cc
@@ -16,6 +16,9 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// NativeFrameView, public:
+// static
+const char NativeFrameView::kViewClassName[] = "NativeFrameView";
+
NativeFrameView::NativeFrameView(Widget* frame)
: NonClientFrameView(),
frame_(frame) {
@@ -37,8 +40,12 @@ gfx::Rect NativeFrameView::GetWindowBoundsForClientBounds(
return views::GetWindowBoundsForClientBounds(
static_cast<View*>(const_cast<NativeFrameView*>(this)), client_bounds);
#else
- // TODO(sad):
- return client_bounds;
+ // Enforce minimum size (1, 1) in case that |client_bounds| is passed with
+ // empty size.
+ gfx::Rect window_bounds = client_bounds;
+ if (window_bounds.IsEmpty())
+ window_bounds.set_size(gfx::Size(1,1));
+ return window_bounds;
#endif
}
@@ -63,20 +70,30 @@ void NativeFrameView::UpdateWindowTitle() {
// Nothing to do.
}
-// Returns the client size. On Windows, this is the expected behavior for
-// native frames (see |NativeWidgetWin::WidgetSizeIsClientSize()|), while other
-// platforms currently always return client bounds from
-// |GetWindowBoundsForClientBounds()|.
-gfx::Size NativeFrameView::GetPreferredSize() {
- return frame_->client_view()->GetPreferredSize();
+gfx::Size NativeFrameView::GetPreferredSize() const {
+ gfx::Size client_preferred_size = frame_->client_view()->GetPreferredSize();
+#if defined(OS_WIN)
+ // Returns the client size. On Windows, this is the expected behavior for
+ // native frames (see |NativeWidgetWin::WidgetSizeIsClientSize()|), while
+ // other platforms currently always return client bounds from
+ // |GetWindowBoundsForClientBounds()|.
+ return client_preferred_size;
+#else
+ return frame_->non_client_view()->GetWindowBoundsForClientBounds(
+ gfx::Rect(client_preferred_size)).size();
+#endif
}
-gfx::Size NativeFrameView::GetMinimumSize() {
+gfx::Size NativeFrameView::GetMinimumSize() const {
return frame_->client_view()->GetMinimumSize();
}
-gfx::Size NativeFrameView::GetMaximumSize() {
+gfx::Size NativeFrameView::GetMaximumSize() const {
return frame_->client_view()->GetMaximumSize();
}
+const char* NativeFrameView::GetClassName() const {
+ return kViewClassName;
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/native_frame_view.h b/chromium/ui/views/window/native_frame_view.h
index 378e354bf79..154453d3eba 100644
--- a/chromium/ui/views/window/native_frame_view.h
+++ b/chromium/ui/views/window/native_frame_view.h
@@ -13,6 +13,8 @@ class Widget;
class VIEWS_EXPORT NativeFrameView : public NonClientFrameView {
public:
+ static const char kViewClassName[];
+
explicit NativeFrameView(Widget* frame);
virtual ~NativeFrameView();
@@ -28,9 +30,10 @@ class VIEWS_EXPORT NativeFrameView : public NonClientFrameView {
virtual void UpdateWindowTitle() OVERRIDE;
// View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
+ virtual const char* GetClassName() const OVERRIDE;
private:
// Our containing frame.
diff --git a/chromium/ui/views/window/non_client_view.cc b/chromium/ui/views/window/non_client_view.cc
index f7cd70e5cd3..e4068dba177 100644
--- a/chromium/ui/views/window/non_client_view.cc
+++ b/chromium/ui/views/window/non_client_view.cc
@@ -4,7 +4,7 @@
#include "ui/views/window/non_client_view.h"
-#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/accessibility/ax_view_state.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/views/rect_based_targeting_utils.h"
@@ -127,14 +127,14 @@ void NonClientView::LayoutFrameView() {
frame_view_->Layout();
}
-void NonClientView::SetAccessibleName(const string16& name) {
+void NonClientView::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
////////////////////////////////////////////////////////////////////////////////
// NonClientView, View overrides:
-gfx::Size NonClientView::GetPreferredSize() {
+gfx::Size NonClientView::GetPreferredSize() const {
// TODO(pkasting): This should probably be made to look similar to
// GetMinimumSize() below. This will require implementing GetPreferredSize()
// better in the various frame views.
@@ -142,11 +142,11 @@ gfx::Size NonClientView::GetPreferredSize() {
return GetWindowBoundsForClientBounds(client_bounds).size();
}
-gfx::Size NonClientView::GetMinimumSize() {
+gfx::Size NonClientView::GetMinimumSize() const {
return frame_view_->GetMinimumSize();
}
-gfx::Size NonClientView::GetMaximumSize() {
+gfx::Size NonClientView::GetMaximumSize() const {
return frame_view_->GetMaximumSize();
}
@@ -177,8 +177,8 @@ void NonClientView::ViewHierarchyChanged(
}
}
-void NonClientView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_CLIENT;
+void NonClientView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_CLIENT;
state->name = accessible_name_;
}
@@ -186,8 +186,8 @@ const char* NonClientView::GetClassName() const {
return kViewClassName;
}
-views::View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) {
- if (!views::UsePointBasedTargeting(rect))
+View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) {
+ if (!UsePointBasedTargeting(rect))
return View::GetEventHandlerForRect(rect);
// Because of the z-ordering of our child views (the client view is positioned
@@ -212,7 +212,7 @@ views::View* NonClientView::GetEventHandlerForRect(const gfx::Rect& rect) {
return View::GetEventHandlerForRect(rect);
}
-views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
+View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
// The same logic as for |GetEventHandlerForRect()| applies here.
if (frame_view_->parent() == this) {
// During the reset of the frame_view_ it's possible to be in this code
@@ -220,7 +220,7 @@ views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
// removed from the NonClientView.
gfx::Point point_in_child_coords(point);
View::ConvertPointToTarget(this, frame_view_.get(), &point_in_child_coords);
- views::View* handler =
+ View* handler =
frame_view_->GetTooltipHandlerForPoint(point_in_child_coords);
if (handler)
return handler;
@@ -232,12 +232,23 @@ views::View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
////////////////////////////////////////////////////////////////////////////////
// NonClientFrameView, public:
+NonClientFrameView::~NonClientFrameView() {
+}
+
void NonClientFrameView::SetInactiveRenderingDisabled(bool disable) {
- if (paint_as_active_ == disable)
+ if (inactive_rendering_disabled_ == disable)
return;
- paint_as_active_ = disable;
- ShouldPaintAsActiveChanged();
+ bool should_paint_as_active_old = ShouldPaintAsActive();
+ inactive_rendering_disabled_ = disable;
+
+ // The widget schedules a paint when the activation changes.
+ if (should_paint_as_active_old != ShouldPaintAsActive())
+ SchedulePaint();
+}
+
+bool NonClientFrameView::ShouldPaintAsActive() const {
+ return inactive_rendering_disabled_ || GetWidget()->IsActive();
}
int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point,
@@ -301,16 +312,8 @@ bool NonClientFrameView::HitTestRect(const gfx::Rect& rect) const {
////////////////////////////////////////////////////////////////////////////////
// NonClientFrameView, protected:
-bool NonClientFrameView::ShouldPaintAsActive() const {
- return GetWidget()->IsActive() || paint_as_active_;
-}
-
-void NonClientFrameView::ShouldPaintAsActiveChanged() {
- SchedulePaint();
-}
-
-void NonClientFrameView::GetAccessibleState(ui::AccessibleViewState* state) {
- state->role = ui::AccessibilityTypes::ROLE_CLIENT;
+void NonClientFrameView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_CLIENT;
}
const char* NonClientFrameView::GetClassName() const {
@@ -322,4 +325,7 @@ void NonClientFrameView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
// FrameView when it is itself laid out, see comment in NonClientView::Layout.
}
+NonClientFrameView::NonClientFrameView() : inactive_rendering_disabled_(false) {
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/non_client_view.h b/chromium/ui/views/window/non_client_view.h
index 2c3b1d9fe49..77181426418 100644
--- a/chromium/ui/views/window/non_client_view.h
+++ b/chromium/ui/views/window/non_client_view.h
@@ -37,12 +37,18 @@ class VIEWS_EXPORT NonClientFrameView : public View {
kClientEdgeThickness = 1,
};
+ virtual ~NonClientFrameView();
+
// Sets whether the window should be rendered as active regardless of the
// actual active state. Used when bubbles become active to make their parent
// appear active. A value of true makes the window render as active always,
// false gives normal behavior.
void SetInactiveRenderingDisabled(bool disable);
+ // Used to determine if the frame should be painted as active. Keyed off the
+ // window's actual active state and |inactive_rendering_disabled_|.
+ bool ShouldPaintAsActive() const;
+
// Helper for non-client view implementations to determine which area of the
// window border the specified |point| falls within. The other parameters are
// the size of the sizing edges, and whether or not the window can be
@@ -74,28 +80,18 @@ class VIEWS_EXPORT NonClientFrameView : public View {
// Overridden from View:
virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
protected:
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
- NonClientFrameView() : paint_as_active_(false) {}
-
- // Used to determine if the frame should be painted as active. Keyed off the
- // window's actual active state and the override, see
- // SetInactiveRenderingDisabled() above.
- bool ShouldPaintAsActive() const;
-
- // Invoked from SetInactiveRenderingDisabled(). This implementation invokes
- // SchedulesPaint as necessary.
- virtual void ShouldPaintAsActiveChanged();
+ NonClientFrameView();
private:
- // True when the non-client view should always be rendered as if the window
- // were active, regardless of whether or not the top level window actually
- // is active.
- bool paint_as_active_;
+ // Prevents the non-client frame view from being rendered as inactive when
+ // true.
+ bool inactive_rendering_disabled_;
};
////////////////////////////////////////////////////////////////////////////////
@@ -166,8 +162,6 @@ class VIEWS_EXPORT NonClientView : public View {
// Prevents the window from being rendered as deactivated when |disable| is
// true, until called with |disable| false. Used when a sub-window is to be
// shown that shouldn't visually de-activate the window.
- // Subclasses can override this to perform additional actions when this value
- // changes.
void SetInactiveRenderingDisabled(bool disable);
// Returns the bounds of the window required to display the content area at
@@ -208,14 +202,14 @@ class VIEWS_EXPORT NonClientView : public View {
void LayoutFrameView();
// Set the accessible name of this view.
- void SetAccessibleName(const string16& name);
+ void SetAccessibleName(const base::string16& name);
// NonClientView, View overrides:
- virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual gfx::Size GetMinimumSize() OVERRIDE;
- virtual gfx::Size GetMaximumSize() OVERRIDE;
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual gfx::Size GetMinimumSize() const OVERRIDE;
+ virtual gfx::Size GetMaximumSize() const OVERRIDE;
virtual void Layout() OVERRIDE;
- virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
+ virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual views::View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE;
@@ -243,7 +237,7 @@ class VIEWS_EXPORT NonClientView : public View {
View* overlay_view_;
// The accessible name of this view.
- string16 accessible_name_;
+ base::string16 accessible_name_;
DISALLOW_COPY_AND_ASSIGN(NonClientView);
};
diff --git a/chromium/ui/views/window/window_button_order_provider.cc b/chromium/ui/views/window/window_button_order_provider.cc
new file mode 100644
index 00000000000..b1ac70e4727
--- /dev/null
+++ b/chromium/ui/views/window/window_button_order_provider.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/window/window_button_order_provider.h"
+
+namespace views {
+
+// static
+WindowButtonOrderProvider* WindowButtonOrderProvider::instance_ = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowButtonOrderProvider, public:
+
+// static
+WindowButtonOrderProvider* WindowButtonOrderProvider::GetInstance() {
+ if (!instance_)
+ instance_ = new WindowButtonOrderProvider;
+ return instance_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowButtonOrderProvider, protected:
+
+WindowButtonOrderProvider::WindowButtonOrderProvider() {
+ trailing_buttons_.push_back(views::FRAME_BUTTON_MINIMIZE);
+ trailing_buttons_.push_back(views::FRAME_BUTTON_MAXIMIZE);
+ trailing_buttons_.push_back(views::FRAME_BUTTON_CLOSE);
+}
+
+WindowButtonOrderProvider::~WindowButtonOrderProvider() {
+}
+
+void WindowButtonOrderProvider::SetWindowButtonOrder(
+ const std::vector<views::FrameButton>& leading_buttons,
+ const std::vector<views::FrameButton>& trailing_buttons) {
+ leading_buttons_ = leading_buttons;
+ trailing_buttons_ = trailing_buttons;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/window/window_button_order_provider.h b/chromium/ui/views/window/window_button_order_provider.h
new file mode 100644
index 00000000000..f50a49f0fb7
--- /dev/null
+++ b/chromium/ui/views/window/window_button_order_provider.h
@@ -0,0 +1,56 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_
+#define UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/views/views_export.h"
+#include "ui/views/window/frame_buttons.h"
+
+namespace views {
+
+// Stores the ordering of window control buttons. Provides a default ordering
+// of |FRAME_BUTTON_MINIMZE|, |FRAME_BUTTON_MAXIMIZE|, |FRAME_BUTTON_CLOSE|,
+// where all controls are on the trailing end of a window.
+//
+// On Linux users can provide configuration files to control the ordering. This
+// configuration is checked and overrides the defaults.
+class VIEWS_EXPORT WindowButtonOrderProvider {
+ public:
+ static WindowButtonOrderProvider* GetInstance();
+
+ const std::vector<views::FrameButton>& leading_buttons() const {
+ return leading_buttons_;
+ }
+
+ const std::vector<views::FrameButton>& trailing_buttons() const {
+ return trailing_buttons_;
+ }
+
+ void SetWindowButtonOrder(
+ const std::vector<views::FrameButton>& leading_buttons,
+ const std::vector<views::FrameButton>& trailing_buttons);
+
+ protected:
+ WindowButtonOrderProvider();
+ virtual ~WindowButtonOrderProvider();
+
+ private:
+ static WindowButtonOrderProvider* instance_;
+
+ // Layout arrangement of the window caption buttons. On linux these will be
+ // set via a WindowButtonOrderObserver. On other platforms a default
+ // arrangement of a trailing minimize, maximize, close, will be set.
+ std::vector<views::FrameButton> leading_buttons_;
+ std::vector<views::FrameButton> trailing_buttons_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowButtonOrderProvider);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_WINDOW_WINDOW_BUTTON_ORDER_PROVIDER_H_