summaryrefslogtreecommitdiff
path: root/chromium/ui
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/ui
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/ui')
-rw-r--r--chromium/ui/OWNERS3
-rw-r--r--chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h6
-rw-r--r--chromium/ui/accelerated_widget_mac/accelerated_widget_mac.mm4
-rw-r--r--chromium/ui/accelerated_widget_mac/display_link_mac.cc22
-rw-r--r--chromium/ui/accessibility/BUILD.gn14
-rw-r--r--chromium/ui/accessibility/accessibility.gyp7
-rw-r--r--chromium/ui/accessibility/ax_enums.idl15
-rw-r--r--chromium/ui/accessibility/ax_node_data.cc49
-rw-r--r--chromium/ui/accessibility/ax_node_data.h23
-rw-r--r--chromium/ui/accessibility/ax_text_utils.cc22
-rw-r--r--chromium/ui/accessibility/ax_text_utils_unittest.cc48
-rw-r--r--chromium/ui/accessibility/ax_tree.cc2
-rw-r--r--chromium/ui/accessibility/ax_tree.h5
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.cc238
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.h54
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner_unittest.cc244
-rw-r--r--chromium/ui/accessibility/ax_tree_data.cc31
-rw-r--r--chromium/ui/accessibility/ax_tree_data.h15
-rw-r--r--chromium/ui/accessibility/ax_tree_unittest.cc7
-rw-r--r--chromium/ui/accessibility/ax_tree_update.h1
-rw-r--r--chromium/ui/accessibility/extensions/alt/hide-images.css12
-rw-r--r--chromium/ui/accessibility/extensions/colorenhancer/res/setup.css2
-rw-r--r--chromium/ui/accessibility/platform/atk_util_auralinux.cc137
-rw-r--r--chromium/ui/accessibility/platform/atk_util_auralinux.h8
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.cc42
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.h14
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc5
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.cc6
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.mm2
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.cc94
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.h28
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc17
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.cc3
-rw-r--r--chromium/ui/android/BUILD.gn90
-rw-r--r--chromium/ui/android/edge_effect.cc3
-rw-r--r--chromium/ui/android/edge_effect_l.cc3
-rw-r--r--chromium/ui/android/overscroll_glow.cc2
-rw-r--r--chromium/ui/android/resources/resource_manager_impl_unittest.cc2
-rw-r--r--chromium/ui/android/ui_android.gyp24
-rw-r--r--chromium/ui/android/window_android_compositor.cc28
-rw-r--r--chromium/ui/android/window_android_compositor.h5
-rw-r--r--chromium/ui/app_list/app_list.gyp16
-rw-r--r--chromium/ui/app_list/shower/app_list_shower.gyp107
-rw-r--r--chromium/ui/app_list/shower/app_list_shower_unittests.isolate78
-rw-r--r--chromium/ui/arc/BUILD.gn18
-rw-r--r--chromium/ui/arc/DEPS1
-rw-r--r--chromium/ui/arc/arc.gyp27
-rw-r--r--chromium/ui/arc/notification/arc_notification_item.cc37
-rw-r--r--chromium/ui/arc/notification/arc_notification_item.h3
-rw-r--r--chromium/ui/arc/notification/arc_notification_manager.cc155
-rw-r--r--chromium/ui/arc/notification/arc_notification_manager.h24
-rw-r--r--chromium/ui/arc/notification/arc_notification_manager_unittest.cc187
-rw-r--r--chromium/ui/aura/BUILD.gn46
-rw-r--r--chromium/ui/aura/aura.gyp53
-rw-r--r--chromium/ui/aura/bench/DEPS8
-rw-r--r--chromium/ui/aura/bench/bench_main.cc389
-rw-r--r--chromium/ui/aura/demo/demo_main.cc4
-rw-r--r--chromium/ui/aura/env.cc19
-rw-r--r--chromium/ui/aura/gestures/gesture_recognizer_unittest.cc55
-rw-r--r--chromium/ui/aura/mus/mus_util.cc13
-rw-r--r--chromium/ui/aura/remote_window_tree_host_win.cc522
-rw-r--r--chromium/ui/aura/remote_window_tree_host_win.h197
-rw-r--r--chromium/ui/aura/window.cc3
-rw-r--r--chromium/ui/aura/window_event_dispatcher.cc23
-rw-r--r--chromium/ui/aura/window_event_dispatcher_unittest.cc2
-rw-r--r--chromium/ui/aura/window_targeter.cc9
-rw-r--r--chromium/ui/aura/window_tree_host.cc6
-rw-r--r--chromium/ui/aura/window_tree_host_mac.h4
-rw-r--r--chromium/ui/aura/window_tree_host_platform.cc4
-rw-r--r--chromium/ui/aura/window_tree_host_x11.cc117
-rw-r--r--chromium/ui/aura/window_tree_host_x11.h7
-rw-r--r--chromium/ui/aura/window_unittest.cc30
-rw-r--r--chromium/ui/base/BUILD.gn105
-rw-r--r--chromium/ui/base/OWNERS2
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.cc5
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.mm34
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac.h70
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac.mm179
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm99
-rw-r--r--chromium/ui/base/clipboard/custom_data_helper.cc20
-rw-r--r--chromium/ui/base/clipboard/custom_data_helper_unittest.cc8
-rw-r--r--chromium/ui/base/cocoa/appkit_utils.mm62
-rw-r--r--chromium/ui/base/cocoa/cocoa_base_utils.h8
-rw-r--r--chromium/ui/base/cocoa/cocoa_base_utils.mm11
-rw-r--r--chromium/ui/base/cocoa/command_dispatcher.mm5
-rw-r--r--chromium/ui/base/cocoa/controls/blue_label_button.mm5
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm2
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_text_view.mm2
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm11
-rw-r--r--chromium/ui/base/cocoa/menu_controller_unittest.mm5
-rw-r--r--chromium/ui/base/cocoa/nib_loading.mm15
-rw-r--r--chromium/ui/base/cocoa/three_part_image.h12
-rw-r--r--chromium/ui/base/cocoa/three_part_image.mm16
-rw-r--r--chromium/ui/base/cocoa/three_part_image_unittest.mm28
-rw-r--r--chromium/ui/base/cursor/cursors_aura.cc13
-rw-r--r--chromium/ui/base/default_style.h40
-rw-r--r--chromium/ui/base/default_theme_provider.h2
-rw-r--r--chromium/ui/base/default_theme_provider_mac.mm8
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc1
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc4
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h8
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm49
-rw-r--r--chromium/ui/base/ime/BUILD.gn21
-rw-r--r--chromium/ui/base/ime/candidate_window.cc2
-rw-r--r--chromium/ui/base/ime/candidate_window.h1
-rw-r--r--chromium/ui/base/ime/composition_text.cc2
-rw-r--r--chromium/ui/base/ime/composition_text.h1
-rw-r--r--chromium/ui/base/ime/dummy_text_input_client.cc10
-rw-r--r--chromium/ui/base/ime/dummy_text_input_client.h7
-rw-r--r--chromium/ui/base/ime/ime_engine_handler_interface.cc44
-rw-r--r--chromium/ui/base/ime/ime_engine_handler_interface.h137
-rw-r--r--chromium/ui/base/ime/ime_engine_observer.h81
-rw-r--r--chromium/ui/base/ime/ime_input_context_handler_interface.h4
-rw-r--r--chromium/ui/base/ime/input_method_auralinux.cc115
-rw-r--r--chromium/ui/base/ime/input_method_auralinux.h21
-rw-r--r--chromium/ui/base/ime/input_method_base.cc86
-rw-r--r--chromium/ui/base/ime/input_method_base.h25
-rw-r--r--chromium/ui/base/ime/input_method_chromeos.cc55
-rw-r--r--chromium/ui/base/ime/input_method_chromeos.h10
-rw-r--r--chromium/ui/base/ime/input_method_chromeos_unittest.cc46
-rw-r--r--chromium/ui/base/ime/input_method_factory.cc3
-rw-r--r--chromium/ui/base/ime/input_method_win.cc146
-rw-r--r--chromium/ui/base/ime/input_method_win.h11
-rw-r--r--chromium/ui/base/ime/remote_input_method_delegate_win.h42
-rw-r--r--chromium/ui/base/ime/remote_input_method_win.cc385
-rw-r--r--chromium/ui/base/ime/remote_input_method_win.h100
-rw-r--r--chromium/ui/base/ime/remote_input_method_win_unittest.cc831
-rw-r--r--chromium/ui/base/ime/ui_base_ime.gyp19
-rw-r--r--chromium/ui/base/ime/win/imm32_manager.cc5
-rw-r--r--chromium/ui/base/ios/cru_context_menu_controller.h6
-rw-r--r--chromium/ui/base/ios/cru_context_menu_controller.mm185
-rw-r--r--chromium/ui/base/l10n/l10n_util.cc20
-rw-r--r--chromium/ui/base/l10n/l10n_util_collator.h14
-rw-r--r--chromium/ui/base/layout.cc21
-rw-r--r--chromium/ui/base/layout.h24
-rw-r--r--chromium/ui/base/layout_mac.mm8
-rw-r--r--chromium/ui/base/layout_unittest.cc12
-rw-r--r--chromium/ui/base/material_design/material_design_controller.cc (renamed from chromium/ui/base/resource/material_design/material_design_controller.cc)58
-rw-r--r--chromium/ui/base/material_design/material_design_controller.h (renamed from chromium/ui/base/resource/material_design/material_design_controller.h)9
-rw-r--r--chromium/ui/base/material_design/material_design_controller_unittest.cc (renamed from chromium/ui/base/resource/material_design/material_design_controller_unittest.cc)14
-rw-r--r--chromium/ui/base/models/dialog_model.h3
-rw-r--r--chromium/ui/base/models/table_model.cc2
-rw-r--r--chromium/ui/base/models/table_model.h1
-rw-r--r--chromium/ui/base/models/tree_node_model.h15
-rw-r--r--chromium/ui/base/nine_image_painter_factory.cc1
-rw-r--r--chromium/ui/base/resource/data_pack.h4
-rw-r--r--chromium/ui/base/resource/data_pack_export.h37
-rw-r--r--chromium/ui/base/resource/resource_bundle.cc194
-rw-r--r--chromium/ui/base/resource/resource_bundle.h79
-rw-r--r--chromium/ui/base/resource/resource_bundle_android.cc4
-rw-r--r--chromium/ui/base/resource/resource_bundle_auralinux.cc4
-rw-r--r--chromium/ui/base/resource/resource_bundle_ios.mm7
-rw-r--r--chromium/ui/base/resource/resource_bundle_mac.mm97
-rw-r--r--chromium/ui/base/resource/resource_bundle_unittest.cc64
-rw-r--r--chromium/ui/base/resource/resource_bundle_win.cc5
-rw-r--r--chromium/ui/base/resource/resource_handle.h6
-rw-r--r--chromium/ui/base/resource/scale_factor.cc24
-rw-r--r--chromium/ui/base/resource/scale_factor.h37
-rw-r--r--chromium/ui/base/resource/scale_factor_unittest.cc23
-rw-r--r--chromium/ui/base/template_expressions.cc80
-rw-r--r--chromium/ui/base/template_expressions.h9
-rw-r--r--chromium/ui/base/template_expressions_unittest.cc44
-rw-r--r--chromium/ui/base/theme_provider.h6
-rw-r--r--chromium/ui/base/ui_base.gyp64
-rw-r--r--chromium/ui/base/ui_base_switches.cc6
-rw-r--r--chromium/ui/base/ui_base_switches.h2
-rw-r--r--chromium/ui/base/ui_base_tests.gyp19
-rw-r--r--chromium/ui/base/ui_base_types.h4
-rw-r--r--chromium/ui/base/ui_base_unittests_apk.isolate1
-rw-r--r--chromium/ui/base/ui_features.gni5
-rw-r--r--chromium/ui/base/user_activity/user_activity_detector.cc7
-rw-r--r--chromium/ui/base/webui/web_ui_util.cc9
-rw-r--r--chromium/ui/base/win/open_file_name_win.cc12
-rw-r--r--chromium/ui/base/win/open_file_name_win.h6
-rw-r--r--chromium/ui/base/win/open_file_name_win_unittest.cc16
-rw-r--r--chromium/ui/base/win/shell.cc38
-rw-r--r--chromium/ui/base/win/shell.h9
-rw-r--r--chromium/ui/base/x/selection_owner.cc3
-rw-r--r--chromium/ui/base/x/selection_owner.h1
-rw-r--r--chromium/ui/base/x/selection_requestor.cc3
-rw-r--r--chromium/ui/base/x/selection_utils.cc4
-rw-r--r--chromium/ui/base/x/selection_utils.h1
-rw-r--r--chromium/ui/compositor/BUILD.gn16
-rw-r--r--chromium/ui/compositor/compositing_recorder.cc2
-rw-r--r--chromium/ui/compositor/compositor.cc27
-rw-r--r--chromium/ui/compositor/compositor.gyp14
-rw-r--r--chromium/ui/compositor/compositor.h2
-rw-r--r--chromium/ui/compositor/compositor_switches.cc3
-rw-r--r--chromium/ui/compositor/compositor_switches.h1
-rw-r--r--chromium/ui/compositor/layer.cc131
-rw-r--r--chromium/ui/compositor/layer.h35
-rw-r--r--chromium/ui/compositor/layer_animation_delegate.h10
-rw-r--r--chromium/ui/compositor/layer_animation_element.cc41
-rw-r--r--chromium/ui/compositor/layer_animation_element.h2
-rw-r--r--chromium/ui/compositor/layer_animation_sequence_unittest.cc6
-rw-r--r--chromium/ui/compositor/layer_animator.cc86
-rw-r--r--chromium/ui/compositor/layer_animator.h20
-rw-r--r--chromium/ui/compositor/layer_animator_unittest.cc65
-rw-r--r--chromium/ui/compositor/layer_owner.cc2
-rw-r--r--chromium/ui/compositor/layer_owner_unittest.cc48
-rw-r--r--chromium/ui/compositor/layer_threaded_animation_delegate.h26
-rw-r--r--chromium/ui/compositor/layer_unittest.cc197
-rw-r--r--chromium/ui/compositor/paint_recorder.cc5
-rw-r--r--chromium/ui/compositor/transform_animation_curve_adapter.cc3
-rw-r--r--chromium/ui/compositor/transform_animation_curve_adapter.h2
-rw-r--r--chromium/ui/display/BUILD.gn203
-rw-r--r--chromium/ui/display/DEPS3
-rw-r--r--chromium/ui/display/display.gyp13
-rw-r--r--chromium/ui/display/display_unittests.isolate2
-rw-r--r--chromium/ui/display/manager/display_layout.cc256
-rw-r--r--chromium/ui/display/manager/display_layout.h114
-rw-r--r--chromium/ui/display/manager/display_layout_builder.cc68
-rw-r--r--chromium/ui/display/manager/display_layout_builder.h57
-rw-r--r--chromium/ui/display/manager/display_layout_builder_unittest.cc49
-rw-r--r--chromium/ui/display/types/display_snapshot.cc25
-rw-r--r--chromium/ui/display/types/display_snapshot.h14
-rw-r--r--chromium/ui/display/types/native_display_delegate.h9
-rw-r--r--chromium/ui/display/util/x11/edid_parser_x11.cc43
-rw-r--r--chromium/ui/display/util/x11/edid_parser_x11.h50
-rw-r--r--chromium/ui/display/win/display_info.cc60
-rw-r--r--chromium/ui/display/win/display_info.h44
-rw-r--r--chromium/ui/display/win/screen_win.cc242
-rw-r--r--chromium/ui/display/win/screen_win.h102
-rw-r--r--chromium/ui/display/win/screen_win_display.cc37
-rw-r--r--chromium/ui/display/win/screen_win_display.h36
-rw-r--r--chromium/ui/display/win/screen_win_unittest.cc784
-rw-r--r--chromium/ui/events/BUILD.gn47
-rw-r--r--chromium/ui/events/android/key_event_utils.cc32
-rw-r--r--chromium/ui/events/android/key_event_utils.h31
-rw-r--r--chromium/ui/events/blink/DEPS1
-rw-r--r--chromium/ui/events/blink/blink_event_util.cc164
-rw-r--r--chromium/ui/events/blink/blink_event_util.h14
-rw-r--r--chromium/ui/events/blink/blink_event_util_unittest.cc30
-rw-r--r--chromium/ui/events/blink/input_handler_proxy.cc456
-rw-r--r--chromium/ui/events/blink/input_handler_proxy.h30
-rw-r--r--chromium/ui/events/blink/input_handler_proxy_unittest.cc541
-rw-r--r--chromium/ui/events/blink/input_scroll_elasticity_controller.cc65
-rw-r--r--chromium/ui/events/blink/input_scroll_elasticity_controller.h9
-rw-r--r--chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc308
-rw-r--r--chromium/ui/events/blink/synchronous_input_handler_proxy.h7
-rw-r--r--chromium/ui/events/cocoa/events_mac.mm20
-rw-r--r--chromium/ui/events/cocoa/events_mac_unittest.mm5
-rw-r--r--chromium/ui/events/devices/input_device.cc2
-rw-r--r--chromium/ui/events/devices/input_device.h1
-rw-r--r--chromium/ui/events/devices/x11/device_data_manager_x11.cc33
-rw-r--r--chromium/ui/events/devices/x11/device_data_manager_x11.h3
-rw-r--r--chromium/ui/events/event.cc263
-rw-r--r--chromium/ui/events/event.h227
-rw-r--r--chromium/ui/events/event_constants.h10
-rw-r--r--chromium/ui/events/event_unittest.cc322
-rw-r--r--chromium/ui/events/event_utils.cc2
-rw-r--r--chromium/ui/events/event_utils.h11
-rw-r--r--chromium/ui/events/events.gyp17
-rw-r--r--chromium/ui/events/events_default.cc19
-rw-r--r--chromium/ui/events/events_stub.cc20
-rw-r--r--chromium/ui/events/events_unittests.gyp10
-rw-r--r--chromium/ui/events/events_unittests_apk.isolate1
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.cc20
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.h9
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc100
-rw-r--r--chromium/ui/events/gesture_detection/gesture_detector.cc2
-rw-r--r--chromium/ui/events/gesture_detection/gesture_detector.h1
-rw-r--r--chromium/ui/events/gesture_detection/gesture_event_data.cc2
-rw-r--r--chromium/ui/events/gesture_detection/gesture_event_data.h1
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.cc2
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.h1
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc2
-rw-r--r--chromium/ui/events/gesture_detection/motion_event_generic.cc2
-rw-r--r--chromium/ui/events/gesture_detection/motion_event_generic.h1
-rw-r--r--chromium/ui/events/gesture_event_details.h18
-rw-r--r--chromium/ui/events/gestures/blink/web_gesture_curve_impl.h1
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura.cc2
-rw-r--r--chromium/ui/events/gestures/motion_event_aura.cc8
-rw-r--r--chromium/ui/events/gestures/motion_event_aura_unittest.cc12
-rw-r--r--chromium/ui/events/ipc/BUILD.gn3
-rw-r--r--chromium/ui/events/ipc/latency_info_param_traits.cc26
-rw-r--r--chromium/ui/events/ipc/latency_info_param_traits.h6
-rw-r--r--chromium/ui/events/ipc/latency_info_param_traits_unittest.cc17
-rw-r--r--chromium/ui/events/keycodes/dom/dom_key.h9
-rw-r--r--chromium/ui/events/keycodes/dom/dom_key_data.inc683
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter.cc7
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter_data.inc68
-rw-r--r--chromium/ui/events/keycodes/dom/keycode_converter_unittest.cc129
-rw-r--r--chromium/ui/events/keycodes/dom_us_layout_data.h56
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_android.cc10
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm115
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_unittest.cc12
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc8
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win.cc281
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win.h65
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win_unittest.cc250
-rw-r--r--chromium/ui/events/keycodes/xkb_keysym.h18
-rw-r--r--chromium/ui/events/latency_info.cc29
-rw-r--r--chromium/ui/events/latency_info.h40
-rw-r--r--chromium/ui/events/latency_info_unittest.cc12
-rw-r--r--chromium/ui/events/null_event_targeter.h5
-rw-r--r--chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc9
-rw-r--r--chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h6
-rw-r--r--chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc4
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.cc17
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.h1
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h1
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h1
-rw-r--r--chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h1
-rw-r--r--chromium/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc16
-rw-r--r--chromium/ui/events/ozone/evdev/touch_evdev_types.cc3
-rw-r--r--chromium/ui/events/ozone/evdev/touch_evdev_types.h2
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc26
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc74
-rw-r--r--chromium/ui/events/ozone/layout/layout_util.cc2
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc29
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h2
-rw-r--r--chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc6
-rw-r--r--chromium/ui/events/platform/x11/BUILD.gn18
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.cc70
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.h50
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source_glib.cc91
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source_glib.h53
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source_libevent.cc209
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source_libevent.h79
-rw-r--r--chromium/ui/events/platform/x11/x11_events_platform.gyp13
-rw-r--r--chromium/ui/events/win/event_utils_win_unittest.cc66
-rw-r--r--chromium/ui/events/win/events_win.cc24
-rw-r--r--chromium/ui/events/x/BUILD.gn5
-rw-r--r--chromium/ui/events/x/events_x.cc18
-rw-r--r--chromium/ui/events/x/events_x_unittest.cc26
-rw-r--r--chromium/ui/events/x/events_x_utils.cc17
-rw-r--r--chromium/ui/events/x/events_x_utils.h8
-rw-r--r--chromium/ui/file_manager/audio_player/js/compiled_resources.gyp4
-rw-r--r--chromium/ui/file_manager/file_manager/background/js/compiled_resources.gyp1
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp8
-rw-r--r--chromium/ui/file_manager/gallery/js/compiled_resources.gyp3
-rw-r--r--chromium/ui/file_manager/video_player/js/compiled_resources.gyp2
-rw-r--r--chromium/ui/gfx/BUILD.gn137
-rw-r--r--chromium/ui/gfx/animation/animation.cc24
-rw-r--r--chromium/ui/gfx/animation/animation.h5
-rw-r--r--chromium/ui/gfx/animation/animation_mac.mm33
-rw-r--r--chromium/ui/gfx/animation/animation_win.cc28
-rw-r--r--chromium/ui/gfx/animation/multi_animation.h9
-rw-r--r--chromium/ui/gfx/animation/multi_animation_unittest.cc4
-rw-r--r--chromium/ui/gfx/blit_unittest.cc8
-rw-r--r--chromium/ui/gfx/canvas.cc125
-rw-r--r--chromium/ui/gfx/canvas.h25
-rw-r--r--chromium/ui/gfx/canvas_paint_mac.h1
-rw-r--r--chromium/ui/gfx/canvas_paint_mac.mm16
-rw-r--r--chromium/ui/gfx/canvas_skia.cc3
-rw-r--r--chromium/ui/gfx/color_palette.h9
-rw-r--r--chromium/ui/gfx/color_utils.cc111
-rw-r--r--chromium/ui/gfx/color_utils.h50
-rw-r--r--chromium/ui/gfx/display.cc2
-rw-r--r--chromium/ui/gfx/display.h12
-rw-r--r--chromium/ui/gfx/display_finder.cc50
-rw-r--r--chromium/ui/gfx/display_finder.h31
-rw-r--r--chromium/ui/gfx/font_fallback_linux.cc184
-rw-r--r--chromium/ui/gfx/font_fallback_linux.h38
-rw-r--r--chromium/ui/gfx/font_render_params.cc5
-rw-r--r--chromium/ui/gfx/font_render_params.h6
-rw-r--r--chromium/ui/gfx/font_render_params_linux.cc32
-rw-r--r--chromium/ui/gfx/font_render_params_linux_unittest.cc2
-rw-r--r--chromium/ui/gfx/generic_shared_memory_id.h4
-rw-r--r--chromium/ui/gfx/geometry/cubic_bezier.cc240
-rw-r--r--chromium/ui/gfx/geometry/cubic_bezier.h66
-rw-r--r--chromium/ui/gfx/geometry/cubic_bezier_unittest.cc49
-rw-r--r--chromium/ui/gfx/geometry/insets.cc7
-rw-r--r--chromium/ui/gfx/geometry/insets.h3
-rw-r--r--chromium/ui/gfx/geometry/insets_f.cc7
-rw-r--r--chromium/ui/gfx/geometry/insets_f.h5
-rw-r--r--chromium/ui/gfx/gfx.gyp15
-rw-r--r--chromium/ui/gfx/gfx_tests.gyp2
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.cc3
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.h5
-rw-r--r--chromium/ui/gfx/harfbuzz_font_skia.cc15
-rw-r--r--chromium/ui/gfx/icon_util_unittest.cc6
-rw-r--r--chromium/ui/gfx/image/image.cc21
-rw-r--r--chromium/ui/gfx/image/image.h7
-rw-r--r--chromium/ui/gfx/image/image_png_rep.cc2
-rw-r--r--chromium/ui/gfx/image/image_png_rep.h1
-rw-r--r--chromium/ui/gfx/image/image_skia.cc318
-rw-r--r--chromium/ui/gfx/image/image_skia_source.cc13
-rw-r--r--chromium/ui/gfx/image/image_skia_source.h6
-rw-r--r--chromium/ui/gfx/image/image_unittest.cc20
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.cc8
-rw-r--r--chromium/ui/gfx/image/image_util.cc90
-rw-r--r--chromium/ui/gfx/image/image_util.h24
-rw-r--r--chromium/ui/gfx/image/image_util_unittest.cc175
-rw-r--r--chromium/ui/gfx/ipc/BUILD.gn1
-rw-r--r--chromium/ui/gfx/ipc/gfx_ipc.gyp1
-rw-r--r--chromium/ui/gfx/ipc/gfx_param_traits.cc158
-rw-r--r--chromium/ui/gfx/ipc/gfx_param_traits.h89
-rw-r--r--chromium/ui/gfx/ipc/skia/BUILD.gn23
-rw-r--r--chromium/ui/gfx/ipc/skia/gfx_ipc_skia.gyp34
-rw-r--r--chromium/ui/gfx/ipc/skia/gfx_skia_ipc_export.h29
-rw-r--r--chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc135
-rw-r--r--chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.h49
-rw-r--r--chromium/ui/gfx/mac/io_surface.cc10
-rw-r--r--chromium/ui/gfx/mac/io_surface.h18
-rw-r--r--chromium/ui/gfx/native_widget_types.h24
-rw-r--r--chromium/ui/gfx/paint_vector_icon.cc4
-rw-r--r--chromium/ui/gfx/path.h3
-rw-r--r--chromium/ui/gfx/path_mac.h21
-rw-r--r--chromium/ui/gfx/path_mac.mm125
-rw-r--r--chromium/ui/gfx/path_mac_unittest.mm258
-rw-r--r--chromium/ui/gfx/platform_font_linux.cc6
-rw-r--r--chromium/ui/gfx/platform_font_linux.h2
-rw-r--r--chromium/ui/gfx/range/range.cc17
-rw-r--r--chromium/ui/gfx/range/range.h31
-rw-r--r--chromium/ui/gfx/render_text.cc47
-rw-r--r--chromium/ui/gfx/render_text.h5
-rw-r--r--chromium/ui/gfx/render_text_harfbuzz.cc17
-rw-r--r--chromium/ui/gfx/render_text_harfbuzz.h2
-rw-r--r--chromium/ui/gfx/render_text_mac.h1
-rw-r--r--chromium/ui/gfx/render_text_mac.mm5
-rw-r--r--chromium/ui/gfx/render_text_unittest.cc45
-rw-r--r--chromium/ui/gfx/screen.cc48
-rw-r--r--chromium/ui/gfx/screen.h52
-rw-r--r--chromium/ui/gfx/screen_mac.mm29
-rw-r--r--chromium/ui/gfx/screen_type_delegate.h33
-rw-r--r--chromium/ui/gfx/screen_unittest.cc5
-rw-r--r--chromium/ui/gfx/screen_win.cc216
-rw-r--r--chromium/ui/gfx/screen_win.h66
-rw-r--r--chromium/ui/gfx/screen_win_unittest.cc80
-rw-r--r--chromium/ui/gfx/selection_model.h2
-rw-r--r--chromium/ui/gfx/skbitmap_operations.cc5
-rw-r--r--chromium/ui/gfx/skia_util.cc46
-rw-r--r--chromium/ui/gfx/skia_util.h23
-rw-r--r--chromium/ui/gfx/sys_color_change_listener.cc10
-rw-r--r--chromium/ui/gfx/text_elider.cc7
-rw-r--r--chromium/ui/gfx/text_elider.h2
-rw-r--r--chromium/ui/gfx/text_elider_unittest.cc6
-rw-r--r--chromium/ui/gfx/vector_icons/aggregate_vector_icons.py4
-rw-r--r--chromium/ui/gfx/vector_icons/autofill.icon29
-rw-r--r--chromium/ui/gfx/vector_icons/combobox_arrow_mac.icon13
-rw-r--r--chromium/ui/gfx/vector_icons/menu_radio_empty.icon8
-rw-r--r--chromium/ui/gfx/vector_icons/menu_radio_selected.icon9
-rw-r--r--chromium/ui/gfx/vector_icons/tab_bluetooth_connected.icon34
-rw-r--r--chromium/ui/gfx/vector_icons/tab_usb_connected.icon39
-rw-r--r--chromium/ui/gfx/vector_icons/translate.icon121
-rw-r--r--chromium/ui/gfx/vector_icons/upgrade_menu_item.icon16
-rw-r--r--chromium/ui/gfx/win/direct_write.cc10
-rw-r--r--chromium/ui/gfx/win/physical_size.cc163
-rw-r--r--chromium/ui/gfx/win/physical_size.h31
-rw-r--r--chromium/ui/gfx/win/rendering_window_manager.cc70
-rw-r--r--chromium/ui/gfx/win/rendering_window_manager.h48
-rw-r--r--chromium/ui/gl/BUILD.gn23
-rw-r--r--chromium/ui/gl/OWNERS2
-rw-r--r--chromium/ui/gl/angle_platform_impl.cc3
-rwxr-xr-xchromium/ui/gl/generate_bindings.py20
-rw-r--r--chromium/ui/gl/gl.gyp12
-rw-r--r--chromium/ui/gl/gl_bindings.cc2
-rw-r--r--chromium/ui/gl/gl_bindings_api_autogen_gl.h1
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_egl.cc45
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.cc360
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.h6
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_glx.cc48
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.cc8
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.h1
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_osmesa.cc11
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_wgl.cc18
-rw-r--r--chromium/ui/gl/gl_bindings_skia_in_process.cc995
-rw-r--r--chromium/ui/gl/gl_bindings_skia_in_process.h20
-rw-r--r--chromium/ui/gl/gl_context_egl.cc7
-rw-r--r--chromium/ui/gl/gl_context_osmesa.cc14
-rw-r--r--chromium/ui/gl/gl_fence.cc9
-rw-r--r--chromium/ui/gl/gl_fence.h6
-rw-r--r--chromium/ui/gl/gl_fence_nv.cc8
-rw-r--r--chromium/ui/gl/gl_fence_nv.h2
-rw-r--r--chromium/ui/gl/gl_image_io_surface.h26
-rw-r--r--chromium/ui/gl/gl_image_io_surface.mm297
-rw-r--r--chromium/ui/gl/gl_image_io_surface_unittest.cc20
-rw-r--r--chromium/ui/gl/gl_image_memory.cc3
-rw-r--r--chromium/ui/gl/gl_image_ozone_native_pixmap.cc13
-rw-r--r--chromium/ui/gl/gl_image_ozone_native_pixmap.h1
-rw-r--r--chromium/ui/gl/gl_image_ozone_native_pixmap_unittest.cc2
-rw-r--r--chromium/ui/gl/gl_image_ref_counted_memory_unittest.cc2
-rw-r--r--chromium/ui/gl/gl_image_shared_memory_unittest.cc4
-rw-r--r--chromium/ui/gl/gl_implementation.cc2
-rw-r--r--chromium/ui/gl/gl_implementation_x11.cc4
-rw-r--r--chromium/ui/gl/gl_mock.cc20
-rw-r--r--chromium/ui/gl/gl_mock.h31
-rw-r--r--chromium/ui/gl/gl_mock_autogen_gl.h1
-rw-r--r--chromium/ui/gl/gl_surface.cc22
-rw-r--r--chromium/ui/gl/gl_surface.h26
-rw-r--r--chromium/ui/gl/gl_surface_android.cc2
-rw-r--r--chromium/ui/gl/gl_surface_egl.cc305
-rw-r--r--chromium/ui/gl/gl_surface_egl.h17
-rw-r--r--chromium/ui/gl/gl_surface_glx.cc4
-rw-r--r--chromium/ui/gl/gl_surface_glx.h4
-rw-r--r--chromium/ui/gl/gl_surface_mac.cc4
-rw-r--r--chromium/ui/gl/gl_surface_osmesa.cc19
-rw-r--r--chromium/ui/gl/gl_surface_osmesa.h10
-rw-r--r--chromium/ui/gl/gl_surface_overlay.cc2
-rw-r--r--chromium/ui/gl/gl_surface_overlay.h1
-rw-r--r--chromium/ui/gl/gl_surface_ozone.cc85
-rw-r--r--chromium/ui/gl/gl_surface_stub.cc10
-rw-r--r--chromium/ui/gl/gl_surface_stub.h6
-rw-r--r--chromium/ui/gl/gl_surface_wgl.cc4
-rw-r--r--chromium/ui/gl/gl_surface_wgl.h4
-rw-r--r--chromium/ui/gl/gl_surface_win.cc12
-rw-r--r--chromium/ui/gl/gl_surface_x11.cc10
-rw-r--r--chromium/ui/gl/gl_switches.cc25
-rw-r--r--chromium/ui/gl/gl_switches.h3
-rw-r--r--chromium/ui/gl/gl_unittests_apk.isolate1
-rw-r--r--chromium/ui/gl/gl_version_info.cc1
-rw-r--r--chromium/ui/gl/gpu_switching_manager.h1
-rw-r--r--chromium/ui/gl/gpu_timing.cc43
-rw-r--r--chromium/ui/gl/gpu_timing_fake.cc12
-rw-r--r--chromium/ui/gl/gpu_timing_unittest.cc46
-rw-r--r--chromium/ui/gl/vsync_provider_win.cc21
-rw-r--r--chromium/ui/gl/vsync_provider_win.h3
-rw-r--r--chromium/ui/keyboard/BUILD.gn11
-rw-r--r--chromium/ui/keyboard/content/keyboard_ui_content.cc2
-rw-r--r--chromium/ui/keyboard/keyboard.gyp15
-rw-r--r--chromium/ui/keyboard/keyboard.mojom25
-rw-r--r--chromium/ui/keyboard/keyboard_controller.cc3
-rw-r--r--chromium/ui/keyboard/keyboard_controller.h4
-rw-r--r--chromium/ui/keyboard/keyboard_controller_unittest.cc14
-rw-r--r--chromium/ui/keyboard/resources/OWNERS3
-rw-r--r--chromium/ui/keyboard/resources/inputview_adapter.js11
-rw-r--r--chromium/ui/login/account_picker/user_pod_row.css2
-rw-r--r--chromium/ui/login/account_picker/user_pod_row.js30
-rw-r--r--chromium/ui/login/display_manager.js2
-rw-r--r--chromium/ui/login/screen_container.css10
-rw-r--r--chromium/ui/message_center/BUILD.gn21
-rw-r--r--chromium/ui/message_center/cocoa/settings_controller_unittest.mm3
-rw-r--r--chromium/ui/message_center/fake_message_center.cc6
-rw-r--r--chromium/ui/message_center/fake_message_center.h3
-rw-r--r--chromium/ui/message_center/fake_message_center_tray_delegate.h1
-rw-r--r--chromium/ui/message_center/fake_notifier_settings_provider.cc6
-rw-r--r--chromium/ui/message_center/fake_notifier_settings_provider.h1
-rw-r--r--chromium/ui/message_center/message_center.gyp17
-rw-r--r--chromium/ui/message_center/message_center.h10
-rw-r--r--chromium/ui/message_center/message_center_impl.cc21
-rw-r--r--chromium/ui/message_center/message_center_impl.h6
-rw-r--r--chromium/ui/message_center/message_center_impl_unittest.cc10
-rw-r--r--chromium/ui/message_center/notification.cc16
-rw-r--r--chromium/ui/message_center/notification.h40
-rw-r--r--chromium/ui/message_center/notifier_settings.cc7
-rw-r--r--chromium/ui/message_center/notifier_settings.h12
-rw-r--r--chromium/ui/message_center/popup_timer.cc138
-rw-r--r--chromium/ui/message_center/popup_timer.h76
-rw-r--r--chromium/ui/message_center/popup_timers_controller.cc126
-rw-r--r--chromium/ui/message_center/popup_timers_controller.h80
-rw-r--r--chromium/ui/message_center/views/constants.h2
-rw-r--r--chromium/ui/message_center/views/message_center_button_bar.cc6
-rw-r--r--chromium/ui/message_center/views/message_center_button_bar.h3
-rw-r--r--chromium/ui/message_center/views/message_center_view.cc22
-rw-r--r--chromium/ui/message_center/views/message_center_view.h2
-rw-r--r--chromium/ui/message_center/views/message_center_view_unittest.cc123
-rw-r--r--chromium/ui/message_center/views/message_list_view.cc13
-rw-r--r--chromium/ui/message_center/views/message_list_view.h2
-rw-r--r--chromium/ui/message_center/views/message_popup_collection.cc39
-rw-r--r--chromium/ui/message_center/views/message_popup_collection_unittest.cc41
-rw-r--r--chromium/ui/message_center/views/message_view.cc38
-rw-r--r--chromium/ui/message_center/views/message_view.h11
-rw-r--r--chromium/ui/message_center/views/notification_view.cc131
-rw-r--r--chromium/ui/message_center/views/notification_view.h5
-rw-r--r--chromium/ui/message_center/views/notification_view_unittest.cc145
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.cc7
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.h5
-rw-r--r--chromium/ui/message_center/views/toast_contents_view.cc4
-rw-r--r--chromium/ui/metro_viewer/BUILD.gn19
-rw-r--r--chromium/ui/metro_viewer/DEPS4
-rw-r--r--chromium/ui/metro_viewer/OWNERS12
-rw-r--r--chromium/ui/metro_viewer/ime_types.cc30
-rw-r--r--chromium/ui/metro_viewer/ime_types.h50
-rw-r--r--chromium/ui/metro_viewer/metro_viewer.gyp29
-rw-r--r--chromium/ui/metro_viewer/metro_viewer_message_generator.cc33
-rw-r--r--chromium/ui/metro_viewer/metro_viewer_message_generator.h7
-rw-r--r--chromium/ui/metro_viewer/metro_viewer_messages.h228
-rw-r--r--chromium/ui/mojo/geometry/mojo_bindings.gyp4
-rw-r--r--chromium/ui/mojo/init/ui_init.cc4
-rw-r--r--chromium/ui/native_theme/common_theme.cc58
-rw-r--r--chromium/ui/native_theme/common_theme.h12
-rw-r--r--chromium/ui/native_theme/native_theme.cc10
-rw-r--r--chromium/ui/native_theme/native_theme.h10
-rw-r--r--chromium/ui/native_theme/native_theme_aura.cc6
-rw-r--r--chromium/ui/native_theme/native_theme_aura.h2
-rw-r--r--chromium/ui/native_theme/native_theme_aurawin.cc4
-rw-r--r--chromium/ui/native_theme/native_theme_base.cc24
-rw-r--r--chromium/ui/native_theme/native_theme_base.h2
-rw-r--r--chromium/ui/native_theme/native_theme_dark_aura.cc67
-rw-r--r--chromium/ui/native_theme/native_theme_dark_win.cc2
-rw-r--r--chromium/ui/native_theme/native_theme_mac.h19
-rw-r--r--chromium/ui/native_theme/native_theme_mac.mm192
-rw-r--r--chromium/ui/native_theme/native_theme_win.cc32
-rw-r--r--chromium/ui/ozone/BUILD.gn120
-rw-r--r--chromium/ui/ozone/common/BUILD.gn35
-rw-r--r--chromium/ui/ozone/common/display_mode_proxy.h3
-rw-r--r--chromium/ui/ozone/common/display_snapshot_proxy.cc14
-rw-r--r--chromium/ui/ozone/common/display_snapshot_proxy.h3
-rw-r--r--chromium/ui/ozone/common/display_util.cc3
-rw-r--r--chromium/ui/ozone/common/display_util.h4
-rw-r--r--chromium/ui/ozone/common/egl_util.cc23
-rw-r--r--chromium/ui/ozone/common/egl_util.h7
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc7
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h11
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_messages.h13
-rw-r--r--chromium/ui/ozone/common/native_display_delegate_ozone.cc6
-rw-r--r--chromium/ui/ozone/common/native_display_delegate_ozone.h12
-rw-r--r--chromium/ui/ozone/common/stub_client_native_pixmap_factory.cc1
-rw-r--r--chromium/ui/ozone/common/stub_client_native_pixmap_factory.h2
-rw-r--r--chromium/ui/ozone/common/stub_overlay_manager.h3
-rw-r--r--chromium/ui/ozone/demo/BUILD.gn1
-rw-r--r--chromium/ui/ozone/demo/ozone_demo.cc3
-rw-r--r--chromium/ui/ozone/demo/software_renderer.cc2
-rw-r--r--chromium/ui/ozone/demo/surfaceless_gl_renderer.h1
-rw-r--r--chromium/ui/ozone/empty.cc6
-rw-r--r--chromium/ui/ozone/ozone.gni38
-rw-r--r--chromium/ui/ozone/ozone.gyp77
-rw-r--r--chromium/ui/ozone/platform/caca/BUILD.gn4
-rw-r--r--chromium/ui/ozone/platform/caca/caca.gypi2
-rw-r--r--chromium/ui/ozone/platform/caca/caca_window_manager.cc2
-rw-r--r--chromium/ui/ozone/platform/caca/ozone_platform_caca.cc7
-rw-r--r--chromium/ui/ozone/platform/cast/BUILD.gn11
-rw-r--r--chromium/ui/ozone/platform/cast/DEPS1
-rw-r--r--chromium/ui/ozone/platform/cast/OWNERS2
-rw-r--r--chromium/ui/ozone/platform/cast/cast.gypi9
-rw-r--r--chromium/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc4
-rw-r--r--chromium/ui/ozone/platform/cast/overlay_manager_cast.cc18
-rw-r--r--chromium/ui/ozone/platform/cast/overlay_manager_cast.h14
-rw-r--r--chromium/ui/ozone/platform/cast/ozone_platform_cast.cc14
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.cc49
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.h12
-rw-r--r--chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.cc24
-rw-r--r--chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.h2
-rw-r--r--chromium/ui/ozone/platform/drm/BUILD.gn30
-rw-r--r--chromium/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc36
-rw-r--r--chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.cc98
-rw-r--r--chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h44
-rw-r--r--chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.cc79
-rw-r--r--chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.h49
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util.cc25
-rw-r--r--chromium/ui/ozone/platform/drm/common/scoped_drm_types.h23
-rw-r--r--chromium/ui/ozone/platform/drm/gbm.gypi27
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_buffer.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.cc227
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_display.cc19
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_display.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc19
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc112
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h13
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc122
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc33
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.h14
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc22
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h14
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc28
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h12
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/fake_plane_info.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/fake_plane_info.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc115
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_buffer.h25
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc49
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc24
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h22
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc13
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/overlay_plane.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/overlay_plane.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.h3
-rw-r--r--chromium/ui/ozone/platform/drm/host/channel_observer.h21
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.cc226
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.h109
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor_core.cc171
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor_core.h98
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host.cc35
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host.h20
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc470
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h146
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.cc490
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.h162
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc275
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h82
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc8
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h6
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc152
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h57
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc138
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h43
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host.cc33
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host.h25
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host_manager.h1
-rw-r--r--chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h76
-rw-r--r--chromium/ui/ozone/platform/drm/host/gpu_thread_observer.h24
-rw-r--r--chromium/ui/ozone/platform/drm/mus_thread_proxy.cc339
-rw-r--r--chromium/ui/ozone/platform/drm/mus_thread_proxy.h141
-rw-r--r--chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc91
-rw-r--r--chromium/ui/ozone/platform/egltest/BUILD.gn6
-rw-r--r--chromium/ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.cc2
-rw-r--r--chromium/ui/ozone/platform/egltest/egltest.gypi2
-rw-r--r--chromium/ui/ozone/platform/egltest/ozone_platform_egltest.cc44
-rw-r--r--chromium/ui/ozone/platform/headless/BUILD.gn4
-rw-r--r--chromium/ui/ozone/platform/headless/client_native_pixmap_factory_headless.cc2
-rw-r--r--chromium/ui/ozone/platform/headless/headless.gypi2
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.cc8
-rw-r--r--chromium/ui/ozone/platform/headless/ozone_platform_headless.cc5
-rw-r--r--chromium/ui/ozone/platform/wayland/BUILD.gn68
-rw-r--r--chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc15
-rw-r--r--chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.h17
-rw-r--r--chromium/ui/ozone/platform/wayland/fake_server.cc391
-rw-r--r--chromium/ui/ozone/platform/wayland/fake_server.h212
-rw-r--r--chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.cc13
-rw-r--r--chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.h37
-rw-r--r--chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc109
-rw-r--r--chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h17
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland.gypi87
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_display.cc215
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_display.h87
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_display_unittest.cc48
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_object.cc67
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_object.h121
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_pointer.cc143
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_pointer.h56
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc232
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc170
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_surface_factory.h45
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc83
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_test.cc56
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_test.h47
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window.cc183
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window.h86
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc117
-rw-r--r--chromium/ui/ozone/platform/x11/BUILD.gn42
-rw-r--r--chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.cc15
-rw-r--r--chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.h17
-rw-r--r--chromium/ui/ozone/platform/x11/ozone_platform_x11.cc129
-rw-r--r--chromium/ui/ozone/platform/x11/ozone_platform_x11.h17
-rw-r--r--chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.cc100
-rw-r--r--chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.h52
-rw-r--r--chromium/ui/ozone/platform/x11/x11_surface_factory.cc133
-rw-r--r--chromium/ui/ozone/platform/x11/x11_surface_factory.h34
-rw-r--r--chromium/ui/ozone/public/client_native_pixmap_factory.h3
-rw-r--r--chromium/ui/ozone/public/overlay_candidates_ozone.cc3
-rw-r--r--chromium/ui/ozone/public/overlay_candidates_ozone.h1
-rw-r--r--chromium/ui/ozone/public/ozone_platform.h4
-rw-r--r--chromium/ui/ozone/public/surface_factory_ozone.cc8
-rw-r--r--chromium/ui/ozone/public/surface_factory_ozone.h15
-rw-r--r--chromium/ui/ozone/public/surface_ozone_canvas.h2
-rw-r--r--chromium/ui/ozone/public/surface_ozone_egl.cc7
-rw-r--r--chromium/ui/ozone/public/surface_ozone_egl.h21
-rw-r--r--chromium/ui/platform_window/BUILD.gn2
-rw-r--r--chromium/ui/platform_window/stub/stub_window.gyp24
-rw-r--r--chromium/ui/platform_window/text_input_state.cc2
-rw-r--r--chromium/ui/platform_window/text_input_state.h1
-rw-r--r--chromium/ui/platform_window/win/win_window.cc6
-rw-r--r--chromium/ui/platform_window/x11/BUILD.gn24
-rw-r--r--chromium/ui/platform_window/x11/DEPS2
-rw-r--r--chromium/ui/platform_window/x11/x11_cursor_ozone.cc84
-rw-r--r--chromium/ui/platform_window/x11/x11_cursor_ozone.h48
-rw-r--r--chromium/ui/platform_window/x11/x11_window.cc305
-rw-r--r--chromium/ui/platform_window/x11/x11_window.gyp2
-rw-r--r--chromium/ui/platform_window/x11/x11_window.h65
-rw-r--r--chromium/ui/platform_window/x11/x11_window_base.cc288
-rw-r--r--chromium/ui/platform_window/x11/x11_window_base.h100
-rw-r--r--chromium/ui/platform_window/x11/x11_window_manager_ozone.cc27
-rw-r--r--chromium/ui/platform_window/x11/x11_window_manager_ozone.h37
-rw-r--r--chromium/ui/platform_window/x11/x11_window_ozone.cc85
-rw-r--r--chromium/ui/platform_window/x11/x11_window_ozone.h49
-rw-r--r--chromium/ui/resources/BUILD.gn54
-rw-r--r--chromium/ui/shell_dialogs/BUILD.gn20
-rw-r--r--chromium/ui/shell_dialogs/linux_shell_dialog.cc23
-rw-r--r--chromium/ui/shell_dialogs/run_all_unittests.cc73
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog.cc48
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog.h21
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.cc5
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.h4
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_auraandroid.cc56
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_auraandroid.h48
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_mac.h92
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_mac.mm133
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm470
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.cc68
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.h4
-rw-r--r--chromium/ui/shell_dialogs/shell_dialog_linux.cc34
-rw-r--r--chromium/ui/shell_dialogs/shell_dialog_linux.h (renamed from chromium/ui/shell_dialogs/linux_shell_dialog.h)15
-rw-r--r--chromium/ui/shell_dialogs/shell_dialogs.gyp33
-rw-r--r--chromium/ui/shell_dialogs/shell_dialogs_delegate.h24
-rw-r--r--chromium/ui/snapshot/BUILD.gn1
-rw-r--r--chromium/ui/snapshot/snapshot.gyp6
-rw-r--r--chromium/ui/snapshot/snapshot_android.cc3
-rw-r--r--chromium/ui/snapshot/snapshot_mac.mm3
-rw-r--r--chromium/ui/strings/translations/ui_strings_bn.xtb10
-rw-r--r--chromium/ui/strings/translations/ui_strings_zh-CN.xtb2
-rw-r--r--chromium/ui/strings/ui_strings.grd11
-rw-r--r--chromium/ui/surface/BUILD.gn10
-rw-r--r--chromium/ui/surface/OWNERS1
-rw-r--r--chromium/ui/surface/accelerated_surface_mac.cc266
-rw-r--r--chromium/ui/surface/accelerated_surface_mac.h147
-rw-r--r--chromium/ui/surface/surface.gyp11
-rw-r--r--chromium/ui/surface/transport_dib_posix.cc3
-rw-r--r--chromium/ui/surface/transport_dib_win.cc4
-rw-r--r--chromium/ui/touch_selection/BUILD.gn9
-rw-r--r--chromium/ui/touch_selection/ui_touch_selection_unittests_apk.isolate1
-rw-r--r--chromium/ui/views/BUILD.gn23
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.cc72
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.h36
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc61
-rw-r--r--chromium/ui/views/accessibility/ax_view_obj_wrapper.cc5
-rw-r--r--chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc5
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.cc4
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.h2
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility.cc3
-rw-r--r--chromium/ui/views/accessible_pane_view_unittest.cc11
-rw-r--r--chromium/ui/views/animation/OWNERS1
-rw-r--r--chromium/ui/views/animation/bounds_animator.h1
-rw-r--r--chromium/ui/views/animation/button_ink_drop_delegate.cc43
-rw-r--r--chromium/ui/views/animation/button_ink_drop_delegate.h22
-rw-r--r--chromium/ui/views/animation/flood_fill_ink_drop_animation.cc327
-rw-r--r--chromium/ui/views/animation/flood_fill_ink_drop_animation.h131
-rw-r--r--chromium/ui/views/animation/ink_drop_animation.cc455
-rw-r--r--chromium/ui/views/animation/ink_drop_animation.h210
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller.h28
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller_factory.cc31
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller_factory_unittest.cc77
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller_impl.cc256
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller_impl.h108
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_controller_impl_unittest.cc241
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_ended_reason.cc23
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_ended_reason.h25
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_observer.cc26
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_observer.h43
-rw-r--r--chromium/ui/views/animation/ink_drop_animation_unittest.cc552
-rw-r--r--chromium/ui/views/animation/ink_drop_delegate.h19
-rw-r--r--chromium/ui/views/animation/ink_drop_host.h12
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.cc74
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.h48
-rw-r--r--chromium/ui/views/animation/ink_drop_hover.cc146
-rw-r--r--chromium/ui/views/animation/ink_drop_hover.h117
-rw-r--r--chromium/ui/views/animation/ink_drop_hover_observer.h41
-rw-r--r--chromium/ui/views/animation/ink_drop_hover_unittest.cc144
-rw-r--r--chromium/ui/views/animation/ink_drop_painted_layer_delegates.cc33
-rw-r--r--chromium/ui/views/animation/ink_drop_painted_layer_delegates.h25
-rw-r--r--chromium/ui/views/animation/ink_drop_state.cc12
-rw-r--r--chromium/ui/views/animation/ink_drop_state.h22
-rw-r--r--chromium/ui/views/animation/square_ink_drop_animation.cc555
-rw-r--r--chromium/ui/views/animation/square_ink_drop_animation.h184
-rw-r--r--chromium/ui/views/animation/square_ink_drop_animation_unittest.cc248
-rw-r--r--chromium/ui/views/background.cc18
-rw-r--r--chromium/ui/views/background.h11
-rw-r--r--chromium/ui/views/border.cc5
-rw-r--r--chromium/ui/views/bubble/bubble_border.cc73
-rw-r--r--chromium/ui/views/bubble/bubble_border.h22
-rw-r--r--chromium/ui/views/bubble/bubble_border_unittest.cc68
-rw-r--r--chromium/ui/views/bubble/bubble_delegate.cc33
-rw-r--r--chromium/ui/views/bubble/bubble_delegate.h7
-rw-r--r--chromium/ui/views/bubble/bubble_delegate_unittest.cc1
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate.cc319
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate.h205
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc316
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc244
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h24
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view_unittest.cc43
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter_unittest.cc4
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.cc13
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.h13
-rw-r--r--chromium/ui/views/button_drag_utils.cc21
-rw-r--r--chromium/ui/views/cocoa/bridged_content_view.h6
-rw-r--r--chromium/ui/views/cocoa/bridged_content_view.mm105
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.h11
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.mm135
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm37
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_unittest.mm58
-rw-r--r--chromium/ui/views/cocoa/cocoa_mouse_capture.h2
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_nswindow.mm13
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.h3
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.mm7
-rw-r--r--chromium/ui/views/cocoa/views_scrollbar_bridge.h40
-rw-r--r--chromium/ui/views/cocoa/views_scrollbar_bridge.mm49
-rw-r--r--chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm13
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.cc6
-rw-r--r--chromium/ui/views/controls/button/blue_button.cc2
-rw-r--r--chromium/ui/views/controls/button/button.h4
-rw-r--r--chromium/ui/views/controls/button/custom_button.cc169
-rw-r--r--chromium/ui/views/controls/button/custom_button.h59
-rw-r--r--chromium/ui/views/controls/button/custom_button_unittest.cc176
-rw-r--r--chromium/ui/views/controls/button/image_button.cc10
-rw-r--r--chromium/ui/views/controls/button/label_button.cc98
-rw-r--r--chromium/ui/views/controls/button/label_button.h16
-rw-r--r--chromium/ui/views/controls/button/label_button_border.cc20
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc117
-rw-r--r--chromium/ui/views/controls/button/md_text_button.cc111
-rw-r--r--chromium/ui/views/controls/button/md_text_button.h44
-rw-r--r--chromium/ui/views/controls/button/menu_button.cc138
-rw-r--r--chromium/ui/views/controls/button/menu_button.h27
-rw-r--r--chromium/ui/views/controls/button/menu_button_listener.h15
-rw-r--r--chromium/ui/views/controls/button/menu_button_unittest.cc293
-rw-r--r--chromium/ui/views/controls/combobox/combobox.cc53
-rw-r--r--chromium/ui/views/controls/combobox/combobox.h4
-rw-r--r--chromium/ui/views/controls/focusable_border.cc18
-rw-r--r--chromium/ui/views/controls/focusable_border.h3
-rw-r--r--chromium/ui/views/controls/focusable_rounded_border_mac.cc44
-rw-r--r--chromium/ui/views/controls/focusable_rounded_border_mac.h30
-rw-r--r--chromium/ui/views/controls/glow_hover_controller.cc14
-rw-r--r--chromium/ui/views/controls/image_view.cc2
-rw-r--r--chromium/ui/views/controls/image_view.h4
-rw-r--r--chromium/ui/views/controls/label.cc17
-rw-r--r--chromium/ui/views/controls/label_unittest.cc2
-rw-r--r--chromium/ui/views/controls/link.cc2
-rw-r--r--chromium/ui/views/controls/menu/menu_config.cc1
-rw-r--r--chromium/ui/views/controls/menu/menu_config.h3
-rw-r--r--chromium/ui/views/controls/menu/menu_config_android.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_config_mac.mm13
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc470
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.h50
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc350
-rw-r--r--chromium/ui/views/controls/menu/menu_event_dispatcher.cc89
-rw-r--r--chromium/ui/views/controls/menu/menu_event_dispatcher.h39
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.cc17
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.h11
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc8
-rw-r--r--chromium/ui/views/controls/menu/menu_key_event_handler.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_aura.cc35
-rw-r--r--chromium/ui/views/controls/menu/menu_message_loop_aura.h4
-rw-r--r--chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc85
-rw-r--r--chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h38
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_model_adapter.h7
-rw-r--r--chromium/ui/views/controls/menu/menu_runner.h2
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm74
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.cc6
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm3
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_unittest.cc113
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.cc4
-rw-r--r--chromium/ui/views/controls/menu/menu_separator_views.cc14
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc2
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm37
-rw-r--r--chromium/ui/views/controls/progress_bar.cc13
-rw-r--r--chromium/ui/views/controls/scroll_view.cc26
-rw-r--r--chromium/ui/views/controls/scroll_view_unittest.cc165
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar.cc22
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar.h1
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h121
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm487
-rw-r--r--chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc108
-rw-r--r--chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h39
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc2
-rw-r--r--chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc80
-rw-r--r--chromium/ui/views/controls/single_split_view.cc31
-rw-r--r--chromium/ui/views/controls/single_split_view_unittest.cc97
-rw-r--r--chromium/ui/views/controls/slide_out_view.cc41
-rw-r--r--chromium/ui/views/controls/slide_out_view.h9
-rw-r--r--chromium/ui/views/controls/styled_label.cc3
-rw-r--r--chromium/ui/views/controls/styled_label_unittest.cc31
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc22
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc12
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc10
-rw-r--r--chromium/ui/views/controls/tree/tree_view.cc5
-rw-r--r--chromium/ui/views/controls/webview/webview.cc17
-rw-r--r--chromium/ui/views/controls/webview/webview.h3
-rw-r--r--chromium/ui/views/controls/webview/webview_unittest.cc40
-rw-r--r--chromium/ui/views/corewm/cursor_height_provider_win.cc4
-rw-r--r--chromium/ui/views/corewm/tooltip.h3
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.cc9
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.h4
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.cc11
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.h3
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc9
-rw-r--r--chromium/ui/views/corewm/tooltip_win.cc11
-rw-r--r--chromium/ui/views/corewm/tooltip_win.h3
-rw-r--r--chromium/ui/views/drag_utils.cc7
-rw-r--r--chromium/ui/views/event_monitor_mac.mm7
-rw-r--r--chromium/ui/views/examples/button_example.cc12
-rw-r--r--chromium/ui/views/examples/combobox_example.cc39
-rw-r--r--chromium/ui/views/examples/combobox_example.h4
-rw-r--r--chromium/ui/views/examples/examples.gyp13
-rw-r--r--chromium/ui/views/examples/examples_main.cc5
-rw-r--r--chromium/ui/views/examples/menu_example.cc12
-rw-r--r--chromium/ui/views/examples/multiline_example.cc2
-rw-r--r--chromium/ui/views/examples/widget_example.cc7
-rw-r--r--chromium/ui/views/layout/box_layout.cc2
-rw-r--r--chromium/ui/views/layout/layout_constants.h3
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.cc4
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.h4
-rw-r--r--chromium/ui/views/mouse_watcher_view_host.cc4
-rw-r--r--chromium/ui/views/mus/BUILD.gn33
-rw-r--r--chromium/ui/views/mus/DEPS6
-rw-r--r--chromium/ui/views/mus/aura_init.cc15
-rw-r--r--chromium/ui/views/mus/aura_init.h6
-rw-r--r--chromium/ui/views/mus/input_method_mus.cc2
-rw-r--r--chromium/ui/views/mus/native_widget_mus.cc317
-rw-r--r--chromium/ui/views/mus/native_widget_mus.h31
-rw-r--r--chromium/ui/views/mus/native_widget_mus_unittest.cc197
-rw-r--r--chromium/ui/views/mus/platform_test_helper_mus.cc93
-rw-r--r--chromium/ui/views/mus/platform_window_mus.cc64
-rw-r--r--chromium/ui/views/mus/platform_window_mus.h24
-rw-r--r--chromium/ui/views/mus/run_all_unittests_mus.cc9
-rw-r--r--chromium/ui/views/mus/screen_mus.cc237
-rw-r--r--chromium/ui/views/mus/screen_mus.h75
-rw-r--r--chromium/ui/views/mus/screen_mus_delegate.h23
-rw-r--r--chromium/ui/views/mus/surface_binding.cc35
-rw-r--r--chromium/ui/views/mus/surface_binding.h4
-rw-r--r--chromium/ui/views/mus/surface_context_factory.cc6
-rw-r--r--chromium/ui/views/mus/surface_context_factory.h4
-rw-r--r--chromium/ui/views/mus/window_manager_connection.cc144
-rw-r--r--chromium/ui/views/mus/window_manager_connection.h50
-rw-r--r--chromium/ui/views/mus/window_manager_constants_converters.cc20
-rw-r--r--chromium/ui/views/mus/window_manager_frame_values.h10
-rw-r--r--chromium/ui/views/mus/window_tree_host_mus.cc20
-rw-r--r--chromium/ui/views/mus/window_tree_host_mus.h24
-rw-r--r--chromium/ui/views/painter.cc47
-rw-r--r--chromium/ui/views/painter.h4
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/menu_radio_empty.pngbin334 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/menu_radio_selected.pngbin379 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/menu_radio_empty.pngbin681 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/menu_radio_selected.pngbin836 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/views_resources.grd2
-rw-r--r--chromium/ui/views/run_all_unittests.cc6
-rw-r--r--chromium/ui/views/run_all_unittests.h14
-rw-r--r--chromium/ui/views/run_all_unittests_main.cc9
-rw-r--r--chromium/ui/views/shadow_border.cc3
-rw-r--r--chromium/ui/views/style/mac/combobox_background_mac.cc57
-rw-r--r--chromium/ui/views/style/mac/combobox_background_mac.h37
-rw-r--r--chromium/ui/views/style/mac/dialog_button_border_mac.cc20
-rw-r--r--chromium/ui/views/style/platform_style.cc30
-rw-r--r--chromium/ui/views/style/platform_style.h19
-rw-r--r--chromium/ui/views/style/platform_style_mac.cc22
-rw-r--r--chromium/ui/views/style/platform_style_mac.mm59
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc8
-rw-r--r--chromium/ui/views/view.cc163
-rw-r--r--chromium/ui/views/view.h32
-rw-r--r--chromium/ui/views/view_targeter.cc8
-rw-r--r--chromium/ui/views/view_targeter_delegate.h12
-rw-r--r--chromium/ui/views/view_unittest.cc107
-rw-r--r--chromium/ui/views/views.gyp112
-rw-r--r--chromium/ui/views/views_unittests.isolate70
-rw-r--r--chromium/ui/views/widget/android/android_focus_rules.cc19
-rw-r--r--chromium/ui/views/widget/android/android_focus_rules.h28
-rw-r--r--chromium/ui/views/widget/android/native_widget_android.cc841
-rw-r--r--chromium/ui/views/widget/android/native_widget_android.h249
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc34
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h32
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc29
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc49
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_win.h6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc25
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc36
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h16
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc14
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h1
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc13
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_window_event_filter.cc3
-rw-r--r--chromium/ui/views/widget/desktop_widget_unittest.cc7
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc23
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h5
-rw-r--r--chromium/ui/views/widget/native_widget_aura_unittest.cc51
-rw-r--r--chromium/ui/views/widget/native_widget_delegate.h12
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h1
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm26
-rw-r--r--chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm81
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm424
-rw-r--r--chromium/ui/views/widget/native_widget_private.h1
-rw-r--r--chromium/ui/views/widget/tooltip_manager.h7
-rw-r--r--chromium/ui/views/widget/tooltip_manager_aura.cc10
-rw-r--r--chromium/ui/views/widget/tooltip_manager_aura.h3
-rw-r--r--chromium/ui/views/widget/widget.cc115
-rw-r--r--chromium/ui/views/widget/widget.h70
-rw-r--r--chromium/ui/views/widget/widget_delegate.cc14
-rw-r--r--chromium/ui/views/widget/widget_delegate.h2
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc139
-rw-r--r--chromium/ui/views/widget/widget_removals_observer.h6
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc421
-rw-r--r--chromium/ui/views/win/fullscreen_handler.cc58
-rw-r--r--chromium/ui/views/win/fullscreen_handler.h7
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc406
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h27
-rw-r--r--chromium/ui/views/win/hwnd_message_handler_delegate.h24
-rw-r--r--chromium/ui/views/win/windows_session_change_observer.cc1
-rw-r--r--chromium/ui/views/window/client_view.cc2
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc16
-rw-r--r--chromium/ui/views/window/custom_frame_view.h7
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc204
-rw-r--r--chromium/ui/views/window/dialog_client_view.h46
-rw-r--r--chromium/ui/views/window/dialog_client_view_unittest.cc191
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc42
-rw-r--r--chromium/ui/views/window/dialog_delegate.h19
-rw-r--r--chromium/ui/views/window/dialog_delegate_unittest.cc133
-rw-r--r--chromium/ui/views/window/frame_background.cc66
-rw-r--r--chromium/ui/views/window/frame_background.h20
-rw-r--r--chromium/ui/views/window/non_client_view.cc42
-rw-r--r--chromium/ui/views/window/non_client_view.h36
-rw-r--r--chromium/ui/views_content_client/views_content_browser_client.cc14
-rw-r--r--chromium/ui/views_content_client/views_content_browser_client.h8
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts_chromeos.cc27
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc3
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts_mac.mm4
-rw-r--r--chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp (renamed from chromium/ui/webui/resources/cr_elements/compiled_resources.gyp)4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_events/cr_events.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_events/cr_events.js2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js3
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js79
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources.gyp20
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp17
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html27
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js90
-rw-r--r--chromium/ui/webui/resources/cr_elements/demo_element.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/compiled_resources.gyp43
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/compiled_resources2.gyp48
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_icon.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_icon.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_list.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_list.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_select.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/network/cr_network_select.js3
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/compiled_resources.gyp81
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp44
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js2
-rw-r--r--chromium/ui/webui/resources/cr_elements_resources.grdp6
-rw-r--r--chromium/ui/webui/resources/css/bubble.css2
-rw-r--r--chromium/ui/webui/resources/css/dialogs.css12
-rw-r--r--chromium/ui/webui/resources/css/overlay.css12
-rw-r--r--chromium/ui/webui/resources/css/text_defaults.css10
-rw-r--r--chromium/ui/webui/resources/css/text_defaults_md.css10
-rw-r--r--chromium/ui/webui/resources/css/trash.css8
-rw-r--r--chromium/ui/webui/resources/css/tree.css6
-rw-r--r--chromium/ui/webui/resources/css/widgets.css2
-rw-r--r--chromium/ui/webui/resources/html/cr.html1
-rw-r--r--chromium/ui/webui/resources/html/polymer.html2
-rw-r--r--chromium/ui/webui/resources/html/polymer_config.html1
-rw-r--r--chromium/ui/webui/resources/html/promise_resolver.html1
-rw-r--r--chromium/ui/webui/resources/html/web_ui_listener_behavior.html2
-rw-r--r--chromium/ui/webui/resources/images/2x/otr_icon_standalone.pngbin2739 -> 0 bytes
-rw-r--r--chromium/ui/webui/resources/images/icon_bookmarks.svg4
-rw-r--r--chromium/ui/webui/resources/images/icon_extensions.svg4
-rw-r--r--chromium/ui/webui/resources/images/icon_history.svg4
-rw-r--r--chromium/ui/webui/resources/images/icon_passwords.svg3
-rw-r--r--chromium/ui/webui/resources/images/icon_tabs.svg6
-rw-r--r--chromium/ui/webui/resources/images/icon_themes.svg3
-rw-r--r--chromium/ui/webui/resources/images/otr_icon_standalone.pngbin1392 -> 0 bytes
-rw-r--r--chromium/ui/webui/resources/images/throbber_medium.svg8
-rw-r--r--chromium/ui/webui/resources/images/throbber_small.svg8
-rw-r--r--chromium/ui/webui/resources/js/action_link.js2
-rw-r--r--chromium/ui/webui/resources/js/assert.js8
-rw-r--r--chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp (renamed from chromium/ui/webui/resources/js/chromeos/compiled_resources.gyp)12
-rw-r--r--chromium/ui/webui/resources/js/compiled_resources.gyp39
-rw-r--r--chromium/ui/webui/resources/js/compiled_resources2.gyp47
-rw-r--r--chromium/ui/webui/resources/js/cr.js145
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/card_slider.js23
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/compiled_resources.gyp1
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/compiled_resources2.gyp57
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_grid.js6
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_row.js15
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/list_selection_model.js1
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/menu_item.js9
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/overlay.js7
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/page_manager/page_manager.js3
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/position_util.js7
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/splitter.js47
-rw-r--r--chromium/ui/webui/resources/js/event_tracker.js2
-rw-r--r--chromium/ui/webui/resources/js/i18n_behavior.js7
-rw-r--r--chromium/ui/webui/resources/js/promise_resolver.js35
-rw-r--r--chromium/ui/webui/resources/js/util.js62
-rw-r--r--chromium/ui/webui/resources/js/web_ui_listener_behavior.js43
-rw-r--r--chromium/ui/webui/resources/polymer_resources.grdp39
-rw-r--r--chromium/ui/webui/resources/webui_resources.grd16
-rw-r--r--chromium/ui/wm/BUILD.gn27
-rw-r--r--chromium/ui/wm/core/cursor_manager.cc9
-rw-r--r--chromium/ui/wm/core/cursor_manager.h6
-rw-r--r--chromium/ui/wm/core/cursor_manager_unittest.cc35
-rw-r--r--chromium/ui/wm/core/default_screen_position_client.cc9
-rw-r--r--chromium/ui/wm/core/image_grid.cc24
-rw-r--r--chromium/ui/wm/core/nested_accelerator_controller.cc59
-rw-r--r--chromium/ui/wm/core/nested_accelerator_controller.h47
-rw-r--r--chromium/ui/wm/core/nested_accelerator_controller_unittest.cc210
-rw-r--r--chromium/ui/wm/core/nested_accelerator_delegate.h34
-rw-r--r--chromium/ui/wm/core/nested_accelerator_dispatcher.cc21
-rw-r--r--chromium/ui/wm/core/nested_accelerator_dispatcher.h55
-rw-r--r--chromium/ui/wm/core/nested_accelerator_dispatcher_linux.cc104
-rw-r--r--chromium/ui/wm/core/nested_accelerator_dispatcher_win.cc76
-rw-r--r--chromium/ui/wm/core/shadow_unittest.cc6
-rw-r--r--chromium/ui/wm/public/dispatcher_client.cc52
-rw-r--r--chromium/ui/wm/public/dispatcher_client.h59
-rw-r--r--chromium/ui/wm/public/tooltip_client.h3
-rw-r--r--chromium/ui/wm/wm.gyp17
1207 files changed, 36737 insertions, 20504 deletions
diff --git a/chromium/ui/OWNERS b/chromium/ui/OWNERS
index b86b2dfb78c..79875b5f571 100644
--- a/chromium/ui/OWNERS
+++ b/chromium/ui/OWNERS
@@ -1,9 +1,10 @@
sadrul@chromium.org
sky@chromium.org
+thakis@chromium.org
# Mac stuff
avi@chromium.org
-thakis@chromium.org
+ccameron@chromium.org
per-file *.isolate=maruel@chromium.org
per-file *.isolate=tandrii@chromium.org
diff --git a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
index 696dc188347..fea9a515e8d 100644
--- a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
+++ b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.h
@@ -51,7 +51,7 @@ class AcceleratedWidgetMacNSView {
// in an NSView by setting the AcceleratedWidgetMacNSView for the helper.
class ACCELERATED_WIDGET_MAC_EXPORT AcceleratedWidgetMac {
public:
- explicit AcceleratedWidgetMac(bool needs_gl_finish_workaround);
+ AcceleratedWidgetMac();
virtual ~AcceleratedWidgetMac();
gfx::AcceleratedWidget accelerated_widget() { return native_widget_; }
@@ -113,10 +113,6 @@ class ACCELERATED_WIDGET_MAC_EXPORT AcceleratedWidgetMac {
// The size in DIP of the last swap received from |compositor_|.
gfx::Size last_swap_size_dip_;
- // Whether surfaces created by the widget should use the glFinish() workaround
- // after compositing.
- bool needs_gl_finish_workaround_;
-
DISALLOW_COPY_AND_ASSIGN(AcceleratedWidgetMac);
};
diff --git a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.mm b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.mm
index 135f64c2e4b..fc9269bd20f 100644
--- a/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.mm
+++ b/chromium/ui/accelerated_widget_mac/accelerated_widget_mac.mm
@@ -45,9 +45,7 @@ AcceleratedWidgetMac* GetHelperFromAcceleratedWidget(
////////////////////////////////////////////////////////////////////////////////
// AcceleratedWidgetMac
-AcceleratedWidgetMac::AcceleratedWidgetMac(bool needs_gl_finish_workaround)
- : view_(NULL),
- needs_gl_finish_workaround_(needs_gl_finish_workaround) {
+AcceleratedWidgetMac::AcceleratedWidgetMac() : view_(nullptr) {
// Disable the fade-in animation as the layers are added.
ScopedCAActionDisabler disabler;
diff --git a/chromium/ui/accelerated_widget_mac/display_link_mac.cc b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
index d9cc46876f9..72470f64b1e 100644
--- a/chromium/ui/accelerated_widget_mac/display_link_mac.cc
+++ b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
@@ -25,6 +25,20 @@ struct ScopedTypeRefTraits<CVDisplayLinkRef> {
} // namespace base
+namespace {
+
+// Empty callback set during tear down.
+CVReturn VoidDisplayLinkCallback(CVDisplayLinkRef display_link,
+ const CVTimeStamp* now,
+ const CVTimeStamp* output_time,
+ CVOptionFlags flags_in,
+ CVOptionFlags* flags_out,
+ void* context) {
+ return kCVReturnSuccess;
+}
+
+} // namespace
+
namespace ui {
// static
@@ -86,6 +100,14 @@ DisplayLinkMac::DisplayLinkMac(
DisplayLinkMac::~DisplayLinkMac() {
StopDisplayLink();
+ // Usually |display_link_| holds the last reference to CVDisplayLinkRef, but
+ // that's not guaranteed, so it might not free all resources after the
+ // destructor completes. Ensure the callback is cleared out regardless to
+ // avoid possible crashes (see http://crbug.com/564780).
+ CVReturn ret = CVDisplayLinkSetOutputCallback(
+ display_link_, VoidDisplayLinkCallback, nullptr);
+ DCHECK_EQ(kCGErrorSuccess, ret);
+
DisplayMap::iterator found = display_map_.Get().find(display_id_);
DCHECK(found != display_map_.Get().end());
DCHECK(found->second == this);
diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn
index 59f7eee48da..53d0801513c 100644
--- a/chromium/ui/accessibility/BUILD.gn
+++ b/chromium/ui/accessibility/BUILD.gn
@@ -50,6 +50,8 @@ component("accessibility") {
"ax_text_utils.h",
"ax_tree.cc",
"ax_tree.h",
+ "ax_tree_combiner.cc",
+ "ax_tree_combiner.h",
"ax_tree_data.cc",
"ax_tree_data.h",
"ax_tree_serializer.cc",
@@ -74,6 +76,7 @@ component("accessibility") {
public_deps = [
":ax_gen",
"//base",
+ "//base:i18n",
"//ui/base",
"//ui/gfx",
"//ui/gfx/geometry",
@@ -126,19 +129,11 @@ source_set("test_support") {
]
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("accessibility_unittests_run") {
- testonly = true
- deps = [
- ":accessibility_unittests",
- ]
-}
-
test("accessibility_unittests") {
sources = [
"ax_generated_tree_unittest.cc",
"ax_text_utils_unittest.cc",
+ "ax_tree_combiner_unittest.cc",
"ax_tree_serializer_unittest.cc",
"ax_tree_unittest.cc",
"platform/ax_platform_node_win_unittest.cc",
@@ -149,6 +144,7 @@ test("accessibility_unittests") {
":test_support",
"//base",
"//base/test:run_all_unittests",
+ "//skia",
"//testing/gtest",
"//ui/base",
"//ui/gfx",
diff --git a/chromium/ui/accessibility/accessibility.gyp b/chromium/ui/accessibility/accessibility.gyp
index f32ca767d3f..5489aa13fac 100644
--- a/chromium/ui/accessibility/accessibility.gyp
+++ b/chromium/ui/accessibility/accessibility.gyp
@@ -17,6 +17,8 @@
'hard_dependency': 1,
'dependencies': [
'../../base/base.gyp:base',
+ '../../base/base.gyp:base_i18n',
+ '../../skia/skia.gyp:skia',
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_geometry',
'ax_gen',
@@ -36,6 +38,8 @@
'ax_text_utils.h',
'ax_tree.cc',
'ax_tree.h',
+ 'ax_tree_combiner.cc',
+ 'ax_tree_combiner.h',
'ax_tree_data.cc',
'ax_tree_data.h',
'ax_tree_serializer.cc',
@@ -116,6 +120,7 @@
'dependencies': [
'../../base/base.gyp:base',
'../../base/base.gyp:run_all_unittests',
+ '../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_geometry',
@@ -126,6 +131,7 @@
'sources': [
'ax_generated_tree_unittest.cc',
'ax_text_utils_unittest.cc',
+ 'ax_tree_combiner_unittest.cc',
'ax_tree_serializer_unittest.cc',
'ax_tree_unittest.cc',
'platform/ax_platform_node_win_unittest.cc'
@@ -200,6 +206,7 @@
'variables': {
'java_in_dir': '<(DEPTH)/build/android/empty',
'has_java_resources': 0,
+ 'never_lint': 1,
},
'dependencies': [
'ax_enumerations_java',
diff --git a/chromium/ui/accessibility/ax_enums.idl b/chromium/ui/accessibility/ax_enums.idl
index 4bb7d9f9b10..be08a8a36d9 100644
--- a/chromium/ui/accessibility/ax_enums.idl
+++ b/chromium/ui/accessibility/ax_enums.idl
@@ -30,6 +30,7 @@
blur, // Remove: http://crbug.com/392502
checked_state_changed, // Implicit
children_changed,
+ clicked,
document_selection_changed,
focus,
hide, // Remove: http://crbug.com/392502
@@ -64,6 +65,7 @@
};
enum AXRole {
+ abbr,
alert_dialog,
alert,
annotation,
@@ -74,7 +76,7 @@
// TODO(nektar): Remove busy_indicator because it's used nowhere.
busy_indicator,
button,
- button_drop_down,
+ button_drop_down, // Not used on Web.
canvas,
caption,
cell,
@@ -130,6 +132,7 @@
mark,
marquee,
math,
+ menu,
menu_bar,
menu_button,
menu_item,
@@ -137,7 +140,6 @@
menu_item_radio,
menu_list_option,
menu_list_popup,
- menu,
meter,
navigation,
note,
@@ -204,7 +206,6 @@
enabled, // content only
expanded,
focusable,
- focused,
haspopup,
horizontal,
hovered,
@@ -235,14 +236,18 @@
[cpp_enum_prefix_override="ax_attr"] enum AXStringAttribute {
access_key,
action,
+ // Only used when invalid_state == invalid_state_other.
+ aria_invalid_value,
auto_complete,
container_live_relevant,
container_live_status,
description,
display,
+ // Only present when different from parent.
+ font_family,
html_tag,
- // Only used when invalid_state == invalid_state_other.
- aria_invalid_value,
+ // Only present when different from parent.
+ language,
name,
live_relevant,
live_status,
diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc
index fe1b3db56cb..e199f0190f8 100644
--- a/chromium/ui/accessibility/ax_node_data.cc
+++ b/chromium/ui/accessibility/ax_node_data.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "ui/gfx/transform.h"
using base::DoubleToString;
using base::IntToString;
@@ -65,6 +66,39 @@ AXNodeData::AXNodeData()
AXNodeData::~AXNodeData() {
}
+AXNodeData::AXNodeData(const AXNodeData& other) {
+ id = other.id;
+ role = other.role;
+ state = other.state;
+ string_attributes = other.string_attributes;
+ int_attributes = other.int_attributes;
+ float_attributes = other.float_attributes;
+ bool_attributes = other.bool_attributes;
+ intlist_attributes = other.intlist_attributes;
+ html_attributes = other.html_attributes;
+ child_ids = other.child_ids;
+ location = other.location;
+ if (other.transform)
+ transform.reset(new gfx::Transform(*other.transform));
+}
+
+AXNodeData& AXNodeData::operator=(AXNodeData other) {
+ id = other.id;
+ role = other.role;
+ state = other.state;
+ string_attributes = other.string_attributes;
+ int_attributes = other.int_attributes;
+ float_attributes = other.float_attributes;
+ bool_attributes = other.bool_attributes;
+ intlist_attributes = other.intlist_attributes;
+ html_attributes = other.html_attributes;
+ child_ids = other.child_ids;
+ location = other.location;
+ if (other.transform)
+ transform.reset(new gfx::Transform(*other.transform));
+ return *this;
+}
+
bool AXNodeData::HasBoolAttribute(AXBoolAttribute attribute) const {
auto iter = FindInVectorOfPairs(attribute, bool_attributes);
return iter != bool_attributes.end();
@@ -273,8 +307,6 @@ std::string AXNodeData::ToString() const {
result += " EXPANDED";
if (state & (1 << AX_STATE_FOCUSABLE))
result += " FOCUSABLE";
- if (state & (1 << AX_STATE_FOCUSED))
- result += " FOCUSED";
if (state & (1 << AX_STATE_HASPOPUP))
result += " HASPOPUP";
if (state & (1 << AX_STATE_HOVERED))
@@ -311,6 +343,9 @@ std::string AXNodeData::ToString() const {
IntToString(location.width()) + ", " +
IntToString(location.height()) + ")";
+ if (transform && !transform->IsIdentity())
+ result += " transform=" + transform->ToString();
+
for (size_t i = 0; i < int_attributes.size(); ++i) {
std::string value = IntToString(int_attributes[i].second);
switch (int_attributes[i].first) {
@@ -486,6 +521,9 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_ACTION:
result += " action=" + value;
break;
+ case AX_ATTR_ARIA_INVALID_VALUE:
+ result += " aria_invalid_value=" + value;
+ break;
case AX_ATTR_AUTO_COMPLETE:
result += " autocomplete=" + value;
break;
@@ -495,11 +533,14 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_DISPLAY:
result += " display=" + value;
break;
+ case AX_ATTR_FONT_FAMILY:
+ result += " font-family=" + value;
+ break;
case AX_ATTR_HTML_TAG:
result += " html_tag=" + value;
break;
- case AX_ATTR_ARIA_INVALID_VALUE:
- result += " aria_invalid_value=" + value;
+ case AX_ATTR_LANGUAGE:
+ result += " language=" + value;
break;
case AX_ATTR_LIVE_RELEVANT:
result += " relevant=" + value;
diff --git a/chromium/ui/accessibility/ax_node_data.h b/chromium/ui/accessibility/ax_node_data.h
index 5bb8c147ff5..067adaa3e93 100644
--- a/chromium/ui/accessibility/ax_node_data.h
+++ b/chromium/ui/accessibility/ax_node_data.h
@@ -11,12 +11,17 @@
#include <string>
#include <vector>
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_export.h"
#include "ui/gfx/geometry/rect.h"
+namespace gfx {
+class Transform;
+};
+
namespace ui {
// A compact representation of the accessibility information for a
@@ -26,6 +31,9 @@ struct AX_EXPORT AXNodeData {
AXNodeData();
virtual ~AXNodeData();
+ AXNodeData(const AXNodeData& other);
+ AXNodeData& operator=(AXNodeData other);
+
// Accessing accessibility attributes:
//
// There are dozens of possible attributes for an accessibility node,
@@ -94,12 +102,11 @@ struct AX_EXPORT AXNodeData {
bool IsRoot() const;
void SetRoot();
- // This is a simple serializable struct. All member variables should be
- // public and copyable.
+ // As much as possible this should behave as a simple, serializable,
+ // copyable struct.
int32_t id;
AXRole role;
uint32_t state;
- gfx::Rect location;
std::vector<std::pair<AXStringAttribute, std::string> > string_attributes;
std::vector<std::pair<AXIntAttribute, int32_t>> int_attributes;
std::vector<std::pair<AXFloatAttribute, float> > float_attributes;
@@ -108,6 +115,16 @@ struct AX_EXPORT AXNodeData {
intlist_attributes;
base::StringPairs html_attributes;
std::vector<int32_t> child_ids;
+
+ // The object's location relative to its window or frame.
+ gfx::Rect location;
+
+ // An additional transform to apply to position this object and its subtree.
+ // NOTE: this member is a scoped_ptr because it's rare and gfx::Transform
+ // takes up a fair amount of space. The assignment operator and copy
+ // constructor both make a duplicate of the owned pointer, so it acts more
+ // like a member than a pointer.
+ scoped_ptr<gfx::Transform> transform;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_text_utils.cc b/chromium/ui/accessibility/ax_text_utils.cc
index 1e68559027e..698e53b9613 100644
--- a/chromium/ui/accessibility/ax_text_utils.cc
+++ b/chromium/ui/accessibility/ax_text_utils.cc
@@ -4,6 +4,7 @@
#include "ui/accessibility/ax_text_utils.h"
+#include "base/i18n/break_iterator.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
@@ -25,7 +26,16 @@ size_t FindAccessibleTextBoundary(const base::string16& text,
return start_offset + 1;
else
return start_offset;
- } else if (boundary == LINE_BOUNDARY) {
+ }
+
+ base::i18n::BreakIterator word_iter(text,
+ base::i18n::BreakIterator::BREAK_WORD);
+ if (boundary == WORD_BOUNDARY) {
+ if (!word_iter.Init())
+ return start_offset;
+ }
+
+ if (boundary == LINE_BOUNDARY) {
if (direction == FORWARDS_DIRECTION) {
for (size_t j = 0; j < line_breaks.size(); ++j) {
size_t line_break = line_breaks[j] >= 0 ? line_breaks[j] : 0;
@@ -62,8 +72,12 @@ size_t FindAccessibleTextBoundary(const base::string16& text,
NOTREACHED(); // These are handled above.
break;
case WORD_BOUNDARY:
- if (base::IsUnicodeWhitespace(text[pos]))
- return result;
+ if (word_iter.IsStartOfWord(result)) {
+ // If we are searching forward and we are still at the start offset,
+ // we need to find the next word.
+ if (direction == BACKWARDS_DIRECTION || result != start_offset)
+ return result;
+ }
break;
case PARAGRAPH_BOUNDARY:
if (text[pos] == '\n')
@@ -89,4 +103,4 @@ size_t FindAccessibleTextBoundary(const base::string16& text,
}
}
-} // Namespace ui
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_text_utils_unittest.cc b/chromium/ui/accessibility/ax_text_utils_unittest.cc
index 1c2a4a1e4e1..2c7f491d619 100644
--- a/chromium/ui/accessibility/ax_text_utils_unittest.cc
+++ b/chromium/ui/accessibility/ax_text_utils_unittest.cc
@@ -10,6 +10,49 @@
namespace ui {
+TEST(AXTextUtils, FindAccessibleTextBoundaryWord) {
+ const base::string16 text =
+ base::UTF8ToUTF16("Hello there.This/is\ntesting.");
+ const size_t text_length = text.length();
+ std::vector<int> line_start_offsets;
+ line_start_offsets.push_back(19);
+ size_t result;
+
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 0, FORWARDS_DIRECTION);
+ EXPECT_EQ(6UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 5, BACKWARDS_DIRECTION);
+ EXPECT_EQ(0UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 6, FORWARDS_DIRECTION);
+ EXPECT_EQ(12UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 11, BACKWARDS_DIRECTION);
+ EXPECT_EQ(6UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 12, BACKWARDS_DIRECTION);
+ EXPECT_EQ(12UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 15, FORWARDS_DIRECTION);
+ EXPECT_EQ(17UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 15, BACKWARDS_DIRECTION);
+ EXPECT_EQ(12UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 16, FORWARDS_DIRECTION);
+ EXPECT_EQ(17UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 17, FORWARDS_DIRECTION);
+ EXPECT_EQ(20UL, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ 20, FORWARDS_DIRECTION);
+ EXPECT_EQ(text_length, result);
+ result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
+ text_length, BACKWARDS_DIRECTION);
+ EXPECT_EQ(20UL, result);
+}
+
TEST(AXTextUtils, FindAccessibleTextBoundaryLine) {
const base::string16 text = base::UTF8ToUTF16("Line 1.\nLine 2\n\t");
const size_t text_length = text.length();
@@ -18,7 +61,6 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryLine) {
line_start_offsets.push_back(15);
size_t result;
-
// Basic cases.
result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
5, FORWARDS_DIRECTION);
@@ -30,9 +72,7 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryLine) {
10, FORWARDS_DIRECTION);
EXPECT_EQ(15UL, result);
-
// Edge cases.
-
result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
text_length, BACKWARDS_DIRECTION);
EXPECT_EQ(15UL, result);
@@ -68,4 +108,4 @@ TEST(AXTextUtils, FindAccessibleTextBoundaryLine) {
EXPECT_EQ(text_length, result);
}
-} // Namespace ui.
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree.cc b/chromium/ui/accessibility/ax_tree.cc
index bd879eaac44..6282fb75c10 100644
--- a/chromium/ui/accessibility/ax_tree.cc
+++ b/chromium/ui/accessibility/ax_tree.cc
@@ -180,6 +180,8 @@ bool AXTree::UpdateNode(const AXNodeData& src,
AXNode* node = GetFromId(src.id);
if (node) {
update_state->pending_nodes.erase(node);
+ if (delegate_)
+ delegate_->OnNodeDataWillChange(this, node->data(), src);
node->SetData(src);
} else {
if (src.role != AX_ROLE_ROOT_WEB_AREA &&
diff --git a/chromium/ui/accessibility/ax_tree.h b/chromium/ui/accessibility/ax_tree.h
index 62b0709fc35..888170749a4 100644
--- a/chromium/ui/accessibility/ax_tree.h
+++ b/chromium/ui/accessibility/ax_tree.h
@@ -41,6 +41,11 @@ class AX_EXPORT AXTreeDelegate {
AXTreeDelegate();
virtual ~AXTreeDelegate();
+ // Called before a node's data gets updated.
+ virtual void OnNodeDataWillChange(AXTree* tree,
+ const AXNodeData& old_node_data,
+ const AXNodeData& new_node_data) = 0;
+
// Called when tree data changes.
virtual void OnTreeDataChanged(AXTree* tree) = 0;
diff --git a/chromium/ui/accessibility/ax_tree_combiner.cc b/chromium/ui/accessibility/ax_tree_combiner.cc
new file mode 100644
index 00000000000..56f7cacd1cb
--- /dev/null
+++ b/chromium/ui/accessibility/ax_tree_combiner.cc
@@ -0,0 +1,238 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_tree_combiner.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace ui {
+namespace {
+
+// Return true if |attr| is a node ID that would need to be mapped when
+// renumbering the ids in a combined tree.
+bool IsNodeIdIntAttribute(AXIntAttribute attr) {
+ switch (attr) {
+ case AX_ATTR_ACTIVEDESCENDANT_ID:
+ case AX_ATTR_TABLE_HEADER_ID:
+ case AX_ATTR_TABLE_COLUMN_HEADER_ID:
+ case AX_ATTR_TABLE_ROW_HEADER_ID:
+ return true;
+
+ // Note: all of the attributes are included here explicitly,
+ // rather than using "default:", so that it's a compiler error to
+ // add a new attribute without explicitly considering whether it's
+ // a node id attribute or not.
+ case AX_INT_ATTRIBUTE_NONE:
+ case AX_ATTR_SCROLL_X:
+ case AX_ATTR_SCROLL_X_MIN:
+ case AX_ATTR_SCROLL_X_MAX:
+ case AX_ATTR_SCROLL_Y:
+ case AX_ATTR_SCROLL_Y_MIN:
+ case AX_ATTR_SCROLL_Y_MAX:
+ case AX_ATTR_TEXT_SEL_START:
+ case AX_ATTR_TEXT_SEL_END:
+ case AX_ATTR_TABLE_ROW_COUNT:
+ case AX_ATTR_TABLE_COLUMN_COUNT:
+ case AX_ATTR_TABLE_ROW_INDEX:
+ case AX_ATTR_TABLE_COLUMN_INDEX:
+ case AX_ATTR_TABLE_CELL_COLUMN_INDEX:
+ case AX_ATTR_TABLE_CELL_COLUMN_SPAN:
+ case AX_ATTR_TABLE_CELL_ROW_INDEX:
+ case AX_ATTR_TABLE_CELL_ROW_SPAN:
+ case AX_ATTR_SORT_DIRECTION:
+ case AX_ATTR_HIERARCHICAL_LEVEL:
+ case AX_ATTR_NAME_FROM:
+ case AX_ATTR_DESCRIPTION_FROM:
+ case AX_ATTR_CHILD_TREE_ID:
+ case AX_ATTR_SET_SIZE:
+ case AX_ATTR_POS_IN_SET:
+ case AX_ATTR_COLOR_VALUE:
+ case AX_ATTR_BACKGROUND_COLOR:
+ case AX_ATTR_COLOR:
+ case AX_ATTR_INVALID_STATE:
+ case AX_ATTR_TEXT_DIRECTION:
+ case AX_ATTR_TEXT_STYLE:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// Return true if |attr| contains a vector of node ids that would need
+// to be mapped when renumbering the ids in a combined tree.
+bool IsNodeIdIntListAttribute(AXIntListAttribute attr) {
+ switch (attr) {
+ case AX_ATTR_CELL_IDS:
+ case AX_ATTR_CONTROLS_IDS:
+ case AX_ATTR_DESCRIBEDBY_IDS:
+ case AX_ATTR_FLOWTO_IDS:
+ case AX_ATTR_INDIRECT_CHILD_IDS:
+ case AX_ATTR_LABELLEDBY_IDS:
+ case AX_ATTR_UNIQUE_CELL_IDS:
+ return true;
+
+ // Note: all of the attributes are included here explicitly,
+ // rather than using "default:", so that it's a compiler error to
+ // add a new attribute without explicitly considering whether it's
+ // a node id attribute or not.
+ case AX_INT_LIST_ATTRIBUTE_NONE:
+ case AX_ATTR_LINE_BREAKS:
+ case AX_ATTR_CHARACTER_OFFSETS:
+ case AX_ATTR_WORD_STARTS:
+ case AX_ATTR_WORD_ENDS:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+} // namespace
+
+AXTreeCombiner::AXTreeCombiner() {
+}
+
+AXTreeCombiner::~AXTreeCombiner() {
+}
+
+void AXTreeCombiner::AddTree(const AXTreeUpdate& tree, bool is_root) {
+ trees_.push_back(tree);
+ if (is_root) {
+ DCHECK_EQ(root_tree_id_, -1);
+ root_tree_id_ = tree.tree_data.tree_id;
+ }
+}
+
+bool AXTreeCombiner::Combine() {
+ // First create a map from tree ID to tree update.
+ for (const auto& tree : trees_) {
+ int32_t tree_id = tree.tree_data.tree_id;
+ if (tree_id_map_.find(tree_id) != tree_id_map_.end())
+ return false;
+ tree_id_map_[tree.tree_data.tree_id] = &tree;
+ }
+
+ // Make sure the root tree ID is in the map, otherwise fail.
+ if (tree_id_map_.find(root_tree_id_) == tree_id_map_.end())
+ return false;
+
+ // Process the nodes recursively, starting with the root tree.
+ const AXTreeUpdate* root = tree_id_map_.find(root_tree_id_)->second;
+ ProcessTree(root);
+
+ // Finally, handle the tree ID, taking into account which subtree might
+ // have focus and mapping IDs from the tree data appropriately.
+ combined_.has_tree_data = true;
+ combined_.tree_data = root->tree_data;
+ int32_t focused_tree_id = root->tree_data.focused_tree_id;
+ const AXTreeUpdate* focused_tree = root;
+ if (tree_id_map_.find(focused_tree_id) != tree_id_map_.end())
+ focused_tree = tree_id_map_[focused_tree_id];
+ combined_.tree_data.focus_id =
+ MapId(focused_tree_id, focused_tree->tree_data.focus_id);
+ combined_.tree_data.sel_anchor_object_id =
+ MapId(focused_tree_id, focused_tree->tree_data.sel_anchor_object_id);
+ combined_.tree_data.sel_focus_object_id =
+ MapId(focused_tree_id, focused_tree->tree_data.sel_focus_object_id);
+ combined_.tree_data.sel_anchor_offset =
+ focused_tree->tree_data.sel_anchor_offset;
+ combined_.tree_data.sel_focus_offset =
+ focused_tree->tree_data.sel_focus_offset;
+
+ // Debug-mode check that the resulting combined tree is valid.
+ AXTree tree;
+ DCHECK(tree.Unserialize(combined_))
+ << combined_.ToString() << "\n" << tree.error();
+
+ return true;
+}
+
+int32_t AXTreeCombiner::MapId(int32_t tree_id, int32_t node_id) {
+ auto tree_id_node_id = std::make_pair(tree_id, node_id);
+ if (tree_id_node_id_map_[tree_id_node_id] == 0)
+ tree_id_node_id_map_[tree_id_node_id] = next_id_++;
+ return tree_id_node_id_map_[tree_id_node_id];
+}
+
+void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
+ // The root of each tree may contain a transform that needs to apply
+ // to all of its descendants.
+ gfx::Transform old_transform = transform_;
+ if (!tree->nodes.empty() && tree->nodes[0].transform)
+ transform_.ConcatTransform(*tree->nodes[0].transform);
+
+ int32_t tree_id = tree->tree_data.tree_id;
+ for (size_t i = 0; i < tree->nodes.size(); ++i) {
+ AXNodeData node = tree->nodes[i];
+ int32_t child_tree_id = node.GetIntAttribute(AX_ATTR_CHILD_TREE_ID);
+
+ // It's not valid to have an accessibility tree with more than one
+ // ROOT_WEB_AREA role, so change subdocuments into just groups.
+ if (node.role == AX_ROLE_ROOT_WEB_AREA && tree_id != root_tree_id_)
+ node.role = AX_ROLE_GROUP;
+
+ // Map the node's ID.
+ node.id = MapId(tree_id, node.id);
+
+ // Map the node's child IDs.
+ for (size_t j = 0; j < node.child_ids.size(); ++j)
+ node.child_ids[j] = MapId(tree_id, node.child_ids[j]);
+
+ // Map other int attributes that refer to node IDs, and remove the
+ // AX_ATTR_CHILD_TREE_ID attribute.
+ for (size_t j = 0; j < node.int_attributes.size(); ++j) {
+ auto& attr = node.int_attributes[j];
+ if (IsNodeIdIntAttribute(attr.first))
+ attr.second = MapId(tree_id, attr.second);
+ if (attr.first == AX_ATTR_CHILD_TREE_ID) {
+ attr.first = AX_INT_ATTRIBUTE_NONE;
+ attr.second = 0;
+ }
+ }
+
+ // Map other int list attributes that refer to node IDs.
+ for (size_t j = 0; j < node.intlist_attributes.size(); ++j) {
+ auto& attr = node.intlist_attributes[j];
+ if (IsNodeIdIntListAttribute(attr.first)) {
+ for (size_t k = 0; k < attr.second.size(); k++)
+ attr.second[k] = MapId(tree_id, attr.second[k]);
+ }
+ }
+
+ // Apply the transformation to the object's bounds to put it in
+ // the coordinate space of the root frame.
+ gfx::RectF boundsf(node.location);
+ transform_.TransformRect(&boundsf);
+ node.location = gfx::Rect(boundsf.x(), boundsf.y(),
+ boundsf.width(), boundsf.height());
+
+ // See if this node has a child tree. As a sanity check make sure the
+ // child tree lists this tree as its parent tree id.
+ const AXTreeUpdate* child_tree = nullptr;
+ if (tree_id_map_.find(child_tree_id) != tree_id_map_.end()) {
+ child_tree = tree_id_map_.find(child_tree_id)->second;
+ if (child_tree->tree_data.parent_tree_id != tree_id)
+ child_tree = nullptr;
+ if (child_tree && child_tree->nodes.empty())
+ child_tree = nullptr;
+ if (child_tree) {
+ node.child_ids.push_back(MapId(child_tree_id,
+ child_tree->nodes[0].id));
+ }
+ }
+
+ // Put the rewritten AXNodeData into the output data structure.
+ combined_.nodes.push_back(node);
+
+ // Recurse into the child tree now, if any.
+ if (child_tree)
+ ProcessTree(child_tree);
+ }
+
+ // Reset the transform.
+ transform_ = old_transform;
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_combiner.h b/chromium/ui/accessibility/ax_tree_combiner.h
new file mode 100644
index 00000000000..37b9fa56879
--- /dev/null
+++ b/chromium/ui/accessibility/ax_tree_combiner.h
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ACCESSIBILITY_AX_TREE_COMBINER_H_
+#define UI_ACCESSIBILITY_AX_TREE_COMBINER_H_
+
+#include <vector>
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_update.h"
+#include "ui/gfx/transform.h"
+
+namespace ui {
+
+// This helper class takes multiple accessibility trees that reference each
+// other via tree IDs, and combines them into a single accessibility tree
+// that spans all of them.
+//
+// Since node IDs are relative to each ID, it has to renumber all of the IDs
+// and update all of the attributes that reference IDs of other nodes to
+// ensure they point to the right node. It also applies transformations to
+// local bounding rectangles to make them global.
+//
+// It also makes sure the final combined tree points to the correct focused
+// node across all of the trees based on the focused tree ID of the root tree.
+class AX_EXPORT AXTreeCombiner {
+ public:
+ AXTreeCombiner();
+ ~AXTreeCombiner();
+
+ void AddTree(const AXTreeUpdate& tree, bool is_root);
+ bool Combine();
+
+ const AXTreeUpdate& combined() { return combined_; }
+
+ private:
+ int32_t MapId(int32_t tree_id, int32_t node_id);
+
+ void ProcessTree(const AXTreeUpdate* tree);
+
+ std::vector<ui::AXTreeUpdate> trees_;
+ int32_t root_tree_id_ = -1;
+ int32_t next_id_ = 1;
+ std::map<int32_t, const AXTreeUpdate*> tree_id_map_;
+ std::map<std::pair<int32_t, int32_t>, int32_t> tree_id_node_id_map_;
+ AXTreeUpdate combined_;
+ gfx::Transform transform_;
+};
+
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_TREE_COMBINER_H_
diff --git a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
new file mode 100644
index 00000000000..0d4e6980b16
--- /dev/null
+++ b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -0,0 +1,244 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_tree_combiner.h"
+
+namespace ui {
+
+TEST(CombineAXTreesTest, RenumberOneTree) {
+ AXTreeUpdate tree;
+ tree.has_tree_data = true;
+ tree.tree_data.tree_id = 1;
+ tree.nodes.resize(3);
+ tree.nodes[0].id = 2;
+ tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ tree.nodes[0].child_ids.push_back(4);
+ tree.nodes[0].child_ids.push_back(6);
+ tree.nodes[1].id = 4;
+ tree.nodes[2].id = 6;
+
+ AXTreeCombiner combiner;
+ combiner.AddTree(tree, true);
+ combiner.Combine();
+
+ const AXTreeUpdate& combined = combiner.combined();
+
+ ASSERT_EQ(3U, combined.nodes.size());
+ EXPECT_EQ(1, combined.nodes[0].id);
+ ASSERT_EQ(2U, combined.nodes[0].child_ids.size());
+ EXPECT_EQ(2, combined.nodes[0].child_ids[0]);
+ EXPECT_EQ(3, combined.nodes[0].child_ids[1]);
+ EXPECT_EQ(2, combined.nodes[1].id);
+ EXPECT_EQ(3, combined.nodes[2].id);
+}
+
+TEST(CombineAXTreesTest, EmbedChildTree) {
+ AXTreeUpdate parent_tree;
+ parent_tree.has_tree_data = true;
+ parent_tree.tree_data.tree_id = 1;
+ parent_tree.nodes.resize(3);
+ parent_tree.nodes[0].id = 1;
+ parent_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ parent_tree.nodes[0].child_ids.push_back(2);
+ parent_tree.nodes[0].child_ids.push_back(3);
+ parent_tree.nodes[1].id = 2;
+ parent_tree.nodes[1].role = AX_ROLE_BUTTON;
+ parent_tree.nodes[2].id = 3;
+ parent_tree.nodes[2].role = AX_ROLE_IFRAME;
+ parent_tree.nodes[2].AddIntAttribute(AX_ATTR_CHILD_TREE_ID, 2);
+
+ AXTreeUpdate child_tree;
+ child_tree.has_tree_data = true;
+ child_tree.tree_data.parent_tree_id = 1;
+ child_tree.tree_data.tree_id = 2;
+ child_tree.nodes.resize(3);
+ child_tree.nodes[0].id = 1;
+ child_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ child_tree.nodes[0].child_ids.push_back(2);
+ child_tree.nodes[0].child_ids.push_back(3);
+ child_tree.nodes[1].id = 2;
+ child_tree.nodes[1].role = AX_ROLE_CHECK_BOX;
+ child_tree.nodes[2].id = 3;
+ child_tree.nodes[2].role = AX_ROLE_RADIO_BUTTON;
+
+ AXTreeCombiner combiner;
+ combiner.AddTree(parent_tree, true);
+ combiner.AddTree(child_tree, false);
+ combiner.Combine();
+
+ const AXTreeUpdate& combined = combiner.combined();
+
+ ASSERT_EQ(6U, combined.nodes.size());
+ EXPECT_EQ(1, combined.nodes[0].id);
+ ASSERT_EQ(2U, combined.nodes[0].child_ids.size());
+ EXPECT_EQ(2, combined.nodes[0].child_ids[0]);
+ EXPECT_EQ(3, combined.nodes[0].child_ids[1]);
+ EXPECT_EQ(2, combined.nodes[1].id);
+ EXPECT_EQ(AX_ROLE_BUTTON, combined.nodes[1].role);
+ EXPECT_EQ(3, combined.nodes[2].id);
+ EXPECT_EQ(AX_ROLE_IFRAME, combined.nodes[2].role);
+ EXPECT_EQ(1U, combined.nodes[2].child_ids.size());
+ EXPECT_EQ(4, combined.nodes[2].child_ids[0]);
+ EXPECT_EQ(4, combined.nodes[3].id);
+ EXPECT_EQ(AX_ROLE_GROUP, combined.nodes[3].role);
+ EXPECT_EQ(5, combined.nodes[4].id);
+ EXPECT_EQ(AX_ROLE_CHECK_BOX, combined.nodes[4].role);
+ EXPECT_EQ(6, combined.nodes[5].id);
+ EXPECT_EQ(AX_ROLE_RADIO_BUTTON, combined.nodes[5].role);
+}
+
+TEST(CombineAXTreesTest, MapAllIdAttributes) {
+ // This is a nonsensical accessibility tree, the goal is to make sure
+ // that all attributes that reference IDs of other nodes are remapped.
+
+ AXTreeUpdate tree;
+ tree.has_tree_data = true;
+ tree.tree_data.tree_id = 1;
+ tree.nodes.resize(2);
+ tree.nodes[0].id = 11;
+ tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ tree.nodes[0].child_ids.push_back(22);
+ tree.nodes[0].AddIntAttribute(AX_ATTR_TABLE_HEADER_ID, 22);
+ tree.nodes[0].AddIntAttribute(AX_ATTR_TABLE_ROW_HEADER_ID, 22);
+ tree.nodes[0].AddIntAttribute(AX_ATTR_TABLE_COLUMN_HEADER_ID, 22);
+ tree.nodes[0].AddIntAttribute(AX_ATTR_ACTIVEDESCENDANT_ID, 22);
+ std::vector<int32_t> ids { 22 };
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_INDIRECT_CHILD_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_CONTROLS_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_DESCRIBEDBY_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_FLOWTO_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_LABELLEDBY_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_CELL_IDS, ids);
+ tree.nodes[0].AddIntListAttribute(AX_ATTR_UNIQUE_CELL_IDS, ids);
+ tree.nodes[1].id = 22;
+
+ AXTreeCombiner combiner;
+ combiner.AddTree(tree, true);
+ combiner.Combine();
+
+ const AXTreeUpdate& combined = combiner.combined();
+
+ ASSERT_EQ(2U, combined.nodes.size());
+ EXPECT_EQ(1, combined.nodes[0].id);
+ ASSERT_EQ(1U, combined.nodes[0].child_ids.size());
+ EXPECT_EQ(2, combined.nodes[0].child_ids[0]);
+ EXPECT_EQ(2, combined.nodes[1].id);
+
+ EXPECT_EQ(2, combined.nodes[0].GetIntAttribute(AX_ATTR_TABLE_HEADER_ID));
+ EXPECT_EQ(2, combined.nodes[0].GetIntAttribute(AX_ATTR_TABLE_ROW_HEADER_ID));
+ EXPECT_EQ(2, combined.nodes[0].GetIntAttribute(
+ AX_ATTR_TABLE_COLUMN_HEADER_ID));
+ EXPECT_EQ(2, combined.nodes[0].GetIntAttribute(AX_ATTR_ACTIVEDESCENDANT_ID));
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_INDIRECT_CHILD_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_CONTROLS_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_DESCRIBEDBY_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_FLOWTO_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_LABELLEDBY_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_CELL_IDS)[0]);
+ EXPECT_EQ(2, combined.nodes[0].GetIntListAttribute(
+ AX_ATTR_UNIQUE_CELL_IDS)[0]);
+}
+
+TEST(CombineAXTreesTest, Coordinates) {
+ AXTreeUpdate parent_tree;
+ parent_tree.has_tree_data = true;
+ parent_tree.tree_data.tree_id = 1;
+ parent_tree.nodes.resize(3);
+ parent_tree.nodes[0].id = 1;
+ parent_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ parent_tree.nodes[0].child_ids.push_back(2);
+ parent_tree.nodes[0].child_ids.push_back(3);
+ parent_tree.nodes[1].id = 2;
+ parent_tree.nodes[1].role = AX_ROLE_BUTTON;
+ parent_tree.nodes[1].location = gfx::Rect(50, 10, 200, 100);
+ parent_tree.nodes[2].id = 3;
+ parent_tree.nodes[2].role = AX_ROLE_IFRAME;
+ parent_tree.nodes[2].AddIntAttribute(AX_ATTR_CHILD_TREE_ID, 2);
+
+ AXTreeUpdate child_tree;
+ child_tree.has_tree_data = true;
+ child_tree.tree_data.parent_tree_id = 1;
+ child_tree.tree_data.tree_id = 2;
+ child_tree.nodes.resize(2);
+ child_tree.nodes[0].id = 1;
+ child_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ child_tree.nodes[0].child_ids.push_back(2);
+
+ child_tree.nodes[0].transform.reset(new gfx::Transform());
+ child_tree.nodes[0].transform->Translate(0, 300);
+ child_tree.nodes[0].transform->Scale(2.0, 2.0);
+
+ child_tree.nodes[1].id = 2;
+ child_tree.nodes[1].role = AX_ROLE_BUTTON;
+ child_tree.nodes[1].location = gfx::Rect(50, 10, 200, 100);
+
+ AXTreeCombiner combiner;
+ combiner.AddTree(parent_tree, true);
+ combiner.AddTree(child_tree, false);
+ combiner.Combine();
+
+ const AXTreeUpdate& combined = combiner.combined();
+
+ ASSERT_EQ(5U, combined.nodes.size());
+ EXPECT_EQ(50, combined.nodes[1].location.x());
+ EXPECT_EQ(10, combined.nodes[1].location.y());
+ EXPECT_EQ(200, combined.nodes[1].location.width());
+ EXPECT_EQ(100, combined.nodes[1].location.height());
+ EXPECT_EQ(100, combined.nodes[4].location.x());
+ EXPECT_EQ(320, combined.nodes[4].location.y());
+ EXPECT_EQ(400, combined.nodes[4].location.width());
+ EXPECT_EQ(200, combined.nodes[4].location.height());
+}
+
+TEST(CombineAXTreesTest, FocusedTree) {
+ AXTreeUpdate parent_tree;
+ parent_tree.has_tree_data = true;
+ parent_tree.tree_data.tree_id = 1;
+ parent_tree.tree_data.focused_tree_id = 2;
+ parent_tree.tree_data.focus_id = 2;
+ parent_tree.nodes.resize(3);
+ parent_tree.nodes[0].id = 1;
+ parent_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ parent_tree.nodes[0].child_ids.push_back(2);
+ parent_tree.nodes[0].child_ids.push_back(3);
+ parent_tree.nodes[1].id = 2;
+ parent_tree.nodes[1].role = AX_ROLE_BUTTON;
+ parent_tree.nodes[2].id = 3;
+ parent_tree.nodes[2].role = AX_ROLE_IFRAME;
+ parent_tree.nodes[2].AddIntAttribute(AX_ATTR_CHILD_TREE_ID, 2);
+
+ AXTreeUpdate child_tree;
+ child_tree.has_tree_data = true;
+ child_tree.tree_data.parent_tree_id = 1;
+ child_tree.tree_data.tree_id = 2;
+ child_tree.tree_data.focus_id = 3;
+ child_tree.nodes.resize(3);
+ child_tree.nodes[0].id = 1;
+ child_tree.nodes[0].role = AX_ROLE_ROOT_WEB_AREA;
+ child_tree.nodes[0].child_ids.push_back(2);
+ child_tree.nodes[0].child_ids.push_back(3);
+ child_tree.nodes[1].id = 2;
+ child_tree.nodes[1].role = AX_ROLE_CHECK_BOX;
+ child_tree.nodes[2].id = 3;
+ child_tree.nodes[2].role = AX_ROLE_RADIO_BUTTON;
+
+ AXTreeCombiner combiner;
+ combiner.AddTree(parent_tree, true);
+ combiner.AddTree(child_tree, false);
+ combiner.Combine();
+
+ const AXTreeUpdate& combined = combiner.combined();
+
+ ASSERT_EQ(6U, combined.nodes.size());
+ EXPECT_EQ(6, combined.tree_data.focus_id);
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_data.cc b/chromium/ui/accessibility/ax_tree_data.cc
index 9475a597ff5..4e434dba306 100644
--- a/chromium/ui/accessibility/ax_tree_data.cc
+++ b/chromium/ui/accessibility/ax_tree_data.cc
@@ -19,14 +19,18 @@ namespace ui {
AXTreeData::AXTreeData()
: tree_id(-1),
parent_tree_id(-1),
+ focused_tree_id(-1),
loaded(false),
loading_progress(0.0),
+ focus_id(-1),
sel_anchor_object_id(-1),
sel_anchor_offset(-1),
sel_focus_object_id(-1),
sel_focus_offset(-1) {
}
+AXTreeData::AXTreeData(const AXTreeData& other) = default;
+
AXTreeData::~AXTreeData() {
}
@@ -39,20 +43,24 @@ std::string AXTreeData::ToString() const {
result += " tree_id=" + IntToString(tree_id);
if (parent_tree_id != -1)
result += " parent_tree_id=" + IntToString(parent_tree_id);
+ if (focused_tree_id != -1)
+ result += " focused_tree_id=" + IntToString(focused_tree_id);
- if (!url.empty())
- result += " url=" + url;
- if (!title.empty())
- result += " title=" + title;
- if (!mimetype.empty())
- result += " mimetype=" + mimetype;
if (!doctype.empty())
result += " doctype=" + doctype;
-
if (loaded)
result += " loaded=true";
if (loading_progress != 0.0)
result += " loading_progress=" + DoubleToString(loading_progress);
+ if (!mimetype.empty())
+ result += " mimetype=" + mimetype;
+ if (!url.empty())
+ result += " url=" + url;
+ if (!title.empty())
+ result += " title=" + title;
+
+ if (focus_id != -1)
+ result += " focus_id=" + IntToString(focus_id);
if (sel_anchor_object_id != -1) {
result += " sel_anchor_object_id=" + IntToString(sel_anchor_object_id);
@@ -69,12 +77,11 @@ std::string AXTreeData::ToString() const {
bool operator==(const AXTreeData& lhs, const AXTreeData& rhs) {
return (lhs.tree_id == rhs.tree_id &&
lhs.parent_tree_id == rhs.parent_tree_id &&
- lhs.url == rhs.url &&
- lhs.title == rhs.title &&
- lhs.mimetype == rhs.mimetype &&
- lhs.doctype == rhs.doctype &&
- lhs.loaded == rhs.loaded &&
+ lhs.focused_tree_id == rhs.focused_tree_id &&
+ lhs.doctype == rhs.doctype && lhs.loaded == rhs.loaded &&
lhs.loading_progress == rhs.loading_progress &&
+ lhs.mimetype == rhs.mimetype && lhs.title == rhs.title &&
+ lhs.url == rhs.url && lhs.focus_id == rhs.focus_id &&
lhs.sel_anchor_object_id == rhs.sel_anchor_object_id &&
lhs.sel_anchor_offset == rhs.sel_anchor_offset &&
lhs.sel_focus_object_id == rhs.sel_focus_object_id &&
diff --git a/chromium/ui/accessibility/ax_tree_data.h b/chromium/ui/accessibility/ax_tree_data.h
index 2922a18369a..83a15890666 100644
--- a/chromium/ui/accessibility/ax_tree_data.h
+++ b/chromium/ui/accessibility/ax_tree_data.h
@@ -23,6 +23,7 @@ namespace ui {
// tree and not associated with any particular node in the tree.
struct AX_EXPORT AXTreeData {
AXTreeData();
+ AXTreeData(const AXTreeData& other);
virtual ~AXTreeData();
// Return a string representation of this data, for debugging.
@@ -37,13 +38,21 @@ struct AX_EXPORT AXTreeData {
// The ID of the accessibility tree that this tree is contained in, if any.
int32_t parent_tree_id;
+ // The ID of the accessibility tree that has focus. This is typically set
+ // on the root frame in a frame tree.
+ int32_t focused_tree_id;
+
// Attributes specific to trees that are web frames.
- std::string url;
- std::string title;
- std::string mimetype;
std::string doctype;
bool loaded;
float loading_progress;
+ std::string mimetype;
+ std::string title;
+ std::string url;
+
+ // The node with keyboard focus within this tree, if any, or -1 if no node
+ // in this tree has focus.
+ int32_t focus_id;
// The current text selection within this tree, if any, expressed as the
// node ID and character offset of the anchor (selection start) and focus
diff --git a/chromium/ui/accessibility/ax_tree_unittest.cc b/chromium/ui/accessibility/ax_tree_unittest.cc
index 16706e757d0..27f8dae879b 100644
--- a/chromium/ui/accessibility/ax_tree_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_unittest.cc
@@ -23,6 +23,9 @@ class FakeAXTreeDelegate : public AXTreeDelegate {
: tree_data_changed_(false),
root_changed_(false) {}
+ void OnNodeDataWillChange(AXTree* tree,
+ const AXNodeData& old_node_data,
+ const AXNodeData& new_node_data) override {}
void OnTreeDataChanged(AXTree* tree) override {
tree_data_changed_ = true;
}
@@ -99,7 +102,7 @@ TEST(AXTreeTest, SerializeSimpleAXTree) {
AXNodeData root;
root.id = 1;
root.role = AX_ROLE_ROOT_WEB_AREA;
- root.state = (1 << AX_STATE_FOCUSABLE) | (1 << AX_STATE_FOCUSED);
+ root.state = 1 << AX_STATE_FOCUSABLE;
root.location = gfx::Rect(0, 0, 800, 600);
root.child_ids.push_back(2);
root.child_ids.push_back(3);
@@ -151,7 +154,7 @@ TEST(AXTreeTest, SerializeSimpleAXTree) {
EXPECT_EQ(
"AXTree title=Title\n"
- "id=1 rootWebArea FOCUSABLE FOCUSED (0, 0)-(800, 600) child_ids=2,3\n"
+ "id=1 rootWebArea FOCUSABLE (0, 0)-(800, 600) child_ids=2,3\n"
" id=2 button (20, 20)-(200, 30)\n"
" id=3 checkBox (20, 50)-(200, 30)\n",
dst_tree.ToString());
diff --git a/chromium/ui/accessibility/ax_tree_update.h b/chromium/ui/accessibility/ax_tree_update.h
index 662bdfa88db..f9fb1fa2582 100644
--- a/chromium/ui/accessibility/ax_tree_update.h
+++ b/chromium/ui/accessibility/ax_tree_update.h
@@ -11,6 +11,7 @@
#include <string>
#include <vector>
+#include "base/containers/hash_tables.h"
#include "base/strings/string_number_conversions.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_data.h"
diff --git a/chromium/ui/accessibility/extensions/alt/hide-images.css b/chromium/ui/accessibility/extensions/alt/hide-images.css
index a9d30e333a9..840d7f23397 100644
--- a/chromium/ui/accessibility/extensions/alt/hide-images.css
+++ b/chromium/ui/accessibility/extensions/alt/hide-images.css
@@ -29,19 +29,19 @@ body[show-alt] img:not([aria-hidden=true]):not([role=presentation]):not([alt='']
@-webkit-keyframes slideDown {
from {
- -webkit-transform: translateY(-150%);
+ transform: translateY(-150%);
}
to {
- -webkit-transform: translateY(0px);
+ transform: translateY(0px);
}
}
@-webkit-keyframes slideUp {
from {
- -webkit-transform: translateY(0%);
+ transform: translateY(0%);
}
to {
- -webkit-transform: translateY(-150%);
+ transform: translateY(-150%);
}
}
@@ -52,7 +52,7 @@ body[show-alt] .show-alt-infobar {
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-direction: forwards;
- -webkit-transform: translateY(0%);
+ transform: translateY(0%);
}
body:not([show-alt]) .show-alt-infobar {
@@ -62,7 +62,7 @@ body:not([show-alt]) .show-alt-infobar {
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: ease;
-webkit-animation-direction: forwards;
- -webkit-transform: translateY(-150%);
+ transform: translateY(-150%);
}
.show-alt-infobar {
diff --git a/chromium/ui/accessibility/extensions/colorenhancer/res/setup.css b/chromium/ui/accessibility/extensions/colorenhancer/res/setup.css
index 747b42b10b7..fbb1470005d 100644
--- a/chromium/ui/accessibility/extensions/colorenhancer/res/setup.css
+++ b/chromium/ui/accessibility/extensions/colorenhancer/res/setup.css
@@ -68,7 +68,7 @@ table input[type="button"] {
}
.swatch span {
- -webkit-transform: translate(-5px, -22px);
+ transform: translate(-5px, -22px);
font: 60pt sans;
display: flex;
height: 40px;
diff --git a/chromium/ui/accessibility/platform/atk_util_auralinux.cc b/chromium/ui/accessibility/platform/atk_util_auralinux.cc
index 02563199409..46ad3be53be 100644
--- a/chromium/ui/accessibility/platform/atk_util_auralinux.cc
+++ b/chromium/ui/accessibility/platform/atk_util_auralinux.cc
@@ -8,7 +8,9 @@
#endif
#include <glib-2.0/gmodule.h>
+#include "base/bind.h"
#include "base/files/file_path.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "ui/accessibility/platform/atk_util_auralinux.h"
@@ -16,41 +18,42 @@
namespace {
-#if defined(USE_GCONF)
+typedef void (*gnome_accessibility_module_init)();
-const char kGnomeAccessibilityEnabledKey[] =
- "/desktop/gnome/interface/accessibility";
+const char kAtkBridgePath[] = "gtk-2.0/modules/libatk-bridge.so";
+const char kAtkBridgeSymbolName[] = "gnome_accessibility_module_init";
-bool ShouldEnableAccessibility() {
- GConfClient* client = gconf_client_get_default();
- if (!client) {
- LOG(ERROR) << "gconf_client_get_default failed";
+gnome_accessibility_module_init g_accessibility_module_init = nullptr;
+
+bool AccessibilityModuleInitOnFileThread() {
+ // Try to load libatk-bridge.so.
+ base::FilePath atk_bridge_path(ATK_LIB_DIR);
+ atk_bridge_path = atk_bridge_path.Append(kAtkBridgePath);
+ GModule* bridge = g_module_open(atk_bridge_path.value().c_str(),
+ static_cast<GModuleFlags>(0));
+ if (!bridge) {
+ VLOG(1) << "Unable to open module " << atk_bridge_path.value();
return false;
}
- GError* error = nullptr;
- gboolean value = gconf_client_get_bool(client,
- kGnomeAccessibilityEnabledKey,
- &error);
- if (error) {
- VLOG(1) << "gconf_client_get_bool failed";
- g_error_free(error);
- g_object_unref(client);
+ if (!g_module_symbol(bridge, kAtkBridgeSymbolName,
+ (gpointer *)&g_accessibility_module_init)) {
+ VLOG(1) << "Unable to get symbol pointer from " << atk_bridge_path.value();
+ // Just to make sure it's null;
+ g_accessibility_module_init = nullptr;
return false;
}
- g_object_unref(client);
- return value;
+ return true;
}
-#else // !defined(USE_GCONF)
+#if defined(USE_GCONF)
-bool ShouldEnableAccessibility() {
- // TODO(k.czech): implement this for non-GNOME desktops.
- return false;
-}
+const char kAccessibilityEnabled[] = "ACCESSIBILITY_ENABLED";
+const char kGnomeAccessibilityEnabledKey[] =
+ "/desktop/gnome/interface/accessibility";
-#endif // defined(USE_GCONF)
+#endif
} // namespace
@@ -139,44 +142,88 @@ AtkUtilAuraLinux* AtkUtilAuraLinux::GetInstance() {
return base::Singleton<AtkUtilAuraLinux>::get();
}
+#if defined(USE_GCONF)
+
+AtkUtilAuraLinux::AtkUtilAuraLinux()
+ : is_enabled_(false) {
+}
+
+#else
+
AtkUtilAuraLinux::AtkUtilAuraLinux() {
}
+#endif // defined(USE_GCONF)
+
void AtkUtilAuraLinux::Initialize(
- scoped_refptr<base::TaskRunner> /* init_task_runner */) {
- // TODO(k.czech): use |init_task_runner| to post a task to do the
- // initialization rather than doing it on this thread.
- // http://crbug.com/468112
+ scoped_refptr<base::TaskRunner> init_task_runner) {
// Register our util class.
g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE));
- if (!ShouldEnableAccessibility()) {
- VLOG(1) << "Will not enable ATK accessibility support.";
- return;
+ init_task_runner->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(
+ &AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread,
+ base::Unretained(this)),
+ base::Bind(
+ &AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread,
+ base::Unretained(this)));
+}
+
+AtkUtilAuraLinux::~AtkUtilAuraLinux() {
+}
+
+#if defined(USE_GCONF)
+
+void AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread() {
+ char* enable_accessibility = getenv(kAccessibilityEnabled);
+ if ((enable_accessibility && atoi(enable_accessibility) == 1) ||
+ CheckPlatformAccessibilitySupportOnFileThread())
+ is_enabled_ = AccessibilityModuleInitOnFileThread();
+}
+
+bool AtkUtilAuraLinux::CheckPlatformAccessibilitySupportOnFileThread() {
+ GConfClient* client = gconf_client_get_default();
+ if (!client) {
+ LOG(ERROR) << "gconf_client_get_default failed";
+ return false;
}
- VLOG(1) << "Enabling ATK accessibility support.";
+ GError* error = nullptr;
+ bool is_enabled = gconf_client_get_bool(client,
+ kGnomeAccessibilityEnabledKey,
+ &error);
- // Try to load libatk-bridge.so.
- base::FilePath atk_bridge_path(ATK_LIB_DIR);
- atk_bridge_path = atk_bridge_path.Append("gtk-2.0/modules/libatk-bridge.so");
- GModule* bridge = g_module_open(atk_bridge_path.value().c_str(),
- static_cast<GModuleFlags>(0));
- if (!bridge) {
- VLOG(1) << "Unable to open module " << atk_bridge_path.value();
- return;
+ g_object_unref(client);
+
+ if (error) {
+ VLOG(1) << "gconf_client_get_bool failed";
+ g_error_free(error);
+ return false;
}
- // Try to call gnome_accessibility_module_init from libatk-bridge.so.
- void (*gnome_accessibility_module_init)();
- if (g_module_symbol(bridge, "gnome_accessibility_module_init",
- (gpointer *)&gnome_accessibility_module_init)) {
- (*gnome_accessibility_module_init)();
+ return is_enabled;
+}
+
+void AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread() {
+ if (!is_enabled_) {
+ VLOG(1) << "Will not enable ATK accessibility support.";
+ return;
}
+
+ DCHECK(g_accessibility_module_init);
+ g_accessibility_module_init();
}
-AtkUtilAuraLinux::~AtkUtilAuraLinux() {
+#else
+
+void AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread() {
+}
+
+void AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread() {
}
+#endif // defined(USE_GCONF)
+
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/atk_util_auralinux.h b/chromium/ui/accessibility/platform/atk_util_auralinux.h
index a5bc75d9311..8342a1299c7 100644
--- a/chromium/ui/accessibility/platform/atk_util_auralinux.h
+++ b/chromium/ui/accessibility/platform/atk_util_auralinux.h
@@ -29,6 +29,14 @@ class AtkUtilAuraLinux {
private:
friend struct base::DefaultSingletonTraits<AtkUtilAuraLinux>;
+
+ void CheckIfAccessibilityIsEnabledOnFileThread();
+ bool CheckPlatformAccessibilitySupportOnFileThread();
+ void FinishAccessibilityInitOnUIThread();
+
+#if defined(USE_GCONF)
+ bool is_enabled_;
+#endif
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.cc b/chromium/ui/accessibility/platform/ax_platform_node.cc
index 8f889458ddb..adfcc1e2ad2 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node.cc
@@ -4,12 +4,23 @@
#include "ui/accessibility/platform/ax_platform_node.h"
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
namespace ui {
+namespace {
+
+using UniqueIdMap = base::hash_map<int32_t, AXPlatformNode*>;
+// Map from each AXPlatformNode's unique id to its instance.
+base::LazyInstance<UniqueIdMap> g_unique_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+}
+
#if !defined(PLATFORM_HAS_AX_PLATFORM_NODE_IMPL)
// static
AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
@@ -28,10 +39,39 @@ AXPlatformNode* AXPlatformNode::FromNativeViewAccessible(
}
#endif
-AXPlatformNode::AXPlatformNode() {
+// static
+int32_t AXPlatformNode::GetNextUniqueId() {
+ static int32_t next_unique_id = 1;
+ int32_t unique_id = next_unique_id;
+ if (next_unique_id == INT32_MAX)
+ next_unique_id = 1;
+ else
+ next_unique_id++;
+
+ return unique_id;
+}
+
+AXPlatformNode::AXPlatformNode() : unique_id_(GetNextUniqueId()) {
+ g_unique_id_map.Get()[unique_id_] = this;
}
AXPlatformNode::~AXPlatformNode() {
+ if (unique_id_)
+ g_unique_id_map.Get().erase(unique_id_);
+}
+
+void AXPlatformNode::Destroy() {
+ g_unique_id_map.Get().erase(unique_id_);
+ unique_id_ = 0;
+}
+
+AXPlatformNode* AXPlatformNode::GetFromUniqueId(int32_t unique_id) {
+ UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
+ auto iter = unique_ids->find(unique_id);
+ if (iter != unique_ids->end())
+ return iter->second;
+
+ return nullptr;
}
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.h b/chromium/ui/accessibility/platform/ax_platform_node.h
index 1d0ed510b38..c9df25947dd 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node.h
@@ -46,9 +46,17 @@ class AX_EXPORT AXPlatformNode {
static AXPlatformNode* FromNativeViewAccessible(
gfx::NativeViewAccessible accessible);
+ // Each platform accessibility object has a unique id that's guaranteed
+ // to be a positive number. (It's stored in an int32_t as opposed to
+ // uint32_t because some platforms want to negate it, so we want to ensure
+ // the range is below the signed int max.) This can be used when the
+ // id has to be unique across multiple frames, since node ids are
+ // only unique within one tree.
+ static int32_t GetNextUniqueId();
+
// Call Destroy rather than deleting this, because the subclass may
// use reference counting.
- virtual void Destroy() = 0;
+ virtual void Destroy();
// Get the platform-specific accessible object type for this instance.
// On some platforms this is just a type cast, on others it may be a
@@ -65,6 +73,10 @@ class AX_EXPORT AXPlatformNode {
protected:
AXPlatformNode();
virtual ~AXPlatformNode();
+
+ AXPlatformNode* GetFromUniqueId(int32_t unique_id);
+
+ int32_t unique_id_;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 801c3473e66..04e96c02ba5 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -448,14 +448,15 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDED);
if (state & (1 << ui::AX_STATE_FOCUSABLE))
atk_state_set_add_state(atk_state_set, ATK_STATE_FOCUSABLE);
- if (state & (1 << ui::AX_STATE_FOCUSED))
- atk_state_set_add_state(atk_state_set, ATK_STATE_FOCUSED);
if (state & (1 << ui::AX_STATE_PRESSED))
atk_state_set_add_state(atk_state_set, ATK_STATE_PRESSED);
if (state & (1 << ui::AX_STATE_SELECTABLE))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTABLE);
if (state & (1 << ui::AX_STATE_SELECTED))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTED);
+
+ if (delegate_->GetFocus() == GetNativeViewAccessible())
+ atk_state_set_add_state(atk_state_set, ATK_STATE_FOCUSED);
}
void AXPlatformNodeAuraLinux::GetAtkRelations(AtkRelationSet* atk_relation_set)
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
index 2c1bf90507d..4937e4d3178 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
@@ -44,6 +44,7 @@ gfx::NativeViewAccessible AXPlatformNodeBase::ChildAtIndex(int index) {
// AXPlatformNode overrides.
void AXPlatformNodeBase::Destroy() {
+ AXPlatformNode::Destroy();
delegate_ = nullptr;
delete this;
}
@@ -92,7 +93,10 @@ bool AXPlatformNodeBase::IsDescendant(AXPlatformNodeBase* node) {
return false;
if (node == this)
return true;
- AXPlatformNodeBase* parent = FromNativeViewAccessible(node->GetParent());
+ gfx::NativeViewAccessible native_parent = node->GetParent();
+ if (!native_parent)
+ return false;
+ AXPlatformNodeBase* parent = FromNativeViewAccessible(native_parent);
return IsDescendant(parent);
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
index a4384f9ac77..c4b54d421bd 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -24,6 +24,7 @@ typedef std::map<ui::AXRole, NSString*> RoleMap;
RoleMap BuildRoleMap() {
const MapEntry roles[] = {
+ {ui::AX_ROLE_ABBR, NSAccessibilityGroupRole},
{ui::AX_ROLE_ALERT, NSAccessibilityGroupRole},
{ui::AX_ROLE_ALERT_DIALOG, NSAccessibilityGroupRole},
{ui::AX_ROLE_ANNOTATION, NSAccessibilityUnknownRole},
@@ -55,6 +56,7 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_DISCLOSURE_TRIANGLE, NSAccessibilityDisclosureTriangleRole},
{ui::AX_ROLE_DIV, NSAccessibilityGroupRole},
{ui::AX_ROLE_DOCUMENT, NSAccessibilityGroupRole},
+ {ui::AX_ROLE_EMBEDDED_OBJECT, NSAccessibilityGroupRole},
{ui::AX_ROLE_FIGCAPTION, NSAccessibilityGroupRole},
{ui::AX_ROLE_FIGURE, NSAccessibilityGroupRole},
{ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole},
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
index ee7a4f9f8c6..c8f7d5445c3 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
@@ -78,35 +78,36 @@ namespace ui {
namespace {
-typedef base::hash_map<LONG, AXPlatformNodeWin*> UniqueIdWinMap;
-// Map from each AXPlatformNodeWin's unique id to its instance.
-base::LazyInstance<UniqueIdWinMap> g_unique_id_win_map =
- LAZY_INSTANCE_INITIALIZER;
-
typedef base::hash_set<AXPlatformNodeWin*> AXPlatformNodeWinSet;
// Set of all AXPlatformNodeWin objects that were the target of an
// alert event.
base::LazyInstance<AXPlatformNodeWinSet> g_alert_targets =
LAZY_INSTANCE_INITIALIZER;
-LONG GetNextNegativeUniqueIdForWinAccessibility(AXPlatformNodeWin* obj) {
- static LONG next_unique_id = -1;
- LONG unique_id = next_unique_id;
- if (next_unique_id == LONG_MIN)
- next_unique_id = -1;
- else
- next_unique_id--;
+base::LazyInstance<base::ObserverList<IAccessible2UsageObserver>>
+ g_iaccessible2_usage_observer_list = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
- g_unique_id_win_map.Get().insert(std::make_pair(unique_id, obj));
+//
+// IAccessible2UsageObserver
+//
- return unique_id;
+IAccessible2UsageObserver::IAccessible2UsageObserver() {
}
-void UnregisterNegativeUniqueId(LONG unique_id) {
- g_unique_id_win_map.Get().erase(unique_id);
+IAccessible2UsageObserver::~IAccessible2UsageObserver() {
}
-} // namespace
+// static
+base::ObserverList<IAccessible2UsageObserver>&
+ GetIAccessible2UsageObserverList() {
+ return g_iaccessible2_usage_observer_list.Get();
+}
+
+//
+// AXPlatformNode::Create
+//
// static
AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
@@ -129,8 +130,11 @@ AXPlatformNode* AXPlatformNode::FromNativeViewAccessible(
return ax_platform_node.get();
}
-AXPlatformNodeWin::AXPlatformNodeWin()
- : unique_id_win_(GetNextNegativeUniqueIdForWinAccessibility(this)) {
+//
+// AXPlatformNodeWin
+//
+
+AXPlatformNodeWin::AXPlatformNodeWin() {
}
AXPlatformNodeWin::~AXPlatformNodeWin() {
@@ -143,7 +147,6 @@ AXPlatformNodeWin::~AXPlatformNodeWin() {
void AXPlatformNodeWin::Destroy() {
delegate_ = nullptr;
- UnregisterNegativeUniqueId(unique_id_win_);
RemoveAlertTarget();
Release();
}
@@ -157,11 +160,17 @@ void AXPlatformNodeWin::NotifyAccessibilityEvent(ui::AXEvent event_type) {
if (!hwnd)
return;
+ // Menu items fire selection events but Windows screen readers work reliably
+ // with focus events. Remap here.
+ if (event_type == ui::AX_EVENT_SELECTION &&
+ GetData().role == ui::AX_ROLE_MENU_ITEM)
+ event_type = ui::AX_EVENT_FOCUS;
+
int native_event = MSAAEvent(event_type);
if (native_event < EVENT_MIN)
return;
- ::NotifyWinEvent(native_event, hwnd, OBJID_CLIENT, unique_id_win_);
+ ::NotifyWinEvent(native_event, hwnd, OBJID_CLIENT, -unique_id_);
// Keep track of objects that are a target of an alert event.
if (event_type == ui::AX_EVENT_ALERT)
@@ -324,25 +333,28 @@ STDMETHODIMP AXPlatformNodeWin::get_accChild(VARIANT var_child,
// that want to enumerate all immediate children.
*disp_child = delegate_->ChildAtIndex(child_id - 1);
if (!(*disp_child))
- return E_FAIL;
+ return E_INVALIDARG;
(*disp_child)->AddRef();
return S_OK;
}
if (child_id >= 0)
- return E_FAIL;
+ return E_INVALIDARG;
// Negative child ids can be used to map to any descendant.
- UniqueIdWinMap* unique_ids = g_unique_id_win_map.Pointer();
- auto iter = unique_ids->find(child_id);
- if (iter != unique_ids->end()) {
- *disp_child = iter->second;
+ AXPlatformNodeWin* child = static_cast<AXPlatformNodeWin*>(
+ GetFromUniqueId(-child_id));
+ if (child && !IsDescendant(child))
+ child = nullptr;
+
+ if (child) {
+ *disp_child = child;
(*disp_child)->AddRef();
return S_OK;
}
*disp_child = nullptr;
- return E_FAIL;
+ return E_INVALIDARG;
}
STDMETHODIMP AXPlatformNodeWin::get_accChildCount(LONG* child_count) {
@@ -498,7 +510,7 @@ STDMETHODIMP AXPlatformNodeWin::get_states(AccessibleStates* states) {
STDMETHODIMP AXPlatformNodeWin::get_uniqueID(LONG* unique_id) {
COM_OBJECT_VALIDATE_1_ARG(unique_id);
- *unique_id = unique_id_win_;
+ *unique_id = -unique_id_;
return S_OK;
}
@@ -876,6 +888,13 @@ STDMETHODIMP AXPlatformNodeWin::scrollSubstringToPoint(
STDMETHODIMP AXPlatformNodeWin::QueryService(
REFGUID guidService, REFIID riid, void** object) {
COM_OBJECT_VALIDATE_1_ARG(object);
+
+ if (riid == IID_IAccessible2) {
+ FOR_EACH_OBSERVER(IAccessible2UsageObserver,
+ GetIAccessible2UsageObserverList(),
+ OnIAccessible2Used());
+ }
+
if (guidService == IID_IAccessible ||
guidService == IID_IAccessible2 ||
guidService == IID_IAccessible2_2 ||
@@ -982,8 +1001,6 @@ int AXPlatformNodeWin::MSAAState() {
msaa_state |= STATE_SYSTEM_EXPANDED;
if (state & (1 << ui::AX_STATE_FOCUSABLE))
msaa_state |= STATE_SYSTEM_FOCUSABLE;
- if (state & (1 << ui::AX_STATE_FOCUSED))
- msaa_state |= STATE_SYSTEM_FOCUSED;
if (state & (1 << ui::AX_STATE_HASPOPUP))
msaa_state |= STATE_SYSTEM_HASPOPUP;
if (state & (1 << ui::AX_STATE_HOVERED))
@@ -1007,6 +1024,21 @@ int AXPlatformNodeWin::MSAAState() {
if (state & (1 << ui::AX_STATE_DISABLED))
msaa_state |= STATE_SYSTEM_UNAVAILABLE;
+ gfx::NativeViewAccessible focus = delegate_->GetFocus();
+ if (focus == GetNativeViewAccessible())
+ msaa_state |= STATE_SYSTEM_FOCUSED;
+
+ // On Windows, the "focus" bit should be set on certain containers, like
+ // menu bars, when visible.
+ //
+ // TODO(dmazzoni): this should probably check if focus is actually inside
+ // the menu bar, but we don't currently track focus inside menu pop-ups,
+ // and Chrome only has one menu visible at a time so this works for now.
+ if (GetData().role == ui::AX_ROLE_MENU_BAR &&
+ !(state & (1 << ui::AX_STATE_INVISIBLE))) {
+ msaa_state |= STATE_SYSTEM_FOCUSED;
+ }
+
return msaa_state;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.h b/chromium/ui/accessibility/platform/ax_platform_node_win.h
index 5d264211b34..eb747ed4d0b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.h
@@ -9,11 +9,29 @@
#include <atlcom.h>
#include <oleacc.h>
+#include "base/observer_list.h"
#include "third_party/iaccessible2/ia2_api_all.h"
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
namespace ui {
+// A simple interface for a class that wants to be notified when IAccessible2
+// is used by a client, a strong indication that full accessibility support
+// should be enabled.
+class AX_EXPORT IAccessible2UsageObserver {
+ public:
+ IAccessible2UsageObserver();
+ virtual ~IAccessible2UsageObserver();
+ virtual void OnIAccessible2Used() = 0;
+};
+
+// Get an observer list that allows modules across the codebase to
+// listen to when usage of IAccessible2 is detected.
+extern AX_EXPORT base::ObserverList<IAccessible2UsageObserver>&
+ GetIAccessible2UsageObserverList();
+
class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
AXPlatformNodeWin
: public CComObjectRootEx<CComMultiThreadModel>,
@@ -279,16 +297,6 @@ AXPlatformNodeWin
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
ui::TextBoundaryDirection direction);
-
- // A windows-specific unique ID for this object. It's returned in
- // IAccessible2::get_uniqueID, but more importantly it's used for
- // firing events. On Windows, we fire events on the nearest parent HWND
- // and pass the unique ID as the child id parameter. When the client
- // wants to retrieve the object the event was fired on, it calls
- // get_accChild and passes the child ID. We use negative IDs for the unique
- // ID so we can distinguish a request for an arbitrary child from a request
- // for an immediate child of an object by its 0-based index.
- LONG unique_id_win_;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 08be59b21f1..d5a4f81e501 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -315,7 +315,8 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
// Asking for child id 3 should fail.
ScopedComPtr<IDispatch> result;
ScopedVariant child3(3);
- ASSERT_EQ(E_FAIL, root_iaccessible->get_accChild(child3, result.Receive()));
+ ASSERT_EQ(E_INVALIDARG,
+ root_iaccessible->get_accChild(child3, result.Receive()));
}
// We should be able to ask for the button by its unique id too.
@@ -332,6 +333,20 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
ASSERT_EQ(result.get(), button_iaccessible);
}
+ // We shouldn't be able to ask for the root node by its unique ID
+ // from one of its children, though.
+ LONG root_unique_id;
+ ScopedComPtr<IAccessible2> root_iaccessible2 =
+ ToIAccessible2(root_iaccessible);
+ root_iaccessible2->get_uniqueID(&root_unique_id);
+ ASSERT_LT(root_unique_id, 0);
+ {
+ ScopedComPtr<IDispatch> result;
+ ScopedVariant root_id_variant(root_unique_id);
+ ASSERT_EQ(E_INVALIDARG, button_iaccessible->get_accChild(root_id_variant,
+ result.Receive()));
+ }
+
// Now check parents.
{
ScopedComPtr<IDispatch> result;
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
index fbb76ca13be..f2b91731aa4 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -18,6 +18,9 @@ gfx::Vector2d g_offset;
// A simple implementation of AXTreeDelegate to catch when AXNodes are
// deleted so we can delete their wrappers.
class TestAXTreeDelegate : public AXTreeDelegate {
+ void OnNodeDataWillChange(AXTree* tree,
+ const AXNodeData& old_node_data,
+ const AXNodeData& new_node_data) override {}
void OnTreeDataChanged(AXTree* tree) override {}
void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override {
auto iter = g_node_to_wrapper_map.find(node);
diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn
index 85a4e92b4ee..fc4c55047a7 100644
--- a/chromium/ui/android/BUILD.gn
+++ b/chromium/ui/android/BUILD.gn
@@ -34,7 +34,6 @@ component("android") {
"view_android.h",
"window_android.cc",
"window_android.h",
- "window_android_compositor.cc",
"window_android_compositor.h",
"window_android_observer.h",
]
@@ -131,7 +130,76 @@ android_resources("ui_java_resources") {
}
android_library("ui_java") {
- DEPRECATED_java_in_dir = "java/src"
+ java_files = [
+ "java/src/org/chromium/ui/ColorPickerAdvanced.java",
+ "java/src/org/chromium/ui/ColorPickerAdvancedComponent.java",
+ "java/src/org/chromium/ui/ColorPickerDialog.java",
+ "java/src/org/chromium/ui/ColorPickerMoreButton.java",
+ "java/src/org/chromium/ui/ColorPickerSimple.java",
+ "java/src/org/chromium/ui/ColorSuggestion.java",
+ "java/src/org/chromium/ui/ColorSuggestionListAdapter.java",
+ "java/src/org/chromium/ui/DropdownAdapter.java",
+ "java/src/org/chromium/ui/DropdownDividerDrawable.java",
+ "java/src/org/chromium/ui/DropdownItem.java",
+ "java/src/org/chromium/ui/DropdownPopupWindow.java",
+ "java/src/org/chromium/ui/OnColorChangedListener.java",
+ "java/src/org/chromium/ui/UiUtils.java",
+ "java/src/org/chromium/ui/VSyncMonitor.java",
+ "java/src/org/chromium/ui/autofill/AutofillDelegate.java",
+ "java/src/org/chromium/ui/autofill/AutofillKeyboardAccessory.java",
+ "java/src/org/chromium/ui/autofill/AutofillPopup.java",
+ "java/src/org/chromium/ui/autofill/AutofillSuggestion.java",
+ "java/src/org/chromium/ui/base/ActivityWindowAndroid.java",
+ "java/src/org/chromium/ui/base/AndroidPermissionDelegate.java",
+ "java/src/org/chromium/ui/base/Clipboard.java",
+ "java/src/org/chromium/ui/base/DeviceFormFactor.java",
+ "java/src/org/chromium/ui/base/LocalizationUtils.java",
+ "java/src/org/chromium/ui/base/ResourceBundle.java",
+ "java/src/org/chromium/ui/base/SelectFileDialog.java",
+ "java/src/org/chromium/ui/base/TouchDevice.java",
+ "java/src/org/chromium/ui/base/ViewAndroidDelegate.java",
+ "java/src/org/chromium/ui/base/WindowAndroid.java",
+ "java/src/org/chromium/ui/gfx/BitmapHelper.java",
+ "java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java",
+ "java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java",
+ "java/src/org/chromium/ui/gl/SurfaceTextureListener.java",
+ "java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java",
+ "java/src/org/chromium/ui/interpolators/BakedBezierInterpolator.java",
+ "java/src/org/chromium/ui/picker/ChromeDatePickerDialog.java",
+ "java/src/org/chromium/ui/picker/DateDialogNormalizer.java",
+ "java/src/org/chromium/ui/picker/DateTimePickerDialog.java",
+ "java/src/org/chromium/ui/picker/DateTimeSuggestion.java",
+ "java/src/org/chromium/ui/picker/DateTimeSuggestionListAdapter.java",
+ "java/src/org/chromium/ui/picker/InputDialogContainer.java",
+ "java/src/org/chromium/ui/picker/MonthPicker.java",
+ "java/src/org/chromium/ui/picker/MonthPickerDialog.java",
+ "java/src/org/chromium/ui/picker/MultiFieldTimePickerDialog.java",
+ "java/src/org/chromium/ui/picker/TwoFieldDatePicker.java",
+ "java/src/org/chromium/ui/picker/TwoFieldDatePickerDialog.java",
+ "java/src/org/chromium/ui/picker/WeekPicker.java",
+ "java/src/org/chromium/ui/picker/WeekPickerDialog.java",
+ "java/src/org/chromium/ui/resources/LayoutResource.java",
+ "java/src/org/chromium/ui/resources/Resource.java",
+ "java/src/org/chromium/ui/resources/ResourceLoader.java",
+ "java/src/org/chromium/ui/resources/ResourceManager.java",
+ "java/src/org/chromium/ui/resources/async/AsyncPreloadResourceLoader.java",
+ "java/src/org/chromium/ui/resources/dynamics/BitmapDynamicResource.java",
+ "java/src/org/chromium/ui/resources/dynamics/DynamicResource.java",
+ "java/src/org/chromium/ui/resources/dynamics/DynamicResourceLoader.java",
+ "java/src/org/chromium/ui/resources/dynamics/ViewResourceAdapter.java",
+ "java/src/org/chromium/ui/resources/dynamics/ViewResourceInflater.java",
+ "java/src/org/chromium/ui/resources/sprites/CrushedSpriteResource.java",
+ "java/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceLoader.java",
+ "java/src/org/chromium/ui/resources/statics/NinePatchData.java",
+ "java/src/org/chromium/ui/resources/statics/StaticResource.java",
+ "java/src/org/chromium/ui/resources/statics/StaticResourceLoader.java",
+ "java/src/org/chromium/ui/resources/system/SystemResourceLoader.java",
+ "java/src/org/chromium/ui/text/NoUnderlineClickableSpan.java",
+ "java/src/org/chromium/ui/text/SpanApplier.java",
+ "java/src/org/chromium/ui/widget/ButtonCompat.java",
+ "java/src/org/chromium/ui/widget/TextViewWithClickableSpans.java",
+ "java/src/org/chromium/ui/widget/Toast.java",
+ ]
deps = [
":ui_java_resources",
"//base:base_java",
@@ -140,7 +208,10 @@ android_library("ui_java") {
}
android_library("ui_javatests") {
- DEPRECATED_java_in_dir = "javatests/src"
+ java_files = [
+ "javatests/src/org/chromium/ui/picker/DateTimePickerDialogTest.java",
+ "javatests/src/org/chromium/ui/resources/sprites/CrushedSpriteResourceTest.java",
+ ]
testonly = true
deps = [
":ui_java",
@@ -150,6 +221,19 @@ android_library("ui_javatests") {
]
}
+# GYP: //ui/android/ui_android.gyp:ui_junit_tests
+junit_binary("ui_junit_tests") {
+ java_files = [
+ "junit/src/org/chromium/ui/picker/DateDialogNormalizerTest.java",
+ "junit/src/org/chromium/ui/text/SpanApplierTest.java",
+ ]
+ deps = [
+ "//base:base_java",
+ "//base:base_junit_test_support",
+ "//ui/android:ui_java",
+ ]
+}
+
test("ui_android_unittests") {
sources = [
"overscroll_refresh_unittest.cc",
diff --git a/chromium/ui/android/edge_effect.cc b/chromium/ui/android/edge_effect.cc
index 5796c023d75..a5189405681 100644
--- a/chromium/ui/android/edge_effect.cc
+++ b/chromium/ui/android/edge_effect.cc
@@ -65,8 +65,7 @@ class EdgeEffect::EffectLayer {
public:
EffectLayer(ui::SystemUIResourceType resource_type,
ui::ResourceManager* resource_manager)
- : ui_resource_layer_(cc::UIResourceLayer::Create(
- WindowAndroidCompositor::LayerSettings())),
+ : ui_resource_layer_(cc::UIResourceLayer::Create()),
resource_type_(resource_type),
resource_manager_(resource_manager) {}
diff --git a/chromium/ui/android/edge_effect_l.cc b/chromium/ui/android/edge_effect_l.cc
index 3a19775d27a..305ca4971de 100644
--- a/chromium/ui/android/edge_effect_l.cc
+++ b/chromium/ui/android/edge_effect_l.cc
@@ -51,8 +51,7 @@ const ui::SystemUIResourceType kResourceId = ui::OVERSCROLL_GLOW_L;
EdgeEffectL::EdgeEffectL(ui::ResourceManager* resource_manager)
: resource_manager_(resource_manager),
- glow_(cc::UIResourceLayer::Create(
- WindowAndroidCompositor::LayerSettings())),
+ glow_(cc::UIResourceLayer::Create()),
glow_alpha_(0),
glow_scale_y_(0),
glow_alpha_start_(0),
diff --git a/chromium/ui/android/overscroll_glow.cc b/chromium/ui/android/overscroll_glow.cc
index 3f9fb02df26..7f3c43da306 100644
--- a/chromium/ui/android/overscroll_glow.cc
+++ b/chromium/ui/android/overscroll_glow.cc
@@ -194,7 +194,7 @@ bool OverscrollGlow::InitializeIfNecessary() {
return true;
DCHECK(!root_layer_.get());
- root_layer_ = cc::Layer::Create(WindowAndroidCompositor::LayerSettings());
+ root_layer_ = cc::Layer::Create();
for (size_t i = 0; i < EDGE_COUNT; ++i) {
edge_effects_[i] = client_->CreateEdgeEffect();
DCHECK(edge_effects_[i]);
diff --git a/chromium/ui/android/resources/resource_manager_impl_unittest.cc b/chromium/ui/android/resources/resource_manager_impl_unittest.cc
index 649ce7be5c5..957b2a14e92 100644
--- a/chromium/ui/android/resources/resource_manager_impl_unittest.cc
+++ b/chromium/ui/android/resources/resource_manager_impl_unittest.cc
@@ -97,7 +97,7 @@ class ResourceManagerTest : public testing::Test {
params.settings = &settings;
params.task_graph_runner = &task_graph_runner_;
host_.reset(new MockLayerTreeHost(&params,
- cc::CompositorMode::SingleThreaded));
+ cc::CompositorMode::SINGLE_THREADED));
resource_manager_.Init(host_.get());
}
diff --git a/chromium/ui/android/ui_android.gyp b/chromium/ui/android/ui_android.gyp
index b1d2857afb7..c818edb82f6 100644
--- a/chromium/ui/android/ui_android.gyp
+++ b/chromium/ui/android/ui_android.gyp
@@ -47,7 +47,6 @@
'view_android.h',
'window_android.cc',
'window_android.h',
- 'window_android_compositor.cc',
'window_android_compositor.h',
'window_android_observer.h',
],
@@ -167,6 +166,29 @@
],
},
{
+ # GN: //ui/android:ui_junit_tests
+ 'target_name': 'ui_junit_tests',
+ 'type': 'none',
+ 'dependencies': [
+ 'ui_java',
+ '../../base/base.gyp:base',
+ '../../base/base.gyp:base_junit_test_support',
+ '../../testing/android/junit/junit_test.gyp:junit_test_support',
+ ],
+ 'variables': {
+ 'main_class': 'org.chromium.testing.local.JunitTestMain',
+ 'src_paths': [
+ 'junit/',
+ ],
+ 'test_type': 'junit',
+ 'wrapper_script_name': 'helper/<(_target_name)',
+ },
+ 'includes': [
+ '../../build/android/test_runner.gypi',
+ '../../build/host_jar.gypi',
+ ],
+ },
+ {
# GN version: //ui/android:ui_android_unittests
'target_name': 'ui_android_unittests',
'type': '<(gtest_target_type)',
diff --git a/chromium/ui/android/window_android_compositor.cc b/chromium/ui/android/window_android_compositor.cc
deleted file mode 100644
index 3fb53ead0d6..00000000000
--- a/chromium/ui/android/window_android_compositor.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-#include "ui/android/window_android_compositor.h"
-
-#include "base/lazy_instance.h"
-#include "cc/layers/layer_settings.h"
-
-namespace ui {
-
-namespace {
-base::LazyInstance<cc::LayerSettings> g_layer_settings =
- LAZY_INSTANCE_INITIALIZER;
-} // anonymous namespace
-
-// static
-const cc::LayerSettings& WindowAndroidCompositor::LayerSettings() {
- return g_layer_settings.Get();
-}
-
-// static
-void WindowAndroidCompositor::SetLayerSettings(
- const cc::LayerSettings& settings) {
- g_layer_settings.Get() = settings;
-}
-
-} // namespace ui
diff --git a/chromium/ui/android/window_android_compositor.h b/chromium/ui/android/window_android_compositor.h
index 51627d0d169..a6ffb336723 100644
--- a/chromium/ui/android/window_android_compositor.h
+++ b/chromium/ui/android/window_android_compositor.h
@@ -10,7 +10,6 @@
namespace cc {
class Layer;
-class LayerSettings;
}
namespace ui {
@@ -20,12 +19,8 @@ class ResourceManager;
// Android interface for compositor-related tasks.
class UI_ANDROID_EXPORT WindowAndroidCompositor {
public:
- static const cc::LayerSettings& LayerSettings();
- static void SetLayerSettings(const cc::LayerSettings& settings);
-
virtual ~WindowAndroidCompositor() {}
- virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) = 0;
virtual void RequestCopyOfOutputOnRootLayer(
scoped_ptr<cc::CopyOutputRequest> request) = 0;
virtual void OnVSync(base::TimeTicks frame_time,
diff --git a/chromium/ui/app_list/app_list.gyp b/chromium/ui/app_list/app_list.gyp
index 5bbfc77e8f1..e8d42112297 100644
--- a/chromium/ui/app_list/app_list.gyp
+++ b/chromium/ui/app_list/app_list.gyp
@@ -317,17 +317,6 @@
['exclude', 'cocoa/'],
],
}],
- # See http://crbug.com/162998#c4 for why this is needed.
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
@@ -370,11 +359,6 @@
'../../content/content.gyp:sandbox_helper_win',
],
}],
- ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
],
},
],
diff --git a/chromium/ui/app_list/shower/app_list_shower.gyp b/chromium/ui/app_list/shower/app_list_shower.gyp
new file mode 100644
index 00000000000..1d342622265
--- /dev/null
+++ b/chromium/ui/app_list/shower/app_list_shower.gyp
@@ -0,0 +1,107 @@
+# 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.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ # GN version: //ui/app_list/shower
+ 'target_name': 'app_list_shower',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../skia/skia.gyp:skia',
+ '../../aura/aura.gyp:aura',
+ '../../compositor/compositor.gyp:compositor',
+ '../../events/events.gyp:events_base',
+ '../../events/events.gyp:events',
+ '../../gfx/gfx.gyp:gfx_geometry',
+ '../../views/views.gyp:views',
+ '../app_list.gyp:app_list',
+ ],
+ 'defines': [
+ 'APP_LIST_SHOWER_IMPLEMENTATION',
+ ],
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'app_list_shower.h',
+ 'app_list_shower_delegate.h',
+ 'app_list_shower_delegate_factory.h',
+ 'app_list_shower_export.h',
+ 'app_list_shower_impl.cc',
+ 'app_list_shower_impl.h',
+ ],
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ {
+ # GN version: //ui/app_list/shower:test_support
+ 'target_name': 'app_list_shower_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../skia/skia.gyp:skia',
+ 'app_list_shower',
+ ],
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'test/app_list_shower_impl_test_api.cc',
+ 'test/app_list_shower_impl_test_api.h',
+ ],
+ },
+ {
+ # GN version: //ui/app_list/shower:app_list_shower_unittests
+ 'target_name': 'app_list_shower_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../base/base.gyp:test_support_base',
+ '../../../skia/skia.gyp:skia',
+ '../../../testing/gtest.gyp:gtest',
+ '../../aura/aura.gyp:aura_test_support',
+ '../../resources/ui_resources.gyp:ui_test_pak',
+ '../../views/views.gyp:views',
+ '../../wm/wm.gyp:wm',
+ '../app_list.gyp:app_list_test_support',
+ 'app_list_shower',
+ 'app_list_shower_test_support',
+ ],
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'app_list_shower_impl_unittest.cc',
+ 'test/run_all_unittests.cc',
+ ],
+ # Disable c4267 warnings until we fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ ],
+ 'conditions': [
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
+ {
+ 'target_name': 'app_list_shower_unittests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'app_list_shower_unittests',
+ ],
+ 'includes': [
+ '../../../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'app_list_shower_unittests.isolate',
+ ],
+ 'conditions': [
+ ['use_x11 == 1', {
+ 'dependencies': [
+ '../../../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+ ],
+ }],
+ ],
+ },
+ ],
+ }],
+ ],
+}
diff --git a/chromium/ui/app_list/shower/app_list_shower_unittests.isolate b/chromium/ui/app_list/shower/app_list_shower_unittests.isolate
new file mode 100644
index 00000000000..2a89e3e7264
--- /dev/null
+++ b/chromium/ui/app_list/shower/app_list_shower_unittests.isolate
@@ -0,0 +1,78 @@
+# Copyright (c) 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.
+{
+ 'conditions': [
+ ['use_x11==0', {
+ 'variables': {
+ 'command': [
+ '../../../testing/test_env.py',
+ '<(PRODUCT_DIR)/app_list_shower_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ },
+ }],
+ ['use_x11==1', {
+ 'variables': {
+ 'command': [
+ '../../../testing/xvfb.py',
+ '<(PRODUCT_DIR)',
+ '<(PRODUCT_DIR)/app_list_shower_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ 'files': [
+ '../../../testing/xvfb.py',
+ '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
+ '../../../testing/test_env.py',
+ '<(PRODUCT_DIR)/ui_test.pak',
+ ],
+ },
+ }],
+ ['OS=="linux"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/libosmesa.so',
+ ],
+ },
+ }],
+ ['OS=="mac"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/osmesa.so',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/osmesa.dll',
+ ],
+ },
+ }],
+ ['OS=="mac" and asan==1 and fastbuild==0', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/app_list_shower_unittests.dSYM/',
+ '<(PRODUCT_DIR)/osmesa.so.dSYM/',
+ ],
+ },
+ }],
+ ],
+ 'includes': [
+ '../../../base/base.isolate',
+ ],
+}
diff --git a/chromium/ui/arc/BUILD.gn b/chromium/ui/arc/BUILD.gn
index 76a4b95e5f3..7b987aa7d9b 100644
--- a/chromium/ui/arc/BUILD.gn
+++ b/chromium/ui/arc/BUILD.gn
@@ -21,3 +21,21 @@ static_library("arc") {
"//ui/message_center",
]
}
+
+static_library("ui_arc_unittests") {
+ testonly = true
+ sources = [
+ "notification/arc_notification_manager_unittest.cc",
+ "test/run_all_unittests.cc",
+ ]
+
+ deps = [
+ ":arc",
+ "//base",
+ "//base/test:test_support",
+ "//components/arc:arc_test_support",
+ "//mojo/edk/system",
+ "//mojo/message_pump",
+ "//ui/message_center:test_support",
+ ]
+}
diff --git a/chromium/ui/arc/DEPS b/chromium/ui/arc/DEPS
index ea22bc1561d..b692d8152c9 100644
--- a/chromium/ui/arc/DEPS
+++ b/chromium/ui/arc/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+ash",
"+components/arc",
"+mojo",
]
diff --git a/chromium/ui/arc/arc.gyp b/chromium/ui/arc/arc.gyp
index b0789e13137..e1a40a766f9 100644
--- a/chromium/ui/arc/arc.gyp
+++ b/chromium/ui/arc/arc.gyp
@@ -8,15 +8,17 @@
},
'targets': [
{
+ # GN: //ui/arc:arc
'target_name': 'arc',
'type': 'static_library',
'include_dirs': [
- '..',
+ '../..',
],
'dependencies': [
'../gfx/gfx.gyp:gfx_geometry',
'../message_center/message_center.gyp:message_center',
'../../base/base.gyp:base',
+ '../../url/url.gyp:url_lib',
'../../skia/skia.gyp:skia',
'../../components/components.gyp:arc_mojo_bindings',
'../../components/components.gyp:signin_core_account_id',
@@ -28,5 +30,28 @@
'notification/arc_notification_item.h',
],
},
+ {
+ # GN: //ui/arc:ui_arc_unittests
+ 'target_name': 'ui_arc_unittests',
+ 'type': '<(gtest_target_type)',
+ 'include_dirs': [
+ '../..',
+ ],
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ '../../base/base.gyp:test_support_base',
+ '../../components/components.gyp:arc_test_support',
+ '../../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../../mojo/mojo_public.gyp:mojo_message_pump_lib',
+ '../../testing/gtest.gyp:gtest',
+ '../message_center/message_center.gyp:message_center_test_support',
+ 'arc',
+ ],
+ 'sources': [
+ 'notification/arc_notification_manager_unittest.cc',
+ 'test/run_all_unittests.cc',
+ ],
+ },
],
}
diff --git a/chromium/ui/arc/notification/arc_notification_item.cc b/chromium/ui/arc/notification/arc_notification_item.cc
index 05e67ab07ee..f0d791bbe90 100644
--- a/chromium/ui/arc/notification/arc_notification_item.cc
+++ b/chromium/ui/arc/notification/arc_notification_item.cc
@@ -60,6 +60,11 @@ class ArcNotificationDelegate : public message_center::NotificationDelegate {
item_->Click();
}
+ void ButtonClick(int button_index) override {
+ if (item_)
+ item_->ButtonClick(button_index);
+ }
+
private:
// The destructor is private since this class is ref-counted.
~ArcNotificationDelegate() override {}
@@ -104,15 +109,15 @@ void ArcNotificationItem::UpdateWithArcNotificationData(
message_center::NotificationType type;
switch (data.type) {
- case ARC_NOTIFICATION_TYPE_BASIC:
- type = message_center::NOTIFICATION_TYPE_SIMPLE;
+ case ArcNotificationType::BASIC:
+ type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
break;
- case ARC_NOTIFICATION_TYPE_IMAGE:
+ case ArcNotificationType::IMAGE:
// TODO(yoshiki): Implement this types.
- type = message_center::NOTIFICATION_TYPE_SIMPLE;
+ type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
LOG(ERROR) << "Unsupported notification type: image";
break;
- case ARC_NOTIFICATION_TYPE_PROGRESS:
+ case ArcNotificationType::PROGRESS:
type = message_center::NOTIFICATION_TYPE_PROGRESS;
rich_data.timestamp = base::Time::UnixEpoch() +
base::TimeDelta::FromMilliseconds(data.time);
@@ -122,8 +127,17 @@ void ArcNotificationItem::UpdateWithArcNotificationData(
data.progress_max * 100))));
break;
}
- DCHECK(0 <= data.type && data.type <= ARC_NOTIFICATION_TYPE_MAX)
- << "Unsupported notification type: " << data.type;
+ DCHECK(IsKnownEnumValue(data.type)) << "Unsupported notification type: "
+ << data.type;
+
+ for (size_t i = 0; i < data.buttons.size(); i++) {
+ rich_data.buttons.push_back(message_center::ButtonInfo(
+ base::UTF8ToUTF16(data.buttons.at(i)->label.get())));
+ }
+
+ // If the client is old (version < 1), both |no_clear| and |ongoing_event|
+ // are false.
+ rich_data.pinned = (data.no_clear || data.ongoing_event);
// The identifier of the notifier, which is used to distinguish the notifiers
// in the message center.
@@ -158,9 +172,9 @@ void ArcNotificationItem::UpdateWithArcNotificationData(
ArcNotificationItem::~ArcNotificationItem() {}
-void ArcNotificationItem::OnClosedFromAndroid() {
+void ArcNotificationItem::OnClosedFromAndroid(bool by_user) {
being_removed_by_manager_ = true; // Closing is initiated by the manager.
- message_center_->RemoveNotification(notification_id_, true /* by_user */);
+ message_center_->RemoveNotification(notification_id_, by_user);
}
void ArcNotificationItem::Close(bool by_user) {
@@ -179,6 +193,11 @@ void ArcNotificationItem::Click() {
manager_->SendNotificationClickedOnChrome(notification_key_);
}
+void ArcNotificationItem::ButtonClick(int button_index) {
+ manager_->SendNotificationButtonClickedOnChrome(
+ notification_key_, button_index);
+}
+
void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chromium/ui/arc/notification/arc_notification_item.h b/chromium/ui/arc/notification/arc_notification_item.h
index 902471686dd..8d8346ab8a6 100644
--- a/chromium/ui/arc/notification/arc_notification_item.h
+++ b/chromium/ui/arc/notification/arc_notification_item.h
@@ -30,11 +30,12 @@ class ArcNotificationItem {
void UpdateWithArcNotificationData(const ArcNotificationData& data);
// Methods called from ArcNotificationManager:
- void OnClosedFromAndroid();
+ void OnClosedFromAndroid(bool by_user);
// Methods called from ArcNotificationItemDelegate:
void Close(bool by_user);
void Click();
+ void ButtonClick(int button_index);
private:
void OnImageDecoded(const SkBitmap& bitmap);
diff --git a/chromium/ui/arc/notification/arc_notification_manager.cc b/chromium/ui/arc/notification/arc_notification_manager.cc
index 91b8c269b25..77869328be3 100644
--- a/chromium/ui/arc/notification/arc_notification_manager.cc
+++ b/chromium/ui/arc/notification/arc_notification_manager.cc
@@ -4,91 +4,184 @@
#include "ui/arc/notification/arc_notification_manager.h"
+#include "ash/shell.h"
+#include "ash/system/toast/toast_manager.h"
#include "base/stl_util.h"
#include "ui/arc/notification/arc_notification_item.h"
namespace arc {
-ArcNotificationManager::ArcNotificationManager(ArcBridgeService* arc_bridge,
+ArcNotificationManager::ArcNotificationManager(ArcBridgeService* bridge_service,
const AccountId& main_profile_id)
- : arc_bridge_(arc_bridge),
+ : ArcNotificationManager(bridge_service,
+ main_profile_id,
+ message_center::MessageCenter::Get()) {}
+
+ArcNotificationManager::ArcNotificationManager(
+ ArcBridgeService* bridge_service,
+ const AccountId& main_profile_id,
+ message_center::MessageCenter* message_center)
+ : ArcService(bridge_service),
main_profile_id_(main_profile_id),
+ message_center_(message_center),
binding_(this) {
- // This must be initialized after ArcBridgeService.
- DCHECK(arc_bridge_);
- DCHECK_EQ(arc_bridge_, ArcBridgeService::Get());
- arc_bridge_->AddObserver(this);
+ arc_bridge_service()->AddObserver(this);
}
ArcNotificationManager::~ArcNotificationManager() {
- // This should be free'd before ArcBridgeService.
- DCHECK(ArcBridgeService::Get());
- DCHECK_EQ(arc_bridge_, ArcBridgeService::Get());
- arc_bridge_->RemoveObserver(this);
+ arc_bridge_service()->RemoveObserver(this);
}
void ArcNotificationManager::OnNotificationsInstanceReady() {
- NotificationsInstance* notifications_instance =
- arc_bridge_->notifications_instance();
+ DCHECK(!ready_);
+
+ auto notifications_instance = arc_bridge_service()->notifications_instance();
if (!notifications_instance) {
VLOG(2) << "Request to refresh app list when bridge service is not ready.";
return;
}
- NotificationsHostPtr host;
- binding_.Bind(mojo::GetProxy(&host));
- notifications_instance->Init(std::move(host));
+ notifications_instance->Init(binding_.CreateInterfacePtrAndBind());
+ ready_ = true;
+}
+
+void ArcNotificationManager::OnNotificationsInstanceClosed() {
+ DCHECK(ready_);
+ while (!items_.empty()) {
+ auto it = items_.begin();
+ scoped_ptr<ArcNotificationItem> item = std::move(it->second);
+ items_.erase(it);
+ item->OnClosedFromAndroid(false /* by_user */);
+ }
+ ready_ = false;
}
void ArcNotificationManager::OnNotificationPosted(ArcNotificationDataPtr data) {
- ArcNotificationItem* item = items_.get(data->key);
- if (!item) {
+ const std::string& key = data->key;
+ auto it = items_.find(key);
+ if (it == items_.end()) {
// Show a notification on the primary loged-in user's desktop.
// TODO(yoshiki): Reconsider when ARC supports multi-user.
- item = new ArcNotificationItem(this, message_center::MessageCenter::Get(),
- data->key, main_profile_id_);
- items_.set(data->key, make_scoped_ptr(item));
+ ArcNotificationItem* item =
+ new ArcNotificationItem(this, message_center_, key, main_profile_id_);
+ // TODO(yoshiki): Use emplacement for performance when it's available.
+ auto result = items_.insert(std::make_pair(key, make_scoped_ptr(item)));
+ DCHECK(result.second);
+ it = result.first;
}
- item->UpdateWithArcNotificationData(*data);
+ it->second->UpdateWithArcNotificationData(*data);
}
void ArcNotificationManager::OnNotificationRemoved(const mojo::String& key) {
- ItemMap::iterator it = items_.find(key.get());
+ auto it = items_.find(key.get());
if (it == items_.end()) {
VLOG(3) << "Android requests to remove a notification (key: " << key
<< "), but it is already gone.";
return;
}
- scoped_ptr<ArcNotificationItem> item(items_.take_and_erase(it));
- item->OnClosedFromAndroid();
+ scoped_ptr<ArcNotificationItem> item = std::move(it->second);
+ items_.erase(it);
+ item->OnClosedFromAndroid(true /* by_user */);
}
void ArcNotificationManager::SendNotificationRemovedFromChrome(
const std::string& key) {
- ItemMap::iterator it = items_.find(key);
+ auto it = items_.find(key);
if (it == items_.end()) {
VLOG(3) << "Chrome requests to remove a notification (key: " << key
<< "), but it is already gone.";
return;
}
- scoped_ptr<ArcNotificationItem> item(items_.take_and_erase(it));
+ // The removed ArcNotificationItem needs to live in this scope, since the
+ // given argument |key| may be a part of the removed item.
+ scoped_ptr<ArcNotificationItem> item = std::move(it->second);
+ items_.erase(it);
- arc_bridge_->notifications_instance()->SendNotificationEventToAndroid(
- key, ARC_NOTIFICATION_EVENT_CLOSED);
+ auto notifications_instance = arc_bridge_service()->notifications_instance();
+
+ // On shutdown, the ARC channel may quit earlier then notifications.
+ if (!notifications_instance) {
+ VLOG(2) << "ARC Notification (key: " << key
+ << ") is closed, but the ARC channel has already gone.";
+ return;
+ }
+
+ notifications_instance->SendNotificationEventToAndroid(
+ key, ArcNotificationEvent::CLOSED);
}
void ArcNotificationManager::SendNotificationClickedOnChrome(
const std::string& key) {
- if (!items_.contains(key)) {
+ if (items_.find(key) == items_.end()) {
VLOG(3) << "Chrome requests to fire a click event on notification (key: "
<< key << "), but it is gone.";
return;
}
- arc_bridge_->notifications_instance()->SendNotificationEventToAndroid(
- key, ARC_NOTIFICATION_EVENT_BODY_CLICKED);
+ auto notifications_instance = arc_bridge_service()->notifications_instance();
+
+ // On shutdown, the ARC channel may quit earlier then notifications.
+ if (!notifications_instance) {
+ VLOG(2) << "ARC Notification (key: " << key
+ << ") is clicked, but the ARC channel has already gone.";
+ return;
+ }
+
+ notifications_instance->SendNotificationEventToAndroid(
+ key, ArcNotificationEvent::BODY_CLICKED);
+}
+
+void ArcNotificationManager::SendNotificationButtonClickedOnChrome(
+ const std::string& key, int button_index) {
+ if (items_.find(key) == items_.end()) {
+ VLOG(3) << "Chrome requests to fire a click event on notification (key: "
+ << key << "), but it is gone.";
+ return;
+ }
+
+ auto notifications_instance = arc_bridge_service()->notifications_instance();
+
+ // On shutdown, the ARC channel may quit earlier then notifications.
+ if (!notifications_instance) {
+ VLOG(2) << "ARC Notification (key: " << key
+ << ")'s button is clicked, but the ARC channel has already gone.";
+ return;
+ }
+
+ arc::ArcNotificationEvent command;
+ switch (button_index) {
+ case 0:
+ command = ArcNotificationEvent::BUTTON_1_CLICKED;
+ break;
+ case 1:
+ command = ArcNotificationEvent::BUTTON_2_CLICKED;
+ break;
+ case 2:
+ command = ArcNotificationEvent::BUTTON_3_CLICKED;
+ break;
+ case 3:
+ command = ArcNotificationEvent::BUTTON_4_CLICKED;
+ break;
+ case 4:
+ command = ArcNotificationEvent::BUTTON_5_CLICKED;
+ break;
+ default:
+ VLOG(3) << "Invalid button index (key: " << key << ", index: " <<
+ button_index << ").";
+ return;
+ }
+
+ notifications_instance->SendNotificationEventToAndroid(key, command);
+}
+
+void ArcNotificationManager::OnToastPosted(ArcToastDataPtr data) {
+ ash::Shell::GetInstance()->toast_manager()->Show(data->text, data->duration);
+}
+
+void ArcNotificationManager::OnToastCancelled(ArcToastDataPtr data) {
+ // TODO(yoshiki): Implement cancel.
}
} // namespace arc
diff --git a/chromium/ui/arc/notification/arc_notification_manager.h b/chromium/ui/arc/notification/arc_notification_manager.h
index d197be81e4b..7dfba3412f7 100644
--- a/chromium/ui/arc/notification/arc_notification_manager.h
+++ b/chromium/ui/arc/notification/arc_notification_manager.h
@@ -5,45 +5,59 @@
#ifndef UI_ARC_NOTIFICATION_ARC_NOTIFICATION_MANAGER_H_
#define UI_ARC_NOTIFICATION_ARC_NOTIFICATION_MANAGER_H_
-#include <map>
#include <string>
+#include <unordered_map>
-#include "base/containers/scoped_ptr_hash_map.h"
#include "components/arc/arc_bridge_service.h"
+#include "components/arc/arc_service.h"
#include "components/arc/common/notifications.mojom.h"
#include "components/signin/core/account_id/account_id.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "ui/message_center/message_center.h"
namespace arc {
class ArcNotificationItem;
-class ArcNotificationManager : public ArcBridgeService::Observer,
+class ArcNotificationManager : public ArcService,
+ public ArcBridgeService::Observer,
public NotificationsHost {
public:
ArcNotificationManager(ArcBridgeService* bridge_service,
const AccountId& main_profile_id);
+
+ ArcNotificationManager(ArcBridgeService* bridge_service,
+ const AccountId& main_profile_id,
+ message_center::MessageCenter* message_center);
+
~ArcNotificationManager() override;
// ArcBridgeService::Observer implementation:
void OnNotificationsInstanceReady() override;
+ void OnNotificationsInstanceClosed() override;
// NotificationsHost implementation:
void OnNotificationPosted(ArcNotificationDataPtr data) override;
void OnNotificationRemoved(const mojo::String& key) override;
+ void OnToastPosted(ArcToastDataPtr data) override;
+ void OnToastCancelled(ArcToastDataPtr data) override;
// Methods called from ArcNotificationItem:
void SendNotificationRemovedFromChrome(const std::string& key);
void SendNotificationClickedOnChrome(const std::string& key);
+ void SendNotificationButtonClickedOnChrome(
+ const std::string& key, int button_index);
private:
- ArcBridgeService* const arc_bridge_;
const AccountId main_profile_id_;
+ message_center::MessageCenter* const message_center_;
using ItemMap =
- base::ScopedPtrHashMap<std::string, scoped_ptr<ArcNotificationItem>>;
+ std::unordered_map<std::string, scoped_ptr<ArcNotificationItem>>;
ItemMap items_;
+ bool ready_ = false;
+
mojo::Binding<arc::NotificationsHost> binding_;
DISALLOW_COPY_AND_ASSIGN(ArcNotificationManager);
diff --git a/chromium/ui/arc/notification/arc_notification_manager_unittest.cc b/chromium/ui/arc/notification/arc_notification_manager_unittest.cc
new file mode 100644
index 00000000000..4241860725c
--- /dev/null
+++ b/chromium/ui/arc/notification/arc_notification_manager_unittest.cc
@@ -0,0 +1,187 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "components/arc/test/fake_arc_bridge_instance.h"
+#include "components/arc/test/fake_arc_bridge_service.h"
+#include "components/arc/test/fake_notifications_instance.h"
+#include "mojo/message_pump/message_pump_mojo.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/arc/notification/arc_notification_manager.h"
+#include "ui/message_center/fake_message_center.h"
+
+namespace arc {
+
+namespace {
+
+const char kDummyNotificationKey[] = "DUMMY_NOTIFICATION_KEY";
+
+class MockMessageCenter : public message_center::FakeMessageCenter {
+ public:
+ MockMessageCenter() {}
+ ~MockMessageCenter() override {
+ STLDeleteContainerPointers(
+ visible_notifications_.begin(), visible_notifications_.end());
+ }
+
+ void AddNotification(
+ scoped_ptr<message_center::Notification> notification) override {
+ visible_notifications_.insert(notification.release());
+ }
+
+ void RemoveNotification(const std::string& id, bool by_user) override {
+ for (auto it = visible_notifications_.begin();
+ it != visible_notifications_.end(); it++) {
+ if ((*it)->id() == id) {
+ delete *it;
+ visible_notifications_.erase(it);
+ return;
+ }
+ }
+ }
+
+ const message_center::NotificationList::Notifications&
+ GetVisibleNotifications() override {
+ return visible_notifications_;
+ }
+
+ private:
+ message_center::NotificationList::Notifications visible_notifications_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMessageCenter);
+};
+
+class ArcBridgeServiceObserver : public ArcBridgeService::Observer {
+ public:
+ ArcBridgeServiceObserver() = default;
+ void OnNotificationsInstanceReady() override { ready_ = true; }
+
+ bool IsReady() { return ready_; }
+
+ private:
+ bool ready_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ArcBridgeServiceObserver);
+};
+
+} // anonymous namespace
+
+class ArcNotificationManagerTest : public testing::Test {
+ public:
+ ArcNotificationManagerTest()
+ : loop_(mojo::common::MessagePumpMojo::Create()) {}
+ ~ArcNotificationManagerTest() override { loop_.RunUntilIdle(); }
+
+ protected:
+ FakeArcBridgeService* service() { return service_.get(); }
+ FakeNotificationsInstance* arc_notifications_instance() {
+ return arc_notifications_instance_.get();
+ }
+ ArcNotificationManager* arc_notification_manager() {
+ return arc_notification_manager_.get();
+ }
+ MockMessageCenter* message_center() { return message_center_.get(); }
+
+ std::string CreateNotification() {
+ return CreateNotificationWithKey(kDummyNotificationKey);
+ }
+
+ std::string CreateNotificationWithKey(const std::string& key) {
+ auto data = ArcNotificationData::New();
+ data->key = key;
+ data->title = "TITLE";
+ data->message = "MESSAGE";
+
+ std::vector<unsigned char> icon_data;
+ data->icon_data.Swap(&icon_data);
+
+ arc_notification_manager()->OnNotificationPosted(std::move(data));
+
+ return key;
+ }
+
+ private:
+ base::MessageLoop loop_;
+ scoped_ptr<FakeArcBridgeService> service_;
+ scoped_ptr<FakeNotificationsInstance> arc_notifications_instance_;
+ scoped_ptr<ArcNotificationManager> arc_notification_manager_;
+ scoped_ptr<MockMessageCenter> message_center_;
+
+ void SetUp() override {
+ NotificationsInstancePtr arc_notifications_instance;
+ arc_notifications_instance_.reset(
+ new FakeNotificationsInstance(GetProxy(&arc_notifications_instance)));
+ service_.reset(new FakeArcBridgeService());
+ message_center_.reset(new MockMessageCenter());
+
+ arc_notification_manager_.reset(new ArcNotificationManager(
+ service(), EmptyAccountId(), message_center_.get()));
+
+ ArcBridgeServiceObserver observer;
+ service_->AddObserver(&observer);
+ service_->OnNotificationsInstanceReady(
+ std::move(arc_notifications_instance));
+
+ while (!observer.IsReady())
+ loop_.RunUntilIdle();
+
+ service_->RemoveObserver(&observer);
+ }
+
+ void TearDown() override {
+ arc_notification_manager_.reset();
+ message_center_.reset();
+ service_.reset();
+ arc_notifications_instance_.reset();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ArcNotificationManagerTest);
+};
+
+TEST_F(ArcNotificationManagerTest, NotificationCreatedAndRemoved) {
+ EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
+ std::string key = CreateNotification();
+ EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
+
+ arc_notification_manager()->OnNotificationRemoved(key);
+
+ EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
+}
+
+TEST_F(ArcNotificationManagerTest, NotificationRemovedByChrome) {
+ service()->SetReady();
+ EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
+ std::string key = CreateNotification();
+ EXPECT_EQ(1u, message_center()->GetVisibleNotifications().size());
+
+ {
+ message_center::Notification* notification =
+ *message_center()->GetVisibleNotifications().begin();
+ notification->delegate()->Close(true /* by_user */);
+ // |notification| gets stale here.
+ }
+
+ arc_notifications_instance()->WaitForIncomingMethodCall();
+
+ ASSERT_EQ(1u, arc_notifications_instance()->events().size());
+ EXPECT_EQ(key, arc_notifications_instance()->events().at(0).first);
+ EXPECT_EQ(ArcNotificationEvent::CLOSED,
+ arc_notifications_instance()->events().at(0).second);
+}
+
+TEST_F(ArcNotificationManagerTest, NotificationRemovedByConnectionClose) {
+ service()->SetReady();
+ EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
+ CreateNotificationWithKey("notification1");
+ CreateNotificationWithKey("notification2");
+ CreateNotificationWithKey("notification3");
+ EXPECT_EQ(3u, message_center()->GetVisibleNotifications().size());
+
+ arc_notification_manager()->OnNotificationsInstanceClosed();
+
+ EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size());
+}
+
+} // namespace arc
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn
index 6f112e67766..b1b32287118 100644
--- a/chromium/ui/aura/BUILD.gn
+++ b/chromium/ui/aura/BUILD.gn
@@ -15,8 +15,6 @@ component("aura") {
"../wm/public/activation_delegate.h",
"../wm/public/animation_host.cc",
"../wm/public/animation_host.h",
- "../wm/public/dispatcher_client.cc",
- "../wm/public/dispatcher_client.h",
"../wm/public/drag_drop_client.cc",
"../wm/public/drag_drop_client.h",
"../wm/public/drag_drop_delegate.cc",
@@ -68,8 +66,6 @@ component("aura") {
"layout_manager.h",
"mus/mus_util.cc",
"mus/mus_util.h",
- "remote_window_tree_host_win.cc",
- "remote_window_tree_host_win.h",
"scoped_window_targeter.cc",
"scoped_window_targeter.h",
"window.cc",
@@ -135,7 +131,6 @@ component("aura") {
deps += [
"//ipc",
- "//ui/metro_viewer",
"//ui/platform_window/win",
]
}
@@ -252,46 +247,6 @@ executable("demo") {
}
}
-executable("bench") {
- output_name = "aura_bench"
- testonly = true
-
- sources = [
- "bench/bench_main.cc",
- ]
-
- deps = [
- ":test_support",
- "//base",
- "//base:i18n",
- "//build/config/sanitizers:deps",
- "//cc",
- "//gpu/command_buffer/client:gles2_interface",
- "//skia",
- "//third_party/icu",
- "//ui/base",
- "//ui/compositor",
- "//ui/compositor:test_support",
- "//ui/events",
- "//ui/gfx",
- "//ui/gfx/geometry",
- "//ui/gl",
- ]
-
- if (use_x11) {
- deps += [ "//ui/gfx/x" ]
- }
-}
-
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("aura_unittests_run") {
- testonly = true
- deps = [
- ":aura_unittests",
- ]
-}
-
test("aura_unittests") {
sources = [
"gestures/gesture_recognizer_unittest.cc",
@@ -303,7 +258,6 @@ test("aura_unittests") {
deps = [
":test_support",
- "//base/allocator",
"//base/test:test_support",
"//skia",
"//testing/gtest",
diff --git a/chromium/ui/aura/aura.gyp b/chromium/ui/aura/aura.gyp
index 12230e22965..3020e2d4da2 100644
--- a/chromium/ui/aura/aura.gyp
+++ b/chromium/ui/aura/aura.gyp
@@ -37,8 +37,6 @@
'../wm/public/activation_delegate.h',
'../wm/public/animation_host.cc',
'../wm/public/animation_host.h',
- '../wm/public/dispatcher_client.cc',
- '../wm/public/dispatcher_client.h',
'../wm/public/drag_drop_client.cc',
'../wm/public/drag_drop_client.h',
'../wm/public/drag_drop_delegate.cc',
@@ -88,8 +86,8 @@
'input_state_lookup_win.h',
'layout_manager.cc',
'layout_manager.h',
- 'remote_window_tree_host_win.cc',
- 'remote_window_tree_host_win.h',
+ 'mus/mus_util.cc',
+ 'mus/mus_util.h',
'scoped_window_targeter.cc',
'scoped_window_targeter.h',
'window.cc',
@@ -126,7 +124,6 @@
}],
['OS=="win"', {
'dependencies': [
- '../metro_viewer/metro_viewer.gyp:metro_viewer_messages',
'../platform_window/win/win_window.gyp:win_window',
'../../ipc/ipc.gyp:ipc',
],
@@ -140,12 +137,6 @@
'../ozone/ozone.gyp:ozone_base',
],
}],
- ['OS!="win" and OS!="android" and use_ozone==0', {
- 'sources!': [
- 'window_tree_host_platform.cc',
- 'window_tree_host_platform.h',
- ],
- }],
['OS=="android"', {
'dependencies': [
'../platform_window/android/android_window.gyp:android_window',
@@ -243,40 +234,6 @@
]
},
{
- 'target_name': 'aura_bench',
- 'type': 'executable',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../base/base.gyp:base_i18n',
- '../../cc/cc.gyp:cc',
- '../../gpu/gpu.gyp:gles2_implementation',
- '../../skia/skia.gyp:skia',
- '../../third_party/icu/icu.gyp:icui18n',
- '../../third_party/icu/icu.gyp:icuuc',
- '../base/ui_base.gyp:ui_base',
- '../compositor/compositor.gyp:compositor',
- '../compositor/compositor.gyp:compositor_test_support',
- '../events/events.gyp:events',
- '../gfx/gfx.gyp:gfx',
- '../gfx/gfx.gyp:gfx_geometry',
- 'aura',
- 'aura_test_support',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'bench/bench_main.cc',
- ],
- 'conditions': [
- ['use_x11==1', {
- 'dependencies': [
- '../gfx/x/gfx_x11.gyp:gfx_x11',
- ],
- }],
- ]
- },
- {
'target_name': 'aura_unittests',
'type': 'executable',
'dependencies': [
@@ -314,12 +271,6 @@
'<(DEPTH)/third_party/mesa/mesa.gyp:osmesa',
],
}],
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- # See http://crbug.com/162998#c4 for why this is needed.
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
],
},
],
diff --git a/chromium/ui/aura/bench/DEPS b/chromium/ui/aura/bench/DEPS
deleted file mode 100644
index 315ad72c16e..00000000000
--- a/chromium/ui/aura/bench/DEPS
+++ /dev/null
@@ -1,8 +0,0 @@
-include_rules = [
- "+cc",
- "-cc/blink",
- "-cc/surfaces",
- "+gpu/command_buffer/client/gles2_interface.h",
- "+third_party/khronos",
- "+ui/gl/gl_surface.h", # To initialize GL bindings.
-]
diff --git a/chromium/ui/aura/bench/bench_main.cc b/chromium/ui/aura/bench/bench_main.cc
deleted file mode 100644
index 918990a3679..00000000000
--- a/chromium/ui/aura/bench/bench_main.cc
+++ /dev/null
@@ -1,389 +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.
-
-#if defined(USE_X11)
-#include <X11/Xlib.h>
-#endif
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/i18n/icu_util.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_split.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "cc/output/context_provider.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/skia/include/core/SkXfermode.h"
-#include "ui/aura/client/default_capture_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/test/test_focus_client.h"
-#include "ui/aura/test/test_screen.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/hit_test.h"
-#include "ui/compositor/compositor.h"
-#include "ui/compositor/compositor_observer.h"
-#include "ui/compositor/debug_utils.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/paint_recorder.h"
-#include "ui/compositor/test/in_process_context_factory.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/skia_util.h"
-#include "ui/gfx/x/x11_connection.h"
-#include "ui/gl/gl_surface.h"
-
-#ifndef GL_GLEXT_PROTOTYPES
-#define GL_GLEXT_PROTOTYPES 1
-#endif
-#include "third_party/khronos/GLES2/gl2ext.h"
-
-using base::TimeTicks;
-using ui::Compositor;
-using ui::Layer;
-using ui::LayerDelegate;
-
-namespace {
-
-class ColoredLayer : public Layer, public LayerDelegate {
- public:
- explicit ColoredLayer(SkColor color)
- : Layer(ui::LAYER_TEXTURED),
- color_(color),
- draw_(true) {
- set_delegate(this);
- }
-
- ~ColoredLayer() override {}
-
- // Overridden from LayerDelegate:
- void OnPaintLayer(const ui::PaintContext& context) override {
- if (draw_) {
- ui::PaintRecorder recorder(context, size());
- recorder.canvas()->DrawColor(color_);
- }
- }
-
- void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
-
- void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
-
- base::Closure PrepareForLayerBoundsChange() override {
- return base::Closure();
- }
-
- void set_color(SkColor color) { color_ = color; }
- void set_draw(bool draw) { draw_ = draw; }
-
- private:
- SkColor color_;
- bool draw_;
-
- DISALLOW_COPY_AND_ASSIGN(ColoredLayer);
-};
-
-const int kFrames = 100;
-
-// Benchmark base class, hooks up drawing callback and displaying FPS.
-class BenchCompositorObserver : public ui::CompositorObserver {
- public:
- explicit BenchCompositorObserver(int max_frames)
- : start_time_(),
- frames_(0),
- max_frames_(max_frames) {
- }
- virtual ~BenchCompositorObserver() {}
-
- void OnCompositingDidCommit(ui::Compositor* compositor) override {}
-
- void OnCompositingStarted(Compositor* compositor,
- base::TimeTicks start_time) override {}
-
- void OnCompositingEnded(Compositor* compositor) override {
- if (start_time_.is_null()) {
- start_time_ = TimeTicks::Now();
- } else {
- ++frames_;
- if (frames_ % kFrames == 0) {
- TimeTicks now = TimeTicks::Now();
- double ms = (now - start_time_).InMillisecondsF() / kFrames;
- LOG(INFO) << "FPS: " << 1000.f / ms << " (" << ms << " ms)";
- start_time_ = now;
- }
- }
- if (max_frames_ && frames_ == max_frames_) {
- base::MessageLoop::current()->QuitWhenIdle();
- } else {
- Draw();
- }
- }
-
- void OnCompositingAborted(Compositor* compositor) override {}
-
- void OnCompositingLockStateChanged(Compositor* compositor) override {}
-
- void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
-
- virtual void Draw() {}
-
- int frames() const { return frames_; }
-
- private:
- TimeTicks start_time_;
- int frames_;
- int max_frames_;
-
- DISALLOW_COPY_AND_ASSIGN(BenchCompositorObserver);
-};
-
-void ReturnMailbox(scoped_refptr<cc::ContextProvider> context_provider,
- GLuint texture,
- const gpu::SyncToken& sync_token,
- bool is_lost) {
- gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
- gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
- gl->DeleteTextures(1, &texture);
- gl->ShallowFlushCHROMIUM();
-}
-
-gfx::Size GetFullscreenSize() {
-#if defined(OS_WIN)
- return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN));
-#else
- NOTIMPLEMENTED();
- return gfx::Size(1024, 768);
-#endif
-}
-
-// A benchmark that adds a texture layer that is updated every frame.
-class WebGLBench : public BenchCompositorObserver {
- public:
- WebGLBench(ui::ContextFactory* context_factory,
- Layer* parent,
- Compositor* compositor,
- int max_frames)
- : BenchCompositorObserver(max_frames),
- parent_(parent),
- webgl_(ui::LAYER_SOLID_COLOR),
- compositor_(compositor),
- fbo_(0),
- do_draw_(true) {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- do_draw_ = !command_line->HasSwitch("disable-draw");
-
- std::string webgl_size = command_line->GetSwitchValueASCII("webgl-size");
- int width = 0;
- int height = 0;
- if (!webgl_size.empty()) {
- std::vector<std::string> split_size = base::SplitString(
- webgl_size, "x", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (split_size.size() == 2) {
- width = atoi(split_size[0].c_str());
- height = atoi(split_size[1].c_str());
- }
- }
- if (!width || !height) {
- width = 800;
- height = 600;
- }
- gfx::Rect bounds(width, height);
- webgl_.SetBounds(bounds);
- parent_->Add(&webgl_);
-
- context_provider_ = context_factory->SharedMainThreadContextProvider();
- gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
- GLuint texture = 0;
- gl->GenTextures(1, &texture);
- gl->BindTexture(GL_TEXTURE_2D, texture);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- width,
- height,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
- gpu::Mailbox mailbox;
- gl->GenMailboxCHROMIUM(mailbox.name);
- gl->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
-
- gl->GenFramebuffers(1, &fbo_);
- gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
- gl->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
- gl->ClearColor(0.f, 1.f, 0.f, 1.f);
- gl->Clear(GL_COLOR_BUFFER_BIT);
-
- const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
- gl->Flush();
-
- gpu::SyncToken sync_token;
- gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
- webgl_.SetTextureMailbox(
- cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D),
- cc::SingleReleaseCallback::Create(
- base::Bind(ReturnMailbox, context_provider_, texture)),
- bounds.size());
- compositor->AddObserver(this);
- }
-
- ~WebGLBench() override {
- webgl_.SetShowSolidColorContent();
- gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
- gl->DeleteFramebuffers(1, &fbo_);
- compositor_->RemoveObserver(this);
- }
-
- void Draw() override {
- if (do_draw_) {
- gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
- gl->ClearColor((frames() % kFrames)*1.0/kFrames, 1.f, 0.f, 1.f);
- gl->Clear(GL_COLOR_BUFFER_BIT);
- gl->Flush();
- }
- webgl_.SchedulePaint(gfx::Rect(webgl_.bounds().size()));
- compositor_->ScheduleDraw();
- }
-
- private:
- Layer* parent_;
- Layer webgl_;
- Compositor* compositor_;
- scoped_refptr<cc::ContextProvider> context_provider_;
-
- // The FBO that is used to render to the texture.
- unsigned int fbo_;
-
- // Whether or not to draw to the texture every frame.
- bool do_draw_;
-
- DISALLOW_COPY_AND_ASSIGN(WebGLBench);
-};
-
-// A benchmark that paints (in software) all tiles every frame.
-class SoftwareScrollBench : public BenchCompositorObserver {
- public:
- SoftwareScrollBench(ColoredLayer* layer,
- Compositor* compositor,
- int max_frames)
- : BenchCompositorObserver(max_frames),
- layer_(layer),
- compositor_(compositor) {
- compositor->AddObserver(this);
- layer_->set_draw(
- !base::CommandLine::ForCurrentProcess()->HasSwitch("disable-draw"));
- }
-
- ~SoftwareScrollBench() override { compositor_->RemoveObserver(this); }
-
- void Draw() override {
- layer_->set_color(
- SkColorSetARGBInline(255*(frames() % kFrames)/kFrames, 255, 0, 255));
- layer_->SchedulePaint(gfx::Rect(layer_->bounds().size()));
- }
-
- private:
- ColoredLayer* layer_;
- Compositor* compositor_;
-
- DISALLOW_COPY_AND_ASSIGN(SoftwareScrollBench);
-};
-
-} // namespace
-
-int main(int argc, char** argv) {
- base::CommandLine::Init(argc, argv);
-
- base::AtExitManager exit_manager;
-
-#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.
- bool context_factory_for_test = false;
- scoped_ptr<ui::InProcessContextFactory> context_factory(
- new ui::InProcessContextFactory(context_factory_for_test, nullptr));
-
- base::i18n::InitializeICU();
-
- base::MessageLoopForUI message_loop;
- aura::Env::CreateInstance(true);
- aura::Env::GetInstance()->set_context_factory(context_factory.get());
- scoped_ptr<aura::TestScreen> test_screen(
- aura::TestScreen::Create(GetFullscreenSize()));
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
- scoped_ptr<aura::WindowTreeHost> host(
- test_screen->CreateHostForPrimaryDisplay());
- aura::client::SetCaptureClient(
- host->window(),
- new aura::client::DefaultCaptureClient(host->window()));
-
- scoped_ptr<aura::client::FocusClient> focus_client(
- new aura::test::TestFocusClient);
- aura::client::SetFocusClient(host->window(), focus_client.get());
-
- // add layers
- ColoredLayer background(SK_ColorRED);
- background.SetBounds(host->window()->bounds());
- host->window()->layer()->Add(&background);
-
- ColoredLayer window(SK_ColorBLUE);
- window.SetBounds(gfx::Rect(background.bounds().size()));
- background.Add(&window);
-
- Layer content_layer(ui::LAYER_NOT_DRAWN);
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- bool force = command_line->HasSwitch("force-render-surface");
- content_layer.SetForceRenderSurface(force);
- gfx::Rect bounds(window.bounds().size());
- bounds.Inset(0, 30, 0, 0);
- content_layer.SetBounds(bounds);
- window.Add(&content_layer);
-
- ColoredLayer page_background(SK_ColorWHITE);
- page_background.SetBounds(gfx::Rect(content_layer.bounds().size()));
- content_layer.Add(&page_background);
-
- int frames = atoi(command_line->GetSwitchValueASCII("frames").c_str());
- scoped_ptr<BenchCompositorObserver> bench;
-
- if (command_line->HasSwitch("bench-software-scroll")) {
- bench.reset(new SoftwareScrollBench(&page_background,
- host->compositor(),
- frames));
- } else {
- bench.reset(new WebGLBench(context_factory.get(),
- &page_background,
- host->compositor(),
- frames));
- }
-
-#ifndef NDEBUG
- ui::PrintLayerHierarchy(host->window()->layer(), gfx::Point(100, 100));
-#endif
-
- host->Show();
- base::MessageLoopForUI::current()->Run();
- focus_client.reset();
- host.reset();
-
- return 0;
-}
diff --git a/chromium/ui/aura/demo/demo_main.cc b/chromium/ui/aura/demo/demo_main.cc
index f485a8ce954..ea86753f8b3 100644
--- a/chromium/ui/aura/demo/demo_main.cc
+++ b/chromium/ui/aura/demo/demo_main.cc
@@ -30,7 +30,7 @@
#include "ui/gl/gl_surface.h"
#if defined(USE_X11)
-#include "ui/gfx/x/x11_connection.h"
+#include "ui/gfx/x/x11_connection.h" // nogncheck
#endif
#if defined(OS_WIN)
@@ -150,7 +150,7 @@ int DemoMain() {
aura::Env::GetInstance()->set_context_factory(context_factory.get());
scoped_ptr<aura::TestScreen> test_screen(
aura::TestScreen::Create(gfx::Size()));
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen.get());
+ gfx::Screen::SetScreenInstance(test_screen.get());
scoped_ptr<aura::WindowTreeHost> host(
test_screen->CreateHostForPrimaryDisplay());
scoped_ptr<DemoWindowTreeClient> window_tree_client(
diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc
index 148300ca43b..7e82d4e13cd 100644
--- a/chromium/ui/aura/env.cc
+++ b/chromium/ui/aura/env.cc
@@ -4,6 +4,7 @@
#include "ui/aura/env.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "ui/aura/env_observer.h"
@@ -23,6 +24,14 @@ namespace {
base::LazyInstance<base::ThreadLocalPointer<Env> >::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
+#if defined(USE_OZONE)
+// Returns true if running inside of mus. Checks for mojo specific flag.
+bool RunningInsideMus() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ "primordial-pipe-token");
+}
+#endif
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -84,12 +93,16 @@ Env::~Env() {
}
void Env::Init(bool create_event_source) {
+ if (!create_event_source)
+ return;
#if defined(USE_OZONE)
// The ozone platform can provide its own event source. So initialize the
- // platform before creating the default event source.
- ui::OzonePlatform::InitializeForUI();
+ // platform before creating the default event source. If running inside mus
+ // let the mus process initialize ozone instead.
+ if (!RunningInsideMus())
+ ui::OzonePlatform::InitializeForUI();
#endif
- if (create_event_source && !ui::PlatformEventSource::GetInstance())
+ if (!ui::PlatformEventSource::GetInstance())
event_source_ = ui::PlatformEventSource::CreateDefault();
}
diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
index 820c914672d..64057fe5814 100644
--- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -638,6 +638,18 @@ void DelayByShowPressTimeout() {
run_loop.Run();
}
+void SetTouchRadius(ui::TouchEvent* event, float radius_x, float radius_y) {
+ // Using ctor (over direct struct access) due to it's special behavior with
+ // radii.
+ ui::PointerDetails details(ui::EventPointerType::POINTER_TYPE_TOUCH,
+ radius_x,
+ radius_y,
+ event->pointer_details().force,
+ event->pointer_details().tilt_x,
+ event->pointer_details().tilt_y);
+ event->set_pointer_details(details);
+}
+
} // namespace
class GestureRecognizerTest : public AuraTestBase,
@@ -738,8 +750,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
kTouchId, tes.Now());
- press.set_radius_x(5);
- press.set_radius_y(12);
+ SetTouchRadius(&press, 5, 12);
DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -755,8 +766,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
kTouchId, tes.LeapForward(50));
- release.set_radius_x(5);
- release.set_radius_y(12);
+ SetTouchRadius(&release, 5, 12);
DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
@@ -781,8 +791,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(365, 290),
kTouchId, tes.Now());
- press.set_radius_x(8);
- press.set_radius_y(14);
+ SetTouchRadius(&press, 8, 14);
DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -796,8 +805,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(367, 291),
kTouchId, tes.LeapForward(50));
- release.set_radius_x(20);
- release.set_radius_y(13);
+ SetTouchRadius(&release, 20, 13);
DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
@@ -822,8 +830,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(46, 205),
kTouchId, tes.Now());
- press.set_radius_x(6);
- press.set_radius_y(10);
+ SetTouchRadius(&press, 6, 10);
DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -838,8 +845,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(49, 204),
kTouchId, tes.LeapForward(50));
- move.set_radius_x(8);
- move.set_radius_y(12);
+ SetTouchRadius(&move, 8, 12);
DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
@@ -853,8 +859,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(49, 204),
kTouchId, tes.LeapForward(50));
- release.set_radius_x(4);
- release.set_radius_y(8);
+ SetTouchRadius(&release, 4, 8);
DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
@@ -879,8 +884,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(400, 150),
kTouchId, tes.Now());
- press.set_radius_x(7);
- press.set_radius_y(10);
+ SetTouchRadius(&press, 7, 10);
DispatchEventUsingWindowDispatcher(&press);
EXPECT_FALSE(delegate->tap());
EXPECT_TRUE(delegate->tap_down());
@@ -894,8 +898,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(397, 151),
kTouchId, tes.LeapForward(50));
- move.set_radius_x(13);
- move.set_radius_y(12);
+ SetTouchRadius(&move, 13, 12);
DispatchEventUsingWindowDispatcher(&move);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
@@ -909,8 +912,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(397, 149),
kTouchId, tes.LeapForward(50));
- move1.set_radius_x(16);
- move1.set_radius_y(16);
+ SetTouchRadius(&move1, 16, 16);
DispatchEventUsingWindowDispatcher(&move1);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
@@ -924,8 +926,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(400, 150),
kTouchId, tes.LeapForward(50));
- move2.set_radius_x(14);
- move2.set_radius_y(10);
+ SetTouchRadius(&move2, 14, 10);
DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_down());
@@ -939,8 +940,7 @@ TEST_F(GestureRecognizerTest, GestureEventTapRegion) {
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(401, 149),
kTouchId, tes.LeapForward(50));
- release.set_radius_x(8);
- release.set_radius_y(9);
+ SetTouchRadius(&release, 8, 9);
DispatchEventUsingWindowDispatcher(&release);
EXPECT_TRUE(delegate->tap());
@@ -2532,7 +2532,7 @@ TEST_F(GestureRecognizerTest, PressDoesNotCrash) {
delegate.get(), -1234, gfx::Rect(10, 10, 300, 300), root_window()));
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(45, 45), 7, tes.Now());
- press.set_radius_x(40);
+ SetTouchRadius(&press, 40, 0);
DispatchEventUsingWindowDispatcher(&press);
EXPECT_TRUE(delegate->tap_down());
EXPECT_EQ(gfx::Rect(5, 5, 80, 80).ToString(),
@@ -3462,7 +3462,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
ui::TouchEvent press2(
ui::ET_TOUCH_PRESSED, gfx::Point(201, 201), kTouchId2,
tes.LeapForward(400));
- press2.set_radius_x(5);
+ SetTouchRadius(&press2, 5, 0);
DispatchEventUsingWindowDispatcher(&press2);
EXPECT_FALSE(delegate->pinch_begin());
EXPECT_EQ(gfx::Rect(101, 196, 105, 10).ToString(),
@@ -3482,8 +3482,7 @@ TEST_F(GestureRecognizerTest, BoundingBoxRadiusChange) {
// The position doesn't move, but the radius changes.
ui::TouchEvent move2(
ui::ET_TOUCH_MOVED, gfx::Point(50, 50), kTouchId, tes.LeapForward(40));
- move2.set_radius_x(50);
- move2.set_radius_y(60);
+ SetTouchRadius(&move2, 50, 60);
DispatchEventUsingWindowDispatcher(&move2);
EXPECT_FALSE(delegate->tap());
EXPECT_FALSE(delegate->tap_cancel());
diff --git a/chromium/ui/aura/mus/mus_util.cc b/chromium/ui/aura/mus/mus_util.cc
index ed57f6a6e1a..468b336c450 100644
--- a/chromium/ui/aura/mus/mus_util.cc
+++ b/chromium/ui/aura/mus/mus_util.cc
@@ -5,17 +5,26 @@
#include "ui/aura/mus/mus_util.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
namespace aura {
+namespace {
+
+// This code uses Set/GetNativeWindowProperty instead of Set/GetProperty to
+// avoid a dependency on mus.
+const char kMusWindowKey[] = "mus";
+
+} // namespace
mus::Window* GetMusWindow(Window* window) {
if (!window)
return nullptr;
- return static_cast<mus::Window*>(window->GetNativeWindowProperty("mus"));
+ return static_cast<mus::Window*>(
+ window->GetNativeWindowProperty(kMusWindowKey));
}
void SetMusWindow(Window* window, mus::Window* mus_window) {
- window->SetNativeWindowProperty("mus", mus_window);
+ window->SetNativeWindowProperty(kMusWindowKey, mus_window);
}
} // namespace aura
diff --git a/chromium/ui/aura/remote_window_tree_host_win.cc b/chromium/ui/aura/remote_window_tree_host_win.cc
deleted file mode 100644
index a303d98ec99..00000000000
--- a/chromium/ui/aura/remote_window_tree_host_win.cc
+++ /dev/null
@@ -1,522 +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/aura/remote_window_tree_host_win.h"
-
-#include <windows.h>
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/message_loop/message_loop.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "ui/aura/client/cursor_client.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/composition_text.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/remote_input_method_win.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/base/view_prop.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_code_conversion_win.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/metro_viewer/metro_viewer_messages.h"
-
-namespace aura {
-
-namespace {
-
-const char* kWindowTreeHostWinKey = "__AURA_REMOTE_WINDOW_TREE_HOST_WIN__";
-
-// Sets the keystate for the virtual key passed in to down or up.
-void SetKeyState(uint8_t* key_states,
- bool key_down,
- uint32_t virtual_key_code) {
- DCHECK(key_states);
-
- if (key_down)
- key_states[virtual_key_code] |= 0x80;
- else
- key_states[virtual_key_code] &= 0x7F;
-}
-
-// Sets the keyboard states for the Shift/Control/Alt/Caps lock keys.
-void SetVirtualKeyStates(uint32_t flags) {
- uint8_t keyboard_state[256] = {0};
- ::GetKeyboardState(keyboard_state);
-
- SetKeyState(keyboard_state, !!(flags & ui::EF_SHIFT_DOWN), VK_SHIFT);
- SetKeyState(keyboard_state, !!(flags & ui::EF_CONTROL_DOWN), VK_CONTROL);
- SetKeyState(keyboard_state, !!(flags & ui::EF_ALT_DOWN), VK_MENU);
- SetKeyState(keyboard_state, !!(flags & ui::EF_CAPS_LOCK_ON), VK_CAPITAL);
- SetKeyState(keyboard_state, !!(flags & ui::EF_LEFT_MOUSE_BUTTON), VK_LBUTTON);
- SetKeyState(keyboard_state, !!(flags & ui::EF_RIGHT_MOUSE_BUTTON),
- VK_RBUTTON);
- SetKeyState(keyboard_state, !!(flags & ui::EF_MIDDLE_MOUSE_BUTTON),
- VK_MBUTTON);
-
- ::SetKeyboardState(keyboard_state);
-}
-
-void FillCompositionText(
- const base::string16& text,
- int32_t selection_start,
- int32_t selection_end,
- const std::vector<metro_viewer::UnderlineInfo>& underlines,
- ui::CompositionText* composition_text) {
- composition_text->Clear();
- composition_text->text = text;
- composition_text->selection.set_start(selection_start);
- composition_text->selection.set_end(selection_end);
- composition_text->underlines.resize(underlines.size());
- for (size_t i = 0; i < underlines.size(); ++i) {
- composition_text->underlines[i].start_offset = underlines[i].start_offset;
- composition_text->underlines[i].end_offset = underlines[i].end_offset;
- composition_text->underlines[i].color = SK_ColorBLACK;
- composition_text->underlines[i].thick = underlines[i].thick;
- composition_text->underlines[i].background_color = SK_ColorTRANSPARENT;
- }
-}
-
-} // namespace
-
-RemoteWindowTreeHostWin* g_instance = NULL;
-
-// static
-RemoteWindowTreeHostWin* RemoteWindowTreeHostWin::Instance() {
- return g_instance;
-}
-
-RemoteWindowTreeHostWin::RemoteWindowTreeHostWin()
- : remote_window_(NULL),
- host_(NULL),
- ignore_mouse_moves_until_set_cursor_ack_(0),
- event_flags_(0),
- window_size_(GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN)) {
- CHECK(!g_instance);
- g_instance = this;
- prop_.reset(new ui::ViewProp(NULL, kWindowTreeHostWinKey, this));
- CreateCompositor();
- OnAcceleratedWidgetAvailable();
-}
-
-RemoteWindowTreeHostWin::~RemoteWindowTreeHostWin() {
- DestroyCompositor();
- DestroyDispatcher();
- DCHECK_EQ(g_instance, this);
- g_instance = NULL;
-}
-
-// static
-bool RemoteWindowTreeHostWin::IsValid() {
- return Instance()->remote_window_ != NULL;
-}
-
-void RemoteWindowTreeHostWin::SetRemoteWindowHandle(HWND remote_window) {
- remote_window_ = remote_window;
-}
-
-void RemoteWindowTreeHostWin::Connected(IPC::Sender* host) {
- CHECK(host_ == NULL);
- DCHECK(remote_window_);
- host_ = host;
- // Recreate the compositor for the target surface represented by the
- // remote_window HWND.
- CreateCompositor();
- OnAcceleratedWidgetAvailable();
- InitCompositor();
-}
-
-void RemoteWindowTreeHostWin::Disconnected() {
- // Don't CHECK here, Disconnected is called on a channel error which can
- // happen before we're successfully Connected.
- if (!host_)
- return;
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (remote_input_method_private)
- remote_input_method_private->SetRemoteDelegate(NULL);
- host_ = NULL;
- remote_window_ = NULL;
-}
-
-bool RemoteWindowTreeHostWin::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RemoteWindowTreeHostWin, message)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseMoved, OnMouseMoved)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MouseButton, OnMouseButton)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyDown, OnKeyDown)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_KeyUp, OnKeyUp)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_Character, OnChar)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowActivated,
- OnWindowActivated)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_EdgeGesture, OnEdgeGesture)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchDown,
- OnTouchDown)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchUp,
- OnTouchUp)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_TouchMoved,
- OnTouchMoved)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetCursorPosAck,
- OnSetCursorPosAck)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCandidatePopupChanged,
- OnImeCandidatePopupChanged)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeCompositionChanged,
- OnImeCompositionChanged)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeTextCommitted,
- OnImeTextCommitted)
- IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ImeInputSourceChanged,
- OnImeInputSourceChanged)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void RemoteWindowTreeHostWin::HandleOpenURLOnDesktop(
- const base::FilePath& shortcut,
- const base::string16& url) {
- if (!host_)
- return;
- host_->Send(new MetroViewerHostMsg_OpenURLOnDesktop(shortcut, url));
-}
-
-void RemoteWindowTreeHostWin::HandleWindowSizeChanged(uint32_t width,
- uint32_t height) {
- SetBounds(gfx::Rect(0, 0, width, height));
-}
-
-bool RemoteWindowTreeHostWin::IsForegroundWindow() {
- return ::GetForegroundWindow() == remote_window_;
-}
-
-Window* RemoteWindowTreeHostWin::GetAshWindow() {
- return window();
-}
-
-ui::EventSource* RemoteWindowTreeHostWin::GetEventSource() {
- return this;
-}
-
-gfx::AcceleratedWidget RemoteWindowTreeHostWin::GetAcceleratedWidget() {
- if (remote_window_)
- return remote_window_;
- // Getting here should only happen for ash_unittests.exe and related code.
- return ::GetDesktopWindow();
-}
-
-void RemoteWindowTreeHostWin::ShowImpl() {
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (remote_input_method_private)
- remote_input_method_private->SetRemoteDelegate(this);
-}
-
-void RemoteWindowTreeHostWin::HideImpl() {
- NOTIMPLEMENTED();
-}
-
-gfx::Rect RemoteWindowTreeHostWin::GetBounds() const {
- return gfx::Rect(window_size_);
-}
-
-void RemoteWindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
- window_size_ = bounds.size();
- OnHostResized(bounds.size());
-}
-
-gfx::Point RemoteWindowTreeHostWin::GetLocationOnNativeScreen() const {
- return gfx::Point(0, 0);
-}
-
-void RemoteWindowTreeHostWin::SetCapture() {
-}
-
-void RemoteWindowTreeHostWin::ReleaseCapture() {
-}
-
-void RemoteWindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
- if (!host_)
- return;
- host_->Send(
- new MetroViewerHostMsg_SetCursor(uint64_t(native_cursor.platform())));
-}
-
-void RemoteWindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
- VLOG(1) << "In MoveCursorTo: " << location.x() << ", " << location.y();
- if (!host_)
- return;
-
- // This function can be called in cases like when the mouse cursor is
- // restricted within a viewport (For e.g. LockCursor) which assumes that
- // subsequent mouse moves would be received starting with the new cursor
- // coordinates. This is a challenge for Windows ASH for the reasons
- // outlined below.
- // Other cases which don't expect this behavior should continue to work
- // without issues.
-
- // The mouse events are received by the viewer process and sent to the
- // browser. If we invoke the SetCursor API here we continue to receive
- // mouse messages from the viewer which were posted before the SetCursor
- // API executes which messes up the state in the browser. To workaround
- // this we invoke the SetCursor API in the viewer process and ignore
- // mouse messages until we received an ACK from the viewer indicating that
- // the SetCursor operation completed.
- ignore_mouse_moves_until_set_cursor_ack_++;
- VLOG(1) << "In MoveCursorTo. Sending IPC";
- host_->Send(new MetroViewerHostMsg_SetCursorPos(location.x(), location.y()));
-}
-
-void RemoteWindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
- NOTIMPLEMENTED();
-}
-
-void RemoteWindowTreeHostWin::CancelComposition() {
- if (!host_)
- return;
- host_->Send(new MetroViewerHostMsg_ImeCancelComposition);
-}
-
-void RemoteWindowTreeHostWin::OnTextInputClientUpdated(
- const std::vector<int32_t>& input_scopes,
- const std::vector<gfx::Rect>& composition_character_bounds) {
- if (!host_)
- return;
- std::vector<metro_viewer::CharacterBounds> character_bounds;
- for (size_t i = 0; i < composition_character_bounds.size(); ++i) {
- const gfx::Rect& rect = composition_character_bounds[i];
- metro_viewer::CharacterBounds bounds;
- bounds.left = rect.x();
- bounds.top = rect.y();
- bounds.right = rect.right();
- bounds.bottom = rect.bottom();
- character_bounds.push_back(bounds);
- }
- host_->Send(new MetroViewerHostMsg_ImeTextInputClientUpdated(
- input_scopes, character_bounds));
-}
-
-gfx::Point PointFromNativeEvent(int32_t x, int32_t y) {
- static float scale_factor = gfx::GetDPIScale();
- gfx::Point result( x * scale_factor, y * scale_factor);
- return result;
-}
-
-void RemoteWindowTreeHostWin::OnMouseMoved(int32_t x,
- int32_t y,
- int32_t flags) {
- if (ignore_mouse_moves_until_set_cursor_ack_)
- return;
-
- gfx::Point location = PointFromNativeEvent(x, y);
- ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
- ui::EventTimeForNow(), flags, 0);
- SendEventToProcessor(&event);
-}
-
-void RemoteWindowTreeHostWin::OnMouseButton(
- const MetroViewerHostMsg_MouseButtonParams& params) {
- gfx::Point location = PointFromNativeEvent(params.x, params.y);
- ui::MouseEvent mouse_event(
- params.event_type, location, location, ui::EventTimeForNow(),
- static_cast<int>(params.flags), static_cast<int>(params.changed_button));
-
- SetEventFlags(params.flags | key_event_flags());
- if (params.event_type == ui::ET_MOUSEWHEEL) {
- int x_offset = params.is_horizontal_wheel ? params.extra : 0;
- int y_offset = !params.is_horizontal_wheel ? params.extra : 0;
- ui::MouseWheelEvent wheel_event(mouse_event, x_offset, y_offset);
- SendEventToProcessor(&wheel_event);
- } else if (params.event_type == ui::ET_MOUSE_PRESSED) {
- // TODO(shrikant): Ideally modify code in event.cc by adding automatic
- // tracking of double clicks in synthetic MouseEvent constructor code.
- // Non-synthetic MouseEvent constructor code does automatically track
- // this. Need to use some caution while modifying synthetic constructor
- // as many tests and other code paths depend on it and apparently
- // specifically depend on non implicit tracking of previous mouse event.
- if (last_mouse_click_event_ &&
- ui::MouseEvent::IsRepeatedClickEvent(mouse_event,
- *last_mouse_click_event_)) {
- mouse_event.SetClickCount(2);
- } else {
- mouse_event.SetClickCount(1);
- }
- last_mouse_click_event_ .reset(new ui::MouseEvent(mouse_event));
- SendEventToProcessor(&mouse_event);
- } else {
- SendEventToProcessor(&mouse_event);
- }
-}
-
-void RemoteWindowTreeHostWin::OnKeyDown(uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags) {
- DispatchKeyboardMessage(ui::ET_KEY_PRESSED, vkey, repeat_count, scan_code,
- flags, false);
-}
-
-void RemoteWindowTreeHostWin::OnKeyUp(uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags) {
- DispatchKeyboardMessage(ui::ET_KEY_RELEASED, vkey, repeat_count, scan_code,
- flags, false);
-}
-
-void RemoteWindowTreeHostWin::OnChar(uint32_t key_code,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags) {
- DispatchKeyboardMessage(ui::ET_KEY_PRESSED, key_code, repeat_count,
- scan_code, flags, true);
-}
-
-void RemoteWindowTreeHostWin::OnWindowActivated(bool repaint) {
- OnHostActivated();
- if (repaint && compositor())
- compositor()->ScheduleFullRedraw();
-}
-
-void RemoteWindowTreeHostWin::OnEdgeGesture() {
- ui::GestureEvent event(
- 0,
- 0,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_WIN8_EDGE_SWIPE));
- SendEventToProcessor(&event);
-}
-
-void RemoteWindowTreeHostWin::OnTouchDown(int32_t x,
- int32_t y,
- uint64_t timestamp,
- uint32_t pointer_id) {
- gfx::Point location = PointFromNativeEvent(x, y);
- ui::TouchEvent event(ui::ET_TOUCH_PRESSED,
- location,
- pointer_id,
- base::TimeDelta::FromMicroseconds(timestamp));
- SendEventToProcessor(&event);
-}
-
-void RemoteWindowTreeHostWin::OnTouchUp(int32_t x,
- int32_t y,
- uint64_t timestamp,
- uint32_t pointer_id) {
- gfx::Point location = PointFromNativeEvent(x, y);
- ui::TouchEvent event(ui::ET_TOUCH_RELEASED,
- location,
- pointer_id,
- base::TimeDelta::FromMicroseconds(timestamp));
- SendEventToProcessor(&event);
-}
-
-void RemoteWindowTreeHostWin::OnTouchMoved(int32_t x,
- int32_t y,
- uint64_t timestamp,
- uint32_t pointer_id) {
- gfx::Point location = PointFromNativeEvent(x, y);
- ui::TouchEvent event(ui::ET_TOUCH_MOVED,
- location,
- pointer_id,
- base::TimeDelta::FromMicroseconds(timestamp));
- SendEventToProcessor(&event);
-}
-
-void RemoteWindowTreeHostWin::OnSetCursorPosAck() {
- DCHECK_GT(ignore_mouse_moves_until_set_cursor_ack_, 0);
- ignore_mouse_moves_until_set_cursor_ack_--;
-}
-
-ui::RemoteInputMethodPrivateWin*
-RemoteWindowTreeHostWin::GetRemoteInputMethodPrivate() {
- return ui::RemoteInputMethodPrivateWin::Get(GetInputMethod());
-}
-
-void RemoteWindowTreeHostWin::OnImeCandidatePopupChanged(bool visible) {
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (!remote_input_method_private)
- return;
- remote_input_method_private->OnCandidatePopupChanged(visible);
-}
-
-void RemoteWindowTreeHostWin::OnImeCompositionChanged(
- const base::string16& text,
- int32_t selection_start,
- int32_t selection_end,
- const std::vector<metro_viewer::UnderlineInfo>& underlines) {
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (!remote_input_method_private)
- return;
- ui::CompositionText composition_text;
- FillCompositionText(
- text, selection_start, selection_end, underlines, &composition_text);
- remote_input_method_private->OnCompositionChanged(composition_text);
-}
-
-void RemoteWindowTreeHostWin::OnImeTextCommitted(const base::string16& text) {
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (!remote_input_method_private)
- return;
- remote_input_method_private->OnTextCommitted(text);
-}
-
-void RemoteWindowTreeHostWin::OnImeInputSourceChanged(uint16_t language_id,
- bool is_ime) {
- ui::RemoteInputMethodPrivateWin* remote_input_method_private =
- GetRemoteInputMethodPrivate();
- if (!remote_input_method_private)
- return;
- remote_input_method_private->OnInputSourceChanged(language_id, is_ime);
-}
-
-void RemoteWindowTreeHostWin::DispatchKeyboardMessage(ui::EventType type,
- uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags,
- bool is_character) {
- SetEventFlags(flags | mouse_event_flags());
- if (base::MessageLoop::current()->IsNested()) {
- int index = (flags & ui::EF_ALT_DOWN) ? 1 : 0;
- const int char_message[] = {WM_CHAR, WM_SYSCHAR};
- const int keydown_message[] = {WM_KEYDOWN, WM_SYSKEYDOWN};
- const int keyup_message[] = {WM_KEYUP, WM_SYSKEYUP};
- uint32_t message =
- is_character ? char_message[index]
- : (type == ui::ET_KEY_PRESSED ? keydown_message[index]
- : keyup_message[index]);
- ::PostThreadMessage(::GetCurrentThreadId(),
- message,
- vkey,
- repeat_count | scan_code >> 15);
- } else if (is_character) {
- ui::KeyEvent event(static_cast<base::char16>(vkey),
- ui::KeyboardCodeForWindowsKeyCode(vkey),
- flags);
- SendEventToProcessor(&event);
- } else {
- ui::KeyEvent event(type,
- ui::KeyboardCodeForWindowsKeyCode(vkey),
- flags);
- SendEventToProcessor(&event);
- }
-}
-
-void RemoteWindowTreeHostWin::SetEventFlags(uint32_t flags) {
- if (flags == event_flags_)
- return;
- event_flags_ = flags;
- SetVirtualKeyStates(event_flags_);
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/remote_window_tree_host_win.h b/chromium/ui/aura/remote_window_tree_host_win.h
deleted file mode 100644
index 4614fd6e8aa..00000000000
--- a/chromium/ui/aura/remote_window_tree_host_win.h
+++ /dev/null
@@ -1,197 +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_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
-#define UI_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/remote_input_method_delegate_win.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/event_source.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/metro_viewer/ime_types.h"
-
-struct MetroViewerHostMsg_MouseButtonParams;
-
-namespace base {
-class FilePath;
-}
-
-namespace ui {
-class RemoteInputMethodPrivateWin;
-class ViewProp;
-}
-
-namespace IPC {
-class Message;
-class Sender;
-}
-
-namespace aura {
-
-// WindowTreeHost implementaton that receives events from a different
-// process. In the case of Windows this is the Windows 8 (aka Metro)
-// frontend process, which forwards input events to this class.
-class AURA_EXPORT RemoteWindowTreeHostWin
- : public WindowTreeHost,
- public ui::internal::RemoteInputMethodDelegateWin {
- public:
- // Returns the current RemoteWindowTreeHostWin. This does *not* create a
- // RemoteWindowTreeHostWin.
- static RemoteWindowTreeHostWin* Instance();
-
- // Returns true if there is a RemoteWindowTreeHostWin and it has a valid
- // HWND. A return value of false typically indicates we're not in metro mode.
- static bool IsValid();
-
- // Sets the handle to the remote window. The |remote_window| is the actual
- // window owned by the viewer process. Call this before Connected() for some
- // customers like input method initialization which needs the handle.
- void SetRemoteWindowHandle(HWND remote_window);
- HWND remote_window() { return remote_window_; }
-
- // The |host| can be used when we need to send a message to it.
- void Connected(IPC::Sender* host);
- // Called when the remote process has closed its IPC connection.
- void Disconnected();
-
- // Called when we have a message from the remote process.
- bool OnMessageReceived(const IPC::Message& message);
-
- void HandleOpenURLOnDesktop(const base::FilePath& shortcut,
- const base::string16& url);
-
- void HandleWindowSizeChanged(uint32_t width, uint32_t height);
-
- // Returns the active ASH root window.
- Window* GetAshWindow();
-
- // Returns true if the remote window is the foreground window according to the
- // OS.
- bool IsForegroundWindow();
-
- protected:
- RemoteWindowTreeHostWin();
- ~RemoteWindowTreeHostWin() override;
-
- private:
- // IPC message handing methods:
- void OnMouseMoved(int32_t x, int32_t y, int32_t flags);
- void OnMouseButton(const MetroViewerHostMsg_MouseButtonParams& params);
- void OnKeyDown(uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags);
- void OnKeyUp(uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags);
- void OnChar(uint32_t key_code,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags);
- void OnWindowActivated(bool repaint);
- void OnEdgeGesture();
- void OnTouchDown(int32_t x,
- int32_t y,
- uint64_t timestamp,
- uint32_t pointer_id);
- void OnTouchUp(int32_t x, int32_t y, uint64_t timestamp, uint32_t pointer_id);
- void OnTouchMoved(int32_t x,
- int32_t y,
- uint64_t timestamp,
- uint32_t pointer_id);
- void OnSetCursorPosAck();
-
- // For Input Method support:
- ui::RemoteInputMethodPrivateWin* GetRemoteInputMethodPrivate();
- void OnImeCandidatePopupChanged(bool visible);
- void OnImeCompositionChanged(
- const base::string16& text,
- int32_t selection_start,
- int32_t selection_end,
- const std::vector<metro_viewer::UnderlineInfo>& underlines);
- void OnImeTextCommitted(const base::string16& text);
- void OnImeInputSourceChanged(uint16_t language_id, bool is_ime);
-
- // WindowTreeHost overrides:
- ui::EventSource* GetEventSource() override;
- gfx::AcceleratedWidget GetAcceleratedWidget() override;
- void ShowImpl() override;
- void HideImpl() override;
- gfx::Rect GetBounds() const override;
- void SetBounds(const gfx::Rect& bounds) override;
- gfx::Point GetLocationOnNativeScreen() const override;
- void SetCapture() override;
- void ReleaseCapture() override;
- void SetCursorNative(gfx::NativeCursor cursor) override;
- void MoveCursorToNative(const gfx::Point& location) override;
- void OnCursorVisibilityChangedNative(bool show) override;
-
- // ui::internal::RemoteInputMethodDelegateWin overrides:
- void CancelComposition() override;
- void OnTextInputClientUpdated(
- const std::vector<int32_t>& input_scopes,
- const std::vector<gfx::Rect>& composition_character_bounds) override;
-
- // Helper function to dispatch a keyboard message to the desired target.
- // The default target is the WindowEventDispatcher. For nested message loop
- // invocations we post a synthetic keyboard message directly into the message
- // loop. The dispatcher for the nested loop would then decide how this
- // message is routed.
- void DispatchKeyboardMessage(ui::EventType type,
- uint32_t vkey,
- uint32_t repeat_count,
- uint32_t scan_code,
- uint32_t flags,
- bool is_character);
-
- // Sets the event flags. |flags| is a bitmask of EventFlags. If there is a
- // change the system virtual key state is updated as well. This way if chrome
- // queries for key state it matches that of event being dispatched.
- void SetEventFlags(uint32_t flags);
-
- uint32_t mouse_event_flags() const {
- return event_flags_ & (ui::EF_LEFT_MOUSE_BUTTON |
- ui::EF_MIDDLE_MOUSE_BUTTON |
- ui::EF_RIGHT_MOUSE_BUTTON);
- }
-
- uint32_t key_event_flags() const {
- return event_flags_ & (ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
- ui::EF_ALT_DOWN | ui::EF_CAPS_LOCK_ON);
- }
-
- HWND remote_window_;
- IPC::Sender* host_;
- scoped_ptr<ui::ViewProp> prop_;
-
- // Incremented if we need to ignore mouse messages until the SetCursorPos
- // operation is acked by the viewer.
- int ignore_mouse_moves_until_set_cursor_ack_;
-
- // Tracking last click event for synthetically generated mouse events.
- scoped_ptr<ui::MouseEvent> last_mouse_click_event_;
-
- // State of the keyboard/mouse at the time of the last input event. See
- // description of SetEventFlags().
- uint32_t event_flags_;
-
- // Current size of this root window.
- gfx::Size window_size_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteWindowTreeHostWin);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_REMOTE_WINDOW_TREE_HOST_WIN_H_
diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc
index bd9f023042f..0b848e9fb50 100644
--- a/chromium/ui/aura/window.cc
+++ b/chromium/ui/aura/window.cc
@@ -67,8 +67,7 @@ class ScopedCursorHider {
client::CursorClient* cursor_client = client::GetCursorClient(window_);
if (cursor_client) {
const gfx::Display& display =
- gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(
- window_);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_);
cursor_client->SetDisplay(display);
cursor_client->ShowCursor();
}
diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc
index d9c59136b24..39dc1a48937 100644
--- a/chromium/ui/aura/window_event_dispatcher.cc
+++ b/chromium/ui/aura/window_event_dispatcher.cc
@@ -107,14 +107,11 @@ void WindowEventDispatcher::RepostEvent(const ui::LocatedEvent* event) {
// We allow for only one outstanding repostable event. This is used
// in exiting context menus. A dropped repost request is allowed.
if (event->type() == ui::ET_MOUSE_PRESSED) {
- held_repostable_event_.reset(
- new ui::MouseEvent(
- static_cast<const ui::MouseEvent&>(*event),
- static_cast<aura::Window*>(event->target()),
- window()));
+ held_repostable_event_.reset(new ui::MouseEvent(
+ *event->AsMouseEvent(), static_cast<aura::Window*>(event->target()),
+ window()));
} else if (event->type() == ui::ET_TOUCH_PRESSED) {
- held_repostable_event_.reset(
- new ui::TouchEvent(static_cast<const ui::TouchEvent&>(*event)));
+ held_repostable_event_.reset(new ui::TouchEvent(*event->AsTouchEvent()));
} else {
DCHECK(event->type() == ui::ET_GESTURE_TAP_DOWN);
held_repostable_event_.reset();
@@ -474,14 +471,11 @@ ui::EventDispatchDetails WindowEventDispatcher::PreDispatchEvent(
DispatchDetails details;
if (event->IsMouseEvent()) {
- details = PreDispatchMouseEvent(target_window,
- static_cast<ui::MouseEvent*>(event));
+ details = PreDispatchMouseEvent(target_window, event->AsMouseEvent());
} else if (event->IsScrollEvent()) {
- details = PreDispatchLocatedEvent(target_window,
- static_cast<ui::ScrollEvent*>(event));
+ details = PreDispatchLocatedEvent(target_window, event->AsScrollEvent());
} else if (event->IsTouchEvent()) {
- details = PreDispatchTouchEvent(target_window,
- static_cast<ui::TouchEvent*>(event));
+ details = PreDispatchTouchEvent(target_window, event->AsTouchEvent());
}
if (details.dispatcher_destroyed || details.target_destroyed)
return details;
@@ -508,8 +502,7 @@ ui::EventDispatchDetails WindowEventDispatcher::PostDispatchEvent(
// being dispatched.
if (is_dispatched_held_event(event) || !held_move_event_ ||
!held_move_event_->IsTouchEvent()) {
- const ui::TouchEvent& touchevent =
- static_cast<const ui::TouchEvent&>(event);
+ const ui::TouchEvent& touchevent = *event.AsTouchEvent();
if (!touchevent.synchronous_handling_disabled()) {
scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc
index c8ae024b1bd..ef992595830 100644
--- a/chromium/ui/aura/window_event_dispatcher_unittest.cc
+++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc
@@ -2633,7 +2633,7 @@ TEST_F(WindowEventDispatcherTest, TouchMovesMarkedWhenCausingScroll) {
ui::ET_TOUCH_RELEASED, location + gfx::Vector2d(200, 200), 0,
ui::EventTimeForNow() + base::TimeDelta::FromSeconds(1));
DispatchEventUsingWindowDispatcher(&release);
- EXPECT_FALSE(recorder.LastTouchMayCauseScrolling());
+ EXPECT_TRUE(recorder.LastTouchMayCauseScrolling());
EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_TOUCH_RELEASED));
EXPECT_TRUE(recorder.HasReceivedEvent(ui::ET_GESTURE_SCROLL_END));
diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc
index 4b720518e5b..96413d02538 100644
--- a/chromium/ui/aura/window_targeter.cc
+++ b/chromium/ui/aura/window_targeter.cc
@@ -62,10 +62,9 @@ bool WindowTargeter::EventLocationInsideBounds(
ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
ui::Event* event) {
Window* window = static_cast<Window*>(root);
- Window* target =
- event->IsKeyEvent()
- ? FindTargetForKeyEvent(window, *static_cast<ui::KeyEvent*>(event))
- : FindTargetForNonKeyEvent(window, event);
+ Window* target = event->IsKeyEvent()
+ ? FindTargetForKeyEvent(window, *event->AsKeyEvent())
+ : FindTargetForNonKeyEvent(window, event);
if (target && !window->parent() && !window->Contains(target)) {
// |window| is the root window, but |target| is not a descendent of
// |window|. So do not allow dispatching from here. Instead, dispatch the
@@ -148,7 +147,7 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
if (event.IsTouchEvent()) {
// Query the gesture-recognizer to find targets for touch events.
- const ui::TouchEvent& touch = static_cast<const ui::TouchEvent&>(event);
+ const ui::TouchEvent& touch = *event.AsTouchEvent();
ui::GestureConsumer* consumer =
ui::GestureRecognizer::Get()->GetTouchLockedTarget(touch);
if (consumer)
diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc
index bb988e1f86d..aa6fb73ec12 100644
--- a/chromium/ui/aura/window_tree_host.cc
+++ b/chromium/ui/aura/window_tree_host.cc
@@ -32,8 +32,8 @@ const char kWindowTreeHostForAcceleratedWidget[] =
"__AURA_WINDOW_TREE_HOST_ACCELERATED_WIDGET__";
float GetDeviceScaleFactorFromDisplay(Window* window) {
- gfx::Display display = gfx::Screen::GetScreenFor(window)->
- GetDisplayNearestWindow(window);
+ gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window);
DCHECK(display.is_valid());
return display.device_scale_factor();
}
@@ -314,7 +314,7 @@ void WindowTreeHost::MoveCursorToInternal(const gfx::Point& root_location,
client::CursorClient* cursor_client = client::GetCursorClient(window());
if (cursor_client) {
const gfx::Display& display =
- gfx::Screen::GetScreenFor(window())->GetDisplayNearestWindow(window());
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window());
cursor_client->SetDisplay(display);
}
dispatcher()->OnCursorMovedToRootLocation(root_location);
diff --git a/chromium/ui/aura/window_tree_host_mac.h b/chromium/ui/aura/window_tree_host_mac.h
index eefb7e1e52b..d8adb74e80d 100644
--- a/chromium/ui/aura/window_tree_host_mac.h
+++ b/chromium/ui/aura/window_tree_host_mac.h
@@ -20,10 +20,6 @@ class MouseEvent;
namespace aura {
-namespace internal {
-class TouchEventCalibrate;
-}
-
class AURA_EXPORT WindowTreeHostMac : public WindowTreeHost {
public:
explicit WindowTreeHostMac(const gfx::Rect& bounds);
diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc
index 1e4baf6392e..8dfa4d05327 100644
--- a/chromium/ui/aura/window_tree_host_platform.cc
+++ b/chromium/ui/aura/window_tree_host_platform.cc
@@ -83,7 +83,7 @@ void WindowTreeHostPlatform::HideImpl() {
}
gfx::Rect WindowTreeHostPlatform::GetBounds() const {
- return window_->GetBounds();
+ return window_ ? window_->GetBounds() : gfx::Rect();
}
void WindowTreeHostPlatform::SetBounds(const gfx::Rect& bounds) {
@@ -125,7 +125,7 @@ void WindowTreeHostPlatform::OnCursorVisibilityChangedNative(bool show) {
void WindowTreeHostPlatform::OnBoundsChanged(const gfx::Rect& new_bounds) {
float current_scale = compositor()->device_scale_factor();
- float new_scale = gfx::Screen::GetScreenFor(window())
+ float new_scale = gfx::Screen::GetScreen()
->GetDisplayNearestWindow(window())
.device_scale_factor();
gfx::Rect old_bounds = bounds_;
diff --git a/chromium/ui/aura/window_tree_host_x11.cc b/chromium/ui/aura/window_tree_host_x11.cc
index ebcb154e60b..a5675e9f3ce 100644
--- a/chromium/ui/aura/window_tree_host_x11.cc
+++ b/chromium/ui/aura/window_tree_host_x11.cc
@@ -45,6 +45,7 @@
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/platform/platform_event_observer.h"
+#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/screen.h"
@@ -103,107 +104,6 @@ bool default_override_redirect = false;
} // namespace
-namespace internal {
-
-// TODO(miletus) : Move this into DeviceDataManager.
-// Accomplishes 2 tasks concerning touch event calibration:
-// 1. Being a message-pump observer,
-// routes all the touch events to the X root window,
-// where they can be calibrated later.
-// 2. Has the Calibrate method that does the actual bezel calibration,
-// when invoked from X root window's event dispatcher.
-class TouchEventCalibrate : public ui::PlatformEventObserver {
- public:
- TouchEventCalibrate() : left_(0), right_(0), top_(0), bottom_(0) {
- if (ui::PlatformEventSource::GetInstance())
- ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
- std::vector<std::string> parts = base::SplitString(
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTouchCalibration),
- ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (parts.size() >= 4) {
- if (!base::StringToInt(parts[0], &left_))
- DLOG(ERROR) << "Incorrect left border calibration value passed.";
- if (!base::StringToInt(parts[1], &right_))
- DLOG(ERROR) << "Incorrect right border calibration value passed.";
- if (!base::StringToInt(parts[2], &top_))
- DLOG(ERROR) << "Incorrect top border calibration value passed.";
- if (!base::StringToInt(parts[3], &bottom_))
- DLOG(ERROR) << "Incorrect bottom border calibration value passed.";
- }
- }
-
- ~TouchEventCalibrate() override {
- if (ui::PlatformEventSource::GetInstance())
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
- }
-
- // Modify the location of the |event|,
- // expanding it from |bounds| to (|bounds| + bezels).
- // Required when touchscreen is bigger than screen (i.e. has bezels),
- // because we receive events in touchscreen coordinates,
- // which need to be expanded when converting to screen coordinates,
- // so that location on bezels will be outside of screen area.
- void Calibrate(ui::TouchEvent* event, const gfx::Rect& bounds) {
- int x = event->x();
- int y = event->y();
-
- if (!left_ && !right_ && !top_ && !bottom_)
- return;
-
- const int resolution_x = bounds.width();
- const int resolution_y = bounds.height();
- if (left_ || right_) {
- // Offset the x position to the real
- x -= left_;
- // Scale the screen area back to the full resolution of the screen.
- x = (x * resolution_x) / (resolution_x - (right_ + left_));
- }
- if (top_ || bottom_) {
- // When there is a top bezel we add our border,
- y -= top_;
- // Scale the screen area back to the full resolution of the screen.
- y = (y * resolution_y) / (resolution_y - (bottom_ + top_));
- }
-
- // Set the modified coordinate back to the event.
- if (event->root_location() == event->location()) {
- // Usually those will be equal,
- // if not, I am not sure what the correct value should be.
- event->set_root_location(gfx::Point(x, y));
- }
- event->set_location(gfx::Point(x, y));
- }
-
- private:
- // ui::PlatformEventObserver:
- void WillProcessEvent(const ui::PlatformEvent& event) override {
- if (event->type == GenericEvent &&
- (event->xgeneric.evtype == XI_TouchBegin ||
- event->xgeneric.evtype == XI_TouchUpdate ||
- event->xgeneric.evtype == XI_TouchEnd)) {
- XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event->xcookie.data);
- xievent->event = xievent->root;
- xievent->event_x = xievent->root_x;
- xievent->event_y = xievent->root_y;
- }
- }
-
- void DidProcessEvent(const ui::PlatformEvent& event) override {}
-
- // The difference in screen's native resolution pixels between
- // the border of the touchscreen and the border of the screen,
- // aka bezel sizes.
- int left_;
- int right_;
- int top_;
- int bottom_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchEventCalibrate);
-};
-
-} // namespace internal
-
////////////////////////////////////////////////////////////////////////////////
// WindowTreeHostX11
@@ -214,7 +114,6 @@ WindowTreeHostX11::WindowTreeHostX11(const gfx::Rect& bounds)
current_cursor_(ui::kCursorNull),
window_mapped_(false),
bounds_(bounds),
- touch_calibrate_(new internal::TouchEventCalibrate),
atom_cache_(xdisplay_, kAtomsToCache) {
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
@@ -358,8 +257,8 @@ uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) {
client::CursorClient* cursor_client =
client::GetCursorClient(root_window);
if (cursor_client) {
- const gfx::Display display = gfx::Screen::GetScreenFor(
- root_window)->GetDisplayNearestWindow(root_window);
+ const gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(root_window);
cursor_client->SetDisplay(display);
}
// EnterNotify creates ET_MOUSE_MOVE. Mark as synthesized as this is
@@ -500,8 +399,9 @@ void WindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
// Even if the host window's size doesn't change, aura's root window
// size, which is in DIP, changes when the scale changes.
float current_scale = compositor()->device_scale_factor();
- float new_scale = gfx::Screen::GetScreenFor(window())->
- GetDisplayNearestWindow(window()).device_scale_factor();
+ float new_scale = gfx::Screen::GetScreen()
+ ->GetDisplayNearestWindow(window())
+ .device_scale_factor();
bool origin_changed = bounds_.origin() != bounds.origin();
bool size_changed = bounds_.size() != bounds.size();
XWindowChanges changes = {0};
@@ -572,7 +472,6 @@ void WindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) {
ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
XEvent* xev = event;
- XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
if (!factory->ShouldProcessXI2Event(xev))
return;
@@ -599,10 +498,6 @@ void WindowTreeHostX11::DispatchXI2Event(const base::NativeEvent& event) {
case ui::ET_TOUCH_CANCELLED:
case ui::ET_TOUCH_RELEASED: {
ui::TouchEvent touchev(xev);
- if (ui::DeviceDataManagerX11::GetInstance()->TouchEventNeedsCalibrate(
- xiev->deviceid)) {
- touch_calibrate_->Calibrate(&touchev, bounds_);
- }
TranslateAndDispatchLocatedEvent(&touchev);
break;
}
diff --git a/chromium/ui/aura/window_tree_host_x11.h b/chromium/ui/aura/window_tree_host_x11.h
index 906f605a9b0..0587bb6fa08 100644
--- a/chromium/ui/aura/window_tree_host_x11.h
+++ b/chromium/ui/aura/window_tree_host_x11.h
@@ -27,13 +27,8 @@ class MouseEvent;
namespace aura {
-namespace internal {
-class TouchEventCalibrate;
-}
-
class AURA_EXPORT WindowTreeHostX11 : public WindowTreeHost,
public ui::PlatformEventDispatcher {
-
public:
explicit WindowTreeHostX11(const gfx::Rect& bounds);
~WindowTreeHostX11() override;
@@ -95,8 +90,6 @@ class AURA_EXPORT WindowTreeHostX11 : public WindowTreeHost,
// The bounds of |xwindow_|.
gfx::Rect bounds_;
- scoped_ptr<internal::TouchEventCalibrate> touch_calibrate_;
-
ui::X11AtomCache atom_cache_;
DISALLOW_COPY_AND_ASSIGN(WindowTreeHostX11);
diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc
index 60792c2a4b7..f2699eb8b0e 100644
--- a/chromium/ui/aura/window_unittest.cc
+++ b/chromium/ui/aura/window_unittest.cc
@@ -358,19 +358,19 @@ TEST_F(WindowTest, MoveCursorTo) {
Window* root = root_window();
root->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("10,10",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
w1->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("20,20",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
w11->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("25,25",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
w111->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("30,30",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
w1111->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("35,35",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
}
TEST_F(WindowTest, ContainsMouse) {
@@ -398,8 +398,8 @@ TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
// TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
#endif
- EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
- root_window())->GetCursorScreenPoint().ToString());
+ EXPECT_EQ("10,10",
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
}
// Tests Window::ConvertPointToWindow() with transform to non-root windows.
@@ -413,21 +413,21 @@ TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
w1->SetTransform(transform1);
w1->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("30,30",
- gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
gfx::Transform transform2;
transform2.Translate(-10, 20);
w1->SetTransform(transform2);
w1->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("10,40",
- gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
gfx::Transform transform3;
transform3.Rotate(90.0);
w1->SetTransform(transform3);
w1->MoveCursorTo(gfx::Point(5, 5));
EXPECT_EQ("5,15",
- gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
gfx::Transform transform4;
transform4.Translate(100.0, 100.0);
@@ -436,7 +436,7 @@ TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
w1->SetTransform(transform4);
w1->MoveCursorTo(gfx::Point(10, 10));
EXPECT_EQ("60,130",
- gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
}
// Test Window::ConvertPointToWindow() with complex transforms to both root and
@@ -453,8 +453,6 @@ TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
scoped_ptr<Window> w1111(
CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
- Window* root = root_window();
-
// The root window expects transforms that produce integer rects.
gfx::Transform root_transform;
root_transform.Translate(60.0, 70.0);
@@ -479,7 +477,7 @@ TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
#endif
EXPECT_EQ("20,53",
- gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
+ gfx::Screen::GetScreen()->GetCursorScreenPoint().ToString());
}
// Tests that we do not crash when a Window is destroyed by going out of
@@ -1588,7 +1586,7 @@ TEST_F(WindowTest, IgnoreEventsTest) {
TEST_F(WindowTest, Transform) {
gfx::Size size = host()->GetBounds().size();
EXPECT_EQ(gfx::Rect(size),
- gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
+ gfx::Screen::GetScreen()->GetDisplayNearestPoint(
gfx::Point()).bounds());
// Rotate it clock-wise 90 degrees.
@@ -1603,7 +1601,7 @@ TEST_F(WindowTest, Transform) {
root_window()->bounds().size().ToString());
EXPECT_EQ(
gfx::Rect(transformed_size).ToString(),
- gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
+ gfx::Screen::GetScreen()->GetDisplayNearestPoint(
gfx::Point()).bounds().ToString());
// Host size shouldn't change.
diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn
index 6190b065df1..db554383406 100644
--- a/chromium/ui/base/BUILD.gn
+++ b/chromium/ui/base/BUILD.gn
@@ -2,18 +2,56 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/buildflag_header.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/ui.gni")
import("//testing/test.gni")
+import("//ui/base/ui_features.gni")
+import("//ui/ozone/ozone.gni")
if (is_android) {
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
+} else if (is_mac) {
+ import("//build/config/mac/rules.gni")
}
build_ime = !is_ios
+# As part of building Chrome on iOS, it is necessary to run a tool on
+# the host to load datapack and generate output in a format defined
+# by the platform (this is to support notifications).
+#
+# Introduce a standalone target that build on both 'host' and 'target'
+# toolset that just build the support to load datapack. The dependency
+# should be kept minimal to have to build too many targets with multiple
+# toolsets.
+component("ui_data_pack") {
+ sources = [
+ "resource/data_pack.cc",
+ "resource/data_pack.h",
+ "resource/data_pack_export.h",
+ "resource/resource_handle.h",
+ "resource/scale_factor.cc",
+ "resource/scale_factor.h",
+ ]
+
+ deps = [
+ "//base",
+ ]
+
+ defines = [ "UI_DATA_PACK_IMPLEMENTATION" ]
+
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+}
+
+buildflag_header("ui_features") {
+ header = "ui_features.h"
+ flags = [ "ENABLE_HIDPI=$enable_hidpi" ]
+}
+
component("base") {
output_name = "ui_base"
@@ -30,6 +68,8 @@ component("base") {
"clipboard/clipboard_mac.h",
"clipboard/clipboard_mac.mm",
"clipboard/clipboard_types.h",
+ "clipboard/clipboard_util_mac.h",
+ "clipboard/clipboard_util_mac.mm",
"clipboard/clipboard_util_win.cc",
"clipboard/clipboard_util_win.h",
"clipboard/clipboard_win.cc",
@@ -101,6 +141,7 @@ component("base") {
"cursor/cursor_android.cc",
"cursor/cursor_loader.h",
"cursor/cursor_win.cc",
+ "default_style.h",
"default_theme_provider_mac.mm",
"device_form_factor.h",
"device_form_factor_android.cc",
@@ -148,6 +189,8 @@ component("base") {
"layout.cc",
"layout.h",
"layout_mac.mm",
+ "material_design/material_design_controller.cc",
+ "material_design/material_design_controller.h",
"models/button_menu_item_model.cc",
"models/button_menu_item_model.h",
"models/combobox_model.cc",
@@ -178,10 +221,6 @@ component("base") {
"nine_image_painter_factory.h",
"page_transition_types.cc",
"page_transition_types.h",
- "resource/data_pack.cc",
- "resource/data_pack.h",
- "resource/material_design/material_design_controller.cc",
- "resource/material_design/material_design_controller.h",
"resource/resource_bundle.cc",
"resource/resource_bundle.h",
"resource/resource_bundle_android.cc",
@@ -192,7 +231,6 @@ component("base") {
"resource/resource_bundle_win.h",
"resource/resource_data_dll_win.cc",
"resource/resource_data_dll_win.h",
- "resource/resource_handle.h",
"template_expressions.cc",
"template_expressions.h",
"theme_provider.cc",
@@ -318,6 +356,7 @@ component("base") {
defines = [ "UI_BASE_IMPLEMENTATION" ]
public_deps = [
+ ":ui_features",
"//base",
"//skia",
"//ui/events:events_base",
@@ -331,6 +370,7 @@ component("base") {
"//base/third_party/dynamic_annotations",
"//net",
"//third_party/icu",
+ "//ui/base:ui_data_pack",
"//ui/events",
"//ui/events/devices",
"//ui/resources",
@@ -371,7 +411,7 @@ component("base") {
"dragdrop/drag_utils_aura.cc",
]
}
- if (use_x11) {
+ if (use_x11 || ozone_platform_x11) {
sources += [
"x/x11_foreign_window_manager.cc",
"x/x11_foreign_window_manager.h",
@@ -479,7 +519,7 @@ component("base") {
]
}
- if (use_x11) {
+ if (use_x11 || ozone_platform_x11) {
#'all_dependent_settings': {
#'ldflags': [
#'-L<(PRODUCT_DIR)',
@@ -517,6 +557,7 @@ component("base") {
]
deps += [
+ "//ui/events/ozone:events_ozone_evdev",
"//ui/events/ozone:events_ozone_layout",
"//ui/ozone:ozone_base",
]
@@ -599,6 +640,8 @@ source_set("test_support") {
"test/scoped_fake_nswindow_focus.mm",
"test/scoped_fake_nswindow_fullscreen.h",
"test/scoped_fake_nswindow_fullscreen.mm",
+ "test/scoped_preferred_scroller_style_mac.h",
+ "test/scoped_preferred_scroller_style_mac.mm",
"test/test_clipboard.cc",
"test/test_clipboard.h",
"test/windowed_nsnotification_observer.h",
@@ -621,6 +664,7 @@ source_set("test_support") {
"//base/test:test_config",
"//skia",
"//testing/gtest",
+ "//ui/base:ui_data_pack",
"//ui/events:events_base",
"//ui/events:test_support",
"//ui/gfx",
@@ -635,7 +679,10 @@ source_set("test_support") {
"ime/dummy_text_input_client.h",
]
- deps += [ "//ui/base/ime" ]
+ deps += [
+ "//ui/base/ime",
+ "//ui/events",
+ ]
}
if (!use_aura) {
@@ -659,30 +706,33 @@ if (is_android) {
}
}
-#
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("ui_base_unittests_run") {
+bundle_data("ui_base_unittests_bundle_data") {
testonly = true
- deps = [
- ":ui_base_unittests",
+ sources = [
+ "test/data/data_pack_unittest/truncated-header.pak",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}",
]
}
# GYP version: ui/base/ui_base_tests.gyp:ui_base_unittests
test("ui_base_unittests") {
sources = [
+ "clipboard/clipboard_util_mac_unittest.mm",
"ios/cru_context_menu_controller_unittest.mm",
"l10n/l10n_util_mac_unittest.mm",
"l10n/l10n_util_unittest.cc",
"l10n/l10n_util_win_unittest.cc",
"l10n/time_format_unittest.cc",
"layout_unittest.cc",
+ "material_design/material_design_controller_unittest.cc",
"models/tree_node_iterator_unittest.cc",
"resource/data_pack_literal.cc",
"resource/data_pack_unittest.cc",
- "resource/material_design/material_design_controller_unittest.cc",
"resource/resource_bundle_unittest.cc",
+ "resource/scale_factor_unittest.cc",
"template_expressions_unittest.cc",
"test/run_all_unittests.cc",
"user_activity/user_activity_detector_unittest.cc",
@@ -743,7 +793,6 @@ test("ui_base_unittests") {
"ime/composition_text_unittest.cc",
"ime/input_method_base_unittest.cc",
"ime/input_method_chromeos_unittest.cc",
- "ime/remote_input_method_win_unittest.cc",
"ime/win/imm32_manager_unittest.cc",
"ime/win/tsf_input_scope_unittest.cc",
]
@@ -766,8 +815,8 @@ test("ui_base_unittests") {
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
deps = [
+ ":ui_base_unittests_bundle_data",
"//base",
- "//base/allocator",
"//base/test:test_support",
"//net",
"//skia",
@@ -776,6 +825,7 @@ test("ui_base_unittests") {
"//third_party/icu",
"//ui/base",
"//ui/base:test_support",
+ "//ui/base:ui_data_pack",
"//ui/events:events_base",
"//ui/events:test_support",
"//ui/gfx:test_support",
@@ -785,14 +835,14 @@ test("ui_base_unittests") {
"//url",
]
- if (is_ios) {
- # TODO(GYP) lots of iOS-only steps for ui_base_unittests
- }
-
if (build_ime) {
deps += [ "//ui/base/ime" ]
}
+ if (is_ios) {
+ deps += [ "//ui/resources:ui_test_pak_bundle_data" ]
+ }
+
if (is_win) {
sources += [
"dragdrop/os_exchange_data_win_unittest.cc",
@@ -843,8 +893,8 @@ test("ui_base_unittests") {
if (is_mac) {
deps += [
+ ":ui_unittests Framework",
"//third_party/mozilla",
- #'ui_base_tests_bundle', TODO(GYP)
]
}
@@ -899,4 +949,13 @@ test("ui_base_unittests") {
}
}
}
-# TODO(GYP) Mac (ui_base_tests_bundle)
+
+if (is_mac) {
+ mac_framework("ui_unittests Framework") {
+ testonly = true
+ deps = [
+ "//ui/resources:ui_test_pak_bundle_data",
+ ]
+ info_plist = "test/framework-Info.plist"
+ }
+}
diff --git a/chromium/ui/base/OWNERS b/chromium/ui/base/OWNERS
index b444384491e..b6ad79f101c 100644
--- a/chromium/ui/base/OWNERS
+++ b/chromium/ui/base/OWNERS
@@ -2,6 +2,8 @@ per-file *.isolate=maruel@chromium.org
per-file *.isolate=tandrii@chromium.org
per-file *.isolate=vadimsh@chromium.org
+per-file template_expressions*=dschuyler@chromium.org
+
# If you're doing structural changes get a review from one of the ui/OWNERS.
per-file *.gyp*=*
per-file BUILD.gn=*
diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc
index 47465b04813..86d86b5be1d 100644
--- a/chromium/ui/base/clipboard/clipboard_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_android.cc
@@ -116,10 +116,9 @@ void ClipboardMap::CommitToAndroidClipboard() {
ScopedJavaLocalRef<jstring> str =
ConvertUTF8ToJavaString(env, map_[kPlainTextFormat].c_str());
DCHECK(str.obj());
-
Java_Clipboard_setText(env, clipboard_manager_.obj(), str.obj());
} else {
- Java_Clipboard_setText(env, clipboard_manager_.obj(), nullptr);
+ Java_Clipboard_clear(env, clipboard_manager_.obj());
NOTIMPLEMENTED();
}
}
@@ -128,7 +127,7 @@ void ClipboardMap::Clear() {
JNIEnv* env = AttachCurrentThread();
base::AutoLock lock(lock_);
map_.clear();
- Java_Clipboard_setText(env, clipboard_manager_.obj(), NULL);
+ Java_Clipboard_clear(env, clipboard_manager_.obj());
}
// Add a key:jstr pair to map, but only if jstr is not null, and also
diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm
index eb4fc21b11a..f3a4c434704 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_mac.mm
@@ -20,6 +20,7 @@
#include "skia/ext/skia_utils_mac.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/size.h"
@@ -29,9 +30,6 @@ namespace ui {
namespace {
-// Would be nice if this were in UTCoreTypes.h, but it isn't
-NSString* const kUTTypeURLName = @"public.url-name";
-
// Tells us if WebKit was the last to write to the pasteboard. There's no
// actual data associated with this type.
NSString* const kWebSmartPastePboardType = @"NeXT smart paste pasteboard type";
@@ -114,7 +112,7 @@ const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSStringPboardType));
+ CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSPasteboardTypeString));
return type;
}
@@ -245,7 +243,7 @@ void ClipboardMac::ReadText(ClipboardType type, base::string16* result) const {
DCHECK(CalledOnValidThread());
DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
NSPasteboard* pb = GetPasteboard();
- NSString* contents = [pb stringForType:NSStringPboardType];
+ NSString* contents = [pb stringForType:NSPasteboardTypeString];
*result = base::SysNSStringToUTF16(contents);
}
@@ -255,7 +253,7 @@ void ClipboardMac::ReadAsciiText(ClipboardType type,
DCHECK(CalledOnValidThread());
DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
NSPasteboard* pb = GetPasteboard();
- NSString* contents = [pb stringForType:NSStringPboardType];
+ NSString* contents = [pb stringForType:NSPasteboardTypeString];
if (!contents)
result->clear();
@@ -279,7 +277,7 @@ void ClipboardMac::ReadHTML(ClipboardType type,
NSPasteboard* pb = GetPasteboard();
NSArray* supportedTypes = [NSArray arrayWithObjects:NSHTMLPboardType,
NSRTFPboardType,
- NSStringPboardType,
+ NSPasteboardTypeString,
nil];
NSString* bestType = [pb availableTypeFromArray:supportedTypes];
if (bestType) {
@@ -354,12 +352,12 @@ void ClipboardMac::ReadBookmark(base::string16* title, std::string* url) const {
NSPasteboard* pb = GetPasteboard();
if (title) {
- NSString* contents = [pb stringForType:kUTTypeURLName];
+ NSString* contents = ClipboardUtil::GetTitleFromPasteboardURL(pb);
*title = base::SysNSStringToUTF16(contents);
}
if (url) {
- NSString* url_string = [[NSURL URLFromPasteboard:pb] absoluteString];
+ NSString* url_string = ClipboardUtil::GetURLFromPasteboardURL(pb);
if (!url_string)
url->clear();
else
@@ -393,8 +391,8 @@ void ClipboardMac::WriteText(const char* text_data, size_t text_len) {
std::string text_str(text_data, text_len);
NSString* text = base::SysUTF8ToNSString(text_str);
NSPasteboard* pb = GetPasteboard();
- [pb addTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
- [pb setString:text forType:NSStringPboardType];
+ [pb addTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
+ [pb setString:text forType:NSPasteboardTypeString];
}
void ClipboardMac::WriteHTML(const char* markup_data,
@@ -425,18 +423,10 @@ void ClipboardMac::WriteBookmark(const char* title_data,
std::string url_str(url_data, url_len);
NSString* url = base::SysUTF8ToNSString(url_str);
- // TODO(playmobil): In the Windows version of this function, an HTML
- // representation of the bookmark is also added to the clipboard, to support
- // drag and drop of web shortcuts. I don't think we need to do this on the
- // Mac, but we should double check later on.
- NSURL* nsurl = [NSURL URLWithString:url];
-
+ base::scoped_nsobject<NSPasteboardItem> item(
+ ClipboardUtil::PasteboardItemFromUrl(url, title));
NSPasteboard* pb = GetPasteboard();
- // passing UTIs into the pasteboard methods is valid >= 10.5
- [pb addTypes:[NSArray arrayWithObjects:NSURLPboardType, kUTTypeURLName, nil]
- owner:nil];
- [nsurl writeToPasteboard:pb];
- [pb setString:title forType:kUTTypeURLName];
+ ui::ClipboardUtil::AddDataToPasteboard(pb, item);
}
void ClipboardMac::WriteBitmap(const SkBitmap& bitmap) {
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac.h b/chromium/ui/base/clipboard/clipboard_util_mac.h
new file mode 100644
index 00000000000..1c4ff0ad99d
--- /dev/null
+++ b/chromium/ui/base/clipboard/clipboard_util_mac.h
@@ -0,0 +1,70 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_CLIPBOARD_CLIPBOARD_UTIL_MAC_H_
+#define UI_BASE_CLIPBOARD_CLIPBOARD_UTIL_MAC_H_
+
+#import <AppKit/AppKit.h>
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+class UI_BASE_EXPORT UniquePasteboard
+ : public base::RefCounted<UniquePasteboard> {
+ public:
+ UniquePasteboard();
+
+ NSPasteboard* get() { return pasteboard_; }
+
+ private:
+ friend class base::RefCounted<UniquePasteboard>;
+ ~UniquePasteboard();
+ base::scoped_nsobject<NSPasteboard> pasteboard_;
+};
+
+class UI_BASE_EXPORT ClipboardUtil {
+ public:
+ // Returns an NSPasteboardItem that represents the given |url|.
+ // |url| must not be nil.
+ // If |title| is nil, |url| is used in its place.
+ static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromUrl(
+ NSString* url,
+ NSString* title);
+
+ // Returns an NSPasteboardItem that represents the given |urls| and |titles|.
+ static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromUrls(
+ NSArray* urls,
+ NSArray* titles);
+
+ // Returns an NSPasteboardItem that represents the given string.
+ // |string| must not be nil.
+ static base::scoped_nsobject<NSPasteboardItem> PasteboardItemFromString(
+ NSString* string);
+
+ // Returns the title or url associated with a NSPasteboard which contains an
+ // url NSPasteboardItem.
+ static NSString* GetTitleFromPasteboardURL(NSPasteboard* pboard);
+ static NSString* GetURLFromPasteboardURL(NSPasteboard* pboard);
+
+ // Returns the UTI of a pasteboard type.
+ static NSString* UTIForPasteboardType(NSString* type);
+ static NSString* UTIForWebURLsAndTitles();
+
+ // For each pasteboard type in |item| that is not in |pboard|, add the type
+ // and its associated data.
+ static void AddDataToPasteboard(NSPasteboard* pboard, NSPasteboardItem* item);
+
+ // Returns whether the operation was succesful. On success, the two arrays are
+ // guaranteed to be equal length, and are populated with strings of |urls| and
+ // |titles|.
+ static bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
+ NSArray** urls,
+ NSArray** titles);
+};
+}
+
+#endif // UI_BASE_CLIPBOARD_CLIPBOARD_UTIL_MAC_H_
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac.mm b/chromium/ui/base/clipboard/clipboard_util_mac.mm
new file mode 100644
index 00000000000..7d0d774122c
--- /dev/null
+++ b/chromium/ui/base/clipboard/clipboard_util_mac.mm
@@ -0,0 +1,179 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/clipboard/clipboard_util_mac.h"
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+
+namespace {
+NSString* const kWebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
+NSString* const kCorePasteboardFlavorType_url =
+ @"CorePasteboardFlavorType 0x75726C20"; // 'url ' url
+NSString* const kCorePasteboardFlavorType_urln =
+ @"CorePasteboardFlavorType 0x75726C6E"; // 'urln' title
+
+// It's much more convenient to return an NSString than a
+// base::ScopedCFTypeRef<CFStringRef>, since the methods on NSPasteboardItem
+// require an NSString*.
+NSString* UTIFromPboardType(NSString* type) {
+ return [base::mac::CFToNSCast(UTTypeCreatePreferredIdentifierForTag(
+ kUTTagClassNSPboardType, base::mac::NSToCFCast(type), kUTTypeData))
+ autorelease];
+}
+} // namespace
+
+namespace ui {
+
+UniquePasteboard::UniquePasteboard()
+ : pasteboard_([[NSPasteboard pasteboardWithUniqueName] retain]) {}
+
+UniquePasteboard::~UniquePasteboard() {
+ [pasteboard_ releaseGlobally];
+}
+
+// static
+base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromUrl(
+ NSString* urlString,
+ NSString* title) {
+ DCHECK(urlString);
+ if (!title)
+ title = urlString;
+
+ base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
+
+ NSURL* url = [NSURL URLWithString:urlString];
+ if ([url isFileURL] &&
+ [[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
+ [item setPropertyList:@[ [url path] ]
+ forType:UTIFromPboardType(NSFilenamesPboardType)];
+ }
+
+ // Set Safari's URL + title arrays Pboard type.
+ NSArray* urlsAndTitles = @[ @[ urlString ], @[ title ] ];
+ [item setPropertyList:urlsAndTitles
+ forType:UTIFromPboardType(kWebURLsWithTitlesPboardType)];
+
+ // Set NSURLPboardType. The format of the property list is divined from
+ // Webkit's function PlatformPasteboard::setStringForType.
+ // https://github.com/WebKit/webkit/blob/master/Source/WebCore/platform/mac/PlatformPasteboardMac.mm
+ NSURL* base = [url baseURL];
+ if (base) {
+ [item setPropertyList:@[ [url relativeString], [base absoluteString] ]
+ forType:UTIFromPboardType(NSURLPboardType)];
+ } else if (url) {
+ [item setPropertyList:@[ [url absoluteString], @"" ]
+ forType:UTIFromPboardType(NSURLPboardType)];
+ }
+
+ [item setString:urlString forType:NSPasteboardTypeString];
+
+ [item setData:[urlString dataUsingEncoding:NSUTF8StringEncoding]
+ forType:UTIFromPboardType(kCorePasteboardFlavorType_url)];
+
+ [item setData:[title dataUsingEncoding:NSUTF8StringEncoding]
+ forType:UTIFromPboardType(kCorePasteboardFlavorType_urln)];
+ return item;
+}
+
+// static
+base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromUrls(
+ NSArray* urls,
+ NSArray* titles) {
+ base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
+
+ // Set Safari's URL + title arrays Pboard type.
+ NSArray* urlsAndTitles = @[ urls, titles ];
+ [item setPropertyList:urlsAndTitles
+ forType:UTIFromPboardType(kWebURLsWithTitlesPboardType)];
+
+ return item;
+}
+
+// static
+base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromString(
+ NSString* string) {
+ base::scoped_nsobject<NSPasteboardItem> item([[NSPasteboardItem alloc] init]);
+ [item setString:string forType:NSPasteboardTypeString];
+ return item;
+}
+
+//static
+NSString* ClipboardUtil::GetTitleFromPasteboardURL(NSPasteboard* pboard) {
+ return
+ [pboard stringForType:UTIFromPboardType(kCorePasteboardFlavorType_urln)];
+}
+
+//static
+NSString* ClipboardUtil::GetURLFromPasteboardURL(NSPasteboard* pboard) {
+ return
+ [pboard stringForType:UTIFromPboardType(kCorePasteboardFlavorType_url)];
+}
+
+// static
+NSString* ClipboardUtil::UTIForPasteboardType(NSString* type) {
+ return UTIFromPboardType(type);
+}
+
+// static
+NSString* ClipboardUtil::UTIForWebURLsAndTitles() {
+ return UTIFromPboardType(kWebURLsWithTitlesPboardType);
+}
+
+// static
+void ClipboardUtil::AddDataToPasteboard(NSPasteboard* pboard,
+ NSPasteboardItem* item) {
+ NSSet* oldTypes = [NSSet setWithArray:[pboard types]];
+ NSMutableSet* newTypes = [NSMutableSet setWithArray:[item types]];
+ [newTypes minusSet:oldTypes];
+
+ [pboard addTypes:[newTypes allObjects] owner:nil];
+ for (NSString* type in newTypes) {
+ // Technically, the object associated with |type| might be an NSString or a
+ // property list. It doesn't matter though, since the type gets pulled from
+ // and shoved into an NSDictionary.
+ [pboard setData:[item dataForType:type] forType:type];
+ }
+}
+
+// static
+bool ClipboardUtil::URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
+ NSArray** urls,
+ NSArray** titles) {
+ NSArray* bookmarkPairs = base::mac::ObjCCast<NSArray>([pboard
+ propertyListForType:UTIFromPboardType(kWebURLsWithTitlesPboardType)]);
+ if (!bookmarkPairs)
+ return false;
+
+ if ([bookmarkPairs count] != 2)
+ return false;
+
+ NSArray* urlsArr =
+ base::mac::ObjCCast<NSArray>([bookmarkPairs objectAtIndex:0]);
+ NSArray* titlesArr =
+ base::mac::ObjCCast<NSArray>([bookmarkPairs objectAtIndex:1]);
+
+ if (!urlsArr || !titlesArr)
+ return false;
+ if ([urlsArr count] < 1)
+ return false;
+ if ([urlsArr count] != [titlesArr count])
+ return false;
+
+ for (id obj in urlsArr) {
+ if (![obj isKindOfClass:[NSString class]])
+ return false;
+ }
+
+ for (id obj in titlesArr) {
+ if (![obj isKindOfClass:[NSString class]])
+ return false;
+ }
+
+ *urls = urlsArr;
+ *titles = titlesArr;
+ return true;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm b/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm
new file mode 100644
index 00000000000..28728c2e9bc
--- /dev/null
+++ b/chromium/ui/base/clipboard/clipboard_util_mac_unittest.mm
@@ -0,0 +1,99 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/base/clipboard/clipboard_util_mac.h"
+
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+#include "third_party/mozilla/NSPasteboard+Utils.h"
+
+namespace {
+
+class ClipboardUtilMacTest : public PlatformTest {
+ public:
+ ClipboardUtilMacTest() { }
+};
+
+TEST_F(ClipboardUtilMacTest, PasteboardItemFromUrl) {
+ NSString* urlString =
+ @"https://www.google.com/"
+ @"search?q=test&oq=test&aqs=chrome..69i57l2j69i60l4.278j0j7&"
+ @"sourceid=chrome&ie=UTF-8";
+
+ base::scoped_nsobject<NSPasteboardItem> item(
+ ui::ClipboardUtil::PasteboardItemFromUrl(urlString, nil));
+ scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
+ [pasteboard->get() writeObjects:@[ item ]];
+
+ NSArray* urls = nil;
+ NSArray* titles = nil;
+ [pasteboard->get() getURLs:&urls andTitles:&titles convertingFilenames:NO];
+
+ ASSERT_EQ(1u, [urls count]);
+ EXPECT_NSEQ(urlString, [urls objectAtIndex:0]);
+ ASSERT_EQ(1u, [titles count]);
+ EXPECT_NSEQ(urlString, [titles objectAtIndex:0]);
+
+ NSURL* url = [NSURL URLFromPasteboard:pasteboard->get()];
+ EXPECT_NSEQ([url absoluteString], urlString);
+}
+
+TEST_F(ClipboardUtilMacTest, PasteboardItemWithTitle) {
+ NSString* urlString = @"https://www.google.com/";
+ NSString* title = @"Burrowing Yams";
+
+ base::scoped_nsobject<NSPasteboardItem> item(
+ ui::ClipboardUtil::PasteboardItemFromUrl(urlString, title));
+ scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
+ [pasteboard->get() writeObjects:@[ item ]];
+
+ NSArray* urls = nil;
+ NSArray* titles = nil;
+ [pasteboard->get() getURLs:&urls andTitles:&titles convertingFilenames:NO];
+
+ ASSERT_EQ(1u, [urls count]);
+ EXPECT_NSEQ(urlString, [urls objectAtIndex:0]);
+ ASSERT_EQ(1u, [titles count]);
+ EXPECT_NSEQ(title, [titles objectAtIndex:0]);
+
+ NSURL* url = [NSURL URLFromPasteboard:pasteboard->get()];
+ EXPECT_NSEQ([url absoluteString], urlString);
+}
+
+TEST_F(ClipboardUtilMacTest, PasteboardItemWithFilePath) {
+ NSURL* url = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
+ ASSERT_TRUE(url);
+ NSString* urlString = [url absoluteString];
+
+ base::scoped_nsobject<NSPasteboardItem> item(
+ ui::ClipboardUtil::PasteboardItemFromUrl(urlString, nil));
+ scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
+ [pasteboard->get() writeObjects:@[ item ]];
+
+ NSArray* urls = nil;
+ NSArray* titles = nil;
+ [pasteboard->get() getURLs:&urls andTitles:&titles convertingFilenames:NO];
+
+ ASSERT_EQ(1u, [urls count]);
+ EXPECT_NSEQ(urlString, [urls objectAtIndex:0]);
+ ASSERT_EQ(1u, [titles count]);
+ EXPECT_NSEQ(urlString, [titles objectAtIndex:0]);
+
+ NSURL* urlFromPasteboard = [NSURL URLFromPasteboard:pasteboard->get()];
+ EXPECT_NSEQ(urlFromPasteboard, url);
+}
+
+TEST_F(ClipboardUtilMacTest, CheckForLeak) {
+ for (int i = 0; i < 10000; ++i) {
+ @autoreleasepool {
+ scoped_refptr<ui::UniquePasteboard> pboard = new ui::UniquePasteboard;
+ EXPECT_TRUE(pboard->get());
+ }
+ }
+}
+
+} // namespace
diff --git a/chromium/ui/base/clipboard/custom_data_helper.cc b/chromium/ui/base/clipboard/custom_data_helper.cc
index a50a0a072c7..e67829a3107 100644
--- a/chromium/ui/base/clipboard/custom_data_helper.cc
+++ b/chromium/ui/base/clipboard/custom_data_helper.cc
@@ -43,8 +43,8 @@ void ReadCustomDataTypes(const void* data,
SkippablePickle pickle(data, data_length);
base::PickleIterator iter(pickle);
- size_t size = 0;
- if (!iter.ReadSizeT(&size))
+ uint32_t size = 0;
+ if (!iter.ReadUInt32(&size))
return;
// Keep track of the original elements in the types vector. On failure, we
@@ -52,7 +52,7 @@ void ReadCustomDataTypes(const void* data,
// custom data pickles.
size_t original_size = types->size();
- for (size_t i = 0; i < size; ++i) {
+ for (uint32_t i = 0; i < size; ++i) {
types->push_back(base::string16());
if (!iter.ReadString16(&types->back()) || !pickle.SkipString16(&iter)) {
types->resize(original_size);
@@ -68,11 +68,11 @@ void ReadCustomDataForType(const void* data,
SkippablePickle pickle(data, data_length);
base::PickleIterator iter(pickle);
- size_t size = 0;
- if (!iter.ReadSizeT(&size))
+ uint32_t size = 0;
+ if (!iter.ReadUInt32(&size))
return;
- for (size_t i = 0; i < size; ++i) {
+ for (uint32_t i = 0; i < size; ++i) {
base::string16 deserialized_type;
if (!iter.ReadString16(&deserialized_type))
return;
@@ -91,11 +91,11 @@ void ReadCustomDataIntoMap(const void* data,
base::Pickle pickle(reinterpret_cast<const char*>(data), data_length);
base::PickleIterator iter(pickle);
- size_t size = 0;
- if (!iter.ReadSizeT(&size))
+ uint32_t size = 0;
+ if (!iter.ReadUInt32(&size))
return;
- for (size_t i = 0; i < size; ++i) {
+ for (uint32_t i = 0; i < size; ++i) {
base::string16 type;
if (!iter.ReadString16(&type)) {
// Data is corrupt, return an empty map.
@@ -115,7 +115,7 @@ void ReadCustomDataIntoMap(const void* data,
void WriteCustomDataToPickle(
const std::map<base::string16, base::string16>& data,
base::Pickle* pickle) {
- pickle->WriteSizeT(data.size());
+ pickle->WriteUInt32(data.size());
for (std::map<base::string16, base::string16>::const_iterator it =
data.begin();
it != data.end();
diff --git a/chromium/ui/base/clipboard/custom_data_helper_unittest.cc b/chromium/ui/base/clipboard/custom_data_helper_unittest.cc
index 1ed53c66750..4d515476559 100644
--- a/chromium/ui/base/clipboard/custom_data_helper_unittest.cc
+++ b/chromium/ui/base/clipboard/custom_data_helper_unittest.cc
@@ -120,7 +120,7 @@ TEST(CustomDataHelperTest, BadReadTypes) {
expected.push_back(ASCIIToUTF16("f"));
base::Pickle malformed;
- malformed.WriteSizeT(1000);
+ malformed.WriteUInt32(1000);
malformed.WriteString16(ASCIIToUTF16("hello"));
malformed.WriteString16(ASCIIToUTF16("world"));
std::vector<base::string16> actual(expected);
@@ -128,7 +128,7 @@ TEST(CustomDataHelperTest, BadReadTypes) {
EXPECT_EQ(expected, actual);
base::Pickle malformed2;
- malformed2.WriteSizeT(1);
+ malformed2.WriteUInt32(1);
malformed2.WriteString16(ASCIIToUTF16("hello"));
std::vector<base::string16> actual2(expected);
ReadCustomDataTypes(malformed2.data(), malformed2.size(), &actual2);
@@ -140,7 +140,7 @@ TEST(CustomDataHelperTest, BadPickle) {
std::map<base::string16, base::string16> result_map;
base::Pickle malformed;
- malformed.WriteSizeT(1000);
+ malformed.WriteUInt32(1000);
malformed.WriteString16(ASCIIToUTF16("hello"));
malformed.WriteString16(ASCIIToUTF16("world"));
@@ -153,7 +153,7 @@ TEST(CustomDataHelperTest, BadPickle) {
EXPECT_EQ(0u, result_map.size());
base::Pickle malformed2;
- malformed2.WriteSizeT(1);
+ malformed2.WriteUInt32(1);
malformed2.WriteString16(ASCIIToUTF16("hello"));
ReadCustomDataForType(malformed2.data(),
diff --git a/chromium/ui/base/cocoa/appkit_utils.mm b/chromium/ui/base/cocoa/appkit_utils.mm
index 6aa90ae6789..ce672699f5d 100644
--- a/chromium/ui/base/cocoa/appkit_utils.mm
+++ b/chromium/ui/base/cocoa/appkit_utils.mm
@@ -15,18 +15,45 @@ NSImage* GetImage(int image_id) {
.ToNSImage();
}
-// Whether windows should miniaturize on a double-click on the title bar.
-bool ShouldWindowsMiniaturizeOnDoubleClick() {
- // We use an undocumented method in Cocoa; if it doesn't exist, default to
- // |true|. If it ever goes away, we can do (using an undocumented pref key):
- // NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
- // return ![defaults objectForKey:@"AppleMiniaturizeOnDoubleClick"] ||
- // [defaults boolForKey:@"AppleMiniaturizeOnDoubleClick"];
+// Double-click in window title bar actions.
+enum class DoubleClickAction {
+ NONE,
+ MINIMIZE,
+ MAXIMIZE,
+};
+
+// The action to take when the user double-clicks in the window title bar.
+DoubleClickAction WindowTitleBarDoubleClickAction() {
+ // El Capitan introduced a Dock preference to configure the window title bar
+ // double-click action (Minimize, Maximize, or nothing).
+ if (base::mac::IsOSElCapitanOrLater()) {
+ NSString* doubleClickAction = [[NSUserDefaults standardUserDefaults]
+ objectForKey:@"AppleActionOnDoubleClick"];
+
+ if ([doubleClickAction isEqualToString:@"Minimize"]) {
+ return DoubleClickAction::MINIMIZE;
+ } else if ([doubleClickAction isEqualToString:@"Maximize"]) {
+ return DoubleClickAction::MAXIMIZE;
+ }
+
+ return DoubleClickAction::NONE;
+ }
+
+ // Determine minimize using an undocumented method in Cocoa. If we're
+ // running on an earlier version of the OS that doesn't implement it,
+ // just default to the minimize action.
BOOL methodImplemented =
[NSWindow respondsToSelector:@selector(_shouldMiniaturizeOnDoubleClick)];
- DCHECK(methodImplemented);
- return !methodImplemented ||
- [NSWindow performSelector:@selector(_shouldMiniaturizeOnDoubleClick)];
+ if (!methodImplemented ||
+ [NSWindow performSelector:@selector(_shouldMiniaturizeOnDoubleClick)]) {
+ return DoubleClickAction::MINIMIZE;
+ }
+
+ // At this point _shouldMiniaturizeOnDoubleClick has returned |NO|. On
+ // Yosemite, that means a double-click should Maximize the window, and on
+ // all prior OSes a double-click should do nothing.
+ return base::mac::IsOSYosemite() ? DoubleClickAction::MAXIMIZE
+ : DoubleClickAction::NONE;
}
} // namespace
@@ -54,10 +81,17 @@ void DrawNinePartImage(NSRect frame,
}
void WindowTitlebarReceivedDoubleClick(NSWindow* window, id sender) {
- if (ShouldWindowsMiniaturizeOnDoubleClick()) {
- [window performMiniaturize:sender];
- } else if (base::mac::IsOSYosemiteOrLater()) {
- [window performZoom:sender];
+ switch (WindowTitleBarDoubleClickAction()) {
+ case DoubleClickAction::MINIMIZE:
+ [window performMiniaturize:sender];
+ break;
+
+ case DoubleClickAction::MAXIMIZE:
+ [window performZoom:sender];
+ break;
+
+ case DoubleClickAction::NONE:
+ break;
}
}
diff --git a/chromium/ui/base/cocoa/cocoa_base_utils.h b/chromium/ui/base/cocoa/cocoa_base_utils.h
index c479f72f2a5..627fe3ba325 100644
--- a/chromium/ui/base/cocoa/cocoa_base_utils.h
+++ b/chromium/ui/base/cocoa/cocoa_base_utils.h
@@ -26,6 +26,14 @@ UI_BASE_EXPORT WindowOpenDisposition
UI_BASE_EXPORT WindowOpenDisposition
WindowOpenDispositionFromNSEventWithFlags(NSEvent* event, NSUInteger flags);
+// Converts a point from window coordinates to screen coordinates.
+UI_BASE_EXPORT NSPoint ConvertPointFromWindowToScreen(NSWindow* window,
+ NSPoint point);
+
+// Converts a point from screen coordinates to window coordinates.
+UI_BASE_EXPORT NSPoint ConvertPointFromScreenToWindow(NSWindow* window,
+ NSPoint point);
+
} // namespace ui
#endif // UI_BASE_COCOA_COCOA_BASE_UTILS_H_
diff --git a/chromium/ui/base/cocoa/cocoa_base_utils.mm b/chromium/ui/base/cocoa/cocoa_base_utils.mm
index 0830f3488a8..ca5d885abf8 100644
--- a/chromium/ui/base/cocoa/cocoa_base_utils.mm
+++ b/chromium/ui/base/cocoa/cocoa_base_utils.mm
@@ -4,6 +4,7 @@
#include "ui/base/cocoa/cocoa_base_utils.h"
+#include "base/mac/sdk_forward_declarations.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
namespace ui {
@@ -19,4 +20,14 @@ WindowOpenDisposition WindowOpenDispositionFromNSEventWithFlags(
return DispositionFromEventFlags(event_flags);
}
+NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point) {
+ NSRect point_rect = NSMakeRect(point.x, point.y, 0, 0);
+ return [window convertRectToScreen:point_rect].origin;
+}
+
+NSPoint ConvertPointFromScreenToWindow(NSWindow* window, NSPoint point) {
+ NSRect point_rect = NSMakeRect(point.x, point.y, 0, 0);
+ return [window convertRectFromScreen:point_rect].origin;
+}
+
} // namespace ui
diff --git a/chromium/ui/base/cocoa/command_dispatcher.mm b/chromium/ui/base/cocoa/command_dispatcher.mm
index 64ac8fd1bb2..46a351b4ce8 100644
--- a/chromium/ui/base/cocoa/command_dispatcher.mm
+++ b/chromium/ui/base/cocoa/command_dispatcher.mm
@@ -5,6 +5,7 @@
#import "ui/base/cocoa/command_dispatcher.h"
#include "base/logging.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
namespace {
@@ -15,8 +16,8 @@ NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) {
// Convert the event's location from the original window's coordinates into
// our own.
NSPoint location = [event locationInWindow];
- location = [[event window] convertBaseToScreen:location];
- location = [window convertScreenToBase:location];
+ location = ui::ConvertPointFromWindowToScreen([event window], location);
+ location = ui::ConvertPointFromScreenToWindow(window, location);
// Various things *only* apply to key down/up.
bool is_a_repeat = false;
diff --git a/chromium/ui/base/cocoa/controls/blue_label_button.mm b/chromium/ui/base/cocoa/controls/blue_label_button.mm
index 9d9b5805c9c..37ecc8da0f2 100644
--- a/chromium/ui/base/cocoa/controls/blue_label_button.mm
+++ b/chromium/ui/base/cocoa/controls/blue_label_button.mm
@@ -29,6 +29,8 @@ const SkColor kPressInnerRingColor = SkColorSetRGB(0x3f, 0x73, 0xcd);
const SkColor kOuterRingColor = SkColorSetRGB(0x2b, 0x67, 0xce);
const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2);
+const int kFontSizeDelta = ui::ResourceBundle::kSmallFontDelta;
+
@interface BlueLabelButtonCell : NSButtonCell
+ (NSAttributedString*)generateAttributedString:(NSString*)buttonText;
@@ -54,8 +56,7 @@ const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2);
+ (NSAttributedString*)generateAttributedString:(NSString*)buttonText {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- NSFont* buttonFont = rb.GetFontList(ui::ResourceBundle::SmallFont).
- GetPrimaryFont().GetNativeFont();
+ NSFont* buttonFont = rb.GetFontWithDelta(kFontSizeDelta).GetNativeFont();
base::scoped_nsobject<NSMutableParagraphStyle> buttonTextParagraphStyle(
[[NSMutableParagraphStyle alloc] init]);
[buttonTextParagraphStyle setAlignment:NSCenterTextAlignment];
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm
index e67e60db12e..754be72f613 100644
--- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm
+++ b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm
@@ -91,7 +91,7 @@ using hyperlink_button_cell::UnderlineBehavior;
// Creates the NSDictionary of attributes for the attributed string.
- (NSDictionary*)linkAttributes {
- NSUInteger underlineMask = NSNoUnderlineStyle;
+ NSUInteger underlineMask = NSUnderlineStyleNone;
if (underlineBehavior_ == UnderlineBehavior::ALWAYS ||
(mouseIsInside_ && [self isEnabled] &&
underlineBehavior_ == UnderlineBehavior::ON_HOVER)) {
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm b/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm
index 2a50e0f4a94..dd5e4504333 100644
--- a/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm
+++ b/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm
@@ -162,7 +162,7 @@ const float kTextBaselineShift = -1.0;
NSUnderlineStyleAttributeName : @(YES),
NSCursorAttributeName : [NSCursor pointingHandCursor],
NSLinkAttributeName : url,
- NSUnderlineStyleAttributeName : @(NSSingleUnderlineStyle)
+ NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle)
};
[[self textStorage] addAttributes:attributes range:range];
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm b/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
index 671be65386c..28014246f75 100644
--- a/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
+++ b/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
@@ -40,11 +40,12 @@ class HyperlinkTextViewTest : public ui::CocoaTest {
[[NSMutableDictionary dictionaryWithDictionary:
GetDefaultTextAttributes()] retain]);
[linkAttributes_ addEntriesFromDictionary:@{
- NSForegroundColorAttributeName : [NSColor blueColor],
- NSUnderlineStyleAttributeName : @(YES),
- NSCursorAttributeName : [NSCursor pointingHandCursor],
- NSUnderlineStyleAttributeName : @(NSSingleUnderlineStyle),
- NSLinkAttributeName : @""}];
+ NSForegroundColorAttributeName : [NSColor blueColor],
+ NSUnderlineStyleAttributeName : @(YES),
+ NSCursorAttributeName : [NSCursor pointingHandCursor],
+ NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle),
+ NSLinkAttributeName : @""
+ }];
}
return [NSMutableDictionary dictionaryWithDictionary:linkAttributes_];
}
diff --git a/chromium/ui/base/cocoa/menu_controller_unittest.mm b/chromium/ui/base/cocoa/menu_controller_unittest.mm
index 5bda6b6c096..57a32bed3fb 100644
--- a/chromium/ui/base/cocoa/menu_controller_unittest.mm
+++ b/chromium/ui/base/cocoa/menu_controller_unittest.mm
@@ -271,8 +271,9 @@ TEST_F(MenuControllerTest, Validate) {
// Tests that items which have a font set actually use that font.
TEST_F(MenuControllerTest, LabelFontList) {
Delegate delegate;
- const gfx::FontList& bold = ResourceBundle::GetSharedInstance().GetFontList(
- ResourceBundle::BoldFont);
+ const gfx::FontList& bold =
+ ResourceBundle::GetSharedInstance().GetFontListWithDelta(0,
+ gfx::Font::BOLD);
FontListMenuModel model(&delegate, &bold, 0);
model.AddItem(1, ASCIIToUTF16("one"));
model.AddItem(2, ASCIIToUTF16("two"));
diff --git a/chromium/ui/base/cocoa/nib_loading.mm b/chromium/ui/base/cocoa/nib_loading.mm
index dd0eb48d806..6deea19f698 100644
--- a/chromium/ui/base/cocoa/nib_loading.mm
+++ b/chromium/ui/base/cocoa/nib_loading.mm
@@ -7,6 +7,11 @@
#include "base/mac/bundle_locations.h"
#include "base/mac/scoped_nsobject.h"
+@interface NSNib (MountainLionSDK)
+- (BOOL)instantiateWithOwner:(nullable id)owner
+ topLevelObjects:(NSArray* __nonnull* __nullable)topLevelObjects;
+@end
+
namespace ui {
NSView* GetViewFromNib(NSString* name) {
@@ -17,18 +22,10 @@ NSView* GetViewFromNib(NSString* name) {
return nil;
NSArray* objects;
- BOOL success = [nib instantiateNibWithOwner:nil
- topLevelObjects:&objects];
+ BOOL success = [nib instantiateWithOwner:nil topLevelObjects:&objects];
if (!success)
return nil;
- // When loading a nib manually (as opposed to using an NSWindowController or
- // NSViewController), all the top-level objects need to be explicitly
- // released. See
- // http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW10
- // for more information.
- [objects makeObjectsPerformSelector:@selector(release)];
-
// For some strange reason, even nibs that appear to have but one top-level
// object often have more (an NSApplication, etc.). Filter out what isn't
// desired.
diff --git a/chromium/ui/base/cocoa/three_part_image.h b/chromium/ui/base/cocoa/three_part_image.h
index ebeef5fdc4d..72da5ca918a 100644
--- a/chromium/ui/base/cocoa/three_part_image.h
+++ b/chromium/ui/base/cocoa/three_part_image.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_COCOA_THREE_PART_IMAGE_H
-#define UI_BASE_COCOA_THREE_PART_IMAGE_H
+#ifndef UI_BASE_COCOA_THREE_PART_IMAGE_H_
+#define UI_BASE_COCOA_THREE_PART_IMAGE_H_
#import <Cocoa/Cocoa.h>
@@ -18,9 +18,9 @@ namespace ui {
// Vertical orientation is not currently supported.
class UI_BASE_EXPORT ThreePartImage {
public:
- // |left_id|, |middle_id|, and |right_id| are ResourceBundle image
- // identifiers. Specify 0 for |middle_id| if there is no middle image.
- ThreePartImage(int left_id, int middle_id, int right_id);
+ // Create a ThreePartImage from existing NSImages. Specify nil for |middle| if
+ // there is no middle image.
+ ThreePartImage(NSImage* left, NSImage* middle, NSImage* right);
~ThreePartImage();
// Returns the image rects if drawn in |bounds|.
@@ -51,4 +51,4 @@ class UI_BASE_EXPORT ThreePartImage {
} // namespace ui
-#endif // UI_BASE_COCOA_THREE_PART_IMAGE_H
+#endif // UI_BASE_COCOA_THREE_PART_IMAGE_H_
diff --git a/chromium/ui/base/cocoa/three_part_image.mm b/chromium/ui/base/cocoa/three_part_image.mm
index 5fb8916f9f2..18ec2ddbfd0 100644
--- a/chromium/ui/base/cocoa/three_part_image.mm
+++ b/chromium/ui/base/cocoa/three_part_image.mm
@@ -9,17 +9,17 @@
namespace ui {
-ThreePartImage::ThreePartImage(int left_id, int middle_id, int right_id) {
- DCHECK(left_id);
- DCHECK(right_id);
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- leftImage_.reset(rb.GetNativeImageNamed(left_id).CopyNSImage());
- rightImage_.reset(rb.GetNativeImageNamed(right_id).CopyNSImage());
+ThreePartImage::ThreePartImage(NSImage* left, NSImage* middle, NSImage* right) {
+ DCHECK(left);
+ DCHECK(right);
+ leftImage_.reset([left retain]);
+ rightImage_.reset([right retain]);
leftSize_ = [leftImage_ size];
rightSize_ = [rightImage_ size];
- if (middle_id)
- middleImage_.reset(rb.GetNativeImageNamed(middle_id).CopyNSImage());
+ if (middle) {
+ middleImage_.reset([middle retain]);
+ }
}
ThreePartImage::~ThreePartImage() {
diff --git a/chromium/ui/base/cocoa/three_part_image_unittest.mm b/chromium/ui/base/cocoa/three_part_image_unittest.mm
index 43db298ec77..efccbefce07 100644
--- a/chromium/ui/base/cocoa/three_part_image_unittest.mm
+++ b/chromium/ui/base/cocoa/three_part_image_unittest.mm
@@ -6,6 +6,7 @@
#include "base/memory/scoped_ptr.h"
#include "testing/gtest_mac.h"
+#include "ui/base/resource/resource_bundle.h"
#import "ui/gfx/test/ui_cocoa_test_helper.h"
#include "ui/resources/grit/ui_resources.h"
@@ -13,9 +14,14 @@ namespace ui {
namespace test {
TEST(ThreePartImageTest, GetRects) {
- ThreePartImage image(IDR_BROWSER_ACTION_BADGE_LEFT,
- IDR_BROWSER_ACTION_BADGE_CENTER,
- IDR_BROWSER_ACTION_BADGE_RIGHT);
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ base::scoped_nsobject<NSImage> leftImage(
+ rb.GetNativeImageNamed(IDR_BROWSER_ACTION_BADGE_LEFT).CopyNSImage());
+ base::scoped_nsobject<NSImage> middleImage(
+ rb.GetNativeImageNamed(IDR_BROWSER_ACTION_BADGE_CENTER).CopyNSImage());
+ base::scoped_nsobject<NSImage> rightImage(
+ rb.GetNativeImageNamed(IDR_BROWSER_ACTION_BADGE_RIGHT).CopyNSImage());
+ ThreePartImage image(leftImage, middleImage, rightImage);
NSRect bounds = NSMakeRect(0, 0, 20, 11);
EXPECT_NSRECT_EQ(NSMakeRect(0, 0, 4, 11), image.GetLeftRect(bounds));
EXPECT_NSRECT_EQ(NSMakeRect(4, 0, 12, 11), image.GetMiddleRect(bounds));
@@ -23,9 +29,12 @@ TEST(ThreePartImageTest, GetRects) {
}
TEST(ThreePartImageTest, GetRectsWithoutMiddle) {
- ThreePartImage image(IDR_BROWSER_ACTION_BADGE_LEFT,
- 0,
- IDR_BROWSER_ACTION_BADGE_RIGHT);
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ base::scoped_nsobject<NSImage> leftImage(
+ rb.GetNativeImageNamed(IDR_BROWSER_ACTION_BADGE_LEFT).CopyNSImage());
+ base::scoped_nsobject<NSImage> rightImage(
+ rb.GetNativeImageNamed(IDR_BROWSER_ACTION_BADGE_RIGHT).CopyNSImage());
+ ThreePartImage image(leftImage, nullptr, rightImage);
NSRect bounds = NSMakeRect(0, 0, 20, 11);
EXPECT_NSRECT_EQ(NSMakeRect(0, 0, 4, 11), image.GetLeftRect(bounds));
EXPECT_NSRECT_EQ(NSMakeRect(4, 0, 12, 11), image.GetMiddleRect(bounds));
@@ -33,7 +42,12 @@ TEST(ThreePartImageTest, GetRectsWithoutMiddle) {
}
TEST(ThreePartImageTest, HitTest) {
- ThreePartImage image(IDR_BACK_ARROW, 0, IDR_FORWARD_ARROW);
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ base::scoped_nsobject<NSImage> leftImage(
+ rb.GetNativeImageNamed(IDR_BACK_ARROW).CopyNSImage());
+ base::scoped_nsobject<NSImage> rightImage(
+ rb.GetNativeImageNamed(IDR_FORWARD_ARROW).CopyNSImage());
+ ThreePartImage image(leftImage, nullptr, rightImage);
NSRect bounds = NSMakeRect(0, 0, 512, 128);
// The middle of the arrows are hits.
diff --git a/chromium/ui/base/cursor/cursors_aura.cc b/chromium/ui/base/cursor/cursors_aura.cc
index 8dca8ff1500..993368e39c0 100644
--- a/chromium/ui/base/cursor/cursors_aura.cc
+++ b/chromium/ui/base/cursor/cursors_aura.cc
@@ -13,6 +13,11 @@
#include "ui/gfx/image/image_skia.h"
#include "ui/resources/grit/ui_resources.h"
+#if defined(OS_WIN)
+#include "ui/base/cursor/cursor_loader_win.h"
+#include "ui/gfx/icon_util.h"
+#endif
+
namespace ui {
namespace {
@@ -228,6 +233,13 @@ bool GetCursorBitmap(const Cursor& cursor,
SkBitmap* bitmap,
gfx::Point* point) {
DCHECK(bitmap && point);
+#if defined(OS_WIN)
+ Cursor cursor_copy = cursor;
+ ui::CursorLoaderWin cursor_loader;
+ cursor_loader.SetPlatformCursor(&cursor_copy);
+ const scoped_ptr<SkBitmap> cursor_bitmap(IconUtil::CreateSkBitmapFromHICON(
+ cursor_copy.platform()));
+#else
int resource_id;
if (!GetCursorDataFor(ui::CURSOR_SET_NORMAL,
cursor.native_type(),
@@ -239,6 +251,7 @@ bool GetCursorBitmap(const Cursor& cursor,
const SkBitmap* cursor_bitmap = ResourceBundle::GetSharedInstance().
GetImageSkiaNamed(resource_id)->bitmap();
+#endif
if (!cursor_bitmap)
return false;
*bitmap = *cursor_bitmap;
diff --git a/chromium/ui/base/default_style.h b/chromium/ui/base/default_style.h
new file mode 100644
index 00000000000..49790af2a8e
--- /dev/null
+++ b/chromium/ui/base/default_style.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_DEFAULT_STYLE_H_
+#define UI_BASE_DEFAULT_STYLE_H_
+
+#include "build/build_config.h"
+
+// This file contains the constants that provide the default style for UI
+// controls and dialogs.
+
+namespace ui {
+
+// Default font size delta for messages in dialogs. Note that on Windows, the
+// "base" font size is determined by consulting the system for the font used in
+// native MessageBox dialogs. On Mac, it is [NSFont systemFontSize]. Linux
+// consults the default font description for a GTK Widget context. On ChromeOS,
+// ui::ResourceBundle provides a description via IDS_UI_FONT_FAMILY_CROS.
+const int kMessageFontSizeDelta = 0;
+
+// Default font size delta for dialog buttons, textfields, and labels.
+#if defined(OS_MACOSX)
+// Cocoa dialogs prefer [NSFont smallSystemFontSize] for labels (typically 11pt
+// vs 13pt).
+const int kLabelFontSizeDelta = -2;
+#else
+const int kLabelFontSizeDelta = 0;
+#endif
+
+// Font size delta for dialog titles.
+#if defined(OS_MACOSX)
+const int kTitleFontSizeDelta = 0;
+#else
+const int kTitleFontSizeDelta = 3;
+#endif
+
+} // namespace ui
+
+#endif // UI_BASE_DEFAULT_STYLE_H_
diff --git a/chromium/ui/base/default_theme_provider.h b/chromium/ui/base/default_theme_provider.h
index 35d47b2fedb..91ee8d86d11 100644
--- a/chromium/ui/base/default_theme_provider.h
+++ b/chromium/ui/base/default_theme_provider.h
@@ -35,6 +35,8 @@ class UI_BASE_EXPORT DefaultThemeProvider : public ThemeProvider {
#if defined(OS_MACOSX)
bool UsingSystemTheme() const override;
+ bool InIncognitoMode() const override;
+ bool HasCustomColor(int id) const override;
NSImage* GetNSImageNamed(int id) const override;
NSColor* GetNSImageColorNamed(int id) const override;
NSColor* GetNSColor(int id) const override;
diff --git a/chromium/ui/base/default_theme_provider_mac.mm b/chromium/ui/base/default_theme_provider_mac.mm
index 71b0f8eb86b..74acb3b4982 100644
--- a/chromium/ui/base/default_theme_provider_mac.mm
+++ b/chromium/ui/base/default_theme_provider_mac.mm
@@ -14,6 +14,14 @@ bool DefaultThemeProvider::UsingSystemTheme() const {
return true;
}
+bool DefaultThemeProvider::InIncognitoMode() const {
+ return false;
+}
+
+bool DefaultThemeProvider::HasCustomColor(int id) const {
+ return false;
+}
+
NSImage* DefaultThemeProvider::GetNSImageNamed(int id) const {
return ResourceBundle::GetSharedInstance().
GetNativeImageNamed(id).ToNSImage();
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc
index 9cd070a29e6..009c3eec9b5 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
-#include "net/base/net_util.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/file_info.h"
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
index 457ba6b41f7..90fa7c20420 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
@@ -13,7 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/dragdrop/file_info.h"
-#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/events/platform/x11/x11_event_source_glib.h"
#include "url/gurl.h"
const char kFileURL[] = "file:///home/user/file.txt";
@@ -39,7 +39,7 @@ class OSExchangeDataProviderAuraX11Test : public testing::Test {
protected:
base::MessageLoopForUI message_loop;
- X11EventSource event_source;
+ X11EventSourceGlib event_source;
ui::OSExchangeDataProviderAuraX11 provider;
};
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h
index c619ab9d806..378602923a9 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h
@@ -5,20 +5,21 @@
#ifndef UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_MAC_H_
#define UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_MAC_H_
-#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/dragdrop/os_exchange_data.h"
@class NSPasteboard;
namespace ui {
+class UniquePasteboard;
// OSExchangeData::Provider implementation for Mac.
class UI_BASE_EXPORT OSExchangeDataProviderMac
: public OSExchangeData::Provider {
public:
OSExchangeDataProviderMac();
- explicit OSExchangeDataProviderMac(NSPasteboard* pasteboard);
~OSExchangeDataProviderMac() override;
// Overridden from OSExchangeData::Provider:
@@ -45,7 +46,8 @@ class UI_BASE_EXPORT OSExchangeDataProviderMac
bool HasCustomFormat(const Clipboard::FormatType& format) const override;
private:
- base::scoped_nsobject<NSPasteboard> pasteboard_;
+ explicit OSExchangeDataProviderMac(scoped_refptr<ui::UniquePasteboard>);
+ scoped_refptr<ui::UniquePasteboard> pasteboard_;
DISALLOW_COPY_AND_ASSIGN(OSExchangeDataProviderMac);
};
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm
index 72d647f1406..030d0d08412 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -11,17 +11,17 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
#include "url/gurl.h"
namespace ui {
OSExchangeDataProviderMac::OSExchangeDataProviderMac()
- : pasteboard_([[NSPasteboard pasteboardWithUniqueName] retain]) {
-}
+ : pasteboard_(new ui::UniquePasteboard) {}
-OSExchangeDataProviderMac::OSExchangeDataProviderMac(NSPasteboard* pasteboard)
- : pasteboard_([pasteboard retain]) {
-}
+OSExchangeDataProviderMac::OSExchangeDataProviderMac(
+ scoped_refptr<ui::UniquePasteboard> pb)
+ : pasteboard_(pb) {}
OSExchangeDataProviderMac::~OSExchangeDataProviderMac() {
}
@@ -40,21 +40,21 @@ bool OSExchangeDataProviderMac::DidOriginateFromRenderer() const {
}
void OSExchangeDataProviderMac::SetString(const base::string16& string) {
- [pasteboard_ writeObjects:@[ base::SysUTF16ToNSString(string) ]];
+ [pasteboard_->get() writeObjects:@[ base::SysUTF16ToNSString(string) ]];
}
void OSExchangeDataProviderMac::SetURL(const GURL& url,
const base::string16& title) {
NSURL* ns_url = [NSURL URLWithString:base::SysUTF8ToNSString(url.spec())];
- [pasteboard_ writeObjects:@[ ns_url ]];
+ [pasteboard_->get() writeObjects:@[ ns_url ]];
- [pasteboard_ setString:base::SysUTF16ToNSString(title)
- forType:kCorePasteboardFlavorType_urln];
+ [pasteboard_->get() setString:base::SysUTF16ToNSString(title)
+ forType:kCorePasteboardFlavorType_urln];
}
void OSExchangeDataProviderMac::SetFilename(const base::FilePath& path) {
- [pasteboard_ setPropertyList:@[ base::SysUTF8ToNSString(path.value()) ]
- forType:NSFilenamesPboardType];
+ [pasteboard_->get() setPropertyList:@[ base::SysUTF8ToNSString(path.value()) ]
+ forType:NSFilenamesPboardType];
}
void OSExchangeDataProviderMac::SetFilenames(
@@ -66,13 +66,14 @@ void OSExchangeDataProviderMac::SetPickledData(
const Clipboard::FormatType& format,
const base::Pickle& data) {
NSData* ns_data = [NSData dataWithBytes:data.data() length:data.size()];
- [pasteboard_ setData:ns_data forType:format.ToNSString()];
+ [pasteboard_->get() setData:ns_data forType:format.ToNSString()];
}
bool OSExchangeDataProviderMac::GetString(base::string16* data) const {
DCHECK(data);
- NSArray* items = [pasteboard_ readObjectsForClasses:@[ [NSString class] ]
- options:@{ }];
+ NSArray* items =
+ [pasteboard_->get() readObjectsForClasses:@[ [NSString class] ]
+ options:@{}];
// There was no NSString, check for an NSURL.
if ([items count] == 0) {
@@ -95,8 +96,8 @@ bool OSExchangeDataProviderMac::GetURLAndTitle(
base::string16* title) const {
DCHECK(url);
DCHECK(title);
- NSArray* items = [pasteboard_ readObjectsForClasses:@[ [NSURL class] ]
- options:@{ }];
+ NSArray* items =
+ [pasteboard_->get() readObjectsForClasses:@[ [NSURL class] ] options:@{}];
if ([items count] == 0)
return false;
@@ -105,7 +106,8 @@ bool OSExchangeDataProviderMac::GetURLAndTitle(
if (policy == OSExchangeData::DO_NOT_CONVERT_FILENAMES) {
// If the URL matches a filename, assume that it came from SetFilename().
// Don't return it if we are not supposed to convert filename to URL.
- NSArray* paths = [pasteboard_ propertyListForType:NSFilenamesPboardType];
+ NSArray* paths =
+ [pasteboard_->get() propertyListForType:NSFilenamesPboardType];
NSString* url_path = [[ns_url path] stringByStandardizingPath];
for (NSString* path in paths) {
if ([[path stringByStandardizingPath] isEqualToString:url_path])
@@ -115,12 +117,13 @@ bool OSExchangeDataProviderMac::GetURLAndTitle(
*url = GURL([[ns_url absoluteString] UTF8String]);
*title = base::SysNSStringToUTF16(
- [pasteboard_ stringForType:kCorePasteboardFlavorType_urln]);
+ [pasteboard_->get() stringForType:kCorePasteboardFlavorType_urln]);
return true;
}
bool OSExchangeDataProviderMac::GetFilename(base::FilePath* path) const {
- NSArray* paths = [pasteboard_ propertyListForType:NSFilenamesPboardType];
+ NSArray* paths =
+ [pasteboard_->get() propertyListForType:NSFilenamesPboardType];
if ([paths count] == 0)
return false;
@@ -138,7 +141,7 @@ bool OSExchangeDataProviderMac::GetPickledData(
const Clipboard::FormatType& format,
base::Pickle* data) const {
DCHECK(data);
- NSData* ns_data = [pasteboard_ dataForType:format.ToNSString()];
+ NSData* ns_data = [pasteboard_->get() dataForType:format.ToNSString()];
if (!ns_data)
return false;
@@ -149,7 +152,7 @@ bool OSExchangeDataProviderMac::GetPickledData(
bool OSExchangeDataProviderMac::HasString() const {
NSArray* classes = @[ [NSString class] ];
- return [pasteboard_ canReadObjectForClasses:classes options:nil];
+ return [pasteboard_->get() canReadObjectForClasses:classes options:nil];
}
bool OSExchangeDataProviderMac::HasURL(
@@ -160,12 +163,12 @@ bool OSExchangeDataProviderMac::HasURL(
}
bool OSExchangeDataProviderMac::HasFile() const {
- return [[pasteboard_ types] containsObject:NSFilenamesPboardType];
+ return [[pasteboard_->get() types] containsObject:NSFilenamesPboardType];
}
bool OSExchangeDataProviderMac::HasCustomFormat(
const Clipboard::FormatType& format) const {
- return [[pasteboard_ types] containsObject:format.ToNSString()];
+ return [[pasteboard_->get() types] containsObject:format.ToNSString()];
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn
index b915757c0d4..668f4f9d0ae 100644
--- a/chromium/ui/base/ime/BUILD.gn
+++ b/chromium/ui/base/ime/BUILD.gn
@@ -5,6 +5,14 @@
import("//build/config/ui.gni")
import("//testing/test.gni")
+source_set("text_input_types") {
+ sources = [
+ "text_input_flags.h",
+ "text_input_mode.h",
+ "text_input_type.h",
+ ]
+}
+
component("ime") {
output_name = "ui_base_ime"
sources = [
@@ -34,8 +42,6 @@ component("ime") {
"chromeos/input_method_descriptor.h",
"chromeos/input_method_manager.cc",
"chromeos/input_method_manager.h",
- "chromeos/input_method_whitelist.cc",
- "chromeos/input_method_whitelist.h",
"chromeos/mock_component_extension_ime_manager_delegate.cc",
"chromeos/mock_component_extension_ime_manager_delegate.h",
"chromeos/mock_ime_candidate_window_handler.cc",
@@ -51,9 +57,7 @@ component("ime") {
"composition_underline.h",
"ime_bridge.cc",
"ime_bridge.h",
- "ime_engine_handler_interface.cc",
"ime_engine_handler_interface.h",
- "ime_engine_observer.h",
"ime_input_context_handler_interface.h",
"infolist_entry.cc",
"infolist_entry.h",
@@ -85,12 +89,8 @@ component("ime") {
"linux/linux_input_method_context_factory.h",
"mock_input_method.cc",
"mock_input_method.h",
- "remote_input_method_delegate_win.h",
- "remote_input_method_win.cc",
- "remote_input_method_win.h",
"text_input_client.cc",
"text_input_client.h",
- "text_input_type.h",
"ui_base_ime_export.h",
"win/imm32_manager.cc",
"win/imm32_manager.h",
@@ -116,6 +116,10 @@ component("ime") {
"//url",
]
+ public_deps = [
+ ":text_input_types",
+ ]
+
if (!use_aura || (!is_linux && !use_ozone)) {
sources -= [
"input_method_auralinux.cc",
@@ -142,7 +146,6 @@ component("ime") {
if (is_chromeos) {
deps += [
"//chromeos",
- "//chromeos/ime:gencode",
"//ui/events:dom_keycode_converter",
]
if (!use_ozone) {
diff --git a/chromium/ui/base/ime/candidate_window.cc b/chromium/ui/base/ime/candidate_window.cc
index 60f8c4d7c33..30259f50b05 100644
--- a/chromium/ui/base/ime/candidate_window.cc
+++ b/chromium/ui/base/ime/candidate_window.cc
@@ -99,6 +99,8 @@ CandidateWindow::CandidateWindowProperty::~CandidateWindowProperty() {
CandidateWindow::Entry::Entry() {
}
+CandidateWindow::Entry::Entry(const Entry& other) = default;
+
CandidateWindow::Entry::~Entry() {
}
diff --git a/chromium/ui/base/ime/candidate_window.h b/chromium/ui/base/ime/candidate_window.h
index ad52c33e309..ca2cc2be17d 100644
--- a/chromium/ui/base/ime/candidate_window.h
+++ b/chromium/ui/base/ime/candidate_window.h
@@ -43,6 +43,7 @@ class UI_BASE_IME_EXPORT CandidateWindow {
// Represents a candidate entry.
struct UI_BASE_IME_EXPORT Entry {
Entry();
+ Entry(const Entry& other);
virtual ~Entry();
base::string16 value;
base::string16 label;
diff --git a/chromium/ui/base/ime/composition_text.cc b/chromium/ui/base/ime/composition_text.cc
index d3ae7f3a399..a2e583f6221 100644
--- a/chromium/ui/base/ime/composition_text.cc
+++ b/chromium/ui/base/ime/composition_text.cc
@@ -9,6 +9,8 @@ namespace ui {
CompositionText::CompositionText() {
}
+CompositionText::CompositionText(const CompositionText& other) = default;
+
CompositionText::~CompositionText() {
}
diff --git a/chromium/ui/base/ime/composition_text.h b/chromium/ui/base/ime/composition_text.h
index 9b729b502ba..ba56c627106 100644
--- a/chromium/ui/base/ime/composition_text.h
+++ b/chromium/ui/base/ime/composition_text.h
@@ -17,6 +17,7 @@ namespace ui {
// A struct represents the status of an ongoing composition text.
struct UI_BASE_IME_EXPORT CompositionText {
CompositionText();
+ CompositionText(const CompositionText& other);
~CompositionText();
bool operator==(const CompositionText& rhs) const {
diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc
index 478b489b4c8..ac9b97343ab 100644
--- a/chromium/ui/base/ime/dummy_text_input_client.cc
+++ b/chromium/ui/base/ime/dummy_text_input_client.cc
@@ -3,15 +3,16 @@
// found in the LICENSE file.
#include "ui/base/ime/dummy_text_input_client.h"
+#include "ui/events/event.h"
#include "ui/gfx/geometry/rect.h"
namespace ui {
DummyTextInputClient::DummyTextInputClient()
- : text_input_type_(TEXT_INPUT_TYPE_NONE) {}
+ : text_input_type_(TEXT_INPUT_TYPE_NONE), insert_char_count_(0) {}
DummyTextInputClient::DummyTextInputClient(TextInputType text_input_type)
- : text_input_type_(text_input_type) {}
+ : text_input_type_(text_input_type), insert_char_count_(0) {}
DummyTextInputClient::~DummyTextInputClient() {
}
@@ -29,7 +30,10 @@ void DummyTextInputClient::ClearCompositionText() {
void DummyTextInputClient::InsertText(const base::string16& text) {
}
-void DummyTextInputClient::InsertChar(const KeyEvent& event) {}
+void DummyTextInputClient::InsertChar(const KeyEvent& event) {
+ ++insert_char_count_;
+ last_insert_char_ = event.GetCharacter();
+}
TextInputType DummyTextInputClient::GetTextInputType() const {
return text_input_type_;
diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h
index 3c5178215db..a1779939e44 100644
--- a/chromium/ui/base/ime/dummy_text_input_client.h
+++ b/chromium/ui/base/ime/dummy_text_input_client.h
@@ -49,9 +49,16 @@ class DummyTextInputClient : public TextInputClient {
bool IsEditCommandEnabled(int command_id) override;
void SetEditCommandForNextKeyEvent(int command_id) override;
+ int insert_char_count() const { return insert_char_count_; }
+ base::char16 last_insert_char() const { return last_insert_char_; }
+
TextInputType text_input_type_;
DISALLOW_COPY_AND_ASSIGN(DummyTextInputClient);
+
+ private:
+ int insert_char_count_;
+ base::char16 last_insert_char_;
};
} // namespace ui
diff --git a/chromium/ui/base/ime/ime_engine_handler_interface.cc b/chromium/ui/base/ime/ime_engine_handler_interface.cc
deleted file mode 100644
index 695a547d5fc..00000000000
--- a/chromium/ui/base/ime/ime_engine_handler_interface.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-#include "ui/base/ime/ime_engine_handler_interface.h"
-
-namespace ui {
-
-IMEEngineHandlerInterface::KeyboardEvent::KeyboardEvent()
- : alt_key(false), ctrl_key(false), shift_key(false), caps_lock(false) {}
-
-IMEEngineHandlerInterface::KeyboardEvent::~KeyboardEvent() {}
-
-// ChromeOS only APIs.
-#if defined(OS_CHROMEOS)
-
-IMEEngineHandlerInterface::MenuItem::MenuItem() {}
-
-IMEEngineHandlerInterface::MenuItem::~MenuItem() {}
-
-IMEEngineHandlerInterface::Candidate::Candidate() {}
-
-IMEEngineHandlerInterface::Candidate::~Candidate() {}
-
-namespace {
-// The default entry number of a page in CandidateWindowProperty.
-const int kDefaultPageSize = 9;
-} // namespace
-
-// When the default values are changed, please modify
-// CandidateWindow::CandidateWindowProperty defined in chromeos/ime/ too.
-IMEEngineHandlerInterface::CandidateWindowProperty::CandidateWindowProperty()
- : page_size(kDefaultPageSize),
- is_cursor_visible(true),
- is_vertical(false),
- show_window_at_composition(false) {}
-
-IMEEngineHandlerInterface::CandidateWindowProperty::~CandidateWindowProperty() {
-}
-
-#endif
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/ime_engine_handler_interface.h b/chromium/ui/base/ime/ime_engine_handler_interface.h
index 6290841b3bd..3987085386a 100644
--- a/chromium/ui/base/ime/ime_engine_handler_interface.h
+++ b/chromium/ui/base/ime/ime_engine_handler_interface.h
@@ -54,33 +54,6 @@ class UI_BASE_IME_EXPORT IMEEngineHandlerInterface {
int flags;
};
- struct KeyboardEvent {
- KeyboardEvent();
- virtual ~KeyboardEvent();
-
- std::string type;
- std::string key;
- std::string code;
- int key_code; // only used by on-screen keyboards.
- std::string extension_id;
- bool alt_key;
- bool ctrl_key;
- bool shift_key;
- bool caps_lock;
- };
-
- enum SegmentStyle {
- SEGMENT_STYLE_UNDERLINE,
- SEGMENT_STYLE_DOUBLE_UNDERLINE,
- SEGMENT_STYLE_NO_UNDERLINE,
- };
-
- struct SegmentInfo {
- int start;
- int end;
- SegmentStyle style;
- };
-
virtual ~IMEEngineHandlerInterface() {}
// Called when the Chrome input field get the focus.
@@ -120,15 +93,6 @@ class UI_BASE_IME_EXPORT IMEEngineHandlerInterface {
// If not, InputMethodChromeOS won't feed it with key events.
virtual bool IsInterestedInKeyEvent() const = 0;
- // Set the current composition and associated properties.
- virtual bool SetComposition(int context_id,
- const char* text,
- int selection_start,
- int selection_end,
- int cursor,
- const std::vector<SegmentInfo>& segments,
- std::string* error) = 0;
-
// Clear the current composition.
virtual bool ClearComposition(int context_id, std::string* error) = 0;
@@ -138,10 +102,6 @@ class UI_BASE_IME_EXPORT IMEEngineHandlerInterface {
const char* text,
std::string* error) = 0;
- // Send the sequence of key events.
- virtual bool SendKeyEvents(int context_id,
- const std::vector<KeyboardEvent>& events) = 0;
-
// Returns true if this IME is active, false if not.
virtual bool IsActive() const = 0;
@@ -159,77 +119,8 @@ class UI_BASE_IME_EXPORT IMEEngineHandlerInterface {
int offset,
size_t number_of_chars,
std::string* error) = 0;
-
-// ChromeOS only APIs.
#if defined(OS_CHROMEOS)
- enum {
- MENU_ITEM_MODIFIED_LABEL = 0x0001,
- MENU_ITEM_MODIFIED_STYLE = 0x0002,
- MENU_ITEM_MODIFIED_VISIBLE = 0x0004,
- MENU_ITEM_MODIFIED_ENABLED = 0x0008,
- MENU_ITEM_MODIFIED_CHECKED = 0x0010,
- MENU_ITEM_MODIFIED_ICON = 0x0020,
- };
-
- enum MenuItemStyle {
- MENU_ITEM_STYLE_NONE,
- MENU_ITEM_STYLE_CHECK,
- MENU_ITEM_STYLE_RADIO,
- MENU_ITEM_STYLE_SEPARATOR,
- };
-
- enum CandidateWindowPosition {
- WINDOW_POS_CURSOR,
- WINDOW_POS_COMPOSITTION,
- };
-
- struct MenuItem {
- MenuItem();
- virtual ~MenuItem();
-
- std::string id;
- std::string label;
- MenuItemStyle style;
- bool visible;
- bool enabled;
- bool checked;
-
- unsigned int modified;
- std::vector<MenuItem> children;
- };
-
- struct UsageEntry {
- std::string title;
- std::string body;
- };
-
- struct Candidate {
- Candidate();
- virtual ~Candidate();
-
- std::string value;
- int id;
- std::string label;
- std::string annotation;
- UsageEntry usage;
- std::vector<Candidate> candidates;
- };
-
- struct CandidateWindowProperty {
- CandidateWindowProperty();
- virtual ~CandidateWindowProperty();
- int page_size;
- bool is_cursor_visible;
- bool is_vertical;
- bool show_window_at_composition;
-
- // Auxiliary text is typically displayed in the footer of the candidate
- // window.
- std::string auxiliary_text;
- bool is_auxiliary_text_visible;
- };
-
// Called when a property is activated or changed.
virtual void PropertyActivate(const std::string& property_name) = 0;
@@ -237,41 +128,21 @@ class UI_BASE_IME_EXPORT IMEEngineHandlerInterface {
// based candidate index in lookup table.
virtual void CandidateClicked(uint32_t index) = 0;
- // This function returns the current property of the candidate window.
- // The caller can use the returned value as the default property and
- // modify some of specified items.
- virtual const CandidateWindowProperty& GetCandidateWindowProperty() const = 0;
-
- // Change the property of the candidate window and repaint the candidate
- // window widget.
- virtual void SetCandidateWindowProperty(
- const CandidateWindowProperty& property) = 0;
-
// Show or hide the candidate window.
virtual bool SetCandidateWindowVisible(bool visible, std::string* error) = 0;
- // Set the list of entries displayed in the candidate window.
- virtual bool SetCandidates(int context_id,
- const std::vector<Candidate>& candidates,
- std::string* error) = 0;
-
// Set the position of the cursor in the candidate window.
virtual bool SetCursorPosition(int context_id,
int candidate_id,
std::string* error) = 0;
-
- // Set the list of items that appears in the language menu when this IME is
- // active.
- virtual bool SetMenuItems(const std::vector<MenuItem>& items) = 0;
-
- // Update the state of the menu items.
- virtual bool UpdateMenuItems(const std::vector<MenuItem>& items) = 0;
-
// Hides the input view window (from API call).
virtual void HideInputView() = 0;
-#endif // defined(OS_CHROMEOS)
+#elif defined(OS_LINUX) || defined(OS_WIN)
+ // Get the id of the IME extension.
+ virtual std::string GetExtensionId() const = 0;
+#endif // defined(OS_CHROMEOS)
protected:
IMEEngineHandlerInterface() {}
};
diff --git a/chromium/ui/base/ime/ime_engine_observer.h b/chromium/ui/base/ime/ime_engine_observer.h
deleted file mode 100644
index 7a2bf9d2682..00000000000
--- a/chromium/ui/base/ime/ime_engine_observer.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_IME_IME_ENGINE_OBSERVER_H_
-#define UI_BASE_IME_IME_ENGINE_OBSERVER_H_
-
-#include "build/build_config.h"
-#include "ui/base/ime/ime_engine_handler_interface.h"
-
-namespace ui {
-
-class IMEEngineObserver {
- public:
- virtual ~IMEEngineObserver() {}
-
- // Called when the IME becomes the active IME.
- virtual void OnActivate(const std::string& engine_id) = 0;
-
- // Called when a text field gains focus, and will be sending key events.
- virtual void OnFocus(
- const IMEEngineHandlerInterface::InputContext& context) = 0;
-
- // Called when a text field loses focus, and will no longer generate events.
- virtual void OnBlur(int context_id) = 0;
-
- // Called when the user pressed a key with a text field focused.
- virtual void OnKeyEvent(
- const std::string& engine_id,
- const IMEEngineHandlerInterface::KeyboardEvent& event,
- IMEEngineHandlerInterface::KeyEventDoneCallback& key_data) = 0;
-
- // Called when Chrome terminates on-going text input session.
- virtual void OnReset(const std::string& engine_id) = 0;
-
- // Called when the IME is no longer active.
- virtual void OnDeactivated(const std::string& engine_id) = 0;
-
- // Called when composition bounds are changed.
- virtual void OnCompositionBoundsChanged(
- const std::vector<gfx::Rect>& bounds) = 0;
-
- // Returns whether the observer is interested in key events.
- virtual bool IsInterestedInKeyEvent() const = 0;
-
- // Called when a surrounding text is changed.
- virtual void OnSurroundingTextChanged(const std::string& engine_id,
- const std::string& text,
- int cursor_pos,
- int anchor_pos,
- int offset_pos) = 0;
-
-// ChromeOS only APIs.
-#if defined(OS_CHROMEOS)
-
- enum MouseButtonEvent {
- MOUSE_BUTTON_LEFT,
- MOUSE_BUTTON_RIGHT,
- MOUSE_BUTTON_MIDDLE,
- };
-
- // Called when an InputContext's properties change while it is focused.
- virtual void OnInputContextUpdate(
- const IMEEngineHandlerInterface::InputContext& context) = 0;
-
-
-
- // Called when the user clicks on an item in the candidate list.
- virtual void OnCandidateClicked(const std::string& engine_id,
- int candidate_id,
- MouseButtonEvent button) = 0;
-
- // Called when a menu item for this IME is interacted with.
- virtual void OnMenuItemActivated(const std::string& engine_id,
- const std::string& menu_id) = 0;
-#endif
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_IME_ENGINE_OBSERVER_H_
diff --git a/chromium/ui/base/ime/ime_input_context_handler_interface.h b/chromium/ui/base/ime/ime_input_context_handler_interface.h
index 5a8f6aeae3a..b8fbb2b358b 100644
--- a/chromium/ui/base/ime/ime_input_context_handler_interface.h
+++ b/chromium/ui/base/ime/ime_input_context_handler_interface.h
@@ -10,6 +10,7 @@
#include <string>
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/events/event.h"
namespace ui {
@@ -25,6 +26,9 @@ class UI_BASE_IME_EXPORT IMEInputContextHandlerInterface {
// Called when the engine request deleting surrounding string.
virtual void DeleteSurroundingText(int32_t offset, uint32_t length) = 0;
+
+ // Called when the engine sends a key event.
+ virtual void SendKeyEvent(KeyEvent* event) = 0;
};
} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_auralinux.cc b/chromium/ui/base/ime/input_method_auralinux.cc
index 0b65ec31dc5..97ce8ea79b5 100644
--- a/chromium/ui/base/ime/input_method_auralinux.cc
+++ b/chromium/ui/base/ime/input_method_auralinux.cc
@@ -6,10 +6,22 @@
#include "base/auto_reset.h"
#include "base/environment.h"
+#include "ui/base/ime/ime_bridge.h"
+#include "ui/base/ime/ime_engine_handler_interface.h"
#include "ui/base/ime/linux/linux_input_method_context_factory.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/event.h"
+namespace {
+
+ui::IMEEngineHandlerInterface* GetEngine() {
+ if (ui::IMEBridge::Get())
+ return ui::IMEBridge::Get()->GetCurrentEngineHandler();
+ return nullptr;
+}
+
+} // namespace
+
namespace ui {
InputMethodAuraLinux::InputMethodAuraLinux(
@@ -17,7 +29,8 @@ InputMethodAuraLinux::InputMethodAuraLinux(
: text_input_type_(TEXT_INPUT_TYPE_NONE),
is_sync_mode_(false),
composition_changed_(false),
- suppress_next_result_(false) {
+ suppress_next_result_(false),
+ weak_ptr_factory_(this) {
SetDelegate(delegate);
context_ =
LinuxInputMethodContextFactory::instance()->CreateInputMethodContext(
@@ -52,6 +65,20 @@ void InputMethodAuraLinux::DispatchKeyEvent(ui::KeyEvent* event) {
return;
}
+ if (!event->HasNativeEvent() && sending_key_event_) {
+ // Faked key events that are sent from input.ime.sendKeyEvents.
+ ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ if (details.dispatcher_destroyed || details.target_destroyed ||
+ event->stopped_propagation()) {
+ return;
+ }
+ if ((event->is_char() || event->GetDomKey().IsCharacter()) &&
+ event->type() == ui::ET_KEY_PRESSED) {
+ GetTextInputClient()->InsertChar(*event);
+ }
+ return;
+ }
+
suppress_next_result_ = false;
composition_changed_ = false;
result_text_.clear();
@@ -67,6 +94,52 @@ void InputMethodAuraLinux::DispatchKeyEvent(ui::KeyEvent* event) {
}
}
+ // If there's an active IME extension is listening to the key event, and the
+ // current text input client is not password input client, the key event
+ // should be dispatched to the extension engine in the two conditions:
+ // 1) |filtered| == false: the ET_KEY_PRESSED event of non-character key,
+ // or the ET_KEY_RELEASED event of all key.
+ // 2) |filtered| == true && NeedInsertChar(): the ET_KEY_PRESSED event of
+ // character key.
+ if (text_input_type_ != TEXT_INPUT_TYPE_PASSWORD &&
+ GetEngine() && GetEngine()->IsInterestedInKeyEvent() &&
+ (!filtered || NeedInsertChar())) {
+ ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = base::Bind(
+ &InputMethodAuraLinux::ProcessKeyEventByEngineDone,
+ weak_ptr_factory_.GetWeakPtr(), base::Owned(new ui::KeyEvent(*event)),
+ filtered, composition_changed_,
+ base::Owned(new ui::CompositionText(composition_)),
+ base::Owned(new base::string16(result_text_)));
+ GetEngine()->ProcessKeyEvent(*event, callback);
+ } else {
+ ProcessKeyEventDone(event, filtered, false);
+ }
+}
+
+void InputMethodAuraLinux::ProcessKeyEventByEngineDone(
+ ui::KeyEvent* event,
+ bool filtered,
+ bool composition_changed,
+ ui::CompositionText* composition,
+ base::string16* result_text,
+ bool is_handled) {
+ composition_changed_ = composition_changed;
+ composition_.CopyFrom(*composition);
+ result_text_ = *result_text;
+ ProcessKeyEventDone(event, filtered, is_handled);
+}
+
+void InputMethodAuraLinux::ProcessKeyEventDone(ui::KeyEvent* event,
+ bool filtered,
+ bool is_handled) {
+ DCHECK(event);
+ if (is_handled)
+ return;
+
+ // If the IME extension has not handled the key event, passes the keyevent
+ // back to the previous processing flow. Preconditions for this situation:
+ // 1) |filtered| == false
+ // 2) |filtered| == true && NeedInsertChar()
ui::EventDispatchDetails details;
if (event->type() == ui::ET_KEY_PRESSED && filtered) {
if (NeedInsertChar())
@@ -177,6 +250,21 @@ void InputMethodAuraLinux::UpdateContextFocusState() {
context_simple_->Focus();
else
context_simple_->Blur();
+
+ if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests.
+ return;
+
+ ui::IMEEngineHandlerInterface::InputContext context(
+ GetTextInputType(), GetTextInputMode(), GetTextInputFlags());
+ ui::IMEBridge::Get()->SetCurrentInputContext(context);
+
+ ui::IMEEngineHandlerInterface* engine = GetEngine();
+ if (engine) {
+ if (old_text_input_type != TEXT_INPUT_TYPE_NONE)
+ engine->FocusOut();
+ if (text_input_type_ != TEXT_INPUT_TYPE_NONE)
+ engine->FocusIn(context);
+ }
}
void InputMethodAuraLinux::OnTextInputTypeChanged(
@@ -191,11 +279,19 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) {
return;
NotifyTextInputCaretBoundsChanged(client);
context_->SetCursorLocation(GetTextInputClient()->GetCaretBounds());
+
+ if (!IsTextInputTypeNone() && text_input_type_ != TEXT_INPUT_TYPE_PASSWORD &&
+ GetEngine())
+ GetEngine()->SetCompositionBounds(GetCompositionBounds(client));
}
void InputMethodAuraLinux::CancelComposition(const TextInputClient* client) {
if (!IsTextInputClientFocused(client))
return;
+
+ if (GetEngine())
+ GetEngine()->Reset();
+
ResetContext();
}
@@ -305,17 +401,6 @@ void InputMethodAuraLinux::OnPreeditEnd() {
// Overridden from InputMethodBase.
-void InputMethodAuraLinux::OnFocus() {
- InputMethodBase::OnFocus();
- UpdateContextFocusState();
-}
-
-void InputMethodAuraLinux::OnBlur() {
- ConfirmCompositionText();
- InputMethodBase::OnBlur();
- UpdateContextFocusState();
-}
-
void InputMethodAuraLinux::OnWillChangeFocusedClient(
TextInputClient* focused_before,
TextInputClient* focused) {
@@ -358,9 +443,13 @@ ui::EventDispatchDetails InputMethodAuraLinux::SendFakeProcessKeyEvent(
void InputMethodAuraLinux::ConfirmCompositionText() {
TextInputClient* client = GetTextInputClient();
- if (client && client->HasCompositionText())
+ if (client && client->HasCompositionText()) {
client->ConfirmCompositionText();
+ if (GetEngine())
+ GetEngine()->Reset();
+ }
+
ResetContext();
}
diff --git a/chromium/ui/base/ime/input_method_auralinux.h b/chromium/ui/base/ime/input_method_auralinux.h
index 29b76fdb44f..732d4340189 100644
--- a/chromium/ui/base/ime/input_method_auralinux.h
+++ b/chromium/ui/base/ime/input_method_auralinux.h
@@ -35,8 +35,6 @@ class UI_BASE_IME_EXPORT InputMethodAuraLinux
void OnInputLocaleChanged() override;
std::string GetInputLocale() override;
bool IsCandidatePopupOpen() const override;
- void OnFocus() override;
- void OnBlur() override;
// Overriden from ui::LinuxInputMethodContextDelegate
void OnCommit(const base::string16& text) override;
@@ -59,6 +57,22 @@ class UI_BASE_IME_EXPORT InputMethodAuraLinux
void UpdateContextFocusState();
void ResetContext();
+ // Processes the key event after the event is processed by the system IME or
+ // the extension.
+ void ProcessKeyEventDone(ui::KeyEvent* event, bool filtered, bool is_handled);
+
+ // Callback function for IMEEngineHandlerInterface::ProcessKeyEvent().
+ // It recovers the context when the event is being passed to the extension and
+ // call ProcessKeyEventDone() for the following processing. This is necessary
+ // as this method is async. The environment may be changed by other generated
+ // key events by the time the callback is run.
+ void ProcessKeyEventByEngineDone(ui::KeyEvent* event,
+ bool filtered,
+ bool composition_changed,
+ ui::CompositionText* composition,
+ base::string16* result_text,
+ bool is_handled);
+
scoped_ptr<LinuxInputMethodContext> context_;
scoped_ptr<LinuxInputMethodContext> context_simple_;
@@ -81,6 +95,9 @@ class UI_BASE_IME_EXPORT InputMethodAuraLinux
// event will be discarded.
bool suppress_next_result_;
+ // Used for making callbacks.
+ base::WeakPtrFactory<InputMethodAuraLinux> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(InputMethodAuraLinux);
};
diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc
index df0cb118e53..282b6c4f9ad 100644
--- a/chromium/ui/base/ime/input_method_base.cc
+++ b/chromium/ui/base/ime/input_method_base.cc
@@ -7,6 +7,8 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ime/text_input_client.h"
@@ -15,23 +17,33 @@
namespace ui {
InputMethodBase::InputMethodBase()
- : delegate_(NULL),
- text_input_client_(NULL) {
-}
+ : sending_key_event_(false),
+ delegate_(nullptr),
+ text_input_client_(nullptr) {}
InputMethodBase::~InputMethodBase() {
FOR_EACH_OBSERVER(InputMethodObserver,
observer_list_,
OnInputMethodDestroyed(this));
+ if (ui::IMEBridge::Get() &&
+ ui::IMEBridge::Get()->GetInputContextHandler() == this)
+ ui::IMEBridge::Get()->SetInputContextHandler(nullptr);
}
void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) {
delegate_ = delegate;
}
-void InputMethodBase::OnFocus() {}
+void InputMethodBase::OnFocus() {
+ if (ui::IMEBridge::Get())
+ ui::IMEBridge::Get()->SetInputContextHandler(this);
+}
-void InputMethodBase::OnBlur() {}
+void InputMethodBase::OnBlur() {
+ if (ui::IMEBridge::Get() &&
+ ui::IMEBridge::Get()->GetInputContextHandler() == this)
+ ui::IMEBridge::Get()->SetInputContextHandler(nullptr);
+}
void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) {
SetFocusedTextInputClientInternal(client);
@@ -40,7 +52,7 @@ void InputMethodBase::SetFocusedTextInputClient(TextInputClient* client) {
void InputMethodBase::DetachTextInputClient(TextInputClient* client) {
if (text_input_client_ != client)
return;
- SetFocusedTextInputClientInternal(NULL);
+ SetFocusedTextInputClientInternal(nullptr);
}
TextInputClient* InputMethodBase::GetTextInputClient() const {
@@ -126,9 +138,69 @@ void InputMethodBase::SetFocusedTextInputClientInternal(
if (old == client)
return;
OnWillChangeFocusedClient(old, client);
- text_input_client_ = client; // NULL allowed.
+ text_input_client_ = client; // nullptr allowed.
OnDidChangeFocusedClient(old, client);
NotifyTextInputStateChanged(text_input_client_);
}
+std::vector<gfx::Rect> InputMethodBase::GetCompositionBounds(
+ const TextInputClient* client) {
+ std::vector<gfx::Rect> bounds;
+ if (client->HasCompositionText()) {
+ uint32_t i = 0;
+ gfx::Rect rect;
+ while (client->GetCompositionCharacterBounds(i++, &rect))
+ bounds.push_back(rect);
+ } else {
+ // For case of no composition at present, use caret bounds which is required
+ // by the IME extension for certain features (e.g. physical keyboard
+ // auto-correct).
+ bounds.push_back(client->GetCaretBounds());
+ }
+ return bounds;
+}
+
+bool InputMethodBase::SendFakeProcessKeyEvent(bool pressed) const {
+ KeyEvent evt(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED,
+ pressed ? VKEY_PROCESSKEY : VKEY_UNKNOWN, EF_IME_FABRICATED_KEY);
+ ignore_result(DispatchKeyEventPostIME(&evt));
+ return evt.stopped_propagation();
+}
+
+void InputMethodBase::CommitText(const std::string& text) {
+ if (text.empty() || !GetTextInputClient() || IsTextInputTypeNone())
+ return;
+
+ const base::string16 utf16_text = base::UTF8ToUTF16(text);
+ if (utf16_text.empty())
+ return;
+
+ if (!SendFakeProcessKeyEvent(true))
+ GetTextInputClient()->InsertText(utf16_text);
+ SendFakeProcessKeyEvent(false);
+}
+
+void InputMethodBase::UpdateCompositionText(const CompositionText& composition_,
+ uint32_t cursor_pos,
+ bool visible) {
+ if (IsTextInputTypeNone())
+ return;
+
+ if (!SendFakeProcessKeyEvent(true)) {
+ if (visible && !composition_.text.empty())
+ GetTextInputClient()->SetCompositionText(composition_);
+ else
+ GetTextInputClient()->ClearCompositionText();
+ }
+ SendFakeProcessKeyEvent(false);
+}
+
+void InputMethodBase::DeleteSurroundingText(int32_t offset, uint32_t length) {}
+
+void InputMethodBase::SendKeyEvent(KeyEvent* event) {
+ sending_key_event_ = true;
+ DispatchKeyEvent(event);
+ sending_key_event_ = false;
+}
+
} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h
index e33461138f7..3a44e37f0ec 100644
--- a/chromium/ui/base/ime/input_method_base.h
+++ b/chromium/ui/base/ime/input_method_base.h
@@ -5,10 +5,13 @@
#ifndef UI_BASE_IME_INPUT_METHOD_BASE_H_
#define UI_BASE_IME_INPUT_METHOD_BASE_H_
+#include <vector>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "ui/base/ime/ime_input_context_handler_interface.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/ui_base_ime_export.h"
#include "ui/events/event_dispatcher.h"
@@ -27,7 +30,8 @@ class TextInputClient;
// implementations.
class UI_BASE_IME_EXPORT InputMethodBase
: NON_EXPORTED_BASE(public InputMethod),
- public base::SupportsWeakPtr<InputMethodBase> {
+ public base::SupportsWeakPtr<InputMethodBase>,
+ public IMEInputContextHandlerInterface {
public:
InputMethodBase();
~InputMethodBase() override;
@@ -59,6 +63,18 @@ class UI_BASE_IME_EXPORT InputMethodBase
virtual void OnDidChangeFocusedClient(TextInputClient* focused_before,
TextInputClient* focused) {}
+ // IMEInputContextHandlerInterface:
+ void CommitText(const std::string& text) override;
+ void UpdateCompositionText(const CompositionText& text,
+ uint32_t cursor_pos,
+ bool visible) override;
+ void DeleteSurroundingText(int32_t offset, uint32_t length) override;
+ void SendKeyEvent(KeyEvent* event) override;
+
+ // Sends a fake key event for IME composing without physical key events.
+ // Returns true if the faked key event is stopped propagation.
+ bool SendFakeProcessKeyEvent(bool pressed) const;
+
// Returns true if |client| is currently focused.
bool IsTextInputClientFocused(const TextInputClient* client);
@@ -84,6 +100,13 @@ class UI_BASE_IME_EXPORT InputMethodBase
// |client| which is the text input client with focus.
void NotifyTextInputCaretBoundsChanged(const TextInputClient* client);
+ // Gets the bounds of the composition text or cursor in |client|.
+ std::vector<gfx::Rect> GetCompositionBounds(const TextInputClient* client);
+
+ // Indicates whether the IME extension is currently sending a fake key event.
+ // This is used in SendKeyEvent.
+ bool sending_key_event_;
+
private:
void SetFocusedTextInputClientInternal(TextInputClient* client);
diff --git a/chromium/ui/base/ime/input_method_chromeos.cc b/chromium/ui/base/ime/input_method_chromeos.cc
index 59077b451f0..924c9cf9683 100644
--- a/chromium/ui/base/ime/input_method_chromeos.cc
+++ b/chromium/ui/base/ime/input_method_chromeos.cc
@@ -57,17 +57,6 @@ InputMethodChromeOS::~InputMethodChromeOS() {
ui::IMEBridge::Get()->SetInputContextHandler(NULL);
}
-void InputMethodChromeOS::OnFocus() {
- InputMethodBase::OnFocus();
- OnTextInputTypeChanged(GetTextInputClient());
-}
-
-void InputMethodChromeOS::OnBlur() {
- ConfirmCompositionText();
- InputMethodBase::OnBlur();
- OnTextInputTypeChanged(GetTextInputClient());
-}
-
bool InputMethodChromeOS::OnUntranslatedIMEMessage(
const base::NativeEvent& event,
NativeEventResult* result) {
@@ -180,33 +169,24 @@ void InputMethodChromeOS::OnCaretBoundsChanged(const TextInputClient* client) {
// The current text input type should not be NONE if |context_| is focused.
DCHECK(client == GetTextInputClient());
DCHECK(!IsTextInputTypeNone());
- const gfx::Rect caret_rect = client->GetCaretBounds();
-
- gfx::Rect composition_head;
- std::vector<gfx::Rect> rects;
- if (client->HasCompositionText()) {
- uint32_t i = 0;
- gfx::Rect rect;
- while (client->GetCompositionCharacterBounds(i++, &rect))
- rects.push_back(rect);
- }
-
- // Pepper don't support composition bounds, so fallback to caret bounds to
- // avoid bad user experience (the IME window moved to upper left corner).
- // For case of no composition at present, also use caret bounds which is
- // required by the IME extension for certain features (e.g. physical keyboard
- // autocorrect).
- if (rects.empty())
- rects.push_back(caret_rect);
- composition_head = rects[0];
if (GetEngine())
- GetEngine()->SetCompositionBounds(rects);
+ GetEngine()->SetCompositionBounds(GetCompositionBounds(client));
chromeos::IMECandidateWindowHandlerInterface* candidate_window =
ui::IMEBridge::Get()->GetCandidateWindowHandler();
if (!candidate_window)
return;
+
+ const gfx::Rect caret_rect = client->GetCaretBounds();
+
+ // Pepper doesn't support composition bounds, so fall back to caret bounds to
+ // avoid a bad user experience (the IME window moved to upper left corner).
+ gfx::Rect composition_head;
+ if (client->HasCompositionText())
+ client->GetCompositionCharacterBounds(0, &composition_head);
+ else
+ composition_head = caret_rect;
candidate_window->SetCursorBounds(caret_rect, composition_head);
gfx::Range text_range;
@@ -381,7 +361,10 @@ void InputMethodChromeOS::ProcessFilteredKeyPressEvent(ui::KeyEvent* event) {
}
ui::KeyEvent fabricated_event(ET_KEY_PRESSED,
VKEY_PROCESSKEY,
- event->flags());
+ event->code(),
+ event->flags(),
+ event->GetDomKey(),
+ event->time_stamp());
ignore_result(DispatchKeyEventPostIME(&fabricated_event));
if (fabricated_event.stopped_propagation())
event->StopPropagation();
@@ -459,14 +442,6 @@ bool InputMethodChromeOS::HasInputMethodResult() const {
return result_text_.length() || composition_changed_;
}
-bool InputMethodChromeOS::SendFakeProcessKeyEvent(bool pressed) const {
- KeyEvent evt(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED,
- pressed ? VKEY_PROCESSKEY : VKEY_UNKNOWN,
- EF_IME_FABRICATED_KEY);
- ignore_result(DispatchKeyEventPostIME(&evt));
- return evt.stopped_propagation();
-}
-
void InputMethodChromeOS::CommitText(const std::string& text) {
if (text.empty())
return;
diff --git a/chromium/ui/base/ime/input_method_chromeos.h b/chromium/ui/base/ime/input_method_chromeos.h
index 28da9b7c9bb..343e85dec84 100644
--- a/chromium/ui/base/ime/input_method_chromeos.h
+++ b/chromium/ui/base/ime/input_method_chromeos.h
@@ -22,16 +22,12 @@
namespace ui {
// A ui::InputMethod implementation based on IBus.
-class UI_BASE_IME_EXPORT InputMethodChromeOS
- : public InputMethodBase,
- public ui::IMEInputContextHandlerInterface {
+class UI_BASE_IME_EXPORT InputMethodChromeOS : public InputMethodBase {
public:
explicit InputMethodChromeOS(internal::InputMethodDelegate* delegate);
~InputMethodChromeOS() override;
// Overridden from InputMethod:
- void OnFocus() override;
- void OnBlur() override;
bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
NativeEventResult* result) override;
void DispatchKeyEvent(ui::KeyEvent* event) override;
@@ -91,10 +87,6 @@ class UI_BASE_IME_EXPORT InputMethodChromeOS
// Checks if there is pending input method result.
bool HasInputMethodResult() const;
- // Sends a fake key event for IME composing without physical key events.
- // Returns true if the faked key event is stopped propagation.
- bool SendFakeProcessKeyEvent(bool pressed) const;
-
// Passes keyevent and executes character composition if necessary. Returns
// true if character composer comsumes key event.
bool ExecuteCharacterComposer(const ui::KeyEvent& event);
diff --git a/chromium/ui/base/ime/input_method_chromeos_unittest.cc b/chromium/ui/base/ime/input_method_chromeos_unittest.cc
index d60d99ec038..8ee42945df7 100644
--- a/chromium/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/chromium/ui/base/ime/input_method_chromeos_unittest.cc
@@ -345,12 +345,10 @@ class InputMethodChromeOSTest : public internal::InputMethodDelegate,
TEST_F(InputMethodChromeOSTest, GetInputLocale) {
// ui::InputMethodChromeOS does not support the API.
- ime_->OnFocus();
EXPECT_EQ("", ime_->GetInputLocale());
}
TEST_F(InputMethodChromeOSTest, GetInputTextType) {
- ime_->OnFocus();
EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
input_type_ = TEXT_INPUT_TYPE_PASSWORD;
ime_->OnTextInputTypeChanged(this);
@@ -361,7 +359,6 @@ TEST_F(InputMethodChromeOSTest, GetInputTextType) {
}
TEST_F(InputMethodChromeOSTest, CanComposeInline) {
- ime_->OnFocus();
EXPECT_TRUE(ime_->CanComposeInline());
can_compose_inline_ = false;
ime_->OnTextInputTypeChanged(this);
@@ -369,14 +366,12 @@ TEST_F(InputMethodChromeOSTest, CanComposeInline) {
}
TEST_F(InputMethodChromeOSTest, GetTextInputClient) {
- ime_->OnFocus();
EXPECT_EQ(this, ime_->GetTextInputClient());
ime_->SetFocusedTextInputClient(NULL);
EXPECT_EQ(NULL, ime_->GetTextInputClient());
}
TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedClient) {
- ime_->OnFocus();
EXPECT_EQ(TEXT_INPUT_TYPE_NONE, ime_->GetTextInputType());
ime_->SetFocusedTextInputClient(NULL);
input_type_ = TEXT_INPUT_TYPE_PASSWORD;
@@ -393,7 +388,6 @@ TEST_F(InputMethodChromeOSTest, GetInputTextType_WithoutFocusedClient) {
// Confirm that IBusClient::FocusIn is called on "connected" if input_type_ is
// TEXT.
TEST_F(InputMethodChromeOSTest, FocusIn_Text) {
- ime_->OnFocus();
// A context shouldn't be created since the daemon is not running.
EXPECT_EQ(0U, on_input_method_changed_call_count_);
// Click a text input form.
@@ -413,7 +407,6 @@ TEST_F(InputMethodChromeOSTest, FocusIn_Text) {
// Confirm that InputMethodEngine::FocusIn is called on "connected" even if
// input_type_ is PASSWORD.
TEST_F(InputMethodChromeOSTest, FocusIn_Password) {
- ime_->OnFocus();
EXPECT_EQ(0U, on_input_method_changed_call_count_);
input_type_ = TEXT_INPUT_TYPE_PASSWORD;
ime_->OnTextInputTypeChanged(this);
@@ -425,7 +418,7 @@ TEST_F(InputMethodChromeOSTest, FocusIn_Password) {
// Confirm that IBusClient::FocusOut is called as expected.
TEST_F(InputMethodChromeOSTest, FocusOut_None) {
input_type_ = TEXT_INPUT_TYPE_TEXT;
- ime_->OnFocus();
+ ime_->OnTextInputTypeChanged(this);
EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
input_type_ = TEXT_INPUT_TYPE_NONE;
@@ -437,7 +430,7 @@ TEST_F(InputMethodChromeOSTest, FocusOut_None) {
// Confirm that IBusClient::FocusOut is called as expected.
TEST_F(InputMethodChromeOSTest, FocusOut_Password) {
input_type_ = TEXT_INPUT_TYPE_TEXT;
- ime_->OnFocus();
+ ime_->OnTextInputTypeChanged(this);
EXPECT_EQ(1, mock_ime_engine_handler_->focus_in_call_count());
EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
input_type_ = TEXT_INPUT_TYPE_PASSWORD;
@@ -448,7 +441,6 @@ TEST_F(InputMethodChromeOSTest, FocusOut_Password) {
// FocusIn/FocusOut scenario test
TEST_F(InputMethodChromeOSTest, Focus_Scenario) {
- ime_->OnFocus();
// Confirm that both FocusIn and FocusOut are NOT called.
EXPECT_EQ(0, mock_ime_engine_handler_->focus_in_call_count());
EXPECT_EQ(0, mock_ime_engine_handler_->focus_out_call_count());
@@ -503,7 +495,7 @@ TEST_F(InputMethodChromeOSTest, Focus_Scenario) {
// Test if the new |caret_bounds_| is correctly sent to ibus-daemon.
TEST_F(InputMethodChromeOSTest, OnCaretBoundsChanged) {
input_type_ = TEXT_INPUT_TYPE_TEXT;
- ime_->OnFocus();
+ ime_->OnTextInputTypeChanged(this);
EXPECT_EQ(
1,
mock_ime_candidate_window_handler_->set_cursor_bounds_call_count());
@@ -721,7 +713,6 @@ TEST_F(InputMethodChromeOSTest,
}
TEST_F(InputMethodChromeOSTest, SurroundingText_NoSelectionTest) {
- ime_->OnFocus();
// Click a text input form.
input_type_ = TEXT_INPUT_TYPE_TEXT;
ime_->OnTextInputTypeChanged(this);
@@ -749,7 +740,6 @@ TEST_F(InputMethodChromeOSTest, SurroundingText_NoSelectionTest) {
}
TEST_F(InputMethodChromeOSTest, SurroundingText_SelectionTest) {
- ime_->OnFocus();
// Click a text input form.
input_type_ = TEXT_INPUT_TYPE_TEXT;
ime_->OnTextInputTypeChanged(this);
@@ -776,7 +766,6 @@ TEST_F(InputMethodChromeOSTest, SurroundingText_SelectionTest) {
}
TEST_F(InputMethodChromeOSTest, SurroundingText_PartialText) {
- ime_->OnFocus();
// Click a text input form.
input_type_ = TEXT_INPUT_TYPE_TEXT;
ime_->OnTextInputTypeChanged(this);
@@ -802,7 +791,6 @@ TEST_F(InputMethodChromeOSTest, SurroundingText_PartialText) {
}
TEST_F(InputMethodChromeOSTest, SurroundingText_BecomeEmptyText) {
- ime_->OnFocus();
// Click a text input form.
input_type_ = TEXT_INPUT_TYPE_TEXT;
ime_->OnTextInputTypeChanged(this);
@@ -831,11 +819,6 @@ class InputMethodChromeOSKeyEventTest : public InputMethodChromeOSTest {
InputMethodChromeOSKeyEventTest() {}
~InputMethodChromeOSKeyEventTest() override {}
- void SetUp() override {
- InputMethodChromeOSTest::SetUp();
- ime_->OnFocus();
- }
-
DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSKeyEventTest);
};
@@ -968,4 +951,27 @@ TEST_F(InputMethodChromeOSKeyEventTest, StopPropagationTest) {
EXPECT_EQ(L'A', inserted_char_);
}
+TEST_F(InputMethodChromeOSKeyEventTest, DeadKeyPressTest) {
+ // Preparation.
+ input_type_ = TEXT_INPUT_TYPE_TEXT;
+ ime_->OnTextInputTypeChanged(this);
+
+ ui::KeyEvent eventA(ET_KEY_PRESSED,
+ VKEY_OEM_4, // '['
+ DomCode::BRACKET_LEFT,
+ 0,
+ DomKey::DeadKeyFromCombiningCharacter('^'),
+ EventTimeForNow());
+ ime_->ProcessKeyEventPostIME(&eventA, true);
+
+ const ui::KeyEvent& key_event = dispatched_key_event_;
+
+ EXPECT_EQ(ET_KEY_PRESSED, key_event.type());
+ EXPECT_EQ(VKEY_PROCESSKEY, key_event.key_code());
+ EXPECT_EQ(eventA.code(), key_event.code());
+ EXPECT_EQ(eventA.flags(), key_event.flags());
+ EXPECT_EQ(eventA.GetDomKey(), key_event.GetDomKey());
+ EXPECT_EQ(eventA.time_stamp(), key_event.time_stamp());
+}
+
} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_factory.cc b/chromium/ui/base/ime/input_method_factory.cc
index dd9d31a6665..1fda6daaad7 100644
--- a/chromium/ui/base/ime/input_method_factory.cc
+++ b/chromium/ui/base/ime/input_method_factory.cc
@@ -11,7 +11,6 @@
#include "ui/base/ime/input_method_chromeos.h"
#elif defined(OS_WIN)
#include "ui/base/ime/input_method_win.h"
-#include "ui/base/ime/remote_input_method_win.h"
#elif defined(OS_MACOSX)
#include "ui/base/ime/input_method_mac.h"
#elif defined(USE_AURA) && defined(OS_LINUX) && defined(USE_X11) && \
@@ -53,8 +52,6 @@ scoped_ptr<InputMethod> CreateInputMethod(
#if defined(OS_CHROMEOS)
return make_scoped_ptr(new InputMethodChromeOS(delegate));
#elif defined(OS_WIN)
- if (IsRemoteInputMethodWinRequired(widget))
- return CreateRemoteInputMethodWin(delegate);
return make_scoped_ptr(new InputMethodWin(delegate, widget));
#elif defined(OS_MACOSX)
return make_scoped_ptr(new InputMethodMac(delegate));
diff --git a/chromium/ui/base/ime/input_method_win.cc b/chromium/ui/base/ime/input_method_win.cc
index 6604c6d31bb..df9ac66f233 100644
--- a/chromium/ui/base/ime/input_method_win.cc
+++ b/chromium/ui/base/ime/input_method_win.cc
@@ -6,9 +6,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <cwctype>
#include "base/auto_reset.h"
#include "base/command_line.h"
+#include "ui/base/ime/ime_bridge.h"
+#include "ui/base/ime/ime_engine_handler_interface.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/ui_base_switches.h"
@@ -19,6 +22,16 @@
#include "ui/gfx/win/dpi.h"
#include "ui/gfx/win/hwnd_util.h"
+namespace {
+
+ui::IMEEngineHandlerInterface* GetEngine() {
+ if (ui::IMEBridge::Get())
+ return ui::IMEBridge::Get()->GetCurrentEngineHandler();
+ return nullptr;
+}
+
+} // namespace
+
namespace ui {
namespace {
@@ -35,25 +48,12 @@ InputMethodWin::InputMethodWin(internal::InputMethodDelegate* delegate,
accept_carriage_return_(false),
enabled_(false),
is_candidate_popup_open_(false),
- composing_window_handle_(NULL) {
+ composing_window_handle_(NULL),
+ weak_ptr_factory_(this) {
SetDelegate(delegate);
}
-void InputMethodWin::OnFocus() {
- InputMethodBase::OnFocus();
- if (GetTextInputClient())
- UpdateIMEState();
-}
-
-void InputMethodWin::OnBlur() {
- ConfirmCompositionText();
- // Gets the focused text input client before calling parent's OnBlur() because
- // it will cause GetTextInputClient() returns NULL.
- ui::TextInputClient* client = GetTextInputClient();
- InputMethodBase::OnBlur();
- if (client)
- UpdateIMEState();
-}
+InputMethodWin::~InputMethodWin() {}
bool InputMethodWin::OnUntranslatedIMEMessage(
const base::NativeEvent& event,
@@ -167,19 +167,45 @@ void InputMethodWin::DispatchKeyEvent(ui::KeyEvent* event) {
}
// If only 1 WM_CHAR per the key event, set it as the character of it.
- if (char_msgs.size() == 1)
+ if (char_msgs.size() == 1 &&
+ !std::iswcntrl(static_cast<wint_t>(char_msgs[0].wParam)))
event->set_character(static_cast<base::char16>(char_msgs[0].wParam));
+ // Dispatches the key events to the Chrome IME extension which is listening to
+ // key events on the following two situations:
+ // 1) |char_msgs| is empty when the event is non-character key.
+ // 2) |char_msgs|.size() == 1 when the event is character key and the WM_CHAR
+ // messages have been combined in the event processing flow.
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMergeKeyCharEvents) &&
+ char_msgs.size() <= 1 && GetEngine() &&
+ GetEngine()->IsInterestedInKeyEvent()) {
+ ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = base::Bind(
+ &InputMethodWin::ProcessKeyEventDone, weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(new ui::KeyEvent(*event)),
+ base::Owned(new std::vector<MSG>(char_msgs)));
+ GetEngine()->ProcessKeyEvent(*event, callback);
+ } else {
+ ProcessKeyEventDone(event, &char_msgs, false);
+ }
+}
+
+void InputMethodWin::ProcessKeyEventDone(ui::KeyEvent* event,
+ const std::vector<MSG>* char_msgs,
+ bool is_handled) {
+ DCHECK(event);
+ if (is_handled)
+ return;
+
ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
if (details.dispatcher_destroyed || details.target_destroyed ||
event->stopped_propagation()) {
return;
}
- for (size_t i = 0; i < char_msgs.size(); ++i) {
- MSG msg = char_msgs[i];
+ BOOL handled;
+ for (const auto& msg : (*char_msgs))
OnChar(msg.hwnd, msg.message, msg.wParam, msg.lParam, msg, &handled);
- }
}
void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
@@ -190,10 +216,19 @@ void InputMethodWin::OnTextInputTypeChanged(const TextInputClient* client) {
}
void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
- if (!enabled_ || !IsTextInputClientFocused(client) ||
- !IsWindowFocused(client)) {
+ if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
return;
+ TextInputType text_input_type = GetTextInputType();
+ if (client == GetTextInputClient() &&
+ text_input_type != TEXT_INPUT_TYPE_NONE &&
+ text_input_type != TEXT_INPUT_TYPE_PASSWORD && GetEngine()) {
+ // |enabled_| == false could be faked, and the engine should rely on the
+ // real type from GetTextInputType().
+ GetEngine()->SetCompositionBounds(GetCompositionBounds(client));
}
+ if (!enabled_)
+ return;
+
// The current text input type should not be NONE if |client| is focused.
DCHECK(!IsTextInputTypeNone());
// Tentatively assume that the returned value is DIP (Density Independent
@@ -214,8 +249,18 @@ void InputMethodWin::OnCaretBoundsChanged(const TextInputClient* client) {
}
void InputMethodWin::CancelComposition(const TextInputClient* client) {
- if (enabled_ && IsTextInputClientFocused(client))
- imm32_manager_.CancelIME(toplevel_window_handle_);
+ if (IsTextInputClientFocused(client)) {
+ // |enabled_| == false could be faked, and the engine should rely on the
+ // real type get from GetTextInputType().
+ TextInputType text_input_type = GetTextInputType();
+ if (text_input_type != TEXT_INPUT_TYPE_NONE &&
+ text_input_type != TEXT_INPUT_TYPE_PASSWORD && GetEngine()) {
+ GetEngine()->Reset();
+ }
+
+ if (enabled_)
+ imm32_manager_.CancelIME(toplevel_window_handle_);
+ }
}
void InputMethodWin::OnInputLocaleChanged() {
@@ -591,27 +636,30 @@ bool InputMethodWin::IsWindowFocused(const TextInputClient* client) const {
}
void InputMethodWin::DispatchFabricatedKeyEvent(ui::KeyEvent* event) {
- if (event->is_char()) {
- if (GetTextInputClient()) {
- ui::KeyEvent ch_event(*event);
- ch_event.set_character(static_cast<base::char16>(event->key_code()));
- GetTextInputClient()->InsertChar(ch_event);
- return;
- }
+ // The key event if from calling input.ime.sendKeyEvent or test.
+ ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ if (details.dispatcher_destroyed || details.target_destroyed ||
+ event->stopped_propagation()) {
+ return;
}
- ignore_result(DispatchKeyEventPostIME(event));
+
+ if ((event->is_char() || event->GetDomKey().IsCharacter()) &&
+ event->type() == ui::ET_KEY_PRESSED && GetTextInputClient())
+ GetTextInputClient()->InsertChar(*event);
}
void InputMethodWin::ConfirmCompositionText() {
if (composing_window_handle_)
imm32_manager_.CleanupComposition(composing_window_handle_);
- if (!IsTextInputTypeNone()) {
- // Though above line should confirm the client's composition text by sending
- // a result text to us, in case the input method and the client are in
- // inconsistent states, we check the client's composition state again.
- if (GetTextInputClient()->HasCompositionText())
- GetTextInputClient()->ConfirmCompositionText();
+ // Though above line should confirm the client's composition text by sending a
+ // result text to us, in case the input method and the client are in
+ // inconsistent states, we check the client's composition state again.
+ if (!IsTextInputTypeNone() && GetTextInputClient()->HasCompositionText()) {
+ GetTextInputClient()->ConfirmCompositionText();
+
+ if (GetEngine())
+ GetEngine()->Reset();
}
}
@@ -619,7 +667,10 @@ void InputMethodWin::UpdateIMEState() {
// Use switch here in case we are going to add more text input types.
// We disable input method in password field.
const HWND window_handle = toplevel_window_handle_;
- const TextInputType text_input_type = GetTextInputType();
+ const TextInputType text_input_type =
+ (GetEngine() && GetEngine()->IsInterestedInKeyEvent())
+ ? TEXT_INPUT_TYPE_NONE
+ : GetTextInputType();
const TextInputMode text_input_mode = GetTextInputMode();
switch (text_input_type) {
case ui::TEXT_INPUT_TYPE_NONE:
@@ -636,6 +687,23 @@ void InputMethodWin::UpdateIMEState() {
imm32_manager_.SetTextInputMode(window_handle, text_input_mode);
tsf_inputscope::SetInputScopeForTsfUnawareWindow(
window_handle, text_input_type, text_input_mode);
+
+ if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests.
+ return;
+
+ const TextInputType old_text_input_type =
+ ui::IMEBridge::Get()->GetCurrentInputContext().type;
+ ui::IMEEngineHandlerInterface::InputContext context(
+ GetTextInputType(), GetTextInputMode(), GetTextInputFlags());
+ ui::IMEBridge::Get()->SetCurrentInputContext(context);
+
+ ui::IMEEngineHandlerInterface* engine = GetEngine();
+ if (engine) {
+ if (old_text_input_type != ui::TEXT_INPUT_TYPE_NONE)
+ engine->FocusOut();
+ if (GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE)
+ engine->FocusIn(context);
+ }
}
} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_win.h b/chromium/ui/base/ime/input_method_win.h
index ce411491e23..742085445e3 100644
--- a/chromium/ui/base/ime/input_method_win.h
+++ b/chromium/ui/base/ime/input_method_win.h
@@ -21,10 +21,9 @@ class UI_BASE_IME_EXPORT InputMethodWin : public InputMethodBase {
public:
InputMethodWin(internal::InputMethodDelegate* delegate,
HWND toplevel_window_handle);
+ ~InputMethodWin() override;
// Overridden from InputMethod:
- void OnFocus() override;
- void OnBlur() override;
bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
NativeEventResult* result) override;
void DispatchKeyEvent(ui::KeyEvent* event) override;
@@ -101,6 +100,11 @@ class UI_BASE_IME_EXPORT InputMethodWin : public InputMethodBase {
// Enables or disables the IME according to the current text input type.
void UpdateIMEState();
+ // Callback function for IMEEngineHandlerInterface::ProcessKeyEvent.
+ void ProcessKeyEventDone(ui::KeyEvent* event,
+ const std::vector<MSG>* char_msgs,
+ bool is_handled);
+
// Windows IMM32 wrapper.
// (See "ui/base/ime/win/ime_input.h" for its details.)
ui::IMM32Manager imm32_manager_;
@@ -130,6 +134,9 @@ class UI_BASE_IME_EXPORT InputMethodWin : public InputMethodBase {
// composition.
HWND composing_window_handle_;
+ // Used for making callbacks.
+ base::WeakPtrFactory<InputMethodWin> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(InputMethodWin);
};
diff --git a/chromium/ui/base/ime/remote_input_method_delegate_win.h b/chromium/ui/base/ime/remote_input_method_delegate_win.h
deleted file mode 100644
index a172c7b5100..00000000000
--- a/chromium/ui/base/ime/remote_input_method_delegate_win.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_IME_REMOTE_INPUT_METHOD_DELEGATE_WIN_H_
-#define UI_BASE_IME_REMOTE_INPUT_METHOD_DELEGATE_WIN_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "ui/base/ime/ui_base_ime_export.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace ui {
-namespace internal {
-
-// An interface implemented by the object to forward events that should be
-// handled by the IME which is running in the remote metro_driver process.
-class UI_BASE_IME_EXPORT RemoteInputMethodDelegateWin {
- public:
- virtual ~RemoteInputMethodDelegateWin() {}
-
- // Notifies that composition should be canceled (if any).
- virtual void CancelComposition() = 0;
-
- // Notifies that properties of the focused TextInputClient is changed.
- // Note that an empty |input_scopes| represents that TextInputType is
- // TEXT_INPUT_TYPE_NONE.
- // Caveats: |input_scopes| is defined as std::vector<int32_t> rather than
- // std::vector<InputScope> because the wire format of IPC message
- // MetroViewerHostMsg_ImeTextInputClientUpdated uses std::vector<int32_t> to
- // avoid dependency on <InputScope.h> header.
- virtual void OnTextInputClientUpdated(
- const std::vector<int32_t>& input_scopes,
- const std::vector<gfx::Rect>& composition_character_bounds) = 0;
-};
-
-} // namespace internal
-} // namespace ui
-
-#endif // UI_BASE_IME_REMOTE_INPUT_METHOD_DELEGATE_WIN_H_
diff --git a/chromium/ui/base/ime/remote_input_method_win.cc b/chromium/ui/base/ime/remote_input_method_win.cc
deleted file mode 100644
index 27d242a384b..00000000000
--- a/chromium/ui/base/ime/remote_input_method_win.cc
+++ /dev/null
@@ -1,385 +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/base/ime/remote_input_method_win.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_observer.h"
-#include "ui/base/ime/remote_input_method_delegate_win.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/base/ime/win/tsf_input_scope.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace ui {
-namespace {
-
-const LANGID kFallbackLangID =
- MAKELANGID(LANG_NEUTRAL, SUBLANG_UI_CUSTOM_DEFAULT);
-
-InputMethod* g_public_interface_ = NULL;
-RemoteInputMethodPrivateWin* g_private_interface_ = NULL;
-
-void RegisterInstance(InputMethod* public_interface,
- RemoteInputMethodPrivateWin* private_interface) {
- CHECK(g_public_interface_ == NULL)
- << "Only one instance is supported at the same time";
- CHECK(g_private_interface_ == NULL)
- << "Only one instance is supported at the same time";
- g_public_interface_ = public_interface;
- g_private_interface_ = private_interface;
-}
-
-RemoteInputMethodPrivateWin* GetPrivate(InputMethod* public_interface) {
- if (g_public_interface_ != public_interface)
- return NULL;
- return g_private_interface_;
-}
-
-void UnregisterInstance(InputMethod* public_interface) {
- RemoteInputMethodPrivateWin* private_interface = GetPrivate(public_interface);
- if (g_public_interface_ == public_interface &&
- g_private_interface_ == private_interface) {
- g_public_interface_ = NULL;
- g_private_interface_ = NULL;
- }
-}
-
-std::string GetLocaleString(LCID Locale_id, LCTYPE locale_type) {
- wchar_t buffer[16] = {};
-
- //|chars_written| includes NUL terminator.
- const int chars_written =
- GetLocaleInfo(Locale_id, locale_type, buffer, arraysize(buffer));
- if (chars_written <= 1 || static_cast<int>(arraysize(buffer)) < chars_written)
- return std::string();
- std::string result;
- base::WideToUTF8(buffer, chars_written - 1, &result);
- return result;
-}
-
-std::vector<int32_t> GetInputScopesAsInt(TextInputType text_input_type,
- TextInputMode text_input_mode) {
- std::vector<int32_t> result;
- // An empty vector represents |text_input_type| is TEXT_INPUT_TYPE_NONE.
- if (text_input_type == TEXT_INPUT_TYPE_NONE)
- return result;
-
- const std::vector<InputScope>& input_scopes =
- tsf_inputscope::GetInputScopes(text_input_type, text_input_mode);
- result.reserve(input_scopes.size());
- for (size_t i = 0; i < input_scopes.size(); ++i)
- result.push_back(static_cast<int32_t>(input_scopes[i]));
- return result;
-}
-
-std::vector<gfx::Rect> GetCompositionCharacterBounds(
- const TextInputClient* client) {
- if (!client)
- return std::vector<gfx::Rect>();
-
- std::vector<gfx::Rect> bounds;
- if (client->HasCompositionText()) {
- gfx::Range range;
- if (client->GetCompositionTextRange(&range)) {
- for (uint32_t i = 0; i < range.length(); ++i) {
- gfx::Rect rect;
- if (!client->GetCompositionCharacterBounds(i, &rect))
- break;
- bounds.push_back(rect);
- }
- }
- }
-
- // Use the caret bounds as a fallback if no composition character bounds is
- // available. One typical use case is PPAPI Flash, which does not support
- // GetCompositionCharacterBounds at all. crbug.com/133472
- if (bounds.empty())
- bounds.push_back(client->GetCaretBounds());
- return bounds;
-}
-
-class RemoteInputMethodWin : public InputMethod,
- public RemoteInputMethodPrivateWin {
- public:
- explicit RemoteInputMethodWin(internal::InputMethodDelegate* delegate)
- : delegate_(delegate),
- remote_delegate_(NULL),
- text_input_client_(NULL),
- is_candidate_popup_open_(false),
- is_ime_(false),
- langid_(kFallbackLangID) {
- RegisterInstance(this, this);
- }
-
- ~RemoteInputMethodWin() override {
- FOR_EACH_OBSERVER(InputMethodObserver,
- observer_list_,
- OnInputMethodDestroyed(this));
- UnregisterInstance(this);
- }
-
- private:
- // Overridden from InputMethod:
- void SetDelegate(internal::InputMethodDelegate* delegate) override {
- delegate_ = delegate;
- }
-
- void OnFocus() override {}
-
- void OnBlur() override {}
-
- bool OnUntranslatedIMEMessage(const base::NativeEvent& event,
- NativeEventResult* result) override {
- return false;
- }
-
- void SetFocusedTextInputClient(TextInputClient* client) override {
- std::vector<int32_t> prev_input_scopes;
- std::swap(input_scopes_, prev_input_scopes);
- std::vector<gfx::Rect> prev_bounds;
- std::swap(composition_character_bounds_, prev_bounds);
- if (client) {
- input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
- client->GetTextInputMode());
- composition_character_bounds_ = GetCompositionCharacterBounds(client);
- }
-
- const bool text_input_client_changed = text_input_client_ != client;
- text_input_client_ = client;
- if (text_input_client_changed) {
- FOR_EACH_OBSERVER(InputMethodObserver,
- observer_list_,
- OnTextInputStateChanged(client));
- }
-
- if (!remote_delegate_ || (prev_input_scopes == input_scopes_ &&
- prev_bounds == composition_character_bounds_))
- return;
- remote_delegate_->OnTextInputClientUpdated(input_scopes_,
- composition_character_bounds_);
- }
-
- void DetachTextInputClient(TextInputClient* client) override {
- if (text_input_client_ != client)
- return;
- SetFocusedTextInputClient(NULL);
- }
-
- TextInputClient* GetTextInputClient() const override {
- return text_input_client_;
- }
-
- void DispatchKeyEvent(ui::KeyEvent* event) override {
- if (event->HasNativeEvent()) {
- const base::NativeEvent& native_key_event = event->native_event();
- if (native_key_event.message == WM_CHAR && text_input_client_) {
- text_input_client_->InsertChar(*event);
- event->StopPropagation();
- }
- return;
- }
-
- if (event->is_char()) {
- if (text_input_client_) {
- text_input_client_->InsertChar(*event);
- }
- event->StopPropagation();
- return;
- }
- if (delegate_)
- ignore_result(delegate_->DispatchKeyEventPostIME(event));
- }
-
- void OnTextInputTypeChanged(const TextInputClient* client) override {
- if (!text_input_client_ || text_input_client_ != client)
- return;
- std::vector<int32_t> prev_input_scopes;
- std::swap(input_scopes_, prev_input_scopes);
- input_scopes_ = GetInputScopesAsInt(client->GetTextInputType(),
- client->GetTextInputMode());
- if (input_scopes_ != prev_input_scopes && remote_delegate_) {
- remote_delegate_->OnTextInputClientUpdated(
- input_scopes_, composition_character_bounds_);
- }
- }
-
- void OnCaretBoundsChanged(const TextInputClient* client) override {
- if (!text_input_client_ || text_input_client_ != client)
- return;
- std::vector<gfx::Rect> prev_rects;
- std::swap(composition_character_bounds_, prev_rects);
- composition_character_bounds_ = GetCompositionCharacterBounds(client);
- if (composition_character_bounds_ != prev_rects && remote_delegate_) {
- remote_delegate_->OnTextInputClientUpdated(
- input_scopes_, composition_character_bounds_);
- }
- }
-
- void CancelComposition(const TextInputClient* client) override {
- if (CanSendRemoteNotification(client))
- remote_delegate_->CancelComposition();
- }
-
- void OnInputLocaleChanged() override {}
-
- std::string GetInputLocale() override {
- const LCID locale_id = MAKELCID(langid_, SORT_DEFAULT);
- std::string language =
- GetLocaleString(locale_id, LOCALE_SISO639LANGNAME);
- if (SUBLANGID(langid_) == SUBLANG_NEUTRAL || language.empty())
- return language;
- const std::string& region =
- GetLocaleString(locale_id, LOCALE_SISO3166CTRYNAME);
- if (region.empty())
- return language;
- return language.append(1, '-').append(region);
- }
-
- TextInputType GetTextInputType() const override {
- return text_input_client_ ? text_input_client_->GetTextInputType()
- : TEXT_INPUT_TYPE_NONE;
- }
-
- TextInputMode GetTextInputMode() const override {
- return text_input_client_ ? text_input_client_->GetTextInputMode()
- : TEXT_INPUT_MODE_DEFAULT;
- }
-
- int GetTextInputFlags() const override {
- return text_input_client_ ? text_input_client_->GetTextInputFlags()
- : 0;
- }
-
- bool CanComposeInline() const override {
- return text_input_client_ ? text_input_client_->CanComposeInline() : true;
- }
-
- bool IsCandidatePopupOpen() const override {
- return is_candidate_popup_open_;
- }
-
- void ShowImeIfNeeded() override {}
-
- void AddObserver(InputMethodObserver* observer) override {
- observer_list_.AddObserver(observer);
- }
-
- void RemoveObserver(InputMethodObserver* observer) override {
- observer_list_.RemoveObserver(observer);
- }
-
- // Overridden from RemoteInputMethodPrivateWin:
- void SetRemoteDelegate(
- internal::RemoteInputMethodDelegateWin* delegate) override {
- remote_delegate_ = delegate;
-
- // Sync initial state.
- if (remote_delegate_) {
- remote_delegate_->OnTextInputClientUpdated(
- input_scopes_, composition_character_bounds_);
- }
- }
-
- void OnCandidatePopupChanged(bool visible) override {
- is_candidate_popup_open_ = visible;
- }
-
- void OnInputSourceChanged(LANGID langid, bool /*is_ime*/) override {
- // Note: Currently |is_ime| is not utilized yet.
- const bool changed = (langid_ != langid);
- langid_ = langid;
- if (changed && GetTextInputClient())
- GetTextInputClient()->OnInputMethodChanged();
- }
-
- void OnCompositionChanged(const CompositionText& composition_text) override {
- if (!text_input_client_)
- return;
- text_input_client_->SetCompositionText(composition_text);
- }
-
- void OnTextCommitted(const base::string16& text) override {
- if (!text_input_client_)
- return;
- if (text_input_client_->GetTextInputType() == TEXT_INPUT_TYPE_NONE) {
- // According to the comment in text_input_client.h,
- // TextInputClient::InsertText should never be called when the
- // text input type is TEXT_INPUT_TYPE_NONE.
-
- for (size_t i = 0; i < text.size(); ++i) {
- ui::KeyEvent char_event(text[i], static_cast<ui::KeyboardCode>(text[i]),
- ui::EF_NONE);
- text_input_client_->InsertChar(char_event);
- }
- return;
- }
- text_input_client_->InsertText(text);
- }
-
- bool CanSendRemoteNotification(
- const TextInputClient* text_input_client) const {
- return text_input_client_ &&
- text_input_client_ == text_input_client &&
- remote_delegate_;
- }
-
- base::ObserverList<InputMethodObserver> observer_list_;
-
- internal::InputMethodDelegate* delegate_;
- internal::RemoteInputMethodDelegateWin* remote_delegate_;
-
- TextInputClient* text_input_client_;
- std::vector<int32_t> input_scopes_;
- std::vector<gfx::Rect> composition_character_bounds_;
- bool is_candidate_popup_open_;
- bool is_ime_;
- LANGID langid_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoteInputMethodWin);
-};
-
-} // namespace
-
-bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget) {
- // If the remote input method is already registered then don't do it again.
- if (ui::g_public_interface_ && ui::g_private_interface_)
- return false;
-
- DWORD process_id = 0;
- if (GetWindowThreadProcessId(widget, &process_id) == 0)
- return false;
- base::win::ScopedHandle process_handle(::OpenProcess(
- PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id));
- if (!process_handle.IsValid())
- return false;
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kViewerConnect);
-}
-
-RemoteInputMethodPrivateWin::RemoteInputMethodPrivateWin() {}
-
-scoped_ptr<InputMethod> CreateRemoteInputMethodWin(
- internal::InputMethodDelegate* delegate) {
- return make_scoped_ptr(new RemoteInputMethodWin(delegate));
-}
-
-// static
-RemoteInputMethodPrivateWin* RemoteInputMethodPrivateWin::Get(
- InputMethod* input_method) {
- return GetPrivate(input_method);
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/ime/remote_input_method_win.h b/chromium/ui/base/ime/remote_input_method_win.h
deleted file mode 100644
index a1725b32dd3..00000000000
--- a/chromium/ui/base/ime/remote_input_method_win.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_IME_REMOTE_INPUT_METHOD_WIN_H_
-#define UI_BASE_IME_REMOTE_INPUT_METHOD_WIN_H_
-
-#include <Windows.h>
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string16.h"
-#include "ui/base/ime/ui_base_ime_export.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace ui {
-namespace internal {
-class InputMethodDelegate;
-class RemoteInputMethodDelegateWin;
-} // namespace internal
-
-class InputMethod;
-struct CompositionText;
-
-// RemoteInputMethodWin is a special implementation of ui::InputMethod that
-// works as a proxy of an IME handler running in the metro_driver process.
-// RemoteInputMethodWin works as follows.
-// - Any action to RemoteInputMethodWin should be delegated to the
-// metro_driver process via RemoteInputMethodDelegateWin.
-// - Data retrieval from RemoteInputMethodPrivateWin is implemented with
-// data cache. Whenever the IME state in the metro_driver process is changed,
-// RemoteWindowTreeHostWin, which receives IPCs from metro_driver process,
-// will call RemoteInputMethodPrivateWin::OnCandidatePopupChanged and/or
-// RemoteInputMethodPrivateWin::OnInputSourceChanged accordingly so that
-// the state cache should be updated.
-// - Some IPC messages that represent actions to TextInputClient should be
-// delegated to RemoteInputMethodPrivateWin so that RemoteInputMethodWin can
-// work as a real proxy.
-
-// Returns true if |widget| requires RemoteInputMethodWin.
-bool IsRemoteInputMethodWinRequired(gfx::AcceleratedWidget widget);
-
-// Returns the public interface of RemoteInputMethodWin.
-// Caveats: Currently only one instance of RemoteInputMethodWin is able to run
-// at the same time.
-UI_BASE_IME_EXPORT scoped_ptr<InputMethod> CreateRemoteInputMethodWin(
- internal::InputMethodDelegate* delegate);
-
-// Private interface of RemoteInputMethodWin.
-class UI_BASE_IME_EXPORT RemoteInputMethodPrivateWin {
- public:
- RemoteInputMethodPrivateWin();
-
- // Returns the private interface of RemoteInputMethodWin when and only when
- // |input_method| is instanciated via CreateRemoteInputMethodWin. Caller does
- // not take the ownership of the returned object.
- // As you might notice, this is yet another reinplementation of dynamic_cast
- // or IUnknown::QueryInterface.
- static RemoteInputMethodPrivateWin* Get(InputMethod* input_method);
-
- // Installs RemoteInputMethodDelegateWin delegate. Set NULL to |delegate| to
- // unregister.
- virtual void SetRemoteDelegate(
- internal::RemoteInputMethodDelegateWin* delegate) = 0;
-
- // Updates internal cache so that subsequent calls of
- // RemoteInputMethodWin::IsCandidatePopupOpen can return the correct value
- // based on remote IME activities in the metro_driver process.
- virtual void OnCandidatePopupChanged(bool visible) = 0;
-
- // Updates internal cache so that subsequent calls of
- // RemoteInputMethodWin::GetInputLocale can return the correct values based on
- // remote IME activities in the metro_driver process.
- virtual void OnInputSourceChanged(LANGID langid, bool is_ime) = 0;
-
- // Handles composition-update events occurred in the metro_driver process.
- // Caveats: This method is designed to be used only with
- // metro_driver::TextService. In other words, there is no garantee that this
- // method works a wrapper to call ui::TextInputClient::SetCompositionText.
- virtual void OnCompositionChanged(
- const CompositionText& composition_text) = 0;
-
- // Handles text-commit events occurred in the metro_driver process.
- // Caveats: This method is designed to be used only with
- // metro_driver::TextService. In other words, there is no garantee that this
- // method works a wrapper to call ui::TextInputClient::InsertText. In fact,
- // this method may call ui::TextInputClient::InsertChar when the text input
- // type of the focused text input client is TEXT_INPUT_TYPE_NONE.
- virtual void OnTextCommitted(const base::string16& text) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RemoteInputMethodPrivateWin);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_IME_REMOTE_INPUT_METHOD_WIN_H_
diff --git a/chromium/ui/base/ime/remote_input_method_win_unittest.cc b/chromium/ui/base/ime/remote_input_method_win_unittest.cc
deleted file mode 100644
index 2d15919d938..00000000000
--- a/chromium/ui/base/ime/remote_input_method_win_unittest.cc
+++ /dev/null
@@ -1,831 +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/base/ime/remote_input_method_win.h"
-
-#include <InputScope.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/scoped_observer.h"
-#include "base/strings/string16.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/ime/composition_text.h"
-#include "ui/base/ime/dummy_text_input_client.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_delegate.h"
-#include "ui/base/ime/input_method_observer.h"
-#include "ui/base/ime/remote_input_method_delegate_win.h"
-#include "ui/events/event.h"
-
-namespace ui {
-namespace {
-
-class MockTextInputClient : public DummyTextInputClient {
- public:
- MockTextInputClient()
- : text_input_type_(TEXT_INPUT_TYPE_NONE),
- text_input_mode_(TEXT_INPUT_MODE_DEFAULT),
- call_count_set_composition_text_(0),
- call_count_insert_char_(0),
- call_count_insert_text_(0),
- emulate_pepper_flash_(false) {
- }
-
- size_t call_count_set_composition_text() const {
- return call_count_set_composition_text_;
- }
- const base::string16& inserted_text() const {
- return inserted_text_;
- }
- size_t call_count_insert_char() const {
- return call_count_insert_char_;
- }
- size_t call_count_insert_text() const {
- return call_count_insert_text_;
- }
- void Reset() {
- text_input_type_ = TEXT_INPUT_TYPE_NONE;
- text_input_mode_ = TEXT_INPUT_MODE_DEFAULT;
- call_count_set_composition_text_ = 0;
- inserted_text_.clear();
- call_count_insert_char_ = 0;
- call_count_insert_text_ = 0;
- caret_bounds_ = gfx::Rect();
- composition_character_bounds_.clear();
- emulate_pepper_flash_ = false;
- }
- void set_text_input_type(ui::TextInputType type) {
- text_input_type_ = type;
- }
- void set_text_input_mode(ui::TextInputMode mode) {
- text_input_mode_ = mode;
- }
- void set_caret_bounds(const gfx::Rect& caret_bounds) {
- caret_bounds_ = caret_bounds;
- }
- void set_composition_character_bounds(
- const std::vector<gfx::Rect>& composition_character_bounds) {
- composition_character_bounds_ = composition_character_bounds;
- }
- void set_emulate_pepper_flash(bool enabled) {
- emulate_pepper_flash_ = enabled;
- }
-
- private:
- // Overriden from DummyTextInputClient.
- void SetCompositionText(const ui::CompositionText& composition) override {
- ++call_count_set_composition_text_;
- }
- void InsertChar(const ui::KeyEvent& event) override {
- inserted_text_.append(1, event.GetCharacter());
- ++call_count_insert_char_;
- }
- void InsertText(const base::string16& text) override {
- inserted_text_.append(text);
- ++call_count_insert_text_;
- }
- ui::TextInputType GetTextInputType() const override {
- return text_input_type_;
- }
- ui::TextInputMode GetTextInputMode() const override {
- return text_input_mode_;
- }
- gfx::Rect GetCaretBounds() const override { return caret_bounds_; }
- bool GetCompositionCharacterBounds(uint32_t index,
- gfx::Rect* rect) const override {
- // Emulate the situation of crbug.com/328237.
- if (emulate_pepper_flash_)
- return false;
- if (!rect || composition_character_bounds_.size() <= index)
- return false;
- *rect = composition_character_bounds_[index];
- return true;
- }
- bool HasCompositionText() const override {
- return !composition_character_bounds_.empty();
- }
- bool GetCompositionTextRange(gfx::Range* range) const override {
- if (composition_character_bounds_.empty())
- return false;
- *range = gfx::Range(0, composition_character_bounds_.size());
- return true;
- }
-
- ui::TextInputType text_input_type_;
- ui::TextInputMode text_input_mode_;
- gfx::Rect caret_bounds_;
- std::vector<gfx::Rect> composition_character_bounds_;
- base::string16 inserted_text_;
- size_t call_count_set_composition_text_;
- size_t call_count_insert_char_;
- size_t call_count_insert_text_;
- bool emulate_pepper_flash_;
- DISALLOW_COPY_AND_ASSIGN(MockTextInputClient);
-};
-
-class MockInputMethodDelegate : public internal::InputMethodDelegate {
- public:
- MockInputMethodDelegate() {}
-
- const std::vector<ui::KeyboardCode>& fabricated_key_events() const {
- return fabricated_key_events_;
- }
- void Reset() {
- fabricated_key_events_.clear();
- }
-
- private:
- ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* event) override {
- EXPECT_FALSE(event->HasNativeEvent());
- fabricated_key_events_.push_back(event->key_code());
- event->SetHandled();
- return ui::EventDispatchDetails();
- }
-
- std::vector<ui::KeyboardCode> fabricated_key_events_;
- DISALLOW_COPY_AND_ASSIGN(MockInputMethodDelegate);
-};
-
-class MockRemoteInputMethodDelegateWin
- : public internal::RemoteInputMethodDelegateWin {
- public:
- MockRemoteInputMethodDelegateWin()
- : cancel_composition_called_(false),
- text_input_client_updated_called_(false) {
- }
-
- bool cancel_composition_called() const {
- return cancel_composition_called_;
- }
- bool text_input_client_updated_called() const {
- return text_input_client_updated_called_;
- }
- const std::vector<int32_t>& input_scopes() const { return input_scopes_; }
- const std::vector<gfx::Rect>& composition_character_bounds() const {
- return composition_character_bounds_;
- }
- void Reset() {
- cancel_composition_called_ = false;
- text_input_client_updated_called_ = false;
- input_scopes_.clear();
- composition_character_bounds_.clear();
- }
-
- private:
- void CancelComposition() override { cancel_composition_called_ = true; }
-
- void OnTextInputClientUpdated(
- const std::vector<int32_t>& input_scopes,
- const std::vector<gfx::Rect>& composition_character_bounds) override {
- text_input_client_updated_called_ = true;
- input_scopes_ = input_scopes;
- composition_character_bounds_ = composition_character_bounds;
- }
-
- bool cancel_composition_called_;
- bool text_input_client_updated_called_;
- std::vector<int32_t> input_scopes_;
- std::vector<gfx::Rect> composition_character_bounds_;
- DISALLOW_COPY_AND_ASSIGN(MockRemoteInputMethodDelegateWin);
-};
-
-class MockInputMethodObserver : public InputMethodObserver {
- public:
- MockInputMethodObserver()
- : on_text_input_state_changed_(0),
- on_input_method_destroyed_changed_(0) {
- }
- ~MockInputMethodObserver() override {}
- void Reset() {
- on_text_input_state_changed_ = 0;
- on_input_method_destroyed_changed_ = 0;
- }
- size_t on_text_input_state_changed() const {
- return on_text_input_state_changed_;
- }
- size_t on_input_method_destroyed_changed() const {
- return on_input_method_destroyed_changed_;
- }
-
- private:
- // Overriden from InputMethodObserver.
- void OnTextInputTypeChanged(const TextInputClient* client) override {}
- void OnFocus() override {}
- void OnBlur() override {}
- void OnCaretBoundsChanged(const TextInputClient* client) override {}
- void OnTextInputStateChanged(const TextInputClient* client) override {
- ++on_text_input_state_changed_;
- }
- void OnInputMethodDestroyed(const InputMethod* client) override {
- ++on_input_method_destroyed_changed_;
- }
- void OnShowImeIfNeeded() override {}
-
- size_t on_text_input_state_changed_;
- size_t on_input_method_destroyed_changed_;
- DISALLOW_COPY_AND_ASSIGN(MockInputMethodObserver);
-};
-
-typedef ScopedObserver<InputMethod, InputMethodObserver>
- InputMethodScopedObserver;
-
-TEST(RemoteInputMethodWinTest, RemoteInputMethodPrivateWin) {
- InputMethod* other_ptr = static_cast<InputMethod*>(NULL) + 1;
-
- // Use typed NULL to make EXPECT_NE happy until nullptr becomes available.
- RemoteInputMethodPrivateWin* kNull =
- static_cast<RemoteInputMethodPrivateWin*>(NULL);
- EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(other_ptr));
-
- MockInputMethodDelegate delegate_;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- EXPECT_NE(kNull, RemoteInputMethodPrivateWin::Get(input_method.get()));
-
- InputMethod* dangling_ptr = input_method.get();
- input_method.reset(NULL);
- EXPECT_EQ(kNull, RemoteInputMethodPrivateWin::Get(dangling_ptr));
-}
-
-TEST(RemoteInputMethodWinTest, OnInputSourceChanged) {
- MockInputMethodDelegate delegate_;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
-
- private_ptr->OnInputSourceChanged(
- MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), true);
- EXPECT_EQ("ja-JP", input_method->GetInputLocale());
-
- private_ptr->OnInputSourceChanged(
- MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_QATAR), true);
- EXPECT_EQ("ar-QA", input_method->GetInputLocale());
-}
-
-TEST(RemoteInputMethodWinTest, OnCandidatePopupChanged) {
- MockInputMethodDelegate delegate_;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
-
- // Initial value
- EXPECT_FALSE(input_method->IsCandidatePopupOpen());
-
- // RemoteInputMethodWin::OnCandidatePopupChanged can be called even when the
- // focused text input client is NULL.
- ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
- private_ptr->OnCandidatePopupChanged(false);
- private_ptr->OnCandidatePopupChanged(true);
-
- MockTextInputClient mock_text_input_client;
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- mock_text_input_client.Reset();
-
- private_ptr->OnCandidatePopupChanged(true);
- EXPECT_TRUE(input_method->IsCandidatePopupOpen());
-
- private_ptr->OnCandidatePopupChanged(false);
- EXPECT_FALSE(input_method->IsCandidatePopupOpen());
-}
-
-TEST(RemoteInputMethodWinTest, CancelComposition) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- // This must not cause a crash.
- input_method->CancelComposition(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- input_method->CancelComposition(&mock_text_input_client);
- EXPECT_FALSE(mock_remote_delegate.cancel_composition_called());
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
- input_method->CancelComposition(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.cancel_composition_called());
-}
-
-TEST(RemoteInputMethodWinTest, SetFocusedTextInputClient) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
- mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // Initial state must be synced.
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- ASSERT_EQ(1u, mock_remote_delegate.composition_character_bounds().size());
- EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
- mock_remote_delegate.composition_character_bounds()[0]);
- ASSERT_EQ(1u, mock_remote_delegate.input_scopes().size());
- EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
-
- // State must be cleared by SetFocusedTextInputClient(NULL).
- mock_remote_delegate.Reset();
- input_method->SetFocusedTextInputClient(NULL);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
- EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
-}
-
-TEST(RemoteInputMethodWinTest, DetachTextInputClient) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
- mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // Initial state must be synced.
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- ASSERT_EQ(1u, mock_remote_delegate.composition_character_bounds().size());
- EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
- mock_remote_delegate.composition_character_bounds()[0]);
- ASSERT_EQ(1u, mock_remote_delegate.input_scopes().size());
- EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
-
- // State must be cleared by DetachTextInputClient
- mock_remote_delegate.Reset();
- input_method->DetachTextInputClient(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- EXPECT_TRUE(mock_remote_delegate.composition_character_bounds().empty());
- EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
-}
-
-TEST(RemoteInputMethodWinTest, OnCaretBoundsChanged) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- // This must not cause a crash.
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
-
- mock_text_input_client.set_caret_bounds(gfx::Rect(10, 0, 10, 20));
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // Initial state must be synced.
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- ASSERT_EQ(1u, mock_remote_delegate.composition_character_bounds().size());
- EXPECT_EQ(gfx::Rect(10, 0, 10, 20),
- mock_remote_delegate.composition_character_bounds()[0]);
-
- // Redundant OnCaretBoundsChanged must be ignored.
- mock_remote_delegate.Reset();
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
- EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
-
- // Check OnCaretBoundsChanged is handled. (w/o composition)
- mock_remote_delegate.Reset();
- mock_text_input_client.Reset();
- mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- ASSERT_EQ(1u, mock_remote_delegate.composition_character_bounds().size());
- EXPECT_EQ(gfx::Rect(10, 20, 30, 40),
- mock_remote_delegate.composition_character_bounds()[0]);
-
- // Check OnCaretBoundsChanged is handled. (w/ composition)
- {
- mock_remote_delegate.Reset();
- mock_text_input_client.Reset();
-
- std::vector<gfx::Rect> bounds;
- bounds.push_back(gfx::Rect(10, 20, 30, 40));
- bounds.push_back(gfx::Rect(40, 30, 20, 10));
- mock_text_input_client.set_composition_character_bounds(bounds);
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- EXPECT_EQ(bounds, mock_remote_delegate.composition_character_bounds());
- }
-}
-
-// Test case against crbug.com/328237.
-TEST(RemoteInputMethodWinTest, OnCaretBoundsChangedForPepperFlash) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- mock_remote_delegate.Reset();
- mock_text_input_client.Reset();
- mock_text_input_client.set_emulate_pepper_flash(true);
-
- std::vector<gfx::Rect> caret_bounds;
- caret_bounds.push_back(gfx::Rect(5, 15, 25, 35));
- mock_text_input_client.set_caret_bounds(caret_bounds[0]);
-
- std::vector<gfx::Rect> composition_bounds;
- composition_bounds.push_back(gfx::Rect(10, 20, 30, 40));
- composition_bounds.push_back(gfx::Rect(40, 30, 20, 10));
- mock_text_input_client.set_composition_character_bounds(composition_bounds);
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- // The caret bounds must be used when
- // TextInputClient::GetCompositionCharacterBounds failed.
- EXPECT_EQ(caret_bounds, mock_remote_delegate.composition_character_bounds());
-}
-
-TEST(RemoteInputMethodWinTest, OnTextInputTypeChanged) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- // This must not cause a crash.
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
-
- mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_URL);
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // Initial state must be synced.
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- ASSERT_EQ(1u, mock_remote_delegate.input_scopes().size());
- EXPECT_EQ(IS_URL, mock_remote_delegate.input_scopes()[0]);
-
- // Check TEXT_INPUT_TYPE_NONE is handled.
- mock_remote_delegate.Reset();
- mock_text_input_client.Reset();
- mock_text_input_client.set_text_input_type(ui::TEXT_INPUT_TYPE_NONE);
- mock_text_input_client.set_text_input_mode(ui::TEXT_INPUT_MODE_KATAKANA);
- input_method->OnTextInputTypeChanged(&mock_text_input_client);
- EXPECT_TRUE(mock_remote_delegate.text_input_client_updated_called());
- EXPECT_TRUE(mock_remote_delegate.input_scopes().empty());
-
- // Redundant OnTextInputTypeChanged must be ignored.
- mock_remote_delegate.Reset();
- input_method->OnTextInputTypeChanged(&mock_text_input_client);
- EXPECT_FALSE(mock_remote_delegate.text_input_client_updated_called());
-
- mock_remote_delegate.Reset();
- mock_text_input_client.Reset();
- mock_text_input_client.set_caret_bounds(gfx::Rect(10, 20, 30, 40));
- input_method->OnCaretBoundsChanged(&mock_text_input_client);
-}
-
-TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeKeyEvent) {
- // Basically RemoteInputMethodWin does not handle native keydown event.
-
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- const MSG wm_keydown = { NULL, WM_KEYDOWN, ui::VKEY_A };
- ui::KeyEvent new_keydown(wm_keydown);
- ui::KeyEvent native_keydown(new_keydown);
-
- // This must not cause a crash.
- input_method->DispatchKeyEvent(&native_keydown);
- EXPECT_FALSE(native_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // TextInputClient is not focused yet here.
- native_keydown = new_keydown;
- input_method->DispatchKeyEvent(&native_keydown);
- EXPECT_FALSE(native_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- // TextInputClient is now focused here.
- native_keydown = new_keydown;
- input_method->DispatchKeyEvent(&native_keydown);
- EXPECT_FALSE(native_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, DispatchKeyEvent_NativeCharEvent) {
- // RemoteInputMethodWin handles native char event if possible.
-
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- const MSG wm_char = { NULL, WM_CHAR, 'A', 0 };
- ui::KeyEvent new_char(wm_char);
- ui::KeyEvent native_char(new_char);
-
- // This must not cause a crash.
- input_method->DispatchKeyEvent(&native_char);
- EXPECT_FALSE(native_char.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // TextInputClient is not focused yet here.
- native_char = new_char;
- input_method->DispatchKeyEvent(&native_char);
- EXPECT_FALSE(native_char.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- // TextInputClient is now focused here.
- native_char = new_char;
- input_method->DispatchKeyEvent(&native_char);
- EXPECT_TRUE(native_char.handled());
- EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedKeyDown) {
- // Fabricated non-char event will be delegated to
- // InputMethodDelegate::DispatchFabricatedKeyEventPostIME as long as the
- // delegate is installed.
-
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- ui::KeyEvent new_keydown(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
- new_keydown.set_character(L'A');
- ui::KeyEvent fabricated_keydown(new_keydown);
-
- // This must not cause a crash.
- input_method->DispatchKeyEvent(&fabricated_keydown);
- EXPECT_TRUE(fabricated_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- ASSERT_EQ(1u, delegate_.fabricated_key_events().size());
- EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // TextInputClient is not focused yet here.
- fabricated_keydown = new_keydown;
- input_method->DispatchKeyEvent(&fabricated_keydown);
- EXPECT_TRUE(fabricated_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- ASSERT_EQ(1u, delegate_.fabricated_key_events().size());
- EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
- // TextInputClient is now focused here.
- fabricated_keydown = new_keydown;
- input_method->DispatchKeyEvent(&fabricated_keydown);
- EXPECT_TRUE(fabricated_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- ASSERT_EQ(1u, delegate_.fabricated_key_events().size());
- EXPECT_EQ(L'A', delegate_.fabricated_key_events()[0]);
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetDelegate(NULL);
- // RemoteInputMethodDelegateWin is no longer set here.
- fabricated_keydown = new_keydown;
- input_method->DispatchKeyEvent(&fabricated_keydown);
- EXPECT_FALSE(fabricated_keydown.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
-}
-
-TEST(RemoteInputMethodWinTest, DispatchKeyEvent_FabricatedChar) {
- // Note: RemoteInputMethodWin::DispatchKeyEvent should always return true
- // for fabricated character events.
-
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- ui::KeyEvent new_char(L'A', ui::VKEY_A, ui::EF_NONE);
- ui::KeyEvent fabricated_char(new_char);
-
- // This must not cause a crash.
- input_method->DispatchKeyEvent(&fabricated_char);
- EXPECT_TRUE(fabricated_char.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- // TextInputClient is not focused yet here.
- fabricated_char = new_char;
- input_method->DispatchKeyEvent(&fabricated_char);
- EXPECT_TRUE(fabricated_char.handled());
- EXPECT_TRUE(mock_text_input_client.inserted_text().empty());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- // TextInputClient is now focused here.
- fabricated_char = new_char;
- input_method->DispatchKeyEvent(&fabricated_char);
- EXPECT_TRUE(fabricated_char.handled());
- EXPECT_EQ(L"A", mock_text_input_client.inserted_text());
- EXPECT_TRUE(delegate_.fabricated_key_events().empty());
- delegate_.Reset();
- mock_text_input_client.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, OnCompositionChanged) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- CompositionText composition_text;
-
- // TextInputClient is not focused yet here.
-
- private_ptr->OnCompositionChanged(composition_text);
- EXPECT_EQ(0u, mock_text_input_client.call_count_set_composition_text());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- // TextInputClient is now focused here.
-
- private_ptr->OnCompositionChanged(composition_text);
- EXPECT_EQ(1u, mock_text_input_client.call_count_set_composition_text());
- delegate_.Reset();
- mock_text_input_client.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, OnTextCommitted) {
- MockInputMethodDelegate delegate_;
- MockTextInputClient mock_text_input_client;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
-
- RemoteInputMethodPrivateWin* private_ptr =
- RemoteInputMethodPrivateWin::Get(input_method.get());
- ASSERT_TRUE(private_ptr != NULL);
- MockRemoteInputMethodDelegateWin mock_remote_delegate;
- private_ptr->SetRemoteDelegate(&mock_remote_delegate);
-
- base::string16 committed_text = L"Hello";
-
- // TextInputClient is not focused yet here.
-
- mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
- private_ptr->OnTextCommitted(committed_text);
- EXPECT_EQ(0u, mock_text_input_client.call_count_insert_char());
- EXPECT_EQ(0u, mock_text_input_client.call_count_insert_text());
- EXPECT_EQ(L"", mock_text_input_client.inserted_text());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- input_method->SetFocusedTextInputClient(&mock_text_input_client);
-
- // TextInputClient is now focused here.
-
- mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_TEXT);
- private_ptr->OnTextCommitted(committed_text);
- EXPECT_EQ(0u, mock_text_input_client.call_count_insert_char());
- EXPECT_EQ(1u, mock_text_input_client.call_count_insert_text());
- EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
- delegate_.Reset();
- mock_text_input_client.Reset();
-
- // When TextInputType is TEXT_INPUT_TYPE_NONE, TextInputClient::InsertText
- // should not be used.
- mock_text_input_client.set_text_input_type(TEXT_INPUT_TYPE_NONE);
- private_ptr->OnTextCommitted(committed_text);
- EXPECT_EQ(committed_text.size(),
- mock_text_input_client.call_count_insert_char());
- EXPECT_EQ(0u, mock_text_input_client.call_count_insert_text());
- EXPECT_EQ(committed_text, mock_text_input_client.inserted_text());
- delegate_.Reset();
- mock_text_input_client.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, OnTextInputStateChanged_Observer) {
- DummyTextInputClient text_input_client;
- DummyTextInputClient text_input_client_the_other;
-
- MockInputMethodObserver input_method_observer;
- MockInputMethodDelegate delegate_;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- InputMethodScopedObserver scoped_observer(&input_method_observer);
- scoped_observer.Add(input_method.get());
-
- input_method->SetFocusedTextInputClient(&text_input_client);
- ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
- EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
- input_method_observer.Reset();
-
- input_method->SetFocusedTextInputClient(&text_input_client);
- ASSERT_EQ(&text_input_client, input_method->GetTextInputClient());
- EXPECT_EQ(0u, input_method_observer.on_text_input_state_changed());
- input_method_observer.Reset();
-
- input_method->SetFocusedTextInputClient(&text_input_client_the_other);
- ASSERT_EQ(&text_input_client_the_other, input_method->GetTextInputClient());
- EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
- input_method_observer.Reset();
-
- input_method->DetachTextInputClient(&text_input_client_the_other);
- ASSERT_TRUE(input_method->GetTextInputClient() == NULL);
- EXPECT_EQ(1u, input_method_observer.on_text_input_state_changed());
- input_method_observer.Reset();
-}
-
-TEST(RemoteInputMethodWinTest, OnInputMethodDestroyed_Observer) {
- DummyTextInputClient text_input_client;
- DummyTextInputClient text_input_client_the_other;
-
- MockInputMethodObserver input_method_observer;
- InputMethodScopedObserver scoped_observer(&input_method_observer);
-
- MockInputMethodDelegate delegate_;
- scoped_ptr<InputMethod> input_method(CreateRemoteInputMethodWin(&delegate_));
- input_method->AddObserver(&input_method_observer);
-
- EXPECT_EQ(0u, input_method_observer.on_input_method_destroyed_changed());
- input_method.reset();
- EXPECT_EQ(1u, input_method_observer.on_input_method_destroyed_changed());
-}
-
-} // namespace
-} // namespace ui
diff --git a/chromium/ui/base/ime/ui_base_ime.gyp b/chromium/ui/base/ime/ui_base_ime.gyp
index 22c3e720148..ed873ae0504 100644
--- a/chromium/ui/base/ime/ui_base_ime.gyp
+++ b/chromium/ui/base/ime/ui_base_ime.gyp
@@ -7,6 +7,16 @@
'chromium_code': 1,
},
'targets': [
+ {
+ # GN version: //ui/base/ime:text_input_types
+ 'target_name': 'text_input_types',
+ 'type': 'none',
+ 'sources' : [
+ 'text_input_flags.h',
+ 'text_input_mode.h',
+ 'text_input_type.h',
+ ],
+ },
{
# GN version: //ui/base/ime
'target_name': 'ui_base_ime',
@@ -25,6 +35,7 @@
'../../gfx/gfx.gyp:gfx',
'../../gfx/gfx.gyp:gfx_geometry',
'../ui_base.gyp:ui_base',
+ ':text_input_types',
],
'defines': [
'UI_BASE_IME_IMPLEMENTATION',
@@ -56,8 +67,6 @@
'chromeos/input_method_descriptor.h',
'chromeos/input_method_manager.cc',
'chromeos/input_method_manager.h',
- 'chromeos/input_method_whitelist.cc',
- 'chromeos/input_method_whitelist.h',
'chromeos/mock_component_extension_ime_manager_delegate.cc',
'chromeos/mock_component_extension_ime_manager_delegate.h',
'chromeos/mock_ime_candidate_window_handler.cc',
@@ -73,9 +82,7 @@
'composition_underline.h',
'ime_bridge.cc',
'ime_bridge.h',
- 'ime_engine_handler_interface.cc',
'ime_engine_handler_interface.h',
- 'ime_engine_observer.h',
'ime_input_context_handler_interface.h',
'infolist_entry.cc',
'infolist_entry.h',
@@ -107,12 +114,8 @@
'linux/linux_input_method_context_factory.h',
'mock_input_method.cc',
'mock_input_method.h',
- 'remote_input_method_delegate_win.h',
- 'remote_input_method_win.cc',
- 'remote_input_method_win.h',
'text_input_client.cc',
'text_input_client.h',
- 'text_input_type.h',
'ui_base_ime_export.h',
'win/imm32_manager.cc',
'win/imm32_manager.h',
diff --git a/chromium/ui/base/ime/win/imm32_manager.cc b/chromium/ui/base/ime/win/imm32_manager.cc
index 853bf3ff26a..9f03a2a8651 100644
--- a/chromium/ui/base/ime/win/imm32_manager.cc
+++ b/chromium/ui/base/ime/win/imm32_manager.cc
@@ -15,11 +15,6 @@
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ime/composition_text.h"
-// "imm32.lib" is required by IMM32 APIs used in this file.
-// NOTE(hbono): To comply with a comment from Darin, I have added
-// this #pragma directive instead of adding "imm32.lib" to a project file.
-#pragma comment(lib, "imm32.lib")
-
// Following code requires wchar_t to be same as char16. It should always be
// true on Windows.
static_assert(sizeof(wchar_t) == sizeof(base::char16),
diff --git a/chromium/ui/base/ios/cru_context_menu_controller.h b/chromium/ui/base/ios/cru_context_menu_controller.h
index cb966fa00cd..f656c4af154 100644
--- a/chromium/ui/base/ios/cru_context_menu_controller.h
+++ b/chromium/ui/base/ios/cru_context_menu_controller.h
@@ -6,6 +6,8 @@
#import <UIKit/UIKit.h>
+#include "base/ios/block_types.h"
+
@class CRUContextMenuHolder;
// Abstracts displaying context menus for all device form factors, given a
@@ -25,6 +27,10 @@
atPoint:(CGPoint)localPoint
inView:(UIView*)view;
+// Dismisses displayed context menu.
+- (void)dismissAnimated:(BOOL)animated
+ completionHandler:(ProceduralBlock)completionHandler;
+
@end
#endif // UI_BASE_IOS_CRU_CONTEXT_MENU_CONTROLLER_H_
diff --git a/chromium/ui/base/ios/cru_context_menu_controller.mm b/chromium/ui/base/ios/cru_context_menu_controller.mm
index f615c017b06..d052c99070a 100644
--- a/chromium/ui/base/ios/cru_context_menu_controller.mm
+++ b/chromium/ui/base/ios/cru_context_menu_controller.mm
@@ -6,34 +6,14 @@
#include <algorithm>
-#include "base/ios/ios_util.h"
#include "base/ios/weak_nsobject.h"
#include "base/logging.h"
#import "base/mac/scoped_nsobject.h"
#include "ui/base/device_form_factor.h"
#import "ui/base/ios/cru_context_menu_holder.h"
#include "ui/base/l10n/l10n_util.h"
-#import "ui/gfx/ios/NSString+CrStringDrawing.h"
#include "ui/strings/grit/ui_strings.h"
-namespace {
-
-// Returns the screen's height in points.
-CGFloat GetScreenHeight() {
- DCHECK(!base::ios::IsRunningOnIOS8OrLater());
- switch ([[UIApplication sharedApplication] statusBarOrientation]) {
- case UIInterfaceOrientationLandscapeLeft:
- case UIInterfaceOrientationLandscapeRight:
- return CGRectGetWidth([[UIScreen mainScreen] bounds]);
- case UIInterfaceOrientationPortraitUpsideDown:
- case UIInterfaceOrientationPortrait:
- case UIInterfaceOrientationUnknown:
- return CGRectGetHeight([[UIScreen mainScreen] bounds]);
- }
-}
-
-} // namespace
-
// Abstracts system implementation of popovers and action sheets.
@protocol CRUContextMenuControllerImpl<NSObject>
@@ -44,21 +24,18 @@ CGFloat GetScreenHeight() {
- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder
atPoint:(CGPoint)localPoint
inView:(UIView*)view;
-@end
-// Backs up CRUContextMenuController on iOS 7 by using UIActionSheet.
-@interface CRUActionSheetController
- : NSObject<CRUContextMenuControllerImpl, UIActionSheetDelegate> {
- // The action sheet used to display the UI.
- base::scoped_nsobject<UIActionSheet> _sheet;
- // Holds all the titles and actions for the menu.
- base::scoped_nsobject<CRUContextMenuHolder> _menuHolder;
-}
+// Dismisses displayed context menu.
+- (void)dismissAnimated:(BOOL)animated
+ completionHandler:(ProceduralBlock)completionHandler;
+
@end
-// Backs up CRUContextMenuController on iOS 8 and higher by using
-// UIAlertController.
-@interface CRUAlertController : NSObject<CRUContextMenuControllerImpl>
+// Backs up CRUContextMenuController by using UIAlertController.
+@interface CRUAlertController : NSObject<CRUContextMenuControllerImpl> {
+ // Weak underlying UIAlertController.
+ base::WeakNSObject<UIAlertController> _alert;
+}
// Redefined to readwrite.
@property(nonatomic, readwrite, getter=isVisible) BOOL visible;
@end
@@ -76,15 +53,16 @@ CGFloat GetScreenHeight() {
- (instancetype)init {
self = [super init];
if (self) {
- if (base::ios::IsRunningOnIOS8OrLater()) {
- _impl.reset([[CRUAlertController alloc] init]);
- } else {
- _impl.reset([[CRUActionSheetController alloc] init]);
- }
+ _impl.reset([[CRUAlertController alloc] init]);
}
return self;
}
+- (void)dealloc {
+ [_impl dismissAnimated:NO completionHandler:nil];
+ [super dealloc];
+}
+
- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder
atPoint:(CGPoint)point
inView:(UIView*)view {
@@ -96,134 +74,13 @@ CGFloat GetScreenHeight() {
[_impl showWithHolder:menuHolder atPoint:point inView:view];
}
-@end
-
-#pragma mark - iOS 7
-
-@implementation CRUActionSheetController
-@synthesize visible = _visible;
-
-- (void)dealloc {
- if (_visible) {
- // Context menu must be dismissed explicitly if it is still visible.
- NSUInteger cancelButtonIndex = [_menuHolder itemCount];
- [_sheet dismissWithClickedButtonIndex:cancelButtonIndex animated:NO];
- }
- [super dealloc];
-}
-
-- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder
- atPoint:(CGPoint)point
- inView:(UIView*)view {
- // If the content of UIActionSheet does not fit the screen then scrollbars
- // are added to the menu items area. If that's the case, elide the title to
- // avoid having scrollbars for menu items.
- CGSize spaceAvailableForTitle =
- [self sizeForTitleThatFitsMenuWithHolder:menuHolder
- atPoint:point
- inView:view];
- NSString* menuTitle = menuHolder.menuTitle;
- if (menuTitle) {
- // Show at least one line of text, even if that means the action sheet's
- // items will need to scroll.
- const CGFloat kMinimumVerticalSpace = 21;
- spaceAvailableForTitle.height =
- std::max(kMinimumVerticalSpace, spaceAvailableForTitle.height);
- menuTitle = [menuTitle cr_stringByElidingToFitSize:spaceAvailableForTitle];
- }
-
- // Present UIActionSheet.
- _sheet.reset(
- [self newActionSheetWithHolder:menuHolder title:menuTitle delegate:self]);
- [_sheet setCancelButtonIndex:menuHolder.itemCount];
- [_sheet showFromRect:CGRectMake(point.x, point.y, 1.0, 1.0)
- inView:view
- animated:YES];
-
- _menuHolder.reset([menuHolder retain]);
- _visible = YES;
-}
-
-#pragma mark Implementation
-
-// Returns an approximation of the free space available for the title of an
-// actionSheet filled with |menu| shown in |view| at |point|.
-- (CGSize)sizeForTitleThatFitsMenuWithHolder:(CRUContextMenuHolder*)menuHolder
- atPoint:(CGPoint)point
- inView:(UIView*)view {
- // Create a dummy UIActionSheet.
- base::scoped_nsobject<UIActionSheet> dummySheet(
- [self newActionSheetWithHolder:menuHolder title:nil delegate:nil]);
- // Temporarily add the dummy UIActionSheet to |view|.
- [dummySheet showFromRect:CGRectMake(point.x, point.y, 1.0, 1.0)
- inView:view
- animated:NO];
- // On iPad the actionsheet is positioned under or over |point| (as opposed
- // to next to it) when the user clicks within approximately 200 points of
- // respectively the top or bottom edge. This reduces the amount of vertical
- // space available for the title, hence the large padding on ipad.
- const CGFloat kPaddingiPad = 200;
- const CGFloat kPaddingiPhone = 20;
- BOOL isIPad = ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET;
- const CGFloat padding = isIPad ? kPaddingiPad : kPaddingiPhone;
- // A title uses the full width of the actionsheet and all the vertical
- // space on the screen.
- CGSize result = CGSizeMake(
- CGRectGetWidth([dummySheet frame]),
- GetScreenHeight() - CGRectGetHeight([dummySheet frame]) - padding);
- [dummySheet dismissWithClickedButtonIndex:0 animated:NO];
- return result;
-}
-
-// Returns an UIActionSheet. Callers responsible for releasing returned object.
-- (UIActionSheet*)newActionSheetWithHolder:(CRUContextMenuHolder*)menuHolder
- title:(NSString*)title
- delegate:(id<UIActionSheetDelegate>)delegate {
- UIActionSheet* sheet = [[UIActionSheet alloc] initWithTitle:title
- delegate:delegate
- cancelButtonTitle:nil
- destructiveButtonTitle:nil
- otherButtonTitles:nil];
-
- for (NSString* itemTitle in menuHolder.itemTitles) {
- [sheet addButtonWithTitle:itemTitle];
- }
- [sheet addButtonWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)];
- return sheet;
-}
-
-#pragma mark UIActionSheetDelegate
-
-// Called when the action sheet is dismissed in the modal context menu sheet.
-// There is no way to dismiss the sheet without going through this method. Note
-// that on iPad this method is called with the index of an nonexistent cancel
-// button when the user taps outside the sheet.
-- (void)actionSheet:(UIActionSheet*)actionSheet
- didDismissWithButtonIndex:(NSInteger)buttonIndex {
- NSUInteger unsignedButtonIndex = buttonIndex;
- // Assumes "cancel" button is last in order.
- if (unsignedButtonIndex < [_menuHolder itemCount])
- [_menuHolder performActionAtIndex:unsignedButtonIndex];
- _menuHolder.reset();
- _visible = NO;
-}
-
-// Called when the user chooses a button in the modal context menu sheet. Note
-// that on iPad this method is called with the index of an nonexistent cancel
-// button when the user taps outside the sheet.
-- (void)actionSheet:(UIActionSheet*)actionSheet
- clickedButtonAtIndex:(NSInteger)buttonIndex {
- // Some use cases (e.g. opening a new tab on handset) should not wait for the
- // action sheet to animate away before executing the action.
- if ([_menuHolder shouldDismissImmediatelyOnClickedAtIndex:buttonIndex]) {
- [_sheet dismissWithClickedButtonIndex:buttonIndex animated:NO];
- }
+- (void)dismissAnimated:(BOOL)animated
+ completionHandler:(ProceduralBlock)completionHandler {
+ [_impl dismissAnimated:animated completionHandler:completionHandler];
}
@end
-#pragma mark - iOS8 and higher
-
@implementation CRUAlertController
@synthesize visible = _visible;
@@ -283,6 +140,12 @@ CGFloat GetScreenHeight() {
topController = topController.presentedViewController;
[topController presentViewController:alert animated:YES completion:nil];
self.visible = YES;
+ _alert.reset(alert);
+}
+
+- (void)dismissAnimated:(BOOL)animated
+ completionHandler:(ProceduralBlock)completionHandler {
+ [_alert dismissViewControllerAnimated:animated completion:completionHandler];
}
@end
diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc
index c3e850da221..8f262c511be 100644
--- a/chromium/ui/base/l10n/l10n_util.cc
+++ b/chromium/ui/base/l10n/l10n_util.cc
@@ -50,7 +50,9 @@ namespace {
static const char* const kAcceptLanguageList[] = {
"af", // Afrikaans
"am", // Amharic
+ "an", // Aragonese
"ar", // Arabic
+ "ast", // Asturian
"az", // Azerbaijani
"be", // Belarusian
"bg", // Bulgarian
@@ -74,6 +76,7 @@ static const char* const kAcceptLanguageList[] = {
"en-AU", // English (Australia)
"en-CA", // English (Canada)
"en-GB", // English (UK)
+ "en-IN", // English (India)
"en-NZ", // English (New Zealand)
"en-US", // English (US)
"en-ZA", // English (South Africa)
@@ -82,6 +85,10 @@ static const char* const kAcceptLanguageList[] = {
// Spanish speaking countries?
"es", // Spanish
"es-419", // Spanish (Latin America)
+ "es-AR", // Spanish (Argentina)
+ "es-ES", // Spanish (Spain)
+ "es-MX", // Spanish (Mexico)
+ "es-US", // Spanish (US)
"et", // Estonian
"eu", // Basque
"fa", // Persian
@@ -178,12 +185,14 @@ static const char* const kAcceptLanguageList[] = {
"ur", // Urdu
"uz", // Uzbek
"vi", // Vietnamese
+ "wa", // Walloon
"xh", // Xhosa
"yi", // Yiddish
"yo", // Yoruba
"zh", // Chinese
- "zh-CN", // Chinese (Simplified)
- "zh-TW", // Chinese (Traditional)
+ "zh-CN", // Chinese (China)
+ "zh-HK", // Chinese (Hong Kong)
+ "zh-TW", // Chinese (Taiwan)
"zu", // Zulu
};
@@ -314,6 +323,8 @@ std::string GetLanguage(const std::string& locale) {
return std::string(locale, 0, hyphen_pos);
}
+// TOOD(jshin): revamp this function completely to use a more sytematic
+// and generic locale fallback based on ICU/CLDR.
bool CheckAndResolveLocale(const std::string& locale,
std::string* resolved_locale) {
#if defined(OS_MACOSX)
@@ -355,12 +366,13 @@ bool CheckAndResolveLocale(const std::string& locale,
tmp_locale.append("-CN");
}
} else if (base::LowerCaseEqualsASCII(lang, "en")) {
- // Map Australian, Canadian, New Zealand and South African English
- // to British English for now.
+ // Map Australian, Canadian, Indian, New Zealand and South African
+ // English to British English for now.
// TODO(jungshik): en-CA may have to change sides once
// we have OS locale separate from app locale (Chrome's UI language).
if (base::LowerCaseEqualsASCII(region, "au") ||
base::LowerCaseEqualsASCII(region, "ca") ||
+ base::LowerCaseEqualsASCII(region, "in") ||
base::LowerCaseEqualsASCII(region, "nz") ||
base::LowerCaseEqualsASCII(region, "za")) {
tmp_locale.append("-GB");
diff --git a/chromium/ui/base/l10n/l10n_util_collator.h b/chromium/ui/base/l10n/l10n_util_collator.h
index d2b95f26ae1..423f17a50da 100644
--- a/chromium/ui/base/l10n/l10n_util_collator.h
+++ b/chromium/ui/base/l10n/l10n_util_collator.h
@@ -22,10 +22,7 @@ namespace l10n_util {
// Used by SortStringsUsingMethod. Invokes a method on the objects passed to
// operator (), comparing the string results using a collator.
template <class T, class Method>
-class StringMethodComparatorWithCollator
- : public std::binary_function<const base::string16&,
- const base::string16&,
- bool> {
+class StringMethodComparatorWithCollator {
public:
StringMethodComparatorWithCollator(icu::Collator* collator, Method method)
: collator_(collator),
@@ -46,10 +43,7 @@ class StringMethodComparatorWithCollator
// Used by SortStringsUsingMethod. Invokes a method on the objects passed to
// operator (), comparing the string results using <.
template <class T, class Method>
-class StringMethodComparator
- : public std::binary_function<const base::string16&,
- const base::string16&,
- bool> {
+class StringMethodComparator {
public:
explicit StringMethodComparator(Method method) : method_(method) { }
@@ -88,9 +82,7 @@ void SortStringsUsingMethod(const std::string& locale,
// const base::string16& GetStringKey() const;
// This uses the locale specified in the constructor.
template <class Element>
-class StringComparator : public std::binary_function<const Element&,
- const Element&,
- bool> {
+class StringComparator {
public:
explicit StringComparator(icu::Collator* collator)
: collator_(collator) { }
diff --git a/chromium/ui/base/layout.cc b/chromium/ui/base/layout.cc
index f4ebc0162c5..4299f097114 100644
--- a/chromium/ui/base/layout.cc
+++ b/chromium/ui/base/layout.cc
@@ -26,11 +26,6 @@ namespace {
std::vector<ScaleFactor>* g_supported_scale_factors = NULL;
-const float kScaleFactorScales[] = {1.0f, 1.0f, 1.25f, 1.33f, 1.4f, 1.5f, 1.8f,
- 2.0f, 2.5f, 3.0f};
-static_assert(NUM_SCALE_FACTORS == arraysize(kScaleFactorScales),
- "kScaleFactorScales has incorrect size");
-
} // namespace
void SetSupportedScaleFactors(
@@ -50,7 +45,7 @@ void SetSupportedScaleFactors(
for (std::vector<ScaleFactor>::const_iterator it =
g_supported_scale_factors->begin();
it != g_supported_scale_factors->end(); ++it) {
- scales.push_back(kScaleFactorScales[*it]);
+ scales.push_back(GetScaleForScaleFactor(*it));
}
gfx::ImageSkia::SetSupportedScales(scales);
}
@@ -66,7 +61,7 @@ ScaleFactor GetSupportedScaleFactor(float scale) {
float smallest_diff = std::numeric_limits<float>::max();
for (size_t i = 0; i < g_supported_scale_factors->size(); ++i) {
ScaleFactor scale_factor = (*g_supported_scale_factors)[i];
- float diff = std::abs(kScaleFactorScales[scale_factor] - scale);
+ float diff = std::abs(GetScaleForScaleFactor(scale_factor) - scale);
if (diff < smallest_diff) {
closest_match = scale_factor;
smallest_diff = diff;
@@ -76,13 +71,9 @@ ScaleFactor GetSupportedScaleFactor(float scale) {
return closest_match;
}
-float GetScaleForScaleFactor(ScaleFactor scale_factor) {
- return kScaleFactorScales[scale_factor];
-}
-
bool IsSupportedScale(float scale) {
for (auto scale_factor_idx : *g_supported_scale_factors) {
- if (kScaleFactorScales[scale_factor_idx] == scale)
+ if (GetScaleForScaleFactor(scale_factor_idx) == scale)
return true;
}
return false;
@@ -115,9 +106,9 @@ ScopedSetSupportedScaleFactors::~ScopedSetSupportedScaleFactors() {
#if !defined(OS_MACOSX)
float GetScaleFactorForNativeView(gfx::NativeView view) {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(view);
- gfx::Display display = screen->GetDisplayNearestWindow(view);
- return display.device_scale_factor();
+ return gfx::Screen::GetScreen()
+ ->GetDisplayNearestWindow(view)
+ .device_scale_factor();
}
#endif // !defined(OS_MACOSX)
diff --git a/chromium/ui/base/layout.h b/chromium/ui/base/layout.h
index 8b528580f74..fd2627bbc50 100644
--- a/chromium/ui/base/layout.h
+++ b/chromium/ui/base/layout.h
@@ -9,31 +9,12 @@
#include "base/macros.h"
#include "build/build_config.h"
+#include "ui/base/resource/scale_factor.h"
#include "ui/base/ui_base_export.h"
#include "ui/gfx/native_widget_types.h"
namespace ui {
-// Supported UI scale factors for the platform. This is used as an index
-// into the array |kScaleFactorScales| which maps the enum value to a float.
-// SCALE_FACTOR_NONE is used for density independent resources such as
-// string, html/js files or an image that can be used for any scale factors
-// (such as wallpapers).
-enum ScaleFactor : int {
- SCALE_FACTOR_NONE = 0,
- SCALE_FACTOR_100P,
- SCALE_FACTOR_125P,
- SCALE_FACTOR_133P,
- SCALE_FACTOR_140P,
- SCALE_FACTOR_150P,
- SCALE_FACTOR_180P,
- SCALE_FACTOR_200P,
- SCALE_FACTOR_250P,
- SCALE_FACTOR_300P,
-
- NUM_SCALE_FACTORS // This always appears last.
-};
-
// Changes the value of GetSupportedScaleFactors() to |scale_factors|.
// Use ScopedSetSupportedScaleFactors for unit tests as not to affect the
// state of other tests.
@@ -52,9 +33,6 @@ UI_BASE_EXPORT ScaleFactor GetSupportedScaleFactor(float image_scale);
// Returns the ScaleFactor used by |view|.
UI_BASE_EXPORT float GetScaleFactorForNativeView(gfx::NativeView view);
-// Returns the image scale for the scale factor passed in.
-UI_BASE_EXPORT float GetScaleForScaleFactor(ScaleFactor scale_factor);
-
// Returns true if the scale passed in is the list of supported scales for
// the platform.
UI_BASE_EXPORT bool IsSupportedScale(float scale);
diff --git a/chromium/ui/base/layout_mac.mm b/chromium/ui/base/layout_mac.mm
index 62331e99f0d..27e12e1fa09 100644
--- a/chromium/ui/base/layout_mac.mm
+++ b/chromium/ui/base/layout_mac.mm
@@ -12,9 +12,7 @@ namespace {
float GetScaleFactorScaleForNativeView(gfx::NativeView view) {
if (NSWindow* window = [view window]) {
- if ([window respondsToSelector:@selector(backingScaleFactor)])
- return [window backingScaleFactor];
- return [window userSpaceScaleFactor];
+ return [window backingScaleFactor];
}
NSArray* screens = [NSScreen screens];
@@ -22,9 +20,7 @@ float GetScaleFactorScaleForNativeView(gfx::NativeView view) {
return 1.0f;
NSScreen* screen = [screens objectAtIndex:0];
- if ([screen respondsToSelector:@selector(backingScaleFactor)])
- return [screen backingScaleFactor];
- return [screen userSpaceScaleFactor];
+ return [screen backingScaleFactor];
}
} // namespace
diff --git a/chromium/ui/base/layout_unittest.cc b/chromium/ui/base/layout_unittest.cc
index 4b0c5b1542c..7c975e6b155 100644
--- a/chromium/ui/base/layout_unittest.cc
+++ b/chromium/ui/base/layout_unittest.cc
@@ -14,18 +14,6 @@
namespace ui {
-TEST(LayoutTest, GetScaleFactorScale) {
- EXPECT_FLOAT_EQ(1.0f, GetScaleForScaleFactor(SCALE_FACTOR_100P));
- EXPECT_FLOAT_EQ(1.25f, GetScaleForScaleFactor(SCALE_FACTOR_125P));
- EXPECT_FLOAT_EQ(1.33f, GetScaleForScaleFactor(SCALE_FACTOR_133P));
- EXPECT_FLOAT_EQ(1.4f, GetScaleForScaleFactor(SCALE_FACTOR_140P));
- EXPECT_FLOAT_EQ(1.5f, GetScaleForScaleFactor(SCALE_FACTOR_150P));
- EXPECT_FLOAT_EQ(1.8f, GetScaleForScaleFactor(SCALE_FACTOR_180P));
- EXPECT_FLOAT_EQ(2.0f, GetScaleForScaleFactor(SCALE_FACTOR_200P));
- EXPECT_FLOAT_EQ(2.5f, GetScaleForScaleFactor(SCALE_FACTOR_250P));
- EXPECT_FLOAT_EQ(3.0f, GetScaleForScaleFactor(SCALE_FACTOR_300P));
-}
-
TEST(LayoutTest, GetScaleFactorFromScalePartlySupported) {
std::vector<ScaleFactor> supported_factors;
supported_factors.push_back(SCALE_FACTOR_100P);
diff --git a/chromium/ui/base/resource/material_design/material_design_controller.cc b/chromium/ui/base/material_design/material_design_controller.cc
index b19935e4962..411f553a8ba 100644
--- a/chromium/ui/base/resource/material_design/material_design_controller.cc
+++ b/chromium/ui/base/material_design/material_design_controller.cc
@@ -6,9 +6,22 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_CHROMEOS)
+#include "ui/base/touch/touch_device.h"
+#include "ui/events/devices/device_data_manager.h"
+
+#if defined(USE_OZONE)
+#include <fcntl.h>
+
+#include "base/files/file_enumerator.h"
+#include "ui/events/ozone/evdev/event_device_info.h"
+#endif // defined(USE_OZONE)
+
+#endif // defined(OS_CHROMEOS)
+
namespace ui {
bool MaterialDesignController::is_mode_initialized_ = false;
@@ -28,6 +41,39 @@ bool MaterialDesignController::IsModeMaterial() {
GetMode() == Mode::MATERIAL_HYBRID;
}
+MaterialDesignController::Mode MaterialDesignController::DefaultMode() {
+#if defined(OS_CHROMEOS)
+ if (DeviceDataManager::HasInstance() &&
+ DeviceDataManager::GetInstance()->device_lists_complete()) {
+ return GetTouchScreensAvailability() == TouchScreensAvailability::ENABLED ?
+ Mode::MATERIAL_HYBRID : Mode::MATERIAL_NORMAL;
+ }
+
+#if defined(USE_OZONE)
+ base::FileEnumerator file_enum(
+ base::FilePath(FILE_PATH_LITERAL("/dev/input")), false,
+ base::FileEnumerator::FILES, FILE_PATH_LITERAL("event*[0-9]"));
+ for (base::FilePath path = file_enum.Next(); !path.empty();
+ path = file_enum.Next()) {
+ EventDeviceInfo devinfo;
+ int fd = open(path.value().c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0) {
+ if (devinfo.Initialize(fd, path) && devinfo.HasTouchscreen()) {
+ close(fd);
+ return Mode::MATERIAL_HYBRID;
+ }
+ close(fd);
+ }
+ }
+#endif // defined(USE_OZONE)
+ return Mode::MATERIAL_NORMAL;
+#elif defined(OS_LINUX)
+ return Mode::MATERIAL_NORMAL;
+#else
+ return Mode::NON_MATERIAL;
+#endif // defined(OS_CHROMEOS)
+}
+
void MaterialDesignController::InitializeMode() {
#if !defined(ENABLE_TOPCHROME_MD)
SetMode(Mode::NON_MATERIAL);
@@ -43,10 +89,12 @@ void MaterialDesignController::InitializeMode() {
} else if (switch_value == switches::kTopChromeMDNonMaterial) {
SetMode(Mode::NON_MATERIAL);
} else {
- LOG(ERROR) << "Invalid value='" << switch_value
- << "' for command line switch '" << switches::kTopChromeMD
- << "'.";
- SetMode(Mode::NON_MATERIAL);
+ if (!switch_value.empty()) {
+ LOG(ERROR) << "Invalid value='" << switch_value
+ << "' for command line switch '" << switches::kTopChromeMD
+ << "'.";
+ }
+ SetMode(DefaultMode());
}
#endif // !defined(ENABLE_TOPCHROME_MD)
}
diff --git a/chromium/ui/base/resource/material_design/material_design_controller.h b/chromium/ui/base/material_design/material_design_controller.h
index af92f4d62bc..9ef61c0c4e5 100644
--- a/chromium/ui/base/resource/material_design/material_design_controller.h
+++ b/chromium/ui/base/material_design/material_design_controller.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_BASE_RESOURCE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
-#define UI_BASE_RESOURCE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
+#ifndef UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
+#define UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
#include "base/macros.h"
#include "ui/base/ui_base_export.h"
@@ -34,6 +34,9 @@ class UI_BASE_EXPORT MaterialDesignController {
// Returns true if the current mode is a material design variant.
static bool IsModeMaterial();
+ // Returns the per-platform default material design variant.
+ static Mode DefaultMode();
+
private:
friend class test::MaterialDesignControllerTestAPI;
@@ -64,4 +67,4 @@ class UI_BASE_EXPORT MaterialDesignController {
} // namespace ui
-#endif // UI_BASE_RESOURCE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
+#endif // UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
diff --git a/chromium/ui/base/resource/material_design/material_design_controller_unittest.cc b/chromium/ui/base/material_design/material_design_controller_unittest.cc
index cfc76b59493..543cf3d2c8f 100644
--- a/chromium/ui/base/resource/material_design/material_design_controller_unittest.cc
+++ b/chromium/ui/base/material_design/material_design_controller_unittest.cc
@@ -7,7 +7,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/test/material_design_controller_test_api.h"
#include "ui/base/ui_base_switches.h"
@@ -77,33 +77,33 @@ TEST_F(
MaterialDesignController::GetMode());
}
-// Verify command line value "" maps to Mode::NON_MATERIAL when the compile time
+// Verify command line value "" maps to the default mode when the compile time
// flag is defined.
TEST_F(
MaterialDesignControllerTest,
DisabledCommandLineValueMapsToNonMaterialModeWhenCompileTimeFlagEnabled) {
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kTopChromeMD, "");
- EXPECT_EQ(MaterialDesignController::Mode::NON_MATERIAL,
+ EXPECT_EQ(MaterialDesignController::DefaultMode(),
MaterialDesignController::GetMode());
}
-// Verify no command line value maps to Mode::NON_MATERIAL when the compile time
+// Verify the current mode is reported as the default mode when no command line
// flag is defined.
TEST_F(MaterialDesignControllerTest,
NoCommandLineValueMapsToNonMaterialModeWhenCompileTimeFlagEnabled) {
ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kTopChromeMD));
- EXPECT_EQ(MaterialDesignController::Mode::NON_MATERIAL,
+ EXPECT_EQ(MaterialDesignController::DefaultMode(),
MaterialDesignController::GetMode());
}
-// Verify an invalid command line value uses the default NON_MATERIAL mode.
+// Verify an invalid command line value uses the default mode.
TEST_F(MaterialDesignControllerTest, InvalidCommandLineValue) {
const std::string kInvalidValue = "1nvalid-valu3";
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kTopChromeMD, kInvalidValue);
- EXPECT_EQ(MaterialDesignController::Mode::NON_MATERIAL,
+ EXPECT_EQ(MaterialDesignController::DefaultMode(),
MaterialDesignController::GetMode());
}
diff --git a/chromium/ui/base/models/dialog_model.h b/chromium/ui/base/models/dialog_model.h
index 94f85e98e7a..5607a1675b0 100644
--- a/chromium/ui/base/models/dialog_model.h
+++ b/chromium/ui/base/models/dialog_model.h
@@ -18,9 +18,6 @@ class UI_BASE_EXPORT DialogModel {
public:
virtual ~DialogModel();
- // Returns the title of the dialog.
- virtual base::string16 GetDialogTitle() const = 0;
-
// Returns a mask specifying which of the available DialogButtons are visible
// for the dialog. Note: Dialogs with just an OK button are frowned upon.
virtual int GetDialogButtons() const = 0;
diff --git a/chromium/ui/base/models/table_model.cc b/chromium/ui/base/models/table_model.cc
index b8b18ad0a77..d98cdb2a571 100644
--- a/chromium/ui/base/models/table_model.cc
+++ b/chromium/ui/base/models/table_model.cc
@@ -35,6 +35,8 @@ TableColumn::TableColumn(int id, Alignment alignment, int width, float percent)
initial_sort_is_ascending(true) {
}
+TableColumn::TableColumn(const TableColumn& other) = default;
+
// TableModel -----------------------------------------------------------------
// Used for sorting.
diff --git a/chromium/ui/base/models/table_model.h b/chromium/ui/base/models/table_model.h
index 16e68a94f3a..c7172f4f5d1 100644
--- a/chromium/ui/base/models/table_model.h
+++ b/chromium/ui/base/models/table_model.h
@@ -98,6 +98,7 @@ struct UI_BASE_EXPORT TableColumn {
TableColumn();
TableColumn(int id, Alignment alignment, int width, float percent);
+ TableColumn(const TableColumn& other);
// A unique identifier for the column.
int id;
diff --git a/chromium/ui/base/models/tree_node_model.h b/chromium/ui/base/models/tree_node_model.h
index 9606dc8119c..279667b2a40 100644
--- a/chromium/ui/base/models/tree_node_model.h
+++ b/chromium/ui/base/models/tree_node_model.h
@@ -10,12 +10,11 @@
#include <algorithm>
#include <vector>
-#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
+#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "ui/base/models/tree_model.h"
@@ -70,7 +69,9 @@ class TreeNode : public TreeModelNode {
explicit TreeNode(const base::string16& title)
: title_(title), parent_(NULL) {}
- ~TreeNode() override {}
+ ~TreeNode() override {
+ STLDeleteElements(&children_);
+ }
// Adds |node| as a child of this node, at |index|.
virtual void Add(NodeType* node, int index) {
@@ -92,7 +93,7 @@ class TreeNode : public TreeModelNode {
std::find(children_.begin(), children_.end(), node);
DCHECK(i != children_.end());
node->parent_ = NULL;
- children_.weak_erase(i);
+ children_.erase(i);
return node;
}
@@ -100,7 +101,7 @@ class TreeNode : public TreeModelNode {
void RemoveAll() {
for (size_t i = 0; i < children_.size(); ++i)
children_[i]->parent_ = NULL;
- children_.weak_clear();
+ children_.clear();
}
// Removes all existing children without deleting the nodes and adds all nodes
@@ -169,7 +170,7 @@ class TreeNode : public TreeModelNode {
}
protected:
- std::vector<NodeType*>& children() { return children_.get(); }
+ std::vector<NodeType*>& children() { return children_; }
private:
// Title displayed in the tree.
@@ -179,7 +180,7 @@ class TreeNode : public TreeModelNode {
NodeType* parent_;
// This node's children.
- ScopedVector<NodeType> children_;
+ std::vector<NodeType*> children_;
DISALLOW_COPY_AND_ASSIGN(TreeNode);
};
diff --git a/chromium/ui/base/nine_image_painter_factory.cc b/chromium/ui/base/nine_image_painter_factory.cc
index 691e4ae8817..75281a2b06f 100644
--- a/chromium/ui/base/nine_image_painter_factory.cc
+++ b/chromium/ui/base/nine_image_painter_factory.cc
@@ -14,6 +14,7 @@ namespace ui {
namespace {
std::vector<gfx::ImageSkia> ImageIdsToImages(const int image_ids[]) {
+ DCHECK(image_ids);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
std::vector<gfx::ImageSkia> images(9);
for (size_t i = 0; i < 9; ++i) {
diff --git a/chromium/ui/base/resource/data_pack.h b/chromium/ui/base/resource/data_pack.h
index b2d90684c0f..1292203a6bb 100644
--- a/chromium/ui/base/resource/data_pack.h
+++ b/chromium/ui/base/resource/data_pack.h
@@ -20,8 +20,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string_piece.h"
+#include "ui/base/resource/data_pack_export.h"
#include "ui/base/resource/resource_handle.h"
-#include "ui/base/ui_base_export.h"
namespace base {
class FilePath;
@@ -31,7 +31,7 @@ class RefCountedStaticMemory;
namespace ui {
enum ScaleFactor : int;
-class UI_BASE_EXPORT DataPack : public ResourceHandle {
+class UI_DATA_PACK_EXPORT DataPack : public ResourceHandle {
public:
explicit DataPack(ui::ScaleFactor scale_factor);
~DataPack() override;
diff --git a/chromium/ui/base/resource/data_pack_export.h b/chromium/ui/base/resource/data_pack_export.h
new file mode 100644
index 00000000000..88e908d5cbe
--- /dev/null
+++ b/chromium/ui/base/resource/data_pack_export.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_RESOURCE_DATA_PACK_EXPORT_H_
+#define UI_BASE_RESOURCE_DATA_PACK_EXPORT_H_
+
+// Defines UI_DATA_PACK_EXPORT so that functionality implemented by the data
+// pack loading module can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(UI_DATA_PACK_IMPLEMENTATION)
+#define UI_DATA_PACK_EXPORT __declspec(dllexport)
+#else
+#define UI_DATA_PACK_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(UI_DATA_PACK_IMPLEMENTATION)
+#define UI_DATA_PACK_EXPORT __attribute__((visibility("default")))
+#else
+#define UI_DATA_PACK_EXPORT
+#endif
+
+#endif
+
+#else // !defined(COMPONENT_BUILD)
+
+#define UI_DATA_PACK_EXPORT
+
+#endif
+
+#endif // UI_BASE_RESOURCE_DATA_PACK_EXPORT_H_
diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc
index a2aa5824a19..93230b42da4 100644
--- a/chromium/ui/base/resource/resource_bundle.cc
+++ b/chromium/ui/base/resource/resource_bundle.cc
@@ -28,10 +28,11 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/layout.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/data_pack.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
+#include "ui/base/ui_features.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
@@ -62,11 +63,6 @@ namespace ui {
namespace {
-// Font sizes relative to base font.
-const int kSmallFontSizeDelta = -1;
-const int kMediumFontSizeDelta = 3;
-const int kLargeFontSizeDelta = 8;
-
// PNG-related constants.
const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
const size_t kPngChunkMetadataSize = 12; // length, type, crc32
@@ -394,12 +390,14 @@ gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
DCHECK(!data_packs_.empty()) <<
"Missing call to SetResourcesDataDLL?";
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
- ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
+#if defined(OS_CHROMEOS)
+ ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
+#elif defined(OS_WIN)
+ ui::ScaleFactor scale_factor_to_load =
+ gfx::GetDPIScale() > 1.25 ? GetMaxScaleFactor() : ui::SCALE_FACTOR_100P;
#else
- ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
+ ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
#endif
-
// TODO(oshima): Consider reading the image size from png IHDR chunk and
// skip decoding here and remove #ifdef below.
// ResourceBundle::GetSharedInstance() is destroyed after the
@@ -428,10 +426,6 @@ gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
return images_[resource_id];
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
- return GetNativeImageNamed(resource_id, RTL_DISABLED);
-}
-
base::RefCountedStaticMemory* ResourceBundle::LoadDataResourceBytes(
int resource_id) const {
return LoadDataResourceBytesForScale(resource_id, ui::SCALE_FACTOR_NONE);
@@ -539,29 +533,72 @@ base::string16 ResourceBundle::GetLocalizedString(int message_id) {
return msg;
}
-const gfx::FontList& ResourceBundle::GetFontList(FontStyle style) {
- {
- base::AutoLock lock_scope(*images_and_fonts_lock_);
- LoadFontsIfNecessary();
- }
- switch (style) {
- case BoldFont:
- return *bold_font_list_;
+const gfx::FontList& ResourceBundle::GetFontListWithDelta(
+ int size_delta,
+ gfx::Font::FontStyle style) {
+ base::AutoLock lock_scope(*images_and_fonts_lock_);
+
+ typedef std::pair<int, gfx::Font::FontStyle> Key;
+ const Key styled_key(size_delta, style);
+
+ auto found = font_cache_.find(styled_key);
+ if (found != font_cache_.end())
+ return found->second;
+
+ const Key base_key(0, gfx::Font::NORMAL);
+ gfx::FontList& base = font_cache_[base_key];
+ if (styled_key == base_key)
+ return base;
+
+ // Fonts of a given style are derived from the unstyled font of the same size.
+ // Cache the unstyled font by first inserting a default-constructed font list.
+ // Then, derive it for the initial insertion, or use the iterator that points
+ // to the existing entry that the insertion collided with.
+ const Key sized_key(size_delta, gfx::Font::NORMAL);
+ auto sized = font_cache_.insert(std::make_pair(sized_key, gfx::FontList()));
+ if (sized.second)
+ sized.first->second = base.DeriveWithSizeDelta(size_delta);
+ if (styled_key == sized_key)
+ return sized.first->second;
+
+ auto styled = font_cache_.insert(std::make_pair(styled_key, gfx::FontList()));
+ DCHECK(styled.second); // Otherwise font_cache_.find(..) would have found it.
+ styled.first->second = sized.first->second.DeriveWithStyle(
+ sized.first->second.GetFontStyle() | style);
+ return styled.first->second;
+}
+
+const gfx::Font& ResourceBundle::GetFontWithDelta(int size_delta,
+ gfx::Font::FontStyle style) {
+ return GetFontListWithDelta(size_delta, style).GetPrimaryFont();
+}
+
+const gfx::FontList& ResourceBundle::GetFontList(FontStyle legacy_style) {
+ gfx::Font::FontStyle font_style = gfx::Font::NORMAL;
+ if (legacy_style == BoldFont || legacy_style == SmallBoldFont ||
+ legacy_style == MediumBoldFont || legacy_style == LargeBoldFont)
+ font_style = gfx::Font::BOLD;
+
+ int size_delta = 0;
+ switch (legacy_style) {
case SmallFont:
- return *small_font_list_;
- case MediumFont:
- return *medium_font_list_;
case SmallBoldFont:
- return *small_bold_font_list_;
+ size_delta = kSmallFontDelta;
+ break;
+ case MediumFont:
case MediumBoldFont:
- return *medium_bold_font_list_;
+ size_delta = kMediumFontDelta;
+ break;
case LargeFont:
- return *large_font_list_;
case LargeBoldFont:
- return *large_bold_font_list_;
- default:
- return *base_font_list_;
+ size_delta = kLargeFontDelta;
+ break;
+ case BaseFont:
+ case BoldFont:
+ break;
}
+
+ return GetFontListWithDelta(size_delta, font_style);
}
const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
@@ -571,12 +608,11 @@ const gfx::Font& ResourceBundle::GetFont(FontStyle style) {
void ResourceBundle::ReloadFonts() {
base::AutoLock lock_scope(*images_and_fonts_lock_);
InitDefaultFontList();
- base_font_list_.reset();
- LoadFontsIfNecessary();
+ font_cache_.clear();
}
ScaleFactor ResourceBundle::GetMaxScaleFactor() const {
-#if defined(OS_CHROMEOS) || defined(OS_WIN)
+#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX)
return max_scale_factor_;
#else
return GetSupportedScaleFactors().back();
@@ -608,7 +644,7 @@ void ResourceBundle::InitSharedInstance(Delegate* delegate) {
DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
g_shared_instance_ = new ResourceBundle(delegate);
static std::vector<ScaleFactor> supported_scale_factors;
-#if !defined(OS_IOS) && !defined(OS_WIN)
+#if !defined(OS_IOS)
// On platforms other than iOS, 100P is always a supported scale factor.
// For Windows we have a separate case in this function.
supported_scale_factors.push_back(SCALE_FACTOR_100P);
@@ -625,7 +661,7 @@ void ResourceBundle::InitSharedInstance(Delegate* delegate) {
if (closest != SCALE_FACTOR_100P)
supported_scale_factors.push_back(closest);
#elif defined(OS_IOS)
- gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ gfx::Display display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
if (display.device_scale_factor() > 2.0) {
DCHECK_EQ(3.0, display.device_scale_factor());
supported_scale_factors.push_back(SCALE_FACTOR_300P);
@@ -638,22 +674,8 @@ void ResourceBundle::InitSharedInstance(Delegate* delegate) {
#elif defined(OS_MACOSX)
if (base::mac::IsOSLionOrLater())
supported_scale_factors.push_back(SCALE_FACTOR_200P);
-#elif defined(OS_CHROMEOS)
- // TODO(oshima): Include 200P only if the device support 200P
+#elif defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
supported_scale_factors.push_back(SCALE_FACTOR_200P);
-#elif defined(OS_LINUX) && defined(ENABLE_HIDPI)
- supported_scale_factors.push_back(SCALE_FACTOR_200P);
-#elif defined(OS_WIN)
- bool default_to_100P = true;
- // On Windows if the dpi scale is greater than 1.25 on high dpi machines
- // downscaling from 200 percent looks better than scaling up from 100
- // percent.
- if (gfx::GetDPIScale() > 1.25) {
- supported_scale_factors.push_back(SCALE_FACTOR_200P);
- default_to_100P = false;
- }
- if (default_to_100P)
- supported_scale_factors.push_back(SCALE_FACTOR_100P);
#endif
ui::SetSupportedScaleFactors(supported_scale_factors);
}
@@ -749,76 +771,6 @@ void ResourceBundle::InitDefaultFontList() {
#endif
}
-void ResourceBundle::LoadFontsIfNecessary() {
- images_and_fonts_lock_->AssertAcquired();
- if (!base_font_list_.get()) {
- if (delegate_) {
- base_font_list_ = GetFontListFromDelegate(BaseFont);
- bold_font_list_ = GetFontListFromDelegate(BoldFont);
- small_font_list_ = GetFontListFromDelegate(SmallFont);
- small_bold_font_list_ = GetFontListFromDelegate(SmallBoldFont);
- medium_font_list_ = GetFontListFromDelegate(MediumFont);
- medium_bold_font_list_ = GetFontListFromDelegate(MediumBoldFont);
- large_font_list_ = GetFontListFromDelegate(LargeFont);
- large_bold_font_list_ = GetFontListFromDelegate(LargeBoldFont);
- }
-
- if (!base_font_list_.get())
- base_font_list_.reset(new gfx::FontList());
-
- if (!bold_font_list_.get()) {
- bold_font_list_.reset(new gfx::FontList());
- *bold_font_list_ = base_font_list_->DeriveWithStyle(
- base_font_list_->GetFontStyle() | gfx::Font::BOLD);
- }
-
- if (!small_font_list_.get()) {
- small_font_list_.reset(new gfx::FontList());
- *small_font_list_ =
- base_font_list_->DeriveWithSizeDelta(kSmallFontSizeDelta);
- }
-
- if (!small_bold_font_list_.get()) {
- small_bold_font_list_.reset(new gfx::FontList());
- *small_bold_font_list_ = small_font_list_->DeriveWithStyle(
- small_font_list_->GetFontStyle() | gfx::Font::BOLD);
- }
-
- if (!medium_font_list_.get()) {
- medium_font_list_.reset(new gfx::FontList());
- *medium_font_list_ =
- base_font_list_->DeriveWithSizeDelta(kMediumFontSizeDelta);
- }
-
- if (!medium_bold_font_list_.get()) {
- medium_bold_font_list_.reset(new gfx::FontList());
- *medium_bold_font_list_ = medium_font_list_->DeriveWithStyle(
- medium_font_list_->GetFontStyle() | gfx::Font::BOLD);
- }
-
- if (!large_font_list_.get()) {
- large_font_list_.reset(new gfx::FontList());
- *large_font_list_ =
- base_font_list_->DeriveWithSizeDelta(kLargeFontSizeDelta);
- }
-
- if (!large_bold_font_list_.get()) {
- large_bold_font_list_.reset(new gfx::FontList());
- *large_bold_font_list_ = large_font_list_->DeriveWithStyle(
- large_font_list_->GetFontStyle() | gfx::Font::BOLD);
- }
- }
-}
-
-scoped_ptr<gfx::FontList> ResourceBundle::GetFontListFromDelegate(
- FontStyle style) {
- DCHECK(delegate_);
- scoped_ptr<gfx::Font> font = delegate_->GetFont(style);
- if (font.get())
- return make_scoped_ptr(new gfx::FontList(*font));
- return nullptr;
-}
-
bool ResourceBundle::LoadBitmap(const ResourceHandle& data_handle,
int resource_id,
SkBitmap* bitmap,
diff --git a/chromium/ui/base/resource/resource_bundle.h b/chromium/ui/base/resource/resource_bundle.h
index 3e169a469bd..61f2861b1e9 100644
--- a/chromium/ui/base/resource/resource_bundle.h
+++ b/chromium/ui/base/resource/resource_bundle.h
@@ -43,12 +43,16 @@ class ResourceHandle;
// such as theme graphics. Every resource is loaded only once.
class UI_BASE_EXPORT ResourceBundle {
public:
- // An enumeration of the various font styles used throughout Chrome.
- // The following holds true for the font sizes:
- // Small <= SmallBold <= Base <= Bold <= Medium <= MediumBold <= Large.
+ // Legacy font size deltas. Consider these to be magic numbers. New code
+ // should declare their own size delta constant using an identifier that
+ // imparts some semantic meaning.
+ static const int kSmallFontDelta = -1;
+ static const int kMediumFontDelta = 3;
+ static const int kLargeFontDelta = 8;
+
+ // Legacy font style mappings. TODO(tapted): Phase these out in favour of
+ // client code providing their own constant with the desired font size delta.
enum FontStyle {
- // NOTE: depending upon the locale, using one of the *BoldFont below
- // may *not* actually result in a bold font.
SmallFont,
SmallBoldFont,
BaseFont,
@@ -59,13 +63,6 @@ class UI_BASE_EXPORT ResourceBundle {
LargeBoldFont,
};
- enum ImageRTL {
- // Images are flipped in RTL locales.
- RTL_ENABLED,
- // Images are never flipped.
- RTL_DISABLED,
- };
-
enum LoadResources {
LOAD_COMMON_RESOURCES,
DO_NOT_LOAD_COMMON_RESOURCES
@@ -97,7 +94,7 @@ class UI_BASE_EXPORT ResourceBundle {
// Return an image resource or an empty value to attempt retrieval of the
// default resource.
- virtual gfx::Image GetNativeImageNamed(int resource_id, ImageRTL rtl) = 0;
+ virtual gfx::Image GetNativeImageNamed(int resource_id) = 0;
// Return a static memory resource or NULL to attempt retrieval of the
// default resource.
@@ -115,9 +112,6 @@ class UI_BASE_EXPORT ResourceBundle {
// false to attempt retrieval of the default string.
virtual bool GetLocalizedString(int message_id, base::string16* value) = 0;
- // Returns a font or NULL to attempt retrieval of the default resource.
- virtual scoped_ptr<gfx::Font> GetFont(FontStyle style) = 0;
-
protected:
virtual ~Delegate() {}
};
@@ -219,11 +213,6 @@ class UI_BASE_EXPORT ResourceBundle {
// Note that if the same resource has already been loaded in GetImageNamed(),
// gfx::Image will perform a conversion, rather than using the native image
// loading code of ResourceBundle.
- //
- // If |rtl| is RTL_ENABLED then the image is flipped in RTL locales.
- gfx::Image& GetNativeImageNamed(int resource_id, ImageRTL rtl);
-
- // Same as GetNativeImageNamed() except that RTL is not enabled.
gfx::Image& GetNativeImageNamed(int resource_id);
// Loads the raw bytes of a scale independent data resource.
@@ -253,10 +242,19 @@ class UI_BASE_EXPORT ResourceBundle {
// string if the message_id is not found.
base::string16 GetLocalizedString(int message_id);
- // Returns the font list for the specified style.
- const gfx::FontList& GetFontList(FontStyle style);
+ // Returns a font list derived from the platform-specific "Base" font list.
+ // The result is always cached and exists for the lifetime of the process.
+ const gfx::FontList& GetFontListWithDelta(
+ int size_delta,
+ gfx::Font::FontStyle style = gfx::Font::NORMAL);
- // Returns the font for the specified style.
+ // Returns the primary font from the FontList given by GetFontListWithDelta().
+ const gfx::Font& GetFontWithDelta(
+ int size_delta,
+ gfx::Font::FontStyle style = gfx::Font::NORMAL);
+
+ // Deprecated. Returns fonts using hard-coded size deltas implied by |style|.
+ const gfx::FontList& GetFontList(FontStyle style);
const gfx::Font& GetFont(FontStyle style);
// Resets and reloads the cached fonts. This is useful when the fonts of the
@@ -287,6 +285,12 @@ class UI_BASE_EXPORT ResourceBundle {
// Returns SCALE_FACTOR_100P if no resource is loaded.
ScaleFactor GetMaxScaleFactor() const;
+#if defined(OS_MACOSX)
+ // Loads Material Design data packs and makes them the first items in
+ // |data_packs_|.
+ void LoadMaterialDesignResources();
+#endif
+
protected:
// Returns true if |scale_factor| is supported by this platform.
static bool IsScaleFactorSupported(ScaleFactor scale_factor);
@@ -299,10 +303,13 @@ class UI_BASE_EXPORT ResourceBundle {
CountMaterialDesignDataPacksInResourceBundle);
FRIEND_TEST_ALL_PREFIXES(ResourceBundleMacImageTest,
CheckImageFromMaterialDesign);
+ FRIEND_TEST_ALL_PREFIXES(ChromeBrowserMainMacBrowserTest,
+ MDResourceAccess);
friend class ResourceBundleMacImageTest;
friend class ResourceBundleImageTest;
friend class ResourceBundleTest;
+ friend class ChromeBrowserMainMacBrowserTest;
class ResourceBundleImageSource;
friend class ResourceBundleImageSource;
@@ -356,14 +363,6 @@ class UI_BASE_EXPORT ResourceBundle {
// Initializes the font description of default gfx::FontList.
void InitDefaultFontList();
- // Initializes all the gfx::FontList members if they haven't yet been
- // initialized.
- void LoadFontsIfNecessary();
-
- // Returns a FontList or NULL by calling Delegate::GetFont and converting
- // scoped_ptr<gfx::Font> to scoped_ptr<gfx::FontList>.
- scoped_ptr<gfx::FontList> GetFontListFromDelegate(FontStyle style);
-
// Fills the |bitmap| given the data file to look in and the |resource_id|.
// Returns false if the resource does not exist.
//
@@ -430,17 +429,11 @@ class UI_BASE_EXPORT ResourceBundle {
gfx::Image empty_image_;
- // The various font lists used. Cached to avoid repeated GDI
- // creation/destruction.
- scoped_ptr<gfx::FontList> base_font_list_;
- scoped_ptr<gfx::FontList> bold_font_list_;
- scoped_ptr<gfx::FontList> small_font_list_;
- scoped_ptr<gfx::FontList> small_bold_font_list_;
- scoped_ptr<gfx::FontList> medium_font_list_;
- scoped_ptr<gfx::FontList> medium_bold_font_list_;
- scoped_ptr<gfx::FontList> large_font_list_;
- scoped_ptr<gfx::FontList> large_bold_font_list_;
- scoped_ptr<gfx::FontList> web_font_list_;
+ // The various font lists used, as a map from a signed size delta from the
+ // platform base font size, plus style, to the FontList. Cached to avoid
+ // repeated GDI creation/destruction and font derivation.
+ // Must be accessed only while holding |images_and_fonts_lock_|.
+ std::map<std::pair<int, gfx::Font::FontStyle>, gfx::FontList> font_cache_;
base::FilePath overridden_pak_path_;
diff --git a/chromium/ui/base/resource/resource_bundle_android.cc b/chromium/ui/base/resource/resource_bundle_android.cc
index ae731d680cb..e19a8b8301d 100644
--- a/chromium/ui/base/resource/resource_bundle_android.cc
+++ b/chromium/ui/base/resource/resource_bundle_android.cc
@@ -120,9 +120,7 @@ std::string ResourceBundle::LoadLocaleResources(
return app_locale;
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
- // Flipped image is not used on Android.
- DCHECK_EQ(rtl, RTL_DISABLED);
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
return GetImageNamed(resource_id);
}
diff --git a/chromium/ui/base/resource/resource_bundle_auralinux.cc b/chromium/ui/base/resource/resource_bundle_auralinux.cc
index 7365b1df3d1..8989a9e49c4 100644
--- a/chromium/ui/base/resource/resource_bundle_auralinux.cc
+++ b/chromium/ui/base/resource/resource_bundle_auralinux.cc
@@ -20,9 +20,7 @@ void ResourceBundle::LoadCommonResources() {
LoadChromeResources();
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
- // Flipped image is not used on ChromeOS.
- DCHECK_EQ(rtl, RTL_DISABLED);
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
return GetImageNamed(resource_id);
}
diff --git a/chromium/ui/base/resource/resource_bundle_ios.mm b/chromium/ui/base/resource/resource_bundle_ios.mm
index 88cf829c6dd..17f1c79ac07 100644
--- a/chromium/ui/base/resource/resource_bundle_ios.mm
+++ b/chromium/ui/base/resource/resource_bundle_ios.mm
@@ -89,10 +89,7 @@ base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
return locale_file_path;
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
- // Flipped images are not used on iOS.
- DCHECK_EQ(rtl, RTL_DISABLED);
-
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
// Check to see if the image is already in the cache.
{
base::AutoLock lock(*images_and_fonts_lock_);
@@ -104,7 +101,7 @@ gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
gfx::Image image;
if (delegate_)
- image = delegate_->GetNativeImageNamed(resource_id, rtl);
+ image = delegate_->GetNativeImageNamed(resource_id);
if (image.IsEmpty()) {
// Load the raw data from the resource pack at the current supported scale
diff --git a/chromium/ui/base/resource/resource_bundle_mac.mm b/chromium/ui/base/resource/resource_bundle_mac.mm
index 74d82615606..0b8d526c9a6 100644
--- a/chromium/ui/base/resource/resource_bundle_mac.mm
+++ b/chromium/ui/base/resource/resource_bundle_mac.mm
@@ -14,7 +14,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/sys_string_conversions.h"
#include "base/synchronization/lock.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_handle.h"
#include "ui/gfx/image/image.h"
@@ -49,20 +49,6 @@ base::FilePath GetResourcesPakFilePath(NSString* name, NSString* mac_locale) {
} // namespace
void ResourceBundle::LoadCommonResources() {
- // The material design data packs contain some of the same asset IDs as in
- // the non-material design data packs. Add these to the ResourceBundle
- // first so that they are searched first when a request for an asset is
- // made.
- if (MaterialDesignController::IsModeMaterial()) {
- AddMaterialDesignDataPackFromPath(
- GetResourcesPakFilePath(@"chrome_material_100_percent", nil),
- SCALE_FACTOR_100P);
-
- AddOptionalMaterialDesignDataPackFromPath(
- GetResourcesPakFilePath(@"chrome_material_200_percent", nil),
- SCALE_FACTOR_200P);
- }
-
AddDataPackFromPath(GetResourcesPakFilePath(@"chrome_100_percent",
nil), SCALE_FACTOR_100P);
@@ -74,6 +60,40 @@ void ResourceBundle::LoadCommonResources() {
}
}
+void ResourceBundle::LoadMaterialDesignResources() {
+ if (!MaterialDesignController::IsModeMaterial()) {
+ return;
+ }
+
+ // The Material Design data packs contain some of the same asset IDs as in
+ // the non-Material Design data packs. Set aside the current packs and add the
+ // Material Design packs so that they are searched first when a request for an
+ // asset is made. The Material Design packs cannot be loaded in
+ // LoadCommonResources() because the MaterialDesignController is not always
+ // initialized at the time it is called.
+ // TODO(shrike) - remove this method and restore loading of Material Design
+ // packs to LoadCommonResources() when the MaterialDesignController goes away.
+ std::vector<scoped_ptr<ResourceHandle>> tmp_packs;
+ for (auto it = data_packs_.begin(); it != data_packs_.end(); ++it) {
+ scoped_ptr<ResourceHandle> next_pack(*it);
+ tmp_packs.push_back(std::move(next_pack));
+ }
+ data_packs_.weak_clear();
+
+ AddMaterialDesignDataPackFromPath(
+ GetResourcesPakFilePath(@"chrome_material_100_percent", nil),
+ SCALE_FACTOR_100P);
+
+ AddOptionalMaterialDesignDataPackFromPath(
+ GetResourcesPakFilePath(@"chrome_material_200_percent", nil),
+ SCALE_FACTOR_200P);
+
+ // Add back the non-Material Design packs so that they serve as a fallback.
+ for (auto it = tmp_packs.begin(); it != tmp_packs.end(); ++it) {
+ data_packs_.push_back(std::move(*it));
+ }
+}
+
base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
bool test_file_exists) {
NSString* mac_locale = base::SysUTF8ToNSString(app_locale);
@@ -104,10 +124,7 @@ base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
return locale_file_path;
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
- // Flipped images are not used on Mac.
- DCHECK_EQ(rtl, RTL_DISABLED);
-
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
// Check to see if the image is already in the cache.
{
base::AutoLock lock(*images_and_fonts_lock_);
@@ -124,29 +141,45 @@ gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
gfx::Image image;
if (delegate_)
- image = delegate_->GetNativeImageNamed(resource_id, rtl);
-
- bool found_in_a_material_design_pack = false;
+ image = delegate_->GetNativeImageNamed(resource_id);
if (image.IsEmpty()) {
base::scoped_nsobject<NSImage> ns_image;
+ // Material Design packs are meant to override the standard packs, so
+ // search for the image in those packs first.
for (size_t i = 0; i < data_packs_.size(); ++i) {
+ if (!data_packs_[i]->HasOnlyMaterialDesignAssets())
+ continue;
scoped_refptr<base::RefCountedStaticMemory> data(
data_packs_[i]->GetStaticMemory(resource_id));
if (!data.get())
continue;
- // This loop adds the image resource from each available pack, if it's
- // present. When Material Design packs are available, however, their
- // images are meant to override the same image in the standard packs. The
- // Material Design packs exist at the start of the data_packs_ vector,
- // so make a note that the image was pulled from a Material Design pack,
- // and ignore the same image in the standard packs.
- if (found_in_a_material_design_pack) {
- break;
+ base::scoped_nsobject<NSData> ns_data(
+ [[NSData alloc] initWithBytes:data->front() length:data->size()]);
+ if (!ns_image.get()) {
+ ns_image.reset([[NSImage alloc] initWithData:ns_data]);
+ } else {
+ NSImageRep* image_rep = [NSBitmapImageRep imageRepWithData:ns_data];
+ if (image_rep)
+ [ns_image addRepresentation:image_rep];
}
- found_in_a_material_design_pack =
- data_packs_[i]->HasOnlyMaterialDesignAssets();
+ }
+
+ if (ns_image.get()) {
+ image = gfx::Image(ns_image.release());
+ }
+ }
+
+ if (image.IsEmpty()) {
+ base::scoped_nsobject<NSImage> ns_image;
+ for (size_t i = 0; i < data_packs_.size(); ++i) {
+ if (data_packs_[i]->HasOnlyMaterialDesignAssets())
+ continue;
+ scoped_refptr<base::RefCountedStaticMemory> data(
+ data_packs_[i]->GetStaticMemory(resource_id));
+ if (!data.get())
+ continue;
base::scoped_nsobject<NSData> ns_data(
[[NSData alloc] initWithBytes:data->front() length:data->size()]);
diff --git a/chromium/ui/base/resource/resource_bundle_unittest.cc b/chromium/ui/base/resource/resource_bundle_unittest.cc
index eac9ef37306..0ada42e28be 100644
--- a/chromium/ui/base/resource/resource_bundle_unittest.cc
+++ b/chromium/ui/base/resource/resource_bundle_unittest.cc
@@ -72,9 +72,7 @@ class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate {
MOCK_METHOD2(GetPathForLocalePack, base::FilePath(
const base::FilePath& pack_path, const std::string& locale));
MOCK_METHOD1(GetImageNamed, gfx::Image(int resource_id));
- MOCK_METHOD2(GetNativeImageNamed,
- gfx::Image(int resource_id,
- ui::ResourceBundle::ImageRTL rtl));
+ MOCK_METHOD1(GetNativeImageNamed, gfx::Image(int resource_id));
MOCK_METHOD2(LoadDataResourceBytes,
base::RefCountedStaticMemory*(int resource_id,
ui::ScaleFactor scale_factor));
@@ -93,11 +91,6 @@ class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate {
*value = GetLocalizedStringMock(message_id);
return true;
}
- MOCK_METHOD1(GetFontMock,
- gfx::Font*(ui::ResourceBundle::FontStyle style));
- scoped_ptr<gfx::Font> GetFont(ui::ResourceBundle::FontStyle style) override {
- return make_scoped_ptr(GetFontMock(style));
- }
};
// Returns |bitmap_data| with |custom_chunk| inserted after the IHDR chunk.
@@ -250,7 +243,7 @@ TEST_F(ResourceBundleTest, DelegateGetNativeImageNamed) {
.Times(Between(0, 1))
.WillOnce(Return(empty_image));
EXPECT_CALL(delegate,
- GetNativeImageNamed(resource_id, ui::ResourceBundle::RTL_DISABLED))
+ GetNativeImageNamed(resource_id))
.Times(Between(0, 1))
.WillOnce(Return(empty_image));
@@ -344,59 +337,6 @@ TEST_F(ResourceBundleTest, DelegateGetLocalizedStringWithOverride) {
EXPECT_EQ(delegate_data, result);
}
-#if (defined(USE_OZONE) && !defined(USE_PANGO)) || defined(OS_ANDROID)
-#define MAYBE_DelegateGetFontList DISABLED_DelegateGetFontList
-#else
-#define MAYBE_DelegateGetFontList DelegateGetFontList
-#endif
-
-TEST_F(ResourceBundleTest, MAYBE_DelegateGetFontList) {
- MockResourceBundleDelegate delegate;
- ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
-
- // Should be called once for each font type. When we return NULL the default
- // font will be created.
- gfx::Font* test_font = NULL;
- EXPECT_CALL(delegate, GetFontMock(_))
- .Times(8)
- .WillRepeatedly(Return(test_font));
-
- const gfx::FontList* font_list =
- &resource_bundle->GetFontList(ui::ResourceBundle::BaseFont);
- EXPECT_TRUE(font_list);
-
- const gfx::Font* font =
- &resource_bundle->GetFont(ui::ResourceBundle::BaseFont);
- EXPECT_TRUE(font);
-}
-
-#if defined(OS_CHROMEOS) && defined(USE_PANGO)
-TEST_F(ResourceBundleTest, FontListReload) {
- MockResourceBundleDelegate delegate;
- ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
-
- // Should be called once for each font type. When we return NULL the default
- // font will be created.
- gfx::Font* test_font = nullptr;
- EXPECT_CALL(delegate, GetFontMock(_))
- .Times(16)
- .WillRepeatedly(Return(test_font));
-
- EXPECT_CALL(delegate, GetLocalizedStringMock(IDS_UI_FONT_FAMILY_CROS))
- .WillOnce(Return(base::UTF8ToUTF16("test font, 12px")));
- resource_bundle->ReloadFonts();
- // Don't test the font name; it'll get mapped to something else by Fontconfig.
- EXPECT_EQ(12, gfx::FontList().GetPrimaryFont().GetFontSize());
- EXPECT_EQ(gfx::Font::NORMAL, gfx::FontList().GetPrimaryFont().GetStyle());
-
- EXPECT_CALL(delegate, GetLocalizedStringMock(IDS_UI_FONT_FAMILY_CROS))
- .WillOnce(Return(base::UTF8ToUTF16("test font 2, Bold 10px")));
- resource_bundle->ReloadFonts();
- EXPECT_EQ(10, gfx::FontList().GetPrimaryFont().GetFontSize());
- EXPECT_EQ(gfx::Font::BOLD, gfx::FontList().GetPrimaryFont().GetStyle());
-}
-#endif
-
TEST_F(ResourceBundleTest, LocaleDataPakExists) {
ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
diff --git a/chromium/ui/base/resource/resource_bundle_win.cc b/chromium/ui/base/resource/resource_bundle_win.cc
index 6792870be96..4546b66fcd7 100644
--- a/chromium/ui/base/resource/resource_bundle_win.cc
+++ b/chromium/ui/base/resource/resource_bundle_win.cc
@@ -37,10 +37,7 @@ void ResourceBundle::LoadCommonResources() {
LoadChromeResources();
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl) {
- // Flipped image is not used on Windows.
- DCHECK_EQ(rtl, RTL_DISABLED);
-
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) {
// Windows only uses SkBitmap for gfx::Image, so this is the same as
// GetImageNamed.
return GetImageNamed(resource_id);
diff --git a/chromium/ui/base/resource/resource_handle.h b/chromium/ui/base/resource/resource_handle.h
index 138c739134c..9632c536713 100644
--- a/chromium/ui/base/resource/resource_handle.h
+++ b/chromium/ui/base/resource/resource_handle.h
@@ -8,8 +8,8 @@
#include <stdint.h>
#include "base/strings/string_piece.h"
-#include "ui/base/layout.h"
-#include "ui/base/ui_base_export.h"
+#include "ui/base/resource/data_pack_export.h"
+#include "ui/base/resource/scale_factor.h"
namespace base {
class RefCountedStaticMemory;
@@ -17,7 +17,7 @@ class RefCountedStaticMemory;
namespace ui {
-class UI_BASE_EXPORT ResourceHandle {
+class UI_DATA_PACK_EXPORT ResourceHandle {
public:
// What type of encoding the text resources use.
enum TextEncodingType {
diff --git a/chromium/ui/base/resource/scale_factor.cc b/chromium/ui/base/resource/scale_factor.cc
new file mode 100644
index 00000000000..dceffaec424
--- /dev/null
+++ b/chromium/ui/base/resource/scale_factor.cc
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/resource/scale_factor.h"
+
+#include "base/macros.h"
+
+namespace ui {
+
+namespace {
+
+const float kScaleFactorScales[] = {1.0f, 1.0f, 1.25f, 1.33f, 1.4f, 1.5f, 1.8f,
+ 2.0f, 2.5f, 3.0f};
+static_assert(NUM_SCALE_FACTORS == arraysize(kScaleFactorScales),
+ "kScaleFactorScales has incorrect size");
+
+} // namespace
+
+float GetScaleForScaleFactor(ScaleFactor scale_factor) {
+ return kScaleFactorScales[scale_factor];
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/resource/scale_factor.h b/chromium/ui/base/resource/scale_factor.h
new file mode 100644
index 00000000000..06205851715
--- /dev/null
+++ b/chromium/ui/base/resource/scale_factor.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_RESOURCE_SCALE_FACTOR_H_
+#define UI_BASE_RESOURCE_SCALE_FACTOR_H_
+
+#include "ui/base/resource/data_pack_export.h"
+
+namespace ui {
+
+// Supported UI scale factors for the platform. This is used as an index
+// into the array |kScaleFactorScales| which maps the enum value to a float.
+// SCALE_FACTOR_NONE is used for density independent resources such as
+// string, html/js files or an image that can be used for any scale factors
+// (such as wallpapers).
+enum ScaleFactor : int {
+ SCALE_FACTOR_NONE = 0,
+ SCALE_FACTOR_100P,
+ SCALE_FACTOR_125P,
+ SCALE_FACTOR_133P,
+ SCALE_FACTOR_140P,
+ SCALE_FACTOR_150P,
+ SCALE_FACTOR_180P,
+ SCALE_FACTOR_200P,
+ SCALE_FACTOR_250P,
+ SCALE_FACTOR_300P,
+
+ NUM_SCALE_FACTORS // This always appears last.
+};
+
+// Returns the image scale for the scale factor passed in.
+UI_DATA_PACK_EXPORT float GetScaleForScaleFactor(ScaleFactor scale_factor);
+
+} // namespace ui
+
+#endif // UI_BASE_RESOURCE_SCALE_FACTOR_H_
diff --git a/chromium/ui/base/resource/scale_factor_unittest.cc b/chromium/ui/base/resource/scale_factor_unittest.cc
new file mode 100644
index 00000000000..52bf39b2ab8
--- /dev/null
+++ b/chromium/ui/base/resource/scale_factor_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/resource/scale_factor.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+TEST(ScaleFactorTest, GetScaleFactorScale) {
+ EXPECT_FLOAT_EQ(1.0f, GetScaleForScaleFactor(SCALE_FACTOR_100P));
+ EXPECT_FLOAT_EQ(1.25f, GetScaleForScaleFactor(SCALE_FACTOR_125P));
+ EXPECT_FLOAT_EQ(1.33f, GetScaleForScaleFactor(SCALE_FACTOR_133P));
+ EXPECT_FLOAT_EQ(1.4f, GetScaleForScaleFactor(SCALE_FACTOR_140P));
+ EXPECT_FLOAT_EQ(1.5f, GetScaleForScaleFactor(SCALE_FACTOR_150P));
+ EXPECT_FLOAT_EQ(1.8f, GetScaleForScaleFactor(SCALE_FACTOR_180P));
+ EXPECT_FLOAT_EQ(2.0f, GetScaleForScaleFactor(SCALE_FACTOR_200P));
+ EXPECT_FLOAT_EQ(2.5f, GetScaleForScaleFactor(SCALE_FACTOR_250P));
+ EXPECT_FLOAT_EQ(3.0f, GetScaleForScaleFactor(SCALE_FACTOR_300P));
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/template_expressions.cc b/chromium/ui/base/template_expressions.cc
index 1d63e0c34ea..10aaf4fecf5 100644
--- a/chromium/ui/base/template_expressions.cc
+++ b/chromium/ui/base/template_expressions.cc
@@ -7,37 +7,69 @@
#include <stddef.h>
#include "base/logging.h"
+#include "net/base/escape.h"
+
+namespace {
+const char kLeader[] = "$i18n";
+const size_t kLeaderSize = arraysize(kLeader) - 1;
+const char kKeyOpen = '{';
+const char kKeyClose = '}';
+} // namespace
namespace ui {
std::string ReplaceTemplateExpressions(
- base::StringPiece format_string,
- const std::map<base::StringPiece, std::string>& substitutions) {
+ base::StringPiece source,
+ const TemplateReplacements& replacements) {
std::string formatted;
const size_t kValueLengthGuess = 16;
- formatted.reserve(format_string.length() +
- substitutions.size() * kValueLengthGuess);
- base::StringPiece::const_iterator i = format_string.begin();
- while (i < format_string.end()) {
- if (*i == '$' && i + 2 < format_string.end() && i[1] == '{' &&
- i[2] != '}') {
- size_t key_start = i + strlen("${") - format_string.begin();
- size_t key_length = format_string.find('}', key_start);
- if (key_length == base::StringPiece::npos)
- NOTREACHED() << "TemplateExpression missing ending brace '}'";
- key_length -= key_start;
- base::StringPiece key(format_string.begin() + key_start, key_length);
- const auto& replacement = substitutions.find(key);
- if (replacement != substitutions.end()) {
- formatted.append(replacement->second);
- i += strlen("${") + key_length + strlen("}");
- continue;
- } else {
- NOTREACHED() << "TemplateExpression key not found: " << key;
- }
+ formatted.reserve(source.length() + replacements.size() * kValueLengthGuess);
+ // Two position markers are used as cursors through the |source|.
+ // The |current_pos| will follow behind |next_pos|.
+ size_t current_pos = 0;
+ while (true) {
+ size_t next_pos = source.find(kLeader, current_pos);
+
+ if (next_pos == std::string::npos) {
+ source.substr(current_pos).AppendToString(&formatted);
+ break;
}
- formatted.push_back(*i);
- ++i;
+
+ source.substr(current_pos, next_pos - current_pos)
+ .AppendToString(&formatted);
+ current_pos = next_pos + kLeaderSize;
+
+ size_t context_end = source.find(kKeyOpen, current_pos);
+ CHECK_NE(context_end, std::string::npos);
+ std::string context;
+ source.substr(current_pos, context_end - current_pos)
+ .AppendToString(&context);
+ current_pos = context_end + sizeof(kKeyOpen);
+
+ size_t key_end = source.find(kKeyClose, current_pos);
+ CHECK_NE(key_end, std::string::npos);
+
+ std::string key =
+ source.substr(current_pos, key_end - current_pos).as_string();
+ CHECK(!key.empty());
+
+ TemplateReplacements::const_iterator value = replacements.find(key);
+ CHECK(value != replacements.end()) << "$i18n replacement key \"" << key
+ << "\" not found";
+
+ std::string replacement = value->second;
+ if (context.empty()) {
+ // Make the replacement HTML safe.
+ replacement = net::EscapeForHTML(replacement);
+ } else if (context == "Raw") {
+ // Pass the replacement through unchanged.
+ } else {
+ CHECK(false) << "Unknown context " << context;
+ }
+
+ formatted.append(replacement);
+
+ current_pos = key_end + sizeof(kKeyClose);
}
return formatted;
}
diff --git a/chromium/ui/base/template_expressions.h b/chromium/ui/base/template_expressions.h
index ff14ee1b719..2531d96af20 100644
--- a/chromium/ui/base/template_expressions.h
+++ b/chromium/ui/base/template_expressions.h
@@ -16,12 +16,15 @@
namespace ui {
-// Replace ${foo} in the format string with the value for the foo key in
+// Map of strings for template replacement in |ReplaceTemplateExpressions|.
+typedef std::map<const std::string, std::string> TemplateReplacements;
+
+// Replace $i18n*{foo} in the format string with the value for the foo key in
// |subst|. If the key is not found in the |substitutions| that item will
// be unaltered.
UI_BASE_EXPORT std::string ReplaceTemplateExpressions(
- base::StringPiece format_string,
- const std::map<base::StringPiece, std::string>& substitutions);
+ base::StringPiece source,
+ const TemplateReplacements& replacements);
} // namespace ui
diff --git a/chromium/ui/base/template_expressions_unittest.cc b/chromium/ui/base/template_expressions_unittest.cc
index b56a5e7424c..c219d0c7db9 100644
--- a/chromium/ui/base/template_expressions_unittest.cc
+++ b/chromium/ui/base/template_expressions_unittest.cc
@@ -9,27 +9,49 @@
namespace ui {
TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsPieces) {
- std::map<base::StringPiece, std::string> substitutions;
+ TemplateReplacements substitutions;
substitutions["test"] = "word";
substitutions["5"] = "number";
- EXPECT_EQ("${}", ReplaceTemplateExpressions("${}", substitutions));
EXPECT_EQ("", ReplaceTemplateExpressions("", substitutions));
- EXPECT_EQ("word", ReplaceTemplateExpressions("${test}", substitutions));
- EXPECT_EQ("number ", ReplaceTemplateExpressions("${5} ", substitutions));
- EXPECT_EQ(
- "multiple: word, number.",
- ReplaceTemplateExpressions("multiple: ${test}, ${5}.", substitutions));
+ EXPECT_EQ("word", ReplaceTemplateExpressions("$i18n{test}", substitutions));
+ EXPECT_EQ("number ", ReplaceTemplateExpressions("$i18n{5} ", substitutions));
+ EXPECT_EQ("multiple: word, number.",
+ ReplaceTemplateExpressions("multiple: $i18n{test}, $i18n{5}.",
+ substitutions));
}
TEST(TemplateExpressionsTest,
ReplaceTemplateExpressionsConsecutiveDollarSignsPieces) {
- std::map<base::StringPiece, std::string> substitutions;
+ TemplateReplacements substitutions;
substitutions["a"] = "x";
EXPECT_EQ("$ $$ $$$", ReplaceTemplateExpressions("$ $$ $$$", substitutions));
- EXPECT_EQ("$x", ReplaceTemplateExpressions("$${a}", substitutions));
- EXPECT_EQ("$$x", ReplaceTemplateExpressions("$$${a}", substitutions));
- EXPECT_EQ("$12", ReplaceTemplateExpressions("$12", substitutions));
+ EXPECT_EQ("$x", ReplaceTemplateExpressions("$$i18n{a}", substitutions));
+ EXPECT_EQ("$$x", ReplaceTemplateExpressions("$$$i18n{a}", substitutions));
+ EXPECT_EQ("$i1812", ReplaceTemplateExpressions("$i1812", substitutions));
+}
+
+TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsEscaping) {
+ static TemplateReplacements substitutions;
+ substitutions["punctuationSample"] = "a\"b'c<d>e&f";
+ substitutions["htmlSample"] = "<div>hello</div>";
+ EXPECT_EQ(
+ "a&quot;b&#39;c&lt;d&gt;e&amp;f",
+ ReplaceTemplateExpressions("$i18n{punctuationSample}", substitutions));
+ EXPECT_EQ("&lt;div&gt;hello&lt;/div&gt;",
+ ReplaceTemplateExpressions("$i18n{htmlSample}", substitutions));
+ EXPECT_EQ(
+ "multiple: &lt;div&gt;hello&lt;/div&gt;, a&quot;b&#39;c&lt;d&gt;e&amp;f.",
+ ReplaceTemplateExpressions(
+ "multiple: $i18n{htmlSample}, $i18n{punctuationSample}.",
+ substitutions));
+}
+
+TEST(TemplateExpressionsTest, ReplaceTemplateExpressionsRaw) {
+ static TemplateReplacements substitutions;
+ substitutions["rawSample"] = "<a href=\"example.com\">hello</a>";
+ EXPECT_EQ("<a href=\"example.com\">hello</a>",
+ ReplaceTemplateExpressions("$i18nRaw{rawSample}", substitutions));
}
} // namespace ui
diff --git a/chromium/ui/base/theme_provider.h b/chromium/ui/base/theme_provider.h
index fa86e43ede0..ce98246b051 100644
--- a/chromium/ui/base/theme_provider.h
+++ b/chromium/ui/base/theme_provider.h
@@ -80,9 +80,15 @@ class UI_BASE_EXPORT ThemeProvider {
// ThemeProvider, but it's used in many places on OSX.
virtual bool UsingSystemTheme() const = 0;
+ // Returns whether or not theme is in Incognito mode.
+ virtual bool InIncognitoMode() const = 0;
+
// Gets the NSImage with the specified |id|.
virtual NSImage* GetNSImageNamed(int id) const = 0;
+ // Returns true if the theme has defined a custom color for color |id|.
+ virtual bool HasCustomColor(int id) const = 0;
+
// Gets the NSImage that GetNSImageNamed (above) would return, but returns it
// as a pattern color.
virtual NSColor* GetNSImageColorNamed(int id) const = 0;
diff --git a/chromium/ui/base/ui_base.gyp b/chromium/ui/base/ui_base.gyp
index 565faed3fe6..1eda3ca1e3f 100644
--- a/chromium/ui/base/ui_base.gyp
+++ b/chromium/ui/base/ui_base.gyp
@@ -8,10 +8,56 @@
},
'targets': [
{
+ # GN version: //ui/base:ui_data_pack
+ # As part of building Chrome on iOS, it is necessary to run a tool on
+ # the host to load datapack and generate output in a format defined
+ # by the platform (this is to support notifications).
+ #
+ # Introduce a standalone target that build on both 'host' and 'target'
+ # toolset that just build the support to load datapack. The dependency
+ # should be kept minimal to have to build too many targets with multiple
+ # toolsets.
+ 'target_name': 'ui_data_pack',
+ 'toolsets': ['host', 'target'],
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../base/base.gyp:base',
+ ],
+ 'sources': [
+ 'resource/data_pack.cc',
+ 'resource/data_pack.h',
+ 'resource/data_pack_export.h',
+ 'resource/resource_handle.h',
+ 'resource/scale_factor.cc',
+ 'resource/scale_factor.h',
+ ],
+ 'defines': [
+ 'UI_DATA_PACK_IMPLEMENTATION',
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ # TODO(jschuh): C4267: http://crbug.com/167187 size_t -> int
+ 'msvs_disabled_warnings': [ 4267 ],
+ }],
+ ],
+ },
+ { # GN version: //ui/base:ui_features
+ 'target_name': 'ui_features',
+ 'includes': [ '../../build/buildflag_header.gypi' ],
+ 'variables': {
+ 'buildflag_header_path': 'ui/base/ui_features.h',
+ 'buildflag_flags': [
+ 'ENABLE_HIDPI=<(enable_hidpi)',
+ ],
+ },
+ },
+ {
# GN version: //ui/base
'target_name': 'ui_base',
'type': '<(component)',
'dependencies': [
+ 'ui_data_pack',
+ 'ui_features',
'../../base/base.gyp:base',
'../../base/base.gyp:base_i18n',
'../../base/base.gyp:base_static',
@@ -66,6 +112,8 @@
'clipboard/clipboard_mac.h',
'clipboard/clipboard_mac.mm',
'clipboard/clipboard_types.h',
+ 'clipboard/clipboard_util_mac.h',
+ 'clipboard/clipboard_util_mac.mm',
'clipboard/clipboard_util_win.cc',
'clipboard/clipboard_util_win.h',
'clipboard/clipboard_win.cc',
@@ -163,6 +211,7 @@
'default_theme_provider.cc',
'default_theme_provider.h',
'default_theme_provider_mac.mm',
+ 'default_style.h',
'device_form_factor.h',
'device_form_factor_android.cc',
'device_form_factor_android.h',
@@ -230,6 +279,8 @@
'layout.cc',
'layout.h',
'layout_mac.mm',
+ 'material_design/material_design_controller.cc',
+ 'material_design/material_design_controller.h',
'models/button_menu_item_model.cc',
'models/button_menu_item_model.h',
'models/combobox_model.cc',
@@ -260,10 +311,6 @@
'nine_image_painter_factory.h',
'page_transition_types.cc',
'page_transition_types.h',
- 'resource/data_pack.cc',
- 'resource/data_pack.h',
- 'resource/material_design/material_design_controller.cc',
- 'resource/material_design/material_design_controller.h',
'resource/resource_bundle.cc',
'resource/resource_bundle.h',
'resource/resource_bundle_android.cc',
@@ -274,7 +321,6 @@
'resource/resource_bundle_win.h',
'resource/resource_data_dll_win.cc',
'resource/resource_data_dll_win.h',
- 'resource/resource_handle.h',
'template_expressions.cc',
'template_expressions.h',
'text/bytes_formatting.cc',
@@ -373,6 +419,7 @@
['include', '(^|/)ios/'],
['include', '^l10n/'],
['include', '^layout'],
+ ['include', '^material_design/'],
['include', '^page_transition_type'],
['include', '^resource/'],
['include', 'template_expressions.cc'],
@@ -417,6 +464,7 @@
['use_ozone==1', {
'dependencies': [
'../events/devices/events_devices.gyp:events_devices',
+ '../events/ozone/events_ozone.gyp:events_ozone_evdev',
'../events/ozone/events_ozone.gyp:events_ozone_layout',
'../ozone/ozone.gyp:ozone_base',
],
@@ -651,6 +699,7 @@
'target_name': 'ui_base_test_support',
'type': 'static_library',
'dependencies': [
+ 'ui_data_pack',
'../../base/base.gyp:base',
'../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
@@ -679,7 +728,8 @@
],
'conditions': [
['OS!="ios"', {
- 'dependecies': [
+ 'dependencies': [
+ '../events/events.gyp:events',
'ime/ui_base_ime.gyp:ui_base_ime',
],
'sources': [
@@ -693,6 +743,8 @@
'test/scoped_fake_nswindow_focus.mm',
'test/scoped_fake_nswindow_fullscreen.h',
'test/scoped_fake_nswindow_fullscreen.mm',
+ 'test/scoped_preferred_scroller_style_mac.h',
+ 'test/scoped_preferred_scroller_style_mac.mm',
'test/windowed_nsnotification_observer.h',
'test/windowed_nsnotification_observer.mm',
],
diff --git a/chromium/ui/base/ui_base_switches.cc b/chromium/ui/base/ui_base_switches.cc
index 76609e1f4a4..7ec3c6bf649 100644
--- a/chromium/ui/base/ui_base_switches.cc
+++ b/chromium/ui/base/ui_base_switches.cc
@@ -79,11 +79,7 @@ const char kTopChromeMDMaterial[] = "material";
const char kTopChromeMDMaterialHybrid[] = "material-hybrid";
// Classic, non-material, mode for the |kTopChromeMD| switch.
-const char kTopChromeMDNonMaterial[] = "";
+const char kTopChromeMDNonMaterial[] = "non-material";
#endif // defined(ENABLE_TOPCHROME_MD)
-// On Windows only: requests that Chrome connect to the running Metro viewer
-// process.
-const char kViewerConnect[] = "connect-to-metro-viewer";
-
} // namespace switches
diff --git a/chromium/ui/base/ui_base_switches.h b/chromium/ui/base/ui_base_switches.h
index e0c5849e147..5c4f8a91076 100644
--- a/chromium/ui/base/ui_base_switches.h
+++ b/chromium/ui/base/ui_base_switches.h
@@ -44,8 +44,6 @@ UI_BASE_EXPORT extern const char kTopChromeMDMaterialHybrid[];
UI_BASE_EXPORT extern const char kTopChromeMDNonMaterial[];
#endif // defined(ENABLE_TOPCHROME_MD)
-UI_BASE_EXPORT extern const char kViewerConnect[];
-
} // namespace switches
#endif // UI_BASE_UI_BASE_SWITCHES_H_
diff --git a/chromium/ui/base/ui_base_tests.gyp b/chromium/ui/base/ui_base_tests.gyp
index 483b5ae6dec..bf2027a929a 100644
--- a/chromium/ui/base/ui_base_tests.gyp
+++ b/chromium/ui/base/ui_base_tests.gyp
@@ -28,12 +28,14 @@
'../strings/ui_strings.gyp:ui_strings',
'ime/ui_base_ime.gyp:ui_base_ime',
'ui_base.gyp:ui_base',
+ 'ui_base.gyp:ui_data_pack',
'ui_base.gyp:ui_base_test_support',
],
# iOS uses a small subset of ui. common_sources are the only files that
# are built on iOS.
'common_sources' : [
# Note: file list duplicated in GN build.
+ 'clipboard/clipboard_util_mac_unittest.mm',
'ios/cru_context_menu_controller_unittest.mm',
'l10n/l10n_util_mac_unittest.mm',
'l10n/l10n_util_unittest.cc',
@@ -43,8 +45,9 @@
'models/tree_node_iterator_unittest.cc',
'resource/data_pack_literal.cc',
'resource/data_pack_unittest.cc',
- 'resource/resource_bundle_unittest.cc',
'resource/resource_bundle_mac_unittest.mm',
+ 'resource/resource_bundle_unittest.cc',
+ 'resource/scale_factor_unittest.cc',
'template_expressions_unittest.cc',
'test/run_all_unittests.cc',
],
@@ -72,21 +75,20 @@
'cocoa/tracking_area_unittest.mm',
'dragdrop/os_exchange_data_provider_aurax11_unittest.cc',
'ime/candidate_window_unittest.cc',
- 'ime/composition_text_unittest.cc',
'ime/chromeos/character_composer_unittest.cc',
+ 'ime/composition_text_unittest.cc',
'ime/composition_text_util_pango_unittest.cc',
'ime/input_method_base_unittest.cc',
'ime/input_method_chromeos_unittest.cc',
- 'ime/remote_input_method_win_unittest.cc',
'ime/win/imm32_manager_unittest.cc',
'ime/win/tsf_input_scope_unittest.cc',
+ 'material_design/material_design_controller_unittest.cc',
'models/list_model_unittest.cc',
'models/list_selection_model_unittest.cc',
'models/tree_node_model_unittest.cc',
- 'resource/material_design/material_design_controller_unittest.cc',
'test/data/resource.h',
- 'test/test_clipboard_unittest.cc',
'test/scoped_fake_nswindow_fullscreen_unittest.mm',
+ 'test/test_clipboard_unittest.cc',
'text/bytes_formatting_unittest.cc',
'touch/selection_bound_unittest.cc',
'user_activity/user_activity_detector_unittest.cc',
@@ -166,13 +168,6 @@
'dependencies': [
'../../build/linux/system.gyp:pangocairo',
],
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
}],
['use_x11==1', {
'dependencies': [
diff --git a/chromium/ui/base/ui_base_types.h b/chromium/ui/base/ui_base_types.h
index 4ed9f25cfd5..4d29bb30d8c 100644
--- a/chromium/ui/base/ui_base_types.h
+++ b/chromium/ui/base/ui_base_types.h
@@ -47,7 +47,9 @@ enum MenuSourceType {
MENU_SOURCE_KEYBOARD = 2,
MENU_SOURCE_TOUCH = 3,
MENU_SOURCE_TOUCH_EDIT_MENU = 4,
- MENU_SOURCE_TYPE_LAST = MENU_SOURCE_TOUCH_EDIT_MENU
+ MENU_SOURCE_LONG_PRESS = 5,
+ MENU_SOURCE_LONG_TAP = 6,
+ MENU_SOURCE_TYPE_LAST = MENU_SOURCE_LONG_TAP
};
UI_BASE_EXPORT MenuSourceType GetMenuSourceTypeForEvent(const ui::Event& event);
diff --git a/chromium/ui/base/ui_base_unittests_apk.isolate b/chromium/ui/base/ui_base_unittests_apk.isolate
index 33fc4811634..87a76282f90 100644
--- a/chromium/ui/base/ui_base_unittests_apk.isolate
+++ b/chromium/ui/base/ui_base_unittests_apk.isolate
@@ -9,6 +9,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_ui_base_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'../../third_party/icu/icu.isolate',
diff --git a/chromium/ui/base/ui_features.gni b/chromium/ui/base/ui_features.gni
new file mode 100644
index 00000000000..724c4d44968
--- /dev/null
+++ b/chromium/ui/base/ui_features.gni
@@ -0,0 +1,5 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+enable_hidpi = is_mac || is_win || is_linux
diff --git a/chromium/ui/base/user_activity/user_activity_detector.cc b/chromium/ui/base/user_activity/user_activity_detector.cc
index bffe4796c9e..4f04b8623b7 100644
--- a/chromium/ui/base/user_activity/user_activity_detector.cc
+++ b/chromium/ui/base/user_activity/user_activity_detector.cc
@@ -53,9 +53,7 @@ UserActivityDetector::UserActivityDetector() {
ui::PlatformEventSource* platform_event_source =
ui::PlatformEventSource::GetInstance();
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
- CHECK(platform_event_source);
-#endif
+ // TODO(sad): Need a PES for mus.
if (platform_event_source)
platform_event_source->AddPlatformEventObserver(this);
}
@@ -63,9 +61,6 @@ UserActivityDetector::UserActivityDetector() {
UserActivityDetector::~UserActivityDetector() {
ui::PlatformEventSource* platform_event_source =
ui::PlatformEventSource::GetInstance();
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
- CHECK(platform_event_source);
-#endif
if (platform_event_source)
platform_event_source->RemovePlatformEventObserver(this);
g_instance = nullptr;
diff --git a/chromium/ui/base/webui/web_ui_util.cc b/chromium/ui/base/webui/web_ui_util.cc
index d9c1d76da66..0f91f3f7045 100644
--- a/chromium/ui/base/webui/web_ui_util.cc
+++ b/chromium/ui/base/webui/web_ui_util.cc
@@ -91,9 +91,10 @@ bool ParseScaleFactor(const base::StringPiece& identifier,
void ParsePathAndScale(const GURL& url,
std::string* path,
float* scale_factor) {
- *path = net::UnescapeURLComponent(url.path().substr(1),
- (net::UnescapeRule::URL_SPECIAL_CHARS |
- net::UnescapeRule::SPACES));
+ *path = net::UnescapeURLComponent(
+ url.path().substr(1),
+ net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
+ net::UnescapeRule::SPACES);
if (scale_factor)
*scale_factor = 1.0f;
@@ -123,7 +124,7 @@ void SetLoadTimeDataDefaults(const std::string& app_locale,
}
std::string GetWebUiCssTextDefaults(const std::string& css_template) {
- std::map<base::StringPiece, std::string> placeholders;
+ ui::TemplateReplacements placeholders;
placeholders["textDirection"] = GetTextDirection();
placeholders["fontFamily"] = GetFontFamily();
placeholders["fontSize"] = GetFontSize();
diff --git a/chromium/ui/base/win/open_file_name_win.cc b/chromium/ui/base/win/open_file_name_win.cc
index 5c2df415a23..8b32ae20303 100644
--- a/chromium/ui/base/win/open_file_name_win.cc
+++ b/chromium/ui/base/win/open_file_name_win.cc
@@ -86,15 +86,15 @@ OpenFileName::~OpenFileName() {
}
void OpenFileName::SetFilters(
- const std::vector<base::Tuple<base::string16, base::string16>>& filters) {
+ const std::vector<std::tuple<base::string16, base::string16>>& filters) {
openfilename_.lpstrFilter = NULL;
filter_buffer_.clear();
if (filters.empty())
return;
for (const auto& filter : filters) {
- filter_buffer_.append(base::get<0>(filter));
+ filter_buffer_.append(std::get<0>(filter));
filter_buffer_.push_back(0);
- filter_buffer_.append(base::get<1>(filter));
+ filter_buffer_.append(std::get<1>(filter));
filter_buffer_.push_back(0);
}
filter_buffer_.push_back(0);
@@ -203,9 +203,9 @@ void OpenFileName::SetResult(const base::FilePath& directory,
}
// static
-std::vector<base::Tuple<base::string16, base::string16>>
+std::vector<std::tuple<base::string16, base::string16>>
OpenFileName::GetFilters(const OPENFILENAME* openfilename) {
- std::vector<base::Tuple<base::string16, base::string16>> filters;
+ std::vector<std::tuple<base::string16, base::string16>> filters;
const base::char16* display_string = openfilename->lpstrFilter;
if (!display_string)
@@ -220,7 +220,7 @@ OpenFileName::GetFilters(const OPENFILENAME* openfilename) {
while (*pattern_end)
++pattern_end;
filters.push_back(
- base::MakeTuple(base::string16(display_string, display_string_end),
+ std::make_tuple(base::string16(display_string, display_string_end),
base::string16(pattern, pattern_end)));
display_string = pattern_end + 1;
}
diff --git a/chromium/ui/base/win/open_file_name_win.h b/chromium/ui/base/win/open_file_name_win.h
index 596b1470f5f..5d0b028edbb 100644
--- a/chromium/ui/base/win/open_file_name_win.h
+++ b/chromium/ui/base/win/open_file_name_win.h
@@ -8,11 +8,11 @@
#include <Windows.h>
#include <Commdlg.h>
+#include <tuple>
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.h"
-#include "base/tuple.h"
#include "ui/base/ui_base_export.h"
namespace base {
@@ -34,7 +34,7 @@ class UI_BASE_EXPORT OpenFileName {
// Initializes |lpstrFilter| from the label/pattern pairs in |filters|.
void SetFilters(
- const std::vector<base::Tuple<base::string16, base::string16>>& filters);
+ const std::vector<std::tuple<base::string16, base::string16>>& filters);
// Sets |lpstrInitialDir| and |lpstrFile|.
void SetInitialSelection(const base::FilePath& initial_directory,
@@ -68,7 +68,7 @@ class UI_BASE_EXPORT OpenFileName {
// Returns a vector of label/pattern pairs built from
// |openfilename->lpstrFilter|.
- static std::vector<base::Tuple<base::string16, base::string16>> GetFilters(
+ static std::vector<std::tuple<base::string16, base::string16>> GetFilters(
const OPENFILENAME* openfilename);
private:
diff --git a/chromium/ui/base/win/open_file_name_win_unittest.cc b/chromium/ui/base/win/open_file_name_win_unittest.cc
index 36de27faa96..bce8abcfa72 100644
--- a/chromium/ui/base/win/open_file_name_win_unittest.cc
+++ b/chromium/ui/base/win/open_file_name_win_unittest.cc
@@ -30,8 +30,8 @@ void SetResult(const base::string16& result, ui::win::OpenFileName* ofn) {
}
void CheckFilters(
- const std::vector<base::Tuple<base::string16, base::string16>>& expected,
- const std::vector<base::Tuple<base::string16, base::string16>>& actual) {
+ const std::vector<std::tuple<base::string16, base::string16>>& expected,
+ const std::vector<std::tuple<base::string16, base::string16>>& actual) {
if (expected.size() != actual.size()) {
ADD_FAILURE() << "filter count mismatch. Got " << actual.size()
<< " expected " << expected.size() << ".";
@@ -39,9 +39,9 @@ void CheckFilters(
}
for (size_t i = 0; i < expected.size(); ++i) {
- EXPECT_EQ(base::get<0>(expected[i]), base::get<0>(actual[i]))
+ EXPECT_EQ(std::get<0>(expected[i]), std::get<0>(actual[i]))
<< "Mismatch at index " << i;
- EXPECT_EQ(base::get<1>(expected[i]), base::get<1>(actual[i]))
+ EXPECT_EQ(std::get<1>(expected[i]), std::get<1>(actual[i]))
<< "Mismatch at index " << i;
}
}
@@ -206,19 +206,21 @@ TEST(OpenFileNameTest, SetAndGetFilters) {
const base::string16 kNull(L"\0", 1);
ui::win::OpenFileName ofn(kHwnd, kFlags);
- std::vector<base::Tuple<base::string16, base::string16>> filters;
+ std::vector<std::tuple<base::string16, base::string16>> filters;
ofn.SetFilters(filters);
EXPECT_FALSE(ofn.GetOPENFILENAME()->lpstrFilter);
CheckFilters(filters,
ui::win::OpenFileName::GetFilters(ofn.GetOPENFILENAME()));
- filters.push_back(base::MakeTuple(base::string16(L"a"), base::string16(L"b")));
+ filters.push_back(
+ std::make_tuple(base::string16(L"a"), base::string16(L"b")));
ofn.SetFilters(filters);
CheckFilterString(L"a" + kNull + L"b" + kNull, ofn);
CheckFilters(filters,
ui::win::OpenFileName::GetFilters(ofn.GetOPENFILENAME()));
- filters.push_back(base::MakeTuple(base::string16(L"X"), base::string16(L"Y")));
+ filters.push_back(
+ std::make_tuple(base::string16(L"X"), base::string16(L"Y")));
ofn.SetFilters(filters);
CheckFilterString(L"a" + kNull + L"b" + kNull + L"X" + kNull + L"Y" + kNull,
ofn);
diff --git a/chromium/ui/base/win/shell.cc b/chromium/ui/base/win/shell.cc
index 8dacd14ce4e..cdc0a8da185 100644
--- a/chromium/ui/base/win/shell.cc
+++ b/chromium/ui/base/win/shell.cc
@@ -15,6 +15,7 @@
#include "base/files/file_path.h"
#include "base/native_library.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
@@ -114,7 +115,8 @@ bool PreventWindowFromPinning(HWND hwnd) {
// TODO(calamity): investigate moving this out of the UI thread as COM
// operations may spawn nested message loops which can cause issues.
void SetAppDetailsForWindow(const base::string16& app_id,
- const base::string16& app_icon,
+ const base::FilePath& app_icon_path,
+ int app_icon_index,
const base::string16& relaunch_command,
const base::string16& relaunch_display_name,
HWND hwnd) {
@@ -131,9 +133,14 @@ void SetAppDetailsForWindow(const base::string16& app_id,
if (!app_id.empty())
base::win::SetAppIdForPropertyStore(pps.get(), app_id.c_str());
- if (!app_icon.empty()) {
+ if (!app_icon_path.empty()) {
+ // Always add the icon index explicitly to prevent bad interaction with the
+ // index notation when file path has commas.
base::win::SetStringValueForPropertyStore(
- pps.get(), PKEY_AppUserModel_RelaunchIconResource, app_icon.c_str());
+ pps.get(), PKEY_AppUserModel_RelaunchIconResource,
+ base::StringPrintf(L"%ls,%d", app_icon_path.value().c_str(),
+ app_icon_index)
+ .c_str());
}
if (!relaunch_command.empty()) {
base::win::SetStringValueForPropertyStore(
@@ -148,29 +155,22 @@ void SetAppDetailsForWindow(const base::string16& app_id,
}
void SetAppIdForWindow(const base::string16& app_id, HWND hwnd) {
- SetAppDetailsForWindow(app_id,
- base::string16(),
- base::string16(),
- base::string16(),
- hwnd);
+ SetAppDetailsForWindow(app_id, base::FilePath(), 0, base::string16(),
+ base::string16(), hwnd);
}
-void SetAppIconForWindow(const base::string16& app_icon, HWND hwnd) {
- SetAppDetailsForWindow(base::string16(),
- app_icon,
- base::string16(),
- base::string16(),
- hwnd);
+void SetAppIconForWindow(const base::FilePath& app_icon_path,
+ int app_icon_index,
+ HWND hwnd) {
+ SetAppDetailsForWindow(base::string16(), app_icon_path, app_icon_index,
+ base::string16(), base::string16(), hwnd);
}
void SetRelaunchDetailsForWindow(const base::string16& relaunch_command,
const base::string16& display_name,
HWND hwnd) {
- SetAppDetailsForWindow(base::string16(),
- base::string16(),
- relaunch_command,
- display_name,
- hwnd);
+ SetAppDetailsForWindow(base::string16(), base::FilePath(), 0,
+ relaunch_command, display_name, hwnd);
}
void ClearWindowPropertyStore(HWND hwnd) {
diff --git a/chromium/ui/base/win/shell.h b/chromium/ui/base/win/shell.h
index 458074c6ff9..df784a6e13b 100644
--- a/chromium/ui/base/win/shell.h
+++ b/chromium/ui/base/win/shell.h
@@ -51,10 +51,12 @@ UI_BASE_EXPORT bool OpenAnyViaShell(const base::string16& full_path,
UI_BASE_EXPORT bool PreventWindowFromPinning(HWND hwnd);
// Sets the application id, app icon, relaunch command and relaunch display name
-// for the given window.
+// for the given window. |app_icon_index| should be set to 0 if the app icon
+// file only has a single icon.
UI_BASE_EXPORT void SetAppDetailsForWindow(
const base::string16& app_id,
- const base::string16& app_icon,
+ const base::FilePath& app_icon_path,
+ int app_icon_index,
const base::string16& relaunch_command,
const base::string16& relaunch_display_name,
HWND hwnd);
@@ -65,7 +67,8 @@ UI_BASE_EXPORT void SetAppDetailsForWindow(
UI_BASE_EXPORT void SetAppIdForWindow(const base::string16& app_id, HWND hwnd);
// Sets the application icon for the window specified.
-UI_BASE_EXPORT void SetAppIconForWindow(const base::string16& app_icon,
+UI_BASE_EXPORT void SetAppIconForWindow(const base::FilePath& app_icon_path,
+ int app_icon_index,
HWND hwnd);
// Sets the relaunch command and relaunch display name for the window specified.
diff --git a/chromium/ui/base/x/selection_owner.cc b/chromium/ui/base/x/selection_owner.cc
index d13f088d5aa..170f32e19b2 100644
--- a/chromium/ui/base/x/selection_owner.cc
+++ b/chromium/ui/base/x/selection_owner.cc
@@ -376,6 +376,9 @@ SelectionOwner::IncrementalTransfer::IncrementalTransfer(
foreign_window_manager_id(foreign_window_manager_id) {
}
+SelectionOwner::IncrementalTransfer::IncrementalTransfer(
+ const IncrementalTransfer& other) = default;
+
SelectionOwner::IncrementalTransfer::~IncrementalTransfer() {
}
diff --git a/chromium/ui/base/x/selection_owner.h b/chromium/ui/base/x/selection_owner.h
index f3bec33aca8..6ae933aada2 100644
--- a/chromium/ui/base/x/selection_owner.h
+++ b/chromium/ui/base/x/selection_owner.h
@@ -67,6 +67,7 @@ class UI_BASE_EXPORT SelectionOwner {
int offset,
base::TimeTicks timeout,
int foreign_window_manager_id);
+ IncrementalTransfer(const IncrementalTransfer& other);
~IncrementalTransfer();
// Parameters from the XSelectionRequest. The data is transferred over
diff --git a/chromium/ui/base/x/selection_requestor.cc b/chromium/ui/base/x/selection_requestor.cc
index 977de29f4b8..d4e13d808e0 100644
--- a/chromium/ui/base/x/selection_requestor.cc
+++ b/chromium/ui/base/x/selection_requestor.cc
@@ -54,8 +54,7 @@ scoped_refptr<base::RefCountedMemory> CombineRefCountedMemory(
data[i]->front(),
data[i]->front() + data[i]->size());
}
- return scoped_refptr<base::RefCountedMemory>(
- base::RefCountedBytes::TakeVector(&combined_data));
+ return base::RefCountedBytes::TakeVector(&combined_data);
}
} // namespace
diff --git a/chromium/ui/base/x/selection_utils.cc b/chromium/ui/base/x/selection_utils.cc
index af84c4babbe..d7acd52c029 100644
--- a/chromium/ui/base/x/selection_utils.cc
+++ b/chromium/ui/base/x/selection_utils.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <algorithm>
#include <set>
#include "base/i18n/icu_string_conversions.h"
@@ -120,6 +121,9 @@ base::string16 RefCountedMemoryToString16(
SelectionFormatMap::SelectionFormatMap() {}
+SelectionFormatMap::SelectionFormatMap(const SelectionFormatMap& other) =
+ default;
+
SelectionFormatMap::~SelectionFormatMap() {}
void SelectionFormatMap::Insert(
diff --git a/chromium/ui/base/x/selection_utils.h b/chromium/ui/base/x/selection_utils.h
index 1c4bcbdbc8c..addbcf7db21 100644
--- a/chromium/ui/base/x/selection_utils.h
+++ b/chromium/ui/base/x/selection_utils.h
@@ -66,6 +66,7 @@ class UI_BASE_EXPORT SelectionFormatMap {
typedef InternalMap::const_iterator const_iterator;
SelectionFormatMap();
+ SelectionFormatMap(const SelectionFormatMap& other);
~SelectionFormatMap();
// Copy and assignment deliberately open.
diff --git a/chromium/ui/compositor/BUILD.gn b/chromium/ui/compositor/BUILD.gn
index ff3d4d3f108..7f849b7846a 100644
--- a/chromium/ui/compositor/BUILD.gn
+++ b/chromium/ui/compositor/BUILD.gn
@@ -48,6 +48,7 @@ component("compositor") {
"layer_delegate.h",
"layer_owner.cc",
"layer_owner.h",
+ "layer_threaded_animation_delegate.h",
"layer_tree_owner.cc",
"layer_tree_owner.h",
"layer_type.h",
@@ -110,6 +111,9 @@ source_set("test_support") {
"test/layer_animation_observer_test_api.h",
"test/layer_animator_test_controller.cc",
"test/layer_animator_test_controller.h",
+ "test/multi_layer_animator_test_controller.cc",
+ "test/multi_layer_animator_test_controller.h",
+ "test/multi_layer_animator_test_controller_delegate.h",
"test/test_compositor_host.h",
"test/test_compositor_host_android.cc",
"test/test_compositor_host_mac.mm",
@@ -159,15 +163,6 @@ source_set("test_support") {
}
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("compositor_unittests_run") {
- testonly = true
- deps = [
- ":compositor_unittests",
- ]
-}
-
test("compositor_unittests") {
sources = [
"callback_layer_animation_observer_unittest.cc",
@@ -189,10 +184,11 @@ test("compositor_unittests") {
":compositor",
":test_support",
"//base",
- "//base/allocator",
"//base/test:test_support",
"//cc",
"//cc:test_support",
+ "//cc/surfaces",
+ "//cc/surfaces:surface_id",
"//skia",
"//testing/gmock",
"//testing/gtest",
diff --git a/chromium/ui/compositor/compositing_recorder.cc b/chromium/ui/compositor/compositing_recorder.cc
index 842cc3a2ec3..fd255c731ef 100644
--- a/chromium/ui/compositor/compositing_recorder.cc
+++ b/chromium/ui/compositor/compositing_recorder.cc
@@ -23,7 +23,7 @@ CompositingRecorder::CompositingRecorder(const PaintContext& context,
context_.list_->CreateAndAppendItem<cc::CompositingDisplayItem>(
bounds_in_layer_, alpha, SkXfermode::kSrcOver_Mode,
- nullptr /* no bounds */, skia::RefPtr<SkColorFilter>(),
+ nullptr /* no bounds */, nullptr /* no color filter */,
lcd_text_requires_opaque_layer);
}
diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc
index afb502601aa..9c492698b5c 100644
--- a/chromium/ui/compositor/compositor.cc
+++ b/chromium/ui/compositor/compositor.cc
@@ -87,7 +87,7 @@ Compositor::Compositor(ui::ContextFactory* context_factory,
compositor_lock_(NULL),
layer_animator_collection_(this),
weak_ptr_factory_(this) {
- root_web_layer_ = cc::Layer::Create(Layer::UILayerSettings());
+ root_web_layer_ = cc::Layer::Create();
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -126,6 +126,8 @@ Compositor::Compositor(ui::ContextFactory* context_factory,
// These flags should be mirrored by renderer versions in content/renderer/.
settings.initial_debug_state.show_debug_borders =
command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
+ settings.initial_debug_state.show_fps_counter =
+ command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
settings.initial_debug_state.show_layer_animation_bounds_rects =
command_line->HasSwitch(cc::switches::kUIShowLayerAnimationBounds);
settings.initial_debug_state.show_paint_rects =
@@ -142,12 +144,10 @@ Compositor::Compositor(ui::ContextFactory* context_factory,
settings.initial_debug_state.SetRecordRenderingStats(
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
- if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
- settings.use_property_trees = false;
settings.use_zero_copy = IsUIZeroCopyEnabled();
- settings.renderer_settings.use_rgba_4444_textures =
- command_line->HasSwitch(switches::kUIEnableRGBA4444Textures);
+ if (command_line->HasSwitch(switches::kUIEnableRGBA4444Textures))
+ settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
// UI compositor always uses partial raster if not using zero-copy. Zero copy
// doesn't currently support partial raster.
@@ -172,9 +172,6 @@ Compositor::Compositor(ui::ContextFactory* context_factory,
// thread.
settings.image_decode_tasks_enabled = false;
- settings.use_compositor_animation_timelines = !command_line->HasSwitch(
- switches::kUIDisableCompositorAnimationTimelines);
-
#if !defined(OS_ANDROID)
// TODO(sohanjg): Revisit this memory usage in tile manager.
cc::ManagedMemoryPolicy policy(
@@ -197,11 +194,10 @@ Compositor::Compositor(ui::ContextFactory* context_factory,
UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor",
base::TimeTicks::Now() - before_create);
- if (settings.use_compositor_animation_timelines) {
- animation_timeline_ = cc::AnimationTimeline::Create(
- cc::AnimationIdProvider::NextTimelineId());
- host_->animation_host()->AddAnimationTimeline(animation_timeline_.get());
- }
+ animation_timeline_ =
+ cc::AnimationTimeline::Create(cc::AnimationIdProvider::NextTimelineId());
+ host_->animation_host()->AddAnimationTimeline(animation_timeline_.get());
+
host_->SetRootLayer(root_web_layer_);
host_->set_surface_id_namespace(surface_id_allocator_->id_namespace());
host_->SetVisible(true);
@@ -472,6 +468,11 @@ void Compositor::DidAbortSwapBuffers() {
OnCompositingAborted(this));
}
+void Compositor::SetOutputIsSecure(bool output_is_secure) {
+ host_->SetOutputIsSecure(output_is_secure);
+ host_->SetNeedsRedraw();
+}
+
void Compositor::SendBeginFramesToChildren(const cc::BeginFrameArgs& args) {
FOR_EACH_OBSERVER(CompositorBeginFrameObserver, begin_frame_observer_list_,
OnSendBeginFrame(args));
diff --git a/chromium/ui/compositor/compositor.gyp b/chromium/ui/compositor/compositor.gyp
index 4ab5b0c1146..c692274f84e 100644
--- a/chromium/ui/compositor/compositor.gyp
+++ b/chromium/ui/compositor/compositor.gyp
@@ -66,6 +66,7 @@
'layer_delegate.h',
'layer_owner.cc',
'layer_owner.h',
+ 'layer_threaded_animation_delegate.h',
'layer_tree_owner.cc',
'layer_tree_owner.h',
'layer_type.h',
@@ -128,6 +129,9 @@
'test/layer_animation_observer_test_api.h',
'test/layer_animator_test_controller.cc',
'test/layer_animator_test_controller.h',
+ 'test/multi_layer_animator_test_controller.cc',
+ 'test/multi_layer_animator_test_controller.h',
+ 'test/multi_layer_animator_test_controller_delegate.h',
'test/test_compositor_host.h',
'test/test_compositor_host_android.cc',
'test/test_compositor_host_mac.mm',
@@ -161,6 +165,7 @@
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/base/base.gyp:test_support_base',
'<(DEPTH)/cc/cc.gyp:cc',
+ '<(DEPTH)/cc/cc.gyp:cc_surfaces',
'<(DEPTH)/cc/cc_tests.gyp:cc_test_support',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/testing/gmock.gyp:gmock',
@@ -191,15 +196,6 @@
'<(DEPTH)/third_party/mesa/mesa.gyp:osmesa',
],
}],
- ['os_posix == 1 and OS != "mac"', {
- 'conditions': [
- ['use_allocator!="none"', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
- }],
['OS == "android"', {
'dependencies': [
'../../testing/android/native_test.gyp:native_test_native_code',
diff --git a/chromium/ui/compositor/compositor.h b/chromium/ui/compositor/compositor.h
index 5222b41d956..acae0be40c2 100644
--- a/chromium/ui/compositor/compositor.h
+++ b/chromium/ui/compositor/compositor.h
@@ -318,6 +318,8 @@ class COMPOSITOR_EXPORT Compositor
bool IsLocked() { return compositor_lock_ != NULL; }
+ void SetOutputIsSecure(bool output_is_secure);
+
const cc::LayerTreeDebugState& GetLayerTreeDebugState() const;
void SetLayerTreeDebugState(const cc::LayerTreeDebugState& debug_state);
const cc::RendererSettings& GetRendererSettings() const;
diff --git a/chromium/ui/compositor/compositor_switches.cc b/chromium/ui/compositor/compositor_switches.cc
index 1a2c6ca55e3..c8464ddfdaa 100644
--- a/chromium/ui/compositor/compositor_switches.cc
+++ b/chromium/ui/compositor/compositor_switches.cc
@@ -15,9 +15,6 @@ const char kEnableHardwareOverlays[] = "enable-hardware-overlays";
// Forces tests to produce pixel output when they normally wouldn't.
const char kEnablePixelOutputInTests[] = "enable-pixel-output-in-tests";
-const char kUIDisableCompositorAnimationTimelines[] =
- "ui-disable-compositor-animation-timelines";
-
// Disable partial swap which is needed for some OpenGL drivers / emulators.
const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
diff --git a/chromium/ui/compositor/compositor_switches.h b/chromium/ui/compositor/compositor_switches.h
index 929722a15f5..62705efd076 100644
--- a/chromium/ui/compositor/compositor_switches.h
+++ b/chromium/ui/compositor/compositor_switches.h
@@ -11,7 +11,6 @@ namespace switches {
COMPOSITOR_EXPORT extern const char kEnableHardwareOverlays[];
COMPOSITOR_EXPORT extern const char kEnablePixelOutputInTests[];
-COMPOSITOR_EXPORT extern const char kUIDisableCompositorAnimationTimelines[];
COMPOSITOR_EXPORT extern const char kUIDisablePartialSwap[];
COMPOSITOR_EXPORT extern const char kUIEnableRGBA4444Textures[];
COMPOSITOR_EXPORT extern const char kUIEnableZeroCopy[];
diff --git a/chromium/ui/compositor/layer.cc b/chromium/ui/compositor/layer.cc
index 9503a8a38f6..0f83cb60001 100644
--- a/chromium/ui/compositor/layer.cc
+++ b/chromium/ui/compositor/layer.cc
@@ -10,19 +10,15 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
-#include "cc/layers/delegated_renderer_layer.h"
-#include "cc/layers/layer_settings.h"
#include "cc/layers/nine_patch_layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/layers/texture_layer.h"
#include "cc/output/copy_output_request.h"
-#include "cc/output/delegated_frame_data.h"
#include "cc/output/filter_operation.h"
#include "cc/output/filter_operations.h"
#include "cc/playback/display_item_list_settings.h"
@@ -48,9 +44,6 @@ const ui::Layer* GetRoot(const ui::Layer* layer) {
return layer;
}
-base::LazyInstance<cc::LayerSettings> g_ui_layer_settings =
- LAZY_INSTANCE_INITIALIZER;
-
} // namespace
namespace ui {
@@ -120,19 +113,8 @@ Layer::~Layer() {
children_[i]->parent_ = NULL;
cc_layer_->RemoveFromParent();
-}
-
-// static
-const cc::LayerSettings& Layer::UILayerSettings() {
- return g_ui_layer_settings.Get();
-}
-
-// static
-void Layer::InitializeUILayerSettings() {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- g_ui_layer_settings.Get().use_compositor_animation_timelines =
- !command_line->HasSwitch(
- switches::kUIDisableCompositorAnimationTimelines);
+ if (mailbox_release_callback_)
+ mailbox_release_callback_->Run(gpu::SyncToken(), false);
}
const Compositor* Layer::GetCompositor() const {
@@ -157,7 +139,6 @@ void Layer::SetCompositor(Compositor* compositor,
root_layer->AddChild(cc_layer_);
SetCompositorForAnimatorsInTree(compositor);
- SendPendingThreadedAnimations();
}
void Layer::ResetCompositor() {
@@ -177,10 +158,8 @@ void Layer::Add(Layer* child) {
cc_layer_->AddChild(child->cc_layer_);
child->OnDeviceScaleFactorChanged(device_scale_factor_);
Compositor* compositor = GetCompositor();
- if (compositor) {
+ if (compositor)
child->SetCompositorForAnimatorsInTree(compositor);
- child->SendPendingThreadedAnimations();
- }
}
void Layer::Remove(Layer* child) {
@@ -505,7 +484,6 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
if (texture_layer_.get())
texture_layer_->ClearClient();
- // TODO(piman): delegated_renderer_layer_ cleanup.
cc_layer_->RemoveAllChildren();
if (cc_layer_->parent()) {
@@ -521,7 +499,6 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
content_layer_ = NULL;
solid_color_layer_ = NULL;
texture_layer_ = NULL;
- delegated_renderer_layer_ = NULL;
surface_layer_ = NULL;
for (size_t i = 0; i < children_.size(); ++i) {
@@ -539,9 +516,12 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
SetLayerBackgroundFilters();
}
+bool Layer::HasPendingThreadedAnimationsForTesting() const {
+ return animator_->HasPendingThreadedAnimationsForTesting();
+}
+
void Layer::SwitchCCLayerForTest() {
- scoped_refptr<cc::Layer> new_layer =
- cc::PictureLayer::Create(UILayerSettings(), this);
+ scoped_refptr<cc::Layer> new_layer = cc::PictureLayer::Create(this);
SwitchToLayer(new_layer);
content_layer_ = new_layer;
}
@@ -555,7 +535,7 @@ void Layer::SetTextureMailbox(
DCHECK(release_callback);
if (!texture_layer_.get()) {
scoped_refptr<cc::TextureLayer> new_layer =
- cc::TextureLayer::CreateForMailbox(UILayerSettings(), this);
+ cc::TextureLayer::CreateForMailbox(this);
new_layer->SetFlipped(true);
SwitchToLayer(new_layer);
texture_layer_ = new_layer;
@@ -589,19 +569,6 @@ bool Layer::TextureFlipped() const {
return texture_layer_->flipped();
}
-void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
- gfx::Size frame_size_in_dip) {
- DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
-
- scoped_refptr<cc::DelegatedRendererLayer> new_layer =
- cc::DelegatedRendererLayer::Create(UILayerSettings(), frame_provider);
- SwitchToLayer(new_layer);
- delegated_renderer_layer_ = new_layer;
-
- frame_size_in_dip_ = frame_size_in_dip;
- RecomputeDrawsContentAndUVRect();
-}
-
void Layer::SetShowSurface(
cc::SurfaceId surface_id,
const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
@@ -611,8 +578,8 @@ void Layer::SetShowSurface(
gfx::Size frame_size_in_dip) {
DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
- scoped_refptr<cc::SurfaceLayer> new_layer = cc::SurfaceLayer::Create(
- UILayerSettings(), satisfy_callback, require_callback);
+ scoped_refptr<cc::SurfaceLayer> new_layer =
+ cc::SurfaceLayer::Create(satisfy_callback, require_callback);
new_layer->SetSurfaceId(surface_id, scale, surface_size);
SwitchToLayer(new_layer);
surface_layer_ = new_layer;
@@ -627,8 +594,7 @@ void Layer::SetShowSolidColorContent() {
if (solid_color_layer_.get())
return;
- scoped_refptr<cc::SolidColorLayer> new_layer =
- cc::SolidColorLayer::Create(UILayerSettings());
+ scoped_refptr<cc::SolidColorLayer> new_layer = cc::SolidColorLayer::Create();
SwitchToLayer(new_layer);
solid_color_layer_ = new_layer;
@@ -751,7 +717,7 @@ void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) {
}
void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
- DCHECK(delegated_renderer_layer_.get() || surface_layer_.get());
+ DCHECK(surface_layer_.get());
if (!delegate_)
return;
delegate_->OnDelegatedFrameDamage(damage_rect_in_dip);
@@ -814,6 +780,7 @@ void Layer::SetForceRenderSurface(bool force) {
class LayerDebugInfo : public base::trace_event::ConvertableToTraceFormat {
public:
explicit LayerDebugInfo(const std::string& name) : name_(name) {}
+ ~LayerDebugInfo() override {}
void AppendAsTraceFormat(std::string* out) const override {
base::DictionaryValue dictionary;
dictionary.SetString("layer_name", name_);
@@ -821,13 +788,12 @@ class LayerDebugInfo : public base::trace_event::ConvertableToTraceFormat {
}
private:
- ~LayerDebugInfo() override {}
std::string name_;
};
-scoped_refptr<base::trace_event::ConvertableToTraceFormat> Layer::TakeDebugInfo(
+scoped_ptr<base::trace_event::ConvertableToTraceFormat> Layer::TakeDebugInfo(
cc::Layer* layer) {
- return new LayerDebugInfo(name_);
+ return make_scoped_ptr(new LayerDebugInfo(name_));
}
void Layer::CollectAnimators(
@@ -981,44 +947,6 @@ float Layer::GetDeviceScaleFactor() const {
return device_scale_factor_;
}
-void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
- DCHECK(cc_layer_);
- // Until this layer has a compositor (and hence cc_layer_ has a
- // LayerTreeHost), addAnimation will fail.
- if (GetCompositor()) {
- if (UILayerSettings().use_compositor_animation_timelines) {
- DCHECK(animator_);
- animator_->AddThreadedAnimation(std::move(animation));
- } else {
- cc_layer_->AddAnimation(std::move(animation));
- }
- } else {
- pending_threaded_animations_.push_back(std::move(animation));
- }
-}
-
-void Layer::RemoveThreadedAnimation(int animation_id) {
- DCHECK(cc_layer_);
- if (pending_threaded_animations_.size() == 0) {
- if (UILayerSettings().use_compositor_animation_timelines) {
- DCHECK(animator_);
- animator_->RemoveThreadedAnimation(animation_id);
- } else {
- cc_layer_->RemoveAnimation(animation_id);
- }
- return;
- }
-
- pending_threaded_animations_.erase(
- std::remove_if(
- pending_threaded_animations_.begin(),
- pending_threaded_animations_.end(),
- [animation_id](const scoped_ptr<cc::Animation>& animation) {
- return animation->id() == animation_id;
- }),
- pending_threaded_animations_.end());
-}
-
LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() {
Compositor* compositor = GetCompositor();
return compositor ? compositor->layer_animator_collection() : NULL;
@@ -1028,30 +956,20 @@ cc::Layer* Layer::GetCcLayer() const {
return cc_layer_;
}
-void Layer::SendPendingThreadedAnimations() {
- for (auto& animation : pending_threaded_animations_) {
- if (UILayerSettings().use_compositor_animation_timelines) {
- DCHECK(animator_);
- animator_->AddThreadedAnimation(std::move(animation));
- } else {
- cc_layer_->AddAnimation(std::move(animation));
- }
- }
- pending_threaded_animations_.clear();
-
- for (auto* child : children_)
- child->SendPendingThreadedAnimations();
+LayerThreadedAnimationDelegate* Layer::GetThreadedAnimationDelegate() {
+ DCHECK(animator_);
+ return animator_.get();
}
void Layer::CreateCcLayer() {
if (type_ == LAYER_SOLID_COLOR) {
- solid_color_layer_ = cc::SolidColorLayer::Create(UILayerSettings());
+ solid_color_layer_ = cc::SolidColorLayer::Create();
cc_layer_ = solid_color_layer_.get();
} else if (type_ == LAYER_NINE_PATCH) {
- nine_patch_layer_ = cc::NinePatchLayer::Create(UILayerSettings());
+ nine_patch_layer_ = cc::NinePatchLayer::Create();
cc_layer_ = nine_patch_layer_.get();
} else {
- content_layer_ = cc::PictureLayer::Create(UILayerSettings(), this);
+ content_layer_ = cc::PictureLayer::Create(this);
cc_layer_ = content_layer_.get();
}
cc_layer_->SetTransformOrigin(gfx::Point3F());
@@ -1075,7 +993,7 @@ void Layer::RecomputeDrawsContentAndUVRect() {
static_cast<float>(size.width()) / frame_size_in_dip_.width(),
static_cast<float>(size.height()) / frame_size_in_dip_.height());
texture_layer_->SetUV(uv_top_left, uv_bottom_right);
- } else if (delegated_renderer_layer_.get() || surface_layer_.get()) {
+ } else if (surface_layer_.get()) {
size.SetToMin(frame_size_in_dip_);
}
cc_layer_->SetBounds(size);
@@ -1106,8 +1024,7 @@ void Layer::ResetCompositorForAnimatorsInTree(Compositor* compositor) {
if (animator_) {
animator_->ResetCompositor(compositor);
- if (animator_->is_animating())
- animator_->RemoveFromCollection(collection);
+ animator_->RemoveFromCollection(collection);
}
for (auto* child : children_)
diff --git a/chromium/ui/compositor/layer.h b/chromium/ui/compositor/layer.h
index 689cf39a370..2dcb9c765be 100644
--- a/chromium/ui/compositor/layer.h
+++ b/chromium/ui/compositor/layer.h
@@ -37,8 +37,6 @@ class SkCanvas;
namespace cc {
class ContentLayer;
class CopyOutputRequest;
-class DelegatedFrameProvider;
-class DelegatedRendererLayer;
class Layer;
class NinePatchLayer;
class ResourceUpdateQueue;
@@ -54,6 +52,7 @@ namespace ui {
class Compositor;
class LayerAnimator;
class LayerOwner;
+class LayerThreadedAnimationDelegate;
// Layer manages a texture, transform and a set of child Layers. Any View that
// has enabled layers ends up creating a Layer to manage the texture.
@@ -75,9 +74,6 @@ class COMPOSITOR_EXPORT Layer
explicit Layer(LayerType type);
~Layer() override;
- static const cc::LayerSettings& UILayerSettings();
- static void InitializeUILayerSettings();
-
// Retrieves the Layer's compositor. The Layer will walk up its parent chain
// to locate it. Returns NULL if the Layer is not attached to a compositor.
Compositor* GetCompositor() {
@@ -284,10 +280,6 @@ class COMPOSITOR_EXPORT Layer
void SetTextureFlipped(bool flipped);
bool TextureFlipped() const;
- // Begins showing delegated frames from the |frame_provider|.
- void SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider,
- gfx::Size frame_size_in_dip);
-
// Begins showing content from a surface with a particular id.
void SetShowSurface(cc::SurfaceId surface_id,
const cc::SurfaceLayer::SatisfyCallback& satisfy_callback,
@@ -297,8 +289,7 @@ class COMPOSITOR_EXPORT Layer
gfx::Size frame_size_in_dip);
bool has_external_content() {
- return texture_layer_.get() || delegated_renderer_layer_.get() ||
- surface_layer_.get();
+ return texture_layer_.get() || surface_layer_.get();
}
// Show a solid color instead of delegated or surface contents.
@@ -369,13 +360,11 @@ class COMPOSITOR_EXPORT Layer
bool force_render_surface() const { return force_render_surface_; }
// LayerClient
- scoped_refptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat> TakeDebugInfo(
cc::Layer* layer) override;
// Whether this layer has animations waiting to get sent to its cc::Layer.
- bool HasPendingThreadedAnimations() {
- return pending_threaded_animations_.size() != 0;
- }
+ bool HasPendingThreadedAnimationsForTesting() const;
// Triggers a call to SwitchToLayer.
void SwitchCCLayerForTest();
@@ -409,10 +398,9 @@ class COMPOSITOR_EXPORT Layer
float GetGrayscaleForAnimation() const override;
SkColor GetColorForAnimation() const override;
float GetDeviceScaleFactor() const override;
- void AddThreadedAnimation(scoped_ptr<cc::Animation> animation) override;
- void RemoveThreadedAnimation(int animation_id) override;
- LayerAnimatorCollection* GetLayerAnimatorCollection() override;
cc::Layer* GetCcLayer() const override;
+ LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() override;
+ LayerAnimatorCollection* GetLayerAnimatorCollection() override;
// Creates a corresponding composited layer for |type_|.
void CreateCcLayer();
@@ -430,12 +418,6 @@ class COMPOSITOR_EXPORT Layer
// Cleanup |cc_layer_| and replaces it with |new_layer|.
void SwitchToLayer(scoped_refptr<cc::Layer> new_layer);
- // We cannot send animations to our cc_layer_ until we have been added to a
- // layer tree. Instead, we hold on to these animations in
- // pending_threaded_animations_, and expect SendPendingThreadedAnimations to
- // be called once we have been added to a tree.
- void SendPendingThreadedAnimations();
-
void SetCompositorForAnimatorsInTree(Compositor* compositor);
void ResetCompositorForAnimatorsInTree(Compositor* compositor);
@@ -497,17 +479,12 @@ class COMPOSITOR_EXPORT Layer
scoped_refptr<LayerAnimator> animator_;
- // Animations that are passed to AddThreadedAnimation before this layer is
- // added to a tree.
- std::vector<scoped_ptr<cc::Animation>> pending_threaded_animations_;
-
// Ownership of the layer is held through one of the strongly typed layer
// pointers, depending on which sort of layer this is.
scoped_refptr<cc::Layer> content_layer_;
scoped_refptr<cc::NinePatchLayer> nine_patch_layer_;
scoped_refptr<cc::TextureLayer> texture_layer_;
scoped_refptr<cc::SolidColorLayer> solid_color_layer_;
- scoped_refptr<cc::DelegatedRendererLayer> delegated_renderer_layer_;
scoped_refptr<cc::SurfaceLayer> surface_layer_;
cc::Layer* cc_layer_;
diff --git a/chromium/ui/compositor/layer_animation_delegate.h b/chromium/ui/compositor/layer_animation_delegate.h
index e1ec62451ca..b1db0b300b2 100644
--- a/chromium/ui/compositor/layer_animation_delegate.h
+++ b/chromium/ui/compositor/layer_animation_delegate.h
@@ -5,8 +5,6 @@
#ifndef UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_
#define UI_COMPOSITOR_LAYER_ANIMATION_DELEGATE_H_
-#include "base/memory/scoped_ptr.h"
-#include "cc/animation/animation.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_export.h"
#include "ui/gfx/geometry/rect.h"
@@ -19,6 +17,7 @@ class Layer;
namespace ui {
class LayerAnimatorCollection;
+class LayerThreadedAnimationDelegate;
// Layer animations interact with the layers using this interface.
class COMPOSITOR_EXPORT LayerAnimationDelegate {
@@ -39,14 +38,9 @@ class COMPOSITOR_EXPORT LayerAnimationDelegate {
virtual float GetGrayscaleForAnimation() const = 0;
virtual SkColor GetColorForAnimation() const = 0;
virtual float GetDeviceScaleFactor() const = 0;
-
- // TODO(loyso): Extract these 3 methods as a separate
- // LayerThreadedAnimationDelegate.
- virtual void AddThreadedAnimation(scoped_ptr<cc::Animation> animation) = 0;
- virtual void RemoveThreadedAnimation(int animation_id) = 0;
virtual cc::Layer* GetCcLayer() const = 0;
-
virtual LayerAnimatorCollection* GetLayerAnimatorCollection() = 0;
+ virtual LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() = 0;
protected:
virtual ~LayerAnimationDelegate() {}
diff --git a/chromium/ui/compositor/layer_animation_element.cc b/chromium/ui/compositor/layer_animation_element.cc
index 5e0f558f5c9..edf5bdc89fd 100644
--- a/chromium/ui/compositor/layer_animation_element.cc
+++ b/chromium/ui/compositor/layer_animation_element.cc
@@ -344,7 +344,10 @@ class ThreadedLayerAnimationElement : public LayerAnimationElement {
return false;
if (Started() && IsThreaded()) {
- delegate->RemoveThreadedAnimation(animation_id());
+ LayerThreadedAnimationDelegate* threaded =
+ delegate->GetThreadedAnimationDelegate();
+ DCHECK(threaded);
+ threaded->RemoveThreadedAnimation(animation_id());
}
OnEnd(delegate);
@@ -353,7 +356,10 @@ class ThreadedLayerAnimationElement : public LayerAnimationElement {
void OnAbort(LayerAnimationDelegate* delegate) override {
if (delegate && Started() && IsThreaded()) {
- delegate->RemoveThreadedAnimation(animation_id());
+ LayerThreadedAnimationDelegate* threaded =
+ delegate->GetThreadedAnimationDelegate();
+ DCHECK(threaded);
+ threaded->RemoveThreadedAnimation(animation_id());
}
}
@@ -366,7 +372,11 @@ class ThreadedLayerAnimationElement : public LayerAnimationElement {
set_effective_start_time(base::TimeTicks());
scoped_ptr<cc::Animation> animation = CreateCCAnimation();
animation->set_needs_synchronized_start_time(true);
- delegate->AddThreadedAnimation(std::move(animation));
+
+ LayerThreadedAnimationDelegate* threaded =
+ delegate->GetThreadedAnimationDelegate();
+ DCHECK(threaded);
+ threaded->AddThreadedAnimation(std::move(animation));
}
virtual void OnEnd(LayerAnimationDelegate* delegate) = 0;
@@ -413,9 +423,9 @@ class ThreadedOpacityTransition : public ThreadedLayerAnimationElement {
start_,
target_,
duration()));
- scoped_ptr<cc::Animation> animation(
- cc::Animation::Create(std::move(animation_curve), animation_id(),
- animation_group_id(), cc::Animation::OPACITY));
+ scoped_ptr<cc::Animation> animation(cc::Animation::Create(
+ std::move(animation_curve), animation_id(), animation_group_id(),
+ cc::TargetProperty::OPACITY));
return animation;
}
@@ -466,9 +476,9 @@ class ThreadedTransformTransition : public ThreadedLayerAnimationElement {
start_,
target_,
duration()));
- scoped_ptr<cc::Animation> animation(
- cc::Animation::Create(std::move(animation_curve), animation_id(),
- animation_group_id(), cc::Animation::TRANSFORM));
+ scoped_ptr<cc::Animation> animation(cc::Animation::Create(
+ std::move(animation_curve), animation_id(), animation_group_id(),
+ cc::TargetProperty::TRANSFORM));
return animation;
}
@@ -538,9 +548,9 @@ class InverseTransformTransition : public ThreadedLayerAnimationElement {
}
scoped_ptr<cc::Animation> CreateCCAnimation() override {
- scoped_ptr<cc::Animation> animation(
- cc::Animation::Create(animation_curve_->Clone(), animation_id(),
- animation_group_id(), cc::Animation::TRANSFORM));
+ scoped_ptr<cc::Animation> animation(cc::Animation::Create(
+ animation_curve_->Clone(), animation_id(), animation_group_id(),
+ cc::TargetProperty::TRANSFORM));
return animation;
}
@@ -732,12 +742,11 @@ void LayerAnimationElement::RequestEffectiveStart(
// static
LayerAnimationElement::AnimatableProperty
-LayerAnimationElement::ToAnimatableProperty(
- cc::Animation::TargetProperty property) {
+LayerAnimationElement::ToAnimatableProperty(cc::TargetProperty::Type property) {
switch (property) {
- case cc::Animation::TRANSFORM:
+ case cc::TargetProperty::TRANSFORM:
return TRANSFORM;
- case cc::Animation::OPACITY:
+ case cc::TargetProperty::OPACITY:
return OPACITY;
default:
NOTREACHED();
diff --git a/chromium/ui/compositor/layer_animation_element.h b/chromium/ui/compositor/layer_animation_element.h
index dc08f9001fc..111f25478e0 100644
--- a/chromium/ui/compositor/layer_animation_element.h
+++ b/chromium/ui/compositor/layer_animation_element.h
@@ -45,7 +45,7 @@ class COMPOSITOR_EXPORT LayerAnimationElement {
};
static AnimatableProperty ToAnimatableProperty(
- cc::Animation::TargetProperty property);
+ cc::TargetProperty::Type property);
struct COMPOSITOR_EXPORT TargetValue {
TargetValue();
diff --git a/chromium/ui/compositor/layer_animation_sequence_unittest.cc b/chromium/ui/compositor/layer_animation_sequence_unittest.cc
index 708cc0ad8f2..0a62ddb8d5b 100644
--- a/chromium/ui/compositor/layer_animation_sequence_unittest.cc
+++ b/chromium/ui/compositor/layer_animation_sequence_unittest.cc
@@ -94,7 +94,7 @@ TEST(LayerAnimationSequenceTest, SingleThreadedElement) {
effective_start = start_time + delta;
sequence.OnThreadedAnimationStarted(cc::AnimationEvent(
cc::AnimationEvent::STARTED, 0, sequence.animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
sequence.Progress(effective_start + delta/2, &delegate);
EXPECT_FLOAT_EQ(middle, sequence.last_progressed_fraction());
EXPECT_TRUE(sequence.IsFinished(effective_start + delta));
@@ -148,7 +148,7 @@ TEST(LayerAnimationSequenceTest, MultipleElement) {
EXPECT_EQ(starting_group_id, sequence.animation_group_id());
sequence.OnThreadedAnimationStarted(cc::AnimationEvent(
cc::AnimationEvent::STARTED, 0, sequence.animation_group_id(),
- cc::Animation::OPACITY, opacity_effective_start));
+ cc::TargetProperty::OPACITY, opacity_effective_start));
sequence.Progress(opacity_effective_start + delta/2, &delegate);
EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction());
sequence.Progress(opacity_effective_start + delta, &delegate);
@@ -176,7 +176,7 @@ TEST(LayerAnimationSequenceTest, MultipleElement) {
EXPECT_NE(starting_group_id, sequence.animation_group_id());
sequence.OnThreadedAnimationStarted(cc::AnimationEvent(
cc::AnimationEvent::STARTED, 0, sequence.animation_group_id(),
- cc::Animation::TRANSFORM, transform_effective_start));
+ cc::TargetProperty::TRANSFORM, transform_effective_start));
sequence.Progress(transform_effective_start + delta/2, &delegate);
EXPECT_FLOAT_EQ(0.5, sequence.last_progressed_fraction());
EXPECT_TRUE(sequence.IsFinished(transform_effective_start + delta));
diff --git a/chromium/ui/compositor/layer_animator.cc b/chromium/ui/compositor/layer_animator.cc
index 0f902453ae7..265a568ef45 100644
--- a/chromium/ui/compositor/layer_animator.cc
+++ b/chromium/ui/compositor/layer_animator.cc
@@ -10,11 +10,13 @@
#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "cc/animation/animation_events.h"
+#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/animation/animation_player.h"
+#include "cc/animation/animation_registrar.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/element_animations.h"
-#include "cc/layers/layer_settings.h"
+#include "cc/animation/layer_animation_controller.h"
#include "cc/output/begin_frame_args.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
@@ -54,10 +56,8 @@ LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
is_started_(false),
disable_timer_for_test_(false),
adding_animations_(false) {
- if (Layer::UILayerSettings().use_compositor_animation_timelines) {
- animation_player_ =
- cc::AnimationPlayer::Create(cc::AnimationIdProvider::NextPlayerId());
- }
+ animation_player_ =
+ cc::AnimationPlayer::Create(cc::AnimationIdProvider::NextPlayerId());
}
LayerAnimator::~LayerAnimator() {
@@ -67,6 +67,7 @@ LayerAnimator::~LayerAnimator() {
}
ClearAnimationsInternal();
delegate_ = NULL;
+ DCHECK(!animation_player_->animation_timeline());
}
// static
@@ -136,46 +137,58 @@ void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
}
void LayerAnimator::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
- if (delegate_) {
- if (animation_player_)
- DetachLayerFromAnimationPlayer();
- else
- delegate_->GetCcLayer()->RemoveLayerAnimationEventObserver(this);
- }
- if (new_layer) {
- if (animation_player_)
- AttachLayerToAnimationPlayer(new_layer->id());
- else
- new_layer->AddLayerAnimationEventObserver(this);
- }
+ // Release LAC state for old layer.
+ animation_controller_state_ = nullptr;
+
+ if (delegate_)
+ DetachLayerFromAnimationPlayer();
+ if (new_layer)
+ AttachLayerToAnimationPlayer(new_layer->id());
}
void LayerAnimator::SetCompositor(Compositor* compositor) {
DCHECK(compositor);
- if (animation_player_) {
- cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
- DCHECK(timeline);
- timeline->AttachPlayer(animation_player_);
- DCHECK(delegate_->GetCcLayer());
- AttachLayerToAnimationPlayer(delegate_->GetCcLayer()->id());
+ cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
+ DCHECK(timeline);
+
+ DCHECK(delegate_->GetCcLayer());
+
+ // Register LAC so ElementAnimations picks it up via
+ // AnimationRegistrar::GetAnimationControllerForId.
+ if (animation_controller_state_) {
+ DCHECK_EQ(animation_controller_state_->id(),
+ delegate_->GetCcLayer()->id());
+ timeline->animation_host()
+ ->animation_registrar()
+ ->RegisterAnimationController(animation_controller_state_.get());
}
+
+ timeline->AttachPlayer(animation_player_);
+
+ AttachLayerToAnimationPlayer(delegate_->GetCcLayer()->id());
+
+ // Release LAC (it is referenced in ElementAnimations).
+ animation_controller_state_ = nullptr;
}
void LayerAnimator::ResetCompositor(Compositor* compositor) {
DCHECK(compositor);
- if (animation_player_) {
- DetachLayerFromAnimationPlayer();
- cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
- DCHECK(timeline);
- timeline->DetachPlayer(animation_player_);
+ // Store a reference to LAC if any so it may be picked up in SetCompositor.
+ if (animation_player_->element_animations()) {
+ animation_controller_state_ =
+ animation_player_->element_animations()->layer_animation_controller();
}
+
+ DetachLayerFromAnimationPlayer();
+
+ cc::AnimationTimeline* timeline = compositor->GetAnimationTimeline();
+ DCHECK(timeline);
+ timeline->DetachPlayer(animation_player_);
}
void LayerAnimator::AttachLayerToAnimationPlayer(int layer_id) {
- DCHECK(animation_player_);
-
if (!animation_player_->layer_id())
animation_player_->AttachLayer(layer_id);
else
@@ -189,8 +202,6 @@ void LayerAnimator::AttachLayerToAnimationPlayer(int layer_id) {
}
void LayerAnimator::DetachLayerFromAnimationPlayer() {
- DCHECK(animation_player_);
-
if (animation_player_->element_animations()) {
animation_player_->element_animations()
->layer_animation_controller()
@@ -202,15 +213,17 @@ void LayerAnimator::DetachLayerFromAnimationPlayer() {
}
void LayerAnimator::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) {
- DCHECK(animation_player_);
animation_player_->AddAnimation(std::move(animation));
}
void LayerAnimator::RemoveThreadedAnimation(int animation_id) {
- DCHECK(animation_player_);
animation_player_->RemoveAnimation(animation_id);
}
+bool LayerAnimator::HasPendingThreadedAnimationsForTesting() const {
+ return animation_player_->has_pending_animations_for_testing();
+}
+
cc::AnimationPlayer* LayerAnimator::GetAnimationPlayerForTesting() const {
return animation_player_.get();
}
@@ -440,7 +453,7 @@ void LayerAnimator::AddToCollection(LayerAnimatorCollection* collection) {
}
void LayerAnimator::RemoveFromCollection(LayerAnimatorCollection* collection) {
- if (is_animating() && is_started_) {
+ if (is_started_) {
collection->StopAnimator(this);
is_started_ = false;
}
@@ -951,6 +964,9 @@ LayerAnimator::RunningAnimation::RunningAnimation(
: sequence_(sequence) {
}
+LayerAnimator::RunningAnimation::RunningAnimation(
+ const RunningAnimation& other) = default;
+
LayerAnimator::RunningAnimation::~RunningAnimation() { }
} // namespace ui
diff --git a/chromium/ui/compositor/layer_animator.h b/chromium/ui/compositor/layer_animator.h
index dc37edcbdce..48e8a1e0ab4 100644
--- a/chromium/ui/compositor/layer_animator.h
+++ b/chromium/ui/compositor/layer_animator.h
@@ -18,6 +18,7 @@
#include "cc/animation/layer_animation_event_observer.h"
#include "ui/compositor/compositor_export.h"
#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_threaded_animation_delegate.h"
#include "ui/gfx/animation/tween.h"
namespace cc {
@@ -25,6 +26,7 @@ class Animation;
class AnimationPlayer;
class AnimationTimeline;
class Layer;
+class LayerAnimationController;
}
namespace gfx {
@@ -53,6 +55,7 @@ class ScopedLayerAnimationSettings;
// must guarantee that |this| is valid.
class COMPOSITOR_EXPORT LayerAnimator
: public base::RefCounted<LayerAnimator>,
+ public LayerThreadedAnimationDelegate,
NON_EXPORTED_BASE(public cc::LayerAnimationEventObserver) {
public:
enum PreemptionStrategy {
@@ -117,11 +120,8 @@ class COMPOSITOR_EXPORT LayerAnimator
// Detach AnimationPlayer from Layer and AnimationTimeline
void ResetCompositor(Compositor* compositor);
- // TODO(loyso): Rework it as an implementation for
- // LayerThreadedAnimationDelegate and make it private.
- void AddThreadedAnimation(scoped_ptr<cc::Animation> animation);
- void RemoveThreadedAnimation(int animation_id);
-
+ // Whether this animator has animations waiting to get sent to cc::LAC.
+ bool HasPendingThreadedAnimationsForTesting() const;
cc::AnimationPlayer* GetAnimationPlayerForTesting() const;
// Sets the animation preemption strategy. This determines the behaviour if
@@ -245,6 +245,7 @@ class COMPOSITOR_EXPORT LayerAnimator
class RunningAnimation {
public:
RunningAnimation(const base::WeakPtr<LayerAnimationSequence>& sequence);
+ RunningAnimation(const RunningAnimation& other);
~RunningAnimation();
bool is_sequence_alive() const { return !!sequence_.get(); }
@@ -341,6 +342,10 @@ class COMPOSITOR_EXPORT LayerAnimator
// LayerAnimationEventObserver
void OnAnimationStarted(const cc::AnimationEvent& event) override;
+ // Implementation of LayerThreadedAnimationDelegate.
+ void AddThreadedAnimation(scoped_ptr<cc::Animation> animation) override;
+ void RemoveThreadedAnimation(int animation_id) override;
+
void AttachLayerToAnimationPlayer(int layer_id);
void DetachLayerFromAnimationPlayer();
@@ -387,6 +392,11 @@ class COMPOSITOR_EXPORT LayerAnimator
// aborted.
base::ObserverList<LayerAnimationObserver> observers_;
+ // We store a state of LayerAnimationController here to save it in
+ // ResetCompositor/SetCompositor scope.
+ // TODO(loyso): Remove it. crbug.com/592873.
+ scoped_refptr<cc::LayerAnimationController> animation_controller_state_;
+
DISALLOW_COPY_AND_ASSIGN(LayerAnimator);
};
diff --git a/chromium/ui/compositor/layer_animator_unittest.cc b/chromium/ui/compositor/layer_animator_unittest.cc
index 30f008b7459..b4afb64cd25 100644
--- a/chromium/ui/compositor/layer_animator_unittest.cc
+++ b/chromium/ui/compositor/layer_animator_unittest.cc
@@ -375,7 +375,7 @@ TEST(LayerAnimatorTest, ScheduleThreadedAnimationThatCanRunImmediately) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta / 2);
@@ -484,7 +484,7 @@ TEST(LayerAnimatorTest, ScheduleThreadedAndNonThreadedAnimations) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta / 2);
@@ -746,7 +746,7 @@ TEST(LayerAnimatorTest, StartThreadedAnimationThatCanRunImmediately) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta / 2);
@@ -870,7 +870,7 @@ TEST(LayerAnimatorTest, PreemptThreadedByImmediatelyAnimatingToNewTarget) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta / 2);
@@ -893,7 +893,7 @@ TEST(LayerAnimatorTest, PreemptThreadedByImmediatelyAnimatingToNewTarget) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, second_effective_start));
+ cc::TargetProperty::OPACITY, second_effective_start));
animator->Step(second_effective_start + delta / 2);
@@ -1193,7 +1193,7 @@ TEST(LayerAnimatorTest, MultiPreemptThreadedByImmediatelyAnimatingToNewTarget) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta / 2);
@@ -1221,7 +1221,7 @@ TEST(LayerAnimatorTest, MultiPreemptThreadedByImmediatelyAnimatingToNewTarget) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, second_effective_start));
+ cc::TargetProperty::OPACITY, second_effective_start));
animator->Step(second_effective_start + delta / 2);
@@ -1465,7 +1465,7 @@ TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, effective_start));
+ cc::TargetProperty::OPACITY, effective_start));
animator->Step(effective_start + delta);
EXPECT_TRUE(test_controller.animator()->is_animating());
@@ -1476,7 +1476,7 @@ TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, second_effective_start));
+ cc::TargetProperty::OPACITY, second_effective_start));
animator->Step(second_effective_start + delta);
@@ -1488,7 +1488,7 @@ TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, third_effective_start));
+ cc::TargetProperty::OPACITY, third_effective_start));
animator->Step(third_effective_start + delta);
EXPECT_TRUE(test_controller.animator()->is_animating());
@@ -1499,7 +1499,7 @@ TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, fourth_effective_start));
+ cc::TargetProperty::OPACITY, fourth_effective_start));
// Skip ahead by a lot.
animator->Step(fourth_effective_start + 1000 * delta);
@@ -1512,7 +1512,7 @@ TEST(LayerAnimatorTest, ThreadedCyclicSequences) {
cc::AnimationEvent::STARTED, 0,
test_controller.GetRunningSequence(LayerAnimationElement::OPACITY)
->animation_group_id(),
- cc::Animation::OPACITY, fifth_effective_start));
+ cc::TargetProperty::OPACITY, fifth_effective_start));
// Skip ahead by a lot.
animator->Step(fifth_effective_start + 999 * delta);
@@ -2526,21 +2526,62 @@ TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) {
Layer layer;
root_1.Add(&layer);
LayerAnimator* animator = layer.GetAnimator();
+ EXPECT_FALSE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
+
double target_opacity = 1.0;
base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+
animator->ScheduleAnimation(new LayerAnimationSequence(
LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
EXPECT_TRUE(compositor_1->layer_animator_collection()->HasActiveAnimators());
EXPECT_FALSE(compositor_2->layer_animator_collection()->HasActiveAnimators());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
root_2.Add(&layer);
EXPECT_FALSE(compositor_1->layer_animator_collection()->HasActiveAnimators());
EXPECT_TRUE(compositor_2->layer_animator_collection()->HasActiveAnimators());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
+
host_2.reset();
host_1.reset();
TerminateContextFactoryForTests();
}
+TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
+ bool enable_pixel_output = false;
+ ui::ContextFactory* context_factory =
+ InitializeContextFactoryForTests(enable_pixel_output);
+ const gfx::Rect bounds(10, 10, 100, 100);
+ scoped_ptr<TestCompositorHost> host(
+ TestCompositorHost::Create(bounds, context_factory));
+ host->Show();
+
+ Compositor* compositor = host->GetCompositor();
+
+ Layer root;
+ compositor->SetRootLayer(&root);
+
+ Layer layer;
+ root.Add(&layer);
+
+ LayerAnimator* animator = layer.GetAnimator();
+ double target_opacity = 1.0;
+ base::TimeDelta time_delta = base::TimeDelta::FromSeconds(1);
+
+ animator->ScheduleAnimation(new LayerAnimationSequence(
+ LayerAnimationElement::CreateOpacityElement(target_opacity, time_delta)));
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
+
+ root.Remove(&layer);
+ EXPECT_FALSE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
+
+ root.Add(&layer);
+ EXPECT_TRUE(layer.cc_layer_for_testing()->HasActiveAnimationForTesting());
+
+ host.reset();
+ TerminateContextFactoryForTests();
+}
+
class LayerOwnerAnimationObserver : public LayerAnimationObserver {
public:
LayerOwnerAnimationObserver(LayerAnimator* animator)
diff --git a/chromium/ui/compositor/layer_owner.cc b/chromium/ui/compositor/layer_owner.cc
index c9180810ebd..44bb322ff6c 100644
--- a/chromium/ui/compositor/layer_owner.cc
+++ b/chromium/ui/compositor/layer_owner.cc
@@ -48,6 +48,8 @@ scoped_ptr<Layer> LayerOwner::RecreateLayer() {
new_layer->SetFillsBoundsOpaquely(old_layer->fills_bounds_opaquely());
new_layer->SetFillsBoundsCompletely(old_layer->FillsBoundsCompletely());
new_layer->SetSubpixelPositionOffset(old_layer->subpixel_position_offset());
+ new_layer->SetLayerInverted(old_layer->layer_inverted());
+ new_layer->SetTransform(old_layer->GetTargetTransform());
if (old_layer->type() == LAYER_SOLID_COLOR)
new_layer->SetColor(old_layer->GetTargetColor());
SkRegion* alpha_shape = old_layer->alpha_shape();
diff --git a/chromium/ui/compositor/layer_owner_unittest.cc b/chromium/ui/compositor/layer_owner_unittest.cc
index afb6b947323..69216aa9c14 100644
--- a/chromium/ui/compositor/layer_owner_unittest.cc
+++ b/chromium/ui/compositor/layer_owner_unittest.cc
@@ -7,7 +7,6 @@
#include "base/macros.h"
#include "base/test/null_task_runner.h"
#include "cc/animation/animation_player.h"
-#include "cc/layers/layer_settings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
@@ -144,6 +143,45 @@ TEST(LayerOwnerTest, RecreateRootLayerWithNullCompositor) {
EXPECT_EQ(nullptr, layer_copy->GetCompositor());
}
+TEST(LayerOwnerTest, InvertPropertyRemainSameWithRecreateLayer) {
+ LayerOwner owner;
+ Layer* layer = new Layer;
+ owner.SetLayer(layer);
+
+ layer->SetLayerInverted(true);
+ scoped_ptr<Layer> old_layer1 = owner.RecreateLayer();
+ EXPECT_EQ(old_layer1->layer_inverted(), owner.layer()->layer_inverted());
+
+ old_layer1->SetLayerInverted(false);
+ scoped_ptr<Layer> old_layer2 = owner.RecreateLayer();
+ EXPECT_EQ(old_layer2->layer_inverted(), owner.layer()->layer_inverted());
+}
+
+TEST(LayerOwnerTest, RecreateLayerWithTransform) {
+ LayerOwner owner;
+ Layer* layer = new Layer;
+ owner.SetLayer(layer);
+
+ gfx::Transform transform;
+ transform.Scale(2, 1);
+ transform.Translate(10, 5);
+
+ layer->SetTransform(transform);
+
+ scoped_ptr<Layer> old_layer1 = owner.RecreateLayer();
+ // Both new layer and original layer have the same transform.
+ EXPECT_EQ(transform, old_layer1->GetTargetTransform());
+ EXPECT_EQ(transform, owner.layer()->GetTargetTransform());
+
+ // But they're now separated, so changing the old layer's transform
+ // should not affect the owner's.
+ owner.layer()->SetTransform(gfx::Transform());
+ EXPECT_EQ(transform, old_layer1->GetTargetTransform());
+ scoped_ptr<Layer> old_layer2 = owner.RecreateLayer();
+ EXPECT_TRUE(old_layer2->GetTargetTransform().IsIdentity());
+ EXPECT_TRUE(owner.layer()->GetTargetTransform().IsIdentity());
+}
+
TEST_F(LayerOwnerTestWithCompositor, RecreateRootLayerWithCompositor) {
LayerOwner owner;
Layer* layer = new Layer;
@@ -228,10 +266,6 @@ TEST_F(LayerOwnerTestWithCompositor, RecreateNonRootLayerDuringAnimation) {
// Tests that if LayerOwner-derived class destroys layer, then
// LayerAnimator's player becomes detached from compositor timeline.
TEST_F(LayerOwnerTestWithCompositor, DetachTimelineOnAnimatorDeletion) {
- // This test is meaningless if CC timelines disabled.
- if (!Layer::UILayerSettings().use_compositor_animation_timelines)
- return;
-
scoped_ptr<Layer> root_layer(new Layer);
compositor()->SetRootLayer(root_layer.get());
@@ -255,10 +289,6 @@ TEST_F(LayerOwnerTestWithCompositor, DetachTimelineOnAnimatorDeletion) {
// then LayerAnimator's player becomes attached to timeline.
TEST_F(LayerOwnerTestWithCompositor,
AttachTimelineIfAnimatorCreatedAfterSetCompositor) {
- // This test is meaningless if CC timelines disabled.
- if (!Layer::UILayerSettings().use_compositor_animation_timelines)
- return;
-
scoped_ptr<Layer> root_layer(new Layer);
compositor()->SetRootLayer(root_layer.get());
diff --git a/chromium/ui/compositor/layer_threaded_animation_delegate.h b/chromium/ui/compositor/layer_threaded_animation_delegate.h
new file mode 100644
index 00000000000..b921077e443
--- /dev/null
+++ b/chromium/ui/compositor/layer_threaded_animation_delegate.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_COMPOSITOR_LAYER_THREADED_ANIMATION_DELEGATE_H_
+#define UI_COMPOSITOR_LAYER_THREADED_ANIMATION_DELEGATE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "cc/animation/animation.h"
+#include "ui/compositor/compositor_export.h"
+
+namespace ui {
+
+// Attach CC animations using this interface.
+class COMPOSITOR_EXPORT LayerThreadedAnimationDelegate {
+ public:
+ virtual void AddThreadedAnimation(scoped_ptr<cc::Animation> animation) = 0;
+ virtual void RemoveThreadedAnimation(int animation_id) = 0;
+
+ protected:
+ virtual ~LayerThreadedAnimationDelegate() {}
+};
+
+} // namespace ui
+
+#endif // UI_COMPOSITOR_LAYER_THREADED_ANIMATION_DELEGATE_H_
diff --git a/chromium/ui/compositor/layer_unittest.cc b/chromium/ui/compositor/layer_unittest.cc
index 70581b6d08e..c62177833f2 100644
--- a/chromium/ui/compositor/layer_unittest.cc
+++ b/chromium/ui/compositor/layer_unittest.cc
@@ -20,16 +20,17 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
-#include "cc/layers/delegated_frame_provider.h"
-#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/layer.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
-#include "cc/output/delegated_frame_data.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_sequence.h"
#include "cc/test/pixel_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/dip_util.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/paint_context.h"
@@ -509,6 +510,23 @@ class LayerWithDelegateTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
};
+void ReturnMailbox(bool* run, const gpu::SyncToken& sync_token, bool is_lost) {
+ *run = true;
+}
+
+TEST(LayerStandaloneTest, ReleaseMailboxOnDestruction) {
+ scoped_ptr<Layer> layer(new Layer(LAYER_TEXTURED));
+ bool callback_run = false;
+ cc::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
+ layer->SetTextureMailbox(mailbox,
+ cc::SingleReleaseCallback::Create(
+ base::Bind(ReturnMailbox, &callback_run)),
+ gfx::Size(10, 10));
+ EXPECT_FALSE(callback_run);
+ layer.reset();
+ EXPECT_TRUE(callback_run);
+}
+
// L1
// +-- L2
TEST_F(LayerWithDelegateTest, ConvertPointToLayer_Simple) {
@@ -696,8 +714,8 @@ TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
scoped_ptr<Layer> layer(CreateLayer(LAYER_NOT_DRAWN));
std::string name = "\"\'\\/\b\f\n\r\t\n";
layer->set_name(name);
- scoped_refptr<base::trace_event::ConvertableToTraceFormat> debug_info =
- layer->TakeDebugInfo(layer->cc_layer_for_testing());
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat> debug_info(
+ layer->TakeDebugInfo(layer->cc_layer_for_testing()));
EXPECT_TRUE(debug_info.get());
std::string json;
debug_info->AppendAsTraceFormat(&json);
@@ -712,10 +730,6 @@ TEST_F(LayerWithNullDelegateTest, EscapedDebugNames) {
EXPECT_EQ(name, roundtrip);
}
-void ReturnMailbox(bool* run, const gpu::SyncToken& sync_token, bool is_lost) {
- *run = true;
-}
-
TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
scoped_ptr<Layer> l1(CreateLayer(LAYER_SOLID_COLOR));
l1->SetFillsBoundsOpaquely(true);
@@ -1472,68 +1486,13 @@ TEST_F(LayerWithDelegateTest, SetBoundsWhenInvisible) {
EXPECT_TRUE(delegate.painted());
}
-static scoped_ptr<cc::DelegatedFrameData> MakeFrameData(gfx::Size size) {
- scoped_ptr<cc::DelegatedFrameData> frame_data(new cc::DelegatedFrameData);
- scoped_ptr<cc::RenderPass> render_pass(cc::RenderPass::Create());
- render_pass->SetNew(
- cc::RenderPassId(1, 1), gfx::Rect(size), gfx::Rect(), gfx::Transform());
- frame_data->render_pass_list.push_back(std::move(render_pass));
- return frame_data;
-}
-
-TEST_F(LayerWithDelegateTest, DelegatedLayer) {
- scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
-
- scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
-
- child->SetBounds(gfx::Rect(0, 0, 10, 10));
- child->SetVisible(true);
- root->Add(child.get());
- DrawTree(root.get());
-
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
- new cc::DelegatedFrameResourceCollection;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider;
+namespace {
- // Content matches layer size.
- frame_provider = new cc::DelegatedFrameProvider(
- resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
- child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(10, 10).ToString());
+void FakeSatisfyCallback(cc::SurfaceSequence) {}
- // Content larger than layer.
- child->SetBounds(gfx::Rect(0, 0, 5, 5));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(5, 5).ToString());
+void FakeRequireCallback(cc::SurfaceId, cc::SurfaceSequence) {}
- // Content smaller than layer.
- child->SetBounds(gfx::Rect(0, 0, 10, 10));
- frame_provider = new cc::DelegatedFrameProvider(
- resource_collection.get(), MakeFrameData(gfx::Size(5, 5)));
- child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(5, 5));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(5, 5).ToString());
-
- // Hi-DPI content on low-DPI layer.
- frame_provider = new cc::DelegatedFrameProvider(
- resource_collection.get(), MakeFrameData(gfx::Size(20, 20)));
- child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(10, 10).ToString());
-
- // Hi-DPI content on hi-DPI layer.
- compositor()->SetScaleAndSize(2.f, gfx::Size(1000, 1000));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(10, 10).ToString());
-
- // Low-DPI content on hi-DPI layer.
- frame_provider = new cc::DelegatedFrameProvider(
- resource_collection.get(), MakeFrameData(gfx::Size(10, 10)));
- child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
- EXPECT_EQ(child->cc_layer_for_testing()->bounds().ToString(),
- gfx::Size(10, 10).ToString());
-}
+} // namespace
TEST_F(LayerWithDelegateTest, ExternalContent) {
scoped_ptr<Layer> root(CreateNoTextureLayer(gfx::Rect(0, 0, 1000, 1000)));
@@ -1550,15 +1509,11 @@ TEST_F(LayerWithDelegateTest, ExternalContent) {
EXPECT_TRUE(child->cc_layer_for_testing());
EXPECT_EQ(before.get(), child->cc_layer_for_testing());
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
- new cc::DelegatedFrameResourceCollection;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
- new cc::DelegatedFrameProvider(resource_collection.get(),
- MakeFrameData(gfx::Size(10, 10)));
-
- // Showing delegated content changes the underlying cc layer.
+ // Showing surface content changes the underlying cc layer.
before = child->cc_layer_for_testing();
- child->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
+ child->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback),
+ base::Bind(&FakeRequireCallback), gfx::Size(10, 10),
+ 1.0, gfx::Size(10, 10));
EXPECT_TRUE(child->cc_layer_for_testing());
EXPECT_NE(before.get(), child->cc_layer_for_testing());
@@ -1581,15 +1536,11 @@ TEST_F(LayerWithDelegateTest, LayerFiltersSurvival) {
EXPECT_EQ(layer->layer_grayscale(), 0.5f);
EXPECT_EQ(1u, layer->cc_layer_for_testing()->filters().size());
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
- new cc::DelegatedFrameResourceCollection;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
- new cc::DelegatedFrameProvider(resource_collection.get(),
- MakeFrameData(gfx::Size(10, 10)));
-
- // Showing delegated content changes the underlying cc layer.
+ // Showing surface content changes the underlying cc layer.
scoped_refptr<cc::Layer> before = layer->cc_layer_for_testing();
- layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
+ layer->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback),
+ base::Bind(&FakeRequireCallback), gfx::Size(10, 10),
+ 1.0, gfx::Size(10, 10));
EXPECT_EQ(layer->layer_grayscale(), 0.5f);
EXPECT_TRUE(layer->cc_layer_for_testing());
EXPECT_NE(before.get(), layer->cc_layer_for_testing());
@@ -1605,41 +1556,41 @@ TEST_F(LayerWithRealCompositorTest, AddRemoveThreadedAnimations) {
l1->SetAnimator(LayerAnimator::CreateImplicitAnimator());
l2->SetAnimator(LayerAnimator::CreateImplicitAnimator());
- EXPECT_FALSE(l1->HasPendingThreadedAnimations());
+ EXPECT_FALSE(l1->HasPendingThreadedAnimationsForTesting());
// Trigger a threaded animation.
l1->SetOpacity(0.5f);
- EXPECT_TRUE(l1->HasPendingThreadedAnimations());
+ EXPECT_TRUE(l1->HasPendingThreadedAnimationsForTesting());
// Ensure we can remove a pending threaded animation.
l1->GetAnimator()->StopAnimating();
- EXPECT_FALSE(l1->HasPendingThreadedAnimations());
+ EXPECT_FALSE(l1->HasPendingThreadedAnimationsForTesting());
// Trigger another threaded animation.
l1->SetOpacity(0.2f);
- EXPECT_TRUE(l1->HasPendingThreadedAnimations());
+ EXPECT_TRUE(l1->HasPendingThreadedAnimationsForTesting());
root->Add(l1.get());
GetCompositor()->SetRootLayer(root.get());
// Now that l1 is part of a tree, it should have dispatched the pending
// animation.
- EXPECT_FALSE(l1->HasPendingThreadedAnimations());
+ EXPECT_FALSE(l1->HasPendingThreadedAnimationsForTesting());
// Ensure that l1 no longer holds on to animations.
l1->SetOpacity(0.1f);
- EXPECT_FALSE(l1->HasPendingThreadedAnimations());
+ EXPECT_FALSE(l1->HasPendingThreadedAnimationsForTesting());
// Ensure that adding a layer to an existing tree causes its pending
// animations to get dispatched.
l2->SetOpacity(0.5f);
- EXPECT_TRUE(l2->HasPendingThreadedAnimations());
+ EXPECT_TRUE(l2->HasPendingThreadedAnimationsForTesting());
l1->Add(l2.get());
- EXPECT_FALSE(l2->HasPendingThreadedAnimations());
+ EXPECT_FALSE(l2->HasPendingThreadedAnimationsForTesting());
}
// Tests that in-progress threaded animations complete when a Layer's
@@ -1785,6 +1736,59 @@ TEST_F(LayerWithDelegateTest, DestroyingLayerRemovesTheAnimatorFromCollection) {
EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
}
+// A LayerAnimationObserver that removes a child layer from a parent when an
+// animation completes.
+class LayerRemovingLayerAnimationObserver : public LayerAnimationObserver {
+ public:
+ LayerRemovingLayerAnimationObserver(Layer* root, Layer* child)
+ : root_(root), child_(child) {}
+
+ // LayerAnimationObserver:
+ void OnLayerAnimationEnded(LayerAnimationSequence* sequence) override {
+ root_->Remove(child_);
+ }
+
+ void OnLayerAnimationAborted(LayerAnimationSequence* sequence) override {
+ root_->Remove(child_);
+ }
+
+ void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override {}
+
+ private:
+ Layer* root_;
+ Layer* child_;
+
+ DISALLOW_COPY_AND_ASSIGN(LayerRemovingLayerAnimationObserver);
+};
+
+// Verifies that empty LayerAnimators are not left behind when removing child
+// Layers that own an empty LayerAnimator. See http://crbug.com/552037.
+TEST_F(LayerWithDelegateTest, NonAnimatingAnimatorsAreRemovedFromCollection) {
+ scoped_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
+ scoped_ptr<Layer> parent(CreateLayer(LAYER_TEXTURED));
+ scoped_ptr<Layer> child(CreateLayer(LAYER_TEXTURED));
+ root->Add(parent.get());
+ parent->Add(child.get());
+ compositor()->SetRootLayer(root.get());
+
+ child->SetAnimator(LayerAnimator::CreateDefaultAnimator());
+
+ LayerRemovingLayerAnimationObserver observer(root.get(), parent.get());
+ child->GetAnimator()->AddObserver(&observer);
+
+ LayerAnimationElement* element =
+ ui::LayerAnimationElement::CreateOpacityElement(
+ 0.5f, base::TimeDelta::FromSeconds(1));
+ LayerAnimationSequence* sequence = new LayerAnimationSequence(element);
+
+ child->GetAnimator()->StartAnimation(sequence);
+ EXPECT_TRUE(compositor()->layer_animator_collection()->HasActiveAnimators());
+
+ child->GetAnimator()->StopAnimating();
+ EXPECT_FALSE(root->Contains(parent.get()));
+ EXPECT_FALSE(compositor()->layer_animator_collection()->HasActiveAnimators());
+}
+
namespace {
std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
@@ -1854,12 +1858,9 @@ TEST(LayerDelegateTest, DelegatedFrameDamage) {
FrameDamageCheckingDelegate delegate;
layer->set_delegate(&delegate);
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection =
- new cc::DelegatedFrameResourceCollection;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider(
- new cc::DelegatedFrameProvider(resource_collection.get(),
- MakeFrameData(gfx::Size(10, 10))));
- layer->SetShowDelegatedContent(frame_provider.get(), gfx::Size(10, 10));
+ layer->SetShowSurface(cc::SurfaceId(), base::Bind(&FakeSatisfyCallback),
+ base::Bind(&FakeRequireCallback), gfx::Size(10, 10),
+ 1.0, gfx::Size(10, 10));
EXPECT_FALSE(delegate.delegated_frame_damage_called());
layer->OnDelegatedFrameDamage(damage_rect);
diff --git a/chromium/ui/compositor/paint_recorder.cc b/chromium/ui/compositor/paint_recorder.cc
index fef53c8a196..163a7a77908 100644
--- a/chromium/ui/compositor/paint_recorder.cc
+++ b/chromium/ui/compositor/paint_recorder.cc
@@ -21,8 +21,7 @@ PaintRecorder::PaintRecorder(const PaintContext& context,
// the recorder_ so no need to store a RefPtr to it on this class, we just
// store the gfx::Canvas.
canvas_(skia::SharePtr(context.recorder_->beginRecording(
- gfx::RectToSkRect(gfx::Rect(recording_size))))
- .get(),
+ gfx::RectToSkRect(gfx::Rect(recording_size)))),
context.device_scale_factor_),
cache_(cache),
bounds_in_layer_(context.ToLayerSpaceBounds(recording_size)) {
@@ -44,7 +43,7 @@ PaintRecorder::~PaintRecorder() {
const auto& item =
context_.list_->CreateAndAppendItem<cc::DrawingDisplayItem>(
bounds_in_layer_,
- skia::AdoptRef(context_.recorder_->endRecordingAsPicture()));
+ context_.recorder_->finishRecordingAsPicture());
if (cache_)
cache_->SetCache(item);
}
diff --git a/chromium/ui/compositor/transform_animation_curve_adapter.cc b/chromium/ui/compositor/transform_animation_curve_adapter.cc
index 5439e0a1ac7..c3f2a31bf50 100644
--- a/chromium/ui/compositor/transform_animation_curve_adapter.cc
+++ b/chromium/ui/compositor/transform_animation_curve_adapter.cc
@@ -21,6 +21,9 @@ TransformAnimationCurveAdapter::TransformAnimationCurveAdapter(
gfx::DecomposeTransform(&decomposed_target_value_, target_value_);
}
+TransformAnimationCurveAdapter::TransformAnimationCurveAdapter(
+ const TransformAnimationCurveAdapter& other) = default;
+
TransformAnimationCurveAdapter::~TransformAnimationCurveAdapter() {
}
diff --git a/chromium/ui/compositor/transform_animation_curve_adapter.h b/chromium/ui/compositor/transform_animation_curve_adapter.h
index 05b5644292e..69332414793 100644
--- a/chromium/ui/compositor/transform_animation_curve_adapter.h
+++ b/chromium/ui/compositor/transform_animation_curve_adapter.h
@@ -23,6 +23,8 @@ class COMPOSITOR_EXPORT TransformAnimationCurveAdapter
gfx::Transform target_value,
base::TimeDelta duration);
+ TransformAnimationCurveAdapter(const TransformAnimationCurveAdapter& other);
+
~TransformAnimationCurveAdapter() override;
// TransformAnimationCurve implementation.
diff --git a/chromium/ui/display/BUILD.gn b/chromium/ui/display/BUILD.gn
index 6c6c181ae1e..226485b3c11 100644
--- a/chromium/ui/display/BUILD.gn
+++ b/chromium/ui/display/BUILD.gn
@@ -5,25 +5,79 @@
import("//build/config/ui.gni")
import("//testing/test.gni")
-if (is_chromeos) {
- component("display") {
- sources = [
- "chromeos/apply_content_protection_task.cc",
- "chromeos/apply_content_protection_task.h",
- "chromeos/configure_displays_task.cc",
- "chromeos/configure_displays_task.h",
- "chromeos/display_configurator.cc",
- "chromeos/display_configurator.h",
- "chromeos/display_layout_manager.h",
- "chromeos/display_snapshot_virtual.cc",
- "chromeos/display_snapshot_virtual.h",
- "chromeos/display_util.cc",
- "chromeos/display_util.h",
- "chromeos/ozone/display_configurator_ozone.cc",
- "chromeos/query_content_protection_task.cc",
- "chromeos/query_content_protection_task.h",
- "chromeos/update_display_configuration_task.cc",
- "chromeos/update_display_configuration_task.h",
+component("display") {
+ sources = [
+ "chromeos/apply_content_protection_task.cc",
+ "chromeos/apply_content_protection_task.h",
+ "chromeos/configure_displays_task.cc",
+ "chromeos/configure_displays_task.h",
+ "chromeos/display_configurator.cc",
+ "chromeos/display_configurator.h",
+ "chromeos/display_layout_manager.h",
+ "chromeos/display_snapshot_virtual.cc",
+ "chromeos/display_snapshot_virtual.h",
+ "chromeos/display_util.cc",
+ "chromeos/display_util.h",
+ "chromeos/ozone/display_configurator_ozone.cc",
+ "chromeos/query_content_protection_task.cc",
+ "chromeos/query_content_protection_task.h",
+ "chromeos/update_display_configuration_task.cc",
+ "chromeos/update_display_configuration_task.h",
+ "chromeos/x11/display_configurator_x11.cc",
+ "chromeos/x11/display_mode_x11.cc",
+ "chromeos/x11/display_mode_x11.h",
+ "chromeos/x11/display_snapshot_x11.cc",
+ "chromeos/x11/display_snapshot_x11.h",
+ "chromeos/x11/display_util_x11.cc",
+ "chromeos/x11/display_util_x11.h",
+ "chromeos/x11/native_display_delegate_x11.cc",
+ "chromeos/x11/native_display_delegate_x11.h",
+ "chromeos/x11/native_display_event_dispatcher_x11.cc",
+ "chromeos/x11/native_display_event_dispatcher_x11.h",
+ "display_export.h",
+ "display_switches.cc",
+ "display_switches.h",
+ "manager/display_layout.cc",
+ "manager/display_layout.h",
+ "manager/display_layout_builder.cc",
+ "manager/display_layout_builder.h",
+ "win/display_info.cc",
+ "win/display_info.h",
+ "win/screen_win.cc",
+ "win/screen_win.h",
+ "win/screen_win_display.cc",
+ "win/screen_win_display.h",
+ ]
+
+ defines = [ "DISPLAY_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ui/display/types",
+ "//ui/display/util",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ ]
+
+ if (is_chromeos && use_x11) {
+ sources -= [ "chromeos/ozone/display_configurator_ozone.cc" ]
+ configs += [
+ "//build/config/linux:x11",
+ "//build/config/linux:xext",
+ "//build/config/linux:xi",
+ "//build/config/linux:xrandr",
+ ]
+ deps += [ "//ui/events/platform" ]
+ }
+
+ deps += []
+ if (use_x11) {
+ deps += [ "//ui/gfx/x" ]
+ }
+
+ if (is_chromeos && use_ozone) {
+ deps += [ "//ui/ozone" ]
+ sources -= [
"chromeos/x11/display_configurator_x11.cc",
"chromeos/x11/display_mode_x11.cc",
"chromeos/x11/display_mode_x11.h",
@@ -35,55 +89,11 @@ if (is_chromeos) {
"chromeos/x11/native_display_delegate_x11.h",
"chromeos/x11/native_display_event_dispatcher_x11.cc",
"chromeos/x11/native_display_event_dispatcher_x11.h",
- "display_export.h",
- "display_switches.cc",
- "display_switches.h",
- ]
-
- defines = [ "DISPLAY_IMPLEMENTATION" ]
-
- deps = [
- "//base",
- "//ui/display/types",
- "//ui/display/util",
- "//ui/gfx",
- "//ui/gfx/geometry",
]
-
- if (use_x11) {
- sources -= [ "chromeos/ozone/display_configurator_ozone.cc" ]
- configs += [
- "//build/config/linux:x11",
- "//build/config/linux:xext",
- "//build/config/linux:xi",
- "//build/config/linux:xrandr",
- ]
- deps += [ "//ui/events/platform" ]
- }
-
- deps += []
- if (use_x11) {
- deps += [ "//ui/gfx/x" ]
- }
-
- if (use_ozone) {
- deps += [ "//ui/ozone" ]
- sources -= [
- "chromeos/x11/display_configurator_x11.cc",
- "chromeos/x11/display_mode_x11.cc",
- "chromeos/x11/display_mode_x11.h",
- "chromeos/x11/display_snapshot_x11.cc",
- "chromeos/x11/display_snapshot_x11.h",
- "chromeos/x11/display_util_x11.cc",
- "chromeos/x11/display_util_x11.h",
- "chromeos/x11/native_display_delegate_x11.cc",
- "chromeos/x11/native_display_delegate_x11.h",
- "chromeos/x11/native_display_event_dispatcher_x11.cc",
- "chromeos/x11/native_display_event_dispatcher_x11.h",
- ]
- }
}
+}
+if (is_chromeos) {
component("test_util") {
output_name = "display_test_util"
sources = [
@@ -103,44 +113,34 @@ if (is_chromeos) {
"//ui/gfx/geometry",
]
}
-
- source_set("test_support") {
- testonly = true
- sources = [
- "chromeos/test/action_logger.cc",
- "chromeos/test/action_logger.h",
- "chromeos/test/action_logger_util.cc",
- "chromeos/test/action_logger_util.h",
- "chromeos/test/test_display_layout_manager.cc",
- "chromeos/test/test_display_layout_manager.h",
- "chromeos/test/test_native_display_delegate.cc",
- "chromeos/test/test_native_display_delegate.h",
- ]
-
- public_deps = [
- ":display",
- ]
- deps = [
- "//base",
- "//ui/display/types",
- "//ui/gfx",
- "//ui/gfx:test_support",
- "//ui/gfx/geometry",
- ]
- }
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("display_unittests_run") {
+source_set("test_support") {
testonly = true
+ sources = [
+ "chromeos/test/action_logger.cc",
+ "chromeos/test/action_logger.h",
+ "chromeos/test/action_logger_util.cc",
+ "chromeos/test/action_logger_util.h",
+ "chromeos/test/test_display_layout_manager.cc",
+ "chromeos/test/test_display_layout_manager.h",
+ "chromeos/test/test_native_display_delegate.cc",
+ "chromeos/test/test_native_display_delegate.h",
+ ]
+
+ public_deps = [
+ ":display",
+ ]
deps = [
- ":display_unittests",
+ "//base",
+ "//ui/display/types",
+ "//ui/gfx",
+ "//ui/gfx:test_support",
+ "//ui/gfx/geometry",
]
}
-# This test covers the ChromeOS "display" target as well as the cross-platform
-# //display/util target.
+# This test covers all testable components in display.
test("display_unittests") {
sources = [
"chromeos/apply_content_protection_task_unittest.cc",
@@ -150,29 +150,32 @@ test("display_unittests") {
"chromeos/update_display_configuration_task_unittest.cc",
"chromeos/x11/display_util_x11_unittest.cc",
"chromeos/x11/native_display_event_dispatcher_x11_unittest.cc",
+ "manager/display_layout_builder_unittest.cc",
"util/display_util_unittest.cc",
"util/edid_parser_unittest.cc",
+ "win/screen_win_unittest.cc",
]
deps = [
+ ":display",
"//base",
"//base/test:run_all_unittests",
+ "//base/test:test_support",
"//testing/gtest",
+ "//ui/display/types",
"//ui/display/util",
+ "//ui/gfx:test_support",
"//ui/gfx/geometry",
]
if (is_chromeos) {
deps += [
- ":display",
":test_support",
":test_util",
- "//base/test:test_support",
- "//ui/display/types",
]
}
- if (use_ozone && is_chromeos) {
+ if (is_chromeos && use_ozone) {
sources -= [
"chromeos/x11/display_util_x11_unittest.cc",
"chromeos/x11/native_display_event_dispatcher_x11_unittest.cc",
diff --git a/chromium/ui/display/DEPS b/chromium/ui/display/DEPS
index 7d1062cee84..e3c5f64e455 100644
--- a/chromium/ui/display/DEPS
+++ b/chromium/ui/display/DEPS
@@ -1,5 +1,4 @@
include_rules = [
"+third_party/cros_system_api",
- "+ui/gfx/display.h",
- "+ui/gfx/geometry",
+ "+ui/gfx",
]
diff --git a/chromium/ui/display/display.gyp b/chromium/ui/display/display.gyp
index fe32ea3bbf7..a5c464489b8 100644
--- a/chromium/ui/display/display.gyp
+++ b/chromium/ui/display/display.gyp
@@ -76,6 +76,16 @@
'display_export.h',
'display_switches.cc',
'display_switches.h',
+ 'manager/display_layout.cc',
+ 'manager/display_layout.h',
+ 'manager/display_layout_builder.cc',
+ 'manager/display_layout_builder.h',
+ 'win/display_info.cc',
+ 'win/display_info.h',
+ 'win/screen_win.cc',
+ 'win/screen_win.h',
+ 'win/screen_win_display.cc',
+ 'win/screen_win_display.h',
],
'conditions': [
['use_x11 == 1', {
@@ -196,6 +206,7 @@
'../../testing/gtest.gyp:gtest',
'../../ui/gfx/gfx.gyp:gfx_geometry',
'../../ui/gfx/gfx.gyp:gfx_test_support',
+ 'display',
'display_util',
],
'include_dirs': [
@@ -209,8 +220,10 @@
'chromeos/update_display_configuration_task_unittest.cc',
'chromeos/x11/display_util_x11_unittest.cc',
'chromeos/x11/native_display_event_dispatcher_x11_unittest.cc',
+ 'manager/display_layout_builder_unittest.cc',
'util/display_util_unittest.cc',
'util/edid_parser_unittest.cc',
+ 'win/screen_win_unittest.cc',
],
'conditions': [
['chromeos == 1', {
diff --git a/chromium/ui/display/display_unittests.isolate b/chromium/ui/display/display_unittests.isolate
index 8122341dcc1..a25fc639d45 100644
--- a/chromium/ui/display/display_unittests.isolate
+++ b/chromium/ui/display/display_unittests.isolate
@@ -3,7 +3,7 @@
# found in the LICENSE file.
{
'conditions': [
- ['OS=="linux"', {
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
'command': [
'../../testing/test_env.py',
diff --git a/chromium/ui/display/manager/display_layout.cc b/chromium/ui/display/manager/display_layout.cc
new file mode 100644
index 00000000000..8812888530e
--- /dev/null
+++ b/chromium/ui/display/manager/display_layout.cc
@@ -0,0 +1,256 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/manager/display_layout.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "ui/gfx/display.h"
+
+namespace display {
+namespace {
+
+// DisplayPlacement Positions
+const char kTop[] = "top";
+const char kRight[] = "right";
+const char kBottom[] = "bottom";
+const char kLeft[] = "left";
+const char kUnknown[] = "unknown";
+
+// The maximum value for 'offset' in DisplayLayout in case of outliers. Need
+// to change this value in case to support even larger displays.
+const int kMaxValidOffset = 10000;
+
+bool IsIdInList(int64_t id, const DisplayIdList& list) {
+ const auto iter =
+ std::find_if(list.begin(), list.end(),
+ [id](int64_t display_id) { return display_id == id; });
+ return iter != list.end();
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// DisplayPlacement
+
+DisplayPlacement::DisplayPlacement()
+ : display_id(gfx::Display::kInvalidDisplayID),
+ parent_display_id(gfx::Display::kInvalidDisplayID),
+ position(DisplayPlacement::RIGHT),
+ offset(0) {}
+
+DisplayPlacement::DisplayPlacement(Position pos, int offset)
+ : display_id(gfx::Display::kInvalidDisplayID),
+ parent_display_id(gfx::Display::kInvalidDisplayID),
+ position(pos),
+ offset(offset) {
+ DCHECK_LE(TOP, position);
+ DCHECK_GE(LEFT, position);
+ // Set the default value to |position| in case position is invalid. DCHECKs
+ // above doesn't stop in Release builds.
+ if (TOP > position || LEFT < position)
+ this->position = RIGHT;
+
+ DCHECK_GE(kMaxValidOffset, abs(offset));
+}
+
+DisplayPlacement::DisplayPlacement(const DisplayPlacement& placement)
+ : display_id(placement.display_id),
+ parent_display_id(placement.parent_display_id),
+ position(placement.position),
+ offset(placement.offset) {}
+
+DisplayPlacement& DisplayPlacement::Swap() {
+ switch (position) {
+ case TOP:
+ position = BOTTOM;
+ break;
+ case BOTTOM:
+ position = TOP;
+ break;
+ case RIGHT:
+ position = LEFT;
+ break;
+ case LEFT:
+ position = RIGHT;
+ break;
+ }
+ offset = -offset;
+ std::swap(display_id, parent_display_id);
+ return *this;
+}
+
+std::string DisplayPlacement::ToString() const {
+ std::stringstream s;
+ if (display_id != gfx::Display::kInvalidDisplayID)
+ s << "id=" << display_id << ", ";
+ if (parent_display_id != gfx::Display::kInvalidDisplayID)
+ s << "parent=" << parent_display_id << ", ";
+ s << PositionToString(position) << ", ";
+ s << offset;
+ return s.str();
+}
+
+// static
+std::string DisplayPlacement::PositionToString(Position position) {
+ switch (position) {
+ case TOP:
+ return kTop;
+ case RIGHT:
+ return kRight;
+ case BOTTOM:
+ return kBottom;
+ case LEFT:
+ return kLeft;
+ }
+ return kUnknown;
+}
+
+// static
+bool DisplayPlacement::StringToPosition(const base::StringPiece& string,
+ Position* position) {
+ if (string == kTop) {
+ *position = TOP;
+ return true;
+ }
+
+ if (string == kRight) {
+ *position = RIGHT;
+ return true;
+ }
+
+ if (string == kBottom) {
+ *position = BOTTOM;
+ return true;
+ }
+
+ if (string == kLeft) {
+ *position = LEFT;
+ return true;
+ }
+
+ LOG(ERROR) << "Invalid position value:" << string;
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DisplayLayout
+
+DisplayLayout::DisplayLayout()
+ : mirrored(false),
+ default_unified(true),
+ primary_id(gfx::Display::kInvalidDisplayID) {}
+
+DisplayLayout::~DisplayLayout() {}
+
+// static
+bool DisplayLayout::Validate(const DisplayIdList& list,
+ const DisplayLayout& layout) {
+ // The primary display should be in the list.
+ DCHECK(IsIdInList(layout.primary_id, list));
+
+ // Unified mode, or mirror mode switched from unified mode,
+ // may not have the placement yet.
+ if (layout.placement_list.size() == 0u)
+ return true;
+
+ bool has_primary_as_parent = false;
+ int64_t id = 0;
+
+ for (const auto& placement : layout.placement_list) {
+ // Placements are sorted by display_id.
+ if (id >= placement.display_id) {
+ LOG(ERROR) << "PlacementList must be sorted by display_id";
+ return false;
+ }
+ if (placement.display_id == gfx::Display::kInvalidDisplayID) {
+ LOG(ERROR) << "display_id is not initialized";
+ return false;
+ }
+ if (placement.parent_display_id == gfx::Display::kInvalidDisplayID) {
+ LOG(ERROR) << "display_parent_id is not initialized";
+ return false;
+ }
+ if (placement.display_id == placement.parent_display_id) {
+ LOG(ERROR) << "display_id must not be same as parent_display_id";
+ return false;
+ }
+ if (!IsIdInList(placement.display_id, list)) {
+ LOG(ERROR) << "display_id is not in the id list:" << placement.ToString();
+ return false;
+ }
+
+ if (!IsIdInList(placement.parent_display_id, list)) {
+ LOG(ERROR) << "parent_display_id is not in the id list:"
+ << placement.ToString();
+ return false;
+ }
+ has_primary_as_parent |= layout.primary_id == placement.parent_display_id;
+ }
+ if (!has_primary_as_parent)
+ LOG(ERROR) << "At least, one placement must have the primary as a parent.";
+ return has_primary_as_parent;
+}
+
+scoped_ptr<DisplayLayout> DisplayLayout::Copy() const {
+ scoped_ptr<DisplayLayout> copy(new DisplayLayout);
+ for (const auto& placement : placement_list)
+ copy->placement_list.push_back(placement);
+ copy->mirrored = mirrored;
+ copy->default_unified = default_unified;
+ copy->primary_id = primary_id;
+ return copy;
+}
+
+bool DisplayLayout::HasSamePlacementList(const DisplayLayout& layout) const {
+ if (placement_list.size() != layout.placement_list.size())
+ return false;
+ for (size_t index = 0; index < placement_list.size(); index++) {
+ const DisplayPlacement& placement1 = placement_list[index];
+ const DisplayPlacement& placement2 = layout.placement_list[index];
+ if (placement1.position != placement2.position ||
+ placement1.offset != placement2.offset ||
+ placement1.display_id != placement2.display_id ||
+ placement1.parent_display_id != placement2.parent_display_id) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string DisplayLayout::ToString() const {
+ std::stringstream s;
+ s << "primary=" << primary_id;
+ if (mirrored)
+ s << ", mirrored";
+ if (default_unified)
+ s << ", default_unified";
+ bool added = false;
+ for (const auto& placement : placement_list) {
+ s << (added ? "),(" : " [(");
+ s << placement.ToString();
+ added = true;
+ }
+ if (added)
+ s << ")]";
+ return s.str();
+}
+
+DisplayPlacement DisplayLayout::FindPlacementById(int64_t display_id) const {
+ const auto iter =
+ std::find_if(placement_list.begin(), placement_list.end(),
+ [display_id](const DisplayPlacement& placement) {
+ return placement.display_id == display_id;
+ });
+ return (iter == placement_list.end()) ? DisplayPlacement()
+ : DisplayPlacement(*iter);
+}
+
+} // namespace display
diff --git a/chromium/ui/display/manager/display_layout.h b/chromium/ui/display/manager/display_layout.h
new file mode 100644
index 00000000000..7f5c99c8282
--- /dev/null
+++ b/chromium/ui/display/manager/display_layout.h
@@ -0,0 +1,114 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
+#define UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "ui/display/display_export.h"
+
+namespace base {
+class Value;
+template <typename T> class JSONValueConverter;
+}
+
+namespace gfx {
+class Display;
+}
+
+namespace display {
+
+// An identifier used to manage display layout in DisplayManager /
+// DisplayLayoutStore.
+using DisplayIdList = std::vector<int64_t>;
+
+using DisplayList = std::vector<gfx::Display>;
+
+// DisplayPlacement specifies where the display (D) is placed relative
+// to parent (P) display. In the following example, the display (D)
+// given by |display_id| is placed at the left side of the parent
+// display (P) given by |parent_display_id|, with a negative offset.
+//
+// + +--------+
+// offset | | |
+// + | D +--------+
+// | | |
+// +--------+ P |
+// | |
+// +--------+
+//
+struct DISPLAY_EXPORT DisplayPlacement {
+ // The id of the display this placement will be applied to.
+ int64_t display_id;
+
+ // The parent display id to which the above display is placed.
+ int64_t parent_display_id;
+
+ // To which side the parent display the display is positioned.
+ enum Position { TOP, RIGHT, BOTTOM, LEFT };
+ Position position;
+
+ // The offset of the position of the secondary display. The offset is
+ // based on the top/left edge of the primary display.
+ int offset;
+
+ DisplayPlacement(Position position, int offset);
+ DisplayPlacement();
+ DisplayPlacement(const DisplayPlacement& placement);
+
+ DisplayPlacement& Swap();
+
+ std::string ToString() const;
+
+ static std::string PositionToString(Position position);
+ static bool StringToPosition(const base::StringPiece& string,
+ Position* position);
+};
+
+class DISPLAY_EXPORT DisplayLayout final {
+ public:
+ DisplayLayout();
+ ~DisplayLayout();
+
+ // Validates the layout object.
+ static bool Validate(const DisplayIdList& list, const DisplayLayout& layout);
+
+ std::vector<DisplayPlacement> placement_list;
+
+ // True if displays are mirrored.
+ bool mirrored;
+
+ // True if multi displays should default to unified mode.
+ bool default_unified;
+
+ // The id of the display used as a primary display.
+ int64_t primary_id;
+
+ scoped_ptr<DisplayLayout> Copy() const;
+
+ // Test if the |layout| has the same placement list. Other fields such
+ // as mirrored, primary_id are ignored.
+ bool HasSamePlacementList(const DisplayLayout& layout) const;
+
+ // Returns string representation of the layout for debugging/testing.
+ std::string ToString() const;
+
+ // Returns the DisplayPlacement entry matching |display_id| if it exists,
+ // otherwise returns a DisplayPlacement with an invalid display id.
+ DisplayPlacement FindPlacementById(int64_t display_id) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DisplayLayout);
+};
+
+} // namespace display
+
+#endif // UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_H_
diff --git a/chromium/ui/display/manager/display_layout_builder.cc b/chromium/ui/display/manager/display_layout_builder.cc
new file mode 100644
index 00000000000..8376e74313d
--- /dev/null
+++ b/chromium/ui/display/manager/display_layout_builder.cc
@@ -0,0 +1,68 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/manager/display_layout_builder.h"
+
+#include <algorithm>
+
+namespace display {
+
+DisplayLayoutBuilder::DisplayLayoutBuilder(const DisplayLayout& layout)
+ : layout_(layout.Copy()) {}
+
+DisplayLayoutBuilder::DisplayLayoutBuilder(int64_t primary_id)
+ : layout_(new DisplayLayout) {
+ layout_->primary_id = primary_id;
+}
+
+DisplayLayoutBuilder::~DisplayLayoutBuilder() {}
+
+DisplayLayoutBuilder& DisplayLayoutBuilder::SetDefaultUnified(
+ bool default_unified) {
+ layout_->default_unified = default_unified;
+ return *this;
+}
+
+DisplayLayoutBuilder& DisplayLayoutBuilder::SetMirrored(bool mirrored) {
+ layout_->mirrored = mirrored;
+ return *this;
+}
+
+DisplayLayoutBuilder& DisplayLayoutBuilder::ClearPlacements() {
+ layout_->placement_list.clear();
+ return *this;
+}
+
+DisplayLayoutBuilder& DisplayLayoutBuilder::AddDisplayPlacement(
+ int64_t display_id,
+ int64_t parent_display_id,
+ DisplayPlacement::Position position,
+ int offset) {
+ DisplayPlacement placement;
+ placement.position = position;
+ placement.offset = offset;
+ placement.display_id = display_id;
+ placement.parent_display_id = parent_display_id;
+ layout_->placement_list.push_back(placement);
+ return *this;
+}
+
+DisplayLayoutBuilder& DisplayLayoutBuilder::SetSecondaryPlacement(
+ int64_t secondary_id,
+ DisplayPlacement::Position position,
+ int offset) {
+ layout_->placement_list.clear();
+ AddDisplayPlacement(secondary_id, layout_->primary_id, position, offset);
+ return *this;
+}
+
+scoped_ptr<DisplayLayout> DisplayLayoutBuilder::Build() {
+ std::sort(layout_->placement_list.begin(), layout_->placement_list.end(),
+ [](const DisplayPlacement& a, const DisplayPlacement& b) {
+ return a.display_id < b.display_id;
+ });
+ return std::move(layout_);
+}
+
+} // namespace display
diff --git a/chromium/ui/display/manager/display_layout_builder.h b/chromium/ui/display/manager/display_layout_builder.h
new file mode 100644
index 00000000000..9b3caefac62
--- /dev/null
+++ b/chromium/ui/display/manager/display_layout_builder.h
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
+#define UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/display/display_export.h"
+#include "ui/display/manager/display_layout.h"
+
+namespace display {
+
+class DisplayLayout;
+
+// A utility class to create a DisplayLayout instance.
+class DISPLAY_EXPORT DisplayLayoutBuilder final {
+ public:
+ // Creates a builder that uses a copy of the |layout| as a source.
+ explicit DisplayLayoutBuilder(const DisplayLayout& layout);
+
+ // Creates a builder with the primary display id.
+ explicit DisplayLayoutBuilder(int64_t primary_id);
+
+ ~DisplayLayoutBuilder();
+
+ DisplayLayoutBuilder& SetDefaultUnified(bool default_unified);
+
+ DisplayLayoutBuilder& SetMirrored(bool mirrored);
+
+ DisplayLayoutBuilder& ClearPlacements();
+
+ // Adds a display placement.
+ DisplayLayoutBuilder& AddDisplayPlacement(int64_t display_id,
+ int64_t parent_id,
+ DisplayPlacement::Position position,
+ int offset);
+
+ // Sets the display placement for the secondary display.
+ DisplayLayoutBuilder& SetSecondaryPlacement(
+ int64_t secondary_id,
+ DisplayPlacement::Position position,
+ int offset);
+
+ // Returns the DisplayLayout. After this call, the builder becomes invalid.
+ scoped_ptr<DisplayLayout> Build();
+
+ private:
+ scoped_ptr<DisplayLayout> layout_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayLayoutBuilder);
+};
+
+} // namespace display
+
+#endif // UI_DISPLAY_MANAGER_DISPLAY_LAYOUT_BUILDER_H_
diff --git a/chromium/ui/display/manager/display_layout_builder_unittest.cc b/chromium/ui/display/manager/display_layout_builder_unittest.cc
new file mode 100644
index 00000000000..591a16cbd29
--- /dev/null
+++ b/chromium/ui/display/manager/display_layout_builder_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/manager/display_layout_builder.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace display {
+
+TEST(DisplayLayoutBuilderTest, SecondaryPlacement) {
+ DisplayLayoutBuilder builder(1);
+ builder.SetSecondaryPlacement(2, DisplayPlacement::LEFT, 30);
+ scoped_ptr<DisplayLayout> layout(builder.Build());
+ ASSERT_EQ(1u, layout->placement_list.size());
+
+ EXPECT_EQ(2, layout->placement_list[0].display_id);
+ EXPECT_EQ(1, layout->placement_list[0].parent_display_id);
+ EXPECT_EQ(30, layout->placement_list[0].offset);
+ EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0].position);
+}
+
+TEST(DisplayLayoutBuilderTest, MultiplePlacement) {
+ DisplayLayoutBuilder builder(1);
+ builder.AddDisplayPlacement(5, 1, DisplayPlacement::TOP, 30);
+ builder.AddDisplayPlacement(3, 5, DisplayPlacement::LEFT, 20);
+ builder.AddDisplayPlacement(4, 5, DisplayPlacement::RIGHT, 10);
+ scoped_ptr<DisplayLayout> layout(builder.Build());
+
+ ASSERT_EQ(3u, layout->placement_list.size());
+
+ // placmenets are sorted by display_id.
+ EXPECT_EQ(3, layout->placement_list[0].display_id);
+ EXPECT_EQ(5, layout->placement_list[0].parent_display_id);
+ EXPECT_EQ(20, layout->placement_list[0].offset);
+ EXPECT_EQ(DisplayPlacement::LEFT, layout->placement_list[0].position);
+
+ EXPECT_EQ(4, layout->placement_list[1].display_id);
+ EXPECT_EQ(5, layout->placement_list[1].parent_display_id);
+ EXPECT_EQ(10, layout->placement_list[1].offset);
+ EXPECT_EQ(DisplayPlacement::RIGHT, layout->placement_list[1].position);
+
+ EXPECT_EQ(5, layout->placement_list[2].display_id);
+ EXPECT_EQ(1, layout->placement_list[2].parent_display_id);
+ EXPECT_EQ(30, layout->placement_list[2].offset);
+ EXPECT_EQ(DisplayPlacement::TOP, layout->placement_list[2].position);
+}
+
+} // namespace display
diff --git a/chromium/ui/display/types/display_snapshot.cc b/chromium/ui/display/types/display_snapshot.cc
index 30e3ea890b2..c3f6e382f74 100644
--- a/chromium/ui/display/types/display_snapshot.cc
+++ b/chromium/ui/display/types/display_snapshot.cc
@@ -4,17 +4,31 @@
#include "ui/display/types/display_snapshot.h"
+#include <algorithm>
+
namespace ui {
+namespace {
+
+// The display serial number beginning byte position and its length in the
+// EDID number as defined in the spec.
+// https://en.wikipedia.org/wiki/Extended_Display_Identification_Data
+const size_t kSerialNumberBeginingByte = 12U;
+const size_t kSerialNumberLengthInBytes = 4U;
+
+} // namespace
+
DisplaySnapshot::DisplaySnapshot(int64_t display_id,
const gfx::Point& origin,
const gfx::Size& physical_size,
DisplayConnectionType type,
bool is_aspect_preserving_scaling,
bool has_overscan,
+ bool has_color_correction_matrix,
std::string display_name,
const base::FilePath& sys_path,
const std::vector<const DisplayMode*>& modes,
+ const std::vector<uint8_t>& edid,
const DisplayMode* current_mode,
const DisplayMode* native_mode)
: display_id_(display_id),
@@ -23,12 +37,21 @@ DisplaySnapshot::DisplaySnapshot(int64_t display_id,
type_(type),
is_aspect_preserving_scaling_(is_aspect_preserving_scaling),
has_overscan_(has_overscan),
+ has_color_correction_matrix_(has_color_correction_matrix),
display_name_(display_name),
sys_path_(sys_path),
modes_(modes),
+ edid_(edid),
current_mode_(current_mode),
native_mode_(native_mode),
- product_id_(kInvalidProductID) {}
+ product_id_(kInvalidProductID) {
+ // We must explicitly clear out the bytes that represent the serial number.
+ const size_t end =
+ std::min(kSerialNumberBeginingByte + kSerialNumberLengthInBytes,
+ edid_.size());
+ for (size_t i = kSerialNumberBeginingByte; i < end; ++i)
+ edid_[i] = 0;
+}
DisplaySnapshot::~DisplaySnapshot() {}
diff --git a/chromium/ui/display/types/display_snapshot.h b/chromium/ui/display/types/display_snapshot.h
index 7f697984fe5..d7106916bc0 100644
--- a/chromium/ui/display/types/display_snapshot.h
+++ b/chromium/ui/display/types/display_snapshot.h
@@ -29,9 +29,11 @@ class DISPLAY_TYPES_EXPORT DisplaySnapshot {
DisplayConnectionType type,
bool is_aspect_preserving_scaling,
bool has_overscan,
+ bool has_color_correction_matrix,
std::string display_name,
const base::FilePath& sys_path,
const std::vector<const DisplayMode*>& modes,
+ const std::vector<uint8_t>& edid,
const DisplayMode* current_mode,
const DisplayMode* native_mode);
virtual ~DisplaySnapshot();
@@ -53,11 +55,17 @@ class DISPLAY_TYPES_EXPORT DisplaySnapshot {
int64_t product_id() const { return product_id_; }
const std::vector<const DisplayMode*>& modes() const { return modes_; }
+ const std::vector<uint8_t>& edid() const { return edid_; }
void set_current_mode(const DisplayMode* mode) { current_mode_ = mode; }
void set_origin(const gfx::Point& origin) { origin_ = origin; }
void add_mode(const DisplayMode* mode) { modes_.push_back(mode); }
+ // Whether this display has advanced color correction available.
+ bool has_color_correction_matrix() const {
+ return has_color_correction_matrix_;
+ }
+
// Returns a textual representation of this display state.
virtual std::string ToString() const = 0;
@@ -79,12 +87,18 @@ class DISPLAY_TYPES_EXPORT DisplaySnapshot {
bool has_overscan_;
+ bool has_color_correction_matrix_;
+
std::string display_name_;
base::FilePath sys_path_;
std::vector<const DisplayMode*> modes_; // Not owned.
+ // The display's EDID. It can be empty if nothing extracted such as in the
+ // case of a virtual display.
+ std::vector<uint8_t> edid_;
+
// Mode currently being used by the output.
const DisplayMode* current_mode_;
diff --git a/chromium/ui/display/types/native_display_delegate.h b/chromium/ui/display/types/native_display_delegate.h
index bf59dca8ff0..b17be8f1cff 100644
--- a/chromium/ui/display/types/native_display_delegate.h
+++ b/chromium/ui/display/types/native_display_delegate.h
@@ -107,9 +107,12 @@ class DISPLAY_TYPES_EXPORT NativeDisplayDelegate {
const ui::DisplaySnapshot& output,
ui::ColorCalibrationProfile new_profile) = 0;
- // Set the gamma ramp for the display.
- virtual bool SetGammaRamp(const ui::DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& lut) = 0;
+ // Set the gamma tables and corection matrix for the display.
+ virtual bool SetColorCorrection(
+ const ui::DisplaySnapshot& output,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) = 0;
virtual void AddObserver(NativeDisplayObserver* observer) = 0;
diff --git a/chromium/ui/display/util/x11/edid_parser_x11.cc b/chromium/ui/display/util/x11/edid_parser_x11.cc
index 13059f0fea1..01b6f00e94b 100644
--- a/chromium/ui/display/util/x11/edid_parser_x11.cc
+++ b/chromium/ui/display/util/x11/edid_parser_x11.cc
@@ -75,48 +75,35 @@ bool GetEDIDProperty(XID output, std::vector<uint8_t>* edid) {
return true;
}
-// Gets some useful data from the specified output device, such like
-// manufacturer's ID, product code, and human readable name. Returns false if it
-// fails to get those data and doesn't touch manufacturer ID/product code/name.
-// nullptr can be passed for unwanted output parameters.
-bool GetOutputDeviceData(XID output,
- uint16_t* manufacturer_id,
- std::string* human_readable_name) {
- std::vector<uint8_t> edid;
- if (!GetEDIDProperty(output, &edid))
- return false;
+} // namespace
- return ParseOutputDeviceData(edid, manufacturer_id, nullptr,
- human_readable_name, nullptr, nullptr);
+EDIDParserX11::EDIDParserX11(XID output_id)
+ : output_id_(output_id) {
+ GetEDIDProperty(output_id_, &edid_);
}
-} // namespace
+EDIDParserX11::~EDIDParserX11() {
+}
-bool GetDisplayId(XID output_id,
- uint8_t output_index,
- int64_t* display_id_out) {
- std::vector<uint8_t> edid;
- if (!GetEDIDProperty(output_id, &edid))
+bool EDIDParserX11::GetDisplayId(uint8_t index, int64_t* out_display_id) const {
+ if (edid_.empty())
return false;
- bool result =
- GetDisplayIdFromEDID(edid, output_index, display_id_out, nullptr);
- return result;
+ return GetDisplayIdFromEDID(edid_, index, out_display_id, nullptr);
}
-std::string GetDisplayName(RROutput output) {
+std::string EDIDParserX11::GetDisplayName() const {
std::string display_name;
- GetOutputDeviceData(output, nullptr, &display_name);
+ ParseOutputDeviceData(edid_, nullptr, nullptr, &display_name, nullptr,
+ nullptr);
return display_name;
}
-bool GetOutputOverscanFlag(RROutput output, bool* flag) {
- std::vector<uint8_t> edid;
- if (!GetEDIDProperty(output, &edid))
+bool EDIDParserX11::GetOutputOverscanFlag(bool* out_flag) const {
+ if (edid_.empty())
return false;
- bool found = ParseOutputOverscanFlag(edid, flag);
- return found;
+ return ParseOutputOverscanFlag(edid_, out_flag);
}
} // namespace ui
diff --git a/chromium/ui/display/util/x11/edid_parser_x11.h b/chromium/ui/display/util/x11/edid_parser_x11.h
index 55048e699e4..43f8cd1a48f 100644
--- a/chromium/ui/display/util/x11/edid_parser_x11.h
+++ b/chromium/ui/display/util/x11/edid_parser_x11.h
@@ -8,7 +8,9 @@
#include <stdint.h>
#include <string>
+#include <vector>
+#include "base/macros.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/util/display_util_export.h"
@@ -19,21 +21,39 @@ typedef XID RROutput;
namespace ui {
-// Gets the EDID data from |output| and generates the display id through
-// |GetDisplayIdFromEDID|.
-DISPLAY_UTIL_EXPORT bool GetDisplayId(XID output,
- uint8_t index,
- int64_t* display_id_out);
-
-// Generate the human readable string from EDID obtained from |output|.
-DISPLAY_UTIL_EXPORT std::string GetDisplayName(RROutput output);
-
-// Gets the overscan flag from |output| and stores to |flag|. Returns true if
-// the flag is found. Otherwise returns false and doesn't touch |flag|. The
-// output will produce overscan if |flag| is set to true, but the output may
-// still produce overscan even though it returns true and |flag| is set to
-// false.
-DISPLAY_UTIL_EXPORT bool GetOutputOverscanFlag(RROutput output, bool* flag);
+// Xrandr utility class to help get EDID information.
+class DISPLAY_UTIL_EXPORT EDIDParserX11 {
+ public:
+ EDIDParserX11(XID output_id);
+ ~EDIDParserX11();
+
+ // Sets |out_display_id| to the display ID from the EDID of this output.
+ // Returns true if successful, false otherwise.
+ bool GetDisplayId(uint8_t index, int64_t* out_display_id) const;
+
+ // Generate the human readable string from EDID obtained from |output|.
+ // Returns an empty string upon error.
+ std::string GetDisplayName() const;
+
+ // Gets the overscan flag and stores to |out_flag|. Returns true if the flag
+ // is found. Otherwise returns false and doesn't touch |out_flag|. The output
+ // will produce overscan if |out_flag| is set to true, but the output may
+ // still produce overscan even though it returns true and |out_flag| is set to
+ // false.
+ bool GetOutputOverscanFlag(bool* out_flag) const;
+
+ XID output_id() const { return output_id_; }
+ const std::vector<uint8_t>& edid() const { return edid_; }
+
+ private:
+ XID output_id_;
+
+ // This will be an empty vector upon failure to get the EDID from the
+ // |output_id_|.
+ std::vector<uint8_t> edid_;
+
+ DISALLOW_COPY_AND_ASSIGN(EDIDParserX11);
+};
} // namespace ui
diff --git a/chromium/ui/display/win/display_info.cc b/chromium/ui/display/win/display_info.cc
new file mode 100644
index 00000000000..1b78fb7266d
--- /dev/null
+++ b/chromium/ui/display/win/display_info.cc
@@ -0,0 +1,60 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/win/display_info.h"
+
+#include "base/hash.h"
+#include "base/strings/utf_string_conversions.h"
+
+namespace {
+
+gfx::Display::Rotation GetRotationForDevice(const wchar_t* device_name) {
+ DEVMODE mode;
+ ::ZeroMemory(&mode, sizeof(mode));
+ mode.dmSize = sizeof(mode);
+ mode.dmDriverExtra = 0;
+ if (::EnumDisplaySettings(device_name, ENUM_CURRENT_SETTINGS, &mode)) {
+ switch (mode.dmDisplayOrientation) {
+ case DMDO_DEFAULT:
+ return gfx::Display::ROTATE_0;
+ case DMDO_90:
+ return gfx::Display::ROTATE_90;
+ case DMDO_180:
+ return gfx::Display::ROTATE_180;
+ case DMDO_270:
+ return gfx::Display::ROTATE_270;
+ default:
+ NOTREACHED();
+ }
+ }
+ return gfx::Display::ROTATE_0;
+}
+
+} // namespace
+
+namespace display {
+namespace win {
+
+DisplayInfo::DisplayInfo(const MONITORINFOEX& monitor_info,
+ float device_scale_factor)
+ : DisplayInfo(monitor_info,
+ device_scale_factor,
+ GetRotationForDevice(monitor_info.szDevice)) {}
+
+DisplayInfo::DisplayInfo(const MONITORINFOEX& monitor_info,
+ float device_scale_factor,
+ gfx::Display::Rotation rotation)
+ : id_(DeviceIdFromDeviceName(monitor_info.szDevice)),
+ rotation_(rotation),
+ screen_rect_(monitor_info.rcMonitor),
+ screen_work_rect_(monitor_info.rcWork),
+ device_scale_factor_(device_scale_factor) {}
+
+// static
+int64_t DisplayInfo::DeviceIdFromDeviceName(const wchar_t* device_name) {
+ return static_cast<int64_t>(base::Hash(base::WideToUTF8(device_name)));
+}
+
+} // namespace win
+} // namespace display
diff --git a/chromium/ui/display/win/display_info.h b/chromium/ui/display/win/display_info.h
new file mode 100644
index 00000000000..d9abdc3f2a7
--- /dev/null
+++ b/chromium/ui/display/win/display_info.h
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_WIN_DISPLAY_INFO_H_
+#define UI_DISPLAY_WIN_DISPLAY_INFO_H_
+
+#include <windows.h>
+#include <stdint.h>
+
+#include "ui/display/display_export.h"
+#include "ui/gfx/display.h"
+
+namespace display {
+namespace win {
+
+// Gathers the parameters necessary to create a display::win::ScreenWinDisplay.
+class DISPLAY_EXPORT DisplayInfo final {
+ public:
+ DisplayInfo(const MONITORINFOEX& monitor_info, float device_scale_factor);
+ DisplayInfo(const MONITORINFOEX& monitor_info,
+ float device_scale_factor,
+ gfx::Display::Rotation rotation);
+
+ static int64_t DeviceIdFromDeviceName(const wchar_t* device_name);
+
+ int64_t id() const { return id_; }
+ gfx::Display::Rotation rotation() const { return rotation_; }
+ const gfx::Rect& screen_rect() const { return screen_rect_; }
+ const gfx::Rect& screen_work_rect() const { return screen_work_rect_; }
+ float device_scale_factor() const { return device_scale_factor_; }
+
+ private:
+ int64_t id_;
+ gfx::Display::Rotation rotation_;
+ gfx::Rect screen_rect_;
+ gfx::Rect screen_work_rect_;
+ float device_scale_factor_;
+};
+
+} // namespace win
+} // namespace display
+
+#endif // UI_DISPLAY_WIN_DISPLAY_INFO_H_
diff --git a/chromium/ui/display/win/screen_win.cc b/chromium/ui/display/win/screen_win.cc
new file mode 100644
index 00000000000..96d880f4d51
--- /dev/null
+++ b/chromium/ui/display/win/screen_win.cc
@@ -0,0 +1,242 @@
+// 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/display/win/screen_win.h"
+
+#include <windows.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "ui/display/win/display_info.h"
+#include "ui/display/win/screen_win_display.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/win/dpi.h"
+
+namespace display {
+namespace win {
+
+namespace {
+
+std::vector<ScreenWinDisplay> DisplayInfosToScreenWinDisplays(
+ const std::vector<DisplayInfo>& display_infos) {
+ std::vector<ScreenWinDisplay> screen_win_displays;
+ for (const auto& display_info : display_infos)
+ screen_win_displays.push_back(ScreenWinDisplay(display_info));
+
+ return screen_win_displays;
+}
+
+std::vector<gfx::Display> ScreenWinDisplaysToDisplays(
+ const std::vector<ScreenWinDisplay>& screen_win_displays) {
+ std::vector<gfx::Display> displays;
+ for (const auto& screen_win_display : screen_win_displays)
+ displays.push_back(screen_win_display.display());
+
+ return displays;
+}
+
+MONITORINFOEX MonitorInfoFromHMONITOR(HMONITOR monitor) {
+ MONITORINFOEX monitor_info;
+ ::ZeroMemory(&monitor_info, sizeof(monitor_info));
+ monitor_info.cbSize = sizeof(monitor_info);
+ ::GetMonitorInfo(monitor, &monitor_info);
+ return monitor_info;
+}
+
+BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
+ HDC hdc,
+ LPRECT rect,
+ LPARAM data) {
+ std::vector<DisplayInfo>* display_infos =
+ reinterpret_cast<std::vector<DisplayInfo>*>(data);
+ DCHECK(display_infos);
+ display_infos->push_back(DisplayInfo(MonitorInfoFromHMONITOR(monitor),
+ gfx::GetDPIScale()));
+ return TRUE;
+}
+
+std::vector<DisplayInfo> GetDisplayInfosFromSystem() {
+ std::vector<DisplayInfo> display_infos;
+ EnumDisplayMonitors(nullptr, nullptr, EnumMonitorCallback,
+ reinterpret_cast<LPARAM>(&display_infos));
+ DCHECK_EQ(static_cast<size_t>(::GetSystemMetrics(SM_CMONITORS)),
+ display_infos.size());
+ return display_infos;
+}
+
+} // namespace
+
+ScreenWin::ScreenWin() {
+ Initialize();
+}
+
+ScreenWin::~ScreenWin() = default;
+
+HWND ScreenWin::GetHWNDFromNativeView(gfx::NativeView window) const {
+ NOTREACHED();
+ return nullptr;
+}
+
+gfx::NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
+ NOTREACHED();
+ return nullptr;
+}
+
+gfx::Point ScreenWin::GetCursorScreenPoint() {
+ POINT pt;
+ ::GetCursorPos(&pt);
+ gfx::Point cursor_pos_pixels(pt);
+ return gfx::win::ScreenToDIPPoint(cursor_pos_pixels);
+}
+
+gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
+ POINT cursor_loc;
+ HWND hwnd =
+ ::GetCursorPos(&cursor_loc) ? ::WindowFromPoint(cursor_loc) : nullptr;
+ return GetNativeWindowFromHWND(hwnd);
+}
+
+gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
+ gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point);
+ return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT()));
+}
+
+int ScreenWin::GetNumDisplays() const {
+ return static_cast<int>(screen_win_displays_.size());
+}
+
+std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
+ return ScreenWinDisplaysToDisplays(screen_win_displays_);
+}
+
+gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
+ HWND window_hwnd = GetHWNDFromNativeView(window);
+ if (!window_hwnd) {
+ // When |window| isn't rooted to a display, we should just return the
+ // default display so we get some correct display information like the
+ // scaling factor.
+ return GetPrimaryDisplay();
+ }
+ ScreenWinDisplay screen_win_display =
+ GetScreenWinDisplayNearestHWND(window_hwnd);
+ return screen_win_display.display();
+}
+
+gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
+ gfx::Point screen_point(gfx::win::DIPToScreenPoint(point));
+ ScreenWinDisplay screen_win_display =
+ GetScreenWinDisplayNearestScreenPoint(screen_point);
+ return screen_win_display.display();
+}
+
+gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
+ ScreenWinDisplay screen_win_display =
+ GetScreenWinDisplayNearestScreenRect(match_rect);
+ return screen_win_display.display();
+}
+
+gfx::Display ScreenWin::GetPrimaryDisplay() const {
+ return GetPrimaryScreenWinDisplay().display();
+}
+
+void ScreenWin::AddObserver(gfx::DisplayObserver* observer) {
+ change_notifier_.AddObserver(observer);
+}
+
+void ScreenWin::RemoveObserver(gfx::DisplayObserver* observer) {
+ change_notifier_.RemoveObserver(observer);
+}
+
+void ScreenWin::UpdateFromDisplayInfos(
+ const std::vector<DisplayInfo>& display_infos) {
+ screen_win_displays_ = DisplayInfosToScreenWinDisplays(display_infos);
+}
+
+void ScreenWin::Initialize() {
+ singleton_hwnd_observer_.reset(
+ new gfx::SingletonHwndObserver(
+ base::Bind(&ScreenWin::OnWndProc, base::Unretained(this))));
+ UpdateFromDisplayInfos(GetDisplayInfosFromSystem());
+}
+
+MONITORINFOEX ScreenWin::MonitorInfoFromScreenPoint(
+ const gfx::Point& screen_point) const {
+ POINT initial_loc = { screen_point.x(), screen_point.y() };
+ return MonitorInfoFromHMONITOR(::MonitorFromPoint(initial_loc,
+ MONITOR_DEFAULTTONEAREST));
+}
+
+MONITORINFOEX ScreenWin::MonitorInfoFromScreenRect(const gfx::Rect& screen_rect)
+ const {
+ RECT win_rect = screen_rect.ToRECT();
+ return MonitorInfoFromHMONITOR(::MonitorFromRect(&win_rect,
+ MONITOR_DEFAULTTONEAREST));
+}
+
+MONITORINFOEX ScreenWin::MonitorInfoFromWindow(HWND hwnd,
+ DWORD default_options) const {
+ return MonitorInfoFromHMONITOR(::MonitorFromWindow(hwnd, default_options));
+}
+
+HWND ScreenWin::GetRootWindow(HWND hwnd) const {
+ return ::GetAncestor(hwnd, GA_ROOT);
+}
+
+void ScreenWin::OnWndProc(HWND hwnd,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam) {
+ if (message != WM_DISPLAYCHANGE)
+ return;
+
+ std::vector<gfx::Display> old_displays = GetAllDisplays();
+ UpdateFromDisplayInfos(GetDisplayInfosFromSystem());
+ change_notifier_.NotifyDisplaysChanged(old_displays, GetAllDisplays());
+}
+
+ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestHWND(HWND hwnd)
+ const {
+ return GetScreenWinDisplay(MonitorInfoFromWindow(hwnd,
+ MONITOR_DEFAULTTONEAREST));
+}
+
+ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenRect(
+ const gfx::Rect& screen_rect) const {
+ return GetScreenWinDisplay(MonitorInfoFromScreenRect(screen_rect));
+}
+
+ScreenWinDisplay ScreenWin::GetScreenWinDisplayNearestScreenPoint(
+ const gfx::Point& screen_point) const {
+ return GetScreenWinDisplay(MonitorInfoFromScreenPoint(screen_point));
+}
+
+ScreenWinDisplay ScreenWin::GetPrimaryScreenWinDisplay() const {
+ MONITORINFOEX monitor_info = MonitorInfoFromWindow(nullptr,
+ MONITOR_DEFAULTTOPRIMARY);
+ ScreenWinDisplay screen_win_display = GetScreenWinDisplay(monitor_info);
+ gfx::Display display = screen_win_display.display();
+ // The Windows primary monitor is defined to have an origin of (0, 0).
+ DCHECK_EQ(0, display.bounds().origin().x());
+ DCHECK_EQ(0, display.bounds().origin().y());
+ return screen_win_display;
+}
+
+ScreenWinDisplay ScreenWin::GetScreenWinDisplay(
+ const MONITORINFOEX& monitor_info) const {
+ int64_t id = DisplayInfo::DeviceIdFromDeviceName(monitor_info.szDevice);
+ for (const auto& screen_win_display : screen_win_displays_) {
+ if (screen_win_display.display().id() == id)
+ return screen_win_display;
+ }
+ // There is 1:1 correspondence between MONITORINFOEX and ScreenWinDisplay.
+ // If we make it here, it means we have no displays and we should hand out the
+ // default display.
+ DCHECK_EQ(screen_win_displays_.size(), 0u);
+ return ScreenWinDisplay();
+}
+
+} // namespace win
+} // namespace display
diff --git a/chromium/ui/display/win/screen_win.h b/chromium/ui/display/win/screen_win.h
new file mode 100644
index 00000000000..da18ed1c7ae
--- /dev/null
+++ b/chromium/ui/display/win/screen_win.h
@@ -0,0 +1,102 @@
+// 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_DISPLAY_WIN_SCREEN_WIN_H_
+#define UI_DISPLAY_WIN_SCREEN_WIN_H_
+
+#include <windows.h>
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/display/display_export.h"
+#include "ui/gfx/display_change_notifier.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/win/singleton_hwnd_observer.h"
+
+namespace gfx {
+class Display;
+class Point;
+class Rect;
+} // namespace gfx
+
+namespace display {
+namespace win {
+
+class DisplayInfo;
+class ScreenWinDisplay;
+
+class DISPLAY_EXPORT ScreenWin : public gfx::Screen {
+ public:
+ ScreenWin();
+ ~ScreenWin() override;
+
+ // Returns the HWND associated with the NativeView.
+ virtual HWND GetHWNDFromNativeView(gfx::NativeView window) const;
+
+ // Returns the NativeView associated with the HWND.
+ virtual gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const;
+
+ protected:
+ // gfx::Screen:
+ gfx::Point GetCursorScreenPoint() override;
+ gfx::NativeWindow GetWindowUnderCursor() override;
+ gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
+ int GetNumDisplays() const override;
+ std::vector<gfx::Display> GetAllDisplays() const override;
+ gfx::Display GetDisplayNearestWindow(gfx::NativeView window) const override;
+ gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override;
+ gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
+ gfx::Display GetPrimaryDisplay() const override;
+ void AddObserver(gfx::DisplayObserver* observer) override;
+ void RemoveObserver(gfx::DisplayObserver* observer) override;
+
+ void UpdateFromDisplayInfos(const std::vector<DisplayInfo>& display_infos);
+
+ // Virtual to support mocking by unit tests.
+ virtual void Initialize();
+ virtual MONITORINFOEX MonitorInfoFromScreenPoint(
+ const gfx::Point& screen_point) const;
+ virtual MONITORINFOEX MonitorInfoFromScreenRect(const gfx::Rect& screen_rect)
+ const;
+ virtual MONITORINFOEX MonitorInfoFromWindow(HWND hwnd, DWORD default_options)
+ const;
+ virtual HWND GetRootWindow(HWND hwnd) const;
+
+ private:
+ void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+ // Returns the ScreenWinDisplay closest to or enclosing |hwnd|.
+ ScreenWinDisplay GetScreenWinDisplayNearestHWND(HWND hwnd) const;
+
+ // Returns the ScreenWinDisplay closest to or enclosing |screen_rect|.
+ ScreenWinDisplay GetScreenWinDisplayNearestScreenRect(
+ const gfx::Rect& screen_rect) const;
+
+ // Returns the ScreenWinDisplay closest to or enclosing |screen_point|.
+ ScreenWinDisplay GetScreenWinDisplayNearestScreenPoint(
+ const gfx::Point& screen_point) const;
+
+ // Returns the ScreenWinDisplay corresponding to the primary monitor.
+ ScreenWinDisplay GetPrimaryScreenWinDisplay() const;
+
+ ScreenWinDisplay GetScreenWinDisplay(const MONITORINFOEX& monitor_info) const;
+
+ // Helper implementing the DisplayObserver handling.
+ gfx::DisplayChangeNotifier change_notifier_;
+
+ scoped_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
+
+ // Current list of ScreenWinDisplays.
+ std::vector<ScreenWinDisplay> screen_win_displays_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWin);
+};
+
+} // namespace win
+} // namespace display
+
+#endif // UI_DISPLAY_WIN_SCREEN_WIN_H_
diff --git a/chromium/ui/display/win/screen_win_display.cc b/chromium/ui/display/win/screen_win_display.cc
new file mode 100644
index 00000000000..38104bbc3ff
--- /dev/null
+++ b/chromium/ui/display/win/screen_win_display.cc
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/win/screen_win_display.h"
+
+#include "ui/display/win/display_info.h"
+#include "ui/gfx/win/dpi.h"
+
+namespace display {
+namespace win {
+
+namespace {
+
+gfx::Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info) {
+ gfx::Display display(display_info.id());
+ gfx::Rect dip_screen_bounds(
+ gfx::win::ScreenToDIPRect(display_info.screen_rect()));
+ display.set_bounds(dip_screen_bounds);
+ display.set_work_area(
+ gfx::win::ScreenToDIPRect(display_info.screen_work_rect()));
+ display.SetScaleAndBounds(display_info.device_scale_factor(),
+ display_info.screen_rect());
+ display.set_rotation(display_info.rotation());
+ return display;
+}
+
+} // namespace
+
+ScreenWinDisplay::ScreenWinDisplay() = default;
+
+ScreenWinDisplay::ScreenWinDisplay(const DisplayInfo& display_info)
+ : display_(CreateDisplayFromDisplayInfo(display_info)),
+ pixel_bounds_(display_info.screen_rect()) {}
+
+} // namespace win
+} // namespace display
diff --git a/chromium/ui/display/win/screen_win_display.h b/chromium/ui/display/win/screen_win_display.h
new file mode 100644
index 00000000000..901f2d7e855
--- /dev/null
+++ b/chromium/ui/display/win/screen_win_display.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_WIN_SCREEN_WIN_DISPLAY_H_
+#define UI_DISPLAY_WIN_SCREEN_WIN_DISPLAY_H_
+
+#include <windows.h>
+
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace display {
+namespace win {
+
+class DisplayInfo;
+
+// A display used by gfx::ScreenWin.
+// It holds a display and additional parameters used for DPI calculations.
+class ScreenWinDisplay final {
+ public:
+ ScreenWinDisplay();
+ explicit ScreenWinDisplay(const DisplayInfo& display_info);
+
+ const gfx::Display& display() const { return display_; }
+ const gfx::Rect& pixel_bounds() const { return pixel_bounds_; }
+
+ private:
+ gfx::Display display_;
+ gfx::Rect pixel_bounds_;
+};
+
+} // namespace win
+} // namespace display
+
+#endif // UI_DISPLAY_WIN_SCREEN_WIN_DISPLAY_H_
diff --git a/chromium/ui/display/win/screen_win_unittest.cc b/chromium/ui/display/win/screen_win_unittest.cc
new file mode 100644
index 00000000000..2542167c285
--- /dev/null
+++ b/chromium/ui/display/win/screen_win_unittest.cc
@@ -0,0 +1,784 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/win/screen_win.h"
+
+#include <windows.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+#include <cwchar>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/display/win/display_info.h"
+#include "ui/display/win/screen_win_display.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/test/display_util.h"
+#include "ui/gfx/win/dpi.h"
+
+namespace display {
+namespace win {
+
+namespace {
+
+MONITORINFOEX CreateMonitorInfo(gfx::Rect monitor,
+ gfx::Rect work,
+ std::wstring device_name) {
+ MONITORINFOEX monitor_info;
+ ::ZeroMemory(&monitor_info, sizeof(monitor_info));
+ monitor_info.cbSize = sizeof(monitor_info);
+ monitor_info.rcMonitor = monitor.ToRECT();
+ monitor_info.rcWork = work.ToRECT();
+ size_t device_char_count = ARRAYSIZE(monitor_info.szDevice);
+ wcsncpy(monitor_info.szDevice, device_name.c_str(), device_char_count);
+ monitor_info.szDevice[device_char_count-1] = L'\0';
+ return monitor_info;
+}
+
+class TestScreenWin : public ScreenWin {
+ public:
+ TestScreenWin(const std::vector<DisplayInfo>& display_infos,
+ const std::vector<MONITORINFOEX>& monitor_infos,
+ const std::unordered_map<HWND, gfx::Rect>& hwnd_map)
+ : monitor_infos_(monitor_infos),
+ hwnd_map_(hwnd_map) {
+ UpdateFromDisplayInfos(display_infos);
+ }
+
+ ~TestScreenWin() override = default;
+
+ protected:
+ // display::win::ScreenWin:
+ HWND GetHWNDFromNativeView(gfx::NativeView window) const override {
+ // NativeView is only used as an identifier in this tests, so interchange
+ // NativeView with an HWND for convenience.
+ return reinterpret_cast<HWND>(window);
+ }
+
+ gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const override {
+ // NativeWindow is only used as an identifier in this tests, so interchange
+ // an HWND for a NativeWindow for convenience.
+ return reinterpret_cast<gfx::NativeWindow>(hwnd);
+ }
+
+ private:
+ void Initialize() override {}
+
+ MONITORINFOEX MonitorInfoFromScreenPoint(const gfx::Point& screen_point) const
+ override {
+ for (const MONITORINFOEX& monitor_info : monitor_infos_) {
+ if (gfx::Rect(monitor_info.rcMonitor).Contains(screen_point))
+ return monitor_info;
+ }
+ NOTREACHED();
+ return monitor_infos_[0];
+ }
+
+ MONITORINFOEX MonitorInfoFromScreenRect(const gfx::Rect& screen_rect) const
+ override {
+ MONITORINFOEX candidate = monitor_infos_[0];
+ int largest_area = 0;
+ for (const MONITORINFOEX& monitor_info : monitor_infos_) {
+ gfx::Rect bounds(monitor_info.rcMonitor);
+ if (bounds.Intersects(screen_rect)) {
+ bounds.Intersect(screen_rect);
+ int area = bounds.height() * bounds.width();
+ if (largest_area < area) {
+ candidate = monitor_info;
+ largest_area = area;
+ }
+ }
+ }
+ EXPECT_NE(largest_area, 0);
+ return candidate;
+ }
+
+ MONITORINFOEX MonitorInfoFromWindow(HWND hwnd, DWORD default_options)
+ const override {
+ auto search = hwnd_map_.find(hwnd);
+ if (search != hwnd_map_.end())
+ return MonitorInfoFromScreenRect(search->second);
+
+ EXPECT_EQ(default_options, static_cast<DWORD>(MONITOR_DEFAULTTOPRIMARY));
+ for (const auto& monitor_info : monitor_infos_) {
+ if (monitor_info.rcMonitor.left == 0 &&
+ monitor_info.rcMonitor.top == 0) {
+ return monitor_info;
+ }
+ }
+ NOTREACHED();
+ return monitor_infos_[0];
+ }
+
+ HWND GetRootWindow(HWND hwnd) const override {
+ return hwnd;
+ }
+
+ std::vector<MONITORINFOEX> monitor_infos_;
+ std::unordered_map<HWND, gfx::Rect> hwnd_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestScreenWin);
+};
+
+gfx::Screen* GetScreen() {
+ return gfx::Screen::GetScreen();
+}
+
+// Allows tests to specify the screen and associated state.
+class TestScreenWinInitializer {
+ public:
+ virtual void AddMonitor(const gfx::Rect& pixel_bounds,
+ const gfx::Rect& pixel_work,
+ const wchar_t* device_name,
+ float device_scale_factor) = 0;
+
+ virtual HWND CreateFakeHwnd(const gfx::Rect& bounds) = 0;
+};
+
+class TestScreenWinManager : public TestScreenWinInitializer {
+ public:
+ TestScreenWinManager() = default;
+
+ ~TestScreenWinManager() {
+ gfx::Screen::SetScreenInstance(nullptr);
+ }
+
+ void AddMonitor(const gfx::Rect& pixel_bounds,
+ const gfx::Rect& pixel_work,
+ const wchar_t* device_name,
+ float device_scale_factor) override {
+ MONITORINFOEX monitor_info = CreateMonitorInfo(pixel_bounds,
+ pixel_work,
+ device_name);
+ monitor_infos_.push_back(monitor_info);
+ display_infos_.push_back(DisplayInfo(monitor_info,
+ device_scale_factor,
+ gfx::Display::ROTATE_0));
+ }
+
+ HWND CreateFakeHwnd(const gfx::Rect& bounds) override {
+ EXPECT_EQ(screen_win_, nullptr);
+ hwnd_map_.insert(std::pair<HWND, gfx::Rect>(++hwndLast_, bounds));
+ return hwndLast_;
+ }
+
+ void InitializeScreenWin() {
+ ASSERT_EQ(screen_win_, nullptr);
+ screen_win_.reset(new TestScreenWin(display_infos_,
+ monitor_infos_,
+ hwnd_map_));
+ gfx::Screen::SetScreenInstance(screen_win_.get());
+ }
+
+ ScreenWin* GetScreenWin() {
+ return screen_win_.get();
+ }
+
+ private:
+ HWND hwndLast_ = nullptr;
+ scoped_ptr<ScreenWin> screen_win_;
+ std::vector<MONITORINFOEX> monitor_infos_;
+ std::vector<DisplayInfo> display_infos_;
+ std::unordered_map<HWND, gfx::Rect> hwnd_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestScreenWinManager);
+};
+
+class ScreenWinTest : public testing::Test {
+ protected:
+ ScreenWinTest() = default;
+
+ void SetUp() override {
+ testing::Test::SetUp();
+ gfx::SetDefaultDeviceScaleFactor(1.0);
+ screen_win_initializer_.reset(new TestScreenWinManager());
+ SetUpScreen(screen_win_initializer_.get());
+ screen_win_initializer_->InitializeScreenWin();
+ }
+
+ void TearDown() override {
+ screen_win_initializer_.reset();
+ gfx::SetDefaultDeviceScaleFactor(1.0);
+ testing::Test::TearDown();
+ }
+
+ virtual void SetUpScreen(TestScreenWinInitializer* initializer) = 0;
+
+ gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const {
+ ScreenWin* screen_win = screen_win_initializer_->GetScreenWin();
+ return screen_win->GetNativeWindowFromHWND(hwnd);;
+ }
+
+ private:
+ scoped_ptr<TestScreenWinManager> screen_win_initializer_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTest);
+};
+
+// Single Display of 1.0 Device Scale Factor.
+class ScreenWinTestSingleDisplay1x : public ScreenWinTest {
+ public:
+ ScreenWinTestSingleDisplay1x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 1.0);
+ fake_hwnd_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ }
+
+ HWND GetFakeHwnd() {
+ return fake_hwnd_;
+ }
+
+ private:
+ HWND fake_hwnd_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestSingleDisplay1x);
+};
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(1u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1200), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1100), displays[0].work_area());
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetNumDisplays) {
+ EXPECT_EQ(1, GetScreen()->GetNumDisplays());
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetDisplayNearestWindowPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(screen->GetPrimaryDisplay(),
+ screen->GetDisplayNearestWindow(nullptr));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ gfx::NativeWindow native_window = GetNativeWindowFromHWND(GetFakeHwnd());
+ EXPECT_EQ(screen->GetAllDisplays()[0],
+ screen->GetDisplayNearestWindow(native_window));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(250, 952)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(1919, 1199)));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1x, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(gfx::Point(0, 0), screen->GetPrimaryDisplay().bounds().origin());
+}
+
+// Single Display of 1.25 Device Scale Factor.
+class ScreenWinTestSingleDisplay1_25x : public ScreenWinTest {
+ public:
+ ScreenWinTestSingleDisplay1_25x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ gfx::SetDefaultDeviceScaleFactor(1.25);
+ // Add Monitor of Scale Factor 1.0 since gfx::GetDPIScale performs the
+ // clamping and not ScreenWin.
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 1.0);
+ fake_hwnd_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ }
+
+ HWND GetFakeHwnd() {
+ return fake_hwnd_;
+ }
+
+ private:
+ HWND fake_hwnd_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestSingleDisplay1_25x);
+};
+
+TEST_F(ScreenWinTestSingleDisplay1_25x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(1u, displays.size());
+ // On Windows, scale factors of 1.25 or lower are clamped to 1.0.
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1200), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1100), displays[0].work_area());
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_25x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ gfx::NativeWindow native_window = GetNativeWindowFromHWND(GetFakeHwnd());
+ EXPECT_EQ(screen->GetAllDisplays()[0],
+ screen->GetDisplayNearestWindow(native_window));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_25x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(250, 952)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(1919, 1199)));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_25x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+}
+TEST_F(ScreenWinTestSingleDisplay1_25x, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(gfx::Point(0, 0), screen->GetPrimaryDisplay().bounds().origin());
+}
+
+// Single Display of 1.25 Device Scale Factor.
+class ScreenWinTestSingleDisplay1_5x : public ScreenWinTest {
+ public:
+ ScreenWinTestSingleDisplay1_5x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ gfx::SetDefaultDeviceScaleFactor(1.5);
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 1.5);
+ fake_hwnd_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ }
+
+ HWND GetFakeHwnd() {
+ return fake_hwnd_;
+ }
+
+ private:
+ HWND fake_hwnd_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestSingleDisplay1_5x);
+};
+
+TEST_F(ScreenWinTestSingleDisplay1_5x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(1u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 1280, 800), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 1280, 734), displays[0].work_area());
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_5x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ gfx::NativeWindow native_window = GetNativeWindowFromHWND(GetFakeHwnd());
+ EXPECT_EQ(screen->GetAllDisplays()[0],
+ screen->GetDisplayNearestWindow(native_window));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_5x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(250, 524)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(1279, 733)));
+}
+
+TEST_F(ScreenWinTestSingleDisplay1_5x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+}
+TEST_F(ScreenWinTestSingleDisplay1_5x, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(gfx::Point(0, 0), screen->GetPrimaryDisplay().bounds().origin());
+}
+
+
+// Single Display of 2.0 Device Scale Factor.
+class ScreenWinTestSingleDisplay2x : public ScreenWinTest {
+ public:
+ ScreenWinTestSingleDisplay2x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ gfx::SetDefaultDeviceScaleFactor(2.0);
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 2.0);
+ fake_hwnd_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ }
+
+ HWND GetFakeHwnd() {
+ return fake_hwnd_;
+ }
+
+ private:
+ HWND fake_hwnd_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestSingleDisplay2x);
+};
+
+TEST_F(ScreenWinTestSingleDisplay2x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(1u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 960, 600), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 960, 550), displays[0].work_area());
+}
+
+TEST_F(ScreenWinTestSingleDisplay2x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ gfx::NativeWindow native_window = GetNativeWindowFromHWND(GetFakeHwnd());
+ EXPECT_EQ(screen->GetAllDisplays()[0],
+ screen->GetDisplayNearestWindow(native_window));
+}
+
+TEST_F(ScreenWinTestSingleDisplay2x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(125, 476)));
+ EXPECT_EQ(display, screen->GetDisplayNearestPoint(gfx::Point(959, 599)));
+}
+
+TEST_F(ScreenWinTestSingleDisplay2x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display display = screen->GetAllDisplays()[0];
+ EXPECT_EQ(display, screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+}
+
+// Two Displays of 1.0 Device Scale Factor.
+class ScreenWinTestTwoDisplays1x : public ScreenWinTest {
+ public:
+ ScreenWinTestTwoDisplays1x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 1.0);
+ initializer->AddMonitor(gfx::Rect(1920, 0, 800, 600),
+ gfx::Rect(1920, 0, 800, 600),
+ L"secondary",
+ 1.0);
+ fake_hwnd_left_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ fake_hwnd_right_ =
+ initializer->CreateFakeHwnd(gfx::Rect(1920, 0, 800, 600));
+ }
+
+ HWND GetLeftFakeHwnd() {
+ return fake_hwnd_left_;
+ }
+
+ HWND GetRightFakeHwnd() {
+ return fake_hwnd_right_;
+ }
+
+ private:
+ HWND fake_hwnd_left_ = nullptr;
+ HWND fake_hwnd_right_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestTwoDisplays1x);
+};
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(2u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1200), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 1920, 1100), displays[0].work_area());
+ EXPECT_EQ(gfx::Rect(1920, 0, 800, 600), displays[1].bounds());
+ EXPECT_EQ(gfx::Rect(1920, 0, 800, 600), displays[1].work_area());
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetNumDisplays) {
+ EXPECT_EQ(2, GetScreen()->GetNumDisplays());
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetDisplayNearestWindowPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(screen->GetPrimaryDisplay(),
+ screen->GetDisplayNearestWindow(nullptr));
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ gfx::NativeWindow left_window = GetNativeWindowFromHWND(GetLeftFakeHwnd());
+ EXPECT_EQ(left_display, screen->GetDisplayNearestWindow(left_window));
+
+ gfx::NativeWindow right_window = GetNativeWindowFromHWND(GetRightFakeHwnd());
+ EXPECT_EQ(right_display, screen->GetDisplayNearestWindow(right_window));
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(250, 952)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayNearestPoint(gfx::Point(1919, 1199)));
+
+ EXPECT_EQ(right_display, screen->GetDisplayNearestPoint(gfx::Point(1920, 0)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(2000, 400)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(2719, 599)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(1920, 0, 100, 100)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(2619, 499, 100, 100)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays1x, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display primary = screen->GetPrimaryDisplay();
+ EXPECT_EQ(gfx::Point(0, 0), primary.bounds().origin());
+}
+
+// Two Displays of 2.0 Device Scale Factor.
+class ScreenWinTestTwoDisplays2x : public ScreenWinTest {
+ public:
+ ScreenWinTestTwoDisplays2x() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ gfx::SetDefaultDeviceScaleFactor(2.0);
+ initializer->AddMonitor(gfx::Rect(0, 0, 1920, 1200),
+ gfx::Rect(0, 0, 1920, 1100),
+ L"primary",
+ 2.0);
+ initializer->AddMonitor(gfx::Rect(1920, 0, 800, 600),
+ gfx::Rect(1920, 0, 800, 600),
+ L"secondary",
+ 2.0);
+ fake_hwnd_left_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 1920, 1100));
+ fake_hwnd_right_ =
+ initializer->CreateFakeHwnd(gfx::Rect(1920, 0, 800, 600));
+ }
+
+ HWND GetLeftFakeHwnd() {
+ return fake_hwnd_left_;
+ }
+
+ HWND GetRightFakeHwnd() {
+ return fake_hwnd_right_;
+ }
+
+ private:
+ HWND fake_hwnd_left_ = nullptr;
+ HWND fake_hwnd_right_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestTwoDisplays2x);
+};
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(2u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 960, 600), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 960, 550), displays[0].work_area());
+ EXPECT_EQ(gfx::Rect(960, 0, 400, 300), displays[1].bounds());
+ EXPECT_EQ(gfx::Rect(960, 0, 400, 300), displays[1].work_area());
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetDisplayNearestWindowPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(screen->GetPrimaryDisplay(),
+ screen->GetDisplayNearestWindow(nullptr));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ gfx::NativeWindow left_window = GetNativeWindowFromHWND(GetLeftFakeHwnd());
+ EXPECT_EQ(left_display, screen->GetDisplayNearestWindow(left_window));
+
+ gfx::NativeWindow right_window = GetNativeWindowFromHWND(GetRightFakeHwnd());
+ EXPECT_EQ(right_display, screen->GetDisplayNearestWindow(right_window));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(125, 476)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayNearestPoint(gfx::Point(959, 599)));
+
+ EXPECT_EQ(right_display, screen->GetDisplayNearestPoint(gfx::Point(960, 0)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(1000, 200)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(1359, 299)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(1920, 0, 100, 100)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(2619, 499, 100, 100)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display primary = screen->GetPrimaryDisplay();
+ EXPECT_EQ(gfx::Point(0, 0), primary.bounds().origin());
+}
+
+// Two Displays of 2.0 (Left) and 1.0 (Right) Device Scale Factor under
+// Windows DPI Virtualization. Note that the displays do not form a euclidean
+// space.
+class ScreenWinTestTwoDisplays2x1xVirtualized : public ScreenWinTest {
+ public:
+ ScreenWinTestTwoDisplays2x1xVirtualized() = default;
+
+ void SetUpScreen(TestScreenWinInitializer* initializer) override {
+ gfx::SetDefaultDeviceScaleFactor(2.0);
+ initializer->AddMonitor(gfx::Rect(0, 0, 3200, 1600),
+ gfx::Rect(0, 0, 3200, 1500),
+ L"primary",
+ 2.0);
+ initializer->AddMonitor(gfx::Rect(6400, 0, 3840, 2400),
+ gfx::Rect(6400, 0, 3840, 2400),
+ L"secondary",
+ 2.0);
+ fake_hwnd_left_ = initializer->CreateFakeHwnd(gfx::Rect(0, 0, 3200, 1500));
+ fake_hwnd_right_ =
+ initializer->CreateFakeHwnd(gfx::Rect(6400, 0, 3840, 2400));
+ }
+
+ HWND GetLeftFakeHwnd() {
+ return fake_hwnd_left_;
+ }
+
+ HWND GetRightFakeHwnd() {
+ return fake_hwnd_right_;
+ }
+
+ private:
+ HWND fake_hwnd_left_ = nullptr;
+ HWND fake_hwnd_right_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenWinTestTwoDisplays2x1xVirtualized);
+};
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetDisplays) {
+ std::vector<gfx::Display> displays = GetScreen()->GetAllDisplays();
+ ASSERT_EQ(2u, displays.size());
+ EXPECT_EQ(gfx::Rect(0, 0, 1600, 800), displays[0].bounds());
+ EXPECT_EQ(gfx::Rect(0, 0, 1600, 750), displays[0].work_area());
+ EXPECT_EQ(gfx::Rect(3200, 0, 1920, 1200), displays[1].bounds());
+ EXPECT_EQ(gfx::Rect(3200, 0, 1920, 1200), displays[1].work_area());
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetNumDisplays) {
+ EXPECT_EQ(2, GetScreen()->GetNumDisplays());
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized,
+ GetDisplayNearestWindowPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ EXPECT_EQ(screen->GetPrimaryDisplay(),
+ screen->GetDisplayNearestWindow(nullptr));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetDisplayNearestWindow) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ gfx::NativeWindow left_window = GetNativeWindowFromHWND(GetLeftFakeHwnd());
+ EXPECT_EQ(left_display, screen->GetDisplayNearestWindow(left_window));
+
+ gfx::NativeWindow right_window = GetNativeWindowFromHWND(GetRightFakeHwnd());
+ EXPECT_EQ(right_display, screen->GetDisplayNearestWindow(right_window));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetDisplayNearestPoint) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(0, 0)));
+ EXPECT_EQ(left_display, screen->GetDisplayNearestPoint(gfx::Point(125, 476)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayNearestPoint(gfx::Point(1599, 799)));
+
+ EXPECT_EQ(right_display, screen->GetDisplayNearestPoint(gfx::Point(3200, 0)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(4000, 400)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayNearestPoint(gfx::Point(5119, 1199)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetDisplayMatching) {
+ gfx::Screen* screen = GetScreen();
+ const gfx::Display left_display = screen->GetAllDisplays()[0];
+ const gfx::Display right_display = screen->GetAllDisplays()[1];
+
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(0, 0, 100, 100)));
+ EXPECT_EQ(left_display,
+ screen->GetDisplayMatching(gfx::Rect(1819, 1099, 100, 100)));
+
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(6400, 0, 100, 100)));
+ EXPECT_EQ(right_display,
+ screen->GetDisplayMatching(gfx::Rect(10139, 2299, 100, 100)));
+}
+
+TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetPrimaryDisplay) {
+ gfx::Screen* screen = GetScreen();
+ gfx::Display primary = screen->GetPrimaryDisplay();
+ EXPECT_EQ(gfx::Point(0, 0), primary.bounds().origin());
+}
+
+} // namespace
+
+} // namespace win
+} // namespace display
diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn
index a875264491b..20b75f2cbda 100644
--- a/chromium/ui/events/BUILD.gn
+++ b/chromium/ui/events/BUILD.gn
@@ -10,6 +10,10 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
+if (is_ios) {
+ import("//ios/build/config.gni")
+}
+
static_library("dom_keycode_converter") {
sources = [
"keycodes/dom/dom_code.h",
@@ -57,13 +61,12 @@ component("events_base") {
defines = [ "EVENTS_BASE_IMPLEMENTATION" ]
deps = [
- ":dom_keycode_converter",
"//base/third_party/dynamic_annotations",
- "//ipc:param_traits",
"//skia",
]
public_deps = [
+ ":dom_keycode_converter",
"//base",
"//ui/events/platform",
"//ui/gfx",
@@ -93,6 +96,10 @@ component("events_base") {
"keycodes/xkb_keysym.h",
]
}
+
+ if (!is_ios) {
+ deps += [ "//ipc:param_traits" ]
+ }
}
component("events") {
@@ -121,6 +128,8 @@ component("events") {
"events_stub.cc",
"gestures/gesture_recognizer_impl_mac.cc",
"gestures/gesture_types.h",
+ "keycodes/platform_key_map_win.cc",
+ "keycodes/platform_key_map_win.h",
"null_event_targeter.cc",
"null_event_targeter.h",
"scoped_target_handler.cc",
@@ -201,10 +210,15 @@ component("events") {
sources += [
"android/events_jni_registrar.cc",
"android/events_jni_registrar.h",
+ "android/key_event_utils.cc",
+ "android/key_event_utils.h",
"android/motion_event_android.cc",
"android/motion_event_android.h",
]
- deps += [ ":motionevent_jni_headers" ]
+ deps += [
+ ":keyevent_jni_headers",
+ ":motionevent_jni_headers",
+ ]
}
}
@@ -333,15 +347,6 @@ source_set("test_support") {
}
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("events_unittests_run") {
- testonly = true
- deps = [
- ":events_unittests",
- ]
-}
-
test("events_unittests") {
sources = [
"android/scroller_unittest.cc",
@@ -360,12 +365,13 @@ test("events_unittests") {
"gesture_detection/touch_disposition_gesture_filter_unittest.cc",
"gesture_detection/velocity_tracker_unittest.cc",
"gestures/fling_curve_unittest.cc",
- "ipc/latency_info_param_traits_unittest.cc",
"keycodes/dom/keycode_converter_unittest.cc",
"keycodes/keyboard_code_conversion_unittest.cc",
+ "keycodes/platform_key_map_win_unittest.cc",
"latency_info_unittest.cc",
"platform/platform_event_source_unittest.cc",
"scoped_target_handler_unittest.cc",
+ "win/event_utils_win_unittest.cc",
]
deps = [
@@ -376,12 +382,11 @@ test("events_unittests") {
":test_support",
"//base",
"//base/test:run_all_unittests",
- "//ipc:test_support",
+ "//base/test:test_support",
"//skia",
"//testing/gmock",
"//testing/gtest",
"//ui/events/devices",
- "//ui/events/ipc:events_ipc",
"//ui/events/platform",
"//ui/gfx:test_support",
]
@@ -391,12 +396,15 @@ test("events_unittests") {
"blink/input_handler_proxy_unittest.cc",
"blink/input_scroll_elasticity_controller_unittest.cc",
"gestures/blink/web_gesture_curve_impl_unittest.cc",
+ "ipc/latency_info_param_traits_unittest.cc",
]
deps += [
"//cc",
+ "//ipc:test_support",
"//third_party/WebKit/public:blink_headers",
"//ui/events/blink",
"//ui/events/gestures/blink",
+ "//ui/events/ipc",
]
}
@@ -455,6 +463,10 @@ test("events_unittests") {
if (is_android) {
sources += [ "android/motion_event_android_unittest.cc" ]
}
+
+ if (is_ios) {
+ assert_no_deps = ios_assert_no_deps
+ }
}
if (is_android) {
@@ -462,4 +474,9 @@ if (is_android) {
jni_package = "ui"
classes = [ "android/view/MotionEvent.class" ]
}
+
+ generate_jar_jni("keyevent_jni_headers") {
+ jni_package = "ui"
+ classes = [ "android/view/KeyEvent.class" ]
+ }
}
diff --git a/chromium/ui/events/android/key_event_utils.cc b/chromium/ui/events/android/key_event_utils.cc
new file mode 100644
index 00000000000..af2f2c5b176
--- /dev/null
+++ b/chromium/ui/events/android/key_event_utils.cc
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/android/key_event_utils.h"
+
+#include "jni/KeyEvent_jni.h"
+
+namespace ui {
+namespace events {
+namespace android {
+
+bool RegisterKeyEvent(JNIEnv* env) {
+ return JNI_KeyEvent::RegisterNativesImpl(env);
+}
+
+base::android::ScopedJavaLocalRef<jobject> CreateKeyEvent(JNIEnv* env,
+ int action,
+ int key_code) {
+ return JNI_KeyEvent::Java_KeyEvent_ConstructorAVKE_I_I(env, action, key_code);
+}
+
+int GetKeyEventUnicodeChar(JNIEnv* env,
+ const base::android::JavaRef<jobject>& event,
+ int meta_state) {
+ return static_cast<int>(JNI_KeyEvent::Java_KeyEvent_getUnicodeCharI_I(
+ env, event.obj(), meta_state));
+}
+
+} // namespace android
+} // namespace events
+} // namespace ui
diff --git a/chromium/ui/events/android/key_event_utils.h b/chromium/ui/events/android/key_event_utils.h
new file mode 100644
index 00000000000..83445d1cd27
--- /dev/null
+++ b/chromium/ui/events/android/key_event_utils.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_ANDROID_KEY_EVENT_UTILS_H_
+#define UI_EVENTS_ANDROID_KEY_EVENT_UTILS_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "ui/events/events_export.h"
+
+namespace ui {
+namespace events {
+namespace android {
+
+bool RegisterKeyEvent(JNIEnv* env);
+
+EVENTS_EXPORT base::android::ScopedJavaLocalRef<jobject>
+CreateKeyEvent(JNIEnv* env, int action, int key_code);
+
+EVENTS_EXPORT int GetKeyEventUnicodeChar(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& event,
+ int meta_state);
+
+} // namespace android
+} // namespace events
+} // namespace ui
+
+#endif // UI_EVENTS_ANDROID_KEY_EVENT_UTISL_H_
diff --git a/chromium/ui/events/blink/DEPS b/chromium/ui/events/blink/DEPS
index 6fa4026ac43..9a2a9a8a2e8 100644
--- a/chromium/ui/events/blink/DEPS
+++ b/chromium/ui/events/blink/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+cc/input/input_handler.h",
+ "+cc/input/main_thread_scrolling_reason.h",
"+cc/input/scroll_elasticity_helper.h",
"+cc/trees/swap_promise_monitor.h",
diff --git a/chromium/ui/events/blink/blink_event_util.cc b/chromium/ui/events/blink/blink_event_util.cc
index 108013610d7..687f21fa15c 100644
--- a/chromium/ui/events/blink/blink_event_util.cc
+++ b/chromium/ui/events/blink/blink_event_util.cc
@@ -23,6 +23,7 @@
using blink::WebGestureEvent;
using blink::WebInputEvent;
+using blink::WebPointerProperties;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
@@ -81,30 +82,11 @@ WebTouchPoint::State ToWebTouchPointState(const MotionEvent& event,
return WebTouchPoint::StateUndefined;
}
-WebTouchPoint::PointerType ToWebTouchPointPointerType(const MotionEvent& event,
- size_t pointer_index) {
- switch (event.GetToolType(pointer_index)) {
- case MotionEvent::TOOL_TYPE_UNKNOWN:
- return WebTouchPoint::PointerType::Unknown;
- case MotionEvent::TOOL_TYPE_FINGER:
- return WebTouchPoint::PointerType::Touch;
- case MotionEvent::TOOL_TYPE_STYLUS:
- return WebTouchPoint::PointerType::Pen;
- case MotionEvent::TOOL_TYPE_MOUSE:
- return WebTouchPoint::PointerType::Mouse;
- case MotionEvent::TOOL_TYPE_ERASER:
- return WebTouchPoint::PointerType::Unknown;
- }
- NOTREACHED() << "Invalid MotionEvent::ToolType = "
- << event.GetToolType(pointer_index);
- return WebTouchPoint::PointerType::Unknown;
-}
-
WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
size_t pointer_index) {
WebTouchPoint touch;
touch.id = event.GetPointerId(pointer_index);
- touch.pointerType = ToWebTouchPointPointerType(event, pointer_index);
+ touch.pointerType = ToWebPointerType(event.GetToolType(pointer_index));
touch.state = ToWebTouchPointState(event, pointer_index);
touch.position.x = event.GetX(pointer_index);
touch.position.y = event.GetY(pointer_index);
@@ -179,7 +161,7 @@ WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const MotionEvent& event,
- bool may_cause_scrolling) {
+ bool moved_beyond_slop_region) {
static_assert(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
static_cast<int>(blink::WebTouchEvent::touchesLengthCap),
"inconsistent maximum number of active touch points");
@@ -187,10 +169,12 @@ blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
blink::WebTouchEvent result;
result.type = ToWebInputEventType(event.GetAction());
- result.cancelable = (result.type != WebInputEvent::TouchCancel);
+ result.dispatchType = result.type == WebInputEvent::TouchCancel
+ ? WebInputEvent::EventNonBlocking
+ : WebInputEvent::Blocking;
result.timeStampSeconds =
- (event.GetEventTime() - base::TimeTicks()).InSecondsF(),
- result.causesScrollingIfUncanceled = may_cause_scrolling;
+ (event.GetEventTime() - base::TimeTicks()).InSecondsF();
+ result.movedBeyondSlopRegion = moved_beyond_slop_region;
result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags());
DCHECK_NE(event.GetUniqueEventId(), 0U);
result.uniqueTouchEventId = event.GetUniqueEventId();
@@ -215,16 +199,7 @@ int EventFlagsToWebEventModifiers(int flags) {
if (flags & EF_ALT_DOWN)
modifiers |= blink::WebInputEvent::AltKey;
if (flags & EF_COMMAND_DOWN)
-#if defined(OS_WIN)
- // Evaluate whether OSKey should be set for other platforms.
- // Since this value was never set on Windows before as the meta
- // key; we don't break backwards compatiblity exposing it as the
- // true OS key. However this is not the case for Linux; see
- // http://crbug.com/539979
- modifiers |= blink::WebInputEvent::OSKey;
-#else
modifiers |= blink::WebInputEvent::MetaKey;
-#endif
if (flags & EF_ALTGR_DOWN)
modifiers |= blink::WebInputEvent::AltGrKey;
if (flags & EF_NUM_LOCK_ON)
@@ -366,4 +341,127 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
gfx::PointF(data.raw_x, data.raw_y), data.flags);
}
+scoped_ptr<blink::WebInputEvent> ScaleWebInputEvent(
+ const blink::WebInputEvent& event,
+ float scale) {
+ scoped_ptr<blink::WebInputEvent> scaled_event;
+ if (scale == 1.f)
+ return scaled_event;
+ if (event.type == blink::WebMouseEvent::MouseWheel) {
+ blink::WebMouseWheelEvent* wheel_event = new blink::WebMouseWheelEvent;
+ scaled_event.reset(wheel_event);
+ *wheel_event = static_cast<const blink::WebMouseWheelEvent&>(event);
+ wheel_event->x *= scale;
+ wheel_event->y *= scale;
+ wheel_event->deltaX *= scale;
+ wheel_event->deltaY *= scale;
+ wheel_event->wheelTicksX *= scale;
+ wheel_event->wheelTicksY *= scale;
+ } else if (blink::WebInputEvent::isMouseEventType(event.type)) {
+ blink::WebMouseEvent* mouse_event = new blink::WebMouseEvent;
+ scaled_event.reset(mouse_event);
+ *mouse_event = static_cast<const blink::WebMouseEvent&>(event);
+ mouse_event->x *= scale;
+ mouse_event->y *= scale;
+ mouse_event->windowX = mouse_event->x;
+ mouse_event->windowY = mouse_event->y;
+ mouse_event->movementX *= scale;
+ mouse_event->movementY *= scale;
+ } else if (blink::WebInputEvent::isTouchEventType(event.type)) {
+ blink::WebTouchEvent* touch_event = new blink::WebTouchEvent;
+ scaled_event.reset(touch_event);
+ *touch_event = static_cast<const blink::WebTouchEvent&>(event);
+ for (unsigned i = 0; i < touch_event->touchesLength; i++) {
+ touch_event->touches[i].position.x *= scale;
+ touch_event->touches[i].position.y *= scale;
+ touch_event->touches[i].radiusX *= scale;
+ touch_event->touches[i].radiusY *= scale;
+ }
+ } else if (blink::WebInputEvent::isGestureEventType(event.type)) {
+ blink::WebGestureEvent* gesture_event = new blink::WebGestureEvent;
+ scaled_event.reset(gesture_event);
+ *gesture_event = static_cast<const blink::WebGestureEvent&>(event);
+ gesture_event->x *= scale;
+ gesture_event->y *= scale;
+ switch (gesture_event->type) {
+ case blink::WebInputEvent::GestureScrollUpdate:
+ gesture_event->data.scrollUpdate.deltaX *= scale;
+ gesture_event->data.scrollUpdate.deltaY *= scale;
+ break;
+ case blink::WebInputEvent::GestureScrollBegin:
+ gesture_event->data.scrollBegin.deltaXHint *= scale;
+ gesture_event->data.scrollBegin.deltaYHint *= scale;
+ break;
+
+ case blink::WebInputEvent::GesturePinchUpdate:
+ // Scale in pinch gesture is DSF agnostic.
+ break;
+
+ case blink::WebInputEvent::GestureDoubleTap:
+ case blink::WebInputEvent::GestureTap:
+ case blink::WebInputEvent::GestureTapUnconfirmed:
+ gesture_event->data.tap.width *= scale;
+ gesture_event->data.tap.height *= scale;
+ break;
+
+ case blink::WebInputEvent::GestureTapDown:
+ gesture_event->data.tapDown.width *= scale;
+ gesture_event->data.tapDown.height *= scale;
+ break;
+
+ case blink::WebInputEvent::GestureShowPress:
+ gesture_event->data.showPress.width *= scale;
+ gesture_event->data.showPress.height *= scale;
+ break;
+
+ case blink::WebInputEvent::GestureLongPress:
+ case blink::WebInputEvent::GestureLongTap:
+ gesture_event->data.longPress.width *= scale;
+ gesture_event->data.longPress.height *= scale;
+ break;
+
+ case blink::WebInputEvent::GestureTwoFingerTap:
+ gesture_event->data.twoFingerTap.firstFingerWidth *= scale;
+ gesture_event->data.twoFingerTap.firstFingerHeight *= scale;
+ break;
+
+ case blink::WebInputEvent::GestureFlingStart:
+ gesture_event->data.flingStart.velocityX *= scale;
+ gesture_event->data.flingStart.velocityY *= scale;
+ break;
+
+ // These event does not have location data.
+ case blink::WebInputEvent::GesturePinchBegin:
+ case blink::WebInputEvent::GesturePinchEnd:
+ case blink::WebInputEvent::GestureTapCancel:
+ case blink::WebInputEvent::GestureFlingCancel:
+ case blink::WebInputEvent::GestureScrollEnd:
+ break;
+
+ // TODO(oshima): Find out if ContextMenu needs to be scaled.
+ default:
+ break;
+ }
+ }
+ return scaled_event;
+}
+
+WebPointerProperties::PointerType ToWebPointerType(
+ MotionEvent::ToolType tool_type) {
+ switch (tool_type) {
+ case MotionEvent::TOOL_TYPE_UNKNOWN:
+ return WebPointerProperties::PointerType::Unknown;
+ case MotionEvent::TOOL_TYPE_FINGER:
+ return WebPointerProperties::PointerType::Touch;
+ case MotionEvent::TOOL_TYPE_STYLUS:
+ return WebPointerProperties::PointerType::Pen;
+ case MotionEvent::TOOL_TYPE_MOUSE:
+ return WebPointerProperties::PointerType::Mouse;
+ case MotionEvent::TOOL_TYPE_ERASER:
+ return WebPointerProperties::PointerType::Unknown;
+ }
+ NOTREACHED() << "Invalid MotionEvent::ToolType = " << tool_type;
+ return WebPointerProperties::PointerType::Unknown;
+}
+
} // namespace ui
diff --git a/chromium/ui/events/blink/blink_event_util.h b/chromium/ui/events/blink/blink_event_util.h
index c0f60c921ec..bee5c7a6038 100644
--- a/chromium/ui/events/blink/blink_event_util.h
+++ b/chromium/ui/events/blink/blink_event_util.h
@@ -5,12 +5,17 @@
#ifndef UI_EVENTS_BLINK_BLINK_EVENT_UTIL_H_
#define UI_EVENTS_BLINK_BLINK_EVENT_UTIL_H_
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/gesture_detection/motion_event.h"
+
namespace base {
class TimeDelta;
}
namespace blink {
class WebGestureEvent;
+class WebInputEvent;
class WebTouchEvent;
}
@@ -39,6 +44,13 @@ blink::WebGestureEvent CreateWebGestureEventFromGestureEventData(
int EventFlagsToWebEventModifiers(int flags);
-} // namespace content
+scoped_ptr<blink::WebInputEvent> ScaleWebInputEvent(
+ const blink::WebInputEvent& event,
+ float scale);
+
+blink::WebPointerProperties::PointerType ToWebPointerType(
+ MotionEvent::ToolType tool_type);
+
+} // namespace ui
#endif // UI_EVENTS_BLINK_BLINK_EVENT_UTIL_H_
diff --git a/chromium/ui/events/blink/blink_event_util_unittest.cc b/chromium/ui/events/blink/blink_event_util_unittest.cc
new file mode 100644
index 00000000000..cb0830caabe
--- /dev/null
+++ b/chromium/ui/events/blink/blink_event_util_unittest.cc
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/blink/blink_event_util.h"
+
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/gesture_event_details.h"
+
+namespace ui {
+
+using BlinkEventUtilTest = testing::Test;
+
+TEST(BlinkEventUtilTest, NoScalingWith1DSF) {
+ const ui::GestureEventDetails details(ui::ET_GESTURE_SCROLL_UPDATE,
+ 1,
+ 1);
+ auto event =
+ CreateWebGestureEvent(details,
+ base::TimeDelta::FromMilliseconds(1),
+ gfx::PointF(1.f, 1.f),
+ gfx::PointF(1.f, 1.f),
+ 0);
+ EXPECT_FALSE(ScaleWebInputEvent(event, 1.f));
+ EXPECT_TRUE(ScaleWebInputEvent(event, 2.f));
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/blink/input_handler_proxy.cc b/chromium/ui/events/blink/input_handler_proxy.cc
index 0c164d704ff..2ac8c61b9e9 100644
--- a/chromium/ui/events/blink/input_handler_proxy.cc
+++ b/chromium/ui/events/blink/input_handler_proxy.cc
@@ -16,6 +16,7 @@
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "cc/input/main_thread_scrolling_reason.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/blink/input_handler_proxy_client.h"
#include "ui/events/blink/input_scroll_elasticity_controller.h"
@@ -34,6 +35,8 @@ using blink::WebTouchPoint;
namespace {
+const int32_t kEventDispositionUndefined = -1;
+
// Maximum time between a fling event's timestamp and the first |Animate| call
// for the fling curve to use the fling timestamp as the initial animation time.
// Two frames allows a minor delay between event creation and the first animate.
@@ -122,28 +125,34 @@ WebGestureEvent ObtainGestureScrollBegin(const WebGestureEvent& event) {
}
cc::ScrollState CreateScrollStateForGesture(const WebGestureEvent& event) {
+ cc::ScrollStateData scroll_state_data;
switch (event.type) {
case WebInputEvent::GestureScrollBegin:
- return cc::ScrollState(0, 0, event.x, event.y, 0, 0, true, false, false);
+ scroll_state_data.start_position_x = event.x;
+ scroll_state_data.start_position_y = event.y;
+ scroll_state_data.is_beginning = true;
+ break;
case WebInputEvent::GestureFlingStart:
- return cc::ScrollState(
- 0, 0, event.x, event.y, event.data.flingStart.velocityX,
- event.data.flingStart.velocityX, true, true, false);
+ scroll_state_data.velocity_x = event.data.flingStart.velocityX;
+ scroll_state_data.velocity_y = event.data.flingStart.velocityY;
+ scroll_state_data.is_in_inertial_phase = true;
+ break;
case WebInputEvent::GestureScrollUpdate:
- return cc::ScrollState(-event.data.scrollUpdate.deltaX,
- -event.data.scrollUpdate.deltaY, event.x, event.y,
- event.data.scrollUpdate.velocityX,
- event.data.scrollUpdate.velocityY,
- event.data.scrollUpdate.inertial, false, false);
+ scroll_state_data.delta_x = -event.data.scrollUpdate.deltaX;
+ scroll_state_data.delta_y = -event.data.scrollUpdate.deltaY;
+ scroll_state_data.velocity_x = event.data.scrollUpdate.velocityX;
+ scroll_state_data.velocity_y = event.data.scrollUpdate.velocityY;
+ scroll_state_data.is_in_inertial_phase = event.data.scrollUpdate.inertial;
+ break;
case WebInputEvent::GestureScrollEnd:
- return cc::ScrollState(0, 0, event.x, event.y, 0, 0, false, false, true);
case WebInputEvent::GestureFlingCancel:
- return cc::ScrollState(0, 0, event.x, event.y, 0, 0, false, true, true);
-
+ scroll_state_data.is_ending = true;
+ break;
default:
NOTREACHED();
- return cc::ScrollState(0, 0, 0, 0, 0, 0, false, false, false);
+ break;
}
+ return cc::ScrollState(scroll_state_data);
}
void ReportInputEventLatencyUma(const WebInputEvent& event,
@@ -199,6 +208,13 @@ void ReportInputEventLatencyUma(const WebInputEvent& event,
}
}
+cc::InputHandler::ScrollInputType GestureScrollInputType(
+ blink::WebGestureDevice device) {
+ return device == blink::WebGestureDeviceTouchpad
+ ? cc::InputHandler::WHEEL
+ : cc::InputHandler::TOUCHSCREEN;
+}
+
} // namespace
namespace ui {
@@ -220,7 +236,9 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
disallow_vertical_fling_scroll_(false),
has_fling_animation_started_(false),
smooth_scroll_enabled_(false),
- uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()) {
+ uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()),
+ use_gesture_events_for_mouse_wheel_(true),
+ touch_start_result_(kEventDispositionUndefined) {
DCHECK(client);
input_handler_->BindToClient(this);
cc::ScrollElasticityHelper* scroll_elasticity_helper =
@@ -287,8 +305,9 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(event);
if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
- input_handler_->HaveWheelEventHandlersAt(
- gfx::Point(gesture_event.x, gesture_event.y))) {
+ input_handler_->GetEventListenerProperties(
+ cc::EventListenerClass::kMouseWheel) !=
+ cc::EventListenerProperties::kNone) {
return DID_NOT_HANDLE;
} else {
input_handler_->PinchGestureBegin();
@@ -335,6 +354,12 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
case WebInputEvent::TouchStart:
return HandleTouchStart(static_cast<const WebTouchEvent&>(event));
+ case WebInputEvent::TouchMove:
+ return HandleTouchMove(static_cast<const WebTouchEvent&>(event));
+
+ case WebInputEvent::TouchEnd:
+ return HandleTouchEnd(static_cast<const WebTouchEvent&>(event));
+
case WebInputEvent::MouseMove: {
const WebMouseEvent& mouse_event =
static_cast<const WebMouseEvent&>(event);
@@ -359,18 +384,92 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
return DID_NOT_HANDLE;
}
-bool InputHandlerProxy::ShouldAnimate(
- const blink::WebMouseWheelEvent& event) const {
+void InputHandlerProxy::RecordMainThreadScrollingReasons(
+ WebInputEvent::Type type,
+ uint32_t reasons) {
+ static const char* kGestureHistogramName =
+ "Renderer4.MainThreadGestureScrollReason";
+ static const char* kWheelHistogramName =
+ "Renderer4.MainThreadWheelScrollReason";
+
+ DCHECK(type == WebInputEvent::GestureScrollBegin ||
+ type == WebInputEvent::MouseWheel);
+
+ if (type != WebInputEvent::GestureScrollBegin &&
+ type != WebInputEvent::MouseWheel) {
+ return;
+ }
+
+ if (reasons == cc::MainThreadScrollingReason::kNotScrollingOnMain) {
+ if (type == WebInputEvent::GestureScrollBegin) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGestureHistogramName,
+ cc::MainThreadScrollingReason::kNotScrollingOnMain,
+ cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ kWheelHistogramName,
+ cc::MainThreadScrollingReason::kNotScrollingOnMain,
+ cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount);
+ }
+ }
+
+ for (uint32_t i = 0;
+ i < cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount - 1;
+ ++i) {
+ unsigned val = 1 << i;
+ if (reasons & val) {
+ if (type == WebInputEvent::GestureScrollBegin) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kGestureHistogramName, i + 1,
+ cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION(
+ kWheelHistogramName, i + 1,
+ cc::MainThreadScrollingReason::kMainThreadScrollingReasonCount);
+ }
+ }
+ }
+}
+
+bool InputHandlerProxy::ShouldAnimate(bool has_precise_scroll_deltas) const {
#if defined(OS_MACOSX)
// Mac does not smooth scroll wheel events (crbug.com/574283).
return false;
#else
- return smooth_scroll_enabled_ && !event.hasPreciseScrollingDeltas;
+ return smooth_scroll_enabled_ && !has_precise_scroll_deltas;
#endif
}
InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
const WebMouseWheelEvent& wheel_event) {
+ // Only call |CancelCurrentFling()| if a fling was active, as it will
+ // otherwise disrupt an in-progress touch scroll.
+ if (!wheel_event.hasPreciseScrollingDeltas && fling_curve_)
+ CancelCurrentFling();
+
+ if (use_gesture_events_for_mouse_wheel_) {
+ cc::EventListenerProperties properties =
+ input_handler_->GetEventListenerProperties(
+ cc::EventListenerClass::kMouseWheel);
+ switch (properties) {
+ case cc::EventListenerProperties::kPassive:
+ return DID_HANDLE_NON_BLOCKING;
+ case cc::EventListenerProperties::kBlockingAndPassive:
+ case cc::EventListenerProperties::kBlocking:
+ return DID_NOT_HANDLE;
+ case cc::EventListenerProperties::kNone:
+ return DROP_EVENT;
+ default:
+ NOTREACHED();
+ return DROP_EVENT;
+ }
+ }
+ return ScrollByMouseWheel(wheel_event);
+}
+
+InputHandlerProxy::EventDisposition InputHandlerProxy::ScrollByMouseWheel(
+ const WebMouseWheelEvent& wheel_event) {
InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE;
cc::InputHandlerScrollResult scroll_result;
@@ -388,16 +487,23 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
// TODO(jamesr): We don't properly handle scroll by page in the compositor
// thread, so punt it to the main thread. http://crbug.com/236639
result = DID_NOT_HANDLE;
+ RecordMainThreadScrollingReasons(
+ wheel_event.type, cc::MainThreadScrollingReason::kPageBasedScrolling);
+
} else if (!wheel_event.canScroll) {
// Wheel events with |canScroll| == false will not trigger scrolling,
// only event handlers. Forward to the main thread.
result = DID_NOT_HANDLE;
- } else if (ShouldAnimate(wheel_event)) {
+ } else if (ShouldAnimate(wheel_event.hasPreciseScrollingDeltas)) {
cc::InputHandler::ScrollStatus scroll_status =
input_handler_->ScrollAnimated(gfx::Point(wheel_event.x, wheel_event.y),
scroll_delta);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED:
+
+ RecordMainThreadScrollingReasons(
+ wheel_event.type, scroll_status.main_thread_scrolling_reasons);
+
+ switch (scroll_status.thread) {
+ case cc::InputHandler::SCROLL_ON_IMPL_THREAD:
result = DID_HANDLE;
break;
case cc::InputHandler::SCROLL_IGNORED:
@@ -408,27 +514,38 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
break;
}
} else {
- cc::ScrollState scroll_state_begin(0, 0, wheel_event.x, wheel_event.y, 0, 0,
- true, false, false);
- cc::InputHandler::ScrollStatus scroll_status =
- input_handler_->ScrollBegin(&scroll_state_begin,
- cc::InputHandler::WHEEL);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED: {
+ cc::ScrollStateData scroll_state_begin_data;
+ scroll_state_begin_data.start_position_x = wheel_event.x;
+ scroll_state_begin_data.start_position_y = wheel_event.y;
+ scroll_state_begin_data.is_beginning = true;
+ cc::ScrollState scroll_state_begin(scroll_state_begin_data);
+ cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
+ &scroll_state_begin, cc::InputHandler::WHEEL);
+
+ RecordMainThreadScrollingReasons(
+ wheel_event.type, scroll_status.main_thread_scrolling_reasons);
+
+ switch (scroll_status.thread) {
+ case cc::InputHandler::SCROLL_ON_IMPL_THREAD: {
TRACE_EVENT_INSTANT2("input",
"InputHandlerProxy::handle_input wheel scroll",
TRACE_EVENT_SCOPE_THREAD, "deltaX",
scroll_delta.x(), "deltaY", scroll_delta.y());
- cc::ScrollState scroll_state_update(scroll_delta.x(), scroll_delta.y(),
- wheel_event.x, wheel_event.y, 0, 0,
- false, false, false);
+
+ cc::ScrollStateData scroll_state_update_data;
+ scroll_state_update_data.delta_x = scroll_delta.x();
+ scroll_state_update_data.delta_y = scroll_delta.y();
+ scroll_state_update_data.start_position_x = wheel_event.x;
+ scroll_state_update_data.start_position_y = wheel_event.y;
+ cc::ScrollState scroll_state_update(scroll_state_update_data);
scroll_result = input_handler_->ScrollBy(&scroll_state_update);
HandleOverscroll(gfx::Point(wheel_event.x, wheel_event.y),
scroll_result);
- cc::ScrollState scroll_state_end(0, 0, wheel_event.x, wheel_event.y,
- 0, 0, false, false, true);
+ cc::ScrollStateData scroll_state_end_data;
+ scroll_state_end_data.is_ending = true;
+ cc::ScrollState scroll_state_end(scroll_state_end_data);
input_handler_->ScrollEnd(&scroll_state_end);
result = scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
@@ -445,9 +562,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
case cc::InputHandler::SCROLL_ON_MAIN_THREAD:
result = DID_NOT_HANDLE;
break;
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
- break;
}
}
@@ -479,33 +593,51 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
#endif
cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
cc::InputHandler::ScrollStatus scroll_status;
- if (gesture_event.data.scrollBegin.targetViewport) {
- scroll_status = input_handler_->RootScrollBegin(&scroll_state,
- cc::InputHandler::GESTURE);
+ if (gesture_event.data.scrollBegin.deltaHintUnits ==
+ blink::WebGestureEvent::ScrollUnits::Page) {
+ scroll_status.thread = cc::InputHandler::SCROLL_ON_MAIN_THREAD;
+ scroll_status.main_thread_scrolling_reasons =
+ cc::MainThreadScrollingReason::kContinuingMainThreadScroll;
+ } else if (gesture_event.data.scrollBegin.targetViewport) {
+ scroll_status = input_handler_->RootScrollBegin(
+ &scroll_state, GestureScrollInputType(gesture_event.sourceDevice));
+ } else if (ShouldAnimate(gesture_event.data.scrollBegin.deltaHintUnits !=
+ blink::WebGestureEvent::ScrollUnits::Pixels)) {
+ gfx::Point scroll_point(gesture_event.x, gesture_event.y);
+ scroll_status = input_handler_->ScrollAnimatedBegin(scroll_point);
} else {
- scroll_status =
- input_handler_->ScrollBegin(&scroll_state, cc::InputHandler::GESTURE);
+ scroll_status = input_handler_->ScrollBegin(
+ &scroll_state, GestureScrollInputType(gesture_event.sourceDevice));
}
UMA_HISTOGRAM_ENUMERATION("Renderer4.CompositorScrollHitTestResult",
- scroll_status,
- cc::InputHandler::ScrollStatusCount);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED:
+ scroll_status.thread,
+ cc::InputHandler::LAST_SCROLL_STATUS + 1);
+
+ RecordMainThreadScrollingReasons(gesture_event.type,
+ scroll_status.main_thread_scrolling_reasons);
+
+ InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE;
+ switch (scroll_status.thread) {
+ case cc::InputHandler::SCROLL_ON_IMPL_THREAD:
TRACE_EVENT_INSTANT0("input",
"InputHandlerProxy::handle_input gesture scroll",
TRACE_EVENT_SCOPE_THREAD);
gesture_scroll_on_impl_thread_ = true;
- return DID_HANDLE;
+ result = DID_HANDLE;
+ break;
case cc::InputHandler::SCROLL_UNKNOWN:
case cc::InputHandler::SCROLL_ON_MAIN_THREAD:
- return DID_NOT_HANDLE;
+ result = DID_NOT_HANDLE;
+ break;
case cc::InputHandler::SCROLL_IGNORED:
- return DROP_EVENT;
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
+ result = DROP_EVENT;
break;
}
- return DID_NOT_HANDLE;
+ if (scroll_elasticity_controller_ && result != DID_NOT_HANDLE)
+ HandleScrollElasticityOverscroll(gesture_event,
+ cc::InputHandlerScrollResult());
+
+ return result;
}
InputHandlerProxy::EventDisposition
@@ -514,14 +646,32 @@ InputHandlerProxy::HandleGestureScrollUpdate(
#ifndef NDEBUG
DCHECK(expect_scroll_update_end_);
#endif
-
if (!gesture_scroll_on_impl_thread_ && !gesture_pinch_on_impl_thread_)
return DID_NOT_HANDLE;
cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
+ gfx::Point scroll_point(gesture_event.x, gesture_event.y);
+ gfx::Vector2dF scroll_delta(-gesture_event.data.scrollUpdate.deltaX,
+ -gesture_event.data.scrollUpdate.deltaY);
+
+ if (ShouldAnimate(gesture_event.data.scrollUpdate.deltaUnits !=
+ blink::WebGestureEvent::ScrollUnits::Pixels)) {
+ switch (input_handler_->ScrollAnimated(scroll_point, scroll_delta).thread) {
+ case cc::InputHandler::SCROLL_ON_IMPL_THREAD:
+ return DID_HANDLE;
+ case cc::InputHandler::SCROLL_IGNORED:
+ return DROP_EVENT;
+ default:
+ return DID_NOT_HANDLE;
+ }
+ }
cc::InputHandlerScrollResult scroll_result =
input_handler_->ScrollBy(&scroll_state);
- HandleOverscroll(gfx::Point(gesture_event.x, gesture_event.y), scroll_result);
+ HandleOverscroll(scroll_point, scroll_result);
+
+ if (scroll_elasticity_controller_)
+ HandleScrollElasticityOverscroll(gesture_event, scroll_result);
+
return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
}
@@ -531,10 +681,21 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd(
DCHECK(expect_scroll_update_end_);
expect_scroll_update_end_ = false;
#endif
- cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
- input_handler_->ScrollEnd(&scroll_state);
+ if (ShouldAnimate(gesture_event.data.scrollEnd.deltaUnits !=
+ blink::WebGestureEvent::ScrollUnits::Pixels)) {
+ // Do nothing if the scroll is being animated; the scroll animation will
+ // generate the ScrollEnd when it is done.
+ } else {
+ cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
+ input_handler_->ScrollEnd(&scroll_state);
+ }
if (!gesture_scroll_on_impl_thread_)
return DID_NOT_HANDLE;
+
+ if (scroll_elasticity_controller_)
+ HandleScrollElasticityOverscroll(gesture_event,
+ cc::InputHandlerScrollResult());
+
gesture_scroll_on_impl_thread_ = false;
return DID_HANDLE;
}
@@ -542,8 +703,9 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd(
InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
const WebGestureEvent& gesture_event) {
cc::ScrollState scroll_state = CreateScrollStateForGesture(gesture_event);
- cc::InputHandler::ScrollStatus scroll_status =
- cc::InputHandler::SCROLL_ON_MAIN_THREAD;
+ cc::InputHandler::ScrollStatus scroll_status;
+ scroll_status.main_thread_scrolling_reasons =
+ cc::MainThreadScrollingReason::kNotScrollingOnMain;
switch (gesture_event.sourceDevice) {
case blink::WebGestureDeviceTouchpad:
if (gesture_event.data.flingStart.targetViewport) {
@@ -555,10 +717,13 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
}
break;
case blink::WebGestureDeviceTouchscreen:
- if (!gesture_scroll_on_impl_thread_)
- scroll_status = cc::InputHandler::SCROLL_ON_MAIN_THREAD;
- else
+ if (!gesture_scroll_on_impl_thread_) {
+ scroll_status.thread = cc::InputHandler::SCROLL_ON_MAIN_THREAD;
+ scroll_status.main_thread_scrolling_reasons =
+ cc::MainThreadScrollingReason::kContinuingMainThreadScroll;
+ } else {
scroll_status = input_handler_->FlingScrollBegin();
+ }
break;
case blink::WebGestureDeviceUninitialized:
NOTREACHED();
@@ -569,8 +734,8 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
expect_scroll_update_end_ = false;
#endif
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED: {
+ switch (scroll_status.thread) {
+ case cc::InputHandler::SCROLL_ON_IMPL_THREAD: {
if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad) {
scroll_state.set_is_ending(true);
input_handler_->ScrollEnd(&scroll_state);
@@ -626,27 +791,84 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
}
return DROP_EVENT;
}
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
- break;
}
return DID_NOT_HANDLE;
}
InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
const blink::WebTouchEvent& touch_event) {
+ EventDisposition result = DROP_EVENT;
for (size_t i = 0; i < touch_event.touchesLength; ++i) {
if (touch_event.touches[i].state != WebTouchPoint::StatePressed)
continue;
if (input_handler_->DoTouchEventsBlockScrollAt(
gfx::Point(touch_event.touches[i].position.x,
touch_event.touches[i].position.y))) {
- // TODO(rbyers): We should consider still sending the touch events to
- // main asynchronously (crbug.com/455539).
- return DID_NOT_HANDLE;
+ result = DID_NOT_HANDLE;
+ break;
}
}
- return DROP_EVENT;
+
+ // If |result| is DROP_EVENT it wasn't processed above.
+ if (result == DROP_EVENT) {
+ switch (input_handler_->GetEventListenerProperties(
+ cc::EventListenerClass::kTouchStartOrMove)) {
+ case cc::EventListenerProperties::kPassive:
+ result = DID_HANDLE_NON_BLOCKING;
+ break;
+ case cc::EventListenerProperties::kBlocking:
+ // The touch area rects above already have checked whether it hits
+ // a blocking region. Since it does not the event can be dropped.
+ result = DROP_EVENT;
+ break;
+ case cc::EventListenerProperties::kBlockingAndPassive:
+ // There is at least one passive listener that needs to possibly
+ // be notified so it can't be dropped.
+ result = DID_HANDLE_NON_BLOCKING;
+ break;
+ case cc::EventListenerProperties::kNone:
+ result = DROP_EVENT;
+ break;
+ default:
+ NOTREACHED();
+ result = DROP_EVENT;
+ break;
+ }
+ }
+
+ // Merge |touch_start_result_| and |result| so the result has the highest
+ // priority value according to the sequence; (DROP_EVENT,
+ // DID_HANDLE_NON_BLOCKING, DID_NOT_HANDLE).
+ if (touch_start_result_ == kEventDispositionUndefined ||
+ touch_start_result_ == DROP_EVENT || result == DID_NOT_HANDLE)
+ touch_start_result_ = result;
+
+ // If |result| is still DROP_EVENT look at the touch end handler as
+ // we may not want to discard the entire touch sequence. Note this
+ // code is explicitly after the assignment of the |touch_start_result_|
+ // so the touch moves are not sent to the main thread un-necessarily.
+ if (result == DROP_EVENT &&
+ input_handler_->GetEventListenerProperties(
+ cc::EventListenerClass::kTouchEndOrCancel) !=
+ cc::EventListenerProperties::kNone) {
+ result = DID_HANDLE_NON_BLOCKING;
+ }
+
+ return result;
+}
+
+InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove(
+ const blink::WebTouchEvent& touch_event) {
+ if (touch_start_result_ != kEventDispositionUndefined)
+ return static_cast<EventDisposition>(touch_start_result_);
+ return DID_NOT_HANDLE;
+}
+
+InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchEnd(
+ const blink::WebTouchEvent& touch_event) {
+ if (touch_event.touchesLength == 1)
+ touch_start_result_ = kEventDispositionUndefined;
+ return DID_NOT_HANDLE;
}
bool InputHandlerProxy::FilterInputEventForFlingBoosting(
@@ -697,7 +919,7 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
gfx::Point(gesture_event.x, gesture_event.y),
fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad
? cc::InputHandler::NON_BUBBLING_GESTURE
- : cc::InputHandler::GESTURE)) {
+ : cc::InputHandler::TOUCHSCREEN)) {
CancelCurrentFling();
return false;
}
@@ -899,6 +1121,14 @@ void InputHandlerProxy::SynchronouslySetRootScrollOffset(
input_handler_->SetSynchronousInputHandlerRootScrollOffset(root_offset);
}
+void InputHandlerProxy::SynchronouslyZoomBy(float magnify_delta,
+ const gfx::Point& anchor) {
+ DCHECK(synchronous_input_handler_);
+ input_handler_->PinchGestureBegin();
+ input_handler_->PinchGestureUpdate(magnify_delta, anchor);
+ input_handler_->PinchGestureEnd();
+}
+
void InputHandlerProxy::HandleOverscroll(
const gfx::Point& causal_event_viewport_point,
const cc::InputHandlerScrollResult& scroll_result) {
@@ -938,12 +1168,12 @@ bool InputHandlerProxy::CancelCurrentFling() {
}
bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() {
- bool had_fling_animation = fling_curve_;
+ bool had_fling_animation = !!fling_curve_;
if (had_fling_animation &&
fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchscreen) {
- cc::ScrollState scroll_state(0, 0, fling_parameters_.point.x,
- fling_parameters_.point.y, 0, 0, false, true,
- true);
+ cc::ScrollStateData scroll_state_data;
+ scroll_state_data.is_ending = true;
+ cc::ScrollState scroll_state(scroll_state_data);
input_handler_->ScrollEnd(&scroll_state);
TRACE_EVENT_ASYNC_END0(
"input",
@@ -990,25 +1220,47 @@ void InputHandlerProxy::RequestAnimation() {
bool InputHandlerProxy::TouchpadFlingScroll(
const WebFloatSize& increment) {
- WebMouseWheelEvent synthetic_wheel;
- synthetic_wheel.type = WebInputEvent::MouseWheel;
- synthetic_wheel.timeStampSeconds = InSecondsF(base::TimeTicks::Now());
- synthetic_wheel.deltaX = increment.width;
- synthetic_wheel.deltaY = increment.height;
- synthetic_wheel.hasPreciseScrollingDeltas = true;
- synthetic_wheel.x = fling_parameters_.point.x;
- synthetic_wheel.y = fling_parameters_.point.y;
- synthetic_wheel.globalX = fling_parameters_.globalPoint.x;
- synthetic_wheel.globalY = fling_parameters_.globalPoint.y;
- synthetic_wheel.modifiers = fling_parameters_.modifiers;
-
- InputHandlerProxy::EventDisposition disposition =
- HandleInputEvent(synthetic_wheel);
+ InputHandlerProxy::EventDisposition disposition;
+ cc::EventListenerProperties properties =
+ input_handler_->GetEventListenerProperties(
+ cc::EventListenerClass::kMouseWheel);
+ switch (properties) {
+ case cc::EventListenerProperties::kPassive:
+ disposition = DID_HANDLE_NON_BLOCKING;
+ break;
+ case cc::EventListenerProperties::kBlocking:
+ disposition = DID_NOT_HANDLE;
+ break;
+ case cc::EventListenerProperties::kNone: {
+ WebMouseWheelEvent synthetic_wheel;
+ synthetic_wheel.type = WebInputEvent::MouseWheel;
+ synthetic_wheel.timeStampSeconds = InSecondsF(base::TimeTicks::Now());
+ synthetic_wheel.deltaX = increment.width;
+ synthetic_wheel.deltaY = increment.height;
+ synthetic_wheel.hasPreciseScrollingDeltas = true;
+ synthetic_wheel.x = fling_parameters_.point.x;
+ synthetic_wheel.y = fling_parameters_.point.y;
+ synthetic_wheel.globalX = fling_parameters_.globalPoint.x;
+ synthetic_wheel.globalY = fling_parameters_.globalPoint.y;
+ synthetic_wheel.modifiers = fling_parameters_.modifiers;
+
+ disposition = ScrollByMouseWheel(synthetic_wheel);
+ break;
+ }
+ default:
+ NOTREACHED();
+ return false;
+ }
+
switch (disposition) {
case DID_HANDLE:
return true;
case DROP_EVENT:
break;
+ case DID_HANDLE_NON_BLOCKING:
+ // TODO(dtapuska): Process the fling on the compositor thread
+ // but post the events to the main thread; for now just pass it to the
+ // main thread.
case DID_NOT_HANDLE:
TRACE_EVENT_INSTANT0("input",
"InputHandlerProxy::scrollBy::AbortFling",
@@ -1063,10 +1315,13 @@ bool InputHandlerProxy::scrollBy(const WebFloatSize& increment,
break;
case blink::WebGestureDeviceTouchscreen: {
clipped_increment = ToClientScrollIncrement(clipped_increment);
- cc::ScrollState scroll_state(
- clipped_increment.width, clipped_increment.height,
- fling_parameters_.point.x, fling_parameters_.point.y,
- clipped_velocity.width, clipped_velocity.height, false, true, false);
+ cc::ScrollStateData scroll_state_data;
+ scroll_state_data.delta_x = clipped_increment.width;
+ scroll_state_data.delta_y = clipped_increment.height;
+ scroll_state_data.velocity_x = clipped_velocity.width;
+ scroll_state_data.velocity_y = clipped_velocity.height;
+ scroll_state_data.is_in_inertial_phase = true;
+ cc::ScrollState scroll_state(scroll_state_data);
cc::InputHandlerScrollResult scroll_result =
input_handler_->ScrollBy(&scroll_state);
HandleOverscroll(fling_parameters_.point, scroll_result);
@@ -1092,4 +1347,19 @@ bool InputHandlerProxy::scrollBy(const WebFloatSize& increment,
return did_scroll;
}
+void InputHandlerProxy::HandleScrollElasticityOverscroll(
+ const WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result) {
+ DCHECK(scroll_elasticity_controller_);
+ // Send the event and its disposition to the elasticity controller to update
+ // the over-scroll animation. Note that the call to the elasticity controller
+ // is made asynchronously, to minimize divergence between main thread and
+ // impl thread event handling paths.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&InputScrollElasticityController::ObserveGestureEventAndResult,
+ scroll_elasticity_controller_->GetWeakPtr(), gesture_event,
+ scroll_result));
+}
+
} // namespace ui
diff --git a/chromium/ui/events/blink/input_handler_proxy.h b/chromium/ui/events/blink/input_handler_proxy.h
index e96b31bf40b..4ef107fba76 100644
--- a/chromium/ui/events/blink/input_handler_proxy.h
+++ b/chromium/ui/events/blink/input_handler_proxy.h
@@ -46,10 +46,14 @@ class InputHandlerProxy
}
void set_smooth_scroll_enabled(bool value) { smooth_scroll_enabled_ = value; }
+ void set_use_gesture_events_for_mouse_wheel(bool value) {
+ use_gesture_events_for_mouse_wheel_ = value;
+ }
enum EventDisposition {
DID_HANDLE,
DID_NOT_HANDLE,
+ DID_HANDLE_NON_BLOCKING,
DROP_EVENT
};
EventDisposition HandleInputEventWithLatencyInfo(
@@ -76,6 +80,8 @@ class InputHandlerProxy
void SynchronouslyAnimate(base::TimeTicks time) override;
void SynchronouslySetRootScrollOffset(
const gfx::ScrollOffset& root_offset) override;
+ void SynchronouslyZoomBy(float magnify_delta,
+ const gfx::Point& anchor) override;
// blink::WebGestureCurveTarget implementation.
bool scrollBy(const blink::WebFloatSize& offset,
@@ -85,12 +91,17 @@ class InputHandlerProxy
return gesture_scroll_on_impl_thread_;
}
+ protected:
+ void RecordMainThreadScrollingReasons(blink::WebInputEvent::Type type,
+ uint32_t reasons);
+
private:
friend class test::InputHandlerProxyTest;
// Helper functions for handling more complicated input events.
EventDisposition HandleMouseWheel(
const blink::WebMouseWheelEvent& event);
+ EventDisposition ScrollByMouseWheel(const blink::WebMouseWheelEvent& event);
EventDisposition HandleGestureScrollBegin(
const blink::WebGestureEvent& event);
EventDisposition HandleGestureScrollUpdate(
@@ -99,8 +110,9 @@ class InputHandlerProxy
const blink::WebGestureEvent& event);
EventDisposition HandleGestureFlingStart(
const blink::WebGestureEvent& event);
- EventDisposition HandleTouchStart(
- const blink::WebTouchEvent& event);
+ EventDisposition HandleTouchStart(const blink::WebTouchEvent& event);
+ EventDisposition HandleTouchMove(const blink::WebTouchEvent& event);
+ EventDisposition HandleTouchEnd(const blink::WebTouchEvent& event);
// Returns true if the event should be suppressed due to to an active,
// boost-enabled fling, in which case further processing should cease.
@@ -132,7 +144,12 @@ class InputHandlerProxy
const cc::InputHandlerScrollResult& scroll_result);
// Whether to use a smooth scroll animation for this event.
- bool ShouldAnimate(const blink::WebMouseWheelEvent& event) const;
+ bool ShouldAnimate(bool has_precise_scroll_deltas) const;
+
+ // Update the elastic overscroll controller with |gesture_event|.
+ void HandleScrollElasticityOverscroll(
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result);
scoped_ptr<blink::WebGestureCurve> fling_curve_;
// Parameters for the active fling animation, stored in case we need to
@@ -184,8 +201,13 @@ class InputHandlerProxy
scoped_ptr<InputScrollElasticityController> scroll_elasticity_controller_;
bool smooth_scroll_enabled_;
-
bool uma_latency_reporting_enabled_;
+ bool use_gesture_events_for_mouse_wheel_;
+
+ // The merged result of the last touch start with previous touch starts.
+ // This value will get returned for subsequent TouchMove events to allow
+ // passive events not to block scrolling.
+ int32_t touch_start_result_;
base::TimeTicks last_fling_animate_time_;
diff --git a/chromium/ui/events/blink/input_handler_proxy_unittest.cc b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
index ccf24f47e6f..1ff2d374e10 100644
--- a/chromium/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
@@ -6,6 +6,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/test/histogram_tester.h"
+#include "cc/input/main_thread_scrolling_reason.h"
#include "cc/trees/swap_promise_monitor.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -103,6 +105,8 @@ class MockInputHandler : public cc::InputHandler {
MOCK_METHOD2(RootScrollBegin,
ScrollStatus(cc::ScrollState*,
cc::InputHandler::ScrollInputType type));
+ MOCK_METHOD1(ScrollAnimatedBegin,
+ ScrollStatus(const gfx::Point& viewport_point));
MOCK_METHOD2(ScrollAnimated,
ScrollStatus(const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta));
@@ -130,7 +134,9 @@ class MockInputHandler : public cc::InputHandler {
bool(const gfx::Point& point,
cc::InputHandler::ScrollInputType type));
- MOCK_METHOD1(HaveWheelEventHandlersAt, bool(const gfx::Point& point));
+ MOCK_CONST_METHOD1(
+ GetEventListenerProperties,
+ cc::EventListenerProperties(cc::EventListenerClass event_class));
MOCK_METHOD1(DoTouchEventsBlockScrollAt, bool(const gfx::Point& point));
MOCK_METHOD0(RequestUpdateForSynchronousInputHandler, void());
@@ -242,6 +248,29 @@ WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x,
return point;
}
+const cc::InputHandler::ScrollStatus kImplThreadScrollState(
+ cc::InputHandler::SCROLL_ON_IMPL_THREAD,
+ cc::MainThreadScrollingReason::kNotScrollingOnMain);
+
+const cc::InputHandler::ScrollStatus kMainThreadScrollState(
+ cc::InputHandler::SCROLL_ON_MAIN_THREAD,
+ cc::MainThreadScrollingReason::kEventHandlers);
+
+const cc::InputHandler::ScrollStatus kScrollIgnoredScrollState(
+ cc::InputHandler::SCROLL_IGNORED,
+ cc::MainThreadScrollingReason::kNotScrollable);
+
+class TestInputHandlerProxy : public InputHandlerProxy {
+ public:
+ TestInputHandlerProxy(cc::InputHandler* input_handler,
+ InputHandlerProxyClient* client)
+ : InputHandlerProxy(input_handler, client) {}
+ void RecordMainThreadScrollingReasonsForTest(blink::WebInputEvent::Type type,
+ uint32_t reasons) {
+ RecordMainThreadScrollingReasons(type, reasons);
+ }
+};
+
} // namespace
class InputHandlerProxyTest
@@ -255,7 +284,7 @@ class InputHandlerProxyTest
GetParam() == CHILD_SCROLL_SYNCHRONOUS_HANDLER),
expected_disposition_(InputHandlerProxy::DID_HANDLE) {
input_handler_.reset(
- new ui::InputHandlerProxy(
+ new TestInputHandlerProxy(
&mock_input_handler_, &mock_client_));
scroll_result_did_scroll_.did_scroll = true;
scroll_result_did_not_scroll_.did_scroll = false;
@@ -321,7 +350,7 @@ class InputHandlerProxyTest
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = source_device;
EXPECT_EQ(expected_disposition_,
@@ -330,7 +359,7 @@ class InputHandlerProxyTest
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
gesture_ =
@@ -354,22 +383,32 @@ class InputHandlerProxyTest
input_handler_->smooth_scroll_enabled_ = value;
}
+ void SetMouseWheelGesturesOn(bool value) {
+ input_handler_->set_use_gesture_events_for_mouse_wheel(value);
+ }
+
+ base::HistogramTester& histogram_tester() {
+ return histogram_tester_;
+ }
+
protected:
const bool synchronous_root_scroll_;
const bool install_synchronous_handler_;
testing::StrictMock<MockInputHandler> mock_input_handler_;
testing::StrictMock<MockSynchronousInputHandler>
mock_synchronous_input_handler_;
- scoped_ptr<ui::InputHandlerProxy> input_handler_;
+ scoped_ptr<TestInputHandlerProxy> input_handler_;
testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
WebGestureEvent gesture_;
InputHandlerProxy::EventDisposition expected_disposition_;
+ base::HistogramTester histogram_tester_;
cc::InputHandlerScrollResult scroll_result_did_scroll_;
cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
};
TEST_P(InputHandlerProxyTest, MouseWheelByPageMainThread) {
expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ SetMouseWheelGesturesOn(false);
WebMouseWheelEvent wheel;
wheel.type = WebInputEvent::MouseWheel;
wheel.scrollByPage = true;
@@ -380,6 +419,7 @@ TEST_P(InputHandlerProxyTest, MouseWheelByPageMainThread) {
TEST_P(InputHandlerProxyTest, MouseWheelWithCtrlNotScroll) {
expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ SetMouseWheelGesturesOn(false);
WebMouseWheelEvent wheel;
wheel.type = WebInputEvent::MouseWheel;
wheel.modifiers = WebInputEvent::ControlKey;
@@ -388,6 +428,45 @@ TEST_P(InputHandlerProxyTest, MouseWheelWithCtrlNotScroll) {
VERIFY_AND_RESET_MOCKS();
}
+TEST_P(InputHandlerProxyTest, MouseWheelNoListener) {
+ expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.modifiers = WebInputEvent::ControlKey;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_P(InputHandlerProxyTest, MouseWheelPassiveListener) {
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
+
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.modifiers = WebInputEvent::ControlKey;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_P(InputHandlerProxyTest, MouseWheelBlockingListener) {
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
+
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.modifiers = WebInputEvent::ControlKey;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
+ VERIFY_AND_RESET_MOCKS();
+}
+
// Mac does not smooth scroll wheel events (crbug.com/574283).
#if !defined(OS_MACOSX)
TEST_P(InputHandlerProxyTest, MouseWheelWithPreciseScrollingDeltas) {
@@ -395,6 +474,7 @@ TEST_P(InputHandlerProxyTest, MouseWheelWithPreciseScrollingDeltas) {
TEST_P(InputHandlerProxyTest, DISABLED_MouseWheelWithPreciseScrollingDeltas) {
#endif
SetSmoothScrollEnabled(true);
+ SetMouseWheelGesturesOn(false);
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
WebMouseWheelEvent wheel;
wheel.type = WebInputEvent::MouseWheel;
@@ -404,7 +484,7 @@ TEST_P(InputHandlerProxyTest, DISABLED_MouseWheelWithPreciseScrollingDeltas) {
// Smooth scroll because hasPreciseScrollingDeltas is set to false.
wheel.hasPreciseScrollingDeltas = false;
EXPECT_CALL(mock_input_handler_, ScrollAnimated(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
VERIFY_AND_RESET_MOCKS();
@@ -412,7 +492,7 @@ TEST_P(InputHandlerProxyTest, DISABLED_MouseWheelWithPreciseScrollingDeltas) {
// No smooth scroll because hasPreciseScrollingDeltas is set to true.
wheel.hasPreciseScrollingDeltas = true;
EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollBy(::testing::_))
.WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
@@ -428,12 +508,13 @@ TEST_P(InputHandlerProxyTest, MouseWheelScrollIgnored) {
TEST_P(InputHandlerProxyTest, DISABLED_MouseWheelScrollIgnored) {
#endif
SetSmoothScrollEnabled(true);
+ SetMouseWheelGesturesOn(false);
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
WebMouseWheelEvent wheel;
wheel.type = WebInputEvent::MouseWheel;
EXPECT_CALL(mock_input_handler_, ScrollAnimated(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
+ .WillOnce(testing::Return(kScrollIgnoredScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
VERIFY_AND_RESET_MOCKS();
@@ -445,7 +526,7 @@ TEST_P(InputHandlerProxyTest, GestureScrollStarted) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_,input_handler_->HandleInputEvent(gesture_));
@@ -492,7 +573,7 @@ TEST_P(InputHandlerProxyTest, GestureScrollOnMainThread) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -524,7 +605,7 @@ TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
+ .WillOnce(testing::Return(kScrollIgnoredScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -538,13 +619,66 @@ TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
VERIFY_AND_RESET_MOCKS();
}
+TEST_P(InputHandlerProxyTest, GestureScrollByPage) {
+ // We should send all events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.data.scrollBegin.deltaHintUnits = WebGestureEvent::ScrollUnits::Page;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaY = 1;
+ gesture_.data.scrollUpdate.deltaUnits = WebGestureEvent::ScrollUnits::Page;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ gesture_.type = WebInputEvent::GestureScrollEnd;
+ gesture_.data.scrollUpdate.deltaY = 0;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_))
+ .WillOnce(testing::Return());
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+// Mac does not smooth scroll wheel events (crbug.com/574283).
+#if !defined(OS_MACOSX)
+TEST_P(InputHandlerProxyTest, GestureScrollByCoarsePixels) {
+#else
+TEST_P(InputHandlerProxyTest, DISABLED_GestureScrollByCoarsePixels) {
+#endif
+ SetSmoothScrollEnabled(true);
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.data.scrollBegin.deltaHintUnits =
+ WebGestureEvent::ScrollUnits::Pixels;
+ EXPECT_CALL(mock_input_handler_, ScrollAnimatedBegin(::testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaUnits = WebGestureEvent::ScrollUnits::Pixels;
+
+ EXPECT_CALL(mock_input_handler_, ScrollAnimated(::testing::_, ::testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
TEST_P(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) {
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, RootScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.data.scrollBegin.targetViewport = true;
@@ -559,8 +693,9 @@ TEST_P(InputHandlerProxyTest, GesturePinch) {
VERIFY_AND_RESET_MOCKS();
gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -608,8 +743,9 @@ TEST_P(InputHandlerProxyTest, GesturePinchWithWheelHandler) {
VERIFY_AND_RESET_MOCKS();
gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(true));
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -640,7 +776,7 @@ TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -657,8 +793,9 @@ TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
VERIFY_AND_RESET_MOCKS();
gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -717,7 +854,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchpad) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
@@ -740,7 +877,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
gesture_.type = WebInputEvent::GestureFlingStart;
gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
@@ -764,7 +901,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
+ .WillOnce(testing::Return(kScrollIgnoredScrollState));
gesture_.type = WebInputEvent::GestureFlingStart;
gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
@@ -801,11 +938,12 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
+
// The first animate call should let us pick up an animation start time, but
// we shouldn't actually move anywhere just yet. The first frame after the
// fling start will typically include the last scroll from the gesture that
@@ -821,8 +959,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
// The second call should start scrolling in the -X direction.
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0))))
@@ -838,8 +979,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
// We also should pass the current fling parameters out to the client so the
// rest of the fling can be
// transferred to the main thread.
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0);
// Expected wheel fling animation parameters:
@@ -888,6 +1032,97 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
VERIFY_AND_RESET_MOCKS();
}
+TEST_P(InputHandlerProxyTest, GestureFlingPassiveListener) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ gesture_.type = WebInputEvent::GestureFlingStart;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ WebPoint fling_global_point = WebPoint(17, 23);
+ // Note that for trackpad, wheel events with the Control modifier are
+ // special (reserved for zoom), so don't set that here.
+ int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchpad, fling_delta,
+ fling_point, fling_global_point, modifiers);
+ EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // The first animate call should let us pick up an animation start time, but
+ // we shouldn't actually move anywhere just yet. The first frame after the
+ // fling start will typically include the last scroll from the gesture that
+ // lead to the scroll (either wheel or gesture scroll), so there should be no
+ // visible hitch.
+ EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .Times(0);
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
+ Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // The second call should punt the fling to the main thread
+ // because of a passive event listener.
+ EXPECT_SET_NEEDS_ANIMATE_INPUT(0);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .Times(0);
+ EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0);
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0);
+ // Expected wheel fling animation parameters:
+ // *) fling_delta and fling_point should match the original GestureFlingStart
+ // event
+ // *) startTime should be 10 to match the time parameter of the first
+ // Animate() call after the GestureFlingStart
+ EXPECT_CALL(
+ mock_client_,
+ TransferActiveWheelFlingAnimation(testing::AllOf(
+ testing::Field(&WebActiveWheelFlingParameters::delta,
+ testing::Eq(fling_delta)),
+ testing::Field(&WebActiveWheelFlingParameters::point,
+ testing::Eq(fling_point)),
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint,
+ testing::Eq(fling_global_point)),
+ testing::Field(&WebActiveWheelFlingParameters::modifiers,
+ testing::Eq(modifiers)),
+ testing::Field(&WebActiveWheelFlingParameters::startTime,
+ testing::Eq(10)),
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
+ testing::_))));
+ time += base::TimeDelta::FromMilliseconds(100);
+ Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Since we've aborted the fling, the next animation should be a no-op and
+ // should not result in another
+ // frame being requested.
+ EXPECT_SET_NEEDS_ANIMATE_INPUT(0);
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .Times(0);
+ time += base::TimeDelta::FromMilliseconds(100);
+ Animate(time);
+
+ // Since we've transferred the fling to the main thread, we need to pass the
+ // next GestureFlingCancel to the main
+ // thread as well.
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
@@ -907,10 +1142,9 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
VERIFY_AND_RESET_MOCKS();
// Start the fling animation at time 10. This shouldn't actually scroll, just
@@ -925,8 +1159,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
// The second call should start scrolling in the -X direction.
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0))))
@@ -942,8 +1179,12 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
// We also should pass the current fling parameters out to the client so the
// rest of the fling can be
// transferred to the main thread.
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
+
EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0);
@@ -1007,7 +1248,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1025,8 +1266,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
// Tick the second fling once normally.
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
@@ -1038,8 +1282,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
VERIFY_AND_RESET_MOCKS();
// Then abort the second fling.
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0);
@@ -1072,7 +1319,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchscreen) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1080,7 +1327,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchscreen) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
gesture_.type = WebInputEvent::GestureFlingStart;
@@ -1106,7 +1353,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
+ .WillOnce(testing::Return(kMainThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1133,7 +1380,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1145,7 +1392,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
// Flings ignored by the InputHandler should be dropped, signalling the end
// of the touch scroll sequence.
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
+ .WillOnce(testing::Return(kScrollIgnoredScrollState));
gesture_.type = WebInputEvent::GestureFlingStart;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1157,7 +1404,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
// GestureFlingCancel, as the original GestureFlingStart was dropped.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1171,7 +1418,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1193,7 +1440,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1232,7 +1479,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1256,7 +1503,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1288,7 +1535,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1315,7 +1562,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) {
gesture_.modifiers = modifiers;
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1353,7 +1600,7 @@ TEST_P(InputHandlerProxyTest, GestureScrollOnImplThreadFlagClearedAfterFling) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1378,7 +1625,7 @@ TEST_P(InputHandlerProxyTest, GestureScrollOnImplThreadFlagClearedAfterFling) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// |gesture_scroll_on_impl_thread_| should still be true after
@@ -1426,7 +1673,7 @@ TEST_P(InputHandlerProxyTest,
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1448,7 +1695,7 @@ TEST_P(InputHandlerProxyTest,
fling_point, fling_global_point, modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// |gesture_scroll_on_impl_thread_| should still be true after
@@ -1461,7 +1708,7 @@ TEST_P(InputHandlerProxyTest,
// result, this scroll begin will cancel the previous fling.
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1484,7 +1731,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
gesture_.data.flingStart.velocityX = fling_delta.x;
gesture_.data.flingStart.velocityY = fling_delta.y;
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1497,8 +1744,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
VERIFY_AND_RESET_MOCKS();
// The second animate starts scrolling in the positive X and Y directions.
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Lt(0))))
@@ -1516,8 +1766,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
overscroll.did_overscroll_root = true;
overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100);
overscroll.unused_scroll_delta = gfx::Vector2dF(0, 10);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Lt(0))))
@@ -1537,8 +1790,11 @@ TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
// The next call to animate will no longer scroll vertically.
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(
mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Eq(0))))
@@ -1555,7 +1811,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1579,7 +1835,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1636,7 +1892,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1649,7 +1905,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
gesture_.data.flingStart.velocityX = fling_delta.x;
gesture_.data.flingStart.velocityY = fling_delta.y;
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1734,9 +1990,15 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
VERIFY_AND_RESET_MOCKS();
- EXPECT_CALL(mock_input_handler_,
- DoTouchEventsBlockScrollAt(
- testing::Property(&gfx::Point::x, testing::Gt(0))))
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+ EXPECT_CALL(mock_input_handler_, DoTouchEventsBlockScrollAt(testing::_))
.WillOnce(testing::Return(false));
EXPECT_CALL(mock_input_handler_,
DoTouchEventsBlockScrollAt(
@@ -1784,13 +2046,70 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
VERIFY_AND_RESET_MOCKS();
}
+TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPassivePositive) {
+ // One of the touch points is on a touch-region. So the event should be sent
+ // to the main thread.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
+ .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
+ EXPECT_CALL(mock_input_handler_, DoTouchEventsBlockScrollAt(testing::_))
+ .WillRepeatedly(testing::Return(false));
+
+ WebTouchEvent touch;
+ touch.type = WebInputEvent::TouchStart;
+
+ touch.touchesLength = 3;
+ touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 0, 0);
+ touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
+ touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_P(InputHandlerProxyTest, TouchStartPassiveAndTouchEndBlocking) {
+ // The touch start is not in a touch-region but there is a touch end handler
+ // so to maintain targeting we need to dispatch the touch start as
+ // non-blocking but drop all touch moves.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchEndOrCancel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
+ EXPECT_CALL(mock_input_handler_, DoTouchEventsBlockScrollAt(testing::_))
+ .WillOnce(testing::Return(false));
+
+ WebTouchEvent touch;
+ touch.type = WebInputEvent::TouchStart;
+ touch.touchesLength = 1;
+ touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 0, 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+
+ touch.type = WebInputEvent::TouchMove;
+ touch.touchesLength = 1;
+ touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
+ EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
+ input_handler_->HandleInputEvent(touch));
+ VERIFY_AND_RESET_MOCKS();
+}
+
TEST_P(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) {
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -1811,7 +2130,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) {
gesture_.data.flingStart.velocityX = fling_delta.x;
gesture_.data.flingStart.velocityY = fling_delta.y;
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
@@ -1836,13 +2155,78 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) {
EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
}
+TEST_P(InputHandlerProxyTest, GestureFlingCancelledByWheelEvent) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ VERIFY_AND_RESET_MOCKS();
+
+ // Wheel events received during a scroll shouldn't cancel the fling, but will
+ // cause scrolling.
+ cc::InputHandlerScrollResult result;
+
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
+
+ WebMouseWheelEvent wheel_event;
+ wheel_event.type = WebInputEvent::MouseWheel;
+ input_handler_->HandleInputEvent(wheel_event);
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, animation should be scheduled, but no scrolling occurs.
+ gesture_.type = WebInputEvent::GestureFlingStart;
+ WebFloatPoint fling_delta = WebFloatPoint(100, 100);
+ gesture_.data.flingStart.velocityX = fling_delta.x;
+ gesture_.data.flingStart.velocityY = fling_delta.y;
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ VERIFY_AND_RESET_MOCKS();
+
+ // Wheel events received during a fling should cancel the active fling, and
+ // cause a scroll.
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
+
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kBlocking));
+
+
+ input_handler_->HandleInputEvent(wheel_event);
+ EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ VERIFY_AND_RESET_MOCKS();
+
+ // The call to animate should have no effect, as the fling was cancelled.
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
+ Animate(time);
+ VERIFY_AND_RESET_MOCKS();
+
+ // A fling cancel should be dropped, as there is nothing to cancel.
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
+ input_handler_->HandleInputEvent(gesture_));
+ EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+}
+
TEST_P(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) {
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
VERIFY_AND_RESET_MOCKS();
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
gesture_.type = WebInputEvent::GestureScrollBegin;
gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
@@ -1866,7 +2250,7 @@ TEST_P(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) {
modifiers);
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -2051,7 +2435,7 @@ TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) {
.WillOnce(testing::Return(false));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
time += dt;
gesture_.timeStampSeconds = InSecondsF(time);
@@ -2092,7 +2476,7 @@ TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) {
time += base::TimeDelta::FromMilliseconds(100);
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
Animate(time);
VERIFY_AND_RESET_MOCKS();
@@ -2137,7 +2521,7 @@ TEST_P(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) {
gesture_.data.scrollUpdate.deltaY = -40;
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_))
.WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
@@ -2220,7 +2604,7 @@ TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) {
gesture_.data.scrollUpdate.deltaX = -fling_delta.x;
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::Property(&cc::ScrollState::delta_x,
testing::Eq(fling_delta.x))))
@@ -2327,7 +2711,7 @@ TEST_P(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) {
.WillOnce(testing::Return(scroll_result_did_not_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
Animate(time);
VERIFY_AND_RESET_MOCKS();
@@ -2361,7 +2745,7 @@ TEST_P(InputHandlerProxyTest, DidReceiveInputEvent_ForFling) {
testing::StrictMock<MockInputHandlerProxyClientWithDidAnimateForInput>
mock_client;
input_handler_.reset(
- new ui::InputHandlerProxy(
+ new TestInputHandlerProxy(
&mock_input_handler_, &mock_client));
if (install_synchronous_handler_) {
EXPECT_CALL(mock_input_handler_, RequestUpdateForSynchronousInputHandler())
@@ -2377,7 +2761,7 @@ TEST_P(InputHandlerProxyTest, DidReceiveInputEvent_ForFling) {
gesture_.data.flingStart.velocityY = fling_delta.y;
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
+ .WillOnce(testing::Return(kImplThreadScrollState));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_EQ(InputHandlerProxy::DID_HANDLE,
input_handler_->HandleInputEvent(gesture_));
@@ -2460,6 +2844,21 @@ TEST(SynchronousInputHandlerProxyTest, SetOffset) {
testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
}
+TEST_P(InputHandlerProxyTest, MainThreadScrollingMouseWheelHistograms) {
+ input_handler_->RecordMainThreadScrollingReasonsForTest(
+ WebInputEvent::MouseWheel,
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects |
+ cc::MainThreadScrollingReason::kThreadedScrollingDisabled |
+ cc::MainThreadScrollingReason::kPageOverlay |
+ cc::MainThreadScrollingReason::kAnimatingScrollOnMainThread);
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(base::Bucket(1, 1), base::Bucket(3, 1),
+ base::Bucket(5, 1), base::Bucket(14, 1)));
+}
+
+
INSTANTIATE_TEST_CASE_P(AnimateInput,
InputHandlerProxyTest,
testing::ValuesIn(test_types));
diff --git a/chromium/ui/events/blink/input_scroll_elasticity_controller.cc b/chromium/ui/events/blink/input_scroll_elasticity_controller.cc
index d063093cc26..dedf7de60d5 100644
--- a/chromium/ui/events/blink/input_scroll_elasticity_controller.cc
+++ b/chromium/ui/events/blink/input_scroll_elasticity_controller.cc
@@ -167,6 +167,71 @@ void InputScrollElasticityController::ObserveWheelEventAndResult(
}
}
+void InputScrollElasticityController::ObserveGestureEventAndResult(
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result) {
+ base::TimeTicks event_timestamp =
+ base::TimeTicks() +
+ base::TimeDelta::FromSecondsD(gesture_event.timeStampSeconds);
+
+ switch (gesture_event.type) {
+ case blink::WebInputEvent::GestureScrollBegin: {
+ if (gesture_event.data.scrollBegin.synthetic)
+ return;
+ if (gesture_event.data.scrollBegin.inertial) {
+ if (state_ == kStateInactive)
+ state_ = kStateMomentumScroll;
+ } else if (gesture_event.data.scrollBegin.deltaHintUnits ==
+ blink::WebGestureEvent::PrecisePixels) {
+ scroll_velocity = gfx::Vector2dF();
+ last_scroll_event_timestamp_ = base::TimeTicks();
+ state_ = kStateActiveScroll;
+ pending_overscroll_delta_ = gfx::Vector2dF();
+ }
+ break;
+ }
+ case blink::WebInputEvent::GestureScrollUpdate: {
+ gfx::Vector2dF event_delta(-gesture_event.data.scrollUpdate.deltaX,
+ -gesture_event.data.scrollUpdate.deltaY);
+ switch (state_) {
+ case kStateMomentumAnimated:
+ case kStateInactive:
+ break;
+ case kStateActiveScroll:
+ case kStateMomentumScroll:
+ UpdateVelocity(event_delta, event_timestamp);
+ Overscroll(event_delta, scroll_result.unused_scroll_delta);
+ if (gesture_event.data.scrollUpdate.inertial &&
+ !helper_->StretchAmount().IsZero()) {
+ EnterStateMomentumAnimated(event_timestamp);
+ }
+ break;
+ }
+ break;
+ }
+ case blink::WebInputEvent::GestureScrollEnd: {
+ if (gesture_event.data.scrollEnd.synthetic)
+ return;
+ switch (state_) {
+ case kStateMomentumAnimated:
+ case kStateInactive:
+ break;
+ case kStateActiveScroll:
+ case kStateMomentumScroll:
+ if (helper_->StretchAmount().IsZero()) {
+ EnterStateInactive();
+ } else {
+ EnterStateMomentumAnimated(event_timestamp);
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void InputScrollElasticityController::UpdateVelocity(
const gfx::Vector2dF& event_delta,
const base::TimeTicks& event_timestamp) {
diff --git a/chromium/ui/events/blink/input_scroll_elasticity_controller.h b/chromium/ui/events/blink/input_scroll_elasticity_controller.h
index 8c6468109c8..915b2e88af1 100644
--- a/chromium/ui/events/blink/input_scroll_elasticity_controller.h
+++ b/chromium/ui/events/blink/input_scroll_elasticity_controller.h
@@ -58,6 +58,15 @@ class InputScrollElasticityController {
void ObserveWheelEventAndResult(
const blink::WebMouseWheelEvent& wheel_event,
const cc::InputHandlerScrollResult& scroll_result);
+ // Update the overscroll state based a gesture event that has been processed.
+ // Note that this assumes that all events are coming from a single input
+ // device. If the user simultaneously uses multiple input devices, Cocoa may
+ // not correctly pass all the gesture begin and end events. In this case,
+ // this class may disregard some scrolls that come in at unexpected times.
+ void ObserveGestureEventAndResult(
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result);
+
void Animate(base::TimeTicks time);
void ReconcileStretchAndScroll();
diff --git a/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc b/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
index 82b94343f8e..4ce7b9494ed 100644
--- a/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
+++ b/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -99,6 +99,53 @@ class ScrollElasticityControllerTest : public testing::Test {
input_event_count_ += 1;
}
+ void SendGestureScrollBegin(bool inertial) {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollBegin;
+ event.data.scrollBegin.inertial = inertial;
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ controller_.ObserveGestureEventAndResult(event,
+ cc::InputHandlerScrollResult());
+ input_event_count_ += 1;
+ }
+
+ void SendGestureScrollUpdate(
+ bool inertial,
+ const gfx::Vector2dF& event_delta = gfx::Vector2dF(),
+ const gfx::Vector2dF& overscroll_delta = gfx::Vector2dF()) {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollUpdate;
+ event.data.scrollUpdate.inertial = inertial;
+ event.data.scrollUpdate.deltaX = -event_delta.x();
+ event.data.scrollUpdate.deltaY = -event_delta.y();
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ cc::InputHandlerScrollResult scroll_result;
+ scroll_result.did_overscroll_root = !overscroll_delta.IsZero();
+ scroll_result.unused_scroll_delta = overscroll_delta;
+
+ controller_.ObserveGestureEventAndResult(event, scroll_result);
+ input_event_count_ += 1;
+ }
+
+ void SendGestureScrollEnd() {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollEnd;
+
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ controller_.ObserveGestureEventAndResult(event,
+ cc::InputHandlerScrollResult());
+ input_event_count_ += 1;
+ }
+
const base::TimeTicks& TickCurrentTime() {
current_time_ += base::TimeDelta::FromSecondsD(1 / 60.f);
return current_time_;
@@ -148,6 +195,40 @@ TEST_F(ScrollElasticityControllerTest, Axis) {
EXPECT_EQ(0, helper_.request_begin_frame_count());
}
+// Verify that stretching only occurs in one axis at a time, and that it
+// is biased to the Y axis.
+TEST_F(ScrollElasticityControllerTest, GestureBased_Axis) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(0, 0));
+
+ // If we push equally in the X and Y directions, we should see a stretch only
+ // in the Y direction.
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(10, 10),
+ gfx::Vector2dF(10, 10));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+ EXPECT_LT(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(gfx::Vector2dF());
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+
+ // If we push more in the X direction than the Y direction, we should see a
+ // stretch only in the X direction. This decision should be based on the
+ // input delta, not the actual overscroll delta.
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(-25, 10),
+ gfx::Vector2dF(-25, 40));
+ EXPECT_EQ(3, helper_.set_stretch_amount_count());
+ EXPECT_GT(0.f, helper_.StretchAmount().x());
+ EXPECT_EQ(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(gfx::Vector2dF());
+ EXPECT_EQ(4, helper_.set_stretch_amount_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+}
+
// Verify that we need a total overscroll delta of at least 10 in a pinned
// direction before we start stretching.
TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
@@ -201,7 +282,54 @@ TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
EXPECT_EQ(1, helper_.request_begin_frame_count());
}
-// Verify that an stretch caused by a momentum scroll will switch to the
+// Verify that we need a total overscroll delta of at least 10 in a pinned
+// direction before we start stretching.
+TEST_F(ScrollElasticityControllerTest, GestureBased_MinimumDeltaBeforeStretch) {
+ // We should not start stretching while we are not pinned in the direction
+ // of the scroll (even if there is an overscroll delta). We have to wait for
+ // the regular scroll to eat all of the events.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 10));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 10));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Now pin the -X and +Y direction. The first event will not generate a
+ // stretch
+ // because it is below the delta threshold of 10.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Make the next scroll be in the -X direction more than the +Y direction,
+ // which will erase the memory of the previous unused delta of 8.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(-10, 5),
+ gfx::Vector2dF(-8, 10));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Now push against the pinned +Y direction again by 8. We reset the
+ // previous delta, so this will not generate a stretch.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Push against +Y by another 8. This gets us above the delta threshold of
+ // 10, so we should now have had the stretch set, and it should be in the
+ // +Y direction. The scroll in the -X direction should have been forgotten.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+ EXPECT_LT(0.f, helper_.StretchAmount().y());
+
+ // End the gesture. Because there is a non-zero stretch, we should be in the
+ // animated state, and should have had a frame requested.
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+}
+
+// Verify that a stretch caused by a momentum scroll will switch to the
// animating mode, where input events are ignored, and the stretch is updated
// while animating.
TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
@@ -297,7 +425,93 @@ TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
}
-// Verify that an stretch opposing a scroll is correctly resolved.
+// Verify that a stretch caused by a momentum scroll will switch to the
+// animating mode, where input events are ignored, and the stretch is updated
+// while animating.
+TEST_F(ScrollElasticityControllerTest, GestureBased_MomentumAnimate) {
+ // Do an active scroll, then switch to the momentum phase and scroll for a
+ // bit.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollEnd();
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Hit the -Y edge and overscroll slightly, but not enough to go over the
+ // threshold to cause a stretch.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 0),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+
+ // Take another step, this time going over the threshold. This should update
+ // the stretch amount, and then switch to the animating mode.
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+ EXPECT_GT(-1.f, helper_.StretchAmount().y());
+
+ // Subsequent momentum events should do nothing.
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollEnd();
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+
+ // Subsequent animate events should update the stretch amount and request
+ // another frame.
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(2, helper_.request_begin_frame_count());
+ EXPECT_GT(-1.f, helper_.StretchAmount().y());
+
+ // Touching the trackpad (a PhaseMayBegin event) should disable animation.
+ SendGestureScrollBegin(false);
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(2, helper_.request_begin_frame_count());
+
+ // Releasing the trackpad should re-enable animation.
+ SendGestureScrollEnd();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(3, helper_.request_begin_frame_count());
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(3, helper_.set_stretch_amount_count());
+ EXPECT_EQ(4, helper_.request_begin_frame_count());
+
+ // Keep animating frames until the stretch returns to rest.
+ int stretch_count = 3;
+ int begin_frame_count = 4;
+ while (1) {
+ TickCurrentTimeAndAnimate();
+ if (helper_.StretchAmount().IsZero()) {
+ stretch_count += 1;
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+ break;
+ }
+ stretch_count += 1;
+ begin_frame_count += 1;
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+ }
+
+ // After coming to rest, no subsequent animate calls change anything.
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+}
+
+// Verify that a stretch opposing a scroll is correctly resolved.
TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
SendMouseWheelEvent(PhaseBegan, PhaseNone);
@@ -334,14 +548,50 @@ TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
}
+// Verify that a stretch opposing a scroll is correctly resolved.
+TEST_F(ScrollElasticityControllerTest, GestureBased_ReconcileStretchAndScroll) {
+ SendGestureScrollBegin(false);
+
+ // Verify completely knocking out the scroll in the -Y direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(0, -10));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, -5));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 0));
+
+ // Verify partially knocking out the scroll in the -Y direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 8),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(0, -5));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 3));
+
+ // Verify completely knocking out the scroll in the +X direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(10, 0));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(5, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(10, 5));
+
+ // Verify partially knocking out the scroll in the +X and +Y directions.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(2, 3),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(5, 5));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
+}
+
// Verify that stretching only happens when the area is user scrollable.
TEST_F(ScrollElasticityControllerTest, UserScrollableRequiredForStretch) {
helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
gfx::ScrollOffset(10, 10));
gfx::Vector2dF delta(0, -15);
- // Do an active scroll, and ensure that the stretch amount doesn't change,
- // and also that the stretch amount isn't even ever changed.
+ // Do an active scroll, and ensure that the stretch amount doesn't change.
helper_.SetUserScrollable(false);
SendMouseWheelEvent(PhaseBegan, PhaseNone);
SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
@@ -384,5 +634,55 @@ TEST_F(ScrollElasticityControllerTest, UserScrollableRequiredForStretch) {
EXPECT_GT(ticks_to_zero, 3);
}
+// Verify that stretching only happens when the area is user scrollable.
+TEST_F(ScrollElasticityControllerTest,
+ GestureBased_UserScrollableRequiredForStretch) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(10, 10));
+ gfx::Vector2dF delta(0, -15);
+
+ // Do an active scroll, and ensure that the stretch amount doesn't change.
+ helper_.SetUserScrollable(false);
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Re-enable user scrolling and ensure that stretching is re-enabled.
+ helper_.SetUserScrollable(true);
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_GT(helper_.set_stretch_amount_count(), 0);
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_GT(helper_.set_stretch_amount_count(), 0);
+
+ // Disable user scrolling and tick the timer until the stretch goes back
+ // to zero. Ensure that the return to zero doesn't happen immediately.
+ helper_.SetUserScrollable(false);
+ int ticks_to_zero = 0;
+ while (1) {
+ TickCurrentTimeAndAnimate();
+ if (helper_.StretchAmount().IsZero())
+ break;
+ ticks_to_zero += 1;
+ }
+ EXPECT_GT(ticks_to_zero, 3);
+}
+
} // namespace
} // namespace ui
diff --git a/chromium/ui/events/blink/synchronous_input_handler_proxy.h b/chromium/ui/events/blink/synchronous_input_handler_proxy.h
index 36485f0d72f..cafd7ce66d1 100644
--- a/chromium/ui/events/blink/synchronous_input_handler_proxy.h
+++ b/chromium/ui/events/blink/synchronous_input_handler_proxy.h
@@ -8,6 +8,7 @@
#include "base/time/time.h"
namespace gfx {
+class Point;
class ScrollOffset;
class SizeF;
}
@@ -65,6 +66,12 @@ class SynchronousInputHandlerProxy {
// from what was sent.
virtual void SynchronouslySetRootScrollOffset(
const gfx::ScrollOffset& root_offset) = 0;
+
+ // Similar to SetRootScrollOffset above, to control the zoom level, ie scale
+ // factor. Note |magnify_delta| is an incremental rather than absolute value.
+ // SynchronousInputHandler should be given back the resulting absolute value.
+ virtual void SynchronouslyZoomBy(float magnify_delta,
+ const gfx::Point& anchor) = 0;
};
} // namespace ui
diff --git a/chromium/ui/events/cocoa/events_mac.mm b/chromium/ui/events/cocoa/events_mac.mm
index 79beaf39305..003b8805b80 100644
--- a/chromium/ui/events/cocoa/events_mac.mm
+++ b/chromium/ui/events/cocoa/events_mac.mm
@@ -178,24 +178,20 @@ int GetTouchId(const base::NativeEvent& native_event) {
return 0;
}
-float GetTouchRadiusX(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 0.f;
-}
-
-float GetTouchRadiusY(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 0.f;
-}
-
float GetTouchAngle(const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
return 0.f;
}
-float GetTouchForce(const base::NativeEvent& native_event) {
+PointerDetails GetTouchPointerDetailsFromNative(
+ const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
- return 0.f;
+ return PointerDetails(EventPointerType::POINTER_TYPE_UNKNOWN,
+ /* radius_x */ 1.0,
+ /* radius_y */ 1.0,
+ /* force */ 0.f,
+ /* tilt_x */ 0.f,
+ /* tilt_y */ 0.f);
}
bool GetScrollOffsets(const base::NativeEvent& native_event,
diff --git a/chromium/ui/events/cocoa/events_mac_unittest.mm b/chromium/ui/events/cocoa/events_mac_unittest.mm
index 8a5d84a0afd..96abb2f06da 100644
--- a/chromium/ui/events/cocoa/events_mac_unittest.mm
+++ b/chromium/ui/events/cocoa/events_mac_unittest.mm
@@ -9,6 +9,7 @@
#include "base/mac/scoped_cftyperef.h"
#import "base/mac/scoped_objc_class_swizzler.h"
+#include "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -109,7 +110,9 @@ class EventsMacTest : public CocoaTest {
// of window coordinates (which also requires flipping).
NSPoint window_point =
NSPointFromCGPoint(Flip(window_location).ToCGPoint());
- NSPoint screen_point = [test_window() convertBaseToScreen:window_point];
+ NSRect window_rect = NSMakeRect(window_point.x, window_point.y, 0, 0);
+ NSPoint screen_point =
+ [test_window() convertRectToScreen:window_rect].origin;
CGFloat primary_screen_height =
NSHeight([[[NSScreen screens] firstObject] frame]);
screen_point.y = primary_screen_height - screen_point.y;
diff --git a/chromium/ui/events/devices/input_device.cc b/chromium/ui/events/devices/input_device.cc
index 02139b120d0..4734edd0280 100644
--- a/chromium/ui/events/devices/input_device.cc
+++ b/chromium/ui/events/devices/input_device.cc
@@ -32,6 +32,8 @@ InputDevice::InputDevice(int id,
vendor_id(vendor),
product_id(product) {}
+InputDevice::InputDevice(const InputDevice& other) = default;
+
InputDevice::~InputDevice() {
}
diff --git a/chromium/ui/events/devices/input_device.h b/chromium/ui/events/devices/input_device.h
index c118261ec71..4ef06b38cf8 100644
--- a/chromium/ui/events/devices/input_device.h
+++ b/chromium/ui/events/devices/input_device.h
@@ -33,6 +33,7 @@ struct EVENTS_DEVICES_EXPORT InputDevice {
const base::FilePath& sys_path,
uint16_t vendor,
uint16_t product);
+ InputDevice(const InputDevice& other);
virtual ~InputDevice();
// ID of the device. This ID is unique between all input devices.
diff --git a/chromium/ui/events/devices/x11/device_data_manager_x11.cc b/chromium/ui/events/devices/x11/device_data_manager_x11.cc
index 0ac4f6d3303..b824aac3440 100644
--- a/chromium/ui/events/devices/x11/device_data_manager_x11.cc
+++ b/chromium/ui/events/devices/x11/device_data_manager_x11.cc
@@ -218,7 +218,6 @@ bool DeviceDataManagerX11::IsXInput2Available() const {
void DeviceDataManagerX11::UpdateDeviceList(Display* display) {
cmt_devices_.reset();
touchpads_.reset();
- scrollclass_devices_.reset();
master_pointers_.clear();
for (int i = 0; i < kMaxDeviceNum; ++i) {
valuator_count_[i] = 0;
@@ -424,14 +423,13 @@ int DeviceDataManagerX11::GetScrollClassEventDetail(const XEvent& xev) const {
XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev.xcookie.data);
if (xievent->sourceid >= kMaxDeviceNum)
return SCROLL_TYPE_NO_SCROLL;
- if (!scrollclass_devices_[xievent->sourceid])
- return SCROLL_TYPE_NO_SCROLL;
int horizontal_id = scroll_data_[xievent->sourceid].horizontal.number;
int vertical_id = scroll_data_[xievent->sourceid].vertical.number;
- return (XIMaskIsSet(xievent->valuators.mask, horizontal_id)
+ return (horizontal_id != -1 &&
+ XIMaskIsSet(xievent->valuators.mask, horizontal_id)
? SCROLL_TYPE_HORIZONTAL
: 0) |
- (XIMaskIsSet(xievent->valuators.mask, vertical_id)
+ (vertical_id != -1 && XIMaskIsSet(xievent->valuators.mask, vertical_id)
? SCROLL_TYPE_VERTICAL
: 0);
}
@@ -773,6 +771,16 @@ void DeviceDataManagerX11::UpdateScrollClassDevice(
int deviceid) {
DCHECK(deviceid >= 0 && deviceid < kMaxDeviceNum);
ScrollInfo& info = scroll_data_[deviceid];
+
+ bool legacy_scroll_available =
+ (scroll_class_info->flags & XIScrollFlagNoEmulation) == 0;
+ // If the device's highest resolution is lower than the resolution of xinput1
+ // then use xinput1's events instead (ie. don't configure smooth scrolling).
+ if (legacy_scroll_available &&
+ std::abs(scroll_class_info->increment) <= 1.0) {
+ return;
+ }
+
switch (scroll_class_info->scroll_type) {
case XIScrollTypeVertical:
info.vertical.number = scroll_class_info->number;
@@ -787,7 +795,6 @@ void DeviceDataManagerX11::UpdateScrollClassDevice(
info.horizontal.seen = false;
break;
}
- scrollclass_devices_[deviceid] = true;
}
double DeviceDataManagerX11::ExtractAndUpdateScrollOffset(
@@ -801,20 +808,6 @@ double DeviceDataManagerX11::ExtractAndUpdateScrollOffset(
return offset / axis->increment;
}
-bool DeviceDataManagerX11::TouchEventNeedsCalibrate(int touch_device_id) const {
-#if defined(OS_CHROMEOS)
- if (!base::SysInfo::IsRunningOnChromeOS())
- return false;
-
- const std::vector<TouchscreenDevice>& touch_devices =
- ui::DeviceDataManager::GetInstance()->touchscreen_devices();
- std::vector<TouchscreenDevice>::const_iterator it = FindDeviceWithId(
- touch_devices.begin(), touch_devices.end(), touch_device_id);
- return it != touch_devices.end() && it->type == INPUT_DEVICE_INTERNAL;
-#endif // defined(OS_CHROMEOS)
- return false;
-}
-
void DeviceDataManagerX11::SetDisabledKeyboardAllowedKeys(
scoped_ptr<std::set<KeyboardCode> > excepted_keys) {
DCHECK(!excepted_keys.get() ||
diff --git a/chromium/ui/events/devices/x11/device_data_manager_x11.h b/chromium/ui/events/devices/x11/device_data_manager_x11.h
index 0fb81d1faad..751cdd7c404 100644
--- a/chromium/ui/events/devices/x11/device_data_manager_x11.h
+++ b/chromium/ui/events/devices/x11/device_data_manager_x11.h
@@ -256,8 +256,6 @@ class EVENTS_DEVICES_EXPORT DeviceDataManagerX11 : public DeviceDataManager {
DataType type,
double value);
- bool TouchEventNeedsCalibrate(int touch_device_id) const;
-
// Sets the keys which are still allowed on a disabled keyboard device.
void SetDisabledKeyboardAllowedKeys(
scoped_ptr<std::set<KeyboardCode> > excepted_keys);
@@ -342,7 +340,6 @@ class EVENTS_DEVICES_EXPORT DeviceDataManagerX11 : public DeviceDataManager {
// should be processed.
std::bitset<kMaxDeviceNum> cmt_devices_;
std::bitset<kMaxDeviceNum> touchpads_;
- std::bitset<kMaxDeviceNum> scrollclass_devices_;
// List of the master pointer devices.
std::vector<int> master_pointers_;
diff --git a/chromium/ui/events/event.cc b/chromium/ui/events/event.cc
index f4cf7cfd9fa..6548405f179 100644
--- a/chromium/ui/events/event.cc
+++ b/chromium/ui/events/event.cc
@@ -37,6 +37,43 @@
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" // nogncheck
#endif
+#if defined(OS_WIN)
+#include "ui/events/keycodes/platform_key_map_win.h"
+#endif
+
+// Support a collection of histograms, perhaps one for each entry in an
+// enumeration. This macro manages a block of pointers, adding to a specific
+// one by its index.
+//
+// A typical instantiation looks something like this:
+// STATIC_HISTOGRAM_POINTER_GROUP(
+// GetHistogramNameForIndex(histogram_index),
+// histogram_index, MAXIMUM_HISTOGRAM_INDEX, Add(some_delta),
+// base::Histogram::FactoryGet(
+// GetHistogramNameForType(histogram_index),
+// MINIMUM_SAMPLE, MAXIMUM_SAMPLE, BUCKET_COUNT,
+// base::HistogramBase::kUmaTargetedHistogramFlag));
+//
+// Though it seems inefficient to generate the name twice, the first
+// instance will be used only for DCHECK builds and the second will
+// execute only during the first access to the given index, after which
+// the pointer is cached and the name never needed again.
+//
+// This is defined in this way so that it can be moved unchanged into
+// base/metrics/histogram_macros.h if it is useful in other files.
+#define STATIC_HISTOGRAM_POINTER_GROUP(constant_histogram_name, index, \
+ constant_maximum, \
+ histogram_add_method_invocation, \
+ histogram_factory_get_invocation) \
+ do { \
+ static base::subtle::AtomicWord atomic_histograms[constant_maximum]; \
+ DCHECK_LE(0, index); \
+ DCHECK_LT(index, constant_maximum); \
+ HISTOGRAM_POINTER_USE(&atomic_histograms[index], constant_histogram_name, \
+ histogram_add_method_invocation, \
+ histogram_factory_get_invocation); \
+ } while (0)
+
namespace {
std::string EventTypeName(ui::EventType type) {
@@ -59,6 +96,12 @@ std::string EventTypeName(ui::EventType type) {
CASE_TYPE(ET_TOUCH_MOVED);
CASE_TYPE(ET_TOUCH_CANCELLED);
CASE_TYPE(ET_DROP_TARGET_EVENT);
+ CASE_TYPE(ET_POINTER_DOWN);
+ CASE_TYPE(ET_POINTER_MOVED);
+ CASE_TYPE(ET_POINTER_UP);
+ CASE_TYPE(ET_POINTER_CANCELLED);
+ CASE_TYPE(ET_POINTER_ENTERED);
+ CASE_TYPE(ET_POINTER_EXITED);
CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
CASE_TYPE(ET_GESTURE_SCROLL_END);
CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
@@ -145,6 +188,11 @@ scoped_ptr<Event> Event::Clone(const Event& event) {
new GestureEvent(static_cast<const GestureEvent&>(event)));
}
+ if (event.IsPointerEvent()) {
+ return make_scoped_ptr(
+ new PointerEvent(static_cast<const PointerEvent&>(event)));
+ }
+
if (event.IsScrollEvent()) {
return make_scoped_ptr(
new ScrollEvent(static_cast<const ScrollEvent&>(event)));
@@ -158,6 +206,18 @@ Event::~Event() {
ReleaseCopiedNativeEvent(native_event_);
}
+bool Event::IsMousePointerEvent() const {
+ return IsPointerEvent() &&
+ AsPointerEvent()->pointer_details().pointer_type ==
+ EventPointerType::POINTER_TYPE_MOUSE;
+}
+
+bool Event::IsTouchPointerEvent() const {
+ return IsPointerEvent() &&
+ AsPointerEvent()->pointer_details().pointer_type ==
+ EventPointerType::POINTER_TYPE_TOUCH;
+}
+
GestureEvent* Event::AsGestureEvent() {
CHECK(IsGestureEvent());
return static_cast<GestureEvent*>(this);
@@ -168,6 +228,66 @@ const GestureEvent* Event::AsGestureEvent() const {
return static_cast<const GestureEvent*>(this);
}
+KeyEvent* Event::AsKeyEvent() {
+ CHECK(IsKeyEvent());
+ return static_cast<KeyEvent*>(this);
+}
+
+const KeyEvent* Event::AsKeyEvent() const {
+ CHECK(IsKeyEvent());
+ return static_cast<const KeyEvent*>(this);
+}
+
+MouseEvent* Event::AsMouseEvent() {
+ CHECK(IsMouseEvent());
+ return static_cast<MouseEvent*>(this);
+}
+
+const MouseEvent* Event::AsMouseEvent() const {
+ CHECK(IsMouseEvent());
+ return static_cast<const MouseEvent*>(this);
+}
+
+MouseWheelEvent* Event::AsMouseWheelEvent() {
+ CHECK(IsMouseWheelEvent());
+ return static_cast<MouseWheelEvent*>(this);
+}
+
+const MouseWheelEvent* Event::AsMouseWheelEvent() const {
+ CHECK(IsMouseWheelEvent());
+ return static_cast<const MouseWheelEvent*>(this);
+}
+
+PointerEvent* Event::AsPointerEvent() {
+ CHECK(IsPointerEvent());
+ return static_cast<PointerEvent*>(this);
+}
+
+const PointerEvent* Event::AsPointerEvent() const {
+ CHECK(IsPointerEvent());
+ return static_cast<const PointerEvent*>(this);
+}
+
+ScrollEvent* Event::AsScrollEvent() {
+ CHECK(IsScrollEvent());
+ return static_cast<ScrollEvent*>(this);
+}
+
+const ScrollEvent* Event::AsScrollEvent() const {
+ CHECK(IsScrollEvent());
+ return static_cast<const ScrollEvent*>(this);
+}
+
+TouchEvent* Event::AsTouchEvent() {
+ CHECK(IsTouchEvent());
+ return static_cast<TouchEvent*>(this);
+}
+
+const TouchEvent* Event::AsTouchEvent() const {
+ CHECK(IsTouchEvent());
+ return static_cast<const TouchEvent*>(this);
+}
+
bool Event::HasNativeEvent() const {
base::NativeEvent null_event;
std::memset(&null_event, 0, sizeof(null_event));
@@ -225,16 +345,17 @@ Event::Event(const base::NativeEvent& native_event,
static_cast<base::HistogramBase::Sample>(delta.InMicroseconds());
UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample, 1, 1000000,
100);
- std::string name_for_event =
- base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
- base::HistogramBase* counter_for_type =
+
+ // Though it seems inefficient to generate the string twice, the first
+ // instance will be used only for DCHECK builds and the second won't be
+ // executed at all if the histogram was previously accessed here.
+ STATIC_HISTOGRAM_POINTER_GROUP(
+ base::StringPrintf("Event.Latency.Browser.%s", name_.c_str()),
+ type_, ET_LAST, Add(delta_sample),
base::Histogram::FactoryGet(
- name_for_event,
- 1,
- 1000000,
- 100,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- counter_for_type->Add(delta_sample);
+ base::StringPrintf("Event.Latency.Browser.%s", name_.c_str()),
+ 1, 1000000, 100,
+ base::HistogramBase::kUmaTargetedHistogramFlag));
#if defined(USE_X11)
if (native_event->type == GenericEvent) {
@@ -524,12 +645,7 @@ TouchEvent::TouchEvent(const base::NativeEvent& native_event)
rotation_angle_(GetTouchAngle(native_event)),
may_cause_scrolling_(false),
should_remove_native_touch_id_mapping_(false),
- pointer_details_(PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
- GetTouchRadiusX(native_event),
- GetTouchRadiusY(native_event),
- GetTouchForce(native_event),
- /* tilt_x */ 0.0f,
- /* tilt_y */ 0.0f)) {
+ pointer_details_(GetTouchPointerDetailsFromNative(native_event)) {
latency()->AddLatencyNumberWithTimestamp(
INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
@@ -618,9 +734,9 @@ void TouchEvent::UpdateForRootTransform(
bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
DCHECK(success);
if (decomp.scale[0])
- pointer_details_.radius_x_ *= decomp.scale[0];
+ pointer_details_.radius_x *= decomp.scale[0];
if (decomp.scale[1])
- pointer_details_.radius_y_ *= decomp.scale[1];
+ pointer_details_.radius_y *= decomp.scale[1];
}
void TouchEvent::DisableSynchronousHandling() {
@@ -637,6 +753,108 @@ void TouchEvent::FixRotationAngle() {
}
////////////////////////////////////////////////////////////////////////////////
+// PointerEvent
+
+bool PointerEvent::CanConvertFrom(const Event& event) {
+ switch (event.type()) {
+ case ET_MOUSE_PRESSED:
+ case ET_MOUSE_DRAGGED:
+ case ET_MOUSE_MOVED:
+ case ET_MOUSE_ENTERED:
+ case ET_MOUSE_EXITED:
+ case ET_MOUSE_RELEASED:
+ case ET_TOUCH_PRESSED:
+ case ET_TOUCH_MOVED:
+ case ET_TOUCH_RELEASED:
+ case ET_TOUCH_CANCELLED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+PointerEvent::PointerEvent(const PointerEvent& pointer_event)
+ : LocatedEvent(pointer_event),
+ pointer_id_(pointer_event.pointer_id()),
+ details_(pointer_event.pointer_details()) {}
+
+PointerEvent::PointerEvent(const MouseEvent& mouse_event)
+ : LocatedEvent(mouse_event),
+ pointer_id_(kMousePointerId),
+ details_(mouse_event.pointer_details()) {
+ DCHECK(CanConvertFrom(mouse_event));
+ switch (mouse_event.type()) {
+ case ET_MOUSE_PRESSED:
+ SetType(ET_POINTER_DOWN);
+ break;
+
+ case ET_MOUSE_DRAGGED:
+ case ET_MOUSE_MOVED:
+ SetType(ET_POINTER_MOVED);
+ break;
+
+ case ET_MOUSE_ENTERED:
+ SetType(ET_POINTER_ENTERED);
+ break;
+
+ case ET_MOUSE_EXITED:
+ SetType(ET_POINTER_EXITED);
+ break;
+
+ case ET_MOUSE_RELEASED:
+ SetType(ET_POINTER_UP);
+ break;
+
+ default:
+ NOTREACHED();
+ }
+}
+
+PointerEvent::PointerEvent(const TouchEvent& touch_event)
+ : LocatedEvent(touch_event),
+ pointer_id_(touch_event.touch_id()),
+ details_(touch_event.pointer_details()) {
+ DCHECK(CanConvertFrom(touch_event));
+ switch (touch_event.type()) {
+ case ET_TOUCH_PRESSED:
+ SetType(ET_POINTER_DOWN);
+ break;
+
+ case ET_TOUCH_MOVED:
+ SetType(ET_POINTER_MOVED);
+ break;
+
+ case ET_TOUCH_RELEASED:
+ SetType(ET_POINTER_UP);
+ break;
+
+ case ET_TOUCH_CANCELLED:
+ SetType(ET_POINTER_CANCELLED);
+ break;
+
+ default:
+ NOTREACHED();
+ }
+}
+
+PointerEvent::PointerEvent(EventType type,
+ EventPointerType pointer_type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags,
+ int pointer_id,
+ base::TimeDelta time_stamp)
+ : LocatedEvent(type,
+ gfx::PointF(location),
+ gfx::PointF(location),
+ time_stamp,
+ flags),
+ pointer_id_(pointer_id),
+ details_(PointerDetails(pointer_type)) {}
+
+const int PointerEvent::kMousePointerId = std::numeric_limits<int32_t>::max();
+
+////////////////////////////////////////////////////////////////////////////////
// KeyEvent
// static
@@ -680,6 +898,9 @@ bool KeyEvent::IsRepeated(const KeyEvent& event) {
return false;
}
+KeyEvent::KeyEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : Event(type, time_stamp, flags) {}
+
KeyEvent::KeyEvent(const base::NativeEvent& native_event)
: Event(native_event,
EventTypeFromNative(native_event),
@@ -697,6 +918,8 @@ KeyEvent::KeyEvent(const base::NativeEvent& native_event)
// Only Windows has native character events.
if (is_char_)
key_ = DomKey::FromCharacter(native_event.wParam);
+ else
+ key_ = PlatformKeyMap::DomKeyFromNative(native_event);
#endif
}
@@ -832,14 +1055,10 @@ base::char16 KeyEvent::GetCharacter() const {
// For a control character, key_ contains the corresponding printable
// character. To preserve existing behaviour for now, return the control
// character here; this will likely change -- see e.g. crbug.com/471488.
- if (ucs2_character >= 0x40 && ucs2_character <= 0x7A)
+ if (ucs2_character >= 0x20 && ucs2_character <= 0x7E)
return ucs2_character & 0x1F;
if (ucs2_character == '\r')
return '\n';
- // Transitionally, if key_ contains another control character, return it.
- if (ucs2_character >= 0 && ucs2_character <= 0x1F)
- return ucs2_character;
- return 0;
}
return ucs2_character;
}
diff --git a/chromium/ui/events/event.h b/chromium/ui/events/event.h
index dd3ce7fd6bd..49be333ba8e 100644
--- a/chromium/ui/events/event.h
+++ b/chromium/ui/events/event.h
@@ -6,7 +6,6 @@
#define UI_EVENTS_EVENT_H_
#include <stdint.h>
-
#include "base/compiler_specific.h"
#include "base/event_types.h"
#include "base/gtest_prod_util.h"
@@ -27,9 +26,23 @@ namespace gfx {
class Transform;
}
+namespace IPC {
+template <class P> struct ParamTraits;
+}
+
namespace ui {
class EventTarget;
+class KeyEvent;
+class MouseEvent;
+class MouseWheelEvent;
+class PointerEvent;
+class ScrollEvent;
+class TouchEvent;
enum class DomCode;
+class Event;
+class MouseWheelEvent;
+
+using ScopedEvent = scoped_ptr<Event>;
class EVENTS_EXPORT Event {
public:
@@ -116,6 +129,17 @@ class EVENTS_EXPORT Event {
type_ == ET_TOUCH_CANCELLED;
}
+ bool IsPointerEvent() const {
+ return type_ == ET_POINTER_DOWN || type_ == ET_POINTER_MOVED ||
+ type_ == ET_POINTER_UP || type_ == ET_POINTER_CANCELLED ||
+ type_ == ET_POINTER_ENTERED || type_ == ET_POINTER_EXITED;
+ }
+
+ // Convenience methods to check pointer type of |this|. Returns false if
+ // |this| is not a PointerEvent.
+ bool IsMousePointerEvent() const;
+ bool IsTouchPointerEvent() const;
+
bool IsGestureEvent() const {
switch (type_) {
case ET_GESTURE_SCROLL_BEGIN:
@@ -192,7 +216,7 @@ class EVENTS_EXPORT Event {
bool IsLocatedEvent() const {
return IsMouseEvent() || IsScrollEvent() || IsTouchEvent() ||
- IsGestureEvent();
+ IsGestureEvent() || IsPointerEvent();
}
// Convenience methods to cast |this| to a GestureEvent. IsGestureEvent()
@@ -200,6 +224,37 @@ class EVENTS_EXPORT Event {
GestureEvent* AsGestureEvent();
const GestureEvent* AsGestureEvent() const;
+ // Convenience methods to cast |this| to a KeyEvent. IsKeyEvent()
+ // must be true as a precondition to calling these methods.
+ KeyEvent* AsKeyEvent();
+ const KeyEvent* AsKeyEvent() const;
+
+ // Convenience methods to cast |this| to a MouseEvent. IsMouseEvent()
+ // must be true as a precondition to calling these methods.
+ MouseEvent* AsMouseEvent();
+ const MouseEvent* AsMouseEvent() const;
+
+ // Convenience methods to cast |this| to a MouseWheelEvent.
+ // IsMouseWheelEvent() must be true as a precondition to calling these
+ // methods.
+ MouseWheelEvent* AsMouseWheelEvent();
+ const MouseWheelEvent* AsMouseWheelEvent() const;
+
+ // Convenience methods to cast |this| to a PointerEvent. IsPointerEvent()
+ // must be true as a precondition to calling these methods.
+ PointerEvent* AsPointerEvent();
+ const PointerEvent* AsPointerEvent() const;
+
+ // Convenience methods to cast |this| to a ScrollEvent. IsScrollEvent()
+ // must be true as a precondition to calling these methods.
+ ScrollEvent* AsScrollEvent();
+ const ScrollEvent* AsScrollEvent() const;
+
+ // Convenience methods to cast |this| to a TouchEvent. IsTouchEvent()
+ // must be true as a precondition to calling these methods.
+ TouchEvent* AsTouchEvent();
+ const TouchEvent* AsTouchEvent() const;
+
// Returns true if the event has a valid |native_event_|.
bool HasNativeEvent() const;
@@ -234,6 +289,9 @@ class EVENTS_EXPORT Event {
private:
friend class EventTestApi;
+ // For (de)serialization.
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+
EventType type_;
std::string name_;
base::TimeDelta time_stamp_;
@@ -255,6 +313,13 @@ class EVENTS_EXPORT CancelModeEvent : public Event {
public:
CancelModeEvent();
~CancelModeEvent() override;
+
+ private:
+ // For (de)serialization.
+ CancelModeEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : Event(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::CancelModeEvent>;
};
class EVENTS_EXPORT LocatedEvent : public Event {
@@ -298,6 +363,13 @@ class EVENTS_EXPORT LocatedEvent : public Event {
protected:
friend class LocatedEventTestApi;
+
+ // For (de)serialization.
+ LocatedEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : Event(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::LocatedEvent>;
+
explicit LocatedEvent(const base::NativeEvent& native_event);
// Create a new LocatedEvent which is identical to the provided model.
@@ -327,56 +399,58 @@ class EVENTS_EXPORT LocatedEvent : public Event {
// Structure for handling common fields between touch and mouse to support
// PointerEvents API.
-class EVENTS_EXPORT PointerDetails {
+struct EVENTS_EXPORT PointerDetails {
public:
PointerDetails() {}
explicit PointerDetails(EventPointerType pointer_type)
- : pointer_type_(pointer_type) {}
+ : pointer_type(pointer_type),
+ force(std::numeric_limits<float>::quiet_NaN()) {}
PointerDetails(EventPointerType pointer_type,
float radius_x,
float radius_y,
float force,
float tilt_x,
float tilt_y)
- : pointer_type_(pointer_type),
- radius_x_(radius_x),
- radius_y_(radius_y),
- force_(force),
- tilt_x_(tilt_x),
- tilt_y_(tilt_y) {}
-
- EventPointerType pointer_type() const { return pointer_type_; };
-
- // If we aren't provided with a radius on one axis, use the
- // information from the other axis.
- float radius_x() const { return radius_x_ > 0 ? radius_x_ : radius_y_; }
- float radius_y() const { return radius_y_ > 0 ? radius_y_ : radius_x_; }
- float force() const { return force_; }
- float tilt_x() const { return tilt_x_; }
- float tilt_y() const { return tilt_y_; }
+ : pointer_type(pointer_type),
+ // If we aren't provided with a radius on one axis, use the
+ // information from the other axis.
+ radius_x(radius_x > 0 ? radius_x : radius_y),
+ radius_y(radius_y > 0 ? radius_y : radius_x),
+ force(force),
+ tilt_x(tilt_x),
+ tilt_y(tilt_y) {}
+
+ bool operator==(const PointerDetails& other) const {
+ return pointer_type == other.pointer_type &&
+ radius_x == other.radius_x &&
+ radius_y == other.radius_y &&
+ (force == other.force ||
+ (std::isnan(force) && std::isnan(other.force))) &&
+ tilt_x == other.tilt_x &&
+ tilt_y == other.tilt_y;
+ }
- private:
- // For the mutators of the members on this class.
- friend class TouchEvent;
- friend class MouseEvent;
+ // For serialization.
+ friend struct IPC::ParamTraits<ui::PointerDetails>;
// The type of pointer device.
- EventPointerType pointer_type_ = EventPointerType::POINTER_TYPE_UNKNOWN;
+ EventPointerType pointer_type = EventPointerType::POINTER_TYPE_UNKNOWN;
// Radius of the X (major) axis of the touch ellipse. 0.0 if unknown.
- float radius_x_ = 0.0;
+ float radius_x = 0.0;
// Radius of the Y (minor) axis of the touch ellipse. 0.0 if unknown.
- float radius_y_ = 0.0;
-
- // Force (pressure) of the touch. Normalized to be [0, 1]. Default to be 0.0.
- float force_ = 0.0;
+ float radius_y = 0.0;
- // Angle of tilt of the X (major) axis. 0.0 if unknown.
- float tilt_x_ = 0.0;
+ // Force (pressure) of the touch. Normalized to be [0, 1] except NaN means
+ // pressure is not supported by the input device.
+ float force = 0.0;
- // Angle of tilt of the Y (minor) axis. 0.0 if unknown.
- float tilt_y_ = 0.0;
+ // Tilt of a pen/stylus from surface normal as plane angle in degrees, values
+ // lie in [-90,90]. A positive tilt_x is to the right and a positive tilt_y
+ // is towards the user. 0.0 if unknown.
+ float tilt_x = 0.0;
+ float tilt_y = 0.0;
};
class EVENTS_EXPORT MouseEvent : public LocatedEvent {
@@ -478,6 +552,13 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
pointer_details_ = details;
}
+ protected:
+ // For (de)serialization.
+ MouseEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : LocatedEvent(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::MouseEvent>;
+
private:
FRIEND_TEST_ALL_PREFIXES(EventTest, DoubleClickRequiresRelease);
FRIEND_TEST_ALL_PREFIXES(EventTest, SingleClickRightLeft);
@@ -538,6 +619,12 @@ class EVENTS_EXPORT MouseWheelEvent : public MouseEvent {
const gfx::Vector2d& offset() const { return offset_; }
private:
+ // For (de)serialization.
+ MouseWheelEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : MouseEvent(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::MouseWheelEvent>;
+
gfx::Vector2d offset_;
};
@@ -587,11 +674,6 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
void set_may_cause_scrolling(bool causes) { may_cause_scrolling_ = causes; }
bool may_cause_scrolling() const { return may_cause_scrolling_; }
- // TODO(robert.bradford): ozone_platform_egltest.cc could use
- // UpdateForRootTransform() instead: crbug.com/519337
- void set_radius_x(const float r) { pointer_details_.radius_x_ = r; }
- void set_radius_y(const float r) { pointer_details_.radius_y_ = r; }
-
void set_should_remove_native_touch_id_mapping(
bool should_remove_native_touch_id_mapping) {
should_remove_native_touch_id_mapping_ =
@@ -610,17 +692,27 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// Event details common to MouseEvent and TouchEvent.
const PointerDetails& pointer_details() const { return pointer_details_; }
+ void set_pointer_details(const PointerDetails& pointer_details) {
+ pointer_details_ = pointer_details;
+ }
private:
+ // For (de)serialization.
+ TouchEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : LocatedEvent(type, time_stamp, flags),
+ should_remove_native_touch_id_mapping_(false) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::TouchEvent>;
+
// Adjusts rotation_angle_ to within the acceptable range.
void FixRotationAngle();
// The identity (typically finger) of the touch starting at 0 and incrementing
// for each separable additional touch that the hardware can detect.
- const int touch_id_;
+ int touch_id_;
// A unique identifier for the touch event.
- const uint32_t unique_event_id_;
+ uint32_t unique_event_id_;
// Clockwise angle (in degrees) of the major axis from the X axis. Must be
// less than 180 and non-negative.
@@ -641,6 +733,42 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
PointerDetails pointer_details_;
};
+class EVENTS_EXPORT PointerEvent : public LocatedEvent {
+ public:
+ static const int32_t kMousePointerId;
+
+ // Returns true if a PointerEvent can be constructed from the given mouse or
+ // touch event. For example, PointerEvent does not support ET_MOUSEWHEEL or
+ // ET_MOUSE_CAPTURE_CHANGED.
+ static bool CanConvertFrom(const Event& event);
+
+ PointerEvent(const PointerEvent& pointer_event);
+ explicit PointerEvent(const MouseEvent& mouse_event);
+ explicit PointerEvent(const TouchEvent& touch_event);
+
+ PointerEvent(EventType type,
+ EventPointerType pointer_type,
+ const gfx::Point& location,
+ const gfx::Point& root_location,
+ int flags,
+ int pointer_id,
+ base::TimeDelta time_stamp);
+
+ int32_t pointer_id() const { return pointer_id_; }
+ const PointerDetails& pointer_details() const { return details_; }
+
+ protected:
+ // For (de)serialization.
+ PointerEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : LocatedEvent(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::PointerEvent>;
+
+ private:
+ int32_t pointer_id_;
+ PointerDetails details_;
+};
+
// An interface that individual platforms can use to store additional data on
// KeyEvent.
//
@@ -806,6 +934,11 @@ class EVENTS_EXPORT KeyEvent : public Event {
void set_is_char(bool is_char) { is_char_ = is_char; }
private:
+ // For (de)serialization.
+ KeyEvent(EventType type, base::TimeDelta time_stamp, int flags);
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::KeyEvent>;
+
// Determine key_ on a keystroke event from code_ and flags().
void ApplyLayout() const;
@@ -884,6 +1017,12 @@ class EVENTS_EXPORT ScrollEvent : public MouseEvent {
int finger_count() const { return finger_count_; }
private:
+ // For (de)serialization.
+ ScrollEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : MouseEvent(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::ScrollEvent>;
+
// Potential accelerated offsets.
float x_offset_;
float y_offset_;
@@ -916,6 +1055,12 @@ class EVENTS_EXPORT GestureEvent : public LocatedEvent {
const GestureEventDetails& details() const { return details_; }
private:
+ // For (de)serialization.
+ GestureEvent(EventType type, base::TimeDelta time_stamp, int flags)
+ : LocatedEvent(type, time_stamp, flags) {}
+ friend struct IPC::ParamTraits<ui::ScopedEvent>;
+ friend struct IPC::ParamTraits<ui::GestureEvent>;
+
GestureEventDetails details_;
};
diff --git a/chromium/ui/events/event_constants.h b/chromium/ui/events/event_constants.h
index 623f5a5c885..a6ef9dbcce5 100644
--- a/chromium/ui/events/event_constants.h
+++ b/chromium/ui/events/event_constants.h
@@ -26,6 +26,14 @@ enum EventType {
ET_TOUCH_CANCELLED,
ET_DROP_TARGET_EVENT,
+ // PointerEvent types
+ ET_POINTER_DOWN,
+ ET_POINTER_MOVED,
+ ET_POINTER_UP,
+ ET_POINTER_CANCELLED,
+ ET_POINTER_ENTERED,
+ ET_POINTER_EXITED,
+
// GestureEvent types
ET_GESTURE_SCROLL_BEGIN,
ET_GESTURE_TYPE_START = ET_GESTURE_SCROLL_BEGIN,
@@ -34,7 +42,7 @@ enum EventType {
ET_GESTURE_TAP,
ET_GESTURE_TAP_DOWN,
ET_GESTURE_TAP_CANCEL,
- ET_GESTURE_TAP_UNCONFIRMED, // User tapped, but the tap delay hasn't expired.
+ ET_GESTURE_TAP_UNCONFIRMED, // User tapped, but the tap delay hasn't expired.
ET_GESTURE_DOUBLE_TAP,
ET_GESTURE_BEGIN, // The first event sent when each finger is pressed.
ET_GESTURE_END, // Sent for each released finger.
diff --git a/chromium/ui/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc
index 1e9eebbeeb7..3cb6c478a2b 100644
--- a/chromium/ui/events/event_unittest.cc
+++ b/chromium/ui/events/event_unittest.cc
@@ -18,7 +18,7 @@
#if defined(USE_X11)
#include <X11/Xlib.h>
#include "ui/events/test/events_test_utils_x11.h"
-#include "ui/gfx/x/x11_types.h"
+#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace ui {
@@ -60,6 +60,13 @@ TEST(EventTest, GetCharacter) {
KeyEvent keyev4(event);
EXPECT_EQ(13, keyev4.GetCharacter());
#endif
+
+ // Check if expected Unicode character was returned for a key combination
+ // contains Control.
+ // e.g. Control+Shift+2 produces U+200C on "Persian" keyboard.
+ // http://crbug.com/582453
+ KeyEvent keyev5(0x200C, VKEY_UNKNOWN, EF_CONTROL_DOWN | EF_SHIFT_DOWN);
+ EXPECT_EQ(0x200C, keyev5.GetCharacter());
}
TEST(EventTest, ClickCount) {
@@ -201,60 +208,60 @@ TEST(EventTest, KeyEvent) {
{ VKEY_Z, EF_CONTROL_DOWN, '\x1A' },
{ VKEY_Z, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1A' },
- { VKEY_2, EF_CONTROL_DOWN, '\0' },
+ { VKEY_2, EF_CONTROL_DOWN, '\x12' },
{ VKEY_2, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
- { VKEY_6, EF_CONTROL_DOWN, '\0' },
+ { VKEY_6, EF_CONTROL_DOWN, '\x16' },
{ VKEY_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1E' },
- { VKEY_OEM_MINUS, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_MINUS, EF_CONTROL_DOWN, '\x0D' },
{ VKEY_OEM_MINUS, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1F' },
{ VKEY_OEM_4, EF_CONTROL_DOWN, '\x1B' },
- { VKEY_OEM_4, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_4, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1B' },
{ VKEY_OEM_5, EF_CONTROL_DOWN, '\x1C' },
- { VKEY_OEM_5, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_5, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1C' },
{ VKEY_OEM_6, EF_CONTROL_DOWN, '\x1D' },
- { VKEY_OEM_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_6, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x1D' },
{ VKEY_RETURN, EF_CONTROL_DOWN, '\x0A' },
{ VKEY_0, 0, '0' },
{ VKEY_0, EF_SHIFT_DOWN, ')' },
{ VKEY_0, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, ')' },
- { VKEY_0, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
+ { VKEY_0, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x09' },
{ VKEY_9, 0, '9' },
{ VKEY_9, EF_SHIFT_DOWN, '(' },
{ VKEY_9, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON, '(' },
- { VKEY_9, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\0' },
+ { VKEY_9, EF_SHIFT_DOWN | EF_CONTROL_DOWN, '\x08' },
- { VKEY_NUMPAD0, EF_CONTROL_DOWN, '\0' },
+ { VKEY_NUMPAD0, EF_CONTROL_DOWN, '\x10' },
{ VKEY_NUMPAD0, EF_SHIFT_DOWN, '0' },
- { VKEY_NUMPAD9, EF_CONTROL_DOWN, '\0' },
+ { VKEY_NUMPAD9, EF_CONTROL_DOWN, '\x19' },
{ VKEY_NUMPAD9, EF_SHIFT_DOWN, '9' },
{ VKEY_TAB, EF_NONE, '\t' },
{ VKEY_TAB, EF_CONTROL_DOWN, '\t' },
{ VKEY_TAB, EF_SHIFT_DOWN, '\t' },
- { VKEY_MULTIPLY, EF_CONTROL_DOWN, '\0' },
+ { VKEY_MULTIPLY, EF_CONTROL_DOWN, '\x0A' },
{ VKEY_MULTIPLY, EF_SHIFT_DOWN, '*' },
- { VKEY_ADD, EF_CONTROL_DOWN, '\0' },
+ { VKEY_ADD, EF_CONTROL_DOWN, '\x0B' },
{ VKEY_ADD, EF_SHIFT_DOWN, '+' },
- { VKEY_SUBTRACT, EF_CONTROL_DOWN, '\0' },
+ { VKEY_SUBTRACT, EF_CONTROL_DOWN, '\x0D' },
{ VKEY_SUBTRACT, EF_SHIFT_DOWN, '-' },
- { VKEY_DECIMAL, EF_CONTROL_DOWN, '\0' },
+ { VKEY_DECIMAL, EF_CONTROL_DOWN, '\x0E' },
{ VKEY_DECIMAL, EF_SHIFT_DOWN, '.' },
- { VKEY_DIVIDE, EF_CONTROL_DOWN, '\0' },
+ { VKEY_DIVIDE, EF_CONTROL_DOWN, '\x0F' },
{ VKEY_DIVIDE, EF_SHIFT_DOWN, '/' },
- { VKEY_OEM_1, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_1, EF_CONTROL_DOWN, '\x1B' },
{ VKEY_OEM_1, EF_SHIFT_DOWN, ':' },
- { VKEY_OEM_PLUS, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_PLUS, EF_CONTROL_DOWN, '\x1D' },
{ VKEY_OEM_PLUS, EF_SHIFT_DOWN, '+' },
- { VKEY_OEM_COMMA, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_COMMA, EF_CONTROL_DOWN, '\x0C' },
{ VKEY_OEM_COMMA, EF_SHIFT_DOWN, '<' },
- { VKEY_OEM_PERIOD, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_PERIOD, EF_CONTROL_DOWN, '\x0E' },
{ VKEY_OEM_PERIOD, EF_SHIFT_DOWN, '>' },
- { VKEY_OEM_3, EF_CONTROL_DOWN, '\0' },
+ { VKEY_OEM_3, EF_CONTROL_DOWN, '\x0' },
{ VKEY_OEM_3, EF_SHIFT_DOWN, '~' },
};
@@ -560,13 +567,13 @@ TEST(EventTest, TouchEventRadiusDefaultsToOtherAxis) {
TouchEvent event1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), 0, 0, time,
non_zero_length1, 0, 0, 0);
- EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_x());
- EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_y());
+ EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_x);
+ EXPECT_EQ(non_zero_length1, event1.pointer_details().radius_y);
TouchEvent event2(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), 0, 0, time,
0, non_zero_length2, 0, 0);
- EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_x());
- EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_y());
+ EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_x);
+ EXPECT_EQ(non_zero_length2, event2.pointer_details().radius_y);
}
TEST(EventTest, TouchEventRotationAngleFixing) {
@@ -617,63 +624,52 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
}
}
-TEST(EventTest, PointerEventDetailsTouch) {
+TEST(EventTest, PointerDetailsTouch) {
ui::TouchEvent touch_event_plain(ET_TOUCH_PRESSED, gfx::Point(0, 0), 0,
ui::EventTimeForNow());
EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
- touch_event_plain.pointer_details().pointer_type());
- EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_x());
- EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_y());
- EXPECT_EQ(0.0f, touch_event_plain.pointer_details().force());
- EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_x());
- EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_y());
+ touch_event_plain.pointer_details().pointer_type);
+ EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_x);
+ EXPECT_EQ(0.0f, touch_event_plain.pointer_details().radius_y);
+ EXPECT_TRUE(std::isnan(touch_event_plain.pointer_details().force));
+ EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_x);
+ EXPECT_EQ(0.0f, touch_event_plain.pointer_details().tilt_y);
ui::TouchEvent touch_event_with_details(ET_TOUCH_PRESSED, gfx::Point(0, 0), 0,
0, ui::EventTimeForNow(), 10.0f, 5.0f,
0.0f, 15.0f);
EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
- touch_event_with_details.pointer_details().pointer_type());
- EXPECT_EQ(10.0f, touch_event_with_details.pointer_details().radius_x());
- EXPECT_EQ(5.0f, touch_event_with_details.pointer_details().radius_y());
- EXPECT_EQ(15.0f, touch_event_with_details.pointer_details().force());
- EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_x());
- EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_y());
+ touch_event_with_details.pointer_details().pointer_type);
+ EXPECT_EQ(10.0f, touch_event_with_details.pointer_details().radius_x);
+ EXPECT_EQ(5.0f, touch_event_with_details.pointer_details().radius_y);
+ EXPECT_EQ(15.0f, touch_event_with_details.pointer_details().force);
+ EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_x);
+ EXPECT_EQ(0.0f, touch_event_with_details.pointer_details().tilt_y);
ui::TouchEvent touch_event_copy(touch_event_with_details);
- EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
- touch_event_copy.pointer_details().pointer_type());
- EXPECT_EQ(10.0f, touch_event_copy.pointer_details().radius_x());
- EXPECT_EQ(5.0f, touch_event_copy.pointer_details().radius_y());
- EXPECT_EQ(15.0f, touch_event_copy.pointer_details().force());
- EXPECT_EQ(0.0f, touch_event_copy.pointer_details().tilt_x());
- EXPECT_EQ(0.0f, touch_event_copy.pointer_details().tilt_y());
+ EXPECT_EQ(touch_event_with_details.pointer_details(),
+ touch_event_copy.pointer_details());
}
-TEST(EventTest, PointerEventDetailsMouse) {
+TEST(EventTest, PointerDetailsMouse) {
ui::MouseEvent mouse_event(ET_MOUSE_PRESSED, gfx::Point(0, 0),
gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
EXPECT_EQ(EventPointerType::POINTER_TYPE_MOUSE,
- mouse_event.pointer_details().pointer_type());
- EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_x());
- EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_y());
- EXPECT_EQ(0.0f, mouse_event.pointer_details().force());
- EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_x());
- EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_y());
+ mouse_event.pointer_details().pointer_type);
+ EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_x);
+ EXPECT_EQ(0.0f, mouse_event.pointer_details().radius_y);
+ EXPECT_TRUE(std::isnan(mouse_event.pointer_details().force));
+ EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_x);
+ EXPECT_EQ(0.0f, mouse_event.pointer_details().tilt_y);
ui::MouseEvent mouse_event_copy(mouse_event);
- EXPECT_EQ(EventPointerType::POINTER_TYPE_MOUSE,
- mouse_event_copy.pointer_details().pointer_type());
- EXPECT_EQ(0.0f, mouse_event_copy.pointer_details().radius_x());
- EXPECT_EQ(0.0f, mouse_event_copy.pointer_details().radius_y());
- EXPECT_EQ(0.0f, mouse_event_copy.pointer_details().force());
- EXPECT_EQ(0.0f, mouse_event_copy.pointer_details().tilt_x());
- EXPECT_EQ(0.0f, mouse_event_copy.pointer_details().tilt_y());
+ EXPECT_EQ(mouse_event.pointer_details(), mouse_event_copy.pointer_details());
}
-TEST(EventTest, PointerEventDetailsStylus) {
+TEST(EventTest, PointerDetailsStylus) {
ui::MouseEvent stylus_event(ET_MOUSE_PRESSED, gfx::Point(0, 0),
gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
ui::PointerDetails pointer_details(EventPointerType::POINTER_TYPE_PEN,
@@ -685,21 +681,203 @@ TEST(EventTest, PointerEventDetailsStylus) {
stylus_event.set_pointer_details(pointer_details);
EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
- stylus_event.pointer_details().pointer_type());
- EXPECT_EQ(21.0f, stylus_event.pointer_details().force());
- EXPECT_EQ(45.0f, stylus_event.pointer_details().tilt_x());
- EXPECT_EQ(-45.0f, stylus_event.pointer_details().tilt_y());
- EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_x());
- EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_y());
+ stylus_event.pointer_details().pointer_type);
+ EXPECT_EQ(21.0f, stylus_event.pointer_details().force);
+ EXPECT_EQ(45.0f, stylus_event.pointer_details().tilt_x);
+ EXPECT_EQ(-45.0f, stylus_event.pointer_details().tilt_y);
+ EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_x);
+ EXPECT_EQ(0.0f, stylus_event.pointer_details().radius_y);
ui::MouseEvent stylus_event_copy(stylus_event);
+ EXPECT_EQ(stylus_event.pointer_details(),
+ stylus_event_copy.pointer_details());
+}
+
+TEST(EventTest, PointerDetailsCustomTouch) {
+ ui::TouchEvent touch_event(ET_TOUCH_PRESSED, gfx::Point(0, 0), 0,
+ ui::EventTimeForNow());
+
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
+ touch_event.pointer_details().pointer_type);
+ EXPECT_EQ(0.0f, touch_event.pointer_details().radius_x);
+ EXPECT_EQ(0.0f, touch_event.pointer_details().radius_y);
+ EXPECT_TRUE(std::isnan(touch_event.pointer_details().force));
+ EXPECT_EQ(0.0f, touch_event.pointer_details().tilt_x);
+ EXPECT_EQ(0.0f, touch_event.pointer_details().tilt_y);
+
+ ui::PointerDetails pointer_details(EventPointerType::POINTER_TYPE_PEN,
+ /* radius_x */ 5.0f,
+ /* radius_y */ 6.0f,
+ /* force */ 21.0f,
+ /* tilt_x */ 45.0f,
+ /* tilt_y */ -45.0f);
+ touch_event.set_pointer_details(pointer_details);
+
EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
- stylus_event_copy.pointer_details().pointer_type());
- EXPECT_EQ(21.0f, stylus_event_copy.pointer_details().force());
- EXPECT_EQ(45.0f, stylus_event_copy.pointer_details().tilt_x());
- EXPECT_EQ(-45.0f, stylus_event_copy.pointer_details().tilt_y());
- EXPECT_EQ(0.0f, stylus_event_copy.pointer_details().radius_x());
- EXPECT_EQ(0.0f, stylus_event_copy.pointer_details().radius_y());
+ touch_event.pointer_details().pointer_type);
+ EXPECT_EQ(21.0f, touch_event.pointer_details().force);
+ EXPECT_EQ(45.0f, touch_event.pointer_details().tilt_x);
+ EXPECT_EQ(-45.0f, touch_event.pointer_details().tilt_y);
+ EXPECT_EQ(5.0f, touch_event.pointer_details().radius_x);
+ EXPECT_EQ(6.0f, touch_event.pointer_details().radius_y);
+
+ ui::TouchEvent touch_event_copy(touch_event);
+ EXPECT_EQ(touch_event.pointer_details(), touch_event_copy.pointer_details());
+}
+
+TEST(EventTest, PointerEventCanConvertFrom) {
+ const gfx::Point point;
+ const base::TimeDelta time;
+
+ // Common mouse events can be converted.
+ const EventType mouse_allowed[] = {
+ ET_MOUSE_PRESSED,
+ ET_MOUSE_DRAGGED,
+ ET_MOUSE_MOVED,
+ ET_MOUSE_ENTERED,
+ ET_MOUSE_EXITED,
+ ET_MOUSE_RELEASED
+ };
+ for (size_t i = 0; i < arraysize(mouse_allowed); i++) {
+ MouseEvent event(mouse_allowed[i], point, point, time, 0, 0);
+ EXPECT_TRUE(PointerEvent::CanConvertFrom(event));
+ }
+
+ // Common touch events can be converted.
+ const EventType touch_allowed[] = {
+ ET_TOUCH_PRESSED,
+ ET_TOUCH_MOVED,
+ ET_TOUCH_RELEASED,
+ ET_TOUCH_CANCELLED
+ };
+ for (size_t i = 0; i < arraysize(touch_allowed); i++) {
+ TouchEvent event(touch_allowed[i], point, 0, time);
+ EXPECT_TRUE(PointerEvent::CanConvertFrom(event));
+ }
+
+ // Capture changes cannot be converted.
+ EXPECT_FALSE(
+ PointerEvent::CanConvertFrom(
+ MouseEvent(ET_MOUSE_CAPTURE_CHANGED, point, point, time, 0, 0)));
+
+ // Wheel events cannot be converted.
+ EXPECT_FALSE(
+ PointerEvent::CanConvertFrom(
+ MouseWheelEvent(gfx::Vector2d(), point, point, time, 0, 0)));
+
+ // Non-mouse non-touch events cannot be converted.
+ EXPECT_FALSE(
+ PointerEvent::CanConvertFrom(
+ KeyEvent(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE)));
+}
+
+TEST(EventTest, PointerEventType) {
+ const ui::EventType kMouseTypeMap[][2] = {
+ {ui::ET_MOUSE_PRESSED, ui::ET_POINTER_DOWN},
+ {ui::ET_MOUSE_DRAGGED, ui::ET_POINTER_MOVED},
+ {ui::ET_MOUSE_MOVED, ui::ET_POINTER_MOVED},
+ {ui::ET_MOUSE_ENTERED, ui::ET_POINTER_ENTERED},
+ {ui::ET_MOUSE_EXITED, ui::ET_POINTER_EXITED},
+ {ui::ET_MOUSE_RELEASED, ui::ET_POINTER_UP},
+ };
+ const ui::EventType kTouchTypeMap[][2] = {
+ {ui::ET_TOUCH_PRESSED, ui::ET_POINTER_DOWN},
+ {ui::ET_TOUCH_MOVED, ui::ET_POINTER_MOVED},
+ {ui::ET_TOUCH_RELEASED, ui::ET_POINTER_UP},
+ {ui::ET_TOUCH_CANCELLED, ui::ET_POINTER_CANCELLED},
+ };
+
+ for (size_t i = 0; i < arraysize(kMouseTypeMap); i++) {
+ ui::MouseEvent mouse_event(kMouseTypeMap[i][0], gfx::Point(0, 0),
+ gfx::Point(0, 0), base::TimeDelta(), 0, 0);
+ ui::PointerEvent pointer_event(mouse_event);
+ EXPECT_EQ(kMouseTypeMap[i][1], pointer_event.type());
+ EXPECT_FALSE(pointer_event.IsMouseEvent());
+ EXPECT_FALSE(pointer_event.IsTouchEvent());
+ EXPECT_TRUE(pointer_event.IsPointerEvent());
+ }
+
+ for (size_t i = 0; i < arraysize(kTouchTypeMap); i++) {
+ ui::TouchEvent touch_event(kTouchTypeMap[i][0], gfx::Point(0, 0), 0,
+ base::TimeDelta());
+ ui::PointerEvent pointer_event(touch_event);
+ EXPECT_EQ(kTouchTypeMap[i][1], pointer_event.type());
+ EXPECT_FALSE(pointer_event.IsMouseEvent());
+ EXPECT_FALSE(pointer_event.IsTouchEvent());
+ EXPECT_TRUE(pointer_event.IsPointerEvent());
+ }
+}
+
+TEST(EventTest, PointerEventId) {
+ {
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(0, 0),
+ gfx::Point(0, 0), base::TimeDelta(), 0, 0);
+ ui::PointerEvent pointer_event(mouse_event);
+ EXPECT_EQ(pointer_event.pointer_id(), ui::PointerEvent::kMousePointerId);
+ }
+
+ for (int touch_id = 0; touch_id < 8; touch_id++) {
+ ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), touch_id,
+ base::TimeDelta());
+ ui::PointerEvent pointer_event(touch_event);
+ EXPECT_EQ(pointer_event.pointer_id(), touch_id);
+ }
+}
+
+TEST(EventTest, PointerDetailsPointer) {
+ const float kRadiusX = 10.0f;
+ const float kRadiusY = 5.0f;
+ const float kForce = 15.0f;
+ ui::TouchEvent touch_event(ET_TOUCH_PRESSED, gfx::Point(0, 0), 0, 0,
+ ui::EventTimeForNow(), kRadiusX, kRadiusY, 0.0f,
+ kForce);
+ ui::PointerEvent pointer_event_from_touch(touch_event);
+ EXPECT_EQ(kRadiusX, pointer_event_from_touch.pointer_details().radius_x);
+ EXPECT_EQ(kRadiusY, pointer_event_from_touch.pointer_details().radius_y);
+ EXPECT_EQ(kForce, pointer_event_from_touch.pointer_details().force);
+ EXPECT_EQ(kRadiusX, pointer_event_from_touch.pointer_details().radius_x);
+ EXPECT_EQ(0.0f, pointer_event_from_touch.pointer_details().tilt_x);
+ EXPECT_EQ(0.0f, pointer_event_from_touch.pointer_details().tilt_y);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
+ pointer_event_from_touch.pointer_details().pointer_type);
+
+ ui::MouseEvent mouse_event(ET_MOUSE_PRESSED, gfx::Point(0, 0),
+ gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
+ ui::PointerEvent pointer_event_from_mouse(mouse_event);
+ EXPECT_EQ(mouse_event.pointer_details(),
+ pointer_event_from_mouse.pointer_details());
+}
+
+TEST(EventTest, PointerEventClone) {
+ {
+ ui::PointerEvent ptr_event(
+ ui::TouchEvent(ET_TOUCH_PRESSED, gfx::Point(0, 0), 0, 0,
+ ui::EventTimeForNow(), 10.0f, 5.0f, 0.0f, 15.0f));
+ scoped_ptr<ui::Event> clone(ui::Event::Clone(ptr_event));
+ EXPECT_TRUE(clone->IsPointerEvent());
+ ui::PointerEvent* clone_as_ptr = clone->AsPointerEvent();
+
+ EXPECT_EQ(ptr_event.type(), clone_as_ptr->type());
+ EXPECT_EQ(ptr_event.pointer_id(), clone_as_ptr->pointer_id());
+ EXPECT_EQ(ptr_event.pointer_details(), clone_as_ptr->pointer_details());
+ EXPECT_EQ(ptr_event.location(), clone_as_ptr->location());
+ EXPECT_EQ(ptr_event.root_location(), clone_as_ptr->root_location());
+ }
+
+ {
+ ui::PointerEvent ptr_event(
+ ui::MouseEvent(ET_MOUSE_PRESSED, gfx::Point(0, 0), gfx::Point(0, 0),
+ ui::EventTimeForNow(), 0, 0));
+ scoped_ptr<ui::Event> clone(ui::Event::Clone(ptr_event));
+ EXPECT_TRUE(clone->IsPointerEvent());
+ ui::PointerEvent* clone_as_ptr = clone->AsPointerEvent();
+
+ EXPECT_EQ(ptr_event.type(), clone_as_ptr->type());
+ EXPECT_EQ(ptr_event.pointer_id(), clone_as_ptr->pointer_id());
+ EXPECT_EQ(ptr_event.pointer_details(), clone_as_ptr->pointer_details());
+ EXPECT_EQ(ptr_event.location(), clone_as_ptr->location());
+ EXPECT_EQ(ptr_event.root_location(), clone_as_ptr->root_location());
+ }
}
} // namespace ui
diff --git a/chromium/ui/events/event_utils.cc b/chromium/ui/events/event_utils.cc
index cb4788d1455..aa9ed7b34e9 100644
--- a/chromium/ui/events/event_utils.cc
+++ b/chromium/ui/events/event_utils.cc
@@ -71,7 +71,7 @@ bool ShouldDefaultToNaturalScroll() {
}
gfx::Display::TouchSupport GetInternalDisplayTouchSupport() {
- gfx::Screen* screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
// No screen in some unit tests.
if (!screen)
return gfx::Display::TOUCH_SUPPORT_UNKNOWN;
diff --git a/chromium/ui/events/event_utils.h b/chromium/ui/events/event_utils.h
index 54081a5cac9..4a8e1637eda 100644
--- a/chromium/ui/events/event_utils.h
+++ b/chromium/ui/events/event_utils.h
@@ -115,6 +115,10 @@ base::NativeEvent CopyNativeEvent(
void ReleaseCopiedNativeEvent(
const base::NativeEvent& native_event);
+// Returns the detailed pointer information for touch events.
+EVENTS_EXPORT PointerDetails
+GetTouchPointerDetailsFromNative(const base::NativeEvent& native_event);
+
// Gets the touch id from a native event.
EVENTS_EXPORT int GetTouchId(const base::NativeEvent& native_event);
@@ -122,16 +126,9 @@ EVENTS_EXPORT int GetTouchId(const base::NativeEvent& native_event);
EVENTS_EXPORT void ClearTouchIdIfReleased(
const base::NativeEvent& native_event);
-// Gets the radius along the X/Y axis from a native event. Default is 1.0.
-EVENTS_EXPORT float GetTouchRadiusX(const base::NativeEvent& native_event);
-EVENTS_EXPORT float GetTouchRadiusY(const base::NativeEvent& native_event);
-
// Gets the angle of the major axis away from the X axis. Default is 0.0.
EVENTS_EXPORT float GetTouchAngle(const base::NativeEvent& native_event);
-// Gets the force from a native_event. Normalized to be [0, 1]. Default is 0.0.
-EVENTS_EXPORT float GetTouchForce(const base::NativeEvent& native_event);
-
// Gets the fling velocity from a native event. is_cancel is set to true if
// this was a tap down, intended to stop an ongoing fling.
EVENTS_EXPORT bool GetFlingData(const base::NativeEvent& native_event,
diff --git a/chromium/ui/events/events.gyp b/chromium/ui/events/events.gyp
index 6c23b30b8b8..c8d994f5e4b 100644
--- a/chromium/ui/events/events.gyp
+++ b/chromium/ui/events/events.gyp
@@ -140,6 +140,8 @@
'gestures/gesture_types.h',
'gestures/motion_event_aura.cc',
'gestures/motion_event_aura.h',
+ 'keycodes/platform_key_map_win.cc',
+ 'keycodes/platform_key_map_win.h',
'linux/text_edit_command_auralinux.cc',
'linux/text_edit_command_auralinux.h',
'linux/text_edit_key_bindings_delegate_auralinux.cc',
@@ -206,9 +208,12 @@
'android/events_jni_registrar.h',
'android/motion_event_android.cc',
'android/motion_event_android.h',
+ 'android/key_event_utils.cc',
+ 'android/key_event_utils.h',
],
'dependencies': [
'motionevent_jni_headers',
+ 'keyevent_jni_headers',
],
}],
],
@@ -310,6 +315,7 @@
'sources': [
'ipc/latency_info_param_traits.cc',
'ipc/latency_info_param_traits.h',
+ 'ipc/latency_info_param_traits_macros.h',
],
},
{
@@ -383,7 +389,16 @@
},
'includes': [ '../../build/jar_file_jni_generator.gypi' ],
},
+ {
+ 'target_name': 'keyevent_jni_headers',
+ 'type': 'none',
+ 'variables': {
+ 'jni_gen_package': 'ui',
+ 'input_java_class': 'android/view/KeyEvent.class',
+ },
+ 'includes': [ '../../build/jar_file_jni_generator.gypi' ],
+ },
],
}],
],
-} \ No newline at end of file
+}
diff --git a/chromium/ui/events/events_default.cc b/chromium/ui/events/events_default.cc
index 7d55e8e790f..b6bf22e7d0d 100644
--- a/chromium/ui/events/events_default.cc
+++ b/chromium/ui/events/events_default.cc
@@ -96,18 +96,12 @@ int GetTouchId(const base::NativeEvent& native_event) {
return event->touch_id();
}
-float GetTouchRadiusX(const base::NativeEvent& native_event) {
- const ui::TouchEvent* event =
- static_cast<const ui::TouchEvent*>(native_event);
- DCHECK(event->IsTouchEvent());
- return event->pointer_details().radius_x();
-}
-
-float GetTouchRadiusY(const base::NativeEvent& native_event) {
+PointerDetails GetTouchPointerDetailsFromNative(
+ const base::NativeEvent& native_event) {
const ui::TouchEvent* event =
static_cast<const ui::TouchEvent*>(native_event);
DCHECK(event->IsTouchEvent());
- return event->pointer_details().radius_y();
+ return event->pointer_details();
}
float GetTouchAngle(const base::NativeEvent& native_event) {
@@ -117,13 +111,6 @@ float GetTouchAngle(const base::NativeEvent& native_event) {
return event->rotation_angle();
}
-float GetTouchForce(const base::NativeEvent& native_event) {
- const ui::TouchEvent* event =
- static_cast<const ui::TouchEvent*>(native_event);
- DCHECK(event->IsTouchEvent());
- return event->pointer_details().force();
-}
-
bool GetScrollOffsets(const base::NativeEvent& native_event,
float* x_offset,
float* y_offset,
diff --git a/chromium/ui/events/events_stub.cc b/chromium/ui/events/events_stub.cc
index edd7765b16e..a3343110e91 100644
--- a/chromium/ui/events/events_stub.cc
+++ b/chromium/ui/events/events_stub.cc
@@ -86,24 +86,20 @@ int GetTouchId(const base::NativeEvent& native_event) {
return 0;
}
-float GetTouchRadiusX(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 0.f;
-}
-
-float GetTouchRadiusY(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 0.f;
-}
-
float GetTouchAngle(const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
return 0.f;
}
-float GetTouchForce(const base::NativeEvent& native_event) {
+PointerDetails GetTouchPointerDetailsFromNative(
+ const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
- return 0.f;
+ return PointerDetails(EventPointerType::POINTER_TYPE_UNKNOWN,
+ /* radius_x */ 1.0,
+ /* radius_y */ 1.0,
+ /* force */ 0.f,
+ /* tilt_x */ 0.f,
+ /* tilt_y */ 0.f);
}
bool GetScrollOffsets(const base::NativeEvent& native_event,
diff --git a/chromium/ui/events/events_unittests.gyp b/chromium/ui/events/events_unittests.gyp
index 12f9b2aaa7f..f5a5d01c3e0 100644
--- a/chromium/ui/events/events_unittests.gyp
+++ b/chromium/ui/events/events_unittests.gyp
@@ -57,9 +57,11 @@
'ipc/latency_info_param_traits_unittest.cc',
'keycodes/dom/keycode_converter_unittest.cc',
'keycodes/keyboard_code_conversion_unittest.cc',
+ 'keycodes/platform_key_map_win_unittest.cc',
'latency_info_unittest.cc',
'platform/platform_event_source_unittest.cc',
'scoped_target_handler_unittest.cc',
+ 'win/event_utils_win_unittest.cc',
'x/events_x_unittest.cc',
],
'include_dirs': [
@@ -103,11 +105,6 @@
'gestures/motion_event_aura_unittest.cc',
],
}],
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
# Exclude tests that rely on event_utils.h for platforms that do not
# provide native cracking, i.e., platforms that use events_stub.cc.
['OS!="win" and use_x11!=1 and use_ozone!=1', {
@@ -125,6 +122,7 @@
}],
['OS!="ios"', {
'sources': [
+ 'blink/blink_event_util_unittest.cc',
'blink/input_handler_proxy_unittest.cc',
'blink/input_scroll_elasticity_controller_unittest.cc',
],
@@ -195,4 +193,4 @@
],
}],
],
-} \ No newline at end of file
+}
diff --git a/chromium/ui/events/events_unittests_apk.isolate b/chromium/ui/events/events_unittests_apk.isolate
index c45db50fe0b..0b33b328f6b 100644
--- a/chromium/ui/events/events_unittests_apk.isolate
+++ b/chromium/ui/events/events_unittests_apk.isolate
@@ -8,6 +8,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_events_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'<(PRODUCT_DIR)/bin/run_events_unittests',
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
index e616e7bbd64..be4b197994a 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
@@ -6,12 +6,13 @@
#include "base/auto_reset.h"
#include "base/logging.h"
+#include "ui/events/blink/blink_event_util.h"
#include "ui/events/gesture_detection/motion_event.h"
namespace ui {
FilteredGestureProvider::TouchHandlingResult::TouchHandlingResult()
- : succeeded(false), did_generate_scroll(false) {
+ : succeeded(false), moved_beyond_slop_region(false) {
}
FilteredGestureProvider::FilteredGestureProvider(
@@ -21,7 +22,7 @@ FilteredGestureProvider::FilteredGestureProvider(
gesture_provider_(config, this),
gesture_filter_(this),
handling_event_(false),
- last_touch_event_did_generate_scroll_(false) {
+ any_touch_moved_beyond_slop_region_(false) {
}
FilteredGestureProvider::TouchHandlingResult
@@ -30,7 +31,10 @@ FilteredGestureProvider::OnTouchEvent(const MotionEvent& event) {
base::AutoReset<bool> handling_event(&handling_event_, true);
pending_gesture_packet_ = GestureEventDataPacket::FromTouch(event);
- last_touch_event_did_generate_scroll_ = false;
+
+ if (event.GetAction() == MotionEvent::ACTION_DOWN)
+ any_touch_moved_beyond_slop_region_ = false;
+
if (!gesture_provider_.OnTouchEvent(event))
return TouchHandlingResult();
@@ -43,7 +47,7 @@ FilteredGestureProvider::OnTouchEvent(const MotionEvent& event) {
TouchHandlingResult result;
result.succeeded = true;
- result.did_generate_scroll = last_touch_event_did_generate_scroll_;
+ result.moved_beyond_slop_region = any_touch_moved_beyond_slop_region_;
return result;
}
@@ -76,11 +80,9 @@ const ui::MotionEvent* FilteredGestureProvider::GetCurrentDownEvent() const {
void FilteredGestureProvider::OnGestureEvent(const GestureEventData& event) {
if (handling_event_) {
- if (event.details.type() == ui::ET_GESTURE_SCROLL_BEGIN ||
- event.details.type() == ui::ET_GESTURE_SCROLL_UPDATE ||
- event.details.type() == ui::ET_SCROLL_FLING_START) {
- last_touch_event_did_generate_scroll_ = true;
- }
+ if (event.details.type() == ui::ET_GESTURE_SCROLL_BEGIN)
+ any_touch_moved_beyond_slop_region_ = true;
+
pending_gesture_packet_.Push(event);
return;
}
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
index d8a8dc0d252..c0af13b111c 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
@@ -34,11 +34,8 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider
// |event| and cease further propagation.
bool succeeded;
- // Whether |event| produced scrolling motion, either the start of a scroll,
- // subsequent scroll movement or a fling event.
- // TODO(jdduke): Figure out a way to guarantee that this bit propagates with
- // the processed touch event as it moves downstream.
- bool did_generate_scroll;
+ // Whether |event| occurred beyond the touch slop region.
+ bool moved_beyond_slop_region;
};
TouchHandlingResult OnTouchEvent(const MotionEvent& event) WARN_UNUSED_RESULT;
@@ -66,7 +63,7 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider
ui::TouchDispositionGestureFilter gesture_filter_;
bool handling_event_;
- bool last_touch_event_did_generate_scroll_;
+ bool any_touch_moved_beyond_slop_region_;
ui::GestureEventDataPacket pending_gesture_packet_;
DISALLOW_COPY_AND_ASSIGN(FilteredGestureProvider);
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc
index 4514946ccc7..d3e10f637db 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider_unittest.cc
@@ -22,63 +22,133 @@ class FilteredGestureProviderTest : public GestureProviderClient,
base::MessageLoopForUI message_loop_;
};
-TEST_F(FilteredGestureProviderTest, TouchDidGenerateScroll) {
+// Single touch drag test: After touch-start, the moved_beyond_slop_region bit
+// should stay unset as long as the touch movement is confined to the slop
+// region. Once the touch moves beyond the slop region, the bit should remain
+// set until (incl) touch-end.
+TEST_F(FilteredGestureProviderTest, TouchMovedBeyondSlopRegion_SingleTouch) {
GestureProvider::Config config;
FilteredGestureProvider provider(config, this);
const float kSlopRegion = config.gesture_detector_config.touch_slop;
test::MockMotionEvent event;
+
event.set_event_time(base::TimeTicks::Now());
event.PressPoint(0, 0);
auto result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_FALSE(result.did_generate_scroll);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
event.MovePoint(0, kSlopRegion / 2.f, 0);
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_FALSE(result.did_generate_scroll);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
- // Exceeding the slop should triggering scrolling and be reflected in the API.
event.MovePoint(0, kSlopRegion * 2.f, 0);
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_TRUE(result.did_generate_scroll);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
- // No movement should indicate no scrolling.
event.MovePoint(0, kSlopRegion * 2.f, 0);
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_FALSE(result.did_generate_scroll);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
- // Nonzero movement should reflect scrolling after exceeding the slop region.
event.MovePoint(0, 0, 0);
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_TRUE(result.did_generate_scroll);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
- // Ending a touch with no fling should not indicate scrolling.
event.ReleasePoint();
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_FALSE(result.did_generate_scroll);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
- // Ending a touch with a fling *should* indicate scrolling.
+ // A new touch sequence should reset the bit.
base::TimeTicks time = base::TimeTicks::Now();
event.PressPoint(0, 0);
event.set_event_time(time);
- ASSERT_TRUE(provider.OnTouchEvent(event).succeeded);
+ result = provider.OnTouchEvent(event);
+ ASSERT_TRUE(result.succeeded);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
+ // A fling should set the bit right away.
time += base::TimeDelta::FromMilliseconds(10);
event.MovePoint(0, kSlopRegion * 50, 0);
event.set_event_time(time);
- ASSERT_TRUE(provider.OnTouchEvent(event).succeeded);
+ result = provider.OnTouchEvent(event);
+ ASSERT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
event.ReleasePoint();
result = provider.OnTouchEvent(event);
EXPECT_TRUE(result.succeeded);
- EXPECT_TRUE(result.did_generate_scroll);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+}
+
+// Multi-touch: The moved_beyond_slop_region bit should stay unset as long as
+// all touch-points are stationary, and should be set after (including) the
+// first movement in any touch-point.
+TEST_F(FilteredGestureProviderTest, TouchMovedBeyondSlopRegion_MultiTouch) {
+ GestureProvider::Config config;
+ FilteredGestureProvider provider(config, this);
+
+ const float kSlopRegion = config.gesture_detector_config.touch_slop;
+
+ test::MockMotionEvent event;
+
+ float x = 0;
+ const float y0 = 0;
+ const float y1 = kSlopRegion * 10.f;
+ const float y2 = kSlopRegion * 20.f;
+
+ event.set_event_time(base::TimeTicks::Now());
+ event.PressPoint(x, y0);
+ auto result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
+
+ event.PressPoint(x, y1);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
+
+ event.PressPoint(x, y2);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_FALSE(result.moved_beyond_slop_region);
+
+ for (float multiplier = 0.5f; multiplier < 3.f; multiplier += 2.f) {
+ x = kSlopRegion * multiplier;
+
+ event.MovePoint(0, x, y0);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+
+ event.MovePoint(0, x, y0);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+
+ event.MovePoint(2, x, y2);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+
+ event.MovePoint(1, x, y1);
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+ }
+
+ for(int i = 0; i < 3; i++) {
+ event.ReleasePoint();
+ result = provider.OnTouchEvent(event);
+ EXPECT_TRUE(result.succeeded);
+ EXPECT_TRUE(result.moved_beyond_slop_region);
+ }
}
} // namespace ui
diff --git a/chromium/ui/events/gesture_detection/gesture_detector.cc b/chromium/ui/events/gesture_detection/gesture_detector.cc
index 2996bc70816..6fc39a8e3dd 100644
--- a/chromium/ui/events/gesture_detection/gesture_detector.cc
+++ b/chromium/ui/events/gesture_detection/gesture_detector.cc
@@ -61,6 +61,8 @@ GestureDetector::Config::Config()
single_tap_repeat_interval(1),
velocity_tracker_strategy(VelocityTracker::Strategy::STRATEGY_DEFAULT) {}
+GestureDetector::Config::Config(const Config& other) = default;
+
GestureDetector::Config::~Config() {}
class GestureDetector::TimeoutGestureHandler {
diff --git a/chromium/ui/events/gesture_detection/gesture_detector.h b/chromium/ui/events/gesture_detection/gesture_detector.h
index 49def14b735..9fb699985f2 100644
--- a/chromium/ui/events/gesture_detection/gesture_detector.h
+++ b/chromium/ui/events/gesture_detection/gesture_detector.h
@@ -25,6 +25,7 @@ class GESTURE_DETECTION_EXPORT GestureDetector {
public:
struct GESTURE_DETECTION_EXPORT Config {
Config();
+ Config(const Config& other);
~Config();
base::TimeDelta longpress_timeout;
diff --git a/chromium/ui/events/gesture_detection/gesture_event_data.cc b/chromium/ui/events/gesture_detection/gesture_event_data.cc
index b166ffa0a13..676dadef6f8 100644
--- a/chromium/ui/events/gesture_detection/gesture_event_data.cc
+++ b/chromium/ui/events/gesture_detection/gesture_event_data.cc
@@ -49,6 +49,8 @@ GestureEventData::GestureEventData(EventType type,
details.set_bounding_box(other.details.bounding_box_f());
}
+GestureEventData::GestureEventData(const GestureEventData& other) = default;
+
GestureEventData::GestureEventData()
: motion_event_id(0),
primary_tool_type(MotionEvent::TOOL_TYPE_UNKNOWN),
diff --git a/chromium/ui/events/gesture_detection/gesture_event_data.h b/chromium/ui/events/gesture_detection/gesture_event_data.h
index 8f54355dcf5..541fe125f6b 100644
--- a/chromium/ui/events/gesture_detection/gesture_event_data.h
+++ b/chromium/ui/events/gesture_detection/gesture_event_data.h
@@ -30,6 +30,7 @@ struct GESTURE_DETECTION_EXPORT GestureEventData {
const gfx::RectF& bounding_box,
int flags);
GestureEventData(EventType type, const GestureEventData&);
+ GestureEventData(const GestureEventData& other);
EventType type() const { return details.type(); }
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc
index 2ea2b53407f..40944ff8654 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider.cc
@@ -75,6 +75,8 @@ GestureProvider::Config::Config()
max_gesture_bounds_length(0) {
}
+GestureProvider::Config::Config(const Config& other) = default;
+
GestureProvider::Config::~Config() {
}
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.h b/chromium/ui/events/gesture_detection/gesture_provider.h
index c738f53ab32..0da33163419 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.h
+++ b/chromium/ui/events/gesture_detection/gesture_provider.h
@@ -28,6 +28,7 @@ class GESTURE_DETECTION_EXPORT GestureProvider {
public:
struct GESTURE_DETECTION_EXPORT Config {
Config();
+ Config(const Config& other);
~Config();
gfx::Display display;
GestureDetector::Config gesture_detector_config;
diff --git a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc
index 27081026df0..c13636687c9 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider_config_helper.cc
@@ -90,7 +90,7 @@ GestureProvider::Config GetGestureProviderConfig(
break;
}
- gfx::Screen* screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
// |screen| is sometimes NULL during tests.
if (screen)
config.display = screen->GetPrimaryDisplay();
diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.cc b/chromium/ui/events/gesture_detection/motion_event_generic.cc
index 041bddda256..935584c4796 100644
--- a/chromium/ui/events/gesture_detection/motion_event_generic.cc
+++ b/chromium/ui/events/gesture_detection/motion_event_generic.cc
@@ -50,6 +50,8 @@ PointerProperties::PointerProperties(const MotionEvent& event,
source_device_id(0) {
}
+PointerProperties::PointerProperties(const PointerProperties& other) = default;
+
void PointerProperties::SetAxesAndOrientation(float radius_x,
float radius_y,
float rotation_angle_degree) {
diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.h b/chromium/ui/events/gesture_detection/motion_event_generic.h
index c5ea1b00f4c..bc9b351381a 100644
--- a/chromium/ui/events/gesture_detection/motion_event_generic.h
+++ b/chromium/ui/events/gesture_detection/motion_event_generic.h
@@ -19,6 +19,7 @@ struct GESTURE_DETECTION_EXPORT PointerProperties {
PointerProperties();
PointerProperties(float x, float y, float touch_major);
PointerProperties(const MotionEvent& event, size_t pointer_index);
+ PointerProperties(const PointerProperties& other);
// Sets |touch_major|, |touch_minor|, and |orientation| from the given radius
// and rotation angle (in degrees).
diff --git a/chromium/ui/events/gesture_event_details.h b/chromium/ui/events/gesture_event_details.h
index ff88041fb3e..6a79a4ad1c1 100644
--- a/chromium/ui/events/gesture_event_details.h
+++ b/chromium/ui/events/gesture_event_details.h
@@ -5,12 +5,18 @@
#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
#define UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+#include <string.h>
+
#include "base/logging.h"
#include "ui/events/event_constants.h"
#include "ui/events/events_base_export.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
+namespace IPC {
+template <class P> struct ParamTraits;
+}
+
namespace ui {
struct EVENTS_BASE_EXPORT GestureEventDetails {
@@ -137,6 +143,14 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
return data_.scroll_update.previous_update_in_sequence_prevented;
}
+ // Supports comparison over internal structures for testing.
+ bool operator==(const GestureEventDetails& other) const {
+ return type_ == other.type_ &&
+ !memcmp(&data_, &other.data_, sizeof(Details)) &&
+ touch_points_ == other.touch_points_ &&
+ bounding_box_ == other.bounding_box_;
+ }
+
private:
EventType type_;
union Details {
@@ -182,6 +196,10 @@ struct EVENTS_BASE_EXPORT GestureEventDetails {
int tap_count; // TAP repeat count.
} data_;
+ // For mojo native implementation of (de)serialization.
+ friend struct IPC::ParamTraits<ui::GestureEventDetails>;
+ friend struct IPC::ParamTraits<ui::GestureEventDetails::Details>;
+
int touch_points_; // Number of active touch points in the gesture.
// Bounding box is an axis-aligned rectangle that contains all the
diff --git a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
index d66e842502d..27eb0b4d01a 100644
--- a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
+++ b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/WebKit/public/platform/WebGestureCurve.h"
diff --git a/chromium/ui/events/gestures/gesture_provider_aura.cc b/chromium/ui/events/gestures/gesture_provider_aura.cc
index 9bfe5fd605d..1adbc641244 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura.cc
+++ b/chromium/ui/events/gestures/gesture_provider_aura.cc
@@ -36,7 +36,7 @@ bool GestureProviderAura::OnTouchEvent(TouchEvent* event) {
if (!result.succeeded)
return false;
- event->set_may_cause_scrolling(result.did_generate_scroll);
+ event->set_may_cause_scrolling(result.moved_beyond_slop_region);
pointer_state_.CleanupRemovedTouchPoints(*event);
return true;
}
diff --git a/chromium/ui/events/gestures/motion_event_aura.cc b/chromium/ui/events/gestures/motion_event_aura.cc
index 7b6e34ec117..eff71e1abe2 100644
--- a/chromium/ui/events/gestures/motion_event_aura.cc
+++ b/chromium/ui/events/gestures/motion_event_aura.cc
@@ -33,11 +33,11 @@ PointerProperties GetPointerPropertiesFromTouchEvent(const TouchEvent& touch) {
pointer_properties.raw_x = touch.root_location_f().x();
pointer_properties.raw_y = touch.root_location_f().y();
pointer_properties.id = touch.touch_id();
- pointer_properties.pressure = touch.pointer_details().force();
+ pointer_properties.pressure = touch.pointer_details().force;
pointer_properties.source_device_id = touch.source_device_id();
- pointer_properties.SetAxesAndOrientation(touch.pointer_details().radius_x(),
- touch.pointer_details().radius_y(),
+ pointer_properties.SetAxesAndOrientation(touch.pointer_details().radius_x,
+ touch.pointer_details().radius_y,
touch.rotation_angle());
if (!pointer_properties.touch_major) {
pointer_properties.touch_major =
@@ -48,7 +48,7 @@ PointerProperties GetPointerPropertiesFromTouchEvent(const TouchEvent& touch) {
}
pointer_properties.tool_type = EventPointerTypeToMotionEventToolType(
- touch.pointer_details().pointer_type());
+ touch.pointer_details().pointer_type);
return pointer_properties;
}
diff --git a/chromium/ui/events/gestures/motion_event_aura_unittest.cc b/chromium/ui/events/gestures/motion_event_aura_unittest.cc
index 75f49ff25e6..d9a5f8af125 100644
--- a/chromium/ui/events/gestures/motion_event_aura_unittest.cc
+++ b/chromium/ui/events/gestures/motion_event_aura_unittest.cc
@@ -426,14 +426,16 @@ TEST(MotionEventAuraTest, Cancel) {
TEST(MotionEventAuraTest, ToolType) {
MotionEventAura event;
-
- EXPECT_TRUE(event.OnTouch(TouchWithType(ET_TOUCH_PRESSED, 7)));
+ TouchEvent touch_event = TouchWithType(ET_TOUCH_PRESSED, 7);
+ EXPECT_TRUE(event.OnTouch(touch_event));
ASSERT_EQ(1U, event.GetPointerCount());
EXPECT_EQ(MotionEvent::TOOL_TYPE_FINGER, event.GetToolType(0));
- // TODO(robert.bradford): crbug.com/575162: Test TOOL_TYPE_PEN when
- // TouchEvents can have their PointerDetails::pointer_type() something other
- // than POINTER_TYPE_TOUCH
+ PointerDetails pointer_details(EventPointerType::POINTER_TYPE_PEN, 5.0f, 5.0f,
+ 1.0f, 0.0f, 0.0f);
+ touch_event.set_pointer_details(pointer_details);
+ EXPECT_TRUE(event.OnTouch(touch_event));
+ EXPECT_EQ(MotionEvent::TOOL_TYPE_STYLUS, event.GetToolType(0));
}
TEST(MotionEventAuraTest, Flags) {
diff --git a/chromium/ui/events/ipc/BUILD.gn b/chromium/ui/events/ipc/BUILD.gn
index f7eaf887b80..b6ccbf51d5f 100644
--- a/chromium/ui/events/ipc/BUILD.gn
+++ b/chromium/ui/events/ipc/BUILD.gn
@@ -4,11 +4,12 @@
import("//build/config/ui.gni")
-component("events_ipc") {
+component("ipc") {
output_name = "events_ipc"
sources = [
"latency_info_param_traits.cc",
"latency_info_param_traits.h",
+ "latency_info_param_traits_macros.h",
]
defines = [ "EVENTS_IPC_IMPLEMENTATION" ]
diff --git a/chromium/ui/events/ipc/latency_info_param_traits.cc b/chromium/ui/events/ipc/latency_info_param_traits.cc
index 27d9ab6736f..a472307407a 100644
--- a/chromium/ui/events/ipc/latency_info_param_traits.cc
+++ b/chromium/ui/events/ipc/latency_info_param_traits.cc
@@ -29,23 +29,18 @@ namespace IPC {
#include "ui/events/ipc/latency_info_param_traits.h"
namespace IPC {
-void ParamTraits<ui::LatencyInfo>::Write(Message* m,
- const param_type& p) {
+void ParamTraits<ui::LatencyInfo>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.trace_name_);
WriteParam(m, p.latency_components_);
WriteParam(m, p.input_coordinates_size_);
for (size_t i = 0; i < p.input_coordinates_size_; i++) {
WriteParam(m, p.input_coordinates_[i]);
}
- WriteParam(m, p.coalesced_events_size_);
- for (size_t i = 0; i < p.coalesced_events_size_; i++) {
- WriteParam(m, p.timestamps_of_coalesced_events_[i]);
- }
WriteParam(m, p.trace_id_);
WriteParam(m, p.terminated_);
}
-bool ParamTraits<ui::LatencyInfo>::Read(const Message* m,
+bool ParamTraits<ui::LatencyInfo>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
if (!ReadParam(m, iter, &p->trace_name_))
@@ -64,17 +59,6 @@ bool ParamTraits<ui::LatencyInfo>::Read(const Message* m,
return false;
}
- double timestamp;
- uint32_t coalesced_events_size;
- if (!ReadParam(m, iter, &coalesced_events_size))
- return false;
- for (size_t i = 0; i < coalesced_events_size; i++) {
- if (!ReadParam(m, iter, &timestamp))
- return false;
- if (!p->AddCoalescedEventTimestamp(timestamp))
- return false;
- }
-
if (!ReadParam(m, iter, &p->trace_id_))
return false;
if (!ReadParam(m, iter, &p->terminated_))
@@ -95,12 +79,6 @@ void ParamTraits<ui::LatencyInfo>::Log(const param_type& p,
LogParam(p.input_coordinates_[i], l);
l->append(" ");
}
- LogParam(p.coalesced_events_size_, l);
- l->append(" ");
- for (size_t i = 0; i < p.coalesced_events_size_; i++) {
- LogParam(p.timestamps_of_coalesced_events_[i], l);
- l->append(" ");
- }
LogParam(p.trace_id_, l);
l->append(" ");
LogParam(p.terminated_, l);
diff --git a/chromium/ui/events/ipc/latency_info_param_traits.h b/chromium/ui/events/ipc/latency_info_param_traits.h
index 0716f432d9c..9e11104341f 100644
--- a/chromium/ui/events/ipc/latency_info_param_traits.h
+++ b/chromium/ui/events/ipc/latency_info_param_traits.h
@@ -12,8 +12,10 @@ namespace IPC {
template <>
struct EVENTS_IPC_EXPORT ParamTraits<ui::LatencyInfo> {
typedef ui::LatencyInfo param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
} // namespace IPC
diff --git a/chromium/ui/events/ipc/latency_info_param_traits_unittest.cc b/chromium/ui/events/ipc/latency_info_param_traits_unittest.cc
index 12f6a51135b..69224dace99 100644
--- a/chromium/ui/events/ipc/latency_info_param_traits_unittest.cc
+++ b/chromium/ui/events/ipc/latency_info_param_traits_unittest.cc
@@ -16,7 +16,6 @@ TEST(LatencyInfoParamTraitsTest, Basic) {
LatencyInfo latency;
ASSERT_FALSE(latency.terminated());
ASSERT_EQ(0u, latency.input_coordinates_size());
- ASSERT_EQ(0u, latency.coalesced_events_size());
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1234, 0);
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 1234, 100);
latency.AddLatencyNumber(INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
@@ -29,15 +28,9 @@ TEST(LatencyInfoParamTraitsTest, Basic) {
EXPECT_FALSE(latency.AddInputCoordinate(
LatencyInfo::InputCoordinate(102, 202)));
- EXPECT_TRUE(latency.AddCoalescedEventTimestamp(10.0));
- EXPECT_TRUE(latency.AddCoalescedEventTimestamp(20.0));
- // Up to 2 coalesced events is allowed.
- EXPECT_FALSE(latency.AddCoalescedEventTimestamp(30.0));
-
EXPECT_EQ(100, latency.trace_id());
EXPECT_TRUE(latency.terminated());
EXPECT_EQ(2u, latency.input_coordinates_size());
- EXPECT_EQ(2u, latency.coalesced_events_size());
IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
IPC::WriteParam(&msg, latency);
@@ -54,11 +47,6 @@ TEST(LatencyInfoParamTraitsTest, Basic) {
EXPECT_EQ(latency.input_coordinates()[i].y,
output.input_coordinates()[i].y);
}
- EXPECT_EQ(latency.coalesced_events_size(), output.coalesced_events_size());
- for (size_t i = 0; i < latency.coalesced_events_size(); i++) {
- EXPECT_EQ(latency.timestamps_of_coalesced_events()[i],
- output.timestamps_of_coalesced_events()[i]);
- }
EXPECT_TRUE(output.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
1234,
@@ -80,12 +68,9 @@ TEST(LatencyInfoParamTraitsTest, InvalidData) {
IPC::WriteParam(&msg, std::string());
ui::LatencyInfo::LatencyMap components;
IPC::WriteParam(&msg, components);
+ // input_coordinates_size is 2 but only one InputCoordinate is written.
IPC::WriteParam(&msg, static_cast<uint32_t>(2));
IPC::WriteParam(&msg, ui::LatencyInfo::InputCoordinate());
- IPC::WriteParam(&msg, ui::LatencyInfo::InputCoordinate());
- // coalesced_events_size is 2 but only one event timestamp is written.
- IPC::WriteParam(&msg, static_cast<uint32_t>(2));
- IPC::WriteParam(&msg, static_cast<double>(10.0));
IPC::WriteParam(&msg, static_cast<int64_t>(1234));
IPC::WriteParam(&msg, true);
diff --git a/chromium/ui/events/keycodes/dom/dom_key.h b/chromium/ui/events/keycodes/dom/dom_key.h
index 9c8847869c6..810f82137f6 100644
--- a/chromium/ui/events/keycodes/dom/dom_key.h
+++ b/chromium/ui/events/keycodes/dom/dom_key.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/logging.h"
+#include "ipc/ipc_param_traits.h"
namespace ui {
@@ -80,14 +81,10 @@ class DomKey {
// included here to create constants for them in the DomKey:: scope.
#define DOM_KEY_MAP_DECLARATION enum Key : Base
#define DOM_KEY_UNI(key, id, value) id = (TYPE_UNICODE | (value))
-#define DOM_KEY_MAP_BEGIN FIRST_NON_UNICODE = TYPE_NON_UNICODE,
-#define DOM_KEY_MAP(key, id) id
-#define DOM_KEY_MAP_END LAST_NON_UNICODE
+#define DOM_KEY_MAP(key, id, value) id = (TYPE_NON_UNICODE | (value))
#include "ui/events/keycodes/dom/dom_key_data.inc"
#undef DOM_KEY_MAP_DECLARATION
-#undef DOM_KEY_MAP_BEGIN
#undef DOM_KEY_MAP
-#undef DOM_KEY_MAP_END
#undef DOM_KEY_UNI
// Create a DomKey, with the undefined-value sentinel DomKey::NONE.
@@ -151,6 +148,8 @@ class DomKey {
};
private:
+ friend struct IPC::ParamTraits<ui::DomKey>;
+
Base value_;
};
diff --git a/chromium/ui/events/keycodes/dom/dom_key_data.inc b/chromium/ui/events/keycodes/dom/dom_key_data.inc
index c4a84509dd6..507d97e4bba 100644
--- a/chromium/ui/events/keycodes/dom/dom_key_data.inc
+++ b/chromium/ui/events/keycodes/dom/dom_key_data.inc
@@ -10,7 +10,8 @@
// (enums) and string tables. These names are defined by:
//
// [0] DOM Level 3 KeyboardEvent key Values,
-// http://www.w3.org/TR/DOM-Level-3-Events-key/
+// http://www.w3.org/TR/uievents-key/
+// (current as of W3C Working Draft 15 December 2015)
//
// That reference should be consulted on the meaning and usage of these
// values; this file does not attempt to describe that.
@@ -18,6 +19,9 @@
// The names given in the table here directly match the DOM Level 3 value,
// and for the most part the corresponding enum identifier is generated from
// the name by converting W3C's CamelCaseStyle to Chromium's C_MACRO_STYLE.
+//
+// NOTE: Some uses of this data expect that encodings remain fixed,
+// so existing key values should not be changed.
DOM_KEY_MAP_DECLARATION {
@@ -34,361 +38,498 @@ DOM_KEY_MAP_DECLARATION {
// DELETE conflicts with an unscoped declaration in Windows' <windows.h>.
DOM_KEY_UNI("Delete", DEL, 0x007F),
- DOM_KEY_MAP_BEGIN
-
// =========================================================
// Special Key Values
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-special
+ // http://www.w3.org/TR/uievents-key/#keys-special
// =========================================================
// Unable to identify another key value
- DOM_KEY_MAP("Unidentified", UNIDENTIFIED),
+ DOM_KEY_MAP("Unidentified", UNIDENTIFIED, 0x0001),
// ==========================================================
// Modifier Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-modifier
+ // http://www.w3.org/TR/uievents-key/#keys-modifier
// ==========================================================
- // Key Enum
- DOM_KEY_MAP("Accel", ACCEL), // Never returned in a key event
- DOM_KEY_MAP("Alt", ALT),
- DOM_KEY_MAP("AltGraph", ALT_GRAPH),
- DOM_KEY_MAP("CapsLock", CAPS_LOCK),
- DOM_KEY_MAP("Control", CONTROL),
- DOM_KEY_MAP("Fn", FN),
- DOM_KEY_MAP("FnLock", FN_LOCK),
- DOM_KEY_MAP("Hyper", HYPER),
- DOM_KEY_MAP("Meta", META),
- DOM_KEY_MAP("NumLock", NUM_LOCK),
- DOM_KEY_MAP("OS", OS),
- DOM_KEY_MAP("ScrollLock", SCROLL_LOCK),
- DOM_KEY_MAP("Shift", SHIFT),
- DOM_KEY_MAP("Super", SUPER),
- DOM_KEY_MAP("Symbol", SYMBOL),
- DOM_KEY_MAP("SymbolLock", SYMBOL_LOCK),
+ // Key Enum Value
+ // "Accel" is never returned in a key event.
+ DOM_KEY_MAP("Accel", ACCEL, 0x0101),
+ DOM_KEY_MAP("Alt", ALT, 0x0102),
+ DOM_KEY_MAP("AltGraph", ALT_GRAPH, 0x0103),
+ DOM_KEY_MAP("CapsLock", CAPS_LOCK, 0x0104),
+ DOM_KEY_MAP("Control", CONTROL, 0x0105),
+ DOM_KEY_MAP("Fn", FN, 0x0106),
+ DOM_KEY_MAP("FnLock", FN_LOCK, 0x0107),
+ DOM_KEY_MAP("Hyper", HYPER, 0x0108),
+ DOM_KEY_MAP("Meta", META, 0x0109),
+ DOM_KEY_MAP("NumLock", NUM_LOCK, 0x010A),
+ // "OS" was removed from the spec.
+ // ("OS", OS, 0x010B),
+ DOM_KEY_MAP("ScrollLock", SCROLL_LOCK, 0x010C),
+ DOM_KEY_MAP("Shift", SHIFT, 0x010D),
+ DOM_KEY_MAP("Super", SUPER, 0x010E),
+ DOM_KEY_MAP("Symbol", SYMBOL, 0x010F),
+ DOM_KEY_MAP("SymbolLock", SYMBOL_LOCK, 0x0110),
// Non-standard value corresponding to XKB keysym ISO_Level5_Shift,
// an additional printable-character modifier like Shift and AltGraph,
// used by such layouts as Neo (German) and Multix (French-Canadian).
- // Key Enum
- DOM_KEY_MAP("ShiftLevel5", SHIFT_LEVEL5),
+ // Key Enum Value
+ DOM_KEY_MAP("ShiftLevel5", SHIFT_LEVEL5, 0x0111),
- // Non-standard value representing a latching-modifier key in ui::Keyevent.
+ // Non-standard value representing a latching-modifier key in ui::KeyEvent.
// This is present on some keyboard layouts (Latvian, Tibetan, Cameroon),
// and applies the modifier to the next (non-modifier) key.
// These events are consumed internally and not exposed to the web,
// either directly or as synthetic modifier up/down events.
- // Key Enum
- DOM_KEY_MAP(".AltGraphLatch", ALT_GRAPH_LATCH),
+ // Key Enum Value
+ DOM_KEY_MAP(".AltGraphLatch", ALT_GRAPH_LATCH, 0x0112),
// ============================================================
// Whitespace Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-whitespace
+ // http://www.w3.org/TR/uievents-key/#keys-whitespace
// ============================================================
- // Key Enum
- // "Enter" is encoded in the Unicode space (at the end of this list).
- DOM_KEY_MAP("Separator", SEPARATOR),
+ // Key Enum Value
+ // "Enter" is encoded in the Unicode space (at the top of this list).
+ // "Separator" was removed from the spec.
+ // ("Separator", SEPARATOR, 0x0201),
// "Tab" is encoded in the Unicode space.
// ============================================================
// Navigation Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-navigation
+ // http://www.w3.org/TR/uievents-key/#keys-navigation
// ============================================================
- // Key Enum
- DOM_KEY_MAP("ArrowDown", ARROW_DOWN),
- DOM_KEY_MAP("ArrowLeft", ARROW_LEFT),
- DOM_KEY_MAP("ArrowRight", ARROW_RIGHT),
- DOM_KEY_MAP("ArrowUp", ARROW_UP),
- DOM_KEY_MAP("End", END),
- DOM_KEY_MAP("Home", HOME),
- DOM_KEY_MAP("PageDown", PAGE_DOWN),
- DOM_KEY_MAP("PageUp", PAGE_UP),
+ // Key Enum Value
+ DOM_KEY_MAP("ArrowDown", ARROW_DOWN, 0x0301),
+ DOM_KEY_MAP("ArrowLeft", ARROW_LEFT, 0x0302),
+ DOM_KEY_MAP("ArrowRight", ARROW_RIGHT, 0x0303),
+ DOM_KEY_MAP("ArrowUp", ARROW_UP, 0x0304),
+ DOM_KEY_MAP("End", END, 0x0305),
+ DOM_KEY_MAP("Home", HOME, 0x0306),
+ DOM_KEY_MAP("PageDown", PAGE_DOWN, 0x0307),
+ DOM_KEY_MAP("PageUp", PAGE_UP, 0x0308),
// =========================================================
// Editing Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-editing
+ // http://www.w3.org/TR/uievents-key/#keys-editing
// =========================================================
- // Key Enum
+ // Key Enum Value
// "Backspace" is encoded in the Unicode space.
- DOM_KEY_MAP("Clear", CLEAR),
- DOM_KEY_MAP("Copy", COPY),
- DOM_KEY_MAP("CrSel", CR_SEL), // Cursor Select
- DOM_KEY_MAP("Cut", CUT),
+ DOM_KEY_MAP("Clear", CLEAR, 0x0401),
+ DOM_KEY_MAP("Copy", COPY, 0x0402),
+ // "CrSel" is short for "Cursor Select":
+ DOM_KEY_MAP("CrSel", CR_SEL, 0x0403),
+ DOM_KEY_MAP("Cut", CUT, 0x0404),
// "Delete" is encoded in the Unicode space.
- DOM_KEY_MAP("EraseEof", ERASE_EOF), // Erase to End of Field
- DOM_KEY_MAP("ExSel", EX_SEL), // Extend Selection
- DOM_KEY_MAP("Insert", INSERT),
- DOM_KEY_MAP("Paste", PASTE),
- DOM_KEY_MAP("Redo", REDO),
- DOM_KEY_MAP("Undo", UNDO),
+ // "EraseEof" is short for "Erase to End of Field":
+ DOM_KEY_MAP("EraseEof", ERASE_EOF, 0x0405),
+ // "ExSel" is short for "Extend Selection":
+ DOM_KEY_MAP("ExSel", EX_SEL, 0x0406),
+ DOM_KEY_MAP("Insert", INSERT, 0x0407),
+ DOM_KEY_MAP("Paste", PASTE, 0x0408),
+ DOM_KEY_MAP("Redo", REDO, 0x0409),
+ DOM_KEY_MAP("Undo", UNDO, 0x040A),
// ====================================================
// UI Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-ui
+ // http://www.w3.org/TR/uievents-key/#keys-ui
// ====================================================
- // Key Enum
- DOM_KEY_MAP("Accept", ACCEPT), // Accept current IME conversion
- DOM_KEY_MAP("Again", AGAIN), // Repeat an action
- DOM_KEY_MAP("Attn", ATTN), // Attention
- DOM_KEY_MAP("Cancel", CANCEL),
- DOM_KEY_MAP("ContextMenu", CONTEXT_MENU),
+ // Key Enum Value
+ // "Accept" accepts the current IME conversion:
+ DOM_KEY_MAP("Accept", ACCEPT, 0x0501),
+ // "Again" is used to repeat an action:
+ DOM_KEY_MAP("Again", AGAIN, 0x0502),
+ // "Attn" is short for "Attention":
+ DOM_KEY_MAP("Attn", ATTN, 0x0503),
+ DOM_KEY_MAP("Cancel", CANCEL, 0x0504),
+ DOM_KEY_MAP("ContextMenu", CONTEXT_MENU, 0x0505),
// "Escape" is encoded in the Unicode space.
- DOM_KEY_MAP("Execute", EXECUTE),
- DOM_KEY_MAP("Find", FIND),
- DOM_KEY_MAP("Help", HELP),
- DOM_KEY_MAP("Pause", PAUSE), // Program state - not for media
- DOM_KEY_MAP("Play", PLAY), // Program state - not for media
- DOM_KEY_MAP("Props", PROPS), // Properties
- DOM_KEY_MAP("Select", SELECT),
- DOM_KEY_MAP("ZoomIn", ZOOM_IN),
- DOM_KEY_MAP("ZoomOut", ZOOM_OUT),
+ DOM_KEY_MAP("Execute", EXECUTE, 0x0506),
+ DOM_KEY_MAP("Find", FIND, 0x0507),
+ DOM_KEY_MAP("Help", HELP, 0x0508),
+ // "Pause" applies to program state - not to playing media:
+ DOM_KEY_MAP("Pause", PAUSE, 0x0509),
+ // "Play" applies to program state - not to playing media:
+ DOM_KEY_MAP("Play", PLAY, 0x050A),
+ // "Props" is short for "Properties":
+ DOM_KEY_MAP("Props", PROPS, 0x050B),
+ DOM_KEY_MAP("Select", SELECT, 0x050C),
+ DOM_KEY_MAP("ZoomIn", ZOOM_IN, 0x050D),
+ DOM_KEY_MAP("ZoomOut", ZOOM_OUT, 0x050E),
// ========================================================
// Device Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-device
+ // http://www.w3.org/TR/uievents-key/#keys-device
// ========================================================
- // Key Enum
- DOM_KEY_MAP("BrightnessDown", BRIGHTNESS_DOWN),
- DOM_KEY_MAP("BrightnessUp", BRIGHTNESS_UP),
- DOM_KEY_MAP("Camera", CAMERA),
- DOM_KEY_MAP("Eject", EJECT),
- DOM_KEY_MAP("LogOff", LOG_OFF),
- DOM_KEY_MAP("Power", POWER),
- DOM_KEY_MAP("PowerOff", POWER_OFF),
- DOM_KEY_MAP("PrintScreen", PRINT_SCREEN),
- DOM_KEY_MAP("Hibernate", HIBERNATE),
- DOM_KEY_MAP("Standby", STANDBY),
- DOM_KEY_MAP("WakeUp", WAKE_UP),
+ // Key Enum Value
+ DOM_KEY_MAP("BrightnessDown", BRIGHTNESS_DOWN, 0x0601),
+ DOM_KEY_MAP("BrightnessUp", BRIGHTNESS_UP, 0x0602),
+ // "Camera" moved to Mobile Phone Keys section.
+ // ("Camera", CAMERA, 0x0603),
+ DOM_KEY_MAP("Eject", EJECT, 0x0604),
+ DOM_KEY_MAP("LogOff", LOG_OFF, 0x0605),
+ DOM_KEY_MAP("Power", POWER, 0x0606),
+ DOM_KEY_MAP("PowerOff", POWER_OFF, 0x0607),
+ DOM_KEY_MAP("PrintScreen", PRINT_SCREEN, 0x0608),
+ DOM_KEY_MAP("Hibernate", HIBERNATE, 0x0609),
+ DOM_KEY_MAP("Standby", STANDBY, 0x060A),
+ DOM_KEY_MAP("WakeUp", WAKE_UP, 0x060B),
// =============================================================
// IME and Composition Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-composition
+ // http://www.w3.org/TR/uievents-key/#keys-composition
// =============================================================
- // Key Enum
- DOM_KEY_MAP("AllCandidates", ALL_CANDIDATES),
- DOM_KEY_MAP("Alphanumeric", ALPHANUMERIC),
- DOM_KEY_MAP("CodeInput", CODE_INPUT),
- DOM_KEY_MAP("Compose", COMPOSE),
- DOM_KEY_MAP("Convert", CONVERT),
+ // Key Enum Value
+ DOM_KEY_MAP("AllCandidates", ALL_CANDIDATES, 0x0701),
+ DOM_KEY_MAP("Alphanumeric", ALPHANUMERIC, 0x0702),
+ DOM_KEY_MAP("CodeInput", CODE_INPUT, 0x0703),
+ DOM_KEY_MAP("Compose", COMPOSE, 0x0704),
+ DOM_KEY_MAP("Convert", CONVERT, 0x0705),
// "Dead" is represented as a flag plus combining character.
- DOM_KEY_MAP("FinalMode", FINAL_MODE),
- DOM_KEY_MAP("GroupFirst", GROUP_FIRST),
- DOM_KEY_MAP("GroupLast", GROUP_LAST),
- DOM_KEY_MAP("GroupNext", GROUP_NEXT),
- DOM_KEY_MAP("GroupPrevious", GROUP_PREVIOUS),
- DOM_KEY_MAP("ModeChange", MODE_CHANGE),
- DOM_KEY_MAP("NextCandidate", NEXT_CANDIDATE),
- DOM_KEY_MAP("NonConvert", NON_CONVERT),
- DOM_KEY_MAP("PreviousCandidate", PREVIOUS_CANDIDATE),
- DOM_KEY_MAP("Process", PROCESS),
- DOM_KEY_MAP("SingleCandidate", SINGLE_CANDIDATE),
+ DOM_KEY_MAP("FinalMode", FINAL_MODE, 0x0706),
+ DOM_KEY_MAP("GroupFirst", GROUP_FIRST, 0x0707),
+ DOM_KEY_MAP("GroupLast", GROUP_LAST, 0x0708),
+ DOM_KEY_MAP("GroupNext", GROUP_NEXT, 0x0709),
+ DOM_KEY_MAP("GroupPrevious", GROUP_PREVIOUS, 0x070A),
+ DOM_KEY_MAP("ModeChange", MODE_CHANGE, 0x070B),
+ DOM_KEY_MAP("NextCandidate", NEXT_CANDIDATE, 0x070C),
+ DOM_KEY_MAP("NonConvert", NON_CONVERT, 0x070D),
+ DOM_KEY_MAP("PreviousCandidate", PREVIOUS_CANDIDATE, 0x070E),
+ DOM_KEY_MAP("Process", PROCESS, 0x070F),
+ DOM_KEY_MAP("SingleCandidate", SINGLE_CANDIDATE, 0x0710),
// Keys specific to Korean keyboards
- DOM_KEY_MAP("HangulMode", HANGUL_MODE),
- DOM_KEY_MAP("HanjaMode", HANJA_MODE),
- DOM_KEY_MAP("JunjaMode", JUNJA_MODE),
+ DOM_KEY_MAP("HangulMode", HANGUL_MODE, 0x0711),
+ DOM_KEY_MAP("HanjaMode", HANJA_MODE, 0x0712),
+ DOM_KEY_MAP("JunjaMode", JUNJA_MODE, 0x0713),
// Keys specific to Japanese keyboards
- DOM_KEY_MAP("Eisu", EISU),
- DOM_KEY_MAP("Hankaku", HANKAKU),
- DOM_KEY_MAP("Hiragana", HIRAGANA),
- DOM_KEY_MAP("HiraganaKatakana", HIRAGANA_KATAKANA),
- DOM_KEY_MAP("KanaMode", KANA_MODE),
- DOM_KEY_MAP("KanjiMode", KANJI_MODE),
- DOM_KEY_MAP("Katakana", KATAKANA),
- DOM_KEY_MAP("Romaji", ROMAJI),
- DOM_KEY_MAP("Zenkaku", ZENKAKU),
- DOM_KEY_MAP("ZenkakuHankaku", ZENKAKU_HANKAKU),
+ DOM_KEY_MAP("Eisu", EISU, 0x0714),
+ DOM_KEY_MAP("Hankaku", HANKAKU, 0x0715),
+ DOM_KEY_MAP("Hiragana", HIRAGANA, 0x0716),
+ DOM_KEY_MAP("HiraganaKatakana", HIRAGANA_KATAKANA, 0x0717),
+ DOM_KEY_MAP("KanaMode", KANA_MODE, 0x0718),
+ DOM_KEY_MAP("KanjiMode", KANJI_MODE, 0x0719),
+ DOM_KEY_MAP("Katakana", KATAKANA, 0x071A),
+ DOM_KEY_MAP("Romaji", ROMAJI, 0x071B),
+ DOM_KEY_MAP("Zenkaku", ZENKAKU, 0x071C),
+ DOM_KEY_MAP("ZenkakuHankaku", ZENKAKU_HANKAKU, 0x071D),
// ==========================================================
// General-Purpose Function Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-function
+ // http://www.w3.org/TR/uievents-key/#keys-function
// ==========================================================
// DOM defines open-ended sets, but if we want a finite numeric encoding we
// need to draw the line somewhere. USB and Windows (VK) and Linux (evdev)
// all support 24, so we define 24.
- // Key Enum
- DOM_KEY_MAP("F1", F1),
- DOM_KEY_MAP("F2", F2),
- DOM_KEY_MAP("F3", F3),
- DOM_KEY_MAP("F4", F4),
- DOM_KEY_MAP("F5", F5),
- DOM_KEY_MAP("F6", F6),
- DOM_KEY_MAP("F7", F7),
- DOM_KEY_MAP("F8", F8),
- DOM_KEY_MAP("F9", F9),
- DOM_KEY_MAP("F10", F10),
- DOM_KEY_MAP("F11", F11),
- DOM_KEY_MAP("F12", F12),
- DOM_KEY_MAP("F13", F13),
- DOM_KEY_MAP("F14", F14),
- DOM_KEY_MAP("F15", F15),
- DOM_KEY_MAP("F16", F16),
- DOM_KEY_MAP("F17", F17),
- DOM_KEY_MAP("F18", F18),
- DOM_KEY_MAP("F19", F19),
- DOM_KEY_MAP("F20", F20),
- DOM_KEY_MAP("F21", F21),
- DOM_KEY_MAP("F22", F22),
- DOM_KEY_MAP("F23", F23),
- DOM_KEY_MAP("F24", F24),
- DOM_KEY_MAP("Soft1", SOFT1),
- DOM_KEY_MAP("Soft2", SOFT2),
- DOM_KEY_MAP("Soft3", SOFT3),
- DOM_KEY_MAP("Soft4", SOFT4),
- DOM_KEY_MAP("Soft5", SOFT5),
- DOM_KEY_MAP("Soft6", SOFT6),
- DOM_KEY_MAP("Soft7", SOFT7),
- DOM_KEY_MAP("Soft8", SOFT8),
+ // Key Enum Value
+ DOM_KEY_MAP("F1", F1, 0x0801),
+ DOM_KEY_MAP("F2", F2, 0x0802),
+ DOM_KEY_MAP("F3", F3, 0x0803),
+ DOM_KEY_MAP("F4", F4, 0x0804),
+ DOM_KEY_MAP("F5", F5, 0x0805),
+ DOM_KEY_MAP("F6", F6, 0x0806),
+ DOM_KEY_MAP("F7", F7, 0x0807),
+ DOM_KEY_MAP("F8", F8, 0x0808),
+ DOM_KEY_MAP("F9", F9, 0x0809),
+ DOM_KEY_MAP("F10", F10, 0x080A),
+ DOM_KEY_MAP("F11", F11, 0x080B),
+ DOM_KEY_MAP("F12", F12, 0x080C),
+ DOM_KEY_MAP("F13", F13, 0x080D),
+ DOM_KEY_MAP("F14", F14, 0x080E),
+ DOM_KEY_MAP("F15", F15, 0x080F),
+ DOM_KEY_MAP("F16", F16, 0x0810),
+ DOM_KEY_MAP("F17", F17, 0x0811),
+ DOM_KEY_MAP("F18", F18, 0x0812),
+ DOM_KEY_MAP("F19", F19, 0x0813),
+ DOM_KEY_MAP("F20", F20, 0x0814),
+ DOM_KEY_MAP("F21", F21, 0x0815),
+ DOM_KEY_MAP("F22", F22, 0x0816),
+ DOM_KEY_MAP("F23", F23, 0x0817),
+ DOM_KEY_MAP("F24", F24, 0x0818),
+ DOM_KEY_MAP("Soft1", SOFT1, 0x0901),
+ DOM_KEY_MAP("Soft2", SOFT2, 0x0902),
+ DOM_KEY_MAP("Soft3", SOFT3, 0x0903),
+ DOM_KEY_MAP("Soft4", SOFT4, 0x0904),
+ DOM_KEY_MAP("Soft5", SOFT5, 0x0905),
+ DOM_KEY_MAP("Soft6", SOFT6, 0x0906),
+ DOM_KEY_MAP("Soft7", SOFT7, 0x0907),
+ DOM_KEY_MAP("Soft8", SOFT8, 0x0908),
// ============================================================
// Multimedia Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-multimedia
+ // http://www.w3.org/TR/uievents-key/#keys-multimedia
+ // ============================================================
+
+ // Note: some keys were previously listed in the Media Controller Keys
+ // section of the spec, and retain their original numbering (0x0D__).
+
+ // Key Enum Value
+ DOM_KEY_MAP("ChannelDown", CHANNEL_DOWN, 0x0D0A),
+ DOM_KEY_MAP("ChannelUp", CHANNEL_UP, 0x0D0B),
+ DOM_KEY_MAP("Close", CLOSE, 0x0A01),
+ DOM_KEY_MAP("MailForward", MAIL_FORWARD, 0x0A02),
+ DOM_KEY_MAP("MailReply", MAIL_REPLY, 0x0A03),
+ DOM_KEY_MAP("MailSend", MAIL_SEND, 0x0A04),
+ DOM_KEY_MAP("MediaFastForward", MEDIA_FAST_FORWARD, 0x0D2C),
+ DOM_KEY_MAP("MediaPause", MEDIA_PAUSE, 0x0D2E),
+ DOM_KEY_MAP("MediaPlay", MEDIA_PLAY, 0x0D2F),
+ DOM_KEY_MAP("MediaPlayPause", MEDIA_PLAY_PAUSE, 0x0A05),
+ DOM_KEY_MAP("MediaRecord", MEDIA_RECORD, 0x0D30),
+ DOM_KEY_MAP("MediaRewind", MEDIA_REWIND, 0x0D31),
+ // "MediaSelect" was removed from the spec.
+ // ("MediaSelect", MEDIA_SELECT, 0x0A06),
+ DOM_KEY_MAP("MediaStop", MEDIA_STOP, 0x0A07),
+ DOM_KEY_MAP("MediaTrackNext", MEDIA_TRACK_NEXT, 0x0A08),
+ DOM_KEY_MAP("MediaTrackPrevious", MEDIA_TRACK_PREVIOUS, 0x0A09),
+ DOM_KEY_MAP("New", NEW, 0x0A0A),
+ DOM_KEY_MAP("Open", OPEN, 0x0A0B),
+ DOM_KEY_MAP("Print", PRINT, 0x0A0C),
+ DOM_KEY_MAP("Save", SAVE, 0x0A0D),
+ DOM_KEY_MAP("SpellCheck", SPELL_CHECK, 0x0A0E),
+
// ============================================================
+ // Multimedia Numpad Keys
+ // http://www.w3.org/TR/uievents-key/#keys-multimedia-numpad
+ // ============================================================
+
+ DOM_KEY_MAP("Key11", KEY11, 0x1201),
+ DOM_KEY_MAP("Key12", KEY12, 0x1202),
+
+ // =======================================================
+ // Audio Keys
+ // http://www.w3.org/TR/uievents-key/#keys-audio
+ // =======================================================
+
+ // Note: some keys were previously listed in the Multimedia Keys
+ // (0x0A__) or Media Controller Keys (0x0D__) sections of the spec,
+ // and retain their original numbering.
+
+ // Key Enum Value
+ DOM_KEY_MAP("AudioBalanceLeft", AUDIO_BALANCE_LEFT, 0x0D01),
+ DOM_KEY_MAP("AudioBalanceRight", AUDIO_BALANCE_RIGHT, 0x0D02),
+ DOM_KEY_MAP("AudioBassDown", AUDIO_BASS_DOWN, 0x0E01),
+ DOM_KEY_MAP("AudioBassBoostDown", AUDIO_BASS_BOOST_DOWN, 0x0D03),
+ DOM_KEY_MAP("AudioBassBoostToggle", AUDIO_BASS_BOOST_TOGGLE, 0x0E02),
+ DOM_KEY_MAP("AudioBassBoostUp", AUDIO_BASS_BOOST_UP, 0x0D04),
+ DOM_KEY_MAP("AudioBassUp", AUDIO_BASS_UP, 0x0E03),
+ DOM_KEY_MAP("AudioFaderFront", AUDIO_FADER_FRONT, 0x0D05),
+ DOM_KEY_MAP("AudioFaderRear", AUDIO_FADER_REAR, 0x0D06),
+ DOM_KEY_MAP("AudioSurroundModeNext",AUDIO_SURROUND_MODE_NEXT, 0x0D07),
+ DOM_KEY_MAP("AudioTrebleDown", AUDIO_TREBLE_DOWN, 0x0E04),
+ DOM_KEY_MAP("AudioTrebleUp", AUDIO_TREBLE_UP, 0x0E05),
+ DOM_KEY_MAP("AudioVolumeDown", AUDIO_VOLUME_DOWN, 0x0A0F),
+ DOM_KEY_MAP("AudioVolumeUp", AUDIO_VOLUME_UP, 0x0A10),
+ DOM_KEY_MAP("AudioVolumeMute", AUDIO_VOLUME_MUTE, 0x0A11),
+ DOM_KEY_MAP("MicrophoneToggle", MICROPHONE_TOGGLE, 0x0E06),
+ DOM_KEY_MAP("MicrophoneVolumeDown", MICROPHONE_VOLUME_DOWN, 0x0E07),
+ DOM_KEY_MAP("MicrophoneVolumeUp", MICROPHONE_VOLUME_UP, 0x0E08),
+ DOM_KEY_MAP("MicrophoneVolumeMute", MICROPHONE_VOLUME_MUTE, 0x0E09),
+
+ // ========================================================
+ // Speech Keys
+ // http://www.w3.org/TR/uievents-key/#keys-speech
+ // ========================================================
- // Key Enum
- DOM_KEY_MAP("Close", CLOSE),
- DOM_KEY_MAP("MailForward", MAIL_FORWARD),
- DOM_KEY_MAP("MailReply", MAIL_REPLY),
- DOM_KEY_MAP("MailSend", MAIL_SEND),
- DOM_KEY_MAP("MediaPlayPause", MEDIA_PLAY_PAUSE),
- DOM_KEY_MAP("MediaSelect", MEDIA_SELECT),
- DOM_KEY_MAP("MediaStop", MEDIA_STOP),
- DOM_KEY_MAP("MediaTrackNext", MEDIA_TRACK_NEXT),
- DOM_KEY_MAP("MediaTrackPrevious", MEDIA_TRACK_PREVIOUS),
- DOM_KEY_MAP("New", NEW),
- DOM_KEY_MAP("Open", OPEN),
- DOM_KEY_MAP("Print", PRINT),
- DOM_KEY_MAP("Save", SAVE),
- DOM_KEY_MAP("SpellCheck", SPELL_CHECK),
- DOM_KEY_MAP("VolumeDown", VOLUME_DOWN),
- DOM_KEY_MAP("VolumeUp", VOLUME_UP),
- DOM_KEY_MAP("VolumeMute", VOLUME_MUTE),
+ // Key Enum Value
+ DOM_KEY_MAP("SpeechCorrectionList", SPEECH_CORRECTION_LIST, 0x0F01),
+ DOM_KEY_MAP("SpeechInputToggle", SPEECH_INPUT_TOGGLE, 0x0F02),
// ======================================================
// Application Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-apps
+ // http://www.w3.org/TR/uievents-key/#keys-apps
// ======================================================
- // Key Enum
- DOM_KEY_MAP("LaunchCalculator", LAUNCH_CALCULATOR), // Application 2
- DOM_KEY_MAP("LaunchCalendar", LAUNCH_CALENDAR),
- DOM_KEY_MAP("LaunchMail", LAUNCH_MAIL),
- DOM_KEY_MAP("LaunchMediaPlayer", LAUNCH_MEDIA_PLAYER),
- DOM_KEY_MAP("LaunchMusicPlayer", LAUNCH_MUSIC_PLAYER),
- DOM_KEY_MAP("LaunchMyComputer", LAUNCH_MY_COMPUTER), // Application 1
- DOM_KEY_MAP("LaunchScreenSaver", LAUNCH_SCREEN_SAVER),
- DOM_KEY_MAP("LaunchSpreadsheet", LAUNCH_SPREADSHEET),
- DOM_KEY_MAP("LaunchWebBrowser", LAUNCH_WEB_BROWSER),
- DOM_KEY_MAP("LaunchWebCam", LAUNCH_WEB_CAM),
- DOM_KEY_MAP("LaunchWordProcessor", LAUNCH_WORD_PROCESSOR),
+ // Key Enum Value
+ // "LaunchCalculator" is equivalent to "Launch Application 2":
+ DOM_KEY_MAP("LaunchCalculator", LAUNCH_CALCULATOR, 0x0B01),
+ DOM_KEY_MAP("LaunchCalendar", LAUNCH_CALENDAR, 0x0B02),
+ DOM_KEY_MAP("LaunchContacts", LAUNCH_CONTACTS, 0x0B0C),
+ DOM_KEY_MAP("LaunchMail", LAUNCH_MAIL, 0x0B03),
+ DOM_KEY_MAP("LaunchMediaPlayer", LAUNCH_MEDIA_PLAYER, 0x0B04),
+ DOM_KEY_MAP("LaunchMusicPlayer", LAUNCH_MUSIC_PLAYER, 0x0B05),
+ // "LaunchMyComputer" is equivalent to "Launch Application 1":
+ DOM_KEY_MAP("LaunchMyComputer", LAUNCH_MY_COMPUTER, 0x0B06),
+ DOM_KEY_MAP("LaunchPhone", LAUNCH_PHONE, 0x0B0D),
+ DOM_KEY_MAP("LaunchScreenSaver", LAUNCH_SCREEN_SAVER, 0x0B07),
+ DOM_KEY_MAP("LaunchSpreadsheet", LAUNCH_SPREADSHEET, 0x0B08),
+ DOM_KEY_MAP("LaunchWebBrowser", LAUNCH_WEB_BROWSER, 0x0B09),
+ DOM_KEY_MAP("LaunchWebCam", LAUNCH_WEB_CAM, 0x0B0A),
+ DOM_KEY_MAP("LaunchWordProcessor", LAUNCH_WORD_PROCESSOR, 0x0B0B),
// =========================================================
// Browser Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-browser
+ // http://www.w3.org/TR/uievents-key/#keys-browser
+ // =========================================================
+
+ // Key Enum Value
+ DOM_KEY_MAP("BrowserBack", BROWSER_BACK, 0x0C01),
+ DOM_KEY_MAP("BrowserFavorites", BROWSER_FAVORITES, 0x0C02),
+ DOM_KEY_MAP("BrowserForward", BROWSER_FORWARD, 0x0C03),
+ DOM_KEY_MAP("BrowserHome", BROWSER_HOME, 0x0C04),
+ DOM_KEY_MAP("BrowserRefresh", BROWSER_REFRESH, 0x0C05),
+ DOM_KEY_MAP("BrowserSearch", BROWSER_SEARCH, 0x0C06),
+ DOM_KEY_MAP("BrowserStop", BROWSER_STOP, 0x0C07),
+
+ // =========================================================
+ // Mobile Phone Keys
+ // http://www.w3.org/TR/uievents-key/#keys-mobile
+ // =========================================================
+
+ // Note: some keys were previously listed in the Device Keys (0x06__)
+ // section and retain their original numbering.
+
+ // Key Enum Value
+ DOM_KEY_MAP("AppSwitch", APP_SWITCH, 0x1001),
+ DOM_KEY_MAP("Call", CALL, 0x1002),
+ DOM_KEY_MAP("Camera", CAMERA, 0x0603),
+ DOM_KEY_MAP("CameraFocus", CAMERA_FOCUS, 0x1003),
+ DOM_KEY_MAP("EndCall", END_CALL, 0x1004),
+ DOM_KEY_MAP("GoBack", GO_BACK, 0x1005),
+ DOM_KEY_MAP("GoHome", GO_HOME, 0x1006),
+ DOM_KEY_MAP("HeadsetHook", HEADSET_HOOK, 0x1007),
+ DOM_KEY_MAP("LastNumberRedial", LAST_NUMBER_REDIAL, 0x1008),
+ DOM_KEY_MAP("Notification", NOTIFICATION, 0x1009),
+ DOM_KEY_MAP("MannerMode", MANNER_MODE, 0x100A),
+ DOM_KEY_MAP("VoiceDial", VOICE_DIAL, 0x100B),
+
+ // =========================================================
+ // TV Keys
+ // http://www.w3.org/TR/uievents-key/#keys-tv
// =========================================================
- // Key Enum
- DOM_KEY_MAP("BrowserBack", BROWSER_BACK),
- DOM_KEY_MAP("BrowserFavorites", BROWSER_FAVORITES),
- DOM_KEY_MAP("BrowserForward", BROWSER_FORWARD),
- DOM_KEY_MAP("BrowserHome", BROWSER_HOME),
- DOM_KEY_MAP("BrowserRefresh", BROWSER_REFRESH),
- DOM_KEY_MAP("BrowserSearch", BROWSER_SEARCH),
- DOM_KEY_MAP("BrowserStop", BROWSER_STOP),
+ // Note: some keys were previously listed in the Media Controller
+ // Keys (0x0D__) section and retain their original numbering.
+
+ // Key Enum Value
+ DOM_KEY_MAP("TV", TV, 0x0D49),
+ DOM_KEY_MAP("TV3DMode", TV_3D_MODE, 0x1101),
+ DOM_KEY_MAP("TVAntennaCable", TV_ANTENNA_CABLE, 0x1102),
+ DOM_KEY_MAP("TVAudioDescription", TV_AUDIO_DESCRIPTION, 0x1103),
+ DOM_KEY_MAP("TVAudioDescriptionMixDown", TV_AUDIO_DESCRIPTION_MIX_DOWN,
+ 0x1104),
+ DOM_KEY_MAP("TVAudioDescriptionMixUp", TV_AUDIO_DESCRIPTION_MIX_UP,
+ 0x1105),
+ DOM_KEY_MAP("TVContentsMenu", TV_CONTENTS_MENU, 0x1106),
+ DOM_KEY_MAP("TVDataService", TV_DATA_SERVICE, 0x1107),
+ DOM_KEY_MAP("TVInput", TV_INPUT, 0x0D4A),
+ DOM_KEY_MAP("TVInputComponent1", TV_INPUT_COMPONENT1, 0x1108),
+ DOM_KEY_MAP("TVInputComponent2", TV_INPUT_COMPONENT2, 0x1109),
+ DOM_KEY_MAP("TVInputComposite1", TV_INPUT_COMPOSITE1, 0x110A),
+ DOM_KEY_MAP("TVInputComposite2", TV_INPUT_COMPOSITE2, 0x110B),
+ DOM_KEY_MAP("TVInputHDMI1", TV_INPUT_HDMI1, 0x110C),
+ DOM_KEY_MAP("TVInputHDMI2", TV_INPUT_HDMI2, 0x110D),
+ DOM_KEY_MAP("TVInputHDMI3", TV_INPUT_HDMI3, 0x110E),
+ DOM_KEY_MAP("TVInputHDMI4", TV_INPUT_HDMI4, 0x110F),
+ DOM_KEY_MAP("TVInputVGA1", TV_INPUT_VGA1, 0x1110),
+ DOM_KEY_MAP("TVMediaContext", TV_MEDIA_CONTEXT, 0x1111),
+ DOM_KEY_MAP("TVNetwork", TV_NETWORK, 0x1112),
+ DOM_KEY_MAP("TVNumberEntry", TV_NUMBER_ENTRY, 0x1113),
+ DOM_KEY_MAP("TVPower", TV_POWER, 0x0D4B),
+ DOM_KEY_MAP("TVRadioService", TV_RADIO_SERVICE, 0x1114),
+ DOM_KEY_MAP("TVSatellite", TV_SATELLITE, 0x1115),
+ DOM_KEY_MAP("TVSatelliteBC", TV_SATELLITE_BC, 0x1116),
+ DOM_KEY_MAP("TVSatelliteCS", TV_SATELLITE_CS, 0x1117),
+ DOM_KEY_MAP("TVSatelliteToggle", TV_SATELLITE_TOGGLE, 0x1118),
+ DOM_KEY_MAP("TVTerrestrialAnalog", TV_TERRESTRIAL_ANALOG, 0x1119),
+ DOM_KEY_MAP("TVTerrestrialDigital", TV_TERRESTRIAL_DIGITAL, 0x111A),
+ DOM_KEY_MAP("TVTimer", TV_TIMER, 0x111B),
// ==================================================================
// Media Controller Keys
- // http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-media-controller
+ // http://www.w3.org/TR/uievents-key/#keys-media-controller
// ==================================================================
- // Key Enum
- DOM_KEY_MAP("AudioBalanceLeft", AUDIO_BALANCE_LEFT),
- DOM_KEY_MAP("AudioBalanceRight", AUDIO_BALANCE_RIGHT),
- DOM_KEY_MAP("AudioBassBoostDown", AUDIO_BASS_BOOST_DOWN),
- DOM_KEY_MAP("AudioBassBoostUp", AUDIO_BASS_BOOST_UP),
- DOM_KEY_MAP("AudioFaderFront", AUDIO_FADER_FRONT),
- DOM_KEY_MAP("AudioFaderRear", AUDIO_FADER_REAR),
- DOM_KEY_MAP("AudioSurroundModeNext",AUDIO_SURROUND_MODE_NEXT),
- DOM_KEY_MAP("AVRInput", AVR_INPUT),
- DOM_KEY_MAP("AVRPower", AVR_POWER),
- DOM_KEY_MAP("ChannelDown", CHANNEL_DOWN),
- DOM_KEY_MAP("ChannelUp", CHANNEL_UP),
- DOM_KEY_MAP("ColorF0Red", COLOR_F0_RED),
- DOM_KEY_MAP("ColorF1Green", COLOR_F1_GREEN),
- DOM_KEY_MAP("ColorF2Yellow", COLOR_F2_YELLOW),
- DOM_KEY_MAP("ColorF3Blue", COLOR_F3_BLUE),
- DOM_KEY_MAP("ColorF4Grey", COLOR_F4_GREY),
- DOM_KEY_MAP("ColorF5Brown", COLOR_F5_BROWN),
- DOM_KEY_MAP("ClosedCaptionToggle", CLOSED_CAPTION_TOGGLE),
- DOM_KEY_MAP("Dimmer", DIMMER),
- DOM_KEY_MAP("DisplaySwap", DISPLAY_SWAP),
- DOM_KEY_MAP("Exit", EXIT),
- DOM_KEY_MAP("FavoriteClear0", FAVORITE_CLEAR0),
- DOM_KEY_MAP("FavoriteClear1", FAVORITE_CLEAR1),
- DOM_KEY_MAP("FavoriteClear2", FAVORITE_CLEAR2),
- DOM_KEY_MAP("FavoriteClear3", FAVORITE_CLEAR3),
- DOM_KEY_MAP("FavoriteRecall0", FAVORITE_RECALL0),
- DOM_KEY_MAP("FavoriteRecall1", FAVORITE_RECALL1),
- DOM_KEY_MAP("FavoriteRecall2", FAVORITE_RECALL2),
- DOM_KEY_MAP("FavoriteRecall3", FAVORITE_RECALL3),
- DOM_KEY_MAP("FavoriteStore0", FAVORITE_STORE0),
- DOM_KEY_MAP("FavoriteStore1", FAVORITE_STORE1),
- DOM_KEY_MAP("FavoriteStore2", FAVORITE_STORE2),
- DOM_KEY_MAP("FavoriteStore3", FAVORITE_STORE3),
- DOM_KEY_MAP("Guide", GUIDE),
- DOM_KEY_MAP("GuideNextDay", GUIDE_NEXT_DAY),
- DOM_KEY_MAP("GuidePreviousDay", GUIDE_PREVIOUS_DAY),
- DOM_KEY_MAP("Info", INFO),
- DOM_KEY_MAP("InstantReplay", INSTANT_REPLAY),
- DOM_KEY_MAP("Link", LINK),
- DOM_KEY_MAP("ListProgram", LIST_PROGRAM),
- DOM_KEY_MAP("LiveContent", LIVE_CONTENT),
- DOM_KEY_MAP("Lock", LOCK),
- DOM_KEY_MAP("MediaApps", MEDIA_APPS),
- DOM_KEY_MAP("MediaFastForward", MEDIA_FAST_FORWARD),
- DOM_KEY_MAP("MediaLast", MEDIA_LAST),
- DOM_KEY_MAP("MediaPause", MEDIA_PAUSE),
- DOM_KEY_MAP("MediaPlay", MEDIA_PLAY),
- DOM_KEY_MAP("MediaRecord", MEDIA_RECORD),
- DOM_KEY_MAP("MediaRewind", MEDIA_REWIND),
- DOM_KEY_MAP("MediaSkip", MEDIA_SKIP),
- DOM_KEY_MAP("NextFavoriteChannel", NEXT_FAVORITE_CHANNEL),
- DOM_KEY_MAP("NextUserProfile", NEXT_USER_PROFILE),
- DOM_KEY_MAP("OnDemand", ON_DEMAND),
- DOM_KEY_MAP("PinPDown", PINP_DOWN),
- DOM_KEY_MAP("PinPMove", PINP_MOVE),
- DOM_KEY_MAP("PinPToggle", PINP_TOGGLE),
- DOM_KEY_MAP("PinPUp", PINP_UP),
- DOM_KEY_MAP("PlaySpeedDown", PLAY_SPEED_DOWN),
- DOM_KEY_MAP("PlaySpeedReset", PLAY_SPEED_RESET),
- DOM_KEY_MAP("PlaySpeedUp", PLAY_SPEED_UP),
- DOM_KEY_MAP("RandomToggle", RANDOM_TOGGLE),
- DOM_KEY_MAP("RcLowBattery", RC_LOW_BATTERY),
- DOM_KEY_MAP("RecordSpeedNext", RECORD_SPEED_NEXT),
- DOM_KEY_MAP("RfBypass", RF_BYPASS),
- DOM_KEY_MAP("ScanChannelsToggle", SCAN_CHANNELS_TOGGLE),
- DOM_KEY_MAP("ScreenModeNext", SCREEN_MODE_NEXT),
- DOM_KEY_MAP("Settings", SETTINGS),
- DOM_KEY_MAP("SplitScreenToggle", SPLIT_SCREEN_TOGGLE),
- DOM_KEY_MAP("STBInput", STB_INPUT),
- DOM_KEY_MAP("STBPower", STB_POWER),
- DOM_KEY_MAP("Subtitle", SUBTITLE),
- DOM_KEY_MAP("Teletext", TELETEXT),
- DOM_KEY_MAP("TV", T_V),
- DOM_KEY_MAP("TVInput", TV_INPUT),
- DOM_KEY_MAP("TVPower", TV_POWER),
- DOM_KEY_MAP("VideoModeNext", VIDEO_MODE_NEXT),
- DOM_KEY_MAP("Wink", WINK),
- DOM_KEY_MAP("ZoomToggle", ZOOM_TOGGLE),
-
- DOM_KEY_MAP_END
+ // Key Enum Value
+ DOM_KEY_MAP("AVRInput", AVR_INPUT, 0x0D08),
+ DOM_KEY_MAP("AVRPower", AVR_POWER, 0x0D09),
+ // Moved to Multimedia Keys section:
+ // ("ChannelDown", CHANNEL_DOWN, 0x0D0A),
+ // ("ChannelUp", CHANNEL_UP, 0x0D0B),
+ DOM_KEY_MAP("ColorF0Red", COLOR_F0_RED, 0x0D0C),
+ DOM_KEY_MAP("ColorF1Green", COLOR_F1_GREEN, 0x0D0D),
+ DOM_KEY_MAP("ColorF2Yellow", COLOR_F2_YELLOW, 0x0D0E),
+ DOM_KEY_MAP("ColorF3Blue", COLOR_F3_BLUE, 0x0D0F),
+ DOM_KEY_MAP("ColorF4Grey", COLOR_F4_GREY, 0x0D10),
+ DOM_KEY_MAP("ColorF5Brown", COLOR_F5_BROWN, 0x0D11),
+ DOM_KEY_MAP("ClosedCaptionToggle", CLOSED_CAPTION_TOGGLE, 0x0D12),
+ DOM_KEY_MAP("Dimmer", DIMMER, 0x0D13),
+ DOM_KEY_MAP("DisplaySwap", DISPLAY_SWAP, 0x0D14),
+ DOM_KEY_MAP("DVR", DVR, 0x0D4F),
+ DOM_KEY_MAP("Exit", EXIT, 0x0D15),
+ DOM_KEY_MAP("FavoriteClear0", FAVORITE_CLEAR0, 0x0D16),
+ DOM_KEY_MAP("FavoriteClear1", FAVORITE_CLEAR1, 0x0D17),
+ DOM_KEY_MAP("FavoriteClear2", FAVORITE_CLEAR2, 0x0D18),
+ DOM_KEY_MAP("FavoriteClear3", FAVORITE_CLEAR3, 0x0D19),
+ DOM_KEY_MAP("FavoriteRecall0", FAVORITE_RECALL0, 0x0D1A),
+ DOM_KEY_MAP("FavoriteRecall1", FAVORITE_RECALL1, 0x0D1B),
+ DOM_KEY_MAP("FavoriteRecall2", FAVORITE_RECALL2, 0x0D1C),
+ DOM_KEY_MAP("FavoriteRecall3", FAVORITE_RECALL3, 0x0D1D),
+ DOM_KEY_MAP("FavoriteStore0", FAVORITE_STORE0, 0x0D1E),
+ DOM_KEY_MAP("FavoriteStore1", FAVORITE_STORE1, 0x0D1F),
+ DOM_KEY_MAP("FavoriteStore2", FAVORITE_STORE2, 0x0D20),
+ DOM_KEY_MAP("FavoriteStore3", FAVORITE_STORE3, 0x0D21),
+ DOM_KEY_MAP("Guide", GUIDE, 0x0D22),
+ DOM_KEY_MAP("GuideNextDay", GUIDE_NEXT_DAY, 0x0D23),
+ DOM_KEY_MAP("GuidePreviousDay", GUIDE_PREVIOUS_DAY, 0x0D24),
+ DOM_KEY_MAP("Info", INFO, 0x0D25),
+ DOM_KEY_MAP("InstantReplay", INSTANT_REPLAY, 0x0D26),
+ DOM_KEY_MAP("Link", LINK, 0x0D27),
+ DOM_KEY_MAP("ListProgram", LIST_PROGRAM, 0x0D28),
+ DOM_KEY_MAP("LiveContent", LIVE_CONTENT, 0x0D29),
+ DOM_KEY_MAP("Lock", LOCK, 0x0D2A),
+ DOM_KEY_MAP("MediaApps", MEDIA_APPS, 0x0D2B),
+ DOM_KEY_MAP("MediaAudioTrack", MEDIA_AUDIO_TRACK, 0x0D50),
+ // Moved to Multimedia Keys section:
+ // ("MediaFastForward", MEDIA_FAST_FORWARD, 0x0D2C),
+ DOM_KEY_MAP("MediaLast", MEDIA_LAST, 0x0D2D),
+ // Moved to Multimedia Keys section:
+ // ("MediaPause", MEDIA_PAUSE, 0x0D2E),
+ // ("MediaPlay", MEDIA_PLAY, 0x0D2F),
+ // ("MediaRecord", MEDIA_RECORD, 0x0D30),
+ // ("MediaRewind", MEDIA_REWIND, 0x0D31),
+ DOM_KEY_MAP("MediaSkipBackward", MEDIA_SKIP_BACKWARD, 0x0D51),
+ DOM_KEY_MAP("MediaSkipForward", MEDIA_SKIP_FORWARD, 0x0D52),
+ DOM_KEY_MAP("MediaSkip", MEDIA_SKIP, 0x0D32),
+ DOM_KEY_MAP("MediaStepBackward", MEDIA_STEP_BACKWARD, 0x0D53),
+ DOM_KEY_MAP("MediaStepForward", MEDIA_STEP_FORWARD, 0x0D54),
+ DOM_KEY_MAP("MediaTopMenu", MEDIA_TOP_MENU, 0x0D55),
+ DOM_KEY_MAP("NavigateIn", NAVIGATE_IN, 0x0D56),
+ DOM_KEY_MAP("NavigateNext", NAVIGATE_NEXT, 0x0D57),
+ DOM_KEY_MAP("NavigateOut", NAVIGATE_OUT, 0x0D58),
+ DOM_KEY_MAP("NavigatePrevious", NAVIGATE_PREVIOUS, 0x0D59),
+ DOM_KEY_MAP("NextFavoriteChannel", NEXT_FAVORITE_CHANNEL, 0x0D33),
+ DOM_KEY_MAP("NextUserProfile", NEXT_USER_PROFILE, 0x0D34),
+ DOM_KEY_MAP("OnDemand", ON_DEMAND, 0x0D35),
+ DOM_KEY_MAP("Pairing", PAIRING, 0x0D5A),
+ DOM_KEY_MAP("PinPDown", PINP_DOWN, 0x0D36),
+ DOM_KEY_MAP("PinPMove", PINP_MOVE, 0x0D37),
+ DOM_KEY_MAP("PinPToggle", PINP_TOGGLE, 0x0D38),
+ DOM_KEY_MAP("PinPUp", PINP_UP, 0x0D39),
+ DOM_KEY_MAP("PlaySpeedDown", PLAY_SPEED_DOWN, 0x0D3A),
+ DOM_KEY_MAP("PlaySpeedReset", PLAY_SPEED_RESET, 0x0D3B),
+ DOM_KEY_MAP("PlaySpeedUp", PLAY_SPEED_UP, 0x0D3C),
+ DOM_KEY_MAP("RandomToggle", RANDOM_TOGGLE, 0x0D3D),
+ DOM_KEY_MAP("RcLowBattery", RC_LOW_BATTERY, 0x0D3E),
+ DOM_KEY_MAP("RecordSpeedNext", RECORD_SPEED_NEXT, 0x0D3F),
+ DOM_KEY_MAP("RfBypass", RF_BYPASS, 0x0D40),
+ DOM_KEY_MAP("ScanChannelsToggle", SCAN_CHANNELS_TOGGLE, 0x0D41),
+ DOM_KEY_MAP("ScreenModeNext", SCREEN_MODE_NEXT, 0x0D42),
+ DOM_KEY_MAP("Settings", SETTINGS, 0x0D43),
+ DOM_KEY_MAP("SplitScreenToggle", SPLIT_SCREEN_TOGGLE, 0x0D44),
+ DOM_KEY_MAP("STBInput", STB_INPUT, 0x0D45),
+ DOM_KEY_MAP("STBPower", STB_POWER, 0x0D46),
+ DOM_KEY_MAP("Subtitle", SUBTITLE, 0x0D47),
+ DOM_KEY_MAP("Teletext", TELETEXT, 0x0D48),
+ DOM_KEY_MAP("VideoModeNext", VIDEO_MODE_NEXT, 0x0D4C),
+ DOM_KEY_MAP("Wink", WINK, 0x0D4D),
+ DOM_KEY_MAP("ZoomToggle", ZOOM_TOGGLE, 0x0D4E),
};
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter.cc b/chromium/ui/events/keycodes/dom/keycode_converter.cc
index b1373b4b8c7..4531acd128a 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter.cc
+++ b/chromium/ui/events/keycodes/dom/keycode_converter.cc
@@ -43,14 +43,10 @@ struct DomKeyMapEntry {
#define DOM_KEY_MAP_DECLARATION const DomKeyMapEntry dom_key_map[] =
#define DOM_KEY_UNI(key, id, value) {DomKey::id, key}
-#define DOM_KEY_MAP_BEGIN
-#define DOM_KEY_MAP(key, id) {DomKey::id, key}
-#define DOM_KEY_MAP_END
+#define DOM_KEY_MAP(key, id, value) {DomKey::id, key}
#include "ui/events/keycodes/dom/dom_key_data.inc"
#undef DOM_KEY_MAP_DECLARATION
-#undef DOM_KEY_MAP_BEGIN
#undef DOM_KEY_MAP
-#undef DOM_KEY_MAP_END
#undef DOM_KEY_UNI
const size_t kDomKeyMapEntries = arraysize(dom_key_map);
@@ -235,7 +231,6 @@ bool KeycodeConverter::IsDomKeyForModifier(DomKey dom_key) {
case DomKey::HYPER:
case DomKey::META:
case DomKey::NUM_LOCK:
- case DomKey::OS:
case DomKey::SCROLL_LOCK:
case DomKey::SHIFT:
case DomKey::SUPER:
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter_data.inc b/chromium/ui/events/keycodes/dom/keycode_converter_data.inc
index c46c8e8416c..bf0b47bdfb0 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter_data.inc
+++ b/chromium/ui/events/keycodes/dom/keycode_converter_data.inc
@@ -10,7 +10,7 @@
// [0] USB HID Usage Tables,
// http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
// [1] DOM Level 3 KeyboardEvent code Values,
-// http://www.w3.org/TR/DOM-Level-3-Events-code/
+// http://www.w3.org/TR/uievents-code/
// [2] OS X <HIToolbox/Events.h>
// [3] Linux <linux/input.h> and hid-input.c
// [4] USB HID to PS/2 Scan Code Translation Table
@@ -54,6 +54,10 @@
// are distinct from UI Events' "ContextMenu", which corresponds to
// USB 0x070065 [Keyboard Application] via evdev 0x7F KEY_COMPOSE,
// following Windows convention.)
+//
+// [L3] Linux flattens both USB 0x070048 [Keyboard Pause] and 0x0C00B1
+// [Media Pause] to 0x77 KEY_PAUSE. We map the former, since [1]
+// defines a 'Pause' code but no 'MediaPause' code.
// Windows notes:
//
@@ -89,8 +93,7 @@ USB_KEYMAP_DECLARATION {
USB_KEYMAP(0x000010, 0x0000, 0x0000, 0x0000, 0xffff, "Hyper", HYPER),
USB_KEYMAP(0x000011, 0x0000, 0x0000, 0x0000, 0xffff, "Super", SUPER),
USB_KEYMAP(0x000012, 0x0000, 0x0000, 0x0000, 0xffff, "Fn", FN),
- // FLock is named FN_LOCK because F_LOCK conflicts with <fcntl.h>
- USB_KEYMAP(0x000013, 0x0000, 0x0000, 0x0000, 0xffff, "FLock", FN_LOCK),
+ USB_KEYMAP(0x000013, 0x0000, 0x0000, 0x0000, 0xffff, "FnLock", FN_LOCK),
USB_KEYMAP(0x000014, 0x0000, 0x0000, 0x0000, 0xffff, "Suspend", SUSPEND),
USB_KEYMAP(0x000015, 0x0000, 0x0000, 0x0000, 0xffff, "Resume", RESUME),
USB_KEYMAP(0x000016, 0x0000, 0x0000, 0x0000, 0xffff, "Turbo", TURBO),
@@ -453,7 +456,9 @@ USB_KEYMAP_DECLARATION {
// KEY_BRIGHTNESS* added in Linux 3.16
// http://www.usb.org/developers/hidpage/HUTRR41.pdf
- // USB XKB Win Mac
+ // USB evdev XKB Win Mac Code
+ USB_KEYMAP(0x0c0060, 0x0166, 0x016e, 0x0000, 0xffff, NULL, INFO),
+ USB_KEYMAP(0x0c0061, 0x0172, 0x017a, 0x0000, 0xffff, NULL, CLOSED_CAPTION_TOGGLE),
USB_KEYMAP(0x0c006f, 0x00e1, 0x00e9, 0x0000, 0xffff, "BrightnessUp", BRIGHTNESS_UP),
USB_KEYMAP(0x0c0070, 0x00e0, 0x00e8, 0x0000, 0xffff, "BrightnessDown",
BRIGHTNESS_DOWN), // Display Brightness Decrement
@@ -461,14 +466,19 @@ USB_KEYMAP_DECLARATION {
USB_KEYMAP(0x0c0073, 0x0250, 0x0258, 0x0000, 0xffff, NULL, BRIGHTNESS_MINIMIUM),
USB_KEYMAP(0x0c0074, 0x0251, 0x0259, 0x0000, 0xffff, NULL, BRIGHTNESS_MAXIMUM),
USB_KEYMAP(0x0c0075, 0x00f4, 0x00fc, 0x0000, 0xffff, NULL, BRIGHTNESS_AUTO),
+ USB_KEYMAP(0x0c0083, 0x0195, 0x019d, 0x0000, 0xffff, NULL, MEDIA_LAST),
+ USB_KEYMAP(0x0c008c, 0x00a9, 0x00b1, 0x0000, 0xffff, NULL, LAUNCH_PHONE),
+ USB_KEYMAP(0x0c008d, 0x016a, 0x0172, 0x0000, 0xffff, NULL, PROGRAM_GUIDE),
+ USB_KEYMAP(0x0c0094, 0x00ae, 0x00b6, 0x0000, 0xffff, NULL, EXIT),
+ USB_KEYMAP(0x0c009c, 0x019a, 0x01a2, 0x0000, 0xffff, NULL, CHANNEL_UP),
+ USB_KEYMAP(0x0c009d, 0x019b, 0x01a3, 0x0000, 0xffff, NULL, CHANNEL_DOWN),
// USB evdev XKB Win Mac
- //USB_KEYMAP(0x0c00b0, 0x00cf, 0x00d7, 0x????, 0x????, "MediaPlay", MEDIA_PLAY),
- //USB_KEYMAP(0x0c00b1, 0x0077, 0x007f, 0x????, 0x????, "MediaPause", MEDIA_PAUSE),
- //USB_KEYMAP(0x0c00b2, 0x00a7, 0x00af, 0x????, 0x????, "MediaRecord", MEDIA_RECORD),
- //USB_KEYMAP(0x0c00b3, 0x00d0, 0x00d8, 0x????, 0x????, "MediaFastForward",
- // MEDIA_FAST_FORWARD),
- //USB_KEYMAP(0x0c00b4, 0x00a8, 0x00b0, 0x????, 0x????, "MediaRewind", MEDIA_REWIND),
+ USB_KEYMAP(0x0c00b0, 0x00cf, 0x00d7, 0x0000, 0xffff, "MediaPlay", MEDIA_PLAY),
+ //USB_KEYMAP(0x0c00b1, 0x0077, 0x007f, 0x0000, 0xffff, "MediaPause", MEDIA_PAUSE),
+ USB_KEYMAP(0x0c00b2, 0x00a7, 0x00af, 0x0000, 0xffff, "MediaRecord", MEDIA_RECORD),
+ USB_KEYMAP(0x0c00b3, 0x00d0, 0x00d8, 0x0000, 0xffff, "MediaFastForward", MEDIA_FAST_FORWARD),
+ USB_KEYMAP(0x0c00b4, 0x00a8, 0x00b0, 0x0000, 0xffff, "MediaRewind", MEDIA_REWIND),
USB_KEYMAP(0x0c00b5, 0x00a3, 0x00ab, 0xe019, 0xffff, "MediaTrackNext",
MEDIA_TRACK_NEXT),
USB_KEYMAP(0x0c00b6, 0x00a5, 0x00ad, 0xe010, 0xffff, "MediaTrackPrevious",
@@ -477,15 +487,25 @@ USB_KEYMAP_DECLARATION {
USB_KEYMAP(0x0c00b8, 0x00a1, 0x00a9, 0xe02c, 0xffff, "Eject", EJECT),
USB_KEYMAP(0x0c00cd, 0x00a4, 0x00ac, 0xe022, 0xffff, "MediaPlayPause",
MEDIA_PLAY_PAUSE),
- USB_KEYMAP(0x0c00cf, 0x0246, 0x024e, 0x0000, 0xffff, NULL, VOICE_COMMAND),
+ USB_KEYMAP(0x0c00cf, 0x0246, 0x024e, 0x0000, 0xffff, NULL, SPEECH_INPUT_TOGGLE),
+ USB_KEYMAP(0x0c00e5, 0x00d1, 0x00d9, 0x0000, 0xffff, NULL, BASS_BOOST),
+ //USB_KEYMAP(0x0c00e6, 0x0000, 0x0000, 0x0000, 0xffff, NULL, SURROUND_MODE),
+ //USB_KEYMAP(0x0c0150, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_BALANCE_RIGHT),
+ //USB_KEYMAP(0x0c0151, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_BALANCE_LEFT ),
+ //USB_KEYMAP(0x0c0152, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_BASS_INCREMENT),
+ //USB_KEYMAP(0x0c0153, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_BASS_DECREMENT),
+ //USB_KEYMAP(0x0c0154, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_TREBLE_INCREMENT),
+ //USB_KEYMAP(0x0c0155, 0x0000, 0x0000, 0x0000, 0xffff, NULL, AUDIO_TREBLE_DECREMENT),
// USB#0c0183: AL Consumer Control Configuration
USB_KEYMAP(0x0c0183, 0x00ab, 0x00b3, 0xe06d, 0xffff, "MediaSelect", MEDIA_SELECT),
+ USB_KEYMAP(0x0c0184, 0x01a5, 0x01ad, 0x0000, 0xffff, NULL, LAUNCH_WORD_PROCESSOR),
+ USB_KEYMAP(0x0c0186, 0x01a7, 0x01af, 0x0000, 0xffff, NULL, LAUNCH_SPREADSHEET),
// USB#0x0c018a AL_EmailReader
- USB_KEYMAP(0x0c018a, 0x009b, 0x018a, 0xe06c, 0xffff, "LaunchMail", LAUNCH_MAIL),
+ USB_KEYMAP(0x0c018a, 0x009b, 0x00a3, 0xe06c, 0xffff, "LaunchMail", LAUNCH_MAIL),
// USB#0x0c018d: AL Contacts/Address Book
- //USB_KEYMAP(0x0c018d, 0x01ad, 0x01b5, 0x0000, 0xffff, NULL, LAUNCH_CONTACTS),
+ USB_KEYMAP(0x0c018d, 0x01ad, 0x01b5, 0x0000, 0xffff, NULL, LAUNCH_CONTACTS),
// USB#0x0c018e: AL Calendar/Schedule
- //USB_KEYMAP(0x0c018e, 0x018d, 0x0195, 0x0000, 0xffff, NULL, LAUNCH_CALENDAR),
+ USB_KEYMAP(0x0c018e, 0x018d, 0x0195, 0x0000, 0xffff, NULL, LAUNCH_CALENDAR),
// USB#0x0c018f AL Task/Project Manager
//USB_KEYMAP(0x0c018f, 0x0241, 0x0249, 0x0000, 0xffff, NULL, LAUNCH_TASK_MANAGER),
// USB#0x0c0190: AL Log/Journal/Timecard
@@ -494,15 +514,17 @@ USB_KEYMAP_DECLARATION {
USB_KEYMAP(0x0c0192, 0x008c, 0x0094, 0xe021, 0xffff, "LaunchApp2", LAUNCH_APP2),
// USB#0c0194: My Computer (AL_LocalMachineBrowser)
USB_KEYMAP(0x0c0194, 0x0090, 0x0098, 0xe06b, 0xffff, "LaunchApp1", LAUNCH_APP1),
- //USB_KEYMAP(0x0c0196, 0x0096, 0x009e, 0x0000, 0xffff, NULL, LAUNCH_INTERNET_BROWSER),
+ USB_KEYMAP(0x0c0196, 0x0096, 0x009e, 0x0000, 0xffff, NULL, LAUNCH_INTERNET_BROWSER),
+ USB_KEYMAP(0x0c019C, 0x01b1, 0x01b9, 0x0000, 0xffff, NULL, LOG_OFF),
// USB#0x0c019e: AL Terminal Lock/Screensaver
USB_KEYMAP(0x0c019e, 0x0098, 0x00a0, 0x0000, 0xffff, NULL, LOCK_SCREEN),
// USB#0x0c019f AL Control Panel
- //USB_KEYMAP(0x0c019f, 0x0243, 0x024b, 0x0000, 0xffff, NULL, LAUNCH_CONTROL_PANEL),
+ USB_KEYMAP(0x0c019f, 0x0243, 0x024b, 0x0000, 0xffff, NULL, LAUNCH_CONTROL_PANEL),
// USB#0x0c01a2: AL Select Task/Application
USB_KEYMAP(0x0c01a2, 0x0244, 0x024c, 0x0000, 0xffff, "SelectTask", SELECT_TASK),
// USB#0x0c01a7: AL_Documents
USB_KEYMAP(0x0c01a7, 0x00eb, 0x00f3, 0x0000, 0xffff, NULL, LAUNCH_DOCUMENTS),
+ USB_KEYMAP(0x0c01ab, 0x01b0, 0x01b8, 0x0000, 0xffff, NULL, SPELL_CHECK),
// USB#0x0c01ae: AL Keyboard Layout
USB_KEYMAP(0x0c01ae, 0x0176, 0x017e, 0x0000, 0xffff, NULL, LAUNCH_KEYBOARD_LAYOUT),
USB_KEYMAP(0x0c01b1, 0x0245, 0x024d, 0x0000, 0xffff, "LaunchScreenSaver",
@@ -510,9 +532,15 @@ USB_KEYMAP_DECLARATION {
// USB#0c01b4: Home Directory (AL_FileBrowser) (Explorer)
//USB_KEYMAP(0x0c01b4, 0x0000, 0x0000, 0x0000, 0xffff, NULL, LAUNCH_FILE_BROWSER),
// USB#0x0c01b7: AL Audio Browser
- //USB_KEYMAP(0x0c01b7, 0x0188, 0x0190, 0x0000, 0xffff, NULL, LAUNCH_AUDIO_BROWSER),
+ USB_KEYMAP(0x0c01b7, 0x0188, 0x0190, 0x0000, 0xffff, NULL, LAUNCH_AUDIO_BROWSER),
+ // USB#0x0c0201: AC New
+ USB_KEYMAP(0x0c0201, 0x00b5, 0x00bd, 0x0000, 0xffff, NULL, NEW),
+ // USB#0x0c0203: AC Close
+ USB_KEYMAP(0x0c0203, 0x00ce, 0x00d6, 0x0000, 0xffff, NULL, CLOSE),
+ // USB#0x0c0207: AC Close
+ USB_KEYMAP(0x0c0207, 0x00ea, 0x00f2, 0x0000, 0xffff, NULL, SAVE),
// USB#0x0c0208: AC Print
- //USB_KEYMAP(0x0c0208, 0x00d2, 0x00da, 0x0000, 0xffff, NULL, PRINT),
+ USB_KEYMAP(0x0c0208, 0x00d2, 0x00da, 0x0000, 0xffff, NULL, PRINT),
// USB#0x0c0221: AC_Search
USB_KEYMAP(0x0c0221, 0x00d9, 0x00e1, 0xe065, 0xffff, "BrowserSearch", BROWSER_SEARCH),
// USB#0x0c0223: AC_Home
@@ -530,12 +558,16 @@ USB_KEYMAP_DECLARATION {
// USB#0x0c022a: AC_Bookmarks (Favorites)
USB_KEYMAP(0x0c022a, 0x009c, 0x00a4, 0xe066, 0xffff, "BrowserFavorites",
BROWSER_FAVORITES),
+ USB_KEYMAP(0x0c022d, 0x01a2, 0x01aa, 0x0000, 0xffff, NULL, ZOOM_IN),
+ USB_KEYMAP(0x0c022e, 0x01a3, 0x01ab, 0x0000, 0xffff, NULL, ZOOM_OUT),
// USB#0x0c0230: AC Full Screen View
//USB_KEYMAP(0x0c0230, 0x0000, 0x0000, 0x0000, 0xffff, NULL, ZOOM_FULL),
// USB#0x0c0231: AC Normal View
//USB_KEYMAP(0x0c0231, 0x0000, 0x0000, 0x0000, 0xffff, NULL, ZOOM_NORMAL),
// USB#0x0c0232: AC View Toggle
USB_KEYMAP(0x0c0232, 0x0000, 0x0000, 0x0000, 0xffff, "ZoomToggle", ZOOM_TOGGLE),
+ // USB#0x0c0279: AC Redo/Repeat
+ USB_KEYMAP(0x0c0279, 0x00b6, 0x00be, 0x0000, 0xffff, NULL, REDO),
// USB#0x0c0289: AC_Reply
USB_KEYMAP(0x0c0289, 0x00e8, 0x00f0, 0x0000, 0xffff, "MailReply", MAIL_REPLY),
// USB#0x0c028b: AC_ForwardMsg (MailForward)
diff --git a/chromium/ui/events/keycodes/dom/keycode_converter_unittest.cc b/chromium/ui/events/keycodes/dom/keycode_converter_unittest.cc
index 68e2864e1bb..b6bab477ac9 100644
--- a/chromium/ui/events/keycodes/dom/keycode_converter_unittest.cc
+++ b/chromium/ui/events/keycodes/dom/keycode_converter_unittest.cc
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <set>
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,20 +19,93 @@ using ui::KeycodeConverter;
namespace {
-#if defined(OS_WIN)
-const size_t kExpectedMappedKeyCount = 157;
-#elif defined(OS_LINUX) || defined(OS_ANDROID)
-const size_t kExpectedMappedKeyCount = 178;
-#elif defined(OS_MACOSX)
-const size_t kExpectedMappedKeyCount = 118;
-#else
-const size_t kExpectedMappedKeyCount = 0;
-#endif
+// Number of native codes expected to be mapped for each kind of native code.
+// These are in the same order as the columns in keycode_converter_data.inc
+// as reflected in the USB_KEYMAP() macro below.
+const size_t expected_mapped_key_count[] = {
+ 207, // evdev
+ 207, // xkb
+ 157, // windows
+ 118, // mac
+};
+
+const size_t kNativeColumns = arraysize(expected_mapped_key_count);
+
+struct KeycodeConverterData {
+ uint32_t usb_keycode;
+ const char* code;
+ const char* id;
+ int native_keycode[kNativeColumns];
+};
+
+#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) \
+ { usb, code, #id, { evdev, xkb, win, mac } }
+#define USB_KEYMAP_DECLARATION \
+ const KeycodeConverterData kKeycodeConverterData[] =
+#include "ui/events/keycodes/dom/keycode_converter_data.inc"
+#undef USB_KEYMAP
+#undef USB_KEYMAP_DECLARATION
const uint32_t kUsbNonExistentKeycode = 0xffffff;
const uint32_t kUsbUsBackslash = 0x070031;
const uint32_t kUsbNonUsHash = 0x070032;
+TEST(UsbKeycodeMap, KeycodeConverterData) {
+ // This test looks at all kinds of supported native codes.
+ // Verify that there are no duplicate entries in the mapping.
+ std::map<uint32_t, uint16_t> usb_to_native[kNativeColumns];
+ std::map<uint16_t, uint32_t> native_to_usb[kNativeColumns];
+ int invalid_native_keycode[kNativeColumns];
+ for (size_t i = 0; i < kNativeColumns; ++i) {
+ invalid_native_keycode[i] = kKeycodeConverterData[0].native_keycode[i];
+ }
+ for (const auto& it : kKeycodeConverterData) {
+ SCOPED_TRACE(it.id);
+ for (size_t i = 0; i < kNativeColumns; ++i) {
+ if (it.native_keycode[i] == invalid_native_keycode[i])
+ continue;
+ // Verify that the USB or native codes aren't duplicated.
+ EXPECT_EQ(0U, usb_to_native[i].count(it.usb_keycode))
+ << " duplicate of USB code 0x" << std::hex << std::setfill('0')
+ << std::setw(6) << it.usb_keycode
+ << " to native 0x"
+ << std::setw(4) << it.native_keycode[i]
+ << " (previous was 0x"
+ << std::setw(4) << usb_to_native[i][it.usb_keycode]
+ << ")";
+ usb_to_native[i][it.usb_keycode] = it.native_keycode[i];
+ EXPECT_EQ(0U, native_to_usb[i].count(it.native_keycode[i]))
+ << " duplicate of native code 0x" << std::hex << std::setfill('0')
+ << std::setw(4) << it.native_keycode[i]
+ << " to USB 0x"
+ << std::setw(6) << it.usb_keycode
+ << " (previous was 0x"
+ << std::setw(6) << native_to_usb[i][it.native_keycode[i]]
+ << ")";
+ native_to_usb[i][it.native_keycode[i]] = it.usb_keycode;
+ }
+ }
+ // Verify that the number of mapped keys is what we expect, i.e. we haven't
+ // lost any, and if we've added some then the expectation has been updated.
+ for (size_t i = 0; i < kNativeColumns; ++i) {
+ SCOPED_TRACE(i);
+ EXPECT_EQ(expected_mapped_key_count[i], usb_to_native[i].size());
+ }
+}
+
+TEST(UsbKeycodeMap, EvdevXkb) {
+ // XKB codes on a Linux system are 8 plus the corresponding evdev code.
+ // Verify that this relationship holds in the keycode converter data.
+ for (const auto& it : kKeycodeConverterData) {
+ SCOPED_TRACE(it.id);
+ int evdev_code = it.native_keycode[0];
+ int xkb_code = it.native_keycode[1];
+ if (evdev_code || xkb_code) {
+ EXPECT_EQ(xkb_code, evdev_code + 8);
+ }
+ }
+}
+
TEST(UsbKeycodeMap, Basic) {
// Verify that the first element in the table is the "invalid" code.
const ui::KeycodeMapEntry* keycode_map =
@@ -43,9 +117,6 @@ TEST(UsbKeycodeMap, Basic) {
EXPECT_EQ(ui::KeycodeConverter::InvalidNativeKeycode(),
ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::NONE));
- // Verify that there are no duplicate entries in the mapping.
- std::map<uint32_t, uint16_t> usb_to_native;
- std::map<uint16_t, uint32_t> native_to_usb;
size_t numEntries = ui::KeycodeConverter::NumKeycodeMapEntriesForTest();
for (size_t i = 0; i < numEntries; ++i) {
const ui::KeycodeMapEntry* entry = &keycode_map[i];
@@ -65,32 +136,7 @@ TEST(UsbKeycodeMap, Basic) {
EXPECT_EQ(entry->native_keycode,
ui::KeycodeConverter::DomCodeToNativeKeycode(dom_code));
}
-
- // Verify that the USB or native codes aren't duplicated.
- EXPECT_EQ(0U, usb_to_native.count(entry->usb_keycode))
- << " duplicate of USB code 0x" << std::hex << std::setfill('0')
- << std::setw(6) << entry->usb_keycode
- << " to native 0x"
- << std::setw(4) << entry->native_keycode
- << " (previous was 0x"
- << std::setw(4) << usb_to_native[entry->usb_keycode]
- << ")";
- usb_to_native[entry->usb_keycode] = entry->native_keycode;
- EXPECT_EQ(0U, native_to_usb.count(entry->native_keycode))
- << " duplicate of native code 0x" << std::hex << std::setfill('0')
- << std::setw(4) << entry->native_keycode
- << " to USB 0x"
- << std::setw(6) << entry->usb_keycode
- << " (previous was 0x"
- << std::setw(6) << native_to_usb[entry->native_keycode]
- << ")";
- native_to_usb[entry->native_keycode] = entry->usb_keycode;
}
- ASSERT_EQ(usb_to_native.size(), native_to_usb.size());
-
- // Verify that the number of mapped keys is what we expect, i.e. we haven't
- // lost any, and if we've added some then the expectation has been updated.
- EXPECT_EQ(kExpectedMappedKeyCount, usb_to_native.size());
}
TEST(UsbKeycodeMap, NonExistent) {
@@ -180,7 +226,9 @@ TEST(KeycodeConverter, DomKey) {
EXPECT_STREQ(test.string, s.c_str());
}
}
- // Round-trip test all UI Events KeyboardEvent.key strings.
+ // Round-trip test all UI Events KeyboardEvent.key strings, and check
+ // that encodings are distinct.
+ std::set<ui::DomKey::Base> keys;
const char* s = nullptr;
for (size_t i = 0;
(s = ui::KeycodeConverter::DomKeyStringForTest(i)) != nullptr; ++i) {
@@ -188,6 +236,11 @@ TEST(KeycodeConverter, DomKey) {
ui::DomKey key = ui::KeycodeConverter::KeyStringToDomKey(s);
if (s) {
EXPECT_STREQ(s, ui::KeycodeConverter::DomKeyToKeyString(key).c_str());
+ if (keys.count(key) == 0) {
+ keys.insert(key);
+ } else {
+ ADD_FAILURE() << "duplicate encoding:" << key;
+ }
} else {
EXPECT_EQ(ui::DomKey::NONE, key);
}
diff --git a/chromium/ui/events/keycodes/dom_us_layout_data.h b/chromium/ui/events/keycodes/dom_us_layout_data.h
index 3ed0d241ddd..b0e2646ad9b 100644
--- a/chromium/ui/events/keycodes/dom_us_layout_data.h
+++ b/chromium/ui/events/keycodes/dom_us_layout_data.h
@@ -105,6 +105,7 @@ const struct NonPrintableCodeEntry {
{DomCode::ARROW_RIGHT, DomKey::ARROW_RIGHT},
{DomCode::ARROW_UP, DomKey::ARROW_UP},
{DomCode::BACKSPACE, DomKey::BACKSPACE},
+ {DomCode::BASS_BOOST, DomKey::AUDIO_BASS_BOOST_TOGGLE},
{DomCode::BRIGHTNESS_DOWN, DomKey::BRIGHTNESS_DOWN},
{DomCode::BRIGHTNESS_UP, DomKey::BRIGHTNESS_UP},
// {DomCode::BRIGHTNESS_AUTO, DomKey::_}
@@ -119,6 +120,10 @@ const struct NonPrintableCodeEntry {
{DomCode::BROWSER_SEARCH, DomKey::BROWSER_SEARCH},
{DomCode::BROWSER_STOP, DomKey::BROWSER_STOP},
{DomCode::CAPS_LOCK, DomKey::CAPS_LOCK},
+ {DomCode::CHANNEL_DOWN, DomKey::CHANNEL_DOWN},
+ {DomCode::CHANNEL_UP, DomKey::CHANNEL_UP},
+ {DomCode::CLOSE, DomKey::CLOSE},
+ {DomCode::CLOSED_CAPTION_TOGGLE, DomKey::CLOSED_CAPTION_TOGGLE},
{DomCode::CONTEXT_MENU, DomKey::CONTEXT_MENU},
{DomCode::CONTROL_LEFT, DomKey::CONTROL},
{DomCode::CONTROL_RIGHT, DomKey::CONTROL},
@@ -130,6 +135,7 @@ const struct NonPrintableCodeEntry {
{DomCode::END, DomKey::END},
{DomCode::ENTER, DomKey::ENTER},
{DomCode::ESCAPE, DomKey::ESCAPE},
+ {DomCode::EXIT, DomKey::EXIT},
{DomCode::F1, DomKey::F1},
{DomCode::F2, DomKey::F2},
{DomCode::F3, DomKey::F3},
@@ -160,6 +166,7 @@ const struct NonPrintableCodeEntry {
{DomCode::HELP, DomKey::HELP},
{DomCode::HOME, DomKey::HOME},
{DomCode::HYPER, DomKey::HYPER},
+ {DomCode::INFO, DomKey::INFO},
{DomCode::INSERT, DomKey::INSERT},
// {DomCode::INTL_RO, DomKey::_}
{DomCode::KANA_MODE, DomKey::KANA_MODE},
@@ -170,21 +177,36 @@ const struct NonPrintableCodeEntry {
{DomCode::LANG5, DomKey::ZENKAKU_HANKAKU},
{DomCode::LAUNCH_APP1, DomKey::LAUNCH_MY_COMPUTER},
{DomCode::LAUNCH_APP2, DomKey::LAUNCH_CALCULATOR},
+ {DomCode::LAUNCH_AUDIO_BROWSER, DomKey::LAUNCH_MUSIC_PLAYER},
+ {DomCode::LAUNCH_CALENDAR, DomKey::LAUNCH_CALENDAR},
+ {DomCode::LAUNCH_CONTACTS, DomKey::LAUNCH_CONTACTS},
+ {DomCode::LAUNCH_CONTROL_PANEL, DomKey::SETTINGS},
+ {DomCode::LAUNCH_INTERNET_BROWSER, DomKey::LAUNCH_WEB_BROWSER},
{DomCode::LAUNCH_MAIL, DomKey::LAUNCH_MAIL},
+ {DomCode::LAUNCH_PHONE, DomKey::LAUNCH_PHONE},
{DomCode::LAUNCH_SCREEN_SAVER, DomKey::LAUNCH_SCREEN_SAVER},
+ {DomCode::LAUNCH_SPREADSHEET, DomKey::LAUNCH_SPREADSHEET},
// {DomCode::LAUNCH_DOCUMENTS, DomKey::_}
// {DomCode::LAUNCH_FILE_BROWSER, DomKey::_}
// {DomCode::LAUNCH_KEYBOARD_LAYOUT, DomKey::_}
{DomCode::LOCK_SCREEN, DomKey::LAUNCH_SCREEN_SAVER},
+ {DomCode::LOG_OFF, DomKey::LOG_OFF},
{DomCode::MAIL_FORWARD, DomKey::MAIL_FORWARD},
{DomCode::MAIL_REPLY, DomKey::MAIL_REPLY},
{DomCode::MAIL_SEND, DomKey::MAIL_SEND},
+ {DomCode::MEDIA_FAST_FORWARD, DomKey::MEDIA_FAST_FORWARD},
+ {DomCode::MEDIA_LAST, DomKey::MEDIA_LAST},
+ // {DomCode::MEDIA_PAUSE, DomKey::MEDIA_PAUSE},
+ {DomCode::MEDIA_PLAY, DomKey::MEDIA_PLAY},
{DomCode::MEDIA_PLAY_PAUSE, DomKey::MEDIA_PLAY_PAUSE},
- {DomCode::MEDIA_SELECT, DomKey::MEDIA_SELECT},
+ {DomCode::MEDIA_RECORD, DomKey::MEDIA_RECORD},
+ {DomCode::MEDIA_REWIND, DomKey::MEDIA_REWIND},
+ {DomCode::MEDIA_SELECT, DomKey::LAUNCH_MEDIA_PLAYER},
{DomCode::MEDIA_STOP, DomKey::MEDIA_STOP},
{DomCode::MEDIA_TRACK_NEXT, DomKey::MEDIA_TRACK_NEXT},
{DomCode::MEDIA_TRACK_PREVIOUS, DomKey::MEDIA_TRACK_PREVIOUS},
// {DomCode::MENU, DomKey::_}
+ {DomCode::NEW, DomKey::NEW},
{DomCode::NON_CONVERT, DomKey::NON_CONVERT},
{DomCode::NUM_LOCK, DomKey::NUM_LOCK},
{DomCode::NUMPAD_BACKSPACE, DomKey::BACKSPACE},
@@ -197,28 +219,35 @@ const struct NonPrintableCodeEntry {
// {DomCode::NUMPAD_MEMORY_STORE, DomKey::_}
// {DomCode::NUMPAD_MEMORY_SUBTRACT, DomKey::_}
{DomCode::OPEN, DomKey::OPEN},
- {DomCode::OS_LEFT, DomKey::OS},
- {DomCode::OS_RIGHT, DomKey::OS},
+ {DomCode::OS_LEFT, DomKey::META},
+ {DomCode::OS_RIGHT, DomKey::META},
{DomCode::PAGE_DOWN, DomKey::PAGE_DOWN},
{DomCode::PAGE_UP, DomKey::PAGE_UP},
{DomCode::PASTE, DomKey::PASTE},
{DomCode::PAUSE, DomKey::PAUSE},
{DomCode::POWER, DomKey::POWER},
+ {DomCode::PRINT, DomKey::PRINT},
{DomCode::PRINT_SCREEN, DomKey::PRINT_SCREEN},
+ {DomCode::PROGRAM_GUIDE, DomKey::GUIDE},
{DomCode::PROPS, DomKey::PROPS},
+ {DomCode::REDO, DomKey::REDO},
+ {DomCode::SAVE, DomKey::SAVE},
{DomCode::SCROLL_LOCK, DomKey::SCROLL_LOCK},
{DomCode::SELECT, DomKey::SELECT},
- // {DomCode::SELECT_TASK, DomKey::_}
+ {DomCode::SELECT_TASK, DomKey::APP_SWITCH},
{DomCode::SHIFT_LEFT, DomKey::SHIFT},
{DomCode::SHIFT_RIGHT, DomKey::SHIFT},
+ {DomCode::SPEECH_INPUT_TOGGLE, DomKey::SPEECH_INPUT_TOGGLE},
+ {DomCode::SPELL_CHECK, DomKey::SPELL_CHECK},
{DomCode::SUPER, DomKey::SUPER},
{DomCode::TAB, DomKey::TAB},
{DomCode::UNDO, DomKey::UNDO},
- // {DomCode::VOICE_COMMAND, DomKey::_}
- {DomCode::VOLUME_DOWN, DomKey::VOLUME_DOWN},
- {DomCode::VOLUME_MUTE, DomKey::VOLUME_MUTE},
- {DomCode::VOLUME_UP, DomKey::VOLUME_UP},
+ {DomCode::VOLUME_DOWN, DomKey::AUDIO_VOLUME_DOWN},
+ {DomCode::VOLUME_MUTE, DomKey::AUDIO_VOLUME_MUTE},
+ {DomCode::VOLUME_UP, DomKey::AUDIO_VOLUME_UP},
{DomCode::WAKE_UP, DomKey::WAKE_UP},
+ {DomCode::ZOOM_IN, DomKey::ZOOM_IN},
+ {DomCode::ZOOM_OUT, DomKey::ZOOM_OUT},
{DomCode::ZOOM_TOGGLE, DomKey::ZOOM_TOGGLE},
};
@@ -239,13 +268,12 @@ const struct DomKeyToKeyboardCodeEntry {
{DomKey::CAPS_LOCK, VKEY_CAPITAL},
{DomKey::CONTROL, VKEY_CONTROL},
{DomKey::NUM_LOCK, VKEY_NUMLOCK},
- {DomKey::OS, VKEY_LWIN},
+ {DomKey::META, VKEY_LWIN},
{DomKey::SCROLL_LOCK, VKEY_SCROLL},
{DomKey::SHIFT, VKEY_SHIFT},
// Whitespace Keys
// http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-whitespace
{DomKey::ENTER, VKEY_RETURN},
- {DomKey::SEPARATOR, VKEY_SEPARATOR},
{DomKey::TAB, VKEY_TAB},
// Navigation Keys
// http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-navigation
@@ -334,18 +362,18 @@ const struct DomKeyToKeyboardCodeEntry {
// Multimedia Keys
// http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-multimedia
{DomKey::MEDIA_PLAY_PAUSE, VKEY_MEDIA_PLAY_PAUSE},
- {DomKey::MEDIA_SELECT, VKEY_MEDIA_LAUNCH_MEDIA_SELECT},
{DomKey::MEDIA_STOP, VKEY_MEDIA_STOP},
{DomKey::MEDIA_TRACK_NEXT, VKEY_MEDIA_NEXT_TRACK},
{DomKey::MEDIA_TRACK_PREVIOUS, VKEY_MEDIA_PREV_TRACK},
{DomKey::PRINT, VKEY_PRINT},
- {DomKey::VOLUME_DOWN, VKEY_VOLUME_DOWN},
- {DomKey::VOLUME_MUTE, VKEY_VOLUME_MUTE},
- {DomKey::VOLUME_UP, VKEY_VOLUME_UP},
+ {DomKey::AUDIO_VOLUME_DOWN, VKEY_VOLUME_DOWN},
+ {DomKey::AUDIO_VOLUME_MUTE, VKEY_VOLUME_MUTE},
+ {DomKey::AUDIO_VOLUME_UP, VKEY_VOLUME_UP},
// Application Keys
// http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-apps
{DomKey::LAUNCH_CALCULATOR, VKEY_MEDIA_LAUNCH_APP2},
{DomKey::LAUNCH_MAIL, VKEY_MEDIA_LAUNCH_MAIL},
+ {DomKey::LAUNCH_MEDIA_PLAYER, VKEY_MEDIA_LAUNCH_MEDIA_SELECT},
{DomKey::LAUNCH_MY_COMPUTER, VKEY_MEDIA_LAUNCH_APP1},
// Browser Keys
// http://www.w3.org/TR/DOM-Level-3-Events-key/#keys-browser
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc
index e176a2bfe48..92a9f52124e 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_android.cc
@@ -75,9 +75,9 @@ DomKey GetDomKeyFromAndroidKeycode(int keycode) {
case AKEYCODE_DPAD_RIGHT:
return DomKey::ARROW_RIGHT;
case AKEYCODE_VOLUME_UP:
- return DomKey::VOLUME_UP;
+ return DomKey::AUDIO_VOLUME_UP;
case AKEYCODE_VOLUME_DOWN:
- return DomKey::VOLUME_DOWN;
+ return DomKey::AUDIO_VOLUME_DOWN;
case AKEYCODE_POWER:
return DomKey::POWER;
case AKEYCODE_CAMERA:
@@ -119,7 +119,7 @@ DomKey GetDomKeyFromAndroidKeycode(int keycode) {
case AKEYCODE_MEDIA_FAST_FORWARD:
return DomKey::MEDIA_FAST_FORWARD;
case AKEYCODE_MUTE:
- return DomKey::VOLUME_MUTE;
+ return DomKey::AUDIO_VOLUME_MUTE;
case AKEYCODE_PAGE_UP:
return DomKey::PAGE_UP;
case AKEYCODE_PAGE_DOWN:
@@ -189,7 +189,7 @@ DomKey GetDomKeyFromAndroidKeycode(int keycode) {
case AKEYCODE_NUM_LOCK:
return DomKey::NUM_LOCK;
case AKEYCODE_VOLUME_MUTE:
- return DomKey::VOLUME_MUTE;
+ return DomKey::AUDIO_VOLUME_MUTE;
case AKEYCODE_INFO:
return DomKey::INFO;
case AKEYCODE_CHANNEL_UP:
@@ -201,7 +201,7 @@ DomKey GetDomKeyFromAndroidKeycode(int keycode) {
case AKEYCODE_ZOOM_OUT:
return DomKey::ZOOM_OUT;
case AKEYCODE_TV:
- return DomKey::T_V;
+ return DomKey::TV;
case AKEYCODE_GUIDE:
return DomKey::GUIDE;
case AKEYCODE_CAPTIONS:
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
index f435f4ed2b9..8aae1d92eb4 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -9,6 +9,8 @@
#import <Carbon/Carbon.h>
#include "base/logging.h"
+#include "base/mac/mac_logging.h"
+#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -16,6 +18,9 @@ namespace ui {
namespace {
+// This value is not defined but shows up as 0x36.
+const int kVK_RightCommand = 0x36;
+
// A struct to hold a Windows keycode to Mac virtual keycode mapping.
struct KeyCodeMap {
KeyboardCode keycode;
@@ -106,8 +111,8 @@ const KeyCodeMap kKeyCodesMap[] = {
{ VKEY_Y /* 0x59 */, kVK_ANSI_Y, 'y' },
{ VKEY_Z /* 0x5A */, kVK_ANSI_Z, 'z' },
{ VKEY_LWIN /* 0x5B */, kVK_Command, 0 },
- { VKEY_RWIN /* 0x5C */, 0x36, 0 },
- { VKEY_APPS /* 0x5D */, 0x36, 0 },
+ { VKEY_RWIN /* 0x5C */, kVK_RightCommand, 0 },
+ { VKEY_APPS /* 0x5D */, kVK_RightCommand, 0 },
{ VKEY_SLEEP /* 0x5F */, -1, 0 },
{ VKEY_NUMPAD0 /* 0x60 */, kVK_ANSI_Keypad0, '0' },
{ VKEY_NUMPAD1 /* 0x61 */, kVK_ANSI_Keypad1, '1' },
@@ -439,6 +444,7 @@ KeyboardCode KeyboardCodeFromKeyCode(unsigned short keyCode) {
DomKey DomKeyFromKeyCode(unsigned short keyCode) {
switch (keyCode) {
+ case kVK_ANSI_KeypadEnter:
case kVK_Return:
return DomKey::ENTER;
case kVK_Tab:
@@ -448,6 +454,7 @@ DomKey DomKeyFromKeyCode(unsigned short keyCode) {
case kVK_Escape:
return DomKey::ESCAPE;
case kVK_Command:
+ case kVK_RightCommand:
return DomKey::META;
case kVK_Shift:
case kVK_RightShift:
@@ -463,11 +470,11 @@ DomKey DomKeyFromKeyCode(unsigned short keyCode) {
case kVK_Function:
return DomKey::FN;
case kVK_VolumeUp:
- return DomKey::VOLUME_UP;
+ return DomKey::AUDIO_VOLUME_UP;
case kVK_VolumeDown:
- return DomKey::VOLUME_DOWN;
+ return DomKey::AUDIO_VOLUME_DOWN;
case kVK_Mute:
- return DomKey::VOLUME_MUTE;
+ return DomKey::AUDIO_VOLUME_MUTE;
case kVK_F1:
return DomKey::F1;
case kVK_F2:
@@ -535,11 +542,6 @@ DomKey DomKeyFromKeyCode(unsigned short keyCode) {
DomKey DomKeyFromCharCode(unichar char_code) {
switch (char_code) {
- case 0x03:
- return DomKey::ENTER; // Numpad Enter
- // Mac maps backspace to forward delete unicode.
- case 0x7f:
- return DomKey::BACKSPACE;
case NSUpArrowFunctionKey:
return DomKey::ARROW_UP;
case NSDownArrowFunctionKey:
@@ -635,6 +637,56 @@ DomKey DomKeyFromCharCode(unichar char_code) {
}
}
+UniChar MacKeycodeAndModifiersToCharacter(unsigned short mac_keycode,
+ int modifiers,
+ bool* is_dead_key) {
+ // Convert NSEvent modifiers to format UCKeyTranslate accepts. See docs
+ // on UCKeyTranslate for more info.
+ int unicode_modifiers = 0;
+ if (modifiers & NSShiftKeyMask)
+ unicode_modifiers |= shiftKey;
+ if (modifiers & NSAlphaShiftKeyMask)
+ unicode_modifiers |= alphaLock;
+ // if (modifiers & NSControlKeyMask)
+ // unicode_modifiers |= controlKey;
+ if (modifiers & NSAlternateKeyMask)
+ unicode_modifiers |= optionKey;
+ // if (modifiers & NSCommandKeyMask)
+ // unicode_modifiers |= cmdKey;
+ UInt32 modifier_key_state = (unicode_modifiers >> 8) & 0xFF;
+
+ base::ScopedCFTypeRef<TISInputSourceRef> input_source_copy(
+ TISCopyCurrentKeyboardLayoutInputSource());
+ CFDataRef layout_data = static_cast<CFDataRef>(TISGetInputSourceProperty(
+ input_source_copy, kTISPropertyUnicodeKeyLayoutData));
+ const UCKeyboardLayout* layout =
+ reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data));
+
+ UInt32 dead_key_state = 0;
+ UniCharCount char_count = 0;
+ // According Apple's doc UCKeyTranslate::maxStringLength maybe up to 255 but
+ // would actually be rare to get more than 4.
+ UniChar unicode_string[4];
+ OSStatus status =
+ UCKeyTranslate(layout, static_cast<UInt16>(mac_keycode), kUCKeyActionDown,
+ modifier_key_state, LMGetKbdLast(), 0, &dead_key_state,
+ arraysize(unicode_string), &char_count, unicode_string);
+
+ OSSTATUS_DCHECK(status == noErr, status);
+ *is_dead_key = dead_key_state != 0;
+ if (*is_dead_key) {
+ // A dead key, injecting space to get the diacritic in an isolated form.
+ status = UCKeyTranslate(layout, static_cast<UInt16>(kVK_Space),
+ kUCKeyActionDown, 0, LMGetKbdLast(), 0,
+ &dead_key_state, arraysize(unicode_string),
+ &char_count, unicode_string);
+ OSSTATUS_DCHECK(status == noErr, status);
+ }
+
+ // TODO(chongz): Handle multiple character case. Should be rare.
+ return unicode_string[0];
+}
+
} // namespace
int MacKeyCodeForWindowsKeyCode(KeyboardCode keycode,
@@ -742,12 +794,49 @@ DomCode DomCodeFromNSEvent(NSEvent* event) {
DomKey DomKeyFromNSEvent(NSEvent* event) {
// Apply the lookup based on the character first since that has the
- // Keyboard layout and modifers already applied; whereas the keyCode
+ // Keyboard layout and modifiers already applied; whereas the keyCode
// doesn't.
if ([event type] == NSKeyDown || [event type] == NSKeyUp) {
+ // Cannot use [event characters] to check whether it's a dead key, because
+ // KeyUp event has the character form of the dead key in [event characters].
+ bool is_dead_key = false;
+ // MacKeycodeAndModifiersToCharacter() is efficient (around 6E-4 ms).
+ unichar dead_dom_key_char = MacKeycodeAndModifiersToCharacter(
+ [event keyCode], [event modifierFlags], &is_dead_key);
+ if (is_dead_key)
+ return DomKey::DeadKeyFromCombiningCharacter(dead_dom_key_char);
+
+ // [event characters] will have dead key state applied.
NSString* characters = [event characters];
- if ([characters length] > 0)
- return DomKeyFromCharCode([characters characterAtIndex:0]);
+ if ([characters length] > 0) {
+ // An invalid dead key combination will produce two characters, according
+ // to spec DomKey should be the last character.
+ // e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'.
+ unichar dom_key_char =
+ [characters characterAtIndex:[characters length] - 1];
+ const bool is_ctrl_down = ([event modifierFlags] & NSControlKeyMask) &&
+ !([event modifierFlags] & NSAlternateKeyMask);
+ const bool is_command_down = [event modifierFlags] & NSCommandKeyMask;
+ // On Mac Blink won't insert ASCII character if either Ctrl or Command, or
+ // both, are down.
+ // See EditingBehavior::shouldInsertCharacter()
+ if (std::iscntrl(dom_key_char) ||
+ (dom_key_char < 0x80 && (is_ctrl_down || is_command_down))) {
+ // According to spec if the key combination produces a non-printable
+ // character, the key value should be the character without modifiers
+ // except Shift and AltGr.
+ // See https://w3c.github.io/uievents/#keys-guidelines
+ bool unused_is_dead_key;
+ const int kAllowedModifiersMask =
+ NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
+ // MacKeycodeAndModifiersToCharacter() is efficient (around 6E-4 ms).
+ dom_key_char = MacKeycodeAndModifiersToCharacter(
+ [event keyCode], [event modifierFlags] & kAllowedModifiersMask,
+ &unused_is_dead_key);
+ }
+ if (!std::iscntrl(dom_key_char))
+ return DomKeyFromCharCode(dom_key_char);
+ }
}
return DomKeyFromKeyCode([event keyCode]);
}
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_unittest.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_unittest.cc
index dab5faca4cf..92540fa1611 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_unittest.cc
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_unittest.cc
@@ -246,11 +246,11 @@ TEST(KeyboardCodeConversion, ControlCharacters) {
{true, ui::DomKey::ALT, ui::VKEY_MENU},
{true, ui::DomKey::ALT, ui::VKEY_MENU}},
{ui::DomCode::OS_LEFT,
- {true, ui::DomKey::OS, ui::VKEY_LWIN},
- {true, ui::DomKey::OS, ui::VKEY_LWIN}},
+ {true, ui::DomKey::META, ui::VKEY_LWIN},
+ {true, ui::DomKey::META, ui::VKEY_LWIN}},
{ui::DomCode::OS_RIGHT,
- {true, ui::DomKey::OS, ui::VKEY_LWIN},
- {true, ui::DomKey::OS, ui::VKEY_LWIN}},
+ {true, ui::DomKey::META, ui::VKEY_LWIN},
+ {true, ui::DomKey::META, ui::VKEY_LWIN}},
{ui::DomCode::DIGIT1,
{true, ui::DomKey::Constant<'1'>::Character, ui::VKEY_1},
{true, ui::DomKey::Constant<'!'>::Character, ui::VKEY_1}},
@@ -264,8 +264,8 @@ TEST(KeyboardCodeConversion, ControlCharacters) {
{true, ui::DomKey::F1, ui::VKEY_F1},
{true, ui::DomKey::F1, ui::VKEY_F1}},
{ui::DomCode::VOLUME_UP,
- {true, ui::DomKey::VOLUME_UP, ui::VKEY_VOLUME_UP},
- {true, ui::DomKey::VOLUME_UP, ui::VKEY_VOLUME_UP}},
+ {true, ui::DomKey::AUDIO_VOLUME_UP, ui::VKEY_VOLUME_UP},
+ {true, ui::DomKey::AUDIO_VOLUME_UP, ui::VKEY_VOLUME_UP}},
};
for (const auto& it : kNonControlCharacters) {
// Verify |DomCodeToControlCharacter()|.
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc
index a0bc96ab45d..e6817e18a40 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_xkb.cc
@@ -214,7 +214,7 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym) {
#endif // defined(OS_CHROMEOS)
case XKB_KEY_Super_L:
case XKB_KEY_Super_R:
- return DomKey::OS;
+ return DomKey::META;
case XKB_KEY_Hyper_L:
case XKB_KEY_Hyper_R:
return DomKey::HYPER;
@@ -233,11 +233,11 @@ DomKey NonPrintableXKeySymToDomKey(xkb_keysym_t keysym) {
case XKB_KEY_XF86Suspend:
return DomKey::STANDBY;
case XKB_KEY_XF86AudioLowerVolume:
- return DomKey::VOLUME_DOWN;
+ return DomKey::AUDIO_VOLUME_DOWN;
case XKB_KEY_XF86AudioMute:
- return DomKey::VOLUME_MUTE;
+ return DomKey::AUDIO_VOLUME_MUTE;
case XKB_KEY_XF86AudioRaiseVolume:
- return DomKey::VOLUME_UP;
+ return DomKey::AUDIO_VOLUME_UP;
case XKB_KEY_XF86AudioPlay:
return DomKey::MEDIA_PLAY;
case XKB_KEY_XF86AudioStop:
diff --git a/chromium/ui/events/keycodes/platform_key_map_win.cc b/chromium/ui/events/keycodes/platform_key_map_win.cc
new file mode 100644
index 00000000000..e6760c8944f
--- /dev/null
+++ b/chromium/ui/events/keycodes/platform_key_map_win.cc
@@ -0,0 +1,281 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/keycodes/platform_key_map_win.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/threading/thread_local_storage.h"
+
+#include "ui/events/event_constants.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+
+namespace ui {
+
+namespace {
+
+struct DomCodeEntry {
+ DomCode dom_code;
+ int scan_code;
+};
+#define USB_KEYMAP_DECLARATION const DomCodeEntry supported_dom_code_list[] =
+#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) {DomCode::id, win}
+#include "ui/events/keycodes/dom/keycode_converter_data.inc"
+#undef USB_KEYMAP
+#undef USB_KEYMAP_DECLARATION
+
+// List of modifiers mentioned in https://w3c.github.io/uievents/#keys-modifiers
+// Some modifiers are commented out because they usually don't change keys.
+const EventFlags modifier_flags[] = {
+ EF_SHIFT_DOWN,
+ EF_CONTROL_DOWN,
+ EF_ALT_DOWN,
+ // EF_COMMAND_DOWN,
+ EF_ALTGR_DOWN,
+ // EF_NUM_LOCK_ON,
+ EF_CAPS_LOCK_ON,
+ // EF_SCROLL_LOCK_ON
+};
+const int kModifierFlagsCombinations = (1 << arraysize(modifier_flags)) - 1;
+
+int GetModifierFlags(int combination) {
+ int flags = EF_NONE;
+ for (size_t i = 0; i < arraysize(modifier_flags); ++i) {
+ if (combination & (1 << i))
+ flags |= modifier_flags[i];
+ }
+ return flags;
+}
+
+void SetModifierState(BYTE* keyboard_state, int flags) {
+ // According to MSDN GetKeyState():
+ // 1. If the high-order bit is 1, the key is down; otherwise, it is up.
+ // 2. If the low-order bit is 1, the key is toggled. A key, such as the
+ // CAPS LOCK key, is toggled if it is turned on. The key is off and
+ // untoggled if the low-order bit is 0.
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301.aspx
+ if (flags & EF_SHIFT_DOWN)
+ keyboard_state[VK_SHIFT] |= 0x80;
+
+ if (flags & EF_CONTROL_DOWN)
+ keyboard_state[VK_CONTROL] |= 0x80;
+
+ if (flags & EF_ALT_DOWN)
+ keyboard_state[VK_MENU] |= 0x80;
+
+ if (flags & EF_ALTGR_DOWN) {
+ // AltGr should be RightAlt+LeftControl within Windows, but actually only
+ // the non-located keys will work here.
+ keyboard_state[VK_MENU] |= 0x80;
+ keyboard_state[VK_CONTROL] |= 0x80;
+ }
+
+ if (flags & EF_COMMAND_DOWN)
+ keyboard_state[VK_LWIN] |= 0x80;
+
+ if (flags & EF_NUM_LOCK_ON)
+ keyboard_state[VK_NUMLOCK] |= 0x01;
+
+ if (flags & EF_CAPS_LOCK_ON)
+ keyboard_state[VK_CAPITAL] |= 0x01;
+
+ if (flags & EF_SCROLL_LOCK_ON)
+ keyboard_state[VK_SCROLL] |= 0x01;
+}
+
+DomKey NumPadKeyCodeToDomKey(KeyboardCode key_code) {
+ switch (key_code) {
+ case VKEY_NUMPAD0:
+ return DomKey::Constant<'0'>::Character;
+ case VKEY_NUMPAD1:
+ return DomKey::Constant<'1'>::Character;
+ case VKEY_NUMPAD2:
+ return DomKey::Constant<'2'>::Character;
+ case VKEY_NUMPAD3:
+ return DomKey::Constant<'3'>::Character;
+ case VKEY_NUMPAD4:
+ return DomKey::Constant<'4'>::Character;
+ case VKEY_NUMPAD5:
+ return DomKey::Constant<'5'>::Character;
+ case VKEY_NUMPAD6:
+ return DomKey::Constant<'6'>::Character;
+ case VKEY_NUMPAD7:
+ return DomKey::Constant<'7'>::Character;
+ case VKEY_NUMPAD8:
+ return DomKey::Constant<'8'>::Character;
+ case VKEY_NUMPAD9:
+ return DomKey::Constant<'9'>::Character;
+ case VKEY_CLEAR:
+ return DomKey::CLEAR;
+ case VKEY_PRIOR:
+ return DomKey::PAGE_UP;
+ case VKEY_NEXT:
+ return DomKey::PAGE_DOWN;
+ case VKEY_END:
+ return DomKey::END;
+ case VKEY_HOME:
+ return DomKey::HOME;
+ case VKEY_LEFT:
+ return DomKey::ARROW_LEFT;
+ case VKEY_UP:
+ return DomKey::ARROW_UP;
+ case VKEY_RIGHT:
+ return DomKey::ARROW_RIGHT;
+ case VKEY_DOWN:
+ return DomKey::ARROW_DOWN;
+ case VKEY_INSERT:
+ return DomKey::INSERT;
+ case VKEY_DELETE:
+ return DomKey::DEL;
+ default:
+ return DomKey::NONE;
+ }
+}
+
+void CleanupKeyMapTls(void* data) {
+ PlatformKeyMap* key_map = reinterpret_cast<PlatformKeyMap*>(data);
+ delete key_map;
+}
+
+struct PlatformKeyMapInstanceTlsTraits
+ : public base::DefaultLazyInstanceTraits<base::ThreadLocalStorage::Slot> {
+ static base::ThreadLocalStorage::Slot* New(void* instance) {
+ // Use placement new to initialize our instance in our preallocated space.
+ // TODO(chongz): Use std::default_delete instead of providing own function.
+ return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls);
+ }
+};
+
+base::LazyInstance<base::ThreadLocalStorage::Slot,
+ PlatformKeyMapInstanceTlsTraits>
+ g_platform_key_map_tls_lazy = LAZY_INSTANCE_INITIALIZER;
+
+} // anonymous namespace
+
+PlatformKeyMap::PlatformKeyMap() {}
+
+PlatformKeyMap::PlatformKeyMap(HKL layout) {
+ UpdateLayout(layout);
+}
+
+PlatformKeyMap::~PlatformKeyMap() {}
+
+DomKey PlatformKeyMap::DomKeyFromNativeImpl(DomCode code,
+ KeyboardCode key_code,
+ int flags) const {
+ if (KeycodeConverter::DomCodeToLocation(code) == DomKeyLocation::NUMPAD) {
+ // Derived the DOM Key value from |key_code| instead of |code|, to address
+ // Windows Numlock/Shift interaction - see crbug.com/594552.
+ return NumPadKeyCodeToDomKey(key_code);
+ }
+
+ const int flags_to_try[] = {
+ // Trying to match Firefox's behavior and UIEvents DomKey guidelines.
+ // If the combination doesn't produce a printable character, the key value
+ // should be the key with no modifiers except for Shift and AltGr.
+ // See https://w3c.github.io/uievents/#keys-guidelines
+ flags,
+ flags & (EF_SHIFT_DOWN | EF_ALTGR_DOWN | EF_CAPS_LOCK_ON),
+ flags & (EF_SHIFT_DOWN | EF_CAPS_LOCK_ON),
+ EF_NONE,
+ };
+
+ DomKey key = DomKey::NONE;
+ for (auto try_flags : flags_to_try) {
+ const auto& it = code_to_key_.find(std::make_pair(static_cast<int>(code),
+ try_flags));
+ if (it != code_to_key_.end()) {
+ key = it->second;
+ if (key != DomKey::NONE)
+ break;
+ }
+ }
+ return key;
+}
+
+// static
+DomKey PlatformKeyMap::DomKeyFromNative(const base::NativeEvent& native_event) {
+ // Use TLS because KeyboardLayout is per thread.
+ // However currently PlatformKeyMap will only be used by the host application,
+ // which is just one process and one thread.
+ base::ThreadLocalStorage::Slot* platform_key_map_tls =
+ g_platform_key_map_tls_lazy.Pointer();
+ PlatformKeyMap* platform_key_map =
+ reinterpret_cast<PlatformKeyMap*>(platform_key_map_tls->Get());
+ if (!platform_key_map) {
+ platform_key_map = new PlatformKeyMap();
+ platform_key_map_tls->Set(platform_key_map);
+ }
+
+ HKL current_layout = ::GetKeyboardLayout(0);
+ platform_key_map->UpdateLayout(current_layout);
+ return platform_key_map->DomKeyFromNativeImpl(
+ CodeFromNative(native_event), KeyboardCodeFromNative(native_event),
+ EventFlagsFromNative(native_event));
+}
+
+void PlatformKeyMap::UpdateLayout(HKL layout) {
+ if (layout == keyboard_layout_)
+ return;
+
+ BYTE keyboard_state_to_restore[256];
+ if (!::GetKeyboardState(keyboard_state_to_restore))
+ return;
+
+ // TODO(chongz): Optimize layout switching (see crbug.com/587147).
+ keyboard_layout_ = layout;
+ code_to_key_.clear();
+ // Map size for some sample keyboard layouts:
+ // US: 428, French: 554, Persian: 434, Vietnamese: 1388
+ code_to_key_.reserve(500);
+
+ for (int eindex = 0; eindex <= kModifierFlagsCombinations; ++eindex) {
+ BYTE keyboard_state[256];
+ memset(keyboard_state, 0, sizeof(keyboard_state));
+ int flags = GetModifierFlags(eindex);
+ SetModifierState(keyboard_state, flags);
+ for (const auto& dom_code_entry : supported_dom_code_list) {
+ wchar_t translated_chars[5];
+ int key_code = ::MapVirtualKeyEx(dom_code_entry.scan_code,
+ MAPVK_VSC_TO_VK, keyboard_layout_);
+ int rv = ::ToUnicodeEx(key_code, 0, keyboard_state, translated_chars,
+ arraysize(translated_chars), 0, keyboard_layout_);
+
+ if (rv == -1) {
+ // Dead key, injecting VK_SPACE to get character representation.
+ BYTE empty_state[256];
+ memset(empty_state, 0, sizeof(empty_state));
+ rv = ::ToUnicodeEx(VK_SPACE, 0, empty_state, translated_chars,
+ arraysize(translated_chars), 0, keyboard_layout_);
+ // Expecting a dead key character (not followed by a space).
+ if (rv == 1) {
+ code_to_key_[std::make_pair(static_cast<int>(dom_code_entry.dom_code),
+ flags)] =
+ DomKey::DeadKeyFromCombiningCharacter(translated_chars[0]);
+ } else {
+ // TODO(chongz): Check if this will actually happen.
+ }
+ } else if (rv == 1) {
+ if (translated_chars[0] >= 0x20) {
+ code_to_key_[std::make_pair(static_cast<int>(dom_code_entry.dom_code),
+ flags)] =
+ DomKey::FromCharacter(translated_chars[0]);
+ } else {
+ // Ignores legacy non-printable control characters.
+ }
+ } else {
+ // TODO(chongz): Handle rv <= -2 and rv >= 2.
+ }
+ }
+ }
+ ::SetKeyboardState(keyboard_state_to_restore);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/keycodes/platform_key_map_win.h b/chromium/ui/events/keycodes/platform_key_map_win.h
new file mode 100644
index 00000000000..6d128a7a5dc
--- /dev/null
+++ b/chromium/ui/events/keycodes/platform_key_map_win.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_KEYCODES_PLATFORM_KEY_MAP_WIN_H_
+#define UI_EVENTS_KEYCODES_PLATFORM_KEY_MAP_WIN_H_
+
+#include <windows.h>
+
+#include <unordered_map>
+
+#include "base/event_types.h"
+#include "base/hash.h"
+#include "ui/events/events_export.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/keyboard_codes_win.h"
+
+namespace ui {
+
+enum class DomCode;
+
+class EVENTS_EXPORT PlatformKeyMap {
+ public:
+ // Create and load key map table with specified keyboard layout.
+ // Visible for testing.
+ explicit PlatformKeyMap(HKL layout);
+ ~PlatformKeyMap();
+
+ // Returns the DOM KeyboardEvent key from a native event and the keyboard
+ // layout of current thread.
+ // Updates a per-thread key map cache whenever the layout changes.
+ static DomKey DomKeyFromNative(const base::NativeEvent& native_event);
+
+ private:
+ friend class PlatformKeyMapTest;
+
+ PlatformKeyMap();
+
+ // TODO(chongz): Expose this function when we need to access separate layout.
+ // Returns the DomKey 'meaning' of |code| in the context of specified
+ // |ui_event_flags| and stored keyboard layout.
+ // |key_code| will only be used for NumPad.
+ DomKey DomKeyFromNativeImpl(DomCode code,
+ KeyboardCode key_code,
+ int ui_event_flags) const;
+
+ // TODO(chongz): Expose this function in response to WM_INPUTLANGCHANGE.
+ void UpdateLayout(HKL layout);
+
+ HKL keyboard_layout_ = 0;
+
+ // TODO(chongz): Change type to DomCode when we got a generic pair hash class.
+ typedef std::pair<int /*DomCode*/, int /*EventFlags*/> DomCodeEventFlagsPair;
+ typedef std::unordered_map<DomCodeEventFlagsPair,
+ DomKey,
+ base::IntPairHash<std::pair<int, int>>>
+ DomCodeToKeyMap;
+ DomCodeToKeyMap code_to_key_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformKeyMap);
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_KEYCODES_PLATFORM_KEY_MAP_WIN_H_
diff --git a/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc b/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc
new file mode 100644
index 00000000000..44cbd586715
--- /dev/null
+++ b/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc
@@ -0,0 +1,250 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/keycodes/platform_key_map_win.h"
+
+#include "base/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+
+namespace ui {
+
+namespace {
+
+const wchar_t* LAYOUT_US = L"00000409";
+const wchar_t* LAYOUT_FR = L"0000040c";
+
+struct TestKey {
+ // Have to use KeyboardCode instead of DomCode because we don't know the
+ // physical keyboard layout for try bots.
+ KeyboardCode key_code;
+ const char* normal;
+ const char* shift;
+ const char* capslock;
+ const char* altgr;
+ const char* shift_capslock;
+ const char* shift_altgr;
+ const char* altgr_capslock;
+};
+
+} // anonymous namespace
+
+class PlatformKeyMapTest : public testing::Test {
+ public:
+ PlatformKeyMapTest() {}
+ ~PlatformKeyMapTest() override {}
+
+ void CheckDomCodeToKeyString(const char* label,
+ const PlatformKeyMap& keymap,
+ const TestKey& test_case,
+ HKL layout) {
+ KeyboardCode key_code = test_case.key_code;
+ int scan_code = ::MapVirtualKeyEx(key_code, MAPVK_VK_TO_VSC, layout);
+ DomCode dom_code = KeycodeConverter::NativeKeycodeToDomCode(scan_code);
+ EXPECT_STREQ(test_case.normal,
+ KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(dom_code, key_code, EF_NONE))
+ .c_str())
+ << label;
+ EXPECT_STREQ(test_case.shift, KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(
+ dom_code, key_code, EF_SHIFT_DOWN))
+ .c_str())
+ << label;
+ EXPECT_STREQ(
+ test_case.capslock,
+ KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(dom_code, key_code, EF_CAPS_LOCK_ON))
+ .c_str())
+ << label;
+ EXPECT_STREQ(test_case.altgr, KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(
+ dom_code, key_code, EF_ALTGR_DOWN))
+ .c_str())
+ << label;
+ EXPECT_STREQ(test_case.shift_capslock,
+ KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(
+ dom_code, key_code, EF_SHIFT_DOWN | EF_CAPS_LOCK_ON))
+ .c_str())
+ << label;
+ EXPECT_STREQ(test_case.shift_altgr,
+ KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(dom_code, key_code,
+ EF_SHIFT_DOWN | EF_ALTGR_DOWN))
+ .c_str())
+ << label;
+ EXPECT_STREQ(test_case.altgr_capslock,
+ KeycodeConverter::DomKeyToKeyString(
+ keymap.DomKeyFromNativeImpl(
+ dom_code, key_code, EF_ALTGR_DOWN | EF_CAPS_LOCK_ON))
+ .c_str())
+ << label;
+ }
+
+ DomKey DomKeyFromNativeImpl(const PlatformKeyMap& keymap,
+ DomCode dom_code,
+ KeyboardCode key_code,
+ int flags) {
+ return keymap.DomKeyFromNativeImpl(dom_code, key_code, flags);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PlatformKeyMapTest);
+};
+
+TEST_F(PlatformKeyMapTest, USLayout) {
+ HKL layout = ::LoadKeyboardLayout(LAYOUT_US, 0);
+ PlatformKeyMap keymap(layout);
+
+ const TestKey kUSLayoutTestCases[] = {
+ // n s c a sc sa ac
+ {VKEY_0, "0", ")", "0", "0", ")", ")", "0"},
+ {VKEY_1, "1", "!", "1", "1", "!", "!", "1"},
+ {VKEY_2, "2", "@", "2", "2", "@", "@", "2"},
+ {VKEY_3, "3", "#", "3", "3", "#", "#", "3"},
+ {VKEY_4, "4", "$", "4", "4", "$", "$", "4"},
+ {VKEY_5, "5", "%", "5", "5", "%", "%", "5"},
+ {VKEY_6, "6", "^", "6", "6", "^", "^", "6"},
+ {VKEY_7, "7", "&", "7", "7", "&", "&", "7"},
+ {VKEY_8, "8", "*", "8", "8", "*", "*", "8"},
+ {VKEY_9, "9", "(", "9", "9", "(", "(", "9"},
+ {VKEY_A, "a", "A", "A", "a", "a", "A", "A"},
+ {VKEY_B, "b", "B", "B", "b", "b", "B", "B"},
+ {VKEY_C, "c", "C", "C", "c", "c", "C", "C"},
+ {VKEY_D, "d", "D", "D", "d", "d", "D", "D"},
+ {VKEY_E, "e", "E", "E", "e", "e", "E", "E"},
+ {VKEY_F, "f", "F", "F", "f", "f", "F", "F"},
+ {VKEY_G, "g", "G", "G", "g", "g", "G", "G"},
+ {VKEY_H, "h", "H", "H", "h", "h", "H", "H"},
+ {VKEY_I, "i", "I", "I", "i", "i", "I", "I"},
+ {VKEY_J, "j", "J", "J", "j", "j", "J", "J"},
+ {VKEY_K, "k", "K", "K", "k", "k", "K", "K"},
+ {VKEY_L, "l", "L", "L", "l", "l", "L", "L"},
+ {VKEY_M, "m", "M", "M", "m", "m", "M", "M"},
+ {VKEY_N, "n", "N", "N", "n", "n", "N", "N"},
+ {VKEY_O, "o", "O", "O", "o", "o", "O", "O"},
+ {VKEY_P, "p", "P", "P", "p", "p", "P", "P"},
+ {VKEY_Q, "q", "Q", "Q", "q", "q", "Q", "Q"},
+ {VKEY_R, "r", "R", "R", "r", "r", "R", "R"},
+ {VKEY_S, "s", "S", "S", "s", "s", "S", "S"},
+ {VKEY_T, "t", "T", "T", "t", "t", "T", "T"},
+ {VKEY_U, "u", "U", "U", "u", "u", "U", "U"},
+ {VKEY_V, "v", "V", "V", "v", "v", "V", "V"},
+ {VKEY_W, "w", "W", "W", "w", "w", "W", "W"},
+ {VKEY_X, "x", "X", "X", "x", "x", "X", "X"},
+ {VKEY_Y, "y", "Y", "Y", "y", "y", "Y", "Y"},
+ {VKEY_Z, "z", "Z", "Z", "z", "z", "Z", "Z"},
+ };
+
+ for (const auto& test_case : kUSLayoutTestCases) {
+ CheckDomCodeToKeyString("USLayout", keymap, test_case, layout);
+ }
+}
+
+TEST_F(PlatformKeyMapTest, FRLayout) {
+ HKL layout = ::LoadKeyboardLayout(LAYOUT_FR, 0);
+ PlatformKeyMap keymap(layout);
+
+ const TestKey kFRLayoutTestCases[] = {
+ // n s c a sc sa ac
+ {VKEY_0, "à", "0", "0", "@", "à", "0", "@"},
+ {VKEY_1, "&", "1", "1", "&", "&", "1", "1"},
+ {VKEY_2, "é", "2", "2", "Dead", "é", "2", "Dead"},
+ {VKEY_3, "\"", "3", "3", "#", "\"", "3", "#"},
+ {VKEY_4, "\'", "4", "4", "{", "\'", "4", "{"},
+ {VKEY_5, "(", "5", "5", "[", "(", "5", "["},
+ {VKEY_6, "-", "6", "6", "|", "-", "6", "|"},
+ {VKEY_7, "è", "7", "7", "Dead", "è", "7", "Dead"},
+ {VKEY_8, "_", "8", "8", "\\", "_", "8", "\\"},
+ {VKEY_9, "ç", "9", "9", "^", "ç", "9", "^"},
+ {VKEY_A, "a", "A", "A", "a", "a", "A", "A"},
+ {VKEY_B, "b", "B", "B", "b", "b", "B", "B"},
+ {VKEY_C, "c", "C", "C", "c", "c", "C", "C"},
+ {VKEY_D, "d", "D", "D", "d", "d", "D", "D"},
+ {VKEY_E, "e", "E", "E", "€", "e", "E", "€"},
+ {VKEY_F, "f", "F", "F", "f", "f", "F", "F"},
+ {VKEY_G, "g", "G", "G", "g", "g", "G", "G"},
+ {VKEY_H, "h", "H", "H", "h", "h", "H", "H"},
+ {VKEY_I, "i", "I", "I", "i", "i", "I", "I"},
+ {VKEY_J, "j", "J", "J", "j", "j", "J", "J"},
+ {VKEY_K, "k", "K", "K", "k", "k", "K", "K"},
+ {VKEY_L, "l", "L", "L", "l", "l", "L", "L"},
+ {VKEY_M, "m", "M", "M", "m", "m", "M", "M"},
+ {VKEY_N, "n", "N", "N", "n", "n", "N", "N"},
+ {VKEY_O, "o", "O", "O", "o", "o", "O", "O"},
+ {VKEY_P, "p", "P", "P", "p", "p", "P", "P"},
+ {VKEY_Q, "q", "Q", "Q", "q", "q", "Q", "Q"},
+ {VKEY_R, "r", "R", "R", "r", "r", "R", "R"},
+ {VKEY_S, "s", "S", "S", "s", "s", "S", "S"},
+ {VKEY_T, "t", "T", "T", "t", "t", "T", "T"},
+ {VKEY_U, "u", "U", "U", "u", "u", "U", "U"},
+ {VKEY_V, "v", "V", "V", "v", "v", "V", "V"},
+ {VKEY_W, "w", "W", "W", "w", "w", "W", "W"},
+ {VKEY_X, "x", "X", "X", "x", "x", "X", "X"},
+ {VKEY_Y, "y", "Y", "Y", "y", "y", "Y", "Y"},
+ {VKEY_Z, "z", "Z", "Z", "z", "z", "Z", "Z"},
+ };
+
+ for (const auto& test_case : kFRLayoutTestCases) {
+ CheckDomCodeToKeyString("FRLayout", keymap, test_case, layout);
+ }
+}
+
+TEST_F(PlatformKeyMapTest, NumPad) {
+ HKL layout = ::LoadKeyboardLayout(LAYOUT_US, 0);
+ PlatformKeyMap keymap(layout);
+
+ const struct TestCase {
+ KeyboardCode key_code;
+ DomKey key;
+ } kNumPadTestCases[] = {
+ {VKEY_NUMPAD0, DomKey::FromCharacter('0')},
+ {VKEY_NUMPAD1, DomKey::FromCharacter('1')},
+ {VKEY_NUMPAD2, DomKey::FromCharacter('2')},
+ {VKEY_NUMPAD3, DomKey::FromCharacter('3')},
+ {VKEY_NUMPAD4, DomKey::FromCharacter('4')},
+ {VKEY_NUMPAD5, DomKey::FromCharacter('5')},
+ {VKEY_NUMPAD6, DomKey::FromCharacter('6')},
+ {VKEY_NUMPAD7, DomKey::FromCharacter('7')},
+ {VKEY_NUMPAD8, DomKey::FromCharacter('8')},
+ {VKEY_NUMPAD9, DomKey::FromCharacter('9')},
+ {VKEY_CLEAR, DomKey::CLEAR},
+ {VKEY_PRIOR, DomKey::PAGE_UP},
+ {VKEY_NEXT, DomKey::PAGE_DOWN},
+ {VKEY_END, DomKey::END},
+ {VKEY_HOME, DomKey::HOME},
+ {VKEY_LEFT, DomKey::ARROW_LEFT},
+ {VKEY_UP, DomKey::ARROW_UP},
+ {VKEY_RIGHT, DomKey::ARROW_RIGHT},
+ {VKEY_DOWN, DomKey::ARROW_DOWN},
+ {VKEY_INSERT, DomKey::INSERT},
+ {VKEY_DELETE, DomKey::DEL},
+ };
+
+ for (const auto& test_case : kNumPadTestCases) {
+ KeyboardCode key_code = test_case.key_code;
+ int scan_code = ::MapVirtualKeyEx(key_code, MAPVK_VK_TO_VSC, layout);
+ DomCode dom_code = KeycodeConverter::NativeKeycodeToDomCode(scan_code);
+
+ EXPECT_EQ(test_case.key,
+ DomKeyFromNativeImpl(keymap, dom_code, key_code, EF_NONE))
+ << key_code;
+ EXPECT_EQ(test_case.key,
+ DomKeyFromNativeImpl(keymap, dom_code, key_code, EF_ALTGR_DOWN))
+ << key_code;
+ EXPECT_EQ(test_case.key,
+ DomKeyFromNativeImpl(keymap, dom_code, key_code, EF_CONTROL_DOWN))
+ << key_code;
+ EXPECT_EQ(test_case.key,
+ DomKeyFromNativeImpl(keymap, dom_code, key_code,
+ EF_ALTGR_DOWN | EF_CONTROL_DOWN))
+ << key_code;
+ }
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/keycodes/xkb_keysym.h b/chromium/ui/events/keycodes/xkb_keysym.h
index e0847d2d4bd..79d1f1f95f6 100644
--- a/chromium/ui/events/keycodes/xkb_keysym.h
+++ b/chromium/ui/events/keycodes/xkb_keysym.h
@@ -2,13 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_KEYCODES_XKEYSYMS_H_
-#define UI_EVENTS_KEYCODES_XKEYSYMS_H_
+#ifndef UI_EVENTS_KEYCODES_XKB_KEYSYM_H_
+#define UI_EVENTS_KEYCODES_XKB_KEYSYM_H_
// This file provides definitions of the xkbcommon keysym type (xkb_keysym_t)
// and values (XKB_KEY_...) for both xkbcommon and traditional X11.
-#if defined(USE_X11)
+#if defined(USE_XKBCOMMON)
+
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
+
+#else // !defined(USE_XKBCOMMON)
#define XK_3270 // For XK_3270_BackTab in particular.
#include <X11/X.h>
@@ -16,7 +21,7 @@
#include <X11/Sunkeysym.h>
#include <X11/XF86keysym.h>
-using xkb_keysym_t = KeySym;
+using xkb_keysym_t = uint32_t;
#define XKB_KEY_3270_Duplicate XK_3270_Duplicate
#define XKB_KEY_3270_FieldMark XK_3270_FieldMark
@@ -525,10 +530,7 @@ using xkb_keysym_t = KeySym;
#define XKB_KEY_XF86TouchpadOff XF86XK_TouchpadOff
#define XKB_KEY_XF86AudioMicMute XF86XK_AudioMicMute
-#else // not defined(USE_X11)
-#include <xkbcommon/xkbcommon.h>
-#include <xkbcommon/xkbcommon-keysyms.h>
#endif
-#endif // UI_EVENTS_KEYCODES_XKEYSYMS_H_
+#endif // UI_EVENTS_KEYCODES_XKB_KEYSYM_H_
diff --git a/chromium/ui/events/latency_info.cc b/chromium/ui/events/latency_info.cc
index cd03d4c9091..d935564a7d0 100644
--- a/chromium/ui/events/latency_info.cc
+++ b/chromium/ui/events/latency_info.cc
@@ -37,6 +37,7 @@ const char* GetComponentName(ui::LatencyComponentType type) {
CASE_TYPE(INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT);
CASE_TYPE(INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT);
CASE_TYPE(INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT);
+ CASE_TYPE(INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL);
CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT);
CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT);
CASE_TYPE(INPUT_EVENT_LATENCY_TERMINATED_KEYBOARD_COMPONENT);
@@ -84,7 +85,7 @@ bool IsInputLatencyBeginComponent(ui::LatencyComponentType type) {
class LatencyInfoTracedValue
: public base::trace_event::ConvertableToTraceFormat {
public:
- static scoped_refptr<ConvertableToTraceFormat> FromValue(
+ static scoped_ptr<ConvertableToTraceFormat> FromValue(
scoped_ptr<base::Value> value);
void AppendAsTraceFormat(std::string* out) const override;
@@ -98,9 +99,9 @@ class LatencyInfoTracedValue
DISALLOW_COPY_AND_ASSIGN(LatencyInfoTracedValue);
};
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+scoped_ptr<base::trace_event::ConvertableToTraceFormat>
LatencyInfoTracedValue::FromValue(scoped_ptr<base::Value> value) {
- return scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
+ return scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
new LatencyInfoTracedValue(value.release()));
}
@@ -143,17 +144,16 @@ LatencyInfo::InputCoordinate::InputCoordinate(float x, float y) : x(x), y(y) {
LatencyInfo::LatencyInfo()
: input_coordinates_size_(0),
- coalesced_events_size_(0),
trace_id_(-1),
- terminated_(false) {
-}
+ coalesced_(false),
+ terminated_(false) {}
-LatencyInfo::~LatencyInfo() {
-}
+LatencyInfo::LatencyInfo(const LatencyInfo& other) = default;
+
+LatencyInfo::~LatencyInfo() {}
LatencyInfo::LatencyInfo(int64_t trace_id, bool terminated)
: input_coordinates_size_(0),
- coalesced_events_size_(0),
trace_id_(trace_id),
terminated_(terminated) {}
@@ -315,7 +315,7 @@ void LatencyInfo::AddLatencyNumberWithTimestampImpl(
}
}
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+scoped_ptr<base::trace_event::ConvertableToTraceFormat>
LatencyInfo::AsTraceableData() {
scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
for (const auto& lc : latency_components_) {
@@ -335,7 +335,7 @@ LatencyInfo::AsTraceableData() {
return LatencyInfoTracedValue::FromValue(std::move(record_data));
}
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
+scoped_ptr<base::trace_event::ConvertableToTraceFormat>
LatencyInfo::CoordinatesAsTraceableData() {
scoped_ptr<base::ListValue> coordinates(new base::ListValue());
for (size_t i = 0; i < input_coordinates_size_; i++) {
@@ -380,11 +380,4 @@ bool LatencyInfo::AddInputCoordinate(const InputCoordinate& input_coordinate) {
return true;
}
-bool LatencyInfo::AddCoalescedEventTimestamp(double timestamp) {
- if (coalesced_events_size_ >= kMaxCoalescedEventTimestamps)
- return false;
- timestamps_of_coalesced_events_[coalesced_events_size_++] = timestamp;
- return true;
-}
-
} // namespace ui
diff --git a/chromium/ui/events/latency_info.h b/chromium/ui/events/latency_info.h
index 77efe5f7be3..cf61526ce35 100644
--- a/chromium/ui/events/latency_info.h
+++ b/chromium/ui/events/latency_info.h
@@ -15,9 +15,12 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "ipc/ipc_param_traits.h"
#include "ui/events/events_base_export.h"
+#if !defined(OS_IOS)
+#include "ipc/ipc_param_traits.h" // nogncheck
+#endif
+
namespace ui {
// When adding new components, or new metrics based on LatencyInfo,
@@ -64,6 +67,9 @@ enum LatencyComponentType {
// Timestamp of when the gpu service began swap buffers, unlike
// INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT which measures after.
INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT,
+ // Timestamp of when the gesture scroll update is generated from a mouse wheel
+ // event.
+ INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL,
// ---------------------------TERMINAL COMPONENT-----------------------------
// TERMINAL COMPONENT is when we show the latency end in chrome://tracing.
// Timestamp when the mouse event is acked from renderer and it does not
@@ -76,10 +82,10 @@ enum LatencyComponentType {
// cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_KEYBOARD_COMPONENT,
// Timestamp when the touch event is acked from renderer and it does not
- // cause any rendering schedueld and does not generate any gesture event.
+ // cause any rendering scheduled and does not generate any gesture event.
INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT,
// Timestamp when the gesture event is acked from renderer, and it does not
- // cause any rendering schedueld.
+ // cause any rendering scheduled.
INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT,
// Timestamp when the frame is swapped (i.e. when the rendering caused by
// input event actually takes effect).
@@ -94,7 +100,7 @@ enum LatencyComponentType {
// but the swap failed.
INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT,
LATENCY_COMPONENT_TYPE_LAST =
- INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT,
+ INPUT_EVENT_LATENCY_TERMINATED_SWAP_FAILED_COMPONENT,
};
class EVENTS_BASE_EXPORT LatencyInfo {
@@ -121,7 +127,6 @@ class EVENTS_BASE_EXPORT LatencyInfo {
// Empirically determined constant based on a typical scroll sequence.
enum { kTypicalMaxComponentsPerLatencyInfo = 10 };
- enum { kMaxCoalescedEventTimestamps = 2 };
enum { kMaxInputCoordinates = 2 };
// Map a Latency Component (with a component-specific int64_t id) to a
@@ -131,6 +136,7 @@ class EVENTS_BASE_EXPORT LatencyInfo {
kTypicalMaxComponentsPerLatencyInfo> LatencyMap;
LatencyInfo();
+ LatencyInfo(const LatencyInfo& other);
~LatencyInfo();
// For test only.
@@ -192,18 +198,11 @@ class EVENTS_BASE_EXPORT LatencyInfo {
return input_coordinates_;
}
- // Returns true if there is still room for keeping the |timestamp|,
- // false otherwise.
- bool AddCoalescedEventTimestamp(double timestamp);
-
- uint32_t coalesced_events_size() const { return coalesced_events_size_; }
- const double* timestamps_of_coalesced_events() const {
- return timestamps_of_coalesced_events_;
- }
-
const LatencyMap& latency_components() const { return latency_components_; }
bool terminated() const { return terminated_; }
+ void set_coalesced() { coalesced_ = true; }
+ bool coalesced() const { return coalesced_; }
int64_t trace_id() const { return trace_id_; }
private:
@@ -215,9 +214,9 @@ class EVENTS_BASE_EXPORT LatencyInfo {
const char* trace_name_str);
// Converts latencyinfo into format that can be dumped into trace buffer.
- scoped_refptr<base::trace_event::ConvertableToTraceFormat> AsTraceableData();
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- CoordinatesAsTraceableData();
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat> AsTraceableData();
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>
+ CoordinatesAsTraceableData();
// Shown as part of the name of the trace event for this LatencyInfo.
// String is empty if no tracing is enabled.
@@ -229,15 +228,16 @@ class EVENTS_BASE_EXPORT LatencyInfo {
uint32_t input_coordinates_size_;
InputCoordinate input_coordinates_[kMaxInputCoordinates];
- uint32_t coalesced_events_size_;
- double timestamps_of_coalesced_events_[kMaxCoalescedEventTimestamps];
-
// The unique id for matching the ASYNC_BEGIN/END trace event.
int64_t trace_id_;
+ // Whether this event has been coalesced into another event.
+ bool coalesced_;
// Whether a terminal component has been added.
bool terminated_;
+#if !defined(OS_IOS)
friend struct IPC::ParamTraits<ui::LatencyInfo>;
+#endif
};
} // namespace ui
diff --git a/chromium/ui/events/latency_info_unittest.cc b/chromium/ui/events/latency_info_unittest.cc
index a3dac964e5f..e27986397ea 100644
--- a/chromium/ui/events/latency_info_unittest.cc
+++ b/chromium/ui/events/latency_info_unittest.cc
@@ -67,16 +67,4 @@ TEST(LatencyInfoTest, AddTwoSameEvent) {
EXPECT_EQ(component.event_time.ToInternalValue(), (100 * 2 + 200 * 3) / 5);
}
-TEST(LatencyInfoTest, AddCoalescedEventTimestamp) {
- LatencyInfo info;
- ASSERT_EQ(0u, info.coalesced_events_size());
- for (size_t i = 0; i < LatencyInfo::kMaxCoalescedEventTimestamps; i++)
- EXPECT_TRUE(info.AddCoalescedEventTimestamp(i * 10.0));
- EXPECT_FALSE(info.AddCoalescedEventTimestamp(99.0));
- EXPECT_EQ(LatencyInfo::kMaxCoalescedEventTimestamps,
- info.coalesced_events_size());
- for (size_t i = 0; i < info.coalesced_events_size(); i++)
- EXPECT_EQ(i * 10.0, info.timestamps_of_coalesced_events()[i]);
-}
-
} // namespace ui
diff --git a/chromium/ui/events/null_event_targeter.h b/chromium/ui/events/null_event_targeter.h
index c22e7a7681f..8d9ea4312ae 100644
--- a/chromium/ui/events/null_event_targeter.h
+++ b/chromium/ui/events/null_event_targeter.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#ifndef UI_EVENTS_NULL_EVENT_TARGETER_H_
+#define UI_EVENTS_NULL_EVENT_TARGETER_H_
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "ui/events/event_targeter.h"
@@ -26,3 +29,5 @@ class EVENTS_EXPORT NullEventTargeter : public EventTargeter {
};
} // namespace ui
+
+#endif // UI_EVENTS_NULL_EVENT_TARGETER_H_
diff --git a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
index ca9f0d363e7..16afecc4a93 100644
--- a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.cc
@@ -116,17 +116,14 @@ TouchEventParams::TouchEventParams(int device_id,
int slot,
EventType type,
const gfx::PointF& location,
- const gfx::Vector2dF& radii,
- float pressure,
+ const PointerDetails& details,
const base::TimeDelta& timestamp)
: device_id(device_id),
slot(slot),
type(type),
location(location),
- radii(radii),
- pressure(pressure),
- timestamp(timestamp) {
-}
+ pointer_details(details),
+ timestamp(timestamp) {}
TouchEventParams::TouchEventParams(const TouchEventParams& other) = default;
diff --git a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
index 6c4c4b602b9..164d9f70351 100644
--- a/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
+++ b/chromium/ui/events/ozone/evdev/device_event_dispatcher_evdev.h
@@ -125,8 +125,7 @@ struct EVENTS_OZONE_EVDEV_EXPORT TouchEventParams {
int slot,
EventType type,
const gfx::PointF& location,
- const gfx::Vector2dF& radii,
- float pressure,
+ const PointerDetails& pointer_details,
const base::TimeDelta& timestamp);
TouchEventParams(const TouchEventParams& other);
~TouchEventParams();
@@ -135,8 +134,7 @@ struct EVENTS_OZONE_EVDEV_EXPORT TouchEventParams {
int slot;
EventType type;
gfx::PointF location;
- gfx::Vector2dF radii;
- float pressure;
+ PointerDetails pointer_details;
base::TimeDelta timestamp;
};
diff --git a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
index c3c8a38bd2d..3ff26c0343c 100644
--- a/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
@@ -124,13 +124,13 @@ class EventConverterEvdevImplTest : public testing::Test {
DCHECK_GT(dispatched_events_.size(), index);
ui::Event* ev = dispatched_events_[index].get();
DCHECK(ev->IsKeyEvent());
- return static_cast<ui::KeyEvent*>(ev);
+ return ev->AsKeyEvent();
}
ui::MouseEvent* dispatched_mouse_event(unsigned index) {
DCHECK_GT(dispatched_events_.size(), index);
ui::Event* ev = dispatched_events_[index].get();
DCHECK(ev->IsMouseEvent());
- return static_cast<ui::MouseEvent*>(ev);
+ return ev->AsMouseEvent();
}
void ClearDispatchedEvents() {
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
index 18118290d65..c8e99ee0148 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -276,8 +276,8 @@ void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
float x = params.location.x();
float y = params.location.y();
- double radius_x = params.radii.x();
- double radius_y = params.radii.y();
+ double radius_x = params.pointer_details.radius_x;
+ double radius_y = params.pointer_details.radius_y;
// Transform the event to align touches to the image based on display mode.
DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x,
@@ -287,16 +287,21 @@ void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id,
&radius_y);
+ PointerDetails details = params.pointer_details;
+ details.radius_x = radius_x;
+ details.radius_y = radius_y;
+
// params.slot is guaranteed to be < kNumTouchEvdevSlots.
int touch_id = touch_id_generator_.GetGeneratedID(
params.device_id * kNumTouchEvdevSlots + params.slot);
- TouchEvent touch_event(params.type, gfx::Point(),
- modifiers_.GetModifierFlags(), touch_id,
- params.timestamp, radius_x, radius_y,
- /* angle */ 0.f, params.pressure);
+ TouchEvent touch_event(
+ params.type, gfx::Point(), modifiers_.GetModifierFlags(), touch_id,
+ params.timestamp, /* radius_x */ 0.f, /* radius_y */ 0.f,
+ /* angle */ 0.f, /* force */ 0.f);
touch_event.set_location_f(gfx::PointF(x, y));
touch_event.set_root_location_f(gfx::PointF(x, y));
touch_event.set_source_device_id(params.device_id);
+ touch_event.set_pointer_details(details);
DispatchUiEvent(&touch_event);
if (params.type == ET_TOUCH_RELEASED || params.type == ET_TOUCH_CANCELLED) {
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
index 8e95df65410..5469651ba24 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.h
@@ -14,6 +14,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/task_runner.h"
#include "ui/events/ozone/evdev/event_converter_evdev.h"
#include "ui/events/ozone/evdev/event_device_info.h"
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
index 982d4d8d2d0..7c084ccc301 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
@@ -12,6 +12,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
index 02d0888fdc7..b4fc0e4bda1 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "ui/events/ozone/evdev/event_converter_evdev.h"
#include "ui/events/ozone/evdev/event_device_info.h"
diff --git a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h
index 01034e53cc3..c4bee69c0ab 100644
--- a/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h
+++ b/chromium/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h
@@ -17,6 +17,7 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "ui/events/ozone/evdev/event_device_info.h"
#include "ui/events/ozone/evdev/events_ozone_evdev_export.h"
diff --git a/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
index b7def520c12..bca5eda9709 100644
--- a/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
@@ -209,7 +209,7 @@ class TabletEventConverterEvdevTest : public testing::Test {
DCHECK_GT(dispatched_events_.size(), index);
ui::Event* ev = dispatched_events_[index].get();
DCHECK(ev->IsMouseEvent());
- return static_cast<ui::MouseEvent*>(ev);
+ return ev->AsMouseEvent();
}
void DispatchEventForTest(ui::Event* event) {
@@ -418,20 +418,20 @@ TEST_F(TabletEventConverterEvdevTest, Tap) {
ui::MouseEvent* event = dispatched_event(0);
EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
- event->pointer_details().pointer_type());
- EXPECT_FLOAT_EQ(5.625f, event->pointer_details().tilt_x());
- EXPECT_FLOAT_EQ(0.f, event->pointer_details().tilt_y());
+ event->pointer_details().pointer_type);
+ EXPECT_FLOAT_EQ(5.625f, event->pointer_details().tilt_x);
+ EXPECT_FLOAT_EQ(0.f, event->pointer_details().tilt_y);
event = dispatched_event(1);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->type());
EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
- event->pointer_details().pointer_type());
- EXPECT_FLOAT_EQ((float)992 / 2047, event->pointer_details().force());
+ event->pointer_details().pointer_type);
+ EXPECT_FLOAT_EQ((float)992 / 2047, event->pointer_details().force);
EXPECT_EQ(true, event->IsLeftMouseButton());
event = dispatched_event(2);
EXPECT_EQ(ui::EventPointerType::POINTER_TYPE_PEN,
- event->pointer_details().pointer_type());
+ event->pointer_details().pointer_type);
EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->type());
- EXPECT_FLOAT_EQ(0.0f, event->pointer_details().force());
+ EXPECT_FLOAT_EQ(0.0f, event->pointer_details().force);
EXPECT_EQ(true, event->IsLeftMouseButton());
}
diff --git a/chromium/ui/events/ozone/evdev/touch_evdev_types.cc b/chromium/ui/events/ozone/evdev/touch_evdev_types.cc
index 78807c18749..87d0cffedfc 100644
--- a/chromium/ui/events/ozone/evdev/touch_evdev_types.cc
+++ b/chromium/ui/events/ozone/evdev/touch_evdev_types.cc
@@ -9,6 +9,9 @@ namespace ui {
InProgressTouchEvdev::InProgressTouchEvdev() {
}
+InProgressTouchEvdev::InProgressTouchEvdev(const InProgressTouchEvdev& other) =
+ default;
+
InProgressTouchEvdev::~InProgressTouchEvdev() {}
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/touch_evdev_types.h b/chromium/ui/events/ozone/evdev/touch_evdev_types.h
index 88c6fcde75a..1efe0c62b41 100644
--- a/chromium/ui/events/ozone/evdev/touch_evdev_types.h
+++ b/chromium/ui/events/ozone/evdev/touch_evdev_types.h
@@ -19,6 +19,7 @@ const int kNumTouchEvdevSlots = 20;
// Contains information about an in progress touch.
struct EVENTS_OZONE_EVDEV_EXPORT InProgressTouchEvdev {
InProgressTouchEvdev();
+ InProgressTouchEvdev(const InProgressTouchEvdev& other);
~InProgressTouchEvdev();
// Whether there is new information for the touch.
@@ -37,6 +38,7 @@ struct EVENTS_OZONE_EVDEV_EXPORT InProgressTouchEvdev {
float radius_x = 0;
float radius_y = 0;
float pressure = 0;
+ int tool_code = 0;
};
} // namespace ui
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index 9624ec2a4b6..513adf99e6d 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -78,6 +78,13 @@ int32_t AbsCodeToMtCode(int32_t code) {
}
}
+ui::EventPointerType GetPointerTypeFromEvent(
+ const ui::InProgressTouchEvdev& event) {
+ return (event.tool_code == BTN_TOOL_PEN)
+ ? ui::EventPointerType::POINTER_TYPE_PEN
+ : ui::EventPointerType::POINTER_TYPE_TOUCH;
+}
+
const int kTrackingIdForUnusedSlot = -1;
} // namespace
@@ -185,6 +192,7 @@ void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
events_[0].radius_x = 0;
events_[0].radius_y = 0;
events_[0].pressure = 0;
+ events_[0].tool_code = 0;
}
}
@@ -310,6 +318,13 @@ void TouchEventConverterEvdev::ProcessKey(const input_event& input) {
case BTN_TOUCH:
case BTN_LEFT:
break;
+ case BTN_TOOL_PEN:
+ if (input.value > 0) {
+ events_[current_slot_].tool_code = input.code;
+ } else {
+ events_[current_slot_].tool_code = 0;
+ }
+ break;
default:
NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code;
}
@@ -388,10 +403,13 @@ EventType TouchEventConverterEvdev::GetEventTypeForTouch(
void TouchEventConverterEvdev::ReportEvent(const InProgressTouchEvdev& event,
EventType event_type,
const base::TimeDelta& timestamp) {
- dispatcher_->DispatchTouchEvent(TouchEventParams(
- input_device_.id, event.slot, event_type, gfx::PointF(event.x, event.y),
- gfx::Vector2dF(event.radius_x, event.radius_y), event.pressure,
- timestamp));
+ PointerDetails details(GetPointerTypeFromEvent(event), event.radius_x,
+ event.radius_y, event.pressure,
+ /* tilt_x */ 0.0f,
+ /* tilt_y */ 0.0f);
+ dispatcher_->DispatchTouchEvent(
+ TouchEventParams(input_device_.id, event.slot, event_type,
+ gfx::PointF(event.x, event.y), details, timestamp));
}
void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) {
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 8cdd92fc673..6bb00757d71 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -277,8 +277,10 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(295, event.location.x());
EXPECT_EQ(421, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(58.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.13333334f, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
+ event.pointer_details.pointer_type);
+ EXPECT_FLOAT_EQ(58.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.13333334f, event.pointer_details.force);
// Move.
dev->ConfigureReadMock(mock_kernel_queue_move,
@@ -292,8 +294,10 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(312, event.location.x());
EXPECT_EQ(432, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(50.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.16862745f, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
+ event.pointer_details.pointer_type);
+ EXPECT_FLOAT_EQ(50.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.16862745f, event.pointer_details.force);
// Release.
dev->ConfigureReadMock(mock_kernel_queue_release,
@@ -307,8 +311,10 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(312, event.location.x());
EXPECT_EQ(432, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(50.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.16862745f, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_TOUCH,
+ event.pointer_details.pointer_type);
+ EXPECT_FLOAT_EQ(50.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.16862745f, event.pointer_details.force);
}
TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
@@ -357,7 +363,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(40, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev0.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev0.pointer_details.force);
// Press
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1.type);
@@ -365,7 +371,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(101, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev1.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev1.pointer_details.force);
// Stationary 0, Moves 1.
struct input_event mock_kernel_queue_stationary0_move1[] = {
@@ -381,7 +387,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(40, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev1.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev1.pointer_details.force);
// Move 0, stationary 1.
struct input_event mock_kernel_queue_move0_stationary1[] = {
@@ -398,7 +404,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(39, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev0.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev0.pointer_details.force);
// Release 0, move 1.
struct input_event mock_kernel_queue_release0_move1[] = {
@@ -416,14 +422,14 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(39, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev0.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev0.pointer_details.force);
EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type);
EXPECT_EQ(base::TimeDelta::FromMicroseconds(0), ev1.timestamp);
EXPECT_EQ(38, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev1.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev1.pointer_details.force);
// Release 1.
struct input_event mock_kernel_queue_release1[] = {
@@ -439,7 +445,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
EXPECT_EQ(38, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
- EXPECT_FLOAT_EQ(0.17647059f, ev1.pressure);
+ EXPECT_FLOAT_EQ(0.17647059f, ev1.pointer_details.force);
}
TEST_F(TouchEventConverterEvdevTest, Unsync) {
@@ -509,9 +515,9 @@ TEST_F(TouchEventConverterEvdevTest, ShouldResumeExistingContactsOnStart) {
ui::TouchEventParams ev = dispatched_event(0);
EXPECT_EQ(ET_TOUCH_PRESSED, ev.type);
EXPECT_EQ(0, ev.slot);
- EXPECT_FLOAT_EQ(50.f, ev.radii.x());
- EXPECT_FLOAT_EQ(0.f, ev.radii.y());
- EXPECT_FLOAT_EQ(0.50196081f, ev.pressure);
+ EXPECT_FLOAT_EQ(50.f, ev.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(50.f, ev.pointer_details.radius_y);
+ EXPECT_FLOAT_EQ(0.50196081f, ev.pointer_details.force);
}
TEST_F(TouchEventConverterEvdevTest, ShouldReleaseContactsOnStop) {
@@ -663,8 +669,8 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(3654, event.location.x());
EXPECT_EQ(1055, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(0.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.f, event.pressure);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.force);
// Move.
dev->ConfigureReadMock(mock_kernel_queue_move,
@@ -678,8 +684,8 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(3644, event.location.x());
EXPECT_EQ(1059, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(0.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.f, event.pressure);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.force);
// Release.
dev->ConfigureReadMock(mock_kernel_queue_release,
@@ -693,8 +699,8 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(3644, event.location.x());
EXPECT_EQ(1059, event.location.y());
EXPECT_EQ(0, event.slot);
- EXPECT_FLOAT_EQ(0.f, event.radii.x());
- EXPECT_FLOAT_EQ(0.f, event.pressure);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.radius_x);
+ EXPECT_FLOAT_EQ(0.f, event.pointer_details.force);
// No dispatch on destruction.
DestroyDevice();
@@ -740,12 +746,12 @@ TEST_F(TouchEventConverterEvdevTest,
EXPECT_EQ(0, ev0.slot);
EXPECT_EQ(999, ev0.location.x());
EXPECT_EQ(888, ev0.location.y());
- EXPECT_FLOAT_EQ(0.21568628f, ev0.pressure);
+ EXPECT_FLOAT_EQ(0.21568628f, ev0.pointer_details.force);
EXPECT_EQ(1, ev1.slot);
EXPECT_EQ(777, ev1.location.x());
EXPECT_EQ(666, ev1.location.y());
- EXPECT_FLOAT_EQ(0.17254902f, ev1.pressure);
+ EXPECT_FLOAT_EQ(0.17254902f, ev1.pointer_details.force);
}
// crbug.com/446939
@@ -966,13 +972,13 @@ TEST_F(TouchEventConverterEvdevTest, ActiveStylusTouchAndRelease) {
EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
EXPECT_EQ(9170, event.location.x());
EXPECT_EQ(3658, event.location.y());
- EXPECT_EQ(60.f / 1024, event.pressure);
+ EXPECT_EQ(60.f / 1024, event.pointer_details.force);
event = dispatched_event(1);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
EXPECT_EQ(9173, event.location.x());
EXPECT_EQ(3906, event.location.y());
- EXPECT_EQ(0.f / 1024, event.pressure);
+ EXPECT_EQ(0.f / 1024, event.pointer_details.force);
}
TEST_F(TouchEventConverterEvdevTest, ActiveStylusMotion) {
@@ -1012,25 +1018,33 @@ TEST_F(TouchEventConverterEvdevTest, ActiveStylusMotion) {
EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
EXPECT_EQ(8921, event.location.x());
EXPECT_EQ(1072, event.location.y());
- EXPECT_EQ(35.f / 1024, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
+ event.pointer_details.pointer_type);
+ EXPECT_EQ(35.f / 1024, event.pointer_details.force);
event = dispatched_event(1);
EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
EXPECT_EQ(8934, event.location.x());
EXPECT_EQ(981, event.location.y());
- EXPECT_EQ(184.f / 1024, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
+ event.pointer_details.pointer_type);
+ EXPECT_EQ(184.f / 1024, event.pointer_details.force);
event = dispatched_event(2);
EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
EXPECT_EQ(8930, event.location.x());
EXPECT_EQ(980, event.location.y());
- EXPECT_EQ(348.f / 1024, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
+ event.pointer_details.pointer_type);
+ EXPECT_EQ(348.f / 1024, event.pointer_details.force);
event = dispatched_event(3);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
EXPECT_EQ(8930, event.location.x());
EXPECT_EQ(980, event.location.y());
- EXPECT_EQ(0.f / 1024, event.pressure);
+ EXPECT_EQ(EventPointerType::POINTER_TYPE_PEN,
+ event.pointer_details.pointer_type);
+ EXPECT_EQ(0.f / 1024, event.pointer_details.force);
}
} // namespace ui
diff --git a/chromium/ui/events/ozone/layout/layout_util.cc b/chromium/ui/events/ozone/layout/layout_util.cc
index da0d5fedc28..5be53ecf48b 100644
--- a/chromium/ui/events/ozone/layout/layout_util.cc
+++ b/chromium/ui/events/ozone/layout/layout_util.cc
@@ -24,8 +24,6 @@ int ModifierDomKeyToEventFlag(DomKey key) {
case DomKey::CONTROL:
return EF_CONTROL_DOWN;
case DomKey::META:
- return EF_ALT_DOWN;
- case DomKey::OS:
return EF_COMMAND_DOWN;
case DomKey::SHIFT:
return EF_SHIFT_DOWN;
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
index aee22822030..0baefd46046 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
@@ -7,10 +7,13 @@
#include <stddef.h>
#include <xkbcommon/xkbcommon-names.h>
+#include <algorithm>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/free_deleter.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
@@ -31,10 +34,15 @@ typedef base::Callback<void(const std::string&,
scoped_ptr<char, base::FreeDeleter>)>
LoadKeymapCallback;
-KeyboardCode AlphanumericKeyboardCode(base::char16 character) {
+KeyboardCode AlphanumericKeyboardCode(xkb_keysym_t xkb_keysym,
+ base::char16 character) {
// Plain ASCII letters and digits map directly to VKEY values.
- if ((character >= '0') && (character <= '9'))
- return static_cast<KeyboardCode>(VKEY_0 + character - '0');
+ if ((character >= '0') && (character <= '9')) {
+ int zero = ((xkb_keysym >= XKB_KEY_KP_0) && (xkb_keysym <= XKB_KEY_KP_9))
+ ? VKEY_NUMPAD0
+ : VKEY_0;
+ return static_cast<KeyboardCode>(zero + character - '0');
+ }
if ((character >= 'a') && (character <= 'z'))
return static_cast<KeyboardCode>(VKEY_A + character - 'a');
if ((character >= 'A') && (character <= 'Z'))
@@ -684,8 +692,15 @@ bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName(
true);
return true;
#else
- // NOTIMPLEMENTED();
- return false;
+ // Required by ozone-wayland (at least) for non ChromeOS builds. See
+ // http://xkbcommon.org/doc/current/md_doc_quick-guide.html for further info.
+ xkb_keymap* keymap = xkb_keymap_new_from_string(
+ xkb_context_.get(), layout_name.c_str(), XKB_KEYMAP_FORMAT_TEXT_V1,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap)
+ return false;
+ SetKeymap(keymap);
+ return true;
#endif // defined(OS_CHROMEOS)
}
@@ -774,7 +789,7 @@ bool XkbKeyboardLayoutEngine::Lookup(DomCode dom_code,
}
*dom_key = DomKey::FromCharacter(character);
- *key_code = AlphanumericKeyboardCode(character);
+ *key_code = AlphanumericKeyboardCode(xkb_keysym, character);
if (*key_code == VKEY_UNKNOWN) {
*key_code = DifficultKeyboardCode(dom_code, flags, xkb_keycode, xkb_flags,
xkb_keysym, character);
@@ -875,7 +890,7 @@ KeyboardCode XkbKeyboardLayoutEngine::DifficultKeyboardCode(
return NonPrintableDomKeyToKeyboardCode(plain_key);
// Plain ASCII letters and digits map directly to VKEY values.
- KeyboardCode key_code = AlphanumericKeyboardCode(plain_character);
+ KeyboardCode key_code = AlphanumericKeyboardCode(xkb_keysym, plain_character);
if (key_code != VKEY_UNKNOWN)
return key_code;
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
index c485ecdc60e..ef52db750fa 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
@@ -7,9 +7,11 @@
#include <stdint.h>
#include <xkbcommon/xkbcommon.h>
+
#include <vector>
#include "base/containers/hash_tables.h"
+#include "base/memory/free_deleter.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
index ed59617ca8f..b8488af20d7 100644
--- a/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
+++ b/chromium/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
@@ -45,6 +45,7 @@ class VkTestXkbKeyboardLayoutEngine : public XkbKeyboardLayoutEngine {
struct KeysymEntry {
DomCode dom_code;
xkb_keysym_t keysym;
+ base::char16 character;
};
struct RuleNames {
@@ -128,7 +129,7 @@ class VkTestXkbKeyboardLayoutEngine : public XkbKeyboardLayoutEngine {
return false;
}
*xkb_keysym = keysym_entry_->keysym;
- *character = 0;
+ *character = keysym_entry_->character;
return true;
}
return false;
@@ -815,6 +816,9 @@ TEST_F(XkbLayoutEngineVkTest, KeyboardCodeForNonPrintable) {
{{DomCode::ENTER, XKB_KEY_Return}, VKEY_RETURN},
{{DomCode::NUMPAD_ENTER, XKB_KEY_KP_Enter}, VKEY_RETURN},
{{DomCode::SLEEP, XKB_KEY_XF86Sleep}, VKEY_SLEEP},
+ // Verify that number pad digits produce located VKEY codes.
+ {{DomCode::NUMPAD0, XKB_KEY_KP_0, '0'}, VKEY_NUMPAD0},
+ {{DomCode::NUMPAD9, XKB_KEY_KP_9, '9'}, VKEY_NUMPAD9},
};
for (const auto& e : kVkeyTestCase) {
SCOPED_TRACE(static_cast<int>(e.test.dom_code));
diff --git a/chromium/ui/events/platform/x11/BUILD.gn b/chromium/ui/events/platform/x11/BUILD.gn
index e55afc7ee6f..929613c7f7a 100644
--- a/chromium/ui/events/platform/x11/BUILD.gn
+++ b/chromium/ui/events/platform/x11/BUILD.gn
@@ -3,8 +3,9 @@
# found in the LICENSE file.
import("//build/config/ui.gni")
+import("//ui/ozone/ozone.gni")
-assert(use_x11)
+assert(use_x11 || ozone_platform_x11)
component("x11") {
output_name = "x11_events_platform"
@@ -12,8 +13,6 @@ component("x11") {
sources = [
"x11_event_source.cc",
"x11_event_source.h",
- "x11_event_source_glib.cc",
- "x11_event_source_libevent.cc",
"x11_hotplug_event_handler.cc",
"x11_hotplug_event_handler.h",
]
@@ -27,6 +26,7 @@ component("x11") {
"//ui/events:events_base",
"//ui/events/devices",
"//ui/events/platform",
+ "//ui/events/x",
"//ui/gfx/x",
]
@@ -34,11 +34,17 @@ component("x11") {
"//base",
]
- if (is_linux) {
- sources -= [ "x11_event_source_libevent.cc" ]
+ if (use_glib) {
+ sources += [
+ "x11_event_source_glib.cc",
+ "x11_event_source_glib.h",
+ ]
configs += [ "//build/config/linux:glib" ]
} else {
- sources -= [ "x11_event_source_glib.cc" ]
+ sources += [
+ "x11_event_source_libevent.cc",
+ "x11_event_source_libevent.h",
+ ]
}
}
diff --git a/chromium/ui/events/platform/x11/x11_event_source.cc b/chromium/ui/events/platform/x11/x11_event_source.cc
index ba55e0b1751..e1bc15ecc31 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.cc
+++ b/chromium/ui/events/platform/x11/x11_event_source.cc
@@ -4,51 +4,19 @@
#include "ui/events/platform/x11/x11_event_source.h"
-#include <X11/extensions/XInput2.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
#include <X11/XKBlib.h>
+#include <X11/Xlib.h>
#include "base/logging.h"
#include "ui/events/devices/x11/device_data_manager_x11.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/events/platform/x11/x11_hotplug_event_handler.h"
-#include "ui/gfx/x/x11_types.h"
namespace ui {
namespace {
-int g_xinput_opcode = -1;
-
-bool InitializeXInput2(XDisplay* display) {
- if (!display)
- return false;
-
- int event, err;
-
- int xiopcode;
- if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
- DVLOG(1) << "X Input extension not available.";
- return false;
- }
- g_xinput_opcode = xiopcode;
-
- int major = 2, minor = 2;
- if (XIQueryVersion(display, &major, &minor) == BadRequest) {
- DVLOG(1) << "XInput2 not supported in the server.";
- return false;
- }
- if (major < 2 || (major == 2 && minor < 2)) {
- DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
- << "But 2.2 is required.";
- return false;
- }
-
- return true;
-}
-
bool InitializeXkb(XDisplay* display) {
if (!display)
return false;
@@ -74,21 +42,29 @@ bool InitializeXkb(XDisplay* display) {
} // namespace
-X11EventSource::X11EventSource(XDisplay* display)
- : display_(display),
- continue_stream_(true) {
- CHECK(display_);
+X11EventSource* X11EventSource::instance_ = nullptr;
+
+X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
+ XDisplay* display)
+ : delegate_(delegate), display_(display), continue_stream_(true) {
+ DCHECK(!instance_);
+ instance_ = this;
+
+ DCHECK(delegate_);
+ DCHECK(display_);
DeviceDataManagerX11::CreateInstance();
- InitializeXInput2(display_);
InitializeXkb(display_);
}
X11EventSource::~X11EventSource() {
+ DCHECK_EQ(this, instance_);
+ instance_ = nullptr;
}
// static
X11EventSource* X11EventSource::GetInstance() {
- return static_cast<X11EventSource*>(PlatformEventSource::GetInstance());
+ DCHECK(instance_);
+ return instance_;
}
////////////////////////////////////////////////////////////////////////////////
@@ -118,25 +94,26 @@ void X11EventSource::BlockUntilWindowMapped(XID window) {
}
////////////////////////////////////////////////////////////////////////////////
-// X11EventSource, private
+// X11EventSource, protected
-uint32_t X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
+void X11EventSource::ExtractCookieDataDispatchEvent(XEvent* xevent) {
bool have_cookie = false;
if (xevent->type == GenericEvent &&
XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
have_cookie = true;
}
- uint32_t action = DispatchEvent(xevent);
+ delegate_->ProcessXEvent(xevent);
+ PostDispatchEvent(xevent);
if (have_cookie)
XFreeEventData(xevent->xgeneric.display, &xevent->xcookie);
- return action;
}
-uint32_t X11EventSource::DispatchEvent(XEvent* xevent) {
- uint32_t action = PlatformEventSource::DispatchEvent(xevent);
+void X11EventSource::PostDispatchEvent(XEvent* xevent) {
if (xevent->type == GenericEvent &&
(xevent->xgeneric.evtype == XI_HierarchyChanged ||
- xevent->xgeneric.evtype == XI_DeviceChanged)) {
+ (xevent->xgeneric.evtype == XI_DeviceChanged &&
+ static_cast<XIDeviceChangedEvent*>(xevent->xcookie.data)->reason ==
+ XIDeviceChange))) {
ui::UpdateDeviceList();
hotplug_event_handler_->OnHotplugEvent();
}
@@ -147,7 +124,6 @@ uint32_t X11EventSource::DispatchEvent(XEvent* xevent) {
// Clear stored scroll data
ui::DeviceDataManagerX11::GetInstance()->InvalidateScrollClasses();
}
- return action;
}
void X11EventSource::StopCurrentEventStream() {
diff --git a/chromium/ui/events/platform/x11/x11_event_source.h b/chromium/ui/events/platform/x11/x11_event_source.h
index 26d64601660..58169087e4e 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.h
+++ b/chromium/ui/events/platform/x11/x11_event_source.h
@@ -10,11 +10,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/events/events_export.h"
-#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/x/x11_types.h"
-typedef struct _GPollFD GPollFD;
-typedef struct _GSource GSource;
typedef union _XEvent XEvent;
typedef unsigned long XID;
@@ -22,16 +19,30 @@ namespace ui {
class X11HotplugEventHandler;
-// A PlatformEventSource implementation for reading events from X11 server and
-// dispatching the events to the appropriate dispatcher.
-class EVENTS_EXPORT X11EventSource : public PlatformEventSource {
+// Responsible for notifying X11EventSource when new XEvents are available and
+// processing/dispatching XEvents. Implementations will likely be a
+// PlatformEventSource.
+class X11EventSourceDelegate {
public:
- explicit X11EventSource(XDisplay* display);
- ~X11EventSource() override;
+ X11EventSourceDelegate() = default;
+
+ // Processes (if necessary) and handles dispatching XEvents.
+ virtual void ProcessXEvent(XEvent* xevent) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(X11EventSourceDelegate);
+};
+
+// Receives X11 events and sends them to X11EventSourceDelegate. Handles
+// receiving, pre-process and post-processing XEvents.
+class EVENTS_EXPORT X11EventSource {
+ public:
+ X11EventSource(X11EventSourceDelegate* delegate, XDisplay* display);
+ ~X11EventSource();
static X11EventSource* GetInstance();
- // Called by the glib source dispatch function. Processes all (if any)
+ // Called when there is a new XEvent available. Processes all (if any)
// available X events.
void DispatchXEvents();
@@ -46,26 +57,31 @@ class EVENTS_EXPORT X11EventSource : public PlatformEventSource {
// functions which require a mapped window.
void BlockUntilWindowMapped(XID window);
- protected:
XDisplay* display() { return display_; }
- private:
+ void StopCurrentEventStream();
+ void OnDispatcherListChanged();
+
+ protected:
// Extracts cookie data from |xevent| if it's of GenericType, and dispatches
// the event. This function also frees up the cookie data after dispatch is
// complete.
- uint32_t ExtractCookieDataDispatchEvent(XEvent* xevent);
+ void ExtractCookieDataDispatchEvent(XEvent* xevent);
+
+ // Handles updates after event has been dispatched.
+ void PostDispatchEvent(XEvent* xevent);
+
+ private:
+ static X11EventSource* instance_;
- // PlatformEventSource:
- uint32_t DispatchEvent(XEvent* xevent) override;
- void StopCurrentEventStream() override;
- void OnDispatcherListChanged() override;
+ X11EventSourceDelegate* delegate_;
// The connection to the X11 server used to receive the events.
XDisplay* display_;
// Keeps track of whether this source should continue to dispatch all the
// available events.
- bool continue_stream_;
+ bool continue_stream_ = true;
scoped_ptr<X11HotplugEventHandler> hotplug_event_handler_;
diff --git a/chromium/ui/events/platform/x11/x11_event_source_glib.cc b/chromium/ui/events/platform/x11/x11_event_source_glib.cc
index 21516010811..1eb272a4f29 100644
--- a/chromium/ui/events/platform/x11/x11_event_source_glib.cc
+++ b/chromium/ui/events/platform/x11/x11_event_source_glib.cc
@@ -2,8 +2,7 @@
// 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/x11/x11_event_source.h"
+#include "ui/events/platform/x11/x11_event_source_glib.h"
#include <glib.h>
#include <X11/Xlib.h>
@@ -48,52 +47,52 @@ GSourceFuncs XSourceFuncs = {
NULL
};
-class X11EventSourceGlib : public X11EventSource {
- public:
- explicit X11EventSourceGlib(XDisplay* display)
- : X11EventSource(display),
- x_source_(NULL) {
- InitXSource(ConnectionNumber(display));
- }
-
- ~X11EventSourceGlib() override {
- g_source_destroy(x_source_);
- g_source_unref(x_source_);
- }
-
- private:
- void InitXSource(int fd) {
- CHECK(!x_source_);
- CHECK(display()) << "Unable to get connection to X server";
-
- x_poll_.reset(new GPollFD());
- x_poll_->fd = fd;
- x_poll_->events = G_IO_IN;
- x_poll_->revents = 0;
-
- GLibX11Source* glib_x_source = static_cast<GLibX11Source*>
- (g_source_new(&XSourceFuncs, sizeof(GLibX11Source)));
- glib_x_source->display = display();
- glib_x_source->poll_fd = x_poll_.get();
-
- x_source_ = glib_x_source;
- g_source_add_poll(x_source_, x_poll_.get());
- g_source_set_can_recurse(x_source_, TRUE);
- g_source_set_callback(x_source_, NULL, this, NULL);
- g_source_attach(x_source_, g_main_context_default());
- }
-
- // The GLib event source for X events.
- GSource* x_source_;
-
- // The poll attached to |x_source_|.
- scoped_ptr<GPollFD> x_poll_;
-
- DISALLOW_COPY_AND_ASSIGN(X11EventSourceGlib);
-};
-
} // namespace
+X11EventSourceGlib::X11EventSourceGlib(XDisplay* display)
+ : event_source_(this, display) {
+ InitXSource(ConnectionNumber(display));
+}
+
+X11EventSourceGlib::~X11EventSourceGlib() {
+ g_source_destroy(x_source_);
+ g_source_unref(x_source_);
+}
+
+void X11EventSourceGlib::ProcessXEvent(XEvent* xevent) {
+ DispatchEvent(xevent);
+}
+
+void X11EventSourceGlib::StopCurrentEventStream() {
+ event_source_.StopCurrentEventStream();
+}
+
+void X11EventSourceGlib::OnDispatcherListChanged() {
+ event_source_.OnDispatcherListChanged();
+}
+
+void X11EventSourceGlib::InitXSource(int fd) {
+ DCHECK(!x_source_);
+ DCHECK(event_source_.display()) << "Unable to get connection to X server";
+
+ x_poll_.reset(new GPollFD());
+ x_poll_->fd = fd;
+ x_poll_->events = G_IO_IN;
+ x_poll_->revents = 0;
+
+ GLibX11Source* glib_x_source = static_cast<GLibX11Source*>(
+ g_source_new(&XSourceFuncs, sizeof(GLibX11Source)));
+ glib_x_source->display = event_source_.display();
+ glib_x_source->poll_fd = x_poll_.get();
+
+ x_source_ = glib_x_source;
+ g_source_add_poll(x_source_, x_poll_.get());
+ g_source_set_can_recurse(x_source_, TRUE);
+ g_source_set_callback(x_source_, NULL, &event_source_, NULL);
+ g_source_attach(x_source_, g_main_context_default());
+}
+
+// static
scoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() {
return make_scoped_ptr(new X11EventSourceGlib(gfx::GetXDisplay()));
}
diff --git a/chromium/ui/events/platform/x11/x11_event_source_glib.h b/chromium/ui/events/platform/x11/x11_event_source_glib.h
new file mode 100644
index 00000000000..67a38b1b856
--- /dev/null
+++ b/chromium/ui/events/platform/x11/x11_event_source_glib.h
@@ -0,0 +1,53 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_GLIB_H_
+#define UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_GLIB_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/x/x11_types.h"
+
+typedef struct _GPollFD GPollFD;
+typedef struct _GSource GSource;
+
+namespace ui {
+
+// A PlatformEventSource implementation for X11. Dispatches XEvents and uses
+// Glib to be notified for incoming XEvents.
+class EVENTS_EXPORT X11EventSourceGlib : public X11EventSourceDelegate,
+ public PlatformEventSource {
+ public:
+ explicit X11EventSourceGlib(XDisplay* display);
+ ~X11EventSourceGlib() override;
+
+ // X11EventSourceDelegate:
+ void ProcessXEvent(XEvent* xevent) override;
+
+ private:
+ // PlatformEventSource:
+ void StopCurrentEventStream() override;
+ void OnDispatcherListChanged() override;
+
+ void InitXSource(int fd);
+
+ X11EventSource event_source_;
+
+ // The GLib event source for X events.
+ GSource* x_source_ = nullptr;
+
+ // The poll attached to |x_source_|.
+ scoped_ptr<GPollFD> x_poll_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11EventSourceGlib);
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_GLIB_H_
diff --git a/chromium/ui/events/platform/x11/x11_event_source_libevent.cc b/chromium/ui/events/platform/x11/x11_event_source_libevent.cc
index a3ff7a50f94..cf0e3d648f7 100644
--- a/chromium/ui/events/platform/x11/x11_event_source_libevent.cc
+++ b/chromium/ui/events/platform/x11/x11_event_source_libevent.cc
@@ -2,67 +2,198 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/events/platform/x11/x11_event_source_libevent.h"
#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
-#include "base/macros.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_libevent.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/x/events_x_utils.h"
namespace ui {
namespace {
-class X11EventSourceLibevent : public X11EventSource,
- public base::MessagePumpLibevent::Watcher {
- public:
- explicit X11EventSourceLibevent(XDisplay* display)
- : X11EventSource(display),
- initialized_(false) {
- AddEventWatcher();
+// Translates XI2 XEvent into a ui::Event.
+scoped_ptr<ui::Event> TranslateXI2EventToEvent(const XEvent& xev) {
+ EventType event_type = EventTypeFromXEvent(xev);
+ switch (event_type) {
+ case ET_KEY_PRESSED:
+ case ET_KEY_RELEASED:
+ return make_scoped_ptr(new KeyEvent(event_type,
+ KeyboardCodeFromXKeyEvent(&xev),
+ EventFlagsFromXEvent(xev)));
+ case ET_MOUSE_PRESSED:
+ case ET_MOUSE_MOVED:
+ case ET_MOUSE_DRAGGED:
+ case ET_MOUSE_RELEASED:
+ return make_scoped_ptr(
+ new MouseEvent(event_type, EventLocationFromXEvent(xev),
+ EventSystemLocationFromXEvent(xev),
+ EventTimeFromXEvent(xev), EventFlagsFromXEvent(xev),
+ GetChangedMouseButtonFlagsFromXEvent(xev)));
+ case ET_MOUSEWHEEL:
+ return make_scoped_ptr(new MouseWheelEvent(
+ GetMouseWheelOffsetFromXEvent(xev), EventLocationFromXEvent(xev),
+ EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
+ EventFlagsFromXEvent(xev),
+ GetChangedMouseButtonFlagsFromXEvent(xev)));
+ case ET_SCROLL_FLING_START:
+ case ET_SCROLL_FLING_CANCEL: {
+ float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal;
+ GetFlingDataFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
+ &y_offset_ordinal, nullptr);
+ return make_scoped_ptr(new ScrollEvent(
+ event_type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
+ EventFlagsFromXEvent(xev), x_offset, y_offset, x_offset_ordinal,
+ y_offset_ordinal, 0));
+ }
+ case ET_SCROLL: {
+ float x_offset, y_offset, x_offset_ordinal, y_offset_ordinal;
+ int finger_count;
+ GetScrollOffsetsFromXEvent(xev, &x_offset, &y_offset, &x_offset_ordinal,
+ &y_offset_ordinal, &finger_count);
+ return make_scoped_ptr(new ScrollEvent(
+ event_type, EventLocationFromXEvent(xev), EventTimeFromXEvent(xev),
+ EventFlagsFromXEvent(xev), x_offset, y_offset, x_offset_ordinal,
+ y_offset_ordinal, finger_count));
+ }
+ case ET_TOUCH_MOVED:
+ case ET_TOUCH_PRESSED:
+ case ET_TOUCH_CANCELLED:
+ case ET_TOUCH_RELEASED:
+ return make_scoped_ptr(
+ new TouchEvent(event_type, EventLocationFromXEvent(xev),
+ GetTouchIdFromXEvent(xev), EventTimeFromXEvent(xev)));
+ case ET_UNKNOWN:
+ return nullptr;
+ default:
+ break;
}
+ return nullptr;
+}
- ~X11EventSourceLibevent() override {
+// Translates a XEvent into a ui::Event.
+scoped_ptr<ui::Event> TranslateXEventToEvent(const XEvent& xev) {
+ int flags = EventFlagsFromXEvent(xev);
+ switch (xev.type) {
+ case LeaveNotify:
+ case EnterNotify:
+ // EnterNotify creates ET_MOUSE_MOVED. Mark as synthesized as this is
+ // not real mouse move event.
+ if (xev.type == EnterNotify)
+ flags |= EF_IS_SYNTHESIZED;
+ return make_scoped_ptr(
+ new MouseEvent(ET_MOUSE_MOVED, EventLocationFromXEvent(xev),
+ EventSystemLocationFromXEvent(xev),
+ EventTimeFromXEvent(xev), flags, 0));
+
+ case KeyPress:
+ case KeyRelease:
+ return make_scoped_ptr(new KeyEvent(
+ EventTypeFromXEvent(xev), KeyboardCodeFromXKeyEvent(&xev), flags));
+
+ case ButtonPress:
+ case ButtonRelease: {
+ switch (EventTypeFromXEvent(xev)) {
+ case ET_MOUSEWHEEL:
+ return make_scoped_ptr(new MouseWheelEvent(
+ GetMouseWheelOffsetFromXEvent(xev), EventLocationFromXEvent(xev),
+ EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
+ flags, 0));
+ case ET_MOUSE_PRESSED:
+ case ET_MOUSE_RELEASED:
+ return make_scoped_ptr(new MouseEvent(
+ EventTypeFromXEvent(xev), EventLocationFromXEvent(xev),
+ EventSystemLocationFromXEvent(xev), EventTimeFromXEvent(xev),
+ flags, GetChangedMouseButtonFlagsFromXEvent(xev)));
+ case ET_UNKNOWN:
+ // No event is created for X11-release events for mouse-wheel
+ // buttons.
+ break;
+ default:
+ NOTREACHED();
+ }
+ break;
+ }
+
+ case GenericEvent:
+ return TranslateXI2EventToEvent(xev);
}
+ return nullptr;
+}
- private:
- void AddEventWatcher() {
- if (initialized_)
- return;
- if (!base::MessageLoop::current())
- return;
-
- int fd = ConnectionNumber(display());
- base::MessageLoopForUI::current()->WatchFileDescriptor(fd, true,
- base::MessagePumpLibevent::WATCH_READ, &watcher_controller_, this);
- initialized_ = true;
- }
+} // namespace
- // PlatformEventSource:
- void OnDispatcherListChanged() override {
- AddEventWatcher();
- }
+X11EventSourceLibevent::X11EventSourceLibevent(XDisplay* display)
+ : event_source_(this, display) {
+ AddEventWatcher();
+}
+
+X11EventSourceLibevent::~X11EventSourceLibevent() {}
- // base::MessagePumpLibevent::Watcher:
- void OnFileCanReadWithoutBlocking(int fd) override {
- DispatchXEvents();
+void X11EventSourceLibevent::AddXEventDispatcher(XEventDispatcher* dispatcher) {
+ dispatchers_xevent_.AddObserver(dispatcher);
+}
+
+void X11EventSourceLibevent::RemoveXEventDispatcher(
+ XEventDispatcher* dispatcher) {
+ dispatchers_xevent_.RemoveObserver(dispatcher);
+}
+
+void X11EventSourceLibevent::ProcessXEvent(XEvent* xevent) {
+ scoped_ptr<ui::Event> translated_event = TranslateXEventToEvent(*xevent);
+ if (translated_event) {
+ DispatchEvent(translated_event.get());
+ } else {
+ // Only if we can't translate XEvent into ui::Event, try to dispatch XEvent
+ // directly to XEventDispatchers.
+ DispatchXEventToXEventDispatchers(xevent);
}
+}
- void OnFileCanWriteWithoutBlocking(int fd) override {
- NOTREACHED();
+void X11EventSourceLibevent::AddEventWatcher() {
+ if (initialized_)
+ return;
+ if (!base::MessageLoop::current())
+ return;
+
+ int fd = ConnectionNumber(event_source_.display());
+ base::MessageLoopForUI::current()->WatchFileDescriptor(
+ fd, true, base::MessagePumpLibevent::WATCH_READ, &watcher_controller_,
+ this);
+ initialized_ = true;
+}
+
+void X11EventSourceLibevent::DispatchXEventToXEventDispatchers(XEvent* xevent) {
+ if (dispatchers_xevent_.might_have_observers()) {
+ base::ObserverList<XEventDispatcher>::Iterator iter(&dispatchers_xevent_);
+ while (XEventDispatcher* dispatcher = iter.GetNext()) {
+ if (dispatcher->DispatchXEvent(xevent))
+ break;
+ }
}
+}
- base::MessagePumpLibevent::FileDescriptorWatcher watcher_controller_;
- bool initialized_;
+void X11EventSourceLibevent::StopCurrentEventStream() {
+ event_source_.StopCurrentEventStream();
+}
- DISALLOW_COPY_AND_ASSIGN(X11EventSourceLibevent);
-};
+void X11EventSourceLibevent::OnDispatcherListChanged() {
+ AddEventWatcher();
+ event_source_.OnDispatcherListChanged();
+}
-} // namespace
+void X11EventSourceLibevent::OnFileCanReadWithoutBlocking(int fd) {
+ event_source_.DispatchXEvents();
+}
-scoped_ptr<PlatformEventSource> PlatformEventSource::CreateDefault() {
- return make_scoped_ptr(new X11EventSourceLibevent(gfx::GetXDisplay()));
+void X11EventSourceLibevent::OnFileCanWriteWithoutBlocking(int fd) {
+ NOTREACHED();
}
} // namespace ui
diff --git a/chromium/ui/events/platform/x11/x11_event_source_libevent.h b/chromium/ui/events/platform/x11/x11_event_source_libevent.h
new file mode 100644
index 00000000000..b9f2eba9c8d
--- /dev/null
+++ b/chromium/ui/events/platform/x11/x11_event_source_libevent.h
@@ -0,0 +1,79 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_LIBEVENT_H_
+#define UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_LIBEVENT_H_
+
+#include "base/macros.h"
+#include "base/message_loop/message_pump_libevent.h"
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+
+namespace ui {
+
+// Interface for classes that want to receive XEvent directly. Only used with
+// Ozone X11 currently and only events that can't be translated into ui::Events
+// are sent via this path.
+class EVENTS_EXPORT XEventDispatcher {
+ public:
+ // Sends XEvent to XEventDispatcher for handling. Returns true if the XEvent
+ // was dispatched, otherwise false. After the first XEventDispatcher returns
+ // true XEvent dispatching stops.
+ virtual bool DispatchXEvent(XEvent* xevent) = 0;
+
+ protected:
+ virtual ~XEventDispatcher() {}
+};
+
+// A PlatformEventSource implementation for Ozone X11. Converts XEvents to
+// ui::Events before dispatching. For X11 specific events a separate list of
+// XEventDispatchers is maintained. Uses Libevent to be notified for incoming
+// XEvents.
+class EVENTS_EXPORT X11EventSourceLibevent
+ : public X11EventSourceDelegate,
+ public PlatformEventSource,
+ public base::MessagePumpLibevent::Watcher {
+ public:
+ explicit X11EventSourceLibevent(XDisplay* display);
+ ~X11EventSourceLibevent() override;
+
+ // Adds a XEvent dispatcher to the XEvent dispatcher list.
+ void AddXEventDispatcher(XEventDispatcher* dispatcher);
+
+ // Removes a XEvent dispatcher fERrom the XEvent dispatcher list.
+ void RemoveXEventDispatcher(XEventDispatcher* dispatcher);
+
+ // X11EventSourceDelegate:
+ void ProcessXEvent(XEvent* xevent) override;
+
+ private:
+ // Registers event watcher with Libevent.
+ void AddEventWatcher();
+
+ // Sends XEvent to registered XEventDispatchers.
+ void DispatchXEventToXEventDispatchers(XEvent* xevent);
+
+ // PlatformEventSource:
+ void StopCurrentEventStream() override;
+ void OnDispatcherListChanged() override;
+
+ // base::MessagePumpLibevent::Watcher:
+ void OnFileCanReadWithoutBlocking(int fd) override;
+ void OnFileCanWriteWithoutBlocking(int fd) override;
+
+ X11EventSource event_source_;
+
+ // Keep track of all XEventDispatcher to send XEvents directly to.
+ base::ObserverList<XEventDispatcher> dispatchers_xevent_;
+
+ base::MessagePumpLibevent::FileDescriptorWatcher watcher_controller_;
+ bool initialized_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(X11EventSourceLibevent);
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_LIBEVENT_H_
diff --git a/chromium/ui/events/platform/x11/x11_events_platform.gyp b/chromium/ui/events/platform/x11/x11_events_platform.gyp
index cb1bbcd39c0..a62472227af 100644
--- a/chromium/ui/events/platform/x11/x11_events_platform.gyp
+++ b/chromium/ui/events/platform/x11/x11_events_platform.gyp
@@ -20,13 +20,12 @@
'../../devices/events_devices.gyp:events_devices',
'../../events.gyp:events',
'../../events.gyp:events_base',
+ '../../x/events_x.gyp:events_x',
'../events_platform.gyp:events_platform',
],
'sources': [
'x11_event_source.cc',
'x11_event_source.h',
- 'x11_event_source_glib.cc',
- 'x11_event_source_libevent.cc',
'x11_hotplug_event_handler.cc',
'x11_hotplug_event_handler.h',
],
@@ -35,13 +34,15 @@
'dependencies': [
'../../../../build/linux/system.gyp:glib',
],
- 'sources!': [
- 'x11_event_source_libevent.cc',
+ 'sources': [
+ 'x11_event_source_glib.cc',
+ 'x11_event_source_glib.h',
],
}, {
# use_glib == 0
- 'sources!': [
- 'x11_event_source_glib.cc',
+ 'sources': [
+ 'x11_event_source_libevent.cc',
+ 'x11_event_source_libevent.h',
],
}],
],
diff --git a/chromium/ui/events/win/event_utils_win_unittest.cc b/chromium/ui/events/win/event_utils_win_unittest.cc
new file mode 100644
index 00000000000..a4efce4fa51
--- /dev/null
+++ b/chromium/ui/events/win/event_utils_win_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/event_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/win/window_impl.h"
+
+namespace ui {
+
+namespace {
+
+class TestWindow : public gfx::WindowImpl {
+ public:
+ TestWindow() {}
+ ~TestWindow() override {}
+
+ BOOL ProcessWindowMessage(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ LRESULT& result,
+ DWORD msg_map_id = 0) override {
+ return true;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestWindow);
+};
+
+MSG CreateEvent(UINT type, WORD x, WORD y, HWND hwnd) {
+ MSG event;
+ event.message = type;
+ event.hwnd = hwnd;
+ event.lParam = MAKELPARAM(x, y);
+ return event;
+}
+
+TEST(EventWinTest, EventSystemLocationFromNative) {
+ TestWindow test_window;
+ const WORD x_coord = 10;
+ const WORD y_coord = 20;
+ const WORD x_window_offset = 100;
+ const WORD y_window_offset = 100;
+ test_window.Init(nullptr,
+ gfx::Rect(x_window_offset, y_window_offset, 100, 100));
+ EXPECT_TRUE(test_window.hwnd() != nullptr);
+
+ {
+ MSG event =
+ CreateEvent(WM_MOUSEWHEEL, x_coord, y_coord, test_window.hwnd());
+ // Mouse wheel events already have screen coordinates so they should not be
+ // converted.
+ EXPECT_EQ(gfx::Point(x_coord, y_coord),
+ EventSystemLocationFromNative(event));
+ }
+
+ MSG event = CreateEvent(WM_LBUTTONDOWN, x_coord, y_coord, test_window.hwnd());
+ EXPECT_EQ(gfx::Point(x_coord + x_window_offset, y_coord + y_window_offset),
+ EventSystemLocationFromNative(event));
+}
+
+} // namespace
+
+} // namespace ui
diff --git a/chromium/ui/events/win/events_win.cc b/chromium/ui/events/win/events_win.cc
index 20c6e61b6ae..49b67400edd 100644
--- a/chromium/ui/events/win/events_win.cc
+++ b/chromium/ui/events/win/events_win.cc
@@ -260,7 +260,9 @@ gfx::Point EventSystemLocationFromNative(
const base::NativeEvent& native_event) {
POINT global_point = { static_cast<short>(LOWORD(native_event.lParam)),
static_cast<short>(HIWORD(native_event.lParam)) };
- ClientToScreen(native_event.hwnd, &global_point);
+ // Wheel events have position in screen coordinates.
+ if (!IsMouseWheelEvent(native_event))
+ ClientToScreen(native_event.hwnd, &global_point);
return gfx::Point(global_point);
}
@@ -322,24 +324,20 @@ int GetTouchId(const base::NativeEvent& xev) {
return 0;
}
-float GetTouchRadiusX(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 1.0;
-}
-
-float GetTouchRadiusY(const base::NativeEvent& native_event) {
- NOTIMPLEMENTED();
- return 1.0;
-}
-
float GetTouchAngle(const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
return 0.0;
}
-float GetTouchForce(const base::NativeEvent& native_event) {
+PointerDetails GetTouchPointerDetailsFromNative(
+ const base::NativeEvent& native_event) {
NOTIMPLEMENTED();
- return 0.0;
+ return PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
+ /* radius_x */ 1.0,
+ /* radius_y */ 1.0,
+ /* force */ 0.f,
+ /* tilt_x */ 0.f,
+ /* tilt_y */ 0.f);
}
bool GetScrollOffsets(const base::NativeEvent& native_event,
diff --git a/chromium/ui/events/x/BUILD.gn b/chromium/ui/events/x/BUILD.gn
index 23299469601..991ce6ec8c3 100644
--- a/chromium/ui/events/x/BUILD.gn
+++ b/chromium/ui/events/x/BUILD.gn
@@ -16,8 +16,5 @@ component("x") {
"//ui/events/devices",
"//ui/gfx/x",
]
- configs += [
- "//build/config/linux:glib",
- "//build/config/linux:x11",
- ]
+ configs += [ "//build/config/linux:x11" ]
}
diff --git a/chromium/ui/events/x/events_x.cc b/chromium/ui/events/x/events_x.cc
index 0f27922e090..9432a606b65 100644
--- a/chromium/ui/events/x/events_x.cc
+++ b/chromium/ui/events/x/events_x.cc
@@ -154,20 +154,18 @@ int GetTouchId(const base::NativeEvent& native_event) {
return GetTouchIdFromXEvent(*native_event);
}
-float GetTouchRadiusX(const base::NativeEvent& native_event) {
- return GetTouchRadiusXFromXEvent(*native_event);
-}
-
-float GetTouchRadiusY(const base::NativeEvent& native_event) {
- return GetTouchRadiusYFromXEvent(*native_event);
-}
-
float GetTouchAngle(const base::NativeEvent& native_event) {
return GetTouchAngleFromXEvent(*native_event);
}
-float GetTouchForce(const base::NativeEvent& native_event) {
- return GetTouchForceFromXEvent(*native_event);
+PointerDetails GetTouchPointerDetailsFromNative(
+ const base::NativeEvent& native_event) {
+ return PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
+ GetTouchRadiusXFromXEvent(*native_event),
+ GetTouchRadiusYFromXEvent(*native_event),
+ GetTouchForceFromXEvent(*native_event),
+ /* tilt_x */ 0.f,
+ /* tilt_y */ 0.f);
}
bool GetScrollOffsets(const base::NativeEvent& native_event,
diff --git a/chromium/ui/events/x/events_x_unittest.cc b/chromium/ui/events/x/events_x_unittest.cc
index 3073c8aa8d9..42f38a30e5b 100644
--- a/chromium/ui/events/x/events_x_unittest.cc
+++ b/chromium/ui/events/x/events_x_unittest.cc
@@ -241,9 +241,11 @@ TEST_F(EventsXTest, TouchEventBasic) {
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("10,10", ui::EventLocationFromNative(scoped_xevent).ToString());
EXPECT_EQ(GetTouchId(scoped_xevent), 0);
- EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.15f);
- EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.1f);
+ PointerDetails pointer_details =
+ GetTouchPointerDetailsFromNative(scoped_xevent);
+ EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
+ EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
// Touch update, with new orientation info.
valuators.clear();
@@ -254,9 +256,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
EXPECT_EQ(ui::ET_TOUCH_MOVED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("20,20", ui::EventLocationFromNative(scoped_xevent).ToString());
EXPECT_EQ(GetTouchId(scoped_xevent), 0);
- EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.25f);
- EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.1f);
+ pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
+ EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
+ EXPECT_FLOAT_EQ(pointer_details.force, 0.1f);
// Another touch with tracking id 6, touch id 1.
valuators.clear();
@@ -269,9 +272,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("200,200", ui::EventLocationFromNative(scoped_xevent).ToString());
EXPECT_EQ(GetTouchId(scoped_xevent), 1);
- EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 50);
EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.45f);
- EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.5f);
+ pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
+ EXPECT_FLOAT_EQ(pointer_details.radius_x, 50.0f);
+ EXPECT_FLOAT_EQ(pointer_details.force, 0.5f);
// Touch with tracking id 5 should have old radius/angle value and new pressue
// value.
@@ -282,9 +286,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("30,30", ui::EventLocationFromNative(scoped_xevent).ToString());
EXPECT_EQ(GetTouchId(scoped_xevent), 0);
- EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 10);
EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.25f);
- EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.05f);
+ pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
+ EXPECT_FLOAT_EQ(pointer_details.radius_x, 10.0f);
+ EXPECT_FLOAT_EQ(pointer_details.force, 0.05f);
// Touch with tracking id 6 should have old angle/pressure value and new
// radius value.
@@ -295,9 +300,10 @@ TEST_F(EventsXTest, TouchEventBasic) {
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ui::EventTypeFromNative(scoped_xevent));
EXPECT_EQ("200,200", ui::EventLocationFromNative(scoped_xevent).ToString());
EXPECT_EQ(GetTouchId(scoped_xevent), 1);
- EXPECT_EQ(GetTouchRadiusX(scoped_xevent), 25);
EXPECT_FLOAT_EQ(GetTouchAngle(scoped_xevent), 0.45f);
- EXPECT_FLOAT_EQ(GetTouchForce(scoped_xevent), 0.5f);
+ pointer_details = GetTouchPointerDetailsFromNative(scoped_xevent);
+ EXPECT_FLOAT_EQ(pointer_details.radius_x, 25.0f);
+ EXPECT_FLOAT_EQ(pointer_details.force, 0.5f);
}
int GetTouchIdForTrackingId(uint32_t tracking_id) {
diff --git a/chromium/ui/events/x/events_x_utils.cc b/chromium/ui/events/x/events_x_utils.cc
index 452c096a06a..64b652c7cfc 100644
--- a/chromium/ui/events/x/events_x_utils.cc
+++ b/chromium/ui/events/x/events_x_utils.cc
@@ -626,15 +626,22 @@ gfx::Vector2d GetMouseWheelOffsetFromXEvent(const XEvent& xev) {
int button = xev.type == GenericEvent ? EventButtonFromXEvent(xev)
: xev.xbutton.button;
+ // If this is an xinput1 scroll event from an xinput2 mouse then we need to
+ // block the legacy scroll events for the necessary axes.
+ int scroll_class_type =
+ DeviceDataManagerX11::GetInstance()->GetScrollClassDeviceDetail(xev);
+ bool xi2_vertical = scroll_class_type & SCROLL_TYPE_VERTICAL;
+ bool xi2_horizontal = scroll_class_type & SCROLL_TYPE_HORIZONTAL;
+
switch (button) {
case 4:
- return gfx::Vector2d(0, kWheelScrollAmount);
+ return gfx::Vector2d(0, xi2_vertical ? 0 : kWheelScrollAmount);
case 5:
- return gfx::Vector2d(0, -kWheelScrollAmount);
+ return gfx::Vector2d(0, xi2_vertical ? 0 : -kWheelScrollAmount);
case 6:
- return gfx::Vector2d(kWheelScrollAmount, 0);
+ return gfx::Vector2d(xi2_horizontal ? 0 : kWheelScrollAmount, 0);
case 7:
- return gfx::Vector2d(-kWheelScrollAmount, 0);
+ return gfx::Vector2d(xi2_horizontal ? 0 : -kWheelScrollAmount, 0);
default:
return gfx::Vector2d();
}
@@ -731,7 +738,7 @@ bool GetScrollOffsetsFromXEvent(const XEvent& xev,
return true;
}
- if (DeviceDataManagerX11::GetInstance()->GetScrollClassDeviceDetail(xev) !=
+ if (DeviceDataManagerX11::GetInstance()->GetScrollClassEventDetail(xev) !=
SCROLL_TYPE_NO_SCROLL) {
double x_scroll_offset, y_scroll_offset;
DeviceDataManagerX11::GetInstance()->GetScrollClassOffsets(
diff --git a/chromium/ui/events/x/events_x_utils.h b/chromium/ui/events/x/events_x_utils.h
index 15c4e387f82..0a07061ee17 100644
--- a/chromium/ui/events/x/events_x_utils.h
+++ b/chromium/ui/events/x/events_x_utils.h
@@ -16,16 +16,16 @@ typedef union _XEvent XEvent;
namespace ui {
-// Get the EventType from a XEvent.
+// Gets the EventType from a XEvent.
EVENTS_X_EXPORT EventType EventTypeFromXEvent(const XEvent& xev);
-// Get the EventFlags from a XEvent.
+// Gets the EventFlags from a XEvent.
EVENTS_X_EXPORT int EventFlagsFromXEvent(const XEvent& xev);
-// Get the timestamp from a XEvent.
+// Gets the timestamp from a XEvent.
EVENTS_X_EXPORT base::TimeDelta EventTimeFromXEvent(const XEvent& xev);
-// Get the location from a XEvent. The coordinate system of the resultant
+// Gets the location from a XEvent. The coordinate system of the resultant
// |Point| has the origin at top-left of the "root window". The nature of
// this "root window" and how it maps to platform-specific drawing surfaces is
// defined in ui/aura/root_window.* and ui/aura/window_tree_host*.
diff --git a/chromium/ui/file_manager/audio_player/js/compiled_resources.gyp b/chromium/ui/file_manager/audio_player/js/compiled_resources.gyp
index 9fd6e654008..98f6fa341fb 100644
--- a/chromium/ui/file_manager/audio_player/js/compiled_resources.gyp
+++ b/chromium/ui/file_manager/audio_player/js/compiled_resources.gyp
@@ -15,6 +15,7 @@
# Referenced in common/js/util.js.
'../../../webui/resources/js/cr/ui/dialogs.js',
'../../../webui/resources/js/load_time_data.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/util.js',
'../../file_manager/common/js/util.js',
'../../file_manager/common/js/async_util.js',
@@ -66,6 +67,7 @@
'../../../webui/resources/js/cr/ui/array_data_model.js',
'../../../webui/resources/js/cr/ui/dialogs.js',
'../../../webui/resources/js/load_time_data.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/util.js',
'../../file_manager/common/js/async_util.js',
'../../file_manager/common/js/file_type.js',
@@ -88,6 +90,7 @@
'../../file_manager/background/js/volume_manager.js',
'../../file_manager/foreground/js/volume_manager_wrapper.js',
'../elements/control_panel.js',
+ '../elements/track_info_panel.js',
'../elements/track_list.js',
'../elements/audio_player.js',
],
@@ -109,4 +112,3 @@
}
],
}
-
diff --git a/chromium/ui/file_manager/file_manager/background/js/compiled_resources.gyp b/chromium/ui/file_manager/file_manager/background/js/compiled_resources.gyp
index f1b735fa219..8232bc9155c 100644
--- a/chromium/ui/file_manager/file_manager/background/js/compiled_resources.gyp
+++ b/chromium/ui/file_manager/file_manager/background/js/compiled_resources.gyp
@@ -11,6 +11,7 @@
'../../../../webui/resources/js/load_time_data.js',
'../../../../webui/resources/js/cr.js',
'../../../../webui/resources/js/cr/ui.js',
+ '../../../../webui/resources/js/promise_resolver.js',
'../../../../webui/resources/js/util.js',
'../../../../webui/resources/js/cr/event_target.js',
'../../../../webui/resources/js/cr/ui/array_data_model.js',
diff --git a/chromium/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp b/chromium/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
index 5e8a0ac4e5f..8fd66ac5f4e 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
+++ b/chromium/ui/file_manager/file_manager/foreground/js/compiled_resources.gyp
@@ -11,6 +11,7 @@
'../../../../../third_party/jstemplate/compiled_resources.gyp:jstemplate',
'../../../../../ui/webui/resources/js/load_time_data.js',
'../../../../../ui/webui/resources/js/cr.js',
+ '../../../../../ui/webui/resources/js/promise_resolver.js',
'../../../../../ui/webui/resources/js/util.js',
'../../../../../ui/webui/resources/js/compiled_resources.gyp:i18n_template_no_process',
'../../../../../ui/webui/resources/js/event_tracker.js',
@@ -84,6 +85,7 @@
'./directory_contents.js',
'./directory_model.js',
'./directory_tree_naming_controller.js',
+ './elements_importer.js',
'./empty_folder_controller.js',
'./file_manager.js',
'./file_manager_commands.js',
@@ -122,6 +124,7 @@
'./ui/actions_submenu.js',
'./ui/banners.js',
'./ui/default_task_dialog.js',
+ './ui/details_container.js',
'./ui/dialog_footer.js',
'./ui/directory_tree.js',
'./ui/drag_selector.js',
@@ -130,18 +133,23 @@
'./ui/file_grid.js',
'./ui/file_list_selection_model.js',
'./ui/file_manager_ui.js',
+ './ui/file_metadata_formatter.js',
'./ui/file_table.js',
'./ui/file_table_list.js',
+ './ui/files_alert_dialog.js',
+ './ui/files_confirm_dialog.js',
'./ui/files_menu.js',
'./ui/gear_menu.js',
'./ui/list_container.js',
'./ui/location_line.js',
+ './ui/multi_file_details.js',
'./ui/multi_profile_share_dialog.js',
'./ui/progress_center_panel.js',
'./ui/providers_menu.js',
'./ui/scrollbar.js',
'./ui/search_box.js',
'./ui/share_dialog.js',
+ './ui/single_file_details.js',
'./ui/suggest_apps_dialog.js',
'./main_window_component.js',
'./volume_manager_wrapper.js',
diff --git a/chromium/ui/file_manager/gallery/js/compiled_resources.gyp b/chromium/ui/file_manager/gallery/js/compiled_resources.gyp
index 6a328428593..45747b5781a 100644
--- a/chromium/ui/file_manager/gallery/js/compiled_resources.gyp
+++ b/chromium/ui/file_manager/gallery/js/compiled_resources.gyp
@@ -14,6 +14,7 @@
'../../../webui/resources/js/cr/ui/array_data_model.js',
'../../../webui/resources/js/cr/ui/dialogs.js',
'../../../webui/resources/js/load_time_data.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/util.js',
'../../file_manager/common/js/util.js',
'../../file_manager/common/js/async_util.js',
@@ -64,6 +65,7 @@
'../../../../third_party/polymer/v1_0/components-chromium/paper-input/paper-input-extracted.js',
'../../../../third_party/polymer/v1_0/components-chromium/paper-progress/paper-progress-extracted.js',
'../../../../third_party/polymer/v1_0/components-chromium/paper-ripple/paper-ripple-extracted.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/util.js',
'../../../webui/resources/js/event_tracker.js',
'../../../webui/resources/js/load_time_data.js',
@@ -104,6 +106,7 @@
'../../file_manager/foreground/js/share_client.js',
'../../file_manager/foreground/js/thumbnail_loader.js',
'../../file_manager/foreground/js/ui/file_manager_dialog_base.js',
+ '../../file_manager/foreground/js/ui/files_confirm_dialog.js',
'../../file_manager/foreground/js/ui/share_dialog.js',
'../../file_manager/foreground/js/volume_manager_wrapper.js',
'../../file_manager/background/js/volume_manager.js',
diff --git a/chromium/ui/file_manager/video_player/js/compiled_resources.gyp b/chromium/ui/file_manager/video_player/js/compiled_resources.gyp
index 5123864cad1..749d44b1eb9 100644
--- a/chromium/ui/file_manager/video_player/js/compiled_resources.gyp
+++ b/chromium/ui/file_manager/video_player/js/compiled_resources.gyp
@@ -14,6 +14,7 @@
'../../../webui/resources/js/cr/ui/array_data_model.js',
# Referenced in common/js/util.js.
'../../../webui/resources/js/cr/ui/dialogs.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/load_time_data.js',
'../../../webui/resources/js/util.js',
'../../file_manager/common/js/util.js',
@@ -66,6 +67,7 @@
'../../../webui/resources/js/cr.js',
'../../../webui/resources/js/load_time_data.js',
'../../../webui/resources/js/event_tracker.js',
+ '../../../webui/resources/js/promise_resolver.js',
'../../../webui/resources/js/util.js',
'../../../webui/resources/js/cr/ui.js',
'../../../webui/resources/js/cr/event_target.js',
diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn
index f3c6236e5f9..bdff3e39588 100644
--- a/chromium/ui/gfx/BUILD.gn
+++ b/chromium/ui/gfx/BUILD.gn
@@ -42,6 +42,8 @@ component("gfx") {
"animation/animation_container_element.h",
"animation/animation_container_observer.h",
"animation/animation_delegate.h",
+ "animation/animation_mac.mm",
+ "animation/animation_win.cc",
"animation/linear_animation.cc",
"animation/linear_animation.h",
"animation/multi_animation.cc",
@@ -53,8 +55,6 @@ component("gfx") {
"animation/tween.cc",
"animation/tween.h",
"break_list.h",
- "buffer_format_util.cc",
- "buffer_format_util.h",
"codec/jpeg_codec.cc",
"codec/jpeg_codec.h",
"codec/png_codec.cc",
@@ -72,6 +72,8 @@ component("gfx") {
"display.h",
"display_change_notifier.cc",
"display_change_notifier.h",
+ "display_finder.cc",
+ "display_finder.h",
"display_observer.cc",
"display_observer.h",
"favicon_size.cc",
@@ -80,6 +82,7 @@ component("gfx") {
"font.h",
"font_fallback.h",
"font_fallback_linux.cc",
+ "font_fallback_linux.h",
"font_fallback_mac.mm",
"font_fallback_win.cc",
"font_fallback_win.h",
@@ -95,8 +98,6 @@ component("gfx") {
"font_render_params_win.cc",
"gdi_util.cc",
"gdi_util.h",
- "generic_shared_memory_id.cc",
- "generic_shared_memory_id.h",
"gfx_paths.cc",
"gfx_paths.h",
"icon_util.cc",
@@ -113,6 +114,7 @@ component("gfx") {
"image/image_skia.h",
"image/image_skia_rep.cc",
"image/image_skia_rep.h",
+ "image/image_skia_source.cc",
"image/image_skia_source.h",
"image/image_skia_util_ios.h",
"image/image_skia_util_ios.mm",
@@ -131,16 +133,15 @@ component("gfx") {
"linux_font_delegate.h",
"mac/coordinate_conversion.h",
"mac/coordinate_conversion.mm",
- "mac/io_surface.cc",
- "mac/io_surface.h",
"mac/nswindow_frame_controls.h",
"mac/nswindow_frame_controls.mm",
"mac/scoped_cocoa_disable_screen_updates.h",
- "native_widget_types.h",
"nine_image_painter.cc",
"nine_image_painter.h",
"path.cc",
"path.h",
+ "path_mac.h",
+ "path_mac.mm",
"path_win.cc",
"path_win.h",
"path_x11.cc",
@@ -173,8 +174,6 @@ component("gfx") {
"screen_aura.cc",
"screen_ios.mm",
"screen_mac.mm",
- "screen_win.cc",
- "screen_win.h",
"scrollbar_size.cc",
"scrollbar_size.h",
"selection_model.cc",
@@ -214,6 +213,10 @@ component("gfx") {
"win/dpi.h",
"win/hwnd_util.cc",
"win/hwnd_util.h",
+ "win/physical_size.cc",
+ "win/physical_size.h",
+ "win/rendering_window_manager.cc",
+ "win/rendering_window_manager.h",
"win/scoped_set_map_mode.h",
"win/singleton_hwnd.cc",
"win/singleton_hwnd.h",
@@ -233,8 +236,6 @@ component("gfx") {
"canvas_paint_mac.mm",
"canvas_skia.cc",
"canvas_skia_paint.h",
- "gpu_memory_buffer.cc",
- "gpu_memory_buffer.h",
"image/canvas_image_source.cc",
"image/canvas_image_source.h",
"image/image_skia_operations.cc",
@@ -251,8 +252,17 @@ component("gfx") {
"//build/config/compiler:no_size_t_to_int_warning",
]
+ # This is part of the gfx component in the component build.
defines = [ "GFX_IMPLEMENTATION" ]
+ public_deps = [
+ ":memory_buffer_sources",
+ ":native_widget_types",
+ "//base",
+ "//skia",
+ "//third_party/icu",
+ "//ui/gfx/geometry",
+ ]
deps = [
":gfx_export",
"//base",
@@ -263,12 +273,6 @@ component("gfx") {
"//third_party/harfbuzz-ng",
"//third_party/libpng",
"//third_party/zlib",
- "//ui/gfx/geometry",
- ]
- public_deps = [
- "//base",
- "//skia",
- "//third_party/icu",
]
# Text rendering conditions (complicated so separated out).
@@ -365,6 +369,8 @@ component("gfx") {
if (is_win) {
cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()), which is
# uninteresting.
+
+ libs = [ "setupapi.lib" ]
} else {
sources -= [
"gdi_util.cc",
@@ -412,10 +418,6 @@ component("gfx") {
sources -= [ "path_x11.cc" ]
}
- if (use_ozone) {
- sources += [ "native_pixmap_handle_ozone.h" ]
- }
-
if (use_cairo) {
configs += [ "//build/config/linux:pangocairo" ]
}
@@ -430,7 +432,6 @@ action("aggregate_vector_icons") {
"vector_icons/account_box.icon",
"vector_icons/account_child_invert.icon",
"vector_icons/apps.icon",
- "vector_icons/autofill.icon",
"vector_icons/autologin.icon",
"vector_icons/bar_close.1x.icon",
"vector_icons/bar_close.icon",
@@ -488,6 +489,8 @@ action("aggregate_vector_icons") {
"vector_icons/location_on.icon",
"vector_icons/menu_check.1x.icon",
"vector_icons/menu_check.icon",
+ "vector_icons/menu_radio_empty.icon",
+ "vector_icons/menu_radio_selected.icon",
"vector_icons/midi.icon",
"vector_icons/mixed_content.icon",
"vector_icons/mode_edit.icon",
@@ -529,14 +532,17 @@ action("aggregate_vector_icons") {
"vector_icons/tab_audio.icon",
"vector_icons/tab_audio_muting.1x.icon",
"vector_icons/tab_audio_muting.icon",
+ "vector_icons/tab_bluetooth_connected.icon",
"vector_icons/tab_close_hovered_pressed.1x.icon",
"vector_icons/tab_close_hovered_pressed.icon",
"vector_icons/tab_close_normal.1x.icon",
"vector_icons/tab_close_normal.icon",
"vector_icons/tab_media_capturing.icon",
"vector_icons/tab_media_recording.icon",
+ "vector_icons/tab_usb_connected.icon",
"vector_icons/tablet.icon",
"vector_icons/translate.icon",
+ "vector_icons/upgrade_menu_item.icon",
"vector_icons/warning.icon",
"vector_icons/warning_badge.icon",
"vector_icons/web.icon",
@@ -563,14 +569,86 @@ action("aggregate_vector_icons") {
]
args = [
+ # TODO(brettw) bug 535386: This should not take a directory as an input,
+ # but rather a response file listing the inputs or sometimes the build will
+ # be incorrect. In this case, Ninja won't be able to do proper dependency
+ # tracking since if a file is deleted, the command line will be the same
+ # and the action will not be re-run.
"--working_directory=" + rebase_path("vector_icons/"),
"--output_cc=" + rebase_path(vector_icons_cc_file, root_build_dir),
"--output_h=" + rebase_path(vector_icons_h_file, root_build_dir),
]
+
+ if (is_mac) {
+ sources += [ "vector_icons/combobox_arrow_mac.icon" ]
+ }
}
# Looking for gfx_geometry? It's //ui/gfx/geometry:geometry
+# Depend on this to use native_widget_types.h without pulling in all of gfx.
+source_set("native_widget_types") {
+ public = [
+ "native_widget_types.h",
+ ]
+
+ public_deps = [
+ "//base",
+ ]
+}
+
+# The GPU memory buffer stuff is separate from "gfx" to allow GPU-related
+# things to use these files without pulling in all of gfx, which includes large
+# things like Skia.
+#
+# The structure here allows the memory buffer to be part of the gfx component
+# in the component build, but be a separate source set in a static build.
+group("memory_buffer") {
+ if (is_component_build) {
+ public_deps = [
+ ":gfx",
+ ]
+ } else {
+ public_deps = [
+ ":memory_buffer_sources",
+ ]
+ }
+}
+source_set("memory_buffer_sources") {
+ visibility = [ ":*" ] # Depend on through ":memory_buffer".
+
+ # TODO(brettw) refactor this so these sources are in a coherent directory
+ # structure rather than random samplings of ui/gfx and ui/gfx/mac.
+ sources = [
+ "buffer_format_util.cc",
+ "buffer_format_util.h",
+ "buffer_types.h",
+ "generic_shared_memory_id.cc",
+ "generic_shared_memory_id.h",
+ "gfx_export.h",
+ "mac/io_surface.cc",
+ "mac/io_surface.h",
+ ]
+
+ if (!is_ios) {
+ sources += [
+ "gpu_memory_buffer.cc",
+ "gpu_memory_buffer.h",
+ ]
+ }
+
+ if (use_ozone) {
+ sources += [ "native_pixmap_handle_ozone.h" ]
+ }
+
+ defines = [ "GFX_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ui/gfx/geometry",
+ ]
+}
+
source_set("test_support") {
testonly = true
sources = [
@@ -578,6 +656,7 @@ source_set("test_support") {
"image/image_unittest_util.h",
"image/image_unittest_util_ios.mm",
"image/image_unittest_util_mac.mm",
+ "test/display_util.h",
"test/fontconfig_util_linux.cc",
"test/fontconfig_util_linux.h",
"test/gfx_util.cc",
@@ -612,12 +691,14 @@ source_set("test_support") {
}
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("gfx_unittests_run") {
+bundle_data("gfx_unittests_bundle_data") {
testonly = true
- deps = [
- ":gfx_unittests",
+ sources = [
+ "test/data",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/" +
+ "{{source_root_relative_dir}}/{{source_file_part}}",
]
}
@@ -680,6 +761,7 @@ test("gfx_unittests") {
"image/image_util_unittest.cc",
"mac/coordinate_conversion_unittest.mm",
"nine_image_painter_unittest.cc",
+ "path_mac_unittest.mm",
"platform_font_mac_unittest.mm",
"range/range_mac_unittest.mm",
"range/range_unittest.cc",
@@ -702,6 +784,7 @@ test("gfx_unittests") {
deps = [
":gfx",
+ ":gfx_unittests_bundle_data",
":test_support",
"//base",
"//base/test:test_support",
diff --git a/chromium/ui/gfx/animation/animation.cc b/chromium/ui/gfx/animation/animation.cc
index 3c298285e13..4bc1b248aa7 100644
--- a/chromium/ui/gfx/animation/animation.cc
+++ b/chromium/ui/gfx/animation/animation.cc
@@ -10,10 +10,6 @@
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/rect.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
namespace gfx {
Animation::Animation(base::TimeDelta timer_interval)
@@ -92,21 +88,21 @@ void Animation::SetContainer(AnimationContainer* container) {
container_->Start(this);
}
+#if !defined(OS_WIN)
// static
bool Animation::ShouldRenderRichAnimation() {
-#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- BOOL result;
- // Get "Turn off all unnecessary animations" value.
- if (::SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &result, 0)) {
- return !!result;
- }
- }
- return !::GetSystemMetrics(SM_REMOTESESSION);
-#else
+ // Defined in platform specific file for Windows.
return true;
+}
#endif
+
+#if !defined(OS_WIN) && !defined(OS_MACOSX)
+// static
+bool Animation::ScrollAnimationsEnabledBySystem() {
+ // Defined in platform specific files for Windows and OSX.
+ return true;
}
+#endif
bool Animation::ShouldSendCanceledFromStop() {
return false;
diff --git a/chromium/ui/gfx/animation/animation.h b/chromium/ui/gfx/animation/animation.h
index 44823b0366f..8d8b4d0335b 100644
--- a/chromium/ui/gfx/animation/animation.h
+++ b/chromium/ui/gfx/animation/animation.h
@@ -64,6 +64,11 @@ class GFX_EXPORT Animation : public AnimationContainerElement {
// to give guidance for heavy animations such as "start download" arrow.
static bool ShouldRenderRichAnimation();
+ // Determines on a per-platform basis whether scroll animations (e.g. produced
+ // by home/end key) should be enabled. Should only be called from the browser
+ // process.
+ static bool ScrollAnimationsEnabledBySystem();
+
protected:
// Invoked from Start to allow subclasses to prepare for the animation.
virtual void AnimationStarted() {}
diff --git a/chromium/ui/gfx/animation/animation_mac.mm b/chromium/ui/gfx/animation/animation_mac.mm
new file mode 100644
index 00000000000..e3a4ff2ab0f
--- /dev/null
+++ b/chromium/ui/gfx/animation/animation_mac.mm
@@ -0,0 +1,33 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/animation/animation.h"
+
+#include "base/mac/mac_util.h"
+#include "base/message_loop/message_loop.h"
+
+namespace gfx {
+
+// static
+bool Animation::ScrollAnimationsEnabledBySystem() {
+ // Because of sandboxing, OS settings should only be queried from the browser
+ // process.
+ DCHECK(base::MessageLoopForUI::IsCurrent() ||
+ base::MessageLoopForIO::IsCurrent());
+
+ bool enabled = false;
+ id value = nil;
+ if (base::mac::IsOSMountainLionOrLater()) {
+ value = [[NSUserDefaults standardUserDefaults]
+ objectForKey:@"NSScrollAnimationEnabled"];
+ } else {
+ value = [[NSUserDefaults standardUserDefaults]
+ objectForKey:@"AppleScrollAnimationEnabled"];
+ }
+ if (value)
+ enabled = [value boolValue];
+ return enabled;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/animation/animation_win.cc b/chromium/ui/gfx/animation/animation_win.cc
new file mode 100644
index 00000000000..b8a7d2880a7
--- /dev/null
+++ b/chromium/ui/gfx/animation/animation_win.cc
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/animation/animation.h"
+
+#include "base/win/windows_version.h"
+
+namespace gfx {
+
+// static
+bool Animation::ShouldRenderRichAnimation() {
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ BOOL result;
+ // Get "Turn off all unnecessary animations" value.
+ if (::SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &result, 0)) {
+ return !!result;
+ }
+ }
+ return !::GetSystemMetrics(SM_REMOTESESSION);
+}
+
+// static
+bool Animation::ScrollAnimationsEnabledBySystem() {
+ return ShouldRenderRichAnimation();
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/animation/multi_animation.h b/chromium/ui/gfx/animation/multi_animation.h
index fd28e386493..a74656989ea 100644
--- a/chromium/ui/gfx/animation/multi_animation.h
+++ b/chromium/ui/gfx/animation/multi_animation.h
@@ -33,11 +33,12 @@ class GFX_EXPORT MultiAnimation : public Animation {
// for 200ms with a % between .25 and .75 use the following three values: 200,
// 100, 400.
struct Part {
- Part() : time_ms(0), start_time_ms(0), end_time_ms(0), type(Tween::ZERO) {}
- Part(int time_ms, Tween::Type type)
+ Part() : Part(0, Tween::ZERO) {}
+ Part(int time_ms, Tween::Type type) : Part(time_ms, 0, time_ms, type) {}
+ Part(int time_ms, int start_time_ms, int end_time_ms, Tween::Type type)
: time_ms(time_ms),
- start_time_ms(0),
- end_time_ms(time_ms),
+ start_time_ms(start_time_ms),
+ end_time_ms(end_time_ms),
type(type) {}
int time_ms;
diff --git a/chromium/ui/gfx/animation/multi_animation_unittest.cc b/chromium/ui/gfx/animation/multi_animation_unittest.cc
index b8a11fdacf2..f8bff9a0f0b 100644
--- a/chromium/ui/gfx/animation/multi_animation_unittest.cc
+++ b/chromium/ui/gfx/animation/multi_animation_unittest.cc
@@ -40,9 +40,7 @@ TEST(MultiAnimationTest, Basic) {
TEST(MultiAnimationTest, DifferingStartAndEnd) {
// Create a MultiAnimation with two parts.
MultiAnimation::Parts parts;
- parts.push_back(MultiAnimation::Part(200, Tween::LINEAR));
- parts[0].start_time_ms = 100;
- parts[0].end_time_ms = 400;
+ parts.push_back(MultiAnimation::Part(200, 100, 400, Tween::LINEAR));
MultiAnimation animation(parts, MultiAnimation::GetDefaultTimerInterval());
AnimationContainerElement* as_element =
diff --git a/chromium/ui/gfx/blit_unittest.cc b/chromium/ui/gfx/blit_unittest.cc
index e6245916f76..7598ef65828 100644
--- a/chromium/ui/gfx/blit_unittest.cc
+++ b/chromium/ui/gfx/blit_unittest.cc
@@ -21,7 +21,7 @@ namespace {
// 0x00000000 0x01010101
// 0x12121212 0xFFFFFFFF
template <int w, int h>
-void SetToCanvas(skia::PlatformCanvas* canvas, uint8_t values[h][w]) {
+void SetToCanvas(SkCanvas* canvas, uint8_t values[h][w]) {
ASSERT_EQ(w, canvas->imageInfo().width());
ASSERT_EQ(h, canvas->imageInfo().height());
@@ -44,7 +44,7 @@ void SetToCanvas(skia::PlatformCanvas* canvas, uint8_t values[h][w]) {
// values, where each value has been duplicated into each channel of the given
// bitmap (see SetToCanvas above).
template <int w, int h>
-void VerifyCanvasValues(skia::PlatformCanvas* canvas, uint8_t values[h][w]) {
+void VerifyCanvasValues(SkCanvas* canvas, uint8_t values[h][w]) {
SkBitmap bitmap = skia::ReadPixels(canvas);
SkAutoLockPixels lock(bitmap);
ASSERT_EQ(w, bitmap.width());
@@ -64,7 +64,7 @@ void VerifyCanvasValues(skia::PlatformCanvas* canvas, uint8_t values[h][w]) {
TEST(Blit, ScrollCanvas) {
static const int kCanvasWidth = 5;
static const int kCanvasHeight = 5;
- skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(
+ sk_sp<SkCanvas> canvas(
skia::CreatePlatformCanvas(kCanvasWidth, kCanvasHeight, true));
uint8_t initial_values[kCanvasHeight][kCanvasWidth] = {
{0x00, 0x01, 0x02, 0x03, 0x04},
@@ -152,7 +152,7 @@ TEST(Blit, WithSharedMemory) {
base::SharedMemory shared_mem;
ASSERT_TRUE(shared_mem.CreateAnonymous(kCanvasWidth * kCanvasHeight));
base::SharedMemoryHandle section = shared_mem.handle();
- skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(skia::CreatePlatformCanvas(
+ sk_sp<SkCanvas> canvas(skia::CreatePlatformCanvas(
kCanvasWidth, kCanvasHeight, true, section.GetHandle(),
skia::RETURN_NULL_ON_FAILURE));
ASSERT_TRUE(canvas);
diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc
index 459a0e69b59..b88fd2d5512 100644
--- a/chromium/ui/gfx/canvas.cc
+++ b/chromium/ui/gfx/canvas.cc
@@ -10,6 +10,7 @@
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/rect.h"
@@ -24,18 +25,16 @@
namespace gfx {
Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
- : image_scale_(image_scale),
- canvas_(NULL) {
+ : image_scale_(image_scale) {
Size pixel_size = ScaleToCeiledSize(size, image_scale);
- owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
- pixel_size.height(),
- is_opaque));
- canvas_ = owned_canvas_.get();
+ canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
+ pixel_size.height(),
+ is_opaque));
#if !defined(USE_CAIRO)
// skia::PlatformCanvas instances are initialized to 0 by Cairo, but
// uninitialized on other platforms.
if (!is_opaque)
- owned_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
+ canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
#endif
SkScalar scale_scalar = SkFloatToScalar(image_scale);
@@ -44,11 +43,10 @@ Canvas::Canvas(const Size& size, float image_scale, bool is_opaque)
Canvas::Canvas(const ImageSkiaRep& image_rep, bool is_opaque)
: image_scale_(image_rep.scale()),
- owned_canvas_(skia::AdoptRef(
+ canvas_(skia::AdoptRef(
skia::CreatePlatformCanvas(image_rep.pixel_width(),
image_rep.pixel_height(),
- is_opaque))),
- canvas_(owned_canvas_.get()) {
+ is_opaque))) {
SkScalar scale_scalar = SkFloatToScalar(image_scale_);
canvas_->scale(scale_scalar, scale_scalar);
DrawImageInt(ImageSkia(image_rep), 0, 0);
@@ -56,11 +54,10 @@ Canvas::Canvas(const ImageSkiaRep& image_rep, bool is_opaque)
Canvas::Canvas()
: image_scale_(1.f),
- owned_canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))),
- canvas_(owned_canvas_.get()) {}
+ canvas_(skia::AdoptRef(skia::CreatePlatformCanvas(0, 0, false))) {}
-Canvas::Canvas(SkCanvas* canvas, float image_scale)
- : image_scale_(image_scale), owned_canvas_(), canvas_(canvas) {
+Canvas::Canvas(const skia::RefPtr<SkCanvas>& canvas, float image_scale)
+ : image_scale_(image_scale), canvas_(canvas) {
DCHECK(canvas);
}
@@ -72,10 +69,9 @@ void Canvas::RecreateBackingCanvas(const Size& size,
bool is_opaque) {
image_scale_ = image_scale;
Size pixel_size = ScaleToFlooredSize(size, image_scale);
- owned_canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
- pixel_size.height(),
- is_opaque));
- canvas_ = owned_canvas_.get();
+ canvas_ = skia::AdoptRef(skia::CreatePlatformCanvas(pixel_size.width(),
+ pixel_size.height(),
+ is_opaque));
SkScalar scale_scalar = SkFloatToScalar(image_scale);
canvas_->scale(scale_scalar, scale_scalar);
}
@@ -157,16 +153,10 @@ void Canvas::DrawDashedRect(const Rect& rect, SkColor color) {
}
}
- // Make a shader for the bitmap with an origin of the box we'll draw. This
- // shader is refcounted and will have an initial refcount of 1.
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkShader::CreateBitmapShader(
- *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
- // Assign the shader to the paint & release our reference. The paint will
- // now own the shader and the shader will be destroyed when the paint goes
- // out of scope.
+ // Make a shader for the bitmap with an origin of the box we'll draw.
SkPaint paint;
- paint.setShader(shader.get());
+ paint.setShader(SkShader::MakeBitmapShader(*dots, SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode));
DrawRect(Rect(rect.x(), rect.y(), rect.width(), 1), paint);
DrawRect(Rect(rect.x(), rect.y() + rect.height() - 1, rect.width(), 1),
@@ -428,13 +418,10 @@ void Canvas::DrawImageInPath(const ImageSkia& image,
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
- skia::RefPtr<SkShader> shader = CreateImageRepShader(
- image_rep,
- SkShader::kRepeat_TileMode,
- matrix);
-
SkPaint p(paint);
- p.setShader(shader.get());
+ p.setShader(CreateImageRepShader(image_rep,
+ SkShader::kRepeat_TileMode,
+ matrix));
canvas_->drawPath(path, p);
}
@@ -482,12 +469,30 @@ void Canvas::TileImageInt(const ImageSkia& image,
int dest_y,
int w,
int h) {
- if (!IntersectsClipRectInt(dest_x, dest_y, w, h))
+ SkRect dest_rect = { SkIntToScalar(dest_x),
+ SkIntToScalar(dest_y),
+ SkIntToScalar(dest_x + w),
+ SkIntToScalar(dest_y + h) };
+ if (!IntersectsClipRect(dest_rect))
return;
+ SkPaint paint;
+ if (InitSkPaintForTiling(image, src_x, src_y, tile_scale_x, tile_scale_y,
+ dest_x, dest_y, &paint))
+ canvas_->drawRect(dest_rect, paint);
+}
+
+bool Canvas::InitSkPaintForTiling(const ImageSkia& image,
+ int src_x,
+ int src_y,
+ float tile_scale_x,
+ float tile_scale_y,
+ int dest_x,
+ int dest_y,
+ SkPaint* paint) {
const ImageSkiaRep& image_rep = image.GetRepresentation(image_scale_);
if (image_rep.is_null())
- return;
+ return false;
SkMatrix shader_scale;
shader_scale.setScale(SkFloatToScalar(tile_scale_x),
@@ -495,36 +500,19 @@ void Canvas::TileImageInt(const ImageSkia& image,
shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
- skia::RefPtr<SkShader> shader = CreateImageRepShader(
- image_rep,
- SkShader::kRepeat_TileMode,
- shader_scale);
-
- SkPaint paint;
- paint.setShader(shader.get());
- paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
-
- SkRect dest_rect = { SkIntToScalar(dest_x),
- SkIntToScalar(dest_y),
- SkIntToScalar(dest_x + w),
- SkIntToScalar(dest_y + h) };
- canvas_->drawRect(dest_rect, paint);
+ paint->setShader(CreateImageRepShader(image_rep, SkShader::kRepeat_TileMode,
+ shader_scale));
+ paint->setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ return true;
}
void Canvas::Transform(const gfx::Transform& transform) {
canvas_->concat(transform.matrix());
}
-bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) {
+bool Canvas::IntersectsClipRect(const SkRect& rect) {
SkRect clip;
- return canvas_->getClipBounds(&clip) &&
- clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w),
- SkIntToScalar(y + h));
-}
-
-bool Canvas::IntersectsClipRect(const Rect& rect) {
- return IntersectsClipRectInt(rect.x(), rect.y(),
- rect.width(), rect.height());
+ return canvas_->getClipBounds(&clip) && clip.intersects(rect);
}
void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep,
@@ -546,16 +534,15 @@ void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep,
return;
}
- if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h))
- return;
-
- float user_scale_x = static_cast<float>(dest_w) / src_w;
- float user_scale_y = static_cast<float>(dest_h) / src_h;
-
SkRect dest_rect = { SkIntToScalar(dest_x),
SkIntToScalar(dest_y),
SkIntToScalar(dest_x + dest_w),
SkIntToScalar(dest_y + dest_h) };
+ if (!IntersectsClipRect(dest_rect))
+ return;
+
+ float user_scale_x = static_cast<float>(dest_w) / src_w;
+ float user_scale_y = static_cast<float>(dest_h) / src_h;
// Make a bitmap shader that contains the bitmap we want to draw. This is
// basically what SkCanvas.drawBitmap does internally, but it gives us
@@ -567,15 +554,11 @@ void Canvas::DrawImageIntHelper(const ImageSkiaRep& image_rep,
shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y));
shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y));
- skia::RefPtr<SkShader> shader = CreateImageRepShaderForScale(
- image_rep, SkShader::kRepeat_TileMode, shader_scale,
- remove_image_scale ? image_rep.scale() : 1.f);
-
- // Set up our paint to use the shader & release our reference (now just owned
- // by the paint).
SkPaint p(paint);
p.setFilterQuality(filter ? kLow_SkFilterQuality : kNone_SkFilterQuality);
- p.setShader(shader.get());
+ p.setShader(CreateImageRepShaderForScale(
+ image_rep, SkShader::kRepeat_TileMode, shader_scale,
+ remove_image_scale ? image_rep.scale() : 1.f));
// The rect will be filled by the bitmap.
canvas_->drawRect(dest_rect, p);
diff --git a/chromium/ui/gfx/canvas.h b/chromium/ui/gfx/canvas.h
index 311cf38830c..367aa8a7441 100644
--- a/chromium/ui/gfx/canvas.h
+++ b/chromium/ui/gfx/canvas.h
@@ -89,7 +89,7 @@ class GFX_EXPORT Canvas {
// Creates a Canvas backed by an |sk_canvas| with |image_scale_|.
// |sk_canvas| is assumed to be already scaled based on |image_scale|
// so no additional scaling is applied.
- Canvas(SkCanvas* sk_canvas, float image_scale);
+ Canvas(const skia::RefPtr<SkCanvas>& sk_canvas, float image_scale);
virtual ~Canvas();
@@ -399,6 +399,18 @@ class GFX_EXPORT Canvas {
int w,
int h);
+ // Helper for TileImageInt(). Initializes |paint| for tiling |image| with the
+ // given parameters. Returns false if the provided image does not have a
+ // representation for the current scale.
+ bool InitSkPaintForTiling(const ImageSkia& image,
+ int src_x,
+ int src_y,
+ float tile_scale_x,
+ float tile_scale_y,
+ int dest_x,
+ int dest_y,
+ SkPaint* paint);
+
// Apply transformation on the canvas.
void Transform(const Transform& transform);
@@ -409,14 +421,12 @@ class GFX_EXPORT Canvas {
const Rect& display_rect,
int flags);
- skia::PlatformCanvas* platform_canvas() { return owned_canvas_.get(); }
- SkCanvas* sk_canvas() { return canvas_; }
+ SkCanvas* sk_canvas() { return canvas_.get(); }
float image_scale() const { return image_scale_; }
private:
- // Test whether the provided rectangle intersects the current clip rect.
- bool IntersectsClipRectInt(int x, int y, int w, int h);
- bool IntersectsClipRect(const Rect& rect);
+ // Tests whether the provided rectangle intersects the current clip rect.
+ bool IntersectsClipRect(const SkRect& rect);
// Helper for the DrawImageInt functions declared above. The
// |remove_image_scale| parameter indicates if the scale of the |image_rep|
@@ -439,8 +449,7 @@ class GFX_EXPORT Canvas {
// Canvas::Scale() does not affect |image_scale_|.
float image_scale_;
- skia::RefPtr<skia::PlatformCanvas> owned_canvas_;
- SkCanvas* canvas_;
+ skia::RefPtr<SkCanvas> canvas_;
DISALLOW_COPY_AND_ASSIGN(Canvas);
};
diff --git a/chromium/ui/gfx/canvas_paint_mac.h b/chromium/ui/gfx/canvas_paint_mac.h
index b8d9974db9f..1623b4baed9 100644
--- a/chromium/ui/gfx/canvas_paint_mac.h
+++ b/chromium/ui/gfx/canvas_paint_mac.h
@@ -43,7 +43,6 @@ class GFX_EXPORT CanvasSkiaPaint : public Canvas {
private:
void Init(bool opaque);
- CGContext* context_;
NSRect rectangle_;
// See description above setter.
bool composite_alpha_;
diff --git a/chromium/ui/gfx/canvas_paint_mac.mm b/chromium/ui/gfx/canvas_paint_mac.mm
index cc1c6a4f744..29fdfe5ecf8 100644
--- a/chromium/ui/gfx/canvas_paint_mac.mm
+++ b/chromium/ui/gfx/canvas_paint_mac.mm
@@ -8,25 +8,25 @@
namespace gfx {
CanvasSkiaPaint::CanvasSkiaPaint(NSRect dirtyRect)
- : context_(NULL),
- rectangle_(dirtyRect),
+ : rectangle_(dirtyRect),
composite_alpha_(false) {
Init(true);
}
CanvasSkiaPaint::CanvasSkiaPaint(NSRect dirtyRect, bool opaque)
- : context_(NULL),
- rectangle_(dirtyRect),
+ : rectangle_(dirtyRect),
composite_alpha_(false) {
Init(opaque);
}
CanvasSkiaPaint::~CanvasSkiaPaint() {
if (!is_empty()) {
- platform_canvas()->restoreToCount(1);
+ SkCanvas* canvas = sk_canvas();
+ canvas->restoreToCount(1);
// Blit the dirty rect to the current context.
- CGImageRef image = CGBitmapContextCreateImage(context_);
+ CGImageRef image =
+ CGBitmapContextCreateImage(skia::GetBitmapContext(*canvas));
CGRect dest_rect = NSRectToCGRect(rectangle_);
CGContextRef destination_context =
@@ -60,15 +60,13 @@ void CanvasSkiaPaint::Init(bool opaque) {
gfx::Size size(NSWidth(rectangle_), NSHeight(rectangle_));
RecreateBackingCanvas(size, scale, opaque);
- skia::PlatformCanvas* canvas = platform_canvas();
+ SkCanvas* canvas = sk_canvas();
canvas->clear(SkColorSetARGB(0, 0, 0, 0));
// Need to translate so that the dirty region appears at the origin of the
// surface.
canvas->translate(-SkDoubleToScalar(NSMinX(rectangle_)),
-SkDoubleToScalar(NSMinY(rectangle_)));
-
- context_ = skia::GetBitmapContext(*canvas);
}
} // namespace skia
diff --git a/chromium/ui/gfx/canvas_skia.cc b/chromium/ui/gfx/canvas_skia.cc
index 8f45fce059c..d20f92fe56d 100644
--- a/chromium/ui/gfx/canvas_skia.cc
+++ b/chromium/ui/gfx/canvas_skia.cc
@@ -21,6 +21,7 @@
#include "ui/gfx/range/range.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/shadow_value.h"
+#include "ui/gfx/skia_util.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
@@ -187,7 +188,7 @@ void Canvas::DrawStringRectWithShadows(const base::string16& text,
int line_height,
int flags,
const ShadowValues& shadows) {
- if (!IntersectsClipRect(text_bounds))
+ if (!IntersectsClipRect(RectToSkRect(text_bounds)))
return;
Rect clip_rect(text_bounds);
diff --git a/chromium/ui/gfx/color_palette.h b/chromium/ui/gfx/color_palette.h
index f39e4437922..cb7271ac5aa 100644
--- a/chromium/ui/gfx/color_palette.h
+++ b/chromium/ui/gfx/color_palette.h
@@ -27,6 +27,15 @@ const SkColor kGoogleGreen700 = SkColorSetRGB(0x0B, 0x80, 0x43);
const SkColor kGoogleYellow300 = SkColorSetRGB(0xF7, 0xCB, 0x4D);
const SkColor kGoogleYellow700 = SkColorSetRGB(0xF0, 0x93, 0x00);
+// Material Design canonical colors, from
+// https://www.google.com/design/spec/style/color.html#color-color-palette
+const SkColor kMaterialBlue300 = SkColorSetRGB(0x64, 0xB5, 0xF6);
+const SkColor kMaterialBlue500 = SkColorSetRGB(0x21, 0x96, 0xF3);
+const SkColor kMaterialBlue700 = SkColorSetRGB(0x19, 0x76, 0xD2);
+
+const SkColor kMaterialGrey300 = SkColorSetRGB(0xE0, 0xE0, 0xE0);
+const SkColor kMaterialGrey500 = SkColorSetRGB(0x9E, 0x9E, 0x9E);
+
} // namespace gfx
#endif // UI_GFX_COLOR_PALETTE_H_
diff --git a/chromium/ui/gfx/color_utils.cc b/chromium/ui/gfx/color_utils.cc
index f30c266e1be..a4618f27e66 100644
--- a/chromium/ui/gfx/color_utils.cc
+++ b/chromium/ui/gfx/color_utils.cc
@@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -41,35 +42,21 @@ int calcHue(double temp1, double temp2, double hue) {
else if (hue * 3.0 < 2.0)
result = temp1 + (temp2 - temp1) * (2.0 / 3.0 - hue) * 6.0;
- // Scale the result from 0 - 255 and round off the value.
- return static_cast<int>(result * 255 + .5);
+ return static_cast<int>(std::round(result * 255));
}
-// Next two functions' formulas from:
-// http://www.w3.org/TR/WCAG20/#relativeluminancedef
-// http://www.w3.org/TR/WCAG20/#contrast-ratiodef
-
-double ConvertSRGB(double eight_bit_component) {
+// Assumes sRGB.
+double Linearize(double eight_bit_component) {
const double component = eight_bit_component / 255.0;
return (component <= 0.03928) ?
(component / 12.92) : pow((component + 0.055) / 1.055, 2.4);
}
-SkColor LumaInvertColor(SkColor color) {
+SkColor LightnessInvertColor(SkColor color) {
HSL hsl;
SkColorToHSL(color, &hsl);
hsl.l = 1.0 - hsl.l;
- return HSLToSkColor(hsl, 255);
-}
-
-double ContrastRatio(double foreground_luminance, double background_luminance) {
- DCHECK_GE(foreground_luminance, 0.0);
- DCHECK_GE(background_luminance, 0.0);
- foreground_luminance += 0.05;
- background_luminance += 0.05;
- return (foreground_luminance > background_luminance) ?
- (foreground_luminance / background_luminance) :
- (background_luminance / foreground_luminance);
+ return HSLToSkColor(hsl, SkColorGetA(color));
}
} // namespace
@@ -78,20 +65,29 @@ double ContrastRatio(double foreground_luminance, double background_luminance) {
// ----------------------------------------------------------------------------
double GetContrastRatio(SkColor color_a, SkColor color_b) {
- return ContrastRatio(RelativeLuminance(color_a), RelativeLuminance(color_b));
+ return GetContrastRatio(GetRelativeLuminance(color_a),
+ GetRelativeLuminance(color_b));
}
-unsigned char GetLuminanceForColor(SkColor color) {
- return base::saturated_cast<unsigned char>(
- (0.3 * SkColorGetR(color)) +
- (0.59 * SkColorGetG(color)) +
- (0.11 * SkColorGetB(color)));
+double GetContrastRatio(double luminance_a, double luminance_b) {
+ DCHECK_GE(luminance_a, 0.0);
+ DCHECK_GE(luminance_b, 0.0);
+ luminance_a += 0.05;
+ luminance_b += 0.05;
+ return (luminance_a > luminance_b) ? (luminance_a / luminance_b)
+ : (luminance_b / luminance_a);
}
-double RelativeLuminance(SkColor color) {
- return (0.2126 * ConvertSRGB(SkColorGetR(color))) +
- (0.7152 * ConvertSRGB(SkColorGetG(color))) +
- (0.0722 * ConvertSRGB(SkColorGetB(color)));
+double GetRelativeLuminance(SkColor color) {
+ return (0.2126 * Linearize(SkColorGetR(color))) +
+ (0.7152 * Linearize(SkColorGetG(color))) +
+ (0.0722 * Linearize(SkColorGetB(color)));
+}
+
+uint8_t GetLuma(SkColor color) {
+ return static_cast<uint8_t>(std::round((0.299 * SkColorGetR(color)) +
+ (0.587 * SkColorGetG(color)) +
+ (0.114 * SkColorGetB(color))));
}
void SkColorToHSL(SkColor c, HSL* hsl) {
@@ -134,15 +130,8 @@ SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha) {
// If there's no color, we don't care about hue and can do everything based on
// brightness.
if (!saturation) {
- uint8_t light;
-
- if (lightness < 0)
- light = 0;
- else if (lightness >= 1.0)
- light = 255;
- else
- light = static_cast<uint8_t>(SkDoubleToFixed(lightness) >> 8);
-
+ const uint8_t light =
+ base::saturated_cast<uint8_t>(gfx::ToRoundedInt(lightness * 255));
return SkColorSetARGB(alpha, light, light, light);
}
@@ -150,10 +139,9 @@ SkColor HSLToSkColor(const HSL& hsl, SkAlpha alpha) {
(lightness * (1.0 + saturation)) :
(lightness + saturation - (lightness * saturation));
double temp1 = 2.0 * lightness - temp2;
- return SkColorSetARGB(alpha,
- calcHue(temp1, temp2, hue + 1.0 / 3.0),
- calcHue(temp1, temp2, hue),
- calcHue(temp1, temp2, hue - 1.0 / 3.0));
+ return SkColorSetARGB(alpha, calcHue(temp1, temp2, hue + 1.0 / 3.0),
+ calcHue(temp1, temp2, hue),
+ calcHue(temp1, temp2, hue - 1.0 / 3.0));
}
bool IsWithinHSLRange(const HSL& hsl,
@@ -249,7 +237,7 @@ void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]) {
int pixel_height = bitmap.height();
for (int y = 0; y < pixel_height; ++y) {
for (int x = 0; x < pixel_width; ++x)
- ++histogram[GetLuminanceForColor(bitmap.getColor(x, y))];
+ ++histogram[GetLuma(bitmap.getColor(x, y))];
}
}
@@ -287,35 +275,40 @@ SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) {
double b = (SkColorGetB(foreground) * f_weight +
SkColorGetB(background) * b_weight) / 255.0;
- return SkColorSetARGB(static_cast<int>(normalizer),
- static_cast<int>(r),
- static_cast<int>(g),
- static_cast<int>(b));
+ return SkColorSetARGB(static_cast<int>(std::round(normalizer)),
+ static_cast<int>(std::round(r)),
+ static_cast<int>(std::round(g)),
+ static_cast<int>(std::round(b)));
}
bool IsDark(SkColor color) {
- return GetLuminanceForColor(color) < 128;
+ return GetLuma(color) < 128;
}
-SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha) {
+SkColor BlendTowardOppositeLuma(SkColor color, SkAlpha alpha) {
return AlphaBlend(IsDark(color) ? SK_ColorWHITE : SK_ColorBLACK, color,
alpha);
}
SkColor GetReadableColor(SkColor foreground, SkColor background) {
- const SkColor foreground2 = LumaInvertColor(foreground);
- const double background_luminance = RelativeLuminance(background);
- return (ContrastRatio(RelativeLuminance(foreground), background_luminance) >=
- ContrastRatio(RelativeLuminance(foreground2), background_luminance)) ?
- foreground : foreground2;
+ return PickContrastingColor(foreground, LightnessInvertColor(foreground),
+ background);
+}
+
+SkColor PickContrastingColor(SkColor foreground1,
+ SkColor foreground2,
+ SkColor background) {
+ const double background_luminance = GetRelativeLuminance(background);
+ return (GetContrastRatio(GetRelativeLuminance(foreground1),
+ background_luminance) >=
+ GetContrastRatio(GetRelativeLuminance(foreground2),
+ background_luminance)) ?
+ foreground1 : foreground2;
}
SkColor InvertColor(SkColor color) {
- return SkColorSetARGB(
- SkColorGetA(color),
- 255 - SkColorGetR(color),
- 255 - SkColorGetG(color),
- 255 - SkColorGetB(color));
+ return SkColorSetARGB(SkColorGetA(color), 255 - SkColorGetR(color),
+ 255 - SkColorGetG(color), 255 - SkColorGetB(color));
}
SkColor GetSysSkColor(int which) {
diff --git a/chromium/ui/gfx/color_utils.h b/chromium/ui/gfx/color_utils.h
index 44302c808c8..fc8b4465286 100644
--- a/chromium/ui/gfx/color_utils.h
+++ b/chromium/ui/gfx/color_utils.h
@@ -23,13 +23,21 @@ struct HSL {
// This value is taken from w3c accessibility guidelines.
const double kMinimumReadableContrastRatio = 4.5f;
-// Determines the contrast ratio of two colors.
+// Determines the contrast ratio of two colors or two relative luminance values
+// (as computed by RelativeLuminance()), calculated according to
+// http://www.w3.org/TR/WCAG20/#contrast-ratiodef .
GFX_EXPORT double GetContrastRatio(SkColor color_a, SkColor color_b);
+GFX_EXPORT double GetContrastRatio(double luminance_a, double luminance_b);
-GFX_EXPORT unsigned char GetLuminanceForColor(SkColor color);
+// The relative luminance of |color|, that is, the weighted sum of the
+// linearized RGB components, normalized to 0..1, per BT.709. See
+// http://www.w3.org/TR/WCAG20/#relativeluminancedef .
+GFX_EXPORT double GetRelativeLuminance(SkColor color);
-// Calculated according to http://www.w3.org/TR/WCAG20/#relativeluminancedef
-GFX_EXPORT double RelativeLuminance(SkColor color);
+// The luma of |color|, that is, the weighted sum of the gamma-compressed R'G'B'
+// components, per BT.601, a.k.a. the Y' in Y'UV. See
+// https://en.wikipedia.org/wiki/Luma_(video).
+GFX_EXPORT uint8_t GetLuma(SkColor color);
// Note: these transformations assume sRGB as the source color space
GFX_EXPORT void SkColorToHSL(SkColor c, HSL* hsl);
@@ -50,8 +58,8 @@ GFX_EXPORT bool IsWithinHSLRange(const HSL& hsl,
const HSL& upper_bound);
// Makes |hsl| valid input for HSLShift(). Sets values of hue, saturation
-// and luminosity which are outside of the valid range [0, 1] to -1.
-// -1 is a special value which indicates 'no change'.
+// and lightness which are outside of the valid range [0, 1] to -1. -1 is a
+// special value which indicates 'no change'.
GFX_EXPORT void MakeHSLShiftValid(HSL* hsl);
// HSL-Shift an SkColor. The shift values are in the range of 0-1, with the
@@ -70,8 +78,7 @@ GFX_EXPORT void MakeHSLShiftValid(HSL* hsl);
// 1 = full lightness (make all pixels white).
GFX_EXPORT SkColor HSLShift(SkColor color, const HSL& shift);
-// Builds a histogram based on the Y' of the Y'UV representation of
-// this image.
+// Builds a histogram based on the Y' of the Y'UV representation of this image.
GFX_EXPORT void BuildLumaHistogram(const SkBitmap& bitmap, int histogram[256]);
// Calculates how "boring" an image is. The boring score is the
@@ -87,25 +94,30 @@ GFX_EXPORT double CalculateBoringScore(const SkBitmap& bitmap);
GFX_EXPORT SkColor AlphaBlend(SkColor foreground, SkColor background,
SkAlpha alpha);
-// Returns true if the luminance of |color| is closer to black than white.
+// Returns true if the luma of |color| is closer to black than white.
GFX_EXPORT bool IsDark(SkColor color);
// Makes a dark color lighter or a light color darker by blending |color| with
-// white or black depending on its current luminance. |alpha| controls the
-// amount of white or black that will be alpha-blended into |color|.
-GFX_EXPORT SkColor BlendTowardOppositeLuminance(SkColor color, SkAlpha alpha);
-
-// Given an opaque foreground and background color, try to return a foreground
-// color that is "readable" over the background color by luma-inverting the
-// foreground color and then picking whichever foreground color has higher
-// contrast against the background color. You should not pass colors with
-// non-255 alpha to this routine, since determining the correct behavior in such
-// cases can be impossible.
+// white or black depending on its current luma. |alpha| controls the amount of
+// white or black that will be alpha-blended into |color|.
+GFX_EXPORT SkColor BlendTowardOppositeLuma(SkColor color, SkAlpha alpha);
+
+// Given a foreground and background color, try to return a foreground color
+// that is "readable" over the background color by luma-inverting the foreground
+// color and then using PickContrastingColor() to pick the one with greater
+// contrast. During this process, alpha values will be ignored; the returned
+// color will have the same alpha as |foreground|.
//
// NOTE: This won't do anything but waste time if the supplied foreground color
// has a luma value close to the midpoint (0.5 in the HSL representation).
GFX_EXPORT SkColor GetReadableColor(SkColor foreground, SkColor background);
+// Returns whichever of |foreground1| or |foreground2| has higher contrast with
+// |background|.
+GFX_EXPORT SkColor PickContrastingColor(SkColor foreground1,
+ SkColor foreground2,
+ SkColor background);
+
// Invert a color.
GFX_EXPORT SkColor InvertColor(SkColor color);
diff --git a/chromium/ui/gfx/display.cc b/chromium/ui/gfx/display.cc
index 1777e87e543..7a9539d9bf4 100644
--- a/chromium/ui/gfx/display.cc
+++ b/chromium/ui/gfx/display.cc
@@ -80,6 +80,8 @@ Display::Display()
touch_support_(TOUCH_SUPPORT_UNKNOWN) {
}
+Display::Display(const Display& other) = default;
+
Display::Display(int64_t id)
: id_(id),
device_scale_factor_(GetForcedDeviceScaleFactor()),
diff --git a/chromium/ui/gfx/display.h b/chromium/ui/gfx/display.h
index c6df7e703ad..33db48b77a3 100644
--- a/chromium/ui/gfx/display.h
+++ b/chromium/ui/gfx/display.h
@@ -21,7 +21,7 @@ namespace gfx {
// system. For platforms that support DIP (density independent pixel),
// |bounds()| and |work_area| will return values in DIP coordinate
// system, not in backing pixels.
-class GFX_EXPORT Display {
+class GFX_EXPORT Display final {
public:
// Screen Rotation in clock-wise degrees.
// This enum corresponds to DisplayRotationDefaultProto::Rotation in
@@ -38,11 +38,13 @@ class GFX_EXPORT Display {
// RotationSource allows for the tracking of a Rotation per source of the
// change. ROTATION_SOURCE_ACTIVE is the current rotation of the display.
// Rotation changes not due to an accelerometer, nor the user, are to use this
- // source directly.
+ // source directly. ROTATION_SOURCE_UNKNOWN is when no rotation source has
+ // been provided.
enum RotationSource {
ROTATION_SOURCE_ACCELEROMETER = 0,
ROTATION_SOURCE_ACTIVE,
ROTATION_SOURCE_USER,
+ ROTATION_SOURCE_UNKNOWN,
};
// Touch support for the display.
@@ -58,6 +60,7 @@ class GFX_EXPORT Display {
Display();
explicit Display(int64_t id);
Display(int64_t id, const Rect& bounds);
+ Display(const Display& other);
~Display();
// Returns the forced device scale factor, which is given by
@@ -154,6 +157,11 @@ class GFX_EXPORT Display {
TouchSupport touch_support_;
};
+// This is declared here for use in gtest-based unit tests but is defined in
+// the gfx_test_support target. Depend on that to use this in your unit test.
+// This should not be used in production code - call ToString() instead.
+void PrintTo(const Display& display, ::std::ostream* os);
+
} // namespace gfx
#endif // UI_GFX_DISPLAY_H_
diff --git a/chromium/ui/gfx/display_finder.cc b/chromium/ui/gfx/display_finder.cc
new file mode 100644
index 00000000000..af27f1b3247
--- /dev/null
+++ b/chromium/ui/gfx/display_finder.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/display_finder.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace gfx {
+
+const Display* FindDisplayNearestPoint(const std::vector<Display>& displays,
+ const Point& point) {
+ DCHECK(!displays.empty());
+ int min_distance = std::numeric_limits<int>::max();
+ const Display* nearest_display = nullptr;
+ for (const auto& display : displays) {
+ const int distance = display.bounds().ManhattanDistanceToPoint(point);
+ if (distance < min_distance) {
+ min_distance = distance;
+ nearest_display = &display;
+ }
+ }
+ // There should always be at least one display that is less than INT_MAX away.
+ DCHECK(nearest_display);
+ return nearest_display;
+}
+
+const Display* FindDisplayWithBiggestIntersection(
+ const std::vector<Display>& displays,
+ const Rect& rect) {
+ DCHECK(!displays.empty());
+ int max_area = 0;
+ const Display* matching = nullptr;
+ for (const auto& display : displays) {
+ const Rect intersect = IntersectRects(display.bounds(), rect);
+ const int area = intersect.width() * intersect.height();
+ if (area > max_area) {
+ max_area = area;
+ matching = &display;
+ }
+ }
+ return matching;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/display_finder.h b/chromium/ui/gfx/display_finder.h
new file mode 100644
index 00000000000..2fb81f6eb44
--- /dev/null
+++ b/chromium/ui/gfx/display_finder.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_DISPLAY_FINDER_H_
+#define UI_GFX_DISPLAY_FINDER_H_
+
+#include <vector>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+class Display;
+class Point;
+class Rect;
+
+// Returns the display in |displays| closest to |point|.
+GFX_EXPORT const Display* FindDisplayNearestPoint(
+ const std::vector<Display>& displays,
+ const Point& point);
+
+// Returns the display in |displays| with the biggest intersection of |rect|.
+// If none of the displays intersect |rect| null is returned.
+GFX_EXPORT const Display* FindDisplayWithBiggestIntersection(
+ const std::vector<Display>& displays,
+ const Rect& rect);
+
+} // namespace gfx
+
+#endif // UI_GFX_DISPLAY_FINDER_H_
diff --git a/chromium/ui/gfx/font_fallback_linux.cc b/chromium/ui/gfx/font_fallback_linux.cc
index 919ac649af6..ad690c594f5 100644
--- a/chromium/ui/gfx/font_fallback_linux.cc
+++ b/chromium/ui/gfx/font_fallback_linux.cc
@@ -2,15 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gfx/font_fallback.h"
+#include "ui/gfx/font_fallback_linux.h"
#include <fontconfig/fontconfig.h>
#include <map>
+#include <memory>
#include <string>
#include <vector>
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "ui/gfx/font.h"
namespace gfx {
@@ -62,4 +64,184 @@ std::vector<Font> GetFallbackFonts(const Font& font) {
return *fallback_fonts;
}
+namespace {
+
+class CachedFont {
+ public:
+ // Note: We pass the charset explicitly as callers
+ // should not create CachedFont entries without knowing
+ // that the FcPattern contains a valid charset.
+ CachedFont(FcPattern* pattern, FcCharSet* char_set)
+ : supported_characters_(char_set) {
+ DCHECK(pattern);
+ DCHECK(char_set);
+ fallback_font_.name = GetFontName(pattern);
+ fallback_font_.filename = GetFontFilename(pattern);
+ fallback_font_.ttc_index = GetFontTtcIndex(pattern);
+ fallback_font_.is_bold = IsFontBold(pattern);
+ fallback_font_.is_italic = IsFontItalic(pattern);
+ }
+
+ const FallbackFontData& fallback_font() const { return fallback_font_; }
+
+ bool HasGlyphForCharacter(UChar32 c) const {
+ return supported_characters_ && FcCharSetHasChar(supported_characters_, c);
+ }
+
+ private:
+ static std::string GetFontName(FcPattern* pattern) {
+ FcChar8* familyName = nullptr;
+ if (FcPatternGetString(pattern, FC_FAMILY, 0, &familyName) != FcResultMatch)
+ return std::string();
+ return std::string(reinterpret_cast<const char*>(familyName));
+ }
+
+ static std::string GetFontFilename(FcPattern* pattern) {
+ FcChar8* c_filename = nullptr;
+ if (FcPatternGetString(pattern, FC_FILE, 0, &c_filename) != FcResultMatch)
+ return std::string();
+ return std::string(reinterpret_cast<const char*>(c_filename));
+ }
+
+ static int GetFontTtcIndex(FcPattern* pattern) {
+ int ttcIndex = -1;
+ if (FcPatternGetInteger(pattern, FC_INDEX, 0, &ttcIndex) != FcResultMatch ||
+ ttcIndex < 0)
+ return 0;
+ return ttcIndex;
+ }
+
+ static bool IsFontBold(FcPattern* pattern) {
+ int weight = 0;
+ if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch)
+ return false;
+ return weight >= FC_WEIGHT_BOLD;
+ }
+
+ static bool IsFontItalic(FcPattern* pattern) {
+ int slant = 0;
+ if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch)
+ return false;
+ return slant != FC_SLANT_ROMAN;
+ }
+
+ FallbackFontData fallback_font_;
+ // supported_characters_ is owned by the parent
+ // FcFontSet and should never be freed.
+ FcCharSet* supported_characters_;
+};
+
+class CachedFontSet {
+ public:
+ // CachedFontSet takes ownership of the passed FcFontSet.
+ static std::unique_ptr<CachedFontSet> CreateForLocale(
+ const std::string& locale) {
+ FcFontSet* font_set = CreateFcFontSetForLocale(locale);
+ return base::WrapUnique(new CachedFontSet(font_set));
+ }
+
+ ~CachedFontSet() {
+ fallback_list_.clear();
+ FcFontSetDestroy(font_set_);
+ }
+
+ FallbackFontData GetFallbackFontForChar(UChar32 c) {
+ for (const auto& cached_font : fallback_list_) {
+ if (cached_font.HasGlyphForCharacter(c))
+ return cached_font.fallback_font();
+ }
+ // The previous code just returned garbage if the user didn't
+ // have the necessary fonts, this seems better than garbage.
+ // Current callers happen to ignore any values with an empty family string.
+ return FallbackFontData();
+ }
+
+ private:
+ static FcFontSet* CreateFcFontSetForLocale(const std::string& locale) {
+ FcPattern* pattern = FcPatternCreate();
+
+ if (!locale.empty()) {
+ // FcChar* is unsigned char* so we have to cast.
+ FcPatternAddString(pattern, FC_LANG,
+ reinterpret_cast<const FcChar8*>(locale.c_str()));
+ }
+
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ if (locale.empty())
+ FcPatternDel(pattern, FC_LANG);
+
+ // The result parameter returns if any fonts were found.
+ // We already handle 0 fonts correctly, so we ignore the param.
+ FcResult result;
+ FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
+ FcPatternDestroy(pattern);
+
+ // The caller will take ownership of this FcFontSet.
+ return font_set;
+ }
+
+ CachedFontSet(FcFontSet* font_set) : font_set_(font_set) {
+ FillFallbackList();
+ }
+
+ void FillFallbackList() {
+ DCHECK(fallback_list_.empty());
+ if (!font_set_)
+ return;
+
+ for (int i = 0; i < font_set_->nfont; ++i) {
+ FcPattern* pattern = font_set_->fonts[i];
+
+ // Ignore any bitmap fonts users may still have installed from last
+ // century.
+ FcBool is_scalable;
+ if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) !=
+ FcResultMatch ||
+ !is_scalable)
+ continue;
+
+ // Ignore any fonts FontConfig knows about, but that we don't have
+ // permission to read.
+ FcChar8* c_filename;
+ if (FcPatternGetString(pattern, FC_FILE, 0, &c_filename) != FcResultMatch)
+ continue;
+ if (access(reinterpret_cast<char*>(c_filename), R_OK))
+ continue;
+
+ // Make sure this font can tell us what characters it has glyphs for.
+ FcCharSet* char_set;
+ if (FcPatternGetCharSet(pattern, FC_CHARSET, 0, &char_set) !=
+ FcResultMatch)
+ continue;
+
+ fallback_list_.emplace_back(pattern, char_set);
+ }
+ }
+
+ FcFontSet* font_set_; // Owned by this object.
+ // CachedFont has a FcCharset* which points into the FcFontSet.
+ // If the FcFontSet is ever destroyed, the fallback list
+ // must be cleared first.
+ std::vector<CachedFont> fallback_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CachedFontSet);
+};
+
+typedef std::map<std::string, std::unique_ptr<CachedFontSet>> FontSetCache;
+base::LazyInstance<FontSetCache>::Leaky g_font_sets_by_locale =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+FallbackFontData GetFallbackFontForChar(UChar32 c, const std::string& locale) {
+ auto& cached_font_set = g_font_sets_by_locale.Get()[locale];
+ if (!cached_font_set)
+ cached_font_set = CachedFontSet::CreateForLocale(locale);
+ return cached_font_set->GetFallbackFontForChar(c);
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/font_fallback_linux.h b/chromium/ui/gfx/font_fallback_linux.h
new file mode 100644
index 00000000000..ac9cd572419
--- /dev/null
+++ b/chromium/ui/gfx/font_fallback_linux.h
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_FONT_FALLBACK_LINUX_H_
+#define UI_GFX_FONT_FALLBACK_LINUX_H_
+
+#include <string>
+
+#include "third_party/icu/source/common/unicode/uchar.h"
+#include "ui/gfx/font_fallback.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// Return a font family which provides a glyph for the Unicode code point
+// specified by character.
+// c: a UTF-32 code point
+// preferred_locale: preferred locale identifier for the |characters|
+// (e.g. "en", "ja", "zh-CN")
+//
+// Returns: the font family instance. The instance has an empty font name if the
+// request could not be satisfied.
+//
+// Previously blink::WebFontInfo::fallbackFontForChar.
+struct FallbackFontData {
+ std::string name;
+ std::string filename;
+ int ttc_index = 0;
+ bool is_bold = false;
+ bool is_italic = false;
+};
+GFX_EXPORT FallbackFontData
+GetFallbackFontForChar(UChar32 c, const std::string& preferred_locale);
+
+} // namespace gfx
+
+#endif // UI_GFX_FONT_FALLBACK_LINUX_H_
diff --git a/chromium/ui/gfx/font_render_params.cc b/chromium/ui/gfx/font_render_params.cc
index a434379ee10..7b8543560c8 100644
--- a/chromium/ui/gfx/font_render_params.cc
+++ b/chromium/ui/gfx/font_render_params.cc
@@ -17,6 +17,8 @@ FontRenderParams::FontRenderParams()
subpixel_rendering(SUBPIXEL_RENDERING_NONE) {
}
+FontRenderParams::FontRenderParams(const FontRenderParams& other) = default;
+
FontRenderParams::~FontRenderParams() {}
// static
@@ -61,6 +63,9 @@ FontRenderParamsQuery::FontRenderParamsQuery()
device_scale_factor(0) {
}
+FontRenderParamsQuery::FontRenderParamsQuery(
+ const FontRenderParamsQuery& other) = default;
+
FontRenderParamsQuery::~FontRenderParamsQuery() {}
} // namespace gfx
diff --git a/chromium/ui/gfx/font_render_params.h b/chromium/ui/gfx/font_render_params.h
index 989f9aa129a..7a294bdc3cd 100644
--- a/chromium/ui/gfx/font_render_params.h
+++ b/chromium/ui/gfx/font_render_params.h
@@ -17,6 +17,7 @@ namespace gfx {
// A collection of parameters describing how text should be rendered on Linux.
struct GFX_EXPORT FontRenderParams {
FontRenderParams();
+ FontRenderParams(const FontRenderParams& other);
~FontRenderParams();
// Level of hinting to be applied.
@@ -73,6 +74,7 @@ struct GFX_EXPORT FontRenderParams {
// A query used to determine the appropriate FontRenderParams.
struct GFX_EXPORT FontRenderParamsQuery {
FontRenderParamsQuery();
+ FontRenderParamsQuery(const FontRenderParamsQuery& other);
~FontRenderParamsQuery();
bool is_empty() const {
@@ -106,9 +108,9 @@ GFX_EXPORT FontRenderParams GetFontRenderParams(
GFX_EXPORT void ClearFontRenderParamsCacheForTest();
#endif
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
// Gets the device scale factor to query the FontRenderParams.
-float GetFontRenderParamsDeviceScaleFactor();
+GFX_EXPORT float GetFontRenderParamsDeviceScaleFactor();
// Sets the device scale factor for FontRenderParams to decide
// if it should enable subpixel positioning.
diff --git a/chromium/ui/gfx/font_render_params_linux.cc b/chromium/ui/gfx/font_render_params_linux.cc
index a9afcf344db..b2e8d5eb774 100644
--- a/chromium/ui/gfx/font_render_params_linux.cc
+++ b/chromium/ui/gfx/font_render_params_linux.cc
@@ -19,21 +19,17 @@
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "build/build_config.h"
-#include "ui/gfx/display.h"
#include "ui/gfx/font.h"
#include "ui/gfx/linux_font_delegate.h"
-#include "ui/gfx/screen.h"
#include "ui/gfx/switches.h"
namespace gfx {
namespace {
-#if defined(OS_CHROMEOS)
-// A device scale factor for an internal display (if any)
-// that is used to determine if subpixel positioning should be used.
-float device_scale_factor_for_internal_display = 1.0f;
-#endif
+// A device scale factor used to determine if subpixel positioning
+// should be used.
+float device_scale_factor_ = 1.0f;
// Number of recent GetFontRenderParams() results to cache.
const size_t kCacheSize = 256;
@@ -204,19 +200,9 @@ uint32_t HashFontRenderParamsQuery(const FontRenderParamsQuery& query) {
FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
std::string* family_out) {
FontRenderParamsQuery actual_query(query);
- if (actual_query.device_scale_factor == 0) {
-#if defined(OS_CHROMEOS)
- actual_query.device_scale_factor = device_scale_factor_for_internal_display;
-#else
- // Linux does not support per-display DPI, so we use a slightly simpler
- // code path than on Chrome OS to figure out the device scale factor.
- gfx::Screen* screen = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE);
- if (screen) {
- gfx::Display display = screen->GetPrimaryDisplay();
- actual_query.device_scale_factor = display.device_scale_factor();
- }
-#endif
- }
+ if (actual_query.device_scale_factor == 0)
+ actual_query.device_scale_factor = device_scale_factor_;
+
const uint32_t hash = HashFontRenderParamsQuery(actual_query);
SynchronizedCache* synchronized_cache = g_synchronized_cache.Pointer();
@@ -279,14 +265,12 @@ void ClearFontRenderParamsCacheForTest() {
synchronized_cache->cache.Clear();
}
-#if defined(OS_CHROMEOS)
float GetFontRenderParamsDeviceScaleFactor() {
- return device_scale_factor_for_internal_display;
+ return device_scale_factor_;
}
void SetFontRenderParamsDeviceScaleFactor(float device_scale_factor) {
- device_scale_factor_for_internal_display = device_scale_factor;
+ device_scale_factor_ = device_scale_factor;
}
-#endif
} // namespace gfx
diff --git a/chromium/ui/gfx/font_render_params_linux_unittest.cc b/chromium/ui/gfx/font_render_params_linux_unittest.cc
index 27d1ff3b206..63601d1b3b5 100644
--- a/chromium/ui/gfx/font_render_params_linux_unittest.cc
+++ b/chromium/ui/gfx/font_render_params_linux_unittest.cc
@@ -279,7 +279,6 @@ TEST_F(FontRenderParamsTest, ForceFullHintingWhenAntialiasingIsDisabled) {
EXPECT_FALSE(params.subpixel_positioning);
}
-#if defined(OS_CHROMEOS)
TEST_F(FontRenderParamsTest, ForceSubpixelPositioning) {
{
FontRenderParams params =
@@ -299,7 +298,6 @@ TEST_F(FontRenderParamsTest, ForceSubpixelPositioning) {
SetFontRenderParamsDeviceScaleFactor(1.0f);
}
}
-#endif
TEST_F(FontRenderParamsTest, OnlySetConfiguredValues) {
// Configure the LinuxFontDelegate (which queries GtkSettings on desktop
diff --git a/chromium/ui/gfx/generic_shared_memory_id.h b/chromium/ui/gfx/generic_shared_memory_id.h
index 51f553b2dda..b18c869e2cc 100644
--- a/chromium/ui/gfx/generic_shared_memory_id.h
+++ b/chromium/ui/gfx/generic_shared_memory_id.h
@@ -8,6 +8,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/containers/hash_tables.h"
+#include "base/hash.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "ui/gfx/gfx_export.h"
@@ -58,7 +60,7 @@ template <typename Second>
struct hash<std::pair<gfx::GenericSharedMemoryId, Second>> {
size_t operator()(
const std::pair<gfx::GenericSharedMemoryId, Second>& pair) const {
- return base::HashPair(pair.first.id, pair.second);
+ return base::HashInts(pair.first.id, pair.second);
}
};
diff --git a/chromium/ui/gfx/geometry/cubic_bezier.cc b/chromium/ui/gfx/geometry/cubic_bezier.cc
index fe6dfcc7ff1..16acfc7c942 100644
--- a/chromium/ui/gfx/geometry/cubic_bezier.cc
+++ b/chromium/ui/gfx/geometry/cubic_bezier.cc
@@ -11,129 +11,93 @@
namespace gfx {
-namespace {
-
static const double kBezierEpsilon = 1e-7;
-static const int MAX_STEPS = 30;
-
-static double eval_bezier(double p1, double p2, double t) {
- const double p1_times_3 = 3.0 * p1;
- const double p2_times_3 = 3.0 * p2;
- const double h3 = p1_times_3;
- const double h1 = p1_times_3 - p2_times_3 + 1.0;
- const double h2 = p2_times_3 - 6.0 * p1;
- return t * (t * (t * h1 + h2) + h3);
-}
-static double eval_bezier_derivative(double p1, double p2, double t) {
- const double h1 = 9.0 * p1 - 9.0 * p2 + 3.0;
- const double h2 = 6.0 * p2 - 12.0 * p1;
- const double h3 = 3.0 * p1;
- return t * (t * h1 + h2) + h3;
+CubicBezier::CubicBezier(double p1x, double p1y, double p2x, double p2y) {
+ InitCoefficients(p1x, p1y, p2x, p2y);
+ InitGradients(p1x, p1y, p2x, p2y);
+ InitRange(p1y, p2y);
}
-// Finds t such that eval_bezier(x1, x2, t) = x.
-// There is a unique solution if x1 and x2 lie within (0, 1).
-static double bezier_interp(double x1,
- double x2,
- double x) {
- DCHECK_GE(1.0, x1);
- DCHECK_LE(0.0, x1);
- DCHECK_GE(1.0, x2);
- DCHECK_LE(0.0, x2);
-
- x1 = std::min(std::max(x1, 0.0), 1.0);
- x2 = std::min(std::max(x2, 0.0), 1.0);
- x = std::min(std::max(x, 0.0), 1.0);
-
- // We're just going to do bisection for now (for simplicity), but we could
- // easily do some newton steps if this turns out to be a bottleneck.
- double t = 0.0;
- double step = 1.0;
- for (int i = 0; i < MAX_STEPS; ++i, step *= 0.5) {
- const double error = eval_bezier(x1, x2, t) - x;
- if (std::abs(error) < kBezierEpsilon)
- break;
- t += error > 0.0 ? -step : step;
- }
-
- // We should have terminated the above loop because we got close to x, not
- // because we exceeded MAX_STEPS. Do a DCHECK here to confirm.
- DCHECK_GT(kBezierEpsilon, std::abs(eval_bezier(x1, x2, t) - x));
-
- return t;
+CubicBezier::CubicBezier(const CubicBezier& other) = default;
+
+void CubicBezier::InitCoefficients(double p1x,
+ double p1y,
+ double p2x,
+ double p2y) {
+ // Calculate the polynomial coefficients, implicit first and last control
+ // points are (0,0) and (1,1).
+ cx_ = 3.0 * p1x;
+ bx_ = 3.0 * (p2x - p1x) - cx_;
+ ax_ = 1.0 - cx_ - bx_;
+
+ cy_ = 3.0 * p1y;
+ by_ = 3.0 * (p2y - p1y) - cy_;
+ ay_ = 1.0 - cy_ - by_;
}
-} // namespace
-
-CubicBezier::CubicBezier(double x1, double y1, double x2, double y2)
- : x1_(x1),
- y1_(y1),
- x2_(x2),
- y2_(y2) {
- InitGradients();
-}
-
-CubicBezier::~CubicBezier() {
-}
-
-void CubicBezier::InitGradients() {
- if (x1_ > 0)
- start_gradient_ = y1_ / x1_;
- else if (!y1_ && x2_ > 0)
- start_gradient_ = y2_ / x2_;
+void CubicBezier::InitGradients(double p1x,
+ double p1y,
+ double p2x,
+ double p2y) {
+ // End-point gradients are used to calculate timing function results
+ // outside the range [0, 1].
+ //
+ // There are three possibilities for the gradient at each end:
+ // (1) the closest control point is not horizontally coincident with regard to
+ // (0, 0) or (1, 1). In this case the line between the end point and
+ // the control point is tangent to the bezier at the end point.
+ // (2) the closest control point is coincident with the end point. In
+ // this case the line between the end point and the far control
+ // point is tangent to the bezier at the end point.
+ // (3) the closest control point is horizontally coincident with the end
+ // point, but vertically distinct. In this case the gradient at the
+ // end point is Infinite. However, this causes issues when
+ // interpolating. As a result, we break down to a simple case of
+ // 0 gradient under these conditions.
+
+ if (p1x > 0)
+ start_gradient_ = p1y / p1x;
+ else if (!p1y && p2x > 0)
+ start_gradient_ = p2y / p2x;
else
start_gradient_ = 0;
- if (x2_ < 1)
- end_gradient_ = (y2_ - 1) / (x2_ - 1);
- else if (x2_ == 1 && x1_ < 1)
- end_gradient_ = (y1_ - 1) / (x1_ - 1);
+ if (p2x < 1)
+ end_gradient_ = (p2y - 1) / (p2x - 1);
+ else if (p2x == 1 && p1x < 1)
+ end_gradient_ = (p1y - 1) / (p1x - 1);
else
end_gradient_ = 0;
}
-double CubicBezier::Solve(double x) const {
- if (x < 0)
- return start_gradient_ * x;
- if (x > 1)
- return 1.0 + end_gradient_ * (x - 1.0);
-
- return eval_bezier(y1_, y2_, bezier_interp(x1_, x2_, x));
-}
-
-double CubicBezier::Slope(double x) const {
- double t = bezier_interp(x1_, x2_, x);
- double dx_dt = eval_bezier_derivative(x1_, x2_, t);
- double dy_dt = eval_bezier_derivative(y1_, y2_, t);
- return dy_dt / dx_dt;
-}
-
-void CubicBezier::Range(double* min, double* max) const {
- *min = 0;
- *max = 1;
- if (0 <= y1_ && y1_ < 1 && 0 <= y2_ && y2_ <= 1)
+void CubicBezier::InitRange(double p1y, double p2y) {
+ range_min_ = 0;
+ range_max_ = 1;
+ if (0 <= p1y && p1y < 1 && 0 <= p2y && p2y <= 1)
return;
- // Represent the function's derivative in the form at^2 + bt + c.
+ const double epsilon = kBezierEpsilon;
+
+ // Represent the function's derivative in the form at^2 + bt + c
+ // as in sampleCurveDerivativeY.
// (Technically this is (dy/dt)*(1/3), which is suitable for finding zeros
// but does not actually give the slope of the curve.)
- double a = 3 * (y1_ - y2_) + 1;
- double b = 2 * (y2_ - 2 * y1_);
- double c = y1_;
+ const double a = 3.0 * ay_;
+ const double b = 2.0 * by_;
+ const double c = cy_;
// Check if the derivative is constant.
- if (std::abs(a) < kBezierEpsilon &&
- std::abs(b) < kBezierEpsilon)
+ if (std::abs(a) < epsilon && std::abs(b) < epsilon)
return;
// Zeros of the function's derivative.
- double t_1 = 0;
- double t_2 = 0;
+ double t1 = 0;
+ double t2 = 0;
- if (std::abs(a) < kBezierEpsilon) {
+ if (std::abs(a) < epsilon) {
// The function's derivative is linear.
- t_1 = -c / b;
+ t1 = -c / b;
} else {
// The function's derivative is a quadratic. We find the zeros of this
// quadratic using the quadratic formula.
@@ -141,21 +105,79 @@ void CubicBezier::Range(double* min, double* max) const {
if (discriminant < 0)
return;
double discriminant_sqrt = sqrt(discriminant);
- t_1 = (-b + discriminant_sqrt) / (2 * a);
- t_2 = (-b - discriminant_sqrt) / (2 * a);
+ t1 = (-b + discriminant_sqrt) / (2 * a);
+ t2 = (-b - discriminant_sqrt) / (2 * a);
+ }
+
+ double sol1 = 0;
+ double sol2 = 0;
+
+ if (0 < t1 && t1 < 1)
+ sol1 = SampleCurveY(t1);
+
+ if (0 < t2 && t2 < 1)
+ sol2 = SampleCurveY(t2);
+
+ range_min_ = std::min(std::min(range_min_, sol1), sol2);
+ range_max_ = std::max(std::max(range_max_, sol1), sol2);
+}
+
+double CubicBezier::SolveCurveX(double x, double epsilon) const {
+ DCHECK_GE(x, 0.0);
+ DCHECK_LE(x, 1.0);
+
+ double t0;
+ double t1;
+ double t2;
+ double x2;
+ double d2;
+ int i;
+
+ // First try a few iterations of Newton's method -- normally very fast.
+ for (t2 = x, i = 0; i < 8; i++) {
+ x2 = SampleCurveX(t2) - x;
+ if (fabs(x2) < epsilon)
+ return t2;
+ d2 = SampleCurveDerivativeX(t2);
+ if (fabs(d2) < 1e-6)
+ break;
+ t2 = t2 - x2 / d2;
}
- double sol_1 = 0;
- double sol_2 = 0;
+ // Fall back to the bisection method for reliability.
+ t0 = 0.0;
+ t1 = 1.0;
+ t2 = x;
+
+ while (t0 < t1) {
+ x2 = SampleCurveX(t2);
+ if (fabs(x2 - x) < epsilon)
+ return t2;
+ if (x > x2)
+ t0 = t2;
+ else
+ t1 = t2;
+ t2 = (t1 - t0) * .5 + t0;
+ }
- if (0 < t_1 && t_1 < 1)
- sol_1 = eval_bezier(y1_, y2_, t_1);
+ // Failure.
+ return t2;
+}
- if (0 < t_2 && t_2 < 1)
- sol_2 = eval_bezier(y1_, y2_, t_2);
+double CubicBezier::Solve(double x) const {
+ return SolveWithEpsilon(x, kBezierEpsilon);
+}
- *min = std::min(std::min(*min, sol_1), sol_2);
- *max = std::max(std::max(*max, sol_1), sol_2);
+double CubicBezier::SlopeWithEpsilon(double x, double epsilon) const {
+ x = std::min(std::max(x, 0.0), 1.0);
+ double t = SolveCurveX(x, epsilon);
+ double dx = SampleCurveDerivativeX(t);
+ double dy = SampleCurveDerivativeY(t);
+ return dy / dx;
+}
+
+double CubicBezier::Slope(double x) const {
+ return SlopeWithEpsilon(x, kBezierEpsilon);
}
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/cubic_bezier.h b/chromium/ui/gfx/geometry/cubic_bezier.h
index 5a885f35db2..f32776b82df 100644
--- a/chromium/ui/gfx/geometry/cubic_bezier.h
+++ b/chromium/ui/gfx/geometry/cubic_bezier.h
@@ -12,30 +12,76 @@ namespace gfx {
class GFX_EXPORT CubicBezier {
public:
- CubicBezier(double x1, double y1, double x2, double y2);
- ~CubicBezier();
+ CubicBezier(double p1x, double p1y, double p2x, double p2y);
+ CubicBezier(const CubicBezier& other);
- // Returns an approximation of y at the given x.
+ double SampleCurveX(double t) const {
+ // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
+ return ((ax_ * t + bx_) * t + cx_) * t;
+ }
+
+ double SampleCurveY(double t) const {
+ return ((ay_ * t + by_) * t + cy_) * t;
+ }
+
+ double SampleCurveDerivativeX(double t) const {
+ return (3.0 * ax_ * t + 2.0 * bx_) * t + cx_;
+ }
+
+ double SampleCurveDerivativeY(double t) const {
+ return (3.0 * ay_ * t + 2.0 * by_) * t + cy_;
+ }
+
+ // Given an x value, find a parametric value it came from.
+ // x must be in [0, 1] range. Doesn't use gradients.
+ double SolveCurveX(double x, double epsilon) const;
+
+ // Evaluates y at the given x with default epsilon.
double Solve(double x) const;
+ // Evaluates y at the given x. The epsilon parameter provides a hint as to the
+ // required accuracy and is not guaranteed. Uses gradients if x is
+ // out of [0, 1] range.
+ double SolveWithEpsilon(double x, double epsilon) const {
+ if (x < 0.0)
+ return 0.0 + start_gradient_ * x;
+ if (x > 1.0)
+ return 1.0 + end_gradient_ * (x - 1.0);
+ return SampleCurveY(SolveCurveX(x, epsilon));
+ }
- // Returns an approximation of dy/dx at the given x.
+ // Returns an approximation of dy/dx at the given x with default epsilon.
double Slope(double x) const;
+ // Returns an approximation of dy/dx at the given x.
+ // Clamps x to range [0, 1].
+ double SlopeWithEpsilon(double x, double epsilon) const;
// Sets |min| and |max| to the bezier's minimum and maximium y values in the
// interval [0, 1].
- void Range(double* min, double* max) const;
+ // TODO(loyso): Implement this as two independent getters.
+ void Range(double* min, double* max) const {
+ *min = range_min_;
+ *max = range_max_;
+ }
private:
- void InitGradients();
+ void InitCoefficients(double p1x, double p1y, double p2x, double p2y);
+ void InitGradients(double p1x, double p1y, double p2x, double p2y);
+ void InitRange(double p1y, double p2y);
- double x1_;
- double y1_;
- double x2_;
- double y2_;
+ double ax_;
+ double bx_;
+ double cx_;
+
+ double ay_;
+ double by_;
+ double cy_;
double start_gradient_;
double end_gradient_;
+ double range_min_;
+ double range_max_;
+
DISALLOW_ASSIGN(CubicBezier);
};
diff --git a/chromium/ui/gfx/geometry/cubic_bezier_unittest.cc b/chromium/ui/gfx/geometry/cubic_bezier_unittest.cc
index 9ade0daf42f..a69836185c9 100644
--- a/chromium/ui/gfx/geometry/cubic_bezier_unittest.cc
+++ b/chromium/ui/gfx/geometry/cubic_bezier_unittest.cc
@@ -35,6 +35,15 @@ TEST(CubicBezierTest, Basic) {
EXPECT_NEAR(function.Solve(0.9), 0.96021, epsilon);
EXPECT_NEAR(function.Solve(0.95), 0.98863, epsilon);
EXPECT_NEAR(function.Solve(1), 1, epsilon);
+
+ CubicBezier basic_use(0.5, 1.0, 0.5, 1.0);
+ EXPECT_EQ(0.875, basic_use.Solve(0.5));
+
+ CubicBezier overshoot(0.5, 2.0, 0.5, 2.0);
+ EXPECT_EQ(1.625, overshoot.Solve(0.5));
+
+ CubicBezier undershoot(0.5, -1.0, 0.5, -1.0);
+ EXPECT_EQ(-0.625, undershoot.Solve(0.5));
}
// Tests that solving the bezier works with knots with y not in (0, 1).
@@ -141,6 +150,7 @@ TEST(CubicBezierTest, Slope) {
double epsilon = 0.00015;
+ EXPECT_NEAR(function.Slope(-0.1), 0, epsilon);
EXPECT_NEAR(function.Slope(0), 0, epsilon);
EXPECT_NEAR(function.Slope(0.05), 0.42170, epsilon);
EXPECT_NEAR(function.Slope(0.1), 0.69778, epsilon);
@@ -162,6 +172,7 @@ TEST(CubicBezierTest, Slope) {
EXPECT_NEAR(function.Slope(0.9), 0.69778, epsilon);
EXPECT_NEAR(function.Slope(0.95), 0.42170, epsilon);
EXPECT_NEAR(function.Slope(1), 0, epsilon);
+ EXPECT_NEAR(function.Slope(1.1), 0, epsilon);
}
TEST(CubicBezierTest, InputOutOfRange) {
@@ -169,25 +180,33 @@ TEST(CubicBezierTest, InputOutOfRange) {
EXPECT_EQ(-2.0, simple.Solve(-1.0));
EXPECT_EQ(1.0, simple.Solve(2.0));
- CubicBezier coincidentEndpoints(0.0, 0.0, 1.0, 1.0);
- EXPECT_EQ(-1.0, coincidentEndpoints.Solve(-1.0));
- EXPECT_EQ(2.0, coincidentEndpoints.Solve(2.0));
+ CubicBezier at_edge_of_range(0.5, 1.0, 0.5, 1.0);
+ EXPECT_EQ(0.0, at_edge_of_range.Solve(0.0));
+ EXPECT_EQ(1.0, at_edge_of_range.Solve(1.0));
+
+ CubicBezier large_epsilon(0.5, 1.0, 0.5, 1.0);
+ EXPECT_EQ(-2.0, large_epsilon.SolveWithEpsilon(-1.0, 1.0));
+ EXPECT_EQ(1.0, large_epsilon.SolveWithEpsilon(2.0, 1.0));
+
+ CubicBezier coincident_endpoints(0.0, 0.0, 1.0, 1.0);
+ EXPECT_EQ(-1.0, coincident_endpoints.Solve(-1.0));
+ EXPECT_EQ(2.0, coincident_endpoints.Solve(2.0));
- CubicBezier verticalGradient(0.0, 1.0, 1.0, 0.0);
- EXPECT_EQ(0.0, verticalGradient.Solve(-1.0));
- EXPECT_EQ(1.0, verticalGradient.Solve(2.0));
+ CubicBezier vertical_gradient(0.0, 1.0, 1.0, 0.0);
+ EXPECT_EQ(0.0, vertical_gradient.Solve(-1.0));
+ EXPECT_EQ(1.0, vertical_gradient.Solve(2.0));
- CubicBezier distinctEndpoints(0.1, 0.2, 0.8, 0.8);
- EXPECT_EQ(-2.0, distinctEndpoints.Solve(-1.0));
- EXPECT_EQ(2.0, distinctEndpoints.Solve(2.0));
+ CubicBezier distinct_endpoints(0.1, 0.2, 0.8, 0.8);
+ EXPECT_EQ(-2.0, distinct_endpoints.Solve(-1.0));
+ EXPECT_EQ(2.0, distinct_endpoints.Solve(2.0));
- CubicBezier coincidentEndpoint(0.0, 0.0, 0.8, 0.8);
- EXPECT_EQ(-1.0, coincidentEndpoint.Solve(-1.0));
- EXPECT_EQ(2.0, coincidentEndpoint.Solve(2.0));
+ CubicBezier coincident_endpoint(0.0, 0.0, 0.8, 0.8);
+ EXPECT_EQ(-1.0, coincident_endpoint.Solve(-1.0));
+ EXPECT_EQ(2.0, coincident_endpoint.Solve(2.0));
- CubicBezier threeCoincidentPoints(0.0, 0.0, 0.0, 0.0);
- EXPECT_EQ(0, threeCoincidentPoints.Solve(-1.0));
- EXPECT_EQ(2.0, threeCoincidentPoints.Solve(2.0));
+ CubicBezier three_coincident_points(0.0, 0.0, 0.0, 0.0);
+ EXPECT_EQ(0, three_coincident_points.Solve(-1.0));
+ EXPECT_EQ(2.0, three_coincident_points.Solve(2.0));
}
diff --git a/chromium/ui/gfx/geometry/insets.cc b/chromium/ui/gfx/geometry/insets.cc
index 46fb84ce233..13a05b31dd0 100644
--- a/chromium/ui/gfx/geometry/insets.cc
+++ b/chromium/ui/gfx/geometry/insets.cc
@@ -8,7 +8,12 @@
namespace gfx {
-Insets::Insets() : Insets(0, 0, 0, 0) {}
+Insets::Insets() : Insets(0) {}
+
+Insets::Insets(int all) : Insets(all, all, all, all) {}
+
+Insets::Insets(int vertical, int horizontal)
+ : Insets(vertical, horizontal, vertical, horizontal) {}
Insets::Insets(int top, int left, int bottom, int right)
: top_(top), left_(left), bottom_(bottom), right_(right) {}
diff --git a/chromium/ui/gfx/geometry/insets.h b/chromium/ui/gfx/geometry/insets.h
index 0466d947704..2fc0d62412b 100644
--- a/chromium/ui/gfx/geometry/insets.h
+++ b/chromium/ui/gfx/geometry/insets.h
@@ -12,10 +12,11 @@
namespace gfx {
-// An integer version of gfx::Insets.
class GFX_EXPORT Insets {
public:
Insets();
+ explicit Insets(int all);
+ Insets(int vertical, int horizontal);
Insets(int top, int left, int bottom, int right);
~Insets();
diff --git a/chromium/ui/gfx/geometry/insets_f.cc b/chromium/ui/gfx/geometry/insets_f.cc
index 24ccd627bdb..e4368913ccd 100644
--- a/chromium/ui/gfx/geometry/insets_f.cc
+++ b/chromium/ui/gfx/geometry/insets_f.cc
@@ -8,7 +8,12 @@
namespace gfx {
-InsetsF::InsetsF() : InsetsF(0.f, 0.f, 0.f, 0.f) {}
+InsetsF::InsetsF() : InsetsF(0.f) {}
+
+InsetsF::InsetsF(float all) : InsetsF(all, all, all, all) {}
+
+InsetsF::InsetsF(float vertical, float horizontal)
+ : InsetsF(vertical, horizontal, vertical, horizontal) {}
InsetsF::InsetsF(float top, float left, float bottom, float right)
: top_(top), left_(left), bottom_(bottom), right_(right) {}
diff --git a/chromium/ui/gfx/geometry/insets_f.h b/chromium/ui/gfx/geometry/insets_f.h
index 90592d774a0..7ff2cec2e28 100644
--- a/chromium/ui/gfx/geometry/insets_f.h
+++ b/chromium/ui/gfx/geometry/insets_f.h
@@ -11,11 +11,14 @@
namespace gfx {
-// A floating versin of gfx::Insets.
+// A floating point version of gfx::Insets.
class GFX_EXPORT InsetsF {
public:
InsetsF();
+ explicit InsetsF(float all);
+ InsetsF(float vertical, float horizontal);
InsetsF(float top, float left, float bottom, float right);
+
~InsetsF();
float top() const { return top_; }
diff --git a/chromium/ui/gfx/gfx.gyp b/chromium/ui/gfx/gfx.gyp
index 673d1cfb961..e7936ce5bc5 100644
--- a/chromium/ui/gfx/gfx.gyp
+++ b/chromium/ui/gfx/gfx.gyp
@@ -113,6 +113,8 @@
'animation/animation_container_element.h',
'animation/animation_container_observer.h',
'animation/animation_delegate.h',
+ 'animation/animation_mac.mm',
+ 'animation/animation_win.cc',
'animation/linear_animation.cc',
'animation/linear_animation.h',
'animation/multi_animation.cc',
@@ -153,6 +155,8 @@
'display.h',
'display_change_notifier.cc',
'display_change_notifier.h',
+ 'display_finder.cc',
+ 'display_finder.h',
'display_observer.cc',
'display_observer.h',
'favicon_size.cc',
@@ -161,6 +165,7 @@
'font.h',
'font_fallback.h',
'font_fallback_linux.cc',
+ 'font_fallback_linux.h',
'font_fallback_mac.mm',
'font_fallback_win.cc',
'font_fallback_win.h',
@@ -197,6 +202,7 @@
'image/image_skia_operations.h',
'image/image_skia_rep.cc',
'image/image_skia_rep.h',
+ 'image/image_skia_source.cc',
'image/image_skia_source.h',
'image/image_skia_util_ios.h',
'image/image_skia_util_ios.mm',
@@ -229,6 +235,8 @@
'paint_throbber.h',
'path.cc',
'path.h',
+ 'path_mac.h',
+ 'path_mac.mm',
'path_win.cc',
'path_win.h',
'path_x11.cc',
@@ -267,8 +275,6 @@
'screen_aura.cc',
'screen_ios.mm',
'screen_mac.mm',
- 'screen_win.cc',
- 'screen_win.h',
'scrollbar_size.cc',
'scrollbar_size.h',
'selection_model.cc',
@@ -308,6 +314,10 @@
'win/dpi.h',
'win/hwnd_util.cc',
'win/hwnd_util.h',
+ "win/physical_size.cc",
+ "win/physical_size.h",
+ 'win/rendering_window_manager.cc',
+ 'win/rendering_window_manager.h',
'win/scoped_set_map_mode.h',
'win/singleton_hwnd.cc',
'win/singleton_hwnd.h',
@@ -519,6 +529,7 @@
'image/image_unittest_util.h',
'image/image_unittest_util_ios.mm',
'image/image_unittest_util_mac.mm',
+ 'test/display_util.h',
'test/fontconfig_util_linux.cc',
'test/fontconfig_util_linux.h',
'test/gfx_util.cc',
diff --git a/chromium/ui/gfx/gfx_tests.gyp b/chromium/ui/gfx/gfx_tests.gyp
index 6c72699139f..d468e831882 100644
--- a/chromium/ui/gfx/gfx_tests.gyp
+++ b/chromium/ui/gfx/gfx_tests.gyp
@@ -63,13 +63,13 @@
'image/image_util_unittest.cc',
'mac/coordinate_conversion_unittest.mm',
'nine_image_painter_unittest.cc',
+ 'path_mac_unittest.mm',
'platform_font_linux_unittest.cc',
'platform_font_mac_unittest.mm',
'range/range_mac_unittest.mm',
'range/range_unittest.cc',
'range/range_win_unittest.cc',
'render_text_unittest.cc',
- 'screen_win_unittest.cc',
'sequential_id_generator_unittest.cc',
'shadow_value_unittest.cc',
'skbitmap_operations_unittest.cc',
diff --git a/chromium/ui/gfx/gpu_memory_buffer.cc b/chromium/ui/gfx/gpu_memory_buffer.cc
index 538611c81ea..fe6d4d192ac 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.cc
+++ b/chromium/ui/gfx/gpu_memory_buffer.cc
@@ -20,6 +20,9 @@ GpuMemoryBufferHandle::GpuMemoryBufferHandle()
: type(EMPTY_BUFFER), id(0), handle(base::SharedMemory::NULLHandle()) {
}
+GpuMemoryBufferHandle::GpuMemoryBufferHandle(
+ const GpuMemoryBufferHandle& other) = default;
+
GpuMemoryBufferHandle::~GpuMemoryBufferHandle() {}
bool GpuMemoryBuffer::IsInUseByMacOSWindowServer() const {
diff --git a/chromium/ui/gfx/gpu_memory_buffer.h b/chromium/ui/gfx/gpu_memory_buffer.h
index 15ef3c4140d..423dcf617e7 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.h
+++ b/chromium/ui/gfx/gpu_memory_buffer.h
@@ -18,7 +18,7 @@
#if defined(USE_OZONE)
#include "ui/gfx/native_pixmap_handle_ozone.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
#include "ui/gfx/mac/io_surface.h"
#endif
@@ -39,6 +39,7 @@ using GpuMemoryBufferId = GenericSharedMemoryId;
struct GFX_EXPORT GpuMemoryBufferHandle {
GpuMemoryBufferHandle();
+ GpuMemoryBufferHandle(const GpuMemoryBufferHandle& other);
~GpuMemoryBufferHandle();
bool is_null() const { return type == EMPTY_BUFFER; }
GpuMemoryBufferType type;
@@ -48,7 +49,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle {
int32_t stride;
#if defined(USE_OZONE)
NativePixmapHandle native_pixmap_handle;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
ScopedRefCountedIOSurfaceMachPort mach_port;
#endif
};
diff --git a/chromium/ui/gfx/harfbuzz_font_skia.cc b/chromium/ui/gfx/harfbuzz_font_skia.cc
index 723b68aedc9..e2adeaff4d9 100644
--- a/chromium/ui/gfx/harfbuzz_font_skia.cc
+++ b/chromium/ui/gfx/harfbuzz_font_skia.cc
@@ -16,6 +16,7 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/render_text.h"
+#include "ui/gfx/skia_util.h"
namespace gfx {
@@ -65,14 +66,14 @@ void GetGlyphWidthAndExtents(SkPaint* paint,
paint->getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds);
if (width)
- *width = SkScalarToFixed(sk_width);
+ *width = SkiaScalarToHarfBuzzUnits(sk_width);
if (extents) {
// Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
// y-grows-up.
- extents->x_bearing = SkScalarToFixed(sk_bounds.fLeft);
- extents->y_bearing = SkScalarToFixed(-sk_bounds.fTop);
- extents->width = SkScalarToFixed(sk_bounds.width());
- extents->height = SkScalarToFixed(-sk_bounds.height());
+ extents->x_bearing = SkiaScalarToHarfBuzzUnits(sk_bounds.fLeft);
+ extents->y_bearing = SkiaScalarToHarfBuzzUnits(-sk_bounds.fTop);
+ extents->width = SkiaScalarToHarfBuzzUnits(sk_bounds.width());
+ extents->height = SkiaScalarToHarfBuzzUnits(-sk_bounds.height());
}
}
@@ -132,7 +133,7 @@ hb_position_t GetGlyphKerning(FontData* font_data,
SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
SkScalar size = font_data->paint_.getTextSize();
- return SkScalarToFixed(
+ return SkiaScalarToHarfBuzzUnits(
SkScalarMulDiv(SkIntToScalar(kerning_adjustments[0]), size, upm));
}
@@ -271,7 +272,7 @@ hb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face,
face_cache->first.Init(skia_face);
hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get());
- const int scale = SkScalarToFixed(text_size);
+ const int scale = SkiaScalarToHarfBuzzUnits(text_size);
hb_font_set_scale(harfbuzz_font, scale, scale);
FontData* hb_font_data = new FontData(&face_cache->second);
hb_font_data->paint_.setTypeface(skia_face);
diff --git a/chromium/ui/gfx/icon_util_unittest.cc b/chromium/ui/gfx/icon_util_unittest.cc
index 7daa8cbf551..5ce5aa3055e 100644
--- a/chromium/ui/gfx/icon_util_unittest.cc
+++ b/chromium/ui/gfx/icon_util_unittest.cc
@@ -176,14 +176,14 @@ TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) {
bitmap.reset(new SkBitmap);
ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
bitmap->setInfo(SkImageInfo::MakeA8(kSmallIconWidth, kSmallIconHeight));
- icon = IconUtil::CreateHICONFromSkBitmap(*bitmap).Pass();
+ icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
EXPECT_FALSE(icon.is_valid());
// Invalid bitmap size.
bitmap.reset(new SkBitmap);
ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
bitmap->setInfo(SkImageInfo::MakeN32Premul(0, 0));
- icon = IconUtil::CreateHICONFromSkBitmap(*bitmap).Pass();
+ icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
EXPECT_FALSE(icon.is_valid());
// Valid bitmap configuration but no pixels allocated.
@@ -191,7 +191,7 @@ TEST_F(IconUtilTest, TestBitmapToIconInvalidParameters) {
ASSERT_NE(bitmap.get(), static_cast<SkBitmap*>(NULL));
bitmap->setInfo(SkImageInfo::MakeN32Premul(kSmallIconWidth,
kSmallIconHeight));
- icon = IconUtil::CreateHICONFromSkBitmap(*bitmap).Pass();
+ icon = IconUtil::CreateHICONFromSkBitmap(*bitmap);
EXPECT_FALSE(icon.is_valid());
}
diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc
index 9b59496a0a8..a306cc27418 100644
--- a/chromium/ui/gfx/image/image.cc
+++ b/chromium/ui/gfx/image/image.cc
@@ -510,8 +510,7 @@ const ImageSkia* Image::ToImageSkia() const {
NOTREACHED();
}
CHECK(scoped_rep);
- rep = scoped_rep.get();
- AddRepresentation(std::move(scoped_rep));
+ rep = AddRepresentation(std::move(scoped_rep));
}
return rep->AsImageRepSkia()->image();
}
@@ -541,8 +540,7 @@ UIImage* Image::ToUIImage() const {
NOTREACHED();
}
CHECK(scoped_rep);
- rep = scoped_rep.get();
- AddRepresentation(std::move(scoped_rep));
+ rep = AddRepresentation(std::move(scoped_rep));
}
return rep->AsImageRepCocoaTouch()->image();
}
@@ -575,8 +573,7 @@ NSImage* Image::ToNSImage() const {
NOTREACHED();
}
CHECK(scoped_rep);
- rep = scoped_rep.get();
- AddRepresentation(std::move(scoped_rep));
+ rep = AddRepresentation(std::move(scoped_rep));
}
return rep->AsImageRepCocoa()->image();
}
@@ -749,10 +746,18 @@ internal::ImageRep* Image::GetRepresentation(
return it->second.get();
}
-void Image::AddRepresentation(scoped_ptr<internal::ImageRep> rep) const {
+internal::ImageRep* Image::AddRepresentation(
+ scoped_ptr<internal::ImageRep> rep) const {
CHECK(storage_.get());
RepresentationType type = rep->type();
- storage_->representations().insert(std::make_pair(type, std::move(rep)));
+ auto result =
+ storage_->representations().insert(std::make_pair(type, std::move(rep)));
+
+ // insert should not fail (implies that there was already a representation of
+ // that type in the map).
+ CHECK(result.second) << "type was already in map.";
+
+ return result.first->second.get();
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image.h b/chromium/ui/gfx/image/image.h
index ec05b26d8ff..fa7ed1f2695 100644
--- a/chromium/ui/gfx/image/image.h
+++ b/chromium/ui/gfx/image/image.h
@@ -183,8 +183,11 @@ class GFX_EXPORT Image {
internal::ImageRep* GetRepresentation(
RepresentationType rep_type, bool must_exist) const;
- // Stores a representation into the map.
- void AddRepresentation(scoped_ptr<internal::ImageRep> rep) const;
+ // Stores a representation into the map. A representation of that type must
+ // not already be in the map. Returns a pointer to the representation stored
+ // inside the map.
+ internal::ImageRep* AddRepresentation(
+ scoped_ptr<internal::ImageRep> rep) const;
// Internal class that holds all the representations. This allows the Image to
// be cheaply copied.
diff --git a/chromium/ui/gfx/image/image_png_rep.cc b/chromium/ui/gfx/image/image_png_rep.cc
index 78b496fe95b..8ffa3e26ffe 100644
--- a/chromium/ui/gfx/image/image_png_rep.cc
+++ b/chromium/ui/gfx/image/image_png_rep.cc
@@ -22,6 +22,8 @@ ImagePNGRep::ImagePNGRep(const scoped_refptr<base::RefCountedMemory>& data,
scale(data_scale) {
}
+ImagePNGRep::ImagePNGRep(const ImagePNGRep& other) = default;
+
ImagePNGRep::~ImagePNGRep() {
}
diff --git a/chromium/ui/gfx/image/image_png_rep.h b/chromium/ui/gfx/image/image_png_rep.h
index 5c26134fa73..cdfe41d27ba 100644
--- a/chromium/ui/gfx/image/image_png_rep.h
+++ b/chromium/ui/gfx/image/image_png_rep.h
@@ -18,6 +18,7 @@ struct GFX_EXPORT ImagePNGRep {
ImagePNGRep();
ImagePNGRep(const scoped_refptr<base::RefCountedMemory>& data,
float data_scale);
+ ImagePNGRep(const ImagePNGRep& other);
~ImagePNGRep();
// Width and height of the image, in pixels.
diff --git a/chromium/ui/gfx/image/image_skia.cc b/chromium/ui/gfx/image/image_skia.cc
index b46d38d5ecb..8a1a2c99555 100644
--- a/chromium/ui/gfx/image/image_skia.cc
+++ b/chromium/ui/gfx/image/image_skia.cc
@@ -45,19 +45,6 @@ const float kFallbackToSmallerScaleDiff = 0.20f;
namespace internal {
namespace {
-class Matcher {
- public:
- explicit Matcher(float scale) : scale_(scale) {
- }
-
- bool operator()(const ImageSkiaRep& rep) const {
- return rep.scale() == scale_;
- }
-
- private:
- float scale_;
-};
-
ImageSkiaRep ScaleImageSkiaRep(const ImageSkiaRep& rep, float target_scale) {
if (rep.is_null() || rep.scale() == target_scale)
return rep;
@@ -76,75 +63,39 @@ ImageSkiaRep ScaleImageSkiaRep(const ImageSkiaRep& rep, float target_scale) {
// A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a
// refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
// information. Having both |base::RefCountedThreadSafe| and
-// |base::NonThreadSafe| may sounds strange but necessary to turn
+// |base::NonThreadSafe| may sound strange but is necessary to turn
// the 'thread-non-safe modifiable ImageSkiaStorage' into
// the 'thread-safe read-only ImageSkiaStorage'.
class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
public base::NonThreadSafe {
public:
- ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size)
- : source_(source),
- size_(size),
- read_only_(false) {
- }
-
- ImageSkiaStorage(ImageSkiaSource* source, float scale)
- : source_(source),
- read_only_(false) {
- ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
- if (it == image_reps_.end() || it->is_null())
- source_.reset();
- else
- size_.SetSize(it->GetWidth(), it->GetHeight());
- }
-
- bool has_source() const { return source_.get() != NULL; }
+ ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size);
+ ImageSkiaStorage(ImageSkiaSource* source, float scale);
+ bool has_source() const { return source_ != nullptr; }
std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; }
-
const gfx::Size& size() const { return size_; }
-
bool read_only() const { return read_only_; }
- void DeleteSource() {
- source_.reset();
- }
-
- void SetReadOnly() {
- read_only_ = true;
- }
-
- void DetachFromThread() {
- base::NonThreadSafe::DetachFromThread();
- }
+ void DeleteSource();
+ void SetReadOnly();
+ void DetachFromThread();
// Checks if the current thread can safely modify the storage.
- bool CanModify() const {
- return !read_only_ && CalledOnValidThread();
- }
+ bool CanModify() const;
// Checks if the current thread can safely read the storage.
- bool CanRead() const {
- return (read_only_ && !source_.get()) || CalledOnValidThread();
- }
+ bool CanRead() const;
// Add a new representation. This checks if the scale of the added image
// is not 1.0f, and mark the existing rep as scaled to make
// the image high DPI aware.
- void AddRepresentation(const ImageSkiaRep& image) {
- if (image.scale() != 1.0f) {
- for (ImageSkia::ImageSkiaReps::iterator it = image_reps_.begin();
- it < image_reps_.end();
- ++it) {
- if (it->unscaled()) {
- DCHECK_EQ(1.0f, it->scale());
- it->SetScaled();
- break;
- }
- }
- }
- image_reps_.push_back(image);
- }
+ void AddRepresentation(const ImageSkiaRep& image);
+
+ // Returns whether the underlying image source can provide a representation at
+ // any scale. In this case, the caller is guaranteed that
+ // FindRepresentation(..., true) will always succeed.
+ bool HasRepresentationAtAllScales() const;
// Returns the iterator of the image rep whose density best matches
// |scale|. If the image for the |scale| doesn't exist in the storage and
@@ -159,91 +110,13 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
// Right now only Windows uses 2 and other platforms use 1 by default.
// TODO(mukai, oshima): abandon 1 code path and use 2 for every platforms.
std::vector<ImageSkiaRep>::iterator FindRepresentation(
- float scale, bool fetch_new_image) const {
- ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
-
- ImageSkia::ImageSkiaReps::iterator closest_iter =
- non_const->image_reps().end();
- ImageSkia::ImageSkiaReps::iterator exact_iter =
- non_const->image_reps().end();
- float smallest_diff = std::numeric_limits<float>::max();
- for (ImageSkia::ImageSkiaReps::iterator it =
- non_const->image_reps().begin();
- it < image_reps_.end(); ++it) {
- if (it->scale() == scale) {
- // found exact match
- fetch_new_image = false;
- if (it->is_null())
- continue;
- exact_iter = it;
- break;
- }
- float diff = std::abs(it->scale() - scale);
- if (diff < smallest_diff && !it->is_null()) {
- closest_iter = it;
- smallest_diff = diff;
- }
- }
-
- if (fetch_new_image && source_.get()) {
- DCHECK(CalledOnValidThread()) <<
- "An ImageSkia with the source must be accessed by the same thread.";
-
- ImageSkiaRep image;
- float resource_scale = scale;
- if (g_supported_scales) {
- if (g_supported_scales->back() <= scale) {
- resource_scale = g_supported_scales->back();
- } else {
- for (size_t i = 0; i < g_supported_scales->size(); ++i) {
- if ((*g_supported_scales)[i] + kFallbackToSmallerScaleDiff >=
- scale) {
- resource_scale = (*g_supported_scales)[i];
- break;
- }
- }
- }
- }
- if (scale != resource_scale) {
- std::vector<ImageSkiaRep>::iterator iter = FindRepresentation(
- resource_scale, fetch_new_image);
- DCHECK(iter != image_reps_.end());
- image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale);
- } else {
- image = source_->GetImageForScale(scale);
- // Image may be missing for the specified scale in some cases, such like
- // looking up 2x resources but the 2x resource pack is missing. Falls
- // back to 1x and re-scale it.
- if (image.is_null() && scale != 1.0f)
- image = ScaleImageSkiaRep(source_->GetImageForScale(1.0f), scale);
- }
-
- // If the source returned the new image, store it.
- if (!image.is_null() &&
- std::find_if(image_reps_.begin(), image_reps_.end(),
- Matcher(image.scale())) == image_reps_.end()) {
- non_const->image_reps().push_back(image);
- }
-
- // If the result image's scale isn't same as the expected scale, create
- // null ImageSkiaRep with the |scale| so that the next lookup will
- // fallback to the closest scale.
- if (image.is_null() || image.scale() != scale) {
- non_const->image_reps().push_back(ImageSkiaRep(SkBitmap(), scale));
- }
-
- // image_reps_ must have the exact much now, so find again.
- return FindRepresentation(scale, false);
- }
- return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
- }
+ float scale,
+ bool fetch_new_image) const;
private:
- virtual ~ImageSkiaStorage() {
- // We only care if the storage is modified by the same thread.
- // Don't blow up even if someone else deleted the ImageSkia.
- DetachFromThread();
- }
+ friend class base::RefCountedThreadSafe<ImageSkiaStorage>;
+
+ virtual ~ImageSkiaStorage();
// Vector of bitmaps and their associated scale.
std::vector<gfx::ImageSkiaRep> image_reps_;
@@ -255,9 +128,150 @@ class ImageSkiaStorage : public base::RefCountedThreadSafe<ImageSkiaStorage>,
bool read_only_;
- friend class base::RefCountedThreadSafe<ImageSkiaStorage>;
+ DISALLOW_COPY_AND_ASSIGN(ImageSkiaStorage);
};
+ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source,
+ const gfx::Size& size)
+ : source_(source), size_(size), read_only_(false) {}
+
+ImageSkiaStorage::ImageSkiaStorage(ImageSkiaSource* source, float scale)
+ : source_(source), read_only_(false) {
+ ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
+ if (it == image_reps_.end() || it->is_null())
+ source_.reset();
+ else
+ size_.SetSize(it->GetWidth(), it->GetHeight());
+}
+
+void ImageSkiaStorage::DeleteSource() {
+ source_.reset();
+}
+
+void ImageSkiaStorage::SetReadOnly() {
+ read_only_ = true;
+}
+
+void ImageSkiaStorage::DetachFromThread() {
+ base::NonThreadSafe::DetachFromThread();
+}
+
+bool ImageSkiaStorage::CanModify() const {
+ return !read_only_ && CalledOnValidThread();
+}
+
+bool ImageSkiaStorage::CanRead() const {
+ return (read_only_ && !source_) || CalledOnValidThread();
+}
+
+void ImageSkiaStorage::AddRepresentation(const ImageSkiaRep& image) {
+ // Explicitly adding a representation makes no sense for images that
+ // inherently have representations at all scales already.
+ DCHECK(!HasRepresentationAtAllScales());
+
+ if (image.scale() != 1.0f) {
+ for (ImageSkia::ImageSkiaReps::iterator it = image_reps_.begin();
+ it < image_reps_.end(); ++it) {
+ if (it->unscaled()) {
+ DCHECK_EQ(1.0f, it->scale());
+ it->SetScaled();
+ break;
+ }
+ }
+ }
+ image_reps_.push_back(image);
+}
+
+bool ImageSkiaStorage::HasRepresentationAtAllScales() const {
+ return source_ && source_->HasRepresentationAtAllScales();
+}
+
+std::vector<ImageSkiaRep>::iterator ImageSkiaStorage::FindRepresentation(
+ float scale,
+ bool fetch_new_image) const {
+ ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
+
+ ImageSkia::ImageSkiaReps::iterator closest_iter =
+ non_const->image_reps().end();
+ ImageSkia::ImageSkiaReps::iterator exact_iter = non_const->image_reps().end();
+ float smallest_diff = std::numeric_limits<float>::max();
+ for (ImageSkia::ImageSkiaReps::iterator it = non_const->image_reps().begin();
+ it < image_reps_.end(); ++it) {
+ if (it->scale() == scale) {
+ // found exact match
+ fetch_new_image = false;
+ if (it->is_null())
+ continue;
+ exact_iter = it;
+ break;
+ }
+ float diff = std::abs(it->scale() - scale);
+ if (diff < smallest_diff && !it->is_null()) {
+ closest_iter = it;
+ smallest_diff = diff;
+ }
+ }
+
+ if (fetch_new_image && source_.get()) {
+ DCHECK(CalledOnValidThread())
+ << "An ImageSkia with the source must be accessed by the same thread.";
+
+ ImageSkiaRep image;
+ float resource_scale = scale;
+ if (g_supported_scales) {
+ if (g_supported_scales->back() <= scale) {
+ resource_scale = g_supported_scales->back();
+ } else {
+ for (size_t i = 0; i < g_supported_scales->size(); ++i) {
+ if ((*g_supported_scales)[i] + kFallbackToSmallerScaleDiff >= scale) {
+ resource_scale = (*g_supported_scales)[i];
+ break;
+ }
+ }
+ }
+ }
+ if (scale != resource_scale) {
+ std::vector<ImageSkiaRep>::iterator iter =
+ FindRepresentation(resource_scale, fetch_new_image);
+ DCHECK(iter != image_reps_.end());
+ image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale);
+ } else {
+ image = source_->GetImageForScale(scale);
+ // Image may be missing for the specified scale in some cases, such like
+ // looking up 2x resources but the 2x resource pack is missing. Fall back
+ // to 1x and re-scale it.
+ if (image.is_null() && scale != 1.0f)
+ image = ScaleImageSkiaRep(source_->GetImageForScale(1.0f), scale);
+ }
+
+ // If the source returned the new image, store it.
+ if (!image.is_null() &&
+ std::find_if(image_reps_.begin(), image_reps_.end(),
+ [&image](const ImageSkiaRep& rep) {
+ return rep.scale() == image.scale();
+ }) == image_reps_.end()) {
+ non_const->image_reps().push_back(image);
+ }
+
+ // If the result image's scale isn't same as the expected scale, create a
+ // null ImageSkiaRep with the |scale| so that the next lookup will fall back
+ // to the closest scale.
+ if (image.is_null() || image.scale() != scale) {
+ non_const->image_reps().push_back(ImageSkiaRep(SkBitmap(), scale));
+ }
+
+ // image_reps_ must have the exact much now, so find again.
+ return FindRepresentation(scale, false);
+ }
+ return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
+}
+
+ImageSkiaStorage::~ImageSkiaStorage() {
+ // We only care if the storage is modified by the same thread. Don't blow up
+ // even if someone else deleted the ImageSkia.
+ DetachFromThread();
+}
+
} // internal
ImageSkia::ImageSkia() : storage_(NULL) {
@@ -378,6 +392,14 @@ bool ImageSkia::HasRepresentation(float scale) const {
return false;
CHECK(CanRead());
+ // This check is not only faster than FindRepresentation(), it's important for
+ // getting the right answer in cases of image types that are not based on
+ // discrete preset underlying representations, which otherwise might report
+ // "false" for this if GetRepresentation() has not yet been called for this
+ // |scale|.
+ if (storage_->HasRepresentationAtAllScales())
+ return true;
+
ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, false);
return (it != storage_->image_reps().end() && it->scale() == scale);
}
diff --git a/chromium/ui/gfx/image/image_skia_source.cc b/chromium/ui/gfx/image/image_skia_source.cc
new file mode 100644
index 00000000000..53bc4271ca7
--- /dev/null
+++ b/chromium/ui/gfx/image/image_skia_source.cc
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/image/image_skia_source.h"
+
+namespace gfx {
+
+ImageSkiaSource::~ImageSkiaSource() {}
+
+bool ImageSkiaSource::HasRepresentationAtAllScales() const { return false; }
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_source.h b/chromium/ui/gfx/image/image_skia_source.h
index 6250032292b..9c50760edb6 100644
--- a/chromium/ui/gfx/image/image_skia_source.h
+++ b/chromium/ui/gfx/image/image_skia_source.h
@@ -15,13 +15,17 @@ class ImageSkiaRep;
class GFX_EXPORT ImageSkiaSource {
public:
- virtual ~ImageSkiaSource() {}
+ virtual ~ImageSkiaSource();
// Returns the ImageSkiaRep for the given |scale|. ImageSkia caches the
// returned ImageSkiaRep and calls this method only if it doesn't have
// ImageSkiaRep for given |scale|. There is no need for the implementation to
// cache the image.
virtual gfx::ImageSkiaRep GetImageForScale(float scale) = 0;
+
+ // Subclasses should override this to return true when they are capable of
+ // providing an exact representation at any desired scale factor.
+ virtual bool HasRepresentationAtAllScales() const;
};
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_unittest.cc b/chromium/ui/gfx/image/image_unittest.cc
index d39adacd581..641ccfa88c7 100644
--- a/chromium/ui/gfx/image/image_unittest.cc
+++ b/chromium/ui/gfx/image/image_unittest.cc
@@ -269,7 +269,15 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) {
#endif
}
-TEST_F(ImageTest, MultiResolutionPNGToPlatform) {
+// TODO(crbug.com/153782): disable this test as it fails on iOS retina devices.
+#if defined(OS_IOS)
+#define MAYBE_MultiResolutionPNGToPlatform \
+ DISABLED_MultiResolutionPNGToPlatform
+#else
+#define MAYBE_MultiResolutionPNGToPlatform \
+ MultiResolutionPNGToPlatform
+#endif
+TEST_F(ImageTest, MAYBE_MultiResolutionPNGToPlatform) {
const int kSize1x = 25;
const int kSize2x = 50;
@@ -319,7 +327,15 @@ TEST_F(ImageTest, PlatformToPNGEncodeAndDecode) {
// The platform types use the platform provided encoding/decoding of PNGs. Make
// sure these work with the Skia Encode/Decode.
-TEST_F(ImageTest, PNGEncodeFromSkiaDecodeToPlatform) {
+// TODO(crbug.com/153782): disable this test as it fails on iOS retina devices.
+#if defined(OS_IOS)
+#define MAYBE_PNGEncodeFromSkiaDecodeToPlatform \
+ DISABLED_PNGEncodeFromSkiaDecodeToPlatform
+#else
+#define MAYBE_PNGEncodeFromSkiaDecodeToPlatform \
+ PNGEncodeFromSkiaDecodeToPlatform
+#endif
+TEST_F(ImageTest, MAYBE_PNGEncodeFromSkiaDecodeToPlatform) {
// Force the conversion sequence skia to png to platform_type.
gfx::Image from_bitmap = gfx::Image::CreateFrom1xBitmap(
gt::CreateBitmap(25, 25));
diff --git a/chromium/ui/gfx/image/image_unittest_util.cc b/chromium/ui/gfx/image/image_unittest_util.cc
index 2e150a87701..182826f7e1f 100644
--- a/chromium/ui/gfx/image/image_unittest_util.cc
+++ b/chromium/ui/gfx/image/image_unittest_util.cc
@@ -211,10 +211,16 @@ bool IsEmpty(const gfx::Image& image) {
}
PlatformImage CreatePlatformImage() {
- const SkBitmap bitmap(CreateBitmap(25, 25));
+ SkBitmap bitmap(CreateBitmap(25, 25));
#if defined(OS_IOS)
float scale = ImageSkia::GetMaxSupportedScale();
+ if (scale > 1.0) {
+ // Always create a 25pt x 25pt image.
+ int size = static_cast<int>(25 * scale);
+ bitmap = CreateBitmap(size, size);
+ }
+
base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
CGColorSpaceCreateDeviceRGB());
UIImage* image =
diff --git a/chromium/ui/gfx/image/image_util.cc b/chromium/ui/gfx/image/image_util.cc
index e991da955e4..53bcceee073 100644
--- a/chromium/ui/gfx/image/image_util.cc
+++ b/chromium/ui/gfx/image/image_util.cc
@@ -15,9 +15,23 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
-namespace gfx {
+namespace {
+
+// Returns whether column |x| of |bitmap| has any "visible pixels", where
+// "visible" is defined as having an opactiy greater than an arbitrary small
+// value.
+bool ColumnHasVisiblePixels(const SkBitmap& bitmap, int x) {
+ const SkAlpha kMinimumVisibleOpacity = 12;
+ for (int y = 0; y < bitmap.height(); ++y) {
+ if (SkColorGetA(bitmap.getColor(x, y)) > kMinimumVisibleOpacity)
+ return true;
+ }
+ return false;
+}
-const uint32_t kMinimumVisibleOpacity = 12;
+} // namespace
+
+namespace gfx {
// The iOS implementations of the JPEG functions are in image_util_ios.mm.
#if !defined(OS_IOS)
@@ -52,57 +66,39 @@ bool JPEG1xEncodedDataFromImage(const Image& image, int quality,
}
#endif // !defined(OS_IOS)
-bool VisibleMargins(const ImageSkia& image, int* leading, int* trailing) {
- *leading = 0;
- *trailing = std::max(1, image.width()) - 1;
- if (!image.HasRepresentation(1.0))
- return false;
-
- const ImageSkiaRep& rep = image.GetRepresentation(1.0);
- if (rep.is_null())
- return false;
-
- const SkBitmap& bitmap = rep.sk_bitmap();
- if (bitmap.isNull() || bitmap.width() == 0)
- return false;
-
- if (bitmap.isOpaque())
- return true;
-
- SkAutoLockPixels l(bitmap);
- int inner_min = bitmap.width();
- for (int x = 0; x < bitmap.width(); ++x) {
- for (int y = 0; y < bitmap.height(); ++y) {
- if (SkColorGetA(bitmap.getColor(x, y)) > kMinimumVisibleOpacity) {
- inner_min = x;
- break;
- }
- }
- if (inner_min < bitmap.width())
+void GetVisibleMargins(const ImageSkia& image, int* left, int* right) {
+ *left = 0;
+ *right = 0;
+ if (!image.HasRepresentation(1.f))
+ return;
+ const SkBitmap& bitmap = image.GetRepresentation(1.f).sk_bitmap();
+ if (bitmap.drawsNothing() || bitmap.isOpaque())
+ return;
+
+ SkAutoLockPixels lock(bitmap);
+ int x = 0;
+ for (; x < bitmap.width(); ++x) {
+ if (ColumnHasVisiblePixels(bitmap, x)) {
+ *left = x;
break;
- }
-
- int inner_max = -1;
- for (int x = bitmap.width() - 1; x > inner_min; --x) {
- for (int y = 0; y < bitmap.height(); ++y) {
- if (SkColorGetA(bitmap.getColor(x, y)) > kMinimumVisibleOpacity) {
- inner_max = x;
- break;
- }
}
- if (inner_max > -1)
- break;
}
- if (inner_min == bitmap.width()) {
- *leading = bitmap.width()/2;
- *trailing = bitmap.width()/2 + 1;
- return true;
+ if (x == bitmap.width()) {
+ // Image is fully transparent. Divide the width in half, giving the leading
+ // region the extra pixel for odd widths.
+ *left = (bitmap.width() + 1) / 2;
+ *right = bitmap.width() - *left;
+ return;
}
- *leading = inner_min;
- *trailing = inner_max;
- return true;
+ // Since we already know column *left is non-transparent, we can avoid
+ // rechecking that column; hence the '>' here.
+ for (x = bitmap.width() - 1; x > *left; --x) {
+ if (ColumnHasVisiblePixels(bitmap, x))
+ break;
+ }
+ *right = bitmap.width() - 1 - x;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_util.h b/chromium/ui/gfx/image/image_util.h
index c2ce2a105f6..8f17c368a8c 100644
--- a/chromium/ui/gfx/image/image_util.h
+++ b/chromium/ui/gfx/image/image_util.h
@@ -33,21 +33,15 @@ GFX_EXPORT bool JPEG1xEncodedDataFromImage(const Image& image,
int quality,
std::vector<unsigned char>* dst);
-// Returns the visible (non-transparent) width of the 1x rep of the given
-// image. If the image has no transparency, the leading value will be 0 and
-// the trailing will be the image width. Return values are in the 1x width
-// pixel units. Margins are given in 0-based column format. So if the image
-// has only transparent pixels in columns 0, 1, 2, 3, then the leading value
-// will be 4. Similarly, if there are all transparent pixels in column
-// width-2, width-1, then the trailing margin value will be width-3.
-// Returns true if the value is computed from opacity, false if it is a
-// default value because of null image, missing Rep, etc.
-// This method is only suitable for fairly small images (i.e. 16x16).
-// The margins for a completely transparent image will be w/2-1, w/2, but this
-// will be an expensive operation: it isn't expected that it will be frequently
-// calculated.
-GFX_EXPORT bool VisibleMargins(const ImageSkia& image,
- int* leading, int* trailing);
+// Computes the width of any nearly-transparent regions at the sides of the
+// image and returns them in |left| and |right|. This checks each column of
+// pixels from the outsides in, looking for anything with alpha above a
+// reasonably small value. For a fully-opaque image, the margins will thus be
+// (0, 0); for a fully-transparent image, the margins will be
+// (width / 2, width / 2), with |left| getting the extra pixel for odd widths.
+GFX_EXPORT void GetVisibleMargins(const ImageSkia& image,
+ int* left,
+ int* right);
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_util_unittest.cc b/chromium/ui/gfx/image/image_util_unittest.cc
index 4816891cda1..2cde9c402b4 100644
--- a/chromium/ui/gfx/image/image_util_unittest.cc
+++ b/chromium/ui/gfx/image/image_util_unittest.cc
@@ -26,73 +26,110 @@ TEST(ImageUtilTest, JPEGEncodeAndDecode) {
EXPECT_FALSE(decoded.IsEmpty());
}
-TEST(ImageUtilTest, TestVisibleMargins) {
- // Image with non-transparent piece should return margins at those
- // columns.
- SkBitmap bitmap1;
- bitmap1.allocN32Pixels(16, 16);
- bitmap1.eraseColor(SK_ColorTRANSPARENT);
- bitmap1.eraseArea(SkIRect::MakeLTRB(3, 3, 14, 14), SK_ColorYELLOW);
- gfx::ImageSkia img = gfx::ImageSkia::CreateFrom1xBitmap(bitmap1);
- int x = 0;
- int y = 0;
- gfx::VisibleMargins(img, &x, &y);
- EXPECT_EQ(3, x);
- EXPECT_EQ(13, y);
- EXPECT_EQ(16, img.width());
-
- // Full-width-transparent image should return margins in the center
- // of the image.
- SkBitmap bitmap2;
- bitmap2.allocN32Pixels(16, 16);
- bitmap2.eraseColor(SK_ColorTRANSPARENT);
- gfx::ImageSkia img_transparent = gfx::ImageSkia::CreateFrom1xBitmap(bitmap2);
- x = 0;
- y = 0;
- gfx::VisibleMargins(img_transparent, &x, &y);
- EXPECT_EQ(8, x);
- EXPECT_EQ(9, y);
- EXPECT_EQ(16, img_transparent.width());
-
- // Image with non-transparent piece that is skewed to one side should
- // return margins at those columns.
- SkBitmap bitmap3;
- bitmap3.allocN32Pixels(16, 16);
- bitmap3.eraseColor(SK_ColorTRANSPARENT);
- bitmap3.eraseArea(SkIRect::MakeLTRB(3, 3, 5, 5), SK_ColorYELLOW);
- gfx::ImageSkia img3 = gfx::ImageSkia::CreateFrom1xBitmap(bitmap3);
- x = 0;
- y = 0;
- gfx::VisibleMargins(img3, &x, &y);
- EXPECT_EQ(3, x);
- EXPECT_EQ(4, y);
- EXPECT_EQ(16, img3.width());
-
- // Image with non-transparent piece that is at one edge should
- // return margins at those columns.
- SkBitmap bitmap4;
- bitmap4.allocN32Pixels(16, 16);
- bitmap4.eraseColor(SK_ColorTRANSPARENT);
- bitmap4.eraseArea(SkIRect::MakeLTRB(0, 3, 5, 5), SK_ColorYELLOW);
- gfx::ImageSkia img4 = gfx::ImageSkia::CreateFrom1xBitmap(bitmap4);
- x = 0;
- y = 0;
- gfx::VisibleMargins(img4, &x, &y);
- EXPECT_EQ(0, x);
- EXPECT_EQ(4, y);
- EXPECT_EQ(16, img4.width());
-
- // Image with non-transparent piece that is at trailing edge should
- // return margins at those columns.
- SkBitmap bitmap5;
- bitmap5.allocN32Pixels(16, 16);
- bitmap5.eraseColor(SK_ColorTRANSPARENT);
- bitmap5.eraseArea(SkIRect::MakeLTRB(4, 3, 16, 16), SK_ColorYELLOW);
- gfx::ImageSkia img5 = gfx::ImageSkia::CreateFrom1xBitmap(bitmap5);
- x = 0;
- y = 0;
- gfx::VisibleMargins(img5, &x, &y);
- EXPECT_EQ(4, x);
- EXPECT_EQ(15, y);
- EXPECT_EQ(16, img5.width());
+TEST(ImageUtilTest, GetVisibleMargins) {
+ int left, right;
+
+ // Fully transparent image.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(8, left);
+ EXPECT_EQ(8, right);
+ }
+
+ // Fully non-transparent image.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(0, left);
+ EXPECT_EQ(0, right);
+ }
+
+ // Image with non-transparent section in center.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.eraseArea(SkIRect::MakeLTRB(3, 2, 13, 13), SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(3, left);
+ EXPECT_EQ(3, right);
+ }
+
+ // Image with non-transparent section skewed to one side.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.eraseArea(SkIRect::MakeLTRB(3, 2, 5, 5), SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(3, left);
+ EXPECT_EQ(11, right);
+ }
+
+ // Image with non-transparent section at leading edge.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.eraseArea(SkIRect::MakeLTRB(0, 3, 5, 5), SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(0, left);
+ EXPECT_EQ(11, right);
+ }
+
+ // Image with non-transparent section at trailing edge.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.eraseArea(SkIRect::MakeLTRB(4, 3, 16, 13), SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(4, left);
+ EXPECT_EQ(0, right);
+ }
+
+ // Image with narrow non-transparent section.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.eraseArea(SkIRect::MakeLTRB(8, 3, 9, 5), SK_ColorYELLOW);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(8, left);
+ EXPECT_EQ(7, right);
+ }
+
+ // Image with faint pixels.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 14);
+ bitmap.eraseColor(SkColorSetA(SK_ColorYELLOW, 0x02));
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(8, left);
+ EXPECT_EQ(8, right);
+ }
+
+ // Fully transparent image with odd width.
+ {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(17, 14);
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ gfx::ImageSkia img(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+ gfx::GetVisibleMargins(img, &left, &right);
+ EXPECT_EQ(9, left);
+ EXPECT_EQ(8, right);
+ }
}
diff --git a/chromium/ui/gfx/ipc/BUILD.gn b/chromium/ui/gfx/ipc/BUILD.gn
index 28da1662635..b65ea3a7c3e 100644
--- a/chromium/ui/gfx/ipc/BUILD.gn
+++ b/chromium/ui/gfx/ipc/BUILD.gn
@@ -16,7 +16,6 @@ component("ipc") {
deps = [
"//base",
"//ipc",
- "//skia",
"//ui/gfx",
"//ui/gfx/geometry",
]
diff --git a/chromium/ui/gfx/ipc/gfx_ipc.gyp b/chromium/ui/gfx/ipc/gfx_ipc.gyp
index 80e1947bea2..fac0e4c99d6 100644
--- a/chromium/ui/gfx/ipc/gfx_ipc.gyp
+++ b/chromium/ui/gfx/ipc/gfx_ipc.gyp
@@ -14,7 +14,6 @@
'dependencies': [
'../../../base/base.gyp:base',
'../../../ipc/ipc.gyp:ipc',
- '../../../skia/skia.gyp:skia',
'../gfx.gyp:gfx',
'../gfx.gyp:gfx_geometry',
],
diff --git a/chromium/ui/gfx/ipc/gfx_param_traits.cc b/chromium/ui/gfx/ipc/gfx_param_traits.cc
index a49e1da9598..551957e095d 100644
--- a/chromium/ui/gfx/ipc/gfx_param_traits.cc
+++ b/chromium/ui/gfx/ipc/gfx_param_traits.cc
@@ -9,7 +9,6 @@
#include <string>
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -20,53 +19,14 @@
#include "ipc/mach_port_mac.h"
#endif
-namespace {
-
-struct SkBitmap_Data {
- // The color type for the bitmap (bits per pixel, etc).
- SkColorType fColorType;
-
- // The alpha type for the bitmap (opaque, premul, unpremul).
- SkAlphaType fAlphaType;
-
- // The width of the bitmap in pixels.
- uint32_t fWidth;
-
- // The height of the bitmap in pixels.
- uint32_t fHeight;
-
- void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
- const SkImageInfo& info = bitmap.info();
- fColorType = info.colorType();
- fAlphaType = info.alphaType();
- fWidth = info.width();
- fHeight = info.height();
- }
-
- // Returns whether |bitmap| successfully initialized.
- bool InitSkBitmapFromData(SkBitmap* bitmap,
- const char* pixels,
- size_t pixels_size) const {
- if (!bitmap->tryAllocPixels(
- SkImageInfo::Make(fWidth, fHeight, fColorType, fAlphaType)))
- return false;
- if (pixels_size != bitmap->getSize())
- return false;
- memcpy(bitmap->getPixels(), pixels, pixels_size);
- return true;
- }
-};
-
-} // namespace
-
namespace IPC {
-void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
+void ParamTraits<gfx::Point>::Write(base::Pickle* m, const gfx::Point& p) {
WriteParam(m, p.x());
WriteParam(m, p.y());
}
-bool ParamTraits<gfx::Point>::Read(const Message* m,
+bool ParamTraits<gfx::Point>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Point* r) {
int x, y;
@@ -81,12 +41,18 @@ void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::string* l) {
l->append(base::StringPrintf("(%d, %d)", p.x(), p.y()));
}
-void ParamTraits<gfx::PointF>::Write(Message* m, const gfx::PointF& p) {
+void ParamTraits<gfx::PointF>::GetSize(base::PickleSizer* s,
+ const gfx::PointF& p) {
+ GetParamSize(s, p.x());
+ GetParamSize(s, p.y());
+}
+
+void ParamTraits<gfx::PointF>::Write(base::Pickle* m, const gfx::PointF& p) {
WriteParam(m, p.x());
WriteParam(m, p.y());
}
-bool ParamTraits<gfx::PointF>::Read(const Message* m,
+bool ParamTraits<gfx::PointF>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::PointF* r) {
float x, y;
@@ -101,13 +67,13 @@ void ParamTraits<gfx::PointF>::Log(const gfx::PointF& p, std::string* l) {
l->append(base::StringPrintf("(%f, %f)", p.x(), p.y()));
}
-void ParamTraits<gfx::Point3F>::Write(Message* m, const gfx::Point3F& p) {
+void ParamTraits<gfx::Point3F>::Write(base::Pickle* m, const gfx::Point3F& p) {
WriteParam(m, p.x());
WriteParam(m, p.y());
WriteParam(m, p.z());
}
-bool ParamTraits<gfx::Point3F>::Read(const Message* m,
+bool ParamTraits<gfx::Point3F>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Point3F* r) {
float x, y, z;
@@ -124,14 +90,14 @@ void ParamTraits<gfx::Point3F>::Log(const gfx::Point3F& p, std::string* l) {
l->append(base::StringPrintf("(%f, %f, %f)", p.x(), p.y(), p.z()));
}
-void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
+void ParamTraits<gfx::Size>::Write(base::Pickle* m, const gfx::Size& p) {
DCHECK_GE(p.width(), 0);
DCHECK_GE(p.height(), 0);
int values[2] = { p.width(), p.height() };
m->WriteBytes(&values, sizeof(int) * 2);
}
-bool ParamTraits<gfx::Size>::Read(const Message* m,
+bool ParamTraits<gfx::Size>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Size* r) {
const char* char_values;
@@ -149,12 +115,12 @@ void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
l->append(base::StringPrintf("(%d, %d)", p.width(), p.height()));
}
-void ParamTraits<gfx::SizeF>::Write(Message* m, const gfx::SizeF& p) {
+void ParamTraits<gfx::SizeF>::Write(base::Pickle* m, const gfx::SizeF& p) {
float values[2] = { p.width(), p.height() };
m->WriteBytes(&values, sizeof(float) * 2);
}
-bool ParamTraits<gfx::SizeF>::Read(const Message* m,
+bool ParamTraits<gfx::SizeF>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::SizeF* r) {
const char* char_values;
@@ -170,12 +136,18 @@ void ParamTraits<gfx::SizeF>::Log(const gfx::SizeF& p, std::string* l) {
l->append(base::StringPrintf("(%f, %f)", p.width(), p.height()));
}
-void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& p) {
+void ParamTraits<gfx::Vector2d>::GetSize(base::PickleSizer* s,
+ const gfx::Vector2d& p) {
+ s->AddBytes(sizeof(int) * 2);
+}
+
+void ParamTraits<gfx::Vector2d>::Write(base::Pickle* m,
+ const gfx::Vector2d& p) {
int values[2] = { p.x(), p.y() };
m->WriteBytes(&values, sizeof(int) * 2);
}
-bool ParamTraits<gfx::Vector2d>::Read(const Message* m,
+bool ParamTraits<gfx::Vector2d>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Vector2d* r) {
const char* char_values;
@@ -191,12 +163,13 @@ void ParamTraits<gfx::Vector2d>::Log(const gfx::Vector2d& v, std::string* l) {
l->append(base::StringPrintf("(%d, %d)", v.x(), v.y()));
}
-void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& p) {
+void ParamTraits<gfx::Vector2dF>::Write(base::Pickle* m,
+ const gfx::Vector2dF& p) {
float values[2] = { p.x(), p.y() };
m->WriteBytes(&values, sizeof(float) * 2);
}
-bool ParamTraits<gfx::Vector2dF>::Read(const Message* m,
+bool ParamTraits<gfx::Vector2dF>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Vector2dF* r) {
const char* char_values;
@@ -212,12 +185,12 @@ void ParamTraits<gfx::Vector2dF>::Log(const gfx::Vector2dF& v, std::string* l) {
l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
}
-void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
+void ParamTraits<gfx::Rect>::Write(base::Pickle* m, const gfx::Rect& p) {
int values[4] = { p.x(), p.y(), p.width(), p.height() };
m->WriteBytes(&values, sizeof(int) * 4);
}
-bool ParamTraits<gfx::Rect>::Read(const Message* m,
+bool ParamTraits<gfx::Rect>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Rect* r) {
const char* char_values;
@@ -235,12 +208,17 @@ void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
p.width(), p.height()));
}
-void ParamTraits<gfx::RectF>::Write(Message* m, const gfx::RectF& p) {
+void ParamTraits<gfx::RectF>::GetSize(base::PickleSizer* s,
+ const gfx::RectF& p) {
+ s->AddBytes(sizeof(float) * 4);
+}
+
+void ParamTraits<gfx::RectF>::Write(base::Pickle* m, const gfx::RectF& p) {
float values[4] = { p.x(), p.y(), p.width(), p.height() };
m->WriteBytes(&values, sizeof(float) * 4);
}
-bool ParamTraits<gfx::RectF>::Read(const Message* m,
+bool ParamTraits<gfx::RectF>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::RectF* r) {
const char* char_values;
@@ -256,57 +234,16 @@ void ParamTraits<gfx::RectF>::Log(const gfx::RectF& p, std::string* l) {
p.width(), p.height()));
}
-void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
- size_t fixed_size = sizeof(SkBitmap_Data);
- SkBitmap_Data bmp_data;
- bmp_data.InitSkBitmapDataForTransfer(p);
- m->WriteData(reinterpret_cast<const char*>(&bmp_data),
- static_cast<int>(fixed_size));
- size_t pixel_size = p.getSize();
- SkAutoLockPixels p_lock(p);
- m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
- static_cast<int>(pixel_size));
-}
-
-bool ParamTraits<SkBitmap>::Read(const Message* m,
- base::PickleIterator* iter,
- SkBitmap* r) {
- const char* fixed_data;
- int fixed_data_size = 0;
- if (!iter->ReadData(&fixed_data, &fixed_data_size) ||
- (fixed_data_size <= 0)) {
- NOTREACHED();
- return false;
- }
- if (fixed_data_size != sizeof(SkBitmap_Data))
- return false; // Message is malformed.
-
- const char* variable_data;
- int variable_data_size = 0;
- if (!iter->ReadData(&variable_data, &variable_data_size) ||
- (variable_data_size < 0)) {
- NOTREACHED();
- return false;
- }
- const SkBitmap_Data* bmp_data =
- reinterpret_cast<const SkBitmap_Data*>(fixed_data);
- return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
-}
-
-void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::string* l) {
- l->append("<SkBitmap>");
-}
-
-void ParamTraits<gfx::Range>::Write(Message* m, const gfx::Range& r) {
- m->WriteSizeT(r.start());
- m->WriteSizeT(r.end());
+void ParamTraits<gfx::Range>::Write(base::Pickle* m, const gfx::Range& r) {
+ m->WriteUInt32(r.start());
+ m->WriteUInt32(r.end());
}
-bool ParamTraits<gfx::Range>::Read(const Message* m,
+bool ParamTraits<gfx::Range>::Read(const base::Pickle* m,
base::PickleIterator* iter,
gfx::Range* r) {
- size_t start, end;
- if (!iter->ReadSizeT(&start) || !iter->ReadSizeT(&end))
+ uint32_t start, end;
+ if (!iter->ReadUInt32(&start) || !iter->ReadUInt32(&end))
return false;
r->set_start(start);
r->set_end(end);
@@ -314,15 +251,16 @@ bool ParamTraits<gfx::Range>::Read(const Message* m,
}
void ParamTraits<gfx::Range>::Log(const gfx::Range& r, std::string* l) {
- l->append(base::StringPrintf("(%" PRIuS ", %" PRIuS ")", r.start(), r.end()));
+ l->append(base::StringPrintf("(%d, %d)", r.start(), r.end()));
}
-void ParamTraits<gfx::ScrollOffset>::Write(Message* m, const param_type& p) {
+void ParamTraits<gfx::ScrollOffset>::Write(base::Pickle* m,
+ const param_type& p) {
m->WriteDouble(p.x());
m->WriteDouble(p.y());
}
-bool ParamTraits<gfx::ScrollOffset>::Read(const Message* m,
+bool ParamTraits<gfx::ScrollOffset>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
double x = 0.f;
@@ -346,14 +284,14 @@ void ParamTraits<gfx::ScrollOffset>::Log(const param_type& p, std::string* l) {
#if defined(OS_MACOSX) && !defined(OS_IOS)
void ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort>::Write(
- Message* m,
+ base::Pickle* m,
const param_type p) {
MachPortMac mach_port_mac(p.get());
ParamTraits<MachPortMac>::Write(m, mach_port_mac);
}
bool ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
MachPortMac mach_port_mac;
diff --git a/chromium/ui/gfx/ipc/gfx_param_traits.h b/chromium/ui/gfx/ipc/gfx_param_traits.h
index b7280ef0510..5fbf8859224 100644
--- a/chromium/ui/gfx/ipc/gfx_param_traits.h
+++ b/chromium/ui/gfx/ipc/gfx_param_traits.h
@@ -17,8 +17,6 @@
#include "ui/gfx/mac/io_surface.h"
#endif
-class SkBitmap;
-
namespace gfx {
class Point;
class PointF;
@@ -38,100 +36,113 @@ namespace IPC {
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Point> {
typedef gfx::Point param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::PointF> {
typedef gfx::PointF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void GetSize(base::PickleSizer* s, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Point3F> {
typedef gfx::Point3F param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Size> {
typedef gfx::Size param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::SizeF> {
typedef gfx::SizeF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Vector2d> {
typedef gfx::Vector2d param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void GetSize(base::PickleSizer* s, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Vector2dF> {
typedef gfx::Vector2dF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Rect> {
typedef gfx::Rect param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::RectF> {
typedef gfx::RectF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct GFX_IPC_EXPORT ParamTraits<SkBitmap> {
- typedef SkBitmap param_type;
- static void Write(Message* m, const param_type& p);
-
- // Note: This function expects parameter |r| to be of type &SkBitmap since
- // r->SetConfig() and r->SetPixels() are called.
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
-
+ static void GetSize(base::PickleSizer* s, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::Range> {
typedef gfx::Range param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::ScrollOffset> {
typedef gfx::ScrollOffset param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
@@ -139,12 +150,14 @@ struct GFX_IPC_EXPORT ParamTraits<gfx::ScrollOffset> {
template <>
struct GFX_IPC_EXPORT ParamTraits<gfx::ScopedRefCountedIOSurfaceMachPort> {
typedef gfx::ScopedRefCountedIOSurfaceMachPort param_type;
- static void Write(Message* m, const param_type p);
+ static void Write(base::Pickle* m, const param_type p);
// Note: Read() passes ownership of the Mach send right from the IPC message
// to the ScopedRefCountedIOSurfaceMachPort. Therefore, Read() may only be
// called once for a given message, otherwise the singular right will be
// managed and released by two objects.
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/chromium/ui/gfx/ipc/skia/BUILD.gn b/chromium/ui/gfx/ipc/skia/BUILD.gn
new file mode 100644
index 00000000000..60718d2eeae
--- /dev/null
+++ b/chromium/ui/gfx/ipc/skia/BUILD.gn
@@ -0,0 +1,23 @@
+# 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.
+
+component("skia") {
+ output_name = "gfx_ipc_skia"
+
+ sources = [
+ "gfx_skia_param_traits.cc",
+ "gfx_skia_param_traits.h",
+ ]
+
+ defines = [ "GFX_SKIA_IPC_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ipc",
+ "//skia",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ "//ui/gfx/ipc",
+ ]
+}
diff --git a/chromium/ui/gfx/ipc/skia/gfx_ipc_skia.gyp b/chromium/ui/gfx/ipc/skia/gfx_ipc_skia.gyp
new file mode 100644
index 00000000000..337858def71
--- /dev/null
+++ b/chromium/ui/gfx/ipc/skia/gfx_ipc_skia.gyp
@@ -0,0 +1,34 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [
+ {
+ # GN version: //ui/gfx/ipc/skia
+ 'target_name': 'gfx_ipc_skia',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../../../base/base.gyp:base',
+ '../../../../ipc/ipc.gyp:ipc',
+ '../../../../skia/skia.gyp:skia',
+ '../../gfx.gyp:gfx',
+ '../../gfx.gyp:gfx_geometry',
+ '../gfx_ipc.gyp:gfx_ipc',
+ ],
+ 'defines': [
+ 'GFX_SKIA_IPC_IMPLEMENTATION',
+ ],
+ 'include_dirs': [
+ '../../../..',
+ ],
+ 'sources': [
+ 'gfx_skia_param_traits.cc',
+ 'gfx_skia_param_traits.h',
+ ],
+ },
+ ],
+}
diff --git a/chromium/ui/gfx/ipc/skia/gfx_skia_ipc_export.h b/chromium/ui/gfx/ipc/skia/gfx_skia_ipc_export.h
new file mode 100644
index 00000000000..dc29fb945d6
--- /dev/null
+++ b/chromium/ui/gfx/ipc/skia/gfx_skia_ipc_export.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_IPC_GFX_SKIA_IPC_EXPORT_H_
+#define UI_GFX_IPC_GFX_SKIA_IPC_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GFX_SKIA_IPC_IMPLEMENTATION)
+#define GFX_SKIA_IPC_EXPORT __declspec(dllexport)
+#else
+#define GFX_SKIA_IPC_EXPORT __declspec(dllimport)
+#endif // defined(GFX_SKIA_IPC_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GFX_SKIA_IPC_IMPLEMENTATION)
+#define GFX_SKIA_IPC_EXPORT __attribute__((visibility("default")))
+#else
+#define GFX_SKIA_IPC_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GFX_SKIA_IPC_EXPORT
+#endif
+
+#endif // UI_GFX_IPC_GFX_SKIA_IPC_EXPORT_H_
diff --git a/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc
new file mode 100644
index 00000000000..033590c4060
--- /dev/null
+++ b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.cc
@@ -0,0 +1,135 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
+
+#include <string>
+
+#include "base/pickle.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "ui/gfx/transform.h"
+
+namespace {
+
+struct SkBitmap_Data {
+ // The color type for the bitmap (bits per pixel, etc).
+ SkColorType color_type;
+
+ // The alpha type for the bitmap (opaque, premul, unpremul).
+ SkAlphaType alpha_type;
+
+ // The width of the bitmap in pixels.
+ uint32_t width;
+
+ // The height of the bitmap in pixels.
+ uint32_t height;
+
+ void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
+ const SkImageInfo& info = bitmap.info();
+ color_type = info.colorType();
+ alpha_type = info.alphaType();
+ width = info.width();
+ height = info.height();
+ }
+
+ // Returns whether |bitmap| successfully initialized.
+ bool InitSkBitmapFromData(SkBitmap* bitmap,
+ const char* pixels,
+ size_t pixels_size) const {
+ if (!bitmap->tryAllocPixels(
+ SkImageInfo::Make(width, height, color_type, alpha_type)))
+ return false;
+ if (pixels_size != bitmap->getSize())
+ return false;
+ memcpy(bitmap->getPixels(), pixels, pixels_size);
+ return true;
+ }
+};
+
+} // namespace
+
+namespace IPC {
+
+void ParamTraits<SkBitmap>::Write(base::Pickle* m, const SkBitmap& p) {
+ size_t fixed_size = sizeof(SkBitmap_Data);
+ SkBitmap_Data bmp_data;
+ bmp_data.InitSkBitmapDataForTransfer(p);
+ m->WriteData(reinterpret_cast<const char*>(&bmp_data),
+ static_cast<int>(fixed_size));
+ size_t pixel_size = p.getSize();
+ SkAutoLockPixels p_lock(p);
+ m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
+ static_cast<int>(pixel_size));
+}
+
+bool ParamTraits<SkBitmap>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ SkBitmap* r) {
+ const char* fixed_data;
+ int fixed_data_size = 0;
+ if (!iter->ReadData(&fixed_data, &fixed_data_size) ||
+ (fixed_data_size <= 0)) {
+ return false;
+ }
+ if (fixed_data_size != sizeof(SkBitmap_Data))
+ return false; // Message is malformed.
+
+ const char* variable_data;
+ int variable_data_size = 0;
+ if (!iter->ReadData(&variable_data, &variable_data_size) ||
+ (variable_data_size < 0)) {
+ return false;
+ }
+ const SkBitmap_Data* bmp_data =
+ reinterpret_cast<const SkBitmap_Data*>(fixed_data);
+ return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
+}
+
+void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::string* l) {
+ l->append("<SkBitmap>");
+}
+
+void ParamTraits<gfx::Transform>::Write(base::Pickle* m, const param_type& p) {
+#ifdef SK_MSCALAR_IS_FLOAT
+ float column_major_data[16];
+ p.matrix().asColMajorf(column_major_data);
+#else
+ double column_major_data[16];
+ p.matrix().asColMajord(column_major_data);
+#endif
+ // We do this in a single write for performance reasons.
+ m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
+}
+
+bool ParamTraits<gfx::Transform>::Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r) {
+ const char* column_major_data;
+ if (!iter->ReadBytes(&column_major_data, sizeof(SkMScalar) * 16))
+ return false;
+ r->matrix().setColMajor(
+ reinterpret_cast<const SkMScalar*>(column_major_data));
+ return true;
+}
+
+void ParamTraits<gfx::Transform>::Log(
+ const param_type& p, std::string* l) {
+#ifdef SK_MSCALAR_IS_FLOAT
+ float row_major_data[16];
+ p.matrix().asRowMajorf(row_major_data);
+#else
+ double row_major_data[16];
+ p.matrix().asRowMajord(row_major_data);
+#endif
+ l->append("(");
+ for (int i = 0; i < 16; ++i) {
+ if (i > 0)
+ l->append(", ");
+ LogParam(row_major_data[i], l);
+ }
+ l->append(") ");
+}
+
+} // namespace IPC
diff --git a/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.h b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.h
new file mode 100644
index 00000000000..d3acc930865
--- /dev/null
+++ b/chromium/ui/gfx/ipc/skia/gfx_skia_param_traits.h
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_IPC_GFX_SKIA_PARAM_TRAITS_H_
+#define UI_GFX_IPC_GFX_SKIA_PARAM_TRAITS_H_
+
+#include <string>
+
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_ipc_export.h"
+
+class SkBitmap;
+
+namespace base {
+class Pickle;
+class PickleIterator;
+}
+
+namespace gfx {
+class Transform;
+}
+
+namespace IPC {
+
+template <>
+struct GFX_SKIA_IPC_EXPORT ParamTraits<SkBitmap> {
+ using param_type = SkBitmap;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+template <>
+struct GFX_SKIA_IPC_EXPORT ParamTraits<gfx::Transform> {
+ using param_type = gfx::Transform;
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
+ static void Log(const param_type& p, std::string* l);
+};
+
+} // namespace IPC
+
+#endif // UI_GFX_IPC_GFX_SKIA_PARAM_TRAITS_H_
diff --git a/chromium/ui/gfx/mac/io_surface.cc b/chromium/ui/gfx/mac/io_surface.cc
index e48a813ad42..641c2e0470f 100644
--- a/chromium/ui/gfx/mac/io_surface.cc
+++ b/chromium/ui/gfx/mac/io_surface.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/mach_logging.h"
@@ -17,6 +18,9 @@ namespace gfx {
namespace {
+const base::Feature kIOSurfaceClearYosemite{"IOSurfaceClearYosemite",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
void AddIntegerValue(CFMutableDictionaryRef dictionary,
const CFStringRef key,
int32_t value) {
@@ -155,7 +159,11 @@ IOSurfaceRef CreateIOSurface(const gfx::Size& size, gfx::BufferFormat format) {
// causes PDFs to render incorrectly. Hopefully this check can be removed once
// pdfium switches to a Skia backend on Mac.
// https://crbug.com/594343.
- if (!base::mac::IsOSMavericks()) {
+ bool should_clear = !base::mac::IsOSMavericks();
+ if (base::mac::IsOSYosemite())
+ should_clear = base::FeatureList::IsEnabled(kIOSurfaceClearYosemite);
+
+ if (should_clear) {
// Zero-initialize the IOSurface. Calling IOSurfaceLock/IOSurfaceUnlock
// appears to be sufficient. https://crbug.com/584760#c17
IOReturn r = IOSurfaceLock(surface, 0, nullptr);
diff --git a/chromium/ui/gfx/mac/io_surface.h b/chromium/ui/gfx/mac/io_surface.h
index 4c24fe4697c..1fb01a060c0 100644
--- a/chromium/ui/gfx/mac/io_surface.h
+++ b/chromium/ui/gfx/mac/io_surface.h
@@ -24,6 +24,19 @@ struct IOSurfaceMachPortTraits {
GFX_EXPORT static void Release(mach_port_t);
};
+struct ScopedInUseIOSurfaceTraits {
+ static IOSurfaceRef InvalidValue() { return nullptr; }
+ static IOSurfaceRef Retain(IOSurfaceRef io_surface) {
+ CFRetain(io_surface);
+ IOSurfaceIncrementUseCount(io_surface);
+ return io_surface;
+ }
+ static void Release(IOSurfaceRef io_surface) {
+ IOSurfaceDecrementUseCount(io_surface);
+ CFRelease(io_surface);
+ }
+};
+
} // namespace internal
using IOSurfaceId = GenericSharedMemoryId;
@@ -38,6 +51,11 @@ GFX_EXPORT IOSurfaceRef CreateIOSurface(const Size& size, BufferFormat format);
using ScopedRefCountedIOSurfaceMachPort =
base::ScopedTypeRef<mach_port_t, internal::IOSurfaceMachPortTraits>;
+// A scoper for holding a reference to an IOSurface and also incrementing its
+// in-use counter while the scoper exists.
+using ScopedInUseIOSurface =
+ base::ScopedTypeRef<IOSurfaceRef, internal::ScopedInUseIOSurfaceTraits>;
+
} // namespace gfx
#endif // UI_GFX_MAC_IO_SURFACE_H_
diff --git a/chromium/ui/gfx/native_widget_types.h b/chromium/ui/gfx/native_widget_types.h
index 8297630216c..d9db495b84d 100644
--- a/chromium/ui/gfx/native_widget_types.h
+++ b/chromium/ui/gfx/native_widget_types.h
@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "build/build_config.h"
-#include "ui/gfx/gfx_export.h"
#if defined(OS_ANDROID)
#include <jni.h>
@@ -213,29 +212,6 @@ typedef intptr_t NativeViewId;
const PluginWindowHandle kNullPluginWindow = 0;
#endif
-enum SurfaceType {
- EMPTY,
- NATIVE_DIRECT,
- NULL_TRANSPORT,
- SURFACE_TYPE_LAST = NULL_TRANSPORT
-};
-
-struct GLSurfaceHandle {
- GLSurfaceHandle() : handle(kNullPluginWindow), transport_type(EMPTY) {}
- GLSurfaceHandle(PluginWindowHandle handle_, SurfaceType transport_)
- : handle(handle_), transport_type(transport_) {
- DCHECK(!is_null() || handle == kNullPluginWindow);
- DCHECK(transport_type != NULL_TRANSPORT ||
- handle == kNullPluginWindow);
- }
- bool is_null() const { return transport_type == EMPTY; }
- bool is_transport() const {
- return transport_type == NULL_TRANSPORT;
- }
- PluginWindowHandle handle;
- SurfaceType transport_type;
-};
-
// AcceleratedWidget provides a surface to compositors to paint pixels.
#if defined(OS_WIN)
typedef HWND AcceleratedWidget;
diff --git a/chromium/ui/gfx/paint_vector_icon.cc b/chromium/ui/gfx/paint_vector_icon.cc
index 7121fde314d..6091897f811 100644
--- a/chromium/ui/gfx/paint_vector_icon.cc
+++ b/chromium/ui/gfx/paint_vector_icon.cc
@@ -309,6 +309,10 @@ class VectorIconSource : public CanvasImageSource {
~VectorIconSource() override {}
// CanvasImageSource:
+ bool HasRepresentationAtAllScales() const override {
+ return id_ != VectorIconId::VECTOR_ICON_NONE;
+ }
+
void Draw(gfx::Canvas* canvas) override {
if (path_.empty()) {
PaintVectorIcon(canvas, id_, size_.width(), color_);
diff --git a/chromium/ui/gfx/path.h b/chromium/ui/gfx/path.h
index bb00e13a365..e1cbfa9b93b 100644
--- a/chromium/ui/gfx/path.h
+++ b/chromium/ui/gfx/path.h
@@ -33,9 +33,6 @@ class GFX_EXPORT Path : public SkPath {
Path(const PointF* points, size_t count);
~Path();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Path);
};
}
diff --git a/chromium/ui/gfx/path_mac.h b/chromium/ui/gfx/path_mac.h
new file mode 100644
index 00000000000..f20fa62d7c2
--- /dev/null
+++ b/chromium/ui/gfx/path_mac.h
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_PATH_MAC_H_
+#define UI_GFX_PATH_MAC_H_
+
+#include "ui/gfx/gfx_export.h"
+
+@class NSBezierPath;
+class SkPath;
+
+namespace gfx {
+
+// Returns an autoreleased NSBezierPath corresponding to |path|. Caller should
+// call retain on the returned object, if it wishes to take ownership.
+GFX_EXPORT NSBezierPath* CreateNSBezierPathFromSkPath(const SkPath& path);
+
+} // namespace gfx
+
+#endif // UI_GFX_PATH_MAC_H_
diff --git a/chromium/ui/gfx/path_mac.mm b/chromium/ui/gfx/path_mac.mm
new file mode 100644
index 00000000000..109f80741f4
--- /dev/null
+++ b/chromium/ui/gfx/path_mac.mm
@@ -0,0 +1,125 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/gfx/path_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/gfx/path.h"
+
+namespace {
+
+// Convert a quadratic bezier curve to a cubic bezier curve. Based on the
+// implementation of the private SkConvertQuadToCubic method inside Skia.
+void ConvertQuadToCubicBezier(NSPoint quad[3], NSPoint cubic[4]) {
+ // The resultant cubic will have the same endpoints.
+ cubic[0] = quad[0];
+ cubic[3] = quad[2];
+
+ const double scale = 2.0 / 3.0;
+
+ cubic[1].x = quad[0].x + scale * (quad[1].x - quad[0].x);
+ cubic[1].y = quad[0].y + scale * (quad[1].y - quad[0].y);
+
+ cubic[2].x = quad[2].x + scale * (quad[1].x - quad[2].x);
+ cubic[2].y = quad[2].y + scale * (quad[1].y - quad[2].y);
+}
+
+} // namespace
+
+namespace gfx {
+
+NSBezierPath* CreateNSBezierPathFromSkPath(const SkPath& path) {
+ NSBezierPath* result = [NSBezierPath bezierPath];
+ SkPath::RawIter iter(path);
+ SkPoint sk_points[4] = {{0.0}};
+ SkPath::Verb verb;
+ NSPoint points[4];
+ while ((verb = iter.next(sk_points)) != SkPath::kDone_Verb) {
+ for (size_t i = 0; i < arraysize(points); i++)
+ points[i] = NSMakePoint(sk_points[i].x(), sk_points[i].y());
+
+ switch (verb) {
+ case SkPath::kMove_Verb: {
+ [result moveToPoint:points[0]];
+ break;
+ }
+ case SkPath::kLine_Verb: {
+ DCHECK(NSEqualPoints([result currentPoint], points[0]));
+ [result lineToPoint:points[1]];
+ break;
+ }
+ case SkPath::kQuad_Verb: {
+ DCHECK(NSEqualPoints([result currentPoint], points[0]));
+ NSPoint quad[] = {points[0], points[1], points[2]};
+ // NSBezierPath does not support quadratic bezier curves. Hence convert
+ // to cubic bezier curve.
+ ConvertQuadToCubicBezier(quad, points);
+ [result curveToPoint:points[3]
+ controlPoint1:points[1]
+ controlPoint2:points[2]];
+ break;
+ }
+ case SkPath::kConic_Verb: {
+ DCHECK(NSEqualPoints([result currentPoint], points[0]));
+ // Approximate with quads. Use two for now, increase if more precision
+ // is needed.
+ const size_t kSubdivisionLevels = 1;
+ const size_t kQuadCount = 1 << kSubdivisionLevels;
+ // The quads will share endpoints, so we need one more point than twice
+ // the number of quads.
+ const size_t kPointCount = 1 + 2 * kQuadCount;
+ SkPoint quads[kPointCount];
+ SkPath::ConvertConicToQuads(sk_points[0], sk_points[1], sk_points[2],
+ iter.conicWeight(), quads,
+ kSubdivisionLevels);
+ NSPoint ns_quads[kPointCount];
+ for (size_t i = 0; i < kPointCount; i++)
+ ns_quads[i] = NSMakePoint(quads[i].x(), quads[i].y());
+
+ for (size_t i = 0; i < kQuadCount; i++) {
+ NSPoint quad[] = {ns_quads[2 * i], ns_quads[2 * i + 1],
+ ns_quads[2 * i + 2]};
+ ConvertQuadToCubicBezier(quad, points);
+ DCHECK(NSEqualPoints([result currentPoint], points[0]));
+ [result curveToPoint:points[3]
+ controlPoint1:points[1]
+ controlPoint2:points[2]];
+ }
+ break;
+ }
+ case SkPath::kCubic_Verb: {
+ DCHECK(NSEqualPoints([result currentPoint], points[0]));
+ [result curveToPoint:points[3]
+ controlPoint1:points[1]
+ controlPoint2:points[2]];
+ break;
+ }
+ case SkPath::kClose_Verb: {
+ [result closePath];
+ break;
+ }
+ default: { NOTREACHED(); }
+ }
+ }
+
+ // Set up the fill type.
+ switch (path.getFillType()) {
+ case SkPath::kWinding_FillType:
+ [result setWindingRule:NSNonZeroWindingRule];
+ break;
+ case SkPath::kEvenOdd_FillType:
+ [result setWindingRule:NSEvenOddWindingRule];
+ break;
+ case SkPath::kInverseWinding_FillType:
+ case SkPath::kInverseEvenOdd_FillType:
+ NOTREACHED() << "NSBezierCurve does not support inverse fill types.";
+ break;
+ }
+
+ return result;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/path_mac_unittest.mm b/chromium/ui/gfx/path_mac_unittest.mm
new file mode 100644
index 00000000000..d1d4a99234e
--- /dev/null
+++ b/chromium/ui/gfx/path_mac_unittest.mm
@@ -0,0 +1,258 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/gfx/path_mac.h"
+
+#include <cmath>
+#include <vector>
+
+#import <Cocoa/Cocoa.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/path.h"
+
+namespace gfx {
+
+namespace {
+
+// Returns the point at a distance of |radius| from the point (|centre_x|,
+// |centre_y|), and angle |degrees| from the positive horizontal axis, measured
+// anti-clockwise.
+NSPoint GetRadialPoint(double radius,
+ double degrees,
+ double centre_x,
+ double centre_y) {
+ const double radian = (degrees * SK_ScalarPI) / 180;
+ return NSMakePoint(centre_x + radius * std::cos(radian),
+ centre_y + radius * std::sin(radian));
+}
+
+// Returns the area of a circle with the given |radius|.
+double CalculateCircleArea(double radius) {
+ return SK_ScalarPI * radius * radius;
+}
+
+// Returns the area of a simple polygon. |path| should represent a simple
+// polygon.
+double CalculatePolygonArea(NSBezierPath* path) {
+ // If path represents a single polygon, it will have MoveTo, followed by
+ // multiple LineTo, followed By ClosePath, followed by another MoveTo
+ // NSBezierPathElement.
+ const size_t element_count = [path elementCount];
+ NSPoint points[3];
+ std::vector<NSPoint> poly;
+
+ for (size_t i = 0; i < element_count - 1; i++) {
+ NSBezierPathElement element =
+ [path elementAtIndex:i associatedPoints:points];
+ poly.push_back(points[0]);
+ DCHECK_EQ(element,
+ i ? (i == element_count - 2 ? NSClosePathBezierPathElement
+ : NSLineToBezierPathElement)
+ : NSMoveToBezierPathElement);
+ }
+ DCHECK_EQ([path elementAtIndex:element_count - 1], NSMoveToBezierPathElement);
+
+ // Shoelace Algorithm to find the area of a simple polygon.
+ DCHECK(NSEqualPoints(poly.front(), poly.back()));
+ double area = 0;
+ for (size_t i = 0; i < poly.size() - 1; i++)
+ area += poly[i].x * poly[i + 1].y - poly[i].y * poly[i + 1].x;
+
+ return std::fabs(area) / 2.0;
+}
+
+// Returns the area of a rounded rectangle with the given |width|, |height| and
+// |radius|.
+double CalculateRoundedRectangleArea(double width,
+ double height,
+ double radius) {
+ const double inside_width = width - 2 * radius;
+ const double inside_height = height - 2 * radius;
+ return inside_width * inside_height +
+ 2 * radius * (inside_width + inside_height) +
+ CalculateCircleArea(radius);
+}
+
+// Returns the bounding box of |path| as a Rect.
+Rect GetBoundingBox(NSBezierPath* path) {
+ const NSRect bounds = [path bounds];
+ return ToNearestRect(RectF(bounds.origin.x, bounds.origin.y,
+ bounds.size.width, bounds.size.height));
+}
+
+} // namespace
+
+// Check that empty NSBezierPath is returned for empty SkPath.
+TEST(CreateNSBezierPathFromSkPathTest, EmptyPath) {
+ NSBezierPath* result = CreateNSBezierPathFromSkPath(SkPath());
+ EXPECT_TRUE([result isEmpty]);
+}
+
+// Check that the returned NSBezierPath has the correct winding rule.
+TEST(CreateNSBezierPathFromSkPathTest, FillType) {
+ SkPath path;
+ path.setFillType(SkPath::kWinding_FillType);
+ NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
+ EXPECT_EQ(NSNonZeroWindingRule, [result windingRule]);
+
+ path.setFillType(SkPath::kEvenOdd_FillType);
+ result = CreateNSBezierPathFromSkPath(path);
+ EXPECT_EQ(NSEvenOddWindingRule, [result windingRule]);
+}
+
+// Check that a path containing multiple subpaths, in this case two rectangles,
+// is correctly converted to a NSBezierPath.
+TEST(CreateNSBezierPathFromSkPathTest, TwoRectanglesPath) {
+ const SkRect rects[] = {
+ {0, 0, 50, 50}, {100, 100, 150, 150},
+ };
+ const NSPoint inside_points[] = {
+ {1, 1}, {1, 49}, {49, 49}, {49, 1}, {25, 25},
+ {101, 101}, {101, 149}, {149, 149}, {149, 101}, {125, 125}};
+ const NSPoint outside_points[] = {{-1, -1}, {-1, 51}, {51, 51}, {51, -1},
+ {99, 99}, {99, 151}, {151, 151}, {151, 99},
+ {75, 75}, {-5, -5}};
+ ASSERT_EQ(arraysize(inside_points), arraysize(outside_points));
+ const Rect expected_bounds(0, 0, 150, 150);
+
+ SkPath path;
+ path.addRect(rects[0]);
+ path.addRect(rects[1]);
+ NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
+
+ // Check points near the boundary of the path and verify that they are
+ // reported correctly as being inside/outside the path.
+ for (size_t i = 0; i < arraysize(inside_points); i++) {
+ EXPECT_TRUE([result containsPoint:inside_points[i]]);
+ EXPECT_FALSE([result containsPoint:outside_points[i]]);
+ }
+
+ // Check that the returned result has the correct bounding box. GetBoundingBox
+ // rounds the coordinates to nearest integer values.
+ EXPECT_EQ(expected_bounds, GetBoundingBox(result));
+}
+
+// Test that an SKPath containing a circle is converted correctly to a
+// NSBezierPath.
+TEST(CreateNSBezierPathFromSkPathTest, CirclePath) {
+ const int kRadius = 5;
+ const int kCentreX = 10;
+ const int kCentreY = 15;
+ const double kCushion = 0.1;
+ // Expected bounding box of the circle.
+ const Rect expected_bounds(kCentreX - kRadius, kCentreY - kRadius,
+ 2 * kRadius, 2 * kRadius);
+
+ SkPath path;
+ path.addCircle(SkIntToScalar(kCentreX), SkIntToScalar(kCentreY),
+ SkIntToScalar(kRadius));
+ NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
+
+ // Check points near the boundary of the circle and verify that they are
+ // reported correctly as being inside/outside the path.
+ for (size_t deg = 0; deg < 360; deg++) {
+ NSPoint inside_point =
+ GetRadialPoint(kRadius - kCushion, deg, kCentreX, kCentreY);
+ NSPoint outside_point =
+ GetRadialPoint(kRadius + kCushion, deg, kCentreX, kCentreY);
+ EXPECT_TRUE([result containsPoint:inside_point]);
+ EXPECT_FALSE([result containsPoint:outside_point]);
+ }
+
+ // Check that the returned result has the correct bounding box. GetBoundingBox
+ // rounds the coordinates to nearest integer values.
+ EXPECT_EQ(expected_bounds, GetBoundingBox(result));
+
+ // Check area of converted path is correct up to a certain tolerance value. To
+ // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
+ // polygon.
+ [NSBezierPath setDefaultFlatness:0.01];
+ NSBezierPath* polygon = [result bezierPathByFlatteningPath];
+ const double kTolerance = 0.14;
+ EXPECT_NEAR(CalculateCircleArea(kRadius), CalculatePolygonArea(polygon),
+ kTolerance);
+}
+
+// Test that an SKPath containing a rounded rectangle is converted correctly to
+// a NSBezierPath.
+TEST(CreateNSBezierPathFromSkPathTest, RoundedRectanglePath) {
+ const int kRectangleWidth = 50;
+ const int kRectangleHeight = 100;
+ const int kCornerRadius = 5;
+ const double kCushion = 0.1;
+ // Expected bounding box of the rounded rectangle.
+ const Rect expected_bounds(kRectangleWidth, kRectangleHeight);
+
+ SkRRect rrect;
+ rrect.setRectXY(SkRect::MakeWH(kRectangleWidth, kRectangleHeight),
+ kCornerRadius, kCornerRadius);
+
+ const NSPoint inside_points[] = {
+ // Bottom left corner.
+ {kCornerRadius / 2.0, kCornerRadius / 2.0},
+ // Bottom right corner.
+ {kRectangleWidth - kCornerRadius / 2.0, kCornerRadius / 2.0},
+ // Top Right corner.
+ {kRectangleWidth - kCornerRadius / 2.0,
+ kRectangleHeight - kCornerRadius / 2.0},
+ // Top left corner.
+ {kCornerRadius / 2.0, kRectangleHeight - kCornerRadius / 2.0},
+ // Bottom middle.
+ {kRectangleWidth / 2.0, kCushion},
+ // Right middle.
+ {kRectangleWidth - kCushion, kRectangleHeight / 2.0},
+ // Top middle.
+ {kRectangleWidth / 2.0, kRectangleHeight - kCushion},
+ // Left middle.
+ {kCushion, kRectangleHeight / 2.0}};
+ const NSPoint outside_points[] = {
+ // Bottom left corner.
+ {0, 0},
+ // Bottom right corner.
+ {kRectangleWidth, 0},
+ // Top right corner.
+ {kRectangleWidth, kRectangleHeight},
+ // Top left corner.
+ {0, kRectangleHeight},
+ // Bottom middle.
+ {kRectangleWidth / 2.0, -kCushion},
+ // Right middle.
+ {kRectangleWidth + kCushion, kRectangleHeight / 2.0},
+ // Top middle.
+ {kRectangleWidth / 2.0, kRectangleHeight + kCushion},
+ // Left middle.
+ {-kCushion, kRectangleHeight / 2.0}};
+ ASSERT_EQ(arraysize(inside_points), arraysize(outside_points));
+
+ SkPath path;
+ path.addRRect(rrect);
+ NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
+
+ // Check points near the boundary of the path and verify that they are
+ // reported correctly as being inside/outside the path.
+ for (size_t i = 0; i < arraysize(inside_points); i++) {
+ EXPECT_TRUE([result containsPoint:inside_points[i]]);
+ EXPECT_FALSE([result containsPoint:outside_points[i]]);
+ }
+
+ // Check that the returned result has the correct bounding box. GetBoundingBox
+ // rounds the coordinates to nearest integer values.
+ EXPECT_EQ(expected_bounds, GetBoundingBox(result));
+
+ // Check area of converted path is correct up to a certain tolerance value. To
+ // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
+ // polygon.
+ [NSBezierPath setDefaultFlatness:0.01];
+ NSBezierPath* polygon = [result bezierPathByFlatteningPath];
+ const double kTolerance = 0.14;
+ EXPECT_NEAR(CalculateRoundedRectangleArea(kRectangleWidth, kRectangleHeight,
+ kCornerRadius),
+ CalculatePolygonArea(polygon), kTolerance);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/platform_font_linux.cc b/chromium/ui/gfx/platform_font_linux.cc
index 3c58ccb695b..dba65947477 100644
--- a/chromium/ui/gfx/platform_font_linux.cc
+++ b/chromium/ui/gfx/platform_font_linux.cc
@@ -196,7 +196,6 @@ int PlatformFontLinux::GetFontSize() const {
}
const FontRenderParams& PlatformFontLinux::GetFontRenderParams() {
-#if defined(OS_CHROMEOS)
float current_scale_factor = GetFontRenderParamsDeviceScaleFactor();
if (current_scale_factor != device_scale_factor_) {
FontRenderParamsQuery query;
@@ -207,7 +206,6 @@ const FontRenderParams& PlatformFontLinux::GetFontRenderParams() {
font_render_params_ = gfx::GetFontRenderParams(query, nullptr);
device_scale_factor_ = current_scale_factor;
}
-#endif
return font_render_params_;
}
@@ -237,9 +235,7 @@ void PlatformFontLinux::InitFromDetails(
font_size_pixels_ = font_size_pixels;
style_ = style;
-#if defined(OS_CHROMEOS)
device_scale_factor_ = GetFontRenderParamsDeviceScaleFactor();
-#endif
font_render_params_ = render_params;
}
@@ -249,9 +245,7 @@ void PlatformFontLinux::InitFromPlatformFont(const PlatformFontLinux* other) {
font_family_ = other->font_family_;
font_size_pixels_ = other->font_size_pixels_;
style_ = other->style_;
-#if defined(OS_CHROMEOS)
device_scale_factor_ = other->device_scale_factor_;
-#endif
font_render_params_ = other->font_render_params_;
if (!other->metrics_need_computation_) {
diff --git a/chromium/ui/gfx/platform_font_linux.h b/chromium/ui/gfx/platform_font_linux.h
index 52c4bceb76e..e990f33b1ed 100644
--- a/chromium/ui/gfx/platform_font_linux.h
+++ b/chromium/ui/gfx/platform_font_linux.h
@@ -84,9 +84,7 @@ class GFX_EXPORT PlatformFontLinux : public PlatformFont {
std::string font_family_;
int font_size_pixels_;
int style_;
-#if defined(OS_CHROMEOS)
float device_scale_factor_;
-#endif
// Information describing how the font should be rendered.
FontRenderParams font_render_params_;
diff --git a/chromium/ui/gfx/range/range.cc b/chromium/ui/gfx/range/range.cc
index 1c3968aa6e2..a6475cba2ec 100644
--- a/chromium/ui/gfx/range/range.cc
+++ b/chromium/ui/gfx/range/range.cc
@@ -7,7 +7,6 @@
#include <algorithm>
#include <limits>
-#include "base/format_macros.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
@@ -18,30 +17,30 @@ Range::Range()
end_(0) {
}
-Range::Range(size_t start, size_t end)
+Range::Range(uint32_t start, uint32_t end)
: start_(start),
end_(end) {
}
-Range::Range(size_t position)
+Range::Range(uint32_t position)
: start_(position),
end_(position) {
}
// static
const Range Range::InvalidRange() {
- return Range(std::numeric_limits<size_t>::max());
+ return Range(std::numeric_limits<uint32_t>::max());
}
bool Range::IsValid() const {
return *this != InvalidRange();
}
-size_t Range::GetMin() const {
+uint32_t Range::GetMin() const {
return std::min(start(), end());
}
-size_t Range::GetMax() const {
+uint32_t Range::GetMax() const {
return std::max(start(), end());
}
@@ -68,8 +67,8 @@ bool Range::Contains(const Range& range) const {
}
Range Range::Intersect(const Range& range) const {
- size_t min = std::max(GetMin(), range.GetMin());
- size_t max = std::min(GetMax(), range.GetMax());
+ uint32_t min = std::max(GetMin(), range.GetMin());
+ uint32_t max = std::min(GetMax(), range.GetMax());
if (min >= max) // No intersection.
return InvalidRange();
@@ -78,7 +77,7 @@ Range Range::Intersect(const Range& range) const {
}
std::string Range::ToString() const {
- return base::StringPrintf("{%" PRIuS ",%" PRIuS "}", start(), end());
+ return base::StringPrintf("{%d,%d}", start(), end());
}
std::ostream& operator<<(std::ostream& os, const Range& range) {
diff --git a/chromium/ui/gfx/range/range.h b/chromium/ui/gfx/range/range.h
index 741b318138d..3d9c724de55 100644
--- a/chromium/ui/gfx/range/range.h
+++ b/chromium/ui/gfx/range/range.h
@@ -6,6 +6,7 @@
#define UI_GFX_RANGE_RANGE_H_
#include <stddef.h>
+#include <stdint.h>
#include <ostream>
#include <string>
@@ -39,10 +40,10 @@ class GFX_EXPORT Range {
Range();
// Initializes the range with a start and end.
- Range(size_t start, size_t end);
+ Range(uint32_t start, uint32_t end);
// Initializes the range with the same start and end positions.
- explicit Range(size_t position);
+ explicit Range(uint32_t position);
// Platform constructors.
#if defined(OS_MACOSX)
@@ -53,31 +54,30 @@ class GFX_EXPORT Range {
Range(const CHARRANGE& range, LONG total_length = -1);
#endif
- // Returns a range that is invalid, which is {size_t_max,size_t_max}.
+ // Returns a range that is invalid, which is {UINT32_MAX,UINT32_MAX}.
static const Range InvalidRange();
// Checks if the range is valid through comparison to InvalidRange().
bool IsValid() const;
// Getters and setters.
- size_t start() const { return start_; }
- void set_start(size_t start) { start_ = start; }
+ uint32_t start() const { return start_; }
+ void set_start(uint32_t start) { start_ = start; }
- size_t end() const { return end_; }
- void set_end(size_t end) { end_ = end; }
+ uint32_t end() const { return end_; }
+ void set_end(uint32_t end) { end_ = end; }
// Returns the absolute value of the length.
- size_t length() const {
- ptrdiff_t length = end() - start();
- return length >= 0 ? length : -length;
+ uint32_t length() const {
+ return GetMax() - GetMin();
}
bool is_reversed() const { return start() > end(); }
bool is_empty() const { return start() == end(); }
// Returns the minimum and maximum values.
- size_t GetMin() const;
- size_t GetMax() const;
+ uint32_t GetMin() const;
+ uint32_t GetMax() const;
bool operator==(const Range& other) const;
bool operator!=(const Range& other) const;
@@ -108,8 +108,11 @@ class GFX_EXPORT Range {
std::string ToString() const;
private:
- size_t start_;
- size_t end_;
+ // Note: we use uint32_t instead of size_t because this struct is sent over
+ // IPC which could span 32 & 64 bit processes. This is fine since text spans
+ // shouldn't exceed UINT32_MAX even on 64 bit builds.
+ uint32_t start_;
+ uint32_t end_;
};
GFX_EXPORT std::ostream& operator<<(std::ostream& os, const Range& range);
diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc
index 1757575b32f..b133b976d96 100644
--- a/chromium/ui/gfx/render_text.cc
+++ b/chromium/ui/gfx/render_text.cc
@@ -139,11 +139,15 @@ void AddFadeEffect(const Rect& text_rect,
// Creates a SkShader to fade the text, with |left_part| specifying the left
// fade effect, if any, and |right_part| specifying the right fade effect.
-skia::RefPtr<SkShader> CreateFadeShader(const FontList& font_list,
- const Rect& text_rect,
- const Rect& left_part,
- const Rect& right_part,
- SkColor color) {
+sk_sp<SkShader> CreateFadeShader(const FontList& font_list,
+ const Rect& text_rect,
+ const Rect& left_part,
+ const Rect& right_part,
+ SkColor color) {
+ // The shader should only specify transparency of the fade itself, not the
+ // original transparency, which will be applied by the actual renderer.
+ DCHECK_EQ(SkColorGetA(color), static_cast<uint8_t>(0xff));
+
// In general, fade down to 0 alpha. But when the available width is less
// than four characters, linearly ramp up the fade target alpha to as high as
// 20% at zero width. This allows the user to see the last faded characters a
@@ -174,9 +178,9 @@ skia::RefPtr<SkShader> CreateFadeShader(const FontList& font_list,
const SkPoint points[2] = { PointToSkPoint(text_rect.origin()),
PointToSkPoint(text_rect.top_right()) };
- return skia::AdoptRef(
- SkGradientShader::CreateLinear(&points[0], &colors[0], &positions[0],
- colors.size(), SkShader::kClamp_TileMode));
+ return
+ SkGradientShader::MakeLinear(&points[0], &colors[0], &positions[0],
+ colors.size(), SkShader::kClamp_TileMode);
}
// Converts a FontRenderParams::Hinting value to the corresponding
@@ -236,8 +240,8 @@ SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas)
SkiaTextRenderer::~SkiaTextRenderer() {
}
-void SkiaTextRenderer::SetDrawLooper(SkDrawLooper* draw_looper) {
- paint_.setLooper(draw_looper);
+void SkiaTextRenderer::SetDrawLooper(sk_sp<SkDrawLooper> draw_looper) {
+ paint_.setLooper(std::move(draw_looper));
}
void SkiaTextRenderer::SetFontRenderParams(const FontRenderParams& params,
@@ -269,8 +273,8 @@ void SkiaTextRenderer::SetForegroundColor(SkColor foreground) {
paint_.setColor(foreground);
}
-void SkiaTextRenderer::SetShader(SkShader* shader) {
- paint_.setShader(shader);
+void SkiaTextRenderer::SetShader(sk_sp<SkShader> shader) {
+ paint_.setShader(std::move(shader));
}
void SkiaTextRenderer::SetUnderlineMetrics(SkScalar thickness,
@@ -415,6 +419,8 @@ LineSegment::~LineSegment() {}
Line::Line() : preceding_heights(0), baseline(0) {}
+Line::Line(const Line& other) = default;
+
Line::~Line() {}
#if !defined(OS_MACOSX)
@@ -632,7 +638,8 @@ void RenderText::MoveCursor(BreakType break_type,
bool RenderText::MoveCursorTo(const SelectionModel& model) {
// Enforce valid selection model components.
size_t text_length = text().length();
- Range range(std::min(model.selection().start(), text_length),
+ Range range(std::min(model.selection().start(),
+ static_cast<uint32_t>(text_length)),
std::min(model.caret_pos(), text_length));
// The current model only supports caret positions at valid cursor indices.
if (!IsValidCursorIndex(range.start()) || !IsValidCursorIndex(range.end()))
@@ -644,8 +651,9 @@ bool RenderText::MoveCursorTo(const SelectionModel& model) {
}
bool RenderText::SelectRange(const Range& range) {
- Range sel(std::min(range.start(), text().length()),
- std::min(range.end(), text().length()));
+ uint32_t text_length = static_cast<uint32_t>(text().length());
+ Range sel(std::min(range.start(), text_length),
+ std::min(range.end(), text_length));
// Allow selection bounds at valid indicies amid multi-character graphemes.
if (!IsValidLogicalIndex(sel.start()) || !IsValidLogicalIndex(sel.end()))
return false;
@@ -1227,16 +1235,13 @@ void RenderText::ApplyFadeEffects(internal::SkiaTextRenderer* renderer) {
text_rect.Inset(GetAlignmentOffset(0).x(), 0, 0, 0);
// TODO(msw): Use the actual text colors corresponding to each faded part.
- skia::RefPtr<SkShader> shader =
+ renderer->SetShader(
CreateFadeShader(font_list(), text_rect, left_part, right_part,
- colors_.breaks().front().second);
- if (shader)
- renderer->SetShader(shader.get());
+ SkColorSetA(colors_.breaks().front().second, 0xff)));
}
void RenderText::ApplyTextShadows(internal::SkiaTextRenderer* renderer) {
- skia::RefPtr<SkDrawLooper> looper = CreateShadowDrawLooper(shadows_);
- renderer->SetDrawLooper(looper.get());
+ renderer->SetDrawLooper(CreateShadowDrawLooper(shadows_));
}
base::i18n::TextDirection RenderText::GetTextDirection(
diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h
index 522cc4d0d9b..5913f4dcb68 100644
--- a/chromium/ui/gfx/render_text.h
+++ b/chromium/ui/gfx/render_text.h
@@ -57,14 +57,14 @@ class GFX_EXPORT SkiaTextRenderer {
explicit SkiaTextRenderer(Canvas* canvas);
virtual ~SkiaTextRenderer();
- void SetDrawLooper(SkDrawLooper* draw_looper);
+ void SetDrawLooper(sk_sp<SkDrawLooper> draw_looper);
void SetFontRenderParams(const FontRenderParams& params,
bool subpixel_rendering_suppressed);
void SetTypeface(SkTypeface* typeface);
void SetTextSize(SkScalar size);
void SetFontWithStyle(const Font& font, int font_style);
void SetForegroundColor(SkColor foreground);
- void SetShader(SkShader* shader);
+ void SetShader(sk_sp<SkShader> shader);
// Sets underline metrics to use if the text will be drawn with an underline.
// If not set, default values based on the size of the text will be used. The
// two metrics must be set together.
@@ -170,6 +170,7 @@ struct LineSegment {
// A line of display text, comprised of a line segment list and some metrics.
struct Line {
Line();
+ Line(const Line& other);
~Line();
// Segments that make up this line in visual order.
diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc
index 39fc88cb2c1..590537ebe63 100644
--- a/chromium/ui/gfx/render_text_harfbuzz.cc
+++ b/chromium/ui/gfx/render_text_harfbuzz.cc
@@ -28,6 +28,7 @@
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/harfbuzz_font_skia.h"
#include "ui/gfx/range/range_f.h"
+#include "ui/gfx/skia_util.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"
@@ -460,7 +461,8 @@ class HarfBuzzLineBreaker {
}
const size_t valid_end_pos = std::max(
- segment.char_range.start(), FindValidBoundaryBefore(text_, end_pos));
+ segment.char_range.start(),
+ static_cast<uint32_t>(FindValidBoundaryBefore(text_, end_pos)));
if (end_pos != valid_end_pos) {
end_pos = valid_end_pos;
width = run.GetGlyphWidthForCharRange(
@@ -472,8 +474,9 @@ class HarfBuzzLineBreaker {
// not separate surrogate pair or combining characters.
// See RenderTextTest.Multiline_MinWidth for an example.
if (width == 0 && available_width_ == max_width_) {
- end_pos = std::min(segment.char_range.end(),
- FindValidBoundaryAfter(text_, end_pos + 1));
+ end_pos = std::min(
+ segment.char_range.end(),
+ static_cast<uint32_t>(FindValidBoundaryAfter(text_, end_pos + 1)));
}
return end_pos;
@@ -1501,12 +1504,14 @@ bool RenderTextHarfBuzz::ShapeRunWithFont(const base::string16& text,
DCHECK_LE(infos[i].codepoint, std::numeric_limits<uint16_t>::max());
run->glyphs[i] = static_cast<uint16_t>(infos[i].codepoint);
run->glyph_to_char[i] = infos[i].cluster;
- const SkScalar x_offset = SkFixedToScalar(hb_positions[i].x_offset);
- const SkScalar y_offset = SkFixedToScalar(hb_positions[i].y_offset);
+ const SkScalar x_offset =
+ HarfBuzzUnitsToSkiaScalar(hb_positions[i].x_offset);
+ const SkScalar y_offset =
+ HarfBuzzUnitsToSkiaScalar(hb_positions[i].y_offset);
run->positions[i].set(run->width + x_offset, -y_offset);
run->width += (glyph_width_for_test_ > 0)
? glyph_width_for_test_
- : SkFixedToFloat(hb_positions[i].x_advance);
+ : HarfBuzzUnitsToFloat(hb_positions[i].x_advance);
// Round run widths if subpixel positioning is off to match native behavior.
if (!run->render_params.subpixel_positioning)
run->width = std::floor(run->width + 0.5f);
diff --git a/chromium/ui/gfx/render_text_harfbuzz.h b/chromium/ui/gfx/render_text_harfbuzz.h
index e91effe694b..31c5294ad00 100644
--- a/chromium/ui/gfx/render_text_harfbuzz.h
+++ b/chromium/ui/gfx/render_text_harfbuzz.h
@@ -173,6 +173,8 @@ class GFX_EXPORT RenderTextHarfBuzz : public RenderText {
void DrawVisualText(internal::SkiaTextRenderer* renderer) override;
private:
+ friend class test::RenderTextTestApi;
+
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_HorizontalAlignment);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_NormalWidth);
FRIEND_TEST_ALL_PREFIXES(RenderTextTest, Multiline_WordWrapBehavior);
diff --git a/chromium/ui/gfx/render_text_mac.h b/chromium/ui/gfx/render_text_mac.h
index 042029aa3de..58c027a6552 100644
--- a/chromium/ui/gfx/render_text_mac.h
+++ b/chromium/ui/gfx/render_text_mac.h
@@ -75,6 +75,7 @@ class GFX_EXPORT RenderTextMac : public RenderText {
bool diagonal_strike;
TextRun();
+ TextRun(const TextRun& other);
~TextRun();
};
diff --git a/chromium/ui/gfx/render_text_mac.mm b/chromium/ui/gfx/render_text_mac.mm
index 3a6d01b9f3a..19257a84eb6 100644
--- a/chromium/ui/gfx/render_text_mac.mm
+++ b/chromium/ui/gfx/render_text_mac.mm
@@ -203,6 +203,9 @@ void RenderTextMac::DrawVisualText(internal::SkiaTextRenderer* renderer) {
ApplyFadeEffects(renderer);
ApplyTextShadows(renderer);
+ renderer->SetFontRenderParams(
+ font_list().GetPrimaryFont().GetFontRenderParams(),
+ subpixel_rendering_suppressed());
for (size_t i = 0; i < runs_.size(); ++i) {
const TextRun& run = runs_[i];
@@ -237,6 +240,8 @@ RenderTextMac::TextRun::TextRun()
strike(false),
diagonal_strike(false) {}
+RenderTextMac::TextRun::TextRun(const TextRun& other) = default;
+
RenderTextMac::TextRun::~TextRun() {}
float RenderTextMac::GetLayoutTextWidth() {
diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc
index 51e1ac7a861..9186d4d05f0 100644
--- a/chromium/ui/gfx/render_text_unittest.cc
+++ b/chromium/ui/gfx/render_text_unittest.cc
@@ -3017,9 +3017,9 @@ TEST_F(RenderTextTest, TextDoesntClip) {
const Size kCanvasSize(300, 50);
const int kTestSize = 10;
- skia::RefPtr<SkSurface> surface = skia::AdoptRef(
- SkSurface::NewRasterN32Premul(kCanvasSize.width(), kCanvasSize.height()));
- Canvas canvas(surface->getCanvas(), 1.0f);
+ sk_sp<SkSurface> surface =
+ SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
+ Canvas canvas(skia::SharePtr(surface->getCanvas()), 1.0f);
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetHorizontalAlignment(ALIGN_LEFT);
render_text->SetColor(SK_ColorBLACK);
@@ -3048,27 +3048,36 @@ TEST_F(RenderTextTest, TextDoesntClip) {
kCanvasSize.height());
{
#if !defined(OS_CHROMEOS)
+ int top_test_height = kTestSize;
+#if defined(OS_WIN)
+ // Windows 8+ draws 1 pixel above the display rect.
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ top_test_height = kTestSize - 1;
+#endif // OS_WIN
// TODO(dschuyler): On ChromeOS text draws above the GetStringSize rect.
SCOPED_TRACE("TextDoesntClip Top Side");
rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(),
- kTestSize);
-#endif
+ top_test_height);
+#endif // !OS_CHROMEOS
}
{
+ int bottom_test_y = kTestSize + string_size.height();
+ int bottom_test_height = kTestSize;
+#if defined(OS_WIN)
+ // Windows 8+ draws 1 pixel below the display rect.
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ bottom_test_y = kTestSize + string_size.height() + 1;
+ bottom_test_height = kTestSize - 1;
+ }
+#endif // OS_WIN
SCOPED_TRACE("TextDoesntClip Bottom Side");
- rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0,
- kTestSize + string_size.height(),
- kCanvasSize.width(), kTestSize);
+ rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, bottom_test_y,
+ kCanvasSize.width(), bottom_test_height);
}
{
SCOPED_TRACE("TextDoesntClip Left Side");
-#if defined(OS_WIN)
- // TODO(dschuyler): On Windows XP the Unicode test draws to the left edge
- // as if it is ignoring the SetDisplayRect shift by kTestSize. This
- // appears to be a preexisting issue that wasn't revealed by the prior
- // unit tests.
-#elif defined(OS_MACOSX) || defined(OS_CHROMEOS)
- // TODO(dschuyler): On Windows (non-XP), Chrome OS and Mac smoothing draws
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+ // TODO(dschuyler): On Windows, Chrome OS and Mac smoothing draws to the
// left of text. This appears to be a preexisting issue that wasn't
// revealed by the prior unit tests.
rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, kTestSize, kTestSize - 1,
@@ -3099,9 +3108,9 @@ TEST_F(RenderTextTest, TextDoesClip) {
const Size kCanvasSize(300, 50);
const int kTestSize = 10;
- skia::RefPtr<SkSurface> surface = skia::AdoptRef(
- SkSurface::NewRasterN32Premul(kCanvasSize.width(), kCanvasSize.height()));
- Canvas canvas(surface->getCanvas(), 1.0f);
+ sk_sp<SkSurface> surface =
+ SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
+ Canvas canvas(skia::SharePtr(surface->getCanvas()), 1.0f);
scoped_ptr<RenderText> render_text(RenderText::CreateInstance());
render_text->SetHorizontalAlignment(ALIGN_LEFT);
render_text->SetColor(SK_ColorBLACK);
diff --git a/chromium/ui/gfx/screen.cc b/chromium/ui/gfx/screen.cc
index 06ec78ec885..a07e9218b1f 100644
--- a/chromium/ui/gfx/screen.cc
+++ b/chromium/ui/gfx/screen.cc
@@ -2,16 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/logging.h"
#include "ui/gfx/screen.h"
-#include "ui/gfx/screen_type_delegate.h"
+
+#include "ui/gfx/geometry/rect.h"
namespace gfx {
namespace {
-Screen* g_screen_[SCREEN_TYPE_LAST + 1];
-ScreenTypeDelegate* g_screen_type_delegate_ = NULL;
+Screen* g_screen;
} // namespace
@@ -22,37 +21,30 @@ Screen::~Screen() {
}
// static
-Screen* Screen::GetScreenFor(NativeView view) {
- ScreenType type = SCREEN_TYPE_NATIVE;
- if (g_screen_type_delegate_)
- type = g_screen_type_delegate_->GetScreenTypeForNativeView(view);
- if (type == SCREEN_TYPE_NATIVE)
- return GetNativeScreen();
- DCHECK(g_screen_[type]);
- return g_screen_[type];
-}
-
-// static
-void Screen::SetScreenInstance(ScreenType type, Screen* instance) {
- DCHECK_LE(type, SCREEN_TYPE_LAST);
- g_screen_[type] = instance;
+Screen* Screen::GetScreen() {
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ // TODO(scottmg): https://crbug.com/558054
+ if (!g_screen)
+ g_screen = CreateNativeScreen();
+#endif
+ return g_screen;
}
// static
-Screen* Screen::GetScreenByType(ScreenType type) {
- return g_screen_[type];
+void Screen::SetScreenInstance(Screen* instance) {
+ g_screen = instance;
}
-// static
-void Screen::SetScreenTypeDelegate(ScreenTypeDelegate* delegate) {
- g_screen_type_delegate_ = delegate;
+gfx::Rect Screen::ScreenToDIPRectInWindow(NativeView view,
+ const gfx::Rect& screen_rect) const {
+ float scale = GetDisplayNearestWindow(view).device_scale_factor();
+ return ScaleToEnclosingRect(screen_rect, 1.0f / scale);
}
-// static
-Screen* Screen::GetNativeScreen() {
- if (!g_screen_[SCREEN_TYPE_NATIVE])
- g_screen_[SCREEN_TYPE_NATIVE] = CreateNativeScreen();
- return g_screen_[SCREEN_TYPE_NATIVE];
+gfx::Rect Screen::DIPToScreenRectInWindow(NativeView view,
+ const gfx::Rect& dip_rect) const {
+ float scale = GetDisplayNearestWindow(view).device_scale_factor();
+ return ScaleToEnclosingRect(dip_rect, scale);
}
} // namespace gfx
diff --git a/chromium/ui/gfx/screen.h b/chromium/ui/gfx/screen.h
index 107ee44e243..9352e792cb4 100644
--- a/chromium/ui/gfx/screen.h
+++ b/chromium/ui/gfx/screen.h
@@ -9,51 +9,33 @@
#include "base/macros.h"
#include "ui/gfx/display.h"
-#include "ui/gfx/geometry/point.h"
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/screen_type_delegate.h"
namespace gfx {
+
class DisplayObserver;
+class Point;
class Rect;
// A utility class for getting various info about screen size, displays,
// cursor position, etc.
//
// Note that this class does not represent an individual display connected to a
-// computer -- see the Display class for that. A single Screen object exists on
-// most operating systems regardless of the number of connected displays. On
-// Windows 8, two Screens exist: one for Metro UI and another for the desktop.
+// computer -- see the Display class for that. A single Screen object exists
+// regardless of the number of connected displays.
class GFX_EXPORT Screen {
public:
- // Retrieves the Screen that the specified NativeView belongs to. A value of
- // NULL is treated as |SCREEN_TYPE_NATIVE|.
- static Screen* GetScreenFor(NativeView view);
-
- // Returns the SCREEN_TYPE_NATIVE Screen. This should be used with caution,
- // as it is likely to be incorrect for code that runs on Windows.
- static Screen* GetNativeScreen();
-
- // Sets the global screen for a particular screen type. Only the _NATIVE
- // ScreenType must be provided.
- // NOTE: this does not take ownership of |screen|. Tests must be sure to
- // reset any state they install.
- static void SetScreenInstance(ScreenType type, Screen* instance);
-
- // Returns the global screen for a particular type. Types other than _NATIVE
- // may be NULL.
- static Screen* GetScreenByType(ScreenType type);
-
- // Sets the global ScreenTypeDelegate. May be left unset if the platform
- // uses only the _NATIVE ScreenType.
- // NOTE: this does not take ownership of |delegate|. Tests must be sure to
- // reset any state they install.
- static void SetScreenTypeDelegate(ScreenTypeDelegate* delegate);
-
Screen();
virtual ~Screen();
+ // Retrieves the single Screen object.
+ static Screen* GetScreen();
+
+ // Sets the global screen. NOTE: this does not take ownership of |screen|.
+ // Tests must be sure to reset any state they install.
+ static void SetScreenInstance(Screen* instance);
+
// Returns the current absolute position of the mouse pointer.
virtual gfx::Point GetCursorScreenPoint() = 0;
@@ -91,6 +73,18 @@ class GFX_EXPORT Screen {
virtual void AddObserver(DisplayObserver* observer) = 0;
virtual void RemoveObserver(DisplayObserver* observer) = 0;
+ // Converts |screen_rect| to DIP coordinates in the context of |view| clamping
+ // to the enclosing rect if the coordinates do not fall on pixel boundaries.
+ // If |view| is null, the primary display is used as the context.
+ virtual gfx::Rect ScreenToDIPRectInWindow(NativeView view,
+ const gfx::Rect& screen_rect) const;
+
+ // Converts |dip_rect| to screen coordinates in the context of |view| clamping
+ // to the enclosing rect if the coordinates do not fall on pixel boundaries.
+ // If |view| is null, the primary display is used as the context.
+ virtual gfx::Rect DIPToScreenRectInWindow(NativeView view,
+ const gfx::Rect& dip_rect) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(Screen);
};
diff --git a/chromium/ui/gfx/screen_mac.mm b/chromium/ui/gfx/screen_mac.mm
index 6fb7c6e8dc2..26e0278fa5a 100644
--- a/chromium/ui/gfx/screen_mac.mm
+++ b/chromium/ui/gfx/screen_mac.mm
@@ -13,9 +13,11 @@
#include "base/logging.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "ui/gfx/display.h"
#include "ui/gfx/display_change_notifier.h"
+#include "ui/gfx/mac/coordinate_conversion.h"
namespace {
@@ -23,16 +25,6 @@ namespace {
// See comments in ScreenMac::HandleDisplayReconfiguration.
const int64_t kConfigureDelayMs = 500;
-gfx::Rect ConvertCoordinateSystem(NSRect ns_rect) {
- // Primary monitor is defined as the monitor with the menubar,
- // which is always at index 0.
- NSScreen* primary_screen = [[NSScreen screens] firstObject];
- float primary_screen_height = [primary_screen frame].size.height;
- gfx::Rect rect(NSRectToCGRect(ns_rect));
- rect.set_y(primary_screen_height - rect.y() - rect.height());
- return rect;
-}
-
NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) {
// Default to the monitor with the current keyboard focus, in case
// |match_rect| is not on any screen at all.
@@ -40,7 +32,7 @@ NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) {
int max_area = 0;
for (NSScreen* screen in [NSScreen screens]) {
- gfx::Rect monitor_area = ConvertCoordinateSystem([screen frame]);
+ gfx::Rect monitor_area = gfx::ScreenRectFromNSRect([screen frame]);
gfx::Rect intersection = gfx::IntersectRects(monitor_area, match_rect);
int area = intersection.width() * intersection.height();
if (area > max_area) {
@@ -69,14 +61,10 @@ gfx::Display GetDisplayForScreen(NSScreen* screen) {
visible_frame.size.height);
display.set_work_area(work_area);
} else {
- display.set_bounds(ConvertCoordinateSystem(frame));
- display.set_work_area(ConvertCoordinateSystem(visible_frame));
+ display.set_bounds(gfx::ScreenRectFromNSRect(frame));
+ display.set_work_area(gfx::ScreenRectFromNSRect(visible_frame));
}
- CGFloat scale;
- if ([screen respondsToSelector:@selector(backingScaleFactor)])
- scale = [screen backingScaleFactor];
- else
- scale = [screen userSpaceScaleFactor];
+ CGFloat scale = [screen backingScaleFactor];
if (gfx::Display::HasForceDeviceScaleFactor())
scale = gfx::Display::GetForcedDeviceScaleFactor();
@@ -103,11 +91,8 @@ class ScreenMac : public gfx::Screen {
}
gfx::Point GetCursorScreenPoint() override {
- NSPoint mouseLocation = [NSEvent mouseLocation];
// Flip coordinates to gfx (0,0 in top-left corner) using primary screen.
- NSScreen* screen = [[NSScreen screens] firstObject];
- mouseLocation.y = NSMaxY([screen frame]) - mouseLocation.y;
- return gfx::Point(mouseLocation.x, mouseLocation.y);
+ return gfx::ScreenPointFromNSPoint([NSEvent mouseLocation]);
}
gfx::NativeWindow GetWindowUnderCursor() override {
diff --git a/chromium/ui/gfx/screen_type_delegate.h b/chromium/ui/gfx/screen_type_delegate.h
deleted file mode 100644
index 03dad8f8dea..00000000000
--- a/chromium/ui/gfx/screen_type_delegate.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 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_GFX_SCREEN_TYPE_DELEGATE_H_
-#define UI_GFX_SCREEN_TYPE_DELEGATE_H_
-
-#include "build/build_config.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-
-enum ScreenType {
- SCREEN_TYPE_NATIVE = 0,
-#if defined(OS_CHROMEOS)
- SCREEN_TYPE_ALTERNATE = SCREEN_TYPE_NATIVE,
-#else
- SCREEN_TYPE_ALTERNATE,
-#endif
- SCREEN_TYPE_LAST = SCREEN_TYPE_ALTERNATE,
-};
-
-class GFX_EXPORT ScreenTypeDelegate {
- public:
- virtual ~ScreenTypeDelegate() {}
-
- // Determines which ScreenType a given |view| belongs to.
- virtual ScreenType GetScreenTypeForNativeView(NativeView view) = 0;
-};
-
-} // namespace gfx
-
-#endif // UI_GFX_SCREEN_TYPE_DELEGATE_H_
diff --git a/chromium/ui/gfx/screen_unittest.cc b/chromium/ui/gfx/screen_unittest.cc
index db5a03ffec9..8b63ac70b52 100644
--- a/chromium/ui/gfx/screen_unittest.cc
+++ b/chromium/ui/gfx/screen_unittest.cc
@@ -10,15 +10,14 @@ namespace {
TEST(ScreenTest, GetPrimaryDisplaySize) {
// We aren't actually testing that it's correct, just that it's sane.
- const gfx::Size size =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().size();
+ const gfx::Size size = gfx::Screen::GetScreen()->GetPrimaryDisplay().size();
EXPECT_GE(size.width(), 1);
EXPECT_GE(size.height(), 1);
}
TEST(ScreenTest, GetNumDisplays) {
// We aren't actually testing that it's correct, just that it's sane.
- EXPECT_GE(gfx::Screen::GetNativeScreen()->GetNumDisplays(), 1);
+ EXPECT_GE(gfx::Screen::GetScreen()->GetNumDisplays(), 1);
}
} // namespace
diff --git a/chromium/ui/gfx/screen_win.cc b/chromium/ui/gfx/screen_win.cc
deleted file mode 100644
index 3199f7acaac..00000000000
--- a/chromium/ui/gfx/screen_win.cc
+++ /dev/null
@@ -1,216 +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/gfx/screen_win.h"
-
-#include <windows.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/hash.h"
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/win_util.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/win/dpi.h"
-
-namespace {
-
-MONITORINFOEX GetMonitorInfoForMonitor(HMONITOR monitor) {
- MONITORINFOEX monitor_info;
- ZeroMemory(&monitor_info, sizeof(MONITORINFOEX));
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(monitor, &monitor_info);
- return monitor_info;
-}
-
-gfx::Display GetDisplay(const MONITORINFOEX& monitor_info) {
- int64_t id =
- static_cast<int64_t>(base::Hash(base::WideToUTF8(monitor_info.szDevice)));
- gfx::Rect bounds = gfx::Rect(monitor_info.rcMonitor);
- gfx::Display display(id);
- display.set_bounds(gfx::win::ScreenToDIPRect(bounds));
- display.set_work_area(
- gfx::win::ScreenToDIPRect(gfx::Rect(monitor_info.rcWork)));
- display.SetScaleAndBounds(gfx::GetDPIScale(), bounds);
-
- DEVMODE mode;
- memset(&mode, 0, sizeof(DEVMODE));
- mode.dmSize = sizeof(DEVMODE);
- mode.dmDriverExtra = 0;
- if (EnumDisplaySettings(monitor_info.szDevice,
- ENUM_CURRENT_SETTINGS,
- &mode)) {
- switch (mode.dmDisplayOrientation) {
- case DMDO_DEFAULT:
- display.set_rotation(gfx::Display::ROTATE_0);
- break;
- case DMDO_90:
- display.set_rotation(gfx::Display::ROTATE_90);
- break;
- case DMDO_180:
- display.set_rotation(gfx::Display::ROTATE_180);
- break;
- case DMDO_270:
- display.set_rotation(gfx::Display::ROTATE_270);
- break;
- default:
- NOTREACHED();
- }
- }
-
- return display;
-}
-
-BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor,
- HDC hdc,
- LPRECT rect,
- LPARAM data) {
- std::vector<gfx::Display>* all_displays =
- reinterpret_cast<std::vector<gfx::Display>*>(data);
- DCHECK(all_displays);
-
- MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(monitor);
- gfx::Display display = GetDisplay(monitor_info);
- all_displays->push_back(display);
- return TRUE;
-}
-
-std::vector<gfx::Display> GetDisplays() {
- std::vector<gfx::Display> displays;
- EnumDisplayMonitors(NULL, NULL, EnumMonitorCallback,
- reinterpret_cast<LPARAM>(&displays));
- return displays;
-}
-
-} // namespace
-
-namespace gfx {
-
-ScreenWin::ScreenWin()
- : singleton_hwnd_observer_(new SingletonHwndObserver(
- base::Bind(&ScreenWin::OnWndProc, base::Unretained(this)))),
- displays_(GetDisplays()) {
-}
-
-ScreenWin::~ScreenWin() {}
-
-HWND ScreenWin::GetHWNDFromNativeView(NativeView window) const {
- NOTREACHED();
- return NULL;
-}
-
-NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
- NOTREACHED();
- return NULL;
-}
-
-gfx::Point ScreenWin::GetCursorScreenPoint() {
- POINT pt;
- GetCursorPos(&pt);
- gfx::Point cursor_pos_pixels(pt);
- return gfx::win::ScreenToDIPPoint(cursor_pos_pixels);
-}
-
-gfx::NativeWindow ScreenWin::GetWindowUnderCursor() {
- POINT cursor_loc;
- HWND hwnd = GetCursorPos(&cursor_loc) ? WindowFromPoint(cursor_loc) : NULL;
- return GetNativeWindowFromHWND(hwnd);
-}
-
-gfx::NativeWindow ScreenWin::GetWindowAtScreenPoint(const gfx::Point& point) {
- gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point);
- return GetNativeWindowFromHWND(WindowFromPoint(point_in_pixels.ToPOINT()));
-}
-
-int ScreenWin::GetNumDisplays() const {
- return GetSystemMetrics(SM_CMONITORS);
-}
-
-std::vector<gfx::Display> ScreenWin::GetAllDisplays() const {
- return displays_;
-}
-
-gfx::Display ScreenWin::GetDisplayNearestWindow(gfx::NativeView window) const {
- HWND window_hwnd = GetHWNDFromNativeView(window);
- if (!window_hwnd) {
- // When |window| isn't rooted to a display, we should just return the
- // default display so we get some correct display information like the
- // scaling factor.
- return GetPrimaryDisplay();
- }
-
- MONITORINFOEX monitor_info;
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(MonitorFromWindow(window_hwnd, MONITOR_DEFAULTTONEAREST),
- &monitor_info);
- return GetDisplay(monitor_info);
-}
-
-gfx::Display ScreenWin::GetDisplayNearestPoint(const gfx::Point& point) const {
- gfx::Point point_in_pixels = gfx::win::DIPToScreenPoint(point);
- POINT initial_loc = { point_in_pixels.x(), point_in_pixels.y() };
- HMONITOR monitor = MonitorFromPoint(initial_loc, MONITOR_DEFAULTTONEAREST);
- MONITORINFOEX mi;
- ZeroMemory(&mi, sizeof(MONITORINFOEX));
- mi.cbSize = sizeof(mi);
- if (monitor && GetMonitorInfo(monitor, &mi)) {
- return GetDisplay(mi);
- }
- return gfx::Display();
-}
-
-gfx::Display ScreenWin::GetDisplayMatching(const gfx::Rect& match_rect) const {
- RECT other_bounds_rect = match_rect.ToRECT();
- MONITORINFOEX monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
- &other_bounds_rect, MONITOR_DEFAULTTONEAREST));
- return GetDisplay(monitor_info);
-}
-
-gfx::Display ScreenWin::GetPrimaryDisplay() const {
- MONITORINFOEX mi = GetMonitorInfoForMonitor(
- MonitorFromWindow(NULL, MONITOR_DEFAULTTOPRIMARY));
- gfx::Display display = GetDisplay(mi);
- // TODO(kevers|girard): Test if these checks can be reintroduced for high-DIP
- // once more of the app is DIP-aware.
- if (GetDPIScale() == 1.0) {
- DCHECK_EQ(GetSystemMetrics(SM_CXSCREEN), display.size().width());
- DCHECK_EQ(GetSystemMetrics(SM_CYSCREEN), display.size().height());
- }
- return display;
-}
-
-void ScreenWin::AddObserver(DisplayObserver* observer) {
- change_notifier_.AddObserver(observer);
-}
-
-void ScreenWin::RemoveObserver(DisplayObserver* observer) {
- change_notifier_.RemoveObserver(observer);
-}
-
-void ScreenWin::OnWndProc(HWND hwnd,
- UINT message,
- WPARAM wparam,
- LPARAM lparam) {
- if (message != WM_DISPLAYCHANGE)
- return;
-
- std::vector<gfx::Display> old_displays = displays_;
- displays_ = GetDisplays();
-
- change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
-}
-
-// static
-std::vector<gfx::Display> ScreenWin::GetDisplaysForMonitorInfos(
- const std::vector<MONITORINFOEX>& monitor_infos) {
- std::vector<gfx::Display> displays;
- for (const MONITORINFOEX& monitor_info : monitor_infos)
- displays.push_back(GetDisplay(monitor_info));
-
- return displays;
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/screen_win.h b/chromium/ui/gfx/screen_win.h
deleted file mode 100644
index b1488ae05bb..00000000000
--- a/chromium/ui/gfx/screen_win.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_GFX_SCREEN_WIN_H_
-#define UI_GFX_SCREEN_WIN_H_
-
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/display_change_notifier.h"
-#include "ui/gfx/gfx_export.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/win/singleton_hwnd_observer.h"
-
-namespace gfx {
-
-class GFX_EXPORT ScreenWin : public Screen {
- public:
- ScreenWin();
- ~ScreenWin() override;
-
- // Returns the HWND associated with the NativeView.
- virtual HWND GetHWNDFromNativeView(NativeView window) const;
-
- // Returns the NativeView associated with the HWND.
- virtual NativeWindow GetNativeWindowFromHWND(HWND hwnd) const;
-
- protected:
- // Overridden from gfx::Screen:
- gfx::Point GetCursorScreenPoint() override;
- gfx::NativeWindow GetWindowUnderCursor() override;
- gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
- int GetNumDisplays() const override;
- std::vector<gfx::Display> GetAllDisplays() const override;
- gfx::Display GetDisplayNearestWindow(gfx::NativeView window) const override;
- gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override;
- gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
- gfx::Display GetPrimaryDisplay() const override;
- void AddObserver(DisplayObserver* observer) override;
- void RemoveObserver(DisplayObserver* observer) override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(ScreenWinTest, SingleDisplay1x);
- FRIEND_TEST_ALL_PREFIXES(ScreenWinTest, SingleDisplay2x);
-
- void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-
- static std::vector<gfx::Display> GetDisplaysForMonitorInfos(
- const std::vector<MONITORINFOEX>& monitor_infos);
-
- // Helper implementing the DisplayObserver handling.
- gfx::DisplayChangeNotifier change_notifier_;
-
- scoped_ptr<SingletonHwndObserver> singleton_hwnd_observer_;
-
- // Current list of displays.
- std::vector<gfx::Display> displays_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenWin);
-};
-
-} // namespace gfx
-
-#endif // UI_GFX_SCREEN_WIN_H_
diff --git a/chromium/ui/gfx/screen_win_unittest.cc b/chromium/ui/gfx/screen_win_unittest.cc
deleted file mode 100644
index b1118c17e23..00000000000
--- a/chromium/ui/gfx/screen_win_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/gfx/screen_win.h"
-
-#include <cwchar>
-#include <string>
-#include <vector>
-
-#include <windows.h>
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/win/dpi.h"
-
-namespace gfx {
-
-namespace {
-
-MONITORINFOEX CreateMonitorInfo(gfx::Rect monitor,
- gfx::Rect work,
- std::wstring device_name) {
- MONITORINFOEX monitor_info;
- ::ZeroMemory(&monitor_info, sizeof(monitor_info));
- monitor_info.cbSize = sizeof(monitor_info);
- monitor_info.rcMonitor = monitor.ToRECT();
- monitor_info.rcWork = work.ToRECT();
- size_t device_char_count = ARRAYSIZE(monitor_info.szDevice);
- wcsncpy(monitor_info.szDevice, device_name.c_str(), device_char_count);
- monitor_info.szDevice[device_char_count-1] = L'\0';
- return monitor_info;
-}
-
-} // namespace
-
-class ScreenWinTest : public testing::Test {
- private:
- void SetUp() override {
- testing::Test::SetUp();
- gfx::SetDefaultDeviceScaleFactor(1.0);
- }
-
- void TearDown() override {
- gfx::SetDefaultDeviceScaleFactor(1.0);
- testing::Test::TearDown();
- }
-};
-
-TEST_F(ScreenWinTest, SingleDisplay1x) {
- std::vector<MONITORINFOEX> monitor_infos;
- monitor_infos.push_back(CreateMonitorInfo(gfx::Rect(0, 0, 1920, 1200),
- gfx::Rect(0, 0, 1920, 1100),
- L"primary"));
- std::vector<gfx::Display> displays =
- ScreenWin::GetDisplaysForMonitorInfos(monitor_infos);
-
- ASSERT_EQ(1u, displays.size());
- EXPECT_EQ(gfx::Rect(0, 0, 1920, 1200), displays[0].bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 1920, 1100), displays[0].work_area());
-}
-
-TEST_F(ScreenWinTest, SingleDisplay2x) {
- gfx::SetDefaultDeviceScaleFactor(2.0);
-
- std::vector<MONITORINFOEX> monitor_infos;
- monitor_infos.push_back(CreateMonitorInfo(gfx::Rect(0, 0, 1920, 1200),
- gfx::Rect(0, 0, 1920, 1100),
- L"primary"));
- std::vector<gfx::Display> displays =
- ScreenWin::GetDisplaysForMonitorInfos(monitor_infos);
-
- ASSERT_EQ(1u, displays.size());
- EXPECT_EQ(gfx::Rect(0, 0, 960, 600), displays[0].bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 960, 550), displays[0].work_area());
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/selection_model.h b/chromium/ui/gfx/selection_model.h
index 87a7a2d0b4e..73bf113da5c 100644
--- a/chromium/ui/gfx/selection_model.h
+++ b/chromium/ui/gfx/selection_model.h
@@ -77,7 +77,7 @@ class GFX_EXPORT SelectionModel {
// WARNING: Generally the selection start should not be changed without
// considering the effect on the caret affinity.
- void set_selection_start(size_t pos) { selection_.set_start(pos); }
+ void set_selection_start(uint32_t pos) { selection_.set_start(pos); }
bool operator==(const SelectionModel& sel) const;
bool operator!=(const SelectionModel& sel) const { return !(*this == sel); }
diff --git a/chromium/ui/gfx/skbitmap_operations.cc b/chromium/ui/gfx/skbitmap_operations.cc
index 3865916c903..3b3a7e823f9 100644
--- a/chromium/ui/gfx/skbitmap_operations.cc
+++ b/chromium/ui/gfx/skbitmap_operations.cc
@@ -704,10 +704,9 @@ SkBitmap SkBitmapOperations::CreateColorMask(const SkBitmap& bitmap,
SkCanvas canvas(color_mask);
- skia::RefPtr<SkColorFilter> color_filter = skia::AdoptRef(
- SkColorFilter::CreateModeFilter(c, SkXfermode::kSrcIn_Mode));
SkPaint paint;
- paint.setColorFilter(color_filter.get());
+ paint.setColorFilter(
+ SkColorFilter::MakeModeFilter(c, SkXfermode::kSrcIn_Mode));
canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
return color_mask;
}
diff --git a/chromium/ui/gfx/skia_util.cc b/chromium/ui/gfx/skia_util.cc
index c1e6c184ce1..956a2f08755 100644
--- a/chromium/ui/gfx/skia_util.cc
+++ b/chromium/ui/gfx/skia_util.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/numerics/safe_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkColorPriv.h"
@@ -90,14 +91,14 @@ void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
flattened->set(8, SkMScalarToScalar(transform.matrix().get(3, 3)));
}
-skia::RefPtr<SkShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep,
+sk_sp<SkShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep,
SkShader::TileMode tile_mode,
const SkMatrix& local_matrix) {
return CreateImageRepShaderForScale(image_rep, tile_mode, local_matrix,
image_rep.scale());
}
-skia::RefPtr<SkShader> CreateImageRepShaderForScale(
+sk_sp<SkShader> CreateImageRepShaderForScale(
const gfx::ImageSkiaRep& image_rep,
SkShader::TileMode tile_mode,
const SkMatrix& local_matrix,
@@ -114,12 +115,11 @@ skia::RefPtr<SkShader> CreateImageRepShaderForScale(
shader_scale.setScaleX(local_matrix.getScaleX() / scale);
shader_scale.setScaleY(local_matrix.getScaleY() / scale);
- skia::RefPtr<SkShader> shader = skia::AdoptRef(SkShader::CreateBitmapShader(
- image_rep.sk_bitmap(), tile_mode, tile_mode, &shader_scale));
- return shader;
+ return SkShader::MakeBitmapShader(
+ image_rep.sk_bitmap(), tile_mode, tile_mode, &shader_scale);
}
-skia::RefPtr<SkShader> CreateGradientShader(int start_point,
+sk_sp<SkShader> CreateGradientShader(int start_point,
int end_point,
SkColor start_color,
SkColor end_color) {
@@ -128,8 +128,8 @@ skia::RefPtr<SkShader> CreateGradientShader(int start_point,
grad_points[0].iset(0, start_point);
grad_points[1].iset(0, end_point);
- return skia::AdoptRef(SkGradientShader::CreateLinear(
- grad_points, grad_colors, NULL, 2, SkShader::kRepeat_TileMode));
+ return SkGradientShader::MakeLinear(
+ grad_points, grad_colors, NULL, 2, SkShader::kClamp_TileMode);
}
static SkScalar RadiusToSigma(double radius) {
@@ -138,10 +138,10 @@ static SkScalar RadiusToSigma(double radius) {
return radius > 0 ? SkDoubleToScalar(0.57735f * radius + 0.5) : 0;
}
-skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+sk_sp<SkDrawLooper> CreateShadowDrawLooper(
const std::vector<ShadowValue>& shadows) {
if (shadows.empty())
- return skia::RefPtr<SkDrawLooper>();
+ return nullptr;
SkLayerDrawLooper::Builder looper_builder;
@@ -164,16 +164,15 @@ skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
RadiusToSigma(shadow.blur() / 2),
SkBlurMaskFilter::kHighQuality_BlurFlag));
- skia::RefPtr<SkColorFilter> color_filter = skia::AdoptRef(
- SkColorFilter::CreateModeFilter(shadow.color(),
- SkXfermode::kSrcIn_Mode));
SkPaint* paint = looper_builder.addLayer(layer_info);
paint->setMaskFilter(blur_mask.get());
- paint->setColorFilter(color_filter.get());
+ paint->setColorFilter(
+ SkColorFilter::MakeModeFilter(shadow.color(),
+ SkXfermode::kSrcIn_Mode));
}
- return skia::AdoptRef<SkDrawLooper>(looper_builder.detachLooper());
+ return looper_builder.detach();
}
bool BitmapsAreEqual(const SkBitmap& bitmap1, const SkBitmap& bitmap2) {
@@ -226,4 +225,21 @@ void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]) {
points[3] = PointFToSkPoint(quad.p4());
}
+// We treat HarfBuzz ints as 16.16 fixed-point.
+static const int kHbUnit1 = 1 << 16;
+
+int SkiaScalarToHarfBuzzUnits(SkScalar value) {
+ return base::saturated_cast<int>(value * kHbUnit1);
+}
+
+SkScalar HarfBuzzUnitsToSkiaScalar(int value) {
+ static const SkScalar kSkToHbRatio = SK_Scalar1 / kHbUnit1;
+ return kSkToHbRatio * value;
+}
+
+float HarfBuzzUnitsToFloat(int value) {
+ static const float kFloatToHbRatio = 1.0f / kHbUnit1;
+ return kFloatToHbRatio * value;
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/skia_util.h b/chromium/ui/gfx/skia_util.h
index 25c96d03705..9fd880b2cc4 100644
--- a/chromium/ui/gfx/skia_util.h
+++ b/chromium/ui/gfx/skia_util.h
@@ -54,13 +54,13 @@ GFX_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
// TODO(pkotwicz): Allow shader's local matrix to be changed after the shader
// is created.
//
-GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShader(
+GFX_EXPORT sk_sp<SkShader> CreateImageRepShader(
const gfx::ImageSkiaRep& image_rep,
SkShader::TileMode tile_mode,
const SkMatrix& local_matrix);
// Creates a bitmap shader for the image rep with the passed in scale factor.
-GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShaderForScale(
+GFX_EXPORT sk_sp<SkShader> CreateImageRepShaderForScale(
const gfx::ImageSkiaRep& image_rep,
SkShader::TileMode tile_mode,
const SkMatrix& local_matrix,
@@ -68,15 +68,15 @@ GFX_EXPORT skia::RefPtr<SkShader> CreateImageRepShaderForScale(
// Creates a vertical gradient shader. The caller owns the shader.
// Example usage to avoid leaks:
-GFX_EXPORT skia::RefPtr<SkShader> CreateGradientShader(int start_point,
- int end_point,
- SkColor start_color,
- SkColor end_color);
+GFX_EXPORT sk_sp<SkShader> CreateGradientShader(int start_point,
+ int end_point,
+ SkColor start_color,
+ SkColor end_color);
// Creates a draw looper to generate |shadows|. The caller owns the draw looper.
// NULL is returned if |shadows| is empty since no draw looper is needed in
// this case.
-GFX_EXPORT skia::RefPtr<SkDrawLooper> CreateShadowDrawLooper(
+GFX_EXPORT sk_sp<SkDrawLooper> CreateShadowDrawLooper(
const std::vector<ShadowValue>& shadows);
// Returns true if the two bitmaps contain the same pixels.
@@ -88,6 +88,15 @@ GFX_EXPORT void ConvertSkiaToRGBA(const unsigned char* skia,
int pixel_width,
unsigned char* rgba);
+// Converts a Skia floating-point value to an int appropriate for hb_position_t.
+GFX_EXPORT int SkiaScalarToHarfBuzzUnits(SkScalar value);
+
+// Converts an hb_position_t to a Skia floating-point value.
+GFX_EXPORT SkScalar HarfBuzzUnitsToSkiaScalar(int value);
+
+// Converts an hb_position_t to a float.
+GFX_EXPORT float HarfBuzzUnitsToFloat(int value);
+
} // namespace gfx
#endif // UI_GFX_SKIA_UTIL_H_
diff --git a/chromium/ui/gfx/sys_color_change_listener.cc b/chromium/ui/gfx/sys_color_change_listener.cc
index a81409618e0..fcda18935af 100644
--- a/chromium/ui/gfx/sys_color_change_listener.cc
+++ b/chromium/ui/gfx/sys_color_change_listener.cc
@@ -20,16 +20,16 @@ bool g_is_inverted_color_scheme = false;
bool g_is_inverted_color_scheme_initialized = false;
void UpdateInvertedColorScheme() {
- int foreground_luminance = color_utils::GetLuminanceForColor(
- color_utils::GetSysSkColor(COLOR_WINDOWTEXT));
- int background_luminance = color_utils::GetLuminanceForColor(
- color_utils::GetSysSkColor(COLOR_WINDOW));
+ const uint8_t foreground_luma =
+ color_utils::GetLuma(color_utils::GetSysSkColor(COLOR_WINDOWTEXT));
+ const uint8_t background_luma =
+ color_utils::GetLuma(color_utils::GetSysSkColor(COLOR_WINDOW));
HIGHCONTRAST high_contrast = {0};
high_contrast.cbSize = sizeof(HIGHCONTRAST);
g_is_inverted_color_scheme =
SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &high_contrast, 0) &&
((high_contrast.dwFlags & HCF_HIGHCONTRASTON) != 0) &&
- foreground_luminance > background_luminance;
+ foreground_luma > background_luma;
g_is_inverted_color_scheme_initialized = true;
}
diff --git a/chromium/ui/gfx/text_elider.cc b/chromium/ui/gfx/text_elider.cc
index 4b7a7f9fc99..e8993d79877 100644
--- a/chromium/ui/gfx/text_elider.cc
+++ b/chromium/ui/gfx/text_elider.cc
@@ -259,10 +259,9 @@ base::string16 ElideText(const base::string16& text,
}
bool ElideString(const base::string16& input,
- int max_len,
+ size_t max_len,
base::string16* output) {
- DCHECK_GE(max_len, 0);
- if (static_cast<int>(input.length()) <= max_len) {
+ if (input.length() <= max_len) {
output->assign(input);
return false;
}
@@ -571,7 +570,7 @@ void RectangleText::AddString(const base::string16& input) {
// The BREAK_NEWLINE iterator will keep the trailing newline character,
// except in the case of the last line, which may not have one. Remove
// the newline character, if it exists.
- last_line_ended_in_lf_ = !line.empty() && line[line.length() - 1] == '\n';
+ last_line_ended_in_lf_ = !line.empty() && line.back() == '\n';
if (last_line_ended_in_lf_)
line.resize(line.length() - 1);
AddLine(line);
diff --git a/chromium/ui/gfx/text_elider.h b/chromium/ui/gfx/text_elider.h
index 63f84c91b78..d7d54879989 100644
--- a/chromium/ui/gfx/text_elider.h
+++ b/chromium/ui/gfx/text_elider.h
@@ -96,7 +96,7 @@ GFX_EXPORT base::string16 ElideFilename(const base::FilePath& filename,
// puts "Hell...Tom" in str and returns true.
// TODO(tsepez): Doesn't handle UTF-16 surrogate pairs properly.
// TODO(tsepez): Doesn't handle bidi properly.
-GFX_EXPORT bool ElideString(const base::string16& input, int max_len,
+GFX_EXPORT bool ElideString(const base::string16& input, size_t max_len,
base::string16* output);
// Reformat |input| into |output| so that it fits into a |max_rows| by
diff --git a/chromium/ui/gfx/text_elider_unittest.cc b/chromium/ui/gfx/text_elider_unittest.cc
index ce8c2f07245..4490110ccc3 100644
--- a/chromium/ui/gfx/text_elider_unittest.cc
+++ b/chromium/ui/gfx/text_elider_unittest.cc
@@ -594,7 +594,7 @@ TEST(TextEliderTest, StringSlicerCombiningSurrogate) {
TEST(TextEliderTest, ElideString) {
struct TestData {
const char* input;
- int max_len;
+ size_t max_len;
bool result;
const char* output;
} cases[] = {
@@ -831,7 +831,7 @@ TEST(TextEliderTest, MAYBE_ElideRectangleTextCheckLineWidth) {
EXPECT_LE(GetStringWidthF(lines[1], font_list), kAvailableWidth);
}
-#ifdef OS_CHROMEOS
+#if defined(OS_CHROMEOS)
// This test was created specifically to test a message from crbug.com/415213.
// It tests that width of concatenation of words equals sum of widths of the
// words.
@@ -846,7 +846,7 @@ TEST(TextEliderTest, ElideRectangleTextCheckConcatWidthEqualsSumOfWidths) {
#undef WIDTH
SetFontRenderParamsDeviceScaleFactor(1.0f);
}
-#endif // OS_CHROMEOS
+#endif // defined(OS_CHROMEOS)
// TODO(crbug.com/338784): Enable this on android.
#if defined(OS_ANDROID)
diff --git a/chromium/ui/gfx/vector_icons/aggregate_vector_icons.py b/chromium/ui/gfx/vector_icons/aggregate_vector_icons.py
index 72fbc11cc93..938f1a858fd 100644
--- a/chromium/ui/gfx/vector_icons/aggregate_vector_icons.py
+++ b/chromium/ui/gfx/vector_icons/aggregate_vector_icons.py
@@ -9,6 +9,10 @@ import os
import textwrap
+# TODO(brettw) bug 535386: This should not take a directory as an input, but
+# rather a response file listing the inputs or sometimes the build will be
+# incorrect.
+
def AggregateVectorIcons(working_directory, output_cc, output_h):
"""Compiles all .icon files in a directory into two C++ files.
diff --git a/chromium/ui/gfx/vector_icons/autofill.icon b/chromium/ui/gfx/vector_icons/autofill.icon
deleted file mode 100644
index 811335064ba..00000000000
--- a/chromium/ui/gfx/vector_icons/autofill.icon
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-MOVE_TO, 6, 34.5f,
-LINE_TO, 6, 42,
-LINE_TO, 13.5f, 42,
-LINE_TO, 35.63f, 19.87f,
-LINE_TO, 28.13f, 12.37f,
-LINE_TO, 6, 34.5f,
-LINE_TO, 6, 34.5f,
-CLOSE,
-MOVE_TO, 41.41f, 14.09f,
-CUBIC_TO, 42.2f, 13.3f, 42.2f, 12.04f, 41.41f, 11.26f,
-LINE_TO, 36.74f, 6.59f,
-CUBIC_TO, 35.96f, 5.8f, 34.7f, 5.8f, 33.91f, 6.59f,
-LINE_TO, 30.25f, 10.25f,
-LINE_TO, 37.75f, 17.75f,
-LINE_TO, 41.41f, 14.09f,
-LINE_TO, 41.41f, 14.09f,
-CLOSE,
-MOVE_TO, 24, 38,
-LINE_TO, 20, 42,
-LINE_TO, 42, 42,
-LINE_TO, 42, 38,
-LINE_TO, 24, 38,
-LINE_TO, 24, 38,
-CLOSE,
-END
diff --git a/chromium/ui/gfx/vector_icons/combobox_arrow_mac.icon b/chromium/ui/gfx/vector_icons/combobox_arrow_mac.icon
new file mode 100644
index 00000000000..4f5858287b2
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/combobox_arrow_mac.icon
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+STROKE, 4,
+MOVE_TO, 8, 10,
+LINE_TO, 16, 2,
+LINE_TO, 24, 10,
+MOVE_TO, 8, 22,
+LINE_TO, 16, 30,
+LINE_TO, 24, 22,
+END
diff --git a/chromium/ui/gfx/vector_icons/menu_radio_empty.icon b/chromium/ui/gfx/vector_icons/menu_radio_empty.icon
new file mode 100644
index 00000000000..62ef2daec82
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/menu_radio_empty.icon
@@ -0,0 +1,8 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+CIRCLE, 16, 16, 14,
+CIRCLE, 16, 16, 11,
+END
diff --git a/chromium/ui/gfx/vector_icons/menu_radio_selected.icon b/chromium/ui/gfx/vector_icons/menu_radio_selected.icon
new file mode 100644
index 00000000000..0533b99ba7e
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/menu_radio_selected.icon
@@ -0,0 +1,9 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+CIRCLE, 16, 16, 14,
+CIRCLE, 16, 16, 11,
+CIRCLE, 16, 16, 7,
+END
diff --git a/chromium/ui/gfx/vector_icons/tab_bluetooth_connected.icon b/chromium/ui/gfx/vector_icons/tab_bluetooth_connected.icon
new file mode 100644
index 00000000000..9ed11250a58
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/tab_bluetooth_connected.icon
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+MOVE_TO, 16.8f, 2,
+R_H_LINE_TO, -1.4f,
+R_V_LINE_TO, 10.63f,
+LINE_TO, 8.97f, 6.2f,
+LINE_TO, 7, 8.17f,
+LINE_TO, 14.83f, 16,
+LINE_TO, 7, 23.83f,
+LINE_TO, 8.97f, 25.8f,
+R_LINE_TO, 6.43f, -6.43f,
+V_LINE_TO, 30,
+R_H_LINE_TO, 1.4f,
+R_LINE_TO, 7.99f, -7.99f,
+LINE_TO, 18.77f, 16,
+R_LINE_TO, 6.02f, -6.01f,
+LINE_TO, 16.8f, 2,
+CLOSE,
+MOVE_TO, 18, 7,
+R_LINE_TO, 3, 3,
+R_LINE_TO, -3, 3,
+R_LINE_TO, 0.2f, -5.64f,
+LINE_TO, 18, 7,
+CLOSE,
+R_MOVE_TO, 3, 15.01f,
+LINE_TO, 18, 25,
+R_V_LINE_TO, -6,
+R_LINE_TO, 2.83f, 3.01f,
+H_LINE_TO, 21,
+CLOSE,
+END \ No newline at end of file
diff --git a/chromium/ui/gfx/vector_icons/tab_usb_connected.icon b/chromium/ui/gfx/vector_icons/tab_usb_connected.icon
new file mode 100644
index 00000000000..c383dca1eb0
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/tab_usb_connected.icon
@@ -0,0 +1,39 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 24,
+MOVE_TO, 15, 7,
+R_V_LINE_TO, 4,
+R_H_LINE_TO, 1,
+R_V_LINE_TO, 2,
+R_H_LINE_TO, -3,
+V_LINE_TO, 5,
+R_H_LINE_TO, 2,
+R_LINE_TO, -3, -4,
+R_LINE_TO, -3, 4,
+R_H_LINE_TO, 2,
+R_V_LINE_TO, 8,
+H_LINE_TO, 8,
+R_V_LINE_TO, -2.07f,
+R_CUBIC_TO, 0.7f, -0.37f, 1.2f, -1.08f, 1.2f, -1.93f,
+R_CUBIC_TO, 0, -1.21f, -0.99f, -2.2f, -2.2f, -2.2f,
+R_CUBIC_TO, -1.21f, 0, -2.2f, 0.99f, -2.2f, 2.2f,
+R_CUBIC_TO, 0, 0.85f, 0.5f, 1.56f, 1.2f, 1.93f,
+V_LINE_TO, 13,
+R_CUBIC_TO, 0, 1.11f, 0.89f, 2, 2, 2,
+R_H_LINE_TO, 3,
+R_V_LINE_TO, 3.05f,
+R_CUBIC_TO, -0.71f, 0.37f, -1.2f, 1.1f, -1.2f, 1.95f,
+R_CUBIC_TO, 0, 1.22f, 0.99f, 2.2f, 2.2f, 2.2f,
+R_CUBIC_TO, 1.21f, 0, 2.2f, -0.98f, 2.2f, -2.2f,
+R_CUBIC_TO, 0, -0.85f, -0.49f, -1.58f, -1.2f, -1.95f,
+V_LINE_TO, 15,
+R_H_LINE_TO, 3,
+R_CUBIC_TO, 1.11f, 0, 2, -0.89f, 2, -2,
+R_V_LINE_TO, -2,
+R_H_LINE_TO, 1,
+V_LINE_TO, 7,
+R_H_LINE_TO, -4,
+CLOSE,
+END
diff --git a/chromium/ui/gfx/vector_icons/translate.icon b/chromium/ui/gfx/vector_icons/translate.icon
index 620036f4c7d..d553c9bab1f 100644
--- a/chromium/ui/gfx/vector_icons/translate.icon
+++ b/chromium/ui/gfx/vector_icons/translate.icon
@@ -3,66 +3,73 @@
// found in the LICENSE file.
CANVAS_DIMENSIONS, 16,
-MOVE_TO, 7.7f, 3.8f,
-H_LINE_TO, 6.7f,
-CUBIC_TO, 6.3f, 5.3f, 6, 5.6f, 5.5f, 6.3f,
-R_CUBIC_TO, 0.6f, 0.4f, 1.4f, 0.9f, 2.1f, 1.2f,
-LINE_TO, 7.2f, 8.1f,
-CUBIC_TO, 6.3f, 7.8f, 5.8f, 7.3f, 5, 6.8f,
-R_CUBIC_TO, -0.8f, 0.5f, -1.3f, 1, -2.2f, 1.3f,
-LINE_TO, 2.3f, 7.5f,
-R_CUBIC_TO, 0.8f, -0.3f, 1.6f, -0.8f, 2.1f, -1.2f,
-CUBIC_TO, 4, 5.6f, 3.7f, 5.2f, 3.4f, 4.5f,
-R_H_LINE_TO, 0.7f,
-CUBIC_TO, 4.4f, 5, 4.7f, 5.5f, 5, 5.9f,
-R_CUBIC_TO, 0.5f, -0.6f, 0.9f, -1.1f, 1, -2.2f,
-R_LINE_TO, -3.7f, 0,
-V_LINE_TO, 3.1f,
-R_H_LINE_TO, 2.3f,
-V_LINE_TO, 2.3f,
-R_H_LINE_TO, 0.7f,
-R_V_LINE_TO, 0.7f,
-R_H_LINE_TO, 2.3f,
-V_LINE_TO, 3.8f,
+MOVE_TO, 13.6f, 3.1f,
+LINE_TO, 7.22f, 3.1f,
+LINE_TO, 6.6f, 1,
+LINE_TO, 2.4f, 1,
+CUBIC_TO, 1.63f, 1, 1, 1.63f, 1, 2.4f,
+LINE_TO, 1, 11.5f,
+CUBIC_TO, 1, 12.27f, 1.63f, 12.9f, 2.4f, 12.9f,
+LINE_TO, 7.3f, 12.9f,
+LINE_TO, 8, 15,
+LINE_TO, 13.6f, 15,
+CUBIC_TO, 14.37f, 15, 15, 14.37f, 15, 13.6f,
+LINE_TO, 15, 4.5f,
+CUBIC_TO, 15, 3.73f, 14.37f, 3.1f, 13.6f, 3.1f,
+LINE_TO, 13.6f, 3.1f,
CLOSE,
-MOVE_TO, 7.7f, 1,
-H_LINE_TO, 2.3f,
-CUBIC_TO, 1.7f, 1, 1, 1.7f, 1, 2.3f,
-R_V_LINE_TO, 5.3f,
-CUBIC_TO, 1, 8.2f, 1.8f, 9, 2.3f, 9,
-R_H_LINE_TO, 5.3f,
-CUBIC_TO, 8.2f, 9, 9, 8.2f, 9, 7.7f,
-V_LINE_TO, 2.3f,
-CUBIC_TO, 9, 1.7f, 8.3f, 1, 7.7f, 1,
+MOVE_TO, 4.62f, 9.81f,
+CUBIC_TO, 3.04f, 9.81f, 1.76f, 8.53f, 1.76f, 6.95f,
+CUBIC_TO, 1.76f, 5.37f, 3.04f, 4.09f, 4.62f, 4.09f,
+CUBIC_TO, 5.35f, 4.09f, 6.01f, 4.35f, 6.54f, 4.84f,
+LINE_TO, 6.59f, 4.88f,
+LINE_TO, 5.73f, 5.7f,
+LINE_TO, 5.68f, 5.67f,
+CUBIC_TO, 5.48f, 5.48f, 5.14f, 5.26f, 4.62f, 5.26f,
+CUBIC_TO, 3.7f, 5.26f, 2.95f, 6.02f, 2.95f, 6.95f,
+CUBIC_TO, 2.95f, 7.88f, 3.7f, 8.64f, 4.62f, 8.64f,
+CUBIC_TO, 5.58f, 8.64f, 5.99f, 8.04f, 6.1f, 7.62f,
+LINE_TO, 4.56f, 7.62f,
+LINE_TO, 4.56f, 6.54f,
+LINE_TO, 7.32f, 6.54f,
+LINE_TO, 7.33f, 6.59f,
+CUBIC_TO, 7.36f, 6.73f, 7.36f, 6.87f, 7.36f, 7.01f,
+CUBIC_TO, 7.36f, 8.66f, 6.24f, 9.81f, 4.62f, 9.81f,
+LINE_TO, 4.62f, 9.81f,
CLOSE,
-NEW_PATH,
-MOVE_TO, 13.7f, 7,
-H_LINE_TO, 9,
-H_LINE_TO, 8,
-R_V_LINE_TO, 1,
-R_V_LINE_TO, 0.5f,
-H_LINE_TO, 7,
-V_LINE_TO, 9,
-R_V_LINE_TO, 1,
-R_V_LINE_TO, 3.7f,
-CUBIC_TO, 7, 14.3f, 7.7f, 15, 8.3f, 15,
-R_H_LINE_TO, 5.6f,
-R_CUBIC_TO, 0.6f, 0, 1.1f, -0.6f, 1.1f, -1.1f,
-V_LINE_TO, 8.3f,
-CUBIC_TO, 15, 7.7f, 14.3f, 7, 13.7f, 7,
+MOVE_TO, 8.84f, 8.62f,
+CUBIC_TO, 9.07f, 9.04f, 9.36f, 9.44f, 9.67f, 9.81f,
+LINE_TO, 9.3f, 10.18f,
+LINE_TO, 8.84f, 8.62f,
+LINE_TO, 8.84f, 8.62f,
CLOSE,
-MOVE_TO, 12.4f, 13.2f,
-R_LINE_TO, -0.4f, -1,
-H_LINE_TO, 10,
-R_LINE_TO, -0.4f, 1,
-H_LINE_TO, 8.8f,
-R_LINE_TO, 1.7f, -4.4f,
-R_H_LINE_TO, 1,
-R_LINE_TO, 1.7f, 4.4f,
-H_LINE_TO, 12.4f,
+MOVE_TO, 13.6f, 14.3f,
+LINE_TO, 8.7f, 14.3f,
+LINE_TO, 10.1f, 12.9f,
+LINE_TO, 9.53f, 10.96f,
+LINE_TO, 10.18f, 10.32f,
+LINE_TO, 12.05f, 12.2f,
+LINE_TO, 12.56f, 11.69f,
+LINE_TO, 10.67f, 9.81f,
+CUBIC_TO, 11.3f, 9.09f, 11.79f, 8.24f, 12.01f, 7.36f,
+LINE_TO, 12.9f, 7.36f,
+LINE_TO, 12.9f, 6.63f,
+LINE_TO, 10.35f, 6.63f,
+LINE_TO, 10.35f, 5.9f,
+LINE_TO, 9.62f, 5.9f,
+LINE_TO, 9.62f, 6.63f,
+LINE_TO, 8.25f, 6.63f,
+LINE_TO, 7.43f, 3.8f,
+LINE_TO, 13.6f, 3.8f,
+CUBIC_TO, 13.99f, 3.8f, 14.3f, 4.12f, 14.3f, 4.5f,
+LINE_TO, 14.3f, 13.6f,
+CUBIC_TO, 14.3f, 13.99f, 13.99f, 14.3f, 13.6f, 14.3f,
CLOSE,
-MOVE_TO, 10.1f, 11.4f,
-LINE_TO, 11.9f, 11.4f,
-LINE_TO, 11, 9.2f,
+MOVE_TO, 8.69f, 8.08f,
+LINE_TO, 8.47f, 7.36f,
+LINE_TO, 11.26f, 7.36f,
+CUBIC_TO, 11.26f, 7.36f, 11.02f, 8.27f, 10.17f, 9.27f,
+CUBIC_TO, 9.81f, 8.84f, 9.55f, 8.41f, 9.38f, 8.08f,
+LINE_TO, 8.69f, 8.08f,
CLOSE,
END
diff --git a/chromium/ui/gfx/vector_icons/upgrade_menu_item.icon b/chromium/ui/gfx/vector_icons/upgrade_menu_item.icon
new file mode 100644
index 00000000000..dcf04ed9aa0
--- /dev/null
+++ b/chromium/ui/gfx/vector_icons/upgrade_menu_item.icon
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 32,
+ROUND_RECT, 2, 2, 28, 28, 4,
+MOVE_TO, 12, 24,
+R_H_LINE_TO, 8,
+R_V_LINE_TO, -6,
+R_H_LINE_TO, 4,
+LINE_TO, 16, 8,
+LINE_TO, 8, 18,
+R_H_LINE_TO, 4,
+R_V_LINE_TO, 6,
+CLOSE,
+END
diff --git a/chromium/ui/gfx/win/direct_write.cc b/chromium/ui/gfx/win/direct_write.cc
index 71a023f316b..bf8c881d946 100644
--- a/chromium/ui/gfx/win/direct_write.cc
+++ b/chromium/ui/gfx/win/direct_write.cc
@@ -44,11 +44,8 @@ bool ShouldUseDirectWrite() {
}
void CreateDWriteFactory(IDWriteFactory** factory) {
- if (!ShouldUseDirectWrite() ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableDirectWriteForUI)) {
+ if (!ShouldUseDirectWrite())
return;
- }
using DWriteCreateFactoryProc = decltype(DWriteCreateFactory)*;
HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
@@ -78,6 +75,11 @@ void MaybeInitializeDirectWrite() {
return;
tried_dwrite_initialize = true;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDirectWriteForUI)) {
+ return;
+ }
+
base::win::ScopedComPtr<IDWriteFactory> factory;
CreateDWriteFactory(factory.Receive());
diff --git a/chromium/ui/gfx/win/physical_size.cc b/chromium/ui/gfx/win/physical_size.cc
new file mode 100644
index 00000000000..2aa0c3fd892
--- /dev/null
+++ b/chromium/ui/gfx/win/physical_size.cc
@@ -0,0 +1,163 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/win/physical_size.h"
+
+#include <windows.h>
+#include <setupapi.h>
+
+#include <iostream>
+
+#include "base/logging.h"
+#include "base/memory/free_deleter.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/scoped_generic.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/registry.h"
+
+// This GUID {E6F07B5F-EE97-4A90-B076-33F57BF4EAA7} was taken from
+// https://msdn.microsoft.com/en-us/library/windows/hardware/ff545901.aspx
+const GUID GUID_DEVICEINTERFACE_MONITOR = {
+ 0xE6F07B5F,
+ 0xEE97,
+ 0x4A90,
+ {0xB0, 0x76, 0x33, 0xF5, 0x7B, 0xF4, 0xEA, 0xA7}};
+
+namespace {
+
+struct DeviceInfoListScopedTraits {
+ static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
+
+ static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
+};
+
+bool GetSizeFromRegistry(HDEVINFO device_info_list,
+ SP_DEVINFO_DATA* device_info,
+ int* width_mm,
+ int* height_mm) {
+ base::win::RegKey reg_key(SetupDiOpenDevRegKey(
+ device_info_list, device_info, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ));
+ if (!reg_key.Valid())
+ return false;
+
+ BYTE data[128]; // EDID block is exactly 128 bytes long.
+ ZeroMemory(&data[0], sizeof(data));
+ DWORD data_length = sizeof(data);
+ LONG return_value =
+ reg_key.ReadValue(L"EDID", &data[0], &data_length, nullptr);
+ if (return_value != ERROR_SUCCESS)
+ return false;
+
+ // Byte 54 is the start of the first descriptor block, which contains the
+ // required timing information with the highest preference, and 12 bytes
+ // into that block is the size information.
+ // 66: width least significant bits
+ // 67: height least significant bits
+ // 68: 4 bits for each of width and height most significant bits
+ if (data[54] == 0)
+ return false;
+ const int w = ((data[68] & 0xF0) << 4) + data[66];
+ const int h = ((data[68] & 0x0F) << 8) + data[67];
+
+ if (w <= 0 || h <= 0)
+ return false;
+
+ *width_mm = w;
+ *height_mm = h;
+
+ return true;
+}
+
+bool GetInterfaceDetailAndDeviceInfo(
+ HDEVINFO device_info_list,
+ SP_DEVICE_INTERFACE_DATA* interface_data,
+ scoped_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>*
+ interface_detail,
+ SP_DEVINFO_DATA* device_info) {
+ DCHECK_EQ(sizeof(*device_info), device_info->cbSize);
+ DWORD buffer_size;
+ // This call populates device_info. It will also fail, but if the error is
+ // "insufficient buffer" then it will set buffer_size and we can call again
+ // with an allocated buffer.
+ SetupDiGetDeviceInterfaceDetail(device_info_list, interface_data, nullptr, 0,
+ &buffer_size, device_info);
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ return false;
+
+ interface_detail->reset(
+ reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(buffer_size)));
+ (*interface_detail)->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+ return SetupDiGetDeviceInterfaceDetail(device_info_list, interface_data,
+ interface_detail->get(), buffer_size,
+ nullptr, nullptr) != 0;
+}
+
+} // namespace
+
+namespace gfx {
+
+// The physical size information is only available by looking in the EDID block
+// via setup. However setup has the device path and not the device name that we
+// use to identify displays. Therefore after looking up a device via setup we
+// need to find the display again via EnumDisplayDevices (matching device path
+// to the device ID of the display's interface) so we can return the device name
+// (available from the interface's attached monitor).
+std::vector<PhysicalDisplaySize> GetPhysicalSizeForDisplays() {
+ std::vector<PhysicalDisplaySize> out;
+
+ base::ScopedGeneric<HDEVINFO, DeviceInfoListScopedTraits> device_info_list(
+ SetupDiGetClassDevs(&GUID_DEVICEINTERFACE_MONITOR, nullptr, nullptr,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
+
+ if (!device_info_list.is_valid())
+ return out;
+
+ SP_DEVICE_INTERFACE_DATA interface_data = {};
+ interface_data.cbSize = sizeof(interface_data);
+ int interface_index = 0;
+ while (SetupDiEnumDeviceInterfaces(device_info_list.get(), nullptr,
+ &GUID_DEVICEINTERFACE_MONITOR,
+ interface_index++, &interface_data)) {
+ scoped_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
+ interface_detail;
+ SP_DEVINFO_DATA device_info = {};
+ device_info.cbSize = sizeof(device_info);
+ bool get_info_succeeded =
+ GetInterfaceDetailAndDeviceInfo(device_info_list.get(), &interface_data,
+ &interface_detail, &device_info);
+ if (!get_info_succeeded)
+ continue;
+
+ DISPLAY_DEVICE display_device = {};
+ display_device.cb = sizeof(display_device);
+ int display_index = 0;
+ while (EnumDisplayDevices(nullptr, display_index++, &display_device,
+ EDD_GET_DEVICE_INTERFACE_NAME)) {
+ DISPLAY_DEVICE attached_device = {};
+ attached_device.cb = sizeof(attached_device);
+ int attached_index = 0;
+ while (EnumDisplayDevices(display_device.DeviceName, attached_index++,
+ &attached_device,
+ EDD_GET_DEVICE_INTERFACE_NAME)) {
+ wchar_t* attached_device_id = attached_device.DeviceID;
+ wchar_t* setup_device_path = interface_detail->DevicePath;
+ if (wcsicmp(attached_device_id, setup_device_path) == 0) {
+ int width_mm;
+ int height_mm;
+ bool found = GetSizeFromRegistry(device_info_list.get(), &device_info,
+ &width_mm, &height_mm);
+ if (found) {
+ out.push_back(
+ PhysicalDisplaySize(base::WideToUTF8(display_device.DeviceName),
+ width_mm, height_mm));
+ }
+ break;
+ }
+ }
+ }
+ }
+ return out;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/win/physical_size.h b/chromium/ui/gfx/win/physical_size.h
new file mode 100644
index 00000000000..10d94714ffb
--- /dev/null
+++ b/chromium/ui/gfx/win/physical_size.h
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_WIN_PHYSICAL_SIZE_H_
+#define UI_GFX_WIN_PHYSICAL_SIZE_H_
+
+#include <string>
+#include <vector>
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+struct PhysicalDisplaySize {
+ PhysicalDisplaySize(const std::string& display_name,
+ int width_mm,
+ int height_mm)
+ : display_name(display_name), width_mm(width_mm), height_mm(height_mm) {}
+
+ std::string display_name;
+ int width_mm;
+ int height_mm;
+};
+
+// Gets the physical size for all displays.
+GFX_EXPORT std::vector<PhysicalDisplaySize> GetPhysicalSizeForDisplays();
+
+} // namespace gfx
+
+#endif // UI_GFX_DPI_WIN_H_
diff --git a/chromium/ui/gfx/win/rendering_window_manager.cc b/chromium/ui/gfx/win/rendering_window_manager.cc
new file mode 100644
index 00000000000..a0528ecf9ab
--- /dev/null
+++ b/chromium/ui/gfx/win/rendering_window_manager.cc
@@ -0,0 +1,70 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/win/rendering_window_manager.h"
+
+#include "base/memory/singleton.h"
+
+namespace gfx {
+
+// static
+RenderingWindowManager* RenderingWindowManager::GetInstance() {
+ return base::Singleton<RenderingWindowManager>::get();
+}
+
+void RenderingWindowManager::RegisterParent(HWND parent) {
+ base::AutoLock lock(lock_);
+
+ info_[parent] = nullptr;
+}
+
+bool RenderingWindowManager::RegisterChild(HWND parent, HWND child_window) {
+ if (!child_window)
+ return false;
+
+ base::AutoLock lock(lock_);
+
+ auto it = info_.find(parent);
+ if (it == info_.end())
+ return false;
+ if (it->second)
+ return false;
+
+ info_[parent] = child_window;
+ return true;
+}
+
+void RenderingWindowManager::DoSetParentOnChild(HWND parent) {
+ HWND child;
+ {
+ base::AutoLock lock(lock_);
+
+ auto it = info_.find(parent);
+ if (it == info_.end())
+ return;
+ if (!it->second)
+ return;
+ child = it->second;
+ }
+
+ ::SetParent(child, parent);
+}
+
+void RenderingWindowManager::UnregisterParent(HWND parent) {
+ base::AutoLock lock(lock_);
+ info_.erase(parent);
+}
+
+bool RenderingWindowManager::HasValidChildWindow(HWND parent) {
+ base::AutoLock lock(lock_);
+ auto it = info_.find(parent);
+ if (it == info_.end())
+ return false;
+ return !!it->second && ::IsWindow(it->second);
+}
+
+RenderingWindowManager::RenderingWindowManager() {}
+RenderingWindowManager::~RenderingWindowManager() {}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/win/rendering_window_manager.h b/chromium/ui/gfx/win/rendering_window_manager.h
new file mode 100644
index 00000000000..bbb74ac8d22
--- /dev/null
+++ b/chromium/ui/gfx/win/rendering_window_manager.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
+#define UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
+
+#include <windows.h>
+
+#include <map>
+
+#include "base/synchronization/lock.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace gfx {
+
+// This keeps track of whether a given HWND has a child window which the GPU
+// process renders into.
+class GFX_EXPORT RenderingWindowManager {
+ public:
+ static RenderingWindowManager* GetInstance();
+
+ void RegisterParent(HWND parent);
+ bool RegisterChild(HWND parent, HWND child_window);
+ void DoSetParentOnChild(HWND parent);
+ void UnregisterParent(HWND parent);
+ bool HasValidChildWindow(HWND parent);
+
+ private:
+ friend struct base::DefaultSingletonTraits<RenderingWindowManager>;
+
+ RenderingWindowManager();
+ ~RenderingWindowManager();
+
+ base::Lock lock_;
+ std::map<HWND, HWND> info_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderingWindowManager);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_WIN_RENDERING_WINDOW_MANAGER_H_
diff --git a/chromium/ui/gl/BUILD.gn b/chromium/ui/gl/BUILD.gn
index eb46bd29707..9d92df53943 100644
--- a/chromium/ui/gl/BUILD.gn
+++ b/chromium/ui/gl/BUILD.gn
@@ -34,8 +34,6 @@ component("gl") {
"gl_bindings_autogen_gl.h",
"gl_bindings_autogen_osmesa.cc",
"gl_bindings_autogen_osmesa.h",
- "gl_bindings_skia_in_process.cc",
- "gl_bindings_skia_in_process.h",
"gl_context.cc",
"gl_context.h",
"gl_context_android.cc",
@@ -116,7 +114,7 @@ component("gl") {
defines = [ "GL_IMPLEMENTATION" ]
include_dirs = [
- "//third_party/switfshader/include",
+ "//third_party/swiftshader/include",
"//third_party/mesa/src/include",
]
@@ -126,7 +124,6 @@ component("gl") {
deps = [
"//base/third_party/dynamic_annotations",
- "//skia",
]
public_deps = [
"//base",
@@ -191,8 +188,8 @@ component("gl") {
deps += [ "//ui/gfx/x" ]
data_deps = [
- "//third_party/angle:libEGL_ANGLE",
- "//third_party/angle:libGLESv2_ANGLE",
+ "//third_party/angle:libEGL",
+ "//third_party/angle:libGLESv2",
]
}
if (is_win) {
@@ -270,10 +267,7 @@ component("gl") {
"gl_implementation_ozone.cc",
"gl_surface_ozone.cc",
]
- deps += [
- "//ui/ozone",
- "//ui/ozone:ozone_base",
- ]
+ deps += [ "//ui/ozone" ]
}
}
@@ -328,15 +322,6 @@ source_set("test_support") {
}
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("gl_unittests_run") {
- testonly = true
- deps = [
- ":gl_unittests",
- ]
-}
-
test("gl_unittests") {
sources = [
"gl_api_unittest.cc",
diff --git a/chromium/ui/gl/OWNERS b/chromium/ui/gl/OWNERS
index f8419dc458e..1c3ad17be25 100644
--- a/chromium/ui/gl/OWNERS
+++ b/chromium/ui/gl/OWNERS
@@ -1,7 +1,7 @@
kbr@chromium.org
piman@chromium.org
sievers@chromium.org
-per-file gl_image*=reveman@chromium.org
+per-file *gl_image*=reveman@chromium.org
per-file *_ozone*=alexst@chromium.org
per-file *_ozone*=dnicoara@chromium.org
per-file *_ozone*=spang@chromium.org
diff --git a/chromium/ui/gl/angle_platform_impl.cc b/chromium/ui/gl/angle_platform_impl.cc
index d87f7610170..84c6a3c44c0 100644
--- a/chromium/ui/gl/angle_platform_impl.cc
+++ b/chromium/ui/gl/angle_platform_impl.cc
@@ -52,7 +52,8 @@ angle::Platform::TraceEventHandle ANGLEPlatformImpl::addTraceEvent(
base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp);
base::trace_event::TraceEventHandle handle =
TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
- phase, category_group_enabled, name, id, trace_event_internal::kNoId,
+ phase, category_group_enabled, name,
+ trace_event_internal::kGlobalScope, id, trace_event_internal::kNoId,
base::PlatformThread::CurrentId(), timestamp_tt, num_args, arg_names,
arg_types, arg_values, nullptr, flags);
angle::Platform::TraceEventHandle result;
diff --git a/chromium/ui/gl/generate_bindings.py b/chromium/ui/gl/generate_bindings.py
index 1e0a629863b..9af3179cbed 100755
--- a/chromium/ui/gl/generate_bindings.py
+++ b/chromium/ui/gl/generate_bindings.py
@@ -880,6 +880,9 @@ GL_FUNCTIONS = [
'names': ['glPopGroupMarkerEXT'],
'arguments': 'void', },
{ 'return_type': 'void',
+ 'names': ['glPrimitiveRestartIndex'],
+ 'arguments': 'GLuint index', },
+{ 'return_type': 'void',
'known_as': 'glProgramBinary',
'versions': [{ 'name': 'glProgramBinaryOES' },
{ 'name': 'glProgramBinary',
@@ -1660,16 +1663,16 @@ GLX_FUNCTIONS = [
{ 'return_type': 'bool',
'names': ['glXGetMscRateOML'],
'arguments':
- 'Display* dpy, GLXDrawable drawable, int32* numerator, '
- 'int32* denominator' },
+ 'Display* dpy, GLXDrawable drawable, int32_t* numerator, '
+ 'int32_t* denominator' },
{ 'return_type': 'void',
'names': ['glXGetSelectedEvent'],
'arguments': 'Display* dpy, GLXDrawable drawable, unsigned long* mask', },
{ 'return_type': 'bool',
'names': ['glXGetSyncValuesOML'],
'arguments':
- 'Display* dpy, GLXDrawable drawable, int64* ust, int64* msc, '
- 'int64* sbc' },
+ 'Display* dpy, GLXDrawable drawable, int64_t* ust, int64_t* msc, '
+ 'int64_t* sbc' },
{ 'return_type': 'XVisualInfo*',
'names': ['glXGetVisualFromFBConfig'],
'arguments': 'Display* dpy, GLXFBConfig config', },
@@ -1742,7 +1745,10 @@ FUNCTION_SETS = [
'GL/glextchromium.h',
'GLES2/gl2chromium.h',
'GLES2/gl2extchromium.h'
- ], []],
+ ], [
+ "GL_EXT_unpack_subimage",
+ ]
+ ],
[OSMESA_FUNCTIONS, 'osmesa', [], []],
[EGL_FUNCTIONS, 'egl', [
'EGL/eglext.h',
@@ -2171,6 +2177,8 @@ void Driver%s::InitializeExtensionBindings() {
if return_type == 'void':
file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' %
(function_name, log_argument_names))
+ file.write(' DCHECK(g_driver_%s.debug_fn.%sFn != nullptr);\n' %
+ (set_name.lower(), function_name))
file.write(' g_driver_%s.debug_fn.%sFn(%s);\n' %
(set_name.lower(), function_name, argument_names))
if 'logging_code' in func:
@@ -2183,6 +2191,8 @@ void Driver%s::InitializeExtensionBindings() {
else:
file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' %
(function_name, log_argument_names))
+ file.write(' DCHECK(g_driver_%s.debug_fn.%sFn != nullptr);\n' %
+ (set_name.lower(), function_name))
file.write(' %s result = g_driver_%s.debug_fn.%sFn(%s);\n' %
(return_type, set_name.lower(), function_name, argument_names))
if 'logging_code' in func:
diff --git a/chromium/ui/gl/gl.gyp b/chromium/ui/gl/gl.gyp
index afa2ad0fb5a..9dfd8ed963d 100644
--- a/chromium/ui/gl/gl.gyp
+++ b/chromium/ui/gl/gl.gyp
@@ -47,8 +47,6 @@
'gl_bindings_autogen_gl.h',
'gl_bindings_autogen_osmesa.cc',
'gl_bindings_autogen_osmesa.h',
- 'gl_bindings_skia_in_process.cc',
- 'gl_bindings_skia_in_process.h',
'gl_context.cc',
'gl_context.h',
'gl_context_android.cc',
@@ -186,10 +184,16 @@
'<(DEPTH)/build/linux/system.gyp:xcomposite',
'<(DEPTH)/build/linux/system.gyp:xext',
'<(DEPTH)/ui/events/platform/events_platform.gyp:events_platform',
- '<(DEPTH)/third_party/angle/src/angle.gyp:libEGL_ANGLE',
- '<(DEPTH)/third_party/angle/src/angle.gyp:libGLESv2_ANGLE',
'<(DEPTH)/ui/gfx/x/gfx_x11.gyp:gfx_x11',
],
+ 'copies': [{
+ 'destination': '<(PRODUCT_DIR)',
+ 'files':
+ [
+ "<(PRODUCT_DIR)/lib/libEGL.so",
+ "<(PRODUCT_DIR)/lib/libGLESv2.so",
+ ],
+ }],
}],
['OS=="win"', {
'sources': [
diff --git a/chromium/ui/gl/gl_bindings.cc b/chromium/ui/gl/gl_bindings.cc
index bb700c34740..0f47871411d 100644
--- a/chromium/ui/gl/gl_bindings.cc
+++ b/chromium/ui/gl/gl_bindings.cc
@@ -11,7 +11,7 @@
#include "ui/gl/gl_bindings.h"
#if defined(USE_X11)
-#include "ui/gfx/x/x11_types.h"
+#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
#if defined(OS_WIN)
diff --git a/chromium/ui/gl/gl_bindings_api_autogen_gl.h b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
index 94d4ed8355f..a513ed20942 100644
--- a/chromium/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
@@ -526,6 +526,7 @@ void glPixelStoreiFn(GLenum pname, GLint param) override;
void glPointParameteriFn(GLenum pname, GLint param) override;
void glPolygonOffsetFn(GLfloat factor, GLfloat units) override;
void glPopGroupMarkerEXTFn(void) override;
+void glPrimitiveRestartIndexFn(GLuint index) override;
void glProgramBinaryFn(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
diff --git a/chromium/ui/gl/gl_bindings_autogen_egl.cc b/chromium/ui/gl/gl_bindings_autogen_egl.cc
index 2bb0bfd8e96..c2461d8ed9b 100644
--- a/chromium/ui/gl/gl_bindings_autogen_egl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_egl.cc
@@ -203,6 +203,7 @@ extern "C" {
static EGLBoolean GL_BINDING_CALL Debug_eglBindAPI(EGLenum api) {
GL_SERVICE_LOG("eglBindAPI"
<< "(" << api << ")");
+ DCHECK(g_driver_egl.debug_fn.eglBindAPIFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglBindAPIFn(api);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -213,6 +214,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglBindTexImage(EGLDisplay dpy,
EGLint buffer) {
GL_SERVICE_LOG("eglBindTexImage"
<< "(" << dpy << ", " << surface << ", " << buffer << ")");
+ DCHECK(g_driver_egl.debug_fn.eglBindTexImageFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglBindTexImageFn(dpy, surface, buffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -230,6 +232,7 @@ Debug_eglChooseConfig(EGLDisplay dpy,
<< ", " << static_cast<const void*>(configs) << ", "
<< config_size << ", " << static_cast<const void*>(num_config)
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglChooseConfigFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglChooseConfigFn(
dpy, attrib_list, configs, config_size, num_config);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -243,6 +246,7 @@ static EGLint GL_BINDING_CALL Debug_eglClientWaitSyncKHR(EGLDisplay dpy,
GL_SERVICE_LOG("eglClientWaitSyncKHR"
<< "(" << dpy << ", " << sync << ", " << flags << ", "
<< timeout << ")");
+ DCHECK(g_driver_egl.debug_fn.eglClientWaitSyncKHRFn != nullptr);
EGLint result =
g_driver_egl.debug_fn.eglClientWaitSyncKHRFn(dpy, sync, flags, timeout);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -255,6 +259,7 @@ Debug_eglCopyBuffers(EGLDisplay dpy,
EGLNativePixmapType target) {
GL_SERVICE_LOG("eglCopyBuffers"
<< "(" << dpy << ", " << surface << ", " << target << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCopyBuffersFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglCopyBuffersFn(dpy, surface, target);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -269,6 +274,7 @@ Debug_eglCreateContext(EGLDisplay dpy,
GL_SERVICE_LOG("eglCreateContext"
<< "(" << dpy << ", " << config << ", " << share_context
<< ", " << static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreateContextFn != nullptr);
EGLContext result = g_driver_egl.debug_fn.eglCreateContextFn(
dpy, config, share_context, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -285,6 +291,7 @@ Debug_eglCreateImageKHR(EGLDisplay dpy,
<< "(" << dpy << ", " << ctx << ", " << target << ", "
<< buffer << ", " << static_cast<const void*>(attrib_list)
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreateImageKHRFn != nullptr);
EGLImageKHR result = g_driver_egl.debug_fn.eglCreateImageKHRFn(
dpy, ctx, target, buffer, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -301,6 +308,7 @@ Debug_eglCreatePbufferFromClientBuffer(EGLDisplay dpy,
<< "(" << dpy << ", " << buftype << ", "
<< static_cast<const void*>(buffer) << ", " << config << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreatePbufferFromClientBufferFn != nullptr);
EGLSurface result = g_driver_egl.debug_fn.eglCreatePbufferFromClientBufferFn(
dpy, buftype, buffer, config, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -314,6 +322,7 @@ Debug_eglCreatePbufferSurface(EGLDisplay dpy,
GL_SERVICE_LOG("eglCreatePbufferSurface"
<< "(" << dpy << ", " << config << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreatePbufferSurfaceFn != nullptr);
EGLSurface result =
g_driver_egl.debug_fn.eglCreatePbufferSurfaceFn(dpy, config, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -328,6 +337,7 @@ Debug_eglCreatePixmapSurface(EGLDisplay dpy,
GL_SERVICE_LOG("eglCreatePixmapSurface"
<< "(" << dpy << ", " << config << ", " << pixmap << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreatePixmapSurfaceFn != nullptr);
EGLSurface result = g_driver_egl.debug_fn.eglCreatePixmapSurfaceFn(
dpy, config, pixmap, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -341,6 +351,7 @@ Debug_eglCreateSyncKHR(EGLDisplay dpy,
GL_SERVICE_LOG("eglCreateSyncKHR"
<< "(" << dpy << ", " << type << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreateSyncKHRFn != nullptr);
EGLSyncKHR result =
g_driver_egl.debug_fn.eglCreateSyncKHRFn(dpy, type, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -355,6 +366,7 @@ Debug_eglCreateWindowSurface(EGLDisplay dpy,
GL_SERVICE_LOG("eglCreateWindowSurface"
<< "(" << dpy << ", " << config << ", " << win << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglCreateWindowSurfaceFn != nullptr);
EGLSurface result = g_driver_egl.debug_fn.eglCreateWindowSurfaceFn(
dpy, config, win, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -365,6 +377,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglDestroyContext(EGLDisplay dpy,
EGLContext ctx) {
GL_SERVICE_LOG("eglDestroyContext"
<< "(" << dpy << ", " << ctx << ")");
+ DCHECK(g_driver_egl.debug_fn.eglDestroyContextFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglDestroyContextFn(dpy, ctx);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -374,6 +387,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglDestroyImageKHR(EGLDisplay dpy,
EGLImageKHR image) {
GL_SERVICE_LOG("eglDestroyImageKHR"
<< "(" << dpy << ", " << image << ")");
+ DCHECK(g_driver_egl.debug_fn.eglDestroyImageKHRFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglDestroyImageKHRFn(dpy, image);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -383,6 +397,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglDestroySurface(EGLDisplay dpy,
EGLSurface surface) {
GL_SERVICE_LOG("eglDestroySurface"
<< "(" << dpy << ", " << surface << ")");
+ DCHECK(g_driver_egl.debug_fn.eglDestroySurfaceFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglDestroySurfaceFn(dpy, surface);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -392,6 +407,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglDestroySyncKHR(EGLDisplay dpy,
EGLSyncKHR sync) {
GL_SERVICE_LOG("eglDestroySyncKHR"
<< "(" << dpy << ", " << sync << ")");
+ DCHECK(g_driver_egl.debug_fn.eglDestroySyncKHRFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglDestroySyncKHRFn(dpy, sync);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -404,6 +420,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglGetConfigAttrib(EGLDisplay dpy,
GL_SERVICE_LOG("eglGetConfigAttrib"
<< "(" << dpy << ", " << config << ", " << attribute << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetConfigAttribFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglGetConfigAttribFn(dpy, config, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -418,6 +435,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglGetConfigs(EGLDisplay dpy,
<< "(" << dpy << ", " << static_cast<const void*>(configs)
<< ", " << config_size << ", "
<< static_cast<const void*>(num_config) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetConfigsFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglGetConfigsFn(
dpy, configs, config_size, num_config);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -428,6 +446,7 @@ static EGLContext GL_BINDING_CALL Debug_eglGetCurrentContext(void) {
GL_SERVICE_LOG("eglGetCurrentContext"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetCurrentContextFn != nullptr);
EGLContext result = g_driver_egl.debug_fn.eglGetCurrentContextFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -437,6 +456,7 @@ static EGLDisplay GL_BINDING_CALL Debug_eglGetCurrentDisplay(void) {
GL_SERVICE_LOG("eglGetCurrentDisplay"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetCurrentDisplayFn != nullptr);
EGLDisplay result = g_driver_egl.debug_fn.eglGetCurrentDisplayFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -445,6 +465,7 @@ static EGLDisplay GL_BINDING_CALL Debug_eglGetCurrentDisplay(void) {
static EGLSurface GL_BINDING_CALL Debug_eglGetCurrentSurface(EGLint readdraw) {
GL_SERVICE_LOG("eglGetCurrentSurface"
<< "(" << readdraw << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetCurrentSurfaceFn != nullptr);
EGLSurface result = g_driver_egl.debug_fn.eglGetCurrentSurfaceFn(readdraw);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -454,6 +475,7 @@ static EGLDisplay GL_BINDING_CALL
Debug_eglGetDisplay(EGLNativeDisplayType display_id) {
GL_SERVICE_LOG("eglGetDisplay"
<< "(" << display_id << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetDisplayFn != nullptr);
EGLDisplay result = g_driver_egl.debug_fn.eglGetDisplayFn(display_id);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -463,6 +485,7 @@ static EGLint GL_BINDING_CALL Debug_eglGetError(void) {
GL_SERVICE_LOG("eglGetError"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetErrorFn != nullptr);
EGLint result = g_driver_egl.debug_fn.eglGetErrorFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -476,6 +499,7 @@ Debug_eglGetPlatformDisplayEXT(EGLenum platform,
<< "(" << platform << ", "
<< static_cast<const void*>(native_display) << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetPlatformDisplayEXTFn != nullptr);
EGLDisplay result = g_driver_egl.debug_fn.eglGetPlatformDisplayEXTFn(
platform, native_display, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -486,6 +510,7 @@ static __eglMustCastToProperFunctionPointerType GL_BINDING_CALL
Debug_eglGetProcAddress(const char* procname) {
GL_SERVICE_LOG("eglGetProcAddress"
<< "(" << procname << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetProcAddressFn != nullptr);
__eglMustCastToProperFunctionPointerType result =
g_driver_egl.debug_fn.eglGetProcAddressFn(procname);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -499,6 +524,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglGetSyncAttribKHR(EGLDisplay dpy,
GL_SERVICE_LOG("eglGetSyncAttribKHR"
<< "(" << dpy << ", " << sync << ", " << attribute << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetSyncAttribKHRFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglGetSyncAttribKHRFn(dpy, sync, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -516,6 +542,7 @@ Debug_eglGetSyncValuesCHROMIUM(EGLDisplay dpy,
<< static_cast<const void*>(ust) << ", "
<< static_cast<const void*>(msc) << ", "
<< static_cast<const void*>(sbc) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglGetSyncValuesCHROMIUMFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglGetSyncValuesCHROMIUMFn(
dpy, surface, ust, msc, sbc);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -528,6 +555,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglInitialize(EGLDisplay dpy,
GL_SERVICE_LOG("eglInitialize"
<< "(" << dpy << ", " << static_cast<const void*>(major)
<< ", " << static_cast<const void*>(minor) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglInitializeFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglInitializeFn(dpy, major, minor);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -540,6 +568,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglMakeCurrent(EGLDisplay dpy,
GL_SERVICE_LOG("eglMakeCurrent"
<< "(" << dpy << ", " << draw << ", " << read << ", " << ctx
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglMakeCurrentFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglMakeCurrentFn(dpy, draw, read, ctx);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -555,6 +584,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglPostSubBufferNV(EGLDisplay dpy,
GL_SERVICE_LOG("eglPostSubBufferNV"
<< "(" << dpy << ", " << surface << ", " << x << ", " << y
<< ", " << width << ", " << height << ")");
+ DCHECK(g_driver_egl.debug_fn.eglPostSubBufferNVFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglPostSubBufferNVFn(
dpy, surface, x, y, width, height);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -565,6 +595,7 @@ static EGLenum GL_BINDING_CALL Debug_eglQueryAPI(void) {
GL_SERVICE_LOG("eglQueryAPI"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglQueryAPIFn != nullptr);
EGLenum result = g_driver_egl.debug_fn.eglQueryAPIFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -577,6 +608,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglQueryContext(EGLDisplay dpy,
GL_SERVICE_LOG("eglQueryContext"
<< "(" << dpy << ", " << ctx << ", " << attribute << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglQueryContextFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglQueryContextFn(dpy, ctx, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -587,6 +619,7 @@ static const char* GL_BINDING_CALL Debug_eglQueryString(EGLDisplay dpy,
EGLint name) {
GL_SERVICE_LOG("eglQueryString"
<< "(" << dpy << ", " << name << ")");
+ DCHECK(g_driver_egl.debug_fn.eglQueryStringFn != nullptr);
const char* result = g_driver_egl.debug_fn.eglQueryStringFn(dpy, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -599,6 +632,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglQuerySurface(EGLDisplay dpy,
GL_SERVICE_LOG("eglQuerySurface"
<< "(" << dpy << ", " << surface << ", " << attribute << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_egl.debug_fn.eglQuerySurfaceFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglQuerySurfaceFn(dpy, surface, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -613,6 +647,7 @@ Debug_eglQuerySurfacePointerANGLE(EGLDisplay dpy,
GL_SERVICE_LOG("eglQuerySurfacePointerANGLE"
<< "(" << dpy << ", " << surface << ", " << attribute << ", "
<< value << ")");
+ DCHECK(g_driver_egl.debug_fn.eglQuerySurfacePointerANGLEFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglQuerySurfacePointerANGLEFn(
dpy, surface, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -624,6 +659,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglReleaseTexImage(EGLDisplay dpy,
EGLint buffer) {
GL_SERVICE_LOG("eglReleaseTexImage"
<< "(" << dpy << ", " << surface << ", " << buffer << ")");
+ DCHECK(g_driver_egl.debug_fn.eglReleaseTexImageFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglReleaseTexImageFn(dpy, surface, buffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -634,6 +670,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglReleaseThread(void) {
GL_SERVICE_LOG("eglReleaseThread"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglReleaseThreadFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglReleaseThreadFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -646,6 +683,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglSurfaceAttrib(EGLDisplay dpy,
GL_SERVICE_LOG("eglSurfaceAttrib"
<< "(" << dpy << ", " << surface << ", " << attribute << ", "
<< value << ")");
+ DCHECK(g_driver_egl.debug_fn.eglSurfaceAttribFn != nullptr);
EGLBoolean result =
g_driver_egl.debug_fn.eglSurfaceAttribFn(dpy, surface, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -656,6 +694,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglSwapBuffers(EGLDisplay dpy,
EGLSurface surface) {
GL_SERVICE_LOG("eglSwapBuffers"
<< "(" << dpy << ", " << surface << ")");
+ DCHECK(g_driver_egl.debug_fn.eglSwapBuffersFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglSwapBuffersFn(dpy, surface);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -665,6 +704,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglSwapInterval(EGLDisplay dpy,
EGLint interval) {
GL_SERVICE_LOG("eglSwapInterval"
<< "(" << dpy << ", " << interval << ")");
+ DCHECK(g_driver_egl.debug_fn.eglSwapIntervalFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglSwapIntervalFn(dpy, interval);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -673,6 +713,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglSwapInterval(EGLDisplay dpy,
static EGLBoolean GL_BINDING_CALL Debug_eglTerminate(EGLDisplay dpy) {
GL_SERVICE_LOG("eglTerminate"
<< "(" << dpy << ")");
+ DCHECK(g_driver_egl.debug_fn.eglTerminateFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglTerminateFn(dpy);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -682,6 +723,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglWaitClient(void) {
GL_SERVICE_LOG("eglWaitClient"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglWaitClientFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglWaitClientFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -691,6 +733,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglWaitGL(void) {
GL_SERVICE_LOG("eglWaitGL"
<< "("
<< ")");
+ DCHECK(g_driver_egl.debug_fn.eglWaitGLFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglWaitGLFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -699,6 +742,7 @@ static EGLBoolean GL_BINDING_CALL Debug_eglWaitGL(void) {
static EGLBoolean GL_BINDING_CALL Debug_eglWaitNative(EGLint engine) {
GL_SERVICE_LOG("eglWaitNative"
<< "(" << engine << ")");
+ DCHECK(g_driver_egl.debug_fn.eglWaitNativeFn != nullptr);
EGLBoolean result = g_driver_egl.debug_fn.eglWaitNativeFn(engine);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -709,6 +753,7 @@ static EGLint GL_BINDING_CALL Debug_eglWaitSyncKHR(EGLDisplay dpy,
EGLint flags) {
GL_SERVICE_LOG("eglWaitSyncKHR"
<< "(" << dpy << ", " << sync << ", " << flags << ")");
+ DCHECK(g_driver_egl.debug_fn.eglWaitSyncKHRFn != nullptr);
EGLint result = g_driver_egl.debug_fn.eglWaitSyncKHRFn(dpy, sync, flags);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.cc b/chromium/ui/gl/gl_bindings_autogen_gl.cc
index 8cc565051af..c768ae75e35 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.cc
@@ -311,6 +311,7 @@ void DriverGL::InitializeStaticBindings() {
fn.glPolygonOffsetFn = reinterpret_cast<glPolygonOffsetProc>(
GetGLProcAddress("glPolygonOffset"));
fn.glPopGroupMarkerEXTFn = 0;
+ fn.glPrimitiveRestartIndexFn = 0;
fn.glProgramBinaryFn = 0;
fn.glProgramParameteriFn = 0;
fn.glProgramPathFragmentInputGenNVFn = 0;
@@ -552,6 +553,8 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
extensions.find("GL_EXT_texture_storage ") != std::string::npos;
ext.b_GL_EXT_timer_query =
extensions.find("GL_EXT_timer_query ") != std::string::npos;
+ ext.b_GL_EXT_unpack_subimage =
+ extensions.find("GL_EXT_unpack_subimage ") != std::string::npos;
ext.b_GL_IMG_multisampled_render_to_texture =
extensions.find("GL_IMG_multisampled_render_to_texture ") !=
std::string::npos;
@@ -1632,6 +1635,13 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) {
GetGLProcAddress("glPopGroupMarkerEXT"));
}
+ debug_fn.glPrimitiveRestartIndexFn = 0;
+ if (ver->IsAtLeastGL(3u, 1u)) {
+ fn.glPrimitiveRestartIndexFn =
+ reinterpret_cast<glPrimitiveRestartIndexProc>(
+ GetGLProcAddress("glPrimitiveRestartIndex"));
+ }
+
debug_fn.glProgramBinaryFn = 0;
if (ver->IsAtLeastGL(4u, 1u) || ver->IsAtLeastGLES(3u, 0u) ||
ext.b_GL_ARB_get_program_binary) {
@@ -2034,6 +2044,7 @@ extern "C" {
static void GL_BINDING_CALL Debug_glActiveTexture(GLenum texture) {
GL_SERVICE_LOG("glActiveTexture"
<< "(" << GLEnums::GetStringEnum(texture) << ")");
+ DCHECK(g_driver_gl.debug_fn.glActiveTextureFn != nullptr);
g_driver_gl.debug_fn.glActiveTextureFn(texture);
}
@@ -2041,6 +2052,8 @@ static void GL_BINDING_CALL Debug_glApplyFramebufferAttachmentCMAAINTEL(void) {
GL_SERVICE_LOG("glApplyFramebufferAttachmentCMAAINTEL"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glApplyFramebufferAttachmentCMAAINTELFn !=
+ nullptr);
g_driver_gl.debug_fn.glApplyFramebufferAttachmentCMAAINTELFn();
}
@@ -2048,12 +2061,14 @@ static void GL_BINDING_CALL Debug_glAttachShader(GLuint program,
GLuint shader) {
GL_SERVICE_LOG("glAttachShader"
<< "(" << program << ", " << shader << ")");
+ DCHECK(g_driver_gl.debug_fn.glAttachShaderFn != nullptr);
g_driver_gl.debug_fn.glAttachShaderFn(program, shader);
}
static void GL_BINDING_CALL Debug_glBeginQuery(GLenum target, GLuint id) {
GL_SERVICE_LOG("glBeginQuery"
<< "(" << GLEnums::GetStringEnum(target) << ", " << id << ")");
+ DCHECK(g_driver_gl.debug_fn.glBeginQueryFn != nullptr);
g_driver_gl.debug_fn.glBeginQueryFn(target, id);
}
@@ -2061,6 +2076,7 @@ static void GL_BINDING_CALL
Debug_glBeginTransformFeedback(GLenum primitiveMode) {
GL_SERVICE_LOG("glBeginTransformFeedback"
<< "(" << GLEnums::GetStringEnum(primitiveMode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBeginTransformFeedbackFn != nullptr);
g_driver_gl.debug_fn.glBeginTransformFeedbackFn(primitiveMode);
}
@@ -2069,6 +2085,7 @@ static void GL_BINDING_CALL Debug_glBindAttribLocation(GLuint program,
const char* name) {
GL_SERVICE_LOG("glBindAttribLocation"
<< "(" << program << ", " << index << ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindAttribLocationFn != nullptr);
g_driver_gl.debug_fn.glBindAttribLocationFn(program, index, name);
}
@@ -2076,6 +2093,7 @@ static void GL_BINDING_CALL Debug_glBindBuffer(GLenum target, GLuint buffer) {
GL_SERVICE_LOG("glBindBuffer"
<< "(" << GLEnums::GetStringEnum(target) << ", " << buffer
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBindBufferFn != nullptr);
g_driver_gl.debug_fn.glBindBufferFn(target, buffer);
}
@@ -2085,6 +2103,7 @@ static void GL_BINDING_CALL Debug_glBindBufferBase(GLenum target,
GL_SERVICE_LOG("glBindBufferBase"
<< "(" << GLEnums::GetStringEnum(target) << ", " << index
<< ", " << buffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindBufferBaseFn != nullptr);
g_driver_gl.debug_fn.glBindBufferBaseFn(target, index, buffer);
}
@@ -2096,6 +2115,7 @@ static void GL_BINDING_CALL Debug_glBindBufferRange(GLenum target,
GL_SERVICE_LOG("glBindBufferRange"
<< "(" << GLEnums::GetStringEnum(target) << ", " << index
<< ", " << buffer << ", " << offset << ", " << size << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindBufferRangeFn != nullptr);
g_driver_gl.debug_fn.glBindBufferRangeFn(target, index, buffer, offset, size);
}
@@ -2105,6 +2125,7 @@ static void GL_BINDING_CALL Debug_glBindFragDataLocation(GLuint program,
GL_SERVICE_LOG("glBindFragDataLocation"
<< "(" << program << ", " << colorNumber << ", " << name
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBindFragDataLocationFn != nullptr);
g_driver_gl.debug_fn.glBindFragDataLocationFn(program, colorNumber, name);
}
@@ -2116,6 +2137,7 @@ Debug_glBindFragDataLocationIndexed(GLuint program,
GL_SERVICE_LOG("glBindFragDataLocationIndexed"
<< "(" << program << ", " << colorNumber << ", " << index
<< ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindFragDataLocationIndexedFn != nullptr);
g_driver_gl.debug_fn.glBindFragDataLocationIndexedFn(program, colorNumber,
index, name);
}
@@ -2125,6 +2147,7 @@ static void GL_BINDING_CALL Debug_glBindFramebufferEXT(GLenum target,
GL_SERVICE_LOG("glBindFramebufferEXT"
<< "(" << GLEnums::GetStringEnum(target) << ", " << framebuffer
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBindFramebufferEXTFn != nullptr);
g_driver_gl.debug_fn.glBindFramebufferEXTFn(target, framebuffer);
}
@@ -2139,6 +2162,7 @@ static void GL_BINDING_CALL Debug_glBindImageTextureEXT(GLuint index,
<< "(" << index << ", " << texture << ", " << level << ", "
<< GLEnums::GetStringBool(layered) << ", " << layer << ", "
<< GLEnums::GetStringEnum(access) << ", " << format << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindImageTextureEXTFn != nullptr);
g_driver_gl.debug_fn.glBindImageTextureEXTFn(index, texture, level, layered,
layer, access, format);
}
@@ -2148,12 +2172,14 @@ static void GL_BINDING_CALL Debug_glBindRenderbufferEXT(GLenum target,
GL_SERVICE_LOG("glBindRenderbufferEXT"
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< renderbuffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindRenderbufferEXTFn != nullptr);
g_driver_gl.debug_fn.glBindRenderbufferEXTFn(target, renderbuffer);
}
static void GL_BINDING_CALL Debug_glBindSampler(GLuint unit, GLuint sampler) {
GL_SERVICE_LOG("glBindSampler"
<< "(" << unit << ", " << sampler << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindSamplerFn != nullptr);
g_driver_gl.debug_fn.glBindSamplerFn(unit, sampler);
}
@@ -2161,6 +2187,7 @@ static void GL_BINDING_CALL Debug_glBindTexture(GLenum target, GLuint texture) {
GL_SERVICE_LOG("glBindTexture"
<< "(" << GLEnums::GetStringEnum(target) << ", " << texture
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBindTextureFn != nullptr);
g_driver_gl.debug_fn.glBindTextureFn(target, texture);
}
@@ -2168,12 +2195,14 @@ static void GL_BINDING_CALL Debug_glBindTransformFeedback(GLenum target,
GLuint id) {
GL_SERVICE_LOG("glBindTransformFeedback"
<< "(" << GLEnums::GetStringEnum(target) << ", " << id << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindTransformFeedbackFn != nullptr);
g_driver_gl.debug_fn.glBindTransformFeedbackFn(target, id);
}
static void GL_BINDING_CALL Debug_glBindVertexArrayOES(GLuint array) {
GL_SERVICE_LOG("glBindVertexArrayOES"
<< "(" << array << ")");
+ DCHECK(g_driver_gl.debug_fn.glBindVertexArrayOESFn != nullptr);
g_driver_gl.debug_fn.glBindVertexArrayOESFn(array);
}
@@ -2181,6 +2210,7 @@ static void GL_BINDING_CALL Debug_glBlendBarrierKHR(void) {
GL_SERVICE_LOG("glBlendBarrierKHR"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendBarrierKHRFn != nullptr);
g_driver_gl.debug_fn.glBlendBarrierKHRFn();
}
@@ -2191,12 +2221,14 @@ static void GL_BINDING_CALL Debug_glBlendColor(GLclampf red,
GL_SERVICE_LOG("glBlendColor"
<< "(" << red << ", " << green << ", " << blue << ", " << alpha
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendColorFn != nullptr);
g_driver_gl.debug_fn.glBlendColorFn(red, green, blue, alpha);
}
static void GL_BINDING_CALL Debug_glBlendEquation(GLenum mode) {
GL_SERVICE_LOG("glBlendEquation"
<< "(" << GLEnums::GetStringEnum(mode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendEquationFn != nullptr);
g_driver_gl.debug_fn.glBlendEquationFn(mode);
}
@@ -2205,6 +2237,7 @@ static void GL_BINDING_CALL Debug_glBlendEquationSeparate(GLenum modeRGB,
GL_SERVICE_LOG("glBlendEquationSeparate"
<< "(" << GLEnums::GetStringEnum(modeRGB) << ", "
<< GLEnums::GetStringEnum(modeAlpha) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendEquationSeparateFn != nullptr);
g_driver_gl.debug_fn.glBlendEquationSeparateFn(modeRGB, modeAlpha);
}
@@ -2212,6 +2245,7 @@ static void GL_BINDING_CALL Debug_glBlendFunc(GLenum sfactor, GLenum dfactor) {
GL_SERVICE_LOG("glBlendFunc"
<< "(" << GLEnums::GetStringEnum(sfactor) << ", "
<< GLEnums::GetStringEnum(dfactor) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendFuncFn != nullptr);
g_driver_gl.debug_fn.glBlendFuncFn(sfactor, dfactor);
}
@@ -2224,6 +2258,7 @@ static void GL_BINDING_CALL Debug_glBlendFuncSeparate(GLenum srcRGB,
<< GLEnums::GetStringEnum(dstRGB) << ", "
<< GLEnums::GetStringEnum(srcAlpha) << ", "
<< GLEnums::GetStringEnum(dstAlpha) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlendFuncSeparateFn != nullptr);
g_driver_gl.debug_fn.glBlendFuncSeparateFn(srcRGB, dstRGB, srcAlpha,
dstAlpha);
}
@@ -2243,6 +2278,7 @@ static void GL_BINDING_CALL Debug_glBlitFramebuffer(GLint srcX0,
<< srcY1 << ", " << dstX0 << ", " << dstY0 << ", " << dstX1
<< ", " << dstY1 << ", " << mask << ", "
<< GLEnums::GetStringEnum(filter) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlitFramebufferFn != nullptr);
g_driver_gl.debug_fn.glBlitFramebufferFn(srcX0, srcY0, srcX1, srcY1, dstX0,
dstY0, dstX1, dstY1, mask, filter);
}
@@ -2262,6 +2298,7 @@ static void GL_BINDING_CALL Debug_glBlitFramebufferANGLE(GLint srcX0,
<< srcY1 << ", " << dstX0 << ", " << dstY0 << ", " << dstX1
<< ", " << dstY1 << ", " << mask << ", "
<< GLEnums::GetStringEnum(filter) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlitFramebufferANGLEFn != nullptr);
g_driver_gl.debug_fn.glBlitFramebufferANGLEFn(
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@@ -2281,6 +2318,7 @@ static void GL_BINDING_CALL Debug_glBlitFramebufferEXT(GLint srcX0,
<< srcY1 << ", " << dstX0 << ", " << dstY0 << ", " << dstX1
<< ", " << dstY1 << ", " << mask << ", "
<< GLEnums::GetStringEnum(filter) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBlitFramebufferEXTFn != nullptr);
g_driver_gl.debug_fn.glBlitFramebufferEXTFn(
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
@@ -2293,6 +2331,7 @@ static void GL_BINDING_CALL Debug_glBufferData(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << size
<< ", " << static_cast<const void*>(data) << ", "
<< GLEnums::GetStringEnum(usage) << ")");
+ DCHECK(g_driver_gl.debug_fn.glBufferDataFn != nullptr);
g_driver_gl.debug_fn.glBufferDataFn(target, size, data, usage);
}
@@ -2304,12 +2343,14 @@ static void GL_BINDING_CALL Debug_glBufferSubData(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << offset
<< ", " << size << ", " << static_cast<const void*>(data)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glBufferSubDataFn != nullptr);
g_driver_gl.debug_fn.glBufferSubDataFn(target, offset, size, data);
}
static GLenum GL_BINDING_CALL Debug_glCheckFramebufferStatusEXT(GLenum target) {
GL_SERVICE_LOG("glCheckFramebufferStatusEXT"
<< "(" << GLEnums::GetStringEnum(target) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCheckFramebufferStatusEXTFn != nullptr);
GLenum result = g_driver_gl.debug_fn.glCheckFramebufferStatusEXTFn(target);
GL_SERVICE_LOG("GL_RESULT: " << GLEnums::GetStringEnum(result));
@@ -2320,6 +2361,7 @@ static GLenum GL_BINDING_CALL Debug_glCheckFramebufferStatusEXT(GLenum target) {
static void GL_BINDING_CALL Debug_glClear(GLbitfield mask) {
GL_SERVICE_LOG("glClear"
<< "(" << mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearFn != nullptr);
g_driver_gl.debug_fn.glClearFn(mask);
}
@@ -2330,6 +2372,7 @@ static void GL_BINDING_CALL Debug_glClearBufferfi(GLenum buffer,
GL_SERVICE_LOG("glClearBufferfi"
<< "(" << GLEnums::GetStringEnum(buffer) << ", " << drawbuffer
<< ", " << depth << ", " << stencil << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearBufferfiFn != nullptr);
g_driver_gl.debug_fn.glClearBufferfiFn(buffer, drawbuffer, depth, stencil);
}
@@ -2339,6 +2382,7 @@ static void GL_BINDING_CALL Debug_glClearBufferfv(GLenum buffer,
GL_SERVICE_LOG("glClearBufferfv"
<< "(" << GLEnums::GetStringEnum(buffer) << ", " << drawbuffer
<< ", " << static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearBufferfvFn != nullptr);
g_driver_gl.debug_fn.glClearBufferfvFn(buffer, drawbuffer, value);
}
@@ -2348,6 +2392,7 @@ static void GL_BINDING_CALL Debug_glClearBufferiv(GLenum buffer,
GL_SERVICE_LOG("glClearBufferiv"
<< "(" << GLEnums::GetStringEnum(buffer) << ", " << drawbuffer
<< ", " << static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearBufferivFn != nullptr);
g_driver_gl.debug_fn.glClearBufferivFn(buffer, drawbuffer, value);
}
@@ -2357,6 +2402,7 @@ static void GL_BINDING_CALL Debug_glClearBufferuiv(GLenum buffer,
GL_SERVICE_LOG("glClearBufferuiv"
<< "(" << GLEnums::GetStringEnum(buffer) << ", " << drawbuffer
<< ", " << static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearBufferuivFn != nullptr);
g_driver_gl.debug_fn.glClearBufferuivFn(buffer, drawbuffer, value);
}
@@ -2367,24 +2413,28 @@ static void GL_BINDING_CALL Debug_glClearColor(GLclampf red,
GL_SERVICE_LOG("glClearColor"
<< "(" << red << ", " << green << ", " << blue << ", " << alpha
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glClearColorFn != nullptr);
g_driver_gl.debug_fn.glClearColorFn(red, green, blue, alpha);
}
static void GL_BINDING_CALL Debug_glClearDepth(GLclampd depth) {
GL_SERVICE_LOG("glClearDepth"
<< "(" << depth << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearDepthFn != nullptr);
g_driver_gl.debug_fn.glClearDepthFn(depth);
}
static void GL_BINDING_CALL Debug_glClearDepthf(GLclampf depth) {
GL_SERVICE_LOG("glClearDepthf"
<< "(" << depth << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearDepthfFn != nullptr);
g_driver_gl.debug_fn.glClearDepthfFn(depth);
}
static void GL_BINDING_CALL Debug_glClearStencil(GLint s) {
GL_SERVICE_LOG("glClearStencil"
<< "(" << s << ")");
+ DCHECK(g_driver_gl.debug_fn.glClearStencilFn != nullptr);
g_driver_gl.debug_fn.glClearStencilFn(s);
}
@@ -2393,6 +2443,7 @@ static GLenum GL_BINDING_CALL Debug_glClientWaitSync(GLsync sync,
GLuint64 timeout) {
GL_SERVICE_LOG("glClientWaitSync"
<< "(" << sync << ", " << flags << ", " << timeout << ")");
+ DCHECK(g_driver_gl.debug_fn.glClientWaitSyncFn != nullptr);
GLenum result = g_driver_gl.debug_fn.glClientWaitSyncFn(sync, flags, timeout);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -2407,12 +2458,14 @@ static void GL_BINDING_CALL Debug_glColorMask(GLboolean red,
<< GLEnums::GetStringBool(green) << ", "
<< GLEnums::GetStringBool(blue) << ", "
<< GLEnums::GetStringBool(alpha) << ")");
+ DCHECK(g_driver_gl.debug_fn.glColorMaskFn != nullptr);
g_driver_gl.debug_fn.glColorMaskFn(red, green, blue, alpha);
}
static void GL_BINDING_CALL Debug_glCompileShader(GLuint shader) {
GL_SERVICE_LOG("glCompileShader"
<< "(" << shader << ")");
+ DCHECK(g_driver_gl.debug_fn.glCompileShaderFn != nullptr);
g_driver_gl.debug_fn.glCompileShaderFn(shader);
}
@@ -2429,6 +2482,7 @@ static void GL_BINDING_CALL Debug_glCompressedTexImage2D(GLenum target,
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ", " << border << ", "
<< imageSize << ", " << static_cast<const void*>(data) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCompressedTexImage2DFn != nullptr);
g_driver_gl.debug_fn.glCompressedTexImage2DFn(
target, level, internalformat, width, height, border, imageSize, data);
}
@@ -2448,6 +2502,7 @@ static void GL_BINDING_CALL Debug_glCompressedTexImage3D(GLenum target,
<< width << ", " << height << ", " << depth << ", " << border
<< ", " << imageSize << ", " << static_cast<const void*>(data)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glCompressedTexImage3DFn != nullptr);
g_driver_gl.debug_fn.glCompressedTexImage3DFn(target, level, internalformat,
width, height, depth, border,
imageSize, data);
@@ -2467,6 +2522,7 @@ static void GL_BINDING_CALL Debug_glCompressedTexSubImage2D(GLenum target,
<< ", " << xoffset << ", " << yoffset << ", " << width << ", "
<< height << ", " << GLEnums::GetStringEnum(format) << ", "
<< imageSize << ", " << static_cast<const void*>(data) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCompressedTexSubImage2DFn != nullptr);
g_driver_gl.debug_fn.glCompressedTexSubImage2DFn(
target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
@@ -2488,6 +2544,7 @@ static void GL_BINDING_CALL Debug_glCompressedTexSubImage3D(GLenum target,
<< ", " << width << ", " << height << ", " << depth << ", "
<< GLEnums::GetStringEnum(format) << ", " << imageSize << ", "
<< static_cast<const void*>(data) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCompressedTexSubImage3DFn != nullptr);
g_driver_gl.debug_fn.glCompressedTexSubImage3DFn(
target, level, xoffset, yoffset, zoffset, width, height, depth, format,
imageSize, data);
@@ -2502,6 +2559,7 @@ static void GL_BINDING_CALL Debug_glCopyBufferSubData(GLenum readTarget,
<< "(" << GLEnums::GetStringEnum(readTarget) << ", "
<< GLEnums::GetStringEnum(writeTarget) << ", " << readOffset
<< ", " << writeOffset << ", " << size << ")");
+ DCHECK(g_driver_gl.debug_fn.glCopyBufferSubDataFn != nullptr);
g_driver_gl.debug_fn.glCopyBufferSubDataFn(readTarget, writeTarget,
readOffset, writeOffset, size);
}
@@ -2519,6 +2577,7 @@ static void GL_BINDING_CALL Debug_glCopyTexImage2D(GLenum target,
<< ", " << GLEnums::GetStringEnum(internalformat) << ", " << x
<< ", " << y << ", " << width << ", " << height << ", "
<< border << ")");
+ DCHECK(g_driver_gl.debug_fn.glCopyTexImage2DFn != nullptr);
g_driver_gl.debug_fn.glCopyTexImage2DFn(target, level, internalformat, x, y,
width, height, border);
}
@@ -2535,6 +2594,7 @@ static void GL_BINDING_CALL Debug_glCopyTexSubImage2D(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << level
<< ", " << xoffset << ", " << yoffset << ", " << x << ", " << y
<< ", " << width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glCopyTexSubImage2DFn != nullptr);
g_driver_gl.debug_fn.glCopyTexSubImage2DFn(target, level, xoffset, yoffset, x,
y, width, height);
}
@@ -2553,6 +2613,7 @@ static void GL_BINDING_CALL Debug_glCopyTexSubImage3D(GLenum target,
<< ", " << xoffset << ", " << yoffset << ", " << zoffset
<< ", " << x << ", " << y << ", " << width << ", " << height
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glCopyTexSubImage3DFn != nullptr);
g_driver_gl.debug_fn.glCopyTexSubImage3DFn(target, level, xoffset, yoffset,
zoffset, x, y, width, height);
}
@@ -2560,6 +2621,7 @@ static void GL_BINDING_CALL Debug_glCopyTexSubImage3D(GLenum target,
static void GL_BINDING_CALL Debug_glCoverageModulationNV(GLenum components) {
GL_SERVICE_LOG("glCoverageModulationNV"
<< "(" << GLEnums::GetStringEnum(components) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCoverageModulationNVFn != nullptr);
g_driver_gl.debug_fn.glCoverageModulationNVFn(components);
}
@@ -2578,6 +2640,7 @@ Debug_glCoverFillPathInstancedNV(GLsizei numPaths,
<< GLEnums::GetStringEnum(coverMode) << ", "
<< GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCoverFillPathInstancedNVFn != nullptr);
g_driver_gl.debug_fn.glCoverFillPathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, coverMode, transformType,
transformValues);
@@ -2588,6 +2651,7 @@ static void GL_BINDING_CALL Debug_glCoverFillPathNV(GLuint path,
GL_SERVICE_LOG("glCoverFillPathNV"
<< "(" << path << ", " << GLEnums::GetStringEnum(coverMode)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glCoverFillPathNVFn != nullptr);
g_driver_gl.debug_fn.glCoverFillPathNVFn(path, coverMode);
}
@@ -2606,6 +2670,7 @@ Debug_glCoverStrokePathInstancedNV(GLsizei numPaths,
<< GLEnums::GetStringEnum(coverMode) << ", "
<< GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCoverStrokePathInstancedNVFn != nullptr);
g_driver_gl.debug_fn.glCoverStrokePathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, coverMode, transformType,
transformValues);
@@ -2616,6 +2681,7 @@ static void GL_BINDING_CALL Debug_glCoverStrokePathNV(GLuint name,
GL_SERVICE_LOG("glCoverStrokePathNV"
<< "(" << name << ", " << GLEnums::GetStringEnum(coverMode)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glCoverStrokePathNVFn != nullptr);
g_driver_gl.debug_fn.glCoverStrokePathNVFn(name, coverMode);
}
@@ -2623,6 +2689,7 @@ static GLuint GL_BINDING_CALL Debug_glCreateProgram(void) {
GL_SERVICE_LOG("glCreateProgram"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glCreateProgramFn != nullptr);
GLuint result = g_driver_gl.debug_fn.glCreateProgramFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -2631,6 +2698,7 @@ static GLuint GL_BINDING_CALL Debug_glCreateProgram(void) {
static GLuint GL_BINDING_CALL Debug_glCreateShader(GLenum type) {
GL_SERVICE_LOG("glCreateShader"
<< "(" << GLEnums::GetStringEnum(type) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCreateShaderFn != nullptr);
GLuint result = g_driver_gl.debug_fn.glCreateShaderFn(type);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -2639,6 +2707,7 @@ static GLuint GL_BINDING_CALL Debug_glCreateShader(GLenum type) {
static void GL_BINDING_CALL Debug_glCullFace(GLenum mode) {
GL_SERVICE_LOG("glCullFace"
<< "(" << GLEnums::GetStringEnum(mode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glCullFaceFn != nullptr);
g_driver_gl.debug_fn.glCullFaceFn(mode);
}
@@ -2647,6 +2716,7 @@ static void GL_BINDING_CALL Debug_glDeleteBuffersARB(GLsizei n,
GL_SERVICE_LOG("glDeleteBuffersARB"
<< "(" << n << ", " << static_cast<const void*>(buffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteBuffersARBFn != nullptr);
g_driver_gl.debug_fn.glDeleteBuffersARBFn(n, buffers);
}
@@ -2655,6 +2725,7 @@ static void GL_BINDING_CALL Debug_glDeleteFencesAPPLE(GLsizei n,
GL_SERVICE_LOG("glDeleteFencesAPPLE"
<< "(" << n << ", " << static_cast<const void*>(fences)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteFencesAPPLEFn != nullptr);
g_driver_gl.debug_fn.glDeleteFencesAPPLEFn(n, fences);
}
@@ -2663,6 +2734,7 @@ static void GL_BINDING_CALL Debug_glDeleteFencesNV(GLsizei n,
GL_SERVICE_LOG("glDeleteFencesNV"
<< "(" << n << ", " << static_cast<const void*>(fences)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteFencesNVFn != nullptr);
g_driver_gl.debug_fn.glDeleteFencesNVFn(n, fences);
}
@@ -2671,18 +2743,21 @@ Debug_glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) {
GL_SERVICE_LOG("glDeleteFramebuffersEXT"
<< "(" << n << ", " << static_cast<const void*>(framebuffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteFramebuffersEXTFn != nullptr);
g_driver_gl.debug_fn.glDeleteFramebuffersEXTFn(n, framebuffers);
}
static void GL_BINDING_CALL Debug_glDeletePathsNV(GLuint path, GLsizei range) {
GL_SERVICE_LOG("glDeletePathsNV"
<< "(" << path << ", " << range << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeletePathsNVFn != nullptr);
g_driver_gl.debug_fn.glDeletePathsNVFn(path, range);
}
static void GL_BINDING_CALL Debug_glDeleteProgram(GLuint program) {
GL_SERVICE_LOG("glDeleteProgram"
<< "(" << program << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteProgramFn != nullptr);
g_driver_gl.debug_fn.glDeleteProgramFn(program);
}
@@ -2690,6 +2765,7 @@ static void GL_BINDING_CALL Debug_glDeleteQueries(GLsizei n,
const GLuint* ids) {
GL_SERVICE_LOG("glDeleteQueries"
<< "(" << n << ", " << static_cast<const void*>(ids) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteQueriesFn != nullptr);
g_driver_gl.debug_fn.glDeleteQueriesFn(n, ids);
}
@@ -2698,6 +2774,7 @@ Debug_glDeleteRenderbuffersEXT(GLsizei n, const GLuint* renderbuffers) {
GL_SERVICE_LOG("glDeleteRenderbuffersEXT"
<< "(" << n << ", " << static_cast<const void*>(renderbuffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteRenderbuffersEXTFn != nullptr);
g_driver_gl.debug_fn.glDeleteRenderbuffersEXTFn(n, renderbuffers);
}
@@ -2706,18 +2783,21 @@ static void GL_BINDING_CALL Debug_glDeleteSamplers(GLsizei n,
GL_SERVICE_LOG("glDeleteSamplers"
<< "(" << n << ", " << static_cast<const void*>(samplers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteSamplersFn != nullptr);
g_driver_gl.debug_fn.glDeleteSamplersFn(n, samplers);
}
static void GL_BINDING_CALL Debug_glDeleteShader(GLuint shader) {
GL_SERVICE_LOG("glDeleteShader"
<< "(" << shader << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteShaderFn != nullptr);
g_driver_gl.debug_fn.glDeleteShaderFn(shader);
}
static void GL_BINDING_CALL Debug_glDeleteSync(GLsync sync) {
GL_SERVICE_LOG("glDeleteSync"
<< "(" << sync << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteSyncFn != nullptr);
g_driver_gl.debug_fn.glDeleteSyncFn(sync);
}
@@ -2726,6 +2806,7 @@ static void GL_BINDING_CALL Debug_glDeleteTextures(GLsizei n,
GL_SERVICE_LOG("glDeleteTextures"
<< "(" << n << ", " << static_cast<const void*>(textures)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteTexturesFn != nullptr);
g_driver_gl.debug_fn.glDeleteTexturesFn(n, textures);
}
@@ -2733,6 +2814,7 @@ static void GL_BINDING_CALL
Debug_glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) {
GL_SERVICE_LOG("glDeleteTransformFeedbacks"
<< "(" << n << ", " << static_cast<const void*>(ids) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteTransformFeedbacksFn != nullptr);
g_driver_gl.debug_fn.glDeleteTransformFeedbacksFn(n, ids);
}
@@ -2741,30 +2823,35 @@ Debug_glDeleteVertexArraysOES(GLsizei n, const GLuint* arrays) {
GL_SERVICE_LOG("glDeleteVertexArraysOES"
<< "(" << n << ", " << static_cast<const void*>(arrays)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDeleteVertexArraysOESFn != nullptr);
g_driver_gl.debug_fn.glDeleteVertexArraysOESFn(n, arrays);
}
static void GL_BINDING_CALL Debug_glDepthFunc(GLenum func) {
GL_SERVICE_LOG("glDepthFunc"
<< "(" << GLEnums::GetStringEnum(func) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDepthFuncFn != nullptr);
g_driver_gl.debug_fn.glDepthFuncFn(func);
}
static void GL_BINDING_CALL Debug_glDepthMask(GLboolean flag) {
GL_SERVICE_LOG("glDepthMask"
<< "(" << GLEnums::GetStringBool(flag) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDepthMaskFn != nullptr);
g_driver_gl.debug_fn.glDepthMaskFn(flag);
}
static void GL_BINDING_CALL Debug_glDepthRange(GLclampd zNear, GLclampd zFar) {
GL_SERVICE_LOG("glDepthRange"
<< "(" << zNear << ", " << zFar << ")");
+ DCHECK(g_driver_gl.debug_fn.glDepthRangeFn != nullptr);
g_driver_gl.debug_fn.glDepthRangeFn(zNear, zFar);
}
static void GL_BINDING_CALL Debug_glDepthRangef(GLclampf zNear, GLclampf zFar) {
GL_SERVICE_LOG("glDepthRangef"
<< "(" << zNear << ", " << zFar << ")");
+ DCHECK(g_driver_gl.debug_fn.glDepthRangefFn != nullptr);
g_driver_gl.debug_fn.glDepthRangefFn(zNear, zFar);
}
@@ -2772,18 +2859,21 @@ static void GL_BINDING_CALL Debug_glDetachShader(GLuint program,
GLuint shader) {
GL_SERVICE_LOG("glDetachShader"
<< "(" << program << ", " << shader << ")");
+ DCHECK(g_driver_gl.debug_fn.glDetachShaderFn != nullptr);
g_driver_gl.debug_fn.glDetachShaderFn(program, shader);
}
static void GL_BINDING_CALL Debug_glDisable(GLenum cap) {
GL_SERVICE_LOG("glDisable"
<< "(" << GLEnums::GetStringEnum(cap) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDisableFn != nullptr);
g_driver_gl.debug_fn.glDisableFn(cap);
}
static void GL_BINDING_CALL Debug_glDisableVertexAttribArray(GLuint index) {
GL_SERVICE_LOG("glDisableVertexAttribArray"
<< "(" << index << ")");
+ DCHECK(g_driver_gl.debug_fn.glDisableVertexAttribArrayFn != nullptr);
g_driver_gl.debug_fn.glDisableVertexAttribArrayFn(index);
}
@@ -2795,6 +2885,7 @@ Debug_glDiscardFramebufferEXT(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< numAttachments << ", "
<< static_cast<const void*>(attachments) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDiscardFramebufferEXTFn != nullptr);
g_driver_gl.debug_fn.glDiscardFramebufferEXTFn(target, numAttachments,
attachments);
}
@@ -2805,6 +2896,7 @@ static void GL_BINDING_CALL Debug_glDrawArrays(GLenum mode,
GL_SERVICE_LOG("glDrawArrays"
<< "(" << GLEnums::GetStringEnum(mode) << ", " << first << ", "
<< count << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawArraysFn != nullptr);
g_driver_gl.debug_fn.glDrawArraysFn(mode, first, count);
}
@@ -2816,6 +2908,7 @@ Debug_glDrawArraysInstancedANGLE(GLenum mode,
GL_SERVICE_LOG("glDrawArraysInstancedANGLE"
<< "(" << GLEnums::GetStringEnum(mode) << ", " << first << ", "
<< count << ", " << primcount << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawArraysInstancedANGLEFn != nullptr);
g_driver_gl.debug_fn.glDrawArraysInstancedANGLEFn(mode, first, count,
primcount);
}
@@ -2823,6 +2916,7 @@ Debug_glDrawArraysInstancedANGLE(GLenum mode,
static void GL_BINDING_CALL Debug_glDrawBuffer(GLenum mode) {
GL_SERVICE_LOG("glDrawBuffer"
<< "(" << GLEnums::GetStringEnum(mode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawBufferFn != nullptr);
g_driver_gl.debug_fn.glDrawBufferFn(mode);
}
@@ -2830,6 +2924,7 @@ static void GL_BINDING_CALL Debug_glDrawBuffersARB(GLsizei n,
const GLenum* bufs) {
GL_SERVICE_LOG("glDrawBuffersARB"
<< "(" << n << ", " << static_cast<const void*>(bufs) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawBuffersARBFn != nullptr);
g_driver_gl.debug_fn.glDrawBuffersARBFn(n, bufs);
}
@@ -2841,6 +2936,7 @@ static void GL_BINDING_CALL Debug_glDrawElements(GLenum mode,
<< "(" << GLEnums::GetStringEnum(mode) << ", " << count << ", "
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(indices) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawElementsFn != nullptr);
g_driver_gl.debug_fn.glDrawElementsFn(mode, count, type, indices);
}
@@ -2855,6 +2951,7 @@ Debug_glDrawElementsInstancedANGLE(GLenum mode,
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(indices) << ", " << primcount
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawElementsInstancedANGLEFn != nullptr);
g_driver_gl.debug_fn.glDrawElementsInstancedANGLEFn(mode, count, type,
indices, primcount);
}
@@ -2869,6 +2966,7 @@ static void GL_BINDING_CALL Debug_glDrawRangeElements(GLenum mode,
<< "(" << GLEnums::GetStringEnum(mode) << ", " << start << ", "
<< end << ", " << count << ", " << GLEnums::GetStringEnum(type)
<< ", " << static_cast<const void*>(indices) << ")");
+ DCHECK(g_driver_gl.debug_fn.glDrawRangeElementsFn != nullptr);
g_driver_gl.debug_fn.glDrawRangeElementsFn(mode, start, end, count, type,
indices);
}
@@ -2879,6 +2977,8 @@ Debug_glEGLImageTargetRenderbufferStorageOES(GLenum target,
GL_SERVICE_LOG("glEGLImageTargetRenderbufferStorageOES"
<< "(" << GLEnums::GetStringEnum(target) << ", " << image
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glEGLImageTargetRenderbufferStorageOESFn !=
+ nullptr);
g_driver_gl.debug_fn.glEGLImageTargetRenderbufferStorageOESFn(target, image);
}
@@ -2887,24 +2987,28 @@ Debug_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) {
GL_SERVICE_LOG("glEGLImageTargetTexture2DOES"
<< "(" << GLEnums::GetStringEnum(target) << ", " << image
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glEGLImageTargetTexture2DOESFn != nullptr);
g_driver_gl.debug_fn.glEGLImageTargetTexture2DOESFn(target, image);
}
static void GL_BINDING_CALL Debug_glEnable(GLenum cap) {
GL_SERVICE_LOG("glEnable"
<< "(" << GLEnums::GetStringEnum(cap) << ")");
+ DCHECK(g_driver_gl.debug_fn.glEnableFn != nullptr);
g_driver_gl.debug_fn.glEnableFn(cap);
}
static void GL_BINDING_CALL Debug_glEnableVertexAttribArray(GLuint index) {
GL_SERVICE_LOG("glEnableVertexAttribArray"
<< "(" << index << ")");
+ DCHECK(g_driver_gl.debug_fn.glEnableVertexAttribArrayFn != nullptr);
g_driver_gl.debug_fn.glEnableVertexAttribArrayFn(index);
}
static void GL_BINDING_CALL Debug_glEndQuery(GLenum target) {
GL_SERVICE_LOG("glEndQuery"
<< "(" << GLEnums::GetStringEnum(target) << ")");
+ DCHECK(g_driver_gl.debug_fn.glEndQueryFn != nullptr);
g_driver_gl.debug_fn.glEndQueryFn(target);
}
@@ -2912,6 +3016,7 @@ static void GL_BINDING_CALL Debug_glEndTransformFeedback(void) {
GL_SERVICE_LOG("glEndTransformFeedback"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glEndTransformFeedbackFn != nullptr);
g_driver_gl.debug_fn.glEndTransformFeedbackFn();
}
@@ -2920,6 +3025,7 @@ static GLsync GL_BINDING_CALL Debug_glFenceSync(GLenum condition,
GL_SERVICE_LOG("glFenceSync"
<< "(" << GLEnums::GetStringEnum(condition) << ", " << flags
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glFenceSyncFn != nullptr);
GLsync result = g_driver_gl.debug_fn.glFenceSyncFn(condition, flags);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -2929,18 +3035,21 @@ static void GL_BINDING_CALL Debug_glFinish(void) {
GL_SERVICE_LOG("glFinish"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glFinishFn != nullptr);
g_driver_gl.debug_fn.glFinishFn();
}
static void GL_BINDING_CALL Debug_glFinishFenceAPPLE(GLuint fence) {
GL_SERVICE_LOG("glFinishFenceAPPLE"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glFinishFenceAPPLEFn != nullptr);
g_driver_gl.debug_fn.glFinishFenceAPPLEFn(fence);
}
static void GL_BINDING_CALL Debug_glFinishFenceNV(GLuint fence) {
GL_SERVICE_LOG("glFinishFenceNV"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glFinishFenceNVFn != nullptr);
g_driver_gl.debug_fn.glFinishFenceNVFn(fence);
}
@@ -2948,6 +3057,7 @@ static void GL_BINDING_CALL Debug_glFlush(void) {
GL_SERVICE_LOG("glFlush"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glFlushFn != nullptr);
g_driver_gl.debug_fn.glFlushFn();
}
@@ -2957,6 +3067,7 @@ static void GL_BINDING_CALL Debug_glFlushMappedBufferRange(GLenum target,
GL_SERVICE_LOG("glFlushMappedBufferRange"
<< "(" << GLEnums::GetStringEnum(target) << ", " << offset
<< ", " << length << ")");
+ DCHECK(g_driver_gl.debug_fn.glFlushMappedBufferRangeFn != nullptr);
g_driver_gl.debug_fn.glFlushMappedBufferRangeFn(target, offset, length);
}
@@ -2970,6 +3081,7 @@ Debug_glFramebufferRenderbufferEXT(GLenum target,
<< GLEnums::GetStringEnum(attachment) << ", "
<< GLEnums::GetStringEnum(renderbuffertarget) << ", "
<< renderbuffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glFramebufferRenderbufferEXTFn != nullptr);
g_driver_gl.debug_fn.glFramebufferRenderbufferEXTFn(
target, attachment, renderbuffertarget, renderbuffer);
}
@@ -2984,6 +3096,7 @@ static void GL_BINDING_CALL Debug_glFramebufferTexture2DEXT(GLenum target,
<< GLEnums::GetStringEnum(attachment) << ", "
<< GLEnums::GetStringEnum(textarget) << ", " << texture << ", "
<< level << ")");
+ DCHECK(g_driver_gl.debug_fn.glFramebufferTexture2DEXTFn != nullptr);
g_driver_gl.debug_fn.glFramebufferTexture2DEXTFn(target, attachment,
textarget, texture, level);
}
@@ -3000,6 +3113,8 @@ Debug_glFramebufferTexture2DMultisampleEXT(GLenum target,
<< GLEnums::GetStringEnum(attachment) << ", "
<< GLEnums::GetStringEnum(textarget) << ", " << texture << ", "
<< level << ", " << samples << ")");
+ DCHECK(g_driver_gl.debug_fn.glFramebufferTexture2DMultisampleEXTFn !=
+ nullptr);
g_driver_gl.debug_fn.glFramebufferTexture2DMultisampleEXTFn(
target, attachment, textarget, texture, level, samples);
}
@@ -3016,6 +3131,8 @@ Debug_glFramebufferTexture2DMultisampleIMG(GLenum target,
<< GLEnums::GetStringEnum(attachment) << ", "
<< GLEnums::GetStringEnum(textarget) << ", " << texture << ", "
<< level << ", " << samples << ")");
+ DCHECK(g_driver_gl.debug_fn.glFramebufferTexture2DMultisampleIMGFn !=
+ nullptr);
g_driver_gl.debug_fn.glFramebufferTexture2DMultisampleIMGFn(
target, attachment, textarget, texture, level, samples);
}
@@ -3029,6 +3146,7 @@ static void GL_BINDING_CALL Debug_glFramebufferTextureLayer(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(attachment) << ", " << texture
<< ", " << level << ", " << layer << ")");
+ DCHECK(g_driver_gl.debug_fn.glFramebufferTextureLayerFn != nullptr);
g_driver_gl.debug_fn.glFramebufferTextureLayerFn(target, attachment, texture,
level, layer);
}
@@ -3036,6 +3154,7 @@ static void GL_BINDING_CALL Debug_glFramebufferTextureLayer(GLenum target,
static void GL_BINDING_CALL Debug_glFrontFace(GLenum mode) {
GL_SERVICE_LOG("glFrontFace"
<< "(" << GLEnums::GetStringEnum(mode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glFrontFaceFn != nullptr);
g_driver_gl.debug_fn.glFrontFaceFn(mode);
}
@@ -3043,12 +3162,14 @@ static void GL_BINDING_CALL Debug_glGenBuffersARB(GLsizei n, GLuint* buffers) {
GL_SERVICE_LOG("glGenBuffersARB"
<< "(" << n << ", " << static_cast<const void*>(buffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenBuffersARBFn != nullptr);
g_driver_gl.debug_fn.glGenBuffersARBFn(n, buffers);
}
static void GL_BINDING_CALL Debug_glGenerateMipmapEXT(GLenum target) {
GL_SERVICE_LOG("glGenerateMipmapEXT"
<< "(" << GLEnums::GetStringEnum(target) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGenerateMipmapEXTFn != nullptr);
g_driver_gl.debug_fn.glGenerateMipmapEXTFn(target);
}
@@ -3056,6 +3177,7 @@ static void GL_BINDING_CALL Debug_glGenFencesAPPLE(GLsizei n, GLuint* fences) {
GL_SERVICE_LOG("glGenFencesAPPLE"
<< "(" << n << ", " << static_cast<const void*>(fences)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenFencesAPPLEFn != nullptr);
g_driver_gl.debug_fn.glGenFencesAPPLEFn(n, fences);
}
@@ -3063,6 +3185,7 @@ static void GL_BINDING_CALL Debug_glGenFencesNV(GLsizei n, GLuint* fences) {
GL_SERVICE_LOG("glGenFencesNV"
<< "(" << n << ", " << static_cast<const void*>(fences)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenFencesNVFn != nullptr);
g_driver_gl.debug_fn.glGenFencesNVFn(n, fences);
}
@@ -3071,12 +3194,14 @@ static void GL_BINDING_CALL Debug_glGenFramebuffersEXT(GLsizei n,
GL_SERVICE_LOG("glGenFramebuffersEXT"
<< "(" << n << ", " << static_cast<const void*>(framebuffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenFramebuffersEXTFn != nullptr);
g_driver_gl.debug_fn.glGenFramebuffersEXTFn(n, framebuffers);
}
static GLuint GL_BINDING_CALL Debug_glGenPathsNV(GLsizei range) {
GL_SERVICE_LOG("glGenPathsNV"
<< "(" << range << ")");
+ DCHECK(g_driver_gl.debug_fn.glGenPathsNVFn != nullptr);
GLuint result = g_driver_gl.debug_fn.glGenPathsNVFn(range);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3085,6 +3210,7 @@ static GLuint GL_BINDING_CALL Debug_glGenPathsNV(GLsizei range) {
static void GL_BINDING_CALL Debug_glGenQueries(GLsizei n, GLuint* ids) {
GL_SERVICE_LOG("glGenQueries"
<< "(" << n << ", " << static_cast<const void*>(ids) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGenQueriesFn != nullptr);
g_driver_gl.debug_fn.glGenQueriesFn(n, ids);
}
@@ -3093,6 +3219,7 @@ static void GL_BINDING_CALL Debug_glGenRenderbuffersEXT(GLsizei n,
GL_SERVICE_LOG("glGenRenderbuffersEXT"
<< "(" << n << ", " << static_cast<const void*>(renderbuffers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenRenderbuffersEXTFn != nullptr);
g_driver_gl.debug_fn.glGenRenderbuffersEXTFn(n, renderbuffers);
}
@@ -3100,6 +3227,7 @@ static void GL_BINDING_CALL Debug_glGenSamplers(GLsizei n, GLuint* samplers) {
GL_SERVICE_LOG("glGenSamplers"
<< "(" << n << ", " << static_cast<const void*>(samplers)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenSamplersFn != nullptr);
g_driver_gl.debug_fn.glGenSamplersFn(n, samplers);
}
@@ -3107,6 +3235,7 @@ static void GL_BINDING_CALL Debug_glGenTextures(GLsizei n, GLuint* textures) {
GL_SERVICE_LOG("glGenTextures"
<< "(" << n << ", " << static_cast<const void*>(textures)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenTexturesFn != nullptr);
g_driver_gl.debug_fn.glGenTexturesFn(n, textures);
}
@@ -3114,6 +3243,7 @@ static void GL_BINDING_CALL Debug_glGenTransformFeedbacks(GLsizei n,
GLuint* ids) {
GL_SERVICE_LOG("glGenTransformFeedbacks"
<< "(" << n << ", " << static_cast<const void*>(ids) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGenTransformFeedbacksFn != nullptr);
g_driver_gl.debug_fn.glGenTransformFeedbacksFn(n, ids);
}
@@ -3122,6 +3252,7 @@ static void GL_BINDING_CALL Debug_glGenVertexArraysOES(GLsizei n,
GL_SERVICE_LOG("glGenVertexArraysOES"
<< "(" << n << ", " << static_cast<const void*>(arrays)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGenVertexArraysOESFn != nullptr);
g_driver_gl.debug_fn.glGenVertexArraysOESFn(n, arrays);
}
@@ -3138,6 +3269,7 @@ static void GL_BINDING_CALL Debug_glGetActiveAttrib(GLuint program,
<< static_cast<const void*>(size) << ", "
<< static_cast<const void*>(type) << ", "
<< static_cast<const void*>(name) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetActiveAttribFn != nullptr);
g_driver_gl.debug_fn.glGetActiveAttribFn(program, index, bufsize, length,
size, type, name);
}
@@ -3155,6 +3287,7 @@ static void GL_BINDING_CALL Debug_glGetActiveUniform(GLuint program,
<< static_cast<const void*>(size) << ", "
<< static_cast<const void*>(type) << ", "
<< static_cast<const void*>(name) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetActiveUniformFn != nullptr);
g_driver_gl.debug_fn.glGetActiveUniformFn(program, index, bufsize, length,
size, type, name);
}
@@ -3168,6 +3301,7 @@ Debug_glGetActiveUniformBlockiv(GLuint program,
<< "(" << program << ", " << uniformBlockIndex << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetActiveUniformBlockivFn != nullptr);
g_driver_gl.debug_fn.glGetActiveUniformBlockivFn(program, uniformBlockIndex,
pname, params);
}
@@ -3182,6 +3316,7 @@ Debug_glGetActiveUniformBlockName(GLuint program,
<< "(" << program << ", " << uniformBlockIndex << ", "
<< bufSize << ", " << static_cast<const void*>(length) << ", "
<< static_cast<const void*>(uniformBlockName) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetActiveUniformBlockNameFn != nullptr);
g_driver_gl.debug_fn.glGetActiveUniformBlockNameFn(
program, uniformBlockIndex, bufSize, length, uniformBlockName);
}
@@ -3197,6 +3332,7 @@ Debug_glGetActiveUniformsiv(GLuint program,
<< static_cast<const void*>(uniformIndices) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetActiveUniformsivFn != nullptr);
g_driver_gl.debug_fn.glGetActiveUniformsivFn(program, uniformCount,
uniformIndices, pname, params);
}
@@ -3209,6 +3345,7 @@ static void GL_BINDING_CALL Debug_glGetAttachedShaders(GLuint program,
<< "(" << program << ", " << maxcount << ", "
<< static_cast<const void*>(count) << ", "
<< static_cast<const void*>(shaders) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetAttachedShadersFn != nullptr);
g_driver_gl.debug_fn.glGetAttachedShadersFn(program, maxcount, count,
shaders);
}
@@ -3217,6 +3354,7 @@ static GLint GL_BINDING_CALL Debug_glGetAttribLocation(GLuint program,
const char* name) {
GL_SERVICE_LOG("glGetAttribLocation"
<< "(" << program << ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetAttribLocationFn != nullptr);
GLint result = g_driver_gl.debug_fn.glGetAttribLocationFn(program, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3227,6 +3365,7 @@ static void GL_BINDING_CALL Debug_glGetBooleanv(GLenum pname,
GL_SERVICE_LOG("glGetBooleanv"
<< "(" << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetBooleanvFn != nullptr);
g_driver_gl.debug_fn.glGetBooleanvFn(pname, params);
}
@@ -3237,6 +3376,7 @@ static void GL_BINDING_CALL Debug_glGetBufferParameteriv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetBufferParameterivFn != nullptr);
g_driver_gl.debug_fn.glGetBufferParameterivFn(target, pname, params);
}
@@ -3244,6 +3384,7 @@ static GLenum GL_BINDING_CALL Debug_glGetError(void) {
GL_SERVICE_LOG("glGetError"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGetErrorFn != nullptr);
GLenum result = g_driver_gl.debug_fn.glGetErrorFn();
GL_SERVICE_LOG("GL_RESULT: " << GLEnums::GetStringError(result));
@@ -3257,6 +3398,7 @@ static void GL_BINDING_CALL Debug_glGetFenceivNV(GLuint fence,
GL_SERVICE_LOG("glGetFenceivNV"
<< "(" << fence << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetFenceivNVFn != nullptr);
g_driver_gl.debug_fn.glGetFenceivNVFn(fence, pname, params);
}
@@ -3264,6 +3406,7 @@ static void GL_BINDING_CALL Debug_glGetFloatv(GLenum pname, GLfloat* params) {
GL_SERVICE_LOG("glGetFloatv"
<< "(" << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetFloatvFn != nullptr);
g_driver_gl.debug_fn.glGetFloatvFn(pname, params);
}
@@ -3271,6 +3414,7 @@ static GLint GL_BINDING_CALL Debug_glGetFragDataIndex(GLuint program,
const char* name) {
GL_SERVICE_LOG("glGetFragDataIndex"
<< "(" << program << ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetFragDataIndexFn != nullptr);
GLint result = g_driver_gl.debug_fn.glGetFragDataIndexFn(program, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3280,6 +3424,7 @@ static GLint GL_BINDING_CALL Debug_glGetFragDataLocation(GLuint program,
const char* name) {
GL_SERVICE_LOG("glGetFragDataLocation"
<< "(" << program << ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetFragDataLocationFn != nullptr);
GLint result = g_driver_gl.debug_fn.glGetFragDataLocationFn(program, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3295,6 +3440,8 @@ Debug_glGetFramebufferAttachmentParameterivEXT(GLenum target,
<< GLEnums::GetStringEnum(attachment) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetFramebufferAttachmentParameterivEXTFn !=
+ nullptr);
g_driver_gl.debug_fn.glGetFramebufferAttachmentParameterivEXTFn(
target, attachment, pname, params);
}
@@ -3303,6 +3450,7 @@ static GLenum GL_BINDING_CALL Debug_glGetGraphicsResetStatusARB(void) {
GL_SERVICE_LOG("glGetGraphicsResetStatusARB"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGetGraphicsResetStatusARBFn != nullptr);
GLenum result = g_driver_gl.debug_fn.glGetGraphicsResetStatusARBFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3314,6 +3462,7 @@ static void GL_BINDING_CALL Debug_glGetInteger64i_v(GLenum target,
GL_SERVICE_LOG("glGetInteger64i_v"
<< "(" << GLEnums::GetStringEnum(target) << ", " << index
<< ", " << static_cast<const void*>(data) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetInteger64i_vFn != nullptr);
g_driver_gl.debug_fn.glGetInteger64i_vFn(target, index, data);
}
@@ -3322,6 +3471,7 @@ static void GL_BINDING_CALL Debug_glGetInteger64v(GLenum pname,
GL_SERVICE_LOG("glGetInteger64v"
<< "(" << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetInteger64vFn != nullptr);
g_driver_gl.debug_fn.glGetInteger64vFn(pname, params);
}
@@ -3331,6 +3481,7 @@ static void GL_BINDING_CALL Debug_glGetIntegeri_v(GLenum target,
GL_SERVICE_LOG("glGetIntegeri_v"
<< "(" << GLEnums::GetStringEnum(target) << ", " << index
<< ", " << static_cast<const void*>(data) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetIntegeri_vFn != nullptr);
g_driver_gl.debug_fn.glGetIntegeri_vFn(target, index, data);
}
@@ -3338,6 +3489,7 @@ static void GL_BINDING_CALL Debug_glGetIntegerv(GLenum pname, GLint* params) {
GL_SERVICE_LOG("glGetIntegerv"
<< "(" << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetIntegervFn != nullptr);
g_driver_gl.debug_fn.glGetIntegervFn(pname, params);
}
@@ -3351,6 +3503,7 @@ static void GL_BINDING_CALL Debug_glGetInternalformativ(GLenum target,
<< GLEnums::GetStringEnum(internalformat) << ", "
<< GLEnums::GetStringEnum(pname) << ", " << bufSize << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetInternalformativFn != nullptr);
g_driver_gl.debug_fn.glGetInternalformativFn(target, internalformat, pname,
bufSize, params);
}
@@ -3365,6 +3518,7 @@ static void GL_BINDING_CALL Debug_glGetProgramBinary(GLuint program,
<< static_cast<const void*>(length) << ", "
<< static_cast<const void*>(binaryFormat) << ", "
<< static_cast<const void*>(binary) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramBinaryFn != nullptr);
g_driver_gl.debug_fn.glGetProgramBinaryFn(program, bufSize, length,
binaryFormat, binary);
}
@@ -3377,6 +3531,7 @@ static void GL_BINDING_CALL Debug_glGetProgramInfoLog(GLuint program,
<< "(" << program << ", " << bufsize << ", "
<< static_cast<const void*>(length) << ", "
<< static_cast<const void*>(infolog) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramInfoLogFn != nullptr);
g_driver_gl.debug_fn.glGetProgramInfoLogFn(program, bufsize, length, infolog);
}
@@ -3390,6 +3545,7 @@ Debug_glGetProgramInterfaceiv(GLuint program,
<< GLEnums::GetStringEnum(programInterface) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramInterfaceivFn != nullptr);
g_driver_gl.debug_fn.glGetProgramInterfaceivFn(program, programInterface,
pname, params);
}
@@ -3400,6 +3556,7 @@ static void GL_BINDING_CALL Debug_glGetProgramiv(GLuint program,
GL_SERVICE_LOG("glGetProgramiv"
<< "(" << program << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramivFn != nullptr);
g_driver_gl.debug_fn.glGetProgramivFn(program, pname, params);
}
@@ -3418,6 +3575,7 @@ Debug_glGetProgramResourceiv(GLuint program,
<< ", " << propCount << ", " << static_cast<const void*>(props)
<< ", " << bufSize << ", " << static_cast<const void*>(length)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramResourceivFn != nullptr);
g_driver_gl.debug_fn.glGetProgramResourceivFn(program, programInterface,
index, propCount, props,
bufSize, length, params);
@@ -3431,6 +3589,7 @@ Debug_glGetProgramResourceLocation(GLuint program,
<< "(" << program << ", "
<< GLEnums::GetStringEnum(programInterface) << ", " << name
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramResourceLocationFn != nullptr);
GLint result = g_driver_gl.debug_fn.glGetProgramResourceLocationFn(
program, programInterface, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -3449,6 +3608,7 @@ Debug_glGetProgramResourceName(GLuint program,
<< GLEnums::GetStringEnum(programInterface) << ", " << index
<< ", " << bufSize << ", " << static_cast<const void*>(length)
<< ", " << static_cast<const void*>(name) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetProgramResourceNameFn != nullptr);
g_driver_gl.debug_fn.glGetProgramResourceNameFn(program, programInterface,
index, bufSize, length, name);
}
@@ -3460,6 +3620,7 @@ static void GL_BINDING_CALL Debug_glGetQueryiv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetQueryivFn != nullptr);
g_driver_gl.debug_fn.glGetQueryivFn(target, pname, params);
}
@@ -3469,6 +3630,7 @@ static void GL_BINDING_CALL Debug_glGetQueryObjecti64v(GLuint id,
GL_SERVICE_LOG("glGetQueryObjecti64v"
<< "(" << id << ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetQueryObjecti64vFn != nullptr);
g_driver_gl.debug_fn.glGetQueryObjecti64vFn(id, pname, params);
}
@@ -3478,6 +3640,7 @@ static void GL_BINDING_CALL Debug_glGetQueryObjectiv(GLuint id,
GL_SERVICE_LOG("glGetQueryObjectiv"
<< "(" << id << ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetQueryObjectivFn != nullptr);
g_driver_gl.debug_fn.glGetQueryObjectivFn(id, pname, params);
}
@@ -3487,6 +3650,7 @@ static void GL_BINDING_CALL Debug_glGetQueryObjectui64v(GLuint id,
GL_SERVICE_LOG("glGetQueryObjectui64v"
<< "(" << id << ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetQueryObjectui64vFn != nullptr);
g_driver_gl.debug_fn.glGetQueryObjectui64vFn(id, pname, params);
}
@@ -3496,6 +3660,7 @@ static void GL_BINDING_CALL Debug_glGetQueryObjectuiv(GLuint id,
GL_SERVICE_LOG("glGetQueryObjectuiv"
<< "(" << id << ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetQueryObjectuivFn != nullptr);
g_driver_gl.debug_fn.glGetQueryObjectuivFn(id, pname, params);
}
@@ -3507,6 +3672,7 @@ Debug_glGetRenderbufferParameterivEXT(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetRenderbufferParameterivEXTFn != nullptr);
g_driver_gl.debug_fn.glGetRenderbufferParameterivEXTFn(target, pname, params);
}
@@ -3516,6 +3682,7 @@ static void GL_BINDING_CALL Debug_glGetSamplerParameterfv(GLuint sampler,
GL_SERVICE_LOG("glGetSamplerParameterfv"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetSamplerParameterfvFn != nullptr);
g_driver_gl.debug_fn.glGetSamplerParameterfvFn(sampler, pname, params);
}
@@ -3525,6 +3692,7 @@ static void GL_BINDING_CALL Debug_glGetSamplerParameteriv(GLuint sampler,
GL_SERVICE_LOG("glGetSamplerParameteriv"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetSamplerParameterivFn != nullptr);
g_driver_gl.debug_fn.glGetSamplerParameterivFn(sampler, pname, params);
}
@@ -3536,6 +3704,7 @@ static void GL_BINDING_CALL Debug_glGetShaderInfoLog(GLuint shader,
<< "(" << shader << ", " << bufsize << ", "
<< static_cast<const void*>(length) << ", "
<< static_cast<const void*>(infolog) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetShaderInfoLogFn != nullptr);
g_driver_gl.debug_fn.glGetShaderInfoLogFn(shader, bufsize, length, infolog);
}
@@ -3545,6 +3714,7 @@ static void GL_BINDING_CALL Debug_glGetShaderiv(GLuint shader,
GL_SERVICE_LOG("glGetShaderiv"
<< "(" << shader << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetShaderivFn != nullptr);
g_driver_gl.debug_fn.glGetShaderivFn(shader, pname, params);
}
@@ -3558,6 +3728,7 @@ Debug_glGetShaderPrecisionFormat(GLenum shadertype,
<< GLEnums::GetStringEnum(precisiontype) << ", "
<< static_cast<const void*>(range) << ", "
<< static_cast<const void*>(precision) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetShaderPrecisionFormatFn != nullptr);
g_driver_gl.debug_fn.glGetShaderPrecisionFormatFn(shadertype, precisiontype,
range, precision);
}
@@ -3570,12 +3741,14 @@ static void GL_BINDING_CALL Debug_glGetShaderSource(GLuint shader,
<< "(" << shader << ", " << bufsize << ", "
<< static_cast<const void*>(length) << ", "
<< static_cast<const void*>(source) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetShaderSourceFn != nullptr);
g_driver_gl.debug_fn.glGetShaderSourceFn(shader, bufsize, length, source);
}
static const GLubyte* GL_BINDING_CALL Debug_glGetString(GLenum name) {
GL_SERVICE_LOG("glGetString"
<< "(" << GLEnums::GetStringEnum(name) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetStringFn != nullptr);
const GLubyte* result = g_driver_gl.debug_fn.glGetStringFn(name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3586,6 +3759,7 @@ static const GLubyte* GL_BINDING_CALL Debug_glGetStringi(GLenum name,
GL_SERVICE_LOG("glGetStringi"
<< "(" << GLEnums::GetStringEnum(name) << ", " << index
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glGetStringiFn != nullptr);
const GLubyte* result = g_driver_gl.debug_fn.glGetStringiFn(name, index);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3600,6 +3774,7 @@ static void GL_BINDING_CALL Debug_glGetSynciv(GLsync sync,
<< "(" << sync << ", " << GLEnums::GetStringEnum(pname) << ", "
<< bufSize << ", " << static_cast<const void*>(length) << ", "
<< static_cast<const void*>(values) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetSyncivFn != nullptr);
g_driver_gl.debug_fn.glGetSyncivFn(sync, pname, bufSize, length, values);
}
@@ -3611,6 +3786,7 @@ static void GL_BINDING_CALL Debug_glGetTexLevelParameterfv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << level
<< ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTexLevelParameterfvFn != nullptr);
g_driver_gl.debug_fn.glGetTexLevelParameterfvFn(target, level, pname, params);
}
@@ -3622,6 +3798,7 @@ static void GL_BINDING_CALL Debug_glGetTexLevelParameteriv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << level
<< ", " << GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTexLevelParameterivFn != nullptr);
g_driver_gl.debug_fn.glGetTexLevelParameterivFn(target, level, pname, params);
}
@@ -3632,6 +3809,7 @@ static void GL_BINDING_CALL Debug_glGetTexParameterfv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTexParameterfvFn != nullptr);
g_driver_gl.debug_fn.glGetTexParameterfvFn(target, pname, params);
}
@@ -3642,6 +3820,7 @@ static void GL_BINDING_CALL Debug_glGetTexParameteriv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTexParameterivFn != nullptr);
g_driver_gl.debug_fn.glGetTexParameterivFn(target, pname, params);
}
@@ -3658,6 +3837,7 @@ static void GL_BINDING_CALL Debug_glGetTransformFeedbackVarying(GLuint program,
<< static_cast<const void*>(size) << ", "
<< static_cast<const void*>(type) << ", "
<< static_cast<const void*>(name) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTransformFeedbackVaryingFn != nullptr);
g_driver_gl.debug_fn.glGetTransformFeedbackVaryingFn(
program, index, bufSize, length, size, type, name);
}
@@ -3671,6 +3851,7 @@ Debug_glGetTranslatedShaderSourceANGLE(GLuint shader,
<< "(" << shader << ", " << bufsize << ", "
<< static_cast<const void*>(length) << ", "
<< static_cast<const void*>(source) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetTranslatedShaderSourceANGLEFn != nullptr);
g_driver_gl.debug_fn.glGetTranslatedShaderSourceANGLEFn(shader, bufsize,
length, source);
}
@@ -3679,6 +3860,7 @@ static GLuint GL_BINDING_CALL
Debug_glGetUniformBlockIndex(GLuint program, const char* uniformBlockName) {
GL_SERVICE_LOG("glGetUniformBlockIndex"
<< "(" << program << ", " << uniformBlockName << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformBlockIndexFn != nullptr);
GLuint result =
g_driver_gl.debug_fn.glGetUniformBlockIndexFn(program, uniformBlockName);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -3691,6 +3873,7 @@ static void GL_BINDING_CALL Debug_glGetUniformfv(GLuint program,
GL_SERVICE_LOG("glGetUniformfv"
<< "(" << program << ", " << location << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformfvFn != nullptr);
g_driver_gl.debug_fn.glGetUniformfvFn(program, location, params);
}
@@ -3703,6 +3886,7 @@ Debug_glGetUniformIndices(GLuint program,
<< "(" << program << ", " << uniformCount << ", "
<< static_cast<const void*>(uniformNames) << ", "
<< static_cast<const void*>(uniformIndices) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformIndicesFn != nullptr);
g_driver_gl.debug_fn.glGetUniformIndicesFn(program, uniformCount,
uniformNames, uniformIndices);
}
@@ -3713,6 +3897,7 @@ static void GL_BINDING_CALL Debug_glGetUniformiv(GLuint program,
GL_SERVICE_LOG("glGetUniformiv"
<< "(" << program << ", " << location << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformivFn != nullptr);
g_driver_gl.debug_fn.glGetUniformivFn(program, location, params);
}
@@ -3720,6 +3905,7 @@ static GLint GL_BINDING_CALL Debug_glGetUniformLocation(GLuint program,
const char* name) {
GL_SERVICE_LOG("glGetUniformLocation"
<< "(" << program << ", " << name << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformLocationFn != nullptr);
GLint result = g_driver_gl.debug_fn.glGetUniformLocationFn(program, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3731,6 +3917,7 @@ static void GL_BINDING_CALL Debug_glGetUniformuiv(GLuint program,
GL_SERVICE_LOG("glGetUniformuiv"
<< "(" << program << ", " << location << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetUniformuivFn != nullptr);
g_driver_gl.debug_fn.glGetUniformuivFn(program, location, params);
}
@@ -3740,6 +3927,7 @@ static void GL_BINDING_CALL Debug_glGetVertexAttribfv(GLuint index,
GL_SERVICE_LOG("glGetVertexAttribfv"
<< "(" << index << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetVertexAttribfvFn != nullptr);
g_driver_gl.debug_fn.glGetVertexAttribfvFn(index, pname, params);
}
@@ -3749,6 +3937,7 @@ static void GL_BINDING_CALL Debug_glGetVertexAttribiv(GLuint index,
GL_SERVICE_LOG("glGetVertexAttribiv"
<< "(" << index << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetVertexAttribivFn != nullptr);
g_driver_gl.debug_fn.glGetVertexAttribivFn(index, pname, params);
}
@@ -3758,6 +3947,7 @@ static void GL_BINDING_CALL Debug_glGetVertexAttribPointerv(GLuint index,
GL_SERVICE_LOG("glGetVertexAttribPointerv"
<< "(" << index << ", " << GLEnums::GetStringEnum(pname)
<< ", " << pointer << ")");
+ DCHECK(g_driver_gl.debug_fn.glGetVertexAttribPointervFn != nullptr);
g_driver_gl.debug_fn.glGetVertexAttribPointervFn(index, pname, pointer);
}
@@ -3765,6 +3955,7 @@ static void GL_BINDING_CALL Debug_glHint(GLenum target, GLenum mode) {
GL_SERVICE_LOG("glHint"
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(mode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glHintFn != nullptr);
g_driver_gl.debug_fn.glHintFn(target, mode);
}
@@ -3772,6 +3963,7 @@ static void GL_BINDING_CALL Debug_glInsertEventMarkerEXT(GLsizei length,
const char* marker) {
GL_SERVICE_LOG("glInsertEventMarkerEXT"
<< "(" << length << ", " << marker << ")");
+ DCHECK(g_driver_gl.debug_fn.glInsertEventMarkerEXTFn != nullptr);
g_driver_gl.debug_fn.glInsertEventMarkerEXTFn(length, marker);
}
@@ -3783,6 +3975,7 @@ Debug_glInvalidateFramebuffer(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< numAttachments << ", "
<< static_cast<const void*>(attachments) << ")");
+ DCHECK(g_driver_gl.debug_fn.glInvalidateFramebufferFn != nullptr);
g_driver_gl.debug_fn.glInvalidateFramebufferFn(target, numAttachments,
attachments);
}
@@ -3800,6 +3993,7 @@ Debug_glInvalidateSubFramebuffer(GLenum target,
<< numAttachments << ", "
<< static_cast<const void*>(attachments) << ", " << x << ", "
<< y << ", " << width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glInvalidateSubFramebufferFn != nullptr);
g_driver_gl.debug_fn.glInvalidateSubFramebufferFn(
target, numAttachments, attachments, x, y, width, height);
}
@@ -3807,6 +4001,7 @@ Debug_glInvalidateSubFramebuffer(GLenum target,
static GLboolean GL_BINDING_CALL Debug_glIsBuffer(GLuint buffer) {
GL_SERVICE_LOG("glIsBuffer"
<< "(" << buffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsBufferFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsBufferFn(buffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3815,6 +4010,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsBuffer(GLuint buffer) {
static GLboolean GL_BINDING_CALL Debug_glIsEnabled(GLenum cap) {
GL_SERVICE_LOG("glIsEnabled"
<< "(" << GLEnums::GetStringEnum(cap) << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsEnabledFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsEnabledFn(cap);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3823,6 +4019,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsEnabled(GLenum cap) {
static GLboolean GL_BINDING_CALL Debug_glIsFenceAPPLE(GLuint fence) {
GL_SERVICE_LOG("glIsFenceAPPLE"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsFenceAPPLEFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsFenceAPPLEFn(fence);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3831,6 +4028,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsFenceAPPLE(GLuint fence) {
static GLboolean GL_BINDING_CALL Debug_glIsFenceNV(GLuint fence) {
GL_SERVICE_LOG("glIsFenceNV"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsFenceNVFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsFenceNVFn(fence);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3839,6 +4037,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsFenceNV(GLuint fence) {
static GLboolean GL_BINDING_CALL Debug_glIsFramebufferEXT(GLuint framebuffer) {
GL_SERVICE_LOG("glIsFramebufferEXT"
<< "(" << framebuffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsFramebufferEXTFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsFramebufferEXTFn(framebuffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3847,6 +4046,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsFramebufferEXT(GLuint framebuffer) {
static GLboolean GL_BINDING_CALL Debug_glIsPathNV(GLuint path) {
GL_SERVICE_LOG("glIsPathNV"
<< "(" << path << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsPathNVFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsPathNVFn(path);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3855,6 +4055,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsPathNV(GLuint path) {
static GLboolean GL_BINDING_CALL Debug_glIsProgram(GLuint program) {
GL_SERVICE_LOG("glIsProgram"
<< "(" << program << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsProgramFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsProgramFn(program);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3863,6 +4064,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsProgram(GLuint program) {
static GLboolean GL_BINDING_CALL Debug_glIsQuery(GLuint query) {
GL_SERVICE_LOG("glIsQuery"
<< "(" << query << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsQueryFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsQueryFn(query);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3872,6 +4074,7 @@ static GLboolean GL_BINDING_CALL
Debug_glIsRenderbufferEXT(GLuint renderbuffer) {
GL_SERVICE_LOG("glIsRenderbufferEXT"
<< "(" << renderbuffer << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsRenderbufferEXTFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsRenderbufferEXTFn(renderbuffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3880,6 +4083,7 @@ Debug_glIsRenderbufferEXT(GLuint renderbuffer) {
static GLboolean GL_BINDING_CALL Debug_glIsSampler(GLuint sampler) {
GL_SERVICE_LOG("glIsSampler"
<< "(" << sampler << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsSamplerFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsSamplerFn(sampler);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3888,6 +4092,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsSampler(GLuint sampler) {
static GLboolean GL_BINDING_CALL Debug_glIsShader(GLuint shader) {
GL_SERVICE_LOG("glIsShader"
<< "(" << shader << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsShaderFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsShaderFn(shader);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3896,6 +4101,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsShader(GLuint shader) {
static GLboolean GL_BINDING_CALL Debug_glIsSync(GLsync sync) {
GL_SERVICE_LOG("glIsSync"
<< "(" << sync << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsSyncFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsSyncFn(sync);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3904,6 +4110,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsSync(GLsync sync) {
static GLboolean GL_BINDING_CALL Debug_glIsTexture(GLuint texture) {
GL_SERVICE_LOG("glIsTexture"
<< "(" << texture << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsTextureFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsTextureFn(texture);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3912,6 +4119,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsTexture(GLuint texture) {
static GLboolean GL_BINDING_CALL Debug_glIsTransformFeedback(GLuint id) {
GL_SERVICE_LOG("glIsTransformFeedback"
<< "(" << id << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsTransformFeedbackFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsTransformFeedbackFn(id);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3920,6 +4128,7 @@ static GLboolean GL_BINDING_CALL Debug_glIsTransformFeedback(GLuint id) {
static GLboolean GL_BINDING_CALL Debug_glIsVertexArrayOES(GLuint array) {
GL_SERVICE_LOG("glIsVertexArrayOES"
<< "(" << array << ")");
+ DCHECK(g_driver_gl.debug_fn.glIsVertexArrayOESFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glIsVertexArrayOESFn(array);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3928,12 +4137,14 @@ static GLboolean GL_BINDING_CALL Debug_glIsVertexArrayOES(GLuint array) {
static void GL_BINDING_CALL Debug_glLineWidth(GLfloat width) {
GL_SERVICE_LOG("glLineWidth"
<< "(" << width << ")");
+ DCHECK(g_driver_gl.debug_fn.glLineWidthFn != nullptr);
g_driver_gl.debug_fn.glLineWidthFn(width);
}
static void GL_BINDING_CALL Debug_glLinkProgram(GLuint program) {
GL_SERVICE_LOG("glLinkProgram"
<< "(" << program << ")");
+ DCHECK(g_driver_gl.debug_fn.glLinkProgramFn != nullptr);
g_driver_gl.debug_fn.glLinkProgramFn(program);
}
@@ -3941,6 +4152,7 @@ static void* GL_BINDING_CALL Debug_glMapBuffer(GLenum target, GLenum access) {
GL_SERVICE_LOG("glMapBuffer"
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(access) << ")");
+ DCHECK(g_driver_gl.debug_fn.glMapBufferFn != nullptr);
void* result = g_driver_gl.debug_fn.glMapBufferFn(target, access);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -3953,6 +4165,7 @@ static void* GL_BINDING_CALL Debug_glMapBufferRange(GLenum target,
GL_SERVICE_LOG("glMapBufferRange"
<< "(" << GLEnums::GetStringEnum(target) << ", " << offset
<< ", " << length << ", " << access << ")");
+ DCHECK(g_driver_gl.debug_fn.glMapBufferRangeFn != nullptr);
void* result =
g_driver_gl.debug_fn.glMapBufferRangeFn(target, offset, length, access);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -3964,18 +4177,21 @@ static void GL_BINDING_CALL Debug_glMatrixLoadfEXT(GLenum matrixMode,
GL_SERVICE_LOG("glMatrixLoadfEXT"
<< "(" << GLEnums::GetStringEnum(matrixMode) << ", "
<< static_cast<const void*>(m) << ")");
+ DCHECK(g_driver_gl.debug_fn.glMatrixLoadfEXTFn != nullptr);
g_driver_gl.debug_fn.glMatrixLoadfEXTFn(matrixMode, m);
}
static void GL_BINDING_CALL Debug_glMatrixLoadIdentityEXT(GLenum matrixMode) {
GL_SERVICE_LOG("glMatrixLoadIdentityEXT"
<< "(" << GLEnums::GetStringEnum(matrixMode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glMatrixLoadIdentityEXTFn != nullptr);
g_driver_gl.debug_fn.glMatrixLoadIdentityEXTFn(matrixMode);
}
static void GL_BINDING_CALL Debug_glMemoryBarrierEXT(GLbitfield barriers) {
GL_SERVICE_LOG("glMemoryBarrierEXT"
<< "(" << barriers << ")");
+ DCHECK(g_driver_gl.debug_fn.glMemoryBarrierEXTFn != nullptr);
g_driver_gl.debug_fn.glMemoryBarrierEXTFn(barriers);
}
@@ -3990,6 +4206,7 @@ static void GL_BINDING_CALL Debug_glPathCommandsNV(GLuint path,
<< static_cast<const void*>(commands) << ", " << numCoords
<< ", " << GLEnums::GetStringEnum(coordType) << ", "
<< static_cast<const void*>(coords) << ")");
+ DCHECK(g_driver_gl.debug_fn.glPathCommandsNVFn != nullptr);
g_driver_gl.debug_fn.glPathCommandsNVFn(path, numCommands, commands,
numCoords, coordType, coords);
}
@@ -4000,6 +4217,7 @@ static void GL_BINDING_CALL Debug_glPathParameterfNV(GLuint path,
GL_SERVICE_LOG("glPathParameterfNV"
<< "(" << path << ", " << GLEnums::GetStringEnum(pname) << ", "
<< value << ")");
+ DCHECK(g_driver_gl.debug_fn.glPathParameterfNVFn != nullptr);
g_driver_gl.debug_fn.glPathParameterfNVFn(path, pname, value);
}
@@ -4009,6 +4227,7 @@ static void GL_BINDING_CALL Debug_glPathParameteriNV(GLuint path,
GL_SERVICE_LOG("glPathParameteriNV"
<< "(" << path << ", " << GLEnums::GetStringEnum(pname) << ", "
<< value << ")");
+ DCHECK(g_driver_gl.debug_fn.glPathParameteriNVFn != nullptr);
g_driver_gl.debug_fn.glPathParameteriNVFn(path, pname, value);
}
@@ -4018,6 +4237,7 @@ static void GL_BINDING_CALL Debug_glPathStencilFuncNV(GLenum func,
GL_SERVICE_LOG("glPathStencilFuncNV"
<< "(" << GLEnums::GetStringEnum(func) << ", " << ref << ", "
<< mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glPathStencilFuncNVFn != nullptr);
g_driver_gl.debug_fn.glPathStencilFuncNVFn(func, ref, mask);
}
@@ -4025,6 +4245,7 @@ static void GL_BINDING_CALL Debug_glPauseTransformFeedback(void) {
GL_SERVICE_LOG("glPauseTransformFeedback"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glPauseTransformFeedbackFn != nullptr);
g_driver_gl.debug_fn.glPauseTransformFeedbackFn();
}
@@ -4032,6 +4253,7 @@ static void GL_BINDING_CALL Debug_glPixelStorei(GLenum pname, GLint param) {
GL_SERVICE_LOG("glPixelStorei"
<< "(" << GLEnums::GetStringEnum(pname) << ", " << param
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glPixelStoreiFn != nullptr);
g_driver_gl.debug_fn.glPixelStoreiFn(pname, param);
}
@@ -4039,6 +4261,7 @@ static void GL_BINDING_CALL Debug_glPointParameteri(GLenum pname, GLint param) {
GL_SERVICE_LOG("glPointParameteri"
<< "(" << GLEnums::GetStringEnum(pname) << ", " << param
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glPointParameteriFn != nullptr);
g_driver_gl.debug_fn.glPointParameteriFn(pname, param);
}
@@ -4046,6 +4269,7 @@ static void GL_BINDING_CALL Debug_glPolygonOffset(GLfloat factor,
GLfloat units) {
GL_SERVICE_LOG("glPolygonOffset"
<< "(" << factor << ", " << units << ")");
+ DCHECK(g_driver_gl.debug_fn.glPolygonOffsetFn != nullptr);
g_driver_gl.debug_fn.glPolygonOffsetFn(factor, units);
}
@@ -4053,9 +4277,17 @@ static void GL_BINDING_CALL Debug_glPopGroupMarkerEXT(void) {
GL_SERVICE_LOG("glPopGroupMarkerEXT"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glPopGroupMarkerEXTFn != nullptr);
g_driver_gl.debug_fn.glPopGroupMarkerEXTFn();
}
+static void GL_BINDING_CALL Debug_glPrimitiveRestartIndex(GLuint index) {
+ GL_SERVICE_LOG("glPrimitiveRestartIndex"
+ << "(" << index << ")");
+ DCHECK(g_driver_gl.debug_fn.glPrimitiveRestartIndexFn != nullptr);
+ g_driver_gl.debug_fn.glPrimitiveRestartIndexFn(index);
+}
+
static void GL_BINDING_CALL Debug_glProgramBinary(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -4064,6 +4296,7 @@ static void GL_BINDING_CALL Debug_glProgramBinary(GLuint program,
<< "(" << program << ", "
<< GLEnums::GetStringEnum(binaryFormat) << ", "
<< static_cast<const void*>(binary) << ", " << length << ")");
+ DCHECK(g_driver_gl.debug_fn.glProgramBinaryFn != nullptr);
g_driver_gl.debug_fn.glProgramBinaryFn(program, binaryFormat, binary, length);
}
@@ -4073,6 +4306,7 @@ static void GL_BINDING_CALL Debug_glProgramParameteri(GLuint program,
GL_SERVICE_LOG("glProgramParameteri"
<< "(" << program << ", " << GLEnums::GetStringEnum(pname)
<< ", " << value << ")");
+ DCHECK(g_driver_gl.debug_fn.glProgramParameteriFn != nullptr);
g_driver_gl.debug_fn.glProgramParameteriFn(program, pname, value);
}
@@ -4086,6 +4320,7 @@ Debug_glProgramPathFragmentInputGenNV(GLuint program,
<< "(" << program << ", " << location << ", "
<< GLEnums::GetStringEnum(genMode) << ", " << components
<< ", " << static_cast<const void*>(coeffs) << ")");
+ DCHECK(g_driver_gl.debug_fn.glProgramPathFragmentInputGenNVFn != nullptr);
g_driver_gl.debug_fn.glProgramPathFragmentInputGenNVFn(
program, location, genMode, components, coeffs);
}
@@ -4094,18 +4329,21 @@ static void GL_BINDING_CALL Debug_glPushGroupMarkerEXT(GLsizei length,
const char* marker) {
GL_SERVICE_LOG("glPushGroupMarkerEXT"
<< "(" << length << ", " << marker << ")");
+ DCHECK(g_driver_gl.debug_fn.glPushGroupMarkerEXTFn != nullptr);
g_driver_gl.debug_fn.glPushGroupMarkerEXTFn(length, marker);
}
static void GL_BINDING_CALL Debug_glQueryCounter(GLuint id, GLenum target) {
GL_SERVICE_LOG("glQueryCounter"
<< "(" << id << ", " << GLEnums::GetStringEnum(target) << ")");
+ DCHECK(g_driver_gl.debug_fn.glQueryCounterFn != nullptr);
g_driver_gl.debug_fn.glQueryCounterFn(id, target);
}
static void GL_BINDING_CALL Debug_glReadBuffer(GLenum src) {
GL_SERVICE_LOG("glReadBuffer"
<< "(" << GLEnums::GetStringEnum(src) << ")");
+ DCHECK(g_driver_gl.debug_fn.glReadBufferFn != nullptr);
g_driver_gl.debug_fn.glReadBufferFn(src);
}
@@ -4121,6 +4359,7 @@ static void GL_BINDING_CALL Debug_glReadPixels(GLint x,
<< ", " << GLEnums::GetStringEnum(format) << ", "
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(pixels) << ")");
+ DCHECK(g_driver_gl.debug_fn.glReadPixelsFn != nullptr);
g_driver_gl.debug_fn.glReadPixelsFn(x, y, width, height, format, type,
pixels);
}
@@ -4129,6 +4368,7 @@ static void GL_BINDING_CALL Debug_glReleaseShaderCompiler(void) {
GL_SERVICE_LOG("glReleaseShaderCompiler"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glReleaseShaderCompilerFn != nullptr);
g_driver_gl.debug_fn.glReleaseShaderCompilerFn();
}
@@ -4141,6 +4381,7 @@ Debug_glRenderbufferStorageEXT(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(internalformat) << ", " << width
<< ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glRenderbufferStorageEXTFn != nullptr);
g_driver_gl.debug_fn.glRenderbufferStorageEXTFn(target, internalformat, width,
height);
}
@@ -4155,6 +4396,7 @@ Debug_glRenderbufferStorageMultisample(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << samples
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glRenderbufferStorageMultisampleFn != nullptr);
g_driver_gl.debug_fn.glRenderbufferStorageMultisampleFn(
target, samples, internalformat, width, height);
}
@@ -4169,6 +4411,8 @@ Debug_glRenderbufferStorageMultisampleANGLE(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << samples
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glRenderbufferStorageMultisampleANGLEFn !=
+ nullptr);
g_driver_gl.debug_fn.glRenderbufferStorageMultisampleANGLEFn(
target, samples, internalformat, width, height);
}
@@ -4183,6 +4427,7 @@ Debug_glRenderbufferStorageMultisampleEXT(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << samples
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glRenderbufferStorageMultisampleEXTFn != nullptr);
g_driver_gl.debug_fn.glRenderbufferStorageMultisampleEXTFn(
target, samples, internalformat, width, height);
}
@@ -4197,6 +4442,7 @@ Debug_glRenderbufferStorageMultisampleIMG(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << samples
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glRenderbufferStorageMultisampleIMGFn != nullptr);
g_driver_gl.debug_fn.glRenderbufferStorageMultisampleIMGFn(
target, samples, internalformat, width, height);
}
@@ -4205,6 +4451,7 @@ static void GL_BINDING_CALL Debug_glResumeTransformFeedback(void) {
GL_SERVICE_LOG("glResumeTransformFeedback"
<< "("
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glResumeTransformFeedbackFn != nullptr);
g_driver_gl.debug_fn.glResumeTransformFeedbackFn();
}
@@ -4213,6 +4460,7 @@ static void GL_BINDING_CALL Debug_glSampleCoverage(GLclampf value,
GL_SERVICE_LOG("glSampleCoverage"
<< "(" << value << ", " << GLEnums::GetStringBool(invert)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glSampleCoverageFn != nullptr);
g_driver_gl.debug_fn.glSampleCoverageFn(value, invert);
}
@@ -4222,6 +4470,7 @@ static void GL_BINDING_CALL Debug_glSamplerParameterf(GLuint sampler,
GL_SERVICE_LOG("glSamplerParameterf"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << param << ")");
+ DCHECK(g_driver_gl.debug_fn.glSamplerParameterfFn != nullptr);
g_driver_gl.debug_fn.glSamplerParameterfFn(sampler, pname, param);
}
@@ -4231,6 +4480,7 @@ static void GL_BINDING_CALL Debug_glSamplerParameterfv(GLuint sampler,
GL_SERVICE_LOG("glSamplerParameterfv"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glSamplerParameterfvFn != nullptr);
g_driver_gl.debug_fn.glSamplerParameterfvFn(sampler, pname, params);
}
@@ -4240,6 +4490,7 @@ static void GL_BINDING_CALL Debug_glSamplerParameteri(GLuint sampler,
GL_SERVICE_LOG("glSamplerParameteri"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << param << ")");
+ DCHECK(g_driver_gl.debug_fn.glSamplerParameteriFn != nullptr);
g_driver_gl.debug_fn.glSamplerParameteriFn(sampler, pname, param);
}
@@ -4249,6 +4500,7 @@ static void GL_BINDING_CALL Debug_glSamplerParameteriv(GLuint sampler,
GL_SERVICE_LOG("glSamplerParameteriv"
<< "(" << sampler << ", " << GLEnums::GetStringEnum(pname)
<< ", " << static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glSamplerParameterivFn != nullptr);
g_driver_gl.debug_fn.glSamplerParameterivFn(sampler, pname, params);
}
@@ -4259,12 +4511,14 @@ static void GL_BINDING_CALL Debug_glScissor(GLint x,
GL_SERVICE_LOG("glScissor"
<< "(" << x << ", " << y << ", " << width << ", " << height
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glScissorFn != nullptr);
g_driver_gl.debug_fn.glScissorFn(x, y, width, height);
}
static void GL_BINDING_CALL Debug_glSetFenceAPPLE(GLuint fence) {
GL_SERVICE_LOG("glSetFenceAPPLE"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glSetFenceAPPLEFn != nullptr);
g_driver_gl.debug_fn.glSetFenceAPPLEFn(fence);
}
@@ -4272,6 +4526,7 @@ static void GL_BINDING_CALL Debug_glSetFenceNV(GLuint fence, GLenum condition) {
GL_SERVICE_LOG("glSetFenceNV"
<< "(" << fence << ", " << GLEnums::GetStringEnum(condition)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glSetFenceNVFn != nullptr);
g_driver_gl.debug_fn.glSetFenceNVFn(fence, condition);
}
@@ -4284,6 +4539,7 @@ static void GL_BINDING_CALL Debug_glShaderBinary(GLsizei n,
<< "(" << n << ", " << static_cast<const void*>(shaders)
<< ", " << GLEnums::GetStringEnum(binaryformat) << ", "
<< static_cast<const void*>(binary) << ", " << length << ")");
+ DCHECK(g_driver_gl.debug_fn.glShaderBinaryFn != nullptr);
g_driver_gl.debug_fn.glShaderBinaryFn(n, shaders, binaryformat, binary,
length);
}
@@ -4296,6 +4552,7 @@ static void GL_BINDING_CALL Debug_glShaderSource(GLuint shader,
<< "(" << shader << ", " << count << ", "
<< static_cast<const void*>(str) << ", "
<< static_cast<const void*>(length) << ")");
+ DCHECK(g_driver_gl.debug_fn.glShaderSourceFn != nullptr);
g_driver_gl.debug_fn.glShaderSourceFn(shader, count, str, length);
GL_SERVICE_LOG_CODE_BLOCK({
@@ -4330,6 +4587,7 @@ Debug_glStencilFillPathInstancedNV(GLsizei numPaths,
<< GLEnums::GetStringEnum(fillMode) << ", " << mask << ", "
<< GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilFillPathInstancedNVFn != nullptr);
g_driver_gl.debug_fn.glStencilFillPathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType,
transformValues);
@@ -4341,6 +4599,7 @@ static void GL_BINDING_CALL Debug_glStencilFillPathNV(GLuint path,
GL_SERVICE_LOG("glStencilFillPathNV"
<< "(" << path << ", " << GLEnums::GetStringEnum(fillMode)
<< ", " << mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilFillPathNVFn != nullptr);
g_driver_gl.debug_fn.glStencilFillPathNVFn(path, fillMode, mask);
}
@@ -4350,6 +4609,7 @@ static void GL_BINDING_CALL Debug_glStencilFunc(GLenum func,
GL_SERVICE_LOG("glStencilFunc"
<< "(" << GLEnums::GetStringEnum(func) << ", " << ref << ", "
<< mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilFuncFn != nullptr);
g_driver_gl.debug_fn.glStencilFuncFn(func, ref, mask);
}
@@ -4361,12 +4621,14 @@ static void GL_BINDING_CALL Debug_glStencilFuncSeparate(GLenum face,
<< "(" << GLEnums::GetStringEnum(face) << ", "
<< GLEnums::GetStringEnum(func) << ", " << ref << ", " << mask
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilFuncSeparateFn != nullptr);
g_driver_gl.debug_fn.glStencilFuncSeparateFn(face, func, ref, mask);
}
static void GL_BINDING_CALL Debug_glStencilMask(GLuint mask) {
GL_SERVICE_LOG("glStencilMask"
<< "(" << mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilMaskFn != nullptr);
g_driver_gl.debug_fn.glStencilMaskFn(mask);
}
@@ -4374,6 +4636,7 @@ static void GL_BINDING_CALL Debug_glStencilMaskSeparate(GLenum face,
GLuint mask) {
GL_SERVICE_LOG("glStencilMaskSeparate"
<< "(" << GLEnums::GetStringEnum(face) << ", " << mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilMaskSeparateFn != nullptr);
g_driver_gl.debug_fn.glStencilMaskSeparateFn(face, mask);
}
@@ -4384,6 +4647,7 @@ static void GL_BINDING_CALL Debug_glStencilOp(GLenum fail,
<< "(" << GLEnums::GetStringEnum(fail) << ", "
<< GLEnums::GetStringEnum(zfail) << ", "
<< GLEnums::GetStringEnum(zpass) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilOpFn != nullptr);
g_driver_gl.debug_fn.glStencilOpFn(fail, zfail, zpass);
}
@@ -4396,6 +4660,7 @@ static void GL_BINDING_CALL Debug_glStencilOpSeparate(GLenum face,
<< GLEnums::GetStringEnum(fail) << ", "
<< GLEnums::GetStringEnum(zfail) << ", "
<< GLEnums::GetStringEnum(zpass) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilOpSeparateFn != nullptr);
g_driver_gl.debug_fn.glStencilOpSeparateFn(face, fail, zfail, zpass);
}
@@ -4414,6 +4679,7 @@ Debug_glStencilStrokePathInstancedNV(GLsizei numPaths,
<< static_cast<const void*>(paths) << ", " << pathBase << ", " << ref
<< ", " << mask << ", " << GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilStrokePathInstancedNVFn != nullptr);
g_driver_gl.debug_fn.glStencilStrokePathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, ref, mask, transformType,
transformValues);
@@ -4424,6 +4690,7 @@ static void GL_BINDING_CALL Debug_glStencilStrokePathNV(GLuint path,
GLuint mask) {
GL_SERVICE_LOG("glStencilStrokePathNV"
<< "(" << path << ", " << reference << ", " << mask << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilStrokePathNVFn != nullptr);
g_driver_gl.debug_fn.glStencilStrokePathNVFn(path, reference, mask);
}
@@ -4445,6 +4712,8 @@ Debug_glStencilThenCoverFillPathInstancedNV(GLsizei numPaths,
<< GLEnums::GetStringEnum(coverMode) << ", "
<< GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilThenCoverFillPathInstancedNVFn !=
+ nullptr);
g_driver_gl.debug_fn.glStencilThenCoverFillPathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode,
transformType, transformValues);
@@ -4459,6 +4728,7 @@ Debug_glStencilThenCoverFillPathNV(GLuint path,
<< "(" << path << ", " << GLEnums::GetStringEnum(fillMode)
<< ", " << mask << ", " << GLEnums::GetStringEnum(coverMode)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilThenCoverFillPathNVFn != nullptr);
g_driver_gl.debug_fn.glStencilThenCoverFillPathNVFn(path, fillMode, mask,
coverMode);
}
@@ -4480,6 +4750,8 @@ Debug_glStencilThenCoverStrokePathInstancedNV(GLsizei numPaths,
<< ", " << mask << ", " << GLEnums::GetStringEnum(coverMode) << ", "
<< GLEnums::GetStringEnum(transformType) << ", "
<< static_cast<const void*>(transformValues) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilThenCoverStrokePathInstancedNVFn !=
+ nullptr);
g_driver_gl.debug_fn.glStencilThenCoverStrokePathInstancedNVFn(
numPaths, pathNameType, paths, pathBase, ref, mask, coverMode,
transformType, transformValues);
@@ -4493,6 +4765,7 @@ Debug_glStencilThenCoverStrokePathNV(GLuint path,
GL_SERVICE_LOG("glStencilThenCoverStrokePathNV"
<< "(" << path << ", " << reference << ", " << mask << ", "
<< GLEnums::GetStringEnum(coverMode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glStencilThenCoverStrokePathNVFn != nullptr);
g_driver_gl.debug_fn.glStencilThenCoverStrokePathNVFn(path, reference, mask,
coverMode);
}
@@ -4500,6 +4773,7 @@ Debug_glStencilThenCoverStrokePathNV(GLuint path,
static GLboolean GL_BINDING_CALL Debug_glTestFenceAPPLE(GLuint fence) {
GL_SERVICE_LOG("glTestFenceAPPLE"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glTestFenceAPPLEFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glTestFenceAPPLEFn(fence);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -4508,6 +4782,7 @@ static GLboolean GL_BINDING_CALL Debug_glTestFenceAPPLE(GLuint fence) {
static GLboolean GL_BINDING_CALL Debug_glTestFenceNV(GLuint fence) {
GL_SERVICE_LOG("glTestFenceNV"
<< "(" << fence << ")");
+ DCHECK(g_driver_gl.debug_fn.glTestFenceNVFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glTestFenceNVFn(fence);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -4528,6 +4803,7 @@ static void GL_BINDING_CALL Debug_glTexImage2D(GLenum target,
<< ", " << border << ", " << GLEnums::GetStringEnum(format)
<< ", " << GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(pixels) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexImage2DFn != nullptr);
g_driver_gl.debug_fn.glTexImage2DFn(target, level, internalformat, width,
height, border, format, type, pixels);
}
@@ -4549,6 +4825,7 @@ static void GL_BINDING_CALL Debug_glTexImage3D(GLenum target,
<< GLEnums::GetStringEnum(format) << ", "
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(pixels) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexImage3DFn != nullptr);
g_driver_gl.debug_fn.glTexImage3DFn(target, level, internalformat, width,
height, depth, border, format, type,
pixels);
@@ -4560,6 +4837,7 @@ static void GL_BINDING_CALL Debug_glTexParameterf(GLenum target,
GL_SERVICE_LOG("glTexParameterf"
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", " << param << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexParameterfFn != nullptr);
g_driver_gl.debug_fn.glTexParameterfFn(target, pname, param);
}
@@ -4570,6 +4848,7 @@ static void GL_BINDING_CALL Debug_glTexParameterfv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexParameterfvFn != nullptr);
g_driver_gl.debug_fn.glTexParameterfvFn(target, pname, params);
}
@@ -4579,6 +4858,7 @@ static void GL_BINDING_CALL Debug_glTexParameteri(GLenum target,
GL_SERVICE_LOG("glTexParameteri"
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", " << param << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexParameteriFn != nullptr);
g_driver_gl.debug_fn.glTexParameteriFn(target, pname, param);
}
@@ -4589,6 +4869,7 @@ static void GL_BINDING_CALL Debug_glTexParameteriv(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", "
<< GLEnums::GetStringEnum(pname) << ", "
<< static_cast<const void*>(params) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexParameterivFn != nullptr);
g_driver_gl.debug_fn.glTexParameterivFn(target, pname, params);
}
@@ -4601,6 +4882,7 @@ static void GL_BINDING_CALL Debug_glTexStorage2DEXT(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << levels
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexStorage2DEXTFn != nullptr);
g_driver_gl.debug_fn.glTexStorage2DEXTFn(target, levels, internalformat,
width, height);
}
@@ -4615,6 +4897,7 @@ static void GL_BINDING_CALL Debug_glTexStorage3D(GLenum target,
<< "(" << GLEnums::GetStringEnum(target) << ", " << levels
<< ", " << GLEnums::GetStringEnum(internalformat) << ", "
<< width << ", " << height << ", " << depth << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexStorage3DFn != nullptr);
g_driver_gl.debug_fn.glTexStorage3DFn(target, levels, internalformat, width,
height, depth);
}
@@ -4634,6 +4917,7 @@ static void GL_BINDING_CALL Debug_glTexSubImage2D(GLenum target,
<< height << ", " << GLEnums::GetStringEnum(format) << ", "
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(pixels) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexSubImage2DFn != nullptr);
g_driver_gl.debug_fn.glTexSubImage2DFn(target, level, xoffset, yoffset, width,
height, format, type, pixels);
}
@@ -4656,6 +4940,7 @@ static void GL_BINDING_CALL Debug_glTexSubImage3D(GLenum target,
<< GLEnums::GetStringEnum(format) << ", "
<< GLEnums::GetStringEnum(type) << ", "
<< static_cast<const void*>(pixels) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTexSubImage3DFn != nullptr);
g_driver_gl.debug_fn.glTexSubImage3DFn(target, level, xoffset, yoffset,
zoffset, width, height, depth, format,
type, pixels);
@@ -4670,6 +4955,7 @@ Debug_glTransformFeedbackVaryings(GLuint program,
<< "(" << program << ", " << count << ", "
<< static_cast<const void*>(varyings) << ", "
<< GLEnums::GetStringEnum(bufferMode) << ")");
+ DCHECK(g_driver_gl.debug_fn.glTransformFeedbackVaryingsFn != nullptr);
g_driver_gl.debug_fn.glTransformFeedbackVaryingsFn(program, count, varyings,
bufferMode);
}
@@ -4677,6 +4963,7 @@ Debug_glTransformFeedbackVaryings(GLuint program,
static void GL_BINDING_CALL Debug_glUniform1f(GLint location, GLfloat x) {
GL_SERVICE_LOG("glUniform1f"
<< "(" << location << ", " << x << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1fFn != nullptr);
g_driver_gl.debug_fn.glUniform1fFn(location, x);
}
@@ -4686,12 +4973,14 @@ static void GL_BINDING_CALL Debug_glUniform1fv(GLint location,
GL_SERVICE_LOG("glUniform1fv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1fvFn != nullptr);
g_driver_gl.debug_fn.glUniform1fvFn(location, count, v);
}
static void GL_BINDING_CALL Debug_glUniform1i(GLint location, GLint x) {
GL_SERVICE_LOG("glUniform1i"
<< "(" << location << ", " << x << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1iFn != nullptr);
g_driver_gl.debug_fn.glUniform1iFn(location, x);
}
@@ -4701,12 +4990,14 @@ static void GL_BINDING_CALL Debug_glUniform1iv(GLint location,
GL_SERVICE_LOG("glUniform1iv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1ivFn != nullptr);
g_driver_gl.debug_fn.glUniform1ivFn(location, count, v);
}
static void GL_BINDING_CALL Debug_glUniform1ui(GLint location, GLuint v0) {
GL_SERVICE_LOG("glUniform1ui"
<< "(" << location << ", " << v0 << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1uiFn != nullptr);
g_driver_gl.debug_fn.glUniform1uiFn(location, v0);
}
@@ -4716,6 +5007,7 @@ static void GL_BINDING_CALL Debug_glUniform1uiv(GLint location,
GL_SERVICE_LOG("glUniform1uiv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform1uivFn != nullptr);
g_driver_gl.debug_fn.glUniform1uivFn(location, count, v);
}
@@ -4724,6 +5016,7 @@ static void GL_BINDING_CALL Debug_glUniform2f(GLint location,
GLfloat y) {
GL_SERVICE_LOG("glUniform2f"
<< "(" << location << ", " << x << ", " << y << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2fFn != nullptr);
g_driver_gl.debug_fn.glUniform2fFn(location, x, y);
}
@@ -4733,6 +5026,7 @@ static void GL_BINDING_CALL Debug_glUniform2fv(GLint location,
GL_SERVICE_LOG("glUniform2fv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2fvFn != nullptr);
g_driver_gl.debug_fn.glUniform2fvFn(location, count, v);
}
@@ -4741,6 +5035,7 @@ static void GL_BINDING_CALL Debug_glUniform2i(GLint location,
GLint y) {
GL_SERVICE_LOG("glUniform2i"
<< "(" << location << ", " << x << ", " << y << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2iFn != nullptr);
g_driver_gl.debug_fn.glUniform2iFn(location, x, y);
}
@@ -4750,6 +5045,7 @@ static void GL_BINDING_CALL Debug_glUniform2iv(GLint location,
GL_SERVICE_LOG("glUniform2iv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2ivFn != nullptr);
g_driver_gl.debug_fn.glUniform2ivFn(location, count, v);
}
@@ -4758,6 +5054,7 @@ static void GL_BINDING_CALL Debug_glUniform2ui(GLint location,
GLuint v1) {
GL_SERVICE_LOG("glUniform2ui"
<< "(" << location << ", " << v0 << ", " << v1 << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2uiFn != nullptr);
g_driver_gl.debug_fn.glUniform2uiFn(location, v0, v1);
}
@@ -4767,6 +5064,7 @@ static void GL_BINDING_CALL Debug_glUniform2uiv(GLint location,
GL_SERVICE_LOG("glUniform2uiv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform2uivFn != nullptr);
g_driver_gl.debug_fn.glUniform2uivFn(location, count, v);
}
@@ -4777,6 +5075,7 @@ static void GL_BINDING_CALL Debug_glUniform3f(GLint location,
GL_SERVICE_LOG("glUniform3f"
<< "(" << location << ", " << x << ", " << y << ", " << z
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3fFn != nullptr);
g_driver_gl.debug_fn.glUniform3fFn(location, x, y, z);
}
@@ -4786,6 +5085,7 @@ static void GL_BINDING_CALL Debug_glUniform3fv(GLint location,
GL_SERVICE_LOG("glUniform3fv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3fvFn != nullptr);
g_driver_gl.debug_fn.glUniform3fvFn(location, count, v);
}
@@ -4796,6 +5096,7 @@ static void GL_BINDING_CALL Debug_glUniform3i(GLint location,
GL_SERVICE_LOG("glUniform3i"
<< "(" << location << ", " << x << ", " << y << ", " << z
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3iFn != nullptr);
g_driver_gl.debug_fn.glUniform3iFn(location, x, y, z);
}
@@ -4805,6 +5106,7 @@ static void GL_BINDING_CALL Debug_glUniform3iv(GLint location,
GL_SERVICE_LOG("glUniform3iv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3ivFn != nullptr);
g_driver_gl.debug_fn.glUniform3ivFn(location, count, v);
}
@@ -4815,6 +5117,7 @@ static void GL_BINDING_CALL Debug_glUniform3ui(GLint location,
GL_SERVICE_LOG("glUniform3ui"
<< "(" << location << ", " << v0 << ", " << v1 << ", " << v2
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3uiFn != nullptr);
g_driver_gl.debug_fn.glUniform3uiFn(location, v0, v1, v2);
}
@@ -4824,6 +5127,7 @@ static void GL_BINDING_CALL Debug_glUniform3uiv(GLint location,
GL_SERVICE_LOG("glUniform3uiv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform3uivFn != nullptr);
g_driver_gl.debug_fn.glUniform3uivFn(location, count, v);
}
@@ -4832,6 +5136,7 @@ Debug_glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
GL_SERVICE_LOG("glUniform4f"
<< "(" << location << ", " << x << ", " << y << ", " << z
<< ", " << w << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4fFn != nullptr);
g_driver_gl.debug_fn.glUniform4fFn(location, x, y, z, w);
}
@@ -4841,6 +5146,7 @@ static void GL_BINDING_CALL Debug_glUniform4fv(GLint location,
GL_SERVICE_LOG("glUniform4fv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4fvFn != nullptr);
g_driver_gl.debug_fn.glUniform4fvFn(location, count, v);
}
@@ -4849,6 +5155,7 @@ Debug_glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) {
GL_SERVICE_LOG("glUniform4i"
<< "(" << location << ", " << x << ", " << y << ", " << z
<< ", " << w << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4iFn != nullptr);
g_driver_gl.debug_fn.glUniform4iFn(location, x, y, z, w);
}
@@ -4858,6 +5165,7 @@ static void GL_BINDING_CALL Debug_glUniform4iv(GLint location,
GL_SERVICE_LOG("glUniform4iv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4ivFn != nullptr);
g_driver_gl.debug_fn.glUniform4ivFn(location, count, v);
}
@@ -4866,6 +5174,7 @@ Debug_glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
GL_SERVICE_LOG("glUniform4ui"
<< "(" << location << ", " << v0 << ", " << v1 << ", " << v2
<< ", " << v3 << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4uiFn != nullptr);
g_driver_gl.debug_fn.glUniform4uiFn(location, v0, v1, v2, v3);
}
@@ -4875,6 +5184,7 @@ static void GL_BINDING_CALL Debug_glUniform4uiv(GLint location,
GL_SERVICE_LOG("glUniform4uiv"
<< "(" << location << ", " << count << ", "
<< static_cast<const void*>(v) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniform4uivFn != nullptr);
g_driver_gl.debug_fn.glUniform4uivFn(location, count, v);
}
@@ -4885,6 +5195,7 @@ Debug_glUniformBlockBinding(GLuint program,
GL_SERVICE_LOG("glUniformBlockBinding"
<< "(" << program << ", " << uniformBlockIndex << ", "
<< uniformBlockBinding << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformBlockBindingFn != nullptr);
g_driver_gl.debug_fn.glUniformBlockBindingFn(program, uniformBlockIndex,
uniformBlockBinding);
}
@@ -4897,6 +5208,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix2fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix2fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix2fvFn(location, count, transpose, value);
}
@@ -4908,6 +5220,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix2x3fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix2x3fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix2x3fvFn(location, count, transpose,
value);
}
@@ -4920,6 +5233,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix2x4fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix2x4fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix2x4fvFn(location, count, transpose,
value);
}
@@ -4932,6 +5246,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix3fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix3fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix3fvFn(location, count, transpose, value);
}
@@ -4943,6 +5258,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix3x2fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix3x2fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix3x2fvFn(location, count, transpose,
value);
}
@@ -4955,6 +5271,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix3x4fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix3x4fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix3x4fvFn(location, count, transpose,
value);
}
@@ -4967,6 +5284,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix4fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix4fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix4fvFn(location, count, transpose, value);
}
@@ -4978,6 +5296,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix4x2fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix4x2fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix4x2fvFn(location, count, transpose,
value);
}
@@ -4990,6 +5309,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix4x3fv(GLint location,
<< "(" << location << ", " << count << ", "
<< GLEnums::GetStringBool(transpose) << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUniformMatrix4x3fvFn != nullptr);
g_driver_gl.debug_fn.glUniformMatrix4x3fvFn(location, count, transpose,
value);
}
@@ -4997,6 +5317,7 @@ static void GL_BINDING_CALL Debug_glUniformMatrix4x3fv(GLint location,
static GLboolean GL_BINDING_CALL Debug_glUnmapBuffer(GLenum target) {
GL_SERVICE_LOG("glUnmapBuffer"
<< "(" << GLEnums::GetStringEnum(target) << ")");
+ DCHECK(g_driver_gl.debug_fn.glUnmapBufferFn != nullptr);
GLboolean result = g_driver_gl.debug_fn.glUnmapBufferFn(target);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -5005,18 +5326,21 @@ static GLboolean GL_BINDING_CALL Debug_glUnmapBuffer(GLenum target) {
static void GL_BINDING_CALL Debug_glUseProgram(GLuint program) {
GL_SERVICE_LOG("glUseProgram"
<< "(" << program << ")");
+ DCHECK(g_driver_gl.debug_fn.glUseProgramFn != nullptr);
g_driver_gl.debug_fn.glUseProgramFn(program);
}
static void GL_BINDING_CALL Debug_glValidateProgram(GLuint program) {
GL_SERVICE_LOG("glValidateProgram"
<< "(" << program << ")");
+ DCHECK(g_driver_gl.debug_fn.glValidateProgramFn != nullptr);
g_driver_gl.debug_fn.glValidateProgramFn(program);
}
static void GL_BINDING_CALL Debug_glVertexAttrib1f(GLuint indx, GLfloat x) {
GL_SERVICE_LOG("glVertexAttrib1f"
<< "(" << indx << ", " << x << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib1fFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib1fFn(indx, x);
}
@@ -5025,6 +5349,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib1fv(GLuint indx,
GL_SERVICE_LOG("glVertexAttrib1fv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib1fvFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib1fvFn(indx, values);
}
@@ -5033,6 +5358,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib2f(GLuint indx,
GLfloat y) {
GL_SERVICE_LOG("glVertexAttrib2f"
<< "(" << indx << ", " << x << ", " << y << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib2fFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib2fFn(indx, x, y);
}
@@ -5041,6 +5367,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib2fv(GLuint indx,
GL_SERVICE_LOG("glVertexAttrib2fv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib2fvFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib2fvFn(indx, values);
}
@@ -5050,6 +5377,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib3f(GLuint indx,
GLfloat z) {
GL_SERVICE_LOG("glVertexAttrib3f"
<< "(" << indx << ", " << x << ", " << y << ", " << z << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib3fFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib3fFn(indx, x, y, z);
}
@@ -5058,6 +5386,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib3fv(GLuint indx,
GL_SERVICE_LOG("glVertexAttrib3fv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib3fvFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib3fvFn(indx, values);
}
@@ -5069,6 +5398,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib4f(GLuint indx,
GL_SERVICE_LOG("glVertexAttrib4f"
<< "(" << indx << ", " << x << ", " << y << ", " << z << ", "
<< w << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib4fFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib4fFn(indx, x, y, z, w);
}
@@ -5077,6 +5407,7 @@ static void GL_BINDING_CALL Debug_glVertexAttrib4fv(GLuint indx,
GL_SERVICE_LOG("glVertexAttrib4fv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttrib4fvFn != nullptr);
g_driver_gl.debug_fn.glVertexAttrib4fvFn(indx, values);
}
@@ -5084,6 +5415,7 @@ static void GL_BINDING_CALL Debug_glVertexAttribDivisorANGLE(GLuint index,
GLuint divisor) {
GL_SERVICE_LOG("glVertexAttribDivisorANGLE"
<< "(" << index << ", " << divisor << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribDivisorANGLEFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribDivisorANGLEFn(index, divisor);
}
@@ -5092,6 +5424,7 @@ Debug_glVertexAttribI4i(GLuint indx, GLint x, GLint y, GLint z, GLint w) {
GL_SERVICE_LOG("glVertexAttribI4i"
<< "(" << indx << ", " << x << ", " << y << ", " << z << ", "
<< w << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribI4iFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribI4iFn(indx, x, y, z, w);
}
@@ -5100,6 +5433,7 @@ static void GL_BINDING_CALL Debug_glVertexAttribI4iv(GLuint indx,
GL_SERVICE_LOG("glVertexAttribI4iv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribI4ivFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribI4ivFn(indx, values);
}
@@ -5108,6 +5442,7 @@ Debug_glVertexAttribI4ui(GLuint indx, GLuint x, GLuint y, GLuint z, GLuint w) {
GL_SERVICE_LOG("glVertexAttribI4ui"
<< "(" << indx << ", " << x << ", " << y << ", " << z << ", "
<< w << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribI4uiFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribI4uiFn(indx, x, y, z, w);
}
@@ -5116,6 +5451,7 @@ static void GL_BINDING_CALL Debug_glVertexAttribI4uiv(GLuint indx,
GL_SERVICE_LOG("glVertexAttribI4uiv"
<< "(" << indx << ", " << static_cast<const void*>(values)
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribI4uivFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribI4uivFn(indx, values);
}
@@ -5128,6 +5464,7 @@ static void GL_BINDING_CALL Debug_glVertexAttribIPointer(GLuint indx,
<< "(" << indx << ", " << size << ", "
<< GLEnums::GetStringEnum(type) << ", " << stride << ", "
<< static_cast<const void*>(ptr) << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribIPointerFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribIPointerFn(indx, size, type, stride, ptr);
}
@@ -5142,6 +5479,7 @@ static void GL_BINDING_CALL Debug_glVertexAttribPointer(GLuint indx,
<< GLEnums::GetStringEnum(type) << ", "
<< GLEnums::GetStringBool(normalized) << ", " << stride << ", "
<< static_cast<const void*>(ptr) << ")");
+ DCHECK(g_driver_gl.debug_fn.glVertexAttribPointerFn != nullptr);
g_driver_gl.debug_fn.glVertexAttribPointerFn(indx, size, type, normalized,
stride, ptr);
}
@@ -5153,6 +5491,7 @@ static void GL_BINDING_CALL Debug_glViewport(GLint x,
GL_SERVICE_LOG("glViewport"
<< "(" << x << ", " << y << ", " << width << ", " << height
<< ")");
+ DCHECK(g_driver_gl.debug_fn.glViewportFn != nullptr);
g_driver_gl.debug_fn.glViewportFn(x, y, width, height);
}
@@ -5161,6 +5500,7 @@ static GLenum GL_BINDING_CALL Debug_glWaitSync(GLsync sync,
GLuint64 timeout) {
GL_SERVICE_LOG("glWaitSync"
<< "(" << sync << ", " << flags << ", " << timeout << ")");
+ DCHECK(g_driver_gl.debug_fn.glWaitSyncFn != nullptr);
GLenum result = g_driver_gl.debug_fn.glWaitSyncFn(sync, flags, timeout);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -6024,6 +6364,10 @@ void DriverGL::InitializeDebugBindings() {
debug_fn.glPopGroupMarkerEXTFn = fn.glPopGroupMarkerEXTFn;
fn.glPopGroupMarkerEXTFn = Debug_glPopGroupMarkerEXT;
}
+ if (!debug_fn.glPrimitiveRestartIndexFn) {
+ debug_fn.glPrimitiveRestartIndexFn = fn.glPrimitiveRestartIndexFn;
+ fn.glPrimitiveRestartIndexFn = Debug_glPrimitiveRestartIndex;
+ }
if (!debug_fn.glProgramBinaryFn) {
debug_fn.glProgramBinaryFn = fn.glProgramBinaryFn;
fn.glProgramBinaryFn = Debug_glProgramBinary;
@@ -7673,6 +8017,10 @@ void GLApiBase::glPopGroupMarkerEXTFn(void) {
driver_->fn.glPopGroupMarkerEXTFn();
}
+void GLApiBase::glPrimitiveRestartIndexFn(GLuint index) {
+ driver_->fn.glPrimitiveRestartIndexFn(index);
+}
+
void GLApiBase::glProgramBinaryFn(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -9786,6 +10134,11 @@ void TraceGLApi::glPopGroupMarkerEXTFn(void) {
gl_api_->glPopGroupMarkerEXTFn();
}
+void TraceGLApi::glPrimitiveRestartIndexFn(GLuint index) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glPrimitiveRestartIndex")
+ gl_api_->glPrimitiveRestartIndexFn(index);
+}
+
void TraceGLApi::glProgramBinaryFn(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -12251,6 +12604,13 @@ void NoContextGLApi::glPopGroupMarkerEXTFn(void) {
<< "Trying to call glPopGroupMarkerEXT() without current GL context";
}
+void NoContextGLApi::glPrimitiveRestartIndexFn(GLuint index) {
+ NOTREACHED()
+ << "Trying to call glPrimitiveRestartIndex() without current GL context";
+ LOG(ERROR)
+ << "Trying to call glPrimitiveRestartIndex() without current GL context";
+}
+
void NoContextGLApi::glProgramBinaryFn(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.h b/chromium/ui/gl/gl_bindings_autogen_gl.h
index 9e0ae429b74..28393dca3f4 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.h
@@ -637,6 +637,7 @@ typedef void(GL_BINDING_CALL* glPointParameteriProc)(GLenum pname, GLint param);
typedef void(GL_BINDING_CALL* glPolygonOffsetProc)(GLfloat factor,
GLfloat units);
typedef void(GL_BINDING_CALL* glPopGroupMarkerEXTProc)(void);
+typedef void(GL_BINDING_CALL* glPrimitiveRestartIndexProc)(GLuint index);
typedef void(GL_BINDING_CALL* glProgramBinaryProc)(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -1075,6 +1076,7 @@ struct ExtensionsGL {
bool b_GL_EXT_shader_image_load_store;
bool b_GL_EXT_texture_storage;
bool b_GL_EXT_timer_query;
+ bool b_GL_EXT_unpack_subimage;
bool b_GL_IMG_multisampled_render_to_texture;
bool b_GL_INTEL_framebuffer_CMAA;
bool b_GL_KHR_blend_equation_advanced;
@@ -1305,6 +1307,7 @@ struct ProcsGL {
glPointParameteriProc glPointParameteriFn;
glPolygonOffsetProc glPolygonOffsetFn;
glPopGroupMarkerEXTProc glPopGroupMarkerEXTFn;
+ glPrimitiveRestartIndexProc glPrimitiveRestartIndexFn;
glProgramBinaryProc glProgramBinaryFn;
glProgramParameteriProc glProgramParameteriFn;
glProgramPathFragmentInputGenNVProc glProgramPathFragmentInputGenNVFn;
@@ -1963,6 +1966,7 @@ class GL_EXPORT GLApi {
virtual void glPointParameteriFn(GLenum pname, GLint param) = 0;
virtual void glPolygonOffsetFn(GLfloat factor, GLfloat units) = 0;
virtual void glPopGroupMarkerEXTFn(void) = 0;
+ virtual void glPrimitiveRestartIndexFn(GLuint index) = 0;
virtual void glProgramBinaryFn(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -2600,6 +2604,8 @@ class GL_EXPORT GLApi {
#define glPointParameteri ::gfx::g_current_gl_context->glPointParameteriFn
#define glPolygonOffset ::gfx::g_current_gl_context->glPolygonOffsetFn
#define glPopGroupMarkerEXT ::gfx::g_current_gl_context->glPopGroupMarkerEXTFn
+#define glPrimitiveRestartIndex \
+ ::gfx::g_current_gl_context->glPrimitiveRestartIndexFn
#define glProgramBinary ::gfx::g_current_gl_context->glProgramBinaryFn
#define glProgramParameteri ::gfx::g_current_gl_context->glProgramParameteriFn
#define glProgramPathFragmentInputGenNV \
diff --git a/chromium/ui/gl/gl_bindings_autogen_glx.cc b/chromium/ui/gl/gl_bindings_autogen_glx.cc
index 02aee398e4f..819cd0149d4 100644
--- a/chromium/ui/gl/gl_bindings_autogen_glx.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_glx.cc
@@ -212,6 +212,7 @@ static void GL_BINDING_CALL Debug_glXBindTexImageEXT(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << buffer << ", "
<< static_cast<const void*>(attribList) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXBindTexImageEXTFn != nullptr);
g_driver_glx.debug_fn.glXBindTexImageEXTFn(dpy, drawable, buffer, attribList);
}
@@ -224,6 +225,7 @@ Debug_glXChooseFBConfig(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << screen
<< ", " << static_cast<const void*>(attribList) << ", "
<< static_cast<const void*>(nitems) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXChooseFBConfigFn != nullptr);
GLXFBConfig* result = g_driver_glx.debug_fn.glXChooseFBConfigFn(
dpy, screen, attribList, nitems);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -236,6 +238,7 @@ static XVisualInfo* GL_BINDING_CALL Debug_glXChooseVisual(Display* dpy,
GL_SERVICE_LOG("glXChooseVisual"
<< "(" << static_cast<const void*>(dpy) << ", " << screen
<< ", " << static_cast<const void*>(attribList) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXChooseVisualFn != nullptr);
XVisualInfo* result =
g_driver_glx.debug_fn.glXChooseVisualFn(dpy, screen, attribList);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -249,6 +252,7 @@ static void GL_BINDING_CALL Debug_glXCopyContext(Display* dpy,
GL_SERVICE_LOG("glXCopyContext"
<< "(" << static_cast<const void*>(dpy) << ", " << src << ", "
<< dst << ", " << mask << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCopyContextFn != nullptr);
g_driver_glx.debug_fn.glXCopyContextFn(dpy, src, dst, mask);
}
@@ -262,6 +266,7 @@ static void GL_BINDING_CALL Debug_glXCopySubBufferMESA(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << x << ", " << y << ", " << width << ", " << height
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXCopySubBufferMESAFn != nullptr);
g_driver_glx.debug_fn.glXCopySubBufferMESAFn(dpy, drawable, x, y, width,
height);
}
@@ -274,6 +279,7 @@ static GLXContext GL_BINDING_CALL Debug_glXCreateContext(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(vis) << ", " << shareList << ", "
<< direct << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreateContextFn != nullptr);
GLXContext result =
g_driver_glx.debug_fn.glXCreateContextFn(dpy, vis, shareList, direct);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -290,6 +296,7 @@ Debug_glXCreateContextAttribsARB(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << share_context << ", " << direct << ", "
<< static_cast<const void*>(attrib_list) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreateContextAttribsARBFn != nullptr);
GLXContext result = g_driver_glx.debug_fn.glXCreateContextAttribsARBFn(
dpy, config, share_context, direct, attrib_list);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -302,6 +309,7 @@ static GLXPixmap GL_BINDING_CALL Debug_glXCreateGLXPixmap(Display* dpy,
GL_SERVICE_LOG("glXCreateGLXPixmap"
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(visual) << ", " << pixmap << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreateGLXPixmapFn != nullptr);
GLXPixmap result =
g_driver_glx.debug_fn.glXCreateGLXPixmapFn(dpy, visual, pixmap);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -318,6 +326,7 @@ Debug_glXCreateNewContext(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << renderType << ", " << shareList << ", " << direct
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreateNewContextFn != nullptr);
GLXContext result = g_driver_glx.debug_fn.glXCreateNewContextFn(
dpy, config, renderType, shareList, direct);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -331,6 +340,7 @@ Debug_glXCreatePbuffer(Display* dpy,
GL_SERVICE_LOG("glXCreatePbuffer"
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << static_cast<const void*>(attribList) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreatePbufferFn != nullptr);
GLXPbuffer result =
g_driver_glx.debug_fn.glXCreatePbufferFn(dpy, config, attribList);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -345,6 +355,7 @@ static GLXPixmap GL_BINDING_CALL Debug_glXCreatePixmap(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << pixmap << ", "
<< static_cast<const void*>(attribList) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreatePixmapFn != nullptr);
GLXPixmap result =
g_driver_glx.debug_fn.glXCreatePixmapFn(dpy, config, pixmap, attribList);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -359,6 +370,7 @@ static GLXWindow GL_BINDING_CALL Debug_glXCreateWindow(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << win << ", " << static_cast<const void*>(attribList)
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXCreateWindowFn != nullptr);
GLXWindow result =
g_driver_glx.debug_fn.glXCreateWindowFn(dpy, config, win, attribList);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -369,6 +381,7 @@ static void GL_BINDING_CALL Debug_glXDestroyContext(Display* dpy,
GLXContext ctx) {
GL_SERVICE_LOG("glXDestroyContext"
<< "(" << static_cast<const void*>(dpy) << ", " << ctx << ")");
+ DCHECK(g_driver_glx.debug_fn.glXDestroyContextFn != nullptr);
g_driver_glx.debug_fn.glXDestroyContextFn(dpy, ctx);
}
@@ -377,6 +390,7 @@ static void GL_BINDING_CALL Debug_glXDestroyGLXPixmap(Display* dpy,
GL_SERVICE_LOG("glXDestroyGLXPixmap"
<< "(" << static_cast<const void*>(dpy) << ", " << pixmap
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXDestroyGLXPixmapFn != nullptr);
g_driver_glx.debug_fn.glXDestroyGLXPixmapFn(dpy, pixmap);
}
@@ -385,6 +399,7 @@ static void GL_BINDING_CALL Debug_glXDestroyPbuffer(Display* dpy,
GL_SERVICE_LOG("glXDestroyPbuffer"
<< "(" << static_cast<const void*>(dpy) << ", " << pbuf
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXDestroyPbufferFn != nullptr);
g_driver_glx.debug_fn.glXDestroyPbufferFn(dpy, pbuf);
}
@@ -393,6 +408,7 @@ static void GL_BINDING_CALL Debug_glXDestroyPixmap(Display* dpy,
GL_SERVICE_LOG("glXDestroyPixmap"
<< "(" << static_cast<const void*>(dpy) << ", " << pixmap
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXDestroyPixmapFn != nullptr);
g_driver_glx.debug_fn.glXDestroyPixmapFn(dpy, pixmap);
}
@@ -401,6 +417,7 @@ static void GL_BINDING_CALL Debug_glXDestroyWindow(Display* dpy,
GL_SERVICE_LOG("glXDestroyWindow"
<< "(" << static_cast<const void*>(dpy) << ", " << window
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXDestroyWindowFn != nullptr);
g_driver_glx.debug_fn.glXDestroyWindowFn(dpy, window);
}
@@ -409,6 +426,7 @@ static const char* GL_BINDING_CALL Debug_glXGetClientString(Display* dpy,
GL_SERVICE_LOG("glXGetClientString"
<< "(" << static_cast<const void*>(dpy) << ", " << name
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetClientStringFn != nullptr);
const char* result = g_driver_glx.debug_fn.glXGetClientStringFn(dpy, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -422,6 +440,7 @@ static int GL_BINDING_CALL Debug_glXGetConfig(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(visual) << ", " << attrib << ", "
<< static_cast<const void*>(value) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetConfigFn != nullptr);
int result = g_driver_glx.debug_fn.glXGetConfigFn(dpy, visual, attrib, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -431,6 +450,7 @@ static GLXContext GL_BINDING_CALL Debug_glXGetCurrentContext(void) {
GL_SERVICE_LOG("glXGetCurrentContext"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetCurrentContextFn != nullptr);
GLXContext result = g_driver_glx.debug_fn.glXGetCurrentContextFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -440,6 +460,7 @@ static Display* GL_BINDING_CALL Debug_glXGetCurrentDisplay(void) {
GL_SERVICE_LOG("glXGetCurrentDisplay"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetCurrentDisplayFn != nullptr);
Display* result = g_driver_glx.debug_fn.glXGetCurrentDisplayFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -449,6 +470,7 @@ static GLXDrawable GL_BINDING_CALL Debug_glXGetCurrentDrawable(void) {
GL_SERVICE_LOG("glXGetCurrentDrawable"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetCurrentDrawableFn != nullptr);
GLXDrawable result = g_driver_glx.debug_fn.glXGetCurrentDrawableFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -458,6 +480,7 @@ static GLXDrawable GL_BINDING_CALL Debug_glXGetCurrentReadDrawable(void) {
GL_SERVICE_LOG("glXGetCurrentReadDrawable"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetCurrentReadDrawableFn != nullptr);
GLXDrawable result = g_driver_glx.debug_fn.glXGetCurrentReadDrawableFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -471,6 +494,7 @@ static int GL_BINDING_CALL Debug_glXGetFBConfigAttrib(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ", " << attribute << ", " << static_cast<const void*>(value)
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetFBConfigAttribFn != nullptr);
int result = g_driver_glx.debug_fn.glXGetFBConfigAttribFn(dpy, config,
attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -482,6 +506,7 @@ Debug_glXGetFBConfigFromVisualSGIX(Display* dpy, XVisualInfo* visualInfo) {
GL_SERVICE_LOG("glXGetFBConfigFromVisualSGIX"
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(visualInfo) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetFBConfigFromVisualSGIXFn != nullptr);
GLXFBConfig result =
g_driver_glx.debug_fn.glXGetFBConfigFromVisualSGIXFn(dpy, visualInfo);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -494,6 +519,7 @@ static GLXFBConfig* GL_BINDING_CALL Debug_glXGetFBConfigs(Display* dpy,
GL_SERVICE_LOG("glXGetFBConfigs"
<< "(" << static_cast<const void*>(dpy) << ", " << screen
<< ", " << static_cast<const void*>(nelements) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetFBConfigsFn != nullptr);
GLXFBConfig* result =
g_driver_glx.debug_fn.glXGetFBConfigsFn(dpy, screen, nelements);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -508,6 +534,7 @@ static bool GL_BINDING_CALL Debug_glXGetMscRateOML(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << static_cast<const void*>(numerator) << ", "
<< static_cast<const void*>(denominator) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetMscRateOMLFn != nullptr);
bool result = g_driver_glx.debug_fn.glXGetMscRateOMLFn(
dpy, drawable, numerator, denominator);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -520,6 +547,7 @@ static void GL_BINDING_CALL Debug_glXGetSelectedEvent(Display* dpy,
GL_SERVICE_LOG("glXGetSelectedEvent"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << static_cast<const void*>(mask) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetSelectedEventFn != nullptr);
g_driver_glx.debug_fn.glXGetSelectedEventFn(dpy, drawable, mask);
}
@@ -533,6 +561,7 @@ static bool GL_BINDING_CALL Debug_glXGetSyncValuesOML(Display* dpy,
<< ", " << static_cast<const void*>(ust) << ", "
<< static_cast<const void*>(msc) << ", "
<< static_cast<const void*>(sbc) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetSyncValuesOMLFn != nullptr);
bool result =
g_driver_glx.debug_fn.glXGetSyncValuesOMLFn(dpy, drawable, ust, msc, sbc);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -544,6 +573,7 @@ Debug_glXGetVisualFromFBConfig(Display* dpy, GLXFBConfig config) {
GL_SERVICE_LOG("glXGetVisualFromFBConfig"
<< "(" << static_cast<const void*>(dpy) << ", " << config
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXGetVisualFromFBConfigFn != nullptr);
XVisualInfo* result =
g_driver_glx.debug_fn.glXGetVisualFromFBConfigFn(dpy, config);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -553,6 +583,7 @@ Debug_glXGetVisualFromFBConfig(Display* dpy, GLXFBConfig config) {
static int GL_BINDING_CALL Debug_glXIsDirect(Display* dpy, GLXContext ctx) {
GL_SERVICE_LOG("glXIsDirect"
<< "(" << static_cast<const void*>(dpy) << ", " << ctx << ")");
+ DCHECK(g_driver_glx.debug_fn.glXIsDirectFn != nullptr);
int result = g_driver_glx.debug_fn.glXIsDirectFn(dpy, ctx);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -565,6 +596,7 @@ static int GL_BINDING_CALL Debug_glXMakeContextCurrent(Display* dpy,
GL_SERVICE_LOG("glXMakeContextCurrent"
<< "(" << static_cast<const void*>(dpy) << ", " << draw << ", "
<< read << ", " << ctx << ")");
+ DCHECK(g_driver_glx.debug_fn.glXMakeContextCurrentFn != nullptr);
int result =
g_driver_glx.debug_fn.glXMakeContextCurrentFn(dpy, draw, read, ctx);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -577,6 +609,7 @@ static int GL_BINDING_CALL Debug_glXMakeCurrent(Display* dpy,
GL_SERVICE_LOG("glXMakeCurrent"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << ctx << ")");
+ DCHECK(g_driver_glx.debug_fn.glXMakeCurrentFn != nullptr);
int result = g_driver_glx.debug_fn.glXMakeCurrentFn(dpy, drawable, ctx);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -590,6 +623,7 @@ static int GL_BINDING_CALL Debug_glXQueryContext(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << ctx << ", "
<< attribute << ", " << static_cast<const void*>(value)
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryContextFn != nullptr);
int result =
g_driver_glx.debug_fn.glXQueryContextFn(dpy, ctx, attribute, value);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -604,6 +638,7 @@ static void GL_BINDING_CALL Debug_glXQueryDrawable(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", " << draw << ", "
<< attribute << ", " << static_cast<const void*>(value)
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryDrawableFn != nullptr);
g_driver_glx.debug_fn.glXQueryDrawableFn(dpy, draw, attribute, value);
}
@@ -614,6 +649,7 @@ static int GL_BINDING_CALL Debug_glXQueryExtension(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(errorb) << ", "
<< static_cast<const void*>(event) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryExtensionFn != nullptr);
int result = g_driver_glx.debug_fn.glXQueryExtensionFn(dpy, errorb, event);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -624,6 +660,7 @@ static const char* GL_BINDING_CALL Debug_glXQueryExtensionsString(Display* dpy,
GL_SERVICE_LOG("glXQueryExtensionsString"
<< "(" << static_cast<const void*>(dpy) << ", " << screen
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryExtensionsStringFn != nullptr);
const char* result =
g_driver_glx.debug_fn.glXQueryExtensionsStringFn(dpy, screen);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -636,6 +673,7 @@ static const char* GL_BINDING_CALL Debug_glXQueryServerString(Display* dpy,
GL_SERVICE_LOG("glXQueryServerString"
<< "(" << static_cast<const void*>(dpy) << ", " << screen
<< ", " << name << ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryServerStringFn != nullptr);
const char* result =
g_driver_glx.debug_fn.glXQueryServerStringFn(dpy, screen, name);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -649,6 +687,7 @@ static int GL_BINDING_CALL Debug_glXQueryVersion(Display* dpy,
<< "(" << static_cast<const void*>(dpy) << ", "
<< static_cast<const void*>(maj) << ", "
<< static_cast<const void*>(min) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXQueryVersionFn != nullptr);
int result = g_driver_glx.debug_fn.glXQueryVersionFn(dpy, maj, min);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -660,6 +699,7 @@ static void GL_BINDING_CALL Debug_glXReleaseTexImageEXT(Display* dpy,
GL_SERVICE_LOG("glXReleaseTexImageEXT"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << buffer << ")");
+ DCHECK(g_driver_glx.debug_fn.glXReleaseTexImageEXTFn != nullptr);
g_driver_glx.debug_fn.glXReleaseTexImageEXTFn(dpy, drawable, buffer);
}
@@ -669,6 +709,7 @@ static void GL_BINDING_CALL Debug_glXSelectEvent(Display* dpy,
GL_SERVICE_LOG("glXSelectEvent"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << mask << ")");
+ DCHECK(g_driver_glx.debug_fn.glXSelectEventFn != nullptr);
g_driver_glx.debug_fn.glXSelectEventFn(dpy, drawable, mask);
}
@@ -677,6 +718,7 @@ static void GL_BINDING_CALL Debug_glXSwapBuffers(Display* dpy,
GL_SERVICE_LOG("glXSwapBuffers"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXSwapBuffersFn != nullptr);
g_driver_glx.debug_fn.glXSwapBuffersFn(dpy, drawable);
}
@@ -686,12 +728,14 @@ static void GL_BINDING_CALL Debug_glXSwapIntervalEXT(Display* dpy,
GL_SERVICE_LOG("glXSwapIntervalEXT"
<< "(" << static_cast<const void*>(dpy) << ", " << drawable
<< ", " << interval << ")");
+ DCHECK(g_driver_glx.debug_fn.glXSwapIntervalEXTFn != nullptr);
g_driver_glx.debug_fn.glXSwapIntervalEXTFn(dpy, drawable, interval);
}
static void GL_BINDING_CALL Debug_glXSwapIntervalMESA(unsigned int interval) {
GL_SERVICE_LOG("glXSwapIntervalMESA"
<< "(" << interval << ")");
+ DCHECK(g_driver_glx.debug_fn.glXSwapIntervalMESAFn != nullptr);
g_driver_glx.debug_fn.glXSwapIntervalMESAFn(interval);
}
@@ -702,6 +746,7 @@ static void GL_BINDING_CALL Debug_glXUseXFont(Font font,
GL_SERVICE_LOG("glXUseXFont"
<< "(" << font << ", " << first << ", " << count << ", "
<< list << ")");
+ DCHECK(g_driver_glx.debug_fn.glXUseXFontFn != nullptr);
g_driver_glx.debug_fn.glXUseXFontFn(font, first, count, list);
}
@@ -709,6 +754,7 @@ static void GL_BINDING_CALL Debug_glXWaitGL(void) {
GL_SERVICE_LOG("glXWaitGL"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXWaitGLFn != nullptr);
g_driver_glx.debug_fn.glXWaitGLFn();
}
@@ -718,6 +764,7 @@ static int GL_BINDING_CALL Debug_glXWaitVideoSyncSGI(int divisor,
GL_SERVICE_LOG("glXWaitVideoSyncSGI"
<< "(" << divisor << ", " << remainder << ", "
<< static_cast<const void*>(count) << ")");
+ DCHECK(g_driver_glx.debug_fn.glXWaitVideoSyncSGIFn != nullptr);
int result =
g_driver_glx.debug_fn.glXWaitVideoSyncSGIFn(divisor, remainder, count);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -728,6 +775,7 @@ static void GL_BINDING_CALL Debug_glXWaitX(void) {
GL_SERVICE_LOG("glXWaitX"
<< "("
<< ")");
+ DCHECK(g_driver_glx.debug_fn.glXWaitXFn != nullptr);
g_driver_glx.debug_fn.glXWaitXFn();
}
} // extern "C"
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.cc b/chromium/ui/gl/gl_bindings_autogen_mock.cc
index 2bb8516fc30..d813760c01d 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.cc
@@ -1986,6 +1986,12 @@ void GL_BINDING_CALL MockGLInterface::Mock_glPopGroupMarkerEXT(void) {
interface_->PopGroupMarkerEXT();
}
+void GL_BINDING_CALL
+MockGLInterface::Mock_glPrimitiveRestartIndex(GLuint index) {
+ MakeFunctionUnique("glPrimitiveRestartIndex");
+ interface_->PrimitiveRestartIndex(index);
+}
+
void GL_BINDING_CALL MockGLInterface::Mock_glProgramBinary(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
@@ -3442,6 +3448,8 @@ void* GL_BINDING_CALL MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<void*>(Mock_glPolygonOffset);
if (strcmp(name, "glPopGroupMarkerEXT") == 0)
return reinterpret_cast<void*>(Mock_glPopGroupMarkerEXT);
+ if (strcmp(name, "glPrimitiveRestartIndex") == 0)
+ return reinterpret_cast<void*>(Mock_glPrimitiveRestartIndex);
if (strcmp(name, "glProgramBinary") == 0)
return reinterpret_cast<void*>(Mock_glProgramBinary);
if (strcmp(name, "glProgramBinaryOES") == 0)
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.h b/chromium/ui/gl/gl_bindings_autogen_mock.h
index 283d40ca8eb..88a06fef5d1 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.h
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.h
@@ -745,6 +745,7 @@ static void GL_BINDING_CALL Mock_glPixelStorei(GLenum pname, GLint param);
static void GL_BINDING_CALL Mock_glPointParameteri(GLenum pname, GLint param);
static void GL_BINDING_CALL Mock_glPolygonOffset(GLfloat factor, GLfloat units);
static void GL_BINDING_CALL Mock_glPopGroupMarkerEXT(void);
+static void GL_BINDING_CALL Mock_glPrimitiveRestartIndex(GLuint index);
static void GL_BINDING_CALL Mock_glProgramBinary(GLuint program,
GLenum binaryFormat,
const GLvoid* binary,
diff --git a/chromium/ui/gl/gl_bindings_autogen_osmesa.cc b/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
index 27d31e27584..1f03fe33082 100644
--- a/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
@@ -62,6 +62,7 @@ extern "C" {
static void GL_BINDING_CALL Debug_OSMesaColorClamp(GLboolean enable) {
GL_SERVICE_LOG("OSMesaColorClamp"
<< "(" << GLEnums::GetStringBool(enable) << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaColorClampFn != nullptr);
g_driver_osmesa.debug_fn.OSMesaColorClampFn(enable);
}
@@ -70,6 +71,7 @@ Debug_OSMesaCreateContext(GLenum format, OSMesaContext sharelist) {
GL_SERVICE_LOG("OSMesaCreateContext"
<< "(" << GLEnums::GetStringEnum(format) << ", " << sharelist
<< ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaCreateContextFn != nullptr);
OSMesaContext result =
g_driver_osmesa.debug_fn.OSMesaCreateContextFn(format, sharelist);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -86,6 +88,7 @@ Debug_OSMesaCreateContextExt(GLenum format,
<< "(" << GLEnums::GetStringEnum(format) << ", " << depthBits
<< ", " << stencilBits << ", " << accumBits << ", "
<< sharelist << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaCreateContextExtFn != nullptr);
OSMesaContext result = g_driver_osmesa.debug_fn.OSMesaCreateContextExtFn(
format, depthBits, stencilBits, accumBits, sharelist);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -95,6 +98,7 @@ Debug_OSMesaCreateContextExt(GLenum format,
static void GL_BINDING_CALL Debug_OSMesaDestroyContext(OSMesaContext ctx) {
GL_SERVICE_LOG("OSMesaDestroyContext"
<< "(" << ctx << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaDestroyContextFn != nullptr);
g_driver_osmesa.debug_fn.OSMesaDestroyContextFn(ctx);
}
@@ -107,6 +111,7 @@ static GLboolean GL_BINDING_CALL Debug_OSMesaGetColorBuffer(OSMesaContext c,
<< "(" << c << ", " << static_cast<const void*>(width) << ", "
<< static_cast<const void*>(height) << ", "
<< static_cast<const void*>(format) << ", " << buffer << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaGetColorBufferFn != nullptr);
GLboolean result = g_driver_osmesa.debug_fn.OSMesaGetColorBufferFn(
c, width, height, format, buffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -117,6 +122,7 @@ static OSMesaContext GL_BINDING_CALL Debug_OSMesaGetCurrentContext(void) {
GL_SERVICE_LOG("OSMesaGetCurrentContext"
<< "("
<< ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaGetCurrentContextFn != nullptr);
OSMesaContext result = g_driver_osmesa.debug_fn.OSMesaGetCurrentContextFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -133,6 +139,7 @@ Debug_OSMesaGetDepthBuffer(OSMesaContext c,
<< static_cast<const void*>(height) << ", "
<< static_cast<const void*>(bytesPerValue) << ", " << buffer
<< ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaGetDepthBufferFn != nullptr);
GLboolean result = g_driver_osmesa.debug_fn.OSMesaGetDepthBufferFn(
c, width, height, bytesPerValue, buffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -143,6 +150,7 @@ static void GL_BINDING_CALL Debug_OSMesaGetIntegerv(GLint pname, GLint* value) {
GL_SERVICE_LOG("OSMesaGetIntegerv"
<< "(" << pname << ", " << static_cast<const void*>(value)
<< ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaGetIntegervFn != nullptr);
g_driver_osmesa.debug_fn.OSMesaGetIntegervFn(pname, value);
}
@@ -150,6 +158,7 @@ static OSMESAproc GL_BINDING_CALL
Debug_OSMesaGetProcAddress(const char* funcName) {
GL_SERVICE_LOG("OSMesaGetProcAddress"
<< "(" << funcName << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaGetProcAddressFn != nullptr);
OSMESAproc result = g_driver_osmesa.debug_fn.OSMesaGetProcAddressFn(funcName);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -164,6 +173,7 @@ static GLboolean GL_BINDING_CALL Debug_OSMesaMakeCurrent(OSMesaContext ctx,
<< "(" << ctx << ", " << static_cast<const void*>(buffer)
<< ", " << GLEnums::GetStringEnum(type) << ", " << width
<< ", " << height << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaMakeCurrentFn != nullptr);
GLboolean result = g_driver_osmesa.debug_fn.OSMesaMakeCurrentFn(
ctx, buffer, type, width, height);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -173,6 +183,7 @@ static GLboolean GL_BINDING_CALL Debug_OSMesaMakeCurrent(OSMesaContext ctx,
static void GL_BINDING_CALL Debug_OSMesaPixelStore(GLint pname, GLint value) {
GL_SERVICE_LOG("OSMesaPixelStore"
<< "(" << pname << ", " << value << ")");
+ DCHECK(g_driver_osmesa.debug_fn.OSMesaPixelStoreFn != nullptr);
g_driver_osmesa.debug_fn.OSMesaPixelStoreFn(pname, value);
}
} // extern "C"
diff --git a/chromium/ui/gl/gl_bindings_autogen_wgl.cc b/chromium/ui/gl/gl_bindings_autogen_wgl.cc
index f1bcb2f2ae5..4791424e7dc 100644
--- a/chromium/ui/gl/gl_bindings_autogen_wgl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_wgl.cc
@@ -135,6 +135,7 @@ Debug_wglChoosePixelFormatARB(HDC dc,
<< static_cast<const void*>(float_attrib_list) << ", "
<< max_formats << ", " << static_cast<const void*>(formats)
<< ", " << static_cast<const void*>(num_formats) << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglChoosePixelFormatARBFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglChoosePixelFormatARBFn(
dc, int_attrib_list, float_attrib_list, max_formats, formats,
num_formats);
@@ -147,6 +148,7 @@ static BOOL GL_BINDING_CALL Debug_wglCopyContext(HGLRC hglrcSrc,
UINT mask) {
GL_SERVICE_LOG("wglCopyContext"
<< "(" << hglrcSrc << ", " << hglrcDst << ", " << mask << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglCopyContextFn != nullptr);
BOOL result =
g_driver_wgl.debug_fn.wglCopyContextFn(hglrcSrc, hglrcDst, mask);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -156,6 +158,7 @@ static BOOL GL_BINDING_CALL Debug_wglCopyContext(HGLRC hglrcSrc,
static HGLRC GL_BINDING_CALL Debug_wglCreateContext(HDC hdc) {
GL_SERVICE_LOG("wglCreateContext"
<< "(" << hdc << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglCreateContextFn != nullptr);
HGLRC result = g_driver_wgl.debug_fn.wglCreateContextFn(hdc);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -165,6 +168,7 @@ static HGLRC GL_BINDING_CALL Debug_wglCreateLayerContext(HDC hdc,
int iLayerPlane) {
GL_SERVICE_LOG("wglCreateLayerContext"
<< "(" << hdc << ", " << iLayerPlane << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglCreateLayerContextFn != nullptr);
HGLRC result =
g_driver_wgl.debug_fn.wglCreateLayerContextFn(hdc, iLayerPlane);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -181,6 +185,7 @@ Debug_wglCreatePbufferARB(HDC hDC,
<< "(" << hDC << ", " << iPixelFormat << ", " << iWidth << ", "
<< iHeight << ", " << static_cast<const void*>(piAttribList)
<< ")");
+ DCHECK(g_driver_wgl.debug_fn.wglCreatePbufferARBFn != nullptr);
HPBUFFERARB result = g_driver_wgl.debug_fn.wglCreatePbufferARBFn(
hDC, iPixelFormat, iWidth, iHeight, piAttribList);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -190,6 +195,7 @@ Debug_wglCreatePbufferARB(HDC hDC,
static BOOL GL_BINDING_CALL Debug_wglDeleteContext(HGLRC hglrc) {
GL_SERVICE_LOG("wglDeleteContext"
<< "(" << hglrc << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglDeleteContextFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglDeleteContextFn(hglrc);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -198,6 +204,7 @@ static BOOL GL_BINDING_CALL Debug_wglDeleteContext(HGLRC hglrc) {
static BOOL GL_BINDING_CALL Debug_wglDestroyPbufferARB(HPBUFFERARB hPbuffer) {
GL_SERVICE_LOG("wglDestroyPbufferARB"
<< "(" << hPbuffer << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglDestroyPbufferARBFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglDestroyPbufferARBFn(hPbuffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -207,6 +214,7 @@ static HGLRC GL_BINDING_CALL Debug_wglGetCurrentContext() {
GL_SERVICE_LOG("wglGetCurrentContext"
<< "("
<< ")");
+ DCHECK(g_driver_wgl.debug_fn.wglGetCurrentContextFn != nullptr);
HGLRC result = g_driver_wgl.debug_fn.wglGetCurrentContextFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -216,6 +224,7 @@ static HDC GL_BINDING_CALL Debug_wglGetCurrentDC() {
GL_SERVICE_LOG("wglGetCurrentDC"
<< "("
<< ")");
+ DCHECK(g_driver_wgl.debug_fn.wglGetCurrentDCFn != nullptr);
HDC result = g_driver_wgl.debug_fn.wglGetCurrentDCFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -224,6 +233,7 @@ static HDC GL_BINDING_CALL Debug_wglGetCurrentDC() {
static const char* GL_BINDING_CALL Debug_wglGetExtensionsStringARB(HDC hDC) {
GL_SERVICE_LOG("wglGetExtensionsStringARB"
<< "(" << hDC << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglGetExtensionsStringARBFn != nullptr);
const char* result = g_driver_wgl.debug_fn.wglGetExtensionsStringARBFn(hDC);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -233,6 +243,7 @@ static const char* GL_BINDING_CALL Debug_wglGetExtensionsStringEXT() {
GL_SERVICE_LOG("wglGetExtensionsStringEXT"
<< "("
<< ")");
+ DCHECK(g_driver_wgl.debug_fn.wglGetExtensionsStringEXTFn != nullptr);
const char* result = g_driver_wgl.debug_fn.wglGetExtensionsStringEXTFn();
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -241,6 +252,7 @@ static const char* GL_BINDING_CALL Debug_wglGetExtensionsStringEXT() {
static HDC GL_BINDING_CALL Debug_wglGetPbufferDCARB(HPBUFFERARB hPbuffer) {
GL_SERVICE_LOG("wglGetPbufferDCARB"
<< "(" << hPbuffer << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglGetPbufferDCARBFn != nullptr);
HDC result = g_driver_wgl.debug_fn.wglGetPbufferDCARBFn(hPbuffer);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -249,6 +261,7 @@ static HDC GL_BINDING_CALL Debug_wglGetPbufferDCARB(HPBUFFERARB hPbuffer) {
static BOOL GL_BINDING_CALL Debug_wglMakeCurrent(HDC hdc, HGLRC hglrc) {
GL_SERVICE_LOG("wglMakeCurrent"
<< "(" << hdc << ", " << hglrc << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglMakeCurrentFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglMakeCurrentFn(hdc, hglrc);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -260,6 +273,7 @@ static BOOL GL_BINDING_CALL Debug_wglQueryPbufferARB(HPBUFFERARB hPbuffer,
GL_SERVICE_LOG("wglQueryPbufferARB"
<< "(" << hPbuffer << ", " << iAttribute << ", "
<< static_cast<const void*>(piValue) << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglQueryPbufferARBFn != nullptr);
BOOL result =
g_driver_wgl.debug_fn.wglQueryPbufferARBFn(hPbuffer, iAttribute, piValue);
GL_SERVICE_LOG("GL_RESULT: " << result);
@@ -270,6 +284,7 @@ static int GL_BINDING_CALL Debug_wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,
HDC hDC) {
GL_SERVICE_LOG("wglReleasePbufferDCARB"
<< "(" << hPbuffer << ", " << hDC << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglReleasePbufferDCARBFn != nullptr);
int result = g_driver_wgl.debug_fn.wglReleasePbufferDCARBFn(hPbuffer, hDC);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -278,6 +293,7 @@ static int GL_BINDING_CALL Debug_wglReleasePbufferDCARB(HPBUFFERARB hPbuffer,
static BOOL GL_BINDING_CALL Debug_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
GL_SERVICE_LOG("wglShareLists"
<< "(" << hglrc1 << ", " << hglrc2 << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglShareListsFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglShareListsFn(hglrc1, hglrc2);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -286,6 +302,7 @@ static BOOL GL_BINDING_CALL Debug_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) {
static BOOL GL_BINDING_CALL Debug_wglSwapIntervalEXT(int interval) {
GL_SERVICE_LOG("wglSwapIntervalEXT"
<< "(" << interval << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglSwapIntervalEXTFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglSwapIntervalEXTFn(interval);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
@@ -294,6 +311,7 @@ static BOOL GL_BINDING_CALL Debug_wglSwapIntervalEXT(int interval) {
static BOOL GL_BINDING_CALL Debug_wglSwapLayerBuffers(HDC hdc, UINT fuPlanes) {
GL_SERVICE_LOG("wglSwapLayerBuffers"
<< "(" << hdc << ", " << fuPlanes << ")");
+ DCHECK(g_driver_wgl.debug_fn.wglSwapLayerBuffersFn != nullptr);
BOOL result = g_driver_wgl.debug_fn.wglSwapLayerBuffersFn(hdc, fuPlanes);
GL_SERVICE_LOG("GL_RESULT: " << result);
return result;
diff --git a/chromium/ui/gl/gl_bindings_skia_in_process.cc b/chromium/ui/gl/gl_bindings_skia_in_process.cc
deleted file mode 100644
index d76bd7aba16..00000000000
--- a/chromium/ui/gl/gl_bindings_skia_in_process.cc
+++ /dev/null
@@ -1,995 +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/gl/gl_bindings_skia_in_process.h"
-
-#include "base/logging.h"
-#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_implementation.h"
-
-namespace {
-
-extern "C" {
-// The following stub functions are required because the glXXX routines exported
-// via gl_bindings.h use call-type GL_BINDING_CALL, which on Windows is stdcall.
-// Skia has been built such that its GrGLInterface GL pointers are __cdecl.
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLActiveTexture(GLenum texture) {
- glActiveTexture(texture);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLAttachShader(GLuint program, GLuint shader) {
- glAttachShader(program, shader);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBeginQuery(GLenum target, GLuint id) {
- glBeginQuery(target, id);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindAttribLocation(GLuint program,
- GLuint index,
- const char* name) {
- glBindAttribLocation(program, index, name);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindBuffer(GLenum target, GLuint buffer) {
- glBindBuffer(target, buffer);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindFragDataLocation(GLuint program,
- GLuint colorNumber,
- const GLchar* name) {
- glBindFragDataLocation(program, colorNumber, name);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLBindFragDataLocationIndexed(GLuint program,
- GLuint colorNumber,
- GLuint index,
- const GLchar* name) {
- glBindFragDataLocationIndexed(program, colorNumber, index, name);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindFramebuffer(GLenum target,
- GLuint framebuffer) {
- glBindFramebufferEXT(target, framebuffer);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindRenderbuffer(GLenum target,
- GLuint renderbuffer) {
- glBindRenderbufferEXT(target, renderbuffer);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindTexture(GLenum target, GLuint texture) {
- glBindTexture(target, texture);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBindVertexArray(GLuint array) {
- glBindVertexArrayOES(array);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBlendBarrier() {
- glBlendBarrierKHR();
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBlendColor(GLclampf red,
- GLclampf green,
- GLclampf blue,
- GLclampf alpha) {
- glBlendColor(red, green, blue, alpha);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBlendEquation(GLenum mode) {
- glBlendEquation(mode);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBlendFunc(GLenum sfactor, GLenum dfactor) {
- glBlendFunc(sfactor, dfactor);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBlitFramebuffer(GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1,
- GLbitfield mask,
- GLenum filter) {
- glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
- mask, filter);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBufferData(GLenum target,
- GLsizeiptr size,
- const void* data,
- GLenum usage) {
- glBufferData(target, size, data, usage);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLBufferSubData(GLenum target,
- GLintptr offset,
- GLsizeiptr size,
- const void* data) {
- glBufferSubData(target, offset, size, data);
-}
-
-GLenum GR_GL_FUNCTION_TYPE StubGLCheckFramebufferStatus(GLenum target) {
- return glCheckFramebufferStatusEXT(target);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLClear(GLbitfield mask) {
- glClear(mask);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLClearColor(GLclampf red,
- GLclampf green,
- GLclampf blue,
- GLclampf alpha) {
- glClearColor(red, green, blue, alpha);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLClearStencil(GLint s) {
- glClearStencil(s);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLColorMask(GLboolean red,
- GLboolean green,
- GLboolean blue,
- GLboolean alpha) {
- glColorMask(red, green, blue, alpha);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLCompileShader(GLuint shader) {
- glCompileShader(shader);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLCompressedTexImage2D(GLenum target,
- GLint level,
- GLenum internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLsizei imageSize,
- const void* data) {
- glCompressedTexImage2D(target, level, internalformat, width, height, border,
- imageSize, data);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLCopyTexSubImage2D(GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height) {
- glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
-}
-
-GLuint GR_GL_FUNCTION_TYPE StubGLCreateProgram(void) {
- return glCreateProgram();
-}
-
-GLuint GR_GL_FUNCTION_TYPE StubGLCreateShader(GLenum type) {
- return glCreateShader(type);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLCullFace(GLenum mode) {
- glCullFace(mode);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteBuffers(GLsizei n,
- const GLuint* buffers) {
- glDeleteBuffersARB(n, buffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
- glDeleteFramebuffersEXT(n, framebuffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteQueries(GLsizei n, const GLuint* ids) {
- glDeleteQueries(n, ids);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteProgram(GLuint program) {
- glDeleteProgram(program);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
- glDeleteRenderbuffersEXT(n, renderbuffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteShader(GLuint shader) {
- glDeleteShader(shader);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteTextures(GLsizei n,
- const GLuint* textures) {
- glDeleteTextures(n, textures);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDeleteVertexArrays(GLsizei n,
- const GLuint* arrays) {
- glDeleteVertexArraysOES(n, arrays);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDepthMask(GLboolean flag) {
- glDepthMask(flag);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDisable(GLenum cap) {
- glDisable(cap);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDisableVertexAttribArray(GLuint index) {
- glDisableVertexAttribArray(index);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDiscardFramebuffer(GLenum target,
- GLsizei numAttachments,
- const GLenum* attachments) {
- glDiscardFramebufferEXT(target, numAttachments, attachments);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDrawArrays(GLenum mode,
- GLint first,
- GLsizei count) {
- glDrawArrays(mode, first, count);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDrawBuffer(GLenum mode) {
- glDrawBuffer(mode);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDrawBuffers(GLsizei n, const GLenum* bufs) {
- glDrawBuffersARB(n, bufs);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLDrawElements(GLenum mode,
- GLsizei count,
- GLenum type,
- const void* indices) {
- glDrawElements(mode, count, type, indices);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLEnable(GLenum cap) {
- glEnable(cap);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLEnableVertexAttribArray(GLuint index) {
- glEnableVertexAttribArray(index);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLEndQuery(GLenum target) {
- glEndQuery(target);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLFinish() {
- glFinish();
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLFlush() {
- glFlush();
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLFlushMappedBufferRange(GLenum target,
- GLintptr offset,
- GLsizeiptr length) {
- glFlushMappedBufferRange(target, offset, length);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLFramebufferRenderbuffer(GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer) {
- glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
- renderbuffer);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLFramebufferTexture2D(GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level) {
- glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLFramebufferTexture2DMultisample(GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level,
- GLsizei samples) {
- glFramebufferTexture2DMultisampleEXT(target, attachment, textarget, texture,
- level, samples);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLFrontFace(GLenum mode) {
- glFrontFace(mode);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenBuffers(GLsizei n, GLuint* buffers) {
- glGenBuffersARB(n, buffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenFramebuffers(GLsizei n,
- GLuint* framebuffers) {
- glGenFramebuffersEXT(n, framebuffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenQueries(GLsizei n, GLuint* ids) {
- glGenQueries(n, ids);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenRenderbuffers(GLsizei n,
- GLuint* renderbuffers) {
- glGenRenderbuffersEXT(n, renderbuffers);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenTextures(GLsizei n, GLuint* textures) {
- glGenTextures(n, textures);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenVertexArrays(GLsizei n, GLuint* arrays) {
- glGenVertexArraysOES(n, arrays);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGenerateMipmap(GLenum target) {
- glGenerateMipmapEXT(target);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetBufferParameteriv(GLenum target,
- GLenum pname,
- GLint* params) {
- glGetBufferParameteriv(target, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLGetFramebufferAttachmentParameteriv(GLenum target,
- GLenum attachment,
- GLenum pname,
- GLint* params) {
- glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
-}
-
-GLenum GR_GL_FUNCTION_TYPE StubGLGetError() {
- return glGetError();
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetIntegerv(GLenum pname, GLint* params) {
- glGetIntegerv(pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetProgramInfoLog(GLuint program,
- GLsizei bufsize,
- GLsizei* length,
- char* infolog) {
- glGetProgramInfoLog(program, bufsize, length, infolog);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetProgramiv(GLuint program,
- GLenum pname,
- GLint* params) {
- glGetProgramiv(program, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetRenderbufferParameteriv(GLenum target,
- GLenum pname,
- GLint* params) {
- glGetRenderbufferParameterivEXT(target, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetShaderInfoLog(GLuint shader,
- GLsizei bufsize,
- GLsizei* length,
- char* infolog) {
- glGetShaderInfoLog(shader, bufsize, length, infolog);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetShaderiv(GLuint shader,
- GLenum pname,
- GLint* params) {
- glGetShaderiv(shader, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetShaderPrecisionFormat(GLenum shadertype,
- GLenum precisiontype,
- GLint* range,
- GLint* precision) {
- glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-}
-
-const GLubyte* GR_GL_FUNCTION_TYPE StubGLGetString(GLenum name) {
- return glGetString(name);
-}
-
-const GLubyte* GR_GL_FUNCTION_TYPE StubGLGetStringi(GLenum name, GLuint index) {
- return glGetStringi(name, index);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetQueryiv(GLenum target,
- GLenum pname,
- GLint* params) {
- glGetQueryiv(target, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetQueryObjecti64v(GLuint id,
- GLenum pname,
- GLint64* params) {
- glGetQueryObjecti64v(id, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetQueryObjectiv(GLuint id,
- GLenum pname,
- GLint* params) {
- glGetQueryObjectiv(id, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetQueryObjectui64v(GLuint id,
- GLenum pname,
- GLuint64* params) {
- glGetQueryObjectui64v(id, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetQueryObjectuiv(GLuint id,
- GLenum pname,
- GLuint* params) {
- glGetQueryObjectuiv(id, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLGetTexLevelParameteriv(GLenum target,
- GLint level,
- GLenum pname,
- GLint* params) {
- glGetTexLevelParameteriv(target, level, pname, params);
-}
-
-GLint GR_GL_FUNCTION_TYPE StubGLGetUniformLocation(GLuint program,
- const char* name) {
- return glGetUniformLocation(program, name);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLInsertEventMarker(GLsizei length,
- const char* marker) {
- glInsertEventMarkerEXT(length, marker);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLInvalidateFramebuffer(GLenum target,
- GLsizei numAttachments,
- const GLenum* attachments) {
- glInvalidateFramebuffer(target, numAttachments, attachments);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLInvalidateSubFramebuffer(GLenum target,
- GLsizei numAttachments,
- const GLenum* attachments,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height) {
- glInvalidateSubFramebuffer(target, numAttachments, attachments,
- x, y, width, height);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLLineWidth(GLfloat width) {
- glLineWidth(width);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLLinkProgram(GLuint program) {
- glLinkProgram(program);
-}
-
-void* GR_GL_FUNCTION_TYPE StubGLMapBuffer(GLenum target, GLenum access) {
- return glMapBuffer(target, access);
-}
-
-void* GR_GL_FUNCTION_TYPE StubGLMapBufferRange(GLenum target,
- GLintptr offset,
- GLsizeiptr length,
- GLbitfield access) {
- return glMapBufferRange(target, offset, length, access);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLPixelStorei(GLenum pname, GLint param) {
- glPixelStorei(pname, param);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLPopGroupMarker() {
- glPopGroupMarkerEXT();
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLPushGroupMarker(GLsizei length,
- const char* marker) {
- glPushGroupMarkerEXT(length, marker);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLQueryCounter(GLuint id, GLenum target) {
- glQueryCounter(id, target);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLReadBuffer(GLenum src) {
- glReadBuffer(src);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLReadPixels(GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- void* pixels) {
- glReadPixels(x, y, width, height, format, type, pixels);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLRenderbufferStorage(GLenum target,
- GLenum internalformat,
- GLsizei width,
- GLsizei height) {
- glRenderbufferStorageEXT(target, internalformat, width, height);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLRenderbufferStorageMultisample(GLenum target,
- GLsizei samples,
- GLenum internalformat,
- GLsizei width,
- GLsizei height) {
- glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width,
- height);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLScissor(GLint x,
- GLint y,
- GLsizei width,
- GLsizei height) {
- glScissor(x, y, width, height);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLShaderSource(GLuint shader,
- GLsizei count,
- const char* const* str,
- const GLint* length) {
- glShaderSource(shader, count, str, length);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilFunc(GLenum func,
- GLint ref,
- GLuint mask) {
- glStencilFunc(func, ref, mask);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilFuncSeparate(GLenum face,
- GLenum func,
- GLint ref,
- GLuint mask) {
- glStencilFuncSeparate(face, func, ref, mask);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilMask(GLuint mask) {
- glStencilMask(mask);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilMaskSeparate(GLenum face, GLuint mask) {
- glStencilMaskSeparate(face, mask);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilOp(GLenum fail,
- GLenum zfail,
- GLenum zpass) {
- glStencilOp(fail, zfail, zpass);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLStencilOpSeparate(GLenum face,
- GLenum fail,
- GLenum zfail,
- GLenum zpass) {
- glStencilOpSeparate(face, fail, zfail, zpass);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLTexImage2D(GLenum target,
- GLint level,
- GLint internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void* pixels) {
- glTexImage2D(target, level, internalformat, width, height, border, format,
- type, pixels);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLTexParameteri(GLenum target,
- GLenum pname,
- GLint param) {
- glTexParameteri(target, pname, param);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLTexParameteriv(GLenum target,
- GLenum pname,
- const GLint* params) {
- glTexParameteriv(target, pname, params);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLTexStorage2D(GLenum target,
- GLsizei levels,
- GLenum internalFormat,
- GLsizei width,
- GLsizei height) {
- glTexStorage2DEXT(target, levels, internalFormat, width, height);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLTexSubImage2D(GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const void* pixels) {
- glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
- pixels);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform1f(GLint location, GLfloat v) {
- glUniform1f(location, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform1i(GLint location, GLint v) {
- glUniform1i(location, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform1fv(GLint location,
- GLsizei count,
- const GLfloat* v) {
- glUniform1fv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform1iv(GLint location,
- GLsizei count,
- const GLint* v) {
- glUniform1iv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform2f(GLint location,
- GLfloat v0,
- GLfloat v1) {
- glUniform2f(location, v0, v1);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform2i(GLint location, GLint v0, GLint v1) {
- glUniform2i(location, v0, v1);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform2fv(GLint location,
- GLsizei count,
- const GLfloat* v) {
- glUniform2fv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform2iv(GLint location,
- GLsizei count,
- const GLint* v) {
- glUniform2iv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform3f(GLint location,
- GLfloat v0,
- GLfloat v1,
- GLfloat v2) {
- glUniform3f(location, v0, v1, v2);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform3i(GLint location,
- GLint v0,
- GLint v1,
- GLint v2) {
- glUniform3i(location, v0, v1, v2);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform3fv(GLint location,
- GLsizei count,
- const GLfloat* v) {
- glUniform3fv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform3iv(GLint location,
- GLsizei count,
- const GLint* v) {
- glUniform3iv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform4f(GLint location,
- GLfloat v0,
- GLfloat v1,
- GLfloat v2,
- GLfloat v3) {
- glUniform4f(location, v0, v1, v2, v3);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE
-StubGLUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
- glUniform4i(location, v0, v1, v2, v3);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform4fv(GLint location,
- GLsizei count,
- const GLfloat* v) {
- glUniform4fv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniform4iv(GLint location,
- GLsizei count,
- const GLint* v) {
- glUniform4iv(location, count, v);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniformMatrix2fv(GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat* value) {
- glUniformMatrix2fv(location, count, transpose, value);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniformMatrix3fv(GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat* value) {
- glUniformMatrix3fv(location, count, transpose, value);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUniformMatrix4fv(GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat* value) {
- glUniformMatrix4fv(location, count, transpose, value);
-}
-
-GLboolean GR_GL_FUNCTION_TYPE StubGLUnmapBuffer(GLenum target) {
- return glUnmapBuffer(target);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLUseProgram(GLuint program) {
- glUseProgram(program);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLVertexAttrib1f(GLuint indx,
- const GLfloat value) {
- glVertexAttrib1f(indx, value);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLVertexAttrib2fv(GLuint indx,
- const GLfloat* values) {
- glVertexAttrib2fv(indx, values);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLVertexAttrib3fv(GLuint indx,
- const GLfloat* values) {
- glVertexAttrib3fv(indx, values);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLVertexAttrib4fv(GLuint indx,
- const GLfloat* values) {
- glVertexAttrib4fv(indx, values);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLVertexAttribPointer(GLuint indx,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- const void* ptr) {
- glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
-}
-
-GLvoid GR_GL_FUNCTION_TYPE StubGLViewport(GLint x,
- GLint y,
- GLsizei width,
- GLsizei height) {
- glViewport(x, y, width, height);
-}
-
-GLint GR_GL_FUNCTION_TYPE
-StubGLGetProgramResourceLocation(GLuint program,
- GLenum programInterface,
- const char* name) {
- return glGetProgramResourceLocation(program, programInterface, name);
-}
-
-} // extern "C"
-} // namespace
-
-namespace gfx {
-
-GrGLInterface* CreateInProcessSkiaGLBinding() {
- GrGLStandard standard;
- switch (gfx::GetGLImplementation()) {
- case gfx::kGLImplementationNone:
- NOTREACHED();
- return NULL;
- case gfx::kGLImplementationDesktopGL:
- case gfx::kGLImplementationAppleGL:
- standard = kGL_GrGLStandard;
- break;
- case gfx::kGLImplementationOSMesaGL:
- standard = kGL_GrGLStandard;
- break;
- case gfx::kGLImplementationEGLGLES2:
- standard = kGLES_GrGLStandard;
- break;
- case gfx::kGLImplementationMockGL:
- NOTREACHED();
- return NULL;
- default:
- NOTREACHED();
- return NULL;
- }
-
- GrGLInterface* interface = new GrGLInterface;
- interface->fStandard = standard;
- interface->fExtensions.init(standard,
- StubGLGetString,
- StubGLGetStringi,
- StubGLGetIntegerv);
-
- GrGLInterface::Functions* functions = &interface->fFunctions;
- functions->fActiveTexture = StubGLActiveTexture;
- functions->fAttachShader = StubGLAttachShader;
- functions->fBeginQuery = StubGLBeginQuery;
- functions->fBindAttribLocation = StubGLBindAttribLocation;
- functions->fBindBuffer = StubGLBindBuffer;
- functions->fBindFragDataLocation = StubGLBindFragDataLocation;
- functions->fBindTexture = StubGLBindTexture;
- functions->fBindVertexArray = StubGLBindVertexArray;
- functions->fBlendBarrier = StubGLBlendBarrier;
- functions->fBlendColor = StubGLBlendColor;
- functions->fBlendEquation = StubGLBlendEquation;
- functions->fBlendFunc = StubGLBlendFunc;
- functions->fBufferData = StubGLBufferData;
- functions->fBufferSubData = StubGLBufferSubData;
- functions->fClear = StubGLClear;
- functions->fClearColor = StubGLClearColor;
- functions->fClearStencil = StubGLClearStencil;
- functions->fColorMask = StubGLColorMask;
- functions->fCompileShader = StubGLCompileShader;
- functions->fCompressedTexImage2D = StubGLCompressedTexImage2D;
- functions->fCopyTexSubImage2D = StubGLCopyTexSubImage2D;
- functions->fCreateProgram = StubGLCreateProgram;
- functions->fCreateShader = StubGLCreateShader;
- functions->fCullFace = StubGLCullFace;
- functions->fDeleteBuffers = StubGLDeleteBuffers;
- functions->fDeleteProgram = StubGLDeleteProgram;
- functions->fDeleteQueries = StubGLDeleteQueries;
- functions->fDeleteShader = StubGLDeleteShader;
- functions->fDeleteTextures = StubGLDeleteTextures;
- functions->fDeleteVertexArrays = StubGLDeleteVertexArrays;
- functions->fDepthMask = StubGLDepthMask;
- functions->fDisable = StubGLDisable;
- functions->fDisableVertexAttribArray = StubGLDisableVertexAttribArray;
- functions->fDiscardFramebuffer = StubGLDiscardFramebuffer;
- functions->fDrawArrays = StubGLDrawArrays;
- functions->fDrawBuffer = StubGLDrawBuffer;
- functions->fDrawBuffers = StubGLDrawBuffers;
- functions->fDrawElements = StubGLDrawElements;
- functions->fEnable = StubGLEnable;
- functions->fEnableVertexAttribArray = StubGLEnableVertexAttribArray;
- functions->fEndQuery = StubGLEndQuery;
- functions->fFinish = StubGLFinish;
- functions->fFlush = StubGLFlush;
- functions->fFlushMappedBufferRange = StubGLFlushMappedBufferRange;
- functions->fFrontFace = StubGLFrontFace;
- functions->fGenBuffers = StubGLGenBuffers;
- functions->fGenQueries = StubGLGenQueries;
- functions->fGenTextures = StubGLGenTextures;
- functions->fGenVertexArrays = StubGLGenVertexArrays;
- functions->fGenerateMipmap = StubGLGenerateMipmap;
- functions->fGetBufferParameteriv = StubGLGetBufferParameteriv;
- functions->fGetError = StubGLGetError;
- functions->fGetIntegerv = StubGLGetIntegerv;
- functions->fGetQueryiv = StubGLGetQueryiv;
- functions->fGetQueryObjecti64v = StubGLGetQueryObjecti64v;
- functions->fGetQueryObjectiv = StubGLGetQueryObjectiv;
- functions->fGetQueryObjectui64v = StubGLGetQueryObjectui64v;
- functions->fGetQueryObjectuiv = StubGLGetQueryObjectuiv;
- functions->fGetProgramInfoLog = StubGLGetProgramInfoLog;
- functions->fGetProgramiv = StubGLGetProgramiv;
- functions->fGetShaderInfoLog = StubGLGetShaderInfoLog;
- functions->fGetShaderiv = StubGLGetShaderiv;
- functions->fGetShaderPrecisionFormat = StubGLGetShaderPrecisionFormat;
- functions->fGetString = StubGLGetString;
- functions->fGetStringi = StubGLGetStringi;
- functions->fGetTexLevelParameteriv = StubGLGetTexLevelParameteriv;
- functions->fGetUniformLocation = StubGLGetUniformLocation;
- functions->fInsertEventMarker = StubGLInsertEventMarker;
- functions->fInvalidateFramebuffer = StubGLInvalidateFramebuffer;
- functions->fInvalidateSubFramebuffer = StubGLInvalidateSubFramebuffer;
- functions->fLineWidth = StubGLLineWidth;
- functions->fLinkProgram = StubGLLinkProgram;
- functions->fMapBufferRange = StubGLMapBufferRange;
- functions->fPixelStorei = StubGLPixelStorei;
- functions->fPopGroupMarker = StubGLPopGroupMarker;
- functions->fPushGroupMarker = StubGLPushGroupMarker;
- functions->fQueryCounter = StubGLQueryCounter;
- functions->fReadBuffer = StubGLReadBuffer;
- functions->fReadPixels = StubGLReadPixels;
- functions->fScissor = StubGLScissor;
- functions->fShaderSource = StubGLShaderSource;
- functions->fStencilFunc = StubGLStencilFunc;
- functions->fStencilFuncSeparate = StubGLStencilFuncSeparate;
- functions->fStencilMask = StubGLStencilMask;
- functions->fStencilMaskSeparate = StubGLStencilMaskSeparate;
- functions->fStencilOp = StubGLStencilOp;
- functions->fStencilOpSeparate = StubGLStencilOpSeparate;
- functions->fTexImage2D = StubGLTexImage2D;
- functions->fTexParameteri = StubGLTexParameteri;
- functions->fTexParameteriv = StubGLTexParameteriv;
- functions->fTexSubImage2D = StubGLTexSubImage2D;
- functions->fTexStorage2D = StubGLTexStorage2D;
- functions->fUniform1f = StubGLUniform1f;
- functions->fUniform1i = StubGLUniform1i;
- functions->fUniform1fv = StubGLUniform1fv;
- functions->fUniform1iv = StubGLUniform1iv;
- functions->fUniform2f = StubGLUniform2f;
- functions->fUniform2i = StubGLUniform2i;
- functions->fUniform2fv = StubGLUniform2fv;
- functions->fUniform2iv = StubGLUniform2iv;
- functions->fUniform3f = StubGLUniform3f;
- functions->fUniform3i = StubGLUniform3i;
- functions->fUniform3fv = StubGLUniform3fv;
- functions->fUniform3iv = StubGLUniform3iv;
- functions->fUniform4f = StubGLUniform4f;
- functions->fUniform4i = StubGLUniform4i;
- functions->fUniform4fv = StubGLUniform4fv;
- functions->fUniform4iv = StubGLUniform4iv;
- functions->fUniformMatrix2fv = StubGLUniformMatrix2fv;
- functions->fUniformMatrix3fv = StubGLUniformMatrix3fv;
- functions->fUniformMatrix4fv = StubGLUniformMatrix4fv;
- functions->fUseProgram = StubGLUseProgram;
- functions->fVertexAttrib1f = StubGLVertexAttrib1f;
- functions->fVertexAttrib2fv = StubGLVertexAttrib2fv;
- functions->fVertexAttrib3fv = StubGLVertexAttrib3fv;
- functions->fVertexAttrib4fv = StubGLVertexAttrib4fv;
- functions->fVertexAttribPointer = StubGLVertexAttribPointer;
- functions->fViewport = StubGLViewport;
- functions->fBindFramebuffer = StubGLBindFramebuffer;
- functions->fBindRenderbuffer = StubGLBindRenderbuffer;
- functions->fCheckFramebufferStatus = StubGLCheckFramebufferStatus;
- functions->fDeleteFramebuffers = StubGLDeleteFramebuffers;
- functions->fDeleteRenderbuffers = StubGLDeleteRenderbuffers;
- functions->fFramebufferRenderbuffer = StubGLFramebufferRenderbuffer;
- functions->fFramebufferTexture2D = StubGLFramebufferTexture2D;
- functions->fFramebufferTexture2DMultisample =
- StubGLFramebufferTexture2DMultisample;
- functions->fGenFramebuffers = StubGLGenFramebuffers;
- functions->fGenRenderbuffers = StubGLGenRenderbuffers;
- functions->fGetFramebufferAttachmentParameteriv =
- StubGLGetFramebufferAttachmentParameteriv;
- functions->fGetRenderbufferParameteriv = StubGLGetRenderbufferParameteriv;
- functions->fRenderbufferStorage = StubGLRenderbufferStorage;
- functions->fRenderbufferStorageMultisample =
- StubGLRenderbufferStorageMultisample;
- functions->fRenderbufferStorageMultisampleES2EXT =
- StubGLRenderbufferStorageMultisample;
- functions->fBlitFramebuffer = StubGLBlitFramebuffer;
- functions->fMapBuffer = StubGLMapBuffer;
- functions->fUnmapBuffer = StubGLUnmapBuffer;
- functions->fBindFragDataLocationIndexed =
- StubGLBindFragDataLocationIndexed;
- functions->fGetProgramResourceLocation = StubGLGetProgramResourceLocation;
-
- return interface;
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gl/gl_bindings_skia_in_process.h b/chromium/ui/gl/gl_bindings_skia_in_process.h
deleted file mode 100644
index 23d54eecc22..00000000000
--- a/chromium/ui/gl/gl_bindings_skia_in_process.h
+++ /dev/null
@@ -1,20 +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_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
-#define UI_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
-
-#include "ui/gl/gl_export.h"
-
-struct GrGLInterface;
-
-namespace gfx {
-
-// The GPU back-end for skia requires pointers to GL functions. This function
-// creates a binding for skia-gpu to the in-process GL
-GL_EXPORT GrGLInterface* CreateInProcessSkiaGLBinding();
-
-} // namespace gfx
-
-#endif // UI_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
diff --git a/chromium/ui/gl/gl_context_egl.cc b/chromium/ui/gl/gl_context_egl.cc
index 8a9e4e4cb2f..569c2cca118 100644
--- a/chromium/ui/gl/gl_context_egl.cc
+++ b/chromium/ui/gl/gl_context_egl.cc
@@ -70,6 +70,13 @@ bool GLContextEGL::Initialize(
context_attributes = kContextAttributes;
}
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ LOG(ERROR) << "eglBindApi failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+
context_ = eglCreateContext(
display_,
config_,
diff --git a/chromium/ui/gl/gl_context_osmesa.cc b/chromium/ui/gl/gl_context_osmesa.cc
index ee0f7570ebc..dd04b232278 100644
--- a/chromium/ui/gl/gl_context_osmesa.cc
+++ b/chromium/ui/gl/gl_context_osmesa.cc
@@ -26,8 +26,18 @@ bool GLContextOSMesa::Initialize(GLSurface* compatible_surface,
OSMesaContext share_handle = static_cast<OSMesaContext>(
share_group() ? share_group()->GetHandle() : nullptr);
- GLuint format = compatible_surface->GetFormat();
- DCHECK_NE(format, (unsigned)0);
+ GLuint format = 0;
+ switch (compatible_surface->GetFormat()) {
+ case GLSurface::SURFACE_OSMESA_BGRA:
+ format = OSMESA_BGRA;
+ break;
+ case GLSurface::SURFACE_OSMESA_RGBA:
+ format = OSMESA_RGBA;
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
context_ = OSMesaCreateContextExt(format,
0, // depth bits
0, // stencil bits
diff --git a/chromium/ui/gl/gl_fence.cc b/chromium/ui/gl/gl_fence.cc
index 92aba194c21..62f098c2a83 100644
--- a/chromium/ui/gl/gl_fence.cc
+++ b/chromium/ui/gl/gl_fence.cc
@@ -64,4 +64,13 @@ GLFence* GLFence::Create() {
return fence.release();
}
+bool GLFence::ResetSupported() {
+ // Resetting a fence to its original state isn't supported by default.
+ return false;
+}
+
+void GLFence::ResetState() {
+ NOTIMPLEMENTED();
+}
+
} // namespace gfx
diff --git a/chromium/ui/gl/gl_fence.h b/chromium/ui/gl/gl_fence.h
index cc25a1d735e..2f7a8772f9d 100644
--- a/chromium/ui/gl/gl_fence.h
+++ b/chromium/ui/gl/gl_fence.h
@@ -25,6 +25,12 @@ class GL_EXPORT GLFence {
// client.
virtual void ServerWait() = 0;
+ // Returns true if re-setting state is supported.
+ virtual bool ResetSupported();
+
+ // Resets the fence to the original state.
+ virtual void ResetState();
+
private:
DISALLOW_COPY_AND_ASSIGN(GLFence);
};
diff --git a/chromium/ui/gl/gl_fence_nv.cc b/chromium/ui/gl/gl_fence_nv.cc
index 0e23b283458..df972bd4b5e 100644
--- a/chromium/ui/gl/gl_fence_nv.cc
+++ b/chromium/ui/gl/gl_fence_nv.cc
@@ -20,6 +20,14 @@ GLFenceNV::GLFenceNV() {
// they are bound, in that they acquire their state upon binding.
// We will arbitrarily return TRUE for consistency.
glGenFencesNV(1, &fence_);
+ ResetState();
+}
+
+bool GLFenceNV::ResetSupported() {
+ return true;
+}
+
+void GLFenceNV::ResetState() {
glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
DCHECK(glIsFenceNV(fence_));
glFlush();
diff --git a/chromium/ui/gl/gl_fence_nv.h b/chromium/ui/gl/gl_fence_nv.h
index b1dc88fb967..488251b777a 100644
--- a/chromium/ui/gl/gl_fence_nv.h
+++ b/chromium/ui/gl/gl_fence_nv.h
@@ -17,6 +17,8 @@ class GL_EXPORT GLFenceNV : public GLFence {
~GLFenceNV() override;
// GLFence implementation:
+ bool ResetSupported() override;
+ void ResetState() override;
bool HasCompleted() override;
void ClientWait() override;
void ServerWait() override;
diff --git a/chromium/ui/gl/gl_image_io_surface.h b/chromium/ui/gl/gl_image_io_surface.h
index d8b731828f2..7b68a96b6f5 100644
--- a/chromium/ui/gl/gl_image_io_surface.h
+++ b/chromium/ui/gl/gl_image_io_surface.h
@@ -5,6 +5,7 @@
#ifndef UI_GL_GL_IMAGE_IO_SURFACE_H_
#define UI_GL_GL_IMAGE_IO_SURFACE_H_
+#include <CoreVideo/CVPixelBuffer.h>
#include <IOSurface/IOSurface.h>
#include <stdint.h>
@@ -31,6 +32,14 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
gfx::GenericSharedMemoryId io_surface_id,
gfx::BufferFormat format);
+ // IOSurfaces coming from video decode are wrapped in a CVPixelBuffer
+ // and may be discarded if the owning CVPixelBuffer is destroyed. This
+ // initialization will ensure that the CVPixelBuffer be retained for the
+ // lifetime of the GLImage.
+ bool InitializeWithCVPixelBuffer(CVPixelBufferRef cv_pixel_buffer,
+ gfx::GenericSharedMemoryId io_surface_id,
+ gfx::BufferFormat format);
+
// Overridden from GLImage:
void Destroy(bool have_context) override;
gfx::Size GetSize() override;
@@ -52,8 +61,7 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
gfx::GenericSharedMemoryId io_surface_id() const { return io_surface_id_; }
base::ScopedCFTypeRef<IOSurfaceRef> io_surface();
-
- static void SetLayerForWidget(gfx::AcceleratedWidget widget, CALayer* layer);
+ base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer();
static unsigned GetInternalFormatForTesting(gfx::BufferFormat format);
@@ -61,21 +69,19 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
~GLImageIOSurface() override;
private:
+ class RGBConverter;
+
const gfx::Size size_;
const unsigned internalformat_;
gfx::BufferFormat format_;
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
+ base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
gfx::GenericSharedMemoryId io_surface_id_;
base::ThreadChecker thread_checker_;
- // GL state to support 420v IOSurface conversion to RGB.
- unsigned framebuffer_ = 0;
- unsigned vertex_shader_ = 0;
- unsigned fragment_shader_ = 0;
- unsigned program_ = 0;
- int size_location_ = -1;
- unsigned vertex_buffer_ = 0;
- unsigned yuv_textures_[2] = {};
+ // GL state to support 420v IOSurface conversion to RGB. This is retained
+ // to avoid re-creating the necessary GL programs every frame.
+ scoped_refptr<RGBConverter> rgb_converter_;
DISALLOW_COPY_AND_ASSIGN(GLImageIOSurface);
};
diff --git a/chromium/ui/gl/gl_image_io_surface.mm b/chromium/ui/gl/gl_image_io_surface.mm
index d0ca06b88e9..5d78bc67af7 100644
--- a/chromium/ui/gl/gl_image_io_surface.mm
+++ b/chromium/ui/gl/gl_image_io_surface.mm
@@ -6,16 +6,21 @@
#include <map>
+#include "base/callback_helpers.h"
#include "base/lazy_instance.h"
+#include "base/mac/bind_objc_block.h"
#include "base/mac/foundation_util.h"
#include "base/strings/stringize_macros.h"
+#include "base/strings/stringprintf.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_helper.h"
+#include "ui/gl/scoped_api.h"
#include "ui/gl/scoped_binders.h"
+#include "ui/gl/scoped_cgl.h"
// Note that this must be included after gl_bindings.h to avoid conflicts.
#include <OpenGL/CGLIOSurface.h>
@@ -27,8 +32,10 @@ using gfx::BufferFormat;
namespace gl {
namespace {
-using WidgetToLayerMap = std::map<gfx::AcceleratedWidget, CALayer*>;
-base::LazyInstance<WidgetToLayerMap> g_widget_to_layer_map;
+const char kGLSLVersion[] = "#version 110";
+
+const char kTextureRectangleRequired[] =
+ "#extension GL_ARB_texture_rectangle : require";
// clang-format off
const char kVertexShader[] =
@@ -183,6 +190,170 @@ GLenum DataType(BufferFormat format) {
} // namespace
+class GLImageIOSurface::RGBConverter
+ : public base::RefCounted<GLImageIOSurface::RGBConverter> {
+ public:
+ static scoped_refptr<RGBConverter> GetForCurrentContext();
+ bool CopyTexImage(IOSurfaceRef io_surface, const gfx::Size& size);
+
+ private:
+ friend class base::RefCounted<RGBConverter>;
+ RGBConverter(CGLContextObj cgl_context);
+ ~RGBConverter();
+
+ unsigned framebuffer_ = 0;
+ unsigned vertex_shader_ = 0;
+ unsigned fragment_shader_ = 0;
+ unsigned program_ = 0;
+ int size_location_ = -1;
+ unsigned vertex_buffer_ = 0;
+ base::ScopedTypeRef<CGLContextObj> cgl_context_;
+
+ static base::LazyInstance<
+ std::map<CGLContextObj, GLImageIOSurface::RGBConverter*>>
+ g_rgb_converters;
+ static base::LazyInstance<base::ThreadChecker>
+ g_rgb_converters_thread_checker;
+};
+
+base::LazyInstance<std::map<CGLContextObj, GLImageIOSurface::RGBConverter*>>
+ GLImageIOSurface::RGBConverter::g_rgb_converters;
+
+base::LazyInstance<base::ThreadChecker>
+ GLImageIOSurface::RGBConverter::g_rgb_converters_thread_checker;
+
+scoped_refptr<GLImageIOSurface::RGBConverter>
+GLImageIOSurface::RGBConverter::GetForCurrentContext() {
+ CGLContextObj current_context = CGLGetCurrentContext();
+ DCHECK(current_context);
+ DCHECK(g_rgb_converters_thread_checker.Get().CalledOnValidThread());
+ auto found = g_rgb_converters.Get().find(current_context);
+ if (found != g_rgb_converters.Get().end())
+ return make_scoped_refptr(found->second);
+ return make_scoped_refptr(new RGBConverter(current_context));
+}
+
+GLImageIOSurface::RGBConverter::RGBConverter(CGLContextObj cgl_context)
+ : cgl_context_(cgl_context, base::scoped_policy::RETAIN) {
+ gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
+ glGenFramebuffersEXT(1, &framebuffer_);
+ vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer();
+ vertex_shader_ = gfx::GLHelper::LoadShader(
+ GL_VERTEX_SHADER,
+ base::StringPrintf("%s\n%s", kGLSLVersion, kVertexShader).c_str());
+ fragment_shader_ = gfx::GLHelper::LoadShader(
+ GL_FRAGMENT_SHADER,
+ base::StringPrintf("%s\n%s\n%s", kGLSLVersion, kTextureRectangleRequired,
+ kFragmentShader)
+ .c_str());
+ program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
+
+ gfx::ScopedUseProgram use_program(program_);
+ size_location_ = glGetUniformLocation(program_, "a_texScale");
+ DCHECK_NE(-1, size_location_);
+ int y_sampler_location = glGetUniformLocation(program_, "a_y_texture");
+ DCHECK_NE(-1, y_sampler_location);
+ int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture");
+ DCHECK_NE(-1, uv_sampler_location);
+
+ glUniform1i(y_sampler_location, 0);
+ glUniform1i(uv_sampler_location, 1);
+
+ DCHECK(g_rgb_converters_thread_checker.Get().CalledOnValidThread());
+ DCHECK(g_rgb_converters.Get().find(cgl_context) ==
+ g_rgb_converters.Get().end());
+ g_rgb_converters.Get()[cgl_context] = this;
+}
+
+GLImageIOSurface::RGBConverter::~RGBConverter() {
+ DCHECK(g_rgb_converters_thread_checker.Get().CalledOnValidThread());
+ DCHECK(g_rgb_converters.Get()[cgl_context_] == this);
+ g_rgb_converters.Get().erase(cgl_context_.get());
+ {
+ gfx::ScopedCGLSetCurrentContext(cgl_context_.get());
+ gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
+ glDeleteProgram(program_);
+ glDeleteShader(vertex_shader_);
+ glDeleteShader(fragment_shader_);
+ glDeleteBuffersARB(1, &vertex_buffer_);
+ glDeleteFramebuffersEXT(1, &framebuffer_);
+ }
+ cgl_context_.reset();
+}
+
+bool GLImageIOSurface::RGBConverter::CopyTexImage(IOSurfaceRef io_surface,
+ const gfx::Size& size) {
+ gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
+ DCHECK_EQ(CGLGetCurrentContext(), cgl_context_.get());
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, size.width(), size.height(),
+ 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+ GLint target_texture = 0;
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &target_texture);
+ DCHECK(target_texture);
+
+ // Note that state restoration is done explicitly in the ScopedClosureRunner
+ // instead of scoped binders to avoid https://crbug.com/601729.
+ GLint old_active_texture = -1;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &old_active_texture);
+ GLint old_texture0_binding = -1;
+ glActiveTexture(GL_TEXTURE0);
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture0_binding);
+ GLint old_texture1_binding = -1;
+ glActiveTexture(GL_TEXTURE1);
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_texture1_binding);
+
+ unsigned y_texture = 0;
+ glGenTextures(1, &y_texture);
+ unsigned uv_texture = 0;
+ glGenTextures(1, &uv_texture);
+
+ base::ScopedClosureRunner destroy_resources_runner(base::BindBlock(^{
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture0_binding);
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, old_texture1_binding);
+ glActiveTexture(old_active_texture);
+
+ glDeleteTextures(1, &y_texture);
+ glDeleteTextures(1, &uv_texture);
+ }));
+
+ CGLError cgl_error = kCGLNoError;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, y_texture);
+ cgl_error = CGLTexImageIOSurface2D(cgl_context_, GL_TEXTURE_RECTANGLE_ARB,
+ GL_RED, size.width(), size.height(),
+ GL_RED, GL_UNSIGNED_BYTE, io_surface, 0);
+ if (cgl_error != kCGLNoError) {
+ LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. "
+ << cgl_error;
+ return false;
+ }
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, uv_texture);
+ cgl_error = CGLTexImageIOSurface2D(cgl_context_, GL_TEXTURE_RECTANGLE_ARB,
+ GL_RG, size.width() / 2, size.height() / 2,
+ GL_RG, GL_UNSIGNED_BYTE, io_surface, 1);
+ if (cgl_error != kCGLNoError) {
+ LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. "
+ << cgl_error;
+ return false;
+ }
+
+ gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_);
+ gfx::ScopedViewport viewport(0, 0, size.width(), size.height());
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_RECTANGLE_ARB, target_texture, 0);
+ DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
+ gfx::ScopedUseProgram use_program(program_);
+ glUniform2f(size_location_, size.width(), size.height());
+ gfx::GLHelper::DrawQuad(vertex_buffer_);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_RECTANGLE_ARB, 0, 0);
+ return true;
+}
+
GLImageIOSurface::GLImageIOSurface(const gfx::Size& size,
unsigned internalformat)
: size_(size),
@@ -216,17 +387,27 @@ bool GLImageIOSurface::Initialize(IOSurfaceRef io_surface,
return true;
}
+bool GLImageIOSurface::InitializeWithCVPixelBuffer(
+ CVPixelBufferRef cv_pixel_buffer,
+ gfx::GenericSharedMemoryId io_surface_id,
+ BufferFormat format) {
+ IOSurfaceRef io_surface = CVPixelBufferGetIOSurface(cv_pixel_buffer);
+ if (!io_surface) {
+ LOG(ERROR) << "Can't init GLImage from CVPixelBuffer with no IOSurface";
+ return false;
+ }
+
+ if (!Initialize(io_surface, io_surface_id, format))
+ return false;
+
+ cv_pixel_buffer_.reset(cv_pixel_buffer, base::scoped_policy::RETAIN);
+ return true;
+}
+
void GLImageIOSurface::Destroy(bool have_context) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (have_context && framebuffer_) {
- glDeleteProgram(program_);
- glDeleteShader(vertex_shader_);
- glDeleteShader(fragment_shader_);
- glDeleteBuffersARB(1, &vertex_buffer_);
- glDeleteFramebuffersEXT(1, &framebuffer_);
- glDeleteTextures(2, yuv_textures_);
- }
io_surface_.reset();
+ cv_pixel_buffer_.reset();
}
gfx::Size GLImageIOSurface::GetSize() {
@@ -274,92 +455,13 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) {
if (format_ != BufferFormat::YUV_420_BIPLANAR)
return false;
-
- if (target != GL_TEXTURE_2D) {
- LOG(ERROR) << "YUV_420_BIPLANAR requires TEXTURE_2D target";
+ if (target != GL_TEXTURE_RECTANGLE_ARB) {
+ LOG(ERROR) << "YUV_420_BIPLANAR requires GL_TEXTURE_RECTANGLE_ARB target";
return false;
}
- if (!framebuffer_) {
- glGenFramebuffersEXT(1, &framebuffer_);
- vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer();
- vertex_shader_ = gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader);
- fragment_shader_ =
- gfx::GLHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShader);
- program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
- gfx::ScopedUseProgram use_program(program_);
-
- size_location_ = glGetUniformLocation(program_, "a_texScale");
- DCHECK_NE(-1, size_location_);
- int y_sampler_location = glGetUniformLocation(program_, "a_y_texture");
- DCHECK_NE(-1, y_sampler_location);
- int uv_sampler_location = glGetUniformLocation(program_, "a_uv_texture");
- DCHECK_NE(-1, uv_sampler_location);
-
- glUniform1i(y_sampler_location, 0);
- glUniform1i(uv_sampler_location, 1);
-
- glGenTextures(2, yuv_textures_);
- DCHECK(yuv_textures_[0]);
- DCHECK(yuv_textures_[1]);
- }
-
- CGLContextObj cgl_context =
- static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle());
-
- GLint target_texture = 0;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &target_texture);
- DCHECK(target_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size_.width(), size_.height(), 0,
- GL_RGB, GL_UNSIGNED_BYTE, nullptr);
-
- CGLError cgl_error = kCGLNoError;
- {
- DCHECK(io_surface_);
-
- gfx::ScopedActiveTexture active_texture0(GL_TEXTURE0);
- gfx::ScopedTextureBinder texture_y_binder(GL_TEXTURE_RECTANGLE_ARB,
- yuv_textures_[0]);
- cgl_error = CGLTexImageIOSurface2D(
- cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RED, size_.width(),
- size_.height(), GL_RED, GL_UNSIGNED_BYTE, io_surface_.get(), 0);
- if (cgl_error != kCGLNoError) {
- LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the Y plane. "
- << cgl_error;
- return false;
- }
- {
- gfx::ScopedActiveTexture active_texture1(GL_TEXTURE1);
- gfx::ScopedTextureBinder texture_uv_binder(GL_TEXTURE_RECTANGLE_ARB,
- yuv_textures_[1]);
- cgl_error = CGLTexImageIOSurface2D(
- cgl_context, GL_TEXTURE_RECTANGLE_ARB, GL_RG, size_.width() / 2,
- size_.height() / 2, GL_RG, GL_UNSIGNED_BYTE, io_surface_.get(), 1);
- if (cgl_error != kCGLNoError) {
- LOG(ERROR) << "Error in CGLTexImageIOSurface2D for the UV plane. "
- << cgl_error;
- return false;
- }
-
- gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_);
- gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height());
- glViewport(0, 0, size_.width(), size_.height());
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, target_texture, 0);
- DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
- glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
-
- gfx::ScopedUseProgram use_program(program_);
- glUniform2f(size_location_, size_.width(), size_.height());
-
- gfx::GLHelper::DrawQuad(vertex_buffer_);
-
- // Detach the output texture from the fbo.
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, 0, 0);
- }
- }
- return true;
+ rgb_converter_ = RGBConverter::GetForCurrentContext();
+ return rgb_converter_->CopyTexImage(io_surface_.get(), size_);
}
bool GLImageIOSurface::CopyTexSubImage(unsigned target,
@@ -400,13 +502,8 @@ base::ScopedCFTypeRef<IOSurfaceRef> GLImageIOSurface::io_surface() {
return io_surface_;
}
-// static
-void GLImageIOSurface::SetLayerForWidget(gfx::AcceleratedWidget widget,
- CALayer* layer) {
- if (layer)
- g_widget_to_layer_map.Pointer()->insert(std::make_pair(widget, layer));
- else
- g_widget_to_layer_map.Pointer()->erase(widget);
+base::ScopedCFTypeRef<CVPixelBufferRef> GLImageIOSurface::cv_pixel_buffer() {
+ return cv_pixel_buffer_;
}
// static
diff --git a/chromium/ui/gl/gl_image_io_surface_unittest.cc b/chromium/ui/gl/gl_image_io_surface_unittest.cc
index 487366fd8a1..6028e3feb88 100644
--- a/chromium/ui/gl/gl_image_io_surface_unittest.cc
+++ b/chromium/ui/gl/gl_image_io_surface_unittest.cc
@@ -17,6 +17,16 @@ namespace {
template <gfx::BufferFormat format>
class GLImageIOSurfaceTestDelegate {
public:
+ scoped_refptr<GLImage> CreateImage(const gfx::Size& size) const {
+ scoped_refptr<GLImageIOSurface> image(new GLImageIOSurface(
+ size, GLImageIOSurface::GetInternalFormatForTesting(format)));
+ IOSurfaceRef surface_ref = gfx::CreateIOSurface(size, format);
+ bool rv =
+ image->Initialize(surface_ref, gfx::GenericSharedMemoryId(1), format);
+ EXPECT_TRUE(rv);
+ return image;
+ }
+
scoped_refptr<GLImage> CreateSolidColorImage(const gfx::Size& size,
const uint8_t color[4]) const {
scoped_refptr<GLImageIOSurface> image(new GLImageIOSurface(
@@ -40,6 +50,8 @@ class GLImageIOSurfaceTestDelegate {
return image;
}
+
+ unsigned GetTextureTarget() const { return GL_TEXTURE_RECTANGLE_ARB; }
};
using GLImageTestTypes = testing::Types<
@@ -49,6 +61,14 @@ using GLImageTestTypes = testing::Types<
INSTANTIATE_TYPED_TEST_CASE_P(GLImageIOSurface, GLImageTest, GLImageTestTypes);
+using GLImageIOSurfaceTestTypes =
+ testing::Types<GLImageIOSurfaceTestDelegate<gfx::BufferFormat::RGBA_8888>,
+ GLImageIOSurfaceTestDelegate<gfx::BufferFormat::BGRA_8888>>;
+
+INSTANTIATE_TYPED_TEST_CASE_P(GLImageIOSurface,
+ GLImageZeroInitializeTest,
+ GLImageIOSurfaceTestTypes);
+
INSTANTIATE_TYPED_TEST_CASE_P(
GLImageIOSurface,
GLImageCopyTest,
diff --git a/chromium/ui/gl/gl_image_memory.cc b/chromium/ui/gl/gl_image_memory.cc
index 7cf74c82834..a29a388585f 100644
--- a/chromium/ui/gl/gl_image_memory.cc
+++ b/chromium/ui/gl/gl_image_memory.cc
@@ -261,7 +261,8 @@ scoped_ptr<uint8_t[]> GLES2Data(const gfx::Size& size,
case BufferFormat::R_8: {
size_t gles2_data_stride =
RowSizeForBufferFormat(size.width(), format, 0);
- if (stride == gles2_data_stride)
+ if (stride == gles2_data_stride ||
+ gfx::g_driver_gl.ext.b_GL_EXT_unpack_subimage)
return nullptr; // No data conversion needed
scoped_ptr<uint8_t[]> gles2_data(
diff --git a/chromium/ui/gl/gl_image_ozone_native_pixmap.cc b/chromium/ui/gl/gl_image_ozone_native_pixmap.cc
index 42e96a6e1ca..aeeca9f3850 100644
--- a/chromium/ui/gl/gl_image_ozone_native_pixmap.cc
+++ b/chromium/ui/gl/gl_image_ozone_native_pixmap.cc
@@ -142,6 +142,19 @@ void GLImageOzoneNativePixmap::Destroy(bool have_context) {
gl::GLImageEGL::Destroy(have_context);
}
+bool GLImageOzoneNativePixmap::CopyTexImage(unsigned target) {
+ if (egl_image_ == EGL_NO_IMAGE_KHR) {
+ // Pass-through image type fails to bind and copy; make sure we
+ // don't draw with uninitialized texture.
+ std::vector<unsigned char> data(size_.width() * size_.height() * 4);
+ glTexImage2D(target, 0, GL_RGBA, size_.width(),
+ size_.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ data.data());
+ return true;
+ }
+ return GLImageEGL::CopyTexImage(target);
+}
+
bool GLImageOzoneNativePixmap::ScheduleOverlayPlane(AcceleratedWidget widget,
int z_order,
OverlayTransform transform,
diff --git a/chromium/ui/gl/gl_image_ozone_native_pixmap.h b/chromium/ui/gl/gl_image_ozone_native_pixmap.h
index 318c8ef3df7..469c04415af 100644
--- a/chromium/ui/gl/gl_image_ozone_native_pixmap.h
+++ b/chromium/ui/gl/gl_image_ozone_native_pixmap.h
@@ -22,6 +22,7 @@ class GL_EXPORT GLImageOzoneNativePixmap : public gl::GLImageEGL {
// Overridden from GLImage:
unsigned GetInternalFormat() override;
void Destroy(bool have_context) override;
+ bool CopyTexImage(unsigned target) override;
bool ScheduleOverlayPlane(AcceleratedWidget widget,
int z_order,
OverlayTransform transform,
diff --git a/chromium/ui/gl/gl_image_ozone_native_pixmap_unittest.cc b/chromium/ui/gl/gl_image_ozone_native_pixmap_unittest.cc
index a6784152145..223ba698026 100644
--- a/chromium/ui/gl/gl_image_ozone_native_pixmap_unittest.cc
+++ b/chromium/ui/gl/gl_image_ozone_native_pixmap_unittest.cc
@@ -31,6 +31,8 @@ class GLImageOzoneNativePixmapTestDelegate {
EXPECT_TRUE(image->Initialize(pixmap.get(), pixmap->GetBufferFormat()));
return image;
}
+
+ unsigned GetTextureTarget() const { return GL_TEXTURE_2D; }
};
INSTANTIATE_TYPED_TEST_CASE_P(GLImageOzoneNativePixmap,
diff --git a/chromium/ui/gl/gl_image_ref_counted_memory_unittest.cc b/chromium/ui/gl/gl_image_ref_counted_memory_unittest.cc
index 5d5bdd3adb4..f24b1ecfa37 100644
--- a/chromium/ui/gl/gl_image_ref_counted_memory_unittest.cc
+++ b/chromium/ui/gl/gl_image_ref_counted_memory_unittest.cc
@@ -33,6 +33,8 @@ class GLImageRefCountedMemoryTestDelegate {
EXPECT_TRUE(rv);
return image;
}
+
+ unsigned GetTextureTarget() const { return GL_TEXTURE_2D; }
};
using GLImageTestTypes = testing::Types<
diff --git a/chromium/ui/gl/gl_image_shared_memory_unittest.cc b/chromium/ui/gl/gl_image_shared_memory_unittest.cc
index 57371ad289c..ae33e3845b9 100644
--- a/chromium/ui/gl/gl_image_shared_memory_unittest.cc
+++ b/chromium/ui/gl/gl_image_shared_memory_unittest.cc
@@ -38,6 +38,8 @@ class GLImageSharedMemoryTestDelegate {
EXPECT_TRUE(rv);
return image;
}
+
+ unsigned GetTextureTarget() const { return GL_TEXTURE_2D; }
};
using GLImageTestTypes = testing::Types<
@@ -86,6 +88,8 @@ class GLImageSharedMemoryPoolTestDelegate {
EXPECT_TRUE(rv);
return image;
}
+
+ unsigned GetTextureTarget() const { return GL_TEXTURE_2D; }
};
INSTANTIATE_TYPED_TEST_CASE_P(GLImageSharedMemoryPool,
diff --git a/chromium/ui/gl/gl_implementation.cc b/chromium/ui/gl/gl_implementation.cc
index 40aedde7b6e..af06cbee981 100644
--- a/chromium/ui/gl/gl_implementation.cc
+++ b/chromium/ui/gl/gl_implementation.cc
@@ -53,7 +53,7 @@ void CleanupNativeLibraries(void* unused) {
}
}
-}
+} // namespace
base::ThreadLocalPointer<GLApi>* g_current_gl_context_tls = NULL;
OSMESAApi* g_current_osmesa_context;
diff --git a/chromium/ui/gl/gl_implementation_x11.cc b/chromium/ui/gl/gl_implementation_x11.cc
index 2371c083d76..682f9f9b6d5 100644
--- a/chromium/ui/gl/gl_implementation_x11.cc
+++ b/chromium/ui/gl/gl_implementation_x11.cc
@@ -42,8 +42,8 @@ const char kGLLibraryName[] = "libGL.so.1";
const char kGLESv2LibraryName[] = "libGLESv2.so.2";
const char kEGLLibraryName[] = "libEGL.so.1";
-const char kGLESv2ANGLELibraryName[] = "libGLESv2_ANGLE.so";
-const char kEGLANGLELibraryName[] = "libEGL_ANGLE.so";
+const char kGLESv2ANGLELibraryName[] = "libGLESv2.so";
+const char kEGLANGLELibraryName[] = "libEGL.so";
} // namespace
diff --git a/chromium/ui/gl/gl_mock.cc b/chromium/ui/gl/gl_mock.cc
index 3b835792202..785376fd4f7 100644
--- a/chromium/ui/gl/gl_mock.cc
+++ b/chromium/ui/gl/gl_mock.cc
@@ -6,6 +6,17 @@
namespace gfx {
+namespace {
+
+// This is called mainly to prevent the compiler combining the code of mock
+// functions with identical contents, so that their function pointers will be
+// different.
+void MakeFunctionUnique(const char* func_name) {
+ VLOG(2) << "Calling mock " << func_name;
+}
+
+} // namespace anonymous
+
MockGLInterface::MockGLInterface() {
}
@@ -18,4 +29,13 @@ void MockGLInterface::SetGLInterface(MockGLInterface* gl_interface) {
interface_ = gl_interface;
}
+void GL_BINDING_CALL MockGLInterface::Mock_glTexSubImage3DNoData(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type) {
+ MakeFunctionUnique("glTexSubImage3DNoData");
+ interface_->TexSubImage3DNoData(
+ target, level, xoffset, yoffset, zoffset, width, height, depth,
+ format, type);
+}
+
} // namespace gfx
diff --git a/chromium/ui/gl/gl_mock.h b/chromium/ui/gl/gl_mock.h
index 2a375e6768f..1ef09fabfcd 100644
--- a/chromium/ui/gl/gl_mock.h
+++ b/chromium/ui/gl/gl_mock.h
@@ -42,19 +42,40 @@ class MockGLInterface {
const void* /*data*/) {
NOTREACHED();
}
+
void TexSubImage3D(
- GLenum /*target*/, GLint /*level*/, GLint /*xoffset*/, GLint /*yoffset*/,
- GLint /*zoffset*/, GLsizei /*width*/, GLsizei /*height*/,
- GLsizei /*depth*/, GLenum /*format*/, GLenum /*type*/,
- const void* /*pixels*/) {
- NOTREACHED();
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+ const void* pixels) {
+ if (pixels == nullptr) {
+ TexSubImage3DNoData(target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type);
+ } else {
+ NOTREACHED();
+ }
}
+ MOCK_METHOD10(TexSubImage3DNoData,
+ void(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type));
+
private:
static MockGLInterface* interface_;
// Static mock functions that invoke the member functions of interface_.
#include "gl_bindings_autogen_mock.h"
+
+ static void GL_BINDING_CALL Mock_glTexSubImage3DNoData(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type);
};
} // namespace gfx
diff --git a/chromium/ui/gl/gl_mock_autogen_gl.h b/chromium/ui/gl/gl_mock_autogen_gl.h
index 830425c360e..2a5a4457433 100644
--- a/chromium/ui/gl/gl_mock_autogen_gl.h
+++ b/chromium/ui/gl/gl_mock_autogen_gl.h
@@ -522,6 +522,7 @@ MOCK_METHOD2(PixelStorei, void(GLenum pname, GLint param));
MOCK_METHOD2(PointParameteri, void(GLenum pname, GLint param));
MOCK_METHOD2(PolygonOffset, void(GLfloat factor, GLfloat units));
MOCK_METHOD0(PopGroupMarkerEXT, void());
+MOCK_METHOD1(PrimitiveRestartIndex, void(GLuint index));
MOCK_METHOD4(ProgramBinary,
void(GLuint program,
GLenum binaryFormat,
diff --git a/chromium/ui/gl/gl_surface.cc b/chromium/ui/gl/gl_surface.cc
index a20356ec1bf..da0831528b7 100644
--- a/chromium/ui/gl/gl_surface.cc
+++ b/chromium/ui/gl/gl_surface.cc
@@ -96,6 +96,10 @@ bool GLSurface::InitializeOneOffImplementation(GLImplementation impl,
GLSurface::GLSurface() {}
bool GLSurface::Initialize() {
+ return Initialize(SURFACE_DEFAULT);
+}
+
+bool GLSurface::Initialize(GLSurface::Format format) {
return true;
}
@@ -186,9 +190,9 @@ void* GLSurface::GetConfig() {
return NULL;
}
-unsigned GLSurface::GetFormat() {
+GLSurface::Format GLSurface::GetFormat() {
NOTIMPLEMENTED();
- return 0;
+ return SURFACE_DEFAULT;
}
VSyncProvider* GLSurface::GetVSyncProvider() {
@@ -226,6 +230,10 @@ bool GLSurface::FlipsVertically() const {
return false;
}
+bool GLSurface::BuffersFlipped() const {
+ return false;
+}
+
GLSurface* GLSurface::GetCurrent() {
return current_surface_.Pointer()->Get();
}
@@ -257,8 +265,8 @@ void GLSurface::OnSetSwapInterval(int interval) {
GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
-bool GLSurfaceAdapter::Initialize() {
- return surface_->Initialize();
+bool GLSurfaceAdapter::Initialize(GLSurface::Format format) {
+ return surface_->Initialize(format);
}
void GLSurfaceAdapter::Destroy() {
@@ -365,7 +373,7 @@ void* GLSurfaceAdapter::GetConfig() {
return surface_->GetConfig();
}
-unsigned GLSurfaceAdapter::GetFormat() {
+GLSurface::Format GLSurfaceAdapter::GetFormat() {
return surface_->GetFormat();
}
@@ -390,6 +398,10 @@ bool GLSurfaceAdapter::FlipsVertically() const {
return surface_->FlipsVertically();
}
+bool GLSurfaceAdapter::BuffersFlipped() const {
+ return surface_->BuffersFlipped();
+}
+
GLSurfaceAdapter::~GLSurfaceAdapter() {}
} // namespace gfx
diff --git a/chromium/ui/gl/gl_surface.h b/chromium/ui/gl/gl_surface.h
index d84f391e1ee..6fa69478e18 100644
--- a/chromium/ui/gl/gl_surface.h
+++ b/chromium/ui/gl/gl_surface.h
@@ -36,11 +36,22 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
public:
GLSurface();
+ // Minimum bit depth of surface.
+ enum Format {
+ SURFACE_ARGB8888,
+ SURFACE_RGB565,
+ SURFACE_OSMESA_BGRA,
+ SURFACE_OSMESA_RGBA,
+ SURFACE_SURFACELESS,
+ SURFACE_DEFAULT = SURFACE_ARGB8888
+ };
+
// (Re)create the surface. TODO(apatrick): This is an ugly hack to allow the
// EGL surface associated to be recreated without destroying the associated
// context. The implementation of this function for other GLSurface derived
// classes is in a pending changelist.
virtual bool Initialize();
+ virtual bool Initialize(GLSurface::Format format);
// Destroys the surface.
virtual void Destroy() = 0;
@@ -52,8 +63,8 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
// Recreate the surface without changing the size.
virtual bool Recreate();
- // Unschedule the GpuScheduler and return true to abort the processing of
- // a GL draw call to this surface and defer it until the GpuScheduler is
+ // Unschedule the CommandExecutor and return true to abort the processing of
+ // a GL draw call to this surface and defer it until the CommandExecutor is
// rescheduled.
virtual bool DeferDraws();
@@ -144,7 +155,7 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
virtual void* GetConfig();
// Get the GL pixel format of the surface, if available.
- virtual unsigned GetFormat();
+ virtual GLSurface::Format GetFormat();
// Get access to a helper providing time of recent refresh and period
// of screen refresh. If unavailable, returns NULL.
@@ -184,6 +195,10 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
virtual bool FlipsVertically() const;
+ // Returns true if SwapBuffers or PostSubBuffers causes a flip, such that
+ // the next buffer may be 2 frames old.
+ virtual bool BuffersFlipped() const;
+
// Create a GL surface that renders directly to a view.
static scoped_refptr<GLSurface> CreateViewGLSurface(
gfx::AcceleratedWidget window);
@@ -231,7 +246,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
public:
explicit GLSurfaceAdapter(GLSurface* surface);
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
@@ -262,7 +277,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
void* GetShareHandle() override;
void* GetDisplay() override;
void* GetConfig() override;
- unsigned GetFormat() override;
+ GLSurface::Format GetFormat() override;
VSyncProvider* GetVSyncProvider() override;
bool ScheduleOverlayPlane(int z_order,
OverlayTransform transform,
@@ -271,6 +286,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
const RectF& crop_rect) override;
bool IsSurfaceless() const override;
bool FlipsVertically() const override;
+ bool BuffersFlipped() const override;
GLSurface* surface() const { return surface_.get(); }
diff --git a/chromium/ui/gl/gl_surface_android.cc b/chromium/ui/gl/gl_surface_android.cc
index 4bd113b2b32..1486ec4583d 100644
--- a/chromium/ui/gl/gl_surface_android.cc
+++ b/chromium/ui/gl/gl_surface_android.cc
@@ -59,7 +59,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
scoped_refptr<GLSurface> surface(
- new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
+ new GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, size));
if (!surface->Initialize())
return NULL;
diff --git a/chromium/ui/gl/gl_surface_egl.cc b/chromium/ui/gl/gl_surface_egl.cc
index 20f62986b46..0db0467e555 100644
--- a/chromium/ui/gl/gl_surface_egl.cc
+++ b/chromium/ui/gl/gl_surface_egl.cc
@@ -7,6 +7,9 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
+#include <vector>
+
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -14,6 +17,7 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
+#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/rect.h"
@@ -30,18 +34,13 @@
#include <android/native_window_jni.h>
#endif
-#if defined (USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-#endif
-
#if defined(USE_X11) && !defined(OS_CHROMEOS)
extern "C" {
#include <X11/Xlib.h>
#define Status int
}
#include "ui/base/x/x11_util_internal.h"
-#include "ui/gfx/x/x11_switches.h"
+#include "ui/gfx/x/x11_switches.h" // nogncheck
#endif
#if !defined(EGL_FIXED_SIZE_ANGLE)
@@ -116,7 +115,6 @@ const unsigned int MULTISWAP_FRAME_VSYNC_THRESHOLD = 60;
namespace {
-EGLConfig g_config;
EGLDisplay g_display;
EGLNativeDisplayType g_native_display;
@@ -197,9 +195,6 @@ EGLDisplay GetDisplayFromType(DisplayType display_type,
case DEFAULT:
case SWIFT_SHADER:
return eglGetDisplay(native_display);
- case ANGLE_WARP:
- return GetPlatformANGLEDisplay(native_display,
- EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, true);
case ANGLE_D3D9:
return GetPlatformANGLEDisplay(native_display,
EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, false);
@@ -224,8 +219,6 @@ const char* DisplayTypeString(DisplayType display_type) {
return "Default";
case SWIFT_SHADER:
return "SwiftShader";
- case ANGLE_WARP:
- return "WARP";
case ANGLE_D3D9:
return "D3D9";
case ANGLE_D3D11:
@@ -240,6 +233,156 @@ const char* DisplayTypeString(DisplayType display_type) {
}
}
+bool ValidateEglConfig(EGLDisplay display,
+ const EGLint* config_attribs,
+ EGLint* num_configs) {
+ if (!eglChooseConfig(display,
+ config_attribs,
+ NULL,
+ 0,
+ num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+ if (*num_configs == 0) {
+ LOG(ERROR) << "No suitable EGL configs found.";
+ return false;
+ }
+ return true;
+}
+
+EGLConfig ChooseConfig(GLSurface::Format format) {
+ static std::map<GLSurface::Format, EGLConfig> config_map;
+
+ if (config_map.find(format) != config_map.end()) {
+ return config_map[format];
+ }
+
+ // Choose an EGL configuration.
+ // On X this is only used for PBuffer surfaces.
+ EGLint renderable_type = EGL_OPENGL_ES2_BIT;
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableUnsafeES3APIs)) {
+ renderable_type = EGL_OPENGL_ES3_BIT;
+ }
+
+ EGLint buffer_size = 32;
+ EGLint alpha_size = 8;
+
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kWindowDepth)) {
+ std::string depth =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kWindowDepth);
+
+ bool succeed = base::StringToInt(depth, &buffer_size);
+ DCHECK(succeed);
+
+ alpha_size = buffer_size == 32 ? 8 : 0;
+ }
+#endif
+
+ EGLint surface_type = (format == GLSurface::SURFACE_SURFACELESS)
+ ? EGL_DONT_CARE
+ : EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+
+ EGLint config_attribs_8888[] = {
+ EGL_BUFFER_SIZE, buffer_size,
+ EGL_ALPHA_SIZE, alpha_size,
+ EGL_BLUE_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_RENDERABLE_TYPE, renderable_type,
+ EGL_SURFACE_TYPE, surface_type,
+ EGL_NONE
+ };
+
+ EGLint* choose_attributes = config_attribs_8888;
+ EGLint config_attribs_565[] = {
+ EGL_BUFFER_SIZE, 16,
+ EGL_BLUE_SIZE, 5,
+ EGL_GREEN_SIZE, 6,
+ EGL_RED_SIZE, 5,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, surface_type,
+ EGL_NONE
+ };
+ if (format == GLSurface::SURFACE_RGB565) {
+ choose_attributes = config_attribs_565;
+ }
+
+ EGLint num_configs;
+ EGLint config_size = 1;
+ EGLConfig config = nullptr;
+ EGLConfig* config_data = &config;
+ // Validate if there are any configs for given attribs.
+ if (!ValidateEglConfig(g_display, choose_attributes, &num_configs)) {
+ return config;
+ }
+
+ scoped_ptr<EGLConfig[]> matching_configs(new EGLConfig[num_configs]);
+ if (format == GLSurface::SURFACE_RGB565) {
+ config_size = num_configs;
+ config_data = matching_configs.get();
+ }
+
+ if (!eglChooseConfig(g_display, choose_attributes, config_data, config_size,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << GetLastEGLErrorString();
+ return config;
+ }
+
+ if (format == GLSurface::SURFACE_RGB565) {
+ // Because of the EGL config sort order, we have to iterate
+ // through all of them (it'll put higher sum(R,G,B) bits
+ // first with the above attribs).
+ bool match_found = false;
+ for (int i = 0; i < num_configs; i++) {
+ EGLint red, green, blue, alpha;
+ // Read the relevant attributes of the EGLConfig.
+ if (eglGetConfigAttrib(g_display, matching_configs[i],
+ EGL_RED_SIZE, &red) &&
+ eglGetConfigAttrib(g_display, matching_configs[i],
+ EGL_BLUE_SIZE, &blue) &&
+ eglGetConfigAttrib(g_display, matching_configs[i],
+ EGL_GREEN_SIZE, &green) &&
+ eglGetConfigAttrib(g_display, matching_configs[i],
+ EGL_ALPHA_SIZE, &alpha) &&
+ alpha == 0 &&
+ red == 5 &&
+ green == 6 &&
+ blue == 5) {
+ config = matching_configs[i];
+ match_found = true;
+ break;
+ }
+ }
+ if (!match_found) {
+ // To fall back to default 32 bit format, choose with
+ // the right attributes again.
+ if (!ValidateEglConfig(g_display,
+ config_attribs_8888,
+ &num_configs)) {
+ return config;
+ }
+ if (!eglChooseConfig(g_display,
+ config_attribs_8888,
+ &config,
+ 1,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << GetLastEGLErrorString();
+ return config;
+ }
+ }
+ }
+ config_map[format] = config;
+ return config;
+}
+
} // namespace
void GetEGLInitDisplays(bool supports_angle_d3d,
@@ -274,9 +417,6 @@ void GetEGLInitDisplays(bool supports_angle_d3d,
if (requested_renderer == kANGLEImplementationD3D9Name) {
init_displays->push_back(ANGLE_D3D9);
}
- if (requested_renderer == kANGLEImplementationWARPName) {
- init_displays->push_back(ANGLE_WARP);
- }
}
}
@@ -312,76 +452,6 @@ bool GLSurfaceEGL::InitializeOneOff() {
if (g_display == EGL_NO_DISPLAY)
return false;
- // Choose an EGL configuration.
- // On X this is only used for PBuffer surfaces.
- EGLint renderable_type = EGL_OPENGL_ES2_BIT;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUnsafeES3APIs)) {
- renderable_type = EGL_OPENGL_ES3_BIT;
- }
-
- EGLint buffer_size = 32;
- EGLint alpha_size = 8;
-
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kWindowDepth)) {
- std::string depth =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kWindowDepth);
-
- bool succeed = base::StringToInt(depth, &buffer_size);
- DCHECK(succeed);
-
- alpha_size = buffer_size == 32 ? 8 : 0;
- }
-#endif
-
- const EGLint kConfigAttribs[] = {
- EGL_BUFFER_SIZE, buffer_size,
- EGL_ALPHA_SIZE, alpha_size,
- EGL_BLUE_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_RED_SIZE, 8,
- EGL_RENDERABLE_TYPE, renderable_type,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
- EGL_NONE
- };
-
-#if defined(USE_OZONE)
- const EGLint* config_attribs = ui::OzonePlatform::GetInstance()
- ->GetSurfaceFactoryOzone()
- ->GetEGLSurfaceProperties(kConfigAttribs);
-#else
- const EGLint* config_attribs = kConfigAttribs;
-#endif
-
- EGLint num_configs;
- if (!eglChooseConfig(g_display,
- config_attribs,
- NULL,
- 0,
- &num_configs)) {
- LOG(ERROR) << "eglChooseConfig failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
- if (num_configs == 0) {
- LOG(ERROR) << "No suitable EGL configs found.";
- return false;
- }
-
- if (!eglChooseConfig(g_display,
- config_attribs,
- &g_config,
- 1,
- &num_configs)) {
- LOG(ERROR) << "eglChooseConfig failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS);
g_egl_create_context_robustness_supported =
HasEGLExtension("EGL_EXT_create_context_robustness");
@@ -397,8 +467,8 @@ bool GLSurfaceEGL::InitializeOneOff() {
g_use_direct_composition =
HasEGLExtension("EGL_ANGLE_direct_composition") &&
HasEGLExtension("EGL_ANGLE_flexible_surface_compatibility") &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseDirectComposition);
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableDirectComposition);
// TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
// workaround, since code written for Android WebView takes different paths
@@ -434,10 +504,21 @@ bool GLSurfaceEGL::InitializeOneOff() {
return true;
}
+GLSurface::Format GLSurfaceEGL::GetFormat() {
+ return format_;
+}
+
EGLDisplay GLSurfaceEGL::GetDisplay() {
return g_display;
}
+EGLConfig GLSurfaceEGL::GetConfig() {
+ if (!config_) {
+ config_ = ChooseConfig(format_);
+ }
+ return config_;
+}
+
EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
return g_display;
}
@@ -526,9 +607,7 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay() {
NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
: window_(window),
- config_(NULL),
size_(1, 1),
- alpha_(true),
enable_fixed_size_angle_(false),
surface_(NULL),
supports_post_sub_buffer_(false),
@@ -548,7 +627,8 @@ NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
#endif
}
-bool NativeViewGLSurfaceEGL::Initialize() {
+bool NativeViewGLSurfaceEGL::Initialize(GLSurface::Format format) {
+ format_ = format;
return Initialize(nullptr);
}
@@ -644,10 +724,6 @@ void NativeViewGLSurfaceEGL::Destroy() {
}
}
-EGLConfig NativeViewGLSurfaceEGL::GetConfig() {
- return g_config;
-}
-
bool NativeViewGLSurfaceEGL::IsOffscreen() {
return false;
}
@@ -722,10 +798,9 @@ gfx::Size NativeViewGLSurfaceEGL::GetSize() {
bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size,
float scale_factor,
bool has_alpha) {
- if (size == GetSize() && has_alpha == alpha_)
+ if (size == GetSize())
return true;
- alpha_ = has_alpha;
size_ = size;
scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
@@ -740,7 +815,7 @@ bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size,
Destroy();
- if (!Initialize()) {
+ if (!Initialize(format_)) {
LOG(ERROR) << "Failed to resize window.";
return false;
}
@@ -750,7 +825,7 @@ bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size,
bool NativeViewGLSurfaceEGL::Recreate() {
Destroy();
- if (!Initialize()) {
+ if (!Initialize(format_)) {
LOG(ERROR) << "Failed to create surface.";
return false;
}
@@ -769,6 +844,10 @@ bool NativeViewGLSurfaceEGL::FlipsVertically() const {
return flips_vertically_;
}
+bool NativeViewGLSurfaceEGL::BuffersFlipped() const {
+ return g_use_direct_composition;
+}
+
gfx::SwapResult NativeViewGLSurfaceEGL::PostSubBuffer(int x,
int y,
int width,
@@ -861,7 +940,21 @@ PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
}
bool PbufferGLSurfaceEGL::Initialize() {
+ GLSurface::Format format = SURFACE_DEFAULT;
+#if defined(OS_ANDROID)
+ // This is to allow context virtualization which requires on- and offscreen
+ // to use a compatible config. We expect the client to request RGB565
+ // onscreen surface also for this to work (with the exception of
+ // fullscreen video).
+ if (base::SysInfo::IsLowEndDevice())
+ format = SURFACE_RGB565;
+#endif
+ return Initialize(format);
+}
+
+bool PbufferGLSurfaceEGL::Initialize(GLSurface::Format format) {
EGLSurface old_surface = surface_;
+ format_ = format;
EGLDisplay display = GetDisplay();
if (!display) {
@@ -912,10 +1005,6 @@ void PbufferGLSurfaceEGL::Destroy() {
}
}
-EGLConfig PbufferGLSurfaceEGL::GetConfig() {
- return g_config;
-}
-
bool PbufferGLSurfaceEGL::IsOffscreen() {
return true;
}
@@ -946,7 +1035,7 @@ bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size,
size_ = size;
- if (!Initialize()) {
+ if (!Initialize(format_)) {
LOG(ERROR) << "Failed to resize pbuffer.";
return false;
}
@@ -987,17 +1076,19 @@ PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
SurfacelessEGL::SurfacelessEGL(const gfx::Size& size)
: size_(size) {
+ format_ = GLSurface::SURFACE_SURFACELESS;
}
bool SurfacelessEGL::Initialize() {
- return true;
+ return Initialize(SURFACE_SURFACELESS);
}
-void SurfacelessEGL::Destroy() {
+bool SurfacelessEGL::Initialize(GLSurface::Format format) {
+ format_ = format;
+ return true;
}
-EGLConfig SurfacelessEGL::GetConfig() {
- return g_config;
+void SurfacelessEGL::Destroy() {
}
bool SurfacelessEGL::IsOffscreen() {
diff --git a/chromium/ui/gl/gl_surface_egl.h b/chromium/ui/gl/gl_surface_egl.h
index 45396d47229..97f2b15384e 100644
--- a/chromium/ui/gl/gl_surface_egl.h
+++ b/chromium/ui/gl/gl_surface_egl.h
@@ -14,6 +14,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/size.h"
@@ -52,6 +53,8 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
// Implement GLSurface.
EGLDisplay GetDisplay() override;
+ EGLConfig GetConfig() override;
+ GLSurface::Format GetFormat() override;
static bool InitializeOneOff();
static EGLDisplay GetHardwareDisplay();
@@ -70,6 +73,9 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
protected:
~GLSurfaceEGL() override;
+ EGLConfig config_ = nullptr;
+ GLSurface::Format format_ = GLSurface::SURFACE_DEFAULT;
+
private:
DISALLOW_COPY_AND_ASSIGN(GLSurfaceEGL);
};
@@ -80,8 +86,8 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
explicit NativeViewGLSurfaceEGL(EGLNativeWindowType window);
// Implement GLSurface.
- EGLConfig GetConfig() override;
- bool Initialize() override;
+ using GLSurfaceEGL::Initialize;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
@@ -102,6 +108,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
const Rect& bounds_rect,
const RectF& crop_rect) override;
bool FlipsVertically() const override;
+ bool BuffersFlipped() const override;
// Create a NativeViewGLSurfaceEGL with an externally provided VSyncProvider.
// Takes ownership of the VSyncProvider.
@@ -114,9 +121,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
~NativeViewGLSurfaceEGL() override;
EGLNativeWindowType window_;
- EGLConfig config_;
gfx::Size size_;
- bool alpha_;
bool enable_fixed_size_angle_;
void OnSetSwapInterval(int interval) override;
@@ -154,8 +159,8 @@ class GL_EXPORT PbufferGLSurfaceEGL : public GLSurfaceEGL {
explicit PbufferGLSurfaceEGL(const gfx::Size& size);
// Implement GLSurface.
- EGLConfig GetConfig() override;
bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
@@ -184,8 +189,8 @@ class GL_EXPORT SurfacelessEGL : public GLSurfaceEGL {
explicit SurfacelessEGL(const gfx::Size& size);
// Implement GLSurface.
- EGLConfig GetConfig() override;
bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
bool IsSurfaceless() const override;
diff --git a/chromium/ui/gl/gl_surface_glx.cc b/chromium/ui/gl/gl_surface_glx.cc
index 20a117755c3..dea4bcc66fd 100644
--- a/chromium/ui/gl/gl_surface_glx.cc
+++ b/chromium/ui/gl/gl_surface_glx.cc
@@ -450,7 +450,7 @@ GLXDrawable NativeViewGLSurfaceGLX::GetDrawableHandle() const {
return glx_window_;
}
-bool NativeViewGLSurfaceGLX::Initialize() {
+bool NativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) {
XWindowAttributes attributes;
if (!XGetWindowAttributes(g_display, parent_window_, &attributes)) {
LOG(ERROR) << "XGetWindowAttributes failed for window " << parent_window_
@@ -588,7 +588,7 @@ UnmappedNativeViewGLSurfaceGLX::UnmappedNativeViewGLSurfaceGLX(
size_.SetSize(1, 1);
}
-bool UnmappedNativeViewGLSurfaceGLX::Initialize() {
+bool UnmappedNativeViewGLSurfaceGLX::Initialize(GLSurface::Format format) {
DCHECK(!window_);
gfx::AcceleratedWidget parent_window =
diff --git a/chromium/ui/gl/gl_surface_glx.h b/chromium/ui/gl/gl_surface_glx.h
index 294773cf778..03c127a4a8f 100644
--- a/chromium/ui/gl/gl_surface_glx.h
+++ b/chromium/ui/gl/gl_surface_glx.h
@@ -58,7 +58,7 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX,
explicit NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window);
// Implement GLSurfaceGLX.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
@@ -106,7 +106,7 @@ class GL_EXPORT UnmappedNativeViewGLSurfaceGLX : public GLSurfaceGLX {
explicit UnmappedNativeViewGLSurfaceGLX(const gfx::Size& size);
// Implement GLSurfaceGLX.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
diff --git a/chromium/ui/gl/gl_surface_mac.cc b/chromium/ui/gl/gl_surface_mac.cc
index c481462c774..7e7d5c9b8a2 100644
--- a/chromium/ui/gl/gl_surface_mac.cc
+++ b/chromium/ui/gl/gl_surface_mac.cc
@@ -29,7 +29,7 @@ class GL_EXPORT NoOpGLSurface : public GLSurface {
explicit NoOpGLSurface(const gfx::Size& size) : size_(size) {}
// Implement GLSurface.
- bool Initialize() override { return true; }
+ bool Initialize(GLSurface::Format format) override { return true; }
void Destroy() override {}
bool IsOffscreen() override { return true; }
gfx::SwapResult SwapBuffers() override {
@@ -138,7 +138,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
scoped_refptr<GLSurface> surface(
- new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size));
+ new GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, size));
if (!surface->Initialize())
return NULL;
diff --git a/chromium/ui/gl/gl_surface_osmesa.cc b/chromium/ui/gl/gl_surface_osmesa.cc
index 6521bce4bd8..e39f9bd1a87 100644
--- a/chromium/ui/gl/gl_surface_osmesa.cc
+++ b/chromium/ui/gl/gl_surface_osmesa.cc
@@ -15,24 +15,17 @@
namespace gfx {
-GLSurfaceOSMesa::GLSurfaceOSMesa(OSMesaSurfaceFormat format,
+GLSurfaceOSMesa::GLSurfaceOSMesa(GLSurface::Format format,
const gfx::Size& size)
- : size_(size) {
- switch (format) {
- case OSMesaSurfaceFormatBGRA:
- format_ = OSMESA_BGRA;
- break;
- case OSMesaSurfaceFormatRGBA:
- format_ = OSMESA_RGBA;
- break;
- }
+ : size_(size),
+ format_(format) {
// Implementations of OSMesa surface do not support having a 0 size. In such
// cases use a (1, 1) surface.
if (size_.GetArea() == 0)
size_.SetSize(1, 1);
}
-bool GLSurfaceOSMesa::Initialize() {
+bool GLSurfaceOSMesa::Initialize(GLSurface::Format format) {
return Resize(size_, 1.f, true);
}
@@ -102,7 +95,7 @@ void* GLSurfaceOSMesa::GetHandle() {
return buffer_.get();
}
-unsigned GLSurfaceOSMesa::GetFormat() {
+GLSurface::Format GLSurfaceOSMesa::GetFormat() {
return format_;
}
@@ -117,7 +110,7 @@ gfx::SwapResult GLSurfaceOSMesaHeadless::SwapBuffers() {
}
GLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless()
- : GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, gfx::Size(1, 1)) {
+ : GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, gfx::Size(1, 1)) {
}
GLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
diff --git a/chromium/ui/gl/gl_surface_osmesa.h b/chromium/ui/gl/gl_surface_osmesa.h
index dc5691660b1..d46a55c300e 100644
--- a/chromium/ui/gl/gl_surface_osmesa.h
+++ b/chromium/ui/gl/gl_surface_osmesa.h
@@ -14,17 +14,15 @@
namespace gfx {
-enum OSMesaSurfaceFormat { OSMesaSurfaceFormatBGRA, OSMesaSurfaceFormatRGBA };
-
// A surface that the Mesa software renderer draws to. This is actually just a
// buffer in system memory. GetHandle returns a pointer to the buffer. These
// surfaces can be resized and resizing preserves the contents.
class GL_EXPORT GLSurfaceOSMesa : public GLSurface {
public:
- GLSurfaceOSMesa(OSMesaSurfaceFormat format, const gfx::Size& size);
+ GLSurfaceOSMesa(GLSurface::Format format, const gfx::Size& size);
// Implement GLSurface.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool Resize(const gfx::Size& new_size,
float scale_factor,
@@ -33,14 +31,14 @@ class GL_EXPORT GLSurfaceOSMesa : public GLSurface {
gfx::SwapResult SwapBuffers() override;
gfx::Size GetSize() override;
void* GetHandle() override;
- unsigned GetFormat() override;
+ GLSurface::Format GetFormat() override;
protected:
~GLSurfaceOSMesa() override;
private:
- unsigned format_;
gfx::Size size_;
+ GLSurface::Format format_;
scoped_ptr<int32_t[]> buffer_;
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesa);
diff --git a/chromium/ui/gl/gl_surface_overlay.cc b/chromium/ui/gl/gl_surface_overlay.cc
index e683c10fbd9..299e4a80d5a 100644
--- a/chromium/ui/gl/gl_surface_overlay.cc
+++ b/chromium/ui/gl/gl_surface_overlay.cc
@@ -23,6 +23,8 @@ GLSurfaceOverlay::GLSurfaceOverlay(int z_order,
bounds_rect_(bounds_rect),
crop_rect_(crop_rect) {}
+GLSurfaceOverlay::GLSurfaceOverlay(const GLSurfaceOverlay& other) = default;
+
GLSurfaceOverlay::~GLSurfaceOverlay() {}
bool GLSurfaceOverlay::ScheduleOverlayPlane(AcceleratedWidget widget) const {
diff --git a/chromium/ui/gl/gl_surface_overlay.h b/chromium/ui/gl/gl_surface_overlay.h
index df6923ab6db..240d90b8d27 100644
--- a/chromium/ui/gl/gl_surface_overlay.h
+++ b/chromium/ui/gl/gl_surface_overlay.h
@@ -23,6 +23,7 @@ class GLSurfaceOverlay {
gl::GLImage* image,
const Rect& bounds_rect,
const RectF& crop_rect);
+ GLSurfaceOverlay(const GLSurfaceOverlay& other);
~GLSurfaceOverlay();
// Schedule the image as an overlay plane to be shown at swap time for
diff --git a/chromium/ui/gl/gl_surface_ozone.cc b/chromium/ui/gl/gl_surface_ozone.cc
index 67c1483ca9d..da803976543 100644
--- a/chromium/ui/gl/gl_surface_ozone.cc
+++ b/chromium/ui/gl/gl_surface_ozone.cc
@@ -16,6 +16,7 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/worker_pool.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/egl_util.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h"
#include "ui/gl/gl_image_ozone_native_pixmap.h"
@@ -37,6 +38,32 @@ namespace gfx {
namespace {
+// Helper function for base::Bind to create callback to eglChooseConfig.
+bool EglChooseConfig(EGLDisplay display,
+ const int32_t* attribs,
+ EGLConfig* configs,
+ int32_t config_size,
+ int32_t* num_configs) {
+ return eglChooseConfig(display, attribs, configs, config_size, num_configs);
+}
+
+// Helper function for base::Bind to create callback to eglGetConfigAttrib.
+bool EglGetConfigAttribute(EGLDisplay display,
+ EGLConfig config,
+ int32_t attribute,
+ int32_t* value) {
+ return eglGetConfigAttrib(display, config, attribute, value);
+}
+
+// Populates EglConfigCallbacks with appropriate callbacks.
+ui::EglConfigCallbacks GetEglConfigCallbacks(EGLDisplay display) {
+ ui::EglConfigCallbacks callbacks;
+ callbacks.choose_config = base::Bind(EglChooseConfig, display);
+ callbacks.get_config_attribute = base::Bind(EglGetConfigAttribute, display);
+ callbacks.get_last_error_string = base::Bind(&ui::GetLastEGLErrorString);
+ return callbacks;
+}
+
void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
EGL_FOREVER_KHR);
@@ -49,7 +76,7 @@ class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
AcceleratedWidget widget);
// GLSurface:
- bool Initialize() override;
+ bool Initialize(gfx::GLSurface::Format format) override;
bool Resize(const gfx::Size& size,
float scale_factor,
bool has_alpha) override;
@@ -59,6 +86,7 @@ class GL_EXPORT GLSurfaceOzoneEGL : public NativeViewGLSurfaceEGL {
GLImage* image,
const Rect& bounds_rect,
const RectF& crop_rect) override;
+ EGLConfig GetConfig() override;
private:
using NativeViewGLSurfaceEGL::Initialize;
@@ -81,7 +109,8 @@ GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
ozone_surface_(std::move(ozone_surface)),
widget_(widget) {}
-bool GLSurfaceOzoneEGL::Initialize() {
+bool GLSurfaceOzoneEGL::Initialize(gfx::GLSurface::Format format) {
+ format_ = format;
return Initialize(ozone_surface_->CreateVSyncProvider());
}
@@ -115,6 +144,16 @@ bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
crop_rect);
}
+EGLConfig GLSurfaceOzoneEGL::GetConfig() {
+ if (!config_) {
+ ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
+ config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
+ }
+ if (config_)
+ return config_;
+ return NativeViewGLSurfaceEGL::GetConfig();
+}
+
GLSurfaceOzoneEGL::~GLSurfaceOzoneEGL() {
Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
}
@@ -137,7 +176,7 @@ bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
}
window_ = ozone_surface_->GetNativeWindow();
- if (!Initialize()) {
+ if (!Initialize(format_)) {
LOG(ERROR) << "Failed to initialize.";
return false;
}
@@ -151,7 +190,7 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
AcceleratedWidget widget);
// GLSurface:
- bool Initialize() override;
+ bool Initialize(gfx::GLSurface::Format format) override;
bool Resize(const gfx::Size& size,
float scale_factor,
bool has_alpha) override;
@@ -172,6 +211,7 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
int width,
int height,
const SwapCompletionCallback& callback) override;
+ EGLConfig GetConfig() override;
protected:
struct PendingFrame {
@@ -205,6 +245,7 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
+ private:
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
};
@@ -232,8 +273,8 @@ GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
unsubmitted_frames_.push_back(new PendingFrame());
}
-bool GLSurfaceOzoneSurfaceless::Initialize() {
- if (!SurfacelessEGL::Initialize())
+bool GLSurfaceOzoneSurfaceless::Initialize(gfx::GLSurface::Format format) {
+ if (!SurfacelessEGL::Initialize(format))
return false;
vsync_provider_ = ozone_surface_->CreateVSyncProvider();
if (!vsync_provider_)
@@ -362,6 +403,16 @@ void GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
SwapBuffersAsync(callback);
}
+EGLConfig GLSurfaceOzoneSurfaceless::GetConfig() {
+ if (!config_) {
+ ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
+ config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
+ }
+ if (config_)
+ return config_;
+ return SurfacelessEGL::GetConfig();
+}
+
GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
Destroy(); // The EGL surface must be destroyed before SurfaceOzone.
}
@@ -527,8 +578,16 @@ void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
if (!context_)
return;
scoped_refptr<gfx::GLContext> previous_context = gfx::GLContext::GetCurrent();
- scoped_refptr<gfx::GLSurface> previous_surface = gfx::GLSurface::GetCurrent();
- context_->MakeCurrent(this);
+ scoped_refptr<gfx::GLSurface> previous_surface;
+
+ bool was_current = previous_context && previous_context->IsCurrent(nullptr) &&
+ gfx::GLSurface::GetCurrent() == this;
+ if (!was_current) {
+ // Only take a reference to previous surface if it's not |this|
+ // because otherwise we can take a self reference from our own dtor.
+ previous_surface = gfx::GLSurface::GetCurrent();
+ context_->MakeCurrent(this);
+ }
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
if (fbo_) {
@@ -543,7 +602,7 @@ void GLSurfaceOzoneSurfacelessSurfaceImpl::Destroy() {
image->Destroy(true);
}
- if (previous_context.get()) {
+ if (!was_current) {
previous_context->MakeCurrent(previous_surface.get());
} else {
context_->ReleaseCurrent(this);
@@ -580,6 +639,9 @@ bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
return false;
+ // Image must have Destroy() called before destruction.
+ if (images_[i])
+ images_[i]->Destroy(true);
images_[i] = image;
// Bind image to texture.
ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
@@ -691,7 +753,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
scoped_refptr<GLSurface> surface(
- new GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, size));
+ new GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, size));
if (!surface->Initialize())
return nullptr;
@@ -702,8 +764,9 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
(size.width() == 0 && size.height() == 0)) {
surface = new SurfacelessEGL(size);
- } else
+ } else {
surface = new PbufferGLSurfaceEGL(size);
+ }
if (!surface->Initialize())
return nullptr;
diff --git a/chromium/ui/gl/gl_surface_stub.cc b/chromium/ui/gl/gl_surface_stub.cc
index c49165fee1e..ad5b0b3fe45 100644
--- a/chromium/ui/gl/gl_surface_stub.cc
+++ b/chromium/ui/gl/gl_surface_stub.cc
@@ -9,6 +9,12 @@ namespace gfx {
void GLSurfaceStub::Destroy() {
}
+bool GLSurfaceStub::Resize(const gfx::Size& size,
+ float scale_factor,
+ bool has_alpha) {
+ return true;
+}
+
bool GLSurfaceStub::IsOffscreen() {
return false;
}
@@ -25,6 +31,10 @@ void* GLSurfaceStub::GetHandle() {
return NULL;
}
+bool GLSurfaceStub::BuffersFlipped() const {
+ return buffers_flipped_;
+}
+
GLSurfaceStub::~GLSurfaceStub() {}
} // namespace gfx
diff --git a/chromium/ui/gl/gl_surface_stub.h b/chromium/ui/gl/gl_surface_stub.h
index bf21573e1d5..9115b7c1dcd 100644
--- a/chromium/ui/gl/gl_surface_stub.h
+++ b/chromium/ui/gl/gl_surface_stub.h
@@ -13,19 +13,25 @@ namespace gfx {
class GL_EXPORT GLSurfaceStub : public GLSurface {
public:
void SetSize(const gfx::Size& size) { size_ = size; }
+ void set_buffers_flipped(bool flipped) { buffers_flipped_ = flipped; }
// Implement GLSurface.
void Destroy() override;
+ bool Resize(const gfx::Size& size,
+ float scale_factor,
+ bool has_alpha) override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
gfx::Size GetSize() override;
void* GetHandle() override;
+ bool BuffersFlipped() const override;
protected:
~GLSurfaceStub() override;
private:
gfx::Size size_;
+ bool buffers_flipped_ = false;
};
} // namespace gfx
diff --git a/chromium/ui/gl/gl_surface_wgl.cc b/chromium/ui/gl/gl_surface_wgl.cc
index 6495686f872..8890e5c7562 100644
--- a/chromium/ui/gl/gl_surface_wgl.cc
+++ b/chromium/ui/gl/gl_surface_wgl.cc
@@ -191,7 +191,7 @@ NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
Destroy();
}
-bool NativeViewGLSurfaceWGL::Initialize() {
+bool NativeViewGLSurfaceWGL::Initialize(GLSurface::Format format) {
DCHECK(!device_context_);
RECT rect;
@@ -305,7 +305,7 @@ PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
Destroy();
}
-bool PbufferGLSurfaceWGL::Initialize() {
+bool PbufferGLSurfaceWGL::Initialize(GLSurface::Format format) {
DCHECK(!device_context_);
if (!gfx::g_driver_wgl.fn.wglCreatePbufferARBFn) {
diff --git a/chromium/ui/gl/gl_surface_wgl.h b/chromium/ui/gl/gl_surface_wgl.h
index 32c7f48a3ef..7466bcb0869 100644
--- a/chromium/ui/gl/gl_surface_wgl.h
+++ b/chromium/ui/gl/gl_surface_wgl.h
@@ -36,7 +36,7 @@ class NativeViewGLSurfaceWGL : public GLSurfaceWGL {
explicit NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window);
// Implement GLSurface.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
@@ -60,7 +60,7 @@ class PbufferGLSurfaceWGL : public GLSurfaceWGL {
explicit PbufferGLSurfaceWGL(const gfx::Size& size);
// Implement GLSurface.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
diff --git a/chromium/ui/gl/gl_surface_win.cc b/chromium/ui/gl/gl_surface_win.cc
index 64a3011b9f0..9ac1f38a1a3 100644
--- a/chromium/ui/gl/gl_surface_win.cc
+++ b/chromium/ui/gl/gl_surface_win.cc
@@ -36,7 +36,7 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window);
// Implement subset of GLSurface.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
@@ -55,6 +55,8 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
// Helper routine that does one-off initialization like determining the
// pixel format.
bool GLSurface::InitializeOneOffInternal() {
+ VSyncProviderWin::InitializeOneOff();
+
switch (GetGLImplementation()) {
case kGLImplementationDesktopGL:
if (!GLSurfaceWGL::InitializeOneOff()) {
@@ -81,7 +83,7 @@ bool GLSurface::InitializeOneOffInternal() {
NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
gfx::AcceleratedWidget window)
- : GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, gfx::Size(1, 1)),
+ : GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, gfx::Size(1, 1)),
window_(window),
device_context_(NULL) {
DCHECK(window);
@@ -91,8 +93,8 @@ NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
Destroy();
}
-bool NativeViewGLSurfaceOSMesa::Initialize() {
- if (!GLSurfaceOSMesa::Initialize())
+bool NativeViewGLSurfaceOSMesa::Initialize(GLSurface::Format format) {
+ if (!GLSurfaceOSMesa::Initialize(format))
return false;
device_context_ = GetDC(window_);
@@ -236,7 +238,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
scoped_refptr<GLSurface> surface(
- new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size));
+ new GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, size));
if (!surface->Initialize())
return NULL;
diff --git a/chromium/ui/gl/gl_surface_x11.cc b/chromium/ui/gl/gl_surface_x11.cc
index 3a2a0da9fdd..4e36e2ee86e 100644
--- a/chromium/ui/gl/gl_surface_x11.cc
+++ b/chromium/ui/gl/gl_surface_x11.cc
@@ -32,7 +32,7 @@ class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
static bool InitializeOneOff();
// Implement a subset of GLSurface.
- bool Initialize() override;
+ bool Initialize(GLSurface::Format format) override;
void Destroy() override;
bool Resize(const gfx::Size& new_size,
float scale_factor,
@@ -84,7 +84,7 @@ bool GLSurface::InitializeOneOffInternal() {
NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
gfx::AcceleratedWidget window)
- : GLSurfaceOSMesa(OSMesaSurfaceFormatBGRA, gfx::Size(1, 1)),
+ : GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, gfx::Size(1, 1)),
xdisplay_(gfx::GetXDisplay()),
window_graphics_context_(0),
window_(window),
@@ -109,8 +109,8 @@ bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
return true;
}
-bool NativeViewGLSurfaceOSMesa::Initialize() {
- if (!GLSurfaceOSMesa::Initialize())
+bool NativeViewGLSurfaceOSMesa::Initialize(GLSurface::Format format) {
+ if (!GLSurfaceOSMesa::Initialize(format))
return false;
window_graphics_context_ = XCreateGC(xdisplay_, window_, 0, NULL);
@@ -308,7 +308,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
scoped_refptr<GLSurface> surface(
- new GLSurfaceOSMesa(OSMesaSurfaceFormatRGBA, size));
+ new GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, size));
if (!surface->Initialize())
return NULL;
diff --git a/chromium/ui/gl/gl_switches.cc b/chromium/ui/gl/gl_switches.cc
index fd80ff4c85c..2411517d018 100644
--- a/chromium/ui/gl/gl_switches.cc
+++ b/chromium/ui/gl/gl_switches.cc
@@ -18,7 +18,6 @@ const char kGLImplementationMockName[] = "mock";
const char kANGLEImplementationDefaultName[] = "default";
const char kANGLEImplementationD3D9Name[] = "d3d9";
const char kANGLEImplementationD3D11Name[] = "d3d11";
-const char kANGLEImplementationWARPName[] = "warp";
const char kANGLEImplementationOpenGLName[] = "gl";
const char kANGLEImplementationOpenGLESName[] = "gles";
@@ -67,8 +66,8 @@ const char kSwiftShaderPath[] = "swiftshader-path";
// context will never be lost in any situations, say, a GPU reset.
const char kGpuNoContextLost[] = "gpu-no-context-lost";
-// Turns on the use of DirectComposition to draw to the screen.
-const char kUseDirectComposition[] = "use-direct-composition";
+// Disables the use of DirectComposition to draw to the screen.
+const char kDisableDirectComposition[] = "disable-direct-composition";
// Indicates whether the dual GPU switching is supported or not.
const char kSupportsDualGpus[] = "supports-dual-gpus";
@@ -98,16 +97,16 @@ const char kDisableGLExtensions[] = "disable-gl-extensions";
// GpuProcessHost to the GPU Process. Add your switch to this list if you need
// to read it in the GPU process, else don't add it.
const char* kGLSwitchesCopiedFromGpuProcessHost[] = {
- kDisableGpuVsync,
- kDisableD3D11,
- kEnableGPUServiceLogging,
- kEnableGPUServiceTracing,
- kEnableUnsafeES3APIs,
- kGpuNoContextLost,
- kDisableGLDrawingForTests,
- kOverrideUseGLWithOSMesaForTests,
- kUseANGLE,
- kUseDirectComposition,
+ kDisableGpuVsync,
+ kDisableD3D11,
+ kEnableGPUServiceLogging,
+ kEnableGPUServiceTracing,
+ kEnableUnsafeES3APIs,
+ kGpuNoContextLost,
+ kDisableGLDrawingForTests,
+ kOverrideUseGLWithOSMesaForTests,
+ kUseANGLE,
+ kDisableDirectComposition,
};
const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches =
arraysize(kGLSwitchesCopiedFromGpuProcessHost);
diff --git a/chromium/ui/gl/gl_switches.h b/chromium/ui/gl/gl_switches.h
index 2c6122b217a..8153006bd8c 100644
--- a/chromium/ui/gl/gl_switches.h
+++ b/chromium/ui/gl/gl_switches.h
@@ -23,7 +23,6 @@ extern const char kGLImplementationMockName[];
GL_EXPORT extern const char kANGLEImplementationDefaultName[];
GL_EXPORT extern const char kANGLEImplementationD3D9Name[];
GL_EXPORT extern const char kANGLEImplementationD3D11Name[];
-GL_EXPORT extern const char kANGLEImplementationWARPName[];
GL_EXPORT extern const char kANGLEImplementationOpenGLName[];
GL_EXPORT extern const char kANGLEImplementationOpenGLESName[];
@@ -36,7 +35,7 @@ GL_EXPORT extern const char kDisableGpuVsync[];
GL_EXPORT extern const char kEnableGPUServiceLogging[];
GL_EXPORT extern const char kEnableGPUServiceTracing[];
GL_EXPORT extern const char kGpuNoContextLost[];
-GL_EXPORT extern const char kUseDirectComposition[];
+GL_EXPORT extern const char kDisableDirectComposition[];
GL_EXPORT extern const char kSupportsDualGpus[];
diff --git a/chromium/ui/gl/gl_unittests_apk.isolate b/chromium/ui/gl/gl_unittests_apk.isolate
index 1032ef6c2c1..03c9847ec41 100644
--- a/chromium/ui/gl/gl_unittests_apk.isolate
+++ b/chromium/ui/gl/gl_unittests_apk.isolate
@@ -8,6 +8,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_gl_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'<(PRODUCT_DIR)/bin/run_gl_unittests',
diff --git a/chromium/ui/gl/gl_version_info.cc b/chromium/ui/gl/gl_version_info.cc
index cc960b0a3a8..42616509e54 100644
--- a/chromium/ui/gl/gl_version_info.cc
+++ b/chromium/ui/gl/gl_version_info.cc
@@ -83,6 +83,7 @@ void GLVersionInfo::ParseVersionString(const char* version_str,
}
if (*is_es && *major_version == 3)
*is_es3 = true;
+ DCHECK(major_version != 0);
}
} // namespace gfx
diff --git a/chromium/ui/gl/gpu_switching_manager.h b/chromium/ui/gl/gpu_switching_manager.h
index 7849d4acb71..92e865af7e3 100644
--- a/chromium/ui/gl/gpu_switching_manager.h
+++ b/chromium/ui/gl/gpu_switching_manager.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "build/build_config.h"
diff --git a/chromium/ui/gl/gpu_timing.cc b/chromium/ui/gl/gpu_timing.cc
index 8989bd55b2a..f5d9ae0da4e 100644
--- a/chromium/ui/gl/gpu_timing.cc
+++ b/chromium/ui/gl/gpu_timing.cc
@@ -20,6 +20,12 @@ int64_t NanoToMicro(uint64_t nano_seconds) {
return static_cast<int64_t>(up / base::Time::kNanosecondsPerMicrosecond);
}
+int32_t QueryTimestampBits() {
+ GLint timestamp_bits;
+ glGetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, &timestamp_bits);
+ return static_cast<int32_t>(timestamp_bits);
+}
+
class GPUTimingImpl : public GPUTiming {
public:
GPUTimingImpl(GLContextReal* context);
@@ -73,6 +79,7 @@ class GPUTimingImpl : public GPUTiming {
int64_t offset_ = 0; // offset cache when timer_type_ == kTimerTypeARB
bool offset_valid_ = false;
bool force_time_elapsed_query_ = false;
+ int32_t timestamp_bit_count_gl_ = -1; // gl implementation timestamp bits
uint32_t next_timer_query_id_ = 0;
uint32_t next_good_timer_query_id_ = 0; // identify bad ids for disjoints.
@@ -310,14 +317,21 @@ GPUTimingImpl::GPUTimingImpl(GLContextReal* context) {
DCHECK(context);
const GLVersionInfo* version_info = context->GetVersionInfo();
DCHECK(version_info);
- if (version_info->is_es3 && // glGetInteger64v is supported under ES3.
- context->HasExtension("GL_EXT_disjoint_timer_query")) {
+ if (context->HasExtension("GL_EXT_disjoint_timer_query")) {
timer_type_ = GPUTiming::kTimerTypeDisjoint;
} else if (context->HasExtension("GL_ARB_timer_query")) {
timer_type_ = GPUTiming::kTimerTypeARB;
} else if (context->HasExtension("GL_EXT_timer_query")) {
timer_type_ = GPUTiming::kTimerTypeEXT;
force_time_elapsed_query_ = true;
+ timestamp_bit_count_gl_ = 0;
+ }
+ // The command glGetInteger64v is only supported under ES3 and GL3.2. Since it
+ // is only used for timestamps, we workaround this by emulating timestamps
+ // so WebGL 1.0 will still have access to the extension.
+ if (!version_info->IsAtLeastGLES(3, 0) && !version_info->IsAtLeastGL(3, 2)) {
+ force_time_elapsed_query_ = true;
+ timestamp_bit_count_gl_ = 0;
}
}
@@ -342,9 +356,19 @@ int64_t GPUTimingImpl::CalculateTimerOffset() {
timer_type_ == GPUTiming::kTimerTypeARB) {
GLint64 gl_now = 0;
glGetInteger64v(GL_TIMESTAMP, &gl_now);
- int64_t micro_now = NanoToMicro(gl_now);
- offset_ = GetCurrentCPUTime() - micro_now;
- offset_valid_ = (timer_type_ == GPUTiming::kTimerTypeARB);
+ const int64_t cpu_time = GetCurrentCPUTime();
+ const int64_t micro_offset = cpu_time - NanoToMicro(gl_now);
+
+ // We cannot expect these instructions to run with the accuracy
+ // within 1 microsecond, instead discard differences which are less
+ // than a single millisecond.
+ base::TimeDelta delta =
+ base::TimeDelta::FromMicroseconds(micro_offset - offset_);
+
+ if (delta.magnitude().InMilliseconds() >= 1) {
+ offset_ = micro_offset;
+ offset_valid_ = (timer_type_ == GPUTiming::kTimerTypeARB);
+ }
} else {
offset_ = 0;
offset_valid_ = true;
@@ -382,6 +406,15 @@ void GPUTimingImpl::EndElapsedTimeQuery(scoped_refptr<QueryResult> result) {
scoped_refptr<QueryResult> GPUTimingImpl::DoTimeStampQuery() {
DCHECK(timer_type_ != GPUTiming::kTimerTypeInvalid);
+ // Certain GL drivers have timestamp bit count set to 0 which means timestamps
+ // aren't supported. Emulate them with time elapsed queries if that is the
+ // case.
+ if (timestamp_bit_count_gl_ == -1) {
+ DCHECK(timer_type_ != GPUTiming::kTimerTypeEXT);
+ timestamp_bit_count_gl_ = QueryTimestampBits();
+ force_time_elapsed_query_ = (timestamp_bit_count_gl_ == 0);
+ }
+
if (force_time_elapsed_query_) {
// Replace with elapsed timer queries instead.
scoped_refptr<QueryResult> result = BeginElapsedTimeQuery();
diff --git a/chromium/ui/gl/gpu_timing_fake.cc b/chromium/ui/gl/gpu_timing_fake.cc
index 03f4af3d6ea..bce0bf1acad 100644
--- a/chromium/ui/gl/gpu_timing_fake.cc
+++ b/chromium/ui/gl/gpu_timing_fake.cc
@@ -16,6 +16,9 @@ using ::testing::AtMost;
using ::testing::Exactly;
using ::testing::Invoke;
using ::testing::NotNull;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
int64_t GPUTimingFake::fake_cpu_time_ = 0;
@@ -75,11 +78,13 @@ void GPUTimingFake::ExpectNoDisjointCalls(MockGLInterface& gl) {
EXPECT_CALL(gl, GetIntegerv(GL_GPU_DISJOINT_EXT, _)).Times(Exactly(0));
}
-void GPUTimingFake::ExpectGPUTimeStampQuery(
- MockGLInterface& gl, bool elapsed_query) {
+void GPUTimingFake::ExpectGPUTimeStampQuery(MockGLInterface& gl,
+ bool elapsed_query) {
EXPECT_CALL(gl, GenQueries(1, NotNull())).Times(Exactly(1))
.WillRepeatedly(Invoke(this, &GPUTimingFake::FakeGLGenQueries));
+ EXPECT_CALL(gl, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(64), Return()));
if (!elapsed_query) {
// Time Stamp based queries.
EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, _))
@@ -121,6 +126,9 @@ void GPUTimingFake::ExpectGPUTimerQuery(
if (!elapsed_query) {
// Time Stamp based queries.
+ EXPECT_CALL(gl, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(64), Return()));
+
EXPECT_CALL(gl, GetInteger64v(GL_TIMESTAMP, _))
.WillRepeatedly(
Invoke(this, &GPUTimingFake::FakeGLGetInteger64v));
diff --git a/chromium/ui/gl/gpu_timing_unittest.cc b/chromium/ui/gl/gpu_timing_unittest.cc
index 222fa55612b..22f6562e43b 100644
--- a/chromium/ui/gl/gpu_timing_unittest.cc
+++ b/chromium/ui/gl/gpu_timing_unittest.cc
@@ -17,6 +17,12 @@
namespace gfx {
+using ::testing::Exactly;
+using ::testing::NotNull;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
class GPUTimingTest : public testing::Test {
public:
void SetUp() override {
@@ -87,6 +93,7 @@ TEST_F(GPUTimingTest, FakeTimerTest) {
TEST_F(GPUTimingTest, ForceTimeElapsedQuery) {
// Test that forcing time elapsed query affects all clients.
+ SetupGLContext("3.2", "GL_ARB_timer_query");
scoped_refptr<GPUTimingClient> client1 = CreateGPUTimingClient();
EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
@@ -106,7 +113,7 @@ TEST_F(GPUTimingTest, QueryTimeStampTest) {
scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
scoped_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
- const int64_t begin_cpu_time = 123;
+ const int64_t begin_cpu_time = 1230;
const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
const int64_t cpu_gl_offset =
begin_gl_time / base::Time::kNanosecondsPerMicrosecond - begin_cpu_time;
@@ -163,4 +170,41 @@ TEST_F(GPUTimingTest, QueryTimeStampUsingElapsedTest) {
EXPECT_EQ(begin_cpu_time, end);
}
+TEST_F(GPUTimingTest, QueryTimestampUsingElapsedARBTest) {
+ // Test timestamp queries on platforms with GL_ARB_timer_query but still lack
+ // support for timestamp queries
+ SetupGLContext("3.2", "GL_ARB_timer_query");
+ scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
+ scoped_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
+
+ const int64_t begin_cpu_time = 123;
+ const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
+ const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
+ gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
+ gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
+
+ gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
+
+ // Custom mock override to ensure the timestamp bits are 0
+ EXPECT_CALL(*gl_, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<2>(0), Return()));
+
+ gpu_timer->QueryTimeStamp();
+
+ gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
+ EXPECT_FALSE(gpu_timer->IsAvailable());
+
+ gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
+ EXPECT_TRUE(gpu_timer->IsAvailable());
+ EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
+
+ int64_t start, end;
+ gpu_timer->GetStartEndTimestamps(&start, &end);
+ // Force time elapsed won't be set until a query is actually attempted
+ ASSERT_TRUE(client->IsForceTimeElapsedQuery());
+ EXPECT_EQ(begin_cpu_time, start);
+ EXPECT_EQ(begin_cpu_time, end);
+}
+
} // namespace gpu
diff --git a/chromium/ui/gl/vsync_provider_win.cc b/chromium/ui/gl/vsync_provider_win.cc
index 2152af0f917..ab76a966c64 100644
--- a/chromium/ui/gl/vsync_provider_win.cc
+++ b/chromium/ui/gl/vsync_provider_win.cc
@@ -13,13 +13,30 @@
namespace gfx {
+namespace {
+bool g_use_dwm_vsync;
+} // namespace
+
VSyncProviderWin::VSyncProviderWin(gfx::AcceleratedWidget window)
: window_(window) {
- use_dwm_ = (base::win::GetVersion() >= base::win::VERSION_WIN7);
}
VSyncProviderWin::~VSyncProviderWin() {}
+// static
+void VSyncProviderWin::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return;
+ initialized = true;
+ g_use_dwm_vsync = (base::win::GetVersion() >= base::win::VERSION_WIN7);
+
+ if (g_use_dwm_vsync) {
+ // Prewarm sandbox
+ ::LoadLibrary(L"dwmapi.dll");
+ }
+}
+
void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters");
@@ -29,7 +46,7 @@ void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
// Query the DWM timing info first if available. This will provide the most
// precise values.
- if (use_dwm_) {
+ if (g_use_dwm_vsync) {
DWM_TIMING_INFO timing_info;
timing_info.cbSize = sizeof(timing_info);
HRESULT result = DwmGetCompositionTimingInfo(NULL, &timing_info);
diff --git a/chromium/ui/gl/vsync_provider_win.h b/chromium/ui/gl/vsync_provider_win.h
index f54bad43793..6b7e64cadc5 100644
--- a/chromium/ui/gl/vsync_provider_win.h
+++ b/chromium/ui/gl/vsync_provider_win.h
@@ -13,12 +13,13 @@ class GL_EXPORT VSyncProviderWin : public VSyncProvider {
explicit VSyncProviderWin(gfx::AcceleratedWidget window);
~VSyncProviderWin() override;
+ static void InitializeOneOff();
+
// VSyncProvider overrides;
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
private:
gfx::AcceleratedWidget window_;
- bool use_dwm_;
DISALLOW_COPY_AND_ASSIGN(VSyncProviderWin);
};
diff --git a/chromium/ui/keyboard/BUILD.gn b/chromium/ui/keyboard/BUILD.gn
index 61eb9514eff..ae966b8b448 100644
--- a/chromium/ui/keyboard/BUILD.gn
+++ b/chromium/ui/keyboard/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//mojo/public/tools/bindings/mojom.gni")
import("//testing/test.gni")
import("//third_party/google_input_tools/closure.gni")
import("//third_party/google_input_tools/inputview.gni")
@@ -126,6 +127,15 @@ build_closure("inputview") {
path = rebase_path("//third_party/google_input_tools")
}
+mojom("mojom") {
+ sources = [
+ "keyboard.mojom",
+ ]
+ deps = [
+ "//ui/mojo/geometry:interfaces",
+ ]
+}
+
test("keyboard_unittests") {
sources = [
"keyboard_controller_unittest.cc",
@@ -136,7 +146,6 @@ test("keyboard_unittests") {
deps = [
":keyboard",
"//base",
- "//base/allocator",
"//base/test:test_support",
"//skia",
"//testing/gtest",
diff --git a/chromium/ui/keyboard/content/keyboard_ui_content.cc b/chromium/ui/keyboard/content/keyboard_ui_content.cc
index f117e781b03..7f97525348f 100644
--- a/chromium/ui/keyboard/content/keyboard_ui_content.cc
+++ b/chromium/ui/keyboard/content/keyboard_ui_content.cc
@@ -201,7 +201,7 @@ aura::Window* KeyboardUIContent::GetKeyboardWindow() {
}
bool KeyboardUIContent::HasKeyboardWindow() const {
- return keyboard_contents_;
+ return !!keyboard_contents_;
}
bool KeyboardUIContent::ShouldWindowOverscroll(aura::Window* window) const {
diff --git a/chromium/ui/keyboard/keyboard.gyp b/chromium/ui/keyboard/keyboard.gyp
index 96fc1fdfa67..38d12a008a4 100644
--- a/chromium/ui/keyboard/keyboard.gyp
+++ b/chromium/ui/keyboard/keyboard.gyp
@@ -149,21 +149,6 @@
'keyboard_util_unittest.cc',
'test/run_all_unittests.cc',
],
- 'conditions': [
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- 'link_settings': {
- 'ldflags': ['-rdynamic'],
- },
- }],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
- ],
},
],
}
diff --git a/chromium/ui/keyboard/keyboard.mojom b/chromium/ui/keyboard/keyboard.mojom
new file mode 100644
index 00000000000..212765b17a5
--- /dev/null
+++ b/chromium/ui/keyboard/keyboard.mojom
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module keyboard.mojom;
+
+import "ui/mojo/geometry/geometry.mojom";
+
+interface KeyboardObserver {
+ // Sent any time state changes in the keyboard.
+ OnKeyboardStateChanged(bool is_enabled,
+ bool is_visible,
+ uint64 display_id,
+ mojo.Rect bounds);
+};
+
+interface Keyboard {
+ // TODO(sky): needs display id.
+ Show();
+ Hide();
+
+ // Adds an observer. OnKeyboardStateChanged() is immediately called to give
+ // the initial state.
+ AddObserver(KeyboardObserver observer);
+};
diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc
index 9eeb34789b0..ad1e640afc9 100644
--- a/chromium/ui/keyboard/keyboard_controller.cc
+++ b/chromium/ui/keyboard/keyboard_controller.cc
@@ -388,7 +388,8 @@ void KeyboardController::OnInputMethodDestroyed(
}
void KeyboardController::OnShowImeIfNeeded() {
- ShowKeyboardInternal();
+ if (IsKeyboardEnabled())
+ ShowKeyboardInternal();
}
void KeyboardController::ShowKeyboardInternal() {
diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h
index ecd991d265f..3c0765e57f9 100644
--- a/chromium/ui/keyboard/keyboard_controller.h
+++ b/chromium/ui/keyboard/keyboard_controller.h
@@ -65,9 +65,7 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
aura::Window* GetContainerWindow();
// Whether the container window for the keyboard has been initialized.
- bool keyboard_container_initialized() const {
- return container_.get() != NULL;
- }
+ bool keyboard_container_initialized() const { return container_ != nullptr; }
// Reloads the content of the keyboard. No-op if the keyboard content is not
// loaded yet.
diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc
index ddcf2e0562a..63bbeacb200 100644
--- a/chromium/ui/keyboard/keyboard_controller_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc
@@ -96,7 +96,7 @@ class TestKeyboardUI : public KeyboardUI {
}
// Overridden from KeyboardUI:
- bool HasKeyboardWindow() const override { return window_; }
+ bool HasKeyboardWindow() const override { return !!window_; }
bool ShouldWindowOverscroll(aura::Window* window) const override {
return true;
}
@@ -316,6 +316,7 @@ TEST_F(KeyboardControllerTest, FloatingKeyboardSize) {
// Tests that tapping/clicking inside the keyboard does not give it focus.
TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
+ keyboard::SetAccessibilityKeyboardEnabled(true);
const gfx::Rect& root_bounds = root_window()->bounds();
aura::test::EventCountDelegate delegate;
scoped_ptr<aura::Window> window(new aura::Window(&delegate));
@@ -356,9 +357,11 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
generator.ClickLeftButton();
EXPECT_EQ("1 1", delegate.GetMouseButtonCountsAndReset());
keyboard_container->RemovePreTargetHandler(&observer);
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
+ keyboard::SetAccessibilityKeyboardEnabled(true);
ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT);
@@ -394,6 +397,7 @@ TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
EXPECT_FALSE(WillHideKeyboard());
EXPECT_TRUE(keyboard_container->IsVisible());
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
// Test to prevent spurious overscroll boxes when changing tabs during keyboard
@@ -423,6 +427,7 @@ TEST_F(KeyboardControllerTest, CheckOverscrollInsetDuringVisibilityChange) {
// Verify switch to FLOATING mode will reset the overscroll or resize and when
// in FLOATING mode, overscroll or resize wont be triggered.
TEST_F(KeyboardControllerTest, FloatingKeyboardDontOverscrollOrResize) {
+ keyboard::SetAccessibilityKeyboardEnabled(true);
ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
@@ -453,6 +458,7 @@ TEST_F(KeyboardControllerTest, FloatingKeyboardDontOverscrollOrResize) {
// In FLOATING mode, no overscroll or resize should be triggered.
EXPECT_EQ(3, number_of_calls());
EXPECT_EQ(gfx::Rect(), controller()->current_keyboard_bounds());
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
// Verify switch to FULL_WIDTH mode will move virtual keyboard to the right
@@ -479,6 +485,7 @@ TEST_F(KeyboardControllerTest, SwitchToFullWidthVirtualKeyboard) {
}
TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
+ keyboard::SetAccessibilityKeyboardEnabled(true);
ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
@@ -514,6 +521,7 @@ TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
// Wait for hide keyboard to finish.
base::MessageLoop::current()->Run();
EXPECT_FALSE(keyboard_container->IsVisible());
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
class KeyboardControllerAnimationTest : public KeyboardControllerTest {
@@ -553,6 +561,7 @@ class KeyboardControllerAnimationTest : public KeyboardControllerTest {
// Tests virtual keyboard has correct show and hide animation.
TEST_F(KeyboardControllerAnimationTest, ContainerAnimation) {
ui::Layer* layer = keyboard_container()->layer();
+ keyboard::SetAccessibilityKeyboardEnabled(true);
ShowKeyboard();
// Keyboard container and window should immediately become visible before
@@ -593,12 +602,14 @@ TEST_F(KeyboardControllerAnimationTest, ContainerAnimation) {
EXPECT_GT(hide_start_opacity, hide_end_opacity);
EXPECT_EQ(transform, layer->transform());
EXPECT_EQ(gfx::Rect(), notified_bounds());
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
// Show keyboard during keyboard hide animation should abort the hide animation
// and the keyboard should animate in.
// Test for crbug.com/333284.
TEST_F(KeyboardControllerAnimationTest, ContainerShowWhileHide) {
+ keyboard::SetAccessibilityKeyboardEnabled(true);
ui::Layer* layer = keyboard_container()->layer();
ShowKeyboard();
RunAnimationForLayer(layer);
@@ -611,6 +622,7 @@ TEST_F(KeyboardControllerAnimationTest, ContainerShowWhileHide) {
EXPECT_TRUE(keyboard_window()->IsVisible());
EXPECT_EQ(1.0, layer->opacity());
EXPECT_EQ(gfx::Transform(), layer->transform());
+ keyboard::SetAccessibilityKeyboardEnabled(false);
}
// Test for crbug.com/568274.
diff --git a/chromium/ui/keyboard/resources/OWNERS b/chromium/ui/keyboard/resources/OWNERS
index 7a6ff670440..d1ba0b0bf9b 100644
--- a/chromium/ui/keyboard/resources/OWNERS
+++ b/chromium/ui/keyboard/resources/OWNERS
@@ -1,3 +1,2 @@
-bryeung@chromium.org
bshe@chromium.org
-kevers@chromium.org
+rsadam@chromium.org
diff --git a/chromium/ui/keyboard/resources/inputview_adapter.js b/chromium/ui/keyboard/resources/inputview_adapter.js
index 1e0d459f974..32849e0163c 100644
--- a/chromium/ui/keyboard/resources/inputview_adapter.js
+++ b/chromium/ui/keyboard/resources/inputview_adapter.js
@@ -224,6 +224,16 @@ function registerInputviewApi() {
}
/**
+ * Retrieve the current display size in inches.
+ * @param {function} callback
+ * @private
+ */
+ function getDisplayInInches_(callback) {
+ callback(0);
+ }
+
+
+ /**
* Retrieve the current input method configuration.
* @param {function} callback The callback function for processing the
* name of the active input mehtod.
@@ -320,6 +330,7 @@ function registerInputviewApi() {
getCurrentInputMethod: getCurrentInputMethod_,
getInputMethodConfig: getInputMethodConfig_,
switchToInputMethod: switchToInputMethod_,
+ getDisplayInInches: getDisplayInInches_,
openSettings: openSettings_
};
diff --git a/chromium/ui/login/account_picker/user_pod_row.css b/chromium/ui/login/account_picker/user_pod_row.css
index 412179398c7..88f117b5b9a 100644
--- a/chromium/ui/login/account_picker/user_pod_row.css
+++ b/chromium/ui/login/account_picker/user_pod_row.css
@@ -502,7 +502,7 @@ html[dir=rtl] .user-type-icon-area {
}
.action-box-area.menu-moved-up {
- -webkit-transform: rotate(180deg);
+ transform: rotate(180deg);
}
html[dir=rtl] .action-box-area.active ~ .action-box-menu {
diff --git a/chromium/ui/login/account_picker/user_pod_row.js b/chromium/ui/login/account_picker/user_pod_row.js
index c36496d08a4..8bc93b994df 100644
--- a/chromium/ui/login/account_picker/user_pod_row.js
+++ b/chromium/ui/login/account_picker/user_pod_row.js
@@ -3002,21 +3002,23 @@ cr.define('login', function() {
if (this.pods.length == 1)
return null;
- // The desktop User Manager can send the index of a pod that should be
- // initially focused in url hash.
- var podIndex = parseInt(window.location.hash.substr(1));
- if (isNaN(podIndex) || podIndex >= this.pods.length)
- return null;
- return this.pods[podIndex];
+ // The desktop User Manager can send an URI encoded profile path in the
+ // url hash, that indicates a pod that should be initially focused.
+ var focusedProfilePath =
+ decodeURIComponent(window.location.hash.substr(1));
+ for (var i = 0, pod; pod = this.pods[i]; ++i) {
+ if (focusedProfilePath === pod.user.profilePath)
+ return pod;
+ }
+ return null;
}
var lockedPod = this.lockedPod;
if (lockedPod)
return lockedPod;
- for (var i = 0, pod; pod = this.pods[i]; ++i) {
- if (!pod.multiProfilesPolicyApplied) {
+ for (i = 0; pod = this.pods[i]; ++i) {
+ if (!pod.multiProfilesPolicyApplied)
return pod;
- }
}
return this.pods[0];
},
@@ -3243,14 +3245,18 @@ cr.define('login', function() {
* Called right after the pod row is shown.
*/
handleAfterShow: function() {
+ var focusedPod = this.focusedPod_;
+
// Without timeout changes in pods positions will be animated even though
// it happened when 'flying-pods' class was disabled.
setTimeout(function() {
Oobe.getInstance().toggleClass('flying-pods', true);
+ if (focusedPod)
+ ensureTransitionEndEvent(focusedPod);
}, 0);
+
// Force input focus for user pod on show and once transition ends.
- if (this.focusedPod_) {
- var focusedPod = this.focusedPod_;
+ if (focusedPod) {
var screen = this.parentNode;
var self = this;
focusedPod.addEventListener('webkitTransitionEnd', function f(e) {
@@ -3259,8 +3265,6 @@ cr.define('login', function() {
// Notify screen that it is ready.
screen.onShow();
});
- // Guard timer for 1 second -- it would conver all possible animations.
- ensureTransitionEndEvent(focusedPod, 1000);
}
},
diff --git a/chromium/ui/login/display_manager.js b/chromium/ui/login/display_manager.js
index a945bfef1ca..b8c6b1d27f2 100644
--- a/chromium/ui/login/display_manager.js
+++ b/chromium/ui/login/display_manager.js
@@ -31,6 +31,8 @@
/** @const */ var SCREEN_TERMS_OF_SERVICE = 'terms-of-service';
/** @const */ var SCREEN_WRONG_HWID = 'wrong-hwid';
/** @const */ var SCREEN_DEVICE_DISABLED = 'device-disabled';
+/** @const */ var SCREEN_UNRECOVERABLE_CRYPTOHOME_ERROR =
+ 'unrecoverable-cryptohome-error';
/* Accelerator identifiers. Must be kept in sync with webui_login_view.cc. */
/** @const */ var ACCELERATOR_CANCEL = 'cancel';
diff --git a/chromium/ui/login/screen_container.css b/chromium/ui/login/screen_container.css
index 97a824b8baa..57742eaf678 100644
--- a/chromium/ui/login/screen_container.css
+++ b/chromium/ui/login/screen_container.css
@@ -70,7 +70,8 @@
#oobe.terms-of-service #inner-container,
#oobe.update #inner-container,
#oobe.user-image #inner-container,
-#oobe.wrong-hwid #inner-container {
+#oobe.wrong-hwid #inner-container,
+#oobe.unrecoverable-cryptohome-error #inner-container {
background: white;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3),
0 4px 23px 5px rgba(0, 0, 0, 0.2),
@@ -87,11 +88,11 @@
/* Only play this animation when 'down' class is removed. */
.oobe-display #inner-container:not(.down) {
- -webkit-transition: -webkit-transform 200ms ease-in-out;
+ -webkit-transition: transform 200ms ease-in-out;
}
.oobe-display #inner-container.down {
- -webkit-transform: translateY(50px) rotateX(-2.5deg);
+ transform: translateY(50px) rotateX(-2.5deg);
}
#step-logo {
@@ -147,7 +148,8 @@
#supervised-user-creation-dot,
#terms-of-service-dot,
#tpm-error-message-dot,
-#wrong-hwid-dot {
+#wrong-hwid-dot,
+#unrecoverable-cryptohome-error-dot {
display: none;
}
diff --git a/chromium/ui/message_center/BUILD.gn b/chromium/ui/message_center/BUILD.gn
index bda992c3c37..b925476379f 100644
--- a/chromium/ui/message_center/BUILD.gn
+++ b/chromium/ui/message_center/BUILD.gn
@@ -6,6 +6,7 @@ import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//testing/test.gni")
+# TODO(msw|mukai|dewittj): Move ash-specific files: crbug.com/585175
component("message_center") {
deps = [
"//base",
@@ -73,6 +74,8 @@ component("message_center") {
"notifier_settings.h",
"popup_timer.cc",
"popup_timer.h",
+ "popup_timers_controller.cc",
+ "popup_timers_controller.h",
]
if (is_win) {
@@ -88,6 +91,10 @@ component("message_center") {
"views/constants.h",
"views/desktop_popup_alignment_delegate.cc",
"views/desktop_popup_alignment_delegate.h",
+ "views/message_bubble_base.cc",
+ "views/message_bubble_base.h",
+ "views/message_center_bubble.cc",
+ "views/message_center_bubble.h",
"views/message_center_button_bar.cc",
"views/message_center_button_bar.h",
"views/message_center_controller.h",
@@ -124,15 +131,6 @@ component("message_center") {
"//ui/views",
]
}
-
- if (use_ash) {
- sources += [
- "views/message_bubble_base.cc",
- "views/message_bubble_base.h",
- "views/message_center_bubble.cc",
- "views/message_center_bubble.h",
- ]
- }
} else {
# Notification service disabled.
sources = [
@@ -190,7 +188,6 @@ test("message_center_unittests") {
":message_center",
":test_support",
"//base",
- "//base/allocator",
"//base/test:test_support",
"//skia",
"//testing/gtest",
@@ -205,6 +202,10 @@ test("message_center_unittests") {
"//url",
]
+ data_deps = [
+ "//ui/resources:ui_test_pak_data",
+ ]
+
if (enable_notifications && !is_android) {
sources += [
"cocoa/notification_controller_unittest.mm",
diff --git a/chromium/ui/message_center/cocoa/settings_controller_unittest.mm b/chromium/ui/message_center/cocoa/settings_controller_unittest.mm
index c686fcfe6b2..a1291b7d925 100644
--- a/chromium/ui/message_center/cocoa/settings_controller_unittest.mm
+++ b/chromium/ui/message_center/cocoa/settings_controller_unittest.mm
@@ -37,8 +37,7 @@ NotifierGroup* NewGroup(const std::string& name,
const std::string& login_info) {
return new NotifierGroup(gfx::Image(),
base::UTF8ToUTF16(name),
- base::UTF8ToUTF16(login_info),
- true);
+ base::UTF8ToUTF16(login_info));
}
Notifier* NewNotifier(const std::string& id,
diff --git a/chromium/ui/message_center/fake_message_center.cc b/chromium/ui/message_center/fake_message_center.cc
index c994088c0a3..f2db0dba356 100644
--- a/chromium/ui/message_center/fake_message_center.cc
+++ b/chromium/ui/message_center/fake_message_center.cc
@@ -72,11 +72,7 @@ void FakeMessageCenter::RemoveNotification(const std::string& id,
bool by_user) {
}
-void FakeMessageCenter::RemoveAllNotifications(bool by_user) {
-}
-
-void FakeMessageCenter::RemoveAllVisibleNotifications(bool by_user) {
-}
+void FakeMessageCenter::RemoveAllNotifications(bool by_user, RemoveType type) {}
void FakeMessageCenter::SetNotificationIcon(const std::string& notification_id,
const gfx::Image& image) {
diff --git a/chromium/ui/message_center/fake_message_center.h b/chromium/ui/message_center/fake_message_center.h
index 003efbc7e64..cfbf8e97b37 100644
--- a/chromium/ui/message_center/fake_message_center.h
+++ b/chromium/ui/message_center/fake_message_center.h
@@ -40,8 +40,7 @@ class FakeMessageCenter : public MessageCenter {
scoped_ptr<Notification> new_notification) override;
void RemoveNotification(const std::string& id, bool by_user) override;
- void RemoveAllNotifications(bool by_user) override;
- void RemoveAllVisibleNotifications(bool by_user) override;
+ void RemoveAllNotifications(bool by_user, RemoveType type) override;
void SetNotificationIcon(const std::string& notification_id,
const gfx::Image& image) override;
diff --git a/chromium/ui/message_center/fake_message_center_tray_delegate.h b/chromium/ui/message_center/fake_message_center_tray_delegate.h
index cee0c79940a..d0e9579291f 100644
--- a/chromium/ui/message_center/fake_message_center_tray_delegate.h
+++ b/chromium/ui/message_center/fake_message_center_tray_delegate.h
@@ -34,7 +34,6 @@ class FakeMessageCenterTrayDelegate : public MessageCenterTrayDelegate {
private:
scoped_ptr<MessageCenterTray> tray_;
base::Closure quit_closure_;
- bool displayed_first_run_balloon_;
DISALLOW_COPY_AND_ASSIGN(FakeMessageCenterTrayDelegate);
};
diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.cc b/chromium/ui/message_center/fake_notifier_settings_provider.cc
index 79c153a8783..9cafc933e15 100644
--- a/chromium/ui/message_center/fake_notifier_settings_provider.cc
+++ b/chromium/ui/message_center/fake_notifier_settings_provider.cc
@@ -12,6 +12,9 @@ namespace message_center {
FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem() {
}
+FakeNotifierSettingsProvider::NotifierGroupItem::NotifierGroupItem(
+ const NotifierGroupItem& other) = default;
+
FakeNotifierSettingsProvider::NotifierGroupItem::~NotifierGroupItem() {
}
@@ -28,8 +31,7 @@ FakeNotifierSettingsProvider::FakeNotifierSettingsProvider(
NotifierGroupItem item;
item.group = new NotifierGroup(gfx::Image(),
base::UTF8ToUTF16("Fake name"),
- base::UTF8ToUTF16("fake@email.com"),
- true);
+ base::UTF8ToUTF16("fake@email.com"));
item.notifiers = notifiers;
items_.push_back(item);
}
diff --git a/chromium/ui/message_center/fake_notifier_settings_provider.h b/chromium/ui/message_center/fake_notifier_settings_provider.h
index d5a2c8a8382..e8e6c2ba8a4 100644
--- a/chromium/ui/message_center/fake_notifier_settings_provider.h
+++ b/chromium/ui/message_center/fake_notifier_settings_provider.h
@@ -56,6 +56,7 @@ class FakeNotifierSettingsProvider : public NotifierSettingsProvider {
std::vector<Notifier*> notifiers;
NotifierGroupItem();
+ NotifierGroupItem(const NotifierGroupItem& other);
~NotifierGroupItem();
};
diff --git a/chromium/ui/message_center/message_center.gyp b/chromium/ui/message_center/message_center.gyp
index 90f68388c34..0940f24419c 100644
--- a/chromium/ui/message_center/message_center.gyp
+++ b/chromium/ui/message_center/message_center.gyp
@@ -8,6 +8,7 @@
},
'targets': [
{
+ # TODO(msw|mukai|dewittj): Move ash-specific files: crbug.com/585175
# GN version: //ui/message_center
'target_name': 'message_center',
'type': '<(component)',
@@ -66,6 +67,8 @@
'notifier_settings.h',
'popup_timer.cc',
'popup_timer.h',
+ 'popup_timers_controller.cc',
+ 'popup_timers_controller.h',
'views/bounded_label.cc',
'views/bounded_label.h',
'views/constants.h',
@@ -129,14 +132,6 @@
['exclude', 'views/'],
],
}],
- ['use_ash==0', {
- 'sources!': [
- 'views/message_bubble_base.cc',
- 'views/message_bubble_base.h',
- 'views/message_center_bubble.cc',
- 'views/message_center_bubble.h',
- ],
- }],
# iOS disables notifications altogether, Android implements its own
# notification UI manager instead of deferring to the message center.
['notifications==0 or OS=="android"', {
@@ -239,12 +234,6 @@
['include', '^test/run_all_unittests\\.cc$'],
],
}],
- # See http://crbug.com/162998#c4 for why this is needed.
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
],
}, # target_name: message_center_unittests
],
diff --git a/chromium/ui/message_center/message_center.h b/chromium/ui/message_center/message_center.h
index 00d9545d639..d6ce0c38acb 100644
--- a/chromium/ui/message_center/message_center.h
+++ b/chromium/ui/message_center/message_center.h
@@ -50,6 +50,13 @@ class NotifierSettingsProvider;
class MESSAGE_CENTER_EXPORT MessageCenter {
public:
+ enum class RemoveType {
+ // Remove all notifications.
+ ALL,
+ // Remove non-pinned notification (don't remove invisible ones).
+ NON_PINNED,
+ };
+
// Creates the global message center object.
static void Initialize();
@@ -102,8 +109,7 @@ class MESSAGE_CENTER_EXPORT MessageCenter {
// Removes an existing notification.
virtual void RemoveNotification(const std::string& id, bool by_user) = 0;
- virtual void RemoveAllNotifications(bool by_user) = 0;
- virtual void RemoveAllVisibleNotifications(bool by_user) = 0;
+ virtual void RemoveAllNotifications(bool by_user, RemoveType type) = 0;
// Sets the icon image. Icon appears at the top-left of the notification.
virtual void SetNotificationIcon(const std::string& notification_id,
diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc
index c1a9e122cad..07cbe104ca0 100644
--- a/chromium/ui/message_center/message_center_impl.cc
+++ b/chromium/ui/message_center/message_center_impl.cc
@@ -21,7 +21,7 @@
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/notification_types.h"
-#include "ui/message_center/popup_timer.h"
+#include "ui/message_center/popup_timers_controller.h"
namespace message_center {
namespace internal {
@@ -643,23 +643,20 @@ void MessageCenterImpl::RemoveNotificationsForNotifierId(
}
}
-void MessageCenterImpl::RemoveAllNotifications(bool by_user) {
- // Using not |blockers_| but an empty list since it wants to remove literally
- // all notifications.
- RemoveNotifications(by_user, NotificationBlockers());
-}
+void MessageCenterImpl::RemoveAllNotifications(bool by_user, RemoveType type) {
+ bool remove_pinned = (type == RemoveType::NON_PINNED);
-void MessageCenterImpl::RemoveAllVisibleNotifications(bool by_user) {
- RemoveNotifications(by_user, blockers_);
-}
+ const NotificationBlockers& blockers =
+ (type == RemoveType::ALL ? NotificationBlockers() /* empty blockers */
+ : blockers_ /* use default blockers */);
-void MessageCenterImpl::RemoveNotifications(
- bool by_user,
- const NotificationBlockers& blockers) {
const NotificationList::Notifications notifications =
notification_list_->GetVisibleNotifications(blockers);
std::set<std::string> ids;
for (const auto& notification : notifications) {
+ if (!remove_pinned && notification->pinned())
+ continue;
+
ids.insert(notification->id());
scoped_refptr<NotificationDelegate> delegate = notification->delegate();
if (delegate.get())
diff --git a/chromium/ui/message_center/message_center_impl.h b/chromium/ui/message_center/message_center_impl.h
index 27997922a1b..03dc9bc78f4 100644
--- a/chromium/ui/message_center/message_center_impl.h
+++ b/chromium/ui/message_center/message_center_impl.h
@@ -20,7 +20,7 @@
#include "ui/message_center/message_center_types.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/notifier_settings.h"
-#include "ui/message_center/popup_timer.h"
+#include "ui/message_center/popup_timers_controller.h"
namespace message_center {
class NotificationDelegate;
@@ -58,8 +58,7 @@ class MessageCenterImpl : public MessageCenter,
void UpdateNotification(const std::string& old_id,
scoped_ptr<Notification> new_notification) override;
void RemoveNotification(const std::string& id, bool by_user) override;
- void RemoveAllNotifications(bool by_user) override;
- void RemoveAllVisibleNotifications(bool by_user) override;
+ void RemoveAllNotifications(bool by_user, RemoveType type) override;
void SetNotificationIcon(const std::string& notification_id,
const gfx::Image& image) override;
void SetNotificationImage(const std::string& notification_id,
@@ -116,7 +115,6 @@ class MessageCenterImpl : public MessageCenter,
size_t unread_count;
};
- void RemoveNotifications(bool by_user, const NotificationBlockers& blockers);
void RemoveNotificationsForNotifierId(const NotifierId& notifier_id);
scoped_ptr<NotificationList> notification_list_;
diff --git a/chromium/ui/message_center/message_center_impl_unittest.cc b/chromium/ui/message_center/message_center_impl_unittest.cc
index 2b405fe6de4..bc3828bc994 100644
--- a/chromium/ui/message_center/message_center_impl_unittest.cc
+++ b/chromium/ui/message_center/message_center_impl_unittest.cc
@@ -559,9 +559,10 @@ TEST_F(MessageCenterImplTest, TotalNotificationBlocker) {
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
EXPECT_TRUE(NotificationsContain(notifications, "id4"));
- // RemoveAllVisibleNotifications should remove just visible notifications.
+ // Remove just visible notifications.
blocker.SetNotificationsEnabled(false);
- message_center()->RemoveAllVisibleNotifications(false /* by_user */);
+ message_center()->RemoveAllNotifications(
+ false /* by_user */, MessageCenter::RemoveType::NON_PINNED);
EXPECT_EQ(0u, message_center()->NotificationCount());
blocker.SetNotificationsEnabled(true);
EXPECT_EQ(2u, message_center()->NotificationCount());
@@ -571,9 +572,10 @@ TEST_F(MessageCenterImplTest, TotalNotificationBlocker) {
EXPECT_TRUE(NotificationsContain(notifications, "id3"));
EXPECT_FALSE(NotificationsContain(notifications, "id4"));
- // And RemoveAllNotifications should remove all.
+ // And remove all including invisible notifications.
blocker.SetNotificationsEnabled(false);
- message_center()->RemoveAllNotifications(false /* by_user */);
+ message_center()->RemoveAllNotifications(false /* by_user */,
+ MessageCenter::RemoveType::ALL);
EXPECT_EQ(0u, message_center()->NotificationCount());
}
diff --git a/chromium/ui/message_center/notification.cc b/chromium/ui/message_center/notification.cc
index 9de5ccb3675..b0a379ddb9d 100644
--- a/chromium/ui/message_center/notification.cc
+++ b/chromium/ui/message_center/notification.cc
@@ -34,6 +34,10 @@ RichNotificationData::RichNotificationData()
progress(0),
should_make_spoken_feedback_for_popup_updates(true),
clickable(true),
+#if defined(OS_CHROMEOS)
+ pinned(false),
+#endif // defined(OS_CHROMEOS)
+ renotify(false),
silent(false) {}
RichNotificationData::RichNotificationData(const RichNotificationData& other)
@@ -49,7 +53,11 @@ RichNotificationData::RichNotificationData(const RichNotificationData& other)
should_make_spoken_feedback_for_popup_updates(
other.should_make_spoken_feedback_for_popup_updates),
clickable(other.clickable),
+#if defined(OS_CHROMEOS)
+ pinned(other.pinned),
+#endif // defined(OS_CHROMEOS)
vibration_pattern(other.vibration_pattern),
+ renotify(other.renotify),
silent(other.silent) {}
RichNotificationData::~RichNotificationData() {}
@@ -69,7 +77,7 @@ Notification::Notification(NotificationType type,
title_(title),
message_(message),
icon_(icon),
- adjust_icon_(true),
+ draw_icon_background_(true),
display_source_(display_source),
origin_url_(origin_url),
notifier_id_(notifier_id),
@@ -85,7 +93,7 @@ Notification::Notification(const std::string& id, const Notification& other)
title_(other.title_),
message_(other.message_),
icon_(other.icon_),
- adjust_icon_(other.adjust_icon_),
+ draw_icon_background_(other.draw_icon_background_),
display_source_(other.display_source_),
origin_url_(other.origin_url_),
notifier_id_(other.notifier_id_),
@@ -101,7 +109,7 @@ Notification::Notification(const Notification& other)
title_(other.title_),
message_(other.message_),
icon_(other.icon_),
- adjust_icon_(other.adjust_icon_),
+ draw_icon_background_(other.draw_icon_background_),
display_source_(other.display_source_),
origin_url_(other.origin_url_),
notifier_id_(other.notifier_id_),
@@ -117,7 +125,7 @@ Notification& Notification::operator=(const Notification& other) {
title_ = other.title_;
message_ = other.message_;
icon_ = other.icon_;
- adjust_icon_ = other.adjust_icon_;
+ draw_icon_background_ = other.draw_icon_background_;
display_source_ = other.display_source_;
origin_url_ = other.origin_url_;
notifier_id_ = other.notifier_id_;
diff --git a/chromium/ui/message_center/notification.h b/chromium/ui/message_center/notification.h
index 491943d6e07..f06e92dd29a 100644
--- a/chromium/ui/message_center/notification.h
+++ b/chromium/ui/message_center/notification.h
@@ -53,7 +53,13 @@ class MESSAGE_CENTER_EXPORT RichNotificationData {
std::vector<ButtonInfo> buttons;
bool should_make_spoken_feedback_for_popup_updates;
bool clickable;
+#if defined(OS_CHROMEOS)
+ // Flag if the notification is pinned. If true, the notification is pinned
+ // and user can't remove it.
+ bool pinned;
+#endif // defined(OS_CHROMEOS)
std::vector<int> vibration_pattern;
+ bool renotify;
bool silent;
};
@@ -123,6 +129,13 @@ class MESSAGE_CENTER_EXPORT Notification {
optional_fields_.vibration_pattern = vibration_pattern;
}
+ // This property currently only works in platforms that support native
+ // notifications.
+ // It determines whether the sound and vibration effects should signal
+ // if the notification is replacing another notification.
+ bool renotify() const { return optional_fields_.renotify; }
+ void set_renotify(bool renotify) { optional_fields_.renotify = renotify; }
+
// This property currently has no effect on non-Android platforms.
bool silent() const { return optional_fields_.silent; }
void set_silent(bool silent) { optional_fields_.silent = silent; }
@@ -158,12 +171,10 @@ class MESSAGE_CENTER_EXPORT Notification {
const gfx::Image& icon() const { return icon_; }
void set_icon(const gfx::Image& icon) { icon_ = icon; }
- // Gets and sets whether to adjust the icon before displaying. The adjustment
- // is designed to accomodate legacy HTML icons but isn't necessary for
- // Chrome's hardcoded notifications. NB: this is currently ignored outside of
- // Views.
- bool adjust_icon() const { return adjust_icon_; }
- void set_adjust_icon(bool adjust) { adjust_icon_ = adjust; }
+ // Gets and sets whether to draw a solid background colour behind the
+ // notification's icon. Only applies to the Views implementation.
+ bool draw_icon_background() const { return draw_icon_background_; }
+ void set_draw_icon_background(bool draw) { draw_icon_background_ = draw; }
const gfx::Image& image() const { return optional_fields_.image; }
void set_image(const gfx::Image& image) { optional_fields_.image = image; }
@@ -206,6 +217,17 @@ class MESSAGE_CENTER_EXPORT Notification {
optional_fields_.clickable = clickable;
}
+ bool pinned() const {
+#if defined(OS_CHROMEOS)
+ return optional_fields_.pinned;
+#else
+ return false;
+#endif // defined(OS_CHROMEOS)
+ }
+#if defined(OS_CHROMEOS)
+ void set_pinned(bool pinned) { optional_fields_.pinned = pinned; }
+#endif // defined(OS_CHROMEOS)
+
NotificationDelegate* delegate() const { return delegate_.get(); }
const RichNotificationData& rich_notification_data() const {
@@ -246,9 +268,9 @@ class MESSAGE_CENTER_EXPORT Notification {
// Image data for the associated icon, used by Ash when available.
gfx::Image icon_;
- // True by default; controls whether to apply adjustments such as BG color and
- // size scaling to |icon_|.
- bool adjust_icon_;
+ // True by default; controls whether to draw a solid background colour behind
+ // the |icon_|. Only applies to the Views implementation.
+ bool draw_icon_background_;
// The display string for the source of the notification. Could be
// the same as origin_url_, or the name of an extension.
diff --git a/chromium/ui/message_center/notifier_settings.cc b/chromium/ui/message_center/notifier_settings.cc
index 26546118b9e..f5e9c012b5d 100644
--- a/chromium/ui/message_center/notifier_settings.cc
+++ b/chromium/ui/message_center/notifier_settings.cc
@@ -24,6 +24,8 @@ NotifierId::NotifierId()
: type(SYSTEM_COMPONENT) {
}
+NotifierId::NotifierId(const NotifierId& other) = default;
+
bool NotifierId::operator==(const NotifierId& other) const {
if (type != other.type)
return false;
@@ -63,9 +65,8 @@ Notifier::~Notifier() {
NotifierGroup::NotifierGroup(const gfx::Image& icon,
const base::string16& name,
- const base::string16& login_info,
- size_t index)
- : icon(icon), name(name), login_info(login_info), index(index) {}
+ const base::string16& login_info)
+ : icon(icon), name(name), login_info(login_info) {}
NotifierGroup::~NotifierGroup() {}
diff --git a/chromium/ui/message_center/notifier_settings.h b/chromium/ui/message_center/notifier_settings.h
index 95646afcb39..f01a069f852 100644
--- a/chromium/ui/message_center/notifier_settings.h
+++ b/chromium/ui/message_center/notifier_settings.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <string>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -53,6 +54,8 @@ struct MESSAGE_CENTER_EXPORT NotifierId {
// Constructor for WEB_PAGE type.
explicit NotifierId(const GURL& url);
+ NotifierId(const NotifierId& other);
+
bool operator==(const NotifierId& other) const;
// Allows NotifierId to be used as a key in std::map.
bool operator<(const NotifierId& other) const;
@@ -114,8 +117,7 @@ struct MESSAGE_CENTER_EXPORT Notifier {
struct MESSAGE_CENTER_EXPORT NotifierGroup {
NotifierGroup(const gfx::Image& icon,
const base::string16& name,
- const base::string16& login_info,
- size_t index);
+ const base::string16& login_info);
~NotifierGroup();
// Icon of a notifier group.
@@ -127,10 +129,6 @@ struct MESSAGE_CENTER_EXPORT NotifierGroup {
// More display information about the notifier group.
base::string16 login_info;
- // Unique identifier for the notifier group so that they can be selected in
- // the UI.
- const size_t index;
-
private:
DISALLOW_COPY_AND_ASSIGN(NotifierGroup);
};
@@ -155,7 +153,7 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsObserver {
// for the clients of this module.
class MESSAGE_CENTER_EXPORT NotifierSettingsProvider {
public:
- virtual ~NotifierSettingsProvider() {};
+ virtual ~NotifierSettingsProvider() {}
// Sets the delegate.
virtual void AddObserver(NotifierSettingsObserver* observer) = 0;
diff --git a/chromium/ui/message_center/popup_timer.cc b/chromium/ui/message_center/popup_timer.cc
index f19da62e8df..c79377df32a 100644
--- a/chromium/ui/message_center/popup_timer.cc
+++ b/chromium/ui/message_center/popup_timer.cc
@@ -4,37 +4,14 @@
#include "ui/message_center/popup_timer.h"
-#include <algorithm>
-
-#include "base/stl_util.h"
-#include "ui/message_center/message_center_style.h"
-#include "ui/message_center/message_center_types.h"
-#include "ui/message_center/notification.h"
-#include "ui/message_center/notification_list.h"
-
namespace message_center {
-namespace {
-
-base::TimeDelta GetTimeoutForNotification(Notification* notification) {
- if (notification->priority() > DEFAULT_PRIORITY)
- return base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds);
- if (notification->notifier_id().type == NotifierId::WEB_PAGE)
- return base::TimeDelta::FromSeconds(kAutocloseWebPageDelaySeconds);
- return base::TimeDelta::FromSeconds(kAutocloseDefaultDelaySeconds);
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// PopupTimer
-
PopupTimer::PopupTimer(const std::string& id,
base::TimeDelta timeout,
- base::WeakPtr<PopupTimersController> controller)
+ base::WeakPtr<Delegate> delegate)
: id_(id),
timeout_(timeout),
- timer_controller_(controller),
+ timer_delegate_(delegate),
timer_(new base::OneShotTimer) {}
PopupTimer::~PopupTimer() {
@@ -51,9 +28,11 @@ void PopupTimer::Start() {
base::TimeDelta timeout_to_close =
timeout_ <= passed_ ? base::TimeDelta() : timeout_ - passed_;
start_time_ = base::Time::Now();
- timer_->Start(FROM_HERE, timeout_to_close,
- base::Bind(&PopupTimersController::TimerFinished,
- timer_controller_, id_));
+
+ DCHECK(timer_delegate_);
+ timer_->Start(
+ FROM_HERE, timeout_to_close,
+ base::Bind(&Delegate::TimerFinished, timer_delegate_, id_));
}
void PopupTimer::Pause() {
@@ -70,107 +49,4 @@ void PopupTimer::Reset() {
passed_ = base::TimeDelta();
}
-////////////////////////////////////////////////////////////////////////////////
-// PopupTimersController
-
-PopupTimersController::PopupTimersController(MessageCenter* message_center)
- : message_center_(message_center) {
- message_center_->AddObserver(this);
-}
-
-PopupTimersController::~PopupTimersController() {
- message_center_->RemoveObserver(this);
-}
-
-void PopupTimersController::StartTimer(const std::string& id,
- const base::TimeDelta& timeout) {
- PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
- if (iter != popup_timers_.end()) {
- DCHECK(iter->second);
- iter->second->Start();
- return;
- }
-
- scoped_ptr<PopupTimer> timer(new PopupTimer(id, timeout, AsWeakPtr()));
-
- timer->Start();
- popup_timers_.insert(std::make_pair(id, std::move(timer)));
-}
-
-void PopupTimersController::StartAll() {
- for (const auto& iter : popup_timers_)
- iter.second->Start();
-}
-
-void PopupTimersController::ResetTimer(const std::string& id,
- const base::TimeDelta& timeout) {
- CancelTimer(id);
- StartTimer(id, timeout);
-}
-
-void PopupTimersController::PauseTimer(const std::string& id) {
- PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
- if (iter == popup_timers_.end())
- return;
- iter->second->Pause();
-}
-
-void PopupTimersController::PauseAll() {
- for (const auto& iter : popup_timers_)
- iter.second->Pause();
-}
-
-void PopupTimersController::CancelTimer(const std::string& id) {
- popup_timers_.erase(id);
-}
-
-void PopupTimersController::CancelAll() {
- popup_timers_.clear();
-}
-
-void PopupTimersController::TimerFinished(const std::string& id) {
- if (!ContainsKey(popup_timers_, id))
- return;
-
- CancelTimer(id);
- message_center_->MarkSinglePopupAsShown(id, false);
-}
-
-void PopupTimersController::OnNotificationDisplayed(
- const std::string& id,
- const DisplaySource source) {
- OnNotificationUpdated(id);
-}
-
-void PopupTimersController::OnNotificationUpdated(const std::string& id) {
- NotificationList::PopupNotifications popup_notifications =
- message_center_->GetPopupNotifications();
-
- if (!popup_notifications.size()) {
- CancelAll();
- return;
- }
-
- NotificationList::PopupNotifications::const_iterator iter =
- popup_notifications.begin();
- for (; iter != popup_notifications.end(); ++iter) {
- if ((*iter)->id() == id)
- break;
- }
-
- if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
- CancelTimer(id);
- return;
- }
-
- // Start the timer if not yet.
- if (popup_timers_.find(id) == popup_timers_.end())
- StartTimer(id, GetTimeoutForNotification(*iter));
-}
-
-void PopupTimersController::OnNotificationRemoved(const std::string& id,
- bool by_user) {
- CancelTimer(id);
-}
-
} // namespace message_center
diff --git a/chromium/ui/message_center/popup_timer.h b/chromium/ui/message_center/popup_timer.h
index 7ffca1b14f0..8fa39eb3ff3 100644
--- a/chromium/ui/message_center/popup_timer.h
+++ b/chromium/ui/message_center/popup_timer.h
@@ -5,38 +5,36 @@
#ifndef UI_MESSAGE_CENTER_POPUP_TIMER_H_
#define UI_MESSAGE_CENTER_POPUP_TIMER_H_
-#include <map>
#include <string>
-#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_observer.h"
-#include "ui/message_center/message_center_types.h"
-#include "ui/message_center/notification_blocker.h"
-#include "ui/message_center/notifier_settings.h"
namespace message_center {
-class PopupTimersController;
// A class that manages timeout behavior for notification popups. One instance
// is created per notification popup.
class PopupTimer {
public:
+ // Host the callback for each timer when its time is up.
+ class Delegate {
+ public:
+ virtual void TimerFinished(const std::string& id) = 0;
+ };
+
// Accepts a notification ID, time until callback, and a reference to the
- // controller which will be called back. The reference is a weak pointer so
+ // delegate which will be called back. The reference is a weak pointer so
// that timers never cause a callback on a destructed object.
PopupTimer(const std::string& id,
base::TimeDelta timeout,
- base::WeakPtr<PopupTimersController> controller);
+ base::WeakPtr<Delegate> delegate);
~PopupTimer();
// Starts running the timer. Barring a Pause or Reset call, the timer will
- // call back to |controller| after |timeout| seconds.
+ // call back to |delegate| after |timeout| seconds.
void Start();
// Stops the timer, and retains the amount of time that has passed so that on
@@ -63,7 +61,7 @@ class PopupTimer {
base::Time start_time_;
// Callback recipient.
- base::WeakPtr<PopupTimersController> timer_controller_;
+ base::WeakPtr<Delegate> timer_delegate_;
// The actual timer.
scoped_ptr<base::OneShotTimer> timer_;
@@ -71,60 +69,6 @@ class PopupTimer {
DISALLOW_COPY_AND_ASSIGN(PopupTimer);
};
-// A class that manages all the timers running for individual notification popup
-// windows. It supports weak pointers in order to allow safe callbacks when
-// timers expire.
-class MESSAGE_CENTER_EXPORT PopupTimersController
- : public base::SupportsWeakPtr<PopupTimersController>,
- public MessageCenterObserver {
- public:
- explicit PopupTimersController(MessageCenter* message_center);
- ~PopupTimersController() override;
-
- // MessageCenterObserver implementation.
- void OnNotificationDisplayed(const std::string& id,
- const DisplaySource source) override;
- void OnNotificationUpdated(const std::string& id) override;
- void OnNotificationRemoved(const std::string& id, bool by_user) override;
-
- // Callback for each timer when its time is up.
- virtual void TimerFinished(const std::string& id);
-
- // Pauses all running timers.
- void PauseAll();
-
- // Continues all managed timers.
- void StartAll();
-
- // Removes all managed timers.
- void CancelAll();
-
- // Starts a timer (by creating a PopupTimer) for |id|.
- void StartTimer(const std::string& id,
- const base::TimeDelta& timeout_in_seconds);
-
- // Stops a single timer, reverts it to a new timeout, and restarts it.
- void ResetTimer(const std::string& id,
- const base::TimeDelta& timeout_in_seconds);
-
- // Pauses a single timer, such that it will continue where it left off after a
- // call to StartAll or StartTimer.
- void PauseTimer(const std::string& id);
-
- // Removes and cancels a single popup timer, if it exists.
- void CancelTimer(const std::string& id);
-
- private:
- // Weak, global.
- MessageCenter* message_center_;
-
- // The PopupTimerCollection contains all the managed timers by their ID.
- using PopupTimerCollection = std::map<std::string, scoped_ptr<PopupTimer>>;
- PopupTimerCollection popup_timers_;
-
- DISALLOW_COPY_AND_ASSIGN(PopupTimersController);
-};
-
} // namespace message_center
#endif // UI_MESSAGE_CENTER_POPUP_TIMER_H_
diff --git a/chromium/ui/message_center/popup_timers_controller.cc b/chromium/ui/message_center/popup_timers_controller.cc
new file mode 100644
index 00000000000..14c9065940a
--- /dev/null
+++ b/chromium/ui/message_center/popup_timers_controller.cc
@@ -0,0 +1,126 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/message_center/popup_timers_controller.h"
+
+#include <algorithm>
+
+#include "base/stl_util.h"
+#include "ui/message_center/message_center_style.h"
+
+namespace message_center {
+
+namespace {
+
+base::TimeDelta GetTimeoutForNotification(Notification* notification) {
+ if (notification->priority() > DEFAULT_PRIORITY)
+ return base::TimeDelta::FromSeconds(kAutocloseHighPriorityDelaySeconds);
+ if (notification->notifier_id().type == NotifierId::WEB_PAGE)
+ return base::TimeDelta::FromSeconds(kAutocloseWebPageDelaySeconds);
+ return base::TimeDelta::FromSeconds(kAutocloseDefaultDelaySeconds);
+}
+
+} // namespace
+
+PopupTimersController::PopupTimersController(MessageCenter* message_center)
+ : message_center_(message_center) {
+ message_center_->AddObserver(this);
+}
+
+PopupTimersController::~PopupTimersController() {
+ message_center_->RemoveObserver(this);
+}
+
+void PopupTimersController::StartTimer(const std::string& id,
+ const base::TimeDelta& timeout) {
+ PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
+ if (iter != popup_timers_.end()) {
+ DCHECK(iter->second);
+ iter->second->Start();
+ return;
+ }
+
+ scoped_ptr<PopupTimer> timer(new PopupTimer(id, timeout, AsWeakPtr()));
+
+ timer->Start();
+ popup_timers_.insert(std::make_pair(id, std::move(timer)));
+}
+
+void PopupTimersController::StartAll() {
+ for (const auto& iter : popup_timers_)
+ iter.second->Start();
+}
+
+void PopupTimersController::ResetTimer(const std::string& id,
+ const base::TimeDelta& timeout) {
+ CancelTimer(id);
+ StartTimer(id, timeout);
+}
+
+void PopupTimersController::PauseTimer(const std::string& id) {
+ PopupTimerCollection::const_iterator iter = popup_timers_.find(id);
+ if (iter == popup_timers_.end())
+ return;
+ iter->second->Pause();
+}
+
+void PopupTimersController::PauseAll() {
+ for (const auto& iter : popup_timers_)
+ iter.second->Pause();
+}
+
+void PopupTimersController::CancelTimer(const std::string& id) {
+ popup_timers_.erase(id);
+}
+
+void PopupTimersController::CancelAll() {
+ popup_timers_.clear();
+}
+
+void PopupTimersController::TimerFinished(const std::string& id) {
+ if (!ContainsKey(popup_timers_, id))
+ return;
+
+ CancelTimer(id);
+ message_center_->MarkSinglePopupAsShown(id, false);
+}
+
+void PopupTimersController::OnNotificationDisplayed(
+ const std::string& id,
+ const DisplaySource source) {
+ OnNotificationUpdated(id);
+}
+
+void PopupTimersController::OnNotificationUpdated(const std::string& id) {
+ NotificationList::PopupNotifications popup_notifications =
+ message_center_->GetPopupNotifications();
+
+ if (!popup_notifications.size()) {
+ CancelAll();
+ return;
+ }
+
+ NotificationList::PopupNotifications::const_iterator iter =
+ popup_notifications.begin();
+ for (; iter != popup_notifications.end(); ++iter) {
+ if ((*iter)->id() == id)
+ break;
+ }
+
+ if (iter == popup_notifications.end() || (*iter)->never_timeout()) {
+ CancelTimer(id);
+ return;
+ }
+
+ // Start the timer if not yet.
+ if (popup_timers_.find(id) == popup_timers_.end())
+ StartTimer(id, GetTimeoutForNotification(*iter));
+}
+
+void PopupTimersController::OnNotificationRemoved(const std::string& id,
+ bool by_user) {
+ CancelTimer(id);
+}
+
+} // namespace message_center
diff --git a/chromium/ui/message_center/popup_timers_controller.h b/chromium/ui/message_center/popup_timers_controller.h
new file mode 100644
index 00000000000..d2e2db729cb
--- /dev/null
+++ b/chromium/ui/message_center/popup_timers_controller.h
@@ -0,0 +1,80 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_MESSAGE_CENTER_POPUP_TIMERS_CONTROLLER_H_
+#define UI_MESSAGE_CENTER_POPUP_TIMERS_CONTROLLER_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_observer.h"
+#include "ui/message_center/popup_timer.h"
+
+namespace message_center {
+
+// A class that manages all the timers running for individual notification popup
+// windows. It supports weak pointers in order to allow safe callbacks when
+// timers expire.
+// We can use SupportsWeakPtr<> because PopupTimer does not
+// access this class in its destructor so it is safe to invalidate weak pointers
+// after we destroy |popup_timers_|
+class MESSAGE_CENTER_EXPORT PopupTimersController
+ : public base::SupportsWeakPtr<PopupTimersController>,
+ public MessageCenterObserver,
+ public PopupTimer::Delegate {
+ public:
+ explicit PopupTimersController(MessageCenter* message_center);
+ ~PopupTimersController() override;
+
+ // MessageCenterObserver implementation.
+ void OnNotificationDisplayed(const std::string& id,
+ const DisplaySource source) override;
+ void OnNotificationUpdated(const std::string& id) override;
+ void OnNotificationRemoved(const std::string& id, bool by_user) override;
+
+ // PopupTimer::Delegate implementation
+ void TimerFinished(const std::string& id) override;
+
+ // Pauses all running timers.
+ void PauseAll();
+
+ // Continues all managed timers.
+ void StartAll();
+
+ // Removes all managed timers.
+ void CancelAll();
+
+ // Starts a timer (by creating a PopupTimer) for |id|.
+ void StartTimer(const std::string& id,
+ const base::TimeDelta& timeout_in_seconds);
+
+ // Stops a single timer, reverts it to a new timeout, and restarts it.
+ void ResetTimer(const std::string& id,
+ const base::TimeDelta& timeout_in_seconds);
+
+ // Pauses a single timer, such that it will continue where it left off after a
+ // call to StartAll or StartTimer.
+ void PauseTimer(const std::string& id);
+
+ // Removes and cancels a single popup timer, if it exists.
+ void CancelTimer(const std::string& id);
+
+ private:
+ // Weak, global.
+ MessageCenter* message_center_;
+
+ // The PopupTimerCollection contains all the managed timers by their ID.
+ using PopupTimerCollection = std::map<std::string, scoped_ptr<PopupTimer>>;
+ PopupTimerCollection popup_timers_;
+
+ DISALLOW_COPY_AND_ASSIGN(PopupTimersController);
+};
+
+} // namespace message_center
+
+#endif // UI_MESSAGE_CENTER_POPUP_TIMERS_CONTROLLER_H_
diff --git a/chromium/ui/message_center/views/constants.h b/chromium/ui/message_center/views/constants.h
index 2600d9182b0..9942ed8a1e1 100644
--- a/chromium/ui/message_center/views/constants.h
+++ b/chromium/ui/message_center/views/constants.h
@@ -20,8 +20,6 @@ const SkColor kRegularTextBackgroundColor = SK_ColorWHITE;
const SkColor kDimTextBackgroundColor = SK_ColorWHITE;
const SkColor kContextTextBackgroundColor = SK_ColorWHITE;
-const int kIconSize = message_center::kNotificationIconSize;
-const int kLegacyIconSize = 40;
const int kTextBottomPadding = 12;
const int kItemTitleToMessagePadding = 3;
const int kButtonVecticalPadding = 0;
diff --git a/chromium/ui/message_center/views/message_center_button_bar.cc b/chromium/ui/message_center/views/message_center_button_bar.cc
index 6a11fd56222..fbd5859d9ba 100644
--- a/chromium/ui/message_center/views/message_center_button_bar.cc
+++ b/chromium/ui/message_center/views/message_center_button_bar.cc
@@ -267,6 +267,10 @@ void MessageCenterButtonBar::SetCloseAllButtonEnabled(bool enabled) {
close_all_button_->SetEnabled(enabled);
}
+views::Button* MessageCenterButtonBar::GetCloseAllButtonForTest() const {
+ return close_all_button_;
+}
+
void MessageCenterButtonBar::SetBackArrowVisible(bool visible) {
if (title_arrow_)
title_arrow_->SetVisible(visible);
@@ -281,7 +285,7 @@ void MessageCenterButtonBar::ChildVisibilityChanged(views::View* child) {
void MessageCenterButtonBar::ButtonPressed(views::Button* sender,
const ui::Event& event) {
if (sender == close_all_button_) {
- message_center_view()->ClearAllNotifications();
+ message_center_view()->ClearAllClosableNotifications();
} else if (sender == settings_button_ || sender == title_arrow_) {
MessageCenterView* center_view = message_center_view();
center_view->SetSettingsVisible(!center_view->settings_visible());
diff --git a/chromium/ui/message_center/views/message_center_button_bar.h b/chromium/ui/message_center/views/message_center_button_bar.h
index 74c7b846405..e7932abd1b5 100644
--- a/chromium/ui/message_center/views/message_center_button_bar.h
+++ b/chromium/ui/message_center/views/message_center_button_bar.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "build/build_config.h"
+#include "ui/message_center/message_center_export.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/view.h"
@@ -43,6 +44,8 @@ class MessageCenterButtonBar : public views::View,
// Sometimes we shouldn't see the close-all button.
void SetCloseAllButtonEnabled(bool enabled);
+ MESSAGE_CENTER_EXPORT views::Button* GetCloseAllButtonForTest() const;
+
// Sometimes we shouldn't see the back arrow (not in settings).
void SetBackArrowVisible(bool visible);
diff --git a/chromium/ui/message_center/views/message_center_view.cc b/chromium/ui/message_center/views/message_center_view.cc
index dc6d527d59e..c8664ed7a65 100644
--- a/chromium/ui/message_center/views/message_center_view.cc
+++ b/chromium/ui/message_center/views/message_center_view.cc
@@ -148,7 +148,7 @@ MessageCenterView::MessageCenterView(MessageCenter* message_center,
views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
scroller_->SetPaintToLayer(true);
- scroller_->SetFillsBoundsOpaquely(false);
+ scroller_->layer()->SetFillsBoundsOpaquely(false);
scroller_->layer()->SetMasksToBounds(true);
empty_list_view_.reset(new NoNotificationMessageView);
@@ -255,20 +255,25 @@ void MessageCenterView::SetSettingsVisible(bool visible) {
button_bar_->SetBackArrowVisible(visible);
}
-void MessageCenterView::ClearAllNotifications() {
+void MessageCenterView::ClearAllClosableNotifications() {
if (is_closing_)
return;
SetViewHierarchyEnabled(scroller_, false);
button_bar_->SetAllButtonsEnabled(false);
- message_list_view_->ClearAllNotifications(scroller_->GetVisibleRect());
+ message_list_view_->ClearAllClosableNotifications(
+ scroller_->GetVisibleRect());
}
void MessageCenterView::OnAllNotificationsCleared() {
SetViewHierarchyEnabled(scroller_, true);
button_bar_->SetAllButtonsEnabled(true);
button_bar_->SetCloseAllButtonEnabled(false);
- message_center_->RemoveAllVisibleNotifications(true); // Action by user.
+
+ // Action by user.
+ message_center_->RemoveAllNotifications(
+ true /* by_user */,
+ message_center::MessageCenter::RemoveType::NON_PINNED);
}
size_t MessageCenterView::NumMessageViewsForTest() const {
@@ -588,7 +593,14 @@ void MessageCenterView::NotificationsChanged() {
scroller_->contents()->AddChildView(
no_message_views ? empty_list_view_.get() : message_list_view_.get());
- button_bar_->SetCloseAllButtonEnabled(!no_message_views);
+ bool no_closable_views = true;
+ for (const auto& view : notification_views_) {
+ if (!view.second->IsPinned()) {
+ no_closable_views = false;
+ break;
+ }
+ }
+ button_bar_->SetCloseAllButtonEnabled(!no_closable_views);
scroller_->SetFocusable(!no_message_views);
if (focus_manager && focused_view)
diff --git a/chromium/ui/message_center/views/message_center_view.h b/chromium/ui/message_center/views/message_center_view.h
index af91c4ad402..69d890da77c 100644
--- a/chromium/ui/message_center/views/message_center_view.h
+++ b/chromium/ui/message_center/views/message_center_view.h
@@ -50,7 +50,7 @@ class MESSAGE_CENTER_EXPORT MessageCenterView : public views::View,
void SetNotifications(const NotificationList::Notifications& notifications);
- void ClearAllNotifications();
+ void ClearAllClosableNotifications();
void OnAllNotificationsCleared();
size_t NumMessageViewsForTest() const;
diff --git a/chromium/ui/message_center/views/message_center_view_unittest.cc b/chromium/ui/message_center/views/message_center_view_unittest.cc
index d412cb04416..1d592a3312c 100644
--- a/chromium/ui/message_center/views/message_center_view_unittest.cc
+++ b/chromium/ui/message_center/views/message_center_view_unittest.cc
@@ -17,9 +17,11 @@
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/notification_types.h"
+#include "ui/message_center/views/message_center_button_bar.h"
#include "ui/message_center/views/message_center_controller.h"
#include "ui/message_center/views/message_list_view.h"
#include "ui/message_center/views/notification_view.h"
+#include "ui/views/controls/slide_out_view.h"
namespace message_center {
@@ -34,6 +36,12 @@ enum CallType {
LAYOUT
};
+class DummyEvent : public ui::Event {
+ public:
+ DummyEvent() : Event(ui::ET_UNKNOWN, base::TimeDelta(), 0) {}
+ ~DummyEvent() override {}
+};
+
/* Instrumented/Mock NotificationView subclass ********************************/
class MockNotificationView : public NotificationView {
@@ -94,6 +102,11 @@ class FakeMessageCenterImpl : public FakeMessageCenter {
void SetVisibleNotifications(NotificationList::Notifications notifications) {
visible_notifications_ = notifications;
}
+ void RemoveAllNotifications(bool by_user, RemoveType type) override {
+ if (type == RemoveType::NON_PINNED)
+ remove_all_closable_notification_called_ = true;
+ }
+ bool remove_all_closable_notification_called_ = false;
NotificationList::Notifications visible_notifications_;
};
@@ -111,6 +124,7 @@ class MessageCenterViewTest : public testing::Test,
MessageCenterView* GetMessageCenterView();
MessageListView* GetMessageListView();
+ FakeMessageCenterImpl* GetMessageCenter() const;
NotificationView* GetNotificationView(const std::string& id);
views::BoundsAnimator* GetAnimator();
int GetNotificationCount();
@@ -139,6 +153,8 @@ class MessageCenterViewTest : public testing::Test,
void LogBounds(int depth, views::View* view);
+ MessageCenterButtonBar* GetButtonBar() const;
+
private:
views::View* MakeParent(views::View* child1, views::View* child2);
@@ -146,7 +162,7 @@ class MessageCenterViewTest : public testing::Test,
NotificationList::Notifications notifications_;
scoped_ptr<MessageCenterView> message_center_view_;
- FakeMessageCenterImpl message_center_;
+ scoped_ptr<FakeMessageCenterImpl> message_center_;
std::map<CallType,int> callCounts_;
DISALLOW_COPY_AND_ASSIGN(MessageCenterViewTest);
@@ -159,6 +175,8 @@ MessageCenterViewTest::~MessageCenterViewTest() {
}
void MessageCenterViewTest::SetUp() {
+ message_center_.reset(new FakeMessageCenterImpl());
+
// Create a dummy notification.
Notification* notification1 = new Notification(
NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
@@ -177,12 +195,12 @@ void MessageCenterViewTest::SetUp() {
// ...and a list for it.
notifications_.insert(notification1);
notifications_.insert(notification2);
- message_center_.SetVisibleNotifications(notifications_);
+ message_center_->SetVisibleNotifications(notifications_);
// Then create a new MessageCenterView with that single notification.
base::string16 title;
message_center_view_.reset(new MessageCenterView(
- &message_center_, NULL, 100, false, /*top_down =*/false, title));
+ message_center_.get(), NULL, 100, false, /*top_down =*/false, title));
GetMessageListView()->quit_message_loop_after_animation_for_test_ = true;
GetMessageCenterView()->SetBounds(0, 0, 380, 600);
message_center_view_->SetNotifications(notifications_);
@@ -205,6 +223,10 @@ MessageListView* MessageCenterViewTest::GetMessageListView() {
return message_center_view_->message_list_view_.get();
}
+FakeMessageCenterImpl* MessageCenterViewTest::GetMessageCenter() const {
+ return message_center_.get();
+}
+
NotificationView* MessageCenterViewTest::GetNotificationView(
const std::string& id) {
return message_center_view_->notification_views_[id];
@@ -236,7 +258,7 @@ void MessageCenterViewTest::AddNotification(
scoped_ptr<Notification> notification) {
std::string notification_id = notification->id();
notifications_.insert(notification.release());
- message_center_.SetVisibleNotifications(notifications_);
+ message_center_->SetVisibleNotifications(notifications_);
message_center_view_->OnNotificationAdded(notification_id);
}
@@ -253,7 +275,7 @@ void MessageCenterViewTest::UpdateNotification(
// |notifications| is a "set" container so we don't need to be aware the
// order.
notifications_.insert(notification.release());
- message_center_.SetVisibleNotifications(notifications_);
+ message_center_->SetVisibleNotifications(notifications_);
message_center_view_->OnNotificationUpdated(notification_id);
}
@@ -267,7 +289,7 @@ void MessageCenterViewTest::RemoveNotification(
break;
}
}
- message_center_.SetVisibleNotifications(notifications_);
+ message_center_->SetVisibleNotifications(notifications_);
message_center_view_->OnNotificationRemoved(notification_id, by_user);
}
@@ -322,6 +344,10 @@ void MessageCenterViewTest::LogBounds(int depth, views::View* view) {
LogBounds(depth + 1, view->child_at(i));
}
+MessageCenterButtonBar* MessageCenterViewTest::GetButtonBar() const {
+ return message_center_view_->button_bar_;
+}
+
/* Unit tests *****************************************************************/
TEST_F(MessageCenterViewTest, CallTest) {
@@ -488,4 +514,89 @@ TEST_F(MessageCenterViewTest, PositionAfterRemove) {
GetMessageListView()->height());
}
+TEST_F(MessageCenterViewTest, CloseButton) {
+ views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
+ EXPECT_NE(nullptr, close_button);
+
+ ((views::ButtonListener*)GetButtonBar())
+ ->ButtonPressed(close_button, DummyEvent());
+ base::MessageLoop::current()->Run();
+ EXPECT_TRUE(GetMessageCenter()->remove_all_closable_notification_called_);
+}
+
+TEST_F(MessageCenterViewTest, CloseButtonEnablity) {
+ views::Button* close_button = GetButtonBar()->GetCloseAllButtonForTest();
+ EXPECT_NE(nullptr, close_button);
+
+ // There should be 2 non-pinned notifications.
+ EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_TRUE(close_button->enabled());
+
+ RemoveNotification(kNotificationId1, false);
+ base::MessageLoop::current()->Run();
+
+ // There should be 1 non-pinned notification.
+ EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_TRUE(close_button->enabled());
+
+ RemoveNotification(kNotificationId2, false);
+ base::MessageLoop::current()->Run();
+
+ // There should be no notification.
+ EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_FALSE(close_button->enabled());
+
+ Notification normal_notification(
+ NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId1),
+ base::UTF8ToUTF16("title2"),
+ base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
+ gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+ NotifierId(NotifierId::APPLICATION, "extension_id"),
+ message_center::RichNotificationData(), NULL);
+
+#if defined(OS_CHROMEOS)
+ Notification pinned_notification(
+ NOTIFICATION_TYPE_SIMPLE, std::string(kNotificationId2),
+ base::UTF8ToUTF16("title2"),
+ base::UTF8ToUTF16("message\nwhich\nis\nvertically\nlong\n."),
+ gfx::Image(), base::UTF8ToUTF16("display source"), GURL(),
+ NotifierId(NotifierId::APPLICATION, "extension_id"),
+ message_center::RichNotificationData(), NULL);
+ pinned_notification.set_pinned(true);
+
+ AddNotification(
+ scoped_ptr<Notification>(new Notification(normal_notification)));
+
+ // There should be 1 non-pinned notification.
+ EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_TRUE(close_button->enabled());
+
+ AddNotification(
+ scoped_ptr<Notification>(new Notification(pinned_notification)));
+
+ // There should be 1 normal notification and 1 pinned notification.
+ EXPECT_EQ(2u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_TRUE(close_button->enabled());
+
+ RemoveNotification(kNotificationId1, false);
+
+ // There should be 1 pinned notification.
+ EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_FALSE(close_button->enabled());
+
+ RemoveNotification(kNotificationId2, false);
+
+ // There should be no notification.
+ EXPECT_EQ(0u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_FALSE(close_button->enabled());
+
+ AddNotification(
+ scoped_ptr<Notification>(new Notification(pinned_notification)));
+
+ // There should be 1 pinned notification.
+ EXPECT_EQ(1u, GetMessageCenter()->GetVisibleNotifications().size());
+ EXPECT_FALSE(close_button->enabled());
+#endif // defined(OS_CHROMEOS)
+}
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/message_list_view.cc b/chromium/ui/message_center/views/message_list_view.cc
index 95933305a0e..70879983b38 100644
--- a/chromium/ui/message_center/views/message_list_view.cc
+++ b/chromium/ui/message_center/views/message_list_view.cc
@@ -191,17 +191,24 @@ void MessageListView::ResetRepositionSession() {
fixed_height_ = 0;
}
-void MessageListView::ClearAllNotifications(
+void MessageListView::ClearAllClosableNotifications(
const gfx::Rect& visible_scroll_rect) {
for (int i = 0; i < child_count(); ++i) {
- views::View* child = child_at(i);
+ // Safe cast since all views in MessageListView are MessageViews.
+ MessageView* child = (MessageView*)child_at(i);
if (!child->visible())
continue;
if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty())
continue;
+ if (child->IsPinned())
+ continue;
clearing_all_views_.push_back(child);
}
- DoUpdateIfPossible();
+ if (clearing_all_views_.empty()) {
+ message_center_view()->OnAllNotificationsCleared();
+ } else {
+ DoUpdateIfPossible();
+ }
}
void MessageListView::OnBoundsAnimatorProgressed(
diff --git a/chromium/ui/message_center/views/message_list_view.h b/chromium/ui/message_center/views/message_list_view.h
index 2909f204f15..1007af3a000 100644
--- a/chromium/ui/message_center/views/message_list_view.h
+++ b/chromium/ui/message_center/views/message_list_view.h
@@ -46,7 +46,7 @@ class MessageListView : public views::View,
void UpdateNotification(MessageView* view, const Notification& notification);
void SetRepositionTarget(const gfx::Rect& target_rect);
void ResetRepositionSession();
- void ClearAllNotifications(const gfx::Rect& visible_scroll_rect);
+ void ClearAllClosableNotifications(const gfx::Rect& visible_scroll_rect);
MESSAGE_CENTER_EXPORT void SetRepositionTargetForTest(
const gfx::Rect& target_rect);
diff --git a/chromium/ui/message_center/views/message_popup_collection.cc b/chromium/ui/message_center/views/message_popup_collection.cc
index 1a28ffe591e..e4280aa7871 100644
--- a/chromium/ui/message_center/views/message_popup_collection.cc
+++ b/chromium/ui/message_center/views/message_popup_collection.cc
@@ -83,7 +83,25 @@ void MessagePopupCollection::ClickOnNotification(
void MessagePopupCollection::RemoveNotification(
const std::string& notification_id,
bool by_user) {
- message_center_->RemoveNotification(notification_id, by_user);
+ NotificationList::PopupNotifications notifications =
+ message_center_->GetPopupNotifications();
+ for (NotificationList::PopupNotifications::iterator iter =
+ notifications.begin();
+ iter != notifications.end(); ++iter) {
+ Notification* notification = *iter;
+ DCHECK(notification);
+
+ if (notification->id() != notification_id)
+ continue;
+
+ // Don't remove the notification only when it's not pinned.
+ if (!notification->pinned())
+ message_center_->RemoveNotification(notification_id, by_user);
+ else
+ message_center_->MarkSinglePopupAsShown(notification_id, true /* read */);
+
+ break;
+ }
}
scoped_ptr<ui::MenuModel> MessagePopupCollection::CreateMenuModel(
@@ -139,10 +157,21 @@ void MessagePopupCollection::UpdateWidgets() {
if (FindToast((*iter)->id()))
continue;
- NotificationView* view =
- NotificationView::Create(NULL,
- *(*iter),
- true); // Create top-level notification.
+ NotificationView* view;
+ // Create top-level notification.
+#if defined(OS_CHROMEOS)
+ if ((*iter)->pinned()) {
+ Notification notification = *(*iter);
+ // Override pinned status, since toasts should be closable even when it's
+ // pinned.
+ notification.set_pinned(false);
+ view = NotificationView::Create(NULL, notification, true);
+ } else
+#endif // defined(OS_CHROMEOS)
+ {
+ view = NotificationView::Create(NULL, *(*iter), true);
+ }
+
view->set_context_menu_controller(context_menu_controller_.get());
int view_height = ToastContentsView::GetToastSizeForView(view).height();
int height_available =
diff --git a/chromium/ui/message_center/views/message_popup_collection_unittest.cc b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
index e38bb4b05a5..a41ae016cc2 100644
--- a/chromium/ui/message_center/views/message_popup_collection_unittest.cc
+++ b/chromium/ui/message_center/views/message_popup_collection_unittest.cc
@@ -118,7 +118,8 @@ class MessagePopupCollectionTest : public views::ViewsTestBase {
void CloseAllToasts() {
// Assumes there is at least one toast to close.
EXPECT_TRUE(GetToastCounts() > 0);
- MessageCenter::Get()->RemoveAllNotifications(false);
+ MessageCenter::Get()->RemoveAllNotifications(
+ false /* by_user */, MessageCenter::RemoveType::ALL);
}
gfx::Rect GetToastRectAt(size_t index) {
@@ -480,6 +481,44 @@ TEST_F(MessagePopupCollectionTest, ManyPopupNotifications) {
WaitForTransitionsDone();
}
+#if defined(OS_CHROMEOS)
+
+TEST_F(MessagePopupCollectionTest, CloseNonClosableNotifications) {
+ const char* kNotificationId = "NOTIFICATION1";
+
+ scoped_ptr<Notification> notification(new Notification(
+ NOTIFICATION_TYPE_BASE_FORMAT, kNotificationId,
+ base::UTF8ToUTF16("test title"), base::UTF8ToUTF16("test message"),
+ gfx::Image(), base::string16() /* display_source */, GURL(),
+ NotifierId(NotifierId::APPLICATION, kNotificationId),
+ message_center::RichNotificationData(), new NotificationDelegate()));
+ notification->set_pinned(true);
+
+ // Add a pinned notification.
+ MessageCenter::Get()->AddNotification(std::move(notification));
+ WaitForTransitionsDone();
+
+ // Confirms that there is a toast.
+ EXPECT_EQ(1u, GetToastCounts());
+ EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
+
+ // Close the toast.
+ views::WidgetDelegateView* toast1 = GetToast(kNotificationId);
+ ASSERT_TRUE(toast1 != NULL);
+ ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), 0, 0);
+ toast1->OnMouseEntered(event);
+ static_cast<MessageCenterObserver*>(collection())
+ ->OnNotificationRemoved(kNotificationId, true);
+ WaitForTransitionsDone();
+
+ // Confirms that there is no toast.
+ EXPECT_EQ(0u, GetToastCounts());
+ // But the notification still exists.
+ EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
+}
+
+#endif // defined(OS_CHROMEOS)
} // namespace test
} // namespace message_center
diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc
index 6f2597fb54c..80473515fad 100644
--- a/chromium/ui/message_center/views/message_view.cc
+++ b/chromium/ui/message_center/views/message_view.cc
@@ -26,9 +26,6 @@
namespace {
-const int kCloseIconTopPadding = 5;
-const int kCloseIconRightPadding = 5;
-
const int kShadowOffset = 1;
const int kShadowBlur = 4;
@@ -63,19 +60,6 @@ MessageView::MessageView(MessageViewController* controller,
small_image_view->set_owned_by_client();
small_image_view_.reset(small_image_view);
- PaddedButton *close = new PaddedButton(this);
- close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
- close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
- close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
- close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
- close->set_animate_on_state_change(false);
- close->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
- // The close button should be added to view hierarchy by the derived class.
- // This ensures that it is on top of other views.
- close->set_owned_by_client();
- close_button_.reset(close);
-
focus_painter_ = views::Painter::CreateSolidFocusPainter(
kFocusBorderColor, gfx::Insets(0, 1, 3, 2));
}
@@ -103,12 +87,16 @@ void MessageView::CreateShadowBorder() {
}
bool MessageView::IsCloseButtonFocused() {
- views::FocusManager* focus_manager = GetFocusManager();
- return focus_manager && focus_manager->GetFocusedView() == close_button();
+ // May be overridden by the owner of the close button.
+ return false;
}
void MessageView::RequestFocusOnCloseButton() {
- close_button_->RequestFocus();
+ // May be overridden by the owner of the close button.
+}
+
+bool MessageView::IsPinned() {
+ return false;
}
void MessageView::GetAccessibleState(ui::AXViewState* state) {
@@ -151,7 +139,6 @@ bool MessageView::OnKeyReleased(const ui::KeyEvent& event) {
}
void MessageView::OnPaint(gfx::Canvas* canvas) {
- DCHECK_EQ(this, close_button_->parent());
DCHECK_EQ(this, small_image_view_->parent());
SlideOutView::OnPaint(canvas);
views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
@@ -175,14 +162,6 @@ void MessageView::Layout() {
// Background.
background_view_->SetBoundsRect(content_bounds);
- // Close button.
- gfx::Size close_size(close_button_->GetPreferredSize());
- gfx::Rect close_rect(content_bounds.right() - close_size.width(),
- content_bounds.y(),
- close_size.width(),
- close_size.height());
- close_button_->SetBoundsRect(close_rect);
-
gfx::Size small_image_size(small_image_view_->GetPreferredSize());
gfx::Rect small_image_rect(small_image_size);
small_image_rect.set_origin(gfx::Point(
@@ -229,9 +208,6 @@ void MessageView::OnGestureEvent(ui::GestureEvent* event) {
void MessageView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
- if (sender == close_button()) {
- controller_->RemoveNotification(notification_id_, true); // By user.
- }
}
void MessageView::OnSlideOut() {
diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h
index 47840df6b8f..6a4754e179c 100644
--- a/chromium/ui/message_center/views/message_view.h
+++ b/chromium/ui/message_center/views/message_view.h
@@ -46,8 +46,8 @@ const int kPaddingHorizontal = 18;
const int kWebNotificationButtonWidth = 32;
const int kWebNotificationIconSize = 40;
-// An base class for a notification entry. Contains background, close button
-// and other elements shared by derived notification views.
+// An base class for a notification entry. Contains background and other
+// elements shared by derived notification views.
class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
public views::ButtonListener {
public:
@@ -67,8 +67,9 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
// Creates a shadow around the notification.
void CreateShadowBorder();
- bool IsCloseButtonFocused();
- void RequestFocusOnCloseButton();
+ virtual bool IsCloseButtonFocused();
+ virtual void RequestFocusOnCloseButton();
+ virtual bool IsPinned();
void set_accessible_name(const base::string16& accessible_name) {
accessible_name_ = accessible_name;
@@ -100,7 +101,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
void OnSlideOut() override;
views::ImageView* small_image() { return small_image_view_.get(); }
- views::ImageButton* close_button() { return close_button_.get(); }
views::ScrollView* scroller() { return scroller_; }
private:
@@ -108,7 +108,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::SlideOutView,
std::string notification_id_;
NotifierId notifier_id_;
views::View* background_view_; // Owned by views hierarchy.
- scoped_ptr<views::ImageButton> close_button_;
scoped_ptr<views::ImageView> small_image_view_;
views::ScrollView* scroller_;
diff --git a/chromium/ui/message_center/views/notification_view.cc b/chromium/ui/message_center/views/notification_view.cc
index fe91d1b0946..32aedfb2400 100644
--- a/chromium/ui/message_center/views/notification_view.cc
+++ b/chromium/ui/message_center/views/notification_view.cc
@@ -59,6 +59,9 @@ namespace {
// Dimensions.
const int kProgressBarBottomPadding = 0;
+const int kCloseIconTopPadding = 5;
+const int kCloseIconRightPadding = 5;
+
// static
scoped_ptr<views::Border> MakeEmptyBorder(int top,
int left,
@@ -91,32 +94,6 @@ scoped_ptr<views::Border> MakeSeparatorBorder(int top,
return views::Border::CreateSolidSidedBorder(top, left, 0, 0, color);
}
-// static
-// Return true if and only if the image is null or has alpha.
-bool HasAlpha(gfx::ImageSkia& image, views::Widget* widget) {
- // Determine which bitmap to use.
- float factor = 1.0f;
- if (widget)
- factor = ui::GetScaleFactorForNativeView(widget->GetNativeView());
-
- // Extract that bitmap's alpha and look for a non-opaque pixel there.
- SkBitmap bitmap = image.GetRepresentation(factor).sk_bitmap();
- if (!bitmap.isNull()) {
- SkBitmap alpha;
- bitmap.extractAlpha(&alpha);
- for (int y = 0; y < bitmap.height(); ++y) {
- for (int x = 0; x < bitmap.width(); ++x) {
- if (alpha.getColor(x, y) != SK_ColorBLACK) {
- return true;
- }
- }
- }
- }
-
- // If no opaque pixel was found, return false unless the bitmap is empty.
- return bitmap.isNull();
-}
-
// ItemView ////////////////////////////////////////////////////////////////////
// ItemViews are responsible for drawing each list notification item's title and
@@ -228,7 +205,8 @@ views::View* NotificationView::TargetForRect(views::View* root,
action_buttons_.end());
if (settings_button_view_)
buttons.push_back(settings_button_view_);
- buttons.push_back(close_button());
+ if (close_button_)
+ buttons.push_back(close_button_.get());
for (size_t i = 0; i < buttons.size(); ++i) {
gfx::Point point_in_child = point;
@@ -241,6 +219,7 @@ views::View* NotificationView::TargetForRect(views::View* root,
}
void NotificationView::CreateOrUpdateViews(const Notification& notification) {
+ CreateOrUpdateCloseButtonView(notification);
CreateOrUpdateTitleView(notification);
CreateOrUpdateMessageView(notification);
CreateOrUpdateProgressBarView(notification);
@@ -308,7 +287,6 @@ NotificationView::NotificationView(MessageCenterController* controller,
// image to overlap the content as needed to provide large enough click and
// touch areas (<http://crbug.com/168822> and <http://crbug.com/168856>).
AddChildView(small_image());
- AddChildView(close_button());
SetAccessibleName(notification);
SetEventTargeter(
@@ -349,13 +327,16 @@ int NotificationView::GetHeightForWidth(int width) const {
}
}
- int content_height = std::max(top_height, kIconSize) + bottom_height;
+ int content_height =
+ std::max(top_height, kNotificationIconSize) + bottom_height;
// Adjust the height to make sure there is at least 16px of space below the
// icon if there is any space there (<http://crbug.com/232966>).
- if (content_height > kIconSize)
- content_height = std::max(content_height,
- kIconSize + message_center::kIconBottomPadding);
+ if (content_height > kNotificationIconSize) {
+ content_height =
+ std::max(content_height,
+ kNotificationIconSize + message_center::kIconBottomPadding);
+ }
return content_height + GetInsets().height();
}
@@ -378,11 +359,22 @@ void NotificationView::Layout() {
int top_height = top_view_->GetHeightForWidth(content_width);
top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height);
+ // Close button.
+ if (close_button_) {
+ gfx::Rect content_bounds = GetContentsBounds();
+ gfx::Size close_size(close_button_->GetPreferredSize());
+ gfx::Rect close_rect(content_bounds.right() - close_size.width(),
+ content_bounds.y(), close_size.width(),
+ close_size.height());
+ close_button_->SetBoundsRect(close_rect);
+ }
+
// Icon.
- icon_view_->SetBounds(insets.left(), insets.top(), kIconSize, kIconSize);
+ icon_view_->SetBounds(insets.left(), insets.top(), kNotificationIconSize,
+ kNotificationIconSize);
// Settings & Bottom views.
- int bottom_y = insets.top() + std::max(top_height, kIconSize);
+ int bottom_y = insets.top() + std::max(top_height, kNotificationIconSize);
int bottom_height = bottom_view_->GetHeightForWidth(content_width);
if (settings_button_view_) {
@@ -445,6 +437,10 @@ void NotificationView::ButtonPressed(views::Button* sender,
}
}
+ if (close_button_ && sender == close_button_.get()) {
+ controller_->RemoveNotification(notification_id(), true); // By user.
+ }
+
// Let the superclass handle everything else.
// Warning: This may cause the NotificationView itself to be deleted,
// so don't do anything afterwards.
@@ -533,12 +529,10 @@ base::string16 NotificationView::FormatContextMessage(
if (notification.UseOriginAsContextMessage()) {
const GURL url = notification.origin_url();
DCHECK(url.is_valid());
- // TODO(palmer): Find a way to get the Profile's real languages.
- // crbug.com/496965.
- return gfx::ElideText(url_formatter::FormatUrlForSecurityDisplayOmitScheme(
- url, std::string()),
- views::Label().font_list(), kContextMessageViewWidth,
- gfx::ELIDE_HEAD);
+ return gfx::ElideText(
+ url_formatter::FormatUrlForSecurityDisplayOmitScheme(url),
+ views::Label().font_list(), kContextMessageViewWidth,
+ gfx::ELIDE_HEAD);
}
return gfx::TruncateString(notification.context_message(),
@@ -663,24 +657,20 @@ void NotificationView::CreateOrUpdateListItemViews(
void NotificationView::CreateOrUpdateIconView(
const Notification& notification) {
+ gfx::Size image_view_size(kNotificationIconSize, kNotificationIconSize);
+
if (!icon_view_) {
- icon_view_ = new ProportionalImageView(gfx::Size(kIconSize, kIconSize));
+ icon_view_ = new ProportionalImageView(image_view_size);
AddChildView(icon_view_);
}
gfx::ImageSkia icon = notification.icon().AsImageSkia();
- if (notification.adjust_icon()) {
+ icon_view_->SetImage(icon, icon.size());
+
+ if (notification.draw_icon_background()) {
icon_view_->set_background(
views::Background::CreateSolidBackground(kIconBackgroundColor));
- gfx::Size max_image_size =
- notification.type() == NOTIFICATION_TYPE_SIMPLE &&
- (icon.width() < kIconSize || icon.height() < kIconSize ||
- HasAlpha(icon, GetWidget()))
- ? gfx::Size(kLegacyIconSize, kLegacyIconSize)
- : gfx::Size(kIconSize, kIconSize);
- icon_view_->SetImage(icon, max_image_size);
} else {
- icon_view_->SetImage(icon, icon.size());
icon_view_->set_background(nullptr);
}
}
@@ -772,6 +762,29 @@ void NotificationView::CreateOrUpdateActionButtonViews(
}
}
+void NotificationView::CreateOrUpdateCloseButtonView(
+ const Notification& notification) {
+ set_slide_out_enabled(!notification.pinned());
+
+ if (!notification.pinned() && !close_button_) {
+ PaddedButton* close = new PaddedButton(this);
+ close->SetPadding(-kCloseIconRightPadding, kCloseIconTopPadding);
+ close->SetNormalImage(IDR_NOTIFICATION_CLOSE);
+ close->SetHoveredImage(IDR_NOTIFICATION_CLOSE_HOVER);
+ close->SetPressedImage(IDR_NOTIFICATION_CLOSE_PRESSED);
+ close->set_animate_on_state_change(false);
+ close->SetAccessibleName(l10n_util::GetStringUTF16(
+ IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
+ // The close button should be added to view hierarchy by the derived class.
+ // This ensures that it is on top of other views.
+ close->set_owned_by_client();
+ close_button_.reset(close);
+ AddChildView(close_button_.get());
+ } else if (notification.pinned() && close_button_) {
+ close_button_.reset();
+ }
+}
+
int NotificationView::GetMessageLineLimit(int title_lines, int width) const {
// Image notifications require that the image must be kept flush against
// their icons, but we can allow more text if no image.
@@ -813,4 +826,22 @@ int NotificationView::GetMessageHeight(int width, int limit) const {
message_view_->GetSizeForWidthAndLines(width, limit).height() : 0;
}
+bool NotificationView::IsCloseButtonFocused() {
+ if (!close_button_)
+ return false;
+
+ views::FocusManager* focus_manager = GetFocusManager();
+ return focus_manager &&
+ focus_manager->GetFocusedView() == close_button_.get();
+}
+
+void NotificationView::RequestFocusOnCloseButton() {
+ if (close_button_)
+ close_button_->RequestFocus();
+}
+
+bool NotificationView::IsPinned() {
+ return !close_button_;
+}
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/notification_view.h b/chromium/ui/message_center/views/notification_view.h
index 491080cfbeb..fd42a85879a 100644
--- a/chromium/ui/message_center/views/notification_view.h
+++ b/chromium/ui/message_center/views/notification_view.h
@@ -62,6 +62,9 @@ class MESSAGE_CENTER_EXPORT NotificationView
// Overridden from MessageView:
void UpdateWithNotification(const Notification& notification) override;
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+ bool IsCloseButtonFocused() override;
+ void RequestFocusOnCloseButton() override;
+ bool IsPinned() override;
// Overridden from MessageViewController:
void ClickOnNotification(const std::string& notification_id) override;
@@ -105,6 +108,7 @@ class MESSAGE_CENTER_EXPORT NotificationView
void CreateOrUpdateIconView(const Notification& notification);
void CreateOrUpdateImageView(const Notification& notification);
void CreateOrUpdateActionButtonViews(const Notification& notification);
+ void CreateOrUpdateCloseButtonView(const Notification& notification);
int GetMessageLineLimit(int title_lines, int width) const;
int GetMessageHeight(int width, int limit) const;
@@ -133,6 +137,7 @@ class MESSAGE_CENTER_EXPORT NotificationView
ProportionalImageView* image_view_;
NotificationProgressBarBase* progress_bar_view_;
std::vector<NotificationButton*> action_buttons_;
+ scoped_ptr<views::ImageButton> close_button_;
std::vector<views::View*> separators_;
DISALLOW_COPY_AND_ASSIGN(NotificationView);
diff --git a/chromium/ui/message_center/views/notification_view_unittest.cc b/chromium/ui/message_center/views/notification_view_unittest.cc
index 383d1989dda..9be249c5569 100644
--- a/chromium/ui/message_center/views/notification_view_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_unittest.cc
@@ -11,6 +11,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
@@ -31,6 +32,24 @@
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget_delegate.h"
+namespace {
+
+scoped_ptr<ui::GestureEvent> GenerateGestureEvent(ui::EventType type) {
+ ui::GestureEventDetails detail(type);
+ scoped_ptr<ui::GestureEvent> event(
+ new ui::GestureEvent(0, 0, 0, base::TimeDelta(), detail));
+ return event;
+}
+
+scoped_ptr<ui::GestureEvent> GenerateGestureVerticalScrollUpdateEvent(int dx) {
+ ui::GestureEventDetails detail(ui::ET_GESTURE_SCROLL_UPDATE, dx, 0);
+ scoped_ptr<ui::GestureEvent> event(
+ new ui::GestureEvent(0, 0, 0, base::TimeDelta(), detail));
+ return event;
+}
+
+} // anonymouse namespace
+
namespace message_center {
// A test delegate used for tests that deal with the notification settings
@@ -54,7 +73,9 @@ class NotificationViewTest : public views::ViewsTestBase,
void TearDown() override;
views::Widget* widget() { return notification_view_->GetWidget(); }
- NotificationView* notification_view() { return notification_view_.get(); }
+ NotificationView* notification_view() const {
+ return notification_view_.get();
+ }
Notification* notification() { return notification_.get(); }
RichNotificationData* data() { return data_.get(); }
@@ -155,12 +176,28 @@ class NotificationViewTest : public views::ViewsTestBase,
}
}
+ views::ImageButton* GetCloseButton() {
+ return notification_view()->close_button_.get();
+ }
+
void UpdateNotificationViews() {
notification_view()->CreateOrUpdateViews(*notification());
notification_view()->Layout();
}
+ float GetNotificationScrollAmount() const {
+ return notification_view()->GetTransform().To2dTranslation().x();
+ }
+
+ bool IsRemoved(const std::string& notification_id) const {
+ return (removed_ids_.find(notification_id) != removed_ids_.end());
+ }
+
+ void RemoveNotificationView() { notification_view_.reset(); }
+
private:
+ std::set<std::string> removed_ids_;
+
scoped_ptr<RichNotificationData> data_;
scoped_ptr<Notification> notification_;
scoped_ptr<NotificationView> notification_view_;
@@ -216,8 +253,7 @@ void NotificationViewTest::ClickOnNotification(
void NotificationViewTest::RemoveNotification(
const std::string& notification_id,
bool by_user) {
- // For this test, this method should not be invoked.
- NOTREACHED();
+ removed_ids_.insert(notification_id);
}
scoped_ptr<ui::MenuModel> NotificationViewTest::CreateMenuModel(
@@ -319,42 +355,33 @@ TEST_F(NotificationViewTest, TestIconSizing) {
notification()->set_type(NOTIFICATION_TYPE_SIMPLE);
ProportionalImageView* view = notification_view()->icon_view_;
- // Icons smaller than the legacy size should be scaled up to it.
- notification()->set_icon(CreateTestImage(kLegacyIconSize / 2,
- kLegacyIconSize / 2));
+ // Icons smaller than the maximum size should remain unscaled.
+ notification()->set_icon(CreateTestImage(kNotificationIconSize / 2,
+ kNotificationIconSize / 4));
UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kLegacyIconSize, kLegacyIconSize).ToString(),
+ EXPECT_EQ(gfx::Size(kNotificationIconSize / 2,
+ kNotificationIconSize / 4).ToString(),
GetImagePaintSize(view).ToString());
- // Icons at the legacy size should be unscaled.
- notification()->set_icon(CreateTestImage(kLegacyIconSize, kLegacyIconSize));
+ // Icons of exactly the intended icon size should remain unscaled.
+ notification()->set_icon(CreateTestImage(kNotificationIconSize,
+ kNotificationIconSize));
UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kLegacyIconSize, kLegacyIconSize).ToString(),
+ EXPECT_EQ(gfx::Size(kNotificationIconSize, kNotificationIconSize).ToString(),
GetImagePaintSize(view).ToString());
- // Icons slightly smaller than the preferred size should be scaled down to the
- // legacy size to avoid having tiny borders (http://crbug.com/232966).
- notification()->set_icon(CreateTestImage(kIconSize - 1, kIconSize - 1));
+ // Icons over the maximum size should be scaled down, maintaining proportions.
+ notification()->set_icon(CreateTestImage(2 * kNotificationIconSize,
+ 2 * kNotificationIconSize));
UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kLegacyIconSize, kLegacyIconSize).ToString(),
+ EXPECT_EQ(gfx::Size(kNotificationIconSize, kNotificationIconSize).ToString(),
GetImagePaintSize(view).ToString());
- // Icons at the preferred size or above should be scaled down to the preferred
- // size.
- notification()->set_icon(CreateTestImage(kIconSize, kIconSize));
+ notification()->set_icon(CreateTestImage(4 * kNotificationIconSize,
+ 2 * kNotificationIconSize));
UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kIconSize, kIconSize).ToString(),
- GetImagePaintSize(view).ToString());
-
- notification()->set_icon(CreateTestImage(2 * kIconSize, 2 * kIconSize));
- UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kIconSize, kIconSize).ToString(),
- GetImagePaintSize(view).ToString());
-
- // Large, non-square images' aspect ratios should be preserved.
- notification()->set_icon(CreateTestImage(4 * kIconSize, 2 * kIconSize));
- UpdateNotificationViews();
- EXPECT_EQ(gfx::Size(kIconSize, kIconSize / 2).ToString(),
+ EXPECT_EQ(gfx::Size(kNotificationIconSize,
+ kNotificationIconSize / 2).ToString(),
GetImagePaintSize(view).ToString());
}
@@ -618,4 +645,64 @@ TEST_F(NotificationViewTest, FormatContextMessageTest) {
EXPECT_TRUE(base::UTF16ToUTF8(result).find("hello") == std::string::npos);
}
+TEST_F(NotificationViewTest, SlideOut) {
+ ui::ScopedAnimationDurationScaleMode zero_duration_scope(
+ ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+
+ UpdateNotificationViews();
+ std::string notification_id = notification()->id();
+
+ auto event_begin = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN);
+ auto event_scroll10 = GenerateGestureVerticalScrollUpdateEvent(-10);
+ auto event_scroll500 = GenerateGestureVerticalScrollUpdateEvent(-500);
+ auto event_end = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_END);
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll10.get());
+ EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_EQ(-10.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_EQ(0.f, GetNotificationScrollAmount());
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll500.get());
+ EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_EQ(-500.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_TRUE(IsRemoved(notification_id));
+}
+
+// Pinning notification is ChromeOS only feature.
+#if defined(OS_CHROMEOS)
+
+TEST_F(NotificationViewTest, SlideOutPinned) {
+ ui::ScopedAnimationDurationScaleMode zero_duration_scope(
+ ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+
+ notification()->set_pinned(true);
+ UpdateNotificationViews();
+ std::string notification_id = notification()->id();
+
+ auto event_begin = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_BEGIN);
+ auto event_scroll500 = GenerateGestureVerticalScrollUpdateEvent(-500);
+ auto event_end = GenerateGestureEvent(ui::ET_GESTURE_SCROLL_END);
+
+ notification_view()->OnGestureEvent(event_begin.get());
+ notification_view()->OnGestureEvent(event_scroll500.get());
+ EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_LT(-500.f, GetNotificationScrollAmount());
+ notification_view()->OnGestureEvent(event_end.get());
+ EXPECT_FALSE(IsRemoved(notification_id));
+}
+
+TEST_F(NotificationViewTest, Pinned) {
+ notification()->set_pinned(true);
+
+ UpdateNotificationViews();
+ EXPECT_EQ(NULL, GetCloseButton());
+}
+
+#endif // defined(OS_CHROMEOS)
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/notifier_settings_view.cc b/chromium/ui/message_center/views/notifier_settings_view.cc
index 145512d886a..bf80543124f 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.cc
+++ b/chromium/ui/message_center/views/notifier_settings_view.cc
@@ -578,7 +578,7 @@ void NotifierSettingsView::UpdateContentsView(
base::string16 notifier_group_text = active_group.login_info.empty() ?
active_group.name : active_group.login_info;
notifier_group_selector_ =
- new views::MenuButton(NULL, notifier_group_text, this, true);
+ new views::MenuButton(notifier_group_text, this, true);
notifier_group_selector_->SetBorder(scoped_ptr<views::Border>(
new views::LabelButtonAssetBorder(views::Button::STYLE_BUTTON)));
notifier_group_selector_->SetFocusPainter(nullptr);
@@ -687,8 +687,9 @@ void NotifierSettingsView::ButtonPressed(views::Button* sender,
provider_->SetNotifierEnabled((*iter)->notifier(), (*iter)->checked());
}
-void NotifierSettingsView::OnMenuButtonClicked(views::View* source,
- const gfx::Point& point) {
+void NotifierSettingsView::OnMenuButtonClicked(views::MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) {
notifier_group_menu_model_.reset(new NotifierGroupMenuModel(provider_));
notifier_group_menu_runner_.reset(new views::MenuRunner(
notifier_group_menu_model_.get(), views::MenuRunner::CONTEXT_MENU));
diff --git a/chromium/ui/message_center/views/notifier_settings_view.h b/chromium/ui/message_center/views/notifier_settings_view.h
index 1c635de0223..bbfa2fa7f98 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.h
+++ b/chromium/ui/message_center/views/notifier_settings_view.h
@@ -107,8 +107,9 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Overridden from views::MenuButtonListener:
- void OnMenuButtonClicked(views::View* source,
- const gfx::Point& point) override;
+ void OnMenuButtonClicked(views::MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) override;
views::ImageButton* title_arrow_;
views::Label* title_label_;
diff --git a/chromium/ui/message_center/views/toast_contents_view.cc b/chromium/ui/message_center/views/toast_contents_view.cc
index a11b3b9874c..fd2cb46a50d 100644
--- a/chromium/ui/message_center/views/toast_contents_view.cc
+++ b/chromium/ui/message_center/views/toast_contents_view.cc
@@ -250,7 +250,7 @@ void ToastContentsView::OnDisplayChanged() {
return;
collection_->OnDisplayMetricsChanged(
- Screen::GetScreenFor(native_view)->GetDisplayNearestWindow(native_view));
+ Screen::GetScreen()->GetDisplayNearestWindow(native_view));
}
void ToastContentsView::OnWorkAreaChanged() {
@@ -263,7 +263,7 @@ void ToastContentsView::OnWorkAreaChanged() {
return;
collection_->OnDisplayMetricsChanged(
- Screen::GetScreenFor(native_view)->GetDisplayNearestWindow(native_view));
+ Screen::GetScreen()->GetDisplayNearestWindow(native_view));
}
// views::View
diff --git a/chromium/ui/metro_viewer/BUILD.gn b/chromium/ui/metro_viewer/BUILD.gn
deleted file mode 100644
index 491ca7b4da8..00000000000
--- a/chromium/ui/metro_viewer/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("metro_viewer") {
- sources = [
- "ime_types.cc",
- "ime_types.h",
- "metro_viewer_message_generator.cc",
- "metro_viewer_message_generator.h",
- "metro_viewer_messages.h",
- ]
-
- deps = [
- "//base",
- "//ipc",
- "//ui/events",
- ]
-}
diff --git a/chromium/ui/metro_viewer/DEPS b/chromium/ui/metro_viewer/DEPS
deleted file mode 100644
index 8cb61f5e0a4..00000000000
--- a/chromium/ui/metro_viewer/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+ui/events",
- "+ui/gfx",
-]
diff --git a/chromium/ui/metro_viewer/OWNERS b/chromium/ui/metro_viewer/OWNERS
deleted file mode 100644
index 9b1c2450c48..00000000000
--- a/chromium/ui/metro_viewer/OWNERS
+++ /dev/null
@@ -1,12 +0,0 @@
-# Changes to IPC messages require a security review to avoid introducing
-# new sandbox escapes.
-per-file *_messages*.h=set noparent
-per-file *_messages*.h=dcheng@chromium.org
-per-file *_messages*.h=inferno@chromium.org
-per-file *_messages*.h=jln@chromium.org
-per-file *_messages*.h=jschuh@chromium.org
-per-file *_messages*.h=kenrb@chromium.org
-per-file *_messages*.h=mkwst@chromium.org
-per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=tsepez@chromium.org
-per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/ui/metro_viewer/ime_types.cc b/chromium/ui/metro_viewer/ime_types.cc
deleted file mode 100644
index 9a37152fc99..00000000000
--- a/chromium/ui/metro_viewer/ime_types.cc
+++ /dev/null
@@ -1,30 +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/metro_viewer/ime_types.h"
-
-namespace metro_viewer {
-
-UnderlineInfo::UnderlineInfo()
- : start_offset(0),
- end_offset(0),
- thick(false) {
-}
-
-Composition::Composition()
- : selection_start(0),
- selection_end(0) {
-}
-
-Composition::~Composition() {
-}
-
-CharacterBounds::CharacterBounds()
- : left(0),
- top(0),
- right(0),
- bottom(0) {
-}
-
-} // namespace metro_viewer
diff --git a/chromium/ui/metro_viewer/ime_types.h b/chromium/ui/metro_viewer/ime_types.h
deleted file mode 100644
index d37b40bae14..00000000000
--- a/chromium/ui/metro_viewer/ime_types.h
+++ /dev/null
@@ -1,50 +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_METRO_VIEWER_IME_TYPES_H_
-#define UI_METRO_VIEWER_IME_TYPES_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/strings/string16.h"
-
-namespace metro_viewer {
-
-// An equivalent to ui::CompositionUnderline defined in
-// "ui/base/ime/composition_underline.h". Redefined here to avoid dependency
-// on ui.gyp from metro_driver.gyp.
-struct UnderlineInfo {
- UnderlineInfo();
- int32_t start_offset;
- int32_t end_offset;
- bool thick;
-};
-
-// An equivalent to ui::CompositionText defined in
-// "ui/base/ime/composition_text.h". Redefined here to avoid dependency
-// on ui.gyp from metro_driver.gyp.
-struct Composition {
- Composition();
- ~Composition();
- base::string16 text;
- int32_t selection_start;
- int32_t selection_end;
- std::vector<UnderlineInfo> underlines;
-};
-
-// An equivalent to Win32 RECT structure. This can be gfx::Rect but redefined
-// here to avoid dependency on gfx.gyp from metro_driver.gyp.
-struct CharacterBounds {
- CharacterBounds();
- int32_t left;
- int32_t top;
- int32_t right;
- int32_t bottom;
-};
-
-} // namespace metro_viewer
-
-#endif // UI_METRO_VIEWER_IME_TYPES_H_
diff --git a/chromium/ui/metro_viewer/metro_viewer.gyp b/chromium/ui/metro_viewer/metro_viewer.gyp
deleted file mode 100644
index c8bafdc0a61..00000000000
--- a/chromium/ui/metro_viewer/metro_viewer.gyp
+++ /dev/null
@@ -1,29 +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.
-
-{
- 'variables': {
- 'chromium_code': 1,
- },
- 'targets': [
- {
- # GN version: //ui/metro_viewer
- 'target_name': 'metro_viewer_messages',
- 'type': 'static_library',
- 'dependencies': [
- '../../base/base.gyp:base',
- ],
- 'sources': [
- 'ime_types.cc',
- 'ime_types.h',
- 'metro_viewer_message_generator.cc',
- 'metro_viewer_message_generator.h',
- 'metro_viewer_messages.h',
- ],
- 'include_dirs': [
- '..',
- ],
- },
- ],
-}
diff --git a/chromium/ui/metro_viewer/metro_viewer_message_generator.cc b/chromium/ui/metro_viewer/metro_viewer_message_generator.cc
deleted file mode 100644
index 360321ca240..00000000000
--- a/chromium/ui/metro_viewer/metro_viewer_message_generator.cc
+++ /dev/null
@@ -1,33 +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.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-} // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-} // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "ui/metro_viewer/metro_viewer_message_generator.h"
-} // namespace IPC
diff --git a/chromium/ui/metro_viewer/metro_viewer_message_generator.h b/chromium/ui/metro_viewer/metro_viewer_message_generator.h
deleted file mode 100644
index 4ea868838db..00000000000
--- a/chromium/ui/metro_viewer/metro_viewer_message_generator.h
+++ /dev/null
@@ -1,7 +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.
-
-// Multiply-included file, hence no include guard.
-
-#include "ui/metro_viewer/metro_viewer_messages.h"
diff --git a/chromium/ui/metro_viewer/metro_viewer_messages.h b/chromium/ui/metro_viewer/metro_viewer_messages.h
deleted file mode 100644
index 8dfab4dc771..00000000000
--- a/chromium/ui/metro_viewer/metro_viewer_messages.h
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 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.
-
-// Multiply-included message file, no include guard.
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "ipc/ipc_message_macros.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/metro_viewer/ime_types.h"
-
-#define IPC_MESSAGE_START MetroViewerMsgStart
-
-IPC_ENUM_TRAITS(ui::EventType)
-IPC_ENUM_TRAITS(ui::EventFlags)
-
-// Contains the parameters sent for a mousebutton message.
-IPC_STRUCT_BEGIN(MetroViewerHostMsg_MouseButtonParams)
-
- IPC_STRUCT_MEMBER(int32_t, x)
- IPC_STRUCT_MEMBER(int32_t, y)
- IPC_STRUCT_MEMBER(int32_t, extra)
- IPC_STRUCT_MEMBER(ui::EventType, event_type)
- IPC_STRUCT_MEMBER(uint32_t, flags)
- IPC_STRUCT_MEMBER(ui::EventFlags, changed_button)
- IPC_STRUCT_MEMBER(bool, is_horizontal_wheel)
-
-IPC_STRUCT_END()
-
-// Messages sent from the viewer to the browser:
-
-// Inform the browser of the surface to target for compositing.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_SetTargetSurface,
- gfx::NativeViewId /* target hwnd */,
- float /* device scale */)
-// Informs the browser that the mouse moved.
-IPC_MESSAGE_CONTROL3(MetroViewerHostMsg_MouseMoved,
- int32_t, /* x-coordinate */
- int32_t, /* y-coordinate */
- int32_t /* flags */)
-// Informs the brower that a mouse button was pressed.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_MouseButton,
- MetroViewerHostMsg_MouseButtonParams)
-// Informs the browser that a key was pressed.
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_KeyDown,
- uint32_t, /* virtual key */
- uint32_t, /* repeat count */
- uint32_t, /* scan code */
- uint32_t /* key state */)
-// Informs the browser that a key was released.
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_KeyUp,
- uint32_t, /* virtual key */
- uint32_t, /* repeat count */
- uint32_t, /* scan code */
- uint32_t /* key state */)
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_Character,
- uint32_t, /* virtual key */
- uint32_t, /* repeat count */
- uint32_t, /* scan code */
- uint32_t /* key state */)
-// Informs the browser that the Metro window has been activated.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_WindowActivated,
- bool /* Whether the window should be repainted */)
-
-// Informs the browser that the user has completed an edge gesture.
-IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_EdgeGesture)
-
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_TouchDown,
- int32_t, /* x-coordinate */
- int32_t, /* y-coordinate */
- uint64_t, /* timestamp */
- uint32_t) /* pointer_id */
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_TouchUp,
- int32_t, /* x-coordinate */
- int32_t, /* y-coordinate */
- uint64_t, /* timestamp */
- uint32_t) /* pointer_id */
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_TouchMoved,
- int32_t, /* x-coordinate */
- int32_t, /* y-coordinate */
- uint64_t, /* timestamp */
- uint32_t) /* pointer_id */
-
-// Informs the browser of the result of a file save as operation.
-IPC_MESSAGE_CONTROL3(MetroViewerHostMsg_FileSaveAsDone,
- bool, /* success */
- base::FilePath, /* filename */
- int) /* filter_index */
-
-// Informs the browser of the result of a file open operation.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_FileOpenDone,
- bool, /* success */
- base::FilePath) /* filename */
-
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_MultiFileOpenDone,
- bool, /* success */
- std::vector<base::FilePath>) /* filenames */
-
-// Informs the browser of the result of a select folder operation.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_SelectFolderDone,
- bool, /* success */
- base::FilePath) /* filepath*/
-
-// Messages sent from the browser to the viewer:
-
-// Requests the viewer to activate desktop mode.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_ActivateDesktop,
- base::FilePath /* shortcut */,
- bool /* ash exit */)
-
-// Request the viewer to close itself gracefully.
-IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_MetroExit)
-
-// Requests the viewer to open a URL in desktop mode.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_OpenURLOnDesktop,
- base::FilePath /* shortcut */,
- base::string16 /* url */)
-
-// Requests the viewer to change the pointer to a new cursor.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_SetCursor, int64_t /* cursor */)
-
-// This structure contains the parameters sent to the viewer process to display
-// the file save dialog.
-IPC_STRUCT_BEGIN(MetroViewerHostMsg_SaveAsDialogParams)
-
- // The title of the file save dialog if any.
- IPC_STRUCT_MEMBER(base::string16, title)
-
- // The suggested file name.
- IPC_STRUCT_MEMBER(base::FilePath, suggested_name)
-
- // The save as filter to be used.
- IPC_STRUCT_MEMBER(base::string16, filter)
-
- // The filter index.
- IPC_STRUCT_MEMBER(uint32_t, filter_index)
-
- // The default extension.
- IPC_STRUCT_MEMBER(base::string16, default_extension)
-
-IPC_STRUCT_END()
-
-// Requests the viewer to display the file save dialog.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_DisplayFileSaveAs,
- MetroViewerHostMsg_SaveAsDialogParams)
-
-// Requests the viewer to display the file open dialog.
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_DisplayFileOpen,
- base::string16, /* title */
- base::string16, /* filter */
- base::FilePath, /* Default path */
- bool) /* allow_multi_select */
-
-// Requests the viewer to display the select folder dialog.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_DisplaySelectFolder,
- base::string16) /* title */
-
-// Sent to the viewer process to set the cursor position.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_SetCursorPos,
- int, /* x */
- int) /* y */
-
-// Ack sent by the viewer process indicating that the SetCursorPos operation
-// was completed.
-IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_SetCursorPosAck)
-
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_OpenURL,
- base::string16) /* url */
-
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_SearchRequest,
- base::string16) /* search_string */
-
-// Sent from the metro viewer process to the browser process to indicate that
-// the viewer window size has changed.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_WindowSizeChanged,
- uint32_t, /* width */
- uint32_t) /* height */
-
-IPC_STRUCT_TRAITS_BEGIN(metro_viewer::UnderlineInfo)
- IPC_STRUCT_TRAITS_MEMBER(start_offset)
- IPC_STRUCT_TRAITS_MEMBER(end_offset)
- IPC_STRUCT_TRAITS_MEMBER(thick)
-IPC_STRUCT_TRAITS_END()
-
-// Sent from the metro viewer process to the browser process to update the
-// composition string.
-IPC_MESSAGE_CONTROL4(MetroViewerHostMsg_ImeCompositionChanged,
- base::string16, /* text */
- int32_t, /* selection_start */
- int32_t, /* selection_end */
- std::vector<metro_viewer::UnderlineInfo>) /* underlines */
-
-// Sent from the metro viewer process to the browser process to update the
-// status of popup window that is managed by an IME.
-IPC_MESSAGE_CONTROL1(
- MetroViewerHostMsg_ImeCandidatePopupChanged,
- bool) /* UI visibility */
-
-// Sent from the metro viewer process to the browser process to commit strings.
-IPC_MESSAGE_CONTROL1(MetroViewerHostMsg_ImeTextCommitted,
- base::string16) /* text */
-
-// Sent from the metro viewer process to the browser process to notify that the
-// active text input source is changed.
-IPC_MESSAGE_CONTROL2(MetroViewerHostMsg_ImeInputSourceChanged,
- uint16_t, /* Win32 LangID */
- bool) /* is IME or not */
-
-// Requests the viewer to cancel the on-going composition.
-IPC_MESSAGE_CONTROL0(MetroViewerHostMsg_ImeCancelComposition)
-
-IPC_STRUCT_TRAITS_BEGIN(metro_viewer::CharacterBounds)
- IPC_STRUCT_TRAITS_MEMBER(left)
- IPC_STRUCT_TRAITS_MEMBER(top)
- IPC_STRUCT_TRAITS_MEMBER(right)
- IPC_STRUCT_TRAITS_MEMBER(bottom)
-IPC_STRUCT_TRAITS_END()
-
-// Requests the viewer to update the document context such as attached
-// InputScopes and character bounds.
-IPC_MESSAGE_CONTROL2(
- MetroViewerHostMsg_ImeTextInputClientUpdated,
- std::vector<int32_t>, /* InputScope enums */
- std::vector<metro_viewer::CharacterBounds>) /* character bounds */
diff --git a/chromium/ui/mojo/geometry/mojo_bindings.gyp b/chromium/ui/mojo/geometry/mojo_bindings.gyp
index e5bfe67adee..28e1c98b296 100644
--- a/chromium/ui/mojo/geometry/mojo_bindings.gyp
+++ b/chromium/ui/mojo/geometry/mojo_bindings.gyp
@@ -13,14 +13,14 @@
'geometry.mojom',
],
},
- 'includes': [ '../../../third_party/mojo/mojom_bindings_generator_explicit.gypi' ],
+ 'includes': [ '../../../mojo/mojom_bindings_generator_explicit.gypi' ],
},
{
'target_name': 'mojo_geometry_bindings',
'type': 'static_library',
'dependencies': [
'mojo_geometry_bindings_mojom',
- '../../../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../../../mojo/mojo_public.gyp:mojo_cpp_bindings',
],
},
],
diff --git a/chromium/ui/mojo/init/ui_init.cc b/chromium/ui/mojo/init/ui_init.cc
index 7be35c749b1..34b0ae349e6 100644
--- a/chromium/ui/mojo/init/ui_init.cc
+++ b/chromium/ui/mojo/init/ui_init.cc
@@ -43,7 +43,7 @@ class GestureConfigurationMojo : public ui::GestureConfiguration {
UIInit::UIInit(const std::vector<gfx::Display>& displays)
: screen_(new ScreenMojo(displays)) {
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
+ gfx::Screen::SetScreenInstance(screen_.get());
#if defined(OS_ANDROID)
gesture_configuration_.reset(new GestureConfigurationMojo);
ui::GestureConfiguration::SetInstance(gesture_configuration_.get());
@@ -51,7 +51,7 @@ UIInit::UIInit(const std::vector<gfx::Display>& displays)
}
UIInit::~UIInit() {
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, nullptr);
+ gfx::Screen::SetScreenInstance(nullptr);
#if defined(OS_ANDROID)
ui::GestureConfiguration::SetInstance(nullptr);
#endif
diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc
index d2f808065ae..ab72df6dd66 100644
--- a/chromium/ui/native_theme/common_theme.cc
+++ b/chromium/ui/native_theme/common_theme.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
@@ -29,11 +29,6 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
if (ui::MaterialDesignController::IsModeMaterial()) {
// Dialogs:
static const SkColor kDialogBackgroundColorMd = SK_ColorWHITE;
- // Button:
- static const SkColor kTextButtonEnabledColorMd =
- SkColorSetRGB(0x64, 0x64, 0x64);
- static const SkColor kTextButtonDisabledColorMd =
- SkColorSetA(kTextButtonEnabledColorMd, 0x80);
// MenuItem:
static const SkColor kMenuHighlightBackgroundColorMd =
SkColorSetARGB(0x14, 0x00, 0x00, 0x00);
@@ -54,12 +49,6 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_BubbleBackground:
return kDialogBackgroundColorMd;
- // Button
- case NativeTheme::kColorId_MdTextButtonEnabledColor:
- return kTextButtonEnabledColorMd;
- case NativeTheme::kColorId_MdTextButtonDisabledColor:
- return kTextButtonDisabledColorMd;
-
// MenuItem
case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
return kMenuHighlightBackgroundColorMd;
@@ -132,6 +121,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
static const SkColor kBlueButtonHoverColor = SK_ColorWHITE;
static const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA);
static const SkColor kCallToActionColor = gfx::kGoogleBlue500;
+ static const SkColor kTextOnCallToActionColor = SK_ColorWHITE;
// MenuItem:
static const SkColor kMenuBackgroundColor = SK_ColorWHITE;
static const SkColor kMenuHighlightBackgroundColor =
@@ -263,6 +253,8 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
return kBlueButtonShadowColor;
case NativeTheme::kColorId_CallToActionColor:
return kCallToActionColor;
+ case NativeTheme::kColorId_TextOnCallToActionColor:
+ return kTextOnCallToActionColor;
// MenuItem
case NativeTheme::kColorId_MenuBorderColor:
@@ -405,8 +397,6 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_ThrobberLightColor:
return kThrobberLightColor;
- case NativeTheme::kColorId_MdTextButtonEnabledColor:
- case NativeTheme::kColorId_MdTextButtonDisabledColor:
case NativeTheme::kColorId_NumColors:
break;
}
@@ -415,32 +405,12 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
return gfx::kPlaceholderColor;
}
-gfx::Size CommonThemeGetPartSize(NativeTheme::Part part,
- NativeTheme::State state,
- const NativeTheme::ExtraParams& extra) {
- gfx::Size size;
- switch (part) {
- case NativeTheme::kComboboxArrow:
- return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- IDR_MENU_DROPARROW).Size();
-
- default:
- break;
- }
-
- return size;
-}
-
-void CommonThemePaintComboboxArrow(SkCanvas* canvas, const gfx::Rect& rect) {
- gfx::ImageSkia* arrow = ui::ResourceBundle::GetSharedInstance().
- GetImageSkiaNamed(IDR_MENU_DROPARROW);
- CommonThemeCreateCanvas(canvas)->DrawImageInt(*arrow, rect.x(), rect.y());
-}
-
-void CommonThemePaintMenuItemBackground(const NativeTheme *theme,
- SkCanvas* canvas,
- NativeTheme::State state,
- const gfx::Rect &rect) {
+void CommonThemePaintMenuItemBackground(
+ const NativeTheme* theme,
+ SkCanvas* canvas,
+ NativeTheme::State state,
+ const gfx::Rect& rect,
+ const NativeTheme::MenuItemExtraParams& menu_item) {
SkPaint paint;
switch (state) {
case NativeTheme::kNormal:
@@ -456,6 +426,11 @@ void CommonThemePaintMenuItemBackground(const NativeTheme *theme,
NOTREACHED() << "Invalid state " << state;
break;
}
+ if (menu_item.corner_radius > 0) {
+ const SkScalar radius = SkIntToScalar(menu_item.corner_radius);
+ canvas->drawRoundRect(gfx::RectToSkRect(rect), radius, radius, paint);
+ return;
+ }
canvas->drawRect(gfx::RectToSkRect(rect), paint);
}
@@ -465,7 +440,8 @@ scoped_ptr<gfx::Canvas> CommonThemeCreateCanvas(SkCanvas* sk_canvas) {
// scale factor from canvas scale.
SkMatrix m = sk_canvas->getTotalMatrix();
float device_scale = static_cast<float>(SkScalarAbs(m.getScaleX()));
- return make_scoped_ptr(new gfx::Canvas(sk_canvas, device_scale));
+ return make_scoped_ptr(new gfx::Canvas(skia::SharePtr(sk_canvas),
+ device_scale));
}
} // namespace ui
diff --git a/chromium/ui/native_theme/common_theme.h b/chromium/ui/native_theme/common_theme.h
index 87c5eca78af..48edf85561f 100644
--- a/chromium/ui/native_theme/common_theme.h
+++ b/chromium/ui/native_theme/common_theme.h
@@ -24,20 +24,12 @@ namespace ui {
SkColor NATIVE_THEME_EXPORT GetAuraColor(NativeTheme::ColorId color_id,
const NativeTheme* base_theme);
-gfx::Size NATIVE_THEME_EXPORT CommonThemeGetPartSize(
- NativeTheme::Part part,
- NativeTheme::State state,
- const NativeTheme::ExtraParams& extra);
-
-void NATIVE_THEME_EXPORT CommonThemePaintComboboxArrow(
- SkCanvas* canvas,
- const gfx::Rect& rect);
-
void NATIVE_THEME_EXPORT CommonThemePaintMenuItemBackground(
const NativeTheme* theme,
SkCanvas* canvas,
NativeTheme::State state,
- const gfx::Rect& rect);
+ const gfx::Rect& rect,
+ const NativeTheme::MenuItemExtraParams& menu_item);
// Creates a gfx::Canvas wrapping an SkCanvas.
scoped_ptr<gfx::Canvas> NATIVE_THEME_EXPORT CommonThemeCreateCanvas(
diff --git a/chromium/ui/native_theme/native_theme.cc b/chromium/ui/native_theme/native_theme.cc
index f15f144b8c0..e4911c97d01 100644
--- a/chromium/ui/native_theme/native_theme.cc
+++ b/chromium/ui/native_theme/native_theme.cc
@@ -4,10 +4,20 @@
#include "ui/native_theme/native_theme.h"
+#include <cstring>
+
#include "ui/native_theme/native_theme_observer.h"
namespace ui {
+NativeTheme::ExtraParams::ExtraParams() {
+ memset(this, 0, sizeof(*this));
+}
+
+NativeTheme::ExtraParams::ExtraParams(const ExtraParams& other) {
+ memcpy(this, &other, sizeof(*this));
+}
+
void NativeTheme::SetScrollbarColors(unsigned inactive_color,
unsigned active_color,
unsigned track_color) {
diff --git a/chromium/ui/native_theme/native_theme.h b/chromium/ui/native_theme/native_theme.h
index b09dd15b1c1..917ed956c28 100644
--- a/chromium/ui/native_theme/native_theme.h
+++ b/chromium/ui/native_theme/native_theme.h
@@ -44,7 +44,6 @@ class NATIVE_THEME_EXPORT NativeTheme {
public:
// The part to be painted / sized.
enum Part {
- kComboboxArrow,
kCheckbox,
kInnerSpinButton,
kMenuList,
@@ -132,6 +131,7 @@ class NATIVE_THEME_EXPORT NativeTheme {
struct MenuItemExtraParams {
bool is_selected;
+ int corner_radius;
};
struct MenuListExtraParams {
@@ -196,7 +196,10 @@ class NATIVE_THEME_EXPORT NativeTheme {
int classic_state; // Used on Windows when uxtheme is not available.
};
- union ExtraParams {
+ union NATIVE_THEME_EXPORT ExtraParams {
+ ExtraParams();
+ ExtraParams(const ExtraParams& other);
+
ButtonExtraParams button;
InnerSpinButtonExtraParams inner_spin;
MenuArrowExtraParams menu_arrow;
@@ -262,8 +265,7 @@ class NATIVE_THEME_EXPORT NativeTheme {
kColorId_BlueButtonHoverColor,
kColorId_BlueButtonShadowColor,
kColorId_CallToActionColor,
- kColorId_MdTextButtonEnabledColor,
- kColorId_MdTextButtonDisabledColor,
+ kColorId_TextOnCallToActionColor,
// MenuItem
kColorId_EnabledMenuItemForegroundColor,
kColorId_DisabledMenuItemForegroundColor,
diff --git a/chromium/ui/native_theme/native_theme_aura.cc b/chromium/ui/native_theme/native_theme_aura.cc
index ffb4347a83c..74edcd558c8 100644
--- a/chromium/ui/native_theme/native_theme_aura.cc
+++ b/chromium/ui/native_theme/native_theme_aura.cc
@@ -10,7 +10,7 @@
#include "base/logging.h"
#include "build/build_config.h"
#include "ui/base/layout.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
@@ -130,8 +130,8 @@ void NativeThemeAura::PaintMenuItemBackground(
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const {
- CommonThemePaintMenuItemBackground(this, canvas, state, rect);
+ const MenuItemExtraParams& menu_item) const {
+ CommonThemePaintMenuItemBackground(this, canvas, state, rect, menu_item);
}
void NativeThemeAura::PaintArrowButton(SkCanvas* canvas,
diff --git a/chromium/ui/native_theme/native_theme_aura.h b/chromium/ui/native_theme/native_theme_aura.h
index d9503f6ab2e..85ce5bc708d 100644
--- a/chromium/ui/native_theme/native_theme_aura.h
+++ b/chromium/ui/native_theme/native_theme_aura.h
@@ -29,7 +29,7 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const override;
+ const MenuItemExtraParams& menu_item) const override;
void PaintArrowButton(SkCanvas* gc,
const gfx::Rect& rect,
Part direction,
diff --git a/chromium/ui/native_theme/native_theme_aurawin.cc b/chromium/ui/native_theme/native_theme_aurawin.cc
index 956186b535c..03e53c65fdb 100644
--- a/chromium/ui/native_theme/native_theme_aurawin.cc
+++ b/chromium/ui/native_theme/native_theme_aurawin.cc
@@ -72,10 +72,6 @@ void NativeThemeAuraWin::Paint(SkCanvas* canvas,
gfx::Size NativeThemeAuraWin::GetPartSize(Part part,
State state,
const ExtraParams& extra) const {
- gfx::Size part_size = CommonThemeGetPartSize(part, state, extra);
- if (!part_size.IsEmpty())
- return part_size;
-
// We want aura on windows to use the same size for scrollbars as we would in
// the native theme.
if (IsScrollbarPart(part))
diff --git a/chromium/ui/native_theme/native_theme_base.cc b/chromium/ui/native_theme/native_theme_base.cc
index 1a7837ef3eb..d0f135ac750 100644
--- a/chromium/ui/native_theme/native_theme_base.cc
+++ b/chromium/ui/native_theme/native_theme_base.cc
@@ -97,10 +97,6 @@ namespace ui {
gfx::Size NativeThemeBase::GetPartSize(Part part,
State state,
const ExtraParams& extra) const {
- gfx::Size size = CommonThemeGetPartSize(part, state, extra);
- if (!size.IsEmpty())
- return size;
-
switch (part) {
// Please keep these in the order of NativeTheme::Part.
case kCheckbox:
@@ -197,9 +193,6 @@ void NativeThemeBase::Paint(SkCanvas* canvas,
switch (part) {
// Please keep these in the order of NativeTheme::Part.
- case kComboboxArrow:
- CommonThemePaintComboboxArrow(canvas, rect);
- break;
case kCheckbox:
PaintCheckbox(canvas, state, rect, extra.button);
break;
@@ -213,7 +206,7 @@ void NativeThemeBase::Paint(SkCanvas* canvas,
PaintMenuPopupBackground(canvas, rect.size(), extra.menu_background);
break;
case kMenuItemBackground:
- PaintMenuItemBackground(canvas, state, rect, extra.menu_list);
+ PaintMenuItemBackground(canvas, state, rect, extra.menu_item);
break;
case kProgressBar:
PaintProgressBar(canvas, state, rect, extra.progress_bar);
@@ -616,12 +609,10 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon(
else /* kNormal */
startEndColors = kCheckboxGradientColors;
SkColor colors[3] = {startEndColors[0], startEndColors[0], startEndColors[1]};
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkGradientShader::CreateLinear(
- gradient_bounds, colors, NULL, 3, SkShader::kClamp_TileMode));
SkPaint paint;
paint.setAntiAlias(true);
- paint.setShader(shader.get());
+ paint.setShader(SkGradientShader::MakeLinear(gradient_bounds, colors, NULL, 3,
+ SkShader::kClamp_TileMode));
paint.setStyle(SkPaint::kFill_Style);
canvas->drawRoundRect(skrect, borderRadius, borderRadius, paint);
paint.setShader(NULL);
@@ -700,12 +691,11 @@ void NativeThemeBase::PaintButton(SkCanvas* canvas,
std::swap(gradient_bounds[0], gradient_bounds[1]);
SkColor colors[2] = { light_color, base_color };
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkGradientShader::CreateLinear(
- gradient_bounds, colors, NULL, 2, SkShader::kClamp_TileMode));
paint.setStyle(SkPaint::kFill_Style);
paint.setAntiAlias(true);
- paint.setShader(shader.get());
+ paint.setShader(
+ SkGradientShader::MakeLinear(
+ gradient_bounds, colors, NULL, 2, SkShader::kClamp_TileMode));
canvas->drawRoundRect(skrect, SkIntToScalar(1), SkIntToScalar(1), paint);
paint.setShader(NULL);
@@ -792,7 +782,7 @@ void NativeThemeBase::PaintMenuItemBackground(
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const {
+ const MenuItemExtraParams& menu_item) const {
// By default don't draw anything over the normal background.
}
diff --git a/chromium/ui/native_theme/native_theme_base.h b/chromium/ui/native_theme/native_theme_base.h
index 5b91753426c..a8677d3bf30 100644
--- a/chromium/ui/native_theme/native_theme_base.h
+++ b/chromium/ui/native_theme/native_theme_base.h
@@ -108,7 +108,7 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const;
+ const MenuItemExtraParams& menu_item) const;
virtual void PaintSliderTrack(
SkCanvas* canvas,
diff --git a/chromium/ui/native_theme/native_theme_dark_aura.cc b/chromium/ui/native_theme/native_theme_dark_aura.cc
index 33392455691..b00d32ff7c9 100644
--- a/chromium/ui/native_theme/native_theme_dark_aura.cc
+++ b/chromium/ui/native_theme/native_theme_dark_aura.cc
@@ -4,7 +4,7 @@
#include "ui/native_theme/native_theme_dark_aura.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/color_palette.h"
namespace ui {
@@ -67,6 +67,8 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
return kResultsTableDimmedText;
// Intentional pass-throughs to NativeThemeAura.
+ case kColorId_ButtonEnabledColor:
+ case kColorId_TextOnCallToActionColor:
case kColorId_ResultsTableHoveredBackground:
case kColorId_ResultsTableSelectedBackground:
case kColorId_ResultsTableNormalUrl:
@@ -75,9 +77,70 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
return NativeThemeAura::GetSystemColor(color_id);
// Any other color is not defined and shouldn't be used in a dark theme.
- default:
+ case kColorId_WindowBackground:
+ case kColorId_DialogBackground:
+ case kColorId_BubbleBackground:
+ case kColorId_FocusedBorderColor:
+ case kColorId_UnfocusedBorderColor:
+ case kColorId_ButtonBackgroundColor:
+ case kColorId_ButtonDisabledColor:
+ case kColorId_ButtonHighlightColor:
+ case kColorId_ButtonHoverColor:
+ case kColorId_ButtonHoverBackgroundColor:
+ case kColorId_BlueButtonEnabledColor:
+ case kColorId_BlueButtonDisabledColor:
+ case kColorId_BlueButtonPressedColor:
+ case kColorId_BlueButtonHoverColor:
+ case kColorId_BlueButtonShadowColor:
+ case kColorId_EnabledMenuItemForegroundColor:
+ case kColorId_DisabledMenuItemForegroundColor:
+ case kColorId_DisabledEmphasizedMenuItemForegroundColor:
+ case kColorId_SelectedMenuItemForegroundColor:
+ case kColorId_FocusedMenuItemBackgroundColor:
+ case kColorId_HoverMenuItemBackgroundColor:
+ case kColorId_MenuSeparatorColor:
+ case kColorId_MenuBackgroundColor:
+ case kColorId_MenuBorderColor:
+ case kColorId_EnabledMenuButtonBorderColor:
+ case kColorId_FocusedMenuButtonBorderColor:
+ case kColorId_HoverMenuButtonBorderColor:
+ case kColorId_LabelEnabledColor:
+ case kColorId_LabelDisabledColor:
+ case kColorId_LabelBackgroundColor:
+ case kColorId_LinkDisabled:
+ case kColorId_TextfieldReadOnlyColor:
+ case kColorId_TextfieldReadOnlyBackground:
+ case kColorId_TooltipBackground:
+ case kColorId_TooltipText:
+ case kColorId_TreeBackground:
+ case kColorId_TreeText:
+ case kColorId_TreeSelectedText:
+ case kColorId_TreeSelectedTextUnfocused:
+ case kColorId_TreeSelectionBackgroundFocused:
+ case kColorId_TreeSelectionBackgroundUnfocused:
+ case kColorId_TreeArrow:
+ case kColorId_TableBackground:
+ case kColorId_TableText:
+ case kColorId_TableSelectedText:
+ case kColorId_TableSelectedTextUnfocused:
+ case kColorId_TableSelectionBackgroundFocused:
+ case kColorId_TableSelectionBackgroundUnfocused:
+ case kColorId_TableGroupingIndicatorColor:
+ case kColorId_ResultsTablePositiveText:
+ case kColorId_ResultsTablePositiveHoveredText:
+ case kColorId_ResultsTablePositiveSelectedText:
+ case kColorId_ResultsTableNegativeText:
+ case kColorId_ResultsTableNegativeHoveredText:
+ case kColorId_ResultsTableNegativeSelectedText:
+ case kColorId_ThrobberSpinningColor:
+ case kColorId_ThrobberWaitingColor:
+ case kColorId_ThrobberLightColor:
+ case kColorId_NumColors:
return gfx::kPlaceholderColor;
}
+
+ NOTREACHED();
+ return gfx::kPlaceholderColor;
}
NativeThemeDarkAura::NativeThemeDarkAura() {}
diff --git a/chromium/ui/native_theme/native_theme_dark_win.cc b/chromium/ui/native_theme/native_theme_dark_win.cc
index d2511434926..c79f51eb741 100644
--- a/chromium/ui/native_theme/native_theme_dark_win.cc
+++ b/chromium/ui/native_theme/native_theme_dark_win.cc
@@ -4,7 +4,7 @@
#include "ui/native_theme/native_theme_dark_win.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/native_theme/native_theme_dark_aura.h"
namespace ui {
diff --git a/chromium/ui/native_theme/native_theme_mac.h b/chromium/ui/native_theme/native_theme_mac.h
index 7970a586f2b..43071749bb7 100644
--- a/chromium/ui/native_theme/native_theme_mac.h
+++ b/chromium/ui/native_theme/native_theme_mac.h
@@ -14,24 +14,14 @@ namespace ui {
// Mac implementation of native theme support.
class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
public:
+ static const int kComboboxCornerRadius = 5;
+
static NativeThemeMac* instance();
// Overridden from NativeTheme:
SkColor GetSystemColor(ColorId color_id) const override;
// Overridden from NativeThemeBase:
- void PaintScrollbarTrack(SkCanvas* canvas,
- Part part,
- State state,
- const ScrollbarTrackExtraParams& extra_params,
- const gfx::Rect& rect) const override;
- void PaintScrollbarThumb(SkCanvas* sk_canvas,
- Part part,
- State state,
- const gfx::Rect& rect) const override;
- void PaintScrollbarCorner(SkCanvas* canvas,
- State state,
- const gfx::Rect& rect) const override;
void PaintMenuPopupBackground(
SkCanvas* canvas,
const gfx::Size& size,
@@ -40,7 +30,10 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const override;
+ const MenuItemExtraParams& menu_item) const override;
+
+ // Creates a shader appropriate for painting the background of a button.
+ static sk_sp<SkShader> GetButtonBackgroundShader(State state, int height);
private:
NativeThemeMac();
diff --git a/chromium/ui/native_theme/native_theme_mac.mm b/chromium/ui/native_theme/native_theme_mac.mm
index 43eb1296316..88343f74db2 100644
--- a/chromium/ui/native_theme/native_theme_mac.mm
+++ b/chromium/ui/native_theme/native_theme_mac.mm
@@ -13,38 +13,26 @@
#include "base/macros.h"
#import "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/skia_util.h"
#include "ui/native_theme/common_theme.h"
namespace {
-const SkColor kScrollerTrackGradientColors[] = {
- SkColorSetRGB(0xEF, 0xEF, 0xEF),
- SkColorSetRGB(0xF9, 0xF9, 0xF9),
- SkColorSetRGB(0xFD, 0xFD, 0xFD),
- SkColorSetRGB(0xF6, 0xF6, 0xF6) };
-const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
-const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
-const SkColor kScrollerThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
-const SkColor kScrollerThumbHoverColor = SkColorSetARGB(0x80, 0, 0, 0);
-const int kScrollerTrackBorderWidth = 1;
-
-// The amount the thumb is inset from both the ends and the sides of the track.
-const int kScrollerThumbInset = 3;
-
// Values calculated by reading pixels and solving simultaneous equations
// derived from "A over B" alpha compositing. Steps: Sample the semi-transparent
// pixel over two backgrounds; P1, P2 over backgrounds B1, B2. Use the color
// value between 0.0 and 1.0 (i.e. divide by 255.0). Then,
// alpha = (P2 - P1 + B1 - B2) / (B1 - B2)
// color = (P1 - B1 + alpha * B1) / alpha.
-const SkColor kMenuPopupBackgroundColor = SkColorSetARGB(255, 255, 255, 255);
-const SkColor kMenuSeparatorColor = SkColorSetARGB(243, 228, 228, 228);
+const SkColor kMenuPopupBackgroundColor = SkColorSetARGB(245, 255, 255, 255);
+const SkColor kMenuSeparatorColor = SkColorSetARGB(255, 217, 217, 217);
const SkColor kMenuBorderColor = SkColorSetARGB(60, 0, 0, 0);
-const SkColor kMenuPopupBackgroundColorYosemite =
- SkColorSetARGB(255, 230, 230, 230);
+const SkColor kMenuPopupBackgroundColorMavericks =
+ SkColorSetARGB(255, 255, 255, 255);
+const SkColor kMenuSeparatorColorMavericks = SkColorSetARGB(243, 228, 228, 228);
// Hardcoded color used for some existing dialogs in Chrome's Cocoa UI.
const SkColor kDialogBackgroundColor = SkColorSetRGB(251, 251, 251);
@@ -185,7 +173,8 @@ SkColor NativeThemeMac::GetSystemColor(ColorId color_id) const {
case kColorId_MenuBackgroundColor:
return kMenuPopupBackgroundColor;
case kColorId_MenuSeparatorColor:
- return kMenuSeparatorColor;
+ return base::mac::IsOSMavericks() ? kMenuSeparatorColorMavericks
+ : kMenuSeparatorColor;
case kColorId_MenuBorderColor:
return kMenuBorderColor;
@@ -240,139 +229,14 @@ SkColor NativeThemeMac::GetSystemColor(ColorId color_id) const {
}
}
-void NativeThemeMac::PaintScrollbarTrack(
- SkCanvas* canvas,
- Part part,
- State state,
- const ScrollbarTrackExtraParams& extra_params,
- const gfx::Rect& rect) const {
- // Emulate the non-overlay scroller style from OSX 10.7 and later.
- SkPoint gradient_bounds[2];
- if (part == kScrollbarVerticalTrack) {
- gradient_bounds[0].set(rect.x(), rect.y());
- gradient_bounds[1].set(rect.right(), rect.y());
- } else {
- DCHECK_EQ(part, kScrollbarHorizontalTrack);
- gradient_bounds[0].set(rect.x(), rect.y());
- gradient_bounds[1].set(rect.x(), rect.bottom());
- }
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkGradientShader::CreateLinear(gradient_bounds,
- kScrollerTrackGradientColors,
- NULL,
- arraysize(kScrollerTrackGradientColors),
- SkShader::kClamp_TileMode));
- SkPaint gradient;
- gradient.setShader(shader.get());
-
- SkIRect track_rect = gfx::RectToSkIRect(rect);
- canvas->drawIRect(track_rect, gradient);
-
- // Draw inner and outer line borders.
- if (part == kScrollbarVerticalTrack) {
- SkPaint paint;
- paint.setColor(kScrollerTrackInnerBorderColor);
- canvas->drawRectCoords(track_rect.left(),
- track_rect.top(),
- track_rect.left() + kScrollerTrackBorderWidth,
- track_rect.bottom(),
- paint);
- paint.setColor(kScrollerTrackOuterBorderColor);
- canvas->drawRectCoords(track_rect.right() - kScrollerTrackBorderWidth,
- track_rect.top(),
- track_rect.right(),
- track_rect.bottom(),
- paint);
- } else {
- SkPaint paint;
- paint.setColor(kScrollerTrackInnerBorderColor);
- canvas->drawRectCoords(track_rect.left(),
- track_rect.top(),
- track_rect.right(),
- track_rect.top() + kScrollerTrackBorderWidth,
- paint);
- paint.setColor(kScrollerTrackOuterBorderColor);
- canvas->drawRectCoords(track_rect.left(),
- track_rect.bottom() - kScrollerTrackBorderWidth,
- track_rect.right(),
- track_rect.bottom(),
- paint);
- }
-}
-
-void NativeThemeMac::PaintScrollbarThumb(SkCanvas* canvas,
- Part part,
- State state,
- const gfx::Rect& rect) const {
- gfx::Rect thumb_rect(rect);
- switch (part) {
- case kScrollbarHorizontalThumb:
- thumb_rect.Inset(0, kScrollerTrackBorderWidth, 0, 0);
- break;
- case kScrollbarVerticalThumb:
- thumb_rect.Inset(kScrollerTrackBorderWidth, 0, 0, 0);
- break;
- default:
- NOTREACHED();
- break;
- }
-
- thumb_rect.Inset(kScrollerThumbInset, kScrollerThumbInset);
-
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(state == kHovered ? thumb_active_color_
- : thumb_inactive_color_);
- const SkScalar radius = std::min(rect.width(), rect.height());
- canvas->drawRoundRect(gfx::RectToSkRect(thumb_rect), radius, radius, paint);
-}
-
-void NativeThemeMac::PaintScrollbarCorner(SkCanvas* canvas,
- State state,
- const gfx::Rect& rect) const {
- DCHECK_GT(rect.width(), 0);
- DCHECK_GT(rect.height(), 0);
-
- // Draw radial gradient from top-left corner.
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkGradientShader::CreateRadial(SkPoint::Make(rect.x(), rect.y()),
- rect.width(),
- kScrollerTrackGradientColors,
- NULL,
- arraysize(kScrollerTrackGradientColors),
- SkShader::kClamp_TileMode));
- SkPaint gradient;
- gradient.setStyle(SkPaint::kFill_Style);
- gradient.setAntiAlias(true);
- gradient.setShader(shader.get());
- canvas->drawRect(gfx::RectToSkRect(rect), gradient);
-
- // Draw inner border corner point.
- canvas->drawPoint(rect.x(), rect.y(), kScrollerTrackInnerBorderColor);
-
- // Draw outer borders.
- SkPaint paint;
- paint.setColor(kScrollerTrackOuterBorderColor);
- canvas->drawRectCoords(rect.right() - kScrollerTrackBorderWidth,
- rect.y(),
- rect.right(),
- rect.bottom(),
- paint);
- canvas->drawRectCoords(rect.x(),
- rect.bottom() - kScrollerTrackBorderWidth,
- rect.right(),
- rect.bottom(),
- paint);
-}
-
void NativeThemeMac::PaintMenuPopupBackground(
SkCanvas* canvas,
const gfx::Size& size,
const MenuBackgroundExtraParams& menu_background) const {
SkPaint paint;
paint.setAntiAlias(true);
- if (base::mac::IsOSYosemiteOrLater())
- paint.setColor(kMenuPopupBackgroundColorYosemite);
+ if (base::mac::IsOSMavericks())
+ paint.setColor(kMenuPopupBackgroundColorMavericks);
else
paint.setColor(kMenuPopupBackgroundColor);
const SkScalar radius = SkIntToScalar(menu_background.corner_radius);
@@ -384,7 +248,7 @@ void NativeThemeMac::PaintMenuItemBackground(
SkCanvas* canvas,
State state,
const gfx::Rect& rect,
- const MenuListExtraParams& menu_list) const {
+ const MenuItemExtraParams& menu_item) const {
SkPaint paint;
switch (state) {
case NativeTheme::kNormal:
@@ -405,11 +269,37 @@ void NativeThemeMac::PaintMenuItemBackground(
}
}
+// static
+sk_sp<SkShader> NativeThemeMac::GetButtonBackgroundShader(
+ NativeTheme::State state, int height) {
+ typedef SkColor ColorByState[NativeTheme::State::kNumStates];
+ SkPoint gradient_points[2];
+ gradient_points[0].iset(0, 0);
+ gradient_points[1].iset(0, height);
+
+ SkScalar gradient_positions[] = { 0.0, 0.38, 1.0 };
+
+ ColorByState start_colors;
+ start_colors[NativeTheme::State::kDisabled] = gfx::kMaterialGrey300;
+ start_colors[NativeTheme::State::kHovered] = gfx::kMaterialBlue300;
+ start_colors[NativeTheme::State::kNormal] = gfx::kMaterialBlue300;
+ start_colors[NativeTheme::State::kPressed] = gfx::kMaterialBlue300;
+ ColorByState end_colors;
+ end_colors[NativeTheme::State::kDisabled] = gfx::kMaterialGrey300;
+ end_colors[NativeTheme::State::kHovered] = gfx::kMaterialBlue700;
+ end_colors[NativeTheme::State::kNormal] = gfx::kMaterialBlue700;
+ end_colors[NativeTheme::State::kPressed] = gfx::kMaterialBlue700;
+
+ SkColor gradient_colors[] = {
+ start_colors[state], start_colors[state], end_colors[state]
+ };
+
+ return SkGradientShader::MakeLinear(
+ gradient_points, gradient_colors, gradient_positions, 3,
+ SkShader::kClamp_TileMode);
+}
+
NativeThemeMac::NativeThemeMac() {
- set_scrollbar_button_length(0);
- SetScrollbarColors(kScrollerThumbColor,
- kScrollerThumbHoverColor,
- kScrollerTrackGradientColors[0]);
}
NativeThemeMac::~NativeThemeMac() {
diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc
index 182a27b98b3..94f907500ef 100644
--- a/chromium/ui/native_theme/native_theme_win.cc
+++ b/chromium/ui/native_theme/native_theme_win.cc
@@ -24,7 +24,7 @@
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/skia/include/core/SkShader.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/gdi_util.h"
@@ -77,12 +77,9 @@ void SetCheckerboardShader(SkPaint* paint, const RECT& align_rect) {
SkMatrix local_matrix;
local_matrix.setTranslate(SkIntToScalar(align_rect.left),
SkIntToScalar(align_rect.top));
- skia::RefPtr<SkShader> shader =
- skia::AdoptRef(SkShader::CreateBitmapShader(bitmap,
- SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode,
- &local_matrix));
- paint->setShader(shader.get());
+ paint->setShader(
+ SkShader::MakeBitmapShader(bitmap, SkShader::kRepeat_TileMode,
+ SkShader::kRepeat_TileMode, &local_matrix));
}
// <-a->
@@ -196,10 +193,6 @@ NativeThemeWin* NativeThemeWin::instance() {
gfx::Size NativeThemeWin::GetPartSize(Part part,
State state,
const ExtraParams& extra) const {
- gfx::Size part_size = CommonThemeGetPartSize(part, state, extra);
- if (!part_size.IsEmpty())
- return part_size;
-
// The GetThemePartSize call below returns the default size without
// accounting for user customization (crbug/218291).
switch (part) {
@@ -245,9 +238,6 @@ void NativeThemeWin::Paint(SkCanvas* canvas,
return;
switch (part) {
- case kComboboxArrow:
- CommonThemePaintComboboxArrow(canvas, rect);
- return;
case kMenuPopupGutter:
PaintMenuGutter(canvas, rect);
return;
@@ -258,7 +248,8 @@ void NativeThemeWin::Paint(SkCanvas* canvas,
PaintMenuBackground(canvas, rect);
return;
case kMenuItemBackground:
- CommonThemePaintMenuItemBackground(this, canvas, state, rect);
+ CommonThemePaintMenuItemBackground(this, canvas, state, rect,
+ extra.menu_item);
return;
default:
break;
@@ -466,7 +457,6 @@ void NativeThemeWin::PaintDirect(SkCanvas* canvas,
case kWindowResizeGripper:
PaintWindowResizeGripper(hdc, rect);
return;
- case kComboboxArrow:
case kSliderTrack:
case kSliderThumb:
case kMaxPart:
@@ -722,12 +712,7 @@ void NativeThemeWin::PaintIndirect(SkCanvas* canvas,
// Draw the theme controls using existing HDC-drawing code.
PaintDirect(&offscreen_canvas, part, state, adjusted_rect, adjusted_extra);
- // Copy the pixels to a bitmap that has ref-counted pixel storage, which is
- // necessary to have when drawing to a SkPicture.
- const SkBitmap& hdc_bitmap =
- offscreen_canvas.getDevice()->accessBitmap(false);
- SkBitmap bitmap;
- hdc_bitmap.copyTo(&bitmap, kN32_SkColorType);
+ SkBitmap bitmap = skia::ReadPixels(&offscreen_canvas);
// Post-process the pixels to fix up the alpha values (see big comment above).
const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder);
@@ -1715,7 +1700,6 @@ NativeThemeWin::ThemeName NativeThemeWin::GetThemeName(Part part) {
return TEXTFIELD;
case kWindowResizeGripper:
return STATUS;
- case kComboboxArrow:
case kMenuCheckBackground:
case kMenuPopupBackground:
case kMenuItemBackground:
@@ -1761,7 +1745,6 @@ int NativeThemeWin::GetWindowsPart(Part part,
return SBP_THUMBBTNVERT;
case kWindowResizeGripper:
return SP_GRIPPER;
- case kComboboxArrow:
case kInnerSpinButton:
case kMenuList:
case kMenuCheckBackground:
@@ -1955,7 +1938,6 @@ int NativeThemeWin::GetWindowsState(Part part,
NOTREACHED();
return 0;
}
- case kComboboxArrow:
case kInnerSpinButton:
case kMenuList:
case kMenuCheckBackground:
diff --git a/chromium/ui/ozone/BUILD.gn b/chromium/ui/ozone/BUILD.gn
index e6881de0bef..1470e380867 100644
--- a/chromium/ui/ozone/BUILD.gn
+++ b/chromium/ui/ozone/BUILD.gn
@@ -8,6 +8,8 @@ import("//testing/test.gni")
assert(use_ozone)
+visibility = [ ":*" ]
+
# The list of platforms that will be built.
ozone_platforms = []
@@ -43,6 +45,17 @@ if (ozone_platform_cast) {
ozone_platform_deps += [ "platform/cast" ]
}
+if (ozone_platform_wayland) {
+ ozone_platforms += [ "wayland" ]
+ ozone_platform_deps += [ "platform/wayland" ]
+ ozone_platform_test_deps += [ "platform/wayland:wayland_unittests" ]
+}
+
+if (ozone_platform_x11) {
+ ozone_platforms += [ "x11" ]
+ ozone_platform_deps += [ "platform/x11" ]
+}
+
platform_list_cc_file = "$target_gen_dir/platform_list.cc"
platform_list_h_file = "$target_gen_dir/platform_list.h"
platform_list_txt_file = "$target_gen_dir/platform_list.txt"
@@ -57,23 +70,6 @@ config("vgem_map") {
# GYP version: ui/ozone/ozone.gyp:ozone_base
component("ozone_base") {
sources = [
- "common/display_mode_proxy.cc",
- "common/display_mode_proxy.h",
- "common/display_snapshot_proxy.cc",
- "common/display_snapshot_proxy.h",
- "common/display_util.cc",
- "common/display_util.h",
- "common/egl_util.cc",
- "common/egl_util.h",
- "common/gpu/ozone_gpu_message_generator.cc",
- "common/gpu/ozone_gpu_message_generator.h",
- "common/gpu/ozone_gpu_message_params.cc",
- "common/gpu/ozone_gpu_message_params.h",
- "common/gpu/ozone_gpu_messages.h",
- "common/native_display_delegate_ozone.cc",
- "common/native_display_delegate_ozone.h",
- "common/stub_overlay_manager.cc",
- "common/stub_overlay_manager.h",
"public/cursor_factory_ozone.cc",
"public/cursor_factory_ozone.h",
"public/gpu_platform_support.cc",
@@ -97,7 +93,7 @@ component("ozone_base") {
defines = [ "OZONE_BASE_IMPLEMENTATION" ]
- deps = [
+ public_deps = [
"//base",
"//ipc",
"//skia",
@@ -108,51 +104,76 @@ component("ozone_base") {
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gfx/ipc",
+ "//ui/gfx/ipc/skia",
+ ]
+
+ visibility += [
+ # Everyone should depend on //ui/ozone instead except a handful of
+ # things that would otherwise create a cycle.
+ "//ui/base",
+ "//ui/events/ozone/*",
+ "//ui/ozone/platform/*",
+ "//ui/ozone/common/*",
]
}
-component("ozone") {
+source_set("platform") {
sources = [
"common/stub_client_native_pixmap_factory.cc",
"common/stub_client_native_pixmap_factory.h",
"platform_selection.cc",
"platform_selection.h",
"public/client_native_pixmap_factory.cc",
- "public/client_native_pixmap_factory.h",
"public/ozone_gpu_test_helper.cc",
- "public/ozone_gpu_test_helper.h",
"public/ozone_platform.cc",
- "public/ozone_platform.h",
constructor_list_cc_file,
platform_list_cc_file,
platform_list_h_file,
]
+ public = [
+ "public/client_native_pixmap_factory.h",
+ "public/ozone_gpu_test_helper.h",
+ "public/ozone_platform.h",
+ ]
+
defines = [ "OZONE_IMPLEMENTATION" ]
public_deps = [
":ozone_base",
+ "//base",
+ "//ipc",
+ "//skia",
+ "//ui/display/types",
+ "//ui/events",
+ "//ui/events/devices",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ "//ui/platform_window",
]
- deps =
- [
- ":generate_constructor_list",
- ":generate_ozone_platform_list",
- "//base",
- "//ipc",
- "//skia",
- "//ui/display/types",
- "//ui/display/util",
- "//ui/events",
- "//ui/events/devices",
- "//ui/events/ozone:events_ozone",
- "//ui/gfx",
- "//ui/gfx/geometry",
- "//ui/gfx/ipc",
-
- # TODO(GYP) the GYP version has a way to add additional dependencies via
- # build flags.
- ] + ozone_platform_deps
+ deps = [
+ ":generate_constructor_list",
+ ":generate_ozone_platform_list",
+ ]
+
+ # TODO(GYP) the GYP version has a way to add additional dependencies via
+ # build flags.
+ deps += ozone_platform_deps
+
+ # Platforms are always linked into //ui/ozone and can include our headers.
+ allow_circular_includes_from = ozone_platform_deps
+
+ # This is used for platform tests.
+ visibility += [ "//ui/ozone/platform/*" ]
+}
+
+component("ozone") {
+ visibility = []
+ visibility = [ "*" ]
+ public_deps = [
+ ":platform",
+ ]
}
# GYP version: ui/ozone/ozone.gyp:generate_ozone_platform_list
@@ -171,6 +192,8 @@ action("generate_ozone_platform_list") {
"--output_txt=" + rebase_path(platform_list_txt_file, root_build_dir),
"--default=$ozone_platform",
] + ozone_platforms
+
+ visibility += [ "//media:*" ]
}
# GYP version: ui/ozone/ozone.gyp:generate_constructor_list
@@ -205,8 +228,15 @@ test("ozone_unittests") {
]
deps = [
- "//base/test:test_support",
- "//testing/gtest",
- "//ui/gfx/geometry",
- ] + ozone_platform_test_deps
+ "//base/test:test_support",
+ "//testing/gtest",
+ "//ui/gfx/geometry",
+ ]
+
+ # Add tests of platform internals.
+ deps += ozone_platform_test_deps
+
+ # Platform tests link ozone statically. Make sure we're not getting a
+ # 2nd copy of any code via the component.
+ assert_no_deps = [ "//ui/ozone" ]
}
diff --git a/chromium/ui/ozone/common/BUILD.gn b/chromium/ui/ozone/common/BUILD.gn
new file mode 100644
index 00000000000..0f88278ef64
--- /dev/null
+++ b/chromium/ui/ozone/common/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ui.gni")
+
+assert(use_ozone)
+
+source_set("common") {
+ sources = [
+ "display_mode_proxy.cc",
+ "display_mode_proxy.h",
+ "display_snapshot_proxy.cc",
+ "display_snapshot_proxy.h",
+ "display_util.cc",
+ "display_util.h",
+ "egl_util.cc",
+ "egl_util.h",
+ "gpu/ozone_gpu_message_generator.cc",
+ "gpu/ozone_gpu_message_generator.h",
+ "gpu/ozone_gpu_message_params.cc",
+ "gpu/ozone_gpu_message_params.h",
+ "gpu/ozone_gpu_messages.h",
+ "native_display_delegate_ozone.cc",
+ "native_display_delegate_ozone.h",
+ "stub_overlay_manager.cc",
+ "stub_overlay_manager.h",
+ ]
+
+ public_deps = [
+ "//ui/ozone:ozone_base",
+ ]
+
+ visibility = [ "//ui/ozone/platform/*" ]
+}
diff --git a/chromium/ui/ozone/common/display_mode_proxy.h b/chromium/ui/ozone/common/display_mode_proxy.h
index 0b353791f6c..c1821acb742 100644
--- a/chromium/ui/ozone/common/display_mode_proxy.h
+++ b/chromium/ui/ozone/common/display_mode_proxy.h
@@ -7,13 +7,12 @@
#include "base/macros.h"
#include "ui/display/types/display_mode.h"
-#include "ui/ozone/ozone_base_export.h"
namespace ui {
struct DisplayMode_Params;
-class OZONE_BASE_EXPORT DisplayModeProxy : public DisplayMode {
+class DisplayModeProxy : public DisplayMode {
public:
DisplayModeProxy(const DisplayMode_Params& params);
~DisplayModeProxy() override;
diff --git a/chromium/ui/ozone/common/display_snapshot_proxy.cc b/chromium/ui/ozone/common/display_snapshot_proxy.cc
index 040f82d3270..e057599c781 100644
--- a/chromium/ui/ozone/common/display_snapshot_proxy.cc
+++ b/chromium/ui/ozone/common/display_snapshot_proxy.cc
@@ -18,13 +18,6 @@ bool SameModes(const DisplayMode_Params& lhs, const DisplayMode_Params& rhs) {
lhs.refresh_rate == rhs.refresh_rate;
}
-// Exclude 4K@60kHz becaseu this doesn't work in most devices/configuration now.
-// TODO(marcheu|oshima): Revisit this. crbug.com/39397
-bool IsModeBlackListed(const DisplayMode_Params& mode_params) {
- return mode_params.size.width() >= 3840 &&
- mode_params.size.height() >= 2160 && mode_params.refresh_rate >= 60.0f;
-}
-
} // namespace
DisplaySnapshotProxy::DisplaySnapshotProxy(const DisplaySnapshot_Params& params)
@@ -34,17 +27,16 @@ DisplaySnapshotProxy::DisplaySnapshotProxy(const DisplaySnapshot_Params& params)
params.type,
params.is_aspect_preserving_scaling,
params.has_overscan,
+ params.has_color_correction_matrix,
params.display_name,
params.sys_path,
std::vector<const DisplayMode*>(),
+ params.edid,
NULL,
NULL),
string_representation_(params.string_representation) {
for (size_t i = 0; i < params.modes.size(); ++i) {
- const DisplayMode_Params& mode_params = params.modes[i];
- if (IsModeBlackListed(mode_params))
- continue;
- modes_.push_back(new DisplayModeProxy(mode_params));
+ modes_.push_back(new DisplayModeProxy(params.modes[i]));
if (params.has_current_mode &&
SameModes(params.modes[i], params.current_mode))
diff --git a/chromium/ui/ozone/common/display_snapshot_proxy.h b/chromium/ui/ozone/common/display_snapshot_proxy.h
index f2a53eb7596..6a5c4c96028 100644
--- a/chromium/ui/ozone/common/display_snapshot_proxy.h
+++ b/chromium/ui/ozone/common/display_snapshot_proxy.h
@@ -7,13 +7,12 @@
#include "base/macros.h"
#include "ui/display/types/display_snapshot.h"
-#include "ui/ozone/ozone_base_export.h"
namespace ui {
struct DisplaySnapshot_Params;
-class OZONE_BASE_EXPORT DisplaySnapshotProxy : public DisplaySnapshot {
+class DisplaySnapshotProxy : public DisplaySnapshot {
public:
DisplaySnapshotProxy(const DisplaySnapshot_Params& params);
~DisplaySnapshotProxy() override;
diff --git a/chromium/ui/ozone/common/display_util.cc b/chromium/ui/ozone/common/display_util.cc
index 742dbcf9e3c..254f320b1b4 100644
--- a/chromium/ui/ozone/common/display_util.cc
+++ b/chromium/ui/ozone/common/display_util.cc
@@ -49,11 +49,14 @@ DisplaySnapshot_Params GetDisplaySnapshotParams(
params.type = display.type();
params.is_aspect_preserving_scaling = display.is_aspect_preserving_scaling();
params.has_overscan = display.has_overscan();
+ params.has_color_correction_matrix = display.has_color_correction_matrix();
params.display_name = display.display_name();
params.sys_path = display.sys_path();
for (size_t i = 0; i < display.modes().size(); ++i)
params.modes.push_back(GetDisplayModeParams(*display.modes()[i]));
+ params.edid = display.edid();
+
params.has_current_mode = display.current_mode() != NULL;
if (params.has_current_mode)
params.current_mode = GetDisplayModeParams(*display.current_mode());
diff --git a/chromium/ui/ozone/common/display_util.h b/chromium/ui/ozone/common/display_util.h
index efa4e912961..988712631da 100644
--- a/chromium/ui/ozone/common/display_util.h
+++ b/chromium/ui/ozone/common/display_util.h
@@ -10,7 +10,6 @@
#include <vector>
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
-#include "ui/ozone/ozone_base_export.h"
namespace base {
class FilePath;
@@ -33,8 +32,7 @@ class FindDisplayById {
int64_t display_id_;
};
-DisplayMode_Params OZONE_BASE_EXPORT
-GetDisplayModeParams(const DisplayMode& mode);
+DisplayMode_Params GetDisplayModeParams(const DisplayMode& mode);
DisplaySnapshot_Params GetDisplaySnapshotParams(const DisplaySnapshot& display);
// Create a display using the Ozone command line parameters.
diff --git a/chromium/ui/ozone/common/egl_util.cc b/chromium/ui/ozone/common/egl_util.cc
index 8000360c7b0..a86704640ad 100644
--- a/chromium/ui/ozone/common/egl_util.cc
+++ b/chromium/ui/ozone/common/egl_util.cc
@@ -62,4 +62,27 @@ bool LoadEGLGLES2Bindings(
return true;
}
+void* /* EGLConfig */ ChooseEGLConfig(const EglConfigCallbacks& egl,
+ const int32_t* attributes) {
+ void* config;
+ int32_t num_configs;
+ if (!egl.choose_config.Run(attributes, nullptr, 0, &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << egl.get_last_error_string.Run();
+ return nullptr;
+ }
+
+ if (num_configs == 0) {
+ LOG(ERROR) << "No suitable EGL configs found.";
+ return nullptr;
+ }
+
+ if (!egl.choose_config.Run(attributes, &config, 1, &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << egl.get_last_error_string.Run();
+ return nullptr;
+ }
+ return config;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/common/egl_util.h b/chromium/ui/ozone/common/egl_util.h
index 8e20387fc25..dbf9a8f86e0 100644
--- a/chromium/ui/ozone/common/egl_util.h
+++ b/chromium/ui/ozone/common/egl_util.h
@@ -5,18 +5,16 @@
#ifndef UI_OZONE_COMMON_EGL_UTIL_H_
#define UI_OZONE_COMMON_EGL_UTIL_H_
-#include "ui/ozone/ozone_base_export.h"
#include "ui/ozone/public/surface_factory_ozone.h"
+#include "ui/ozone/public/surface_ozone_egl.h"
namespace ui {
-OZONE_BASE_EXPORT
bool LoadDefaultEGLGLES2Bindings(
SurfaceFactoryOzone::AddGLLibraryCallback add_gl_library,
SurfaceFactoryOzone::SetGLGetProcAddressProcCallback
set_gl_get_proc_address);
-OZONE_BASE_EXPORT
bool LoadEGLGLES2Bindings(
SurfaceFactoryOzone::AddGLLibraryCallback add_gl_library,
SurfaceFactoryOzone::SetGLGetProcAddressProcCallback
@@ -24,6 +22,9 @@ bool LoadEGLGLES2Bindings(
const char* egl_library_name,
const char* gles_library_name);
+void* /* EGLConfig */ ChooseEGLConfig(const EglConfigCallbacks& egl,
+ const int32_t* attributes);
+
} // namespace ui
#endif // UI_OZONE_COMMON_EGL_UTIL_H_
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
index 9b0c9a08c38..7924ee040b0 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
@@ -6,6 +6,7 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
namespace ui {
@@ -17,6 +18,9 @@ DisplayMode_Params::~DisplayMode_Params() {}
DisplaySnapshot_Params::DisplaySnapshot_Params() {
}
+DisplaySnapshot_Params::DisplaySnapshot_Params(
+ const DisplaySnapshot_Params& other) = default;
+
DisplaySnapshot_Params::~DisplaySnapshot_Params() {}
OverlayCheck_Params::OverlayCheck_Params() {}
@@ -30,6 +34,9 @@ OverlayCheck_Params::OverlayCheck_Params(
crop_rect(candidate.crop_rect),
plane_z_order(candidate.plane_z_order) {}
+OverlayCheck_Params::OverlayCheck_Params(const OverlayCheck_Params& other) =
+ default;
+
OverlayCheck_Params::~OverlayCheck_Params() {
}
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
index f38be3c335c..afb0b071d8f 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
@@ -16,12 +16,11 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/overlay_transform.h"
-#include "ui/ozone/ozone_base_export.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
namespace ui {
-struct OZONE_BASE_EXPORT DisplayMode_Params {
+struct DisplayMode_Params {
DisplayMode_Params();
~DisplayMode_Params();
@@ -30,8 +29,9 @@ struct OZONE_BASE_EXPORT DisplayMode_Params {
float refresh_rate = 0.0f;
};
-struct OZONE_BASE_EXPORT DisplaySnapshot_Params {
+struct DisplaySnapshot_Params {
DisplaySnapshot_Params();
+ DisplaySnapshot_Params(const DisplaySnapshot_Params& other);
~DisplaySnapshot_Params();
int64_t display_id = 0;
@@ -40,9 +40,11 @@ struct OZONE_BASE_EXPORT DisplaySnapshot_Params {
DisplayConnectionType type = DISPLAY_CONNECTION_TYPE_NONE;
bool is_aspect_preserving_scaling = false;
bool has_overscan = false;
+ bool has_color_correction_matrix = false;
std::string display_name;
base::FilePath sys_path;
std::vector<DisplayMode_Params> modes;
+ std::vector<uint8_t> edid;
bool has_current_mode = false;
DisplayMode_Params current_mode;
bool has_native_mode = false;
@@ -51,10 +53,11 @@ struct OZONE_BASE_EXPORT DisplaySnapshot_Params {
std::string string_representation;
};
-struct OZONE_BASE_EXPORT OverlayCheck_Params {
+struct OverlayCheck_Params {
OverlayCheck_Params();
OverlayCheck_Params(
const OverlayCandidatesOzone::OverlaySurfaceCandidate& candidate);
+ OverlayCheck_Params(const OverlayCheck_Params& other);
~OverlayCheck_Params();
bool operator<(const OverlayCheck_Params& plane) const;
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h b/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
index 95f84bfadd6..fab2f1887f8 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
@@ -18,12 +18,12 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/ipc/gfx_param_traits_macros.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
-#include "ui/ozone/ozone_base_export.h"
#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT OZONE_BASE_EXPORT
+#define IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_START OzoneGpuMsgStart
@@ -48,9 +48,11 @@ IPC_STRUCT_TRAITS_BEGIN(ui::DisplaySnapshot_Params)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(is_aspect_preserving_scaling)
IPC_STRUCT_TRAITS_MEMBER(has_overscan)
+ IPC_STRUCT_TRAITS_MEMBER(has_color_correction_matrix)
IPC_STRUCT_TRAITS_MEMBER(display_name)
IPC_STRUCT_TRAITS_MEMBER(sys_path)
IPC_STRUCT_TRAITS_MEMBER(modes)
+ IPC_STRUCT_TRAITS_MEMBER(edid)
IPC_STRUCT_TRAITS_MEMBER(has_current_mode)
IPC_STRUCT_TRAITS_MEMBER(current_mode)
IPC_STRUCT_TRAITS_MEMBER(has_native_mode)
@@ -140,10 +142,11 @@ IPC_MESSAGE_CONTROL2(OzoneGpuMsg_SetHDCPState,
int64_t /* display_id */,
ui::HDCPState /* state */)
-// Provides the gamma ramp for display adjustment.
-IPC_MESSAGE_CONTROL2(OzoneGpuMsg_SetGammaRamp,
+IPC_MESSAGE_CONTROL4(OzoneGpuMsg_SetColorCorrection,
int64_t, // display ID,
- std::vector<ui::GammaRampRGBEntry>) // lut
+ std::vector<ui::GammaRampRGBEntry>, // degamma lut
+ std::vector<ui::GammaRampRGBEntry>, // gamma lut
+ std::vector<float>) // transform matrix
IPC_MESSAGE_CONTROL2(OzoneGpuMsg_CheckOverlayCapabilities,
gfx::AcceleratedWidget /* widget */,
diff --git a/chromium/ui/ozone/common/native_display_delegate_ozone.cc b/chromium/ui/ozone/common/native_display_delegate_ozone.cc
index 7dd50377714..24703cd3dd3 100644
--- a/chromium/ui/ozone/common/native_display_delegate_ozone.cc
+++ b/chromium/ui/ozone/common/native_display_delegate_ozone.cc
@@ -110,9 +110,11 @@ bool NativeDisplayDelegateOzone::SetColorCalibrationProfile(
return false;
}
-bool NativeDisplayDelegateOzone::SetGammaRamp(
+bool NativeDisplayDelegateOzone::SetColorCorrection(
const ui::DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& lut) {
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
NOTIMPLEMENTED();
return false;
}
diff --git a/chromium/ui/ozone/common/native_display_delegate_ozone.h b/chromium/ui/ozone/common/native_display_delegate_ozone.h
index 8c5a8cbec95..baf2a6cf114 100644
--- a/chromium/ui/ozone/common/native_display_delegate_ozone.h
+++ b/chromium/ui/ozone/common/native_display_delegate_ozone.h
@@ -8,14 +8,13 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "ui/display/types/native_display_delegate.h"
-#include "ui/ozone/ozone_base_export.h"
namespace ui {
-class OZONE_BASE_EXPORT NativeDisplayDelegateOzone
- : public NativeDisplayDelegate {
+class NativeDisplayDelegateOzone : public NativeDisplayDelegate {
public:
NativeDisplayDelegateOzone();
~NativeDisplayDelegateOzone() override;
@@ -48,9 +47,10 @@ class OZONE_BASE_EXPORT NativeDisplayDelegateOzone
bool SetColorCalibrationProfile(
const ui::DisplaySnapshot& output,
ui::ColorCalibrationProfile new_profile) override;
- bool SetGammaRamp(const ui::DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& lut) override;
-
+ bool SetColorCorrection(const ui::DisplaySnapshot& output,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) override;
void AddObserver(NativeDisplayObserver* observer) override;
void RemoveObserver(NativeDisplayObserver* observer) override;
diff --git a/chromium/ui/ozone/common/stub_client_native_pixmap_factory.cc b/chromium/ui/ozone/common/stub_client_native_pixmap_factory.cc
index 540e1ec8adb..ad32d8a67b7 100644
--- a/chromium/ui/ozone/common/stub_client_native_pixmap_factory.cc
+++ b/chromium/ui/ozone/common/stub_client_native_pixmap_factory.cc
@@ -15,7 +15,6 @@ class StubClientNativePixmapFactory : public ClientNativePixmapFactory {
~StubClientNativePixmapFactory() override {}
// ClientNativePixmapFactory:
- void Initialize(base::ScopedFD device_fd) override {}
bool IsConfigurationSupported(gfx::BufferFormat format,
gfx::BufferUsage usage) const override {
return false;
diff --git a/chromium/ui/ozone/common/stub_client_native_pixmap_factory.h b/chromium/ui/ozone/common/stub_client_native_pixmap_factory.h
index 27192f78992..a38a5571952 100644
--- a/chromium/ui/ozone/common/stub_client_native_pixmap_factory.h
+++ b/chromium/ui/ozone/common/stub_client_native_pixmap_factory.h
@@ -5,7 +5,7 @@
#ifndef UI_OZONE_COMMON_STUB_CLIENT_NATIVE_PIXMAP_FACTORY_H_
#define UI_OZONE_COMMON_STUB_CLIENT_NATIVE_PIXMAP_FACTORY_H_
-#include "ui/ozone/public/client_native_pixmap_factory.h" // nogncheck
+#include "ui/ozone/public/client_native_pixmap_factory.h"
namespace ui {
diff --git a/chromium/ui/ozone/common/stub_overlay_manager.h b/chromium/ui/ozone/common/stub_overlay_manager.h
index 3d42c2b6652..54fa3a36825 100644
--- a/chromium/ui/ozone/common/stub_overlay_manager.h
+++ b/chromium/ui/ozone/common/stub_overlay_manager.h
@@ -6,12 +6,11 @@
#define UI_OZONE_COMMON_STUB_OVERLAY_MANAGER_H_
#include "base/macros.h"
-#include "ui/ozone/ozone_base_export.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
namespace ui {
-class OZONE_BASE_EXPORT StubOverlayManager : public OverlayManagerOzone {
+class StubOverlayManager : public OverlayManagerOzone {
public:
StubOverlayManager();
~StubOverlayManager() override;
diff --git a/chromium/ui/ozone/demo/BUILD.gn b/chromium/ui/ozone/demo/BUILD.gn
index 70b2ded5a27..c05bb92ee2e 100644
--- a/chromium/ui/ozone/demo/BUILD.gn
+++ b/chromium/ui/ozone/demo/BUILD.gn
@@ -33,7 +33,6 @@ executable("ozone_demo") {
"//ui/gfx/geometry",
"//ui/gl",
"//ui/ozone",
- "//ui/ozone:ozone_base",
"//ui/platform_window",
]
}
diff --git a/chromium/ui/ozone/demo/ozone_demo.cc b/chromium/ui/ozone/demo/ozone_demo.cc
index 1e386ebc1bd..151c2803e61 100644
--- a/chromium/ui/ozone/demo/ozone_demo.cc
+++ b/chromium/ui/ozone/demo/ozone_demo.cc
@@ -145,8 +145,7 @@ class DemoWindow : public ui::PlatformWindowDelegate {
void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
void OnDamageRect(const gfx::Rect& damaged_region) override {}
void DispatchEvent(ui::Event* event) override {
- if (event->IsKeyEvent() &&
- static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::US_Q)
+ if (event->IsKeyEvent() && event->AsKeyEvent()->code() == ui::DomCode::US_Q)
Quit();
}
void OnCloseRequest() override { Quit(); }
diff --git a/chromium/ui/ozone/demo/software_renderer.cc b/chromium/ui/ozone/demo/software_renderer.cc
index fb567809f10..175e37998c3 100644
--- a/chromium/ui/ozone/demo/software_renderer.cc
+++ b/chromium/ui/ozone/demo/software_renderer.cc
@@ -49,7 +49,7 @@ void SoftwareRenderer::RenderFrame() {
float fraction = NextFraction();
- skia::RefPtr<SkSurface> surface = software_surface_->GetSurface();
+ sk_sp<SkSurface> surface = software_surface_->GetSurface();
SkColor color =
SkColorSetARGB(0xff, 0, 0xff * fraction, 0xff * (1 - fraction));
diff --git a/chromium/ui/ozone/demo/surfaceless_gl_renderer.h b/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
index c36c22fb7fd..6c8524e6fd6 100644
--- a/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
+++ b/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
@@ -6,6 +6,7 @@
#define UI_OZONE_DEMO_SURFACELESS_GL_RENDERER_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "ui/ozone/demo/gl_renderer.h"
namespace gl {
diff --git a/chromium/ui/ozone/empty.cc b/chromium/ui/ozone/empty.cc
new file mode 100644
index 00000000000..154ead7673b
--- /dev/null
+++ b/chromium/ui/ozone/empty.cc
@@ -0,0 +1,6 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This empty source file exists to force GYP to link the
+// ui/ozone/ozone.gyp:ozone target using the C++ compiler.
diff --git a/chromium/ui/ozone/ozone.gni b/chromium/ui/ozone/ozone.gni
index 8d12805c205..768ddf74a93 100644
--- a/chromium/ui/ozone/ozone.gni
+++ b/chromium/ui/ozone/ozone.gni
@@ -3,10 +3,11 @@
# found in the LICENSE file.
import("//build/config/chromecast_build.gni")
+import("//build/config/ui.gni")
declare_args() {
# Select platforms automatically. Turn this off for manual control.
- ozone_auto_platforms = true
+ ozone_auto_platforms = use_ozone
# This enables memory-mapped access to accelerated graphics buffers via the
# VGEM ("virtual GEM") driver. This is currently only available on Chrome OS
@@ -28,6 +29,7 @@ declare_args() {
ozone_platform_ozonex = false
ozone_platform_headless = false
ozone_platform_x11 = false
+ ozone_platform_wayland = false
if (ozone_auto_platforms) {
# Use headless as the default platform.
@@ -35,30 +37,30 @@ declare_args() {
ozone_platform_headless = true
if (is_chromecast) {
- if (!disable_display) {
- # Enable the Cast ozone platform on all A/V Cast builds.
- ozone_platform_cast = true
+ # Enable the Cast ozone platform on all A/V Cast builds.
+ ozone_platform_cast = true
- # For desktop Chromecast builds, override the default "headless"
- # platform with --ozone-platform=egltest
- # TODO(halliwell): Create a libcast_graphics implementation for desktop
- # using X11, and disable these two platforms. "cast" platform should be
- # the default on every A/V build.
- if (is_cast_desktop_build) {
- ozone_platform_egltest = true
- ozone_platform_ozonex = true
- } else {
- # On device builds, enable "cast" as the default platform.
- ozone_platform = "cast"
- }
+ # For visual desktop Chromecast builds, override the default "headless"
+ # platform with --ozone-platform=x11.
+ # TODO(halliwell): Create a libcast_graphics implementation for desktop
+ # using X11, and disable this platform.
+ if (is_cast_desktop_build && !disable_display) {
+ ozone_platform_x11 = true
+ } else {
+ ozone_platform = "cast"
}
} else if (is_chromeos) {
ozone_platform_gbm = true
- ozone_platform_egltest = true
+ ozone_platform_x11 = true
} else {
# Build all platforms whose deps are in install-build-deps.sh.
# Only these platforms will be compile tested by buildbots.
- ozone_platform_egltest = true
+ ozone_platform_x11 = true
}
}
}
+
+assert(use_ozone || !(ozone_platform_caca || ozone_platform_cast ||
+ ozone_platform_egltest || ozone_platform_gbm ||
+ ozone_platform_ozonex || ozone_platform_headless),
+ "Must set use_ozone to select ozone platforms")
diff --git a/chromium/ui/ozone/ozone.gyp b/chromium/ui/ozone/ozone.gyp
index a878f8ec33f..0458cf3406b 100644
--- a/chromium/ui/ozone/ozone.gyp
+++ b/chromium/ui/ozone/ozone.gyp
@@ -37,28 +37,12 @@
'<(DEPTH)/ui/display/display.gyp:display_util',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
'<(DEPTH)/ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
+ '<(DEPTH)/ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
],
'defines': [
'OZONE_BASE_IMPLEMENTATION',
],
'sources': [
- 'common/display_mode_proxy.cc',
- 'common/display_mode_proxy.h',
- 'common/display_snapshot_proxy.cc',
- 'common/display_snapshot_proxy.h',
- 'common/display_util.cc',
- 'common/display_util.h',
- 'common/egl_util.cc',
- 'common/egl_util.h',
- 'common/gpu/ozone_gpu_message_generator.cc',
- 'common/gpu/ozone_gpu_message_generator.h',
- 'common/gpu/ozone_gpu_message_params.cc',
- 'common/gpu/ozone_gpu_message_params.h',
- 'common/gpu/ozone_gpu_messages.h',
- 'common/native_display_delegate_ozone.cc',
- 'common/native_display_delegate_ozone.h',
- 'common/stub_overlay_manager.cc',
- 'common/stub_overlay_manager.h',
'public/client_native_pixmap.h',
'public/cursor_factory_ozone.cc',
'public/cursor_factory_ozone.h',
@@ -83,9 +67,43 @@
],
},
{
- # GN version: //ui/ozone
- 'target_name': 'ozone',
- 'type': '<(component)',
+ # GN version: //ui/ozone/common
+ 'target_name': 'ozone_common',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'ozone_base',
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/ipc/ipc.gyp:ipc',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/ui/display/display.gyp:display_types',
+ '<(DEPTH)/ui/display/display.gyp:display_util',
+ '<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
+ '<(DEPTH)/ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
+ ],
+ 'sources': [
+ 'common/display_mode_proxy.cc',
+ 'common/display_mode_proxy.h',
+ 'common/display_snapshot_proxy.cc',
+ 'common/display_snapshot_proxy.h',
+ 'common/display_util.cc',
+ 'common/display_util.h',
+ 'common/egl_util.cc',
+ 'common/egl_util.h',
+ 'common/gpu/ozone_gpu_message_generator.cc',
+ 'common/gpu/ozone_gpu_message_generator.h',
+ 'common/gpu/ozone_gpu_message_params.cc',
+ 'common/gpu/ozone_gpu_message_params.h',
+ 'common/gpu/ozone_gpu_messages.h',
+ 'common/native_display_delegate_ozone.cc',
+ 'common/native_display_delegate_ozone.h',
+ 'common/stub_overlay_manager.cc',
+ 'common/stub_overlay_manager.h',
+ ],
+ },
+ {
+ # GN version: //ui/ozone:platform
+ 'target_name': 'ozone_platform',
+ 'type': 'static_library',
'dependencies': [
'<(DEPTH)/base/base.gyp:base',
'<(DEPTH)/ipc/ipc.gyp:ipc',
@@ -97,7 +115,7 @@
'<(DEPTH)/ui/events/ozone/events_ozone.gyp:events_ozone',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx',
'<(DEPTH)/ui/gfx/gfx.gyp:gfx_geometry',
- '<(DEPTH)/ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
+ '<(DEPTH)/ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
'<@(external_ozone_platform_deps)',
'<@(internal_ozone_platform_deps)',
'ozone_base',
@@ -195,13 +213,23 @@
],
},
{
+ # GN version: //ui/ozone
+ 'target_name': 'ozone',
+ 'type': '<(component)',
+ 'sources': [
+ 'empty.cc',
+ ],
+ 'dependencies': [
+ 'ozone_platform',
+ ],
+ },
+ {
'target_name': 'ozone_unittests',
'type': '<(gtest_target_type)',
'sources': [
'run_all_unittests.cc',
],
'dependencies': [
- 'ozone',
'../../base/base.gyp:base',
'../../base/base.gyp:test_support_base',
'../../testing/gtest.gyp:gtest',
@@ -250,5 +278,10 @@
'platform/headless/headless.gypi',
],
}],
+ ['<(ozone_platform_wayland) == 1', {
+ 'includes': [
+ 'platform/wayland/wayland.gypi',
+ ],
+ }],
],
}
diff --git a/chromium/ui/ozone/platform/caca/BUILD.gn b/chromium/ui/ozone/platform/caca/BUILD.gn
index 4f92fce9a08..be3fbb9d435 100644
--- a/chromium/ui/ozone/platform/caca/BUILD.gn
+++ b/chromium/ui/ozone/platform/caca/BUILD.gn
@@ -4,6 +4,8 @@
import("//build/config/linux/pkg_config.gni")
+visibility = [ "//ui/ozone/*" ]
+
source_set("caca") {
sources = [
"caca_event_source.cc",
@@ -29,6 +31,8 @@ source_set("caca") {
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window",
]
configs += [ ":libcaca" ]
diff --git a/chromium/ui/ozone/platform/caca/caca.gypi b/chromium/ui/ozone/platform/caca/caca.gypi
index fc1b6d20651..4fccd3d374e 100644
--- a/chromium/ui/ozone/platform/caca/caca.gypi
+++ b/chromium/ui/ozone/platform/caca/caca.gypi
@@ -19,6 +19,8 @@
'OZONE_IMPLEMENTATION',
],
'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
'../../base/base.gyp:base',
'../../skia/skia.gyp:skia',
'../events/events.gyp:events',
diff --git a/chromium/ui/ozone/platform/caca/caca_window_manager.cc b/chromium/ui/ozone/platform/caca/caca_window_manager.cc
index 11fc46d6635..561a57d8864 100644
--- a/chromium/ui/ozone/platform/caca/caca_window_manager.cc
+++ b/chromium/ui/ozone/platform/caca/caca_window_manager.cc
@@ -140,7 +140,7 @@ scoped_ptr<ui::SurfaceOzoneCanvas> CacaWindowManager::CreateCanvasForWidget(
scoped_ptr<CacaSurface> canvas(new CacaSurface(window));
bool initialized = canvas->Initialize();
DCHECK(initialized);
- return canvas;
+ return std::move(canvas);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/caca/ozone_platform_caca.cc b/chromium/ui/ozone/platform/caca/ozone_platform_caca.cc
index fa2d2142225..dff1fdd2fb4 100644
--- a/chromium/ui/ozone/platform/caca/ozone_platform_caca.cc
+++ b/chromium/ui/ozone/platform/caca/ozone_platform_caca.cc
@@ -16,7 +16,7 @@
#include "ui/ozone/public/gpu_platform_support.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/system_input_injector.h"
namespace ui {
@@ -57,14 +57,11 @@ class OzonePlatformCaca : public OzonePlatform {
delegate, window_manager_.get(), event_source_.get(), bounds));
if (!caca_window->Initialize())
return nullptr;
- return caca_window;
+ return std::move(caca_window);
}
scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
return make_scoped_ptr(new NativeDisplayDelegateOzone());
}
- base::ScopedFD OpenClientNativePixmapDevice() const override {
- return base::ScopedFD();
- }
void InitializeUI() override {
window_manager_.reset(new CacaWindowManager);
diff --git a/chromium/ui/ozone/platform/cast/BUILD.gn b/chromium/ui/ozone/platform/cast/BUILD.gn
index f20e5e6257a..53de77f24af 100644
--- a/chromium/ui/ozone/platform/cast/BUILD.gn
+++ b/chromium/ui/ozone/platform/cast/BUILD.gn
@@ -5,6 +5,11 @@
import("//build/config/chromecast_build.gni")
import("//ui/ozone/ozone.gni")
+visibility = [
+ "//ui/ozone/*",
+ "//chromecast/*",
+]
+
# GYP version: cast.gypi:ozone_platform_cast
# TODO(slan): gn check needs deps on ozone and media to pass. Correct this.
source_set("cast") {
@@ -32,12 +37,16 @@ source_set("cast") {
# do not want to statically link against EGL library.
libs = [ "dl" ]
+ if (disable_display) {
+ defines = [ "DISABLE_DISPLAY" ]
+ }
+
deps = [
"//base",
"//chromecast/graphics:libcast_graphics_1.0",
- "//chromecast/media/base:message_loop",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/ozone:ozone_base",
+ "//ui/ozone/common",
]
}
diff --git a/chromium/ui/ozone/platform/cast/DEPS b/chromium/ui/ozone/platform/cast/DEPS
index 9e7bddfc348..95cbe02f536 100644
--- a/chromium/ui/ozone/platform/cast/DEPS
+++ b/chromium/ui/ozone/platform/cast/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+chromecast/media/base/video_plane_controller.h",
"+chromecast/public"
]
diff --git a/chromium/ui/ozone/platform/cast/OWNERS b/chromium/ui/ozone/platform/cast/OWNERS
index 7513d88f24f..80a937b7403 100644
--- a/chromium/ui/ozone/platform/cast/OWNERS
+++ b/chromium/ui/ozone/platform/cast/OWNERS
@@ -1,3 +1,3 @@
-gunsch@chromium.org
+alokp@chromium.org
halliwell@chromium.org
lcwu@chromium.org
diff --git a/chromium/ui/ozone/platform/cast/cast.gypi b/chromium/ui/ozone/platform/cast/cast.gypi
index 82470548508..a0dbd6e1e69 100644
--- a/chromium/ui/ozone/platform/cast/cast.gypi
+++ b/chromium/ui/ozone/platform/cast/cast.gypi
@@ -4,6 +4,7 @@
{
'variables': {
+ 'disable_display%': 0,
'internal_ozone_platform_deps': [
'ozone_platform_cast',
],
@@ -18,17 +19,23 @@
'target_name': 'ozone_platform_cast',
'type': 'static_library',
'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
'../events/events.gyp:events',
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_geometry',
'../../base/base.gyp:base',
'../../chromecast/chromecast.gyp:cast_public_api',
'../../chromecast/chromecast.gyp:libcast_graphics_1.0',
- '../../chromecast/media/media.gyp:media_base',
],
'include_dirs': [
'<(DEPTH)/third_party/khronos',
],
+ 'conditions': [
+ ['disable_display==1', {
+ 'defines': ['DISABLE_DISPLAY'],
+ }],
+ ],
'sources': [
'client_native_pixmap_factory_cast.cc',
diff --git a/chromium/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc b/chromium/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
index 2173d6b1593..e03335f25fc 100644
--- a/chromium/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
+++ b/chromium/ui/ozone/platform/cast/client_native_pixmap_factory_cast.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "ui/gfx/buffer_types.h"
#include "ui/ozone/public/client_native_pixmap.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h" // nogncheck
+#include "ui/ozone/public/client_native_pixmap_factory.h"
namespace ui {
namespace {
@@ -29,8 +29,6 @@ class ClientNativePixmapCast : public ClientNativePixmap {
class ClientNativePixmapFactoryCast : public ClientNativePixmapFactory {
public:
// ClientNativePixmapFactoryCast implementation:
- void Initialize(base::ScopedFD device_fd) override {}
-
bool IsConfigurationSupported(gfx::BufferFormat format,
gfx::BufferUsage usage) const override {
return format == gfx::BufferFormat::RGBA_8888 &&
diff --git a/chromium/ui/ozone/platform/cast/overlay_manager_cast.cc b/chromium/ui/ozone/platform/cast/overlay_manager_cast.cc
index f2618874d03..993da209697 100644
--- a/chromium/ui/ozone/platform/cast/overlay_manager_cast.cc
+++ b/chromium/ui/ozone/platform/cast/overlay_manager_cast.cc
@@ -4,14 +4,16 @@
#include "ui/ozone/platform/cast/overlay_manager_cast.h"
-#include "chromecast/media/base/video_plane_controller.h"
-#include "chromecast/public/graphics_types.h"
+#include "base/lazy_instance.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
namespace ui {
namespace {
+base::LazyInstance<OverlayManagerCast::OverlayCompositedCallback>
+ g_overlay_composited_callback = LAZY_INSTANCE_INITIALIZER;
+
// Translates a gfx::OverlayTransform into a VideoPlane::Transform.
// Could be just a lookup table once we have unit tests for this code
// to ensure it stays in sync with OverlayTransform.
@@ -60,9 +62,9 @@ void OverlayCandidatesCast::CheckOverlaySupport(
candidate.display_rect.width(), candidate.display_rect.height());
// Update video plane geometry + transform to match compositor quad.
- chromecast::media::VideoPlaneController::GetInstance()->SetGeometry(
- display_rect, ConvertTransform(candidate.transform));
-
+ if (!g_overlay_composited_callback.Get().is_null())
+ g_overlay_composited_callback.Get().Run(
+ display_rect, ConvertTransform(candidate.transform));
return;
}
}
@@ -80,4 +82,10 @@ scoped_ptr<OverlayCandidatesOzone> OverlayManagerCast::CreateOverlayCandidates(
return make_scoped_ptr(new OverlayCandidatesCast());
}
+// static
+void OverlayManagerCast::SetOverlayCompositedCallback(
+ const OverlayCompositedCallback& cb) {
+ g_overlay_composited_callback.Get() = cb;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/cast/overlay_manager_cast.h b/chromium/ui/ozone/platform/cast/overlay_manager_cast.h
index 808ae3675eb..169f3b1c834 100644
--- a/chromium/ui/ozone/platform/cast/overlay_manager_cast.h
+++ b/chromium/ui/ozone/platform/cast/overlay_manager_cast.h
@@ -5,13 +5,17 @@
#ifndef UI_OZONE_PLATFORM_CAST_OVERLAY_MANAGER_CAST_H_
#define UI_OZONE_PLATFORM_CAST_OVERLAY_MANAGER_CAST_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "chromecast/public/graphics_types.h"
+#include "chromecast/public/video_plane.h"
+#include "ui/ozone/ozone_export.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
namespace ui {
-class OverlayManagerCast : public OverlayManagerOzone {
+class OZONE_EXPORT OverlayManagerCast : public OverlayManagerOzone {
public:
OverlayManagerCast();
~OverlayManagerCast() override;
@@ -20,6 +24,14 @@ class OverlayManagerCast : public OverlayManagerOzone {
scoped_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
gfx::AcceleratedWidget w) override;
+ // Callback that's made whenever an overlay quad is processed
+ // in the compositor. Used to allow hardware video plane to
+ // be positioned to match compositor hole.
+ using OverlayCompositedCallback =
+ base::Callback<void(const chromecast::RectF&,
+ chromecast::media::VideoPlane::Transform)>;
+ static void SetOverlayCompositedCallback(const OverlayCompositedCallback& cb);
+
private:
DISALLOW_COPY_AND_ASSIGN(OverlayManagerCast);
diff --git a/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc b/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
index bf2bc8306ed..3600efb7072 100644
--- a/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
+++ b/chromium/ui/ozone/platform/cast/ozone_platform_cast.cc
@@ -19,7 +19,7 @@
#include "ui/ozone/public/cursor_factory_ozone.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/system_input_injector.h"
using chromecast::CastEglPlatform;
@@ -74,9 +74,6 @@ class OzonePlatformCast : public OzonePlatform {
scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
return make_scoped_ptr(new NativeDisplayDelegateOzone());
}
- base::ScopedFD OpenClientNativePixmapDevice() const override {
- return base::ScopedFD();
- }
void InitializeUI() override {
overlay_manager_.reset(new OverlayManagerCast());
@@ -85,8 +82,15 @@ class OzonePlatformCast : public OzonePlatform {
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
// Enable dummy software rendering support if GPU process disabled
+ // or if we're an audio-only build.
// Note: switch is kDisableGpu from content/public/common/content_switches.h
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("disable-gpu"))
+ bool enable_dummy_software_rendering = true;
+#if !defined(DISABLE_DISPLAY)
+ enable_dummy_software_rendering =
+ base::CommandLine::ForCurrentProcess()->HasSwitch("disable-gpu");
+#endif
+
+ if (enable_dummy_software_rendering)
surface_factory_.reset(new SurfaceFactoryCast());
}
void InitializeGPU() override {
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
index 67478460ba6..72fa4e67901 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -48,11 +48,11 @@ class DummySurface : public SurfaceOzoneCanvas {
~DummySurface() override {}
// SurfaceOzoneCanvas implementation:
- skia::RefPtr<SkSurface> GetSurface() override { return surface_; }
+ sk_sp<SkSurface> GetSurface() override { return surface_; }
void ResizeCanvas(const gfx::Size& viewport_size) override {
- surface_ = skia::AdoptRef(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(
- viewport_size.width(), viewport_size.height())));
+ surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
+ viewport_size.width(), viewport_size.height()));
}
void PresentCanvas(const gfx::Rect& damage) override {}
@@ -62,7 +62,7 @@ class DummySurface : public SurfaceOzoneCanvas {
}
private:
- skia::RefPtr<SkSurface> surface_;
+ sk_sp<SkSurface> surface_;
DISALLOW_COPY_AND_ASSIGN(DummySurface);
};
@@ -78,7 +78,9 @@ SurfaceFactoryCast::SurfaceFactoryCast(scoped_ptr<CastEglPlatform> egl_platform)
window_(0),
display_size_(GetInitialDisplaySize()),
new_display_size_(GetInitialDisplaySize()),
- egl_platform_(std::move(egl_platform)) {}
+ egl_platform_(std::move(egl_platform)),
+ overlay_count_(0),
+ previous_frame_overlay_count_(0) {}
SurfaceFactoryCast::~SurfaceFactoryCast() {
ShutdownHardware();
@@ -128,6 +130,31 @@ void SurfaceFactoryCast::ShutdownHardware() {
state_ = kUninitialized;
}
+void SurfaceFactoryCast::OnSwapBuffers() {
+ DCHECK(overlay_count_ == 0 || overlay_count_ == 1);
+
+ // Logging for overlays to help diagnose bugs when nothing is visible on
+ // screen. Logging this every frame would be overwhelming, so we just
+ // log on the transitions from 0 overlays -> 1 overlay and vice versa.
+ if (overlay_count_ == 0 && previous_frame_overlay_count_ != 0) {
+ LOG(INFO) << "Overlays deactivated";
+ } else if (overlay_count_ != 0 && previous_frame_overlay_count_ == 0) {
+ LOG(INFO) << "Overlays activated: " << overlay_bounds_.ToString();
+ } else if (overlay_count_ == previous_frame_overlay_count_ &&
+ overlay_bounds_ != previous_frame_overlay_bounds_) {
+ LOG(INFO) << "Overlay geometry changed to " << overlay_bounds_.ToString();
+ }
+
+ previous_frame_overlay_count_ = overlay_count_;
+ previous_frame_overlay_bounds_ = overlay_bounds_;
+ overlay_count_ = 0;
+}
+
+void SurfaceFactoryCast::OnOverlayScheduled(const gfx::Rect& display_bounds) {
+ ++overlay_count_;
+ overlay_bounds_ = display_bounds;
+}
+
scoped_ptr<SurfaceOzoneCanvas> SurfaceFactoryCast::CreateCanvasForWidget(
gfx::AcceleratedWidget widget) {
// Software canvas support only in headless mode
@@ -210,11 +237,6 @@ void SurfaceFactoryCast::ChildDestroyed() {
DestroyWindow();
}
-const int32_t* SurfaceFactoryCast::GetEGLSurfaceProperties(
- const int32_t* desired_list) {
- return egl_platform_->GetEGLSurfaceProperties(desired_list);
-}
-
scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
gfx::AcceleratedWidget widget,
gfx::Size size,
@@ -222,7 +244,7 @@ scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
gfx::BufferUsage usage) {
class CastPixmap : public NativePixmap {
public:
- CastPixmap() {}
+ CastPixmap(SurfaceFactoryCast* parent) : parent_(parent) {}
void* GetEGLClientBuffer() const override {
// TODO(halliwell): try to implement this through CastEglPlatform.
@@ -240,6 +262,7 @@ scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) override {
+ parent_->OnOverlayScheduled(display_bounds);
return true;
}
void SetProcessingCallback(
@@ -251,9 +274,11 @@ scoped_refptr<NativePixmap> SurfaceFactoryCast::CreateNativePixmap(
private:
~CastPixmap() override {}
+ SurfaceFactoryCast* parent_;
+
DISALLOW_COPY_AND_ASSIGN(CastPixmap);
};
- return make_scoped_refptr(new CastPixmap);
+ return make_scoped_refptr(new CastPixmap(this));
}
bool SurfaceFactoryCast::LoadEGLGLES2Bindings(
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.h b/chromium/ui/ozone/platform/cast/surface_factory_cast.h
index 33837cda782..fd7ab824f39 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.h
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/public/surface_factory_ozone.h"
@@ -32,7 +33,6 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone {
intptr_t GetNativeDisplay() override;
scoped_ptr<SurfaceOzoneEGL> CreateEGLSurfaceForWidget(
gfx::AcceleratedWidget widget) override;
- const int32_t* GetEGLSurfaceProperties(const int32_t* desired_list) override;
scoped_refptr<NativePixmap> CreateNativePixmap(
gfx::AcceleratedWidget widget,
gfx::Size size,
@@ -48,6 +48,10 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone {
void TerminateDisplay();
void ShutdownHardware();
+ // API for keeping track of overlays per frame for logging purposes
+ void OnSwapBuffers();
+ void OnOverlayScheduled(const gfx::Rect& display_bounds);
+
private:
enum HardwareState { kUninitialized, kInitialized, kFailed };
@@ -64,6 +68,12 @@ class SurfaceFactoryCast : public SurfaceFactoryOzone {
gfx::Size new_display_size_;
scoped_ptr<chromecast::CastEglPlatform> egl_platform_;
+ // Overlays scheduled in current and previous frames:
+ int overlay_count_;
+ gfx::Rect overlay_bounds_;
+ int previous_frame_overlay_count_;
+ gfx::Rect previous_frame_overlay_bounds_;
+
DISALLOW_COPY_AND_ASSIGN(SurfaceFactoryCast);
};
diff --git a/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.cc b/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.cc
index bbe8d3c8ad9..d05c1f8c2a7 100644
--- a/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.cc
+++ b/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.cc
@@ -4,7 +4,9 @@
#include "ui/ozone/platform/cast/surface_ozone_egl_cast.h"
+#include "third_party/khronos/EGL/egl.h"
#include "ui/gfx/vsync_provider.h"
+#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/platform/cast/surface_factory_cast.h"
namespace ui {
@@ -18,11 +20,13 @@ intptr_t SurfaceOzoneEglCast::GetNativeWindow() {
}
bool SurfaceOzoneEglCast::OnSwapBuffers() {
+ parent_->OnSwapBuffers();
return true;
}
void SurfaceOzoneEglCast::OnSwapBuffersAsync(
const SwapCompletionCallback& callback) {
+ parent_->OnSwapBuffers();
callback.Run(gfx::SwapResult::SWAP_ACK);
}
@@ -34,4 +38,24 @@ scoped_ptr<gfx::VSyncProvider> SurfaceOzoneEglCast::CreateVSyncProvider() {
return nullptr;
}
+void* /* EGLConfig */ SurfaceOzoneEglCast::GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) {
+ EGLint config_attribs[] = {EGL_BUFFER_SIZE,
+ 32,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_RED_SIZE,
+ 8,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT,
+ EGL_NONE};
+ return ChooseEGLConfig(egl, config_attribs);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.h b/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.h
index 9d19bb6d079..7406cb7fbde 100644
--- a/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.h
+++ b/chromium/ui/ozone/platform/cast/surface_ozone_egl_cast.h
@@ -24,6 +24,8 @@ class SurfaceOzoneEglCast : public SurfaceOzoneEGL {
void OnSwapBuffersAsync(const SwapCompletionCallback& callback) override;
bool ResizeNativeWindow(const gfx::Size& viewport_size) override;
scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
+ void* /* EGLConfig */ GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) override;
private:
SurfaceFactoryCast* parent_;
diff --git a/chromium/ui/ozone/platform/drm/BUILD.gn b/chromium/ui/ozone/platform/drm/BUILD.gn
index 6758a883924..ff90fab2bbb 100644
--- a/chromium/ui/ozone/platform/drm/BUILD.gn
+++ b/chromium/ui/ozone/platform/drm/BUILD.gn
@@ -6,10 +6,11 @@ import("//build/config/linux/pkg_config.gni")
import("//ui/ozone/ozone.gni")
declare_args() {
- use_mesa_platform_null = false
use_drm_atomic = false
}
+visibility = [ "//ui/ozone/*" ]
+
pkg_config("libdrm") {
packages = [ "libdrm" ]
}
@@ -24,6 +25,8 @@ source_set("gbm") {
sources = [
"client_native_pixmap_factory_gbm.cc",
"client_native_pixmap_factory_gbm.h",
+ "common/client_native_pixmap_dmabuf.cc",
+ "common/client_native_pixmap_dmabuf.h",
"common/drm_util.cc",
"common/drm_util.h",
"common/scoped_drm_types.cc",
@@ -78,6 +81,8 @@ source_set("gbm") {
"gpu/hardware_display_plane_manager.h",
"gpu/hardware_display_plane_manager_legacy.cc",
"gpu/hardware_display_plane_manager_legacy.h",
+ "gpu/inter_thread_messaging_proxy.cc",
+ "gpu/inter_thread_messaging_proxy.h",
"gpu/overlay_plane.cc",
"gpu/overlay_plane.h",
"gpu/page_flip_request.cc",
@@ -87,19 +92,14 @@ source_set("gbm") {
"gpu/scanout_buffer.h",
"gpu/screen_manager.cc",
"gpu/screen_manager.h",
- "host/channel_observer.h",
"host/drm_cursor.cc",
"host/drm_cursor.h",
- "host/drm_cursor_core.cc",
- "host/drm_cursor_core.h",
"host/drm_device_handle.cc",
"host/drm_device_handle.h",
"host/drm_display_host.cc",
"host/drm_display_host.h",
"host/drm_display_host_manager.cc",
"host/drm_display_host_manager.h",
- "host/drm_display_host_manager_core.cc",
- "host/drm_display_host_manager_core.h",
"host/drm_gpu_platform_support_host.cc",
"host/drm_gpu_platform_support_host.h",
"host/drm_native_display_delegate.cc",
@@ -112,6 +112,10 @@ source_set("gbm") {
"host/drm_window_host.h",
"host/drm_window_host_manager.cc",
"host/drm_window_host_manager.h",
+ "host/gpu_thread_adapter.h",
+ "host/gpu_thread_observer.h",
+ "mus_thread_proxy.cc",
+ "mus_thread_proxy.h",
"ozone_platform_gbm.cc",
"ozone_platform_gbm.h",
]
@@ -133,6 +137,8 @@ source_set("gbm") {
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window",
]
configs += [ ":libdrm" ]
@@ -150,15 +156,6 @@ source_set("gbm") {
"gpu/hardware_display_plane_manager_atomic.h",
]
}
-
- if (use_vgem_map) {
- configs += [ "//ui/ozone:vgem_map" ]
-
- sources += [
- "common/client_native_pixmap_vgem.cc",
- "common/client_native_pixmap_vgem.h",
- ]
- }
}
source_set("gbm_unittests") {
@@ -189,7 +186,8 @@ source_set("gbm_unittests") {
"//skia",
"//testing/gtest",
"//ui/gfx",
- "//ui/ozone",
+ "//ui/ozone:platform",
+ "//ui/ozone/common",
]
public_configs = [ ":libdrm" ]
diff --git a/chromium/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc b/chromium/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
index 27bb4a4ca1a..3bae9dd0a57 100644
--- a/chromium/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
+++ b/chromium/ui/ozone/platform/drm/client_native_pixmap_factory_gbm.cc
@@ -8,11 +8,8 @@
#include "base/macros.h"
#include "ui/gfx/native_pixmap_handle_ozone.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h" // nogncheck
-
-#if defined(USE_VGEM_MAP)
-#include "ui/ozone/platform/drm/common/client_native_pixmap_vgem.h"
-#endif
+#include "ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h"
+#include "ui/ozone/public/client_native_pixmap_factory.h"
namespace ui {
@@ -39,14 +36,6 @@ class ClientNativePixmapFactoryGbm : public ClientNativePixmapFactory {
~ClientNativePixmapFactoryGbm() override {}
// ClientNativePixmapFactory:
- void Initialize(base::ScopedFD device_fd) override {
-#if defined(USE_VGEM_MAP)
- // It's called in IO thread. We rely on clients for thread-safety.
- // Switching to an IPC message filter ensures thread-safety.
- DCHECK_LT(vgem_fd_.get(), 0);
- vgem_fd_ = std::move(device_fd);
-#endif
- }
bool IsConfigurationSupported(gfx::BufferFormat format,
gfx::BufferUsage usage) const override {
switch (usage) {
@@ -58,8 +47,8 @@ class ClientNativePixmapFactoryGbm : public ClientNativePixmapFactory {
format == gfx::BufferFormat::BGRX_8888;
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT: {
-#if defined(USE_VGEM_MAP)
- return vgem_fd_.is_valid() && format == gfx::BufferFormat::BGRA_8888;
+#if defined(OS_CHROMEOS)
+ return format == gfx::BufferFormat::BGRA_8888;
#else
return false;
#endif
@@ -77,15 +66,13 @@ class ClientNativePixmapFactoryGbm : public ClientNativePixmapFactory {
switch (usage) {
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
-#if defined(USE_VGEM_MAP)
- // A valid |vgem_fd_| is required to acquire a VGEM bo. |vgem_fd_| is
- // set before a widget is created.
- DCHECK_GE(vgem_fd_.get(), 0);
- return ClientNativePixmapVgem::ImportFromDmabuf(
- vgem_fd_.get(), scoped_fd.get(), size, handle.stride);
-#endif
+#if defined(OS_CHROMEOS)
+ return ClientNativePixmapDmaBuf::ImportFromDmabuf(scoped_fd.release(),
+ size, handle.stride);
+#else
NOTREACHED();
return nullptr;
+#endif
case gfx::BufferUsage::GPU_READ:
case gfx::BufferUsage::SCANOUT:
return make_scoped_ptr<ClientNativePixmapGbm>(
@@ -95,11 +82,6 @@ class ClientNativePixmapFactoryGbm : public ClientNativePixmapFactory {
return nullptr;
}
- private:
-#if defined(USE_VGEM_MAP)
- base::ScopedFD vgem_fd_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(ClientNativePixmapFactoryGbm);
};
diff --git a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.cc b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.cc
new file mode 100644
index 00000000000..09e8692c1dc
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.cc
@@ -0,0 +1,98 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h"
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+
+#include "base/process/memory.h"
+#include "base/trace_event/trace_event.h"
+
+#if defined(OS_CHROMEOS)
+// TODO(vignatti): replace the local definitions below with #include
+// <linux/dma-buf.h> once kernel version 4.6 becomes widely used.
+#include <linux/types.h>
+
+struct local_dma_buf_sync {
+ __u64 flags;
+};
+
+#define LOCAL_DMA_BUF_SYNC_READ (1 << 0)
+#define LOCAL_DMA_BUF_SYNC_WRITE (2 << 0)
+#define LOCAL_DMA_BUF_SYNC_START (0 << 2)
+#define LOCAL_DMA_BUF_SYNC_END (1 << 2)
+
+#define LOCAL_DMA_BUF_BASE 'b'
+#define LOCAL_DMA_BUF_IOCTL_SYNC \
+ _IOW(LOCAL_DMA_BUF_BASE, 0, struct local_dma_buf_sync)
+#endif
+
+namespace ui {
+
+namespace {
+
+void PrimeSyncStart(int dmabuf_fd) {
+ struct local_dma_buf_sync sync_start = {0};
+
+ sync_start.flags = LOCAL_DMA_BUF_SYNC_START | LOCAL_DMA_BUF_SYNC_READ;
+ if (drmIoctl(dmabuf_fd, LOCAL_DMA_BUF_IOCTL_SYNC, &sync_start))
+ PLOG(ERROR) << "Failed DMA_BUF_SYNC_START";
+}
+
+void PrimeSyncEnd(int dmabuf_fd) {
+ struct local_dma_buf_sync sync_end = {0};
+
+ sync_end.flags = LOCAL_DMA_BUF_SYNC_END | LOCAL_DMA_BUF_SYNC_WRITE;
+ if (drmIoctl(dmabuf_fd, LOCAL_DMA_BUF_IOCTL_SYNC, &sync_end))
+ PLOG(ERROR) << "Failed DMA_BUF_SYNC_END";
+}
+
+} // namespace
+
+// static
+scoped_ptr<ClientNativePixmap> ClientNativePixmapDmaBuf::ImportFromDmabuf(
+ int dmabuf_fd,
+ const gfx::Size& size,
+ int stride) {
+ DCHECK_GE(dmabuf_fd, 0);
+ return make_scoped_ptr(new ClientNativePixmapDmaBuf(dmabuf_fd, size, stride));
+}
+
+ClientNativePixmapDmaBuf::ClientNativePixmapDmaBuf(int dmabuf_fd,
+ const gfx::Size& size,
+ int stride)
+ : dmabuf_fd_(dmabuf_fd), size_(size), stride_(stride) {
+ TRACE_EVENT0("drm", "ClientNativePixmapDmaBuf");
+ size_t map_size = stride_ * size_.height();
+ data_ = mmap(nullptr, map_size, (PROT_READ | PROT_WRITE), MAP_SHARED,
+ dmabuf_fd, 0);
+ CHECK_NE(data_, MAP_FAILED);
+}
+
+ClientNativePixmapDmaBuf::~ClientNativePixmapDmaBuf() {
+ TRACE_EVENT0("drm", "~ClientNativePixmapDmaBuf");
+ size_t size = stride_ * size_.height();
+ int ret = munmap(data_, size);
+ DCHECK(!ret);
+}
+
+void* ClientNativePixmapDmaBuf::Map() {
+ TRACE_EVENT0("drm", "DmaBuf:Map");
+ PrimeSyncStart(dmabuf_fd_.get());
+ return data_;
+}
+
+void ClientNativePixmapDmaBuf::Unmap() {
+ TRACE_EVENT0("drm", "DmaBuf:Unmap");
+ PrimeSyncEnd(dmabuf_fd_.get());
+}
+
+void ClientNativePixmapDmaBuf::GetStride(int* stride) const {
+ *stride = stride_;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h
new file mode 100644
index 00000000000..b00f34d2124
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_dmabuf.h
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_DMABUF_H_
+#define UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_DMABUF_H_
+
+#include <stdint.h>
+
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/ozone/public/client_native_pixmap.h"
+
+namespace ui {
+
+class ClientNativePixmapDmaBuf : public ClientNativePixmap {
+ public:
+ static scoped_ptr<ClientNativePixmap> ImportFromDmabuf(int dmabuf_fd,
+ const gfx::Size& size,
+ int stride);
+
+ ~ClientNativePixmapDmaBuf() override;
+
+ // Overridden from ClientNativePixmap.
+ void* Map() override;
+ void Unmap() override;
+ void GetStride(int* stride) const override;
+
+ private:
+ ClientNativePixmapDmaBuf(int dmabuf_fd, const gfx::Size& size, int stride);
+
+ base::ScopedFD dmabuf_fd_;
+ const gfx::Size size_;
+ const int stride_;
+ void* data_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientNativePixmapDmaBuf);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_DMABUF_H_
diff --git a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.cc b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.cc
deleted file mode 100644
index 6701102848d..00000000000
--- a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/drm/common/client_native_pixmap_vgem.h"
-
-#include <fcntl.h>
-#include <stddef.h>
-#include <sys/mman.h>
-#include <vgem_drm.h>
-#include <xf86drm.h>
-
-#include "base/process/memory.h"
-#include "base/trace_event/trace_event.h"
-
-namespace ui {
-
-// static
-scoped_ptr<ClientNativePixmap> ClientNativePixmapVgem::ImportFromDmabuf(
- int vgem_fd,
- int dmabuf_fd,
- const gfx::Size& size,
- int stride) {
- DCHECK_GE(vgem_fd, 0);
- DCHECK_GE(dmabuf_fd, 0);
- uint32_t vgem_bo_handle = 0;
- int ret = drmPrimeFDToHandle(vgem_fd, dmabuf_fd, &vgem_bo_handle);
- DCHECK(!ret) << "drmPrimeFDToHandle failed.";
- return make_scoped_ptr(
- new ClientNativePixmapVgem(vgem_fd, vgem_bo_handle, size, stride));
-}
-
-ClientNativePixmapVgem::ClientNativePixmapVgem(int vgem_fd,
- uint32_t vgem_bo_handle,
- const gfx::Size& size,
- int stride)
- : vgem_fd_(vgem_fd),
- vgem_bo_handle_(vgem_bo_handle),
- size_(size),
- stride_(stride),
- data_(nullptr) {
- DCHECK(vgem_bo_handle_);
- struct drm_mode_map_dumb mmap_arg = {0};
- mmap_arg.handle = vgem_bo_handle_;
- size_t map_size = stride_ * size_.height();
- int ret = drmIoctl(vgem_fd_, DRM_IOCTL_VGEM_MODE_MAP_DUMB, &mmap_arg);
- if (ret) {
- PLOG(ERROR) << "fail to map a vgem buffer.";
- base::TerminateBecauseOutOfMemory(map_size);
- }
- DCHECK(mmap_arg.offset);
-
- data_ = mmap(nullptr, map_size, (PROT_READ | PROT_WRITE), MAP_SHARED,
- vgem_fd_, mmap_arg.offset);
- DCHECK_NE(data_, MAP_FAILED);
-}
-
-ClientNativePixmapVgem::~ClientNativePixmapVgem() {
- size_t size = stride_ * size_.height();
- int ret = munmap(data_, size);
- DCHECK(!ret) << "fail to munmap a vgem buffer.";
-
- struct drm_gem_close close = {0};
- close.handle = vgem_bo_handle_;
- ret = drmIoctl(vgem_fd_, DRM_IOCTL_GEM_CLOSE, &close);
- DCHECK(!ret) << "fail to free a vgem buffer.";
-}
-
-void* ClientNativePixmapVgem::Map() {
- return data_;
-}
-
-void ClientNativePixmapVgem::Unmap() {}
-
-void ClientNativePixmapVgem::GetStride(int* stride) const {
- *stride = stride_;
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.h b/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.h
deleted file mode 100644
index 4d42cfe9dd2..00000000000
--- a/chromium/ui/ozone/platform/drm/common/client_native_pixmap_vgem.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_VGEM_H_
-#define UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_VGEM_H_
-
-#include <stdint.h>
-
-#include "base/file_descriptor_posix.h"
-#include "base/macros.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_pixmap_handle_ozone.h"
-#include "ui/ozone/public/client_native_pixmap.h"
-
-namespace ui {
-
-class ClientNativePixmapVgem : public ClientNativePixmap {
- public:
- static scoped_ptr<ClientNativePixmap> ImportFromDmabuf(int vgem_fd,
- int dmabuf_fd,
- const gfx::Size& size,
- int stride);
-
- ~ClientNativePixmapVgem() override;
-
- // Overridden from ClientNativePixmap.
- void* Map() override;
- void Unmap() override;
- void GetStride(int* stride) const override;
-
- private:
- ClientNativePixmapVgem(int vgem_fd,
- uint32_t vgem_bo_handle,
- const gfx::Size& size,
- int stride);
-
- const int vgem_fd_;
- const uint32_t vgem_bo_handle_;
- const gfx::Size size_;
- const int stride_;
- void* data_;
-
- DISALLOW_COPY_AND_ASSIGN(ClientNativePixmapVgem);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_COMMON_CLIENT_NATIVE_PIXMAP_VGEM_H_
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util.cc b/chromium/ui/ozone/platform/drm/common/drm_util.cc
index dbe061ad96b..586571a1972 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util.cc
+++ b/chromium/ui/ozone/platform/drm/common/drm_util.cc
@@ -157,6 +157,19 @@ int ConnectorIndex(int device_index, int display_index) {
return ((device_index << 4) + display_index) & 0xFF;
}
+bool HasColorCorrectionMatrix(int fd, drmModeCrtc* crtc) {
+ ScopedDrmObjectPropertyPtr crtc_props(
+ drmModeObjectGetProperties(fd, crtc->crtc_id, DRM_MODE_OBJECT_CRTC));
+
+ for (uint32_t i = 0; i < crtc_props->count_props; ++i) {
+ ScopedDrmPropertyPtr property(drmModeGetProperty(fd, crtc_props->props[i]));
+ if (property && !strcmp(property->name, "CTM")) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
@@ -229,21 +242,23 @@ DisplaySnapshot_Params CreateDisplaySnapshotParams(
params.type = GetDisplayType(info->connector());
params.is_aspect_preserving_scaling =
IsAspectPreserving(fd, info->connector());
+ params.has_color_correction_matrix =
+ HasColorCorrectionMatrix(fd, info->crtc());
ScopedDrmPropertyBlobPtr edid_blob(
GetDrmPropertyBlob(fd, info->connector(), "EDID"));
if (edid_blob) {
- std::vector<uint8_t> edid(
+ params.edid.assign(
static_cast<uint8_t*>(edid_blob->data),
static_cast<uint8_t*>(edid_blob->data) + edid_blob->length);
- GetDisplayIdFromEDID(edid, connector_index, &params.display_id,
+ GetDisplayIdFromEDID(params.edid, connector_index, &params.display_id,
&params.product_id);
- ParseOutputDeviceData(edid, nullptr, nullptr, &params.display_name, nullptr,
- nullptr);
- ParseOutputOverscanFlag(edid, &params.has_overscan);
+ ParseOutputDeviceData(params.edid, nullptr, nullptr, &params.display_name,
+ nullptr, nullptr);
+ ParseOutputOverscanFlag(params.edid, &params.has_overscan);
} else {
VLOG(1) << "Failed to get EDID blob for connector "
<< info->connector()->connector_id;
diff --git a/chromium/ui/ozone/platform/drm/common/scoped_drm_types.h b/chromium/ui/ozone/platform/drm/common/scoped_drm_types.h
index 2fa16df6656..a56f66199fd 100644
--- a/chromium/ui/ozone/platform/drm/common/scoped_drm_types.h
+++ b/chromium/ui/ozone/platform/drm/common/scoped_drm_types.h
@@ -6,7 +6,6 @@
#define UI_OZONE_PLATFORM_DRM_COMMON_SCOPED_DRM_TYPES_H_
#include "base/memory/scoped_ptr.h"
-#include "ui/ozone/ozone_export.h"
typedef struct _drmModeConnector drmModeConnector;
typedef struct _drmModeCrtc drmModeCrtc;
@@ -22,39 +21,39 @@ typedef struct _drmModeRes drmModeRes;
namespace ui {
-struct OZONE_EXPORT DrmResourcesDeleter {
+struct DrmResourcesDeleter {
void operator()(drmModeRes* resources) const;
};
-struct OZONE_EXPORT DrmConnectorDeleter {
+struct DrmConnectorDeleter {
void operator()(drmModeConnector* connector) const;
};
-struct OZONE_EXPORT DrmCrtcDeleter {
+struct DrmCrtcDeleter {
void operator()(drmModeCrtc* crtc) const;
};
-struct OZONE_EXPORT DrmEncoderDeleter {
+struct DrmEncoderDeleter {
void operator()(drmModeEncoder* encoder) const;
};
-struct OZONE_EXPORT DrmObjectPropertiesDeleter {
+struct DrmObjectPropertiesDeleter {
void operator()(drmModeObjectProperties* properties) const;
};
-struct OZONE_EXPORT DrmPlaneDeleter {
+struct DrmPlaneDeleter {
void operator()(drmModePlane* plane) const;
};
-struct OZONE_EXPORT DrmPlaneResDeleter {
+struct DrmPlaneResDeleter {
void operator()(drmModePlaneRes* plane_res) const;
};
-struct OZONE_EXPORT DrmPropertyDeleter {
+struct DrmPropertyDeleter {
void operator()(drmModePropertyRes* property) const;
};
#if defined(USE_DRM_ATOMIC)
-struct OZONE_EXPORT DrmAtomicReqDeleter {
+struct DrmAtomicReqDeleter {
void operator()(drmModeAtomicReq* property) const;
};
#endif // defined(USE_DRM_ATOMIC)
-struct OZONE_EXPORT DrmPropertyBlobDeleter {
+struct DrmPropertyBlobDeleter {
void operator()(drmModePropertyBlobRes* property) const;
};
-struct OZONE_EXPORT DrmFramebufferDeleter {
+struct DrmFramebufferDeleter {
void operator()(drmModeFB* framebuffer) const;
};
diff --git a/chromium/ui/ozone/platform/drm/gbm.gypi b/chromium/ui/ozone/platform/drm/gbm.gypi
index 26c7029b915..ff131dad935 100644
--- a/chromium/ui/ozone/platform/drm/gbm.gypi
+++ b/chromium/ui/ozone/platform/drm/gbm.gypi
@@ -13,7 +13,6 @@
'internal_ozone_platforms': [
'gbm',
],
- 'use_mesa_platform_null%': 0,
'use_drm_atomic%': 0,
},
'targets': [
@@ -34,6 +33,8 @@
'target_name': 'ozone_platform_gbm',
'type': 'static_library',
'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
'../../base/base.gyp:base',
'../../build/linux/system.gyp:libdrm',
'../../third_party/minigbm/minigbm.gyp:minigbm',
@@ -58,6 +59,8 @@
'sources': [
'client_native_pixmap_factory_gbm.cc',
'client_native_pixmap_factory_gbm.h',
+ 'common/client_native_pixmap_dmabuf.cc',
+ 'common/client_native_pixmap_dmabuf.h',
'common/drm_util.cc',
'common/drm_util.h',
'common/scoped_drm_types.cc',
@@ -113,6 +116,8 @@
'gpu/hardware_display_plane_manager.h',
'gpu/hardware_display_plane_manager_legacy.cc',
'gpu/hardware_display_plane_manager_legacy.h',
+ 'gpu/inter_thread_messaging_proxy.cc',
+ 'gpu/inter_thread_messaging_proxy.h',
'gpu/overlay_plane.cc',
'gpu/overlay_plane.h',
'gpu/page_flip_request.cc',
@@ -121,19 +126,14 @@
'gpu/proxy_helpers.h',
'gpu/screen_manager.cc',
'gpu/screen_manager.h',
- 'host/channel_observer.h',
'host/drm_cursor.cc',
'host/drm_cursor.h',
- 'host/drm_cursor_core.cc',
- 'host/drm_cursor_core.h',
'host/drm_device_handle.cc',
'host/drm_device_handle.h',
'host/drm_display_host.cc',
'host/drm_display_host.h',
'host/drm_display_host_manager.cc',
'host/drm_display_host_manager.h',
- 'host/drm_display_host_manager_core.cc',
- 'host/drm_display_host_manager_core.h',
'host/drm_gpu_platform_support_host.cc',
'host/drm_gpu_platform_support_host.h',
'host/drm_native_display_delegate.cc',
@@ -146,19 +146,14 @@
'host/drm_window_host.h',
'host/drm_window_host_manager.cc',
'host/drm_window_host_manager.h',
+ 'host/gpu_thread_adapter.h',
+ 'host/gpu_thread_observer.h',
+ 'mus_thread_proxy.cc',
+ 'mus_thread_proxy.h',
'ozone_platform_gbm.cc',
'ozone_platform_gbm.h',
],
'conditions': [
- ['use_vgem_map==1', {
- 'dependencies': [
- '../ozone/ozone.gyp:vgem_map',
- ],
- 'sources': [
- 'common/client_native_pixmap_vgem.cc',
- 'common/client_native_pixmap_vgem.h',
- ],
- }],
['use_drm_atomic == 1', {
'sources': [
'gpu/hardware_display_plane_atomic.cc',
@@ -177,7 +172,7 @@
'../../skia/skia.gyp:skia',
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_geometry',
- 'ozone.gyp:ozone',
+ 'ozone.gyp:ozone_platform',
'drm_atomic',
],
'export_dependent_settings': [
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
index 0740ee951c1..f332ce54da6 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -13,7 +13,6 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "ui/gfx/swap_result.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
@@ -28,8 +27,7 @@ class PageFlipRequest;
// One CRTC can be paired up with one or more connectors. The simplest
// configuration represents one CRTC driving one monitor, while pairing up a
// CRTC with multiple connectors results in hardware mirroring.
-class OZONE_EXPORT CrtcController
- : public base::SupportsWeakPtr<CrtcController> {
+class CrtcController : public base::SupportsWeakPtr<CrtcController> {
public:
CrtcController(const scoped_refptr<DrmDevice>& drm,
uint32_t crtc,
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc
index bd2e9a93671..1c50f1c4724 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -38,8 +38,6 @@ DrmBuffer::DrmBuffer(const scoped_refptr<DrmDevice>& drm) : drm_(drm) {
}
DrmBuffer::~DrmBuffer() {
- surface_.clear();
-
if (framebuffer_ && !drm_->RemoveFramebuffer(framebuffer_))
PLOG(ERROR) << "DrmBuffer: RemoveFramebuffer: fb " << framebuffer_;
@@ -78,8 +76,7 @@ bool DrmBuffer::Initialize(const SkImageInfo& info,
}
}
- surface_ =
- skia::AdoptRef(SkSurface::NewRasterDirect(info, mmap_base_, stride_));
+ surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
if (!surface_) {
LOG(ERROR) << "DrmBuffer: Failed to create SkSurface: handle " << handle_;
return false;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h
index 61d553e644e..726cf11934e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "skia/ext/refptr.h"
#include "third_party/skia/include/core/SkSurface.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
namespace ui {
@@ -21,7 +20,7 @@ class DrmDevice;
// Wrapper for a DRM allocated buffer. Keeps track of the native properties of
// the buffer and wraps the pixel memory into a SkSurface which can be used to
// draw into using Skia.
-class OZONE_EXPORT DrmBuffer : public ScanoutBuffer {
+class DrmBuffer : public ScanoutBuffer {
public:
DrmBuffer(const scoped_refptr<DrmDevice>& drm);
@@ -65,7 +64,7 @@ class OZONE_EXPORT DrmBuffer : public ScanoutBuffer {
uint32_t fb_pixel_format_ = 0;
// Wrapper around the native pixel memory.
- skia::RefPtr<SkSurface> surface_;
+ sk_sp<SkSurface> surface_;
DISALLOW_COPY_AND_ASSIGN(DrmBuffer);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
index 464c3805269..0fe4399d979 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
@@ -44,8 +44,7 @@ bool DrmConsoleBuffer::Initialize() {
return false;
}
- surface_ =
- skia::AdoptRef(SkSurface::NewRasterDirect(info, mmap_base_, stride_));
+ surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
if (!surface_)
return false;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h
index 2f28b9e6585..250ca3b54e5 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h
@@ -40,7 +40,7 @@ class DrmConsoleBuffer {
scoped_refptr<DrmDevice> drm_;
// Wrapper around the native pixel memory.
- skia::RefPtr<SkSurface> surface_;
+ sk_sp<SkSurface> surface_;
// Length of a row of pixels.
uint32_t stride_ = 0;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
index 3a30fd23e5a..891a136c8f8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -13,7 +13,9 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/free_deleter.h"
#include "base/message_loop/message_loop.h"
+#include "base/posix/safe_strerror.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -113,6 +115,161 @@ bool CanQueryForResources(int fd) {
return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources);
}
+// TODO(robert.bradford): Replace with libdrm structures after libdrm roll.
+// https://crbug.com/586475
+struct DrmColorLut {
+ uint16_t red;
+ uint16_t green;
+ uint16_t blue;
+ uint16_t reserved;
+};
+
+struct DrmColorCtm {
+ int64_t ctm_coeff[9];
+};
+
+struct DrmModeCreateBlob {
+ uint64_t data;
+ uint32_t length;
+ uint32_t blob_id;
+};
+
+struct DrmModeDestroyBlob {
+ uint32_t blob_id;
+};
+
+#ifndef DRM_IOCTL_MODE_CREATEPROPBLOB
+#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct DrmModeCreateBlob)
+#endif
+
+#ifndef DRM_IOCTL_MODE_DESTROYPROPBLOB
+#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct DrmModeDestroyBlob)
+#endif
+
+int CreatePropertyBlob(int fd, const void* data, size_t length, uint32_t* id) {
+ DrmModeCreateBlob create;
+ int ret;
+
+ if (length >= 0xffffffff)
+ return -ERANGE;
+
+ memset(&create, 0, sizeof(create));
+
+ create.length = length;
+ create.data = (uintptr_t)data;
+ create.blob_id = 0;
+ *id = 0;
+
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create);
+ ret = ret < 0 ? -errno : ret;
+ if (ret != 0)
+ return ret;
+
+ *id = create.blob_id;
+ return 0;
+}
+
+int DestroyPropertyBlob(int fd, uint32_t id) {
+ DrmModeDestroyBlob destroy;
+ int ret;
+
+ memset(&destroy, 0, sizeof(destroy));
+ destroy.blob_id = id;
+ ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy);
+ return ret < 0 ? -errno : ret;
+}
+
+using ScopedDrmColorLutPtr = scoped_ptr<DrmColorLut, base::FreeDeleter>;
+using ScopedDrmColorCtmPtr = scoped_ptr<DrmColorCtm, base::FreeDeleter>;
+
+ScopedDrmColorLutPtr CreateLutBlob(
+ const std::vector<GammaRampRGBEntry>& source) {
+ TRACE_EVENT0("drm", "CreateLutBlob");
+ ScopedDrmColorLutPtr lut(
+ static_cast<DrmColorLut*>(malloc(sizeof(DrmColorLut) * source.size())));
+ DrmColorLut* p = lut.get();
+ for (size_t i = 0; i < source.size(); ++i) {
+ p[i].red = source[i].r;
+ p[i].green = source[i].g;
+ p[i].blue = source[i].b;
+ }
+ return lut;
+}
+
+ScopedDrmColorCtmPtr CreateCTMBlob(
+ const std::vector<float>& correction_matrix) {
+ ScopedDrmColorCtmPtr ctm(
+ static_cast<DrmColorCtm*>(malloc(sizeof(DrmColorCtm))));
+ for (size_t i = 0; i < arraysize(ctm->ctm_coeff); ++i) {
+ if (correction_matrix[i] < 0) {
+ ctm->ctm_coeff[i] = static_cast<uint64_t>(
+ -correction_matrix[i] * (static_cast<uint64_t>(1) << 32));
+ ctm->ctm_coeff[i] |= static_cast<uint64_t>(1) << 63;
+ } else {
+ ctm->ctm_coeff[i] = static_cast<uint64_t>(
+ correction_matrix[i] * (static_cast<uint64_t>(1) << 32));
+ }
+ }
+ return ctm;
+}
+
+bool SetBlobProperty(int fd,
+ uint32_t object_id,
+ uint32_t object_type,
+ uint32_t prop_id,
+ const char* property_name,
+ unsigned char* data,
+ size_t length) {
+ uint32_t blob_id;
+ int res;
+ res = CreatePropertyBlob(fd, data, length, &blob_id);
+ if (res != 0) {
+ LOG(ERROR) << "Error creating property blob: " << base::safe_strerror(res)
+ << " for property " << property_name;
+ return false;
+ }
+ res = drmModeObjectSetProperty(fd, object_id, object_type, prop_id, blob_id);
+ if (res != 0) {
+ LOG(ERROR) << "Error updating property: " << base::safe_strerror(res)
+ << " for property " << property_name;
+ DestroyPropertyBlob(fd, blob_id);
+ return false;
+ }
+ DestroyPropertyBlob(fd, blob_id);
+ return true;
+}
+
+std::vector<GammaRampRGBEntry> ResampleLut(
+ const std::vector<GammaRampRGBEntry>& lut_in,
+ size_t desired_size) {
+ TRACE_EVENT1("drm", "ResampleLut", "desired_size", desired_size);
+ if (lut_in.size() == desired_size)
+ return lut_in;
+
+ std::vector<GammaRampRGBEntry> result;
+ result.resize(desired_size);
+
+ for (size_t i = 0; i < desired_size; ++i) {
+ size_t base_index = lut_in.size() * i / desired_size;
+ size_t remaining = lut_in.size() * i % desired_size;
+ if (base_index < lut_in.size() - 1) {
+ result[i].r = lut_in[base_index].r +
+ (lut_in[base_index + 1].r - lut_in[base_index].r) *
+ remaining / desired_size;
+ result[i].g = lut_in[base_index].g +
+ (lut_in[base_index + 1].g - lut_in[base_index].g) *
+ remaining / desired_size;
+ result[i].b = lut_in[base_index].b +
+ (lut_in[base_index + 1].b - lut_in[base_index].b) *
+ remaining / desired_size;
+ } else {
+ result[i] = lut_in[lut_in.size() - 1];
+ }
+ }
+
+ return result;
+}
+
} // namespace
class DrmDevice::PageFlipManager {
@@ -542,4 +699,74 @@ bool DrmDevice::SetGammaRamp(uint32_t crtc_id,
&g[0], &b[0]) == 0);
}
+bool DrmDevice::SetColorCorrection(
+ uint32_t crtc_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ ScopedDrmObjectPropertyPtr crtc_props(drmModeObjectGetProperties(
+ file_.GetPlatformFile(), crtc_id, DRM_MODE_OBJECT_CRTC));
+ uint64_t degamma_lut_size = 0;
+ uint64_t gamma_lut_size = 0;
+
+ for (uint32_t i = 0; i < crtc_props->count_props; ++i) {
+ ScopedDrmPropertyPtr property(
+ drmModeGetProperty(file_.GetPlatformFile(), crtc_props->props[i]));
+ if (property && !strcmp(property->name, "DEGAMMA_LUT_SIZE")) {
+ degamma_lut_size = crtc_props->prop_values[i];
+ }
+ if (property && !strcmp(property->name, "GAMMA_LUT_SIZE")) {
+ gamma_lut_size = crtc_props->prop_values[i];
+ }
+
+ if (degamma_lut_size && gamma_lut_size)
+ break;
+ }
+
+ if (degamma_lut_size == 0 || gamma_lut_size == 0) {
+ LOG(WARNING) << "No available (de)gamma tables.";
+ return false;
+ }
+
+ ScopedDrmColorLutPtr degamma_blob_data =
+ CreateLutBlob(ResampleLut(degamma_lut, degamma_lut_size));
+ ScopedDrmColorLutPtr gamma_blob_data =
+ CreateLutBlob(ResampleLut(gamma_lut, gamma_lut_size));
+ ScopedDrmColorCtmPtr ctm_blob_data = CreateCTMBlob(correction_matrix);
+
+ for (uint32_t i = 0; i < crtc_props->count_props; ++i) {
+ ScopedDrmPropertyPtr property(
+ drmModeGetProperty(file_.GetPlatformFile(), crtc_props->props[i]));
+ if (!property)
+ continue;
+
+ if (!strcmp(property->name, "DEGAMMA_LUT")) {
+ if (!SetBlobProperty(
+ file_.GetPlatformFile(), crtc_id, DRM_MODE_OBJECT_CRTC,
+ crtc_props->props[i], property->name,
+ reinterpret_cast<unsigned char*>(degamma_blob_data.get()),
+ sizeof(DrmColorLut) * degamma_lut_size))
+ return false;
+ }
+ if (!strcmp(property->name, "GAMMA_LUT")) {
+ if (!SetBlobProperty(
+ file_.GetPlatformFile(), crtc_id, DRM_MODE_OBJECT_CRTC,
+ crtc_props->props[i], property->name,
+ reinterpret_cast<unsigned char*>(gamma_blob_data.get()),
+ sizeof(DrmColorLut) * gamma_lut_size))
+ return false;
+ }
+ if (!strcmp(property->name, "CTM")) {
+ if (!SetBlobProperty(
+ file_.GetPlatformFile(), crtc_id, DRM_MODE_OBJECT_CRTC,
+ crtc_props->props[i], property->name,
+ reinterpret_cast<unsigned char*>(ctm_blob_data.get()),
+ sizeof(DrmColorCtm)))
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.h b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
index 3d4e8186df4..ef863c1e510 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
@@ -18,7 +18,6 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/overlay_transform.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
@@ -39,7 +38,7 @@ struct GammaRampRGBEntry;
// Wraps DRM calls into a nice interface. Used to provide different
// implementations of the DRM calls. For the actual implementation the DRM API
// would be called. In unit tests this interface would be stubbed.
-class OZONE_EXPORT DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
+class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
public:
typedef base::Callback<void(unsigned int /* frame */,
unsigned int /* seconds */,
@@ -164,6 +163,11 @@ class OZONE_EXPORT DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
// Set the gamma ramp for |crtc_id| to reflect the ramps in |lut|.
virtual bool SetGammaRamp(uint32_t crtc_id,
const std::vector<GammaRampRGBEntry>& lut);
+ virtual bool SetColorCorrection(
+ uint32_t crtc_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
virtual bool SetCapability(uint64_t capability, uint64_t value);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
index c4f3304931b..d05221dac81 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
@@ -101,6 +101,10 @@ scoped_refptr<DrmDevice> DrmDeviceManager::GetDrmDevice(
return it->second;
}
+scoped_refptr<DrmDevice> DrmDeviceManager::GetPrimaryDrmDevice() {
+ return primary_device_;
+}
+
const DrmDeviceVector& DrmDeviceManager::GetDrmDevices() const {
return devices_;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
index d415aad1fcb..a893f09e2ad 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
@@ -12,7 +12,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/ozone_export.h"
namespace base {
class FilePath;
@@ -28,7 +27,7 @@ typedef std::vector<scoped_refptr<DrmDevice>> DrmDeviceVector;
// Tracks the mapping between widgets and the DRM devices used to allocate
// buffers for the window represented by the widget.
-class OZONE_EXPORT DrmDeviceManager {
+class DrmDeviceManager {
public:
DrmDeviceManager(scoped_ptr<DrmDeviceGenerator> drm_device_generator);
~DrmDeviceManager();
@@ -48,6 +47,9 @@ class OZONE_EXPORT DrmDeviceManager {
// returns |primary_device_|.
scoped_refptr<DrmDevice> GetDrmDevice(gfx::AcceleratedWidget widget);
+ // Returns |primary_device_|.
+ scoped_refptr<DrmDevice> GetPrimaryDrmDevice();
+
const DrmDeviceVector& GetDrmDevices() const;
private:
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_display.cc b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
index 076cc59d356..6ff1033cffb 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -170,10 +170,21 @@ bool DrmDisplay::SetHDCPState(HDCPState state) {
GetContentProtectionValue(hdcp_property.get(), state));
}
-void DrmDisplay::SetGammaRamp(const std::vector<GammaRampRGBEntry>& lut) {
- if (!drm_->SetGammaRamp(crtc_, lut)) {
- LOG(ERROR) << "Failed to set gamma ramp for display: crtc_id = " << crtc_
- << " size = " << lut.size();
+void DrmDisplay::SetColorCorrection(
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ if (degamma_lut.empty()) {
+ if (!drm_->SetGammaRamp(crtc_, gamma_lut)) {
+ LOG(ERROR) << "Failed to set gamma ramp for display: crtc_id = " << crtc_
+ << " size = " << gamma_lut.size();
+ }
+ } else {
+ if (!drm_->SetColorCorrection(crtc_, degamma_lut, gamma_lut,
+ correction_matrix)) {
+ LOG(ERROR) << "Failed to set color correction for display: crtc_id = "
+ << crtc_;
+ }
}
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_display.h b/chromium/ui/ozone/platform/drm/gpu/drm_display.h
index 86021ae05bf..3742eda146c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_display.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_display.h
@@ -44,7 +44,9 @@ class DrmDisplay {
bool Configure(const drmModeModeInfo* mode, const gfx::Point& origin);
bool GetHDCPState(HDCPState* state);
bool SetHDCPState(HDCPState state);
- void SetGammaRamp(const std::vector<GammaRampRGBEntry>& lut);
+ void SetColorCorrection(const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
private:
ScreenManager* screen_manager_; // Not owned.
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index 402d3c04ca7..da787239ba2 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -99,6 +99,17 @@ std::vector<DisplaySnapshot_Params> DrmGpuDisplayManager::GetDisplays() {
return params_list;
}
+void DrmGpuDisplayManager::GetScanoutFormats(
+ gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats) {
+ const std::vector<uint32_t>& fourcc_formats =
+ drm_device_manager_->GetDrmDevice(widget)
+ ->plane_manager()
+ ->GetSupportedFormats();
+ for (auto& fourcc : fourcc_formats)
+ scanout_formats->push_back(GetBufferFormatFromFourCCFormat(fourcc));
+}
+
bool DrmGpuDisplayManager::TakeDisplayControl() {
const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices();
bool status = true;
@@ -184,16 +195,18 @@ bool DrmGpuDisplayManager::SetHDCPState(int64_t display_id, HDCPState state) {
return display->SetHDCPState(state);
}
-void DrmGpuDisplayManager::SetGammaRamp(
+void DrmGpuDisplayManager::SetColorCorrection(
int64_t display_id,
- const std::vector<GammaRampRGBEntry>& lut) {
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
DrmDisplay* display = FindDisplay(display_id);
if (!display) {
LOG(ERROR) << "There is no display with ID " << display_id;
return;
}
- display->SetGammaRamp(lut);
+ display->SetColorCorrection(degamma_lut, gamma_lut, correction_matrix);
}
DrmDisplay* DrmGpuDisplayManager::FindDisplay(int64_t display_id) {
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index 681a7cdec48..23e80e66f71 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -29,6 +29,11 @@ class DrmGpuDisplayManager {
// displays is refreshed.
std::vector<DisplaySnapshot_Params> GetDisplays();
+ // Returns all scanout formats for |widget| representing a particular display
+ // controller or default display controller for kNullAcceleratedWidget.
+ void GetScanoutFormats(gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats);
+
// Takes/releases the control of the DRM devices.
bool TakeDisplayControl();
void RelinquishDisplayControl();
@@ -40,6 +45,10 @@ class DrmGpuDisplayManager {
bool GetHDCPState(int64_t display_id, HDCPState* state);
bool SetHDCPState(int64_t display_id, HDCPState state);
void SetGammaRamp(int64_t id, const std::vector<GammaRampRGBEntry>& lut);
+ void SetColorCorrection(int64_t id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
private:
DrmDisplay* FindDisplay(int64_t display_id);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
index 1a66c814b44..9fb93b9e242 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -69,7 +69,6 @@ uint32_t FindOptimalBufferFormat(uint32_t original_format,
const gfx::Rect& window_bounds,
HardwareDisplayController* controller) {
bool force_primary_format = false;
- uint32_t optimal_format = original_format;
uint32_t z_order = plane_z_order;
// If Overlay completely covers primary and isn't transparent, try to find
// optimal format w.r.t primary plane. This guarantees that optimal format
@@ -85,17 +84,17 @@ uint32_t FindOptimalBufferFormat(uint32_t original_format,
#endif
}
- if (force_primary_format) {
- optimal_format = DRM_FORMAT_XRGB8888;
- } else {
- if (controller->IsFormatSupported(DRM_FORMAT_UYVY, z_order)) {
- optimal_format = DRM_FORMAT_UYVY;
- } else if (controller->IsFormatSupported(DRM_FORMAT_XRGB8888, z_order)) {
- optimal_format = DRM_FORMAT_XRGB8888;
- }
+ if (force_primary_format)
+ return DRM_FORMAT_XRGB8888;
+
+ // YUV is preferable format if supported.
+ if (controller->IsFormatSupported(DRM_FORMAT_UYVY, z_order)) {
+ return DRM_FORMAT_UYVY;
+ } else if (controller->IsFormatSupported(DRM_FORMAT_XRGB8888, z_order)) {
+ return DRM_FORMAT_XRGB8888;
}
- return optimal_format;
+ return original_format;
}
} // namespace
@@ -142,9 +141,10 @@ std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip(
gfx::Size scaled_buffer_size = GetScaledSize(
overlay.buffer_size, overlay.display_rect, overlay.crop_rect);
- scoped_refptr<ScanoutBuffer> buffer = GetBufferForPageFlipTest(
- drm, scaled_buffer_size, GetFourCCFormatForFramebuffer(overlay.format),
- buffer_generator_, &reusable_buffers);
+ uint32_t original_format = GetFourCCFormatForFramebuffer(overlay.format);
+ scoped_refptr<ScanoutBuffer> buffer =
+ GetBufferForPageFlipTest(drm, scaled_buffer_size, original_format,
+ buffer_generator_, &reusable_buffers);
DCHECK(buffer);
OverlayPlane plane(buffer, overlay.plane_z_order, overlay.transform,
@@ -153,6 +153,37 @@ std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip(
if (controller->TestPageFlip(test_list)) {
overlay.is_overlay_candidate = true;
+
+ // If size scaling is needed, find an optimal format.
+ if (overlay.plane_z_order && scaled_buffer_size != overlay.buffer_size) {
+ uint32_t optimal_format = FindOptimalBufferFormat(
+ original_format, overlay.plane_z_order, overlay.display_rect,
+ window_->bounds(), controller);
+
+ if (original_format != optimal_format) {
+ OverlayPlane original_plain = test_list.back();
+ test_list.pop_back();
+ scoped_refptr<ScanoutBuffer> optimal_buffer =
+ GetBufferForPageFlipTest(drm, scaled_buffer_size, optimal_format,
+ buffer_generator_, &reusable_buffers);
+ DCHECK(optimal_buffer);
+
+ OverlayPlane optimal_plane(optimal_buffer, overlay.plane_z_order,
+ overlay.transform, overlay.display_rect,
+ overlay.crop_rect);
+ test_list.push_back(optimal_plane);
+
+ // If test failed here, it means even though optimal_format is
+ // supported, platform cannot support it with current combination of
+ // layers. This is usually the case when optimal_format needs certain
+ // capabilites (i.e. conversion, scaling etc) and needed hardware
+ // resources might be already in use. Fall back to original format.
+ if (!controller->TestPageFlip(test_list)) {
+ test_list.pop_back();
+ test_list.push_back(original_plain);
+ }
+ }
+ }
} else {
// If test failed here, platform cannot support this configuration
// with current combination of layers. This is usually the case when this
@@ -166,7 +197,7 @@ std::vector<OverlayCheck_Params> DrmOverlayValidator::TestPageFlip(
}
}
- UpdateOverlayHintsCache(drm, test_list, &reusable_buffers);
+ UpdateOverlayHintsCache(test_list);
return validated_params;
}
@@ -208,7 +239,8 @@ OverlayPlaneList DrmOverlayValidator::PrepareBuffersForPageFlip(
target_size = original_size;
}
- if (original_size != target_size || original_format != target_format) {
+ // The size scaling piggybacks the format conversion.
+ if (original_size != target_size) {
scoped_refptr<ScanoutBuffer> processed_buffer =
plane.processing_callback.Run(target_size, target_format);
@@ -225,58 +257,26 @@ void DrmOverlayValidator::ClearCache() {
}
void DrmOverlayValidator::UpdateOverlayHintsCache(
- const scoped_refptr<DrmDevice>& drm,
- const OverlayPlaneList& plane_list,
- std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers) {
+ const OverlayPlaneList& plane_list) {
const auto& iter = overlay_hints_cache_.Get(plane_list);
if (iter != overlay_hints_cache_.end())
return;
- OverlayPlaneList preferred_format_test_list = plane_list;
- HardwareDisplayController* controller = window_->GetController();
+ OverlayPlaneList hints_plane_list = plane_list;
OverlayHintsList overlay_hints;
- for (auto& plane : preferred_format_test_list) {
- uint32_t original_format = plane.buffer->GetFramebufferPixelFormat();
-
- if (plane.z_order == 0) {
- overlay_hints.push_back(
- OverlayHints(original_format, true /* scaling */));
- continue;
- }
-
- uint32_t optimal_format = FindOptimalBufferFormat(
- original_format, plane.z_order, plane.display_bounds, window_->bounds(),
- controller);
-
- if (optimal_format != original_format) {
- scoped_refptr<ScanoutBuffer> original_buffer = plane.buffer;
- plane.buffer =
- GetBufferForPageFlipTest(drm, plane.buffer->GetSize(), optimal_format,
- buffer_generator_, reusable_buffers);
-
- if (!controller->TestPageFlip(preferred_format_test_list)) {
- // If test failed here, it means even though optimal_format is
- // supported, platform cannot support it with current combination of
- // layers. This is usually the case when optimal_format needs certain
- // capabilites (i.e. conversion, scaling etc) and needed hardware
- // resources might be already in use. Fall back to original format.
- optimal_format = original_format;
- plane.buffer = original_buffer;
- }
- }
-
+ for (auto& plane : hints_plane_list) {
+ uint32_t format = plane.buffer->GetFramebufferPixelFormat();
// TODO(kalyank): We always request scaling to be done by 3D engine, VPP
// etc. We should use them only if downscaling is needed and let display
// controller handle up-scaling on platforms which support it.
- overlay_hints.push_back(OverlayHints(optimal_format, true /* scaling */));
- }
+ overlay_hints.push_back(OverlayHints(format, true /* scaling */));
- // Make sure we dont hold reference to buffer when caching this plane list.
- for (auto& plane : preferred_format_test_list)
+ // Make sure we dont hold reference to buffer when caching this plane list.
plane.buffer = nullptr;
+ }
- DCHECK(preferred_format_test_list.size() == overlay_hints.size());
- overlay_hints_cache_.Put(preferred_format_test_list, overlay_hints);
+ DCHECK(hints_plane_list.size() == overlay_hints.size());
+ overlay_hints_cache_.Put(hints_plane_list, overlay_hints);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
index bf09c75a3b9..29b52351390 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -59,21 +59,14 @@ class DrmOverlayValidator {
using OverlayHintsList = std::vector<OverlayHints>;
- // Check if we can optimize format for reducing Display controller read
- // bandwidth for |plane_list| and cache the value.
- void UpdateOverlayHintsCache(
- const scoped_refptr<DrmDevice>& drm,
- const OverlayPlaneList& plane_list,
- std::vector<scoped_refptr<ScanoutBuffer>>* reusable_buffers);
+ // Update hints cache.
+ void UpdateOverlayHintsCache(const OverlayPlaneList& plane_list);
DrmWindow* window_; // Not owned.
ScanoutBufferGenerator* buffer_generator_; // Not owned.
// List of all configurations which have been validated.
- base::MRUCacheBase<OverlayPlaneList,
- OverlayHintsList,
- base::MRUCacheNullDeletor<OverlayHintsList>>
- overlay_hints_cache_;
+ base::MRUCache<OverlayPlaneList, OverlayHintsList> overlay_hints_cache_;
DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidator);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index f39d5f6af5d..66221599587 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -157,16 +157,16 @@ TEST_F(DrmOverlayValidatorTest, WindowWithNoController) {
window_->SetController(nullptr);
std::vector<ui::OverlayCheck_Params> validated_params =
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
- EXPECT_EQ(false, validated_params.front().is_overlay_candidate);
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.front().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
window_->SetController(controller);
}
TEST_F(DrmOverlayValidatorTest, DontPromoteMoreLayersThanAvailablePlanes) {
std::vector<ui::OverlayCheck_Params> validated_params =
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
- EXPECT_EQ(true, validated_params.front().is_overlay_candidate);
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_TRUE(validated_params.front().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
}
TEST_F(DrmOverlayValidatorTest, DontCollapseOverlayToPrimaryInFullScreen) {
@@ -179,8 +179,8 @@ TEST_F(DrmOverlayValidatorTest, DontCollapseOverlayToPrimaryInFullScreen) {
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
// Second candidate should be marked as Invalid as we have only one plane
// per CRTC.
- EXPECT_EQ(true, validated_params.front().is_overlay_candidate);
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_TRUE(validated_params.front().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
}
TEST_F(DrmOverlayValidatorTest, ClearCacheOnReset) {
@@ -202,6 +202,40 @@ TEST_F(DrmOverlayValidatorTest, ClearCacheOnReset) {
ui::OverlayPlaneList plane_list =
overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ EXPECT_EQ(DRM_FORMAT_XRGB8888,
+ plane_list.back().buffer->GetFramebufferPixelFormat());
+ // Check if ClearCache actually clears the cache.
+ overlay_validator_->ClearCache();
+ plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ // There should be no entry in cache for this configuration and should return
+ // default value of DRM_FORMAT_XRGB8888.
+ EXPECT_EQ(DRM_FORMAT_XRGB8888,
+ plane_list.back().buffer->GetFramebufferPixelFormat());
+}
+
+TEST_F(DrmOverlayValidatorTest, ClearCacheOnResetWithScaling) {
+ // This test checks if we invalidate cache when Reset is called.
+ gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
+ overlay_params_.back().buffer_size = overlay_rect_.size();
+ overlay_params_.back().display_rect = overlay_rect_;
+ overlay_params_.back().crop_rect = crop_rect;
+ plane_list_.back().display_bounds = overlay_rect_;
+ plane_list_.back().crop_rect = crop_rect;
+ std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_UYVY};
+
+ ui::FakePlaneInfo primary_plane_info(
+ 100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
+ ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
+ std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
+ plane_manager_->SetPlaneProperties(planes_info);
+ overlay_validator_->ClearCache();
+
+ overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
+
+ ui::OverlayPlaneList plane_list =
+ overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ // Scaling allows format conversion.
EXPECT_EQ(DRM_FORMAT_UYVY,
plane_list.back().buffer->GetFramebufferPixelFormat());
// Check if ClearCache actually clears the cache.
@@ -267,13 +301,47 @@ TEST_F(DrmOverlayValidatorTest, OptimalFormatForOverlayInFullScreen_YUV) {
#endif
}
+TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat) {
+ plane_manager_->ResetPlaneCount();
+ // This test checks for optimal format in case of non full screen video case.
+ overlay_params_.back().buffer_size = overlay_rect_.size();
+ overlay_params_.back().display_rect = overlay_rect_;
+ plane_list_.back().display_bounds = overlay_rect_;
+
+ std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_UYVY};
+ ui::FakePlaneInfo primary_plane_info(
+ 100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
+ ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
+ std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
+ plane_manager_->SetPlaneProperties(planes_info);
+ overlay_validator_->ClearCache();
+
+ std::vector<ui::OverlayCheck_Params> validated_params =
+ overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
+
+ for (const auto& param : validated_params)
+ EXPECT_TRUE(param.is_overlay_candidate);
+
+ EXPECT_EQ(3, plane_manager_->plane_count());
+
+ ui::OverlayPlaneList plane_list =
+ overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ EXPECT_EQ(DRM_FORMAT_XRGB8888,
+ plane_list.back().buffer->GetFramebufferPixelFormat());
+}
+
TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_YUV) {
plane_manager_->ResetPlaneCount();
// This test checks for optimal format in case of non full screen video case.
- // Prefer YUV as optimal format when Overlay supports it.
+ // Prefer YUV as optimal format when Overlay supports it and scaling is
+ // needed.
+ gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
overlay_params_.back().buffer_size = overlay_rect_.size();
overlay_params_.back().display_rect = overlay_rect_;
+ overlay_params_.back().crop_rect = crop_rect;
plane_list_.back().display_bounds = overlay_rect_;
+ plane_list_.back().crop_rect = crop_rect;
std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
DRM_FORMAT_UYVY};
@@ -288,7 +356,7 @@ TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_YUV) {
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
for (const auto& param : validated_params)
- EXPECT_EQ(true, param.is_overlay_candidate);
+ EXPECT_TRUE(param.is_overlay_candidate);
EXPECT_EQ(5, plane_manager_->plane_count());
@@ -323,7 +391,7 @@ TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_XRGB) {
plane_list.back().buffer->GetFramebufferPixelFormat());
EXPECT_EQ(3, plane_manager_->plane_count());
for (const auto& param : validated_params)
- EXPECT_EQ(true, param.is_overlay_candidate);
+ EXPECT_TRUE(param.is_overlay_candidate);
}
TEST_F(DrmOverlayValidatorTest, RejectYUVBuffersIfNotSupported) {
@@ -349,7 +417,7 @@ TEST_F(DrmOverlayValidatorTest, RejectYUVBuffersIfNotSupported) {
validated_params = overlay_validator_->TestPageFlip(validated_params,
ui::OverlayPlaneList());
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
}
TEST_F(DrmOverlayValidatorTest,
@@ -367,9 +435,12 @@ TEST_F(DrmOverlayValidatorTest,
new ui::MockScanoutBuffer(primary_rect_.size())));
EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode));
+ gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
overlay_params_.back().buffer_size = overlay_rect_.size();
overlay_params_.back().display_rect = overlay_rect_;
+ overlay_params_.back().crop_rect = crop_rect;
plane_list_.back().display_bounds = overlay_rect_;
+ plane_list_.back().crop_rect = crop_rect;
ui::FakePlaneInfo primary_crtc_primary_plane(100, 1 << 0, only_rgb_format);
ui::FakePlaneInfo primary_crtc_overlay(101, 1 << 0, xrgb_yuv_packed_formats);
@@ -389,10 +460,10 @@ TEST_F(DrmOverlayValidatorTest,
validated_params = overlay_validator_->TestPageFlip(validated_params,
ui::OverlayPlaneList());
- EXPECT_EQ(true, validated_params.back().is_overlay_candidate);
+ EXPECT_TRUE(validated_params.back().is_overlay_candidate);
- // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
- // should be picked as the optimal format.
+ // Both controllers have Overlay which support DRM_FORMAT_UYVY, and scaling is
+ // needed, hence this should be picked as the optimal format.
ui::OverlayPlaneList plane_list =
overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
EXPECT_EQ(DRM_FORMAT_UYVY,
@@ -408,7 +479,7 @@ TEST_F(DrmOverlayValidatorTest,
validated_params = overlay_validator_->TestPageFlip(validated_params,
ui::OverlayPlaneList());
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
// Check case where we dont have support for packed formats in primary
// display.
@@ -419,7 +490,7 @@ TEST_F(DrmOverlayValidatorTest,
validated_params = overlay_validator_->TestPageFlip(validated_params,
ui::OverlayPlaneList());
- EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
+ EXPECT_FALSE(validated_params.back().is_overlay_candidate);
controller->RemoveCrtc(drm_, kSecondaryCrtc);
}
@@ -458,17 +529,12 @@ TEST_F(DrmOverlayValidatorTest, OptimalFormatYUV_MirroredControllers) {
std::vector<ui::OverlayCheck_Params> validated_params =
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
- EXPECT_EQ(true, validated_params.back().is_overlay_candidate);
- // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
- // should be picked as the optimal format.
+ EXPECT_TRUE(validated_params.back().is_overlay_candidate);
ui::OverlayPlaneList plane_list =
overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
- EXPECT_EQ(DRM_FORMAT_UYVY,
+ EXPECT_EQ(DRM_FORMAT_XRGB8888,
plane_list.back().buffer->GetFramebufferPixelFormat());
- // DRM_FORMAT_XRGB8888 should be the preferred format when either of the
- // controllers dont support UYVY format.
-
// Check case where we dont have support for packed formats in Mirrored CRTC.
planes_info.back().allowed_formats = only_rgb_format;
plane_manager_->SetPlaneProperties(planes_info);
@@ -476,7 +542,7 @@ TEST_F(DrmOverlayValidatorTest, OptimalFormatYUV_MirroredControllers) {
validated_params =
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
- EXPECT_EQ(true, validated_params.back().is_overlay_candidate);
+ EXPECT_TRUE(validated_params.back().is_overlay_candidate);
plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
EXPECT_EQ(DRM_FORMAT_XRGB8888,
@@ -491,7 +557,7 @@ TEST_F(DrmOverlayValidatorTest, OptimalFormatYUV_MirroredControllers) {
validated_params =
overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
- EXPECT_EQ(true, validated_params.back().is_overlay_candidate);
+ EXPECT_TRUE(validated_params.back().is_overlay_candidate);
plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
EXPECT_EQ(DRM_FORMAT_XRGB8888,
@@ -502,9 +568,12 @@ TEST_F(DrmOverlayValidatorTest, OptimalFormatYUV_MirroredControllers) {
TEST_F(DrmOverlayValidatorTest, OptimizeOnlyIfProcessingCallbackPresent) {
// This test checks that we dont manipulate overlay buffers in case Processing
// callback is not present.
+ gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
overlay_params_.back().buffer_size = overlay_rect_.size();
overlay_params_.back().display_rect = overlay_rect_;
+ overlay_params_.back().crop_rect = crop_rect;
plane_list_.back().display_bounds = overlay_rect_;
+ plane_list_.back().crop_rect = crop_rect;
std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
DRM_FORMAT_UYVY};
@@ -519,6 +588,7 @@ TEST_F(DrmOverlayValidatorTest, OptimizeOnlyIfProcessingCallbackPresent) {
ui::OverlayPlaneList plane_list =
overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ // Scaling allows format conversion.
EXPECT_EQ(DRM_FORMAT_UYVY,
plane_list.back().buffer->GetFramebufferPixelFormat());
plane_list_.back().processing_callback.Reset();
@@ -531,9 +601,12 @@ TEST_F(DrmOverlayValidatorTest, OptimizeOnlyIfProcessingCallbackPresent) {
TEST_F(DrmOverlayValidatorTest, DontResetOriginalBufferIfProcessedIsInvalid) {
// This test checks that we dont manipulate overlay buffers in case Processing
// callback is not present.
+ gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
overlay_params_.back().buffer_size = overlay_rect_.size();
overlay_params_.back().display_rect = overlay_rect_;
+ overlay_params_.back().crop_rect = crop_rect;
plane_list_.back().display_bounds = overlay_rect_;
+ plane_list_.back().crop_rect = crop_rect;
std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
DRM_FORMAT_UYVY};
@@ -548,6 +621,7 @@ TEST_F(DrmOverlayValidatorTest, DontResetOriginalBufferIfProcessedIsInvalid) {
ui::OverlayPlaneList plane_list =
overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
+ // Scaling allows format conversion.
EXPECT_EQ(DRM_FORMAT_UYVY,
plane_list.back().buffer->GetFramebufferPixelFormat());
plane_list_.back().processing_callback = base::Bind(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index 63ec6f96db2..20952051b2f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -76,7 +76,10 @@ DrmThread::~DrmThread() {
}
void DrmThread::Start() {
- if (!StartWithOptions(base::Thread::Options(base::MessageLoop::TYPE_IO, 0)))
+ base::Thread::Options thread_options;
+ thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
+ thread_options.priority = base::ThreadPriority::DISPLAY;
+ if (!StartWithOptions(thread_options))
LOG(FATAL) << "Failed to create DRM thread";
}
@@ -106,6 +109,24 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
*buffer = GbmBuffer::CreateBuffer(gbm, format, size, usage);
}
+void DrmThread::CreateBufferFromFD(const gfx::Size& size,
+ gfx::BufferFormat format,
+ base::ScopedFD fd,
+ int32_t stride,
+ scoped_refptr<GbmBuffer>* buffer) {
+ scoped_refptr<GbmDevice> gbm =
+ static_cast<GbmDevice*>(device_manager_->GetPrimaryDrmDevice().get());
+ DCHECK(gbm);
+ *buffer =
+ GbmBuffer::CreateBufferFromFD(gbm, format, size, std::move(fd), stride);
+}
+
+void DrmThread::GetScanoutFormats(
+ gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats) {
+ display_manager_->GetScanoutFormats(widget, scanout_formats);
+}
+
void DrmThread::SchedulePageFlip(gfx::AcceleratedWidget widget,
const std::vector<OverlayPlane>& planes,
const SwapCompletionCallback& callback) {
@@ -221,9 +242,13 @@ void DrmThread::SetHDCPState(
callback.Run(display_id, display_manager_->SetHDCPState(display_id, state));
}
-void DrmThread::SetGammaRamp(int64_t id,
- const std::vector<GammaRampRGBEntry>& lut) {
- display_manager_->SetGammaRamp(id, lut);
+void DrmThread::SetColorCorrection(
+ int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ display_manager_->SetColorCorrection(display_id, degamma_lut, gamma_lut,
+ correction_matrix);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
index 130b0dc4e33..49e55865072 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -58,7 +58,14 @@ class DrmThread : public base::Thread {
gfx::BufferFormat format,
gfx::BufferUsage usage,
scoped_refptr<GbmBuffer>* buffer);
-
+ void CreateBufferFromFD(const gfx::Size& size,
+ gfx::BufferFormat format,
+ base::ScopedFD fd,
+ int stride,
+ scoped_refptr<GbmBuffer>* buffer);
+
+ void GetScanoutFormats(gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats);
void SchedulePageFlip(gfx::AcceleratedWidget widget,
const std::vector<OverlayPlane>& planes,
const SwapCompletionCallback& callback);
@@ -102,7 +109,10 @@ class DrmThread : public base::Thread {
void SetHDCPState(int64_t display_id,
HDCPState state,
const base::Callback<void(int64_t, bool)>& callback);
- void SetGammaRamp(int64_t id, const std::vector<GammaRampRGBEntry>& lut);
+ void SetColorCorrection(int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
// base::Thread:
void Init() override;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
index f0647eb7085..92baacafd05 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
@@ -13,11 +13,14 @@
namespace ui {
-DrmThreadMessageProxy::DrmThreadMessageProxy(DrmThread* drm_thread)
- : drm_thread_(drm_thread), weak_ptr_factory_(this) {}
+DrmThreadMessageProxy::DrmThreadMessageProxy() : weak_ptr_factory_(this) {}
DrmThreadMessageProxy::~DrmThreadMessageProxy() {}
+void DrmThreadMessageProxy::SetDrmThread(DrmThread* thread) {
+ drm_thread_ = thread;
+}
+
void DrmThreadMessageProxy::OnFilterAdded(IPC::Sender* sender) {
sender_ = sender;
@@ -51,10 +54,10 @@ bool DrmThreadMessageProxy::OnMessageReceived(const IPC::Message& message) {
OnRemoveGraphicsDevice)
IPC_MESSAGE_HANDLER(OzoneGpuMsg_GetHDCPState, OnGetHDCPState)
IPC_MESSAGE_HANDLER(OzoneGpuMsg_SetHDCPState, OnSetHDCPState)
- IPC_MESSAGE_HANDLER(OzoneGpuMsg_SetGammaRamp, OnSetGammaRamp);
+ IPC_MESSAGE_HANDLER(OzoneGpuMsg_SetColorCorrection, OnSetColorCorrection)
IPC_MESSAGE_HANDLER(OzoneGpuMsg_CheckOverlayCapabilities,
OnCheckOverlayCapabilities)
- IPC_MESSAGE_UNHANDLED(handled = false);
+ IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -209,13 +212,16 @@ void DrmThreadMessageProxy::OnSetHDCPState(int64_t display_id,
display_id, state, CreateSafeCallback(callback)));
}
-void DrmThreadMessageProxy::OnSetGammaRamp(
+void DrmThreadMessageProxy::OnSetColorCorrection(
int64_t id,
- const std::vector<GammaRampRGBEntry>& lut) {
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
DCHECK(drm_thread_->IsRunning());
drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::SetGammaRamp,
- base::Unretained(drm_thread_), id, lut));
+ FROM_HERE,
+ base::Bind(&DrmThread::SetColorCorrection, base::Unretained(drm_thread_),
+ id, degamma_lut, gamma_lut, correction_matrix));
}
void DrmThreadMessageProxy::OnCheckOverlayCapabilitiesCallback(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
index 6aa90627bdb..1e031516f27 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
@@ -13,6 +13,7 @@
#include "ui/display/types/display_constants.h"
#include "ui/display/types/gamma_ramp_rgb_entry.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
namespace base {
struct FileDescriptor;
@@ -31,9 +32,13 @@ struct DisplayMode_Params;
struct DisplaySnapshot_Params;
struct OverlayCheck_Params;
-class DrmThreadMessageProxy : public IPC::MessageFilter {
+class DrmThreadMessageProxy : public IPC::MessageFilter,
+ public InterThreadMessagingProxy {
public:
- DrmThreadMessageProxy(DrmThread* drm_thread);
+ DrmThreadMessageProxy();
+
+ // InterThreadMessagingProxy.
+ void SetDrmThread(DrmThread* thread) override;
// IPC::MessageFilter:
void OnFilterAdded(IPC::Sender* sender) override;
@@ -68,7 +73,10 @@ class DrmThreadMessageProxy : public IPC::MessageFilter {
void OnRemoveGraphicsDevice(const base::FilePath& path);
void OnGetHDCPState(int64_t display_id);
void OnSetHDCPState(int64_t display_id, HDCPState state);
- void OnSetGammaRamp(int64_t id, const std::vector<GammaRampRGBEntry>& lut);
+ void OnSetColorCorrection(int64_t id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
void OnCheckOverlayCapabilitiesCallback(
gfx::AcceleratedWidget widget,
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index b46e11624ab..208c895e6f0 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -16,9 +16,9 @@ DrmThreadProxy::DrmThreadProxy() {}
DrmThreadProxy::~DrmThreadProxy() {}
-scoped_refptr<DrmThreadMessageProxy>
-DrmThreadProxy::CreateDrmThreadMessageProxy() {
- return make_scoped_refptr(new DrmThreadMessageProxy(&drm_thread_));
+void DrmThreadProxy::BindThreadIntoMessagingProxy(
+ InterThreadMessagingProxy* messaging_proxy) {
+ messaging_proxy->SetDrmThread(&drm_thread_);
}
scoped_ptr<DrmWindowProxy> DrmThreadProxy::CreateDrmWindowProxy(
@@ -39,4 +39,26 @@ scoped_refptr<GbmBuffer> DrmThreadProxy::CreateBuffer(
return buffer;
}
+scoped_refptr<GbmBuffer> DrmThreadProxy::CreateBufferFromFD(
+ const gfx::Size& size,
+ gfx::BufferFormat format,
+ base::ScopedFD fd,
+ int stride) {
+ scoped_refptr<GbmBuffer> buffer;
+ PostSyncTask(
+ drm_thread_.task_runner(),
+ base::Bind(&DrmThread::CreateBufferFromFD, base::Unretained(&drm_thread_),
+ size, format, base::Passed(&fd), stride, &buffer));
+ return buffer;
+}
+
+void DrmThreadProxy::GetScanoutFormats(
+ gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats) {
+ PostSyncTask(
+ drm_thread_.task_runner(),
+ base::Bind(&DrmThread::GetScanoutFormats, base::Unretained(&drm_thread_),
+ widget, scanout_formats));
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index 05e4b530039..213e0527bf1 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -12,8 +12,8 @@
namespace ui {
-class DrmThreadMessageProxy;
class DrmWindowProxy;
+class InterThreadMessagingProxy;
// Mediates the communication between GPU main/IO threads and the DRM thread. It
// serves proxy objects that are safe to call on the GPU threads. The proxy
@@ -23,7 +23,7 @@ class DrmThreadProxy {
explicit DrmThreadProxy();
~DrmThreadProxy();
- scoped_refptr<DrmThreadMessageProxy> CreateDrmThreadMessageProxy();
+ void BindThreadIntoMessagingProxy(InterThreadMessagingProxy* messaging_proxy);
scoped_ptr<DrmWindowProxy> CreateDrmWindowProxy(
gfx::AcceleratedWidget widget);
@@ -33,6 +33,14 @@ class DrmThreadProxy {
gfx::BufferFormat format,
gfx::BufferUsage usage);
+ scoped_refptr<GbmBuffer> CreateBufferFromFD(const gfx::Size& size,
+ gfx::BufferFormat format,
+ base::ScopedFD fd,
+ int stride);
+
+ void GetScanoutFormats(gfx::AcceleratedWidget widget,
+ std::vector<gfx::BufferFormat>* scanout_formats);
+
private:
DrmThread drm_thread_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.h b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
index f5dad7c28da..59407a57043 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
@@ -14,7 +14,6 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/swap_result.h"
#include "ui/gfx/vsync_provider.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "ui/ozone/public/surface_ozone_egl.h"
@@ -46,7 +45,7 @@ class ScreenManager;
//
// If there's no display whose bounds match the window's, the window is
// disconnected and its contents will not be visible to the user.
-class OZONE_EXPORT DrmWindow {
+class DrmWindow {
public:
DrmWindow(gfx::AcceleratedWidget widget,
DrmDeviceManager* device_manager,
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
index ccda65bde6e..25d89dc464d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -34,9 +34,9 @@ const uint32_t kDefaultCrtc = 1;
const uint32_t kDefaultConnector = 2;
const int kDefaultCursorSize = 64;
-std::vector<skia::RefPtr<SkSurface>> GetCursorBuffers(
+std::vector<sk_sp<SkSurface>> GetCursorBuffers(
const scoped_refptr<ui::MockDrmDevice> drm) {
- std::vector<skia::RefPtr<SkSurface>> cursor_buffers;
+ std::vector<sk_sp<SkSurface>> cursor_buffers;
for (const auto& cursor_buffer : drm->buffers()) {
if (cursor_buffer->width() == kDefaultCursorSize &&
cursor_buffer->height() == kDefaultCursorSize) {
@@ -120,7 +120,7 @@ TEST_F(DrmWindowTest, SetCursorImage) {
gfx::Point(4, 2), 0);
SkBitmap cursor;
- std::vector<skia::RefPtr<SkSurface>> cursor_buffers = GetCursorBuffers(drm_);
+ std::vector<sk_sp<SkSurface>> cursor_buffers = GetCursorBuffers(drm_);
EXPECT_EQ(2u, cursor_buffers.size());
// Buffers 1 is the cursor backbuffer we just drew in.
diff --git a/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.cc b/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.cc
index 3695383e53e..2e9a2a732d8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.cc
@@ -18,6 +18,8 @@ FakePlaneInfo::FakePlaneInfo(uint32_t plane_id,
const std::vector<uint32_t>& formats)
: id(plane_id), allowed_crtc_mask(crtc_mask), allowed_formats(formats) {}
+FakePlaneInfo::FakePlaneInfo(const FakePlaneInfo& other) = default;
+
FakePlaneInfo::~FakePlaneInfo() {}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.h b/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.h
index d9c9ea88987..79265ebe534 100644
--- a/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.h
+++ b/chromium/ui/ozone/platform/drm/gpu/fake_plane_info.h
@@ -18,6 +18,7 @@ struct FakePlaneInfo {
FakePlaneInfo(uint32_t plane_id,
uint32_t crtc_mask,
const std::vector<uint32_t>& formats);
+ FakePlaneInfo(const FakePlaneInfo& other);
~FakePlaneInfo();
uint32_t id;
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index 336045dc8db..437ceabc0dc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -20,7 +20,7 @@
#include "ui/ozone/platform/drm/gpu/gbm_device.h"
#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
#include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
namespace ui {
@@ -28,14 +28,28 @@ namespace ui {
GbmBuffer::GbmBuffer(const scoped_refptr<GbmDevice>& gbm,
gbm_bo* bo,
gfx::BufferFormat format,
- gfx::BufferUsage usage)
- : GbmBufferBase(gbm, bo, format, usage), format_(format), usage_(usage) {}
+ gfx::BufferUsage usage,
+ base::ScopedFD fd,
+ int stride)
+ : GbmBufferBase(gbm, bo, format, usage),
+ format_(format),
+ usage_(usage),
+ fd_(std::move(fd)),
+ stride_(stride) {}
GbmBuffer::~GbmBuffer() {
if (bo())
gbm_bo_destroy(bo());
}
+int GbmBuffer::GetFd() const {
+ return fd_.get();
+}
+
+int GbmBuffer::GetStride() const {
+ return stride_;
+}
+
// static
scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer(
const scoped_refptr<GbmDevice>& gbm,
@@ -44,44 +58,61 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBuffer(
gfx::BufferUsage usage) {
TRACE_EVENT2("drm", "GbmBuffer::CreateBuffer", "device",
gbm->device_path().value(), "size", size.ToString());
- bool use_scanout = (usage == gfx::BufferUsage::SCANOUT);
+
unsigned flags = 0;
- // GBM_BO_USE_SCANOUT is the hint of x-tiling.
- if (use_scanout)
- flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
+ switch (usage) {
+ case gfx::BufferUsage::GPU_READ:
+ break;
+ case gfx::BufferUsage::SCANOUT:
+ flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
+ break;
+ case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
+ case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
+ flags = GBM_BO_USE_LINEAR;
+ break;
+ }
+
gbm_bo* bo = gbm_bo_create(gbm->device(), size.width(), size.height(),
GetFourCCFormatFromBufferFormat(format), flags);
if (!bo)
return nullptr;
- scoped_refptr<GbmBuffer> buffer(new GbmBuffer(gbm, bo, format, usage));
- if (use_scanout && !buffer->GetFramebufferId())
+ // The fd returned by gbm_bo_get_fd is not ref-counted and need to be
+ // kept open for the lifetime of the buffer.
+ base::ScopedFD fd(gbm_bo_get_fd(bo));
+ if (!fd.is_valid()) {
+ PLOG(ERROR) << "Failed to export buffer to dma_buf";
+ gbm_bo_destroy(bo);
+ return nullptr;
+ }
+
+ scoped_refptr<GbmBuffer> buffer(new GbmBuffer(
+ gbm, bo, format, usage, std::move(fd), gbm_bo_get_stride(bo)));
+ if (usage == gfx::BufferUsage::SCANOUT && !buffer->GetFramebufferId())
return nullptr;
return buffer;
}
-GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager)
- : surface_manager_(surface_manager) {}
+// static
+scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFD(
+ const scoped_refptr<GbmDevice>& gbm,
+ gfx::BufferFormat format,
+ const gfx::Size& size,
+ base::ScopedFD fd,
+ int stride) {
+ TRACE_EVENT2("drm", "GbmBuffer::CreateBufferFromFD", "device",
+ gbm->device_path().value(), "size", size.ToString());
-void GbmPixmap::Initialize(base::ScopedFD dma_buf, int dma_buf_pitch) {
- dma_buf_ = std::move(dma_buf);
- dma_buf_pitch_ = dma_buf_pitch;
+ // TODO(reveman): Use gbm_bo_import after making buffers survive
+ // GPU process crashes. crbug.com/597932
+ return make_scoped_refptr(new GbmBuffer(
+ gbm, nullptr, format, gfx::BufferUsage::GPU_READ, std::move(fd), stride));
}
-bool GbmPixmap::InitializeFromBuffer(const scoped_refptr<GbmBuffer>& buffer) {
- // We want to use the GBM API because it's going to call into libdrm
- // which might do some optimizations on buffer allocation,
- // especially when sharing buffers via DMABUF.
- base::ScopedFD dma_buf(gbm_bo_get_fd(buffer->bo()));
- if (!dma_buf.is_valid()) {
- PLOG(ERROR) << "Failed to export buffer to dma_buf";
- return false;
- }
- Initialize(std::move(dma_buf), gbm_bo_get_stride(buffer->bo()));
- buffer_ = buffer;
- return true;
-}
+GbmPixmap::GbmPixmap(GbmSurfaceFactory* surface_manager,
+ const scoped_refptr<GbmBuffer>& buffer)
+ : surface_manager_(surface_manager), buffer_(buffer) {}
void GbmPixmap::SetProcessingCallback(
const ProcessingCallback& processing_callback) {
@@ -92,14 +123,14 @@ void GbmPixmap::SetProcessingCallback(
gfx::NativePixmapHandle GbmPixmap::ExportHandle() {
gfx::NativePixmapHandle handle;
- base::ScopedFD dmabuf_fd(HANDLE_EINTR(dup(dma_buf_.get())));
- if (!dmabuf_fd.is_valid()) {
+ base::ScopedFD fd(HANDLE_EINTR(dup(buffer_->GetFd())));
+ if (!fd.is_valid()) {
PLOG(ERROR) << "dup";
return handle;
}
- handle.fd = base::FileDescriptor(dmabuf_fd.release(), true /* auto_close */);
- handle.stride = dma_buf_pitch_;
+ handle.fd = base::FileDescriptor(fd.release(), true /* auto_close */);
+ handle.stride = buffer_->GetStride();
return handle;
}
@@ -111,11 +142,11 @@ void* GbmPixmap::GetEGLClientBuffer() const {
}
int GbmPixmap::GetDmaBufFd() const {
- return dma_buf_.get();
+ return buffer_->GetFd();
}
int GbmPixmap::GetDmaBufPitch() const {
- return dma_buf_pitch_;
+ return buffer_->GetStride();
}
gfx::BufferFormat GbmPixmap::GetBufferFormat() const {
@@ -131,16 +162,14 @@ bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect) {
- // TODO(reveman): Add support for imported buffers. crbug.com/541558
- if (!buffer_) {
- PLOG(ERROR) << "ScheduleOverlayPlane requires a buffer.";
- return false;
- }
-
DCHECK(buffer_->GetUsage() == gfx::BufferUsage::SCANOUT);
+ OverlayPlane::ProcessBufferCallback processing_callback;
+ if (!processing_callback_.is_null())
+ processing_callback = base::Bind(&GbmPixmap::ProcessBuffer, this);
+
surface_manager_->GetSurface(widget)->QueueOverlayPlane(
OverlayPlane(buffer_, plane_z_order, plane_transform, display_bounds,
- crop_rect, base::Bind(&GbmPixmap::ProcessBuffer, this)));
+ crop_rect, processing_callback));
return true;
}
@@ -158,13 +187,13 @@ scoped_refptr<ScanoutBuffer> GbmPixmap::ProcessBuffer(const gfx::Size& size,
scoped_refptr<GbmBuffer> buffer = GbmBuffer::CreateBuffer(
buffer_->drm().get(), buffer_format, size, buffer_->GetUsage());
+ if (!buffer)
+ return nullptr;
// ProcessBuffer is called on DrmThread. We could have used
// CreateNativePixmap to initialize the pixmap, however it posts a
// synchronous task to DrmThread resulting in a deadlock.
- processed_pixmap_ = new GbmPixmap(surface_manager_);
- if (!processed_pixmap_->InitializeFromBuffer(buffer))
- return nullptr;
+ processed_pixmap_ = new GbmPixmap(surface_manager_, buffer);
}
DCHECK(!processing_callback_.is_null());
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.h b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.h
index ff42e1b841a..b62ccfcc1d8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -26,27 +26,39 @@ class GbmBuffer : public GbmBufferBase {
gfx::BufferFormat format,
const gfx::Size& size,
gfx::BufferUsage usage);
+ static scoped_refptr<GbmBuffer> CreateBufferFromFD(
+ const scoped_refptr<GbmDevice>& gbm,
+ gfx::BufferFormat format,
+ const gfx::Size& size,
+ base::ScopedFD fd,
+ int stride);
gfx::BufferFormat GetFormat() const { return format_; }
gfx::BufferUsage GetUsage() const { return usage_; }
+ int GetFd() const;
+ int GetStride() const;
private:
GbmBuffer(const scoped_refptr<GbmDevice>& gbm,
gbm_bo* bo,
gfx::BufferFormat format,
- gfx::BufferUsage usage);
+ gfx::BufferUsage usage,
+ base::ScopedFD fd,
+ int stride);
~GbmBuffer() override;
gfx::BufferFormat format_;
gfx::BufferUsage usage_;
+ base::ScopedFD fd_;
+ int stride_;
DISALLOW_COPY_AND_ASSIGN(GbmBuffer);
};
class GbmPixmap : public NativePixmap {
public:
- explicit GbmPixmap(GbmSurfaceFactory* surface_manager);
- void Initialize(base::ScopedFD dma_buf, int dma_buf_pitch);
- bool InitializeFromBuffer(const scoped_refptr<GbmBuffer>& buffer);
+ GbmPixmap(GbmSurfaceFactory* surface_manager,
+ const scoped_refptr<GbmBuffer>& buffer);
+
void SetProcessingCallback(
const ProcessingCallback& processing_callback) override;
@@ -70,11 +82,8 @@ class GbmPixmap : public NativePixmap {
scoped_refptr<ScanoutBuffer> ProcessBuffer(const gfx::Size& size,
uint32_t format);
- scoped_refptr<GbmBuffer> buffer_;
- base::ScopedFD dma_buf_;
- int dma_buf_pitch_ = -1;
-
GbmSurfaceFactory* surface_manager_;
+ scoped_refptr<GbmBuffer> buffer_;
// OverlayValidator can request scaling or format conversions as needed for
// this Pixmap. This holds the processed buffer.
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index fb9157bc9a8..32762ee73de 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -10,6 +10,7 @@
#include "build/build_config.h"
#include "third_party/khronos/EGL/egl.h"
#include "ui/ozone/common/egl_util.h"
+#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_buffer.h"
@@ -53,28 +54,6 @@ intptr_t GbmSurfaceFactory::GetNativeDisplay() {
return EGL_DEFAULT_DISPLAY;
}
-const int32_t* GbmSurfaceFactory::GetEGLSurfaceProperties(
- const int32_t* desired_list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- static const int32_t kConfigAttribs[] = {EGL_BUFFER_SIZE,
- 32,
- EGL_ALPHA_SIZE,
- 8,
- EGL_BLUE_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_RED_SIZE,
- 8,
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT,
- EGL_NONE};
-
- return kConfigAttribs;
-}
-
bool GbmSurfaceFactory::LoadEGLGLES2Bindings(
AddGLLibraryCallback add_gl_library,
SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
@@ -103,6 +82,13 @@ GbmSurfaceFactory::CreateSurfacelessEGLSurfaceForWidget(
new GbmSurfaceless(drm_thread_->CreateDrmWindowProxy(widget), this));
}
+std::vector<gfx::BufferFormat> GbmSurfaceFactory::GetScanoutFormats(
+ gfx::AcceleratedWidget widget) {
+ std::vector<gfx::BufferFormat> scanout_formats;
+ drm_thread_->GetScanoutFormats(widget, &scanout_formats);
+ return scanout_formats;
+}
+
scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
gfx::AcceleratedWidget widget,
gfx::Size size,
@@ -110,7 +96,7 @@ scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
gfx::BufferUsage usage) {
#if !defined(OS_CHROMEOS)
// Support for memory mapping accelerated buffers requires some
- // CrOS-specific patches (using vgem).
+ // CrOS-specific patches (using dma-buf mmap API).
DCHECK(gfx::BufferUsage::SCANOUT == usage);
#endif
@@ -119,18 +105,19 @@ scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
if (!buffer.get())
return nullptr;
- scoped_refptr<GbmPixmap> pixmap(new GbmPixmap(this));
- if (!pixmap->InitializeFromBuffer(buffer))
- return nullptr;
-
- return pixmap;
+ return make_scoped_refptr(new GbmPixmap(this, buffer));
}
scoped_refptr<ui::NativePixmap> GbmSurfaceFactory::CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) {
- scoped_refptr<GbmPixmap> pixmap(new GbmPixmap(this));
- pixmap->Initialize(base::ScopedFD(handle.fd.fd), handle.stride);
- return pixmap;
+ scoped_refptr<GbmBuffer> buffer = drm_thread_->CreateBufferFromFD(
+ size, format, base::ScopedFD(handle.fd.fd), handle.stride);
+ if (!buffer)
+ return nullptr;
+
+ return make_scoped_refptr(new GbmPixmap(this, buffer));
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
index 5beb886865d..0fb582466d0 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <vector>
#include "base/macros.h"
#include "base/threading/thread_checker.h"
@@ -21,7 +22,7 @@ class GbmSurfaceless;
class GbmSurfaceFactory : public SurfaceFactoryOzone {
public:
- GbmSurfaceFactory(DrmThreadProxy* drm_thread);
+ explicit GbmSurfaceFactory(DrmThreadProxy* drm_thread);
~GbmSurfaceFactory() override;
void RegisterSurface(gfx::AcceleratedWidget widget, GbmSurfaceless* surface);
@@ -30,7 +31,8 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
// SurfaceFactoryOzone:
intptr_t GetNativeDisplay() override;
- const int32_t* GetEGLSurfaceProperties(const int32_t* desired_list) override;
+ std::vector<gfx::BufferFormat> GetScanoutFormats(
+ gfx::AcceleratedWidget widget) override;
bool LoadEGLGLES2Bindings(
AddGLLibraryCallback add_gl_library,
SetGLGetProcAddressProcCallback set_gl_get_proc_address) override;
@@ -46,6 +48,8 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
gfx::BufferFormat format,
gfx::BufferUsage usage) override;
scoped_refptr<NativePixmap> CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) override;
private:
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 500d74c4cdb..f5512b757ae 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -6,6 +6,9 @@
#include <utility>
+#include "base/trace_event/trace_event.h"
+#include "third_party/khronos/EGL/egl.h"
+#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
@@ -44,6 +47,7 @@ bool GbmSurfaceless::OnSwapBuffers() {
void GbmSurfaceless::OnSwapBuffersAsync(
const SwapCompletionCallback& callback) {
+ TRACE_EVENT0("drm", "GbmSurfaceless::OnSwapBuffersAsync");
window_->SchedulePageFlip(planes_, callback);
planes_.clear();
}
@@ -56,4 +60,24 @@ bool GbmSurfaceless::IsUniversalDisplayLinkDevice() {
return planes_.empty() ? false : planes_[0].buffer->RequiresGlFinish();
}
+void* /* EGLConfig */ GbmSurfaceless::GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) {
+ EGLint config_attribs[] = {EGL_BUFFER_SIZE,
+ 32,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_RED_SIZE,
+ 8,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_DONT_CARE,
+ EGL_NONE};
+ return ChooseEGLConfig(egl, config_attribs);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
index 91930020d87..306ef11368c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
@@ -40,6 +40,8 @@ class GbmSurfaceless : public SurfaceOzoneEGL {
void OnSwapBuffersAsync(const SwapCompletionCallback& callback) override;
scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
bool IsUniversalDisplayLinkDevice() override;
+ void* /* EGLConfig */ GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) override;
protected:
scoped_ptr<DrmWindowProxy> window_;
@@ -48,6 +50,7 @@ class GbmSurfaceless : public SurfaceOzoneEGL {
std::vector<OverlayPlane> planes_;
+ private:
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceless);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 220745235e9..8ec577d1f1d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -18,7 +18,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "ui/gfx/swap_result.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
@@ -86,7 +85,7 @@ class DrmDevice;
// only a subset of connectors can be active independently, showing different
// framebuffers. Though, in this case, it would be possible to have all
// connectors active if some use the same CRTC to mirror the display.
-class OZONE_EXPORT HardwareDisplayController {
+class HardwareDisplayController {
typedef base::Callback<void(gfx::SwapResult)> PageFlipCallback;
public:
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
index 798d2f36c5c..729df45bd61 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/macros.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
namespace gfx {
@@ -22,7 +21,7 @@ namespace ui {
class DrmDevice;
-class OZONE_EXPORT HardwareDisplayPlane {
+class HardwareDisplayPlane {
public:
enum Type { kDummy, kPrimary, kOverlay, kCursor };
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index c4cc7e05e87..37ce65322b7 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -36,6 +36,9 @@ HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(uint32_t crtc_id,
: crtc_id(crtc_id), framebuffer(framebuffer), crtc(crtc) {
}
+HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(
+ const PageFlipInfo& other) = default;
+
HardwareDisplayPlaneList::PageFlipInfo::~PageFlipInfo() {
}
@@ -231,7 +234,6 @@ bool HardwareDisplayPlaneManager::AssignOverlayPlanes(
size_t plane_idx = 0;
HardwareDisplayPlane* primary_plane = nullptr;
gfx::Rect primary_display_bounds;
- gfx::Rect primary_src_rect;
uint32_t primary_format;
for (const auto& plane : overlay_list) {
HardwareDisplayPlane* hw_plane =
@@ -269,15 +271,13 @@ bool HardwareDisplayPlaneManager::AssignOverlayPlanes(
// TODO(kalyank): Check if we can move this optimization to
// DrmOverlayCandidatesHost.
if (!needs_blending && primary_format == fourcc_format &&
- primary_display_bounds == plane.display_bounds &&
- fixed_point_rect == primary_src_rect) {
+ primary_display_bounds == plane.display_bounds) {
ResetCurrentPlaneList(plane_list);
hw_plane = primary_plane;
}
} else {
primary_plane = hw_plane;
primary_display_bounds = plane.display_bounds;
- primary_src_rect = fixed_point_rect;
primary_format = fourcc_format;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index e9b04ec06b0..3efdd8b0304 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
@@ -28,7 +27,7 @@ class DrmDevice;
// This contains the list of planes controlled by one HDC on a given DRM fd.
// It is owned by the HDC and filled by the CrtcController.
-struct OZONE_EXPORT HardwareDisplayPlaneList {
+struct HardwareDisplayPlaneList {
HardwareDisplayPlaneList();
~HardwareDisplayPlaneList();
@@ -39,6 +38,7 @@ struct OZONE_EXPORT HardwareDisplayPlaneList {
struct PageFlipInfo {
PageFlipInfo(uint32_t crtc_id, uint32_t framebuffer, CrtcController* crtc);
+ PageFlipInfo(const PageFlipInfo& other);
~PageFlipInfo();
uint32_t crtc_id;
@@ -67,7 +67,7 @@ struct OZONE_EXPORT HardwareDisplayPlaneList {
#endif // defined(USE_DRM_ATOMIC)
};
-class OZONE_EXPORT HardwareDisplayPlaneManager {
+class HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManager();
virtual ~HardwareDisplayPlaneManager();
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
index 3fc911c50d1..d9512eb8727 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
@@ -8,13 +8,11 @@
#include <stdint.h>
#include "base/macros.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
namespace ui {
-class OZONE_EXPORT HardwareDisplayPlaneManagerAtomic
- : public HardwareDisplayPlaneManager {
+class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManagerAtomic();
~HardwareDisplayPlaneManagerAtomic() override;
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
index c716187e111..56c55766e0f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
@@ -8,13 +8,11 @@
#include <stdint.h>
#include "base/macros.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
namespace ui {
-class OZONE_EXPORT HardwareDisplayPlaneManagerLegacy
- : public HardwareDisplayPlaneManager {
+class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManagerLegacy();
~HardwareDisplayPlaneManagerLegacy() override;
diff --git a/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.cc
new file mode 100644
index 00000000000..fd909c29a8b
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.cc
@@ -0,0 +1,11 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
+
+namespace ui {
+
+InterThreadMessagingProxy::~InterThreadMessagingProxy() {}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h b/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h
new file mode 100644
index 00000000000..b0fe234c415
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_INTER_THREAD_MESSAGING_PROXY_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_INTER_THREAD_MESSAGING_PROXY_H_
+
+#include "base/macros.h"
+
+namespace ui {
+
+class DrmThread;
+
+class InterThreadMessagingProxy {
+ public:
+ virtual ~InterThreadMessagingProxy();
+ virtual void SetDrmThread(DrmThread* thread) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_GPU_INTER_THREAD_MESSAGING_PROXY_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index 8dd6af0a7e8..9ab4e237ab2 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -185,8 +185,7 @@ bool MockDrmDevice::CreateDumbBuffer(const SkImageInfo& info,
*handle = allocate_buffer_count_++;
*stride = info.minRowBytes();
void* pixels = new char[info.getSafeSize(*stride)];
- buffers_.push_back(
- skia::AdoptRef(SkSurface::NewRasterDirect(info, pixels, *stride)));
+ buffers_.push_back(SkSurface::MakeRasterDirect(info, pixels, *stride));
buffers_[*handle]->getCanvas()->clear(SK_ColorBLACK);
return true;
@@ -196,7 +195,7 @@ bool MockDrmDevice::DestroyDumbBuffer(uint32_t handle) {
if (handle >= buffers_.size() || !buffers_[handle])
return false;
- buffers_[handle].clear();
+ buffers_[handle].reset();
return true;
}
@@ -228,6 +227,14 @@ bool MockDrmDevice::SetGammaRamp(uint32_t crtc_id,
return true;
}
+bool MockDrmDevice::SetColorCorrection(
+ uint32_t crtc_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ return true;
+}
+
bool MockDrmDevice::SetCapability(uint64_t capability, uint64_t value) {
return false;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
index 48cd37e1d18..13506eee1d3 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -50,9 +50,7 @@ class MockDrmDevice : public DrmDevice {
uint32_t current_framebuffer() const { return current_framebuffer_; }
- const std::vector<skia::RefPtr<SkSurface>> buffers() const {
- return buffers_;
- }
+ const std::vector<sk_sp<SkSurface>> buffers() const { return buffers_; }
uint32_t get_cursor_handle_for_crtc(uint32_t crtc) const {
const auto it = crtc_cursor_map_.find(crtc);
@@ -113,6 +111,10 @@ class MockDrmDevice : public DrmDevice {
const PageFlipCallback& callback) override;
bool SetGammaRamp(uint32_t crtc_id,
const std::vector<GammaRampRGBEntry>& lut) override;
+ bool SetColorCorrection(uint32_t crtc_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) override;
bool SetCapability(uint64_t capability, uint64_t value) override;
private:
@@ -137,7 +139,7 @@ class MockDrmDevice : public DrmDevice {
uint32_t current_framebuffer_;
- std::vector<skia::RefPtr<SkSurface>> buffers_;
+ std::vector<sk_sp<SkSurface>> buffers_;
std::map<uint32_t, uint32_t> crtc_cursor_map_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/overlay_plane.cc b/chromium/ui/ozone/platform/drm/gpu/overlay_plane.cc
index c883eb00aa3..d7016701cd2 100644
--- a/chromium/ui/ozone/platform/drm/gpu/overlay_plane.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/overlay_plane.cc
@@ -27,6 +27,8 @@ OverlayPlane::OverlayPlane(const scoped_refptr<ScanoutBuffer>& buffer,
display_bounds(display_bounds),
crop_rect(crop_rect) {}
+OverlayPlane::OverlayPlane(const OverlayPlane& other) = default;
+
OverlayPlane::~OverlayPlane() {
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/overlay_plane.h b/chromium/ui/ozone/platform/drm/gpu/overlay_plane.h
index 1666e07d870..1225049a767 100644
--- a/chromium/ui/ozone/platform/drm/gpu/overlay_plane.h
+++ b/chromium/ui/ozone/platform/drm/gpu/overlay_plane.h
@@ -12,7 +12,6 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/overlay_transform.h"
-#include "ui/ozone/ozone_export.h"
namespace ui {
@@ -21,7 +20,7 @@ class ScanoutBuffer;
struct OverlayPlane;
typedef std::vector<OverlayPlane> OverlayPlaneList;
-struct OZONE_EXPORT OverlayPlane {
+struct OverlayPlane {
// Simpler constructor for the primary plane.
explicit OverlayPlane(const scoped_refptr<ScanoutBuffer>& buffer);
@@ -30,6 +29,7 @@ struct OZONE_EXPORT OverlayPlane {
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect);
+ OverlayPlane(const OverlayPlane& other);
// This represents a callback function which can handle post processing
// operations like scaling, format conversion etc of the buffer bound to this
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
index aae384b63f6..59f81d2cdb0 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -12,7 +12,6 @@
#include "base/memory/scoped_vector.h"
#include "base/observer_list.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/ozone_export.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
typedef struct _drmModeModeInfo drmModeModeInfo;
@@ -30,7 +29,7 @@ class DrmWindow;
class ScanoutBufferGenerator;
// Responsible for keeping track of active displays and configuring them.
-class OZONE_EXPORT ScreenManager {
+class ScreenManager {
public:
ScreenManager(ScanoutBufferGenerator* surface_generator);
virtual ~ScreenManager();
diff --git a/chromium/ui/ozone/platform/drm/host/channel_observer.h b/chromium/ui/ozone/platform/drm/host/channel_observer.h
deleted file mode 100644
index ffbfa048a89..00000000000
--- a/chromium/ui/ozone/platform/drm/host/channel_observer.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_DRM_HOST_CHANNEL_OBSERVER_H_
-#define UI_OZONE_PLATFORM_DRM_HOST_CHANNEL_OBSERVER_H_
-
-namespace ui {
-
-// Observes the channel state.
-class ChannelObserver {
- public:
- virtual ~ChannelObserver() {}
-
- virtual void OnChannelEstablished() = 0;
- virtual void OnChannelDestroyed() = 0;
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_HOST_CHANNEL_OBSERVER_H_
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
index 31c5b9fb877..b3acdc477e8 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.cc
@@ -1,16 +1,12 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/drm/host/drm_cursor.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
-#include "ui/gfx/geometry/point.h"
+#include "base/trace_event/trace_event.h"
#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
+#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
#if defined(OS_CHROMEOS)
@@ -19,10 +15,50 @@
namespace ui {
+namespace {
+
+class NullProxy : public DrmCursorProxy {
+ public:
+ NullProxy() {}
+ ~NullProxy() override {}
+
+ void CursorSet(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) override {}
+ void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NullProxy);
+};
+
+} // namespace
+
DrmCursor::DrmCursor(DrmWindowHostManager* window_manager)
- : ipc_(&lock_), core_(new DrmCursorCore(&ipc_, window_manager)) {}
+ : window_(gfx::kNullAcceleratedWidget),
+ window_manager_(window_manager),
+ proxy_(new NullProxy()) {}
+
+DrmCursor::~DrmCursor() {}
-DrmCursor::~DrmCursor() {
+void DrmCursor::SetDrmCursorProxy(DrmCursorProxy* proxy) {
+ TRACE_EVENT0("drmcursor", "DrmCursor::SetDrmCursorProxy");
+ DCHECK(thread_checker_.CalledOnValidThread());
+ base::AutoLock lock(lock_);
+ proxy_.reset(proxy);
+}
+
+void DrmCursor::ResetDrmCursorProxy() {
+ TRACE_EVENT0("drmcursor", "DrmCursor::ResetDrmCursorProxy");
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ NullProxy* np = new NullProxy();
+ base::AutoLock lock(lock_);
+ proxy_.reset(np);
+}
+
+gfx::Point DrmCursor::GetBitmapLocationLocked() {
+ return gfx::ToFlooredPoint(location_) - bitmap_->hotspot().OffsetFromOrigin();
}
void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
@@ -35,7 +71,13 @@ void DrmCursor::SetCursor(gfx::AcceleratedWidget window,
BitmapCursorFactoryOzone::GetBitmapCursor(platform_cursor);
base::AutoLock lock(lock_);
- core_->SetCursor(window, bitmap);
+
+ if (window_ != window || bitmap_ == bitmap)
+ return;
+
+ bitmap_ = bitmap;
+
+ SendCursorShowLocked();
}
void DrmCursor::OnWindowAdded(gfx::AcceleratedWidget window,
@@ -45,14 +87,37 @@ void DrmCursor::OnWindowAdded(gfx::AcceleratedWidget window,
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock lock(lock_);
- core_->OnWindowAdded(window, bounds_in_screen, cursor_confined_bounds);
+ if (window_ == gfx::kNullAcceleratedWidget) {
+ // First window added & cursor is not placed. Place it.
+ window_ = window;
+ display_bounds_in_screen_ = bounds_in_screen;
+ confined_bounds_ = cursor_confined_bounds;
+ SetCursorLocationLocked(gfx::PointF(cursor_confined_bounds.CenterPoint()));
+ }
}
void DrmCursor::OnWindowRemoved(gfx::AcceleratedWidget window) {
TRACE_EVENT0("drmcursor", "DrmCursor::OnWindowRemoved");
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock lock(lock_);
- core_->OnWindowRemoved(window);
+
+ if (window_ == window) {
+ // Try to find a new location for the cursor.
+ DrmWindowHost* dest_window = window_manager_->GetPrimaryWindow();
+
+ if (dest_window) {
+ window_ = dest_window->GetAcceleratedWidget();
+ display_bounds_in_screen_ = dest_window->GetBounds();
+ confined_bounds_ = dest_window->GetCursorConfinedBounds();
+ SetCursorLocationLocked(gfx::PointF(confined_bounds_.CenterPoint()));
+ SendCursorShowLocked();
+ } else {
+ window_ = gfx::kNullAcceleratedWidget;
+ display_bounds_in_screen_ = gfx::Rect();
+ confined_bounds_ = gfx::Rect();
+ location_ = gfx::PointF();
+ }
+ }
}
void DrmCursor::CommitBoundsChange(
@@ -62,8 +127,13 @@ void DrmCursor::CommitBoundsChange(
TRACE_EVENT0("drmcursor", "DrmCursor::CommitBoundsChange");
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock lock(lock_);
- core_->CommitBoundsChange(window, new_display_bounds_in_screen,
- new_confined_bounds);
+
+ if (window_ == window) {
+ display_bounds_in_screen_ = new_display_bounds_in_screen;
+ confined_bounds_ = new_confined_bounds;
+ SetCursorLocationLocked(location_);
+ SendCursorShowLocked();
+ }
}
void DrmCursor::MoveCursorTo(gfx::AcceleratedWidget window,
@@ -71,96 +141,118 @@ void DrmCursor::MoveCursorTo(gfx::AcceleratedWidget window,
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursorTo (window)");
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock lock(lock_);
- core_->MoveCursorTo(window, location);
+ gfx::AcceleratedWidget old_window = window_;
+
+ if (window != old_window) {
+ // When moving between displays, hide the cursor on the old display
+ // prior to showing it on the new display.
+ if (old_window != gfx::kNullAcceleratedWidget)
+ SendCursorHideLocked();
+
+ // TODO(rjk): pass this in?
+ DrmWindowHost* drm_window_host = window_manager_->GetWindow(window);
+ display_bounds_in_screen_ = drm_window_host->GetBounds();
+ confined_bounds_ = drm_window_host->GetCursorConfinedBounds();
+ window_ = window;
+ }
+
+ SetCursorLocationLocked(location);
+ if (window != old_window)
+ SendCursorShowLocked();
+ else
+ SendCursorMoveLocked();
}
void DrmCursor::MoveCursorTo(const gfx::PointF& screen_location) {
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursorTo");
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock lock(lock_);
- core_->MoveCursorTo(screen_location);
+
+ // TODO(spang): Moving between windows doesn't work here, but
+ // is not needed for current uses.
+ SetCursorLocationLocked(screen_location -
+ display_bounds_in_screen_.OffsetFromOrigin());
+
+ SendCursorMoveLocked();
}
void DrmCursor::MoveCursor(const gfx::Vector2dF& delta) {
TRACE_EVENT0("drmcursor", "DrmCursor::MoveCursor");
base::AutoLock lock(lock_);
- core_->MoveCursor(delta);
+
+ if (window_ == gfx::kNullAcceleratedWidget)
+ return;
+
+ gfx::Point location;
+#if defined(OS_CHROMEOS)
+ gfx::Vector2dF transformed_delta = delta;
+ ui::CursorController::GetInstance()->ApplyCursorConfigForWindow(
+ window_, &transformed_delta);
+ SetCursorLocationLocked(location_ + transformed_delta);
+#else
+ SetCursorLocationLocked(location_ + delta);
+#endif
+ SendCursorMoveLocked();
}
bool DrmCursor::IsCursorVisible() {
base::AutoLock lock(lock_);
- return core_->IsCursorVisible();
+ return bitmap_;
}
gfx::PointF DrmCursor::GetLocation() {
base::AutoLock lock(lock_);
- return core_->GetLocation();
+ return location_ + display_bounds_in_screen_.OffsetFromOrigin();
}
gfx::Rect DrmCursor::GetCursorConfinedBounds() {
base::AutoLock lock(lock_);
- return core_->GetCursorConfinedBounds();
+ return confined_bounds_ + display_bounds_in_screen_.OffsetFromOrigin();
}
-void DrmCursor::OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& send_callback) {
- TRACE_EVENT0("drmcursor", "DrmCursor::OnChannelEstablished");
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(lock_);
- ipc_.host_id = host_id;
- ipc_.send_runner = send_runner;
- ipc_.send_callback = send_callback;
- // Initial set for this GPU process will happen after the window
- // initializes, in CommitBoundsChange().
-}
+void DrmCursor::SetCursorLocationLocked(const gfx::PointF& location) {
+ gfx::PointF clamped_location = location;
+ clamped_location.SetToMax(gfx::PointF(confined_bounds_.origin()));
+ // Right and bottom edges are exclusive.
+ clamped_location.SetToMin(
+ gfx::PointF(confined_bounds_.right() - 1, confined_bounds_.bottom() - 1));
-void DrmCursor::OnChannelDestroyed(int host_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(lock_);
- if (ipc_.host_id == host_id) {
- ipc_.host_id = -1;
- ipc_.send_runner = NULL;
- ipc_.send_callback.Reset();
- }
+ location_ = clamped_location;
}
-bool DrmCursor::OnMessageReceived(const IPC::Message& message) {
- return false;
+void DrmCursor::SendCursorShowLocked() {
+ if (!bitmap_) {
+ SendCursorHideLocked();
+ return;
+ }
+ CursorSetLockTested(window_, bitmap_->bitmaps(), GetBitmapLocationLocked(),
+ bitmap_->frame_delay_ms());
}
-bool DrmCursor::CursorIPC::IsConnectedLocked() {
- return !send_callback.is_null();
+void DrmCursor::SendCursorHideLocked() {
+ CursorSetLockTested(window_, std::vector<SkBitmap>(), gfx::Point(), 0);
}
-void DrmCursor::CursorIPC::CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- gfx::Point point,
- int frame_delay_ms) {
- SendLocked(new OzoneGpuMsg_CursorSet(window, bitmaps, point, frame_delay_ms));
+void DrmCursor::SendCursorMoveLocked() {
+ if (!bitmap_)
+ return;
+ MoveLockTested(window_, GetBitmapLocationLocked());
}
-void DrmCursor::CursorIPC::Move(gfx::AcceleratedWidget window,
- gfx::Point point) {
- SendLocked(new OzoneGpuMsg_CursorMove(window, point));
+// Lock-testing helpers.
+void DrmCursor::CursorSetLockTested(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) {
+ lock_.AssertAcquired();
+ proxy_->CursorSet(window, bitmaps, point, frame_delay_ms);
}
-void DrmCursor::CursorIPC::SendLocked(IPC::Message* message) {
- lock->AssertAcquired();
-
- if (IsConnectedLocked() &&
- send_runner->PostTask(FROM_HERE, base::Bind(send_callback, message)))
- return;
-
- // Drop disconnected updates. DrmWindowHost will call
- // CommitBoundsChange() when we connect to initialize the cursor
- // location.
- delete message;
+void DrmCursor::MoveLockTested(gfx::AcceleratedWidget window,
+ const gfx::Point& point) {
+ lock_.AssertAcquired();
+ proxy_->Move(window, point);
}
-DrmCursor::CursorIPC::CursorIPC(base::Lock* lock) : host_id(-1), lock(lock) {}
-
-DrmCursor::CursorIPC::~CursorIPC() {}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.h b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
index 2766365f091..70b18f37e9e 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
@@ -1,4 +1,4 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,36 +6,45 @@
#define UI_OZONE_PLATFORM_DRM_HOST_DRM_CURSOR_H_
#include <memory>
+#include <vector>
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
-#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/evdev/cursor_delegate_evdev.h"
-#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/platform/drm/host/drm_cursor_core.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
-
-namespace gfx {
-class PointF;
-class Vector2dF;
-class Rect;
-}
namespace ui {
-class BitmapCursorFactoryOzone;
+class BitmapCursorOzone;
class DrmWindowHostManager;
+// DrmCursor manages all cursor state but is dependent on an injected
+// proxy for how it communicates state changes to other threads or
+// processes. The proxy implementation must satisfy DrmCursorProxy.
+class DrmCursorProxy {
+ public:
+ virtual ~DrmCursorProxy() {}
+
+ // Sets the cursor |bitmaps| on |window| at |point| with |frame_delay_ms|.
+ virtual void CursorSet(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) = 0;
+ // Moves the cursor in |window| to |point|
+ virtual void Move(gfx::AcceleratedWidget window, const gfx::Point& point) = 0;
+};
+
+// DrmCursor manages all cursor state and semantics.
class DrmCursor : public CursorDelegateEvdev {
public:
explicit DrmCursor(DrmWindowHostManager* window_manager);
~DrmCursor() override;
+ // Sets or resets the DrmProxy |proxy|. If |proxy| is set, the DrmCursor uses
+ // it to communicate to the GPU process or thread.
+ void SetDrmCursorProxy(DrmCursorProxy* proxy);
+ void ResetDrmCursorProxy();
+
// Change the cursor over the specifed window.
void SetCursor(gfx::AcceleratedWidget window, PlatformCursor platform_cursor);
@@ -59,39 +68,18 @@ class DrmCursor : public CursorDelegateEvdev {
gfx::PointF GetLocation() override;
gfx::Rect GetCursorConfinedBounds() override;
- // IPC.
- void OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& sender);
- void OnChannelDestroyed(int host_id);
- bool OnMessageReceived(const IPC::Message& message);
-
private:
- // An IPC-based implementation of the DrmCursorProxy that ships
- // messages to the GPU process.
- class CursorIPC : public DrmCursorProxy {
- public:
- explicit CursorIPC(base::Lock* lock);
- ~CursorIPC();
-
- bool IsConnectedLocked();
- void SendLocked(IPC::Message* message);
-
- // DrmCursorProxy implementation.
- void CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- gfx::Point point,
- int frame_delay_ms) override;
- void Move(gfx::AcceleratedWidget window, gfx::Point point) override;
-
- int host_id;
-
- // Callback for IPC updates.
- base::Callback<void(IPC::Message*)> send_callback;
- scoped_refptr<base::SingleThreadTaskRunner> send_runner;
- base::Lock* lock;
- };
+ void SetCursorLocationLocked(const gfx::PointF& location);
+ void SendCursorShowLocked();
+ void SendCursorHideLocked();
+ void SendCursorMoveLocked();
+
+ // Lock-testing helpers.
+ void CursorSetLockTested(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms);
+ void MoveLockTested(gfx::AcceleratedWidget window, const gfx::Point& point);
// The mutex synchronizing this object.
base::Lock lock_;
@@ -99,8 +87,27 @@ class DrmCursor : public CursorDelegateEvdev {
// Enforce our threading constraints.
base::ThreadChecker thread_checker_;
- CursorIPC ipc_;
- std::unique_ptr<DrmCursorCore> core_;
+ // The location of the bitmap (the cursor location is the hotspot location).
+ gfx::Point GetBitmapLocationLocked();
+
+ // The current cursor bitmap (immutable).
+ scoped_refptr<BitmapCursorOzone> bitmap_;
+
+ // The window under the cursor.
+ gfx::AcceleratedWidget window_;
+
+ // The location of the cursor within the window.
+ gfx::PointF location_;
+
+ // The bounds of the display under the cursor.
+ gfx::Rect display_bounds_in_screen_;
+
+ // The bounds that the cursor is confined to in |window|.
+ gfx::Rect confined_bounds_;
+
+ DrmWindowHostManager* window_manager_; // Not owned.
+
+ std::unique_ptr<DrmCursorProxy> proxy_;
DISALLOW_COPY_AND_ASSIGN(DrmCursor);
};
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor_core.cc b/chromium/ui/ozone/platform/drm/host/drm_cursor_core.cc
deleted file mode 100644
index 86b92d494a8..00000000000
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor_core.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/drm/host/drm_cursor_core.h"
-
-#include "ui/events/ozone/chromeos/cursor_controller.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/ozone/platform/drm/host/drm_window_host.h"
-#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
-
-namespace ui {
-
-DrmCursorCore::DrmCursorCore(DrmCursorProxy* proxy,
- DrmWindowHostManager* window_manager)
- : window_(gfx::kNullAcceleratedWidget),
- window_manager_(window_manager),
- proxy_(proxy) {}
-
-DrmCursorCore::~DrmCursorCore() {}
-
-gfx::Point DrmCursorCore::GetBitmapLocationLocked() {
- return gfx::ToFlooredPoint(location_) - bitmap_->hotspot().OffsetFromOrigin();
-}
-
-void DrmCursorCore::SetCursor(gfx::AcceleratedWidget window,
- scoped_refptr<BitmapCursorOzone> bitmap) {
- if (window_ != window || bitmap_ == bitmap)
- return;
-
- bitmap_ = bitmap;
-
- SendCursorShow();
-}
-
-void DrmCursorCore::OnWindowAdded(gfx::AcceleratedWidget window,
- const gfx::Rect& bounds_in_screen,
- const gfx::Rect& cursor_confined_bounds) {
- if (window_ == gfx::kNullAcceleratedWidget) {
- // First window added & cursor is not placed. Place it.
- window_ = window;
- display_bounds_in_screen_ = bounds_in_screen;
- confined_bounds_ = cursor_confined_bounds;
- SetCursorLocation(gfx::PointF(cursor_confined_bounds.CenterPoint()));
- }
-}
-
-void DrmCursorCore::OnWindowRemoved(gfx::AcceleratedWidget window) {
- if (window_ == window) {
- // Try to find a new location for the cursor.
- DrmWindowHost* dest_window = window_manager_->GetPrimaryWindow();
-
- if (dest_window) {
- window_ = dest_window->GetAcceleratedWidget();
- display_bounds_in_screen_ = dest_window->GetBounds();
- confined_bounds_ = dest_window->GetCursorConfinedBounds();
- SetCursorLocation(gfx::PointF(confined_bounds_.CenterPoint()));
- SendCursorShow();
- } else {
- window_ = gfx::kNullAcceleratedWidget;
- display_bounds_in_screen_ = gfx::Rect();
- confined_bounds_ = gfx::Rect();
- location_ = gfx::PointF();
- }
- }
-}
-
-void DrmCursorCore::CommitBoundsChange(
- gfx::AcceleratedWidget window,
- const gfx::Rect& new_display_bounds_in_screen,
- const gfx::Rect& new_confined_bounds) {
- if (window_ == window) {
- display_bounds_in_screen_ = new_display_bounds_in_screen;
- confined_bounds_ = new_confined_bounds;
- SetCursorLocation(location_);
- SendCursorShow();
- }
-}
-
-void DrmCursorCore::MoveCursorTo(gfx::AcceleratedWidget window,
- const gfx::PointF& location) {
- gfx::AcceleratedWidget old_window = window_;
-
- if (window != old_window) {
- // When moving between displays, hide the cursor on the old display
- // prior to showing it on the new display.
- if (old_window != gfx::kNullAcceleratedWidget)
- SendCursorHide();
-
- // TODO(rjk): pass this in?
- DrmWindowHost* drm_window_host = window_manager_->GetWindow(window);
- display_bounds_in_screen_ = drm_window_host->GetBounds();
- confined_bounds_ = drm_window_host->GetCursorConfinedBounds();
- window_ = window;
- }
-
- SetCursorLocation(location);
- if (window != old_window)
- SendCursorShow();
- else
- SendCursorMove();
-}
-
-void DrmCursorCore::MoveCursorTo(const gfx::PointF& screen_location) {
- // TODO(spang): Moving between windows doesn't work here, but
- // is not needed for current uses.
- SetCursorLocation(screen_location -
- display_bounds_in_screen_.OffsetFromOrigin());
-
- SendCursorMove();
-}
-
-void DrmCursorCore::MoveCursor(const gfx::Vector2dF& delta) {
- if (window_ == gfx::kNullAcceleratedWidget)
- return;
-
- gfx::Point location;
-#if defined(OS_CHROMEOS)
- gfx::Vector2dF transformed_delta = delta;
- ui::CursorController::GetInstance()->ApplyCursorConfigForWindow(
- window_, &transformed_delta);
- SetCursorLocation(location_ + transformed_delta);
-#else
- SetCursorLocation(location_ + delta);
-#endif
- SendCursorMove();
-}
-
-bool DrmCursorCore::IsCursorVisible() {
- return bitmap_;
-}
-
-gfx::PointF DrmCursorCore::GetLocation() {
- return location_ + display_bounds_in_screen_.OffsetFromOrigin();
-}
-
-gfx::Rect DrmCursorCore::GetCursorConfinedBounds() {
- return confined_bounds_ + display_bounds_in_screen_.OffsetFromOrigin();
-}
-
-void DrmCursorCore::SetCursorLocation(const gfx::PointF& location) {
- gfx::PointF clamped_location = location;
- clamped_location.SetToMax(gfx::PointF(confined_bounds_.origin()));
- // Right and bottom edges are exclusive.
- clamped_location.SetToMin(
- gfx::PointF(confined_bounds_.right() - 1, confined_bounds_.bottom() - 1));
-
- location_ = clamped_location;
-}
-
-void DrmCursorCore::SendCursorShow() {
- if (!bitmap_) {
- SendCursorHide();
- return;
- }
- proxy_->CursorSet(window_, bitmap_->bitmaps(), GetBitmapLocationLocked(),
- bitmap_->frame_delay_ms());
-}
-
-void DrmCursorCore::SendCursorHide() {
- proxy_->CursorSet(window_, std::vector<SkBitmap>(), gfx::Point(), 0);
-}
-
-void DrmCursorCore::SendCursorMove() {
- if (!bitmap_)
- return;
-
- proxy_->Move(window_, GetBitmapLocationLocked());
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor_core.h b/chromium/ui/ozone/platform/drm/host/drm_cursor_core.h
deleted file mode 100644
index 3dc7bce1edb..00000000000
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor_core.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_CURSOR_CORE_H_
-#define UI_OZONE_PLATFORM_DRM_HOST_DRM_CURSOR_CORE_H_
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace ui {
-class BitmapCursorOzone;
-class DrmWindowHostManager;
-
-// DrmCursorCore manages all cursor state but is dependent on an injected
-// proxy for how it communicates state changes to other threads or
-// processes. The proxy implementation must satisfy DrmCursorProxy.
-class DrmCursorProxy {
- public:
- // Sets the cursor |bitmaps| on |window| at |point| with |frame_delay_ms|.
- virtual void CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- gfx::Point point,
- int frame_delay_ms) = 0;
- // Moves the cursor in |window| to |point|
- virtual void Move(gfx::AcceleratedWidget window, gfx::Point point) = 0;
-};
-
-// DrmCursorCore manages all cursor state and semantics.
-class DrmCursorCore {
- public:
- DrmCursorCore(DrmCursorProxy* proxy, DrmWindowHostManager* window_manager);
- ~DrmCursorCore();
-
- // Change the cursor over the specifed window.
- void SetCursor(gfx::AcceleratedWidget window,
- scoped_refptr<BitmapCursorOzone> platform_cursor);
-
- // Handle window lifecycle.
- void OnWindowAdded(gfx::AcceleratedWidget window,
- const gfx::Rect& bounds_in_screen,
- const gfx::Rect& cursor_confined_bounds);
- void OnWindowRemoved(gfx::AcceleratedWidget window);
-
- // Handle window bounds changes.
- void CommitBoundsChange(gfx::AcceleratedWidget window,
- const gfx::Rect& new_display_bounds_in_screen,
- const gfx::Rect& new_confined_bounds);
-
- // CursorDelegateEvdev:
- void MoveCursorTo(gfx::AcceleratedWidget window, const gfx::PointF& location);
- void MoveCursorTo(const gfx::PointF& screen_location);
- void MoveCursor(const gfx::Vector2dF& delta);
- bool IsCursorVisible();
- gfx::PointF GetLocation();
- gfx::Rect GetCursorConfinedBounds();
-
- private:
- void SetCursorLocation(const gfx::PointF& location);
- void SendCursorShow();
- void SendCursorHide();
- void SendCursorMove();
-
- // The location of the bitmap (the cursor location is the hotspot location).
- gfx::Point GetBitmapLocationLocked();
-
- // The current cursor bitmap (immutable).
- scoped_refptr<BitmapCursorOzone> bitmap_;
-
- // The window under the cursor.
- gfx::AcceleratedWidget window_;
-
- // The location of the cursor within the window.
- gfx::PointF location_;
-
- // The bounds of the display under the cursor.
- gfx::Rect display_bounds_in_screen_;
-
- // The bounds that the cursor is confined to in |window|.
- gfx::Rect confined_bounds_;
-
- DrmWindowHostManager* window_manager_; // Not owned.
-
- // Lifetime managed by the caller.
- DrmCursorProxy* proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(DrmCursorCore);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_HOST_DRM_CURSOR_H_
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
index 9491e4ef2c4..32d36e65b03 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
@@ -4,25 +4,25 @@
#include "ui/ozone/platform/drm/host/drm_display_host.h"
+#include "base/location.h"
#include "base/thread_task_runner_handle.h"
#include "ui/ozone/common/display_snapshot_proxy.h"
#include "ui/ozone/common/display_util.h"
-#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
-#include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
namespace ui {
-DrmDisplayHost::DrmDisplayHost(DrmGpuPlatformSupportHost* sender,
+DrmDisplayHost::DrmDisplayHost(GpuThreadAdapter* sender,
const DisplaySnapshot_Params& params,
bool is_dummy)
: sender_(sender),
snapshot_(new DisplaySnapshotProxy(params)),
is_dummy_(is_dummy) {
- sender_->AddChannelObserver(this);
+ sender_->AddGpuThreadObserver(this);
}
DrmDisplayHost::~DrmDisplayHost() {
- sender_->RemoveChannelObserver(this);
+ sender_->RemoveGpuThreadObserver(this);
ClearCallbacks();
}
@@ -42,11 +42,10 @@ void DrmDisplayHost::Configure(const DisplayMode* mode,
configure_callback_ = callback;
bool status = false;
if (mode) {
- status = sender_->Send(new OzoneGpuMsg_ConfigureNativeDisplay(
- snapshot_->display_id(), GetDisplayModeParams(*mode), origin));
+ status = sender_->GpuConfigureNativeDisplay(
+ snapshot_->display_id(), GetDisplayModeParams(*mode), origin);
} else {
- status = sender_->Send(
- new OzoneGpuMsg_DisableNativeDisplay(snapshot_->display_id()));
+ status = sender_->GpuDisableNativeDisplay(snapshot_->display_id());
}
if (!status)
@@ -67,7 +66,7 @@ void DrmDisplayHost::OnDisplayConfigured(bool status) {
void DrmDisplayHost::GetHDCPState(const GetHDCPStateCallback& callback) {
get_hdcp_callback_ = callback;
- if (!sender_->Send(new OzoneGpuMsg_GetHDCPState(snapshot_->display_id())))
+ if (!sender_->GpuGetHDCPState(snapshot_->display_id()))
OnHDCPStateReceived(false, HDCP_STATE_UNDESIRED);
}
@@ -86,8 +85,7 @@ void DrmDisplayHost::OnHDCPStateReceived(bool status, HDCPState state) {
void DrmDisplayHost::SetHDCPState(HDCPState state,
const SetHDCPStateCallback& callback) {
set_hdcp_callback_ = callback;
- if (!sender_->Send(
- new OzoneGpuMsg_SetHDCPState(snapshot_->display_id(), state)))
+ if (!sender_->GpuSetHDCPState(snapshot_->display_id(), state))
OnHDCPStateUpdated(false);
}
@@ -103,11 +101,15 @@ void DrmDisplayHost::OnHDCPStateUpdated(bool status) {
set_hdcp_callback_.Reset();
}
-void DrmDisplayHost::SetGammaRamp(const std::vector<GammaRampRGBEntry>& lut) {
- sender_->Send(new OzoneGpuMsg_SetGammaRamp(snapshot_->display_id(), lut));
+void DrmDisplayHost::SetColorCorrection(
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ sender_->GpuSetColorCorrection(snapshot_->display_id(), degamma_lut,
+ gamma_lut, correction_matrix);
}
-void DrmDisplayHost::OnChannelEstablished() {
+void DrmDisplayHost::OnGpuThreadReady() {
is_dummy_ = false;
// Note: These responses are done here since the OnChannelDestroyed() is
@@ -115,8 +117,7 @@ void DrmDisplayHost::OnChannelEstablished() {
ClearCallbacks();
}
-void DrmDisplayHost::OnChannelDestroyed() {
-}
+void DrmDisplayHost::OnGpuThreadRetired() {}
void DrmDisplayHost::ClearCallbacks() {
if (!configure_callback_.is_null())
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host.h b/chromium/ui/ozone/platform/drm/host/drm_display_host.h
index 5ea80fc63f7..32cc3523af1 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host.h
@@ -9,17 +9,17 @@
#include "base/memory/scoped_ptr.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/native_display_delegate.h"
-#include "ui/ozone/platform/drm/host/channel_observer.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
namespace ui {
struct DisplaySnapshot_Params;
class DisplaySnapshot;
-class DrmGpuPlatformSupportHost;
+class GpuThreadAdapter;
-class DrmDisplayHost : public ChannelObserver {
+class DrmDisplayHost : public GpuThreadObserver {
public:
- DrmDisplayHost(DrmGpuPlatformSupportHost* sender,
+ DrmDisplayHost(GpuThreadAdapter* sender,
const DisplaySnapshot_Params& params,
bool is_dummy);
~DrmDisplayHost() override;
@@ -32,7 +32,9 @@ class DrmDisplayHost : public ChannelObserver {
const ConfigureCallback& callback);
void GetHDCPState(const GetHDCPStateCallback& callback);
void SetHDCPState(HDCPState state, const SetHDCPStateCallback& callback);
- void SetGammaRamp(const std::vector<GammaRampRGBEntry>& lut);
+ void SetColorCorrection(const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix);
// Called when the IPC from the GPU process arrives to answer the above
// commands.
@@ -40,15 +42,15 @@ class DrmDisplayHost : public ChannelObserver {
void OnHDCPStateReceived(bool status, HDCPState state);
void OnHDCPStateUpdated(bool status);
- // ChannelObserver:
- void OnChannelEstablished() override;
- void OnChannelDestroyed() override;
+ // GpuThreadObserver:
+ void OnGpuThreadReady() override;
+ void OnGpuThreadRetired() override;
private:
// Calls all the callbacks with failure.
void ClearCallbacks();
- DrmGpuPlatformSupportHost* sender_; // Not owned.
+ GpuThreadAdapter* sender_; // Not owned.
scoped_ptr<DisplaySnapshot> snapshot_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
index ba43cdc22e8..458c247ed2b 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -4,149 +4,461 @@
#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
+#include <fcntl.h>
+#include <stddef.h>
+#include <xf86drm.h>
+#include <utility>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
-#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/worker_pool.h"
+#include "ui/display/types/display_snapshot.h"
+#include "ui/events/ozone/device/device_event.h"
+#include "ui/events/ozone/device/device_manager.h"
+#include "ui/ozone/common/display_util.h"
+#include "ui/ozone/platform/drm/common/drm_util.h"
+#include "ui/ozone/platform/drm/host/drm_device_handle.h"
#include "ui/ozone/platform/drm/host/drm_display_host.h"
-#include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
#include "ui/ozone/platform/drm/host/drm_native_display_delegate.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
namespace ui {
+namespace {
+
+typedef base::Callback<void(const base::FilePath&,
+ const base::FilePath&,
+ scoped_ptr<DrmDeviceHandle>)>
+ OnOpenDeviceReplyCallback;
+
+const char kDefaultGraphicsCardPattern[] = "/dev/dri/card%d";
+
+const char* kDisplayActionString[] = {
+ "ADD", "REMOVE", "CHANGE",
+};
+
+// Find sysfs device path for the given device path.
+base::FilePath MapDevPathToSysPath(const base::FilePath& device_path) {
+ // |device_path| looks something like /dev/dri/card0. We take the basename of
+ // that (card0) and append it to /sys/class/drm. /sys/class/drm/card0 is a
+ // symlink that points to something like
+ // /sys/devices/pci0000:00/0000:00:02.0/0000:05:00.0/drm/card0, which exposes
+ // some metadata about the attached device.
+ return base::MakeAbsoluteFilePath(
+ base::FilePath("/sys/class/drm").Append(device_path.BaseName()));
+}
+
+void OpenDeviceOnWorkerThread(
+ const base::FilePath& device_path,
+ const scoped_refptr<base::TaskRunner>& reply_runner,
+ const OnOpenDeviceReplyCallback& callback) {
+ base::FilePath sys_path = MapDevPathToSysPath(device_path);
+
+ scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle());
+ handle->Initialize(device_path, sys_path);
+ reply_runner->PostTask(FROM_HERE,
+ base::Bind(callback, device_path, sys_path,
+ base::Passed(std::move(handle))));
+}
+
+base::FilePath GetPrimaryDisplayCardPath() {
+ struct drm_mode_card_res res;
+ for (int i = 0; /* end on first card# that does not exist */; i++) {
+ std::string card_path = base::StringPrintf(kDefaultGraphicsCardPattern, i);
+
+ if (access(card_path.c_str(), F_OK) != 0)
+ break;
+
+ int fd = open(card_path.c_str(), O_RDWR | O_CLOEXEC);
+ if (fd < 0) {
+ VPLOG(1) << "Failed to open '" << card_path << "'";
+ continue;
+ }
+
+ memset(&res, 0, sizeof(struct drm_mode_card_res));
+ int ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
+ close(fd);
+ if (ret == 0 && res.count_crtcs > 0) {
+ return base::FilePath(card_path);
+ }
+
+ VPLOG_IF(1, ret) << "Failed to get DRM resources for '" << card_path << "'";
+ }
+
+ LOG(FATAL) << "Failed to open primary graphics device.";
+ return base::FilePath(); // Not reached.
+}
+
+class FindDrmDisplayHostById {
+ public:
+ explicit FindDrmDisplayHostById(int64_t display_id)
+ : display_id_(display_id) {}
+
+ bool operator()(const scoped_ptr<DrmDisplayHost>& display) const {
+ return display->snapshot()->display_id() == display_id_;
+ }
+
+ private:
+ int64_t display_id_;
+};
+
+} // namespace
+
DrmDisplayHostManager::DrmDisplayHostManager(
- DrmGpuPlatformSupportHost* proxy,
+ GpuThreadAdapter* proxy,
DeviceManager* device_manager,
InputControllerEvdev* input_controller)
- : sender_(new HostManagerIPC(proxy, this)),
- core_(new DrmDisplayHostManagerCore(sender_.get(),
- device_manager,
- input_controller)) {}
+ : proxy_(proxy),
+ device_manager_(device_manager),
+ input_controller_(input_controller),
+ primary_graphics_card_path_(GetPrimaryDisplayCardPath()),
+ weak_ptr_factory_(this) {
+ {
+ // First device needs to be treated specially. We need to open this
+ // synchronously since the GPU process will need it to initialize the
+ // graphics state.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ base::FilePath primary_graphics_card_path_sysfs =
+ MapDevPathToSysPath(primary_graphics_card_path_);
+
+ primary_drm_device_handle_.reset(new DrmDeviceHandle());
+ if (!primary_drm_device_handle_->Initialize(
+ primary_graphics_card_path_, primary_graphics_card_path_sysfs)) {
+ LOG(FATAL) << "Failed to open primary graphics card";
+ return;
+ }
+ drm_devices_[primary_graphics_card_path_] =
+ primary_graphics_card_path_sysfs;
+ }
+
+ device_manager_->AddObserver(this);
+ proxy_->RegisterHandlerForDrmDisplayHostManager(this);
+ proxy_->AddGpuThreadObserver(this);
+
+ ScopedVector<HardwareDisplayControllerInfo> display_infos =
+ GetAvailableDisplayControllerInfos(primary_drm_device_handle_->fd());
+ has_dummy_display_ = !display_infos.empty();
+ for (size_t i = 0; i < display_infos.size(); ++i) {
+ displays_.push_back(make_scoped_ptr(new DrmDisplayHost(
+ proxy_, CreateDisplaySnapshotParams(
+ display_infos[i], primary_drm_device_handle_->fd(),
+ primary_drm_device_handle_->sys_path(), 0, gfx::Point()),
+ true /* is_dummy */)));
+ }
+}
DrmDisplayHostManager::~DrmDisplayHostManager() {
+ device_manager_->RemoveObserver(this);
+ proxy_->UnRegisterHandlerForDrmDisplayHostManager();
}
DrmDisplayHost* DrmDisplayHostManager::GetDisplay(int64_t display_id) {
- return core_->GetDisplay(display_id);
+ auto it = std::find_if(displays_.begin(), displays_.end(),
+ FindDrmDisplayHostById(display_id));
+ if (it == displays_.end())
+ return nullptr;
+
+ return it->get();
}
void DrmDisplayHostManager::AddDelegate(DrmNativeDisplayDelegate* delegate) {
- core_->AddDelegate(delegate);
+ DCHECK(!delegate_);
+ delegate_ = delegate;
}
void DrmDisplayHostManager::RemoveDelegate(DrmNativeDisplayDelegate* delegate) {
- core_->RemoveDelegate(delegate);
+ DCHECK_EQ(delegate_, delegate);
+ delegate_ = nullptr;
}
void DrmDisplayHostManager::TakeDisplayControl(
const DisplayControlCallback& callback) {
- core_->TakeDisplayControl(callback);
+ if (display_control_change_pending_) {
+ LOG(ERROR) << "TakeDisplayControl called while change already pending";
+ callback.Run(false);
+ return;
+ }
+
+ if (!display_externally_controlled_) {
+ LOG(ERROR) << "TakeDisplayControl called while display already owned";
+ callback.Run(true);
+ return;
+ }
+
+ take_display_control_callback_ = callback;
+ display_control_change_pending_ = true;
+
+ if (!proxy_->GpuTakeDisplayControl())
+ GpuTookDisplayControl(false);
}
void DrmDisplayHostManager::RelinquishDisplayControl(
const DisplayControlCallback& callback) {
- core_->RelinquishDisplayControl(callback);
+ if (display_control_change_pending_) {
+ LOG(ERROR)
+ << "RelinquishDisplayControl called while change already pending";
+ callback.Run(false);
+ return;
+ }
+
+ if (display_externally_controlled_) {
+ LOG(ERROR) << "RelinquishDisplayControl called while display not owned";
+ callback.Run(true);
+ return;
+ }
+
+ relinquish_display_control_callback_ = callback;
+ display_control_change_pending_ = true;
+
+ if (!proxy_->GpuRelinquishDisplayControl())
+ GpuRelinquishedDisplayControl(false);
}
void DrmDisplayHostManager::UpdateDisplays(
const GetDisplaysCallback& callback) {
- core_->UpdateDisplays(callback);
+ get_displays_callback_ = callback;
+ if (!proxy_->GpuRefreshNativeDisplays()) {
+ get_displays_callback_.Reset();
+ RunUpdateDisplaysCallback(callback);
+ }
}
-void DrmDisplayHostManager::OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& send_callback) {
- // The GPU thread may be in a different or the same process.
- core_->GpuThreadStarted();
-}
+void DrmDisplayHostManager::OnDeviceEvent(const DeviceEvent& event) {
+ if (event.device_type() != DeviceEvent::DISPLAY)
+ return;
-void DrmDisplayHostManager::OnChannelDestroyed(int host_id) {
+ event_queue_.push(DisplayEvent(event.action_type(), event.path()));
+ ProcessEvent();
}
-bool DrmDisplayHostManager::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
+void DrmDisplayHostManager::ProcessEvent() {
+ while (!event_queue_.empty() && !task_pending_) {
+ DisplayEvent event = event_queue_.front();
+ event_queue_.pop();
+ VLOG(1) << "Got display event " << kDisplayActionString[event.action_type]
+ << " for " << event.path.value();
+ switch (event.action_type) {
+ case DeviceEvent::ADD:
+ if (drm_devices_.find(event.path) == drm_devices_.end()) {
+ task_pending_ = base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&OpenDeviceOnWorkerThread, event.path,
+ base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&DrmDisplayHostManager::OnAddGraphicsDevice,
+ weak_ptr_factory_.GetWeakPtr())),
+ false /* task_is_slow */);
+ }
+ break;
+ case DeviceEvent::CHANGE:
+ task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmDisplayHostManager::OnUpdateGraphicsDevice,
+ weak_ptr_factory_.GetWeakPtr()));
+ break;
+ case DeviceEvent::REMOVE:
+ DCHECK(event.path != primary_graphics_card_path_)
+ << "Removing primary graphics card";
+ auto it = drm_devices_.find(event.path);
+ if (it != drm_devices_.end()) {
+ task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmDisplayHostManager::OnRemoveGraphicsDevice,
+ weak_ptr_factory_.GetWeakPtr(), it->second));
+ drm_devices_.erase(it);
+ }
+ break;
+ }
+ }
+}
- IPC_BEGIN_MESSAGE_MAP(DrmDisplayHostManager, message)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_UpdateNativeDisplays, OnUpdateNativeDisplays)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayConfigured, OnDisplayConfigured)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateReceived, OnHDCPStateReceived)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateUpdated, OnHDCPStateUpdated)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayControlTaken, OnTakeDisplayControl)
- IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayControlRelinquished,
- OnRelinquishDisplayControl)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
+void DrmDisplayHostManager::OnAddGraphicsDevice(
+ const base::FilePath& dev_path,
+ const base::FilePath& sys_path,
+ scoped_ptr<DrmDeviceHandle> handle) {
+ if (handle->IsValid()) {
+ drm_devices_[dev_path] = sys_path;
+ proxy_->GpuAddGraphicsDevice(sys_path,
+ base::FileDescriptor(handle->PassFD()));
+ NotifyDisplayDelegate();
+ }
+
+ task_pending_ = false;
+ ProcessEvent();
+}
- return handled;
+void DrmDisplayHostManager::OnUpdateGraphicsDevice() {
+ NotifyDisplayDelegate();
+ task_pending_ = false;
+ ProcessEvent();
}
-void DrmDisplayHostManager::OnUpdateNativeDisplays(
- const std::vector<DisplaySnapshot_Params>& params) {
- core_->GpuHasUpdatedNativeDisplays(params);
+void DrmDisplayHostManager::OnRemoveGraphicsDevice(
+ const base::FilePath& sys_path) {
+ proxy_->GpuRemoveGraphicsDevice(sys_path);
+ NotifyDisplayDelegate();
+ task_pending_ = false;
+ ProcessEvent();
}
-void DrmDisplayHostManager::OnDisplayConfigured(int64_t display_id,
- bool status) {
- core_->GpuConfiguredDisplay(display_id, status);
+void DrmDisplayHostManager::OnGpuThreadReady() {
+ // If in the middle of a configuration, just respond with the old list of
+ // displays. This is fine, since after the DRM resources are initialized and
+ // IPC-ed to the GPU NotifyDisplayDelegate() is called to let the display
+ // delegate know that the display configuration changed and it needs to
+ // update it again.
+ if (!get_displays_callback_.is_null()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmDisplayHostManager::RunUpdateDisplaysCallback,
+ weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
+ get_displays_callback_.Reset();
+ }
+
+ // Signal that we're taking DRM master since we're going through the
+ // initialization process again and we'll take all the available resources.
+ if (!take_display_control_callback_.is_null())
+ GpuTookDisplayControl(true);
+
+ if (!relinquish_display_control_callback_.is_null())
+ GpuRelinquishedDisplayControl(false);
+
+ scoped_ptr<DrmDeviceHandle> handle = std::move(primary_drm_device_handle_);
+ {
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ drm_devices_.clear();
+ drm_devices_[primary_graphics_card_path_] =
+ MapDevPathToSysPath(primary_graphics_card_path_);
+
+ if (!handle) {
+ handle.reset(new DrmDeviceHandle());
+ if (!handle->Initialize(primary_graphics_card_path_,
+ drm_devices_[primary_graphics_card_path_]))
+ LOG(FATAL) << "Failed to open primary graphics card";
+ }
+ }
+
+ // Send the primary device first since this is used to initialize graphics
+ // state.
+ proxy_->GpuAddGraphicsDevice(drm_devices_[primary_graphics_card_path_],
+ base::FileDescriptor(handle->PassFD()));
+
+ device_manager_->ScanDevices(this);
+ NotifyDisplayDelegate();
}
-void DrmDisplayHostManager::OnHDCPStateReceived(int64_t display_id,
- bool status,
- HDCPState state) {
- core_->GpuReceivedHDCPState(display_id, status, state);
+void DrmDisplayHostManager::OnGpuThreadRetired() {}
+
+void DrmDisplayHostManager::GpuHasUpdatedNativeDisplays(
+ const std::vector<DisplaySnapshot_Params>& params) {
+ std::vector<scoped_ptr<DrmDisplayHost>> old_displays;
+ displays_.swap(old_displays);
+ for (size_t i = 0; i < params.size(); ++i) {
+ auto it = std::find_if(old_displays.begin(), old_displays.end(),
+ FindDrmDisplayHostById(params[i].display_id));
+ if (it == old_displays.end()) {
+ displays_.push_back(make_scoped_ptr(
+ new DrmDisplayHost(proxy_, params[i], false /* is_dummy */)));
+ } else {
+ (*it)->UpdateDisplaySnapshot(params[i]);
+ displays_.push_back(std::move(*it));
+ old_displays.erase(it);
+ }
+ }
+
+ if (!get_displays_callback_.is_null()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmDisplayHostManager::RunUpdateDisplaysCallback,
+ weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
+ get_displays_callback_.Reset();
+ }
}
-void DrmDisplayHostManager::OnHDCPStateUpdated(int64_t display_id,
- bool status) {
- core_->GpuUpdatedHDCPState(display_id, status);
+void DrmDisplayHostManager::GpuConfiguredDisplay(int64_t display_id,
+ bool status) {
+ DrmDisplayHost* display = GetDisplay(display_id);
+ if (display)
+ display->OnDisplayConfigured(status);
+ else
+ LOG(ERROR) << "Couldn't find display with id=" << display_id;
}
-void DrmDisplayHostManager::OnTakeDisplayControl(bool status) {
- core_->GpuTookDisplayControl(status);
+void DrmDisplayHostManager::GpuReceivedHDCPState(int64_t display_id,
+ bool status,
+ HDCPState state) {
+ DrmDisplayHost* display = GetDisplay(display_id);
+ if (display)
+ display->OnHDCPStateReceived(status, state);
+ else
+ LOG(ERROR) << "Couldn't find display with id=" << display_id;
}
-void DrmDisplayHostManager::OnRelinquishDisplayControl(bool status) {
- core_->GpuRelinquishedDisplayControl(status);
+void DrmDisplayHostManager::GpuUpdatedHDCPState(int64_t display_id,
+ bool status) {
+ DrmDisplayHost* display = GetDisplay(display_id);
+ if (display)
+ display->OnHDCPStateUpdated(status);
+ else
+ LOG(ERROR) << "Couldn't find display with id=" << display_id;
}
-DrmDisplayHostManager::HostManagerIPC::HostManagerIPC(
- DrmGpuPlatformSupportHost* proxy,
- DrmDisplayHostManager* parent)
- : proxy_(proxy), parent_(parent) {}
+void DrmDisplayHostManager::GpuTookDisplayControl(bool status) {
+ if (take_display_control_callback_.is_null()) {
+ LOG(ERROR) << "No callback for take display control";
+ return;
+ }
-DrmDisplayHostManager::HostManagerIPC::~HostManagerIPC() {
- proxy_->UnregisterHandler(parent_);
-}
+ DCHECK(display_externally_controlled_);
+ DCHECK(display_control_change_pending_);
-void DrmDisplayHostManager::HostManagerIPC::RegisterHandler() {
- proxy_->RegisterHandler(parent_);
-}
+ if (status) {
+ input_controller_->SetInputDevicesEnabled(true);
+ display_externally_controlled_ = false;
+ }
-DrmGpuPlatformSupportHost*
-DrmDisplayHostManager::HostManagerIPC::GetGpuPlatformSupportHost() {
- return proxy_;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(take_display_control_callback_, status));
+ take_display_control_callback_.Reset();
+ display_control_change_pending_ = false;
}
-bool DrmDisplayHostManager::HostManagerIPC::RefreshNativeDisplays() {
- return proxy_->Send(new OzoneGpuMsg_RefreshNativeDisplays());
-}
+void DrmDisplayHostManager::GpuRelinquishedDisplayControl(bool status) {
+ if (relinquish_display_control_callback_.is_null()) {
+ LOG(ERROR) << "No callback for relinquish display control";
+ return;
+ }
-bool DrmDisplayHostManager::HostManagerIPC::TakeDisplayControl() {
- return proxy_->Send(new OzoneGpuMsg_TakeDisplayControl());
-}
+ DCHECK(!display_externally_controlled_);
+ DCHECK(display_control_change_pending_);
-bool DrmDisplayHostManager::HostManagerIPC::RelinquishDisplayControl() {
- return proxy_->Send(new OzoneGpuMsg_RelinquishDisplayControl());
+ if (status) {
+ input_controller_->SetInputDevicesEnabled(false);
+ display_externally_controlled_ = true;
+ }
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(relinquish_display_control_callback_, status));
+ relinquish_display_control_callback_.Reset();
+ display_control_change_pending_ = false;
}
-bool DrmDisplayHostManager::HostManagerIPC::AddGraphicsDevice(
- const base::FilePath& path,
- base::FileDescriptor fd) {
- return proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(path, fd));
+void DrmDisplayHostManager::RunUpdateDisplaysCallback(
+ const GetDisplaysCallback& callback) const {
+ std::vector<DisplaySnapshot*> snapshots;
+ for (const auto& display : displays_)
+ snapshots.push_back(display->snapshot());
+
+ callback.Run(snapshots);
}
-bool DrmDisplayHostManager::HostManagerIPC::RemoveGraphicsDevice(
- const base::FilePath& path) {
- return proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path));
+void DrmDisplayHostManager::NotifyDisplayDelegate() const {
+ if (delegate_)
+ delegate_->OnConfigurationChanged();
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
index 1079e199628..fbe10ef6394 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
@@ -7,82 +7,136 @@
#include <stdint.h>
+#include <map>
+#include <queue>
+
+#include "base/file_descriptor_posix.h"
+#include "base/files/scoped_file.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
#include "ui/display/types/native_display_delegate.h"
-#include "ui/ozone/platform/drm/host/drm_display_host_manager_core.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
+#include "ui/events/ozone/device/device_event.h"
+#include "ui/events/ozone/device/device_event_observer.h"
+#include "ui/events/ozone/evdev/event_factory_evdev.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
namespace ui {
class DeviceManager;
+class DrmDeviceHandle;
class DrmDisplayHost;
+class DrmDisplayHostManager;
class DrmGpuPlatformSupportHost;
class DrmNativeDisplayDelegate;
+class GpuThreadAdapter;
struct DisplaySnapshot_Params;
-class DrmDisplayHostManager : public GpuPlatformSupportHost {
+// The portion of the DrmDisplayHostManager implementation that is agnostic
+// in how its communication with GPU-specific functionality is implemented.
+// This is used from both the IPC and the in-process versions in MUS.
+class DrmDisplayHostManager : public DeviceEventObserver, GpuThreadObserver {
public:
- DrmDisplayHostManager(DrmGpuPlatformSupportHost* proxy,
+ DrmDisplayHostManager(GpuThreadAdapter* proxy,
DeviceManager* device_manager,
InputControllerEvdev* input_controller);
~DrmDisplayHostManager() override;
DrmDisplayHost* GetDisplay(int64_t display_id);
+
+ // External API.
void AddDelegate(DrmNativeDisplayDelegate* delegate);
void RemoveDelegate(DrmNativeDisplayDelegate* delegate);
-
void TakeDisplayControl(const DisplayControlCallback& callback);
void RelinquishDisplayControl(const DisplayControlCallback& callback);
void UpdateDisplays(const GetDisplaysCallback& callback);
- // IPC::Listener (by way of GpuPlatformSupportHost) overrides:
- void OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& send_callback) override;
- void OnChannelDestroyed(int host_id) override;
- bool OnMessageReceived(const IPC::Message& message) override;
+ // DeviceEventObserver overrides:
+ void OnDeviceEvent(const DeviceEvent& event) override;
+
+ // GpuThreadObserver overrides:
+ void OnGpuThreadReady() override;
+ void OnGpuThreadRetired() override;
+
+ // Communication-free implementations of actions performed in response to
+ // messages from the GPU thread.
+ void GpuHasUpdatedNativeDisplays(
+ const std::vector<DisplaySnapshot_Params>& displays);
+ void GpuConfiguredDisplay(int64_t display_id, bool status);
+ void GpuReceivedHDCPState(int64_t display_id, bool status, HDCPState state);
+ void GpuUpdatedHDCPState(int64_t display_id, bool status);
+ void GpuTookDisplayControl(bool status);
+ void GpuRelinquishedDisplayControl(bool status);
private:
- // Concrete implementation of sending messages to the GPU thread hosted
- // functionality.
- class HostManagerIPC : public DrmDisplayHostManagerProxy {
- public:
- HostManagerIPC(DrmGpuPlatformSupportHost* proxy,
- DrmDisplayHostManager* parent);
- ~HostManagerIPC() override;
-
- void RegisterHandler() override;
- DrmGpuPlatformSupportHost* GetGpuPlatformSupportHost() override;
- bool TakeDisplayControl() override;
- bool RefreshNativeDisplays() override;
- bool RelinquishDisplayControl() override;
- bool AddGraphicsDevice(const base::FilePath& path,
- base::FileDescriptor fd) override;
- bool RemoveGraphicsDevice(const base::FilePath& path) override;
-
- private:
- DrmGpuPlatformSupportHost* proxy_;
- DrmDisplayHostManager* parent_;
-
- DISALLOW_COPY_AND_ASSIGN(HostManagerIPC);
+ struct DisplayEvent {
+ DisplayEvent(DeviceEvent::ActionType action_type,
+ const base::FilePath& path)
+ : action_type(action_type), path(path) {}
+
+ DeviceEvent::ActionType action_type;
+ base::FilePath path;
};
- // IPC Entry points.
- void OnUpdateNativeDisplays(
- const std::vector<DisplaySnapshot_Params>& displays);
- void OnDisplayConfigured(int64_t display_id, bool status);
- void OnHDCPStateReceived(int64_t display_id, bool status, HDCPState state);
- void OnHDCPStateUpdated(int64_t display_id, bool status);
- void OnTakeDisplayControl(bool status);
- void OnRelinquishDisplayControl(bool status);
+ // Handle hotplug events sequentially.
+ void ProcessEvent();
+
+ // Called as a result of finishing to process the display hotplug event. These
+ // are responsible for dequing the event and scheduling the next event.
+ void OnAddGraphicsDevice(const base::FilePath& path,
+ const base::FilePath& sysfs_path,
+ scoped_ptr<DrmDeviceHandle> handle);
+ void OnUpdateGraphicsDevice();
+ void OnRemoveGraphicsDevice(const base::FilePath& path);
+
+ void RunUpdateDisplaysCallback(const GetDisplaysCallback& callback) const;
+
+ void NotifyDisplayDelegate() const;
+
+ GpuThreadAdapter* proxy_; // Not owned.
+ DeviceManager* device_manager_; // Not owned.
+ InputControllerEvdev* input_controller_; // Not owned.
+
+ DrmNativeDisplayDelegate* delegate_ = nullptr; // Not owned.
+
+ // File path for the primary graphics card which is opened by default in the
+ // GPU process. We'll avoid opening this in hotplug events since it will race
+ // with the GPU process trying to open it and aquire DRM master.
+ base::FilePath primary_graphics_card_path_;
+
+ // Keeps track if there is a dummy display. This happens on initialization
+ // when there is no connection to the GPU to update the displays.
+ bool has_dummy_display_ = false;
+
+ std::vector<scoped_ptr<DrmDisplayHost>> displays_;
+
+ GetDisplaysCallback get_displays_callback_;
+
+ bool display_externally_controlled_ = false;
+ bool display_control_change_pending_ = false;
+ DisplayControlCallback take_display_control_callback_;
+ DisplayControlCallback relinquish_display_control_callback_;
+
+ // Used to serialize display event processing. This is done since
+ // opening/closing DRM devices cannot be done on the UI thread and are handled
+ // on a worker thread. Thus, we need to queue events in order to process them
+ // in the correct order.
+ std::queue<DisplayEvent> event_queue_;
+
+ // True if a display event is currently being processed on a worker thread.
+ bool task_pending_ = false;
+
+ // Keeps track of all the active DRM devices. The key is the device path, the
+ // value is the sysfs path which has been resolved from the device path.
+ std::map<base::FilePath, base::FilePath> drm_devices_;
- // Sends messages to the GPU thread.
- scoped_ptr<HostManagerIPC> sender_;
+ // This is used to cache the primary DRM device until the channel is
+ // established.
+ scoped_ptr<DrmDeviceHandle> primary_drm_device_handle_;
- // Implementation without messaging functionality.
- scoped_ptr<DrmDisplayHostManagerCore> core_;
+ base::WeakPtrFactory<DrmDisplayHostManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DrmDisplayHostManager);
};
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.cc
deleted file mode 100644
index 5d17cc4197c..00000000000
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/drm/host/drm_display_host_manager_core.h"
-
-#include <fcntl.h>
-#include <stddef.h>
-#include <xf86drm.h>
-#include <utility>
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/worker_pool.h"
-#include "ui/display/types/display_snapshot.h"
-#include "ui/events/ozone/device/device_event.h"
-#include "ui/events/ozone/device/device_manager.h"
-#include "ui/ozone/common/display_util.h"
-#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
-#include "ui/ozone/platform/drm/common/drm_util.h"
-#include "ui/ozone/platform/drm/host/drm_device_handle.h"
-#include "ui/ozone/platform/drm/host/drm_display_host.h"
-#include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
-#include "ui/ozone/platform/drm/host/drm_native_display_delegate.h"
-
-namespace ui {
-
-namespace {
-
-typedef base::Callback<void(const base::FilePath&,
- const base::FilePath&,
- scoped_ptr<DrmDeviceHandle>)>
- OnOpenDeviceReplyCallback;
-
-const char kDefaultGraphicsCardPattern[] = "/dev/dri/card%d";
-const char kVgemDevDriCardPath[] = "/dev/dri/";
-const char kVgemSysCardPath[] = "/sys/bus/platform/devices/vgem/drm/";
-
-const char* kDisplayActionString[] = {
- "ADD", "REMOVE", "CHANGE",
-};
-
-// Find sysfs device path for the given device path.
-base::FilePath MapDevPathToSysPath(const base::FilePath& device_path) {
- // |device_path| looks something like /dev/dri/card0. We take the basename of
- // that (card0) and append it to /sys/class/drm. /sys/class/drm/card0 is a
- // symlink that points to something like
- // /sys/devices/pci0000:00/0000:00:02.0/0000:05:00.0/drm/card0, which exposes
- // some metadata about the attached device.
- return base::MakeAbsoluteFilePath(
- base::FilePath("/sys/class/drm").Append(device_path.BaseName()));
-}
-
-void OpenDeviceOnWorkerThread(
- const base::FilePath& device_path,
- const scoped_refptr<base::TaskRunner>& reply_runner,
- const OnOpenDeviceReplyCallback& callback) {
- base::FilePath sys_path = MapDevPathToSysPath(device_path);
-
- scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle());
- handle->Initialize(device_path, sys_path);
- reply_runner->PostTask(FROM_HERE,
- base::Bind(callback, device_path, sys_path,
- base::Passed(std::move(handle))));
-}
-
-base::FilePath GetPrimaryDisplayCardPath() {
- struct drm_mode_card_res res;
- for (int i = 0; /* end on first card# that does not exist */; i++) {
- std::string card_path = base::StringPrintf(kDefaultGraphicsCardPattern, i);
-
- if (access(card_path.c_str(), F_OK) != 0)
- break;
-
- int fd = open(card_path.c_str(), O_RDWR | O_CLOEXEC);
- if (fd < 0) {
- VPLOG(1) << "Failed to open '" << card_path << "'";
- continue;
- }
-
- memset(&res, 0, sizeof(struct drm_mode_card_res));
- int ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
- close(fd);
- if (ret == 0 && res.count_crtcs > 0) {
- return base::FilePath(card_path);
- }
-
- VPLOG_IF(1, ret) << "Failed to get DRM resources for '" << card_path << "'";
- }
-
- LOG(FATAL) << "Failed to open primary graphics device.";
- return base::FilePath(); // Not reached.
-}
-
-base::FilePath GetVgemCardPath() {
- base::FileEnumerator file_iter(base::FilePath(kVgemSysCardPath), false,
- base::FileEnumerator::DIRECTORIES,
- FILE_PATH_LITERAL("card*"));
-
- while (!file_iter.Next().empty()) {
- // Inspect the card%d directories in the directory and extract the filename.
- std::string vgem_card_path =
- kVgemDevDriCardPath + file_iter.GetInfo().GetName().BaseName().value();
- DVLOG(1) << "VGEM card path is " << vgem_card_path;
- return base::FilePath(vgem_card_path);
- }
- DVLOG(1) << "Don't support VGEM";
- return base::FilePath();
-}
-
-class FindDrmDisplayHostById {
- public:
- explicit FindDrmDisplayHostById(int64_t display_id)
- : display_id_(display_id) {}
-
- bool operator()(const scoped_ptr<DrmDisplayHost>& display) const {
- return display->snapshot()->display_id() == display_id_;
- }
-
- private:
- int64_t display_id_;
-};
-
-} // namespace
-
-DrmDisplayHostManagerProxy::~DrmDisplayHostManagerProxy() {}
-
-DrmDisplayHostManagerCore::DrmDisplayHostManagerCore(
- DrmDisplayHostManagerProxy* proxy,
- DeviceManager* device_manager,
- InputControllerEvdev* input_controller)
- : proxy_(proxy),
- device_manager_(device_manager),
- input_controller_(input_controller),
- primary_graphics_card_path_(GetPrimaryDisplayCardPath()),
- weak_ptr_factory_(this) {
- {
- // First device needs to be treated specially. We need to open this
- // synchronously since the GPU process will need it to initialize the
- // graphics state.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
-
- base::FilePath primary_graphics_card_path_sysfs =
- MapDevPathToSysPath(primary_graphics_card_path_);
-
- primary_drm_device_handle_.reset(new DrmDeviceHandle());
- if (!primary_drm_device_handle_->Initialize(
- primary_graphics_card_path_, primary_graphics_card_path_sysfs)) {
- LOG(FATAL) << "Failed to open primary graphics card";
- return;
- }
- drm_devices_[primary_graphics_card_path_] =
- primary_graphics_card_path_sysfs;
-
- vgem_card_path_ = GetVgemCardPath();
- }
-
- device_manager_->AddObserver(this);
- proxy_->RegisterHandler();
-
- ScopedVector<HardwareDisplayControllerInfo> display_infos =
- GetAvailableDisplayControllerInfos(primary_drm_device_handle_->fd());
- has_dummy_display_ = !display_infos.empty();
- for (size_t i = 0; i < display_infos.size(); ++i) {
- displays_.push_back(make_scoped_ptr(new DrmDisplayHost(
- proxy_->GetGpuPlatformSupportHost(),
- CreateDisplaySnapshotParams(
- display_infos[i], primary_drm_device_handle_->fd(),
- primary_drm_device_handle_->sys_path(), 0, gfx::Point()),
- true /* is_dummy */)));
- }
-}
-
-DrmDisplayHostManagerCore::~DrmDisplayHostManagerCore() {
- device_manager_->RemoveObserver(this);
-}
-
-DrmDisplayHost* DrmDisplayHostManagerCore::GetDisplay(int64_t display_id) {
- auto it = std::find_if(displays_.begin(), displays_.end(),
- FindDrmDisplayHostById(display_id));
- if (it == displays_.end())
- return nullptr;
-
- return it->get();
-}
-
-void DrmDisplayHostManagerCore::AddDelegate(
- DrmNativeDisplayDelegate* delegate) {
- DCHECK(!delegate_);
- delegate_ = delegate;
-}
-
-void DrmDisplayHostManagerCore::RemoveDelegate(
- DrmNativeDisplayDelegate* delegate) {
- DCHECK_EQ(delegate_, delegate);
- delegate_ = nullptr;
-}
-
-void DrmDisplayHostManagerCore::TakeDisplayControl(
- const DisplayControlCallback& callback) {
- if (display_control_change_pending_) {
- LOG(ERROR) << "TakeDisplayControl called while change already pending";
- callback.Run(false);
- return;
- }
-
- if (!display_externally_controlled_) {
- LOG(ERROR) << "TakeDisplayControl called while display already owned";
- callback.Run(true);
- return;
- }
-
- take_display_control_callback_ = callback;
- display_control_change_pending_ = true;
-
- if (!proxy_->TakeDisplayControl())
- GpuTookDisplayControl(false);
-}
-
-void DrmDisplayHostManagerCore::RelinquishDisplayControl(
- const DisplayControlCallback& callback) {
- if (display_control_change_pending_) {
- LOG(ERROR)
- << "RelinquishDisplayControl called while change already pending";
- callback.Run(false);
- return;
- }
-
- if (display_externally_controlled_) {
- LOG(ERROR) << "RelinquishDisplayControl called while display not owned";
- callback.Run(true);
- return;
- }
-
- relinquish_display_control_callback_ = callback;
- display_control_change_pending_ = true;
-
- if (!proxy_->RelinquishDisplayControl())
- GpuRelinquishedDisplayControl(false);
-}
-
-void DrmDisplayHostManagerCore::UpdateDisplays(
- const GetDisplaysCallback& callback) {
- get_displays_callback_ = callback;
- if (!proxy_->RefreshNativeDisplays()) {
- get_displays_callback_.Reset();
- RunUpdateDisplaysCallback(callback);
- }
-}
-
-void DrmDisplayHostManagerCore::OnDeviceEvent(const DeviceEvent& event) {
- if (event.device_type() != DeviceEvent::DISPLAY)
- return;
-
- event_queue_.push(DisplayEvent(event.action_type(), event.path()));
- ProcessEvent();
-}
-
-void DrmDisplayHostManagerCore::ProcessEvent() {
- while (!event_queue_.empty() && !task_pending_) {
- DisplayEvent event = event_queue_.front();
- event_queue_.pop();
- VLOG(1) << "Got display event " << kDisplayActionString[event.action_type]
- << " for " << event.path.value();
- switch (event.action_type) {
- case DeviceEvent::ADD:
- if (event.path == vgem_card_path_)
- continue;
- if (drm_devices_.find(event.path) == drm_devices_.end()) {
- task_pending_ = base::WorkerPool::PostTask(
- FROM_HERE,
- base::Bind(
- &OpenDeviceOnWorkerThread, event.path,
- base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&DrmDisplayHostManagerCore::OnAddGraphicsDevice,
- weak_ptr_factory_.GetWeakPtr())),
- false /* task_is_slow */);
- }
- break;
- case DeviceEvent::CHANGE:
- task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&DrmDisplayHostManagerCore::OnUpdateGraphicsDevice,
- weak_ptr_factory_.GetWeakPtr()));
- break;
- case DeviceEvent::REMOVE:
- DCHECK(event.path != primary_graphics_card_path_)
- << "Removing primary graphics card";
- DCHECK(event.path != vgem_card_path_) << "Removing VGEM device";
- auto it = drm_devices_.find(event.path);
- if (it != drm_devices_.end()) {
- task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&DrmDisplayHostManagerCore::OnRemoveGraphicsDevice,
- weak_ptr_factory_.GetWeakPtr(), it->second));
- drm_devices_.erase(it);
- }
- break;
- }
- }
-}
-
-void DrmDisplayHostManagerCore::OnAddGraphicsDevice(
- const base::FilePath& dev_path,
- const base::FilePath& sys_path,
- scoped_ptr<DrmDeviceHandle> handle) {
- if (handle->IsValid()) {
- drm_devices_[dev_path] = sys_path;
- proxy_->AddGraphicsDevice(sys_path, base::FileDescriptor(handle->PassFD()));
- NotifyDisplayDelegate();
- }
-
- task_pending_ = false;
- ProcessEvent();
-}
-
-void DrmDisplayHostManagerCore::OnUpdateGraphicsDevice() {
- NotifyDisplayDelegate();
- task_pending_ = false;
- ProcessEvent();
-}
-
-void DrmDisplayHostManagerCore::OnRemoveGraphicsDevice(
- const base::FilePath& sys_path) {
- proxy_->RemoveGraphicsDevice(sys_path);
- NotifyDisplayDelegate();
- task_pending_ = false;
- ProcessEvent();
-}
-
-void DrmDisplayHostManagerCore::GpuThreadStarted() {
- // If in the middle of a configuration, just respond with the old list of
- // displays. This is fine, since after the DRM resources are initialized and
- // IPC-ed to the GPU NotifyDisplayDelegate() is called to let the display
- // delegate know that the display configuration changed and it needs to
- // update it again.
- if (!get_displays_callback_.is_null()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&DrmDisplayHostManagerCore::RunUpdateDisplaysCallback,
- weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
- get_displays_callback_.Reset();
- }
-
- // Signal that we're taking DRM master since we're going through the
- // initialization process again and we'll take all the available resources.
- if (!take_display_control_callback_.is_null())
- GpuTookDisplayControl(true);
-
- if (!relinquish_display_control_callback_.is_null())
- GpuRelinquishedDisplayControl(false);
-
- scoped_ptr<DrmDeviceHandle> handle = std::move(primary_drm_device_handle_);
- {
- base::ThreadRestrictions::ScopedAllowIO allow_io;
-
- drm_devices_.clear();
- drm_devices_[primary_graphics_card_path_] =
- MapDevPathToSysPath(primary_graphics_card_path_);
-
- if (!handle) {
- handle.reset(new DrmDeviceHandle());
- if (!handle->Initialize(primary_graphics_card_path_,
- drm_devices_[primary_graphics_card_path_]))
- LOG(FATAL) << "Failed to open primary graphics card";
- }
- }
-
- // Send the primary device first since this is used to initialize graphics
- // state.
- proxy_->AddGraphicsDevice(drm_devices_[primary_graphics_card_path_],
- base::FileDescriptor(handle->PassFD()));
-
- device_manager_->ScanDevices(this);
- NotifyDisplayDelegate();
-}
-
-void DrmDisplayHostManagerCore::GpuHasUpdatedNativeDisplays(
- const std::vector<DisplaySnapshot_Params>& params) {
- std::vector<scoped_ptr<DrmDisplayHost>> old_displays;
- displays_.swap(old_displays);
- for (size_t i = 0; i < params.size(); ++i) {
- auto it = std::find_if(old_displays.begin(), old_displays.end(),
- FindDrmDisplayHostById(params[i].display_id));
- if (it == old_displays.end()) {
- displays_.push_back(make_scoped_ptr(
- new DrmDisplayHost(proxy_->GetGpuPlatformSupportHost(), params[i],
- false /* is_dummy */)));
- } else {
- (*it)->UpdateDisplaySnapshot(params[i]);
- displays_.push_back(std::move(*it));
- old_displays.erase(it);
- }
- }
-
- if (!get_displays_callback_.is_null()) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&DrmDisplayHostManagerCore::RunUpdateDisplaysCallback,
- weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
- get_displays_callback_.Reset();
- }
-}
-
-void DrmDisplayHostManagerCore::GpuConfiguredDisplay(int64_t display_id,
- bool status) {
- DrmDisplayHost* display = GetDisplay(display_id);
- if (display)
- display->OnDisplayConfigured(status);
- else
- LOG(ERROR) << "Couldn't find display with id=" << display_id;
-}
-
-void DrmDisplayHostManagerCore::GpuReceivedHDCPState(int64_t display_id,
- bool status,
- HDCPState state) {
- DrmDisplayHost* display = GetDisplay(display_id);
- if (display)
- display->OnHDCPStateReceived(status, state);
- else
- LOG(ERROR) << "Couldn't find display with id=" << display_id;
-}
-
-void DrmDisplayHostManagerCore::GpuUpdatedHDCPState(int64_t display_id,
- bool status) {
- DrmDisplayHost* display = GetDisplay(display_id);
- if (display)
- display->OnHDCPStateUpdated(status);
- else
- LOG(ERROR) << "Couldn't find display with id=" << display_id;
-}
-
-void DrmDisplayHostManagerCore::GpuTookDisplayControl(bool status) {
- if (take_display_control_callback_.is_null()) {
- LOG(ERROR) << "No callback for take display control";
- return;
- }
-
- DCHECK(display_externally_controlled_);
- DCHECK(display_control_change_pending_);
-
- if (status) {
- input_controller_->SetInputDevicesEnabled(true);
- display_externally_controlled_ = false;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(take_display_control_callback_, status));
- take_display_control_callback_.Reset();
- display_control_change_pending_ = false;
-}
-
-void DrmDisplayHostManagerCore::GpuRelinquishedDisplayControl(bool status) {
- if (relinquish_display_control_callback_.is_null()) {
- LOG(ERROR) << "No callback for relinquish display control";
- return;
- }
-
- DCHECK(!display_externally_controlled_);
- DCHECK(display_control_change_pending_);
-
- if (status) {
- input_controller_->SetInputDevicesEnabled(false);
- display_externally_controlled_ = true;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(relinquish_display_control_callback_, status));
- relinquish_display_control_callback_.Reset();
- display_control_change_pending_ = false;
-}
-
-void DrmDisplayHostManagerCore::RunUpdateDisplaysCallback(
- const GetDisplaysCallback& callback) const {
- std::vector<DisplaySnapshot*> snapshots;
- for (const auto& display : displays_)
- snapshots.push_back(display->snapshot());
-
- callback.Run(snapshots);
-}
-
-void DrmDisplayHostManagerCore::NotifyDisplayDelegate() const {
- if (delegate_)
- delegate_->OnConfigurationChanged();
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.h b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.h
deleted file mode 100644
index c9f9f316665..00000000000
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager_core.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_CORE_H_
-#define UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_CORE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <queue>
-
-#include "base/file_descriptor_posix.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/display/types/native_display_delegate.h"
-#include "ui/events/ozone/device/device_event.h"
-#include "ui/events/ozone/device/device_event_observer.h"
-#include "ui/events/ozone/evdev/event_factory_evdev.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
-
-namespace ui {
-
-class DeviceManager;
-class DrmDeviceHandle;
-class DrmDisplayHost;
-class DrmDisplayHostManagerCore;
-class DrmGpuPlatformSupportHost;
-class DrmNativeDisplayDelegate;
-
-struct DisplaySnapshot_Params;
-
-// The concrete implementation of DrmDisplayHostManagerCoreProxy contains all
-// the
-// necessary code for the DrmDisplayHostManagerCoreCore to communicate with
-// the GPU child thread whether by IPC or thead-hop.
-class DrmDisplayHostManagerProxy {
- public:
- virtual ~DrmDisplayHostManagerProxy();
- virtual void RegisterHandler() = 0;
- virtual DrmGpuPlatformSupportHost* GetGpuPlatformSupportHost() = 0;
- virtual bool TakeDisplayControl() = 0;
- virtual bool RefreshNativeDisplays() = 0;
- virtual bool RelinquishDisplayControl() = 0;
- virtual bool AddGraphicsDevice(const base::FilePath& path,
- base::FileDescriptor fd) = 0;
- virtual bool RemoveGraphicsDevice(const base::FilePath& path) = 0;
-};
-
-// The portion of the DrmDisplayHostManagerCore implementation that is agnostic
-// in how its communication with GPU-specific functionality is implemented.
-// This is used from both the IPC and the in-process versions in MUS.
-class DrmDisplayHostManagerCore : public DeviceEventObserver {
- public:
- DrmDisplayHostManagerCore(DrmDisplayHostManagerProxy* proxy,
- DeviceManager* device_manager,
- InputControllerEvdev* input_controller);
- ~DrmDisplayHostManagerCore() override;
-
- DrmDisplayHost* GetDisplay(int64_t display_id);
-
- // External API.
- void AddDelegate(DrmNativeDisplayDelegate* delegate);
- void RemoveDelegate(DrmNativeDisplayDelegate* delegate);
- void TakeDisplayControl(const DisplayControlCallback& callback);
- void RelinquishDisplayControl(const DisplayControlCallback& callback);
- void UpdateDisplays(const GetDisplaysCallback& callback);
-
- // DeviceEventObserver overrides:
- void OnDeviceEvent(const DeviceEvent& event) override;
-
- // Communication-free implementations of actions performed in response to
- // messages from the GPU thread.
- void GpuThreadStarted();
- void GpuHasUpdatedNativeDisplays(
- const std::vector<DisplaySnapshot_Params>& displays);
- void GpuConfiguredDisplay(int64_t display_id, bool status);
- void GpuReceivedHDCPState(int64_t display_id, bool status, HDCPState state);
- void GpuUpdatedHDCPState(int64_t display_id, bool status);
- void GpuTookDisplayControl(bool status);
- void GpuRelinquishedDisplayControl(bool status);
-
- private:
- struct DisplayEvent {
- DisplayEvent(DeviceEvent::ActionType action_type,
- const base::FilePath& path)
- : action_type(action_type), path(path) {}
-
- DeviceEvent::ActionType action_type;
- base::FilePath path;
- };
-
- // Handle hotplug events sequentially.
- void ProcessEvent();
-
- // Called as a result of finishing to process the display hotplug event. These
- // are responsible for dequing the event and scheduling the next event.
- void OnAddGraphicsDevice(const base::FilePath& path,
- const base::FilePath& sysfs_path,
- scoped_ptr<DrmDeviceHandle> handle);
- void OnUpdateGraphicsDevice();
- void OnRemoveGraphicsDevice(const base::FilePath& path);
-
- void RunUpdateDisplaysCallback(const GetDisplaysCallback& callback) const;
-
- void NotifyDisplayDelegate() const;
-
- DrmDisplayHostManagerProxy* proxy_; // Not owned.
- DeviceManager* device_manager_; // Not owned.
- InputControllerEvdev* input_controller_; // Not owned.
-
- DrmNativeDisplayDelegate* delegate_ = nullptr; // Not owned.
-
- // File path for the primary graphics card which is opened by default in the
- // GPU process. We'll avoid opening this in hotplug events since it will race
- // with the GPU process trying to open it and aquire DRM master.
- base::FilePath primary_graphics_card_path_;
-
- // File path for virtual gem (VGEM) device.
- base::FilePath vgem_card_path_;
-
- // Keeps track if there is a dummy display. This happens on initialization
- // when there is no connection to the GPU to update the displays.
- bool has_dummy_display_ = false;
-
- std::vector<scoped_ptr<DrmDisplayHost>> displays_;
-
- GetDisplaysCallback get_displays_callback_;
-
- bool display_externally_controlled_ = false;
- bool display_control_change_pending_ = false;
- DisplayControlCallback take_display_control_callback_;
- DisplayControlCallback relinquish_display_control_callback_;
-
- // Used to serialize display event processing. This is done since
- // opening/closing DRM devices cannot be done on the UI thread and are handled
- // on a worker thread. Thus, we need to queue events in order to process them
- // in the correct order.
- std::queue<DisplayEvent> event_queue_;
-
- // True if a display event is currently being processed on a worker thread.
- bool task_pending_ = false;
-
- // Keeps track of all the active DRM devices. The key is the device path, the
- // value is the sysfs path which has been resolved from the device path.
- std::map<base::FilePath, base::FilePath> drm_devices_;
-
- // This is used to cache the primary DRM device until the channel is
- // established.
- scoped_ptr<DrmDeviceHandle> primary_drm_device_handle_;
-
- base::WeakPtrFactory<DrmDisplayHostManagerCore> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DrmDisplayHostManagerCore);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_CORE_H_
diff --git a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
index cbf759721e8..9f42ec2024f 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -9,44 +9,91 @@
#include "base/trace_event/trace_event.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
-#include "ui/ozone/platform/drm/host/channel_observer.h"
#include "ui/ozone/platform/drm/host/drm_cursor.h"
+#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
namespace ui {
-DrmGpuPlatformSupportHost::DrmGpuPlatformSupportHost(DrmCursor* cursor)
- : cursor_(cursor) {
-}
+namespace {
+
+// Helper class that provides DrmCursor with a mechanism to send messages
+// to the GPU process.
+class CursorIPC : public DrmCursorProxy {
+ public:
+ CursorIPC(scoped_refptr<base::SingleThreadTaskRunner> send_runner,
+ const base::Callback<void(IPC::Message*)>& send_callback);
+ ~CursorIPC() override;
+
+ // DrmCursorProxy implementation.
+ void CursorSet(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) override;
+ void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override;
+
+ private:
+ bool IsConnected();
+ void Send(IPC::Message* message);
-DrmGpuPlatformSupportHost::~DrmGpuPlatformSupportHost() {
+ scoped_refptr<base::SingleThreadTaskRunner> send_runner_;
+ base::Callback<void(IPC::Message*)> send_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(CursorIPC);
+};
+
+CursorIPC::CursorIPC(scoped_refptr<base::SingleThreadTaskRunner> send_runner,
+ const base::Callback<void(IPC::Message*)>& send_callback)
+ : send_runner_(send_runner), send_callback_(send_callback) {}
+
+CursorIPC::~CursorIPC() {}
+
+bool CursorIPC::IsConnected() {
+ return !send_callback_.is_null();
}
-void DrmGpuPlatformSupportHost::RegisterHandler(
- GpuPlatformSupportHost* handler) {
- handlers_.push_back(handler);
+void CursorIPC::CursorSet(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) {
+ Send(new OzoneGpuMsg_CursorSet(window, bitmaps, point, frame_delay_ms));
+}
- if (IsConnected())
- handler->OnChannelEstablished(host_id_, send_runner_, send_callback_);
+void CursorIPC::Move(gfx::AcceleratedWidget window, const gfx::Point& point) {
+ Send(new OzoneGpuMsg_CursorMove(window, point));
}
-void DrmGpuPlatformSupportHost::UnregisterHandler(
- GpuPlatformSupportHost* handler) {
- std::vector<GpuPlatformSupportHost*>::iterator it =
- std::find(handlers_.begin(), handlers_.end(), handler);
- if (it != handlers_.end())
- handlers_.erase(it);
+void CursorIPC::Send(IPC::Message* message) {
+ if (IsConnected() &&
+ send_runner_->PostTask(FROM_HERE, base::Bind(send_callback_, message)))
+ return;
+
+ // Drop disconnected updates. DrmWindowHost will call
+ // CommitBoundsChange() when we connect to initialize the cursor
+ // location.
+ delete message;
}
-void DrmGpuPlatformSupportHost::AddChannelObserver(ChannelObserver* observer) {
- channel_observers_.AddObserver(observer);
+} // namespace
+
+DrmGpuPlatformSupportHost::DrmGpuPlatformSupportHost(DrmCursor* cursor)
+ : cursor_(cursor) {}
+
+DrmGpuPlatformSupportHost::~DrmGpuPlatformSupportHost() {}
+
+void DrmGpuPlatformSupportHost::AddGpuThreadObserver(
+ GpuThreadObserver* observer) {
+ gpu_thread_observers_.AddObserver(observer);
if (IsConnected())
- observer->OnChannelEstablished();
+ observer->OnGpuThreadReady();
}
-void DrmGpuPlatformSupportHost::RemoveChannelObserver(
- ChannelObserver* observer) {
- channel_observers_.RemoveObserver(observer);
+void DrmGpuPlatformSupportHost::RemoveGpuThreadObserver(
+ GpuThreadObserver* observer) {
+ gpu_thread_observers_.RemoveObserver(observer);
}
bool DrmGpuPlatformSupportHost::IsConnected() {
@@ -63,41 +110,37 @@ void DrmGpuPlatformSupportHost::OnChannelEstablished(
send_runner_ = send_runner;
send_callback_ = send_callback;
- for (size_t i = 0; i < handlers_.size(); ++i)
- handlers_[i]->OnChannelEstablished(host_id, send_runner_, send_callback_);
-
- FOR_EACH_OBSERVER(ChannelObserver, channel_observers_,
- OnChannelEstablished());
+ FOR_EACH_OBSERVER(GpuThreadObserver, gpu_thread_observers_,
+ OnGpuThreadReady());
// The cursor is special since it will process input events on the IO thread
// and can by-pass the UI thread. This means that we need to special case it
// and notify it after all other observers/handlers are notified such that the
// (windowing) state on the GPU can be initialized before the cursor is
// allowed to IPC messages (which are targeted to a specific window).
- cursor_->OnChannelEstablished(host_id, send_runner_, send_callback_);
+ cursor_->SetDrmCursorProxy(new CursorIPC(send_runner_, send_callback_));
}
void DrmGpuPlatformSupportHost::OnChannelDestroyed(int host_id) {
TRACE_EVENT1("drm", "DrmGpuPlatformSupportHost::OnChannelDestroyed",
"host_id", host_id);
- cursor_->OnChannelDestroyed(host_id);
if (host_id_ == host_id) {
+ cursor_->ResetDrmCursorProxy();
host_id_ = -1;
send_runner_ = nullptr;
send_callback_.Reset();
- FOR_EACH_OBSERVER(ChannelObserver, channel_observers_,
- OnChannelDestroyed());
+ FOR_EACH_OBSERVER(GpuThreadObserver, gpu_thread_observers_,
+ OnGpuThreadRetired());
}
- for (size_t i = 0; i < handlers_.size(); ++i)
- handlers_[i]->OnChannelDestroyed(host_id);
}
bool DrmGpuPlatformSupportHost::OnMessageReceived(const IPC::Message& message) {
- for (size_t i = 0; i < handlers_.size(); ++i)
- if (handlers_[i]->OnMessageReceived(message))
- return true;
+ if (OnMessageReceivedForDrmDisplayHostManager(message))
+ return true;
+ if (OnMessageReceivedForDrmOverlayManager(message))
+ return true;
return false;
}
@@ -111,4 +154,164 @@ bool DrmGpuPlatformSupportHost::Send(IPC::Message* message) {
return false;
}
+// DisplayHost
+void DrmGpuPlatformSupportHost::RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) {
+ display_manager_ = handler;
+}
+
+void DrmGpuPlatformSupportHost::UnRegisterHandlerForDrmDisplayHostManager() {
+ display_manager_ = nullptr;
+}
+
+bool DrmGpuPlatformSupportHost::OnMessageReceivedForDrmDisplayHostManager(
+ const IPC::Message& message) {
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP(DrmGpuPlatformSupportHost, message)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_UpdateNativeDisplays,
+ OnUpdateNativeDisplays)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayConfigured, OnDisplayConfigured)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateReceived, OnHDCPStateReceived)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateUpdated, OnHDCPStateUpdated)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayControlTaken, OnTakeDisplayControl)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayControlRelinquished,
+ OnRelinquishDisplayControl)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void DrmGpuPlatformSupportHost::OnUpdateNativeDisplays(
+ const std::vector<DisplaySnapshot_Params>& params) {
+ display_manager_->GpuHasUpdatedNativeDisplays(params);
+}
+
+void DrmGpuPlatformSupportHost::OnDisplayConfigured(int64_t display_id,
+ bool status) {
+ display_manager_->GpuConfiguredDisplay(display_id, status);
+}
+
+void DrmGpuPlatformSupportHost::OnHDCPStateReceived(int64_t display_id,
+ bool status,
+ HDCPState state) {
+ display_manager_->GpuReceivedHDCPState(display_id, status, state);
+}
+
+void DrmGpuPlatformSupportHost::OnHDCPStateUpdated(int64_t display_id,
+ bool status) {
+ display_manager_->GpuUpdatedHDCPState(display_id, status);
+}
+
+void DrmGpuPlatformSupportHost::OnTakeDisplayControl(bool status) {
+ display_manager_->GpuTookDisplayControl(status);
+}
+
+void DrmGpuPlatformSupportHost::OnRelinquishDisplayControl(bool status) {
+ display_manager_->GpuRelinquishedDisplayControl(status);
+}
+
+bool DrmGpuPlatformSupportHost::GpuRefreshNativeDisplays() {
+ return Send(new OzoneGpuMsg_RefreshNativeDisplays());
+}
+
+bool DrmGpuPlatformSupportHost::GpuTakeDisplayControl() {
+ return Send(new OzoneGpuMsg_TakeDisplayControl());
+}
+
+bool DrmGpuPlatformSupportHost::GpuRelinquishDisplayControl() {
+ return Send(new OzoneGpuMsg_RelinquishDisplayControl());
+}
+
+bool DrmGpuPlatformSupportHost::GpuAddGraphicsDevice(
+ const base::FilePath& path,
+ const base::FileDescriptor& fd) {
+ return Send(new OzoneGpuMsg_AddGraphicsDevice(path, fd));
+}
+
+bool DrmGpuPlatformSupportHost::GpuRemoveGraphicsDevice(
+ const base::FilePath& path) {
+ return Send(new OzoneGpuMsg_RemoveGraphicsDevice(path));
+}
+
+// Overlays
+void DrmGpuPlatformSupportHost::RegisterHandlerForDrmOverlayManager(
+ DrmOverlayManager* handler) {
+ overlay_manager_ = handler;
+}
+
+void DrmGpuPlatformSupportHost::UnRegisterHandlerForDrmOverlayManager() {
+ overlay_manager_ = nullptr;
+}
+
+bool DrmGpuPlatformSupportHost::OnMessageReceivedForDrmOverlayManager(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DrmGpuPlatformSupportHost, message)
+ IPC_MESSAGE_HANDLER(OzoneHostMsg_OverlayCapabilitiesReceived,
+ OnOverlayResult)
+ // TODO(rjk): insert the extra
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void DrmGpuPlatformSupportHost::OnOverlayResult(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& params) {
+ overlay_manager_->GpuSentOverlayResult(widget, params);
+}
+
+bool DrmGpuPlatformSupportHost::GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& new_params) {
+ return Send(new OzoneGpuMsg_CheckOverlayCapabilities(widget, new_params));
+}
+
+// DrmDisplayHost
+bool DrmGpuPlatformSupportHost::GpuConfigureNativeDisplay(
+ int64_t display_id,
+ const ui::DisplayMode_Params& display_mode,
+ const gfx::Point& point) {
+ return Send(
+ new OzoneGpuMsg_ConfigureNativeDisplay(display_id, display_mode, point));
+}
+
+bool DrmGpuPlatformSupportHost::GpuDisableNativeDisplay(int64_t display_id) {
+ return Send(new OzoneGpuMsg_DisableNativeDisplay(display_id));
+}
+
+bool DrmGpuPlatformSupportHost::GpuGetHDCPState(int64_t display_id) {
+ return Send(new OzoneGpuMsg_GetHDCPState(display_id));
+}
+
+bool DrmGpuPlatformSupportHost::GpuSetHDCPState(int64_t display_id,
+ ui::HDCPState state) {
+ return Send(new OzoneGpuMsg_SetHDCPState(display_id, state));
+}
+
+bool DrmGpuPlatformSupportHost::GpuSetColorCorrection(
+ int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ return Send(new OzoneGpuMsg_SetColorCorrection(display_id, degamma_lut,
+ gamma_lut, correction_matrix));
+}
+
+bool DrmGpuPlatformSupportHost::GpuDestroyWindow(
+ gfx::AcceleratedWidget widget) {
+ return Send(new OzoneGpuMsg_DestroyWindow(widget));
+}
+
+bool DrmGpuPlatformSupportHost::GpuCreateWindow(gfx::AcceleratedWidget widget) {
+ return Send(new OzoneGpuMsg_CreateWindow(widget));
+}
+
+bool DrmGpuPlatformSupportHost::GpuWindowBoundsChanged(
+ gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) {
+ return Send(new OzoneGpuMsg_WindowBoundsChanged(widget, bounds));
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
index 7961fd1b7c7..2cc4a176f43 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
@@ -9,7 +9,10 @@
#include "base/callback.h"
#include "base/observer_list.h"
+#include "ui/display/types/display_constants.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
class SkBitmap;
@@ -20,23 +23,18 @@ class Point;
namespace ui {
-class ChannelObserver;
class DrmCursor;
+class DrmDisplayHostMananger;
+class DrmOverlayManager;
+class GpuThreadObserver;
class DrmGpuPlatformSupportHost : public GpuPlatformSupportHost,
+ public GpuThreadAdapter,
public IPC::Sender {
public:
DrmGpuPlatformSupportHost(DrmCursor* cursor);
~DrmGpuPlatformSupportHost() override;
- void RegisterHandler(GpuPlatformSupportHost* handler);
- void UnregisterHandler(GpuPlatformSupportHost* handler);
-
- void AddChannelObserver(ChannelObserver* observer);
- void RemoveChannelObserver(ChannelObserver* observer);
-
- bool IsConnected();
-
// GpuPlatformSupportHost:
void OnChannelEstablished(
int host_id,
@@ -50,15 +48,77 @@ class DrmGpuPlatformSupportHost : public GpuPlatformSupportHost,
// IPC::Sender:
bool Send(IPC::Message* message) override;
+ // GpuThreadAdapter.
+ // Core functionality.
+ void AddGpuThreadObserver(GpuThreadObserver* observer) override;
+ void RemoveGpuThreadObserver(GpuThreadObserver* observer) override;
+ bool IsConnected() override;
+
+ // Services needed for DrmDisplayHostMananger.
+ void RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) override;
+ void UnRegisterHandlerForDrmDisplayHostManager() override;
+
+ bool GpuTakeDisplayControl() override;
+ bool GpuRefreshNativeDisplays() override;
+ bool GpuRelinquishDisplayControl() override;
+ bool GpuAddGraphicsDevice(const base::FilePath& path,
+ const base::FileDescriptor& fd) override;
+ bool GpuRemoveGraphicsDevice(const base::FilePath& path) override;
+
+ // Methods needed for DrmOverlayManager.
+ // Methods for DrmOverlayManager.
+ void RegisterHandlerForDrmOverlayManager(DrmOverlayManager* handler) override;
+ void UnRegisterHandlerForDrmOverlayManager() override;
+
+ // Services needed by DrmOverlayManager
+ bool GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& new_params) override;
+
+ // Services needed by DrmDisplayHost
+ bool GpuConfigureNativeDisplay(int64_t display_id,
+ const ui::DisplayMode_Params& display_mode,
+ const gfx::Point& point) override;
+ bool GpuDisableNativeDisplay(int64_t display_id) override;
+ bool GpuGetHDCPState(int64_t display_id) override;
+ bool GpuSetHDCPState(int64_t display_id, ui::HDCPState state) override;
+ bool GpuSetColorCorrection(
+ int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) override;
+
+ // Services needed by DrmWindowHost
+ bool GpuDestroyWindow(gfx::AcceleratedWidget widget) override;
+ bool GpuCreateWindow(gfx::AcceleratedWidget widget) override;
+ bool GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) override;
+
private:
+ bool OnMessageReceivedForDrmDisplayHostManager(const IPC::Message& message);
+ void OnUpdateNativeDisplays(
+ const std::vector<DisplaySnapshot_Params>& displays);
+ void OnDisplayConfigured(int64_t display_id, bool status);
+ void OnHDCPStateReceived(int64_t display_id, bool status, HDCPState state);
+ void OnHDCPStateUpdated(int64_t display_id, bool status);
+ void OnTakeDisplayControl(bool status);
+ void OnRelinquishDisplayControl(bool status);
+
+ bool OnMessageReceivedForDrmOverlayManager(const IPC::Message& message);
+ void OnOverlayResult(gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& params);
+
int host_id_ = -1;
scoped_refptr<base::SingleThreadTaskRunner> send_runner_;
base::Callback<void(IPC::Message*)> send_callback_;
- std::vector<GpuPlatformSupportHost*> handlers_; // Not owned.
+ DrmDisplayHostManager* display_manager_; // Not owned.
+ DrmOverlayManager* overlay_manager_; // Not owned.
+
DrmCursor* cursor_; // Not owned.
- base::ObserverList<ChannelObserver> channel_observers_;
+ base::ObserverList<GpuThreadObserver> gpu_thread_observers_;
};
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
index 0d6389bce8c..1563516b107 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
@@ -102,11 +102,13 @@ bool DrmNativeDisplayDelegate::SetColorCalibrationProfile(
return false;
}
-bool DrmNativeDisplayDelegate::SetGammaRamp(
+bool DrmNativeDisplayDelegate::SetColorCorrection(
const ui::DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& lut) {
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
DrmDisplayHost* display = display_manager_->GetDisplay(output.display_id());
- display->SetGammaRamp(lut);
+ display->SetColorCorrection(degamma_lut, gamma_lut, correction_matrix);
return true;
}
diff --git a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
index f62514e1a3a..8141ce710ef 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
@@ -50,8 +50,10 @@ class DrmNativeDisplayDelegate : public NativeDisplayDelegate {
bool SetColorCalibrationProfile(
const ui::DisplaySnapshot& output,
ui::ColorCalibrationProfile new_profile) override;
- bool SetGammaRamp(const ui::DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& lut) override;
+ bool SetColorCorrection(const ui::DisplaySnapshot& output,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) override;
void AddObserver(NativeDisplayObserver* observer) override;
void RemoveObserver(NativeDisplayObserver* observer) override;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
index 3cba7b75d20..a04330d7db2 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.cc
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,159 +10,23 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
-#include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
+#include "ui/ozone/public/overlay_manager_ozone.h"
namespace ui {
-namespace {
-const size_t kMaxCacheSize = 200;
-} // namespace
-
DrmOverlayCandidatesHost::DrmOverlayCandidatesHost(
- DrmGpuPlatformSupportHost* platform_support,
- DrmWindowHost* window)
- : platform_support_(platform_support),
- window_(window),
- cache_(kMaxCacheSize) {
- platform_support_->RegisterHandler(this);
- window_->SetOverlayCandidatesHost(this);
-}
+ DrmOverlayManager* manager,
+ gfx::AcceleratedWidget widget)
+ : overlay_manager_(manager), widget_(widget) {}
-DrmOverlayCandidatesHost::~DrmOverlayCandidatesHost() {
- platform_support_->UnregisterHandler(this);
- window_->SetOverlayCandidatesHost(nullptr);
-}
+DrmOverlayCandidatesHost::~DrmOverlayCandidatesHost() {}
void DrmOverlayCandidatesHost::CheckOverlaySupport(
OverlaySurfaceCandidateList* candidates) {
- std::vector<OverlayCheck_Params> overlay_params;
- for (auto& candidate : *candidates) {
- // Compositor doesn't have information about the total size of primary
- // candidate. We get this information from display rect.
- if (candidate.plane_z_order == 0)
- candidate.buffer_size = gfx::ToNearestRect(candidate.display_rect).size();
-
- overlay_params.push_back(OverlayCheck_Params(candidate));
- }
-
- const auto& iter = cache_.Get(overlay_params);
- // We are still waiting on results for this candidate list from GPU.
- if (iter != cache_.end() && iter->second)
- return;
-
- size_t size = candidates->size();
-
- if (iter == cache_.end()) {
- // We can skip GPU side validation in case all candidates are invalid
- // or we are checking only for Primary.
- bool needs_gpu_validation = false;
- for (size_t i = 0; i < size; i++) {
- const OverlaySurfaceCandidate& candidate = candidates->at(i);
-
- if (candidate.plane_z_order == 0) {
- // We expect primary to be always valid.
- overlay_params.at(i).is_overlay_candidate = true;
- continue;
- }
-
- if (!CanHandleCandidate(candidate)) {
- overlay_params.at(i).is_overlay_candidate = false;
- continue;
- }
-
- needs_gpu_validation = true;
- }
-
- cache_.Put(overlay_params, needs_gpu_validation);
-
- if (needs_gpu_validation)
- SendOverlayValidationRequest(overlay_params);
- } else {
- const std::vector<OverlayCheck_Params>& validated_params = iter->first;
- DCHECK(size == validated_params.size());
-
- for (size_t i = 0; i < size; i++) {
- candidates->at(i).overlay_handled =
- validated_params.at(i).is_overlay_candidate;
- }
- }
-}
-
-void DrmOverlayCandidatesHost::OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& sender) {
- // Reset any old cache.
- ResetCache();
-}
-
-void DrmOverlayCandidatesHost::OnChannelDestroyed(int host_id) {
+ overlay_manager_->CheckOverlaySupport(candidates, widget_);
}
-bool DrmOverlayCandidatesHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = false;
- IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(DrmOverlayCandidatesHost, message, &handled)
- IPC_MESSAGE_FORWARD(OzoneHostMsg_OverlayCapabilitiesReceived, this,
- DrmOverlayCandidatesHost::OnOverlayResult)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void DrmOverlayCandidatesHost::ResetCache() {
- cache_.Clear();
-}
-
-void DrmOverlayCandidatesHost::SendOverlayValidationRequest(
- const std::vector<OverlayCheck_Params>& new_params) const {
- if (!platform_support_->IsConnected())
- return;
-
- platform_support_->Send(new OzoneGpuMsg_CheckOverlayCapabilities(
- window_->GetAcceleratedWidget(), new_params));
-}
-
-void DrmOverlayCandidatesHost::OnOverlayResult(
- bool* handled,
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& params) {
- if (widget != window_->GetAcceleratedWidget())
- return;
-
- *handled = true;
- cache_.Put(params, false);
-}
-
-bool DrmOverlayCandidatesHost::CanHandleCandidate(
- const OverlaySurfaceCandidate& candidate) const {
- if (candidate.buffer_size.IsEmpty())
- return false;
-
- // 0.01 constant chosen to match DCHECKs in gfx::ToNearestRect and avoid
- // that code asserting on quads that we accept.
- if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f))
- return false;
-
- if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID)
- return false;
-
- if (candidate.plane_z_order != 0) {
- // It is possible that the cc rect we get actually falls off the edge of
- // the screen. Usually this is prevented via things like status bars
- // blocking overlaying or cc clipping it, but in case it wasn't properly
- // clipped (since GL will render this situation fine) just ignore it
- // here. This should be an extremely rare occurrance.
- if (!window_->GetBounds().Contains(
- gfx::ToNearestRect(candidate.display_rect))) {
- return false;
- }
- }
-
- if (candidate.is_clipped &&
- !candidate.clip_rect.Contains(candidate.quad_rect_in_target_space))
- return false;
-
- return true;
-}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
index 1d1feb6daaa..2797c2b25a5 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
@@ -1,9 +1,9 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_DRM_HOST_OVERLAY_CANDIDATES_H_
-#define UI_OZONE_PLATFORM_DRM_HOST_OVERLAY_CANDIDATES_H_
+#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_OVERLAY_CANDIDATES_HOST_H_
+#define UI_OZONE_PLATFORM_DRM_HOST_DRM_OVERLAY_CANDIDATES_HOST_H_
#include <stdint.h>
@@ -13,15 +13,13 @@
#include "base/containers/mru_cache.h"
#include "base/macros.h"
-#include "base/memory/scoped_vector.h"
-#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
-#include "ui/ozone/public/gpu_platform_support_host.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
#include "ui/ozone/public/overlay_candidates_ozone.h"
namespace ui {
-class DrmGpuPlatformSupportHost;
-class DrmWindowHost;
+class DrmOverlayManager;
// This is an implementation of OverlayCandidatesOzone where the driver is asked
// about overlay capabilities via IPC. We have no way of querying abstract
@@ -32,50 +30,23 @@ class DrmWindowHost;
// the result is returned in OzoneHostMsg_OverlayCapabilitiesReceived. Testing
// is asynchronous, until the reply arrives that configuration will be failed.
//
-// There is a many:1 relationship between this class and
-// DrmGpuPlatformSupportHost, each compositor will own one of these objects.
-// Each request has a unique request ID, which is assigned from a shared
-// sequence number so that replies can be routed to the correct object.
-class DrmOverlayCandidatesHost : public OverlayCandidatesOzone,
- public GpuPlatformSupportHost {
+// All OverlayCandidatesOzone objects share a single cache of tested
+// configurations stored in the overlay manager.
+class DrmOverlayCandidatesHost : public OverlayCandidatesOzone {
public:
- DrmOverlayCandidatesHost(DrmGpuPlatformSupportHost* platform_support,
- DrmWindowHost* window);
+ DrmOverlayCandidatesHost(DrmOverlayManager* manager_core,
+ gfx::AcceleratedWidget widget);
~DrmOverlayCandidatesHost() override;
- // OverlayCandidatesOzone:
void CheckOverlaySupport(OverlaySurfaceCandidateList* candidates) override;
- // GpuPlatformSupportHost:
- void OnChannelEstablished(
- int host_id,
- scoped_refptr<base::SingleThreadTaskRunner> send_runner,
- const base::Callback<void(IPC::Message*)>& sender) override;
- void OnChannelDestroyed(int host_id) override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- void ResetCache();
-
private:
- void SendOverlayValidationRequest(
- const std::vector<OverlayCheck_Params>& list) const;
- void OnOverlayResult(bool* handled,
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& params);
- bool CanHandleCandidate(const OverlaySurfaceCandidate& candidate) const;
-
- DrmGpuPlatformSupportHost* platform_support_; // Not owned.
- DrmWindowHost* window_; // Not owned.
-
- // List of all OverlayCheck_Params which have been validated in GPU side.
- // Value is set to true if we are waiting for validation results from GPU.
- base::MRUCacheBase<std::vector<OverlayCheck_Params>,
- bool,
- base::MRUCacheNullDeletor<bool>> cache_;
+ DrmOverlayManager* overlay_manager_; // Not owned.
+ gfx::AcceleratedWidget widget_;
DISALLOW_COPY_AND_ASSIGN(DrmOverlayCandidatesHost);
};
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_HOST_OVERLAY_CANDIDATES_H_
+#endif // UI_OZONE_PLATFORM_DRM_HOST_DRM_OVERLAY_CANDIDATES_HOST_H_
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
index ae0a755e3d5..9ba5746f75a 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
@@ -1,37 +1,155 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
+#include <stddef.h>
+
+#include <algorithm>
+
#include "base/command_line.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h"
+#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
-#include "ui/ozone/public/overlay_candidates_ozone.h"
#include "ui/ozone/public/ozone_switches.h"
namespace ui {
-DrmOverlayManager::DrmOverlayManager(
- DrmGpuPlatformSupportHost* platform_support_host,
- DrmWindowHostManager* manager)
- : platform_support_host_(platform_support_host), window_manager_(manager) {
+typedef OverlayCandidatesOzone::OverlaySurfaceCandidateList
+ OverlaySurfaceCandidateList;
+typedef OverlayCandidatesOzone::OverlaySurfaceCandidate OverlaySurfaceCandidate;
+
+namespace {
+const size_t kMaxCacheSize = 200;
+} // namespace
+
+DrmOverlayManager::DrmOverlayManager(GpuThreadAdapter* proxy,
+ DrmWindowHostManager* window_manager)
+ : proxy_(proxy), window_manager_(window_manager), cache_(kMaxCacheSize) {
is_supported_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kOzoneTestSingleOverlaySupport);
+ proxy_->RegisterHandlerForDrmOverlayManager(this);
}
DrmOverlayManager::~DrmOverlayManager() {
+ proxy_->UnRegisterHandlerForDrmOverlayManager();
}
scoped_ptr<OverlayCandidatesOzone> DrmOverlayManager::CreateOverlayCandidates(
gfx::AcceleratedWidget w) {
if (!is_supported_)
return nullptr;
- DrmWindowHost* window = window_manager_->GetWindow(w);
- DCHECK(window);
- return make_scoped_ptr(
- new DrmOverlayCandidatesHost(platform_support_host_, window));
+ return make_scoped_ptr(new DrmOverlayCandidatesHost(this, w));
+}
+
+void DrmOverlayManager::CheckOverlaySupport(
+ OverlayCandidatesOzone::OverlaySurfaceCandidateList* candidates,
+ gfx::AcceleratedWidget widget) {
+ std::vector<OverlayCheck_Params> overlay_params;
+ for (auto& candidate : *candidates) {
+ // Reject candidates that don't fall on a pixel boundary.
+ if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) {
+ DCHECK(candidate.plane_z_order != 0);
+ overlay_params.push_back(OverlayCheck_Params());
+ overlay_params.back().is_overlay_candidate = false;
+ continue;
+ }
+
+ // Compositor doesn't have information about the total size of primary
+ // candidate. We get this information from display rect.
+ if (candidate.plane_z_order == 0)
+ candidate.buffer_size = gfx::ToNearestRect(candidate.display_rect).size();
+
+ overlay_params.push_back(OverlayCheck_Params(candidate));
+ }
+
+ const auto& iter = cache_.Get(overlay_params);
+ // We are still waiting on results for this candidate list from GPU.
+ if (iter != cache_.end() && iter->second)
+ return;
+
+ size_t size = candidates->size();
+
+ if (iter == cache_.end()) {
+ // We can skip GPU side validation in case all candidates are invalid.
+ bool needs_gpu_validation = false;
+ for (size_t i = 0; i < size; i++) {
+ if (!overlay_params.at(i).is_overlay_candidate)
+ continue;
+
+ const OverlaySurfaceCandidate& candidate = candidates->at(i);
+ if (!CanHandleCandidate(candidate, widget)) {
+ DCHECK(candidate.plane_z_order != 0);
+ overlay_params.at(i).is_overlay_candidate = false;
+ continue;
+ }
+
+ needs_gpu_validation = true;
+ }
+
+ cache_.Put(overlay_params, needs_gpu_validation);
+
+ if (needs_gpu_validation)
+ SendOverlayValidationRequest(overlay_params, widget);
+ } else {
+ const std::vector<OverlayCheck_Params>& validated_params = iter->first;
+ DCHECK(size == validated_params.size());
+
+ for (size_t i = 0; i < size; i++) {
+ candidates->at(i).overlay_handled =
+ validated_params.at(i).is_overlay_candidate;
+ }
+ }
+}
+
+void DrmOverlayManager::ResetCache() {
+ cache_.Clear();
+}
+
+void DrmOverlayManager::SendOverlayValidationRequest(
+ const std::vector<OverlayCheck_Params>& new_params,
+ gfx::AcceleratedWidget widget) const {
+ if (!proxy_->IsConnected())
+ return;
+
+ proxy_->GpuCheckOverlayCapabilities(widget, new_params);
+}
+
+void DrmOverlayManager::GpuSentOverlayResult(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& params) {
+ cache_.Put(params, false);
+}
+
+bool DrmOverlayManager::CanHandleCandidate(
+ const OverlaySurfaceCandidate& candidate,
+ gfx::AcceleratedWidget widget) const {
+ if (candidate.buffer_size.IsEmpty())
+ return false;
+
+ if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+
+ if (candidate.plane_z_order != 0) {
+ // It is possible that the cc rect we get actually falls off the edge of
+ // the screen. Usually this is prevented via things like status bars
+ // blocking overlaying or cc clipping it, but in case it wasn't properly
+ // clipped (since GL will render this situation fine) just ignore it
+ // here. This should be an extremely rare occurrance.
+ DrmWindowHost* window = window_manager_->GetWindow(widget);
+ if (!window->GetBounds().Contains(
+ gfx::ToNearestRect(candidate.display_rect))) {
+ return false;
+ }
+ }
+
+ if (candidate.is_clipped &&
+ !candidate.clip_rect.Contains(candidate.quad_rect_in_target_space))
+ return false;
+
+ return true;
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
index b52a9b647a7..6c364d0e75c 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
@@ -1,32 +1,61 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_OVERLAY_MANAGER_H_
#define UI_OZONE_PLATFORM_DRM_HOST_DRM_OVERLAY_MANAGER_H_
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/containers/mru_cache.h"
#include "base/macros.h"
+#include "base/memory/scoped_vector.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
+#include "ui/ozone/public/overlay_candidates_ozone.h"
#include "ui/ozone/public/overlay_manager_ozone.h"
namespace ui {
-
-class DrmGpuPlatformSupportHost;
class DrmWindowHostManager;
class DrmOverlayManager : public OverlayManagerOzone {
public:
- DrmOverlayManager(DrmGpuPlatformSupportHost* platform_support_host,
- DrmWindowHostManager* manager);
+ DrmOverlayManager(GpuThreadAdapter* proxy,
+ DrmWindowHostManager* window_manager);
~DrmOverlayManager() override;
// OverlayManagerOzone:
scoped_ptr<OverlayCandidatesOzone> CreateOverlayCandidates(
gfx::AcceleratedWidget w) override;
+ void ResetCache();
+
+ // Communication-free implementations of actions performed in response to
+ // messages from the GPU thread.
+ void GpuSentOverlayResult(gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& params);
+
+ // Service method for DrmOverlayCandidatesHost
+ void CheckOverlaySupport(
+ OverlayCandidatesOzone::OverlaySurfaceCandidateList* candidates,
+ gfx::AcceleratedWidget widget);
+
private:
- DrmGpuPlatformSupportHost* platform_support_host_;
- DrmWindowHostManager* window_manager_;
+ void SendOverlayValidationRequest(
+ const std::vector<OverlayCheck_Params>& new_params,
+ gfx::AcceleratedWidget widget) const;
+ bool CanHandleCandidate(
+ const OverlayCandidatesOzone::OverlaySurfaceCandidate& candidate,
+ gfx::AcceleratedWidget widget) const;
+
bool is_supported_;
+ GpuThreadAdapter* proxy_; // Not owned.
+ DrmWindowHostManager* window_manager_; // Not owned.
+
+ // List of all OverlayCheck_Params which have been validated in GPU side.
+ // Value is set to true if we are waiting for validation results from GPU.
+ base::MRUCache<std::vector<OverlayCheck_Params>, bool> cache_;
DISALLOW_COPY_AND_ASSIGN(DrmOverlayManager);
};
diff --git a/chromium/ui/ozone/platform/drm/host/drm_window_host.cc b/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
index 4255904d35a..56b59bbb905 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.cc
@@ -11,12 +11,10 @@
#include "ui/events/ozone/events_ozone.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gfx/display.h"
-#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
#include "ui/ozone/platform/drm/host/drm_cursor.h"
#include "ui/ozone/platform/drm/host/drm_display_host.h"
#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
-#include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
-#include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
#include "ui/platform_window/platform_window_delegate.h"
@@ -24,18 +22,19 @@ namespace ui {
DrmWindowHost::DrmWindowHost(PlatformWindowDelegate* delegate,
const gfx::Rect& bounds,
- DrmGpuPlatformSupportHost* sender,
+ GpuThreadAdapter* sender,
EventFactoryEvdev* event_factory,
DrmCursor* cursor,
DrmWindowHostManager* window_manager,
- DrmDisplayHostManager* display_manager)
+ DrmDisplayHostManager* display_manager,
+ DrmOverlayManager* overlay_manager)
: delegate_(delegate),
sender_(sender),
event_factory_(event_factory),
cursor_(cursor),
window_manager_(window_manager),
display_manager_(display_manager),
- overlay_candidates_host_(nullptr),
+ overlay_manager_(overlay_manager),
bounds_(bounds),
widget_(window_manager->NextAcceleratedWidget()) {
window_manager_->AddWindow(widget_, this);
@@ -46,12 +45,12 @@ DrmWindowHost::~DrmWindowHost() {
window_manager_->RemoveWindow(widget_);
cursor_->OnWindowRemoved(widget_);
- sender_->RemoveChannelObserver(this);
- sender_->Send(new OzoneGpuMsg_DestroyWindow(widget_));
+ sender_->RemoveGpuThreadObserver(this);
+ sender_->GpuDestroyWindow(widget_);
}
void DrmWindowHost::Initialize() {
- sender_->AddChannelObserver(this);
+ sender_->AddGpuThreadObserver(this);
PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
cursor_->OnWindowAdded(widget_, bounds_, GetCursorConfinedBounds());
delegate_->OnAcceleratedWidgetAvailable(widget_, 1.f);
@@ -187,26 +186,20 @@ uint32_t DrmWindowHost::DispatchEvent(const PlatformEvent& native_event) {
return POST_DISPATCH_STOP_PROPAGATION;
}
-void DrmWindowHost::OnChannelEstablished() {
- sender_->Send(new OzoneGpuMsg_CreateWindow(widget_));
+void DrmWindowHost::OnGpuThreadReady() {
+ sender_->GpuCreateWindow(widget_);
SendBoundsChange();
}
-void DrmWindowHost::OnChannelDestroyed() {
-}
-
-void DrmWindowHost::SetOverlayCandidatesHost(DrmOverlayCandidatesHost* host) {
- overlay_candidates_host_ = host;
-}
+void DrmWindowHost::OnGpuThreadRetired() {}
void DrmWindowHost::SendBoundsChange() {
// Update the cursor before the window so that the cursor stays within the
// window bounds when the window size shrinks.
cursor_->CommitBoundsChange(widget_, bounds_, GetCursorConfinedBounds());
- sender_->Send(new OzoneGpuMsg_WindowBoundsChanged(widget_, bounds_));
+ sender_->GpuWindowBoundsChanged(widget_, bounds_);
- if (overlay_candidates_host_)
- overlay_candidates_host_->ResetCache();
+ overlay_manager_->ResetCache();
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/host/drm_window_host.h b/chromium/ui/ozone/platform/drm/host/drm_window_host.h
index dabcfc9b459..a66729c2d8d 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.h
@@ -13,18 +13,18 @@
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/platform/drm/host/channel_observer.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
#include "ui/platform_window/platform_window.h"
namespace ui {
class DrmDisplayHostManager;
class DrmCursor;
-class DrmGpuPlatformSupportHost;
-class DrmOverlayCandidatesHost;
class DrmGpuWindow;
+class DrmOverlayManager;
class DrmWindowHostManager;
class EventFactoryEvdev;
+class GpuThreadAdapter;
// Implementation of the platform window. This object and its handle |widget_|
// uniquely identify a window. Since the DRI/GBM platform is split into 2
@@ -38,15 +38,16 @@ class EventFactoryEvdev;
// associated with the window (the surface is created on the GPU process).
class DrmWindowHost : public PlatformWindow,
public PlatformEventDispatcher,
- public ChannelObserver {
+ public GpuThreadObserver {
public:
DrmWindowHost(PlatformWindowDelegate* delegate,
const gfx::Rect& bounds,
- DrmGpuPlatformSupportHost* sender,
+ GpuThreadAdapter* sender,
EventFactoryEvdev* event_factory,
DrmCursor* cursor,
DrmWindowHostManager* window_manager,
- DrmDisplayHostManager* display_manager);
+ DrmDisplayHostManager* display_manager,
+ DrmOverlayManager* overlay_manager);
~DrmWindowHost() override;
void Initialize();
@@ -77,22 +78,20 @@ class DrmWindowHost : public PlatformWindow,
bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override;
- // ChannelObserver:
- void OnChannelEstablished() override;
- void OnChannelDestroyed() override;
-
- void SetOverlayCandidatesHost(DrmOverlayCandidatesHost* host);
+ // GpuThreadObserver:
+ void OnGpuThreadReady() override;
+ void OnGpuThreadRetired() override;
private:
void SendBoundsChange();
PlatformWindowDelegate* delegate_; // Not owned.
- DrmGpuPlatformSupportHost* sender_; // Not owned.
+ GpuThreadAdapter* sender_; // Not owned.
EventFactoryEvdev* event_factory_; // Not owned.
DrmCursor* cursor_; // Not owned.
DrmWindowHostManager* window_manager_; // Not owned.
DrmDisplayHostManager* display_manager_; // Not owned.
- DrmOverlayCandidatesHost* overlay_candidates_host_; // Not owned.
+ DrmOverlayManager* overlay_manager_; // Not owned.
gfx::Rect bounds_;
gfx::AcceleratedWidget widget_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_window_host_manager.h b/chromium/ui/ozone/platform/drm/host/drm_window_host_manager.h
index 3ae8e2db99b..af97c5c9662 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host_manager.h
@@ -17,7 +17,6 @@ class Point;
namespace ui {
-class DrmGpuPlatformSupportHost;
class DrmWindowHost;
// Responsible for keeping the mapping between the allocated widgets and
diff --git a/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h b/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h
new file mode 100644
index 00000000000..866dfd8c4a1
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h
@@ -0,0 +1,76 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_ADAPTER_H_
+#define UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_ADAPTER_H_
+
+#include "base/file_descriptor_posix.h"
+#include "ui/display/types/display_constants.h"
+#include "ui/display/types/gamma_ramp_rgb_entry.h"
+#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
+#include "ui/ozone/public/overlay_candidates_ozone.h"
+
+namespace ui {
+
+class DrmDisplayHostManager;
+class DrmOverlayManager;
+class GpuThreadObserver;
+
+// Provides the services that the various host components need
+// to use either a GPU process or thread for their implementation.
+class GpuThreadAdapter {
+ public:
+ virtual ~GpuThreadAdapter() {}
+
+ virtual bool IsConnected() = 0;
+ virtual void AddGpuThreadObserver(GpuThreadObserver* observer) = 0;
+ virtual void RemoveGpuThreadObserver(GpuThreadObserver* observer) = 0;
+
+ // Methods for Display management.
+ virtual void RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) = 0;
+ virtual void UnRegisterHandlerForDrmDisplayHostManager() = 0;
+
+ // Services needed for DrmDisplayHostMananger
+ virtual bool GpuTakeDisplayControl() = 0;
+ virtual bool GpuRefreshNativeDisplays() = 0;
+ virtual bool GpuRelinquishDisplayControl() = 0;
+ virtual bool GpuAddGraphicsDevice(const base::FilePath& path,
+ const base::FileDescriptor& fd) = 0;
+ virtual bool GpuRemoveGraphicsDevice(const base::FilePath& path) = 0;
+
+ // Methods for DrmOverlayManager.
+ virtual void RegisterHandlerForDrmOverlayManager(
+ DrmOverlayManager* handler) = 0;
+ virtual void UnRegisterHandlerForDrmOverlayManager() = 0;
+
+ // Services needed by DrmOverlayManager
+ virtual bool GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& new_params) = 0;
+
+ // Services needed by DrmDisplayHost
+ virtual bool GpuConfigureNativeDisplay(
+ int64_t display_id,
+ const ui::DisplayMode_Params& display_mode,
+ const gfx::Point& point) = 0;
+ virtual bool GpuDisableNativeDisplay(int64_t display_id) = 0;
+ virtual bool GpuGetHDCPState(int64_t display_id) = 0;
+ virtual bool GpuSetHDCPState(int64_t display_id, ui::HDCPState state) = 0;
+ virtual bool GpuSetColorCorrection(
+ int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) = 0;
+
+ // Services needed by DrmWindowHost
+ virtual bool GpuDestroyWindow(gfx::AcceleratedWidget widget) = 0;
+ virtual bool GpuCreateWindow(gfx::AcceleratedWidget widget) = 0;
+ virtual bool GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_ADAPTER_H_
diff --git a/chromium/ui/ozone/platform/drm/host/gpu_thread_observer.h b/chromium/ui/ozone/platform/drm/host/gpu_thread_observer.h
new file mode 100644
index 00000000000..3307dfa8fcb
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/host/gpu_thread_observer.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_OBSERVER_H_
+#define UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_OBSERVER_H_
+
+namespace ui {
+
+// Observes the channel state.
+class GpuThreadObserver {
+ public:
+ virtual ~GpuThreadObserver() {}
+
+ // Called when a GPU thread implementation has become available.
+ virtual void OnGpuThreadReady() = 0;
+ // Called when the GPU thread implementation has ceased to be
+ // available.
+ virtual void OnGpuThreadRetired() = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_HOST_GPU_THREAD_OBSERVER_H_
diff --git a/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc b/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc
new file mode 100644
index 00000000000..1f3e0167e20
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc
@@ -0,0 +1,339 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/drm/mus_thread_proxy.h"
+
+#include "base/bind.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "ui/ozone/platform/drm/gpu/drm_thread.h"
+#include "ui/ozone/platform/drm/gpu/proxy_helpers.h"
+#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
+
+namespace ui {
+
+MusThreadProxy::MusThreadProxy()
+ : ws_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ drm_thread_(nullptr),
+ weak_ptr_factory_(this) {}
+
+MusThreadProxy::~MusThreadProxy() {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ FOR_EACH_OBSERVER(GpuThreadObserver, gpu_thread_observers_,
+ OnGpuThreadRetired());
+}
+
+// This is configured on the GPU thread.
+void MusThreadProxy::SetDrmThread(DrmThread* thread) {
+ base::AutoLock acquire(lock_);
+ drm_thread_ = thread;
+}
+
+void MusThreadProxy::ProvideManagers(DrmDisplayHostManager* display_manager,
+ DrmOverlayManager* overlay_manager) {
+ display_manager_ = display_manager;
+ overlay_manager_ = overlay_manager;
+}
+
+void MusThreadProxy::StartDrmThread() {
+ DCHECK(drm_thread_);
+ drm_thread_->Start();
+
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&MusThreadProxy::DispatchObserversFromDrmThread,
+ base::Unretained(this)));
+}
+
+void MusThreadProxy::DispatchObserversFromDrmThread() {
+ ws_task_runner_->PostTask(FROM_HERE, base::Bind(&MusThreadProxy::RunObservers,
+ base::Unretained(this)));
+}
+
+void MusThreadProxy::RunObservers() {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ FOR_EACH_OBSERVER(GpuThreadObserver, gpu_thread_observers_,
+ OnGpuThreadReady());
+}
+
+void MusThreadProxy::AddGpuThreadObserver(GpuThreadObserver* observer) {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+
+ gpu_thread_observers_.AddObserver(observer);
+ if (IsConnected())
+ observer->OnGpuThreadReady();
+}
+
+void MusThreadProxy::RemoveGpuThreadObserver(GpuThreadObserver* observer) {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ gpu_thread_observers_.RemoveObserver(observer);
+}
+
+bool MusThreadProxy::IsConnected() {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ base::AutoLock acquire(lock_);
+ if (drm_thread_)
+ return drm_thread_->IsRunning();
+ return false;
+}
+
+// Services needed for DrmDisplayHostMananger.
+void MusThreadProxy::RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_ = handler;
+}
+
+void MusThreadProxy::UnRegisterHandlerForDrmDisplayHostManager() {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_ = nullptr;
+}
+
+bool MusThreadProxy::GpuCreateWindow(gfx::AcceleratedWidget widget) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::CreateWindow,
+ base::Unretained(drm_thread_), widget));
+ return true;
+}
+
+bool MusThreadProxy::GpuDestroyWindow(gfx::AcceleratedWidget widget) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::DestroyWindow,
+ base::Unretained(drm_thread_), widget));
+ return true;
+}
+
+bool MusThreadProxy::GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::SetWindowBounds,
+ base::Unretained(drm_thread_), widget, bounds));
+ return true;
+}
+
+void MusThreadProxy::CursorSet(gfx::AcceleratedWidget widget,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& location,
+ int frame_delay_ms) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::SetCursor, base::Unretained(drm_thread_), widget,
+ bitmaps, location, frame_delay_ms));
+}
+
+void MusThreadProxy::Move(gfx::AcceleratedWidget widget,
+ const gfx::Point& location) {
+ // NOTE: Input events skip the main thread to avoid jank.
+ DCHECK(drm_thread_->IsRunning());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::MoveCursor,
+ base::Unretained(drm_thread_), widget, location));
+}
+
+// Services needed for DrmOverlayManager.
+void MusThreadProxy::RegisterHandlerForDrmOverlayManager(
+ DrmOverlayManager* handler) {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ overlay_manager_ = handler;
+}
+
+void MusThreadProxy::UnRegisterHandlerForDrmOverlayManager() {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ overlay_manager_ = nullptr;
+}
+
+bool MusThreadProxy::GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& overlays) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback =
+ base::Bind(&MusThreadProxy::GpuCheckOverlayCapabilitiesCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::CheckOverlayCapabilities,
+ base::Unretained(drm_thread_), widget, overlays,
+ CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuRefreshNativeDisplays() {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback = base::Bind(&MusThreadProxy::GpuRefreshNativeDisplaysCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::RefreshNativeDisplays,
+ base::Unretained(drm_thread_), CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuConfigureNativeDisplay(int64_t id,
+ const DisplayMode_Params& mode,
+ const gfx::Point& origin) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+
+ auto callback = base::Bind(&MusThreadProxy::GpuConfigureNativeDisplayCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::ConfigureNativeDisplay,
+ base::Unretained(drm_thread_), id, mode, origin,
+ CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuDisableNativeDisplay(int64_t id) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback = base::Bind(&MusThreadProxy::GpuDisableNativeDisplayCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::DisableNativeDisplay,
+ base::Unretained(drm_thread_), id,
+ CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuTakeDisplayControl() {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback = base::Bind(&MusThreadProxy::GpuTakeDisplayControlCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::TakeDisplayControl, base::Unretained(drm_thread_),
+ CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuRelinquishDisplayControl() {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback =
+ base::Bind(&MusThreadProxy::GpuRelinquishDisplayControlCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::RelinquishDisplayControl,
+ base::Unretained(drm_thread_), CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuAddGraphicsDevice(const base::FilePath& path,
+ const base::FileDescriptor& fd) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::AddGraphicsDevice,
+ base::Unretained(drm_thread_), path, fd));
+ return true;
+}
+
+bool MusThreadProxy::GpuRemoveGraphicsDevice(const base::FilePath& path) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&DrmThread::RemoveGraphicsDevice,
+ base::Unretained(drm_thread_), path));
+ return true;
+}
+
+bool MusThreadProxy::GpuGetHDCPState(int64_t display_id) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ auto callback = base::Bind(&MusThreadProxy::GpuGetHDCPStateCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::GetHDCPState, base::Unretained(drm_thread_),
+ display_id, CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuSetHDCPState(int64_t display_id, HDCPState state) {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ DCHECK(drm_thread_->IsRunning());
+ auto callback = base::Bind(&MusThreadProxy::GpuSetHDCPStateCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::SetHDCPState, base::Unretained(drm_thread_),
+ display_id, state, CreateSafeCallback(callback)));
+ return true;
+}
+
+bool MusThreadProxy::GpuSetColorCorrection(
+ int64_t id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ DCHECK(drm_thread_->IsRunning());
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ drm_thread_->task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::SetColorCorrection, base::Unretained(drm_thread_),
+ id, degamma_lut, gamma_lut, correction_matrix));
+ return true;
+}
+
+void MusThreadProxy::GpuCheckOverlayCapabilitiesCallback(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& overlays) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ overlay_manager_->GpuSentOverlayResult(widget, overlays);
+}
+
+void MusThreadProxy::GpuConfigureNativeDisplayCallback(int64_t display_id,
+ bool success) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuConfiguredDisplay(display_id, success);
+}
+
+void MusThreadProxy::GpuRefreshNativeDisplaysCallback(
+ const std::vector<DisplaySnapshot_Params>& displays) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuHasUpdatedNativeDisplays(displays);
+}
+
+void MusThreadProxy::GpuDisableNativeDisplayCallback(int64_t display_id,
+ bool success) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuConfiguredDisplay(display_id, success);
+}
+
+void MusThreadProxy::GpuTakeDisplayControlCallback(bool success) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuTookDisplayControl(success);
+}
+
+void MusThreadProxy::GpuRelinquishDisplayControlCallback(bool success) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuRelinquishedDisplayControl(success);
+}
+
+void MusThreadProxy::GpuGetHDCPStateCallback(int64_t display_id,
+ bool success,
+ HDCPState state) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuReceivedHDCPState(display_id, success, state);
+}
+
+void MusThreadProxy::GpuSetHDCPStateCallback(int64_t display_id,
+ bool success) const {
+ DCHECK(on_window_server_thread_.CalledOnValidThread());
+ display_manager_->GpuUpdatedHDCPState(display_id, success);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/mus_thread_proxy.h b/chromium/ui/ozone/platform/drm/mus_thread_proxy.h
new file mode 100644
index 00000000000..e39eefcb409
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/mus_thread_proxy.h
@@ -0,0 +1,141 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_MUS_THREAD_PROXY_H_
+#define UI_OZONE_PLATFORM_DRM_MUS_THREAD_PROXY_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/synchronization/lock.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
+#include "ui/ozone/platform/drm/host/drm_cursor.h"
+#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace ui {
+
+class DrmCursor;
+class DrmDisplayHostManager;
+class DrmOverlayManager;
+class DrmThread;
+class GpuThreadObserver;
+
+// In Mus, the window server thread (analogous to Chrome's UI thread), GPU and
+// DRM threads coexist in a single Mus process. The |MusThreadProxy| connects
+// these threads together via cross-thread calls.
+class MusThreadProxy : public GpuThreadAdapter,
+ public InterThreadMessagingProxy,
+ public DrmCursorProxy {
+ public:
+ MusThreadProxy();
+ ~MusThreadProxy() override;
+
+ void StartDrmThread();
+ void ProvideManagers(DrmDisplayHostManager* display_manager,
+ DrmOverlayManager* overlay_manager);
+
+ // InterThreadMessagingProxy.
+ void SetDrmThread(DrmThread* thread) override;
+
+ // This is the core functionality. They are invoked when we have a main
+ // thread, a gpu thread and we have called initialize on both.
+ void AddGpuThreadObserver(GpuThreadObserver* observer) override;
+ void RemoveGpuThreadObserver(GpuThreadObserver* observer) override;
+ bool IsConnected() override;
+
+ // Services needed for DrmDisplayHostMananger.
+ void RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) override;
+ void UnRegisterHandlerForDrmDisplayHostManager() override;
+
+ bool GpuTakeDisplayControl() override;
+ bool GpuRefreshNativeDisplays() override;
+ bool GpuRelinquishDisplayControl() override;
+ bool GpuAddGraphicsDevice(const base::FilePath& path,
+ const base::FileDescriptor& fd) override;
+ bool GpuRemoveGraphicsDevice(const base::FilePath& path) override;
+
+ // Services needed for DrmOverlayManager.
+ void RegisterHandlerForDrmOverlayManager(DrmOverlayManager* handler) override;
+ void UnRegisterHandlerForDrmOverlayManager() override;
+
+ bool GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& new_params) override;
+
+ // Services needed by DrmDisplayHost
+ bool GpuConfigureNativeDisplay(int64_t display_id,
+ const ui::DisplayMode_Params& display_mode,
+ const gfx::Point& point) override;
+ bool GpuDisableNativeDisplay(int64_t display_id) override;
+ bool GpuGetHDCPState(int64_t display_id) override;
+ bool GpuSetHDCPState(int64_t display_id, ui::HDCPState state) override;
+ bool GpuSetColorCorrection(
+ int64_t display_id,
+ const std::vector<GammaRampRGBEntry>& degamma_lut,
+ const std::vector<GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) override;
+
+ // Services needed by DrmWindowHost
+ bool GpuDestroyWindow(gfx::AcceleratedWidget widget) override;
+ bool GpuCreateWindow(gfx::AcceleratedWidget widget) override;
+ bool GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) override;
+
+ // DrmCursorProxy.
+ void CursorSet(gfx::AcceleratedWidget window,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& point,
+ int frame_delay_ms) override;
+ void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override;
+
+ private:
+ void RunObservers();
+ void DispatchObserversFromDrmThread();
+
+ void GpuCheckOverlayCapabilitiesCallback(
+ gfx::AcceleratedWidget widget,
+ const std::vector<OverlayCheck_Params>& overlays) const;
+
+ void GpuConfigureNativeDisplayCallback(int64_t display_id,
+ bool success) const;
+
+ void GpuRefreshNativeDisplaysCallback(
+ const std::vector<DisplaySnapshot_Params>& displays) const;
+ void GpuDisableNativeDisplayCallback(int64_t display_id, bool success) const;
+ void GpuTakeDisplayControlCallback(bool success) const;
+ void GpuRelinquishDisplayControlCallback(bool success) const;
+ void GpuGetHDCPStateCallback(int64_t display_id,
+ bool success,
+ HDCPState state) const;
+ void GpuSetHDCPStateCallback(int64_t display_id, bool success) const;
+
+ scoped_refptr<base::SingleThreadTaskRunner> ws_task_runner_;
+
+ DrmThread* drm_thread_; // Not owned.
+
+ // Guards for multi-theaded access to drm_thread_.
+ base::Lock lock_;
+
+ DrmDisplayHostManager* display_manager_; // Not owned.
+ DrmOverlayManager* overlay_manager_; // Not owned.
+
+ base::ObserverList<GpuThreadObserver> gpu_thread_observers_;
+
+ base::ThreadChecker on_window_server_thread_;
+
+ base::WeakPtrFactory<MusThreadProxy> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MusThreadProxy);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_MUS_THREAD_PROXY_H_
diff --git a/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc b/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 3dbe176c0b9..9ccb57a70f9 100644
--- a/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -9,9 +9,12 @@
#include <gbm.h>
#include <stdlib.h>
#include <xf86drm.h>
+
+#include <memory>
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/macros.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/events/ozone/device/device_manager.h"
@@ -35,10 +38,11 @@
#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
+#include "ui/ozone/platform/drm/mus_thread_proxy.h"
#include "ui/ozone/public/cursor_factory_ozone.h"
#include "ui/ozone/public/gpu_platform_support.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/ozone_switches.h"
#if defined(USE_XKBCOMMON)
@@ -72,6 +76,13 @@ class GlApiLoader {
DISALLOW_COPY_AND_ASSIGN(GlApiLoader);
};
+// Returns true if we should operate in Mus mode.
+bool RunningInsideMus() {
+ bool has_channel_handle = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ "mojo-platform-channel-handle");
+ return has_channel_handle;
+}
+
class OzonePlatformGbm : public OzonePlatform {
public:
OzonePlatformGbm() {}
@@ -102,10 +113,15 @@ class OzonePlatformGbm : public OzonePlatform {
scoped_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate,
const gfx::Rect& bounds) override {
- scoped_ptr<DrmWindowHost> platform_window(
- new DrmWindowHost(delegate, bounds, gpu_platform_support_host_.get(),
- event_factory_ozone_.get(), cursor_.get(),
- window_manager_.get(), display_manager_.get()));
+ GpuThreadAdapter* adapter = gpu_platform_support_host_.get();
+ if (RunningInsideMus()) {
+ DCHECK(drm_thread_) << "drm_thread_ should exist (and be running) here.";
+ adapter = mus_thread_proxy_.get();
+ }
+
+ scoped_ptr<DrmWindowHost> platform_window(new DrmWindowHost(
+ delegate, bounds, adapter, event_factory_ozone_.get(), cursor_.get(),
+ window_manager_.get(), display_manager_.get(), overlay_manager_.get()));
platform_window->Initialize();
return std::move(platform_window);
}
@@ -113,17 +129,6 @@ class OzonePlatformGbm : public OzonePlatform {
return make_scoped_ptr(
new DrmNativeDisplayDelegate(display_manager_.get()));
}
- base::ScopedFD OpenClientNativePixmapDevice() const override {
-#if defined(USE_VGEM_MAP)
- int vgem_fd = drmOpenWithType("vgem", nullptr, DRM_NODE_RENDER);
- if (vgem_fd < 0) {
- PLOG(ERROR) << "Failed to find vgem device";
- vgem_fd = -1;
- }
- return base::ScopedFD(vgem_fd);
-#endif
- return base::ScopedFD();
- }
void InitializeUI() override {
device_manager_ = CreateDeviceManager();
window_manager_.reset(new DrmWindowHostManager());
@@ -138,25 +143,54 @@ class OzonePlatformGbm : public OzonePlatform {
event_factory_ozone_.reset(new EventFactoryEvdev(
cursor_.get(), device_manager_.get(),
KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()));
- gpu_platform_support_host_.reset(
- new DrmGpuPlatformSupportHost(cursor_.get()));
- display_manager_.reset(new DrmDisplayHostManager(
- gpu_platform_support_host_.get(), device_manager_.get(),
- event_factory_ozone_->input_controller()));
+
+ GpuThreadAdapter* adapter;
+ if (RunningInsideMus()) {
+ gl_api_loader_.reset(new GlApiLoader());
+ mus_thread_proxy_.reset(new MusThreadProxy());
+ adapter = mus_thread_proxy_.get();
+ cursor_->SetDrmCursorProxy(mus_thread_proxy_.get());
+ } else {
+ gpu_platform_support_host_.reset(
+ new DrmGpuPlatformSupportHost(cursor_.get()));
+ adapter = gpu_platform_support_host_.get();
+ }
+
+ display_manager_.reset(
+ new DrmDisplayHostManager(adapter, device_manager_.get(),
+ event_factory_ozone_->input_controller()));
cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone);
- overlay_manager_.reset(new DrmOverlayManager(
- gpu_platform_support_host_.get(), window_manager_.get()));
+ overlay_manager_.reset(
+ new DrmOverlayManager(adapter, window_manager_.get()));
+
+ if (RunningInsideMus()) {
+ mus_thread_proxy_->ProvideManagers(display_manager_.get(),
+ overlay_manager_.get());
+ }
}
void InitializeGPU() override {
- gl_api_loader_.reset(new GlApiLoader());
+ InterThreadMessagingProxy* itmp;
+ if (RunningInsideMus()) {
+ DCHECK(mus_thread_proxy_);
+ itmp = mus_thread_proxy_.get();
+ } else {
+ gl_api_loader_.reset(new GlApiLoader());
+ scoped_refptr<DrmThreadMessageProxy> message_proxy(
+ new DrmThreadMessageProxy());
+ itmp = message_proxy.get();
+ gpu_platform_support_.reset(new DrmGpuPlatformSupport(message_proxy));
+ }
+
// NOTE: Can't start the thread here since this is called before sandbox
- // initialization.
+ // initialization in multi-process Chrome. In mus, we start the DRM thread.
drm_thread_.reset(new DrmThreadProxy());
+ drm_thread_->BindThreadIntoMessagingProxy(itmp);
surface_factory_.reset(new GbmSurfaceFactory(drm_thread_.get()));
- gpu_platform_support_.reset(
- new DrmGpuPlatformSupport(drm_thread_->CreateDrmThreadMessageProxy()));
+ if (RunningInsideMus()) {
+ mus_thread_proxy_->StartDrmThread();
+ }
}
private:
@@ -176,6 +210,9 @@ class OzonePlatformGbm : public OzonePlatform {
scoped_ptr<DrmDisplayHostManager> display_manager_;
scoped_ptr<DrmOverlayManager> overlay_manager_;
+ // Bridges the DRM, GPU and main threads in mus.
+ scoped_ptr<MusThreadProxy> mus_thread_proxy_;
+
#if defined(USE_XKBCOMMON)
XkbEvdevCodes xkb_evdev_code_converter_;
#endif
diff --git a/chromium/ui/ozone/platform/egltest/BUILD.gn b/chromium/ui/ozone/platform/egltest/BUILD.gn
index d6bca6cdc24..77b1566c359 100644
--- a/chromium/ui/ozone/platform/egltest/BUILD.gn
+++ b/chromium/ui/ozone/platform/egltest/BUILD.gn
@@ -5,6 +5,8 @@
import("//tools/generate_library_loader/generate_library_loader.gni")
import("//ui/ozone/ozone.gni")
+visibility = [ "//ui/ozone/*" ]
+
source_set("egltest") {
sources = [
"client_native_pixmap_factory_egltest.cc",
@@ -26,6 +28,8 @@ source_set("egltest") {
"//ui/events/platform",
"//ui/gfx",
"//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window",
]
}
@@ -69,5 +73,7 @@ if (is_linux && ozone_platform_ozonex) {
deps = [
"//build/config/sanitizers:deps",
]
+
+ visibility += [ "//chromecast/*" ]
}
}
diff --git a/chromium/ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.cc b/chromium/ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.cc
index 9e551f8084c..d6fe65eda7f 100644
--- a/chromium/ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.cc
+++ b/chromium/ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.cc
@@ -4,7 +4,7 @@
#include "ui/ozone/platform/egltest/client_native_pixmap_factory_egltest.h"
-#include "ui/ozone/common/stub_client_native_pixmap_factory.h" // nogncheck
+#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
namespace ui {
diff --git a/chromium/ui/ozone/platform/egltest/egltest.gypi b/chromium/ui/ozone/platform/egltest/egltest.gypi
index 4f79c56c4c7..8daed8cfbf9 100644
--- a/chromium/ui/ozone/platform/egltest/egltest.gypi
+++ b/chromium/ui/ozone/platform/egltest/egltest.gypi
@@ -19,6 +19,8 @@
'OZONE_IMPLEMENTATION',
],
'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
'../../base/base.gyp:base',
'../../third_party/khronos/khronos.gyp:khronos_headers',
'../events/devices/events_devices.gyp:events_devices',
diff --git a/chromium/ui/ozone/platform/egltest/ozone_platform_egltest.cc b/chromium/ui/ozone/platform/egltest/ozone_platform_egltest.cc
index 94012a8410a..8c300beff30 100644
--- a/chromium/ui/ozone/platform/egltest/ozone_platform_egltest.cc
+++ b/chromium/ui/ozone/platform/egltest/ozone_platform_egltest.cc
@@ -30,7 +30,7 @@
#include "ui/ozone/public/cursor_factory_ozone.h"
#include "ui/ozone/public/gpu_platform_support.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#include "ui/ozone/public/surface_ozone_egl.h"
@@ -63,15 +63,10 @@ void ScaleTouchEvent(TouchEvent* event, const gfx::SizeF& size) {
DeviceDataManager::GetInstance()->touchscreen_devices()) {
if (device.id == event->source_device_id()) {
gfx::SizeF touchscreen_size = gfx::SizeF(device.size);
- gfx::PointF location = event->location_f();
-
- location.Scale(size.width() / touchscreen_size.width(),
- size.height() / touchscreen_size.height());
- double ratio = std::sqrt(size.GetArea() / touchscreen_size.GetArea());
-
- event->set_location_f(location);
- event->set_radius_x(event->pointer_details().radius_x() * ratio);
- event->set_radius_y(event->pointer_details().radius_y() * ratio);
+ gfx::Transform transform;
+ transform.Scale(size.width() / touchscreen_size.width(),
+ size.height() / touchscreen_size.height());
+ event->UpdateForRootTransform(transform);
return;
}
}
@@ -241,6 +236,18 @@ class SurfaceOzoneEgltest : public SurfaceOzoneEGL {
return nullptr;
}
+ void* /* EGLConfig */ GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) override {
+ EGLint broken_props[] = {
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_NONE,
+ };
+ return ChooseEGLConfig(egl, broken_props);
+ }
+
private:
LibeglplatformShimLoader* eglplatform_shim_;
intptr_t native_window_;
@@ -263,7 +270,6 @@ class SurfaceFactoryEgltest : public ui::SurfaceFactoryOzone {
intptr_t GetNativeDisplay() override;
scoped_ptr<SurfaceOzoneEGL> CreateEGLSurfaceForWidget(
gfx::AcceleratedWidget widget) override;
- const int32_t* GetEGLSurfaceProperties(const int32_t* desired_list) override;
bool LoadEGLGLES2Bindings(
AddGLLibraryCallback add_gl_library,
SetGLGetProcAddressProcCallback set_gl_get_proc_address) override;
@@ -301,19 +307,6 @@ bool SurfaceFactoryEgltest::LoadEGLGLES2Bindings(
egl_soname, gles_soname);
}
-const int32_t* SurfaceFactoryEgltest::GetEGLSurfaceProperties(
- const int32_t* desired_list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- static const int32_t broken_props[] = {
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
- EGL_NONE,
- };
- return broken_props;
-}
-
// Test platform for EGL.
//
// This is a tiny EGL-based platform. Creation of the native window is
@@ -381,9 +374,6 @@ class OzonePlatformEgltest : public OzonePlatform {
scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
return make_scoped_ptr(new NativeDisplayDelegateOzone());
}
- base::ScopedFD OpenClientNativePixmapDevice() const override {
- return base::ScopedFD();
- }
void InitializeUI() override {
device_manager_ = CreateDeviceManager();
diff --git a/chromium/ui/ozone/platform/headless/BUILD.gn b/chromium/ui/ozone/platform/headless/BUILD.gn
index 54ed505d1e8..4a4fdb37bed 100644
--- a/chromium/ui/ozone/platform/headless/BUILD.gn
+++ b/chromium/ui/ozone/platform/headless/BUILD.gn
@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+visibility = [ "//ui/ozone/*" ]
+
source_set("headless") {
sources = [
"client_native_pixmap_factory_headless.cc",
@@ -25,5 +27,7 @@ source_set("headless") {
"//ui/events/platform",
"//ui/gfx/geometry",
"//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window",
]
}
diff --git a/chromium/ui/ozone/platform/headless/client_native_pixmap_factory_headless.cc b/chromium/ui/ozone/platform/headless/client_native_pixmap_factory_headless.cc
index f1e875d25e3..1f409eb013f 100644
--- a/chromium/ui/ozone/platform/headless/client_native_pixmap_factory_headless.cc
+++ b/chromium/ui/ozone/platform/headless/client_native_pixmap_factory_headless.cc
@@ -4,7 +4,7 @@
#include "ui/ozone/platform/headless/client_native_pixmap_factory_headless.h"
-#include "ui/ozone/common/stub_client_native_pixmap_factory.h" // nogncheck
+#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
namespace ui {
diff --git a/chromium/ui/ozone/platform/headless/headless.gypi b/chromium/ui/ozone/platform/headless/headless.gypi
index 65de1fa12a5..c3569929f39 100644
--- a/chromium/ui/ozone/platform/headless/headless.gypi
+++ b/chromium/ui/ozone/platform/headless/headless.gypi
@@ -19,6 +19,8 @@
'OZONE_IMPLEMENTATION',
],
'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
'../../base/base.gyp:base',
'../base/ui_base.gyp:ui_base',
'../events/events.gyp:events',
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
index c9bbe528402..a8b99525013 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -39,10 +39,10 @@ class FileSurface : public SurfaceOzoneCanvas {
// SurfaceOzoneCanvas overrides:
void ResizeCanvas(const gfx::Size& viewport_size) override {
- surface_ = skia::AdoptRef(SkSurface::NewRaster(SkImageInfo::MakeN32Premul(
- viewport_size.width(), viewport_size.height())));
+ surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
+ viewport_size.width(), viewport_size.height()));
}
- skia::RefPtr<SkSurface> GetSurface() override { return surface_; }
+ sk_sp<SkSurface> GetSurface() override { return surface_; }
void PresentCanvas(const gfx::Rect& damage) override {
if (location_.empty())
return;
@@ -62,7 +62,7 @@ class FileSurface : public SurfaceOzoneCanvas {
private:
base::FilePath location_;
- skia::RefPtr<SkSurface> surface_;
+ sk_sp<SkSurface> surface_;
};
class TestPixmap : public ui::NativePixmap {
diff --git a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
index 509b4c4641e..49325c74ad0 100644
--- a/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
+++ b/chromium/ui/ozone/platform/headless/ozone_platform_headless.cc
@@ -20,7 +20,7 @@
#include "ui/ozone/public/gpu_platform_support.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
-#include "ui/ozone/public/ozone_platform.h" // nogncheck
+#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/ozone_switches.h"
#include "ui/ozone/public/system_input_injector.h"
@@ -78,9 +78,6 @@ class OzonePlatformHeadless : public OzonePlatform {
scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
return make_scoped_ptr(new NativeDisplayDelegateOzone());
}
- base::ScopedFD OpenClientNativePixmapDevice() const override {
- return base::ScopedFD();
- }
void InitializeUI() override {
window_manager_.reset(new HeadlessWindowManager(file_path_));
diff --git a/chromium/ui/ozone/platform/wayland/BUILD.gn b/chromium/ui/ozone/platform/wayland/BUILD.gn
new file mode 100644
index 00000000000..1d8e6113da0
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/BUILD.gn
@@ -0,0 +1,68 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+visibility = [ "//ui/ozone/*" ]
+
+source_set("wayland") {
+ sources = [
+ "client_native_pixmap_factory_wayland.cc",
+ "client_native_pixmap_factory_wayland.h",
+ "ozone_platform_wayland.cc",
+ "ozone_platform_wayland.h",
+ "wayland_display.cc",
+ "wayland_display.h",
+ "wayland_object.cc",
+ "wayland_object.h",
+ "wayland_pointer.cc",
+ "wayland_pointer.h",
+ "wayland_surface_factory.cc",
+ "wayland_surface_factory.h",
+ "wayland_window.cc",
+ "wayland_window.h",
+ ]
+
+ deps = [
+ "//base",
+ "//skia",
+ "//third_party/wayland:wayland_client",
+ "//third_party/wayland-protocols:xdg_shell_protocol",
+ "//ui/events",
+ "//ui/events/platform",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ "//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window",
+ ]
+
+ defines = [ "OZONE_IMPLEMENTATION" ]
+}
+
+source_set("wayland_unittests") {
+ testonly = true
+
+ sources = [
+ "fake_server.cc",
+ "fake_server.h",
+ "mock_platform_window_delegate.cc",
+ "wayland_display_unittest.cc",
+ "wayland_pointer_unittest.cc",
+ "wayland_surface_factory_unittest.cc",
+ "wayland_test.cc",
+ "wayland_test.h",
+ "wayland_window_unittest.cc",
+ ]
+
+ deps = [
+ ":wayland",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/wayland:wayland_server",
+ "//third_party/wayland-protocols:xdg_shell_protocol",
+ "//ui/gfx:test_support",
+ "//ui/ozone:platform",
+ ]
+
+ defines = [ "WL_HIDE_DEPRECATED" ]
+}
diff --git a/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc
new file mode 100644
index 00000000000..eeea61baf57
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.h"
+
+#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
+
+namespace ui {
+
+ClientNativePixmapFactory* CreateClientNativePixmapFactoryWayland() {
+ return CreateStubClientNativePixmapFactory();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.h b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.h
new file mode 100644
index 00000000000..4e0121a1e3b
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_CLIENT_NATIVE_PIXMAP_FACTORY_WAYLAND_H_
+#define UI_OZONE_PLATFORM_WAYLAND_CLIENT_NATIVE_PIXMAP_FACTORY_WAYLAND_H_
+
+namespace ui {
+
+class ClientNativePixmapFactory;
+
+// Constructor hook for use in constructor_list.cc
+ClientNativePixmapFactory* CreateClientNativePixmapFactoryWayland();
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_CLIENT_NATIVE_PIXMAP_FACTORY_WAYLAND_H_
diff --git a/chromium/ui/ozone/platform/wayland/fake_server.cc b/chromium/ui/ozone/platform/wayland/fake_server.cc
new file mode 100644
index 00000000000..0465728b1b2
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/fake_server.cc
@@ -0,0 +1,391 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/fake_server.h"
+
+#include <sys/socket.h>
+#include <wayland-server.h>
+#include <xdg-shell-unstable-v5-server-protocol.h>
+
+#include "base/bind.h"
+#include "base/files/scoped_file.h"
+#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace wl {
+namespace {
+
+const uint32_t kCompositorVersion = 4;
+const uint32_t kSeatVersion = 4;
+const uint32_t kXdgShellVersion = 1;
+
+void DestroyResource(wl_client* client, wl_resource* resource) {
+ wl_resource_destroy(resource);
+}
+
+// wl_compositor
+
+void CreateSurface(wl_client* client, wl_resource* resource, uint32_t id) {
+ auto compositor =
+ static_cast<MockCompositor*>(wl_resource_get_user_data(resource));
+ wl_resource* surface_resource = wl_resource_create(
+ client, &wl_surface_interface, wl_resource_get_version(resource), id);
+ if (!surface_resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ compositor->AddSurface(make_scoped_ptr(new MockSurface(surface_resource)));
+}
+
+const struct wl_compositor_interface compositor_impl = {
+ &CreateSurface, // create_surface
+ nullptr, // create_region
+};
+
+// wl_surface
+
+void Attach(wl_client* client,
+ wl_resource* resource,
+ wl_resource* buffer_resource,
+ int32_t x,
+ int32_t y) {
+ static_cast<MockSurface*>(wl_resource_get_user_data(resource))
+ ->Attach(buffer_resource, x, y);
+}
+
+void Damage(wl_client* client,
+ wl_resource* resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ static_cast<MockSurface*>(wl_resource_get_user_data(resource))
+ ->Damage(x, y, width, height);
+}
+
+void Commit(wl_client* client, wl_resource* resource) {
+ static_cast<MockSurface*>(wl_resource_get_user_data(resource))->Commit();
+}
+
+const struct wl_surface_interface surface_impl = {
+ &DestroyResource, // destroy
+ &Attach, // attach
+ &Damage, // damage
+ nullptr, // frame
+ nullptr, // set_opaque_region
+ nullptr, // set_input_region
+ &Commit, // commit
+ nullptr, // set_buffer_transform
+ nullptr, // set_buffer_scale
+ nullptr, // damage_buffer
+};
+
+// xdg_shell
+
+void UseUnstableVersion(wl_client* client,
+ wl_resource* resource,
+ int32_t version) {
+ static_cast<MockXdgShell*>(wl_resource_get_user_data(resource))
+ ->UseUnstableVersion(version);
+}
+
+void GetXdgSurface(wl_client* client,
+ wl_resource* resource,
+ uint32_t id,
+ wl_resource* surface_resource) {
+ auto surface =
+ static_cast<MockSurface*>(wl_resource_get_user_data(surface_resource));
+ if (surface->xdg_surface) {
+ wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
+ "surface already has a role");
+ return;
+ }
+ wl_resource* xdg_surface_resource = wl_resource_create(
+ client, &xdg_surface_interface, wl_resource_get_version(resource), id);
+ if (!xdg_surface_resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ surface->xdg_surface.reset(new MockXdgSurface(xdg_surface_resource));
+}
+
+void Pong(wl_client* client, wl_resource* resource, uint32_t serial) {
+ static_cast<MockXdgShell*>(wl_resource_get_user_data(resource))->Pong(serial);
+}
+
+const struct xdg_shell_interface xdg_shell_impl = {
+ &DestroyResource, // destroy
+ &UseUnstableVersion, // use_unstable_version
+ &GetXdgSurface, // get_xdg_surface
+ nullptr, // get_xdg_popup
+ &Pong, // pong
+};
+
+// wl_seat
+
+void GetPointer(wl_client* client, wl_resource* resource, uint32_t id) {
+ auto seat = static_cast<MockSeat*>(wl_resource_get_user_data(resource));
+ wl_resource* pointer_resource = wl_resource_create(
+ client, &wl_pointer_interface, wl_resource_get_version(resource), id);
+ if (!pointer_resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ seat->pointer.reset(new MockPointer(pointer_resource));
+}
+
+const struct wl_seat_interface seat_impl = {
+ &GetPointer, // get_pointer
+ nullptr, // get_keyboard
+ nullptr, // get_touch,
+ &DestroyResource, // release
+};
+
+// wl_pointer
+
+const struct wl_pointer_interface pointer_impl = {
+ nullptr, // set_cursor
+ &DestroyResource, // release
+};
+
+// xdg_surface
+
+void SetTitle(wl_client* client, wl_resource* resource, const char* title) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->SetTitle(title);
+}
+
+void SetAppId(wl_client* client, wl_resource* resource, const char* app_id) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->SetAppId(app_id);
+}
+
+void AckConfigure(wl_client* client, wl_resource* resource, uint32_t serial) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->AckConfigure(serial);
+}
+
+void SetMaximized(wl_client* client, wl_resource* resource) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->SetMaximized();
+}
+
+void UnsetMaximized(wl_client* client, wl_resource* resource) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->UnsetMaximized();
+}
+
+void SetMinimized(wl_client* client, wl_resource* resource) {
+ static_cast<MockXdgSurface*>(wl_resource_get_user_data(resource))
+ ->SetMinimized();
+}
+
+const struct xdg_surface_interface xdg_surface_impl = {
+ &DestroyResource, // destroy
+ nullptr, // set_parent
+ &SetTitle, // set_title
+ &SetAppId, // set_app_id
+ nullptr, // show_window_menu
+ nullptr, // move
+ nullptr, // resize
+ &AckConfigure, // ack_configure
+ nullptr, // set_window_geometry
+ &SetMaximized, // set_maximized
+ &UnsetMaximized, // set_unmaximized
+ nullptr, // set_fullscreen
+ nullptr, // unset_fullscreen
+ &SetMinimized, // set_minimized
+};
+
+} // namespace
+
+ServerObject::ServerObject(wl_resource* resource) : resource_(resource) {}
+
+ServerObject::~ServerObject() {
+ if (resource_)
+ wl_resource_destroy(resource_);
+}
+
+// static
+void ServerObject::OnResourceDestroyed(wl_resource* resource) {
+ auto obj = static_cast<ServerObject*>(wl_resource_get_user_data(resource));
+ obj->resource_ = nullptr;
+}
+
+MockXdgSurface::MockXdgSurface(wl_resource* resource) : ServerObject(resource) {
+ wl_resource_set_implementation(resource, &xdg_surface_impl, this,
+ &ServerObject::OnResourceDestroyed);
+}
+
+MockXdgSurface::~MockXdgSurface() {}
+
+MockSurface::MockSurface(wl_resource* resource) : ServerObject(resource) {
+ wl_resource_set_implementation(resource, &surface_impl, this,
+ &ServerObject::OnResourceDestroyed);
+}
+
+MockSurface::~MockSurface() {
+ if (xdg_surface && xdg_surface->resource())
+ wl_resource_destroy(xdg_surface->resource());
+}
+
+MockSurface* MockSurface::FromResource(wl_resource* resource) {
+ if (!wl_resource_instance_of(resource, &wl_surface_interface, &surface_impl))
+ return nullptr;
+ return static_cast<MockSurface*>(wl_resource_get_user_data(resource));
+}
+
+MockPointer::MockPointer(wl_resource* resource) : ServerObject(resource) {
+ wl_resource_set_implementation(resource, &pointer_impl, this,
+ &ServerObject::OnResourceDestroyed);
+}
+
+MockPointer::~MockPointer() {}
+
+void GlobalDeleter::operator()(wl_global* global) {
+ wl_global_destroy(global);
+}
+
+Global::Global(const wl_interface* interface,
+ const void* implementation,
+ uint32_t version)
+ : interface_(interface),
+ implementation_(implementation),
+ version_(version) {}
+
+Global::~Global() {}
+
+bool Global::Initialize(wl_display* display) {
+ global_.reset(wl_global_create(display, interface_, version_, this, &Bind));
+ return global_ != nullptr;
+}
+
+// static
+void Global::Bind(wl_client* client,
+ void* data,
+ uint32_t version,
+ uint32_t id) {
+ auto global = static_cast<Global*>(data);
+ wl_resource* resource = wl_resource_create(
+ client, global->interface_, std::min(version, global->version_), id);
+ if (!resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ if (!global->resource_)
+ global->resource_ = resource;
+ wl_resource_set_implementation(resource, global->implementation_, global,
+ &Global::OnResourceDestroyed);
+}
+
+// static
+void Global::OnResourceDestroyed(wl_resource* resource) {
+ auto global = static_cast<Global*>(wl_resource_get_user_data(resource));
+ if (global->resource_ == resource)
+ global->resource_ = nullptr;
+}
+
+MockCompositor::MockCompositor()
+ : Global(&wl_compositor_interface, &compositor_impl, kCompositorVersion) {}
+
+MockCompositor::~MockCompositor() {}
+
+void MockCompositor::AddSurface(scoped_ptr<MockSurface> surface) {
+ surfaces_.push_back(std::move(surface));
+}
+
+MockSeat::MockSeat() : Global(&wl_seat_interface, &seat_impl, kSeatVersion) {}
+
+MockSeat::~MockSeat() {}
+
+MockXdgShell::MockXdgShell()
+ : Global(&xdg_shell_interface, &xdg_shell_impl, kXdgShellVersion) {}
+
+MockXdgShell::~MockXdgShell() {}
+
+void DisplayDeleter::operator()(wl_display* display) {
+ wl_display_destroy(display);
+}
+
+FakeServer::FakeServer()
+ : Thread("fake_wayland_server"),
+ pause_event_(false, false),
+ resume_event_(false, false) {}
+
+FakeServer::~FakeServer() {
+ Resume();
+ Stop();
+}
+
+bool FakeServer::Start() {
+ display_.reset(wl_display_create());
+ if (!display_)
+ return false;
+ event_loop_ = wl_display_get_event_loop(display_.get());
+
+ int fd[2];
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fd) < 0)
+ return false;
+ base::ScopedFD server_fd(fd[0]);
+ base::ScopedFD client_fd(fd[1]);
+
+ if (wl_display_init_shm(display_.get()) < 0)
+ return false;
+ if (!compositor_.Initialize(display_.get()))
+ return false;
+ if (!seat_.Initialize(display_.get()))
+ return false;
+ if (!xdg_shell_.Initialize(display_.get()))
+ return false;
+
+ client_ = wl_client_create(display_.get(), server_fd.get());
+ if (!client_)
+ return false;
+ (void)server_fd.release();
+
+ base::Thread::Options options;
+ options.message_pump_factory =
+ base::Bind(&FakeServer::CreateMessagePump, base::Unretained(this));
+ if (!base::Thread::StartWithOptions(options))
+ return false;
+
+ setenv("WAYLAND_SOCKET", base::UintToString(client_fd.release()).c_str(), 1);
+
+ return true;
+}
+
+void FakeServer::Pause() {
+ task_runner()->PostTask(
+ FROM_HERE, base::Bind(&FakeServer::DoPause, base::Unretained(this)));
+ pause_event_.Wait();
+}
+
+void FakeServer::Resume() {
+ if (display_)
+ wl_display_flush_clients(display_.get());
+ resume_event_.Signal();
+}
+
+void FakeServer::DoPause() {
+ base::RunLoop().RunUntilIdle();
+ pause_event_.Signal();
+ resume_event_.Wait();
+}
+
+scoped_ptr<base::MessagePump> FakeServer::CreateMessagePump() {
+ auto pump = make_scoped_ptr(new base::MessagePumpLibevent);
+ pump->WatchFileDescriptor(wl_event_loop_get_fd(event_loop_), true,
+ base::MessagePumpLibevent::WATCH_READ, &controller_,
+ this);
+ return std::move(pump);
+}
+
+void FakeServer::OnFileCanReadWithoutBlocking(int fd) {
+ wl_event_loop_dispatch(event_loop_, 0);
+ wl_display_flush_clients(display_.get());
+}
+
+void FakeServer::OnFileCanWriteWithoutBlocking(int fd) {}
+
+} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/fake_server.h b/chromium/ui/ozone/platform/wayland/fake_server.h
new file mode 100644
index 00000000000..a47c8752a92
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/fake_server.h
@@ -0,0 +1,212 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_FAKE_SERVER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_FAKE_SERVER_H_
+
+#include <wayland-server-core.h>
+
+#include "base/bind.h"
+#include "base/message_loop/message_pump_libevent.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+struct wl_client;
+struct wl_display;
+struct wl_event_loop;
+struct wl_global;
+struct wl_resource;
+
+namespace wl {
+
+class ServerObject {
+ public:
+ ServerObject(wl_resource* resource);
+ virtual ~ServerObject();
+
+ wl_resource* resource() { return resource_; }
+
+ static void OnResourceDestroyed(wl_resource* resource);
+
+ private:
+ wl_resource* resource_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServerObject);
+};
+
+class MockXdgSurface : public ServerObject {
+ public:
+ MockXdgSurface(wl_resource* resource);
+ ~MockXdgSurface() override;
+
+ MOCK_METHOD1(SetParent, void(wl_resource* parent));
+ MOCK_METHOD1(SetTitle, void(const char* title));
+ MOCK_METHOD1(SetAppId, void(const char* app_id));
+ MOCK_METHOD1(AckConfigure, void(uint32_t serial));
+ MOCK_METHOD0(SetMaximized, void());
+ MOCK_METHOD0(UnsetMaximized, void());
+ MOCK_METHOD0(SetMinimized, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockXdgSurface);
+};
+
+class MockSurface : public ServerObject {
+ public:
+ MockSurface(wl_resource* resource);
+ ~MockSurface() override;
+
+ static MockSurface* FromResource(wl_resource* resource);
+
+ MOCK_METHOD3(Attach, void(wl_resource* buffer, int32_t x, int32_t y));
+ MOCK_METHOD4(Damage,
+ void(int32_t x, int32_t y, int32_t width, int32_t height));
+ MOCK_METHOD0(Commit, void());
+
+ scoped_ptr<MockXdgSurface> xdg_surface;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSurface);
+};
+
+class MockPointer : public ServerObject {
+ public:
+ MockPointer(wl_resource* resource);
+ ~MockPointer() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockPointer);
+};
+
+struct GlobalDeleter {
+ void operator()(wl_global* global);
+};
+
+class Global {
+ public:
+ Global(const wl_interface* interface,
+ const void* implementation,
+ uint32_t version);
+ virtual ~Global();
+
+ bool Initialize(wl_display* display);
+
+ // The first bound resource to this global, which is usually all that is
+ // useful when testing a simple client.
+ wl_resource* resource() { return resource_; }
+
+ static void Bind(wl_client* client,
+ void* data,
+ uint32_t version,
+ uint32_t id);
+ static void OnResourceDestroyed(wl_resource* resource);
+
+ private:
+ scoped_ptr<wl_global, GlobalDeleter> global_;
+
+ const wl_interface* interface_;
+ const void* implementation_;
+ const uint32_t version_;
+ wl_resource* resource_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(Global);
+};
+
+class MockCompositor : public Global {
+ public:
+ MockCompositor();
+ ~MockCompositor() override;
+
+ void AddSurface(scoped_ptr<MockSurface> surface);
+
+ private:
+ std::vector<scoped_ptr<MockSurface>> surfaces_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockCompositor);
+};
+
+class MockSeat : public Global {
+ public:
+ MockSeat();
+ ~MockSeat() override;
+
+ scoped_ptr<MockPointer> pointer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockSeat);
+};
+
+class MockXdgShell : public Global {
+ public:
+ MockXdgShell();
+ ~MockXdgShell() override;
+
+ MOCK_METHOD1(UseUnstableVersion, void(int32_t version));
+ MOCK_METHOD1(Pong, void(uint32_t serial));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockXdgShell);
+};
+
+struct DisplayDeleter {
+ void operator()(wl_display* display);
+};
+
+class FakeServer : public base::Thread, base::MessagePumpLibevent::Watcher {
+ public:
+ FakeServer();
+ ~FakeServer() override;
+
+ // Start the fake Wayland server. If this succeeds, the WAYLAND_SOCKET
+ // environment variable will be set to the string representation of a file
+ // descriptor that a client can connect to. The caller is responsible for
+ // ensuring that this file descriptor gets closed (for example, by calling
+ // wl_display_connect).
+ bool Start();
+
+ // Pause the server when it becomes idle.
+ void Pause();
+
+ // Resume the server after flushing client connections.
+ void Resume();
+
+ template <typename T>
+ T* GetObject(uint32_t id) {
+ wl_resource* resource = wl_client_get_object(client_, id);
+ return resource ? T::FromResource(resource) : nullptr;
+ }
+
+ MockSeat* seat() { return &seat_; }
+ MockXdgShell* xdg_shell() { return &xdg_shell_; }
+
+ private:
+ void DoPause();
+
+ scoped_ptr<base::MessagePump> CreateMessagePump();
+
+ // base::MessagePumpLibevent::Watcher
+ void OnFileCanReadWithoutBlocking(int fd) override;
+ void OnFileCanWriteWithoutBlocking(int fd) override;
+
+ scoped_ptr<wl_display, DisplayDeleter> display_;
+ wl_client* client_ = nullptr;
+ wl_event_loop* event_loop_ = nullptr;
+
+ base::WaitableEvent pause_event_;
+ base::WaitableEvent resume_event_;
+ bool paused_ = false;
+
+ MockCompositor compositor_;
+ MockSeat seat_;
+ MockXdgShell xdg_shell_;
+
+ base::MessagePumpLibevent::FileDescriptorWatcher controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeServer);
+};
+
+} // namespace wl
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_FAKE_SERVER_H_
diff --git a/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.cc b/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.cc
new file mode 100644
index 00000000000..aeb57a50627
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.cc
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
+
+namespace ui {
+
+MockPlatformWindowDelegate::MockPlatformWindowDelegate() {}
+
+MockPlatformWindowDelegate::~MockPlatformWindowDelegate() {}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.h b/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.h
new file mode 100644
index 00000000000..d9092e5879b
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/mock_platform_window_delegate.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_MOCK_PLATFORM_WINDOW_DELEGATE_H_
+#define UI_OZONE_PLATFORM_WAYLAND_MOCK_PLATFORM_WINDOW_DELEGATE_H_
+
+#include "ui/platform_window/platform_window_delegate.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+class MockPlatformWindowDelegate : public PlatformWindowDelegate {
+ public:
+ MockPlatformWindowDelegate();
+ ~MockPlatformWindowDelegate();
+
+ MOCK_METHOD1(OnBoundsChanged, void(const gfx::Rect& new_bounds));
+ MOCK_METHOD1(OnDamageRect, void(const gfx::Rect& damaged_region));
+ MOCK_METHOD1(DispatchEvent, void(Event* event));
+ MOCK_METHOD0(OnCloseRequest, void());
+ MOCK_METHOD0(OnClosed, void());
+ MOCK_METHOD1(OnWindowStateChanged, void(PlatformWindowState new_state));
+ MOCK_METHOD0(OnLostCapture, void());
+ MOCK_METHOD2(OnAcceleratedWidgetAvailable,
+ void(gfx::AcceleratedWidget widget, float device_pixel_ratio));
+ MOCK_METHOD0(OnAcceleratedWidgetDestroyed, void());
+ MOCK_METHOD1(OnActivationChanged, void(bool active));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockPlatformWindowDelegate);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_MOCK_PLATFORM_WINDOW_DELEGATE_H_
diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
new file mode 100644
index 00000000000..9e5eb150ce3
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -0,0 +1,109 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/ozone_platform_wayland.h"
+
+#include "ui/ozone/common/native_display_delegate_ozone.h"
+#include "ui/ozone/common/stub_overlay_manager.h"
+#include "ui/ozone/platform/wayland/wayland_display.h"
+#include "ui/ozone/platform/wayland/wayland_surface_factory.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+#include "ui/ozone/public/cursor_factory_ozone.h"
+#include "ui/ozone/public/gpu_platform_support.h"
+#include "ui/ozone/public/gpu_platform_support_host.h"
+#include "ui/ozone/public/input_controller.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
+
+namespace ui {
+
+namespace {
+
+class OzonePlatformWayland : public OzonePlatform {
+ public:
+ OzonePlatformWayland() {}
+ ~OzonePlatformWayland() override {}
+
+ // OzonePlatform
+ SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
+ return surface_factory_.get();
+ }
+
+ OverlayManagerOzone* GetOverlayManager() override {
+ return overlay_manager_.get();
+ }
+
+ CursorFactoryOzone* GetCursorFactoryOzone() override {
+ return cursor_factory_.get();
+ }
+
+ InputController* GetInputController() override {
+ return input_controller_.get();
+ }
+
+ GpuPlatformSupport* GetGpuPlatformSupport() override {
+ return gpu_platform_support_.get();
+ }
+
+ GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
+ return gpu_platform_support_host_.get();
+ }
+
+ scoped_ptr<SystemInputInjector> CreateSystemInputInjector() override {
+ return nullptr;
+ }
+
+ scoped_ptr<PlatformWindow> CreatePlatformWindow(
+ PlatformWindowDelegate* delegate,
+ const gfx::Rect& bounds) override {
+ auto window =
+ make_scoped_ptr(new WaylandWindow(delegate, display_.get(), bounds));
+ if (!window->Initialize())
+ return nullptr;
+ return std::move(window);
+ }
+
+ scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
+ return make_scoped_ptr(new NativeDisplayDelegateOzone);
+ }
+
+ void InitializeUI() override {
+ display_.reset(new WaylandDisplay);
+ if (!display_->Initialize())
+ LOG(FATAL) << "Failed to initialize Wayland platform";
+
+ cursor_factory_.reset(new CursorFactoryOzone);
+ overlay_manager_.reset(new StubOverlayManager);
+ input_controller_ = CreateStubInputController();
+ surface_factory_.reset(new WaylandSurfaceFactory(display_.get()));
+ gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
+ }
+
+ void InitializeGPU() override {
+ // Don't reinitialize the surface factory in case InitializeUI was called
+ // previously in the same process.
+ if (!surface_factory_)
+ surface_factory_.reset(new WaylandSurfaceFactory(nullptr));
+ gpu_platform_support_.reset(CreateStubGpuPlatformSupport());
+ }
+
+ private:
+ scoped_ptr<WaylandDisplay> display_;
+ scoped_ptr<WaylandSurfaceFactory> surface_factory_;
+ scoped_ptr<CursorFactoryOzone> cursor_factory_;
+ scoped_ptr<StubOverlayManager> overlay_manager_;
+ scoped_ptr<InputController> input_controller_;
+ scoped_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
+ scoped_ptr<GpuPlatformSupport> gpu_platform_support_;
+
+ DISALLOW_COPY_AND_ASSIGN(OzonePlatformWayland);
+};
+
+} // namespace
+
+OzonePlatform* CreateOzonePlatformWayland() {
+ return new OzonePlatformWayland;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h
new file mode 100644
index 00000000000..2eb802cd466
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_DRM_OZONE_PLATFORM_WAYLAND_H_
+#define UI_OZONE_PLATFORM_DRM_OZONE_PLATFORM_WAYLAND_H_
+
+namespace ui {
+
+class OzonePlatform;
+
+// Constructor hook for use in ozone_platform_list.cc
+OzonePlatform* CreateOzonePlatformWayland();
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_DRM_OZONE_PLATFORM_WAYLAND_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland.gypi b/chromium/ui/ozone/platform/wayland/wayland.gypi
new file mode 100644
index 00000000000..c71b6346172
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland.gypi
@@ -0,0 +1,87 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'internal_ozone_platform_deps': [
+ 'ozone_platform_wayland',
+ ],
+ 'internal_ozone_platform_unittest_deps': [
+ 'ozone_platform_wayland_unittests',
+ ],
+ 'internal_ozone_platforms': [
+ 'wayland'
+ ],
+ },
+ 'targets': [
+ {
+ 'target_name': 'ozone_platform_wayland',
+ 'type': 'static_library',
+ 'defines': [
+ 'OZONE_IMPLEMENTATION',
+ ],
+ 'dependencies': [
+ 'ozone.gyp:ozone_base',
+ 'ozone.gyp:ozone_common',
+ '../../base/base.gyp:base',
+ '../../skia/skia.gyp:skia',
+ '../../third_party/wayland-protocols/wayland-protocols.gyp:xdg_shell_protocol',
+ '../../third_party/wayland/wayland.gyp:wayland_client',
+ '../events/events.gyp:events',
+ '../events/platform/events_platform.gyp:events_platform',
+ ],
+ 'sources': [
+ 'client_native_pixmap_factory_wayland.cc',
+ 'client_native_pixmap_factory_wayland.h',
+ 'ozone_platform_wayland.cc',
+ 'ozone_platform_wayland.h',
+ 'wayland_display.cc',
+ 'wayland_display.h',
+ 'wayland_object.cc',
+ 'wayland_object.h',
+ 'wayland_pointer.cc',
+ 'wayland_pointer.h',
+ 'wayland_surface_factory.cc',
+ 'wayland_surface_factory.h',
+ 'wayland_window.cc',
+ 'wayland_window.h',
+ ],
+ },
+ {
+ 'target_name': 'ozone_platform_wayland_unittests',
+ 'type': 'none',
+ 'dependencies': [
+ 'ozone.gyp:ozone_platform',
+ '../../skia/skia.gyp:skia',
+ '../../testing/gmock.gyp:gmock',
+ '../../third_party/wayland-protocols/wayland-protocols.gyp:xdg_shell_protocol',
+ '../../third_party/wayland/wayland.gyp:wayland_server',
+ '../gfx/gfx.gyp:gfx_test_support',
+ ],
+ 'export_dependent_settings': [
+ '../../skia/skia.gyp:skia',
+ '../../testing/gmock.gyp:gmock',
+ '../../third_party/wayland-protocols/wayland-protocols.gyp:xdg_shell_protocol',
+ '../../third_party/wayland/wayland.gyp:wayland_server',
+ '../gfx/gfx.gyp:gfx_test_support',
+ ],
+ 'direct_dependent_settings': {
+ 'defines': [
+ 'WL_HIDE_DEPRECATED',
+ ],
+ 'sources': [
+ 'fake_server.cc',
+ 'fake_server.h',
+ 'mock_platform_window_delegate.cc',
+ 'wayland_display_unittest.cc',
+ 'wayland_pointer_unittest.cc',
+ 'wayland_surface_factory_unittest.cc',
+ 'wayland_test.cc',
+ 'wayland_test.h',
+ 'wayland_window_unittest.cc',
+ ],
+ },
+ },
+ ],
+}
diff --git a/chromium/ui/ozone/platform/wayland/wayland_display.cc b/chromium/ui/ozone/platform/wayland/wayland_display.cc
new file mode 100644
index 00000000000..a34abe266a5
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_display.cc
@@ -0,0 +1,215 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_display.h"
+
+#include <xdg-shell-unstable-v5-client-protocol.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version");
+
+namespace ui {
+namespace {
+const uint32_t kMaxCompositorVersion = 4;
+const uint32_t kMaxSeatVersion = 4;
+const uint32_t kMaxShmVersion = 1;
+const uint32_t kMaxXdgShellVersion = 1;
+} // namespace
+
+WaylandDisplay::WaylandDisplay() {}
+
+WaylandDisplay::~WaylandDisplay() {}
+
+bool WaylandDisplay::Initialize() {
+ static const wl_registry_listener registry_listener = {
+ &WaylandDisplay::Global, &WaylandDisplay::GlobalRemove,
+ };
+
+ display_.reset(wl_display_connect(nullptr));
+ if (!display_) {
+ LOG(ERROR) << "Failed to connect to Wayland display";
+ return false;
+ }
+
+ registry_.reset(wl_display_get_registry(display_.get()));
+ if (!registry_) {
+ LOG(ERROR) << "Failed to get Wayland registry";
+ return false;
+ }
+
+ wl_registry_add_listener(registry_.get(), &registry_listener, this);
+ wl_display_roundtrip(display_.get());
+
+ if (!compositor_) {
+ LOG(ERROR) << "No wl_compositor object";
+ return false;
+ }
+ if (!shm_) {
+ LOG(ERROR) << "No wl_shm object";
+ return false;
+ }
+ if (!seat_) {
+ LOG(ERROR) << "No wl_seat object";
+ return false;
+ }
+ if (!shell_) {
+ LOG(ERROR) << "No xdg_shell object";
+ return false;
+ }
+
+ return true;
+}
+
+bool WaylandDisplay::StartProcessingEvents() {
+ if (watching_)
+ return true;
+
+ DCHECK(display_);
+ wl_display_flush(display_.get());
+
+ DCHECK(base::MessageLoopForUI::IsCurrent());
+ if (!base::MessageLoopForUI::current()->WatchFileDescriptor(
+ wl_display_get_fd(display_.get()), true,
+ base::MessagePumpLibevent::WATCH_READ, &controller_, this))
+ return false;
+
+ watching_ = true;
+ return true;
+}
+
+void WaylandDisplay::ScheduleFlush() {
+ if (scheduled_flush_ || !watching_)
+ return;
+ base::MessageLoopForUI::current()->task_runner()->PostTask(
+ FROM_HERE, base::Bind(&WaylandDisplay::Flush, base::Unretained(this)));
+ scheduled_flush_ = true;
+}
+
+WaylandWindow* WaylandDisplay::GetWindow(gfx::AcceleratedWidget widget) {
+ auto it = window_map_.find(widget);
+ return it == window_map_.end() ? nullptr : it->second;
+}
+
+void WaylandDisplay::AddWindow(gfx::AcceleratedWidget widget,
+ WaylandWindow* window) {
+ window_map_[widget] = window;
+}
+
+void WaylandDisplay::RemoveWindow(gfx::AcceleratedWidget widget) {
+ window_map_.erase(widget);
+}
+
+void WaylandDisplay::OnDispatcherListChanged() {
+ StartProcessingEvents();
+}
+
+void WaylandDisplay::Flush() {
+ wl_display_flush(display_.get());
+ scheduled_flush_ = false;
+}
+
+void WaylandDisplay::DispatchUiEvent(Event* event) {
+ PlatformEventSource::DispatchEvent(event);
+}
+
+void WaylandDisplay::OnFileCanReadWithoutBlocking(int fd) {
+ wl_display_dispatch(display_.get());
+ for (const auto& window : window_map_)
+ window.second->ApplyPendingBounds();
+}
+
+void WaylandDisplay::OnFileCanWriteWithoutBlocking(int fd) {}
+
+// static
+void WaylandDisplay::Global(void* data,
+ wl_registry* registry,
+ uint32_t name,
+ const char* interface,
+ uint32_t version) {
+ static const wl_seat_listener seat_listener = {
+ &WaylandDisplay::Capabilities, &WaylandDisplay::Name,
+ };
+ static const xdg_shell_listener shell_listener = {
+ &WaylandDisplay::Ping,
+ };
+
+ WaylandDisplay* display = static_cast<WaylandDisplay*>(data);
+ if (!display->compositor_ && strcmp(interface, "wl_compositor") == 0) {
+ display->compositor_ = wl::Bind<wl_compositor>(
+ registry, name, std::min(version, kMaxCompositorVersion));
+ if (!display->compositor_)
+ LOG(ERROR) << "Failed to bind to wl_compositor global";
+ } else if (!display->shm_ && strcmp(interface, "wl_shm") == 0) {
+ display->shm_ =
+ wl::Bind<wl_shm>(registry, name, std::min(version, kMaxShmVersion));
+ if (!display->shm_)
+ LOG(ERROR) << "Failed to bind to wl_shm global";
+ } else if (!display->seat_ && strcmp(interface, "wl_seat") == 0) {
+ display->seat_ =
+ wl::Bind<wl_seat>(registry, name, std::min(version, kMaxSeatVersion));
+ if (!display->seat_) {
+ LOG(ERROR) << "Failed to bind to wl_seat global";
+ return;
+ }
+ wl_seat_add_listener(display->seat_.get(), &seat_listener, display);
+ } else if (!display->shell_ && strcmp(interface, "xdg_shell") == 0) {
+ display->shell_ = wl::Bind<xdg_shell>(
+ registry, name, std::min(version, kMaxXdgShellVersion));
+ if (!display->shell_) {
+ LOG(ERROR) << "Failed to bind to xdg_shell global";
+ return;
+ }
+ xdg_shell_add_listener(display->shell_.get(), &shell_listener, display);
+ xdg_shell_use_unstable_version(display->shell_.get(),
+ XDG_SHELL_VERSION_CURRENT);
+ }
+
+ display->ScheduleFlush();
+}
+
+// static
+void WaylandDisplay::GlobalRemove(void* data,
+ wl_registry* registry,
+ uint32_t name) {
+ NOTIMPLEMENTED();
+}
+
+// static
+void WaylandDisplay::Capabilities(void* data,
+ wl_seat* seat,
+ uint32_t capabilities) {
+ WaylandDisplay* display = static_cast<WaylandDisplay*>(data);
+ if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
+ if (!display->pointer_) {
+ wl_pointer* pointer = wl_seat_get_pointer(display->seat_.get());
+ if (!pointer) {
+ LOG(ERROR) << "Failed to get wl_pointer from seat";
+ return;
+ }
+ display->pointer_ = make_scoped_ptr(new WaylandPointer(
+ pointer, base::Bind(&WaylandDisplay::DispatchUiEvent,
+ base::Unretained(display))));
+ }
+ } else if (display->pointer_) {
+ display->pointer_.reset();
+ }
+ display->ScheduleFlush();
+}
+
+// static
+void WaylandDisplay::Name(void* data, wl_seat* seat, const char* name) {}
+
+// static
+void WaylandDisplay::Ping(void* data, xdg_shell* shell, uint32_t serial) {
+ WaylandDisplay* display = static_cast<WaylandDisplay*>(data);
+ xdg_shell_pong(shell, serial);
+ display->ScheduleFlush();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_display.h b/chromium/ui/ozone/platform/wayland/wayland_display.h
new file mode 100644
index 00000000000..eb72c9ccf07
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_display.h
@@ -0,0 +1,87 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DISPLAY_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DISPLAY_H_
+
+#include <map>
+
+#include "base/message_loop/message_pump_libevent.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/ozone/platform/wayland/wayland_pointer.h"
+
+namespace ui {
+
+class WaylandWindow;
+
+class WaylandDisplay : public PlatformEventSource,
+ public base::MessagePumpLibevent::Watcher {
+ public:
+ WaylandDisplay();
+ ~WaylandDisplay() override;
+
+ bool Initialize();
+ bool StartProcessingEvents();
+
+ // Schedules a flush of the Wayland connection.
+ void ScheduleFlush();
+
+ wl_display* display() { return display_.get(); }
+ wl_compositor* compositor() { return compositor_.get(); }
+ wl_shm* shm() { return shm_.get(); }
+ xdg_shell* shell() { return shell_.get(); }
+
+ WaylandWindow* GetWindow(gfx::AcceleratedWidget widget);
+ void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window);
+ void RemoveWindow(gfx::AcceleratedWidget widget);
+
+ private:
+ void Flush();
+ void DispatchUiEvent(Event* event);
+
+ // PlatformEventSource
+ void OnDispatcherListChanged() override;
+
+ // base::MessagePumpLibevent::Watcher
+ void OnFileCanReadWithoutBlocking(int fd) override;
+ void OnFileCanWriteWithoutBlocking(int fd) override;
+
+ // wl_registry_listener
+ static void Global(void* data,
+ wl_registry* registry,
+ uint32_t name,
+ const char* interface,
+ uint32_t version);
+ static void GlobalRemove(void* data, wl_registry* registry, uint32_t name);
+
+ // wl_seat_listener
+ static void Capabilities(void* data, wl_seat* seat, uint32_t capabilities);
+ static void Name(void* data, wl_seat* seat, const char* name);
+
+ // xdg_shell_listener
+ static void Ping(void* data, xdg_shell* shell, uint32_t serial);
+
+ std::map<gfx::AcceleratedWidget, WaylandWindow*> window_map_;
+
+ wl::Object<wl_display> display_;
+ wl::Object<wl_registry> registry_;
+ wl::Object<wl_compositor> compositor_;
+ wl::Object<wl_seat> seat_;
+ wl::Object<wl_shm> shm_;
+ wl::Object<xdg_shell> shell_;
+
+ scoped_ptr<WaylandPointer> pointer_;
+
+ bool scheduled_flush_ = false;
+ bool watching_ = false;
+ base::MessagePumpLibevent::FileDescriptorWatcher controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandDisplay);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DISPLAY_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_display_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_display_unittest.cc
new file mode 100644
index 00000000000..3b37154a689
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_display_unittest.cc
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <wayland-server-core.h>
+#include <xdg-shell-unstable-v5-server-protocol.h>
+
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/wayland_display.h"
+
+namespace ui {
+
+TEST(WaylandDisplayTest, UseUnstableVersion) {
+ base::MessageLoopForUI message_loop;
+ wl::FakeServer server;
+ EXPECT_CALL(*server.xdg_shell(),
+ UseUnstableVersion(XDG_SHELL_VERSION_CURRENT));
+ ASSERT_TRUE(server.Start());
+ WaylandDisplay display;
+ ASSERT_TRUE(display.Initialize());
+ display.StartProcessingEvents();
+
+ base::RunLoop().RunUntilIdle();
+ server.Pause();
+}
+
+TEST(WaylandDisplayTest, Ping) {
+ base::MessageLoopForUI message_loop;
+ wl::FakeServer server;
+ ASSERT_TRUE(server.Start());
+ WaylandDisplay display;
+ ASSERT_TRUE(display.Initialize());
+ display.StartProcessingEvents();
+
+ base::RunLoop().RunUntilIdle();
+ server.Pause();
+
+ xdg_shell_send_ping(server.xdg_shell()->resource(), 1234);
+ EXPECT_CALL(*server.xdg_shell(), Pong(1234));
+
+ server.Resume();
+ base::RunLoop().RunUntilIdle();
+ server.Pause();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_object.cc b/chromium/ui/ozone/platform/wayland/wayland_object.cc
new file mode 100644
index 00000000000..6b7f1e185ae
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_object.cc
@@ -0,0 +1,67 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_object.h"
+
+#include <wayland-client.h>
+#include <xdg-shell-unstable-v5-client-protocol.h>
+
+namespace wl {
+namespace {
+
+void delete_pointer(wl_pointer* pointer) {
+ if (wl_pointer_get_version(pointer) >= WL_POINTER_RELEASE_SINCE_VERSION)
+ wl_pointer_release(pointer);
+ else
+ wl_pointer_destroy(pointer);
+}
+
+void delete_seat(wl_seat* seat) {
+ if (wl_seat_get_version(seat) >= WL_SEAT_RELEASE_SINCE_VERSION)
+ wl_seat_release(seat);
+ else
+ wl_seat_destroy(seat);
+}
+
+} // namespace
+
+const wl_interface* ObjectTraits<wl_buffer>::interface = &wl_buffer_interface;
+void (*ObjectTraits<wl_buffer>::deleter)(wl_buffer*) = &wl_buffer_destroy;
+
+const wl_interface* ObjectTraits<wl_compositor>::interface =
+ &wl_compositor_interface;
+void (*ObjectTraits<wl_compositor>::deleter)(wl_compositor*) =
+ &wl_compositor_destroy;
+
+const wl_interface* ObjectTraits<wl_display>::interface = &wl_display_interface;
+void (*ObjectTraits<wl_display>::deleter)(wl_display*) = &wl_display_disconnect;
+
+const wl_interface* ObjectTraits<wl_pointer>::interface = &wl_pointer_interface;
+void (*ObjectTraits<wl_pointer>::deleter)(wl_pointer*) = &delete_pointer;
+
+const wl_interface* ObjectTraits<wl_registry>::interface =
+ &wl_registry_interface;
+void (*ObjectTraits<wl_registry>::deleter)(wl_registry*) = &wl_registry_destroy;
+
+const wl_interface* ObjectTraits<wl_seat>::interface = &wl_seat_interface;
+void (*ObjectTraits<wl_seat>::deleter)(wl_seat*) = &delete_seat;
+
+const wl_interface* ObjectTraits<wl_shm>::interface = &wl_shm_interface;
+void (*ObjectTraits<wl_shm>::deleter)(wl_shm*) = &wl_shm_destroy;
+
+const wl_interface* ObjectTraits<wl_shm_pool>::interface =
+ &wl_shm_pool_interface;
+void (*ObjectTraits<wl_shm_pool>::deleter)(wl_shm_pool*) = &wl_shm_pool_destroy;
+
+const wl_interface* ObjectTraits<wl_surface>::interface = &wl_surface_interface;
+void (*ObjectTraits<wl_surface>::deleter)(wl_surface*) = &wl_surface_destroy;
+
+const wl_interface* ObjectTraits<xdg_shell>::interface = &xdg_shell_interface;
+void (*ObjectTraits<xdg_shell>::deleter)(xdg_shell*) = &xdg_shell_destroy;
+
+const wl_interface* ObjectTraits<xdg_surface>::interface =
+ &xdg_surface_interface;
+void (*ObjectTraits<xdg_surface>::deleter)(xdg_surface*) = &xdg_surface_destroy;
+
+} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/wayland_object.h b/chromium/ui/ozone/platform/wayland/wayland_object.h
new file mode 100644
index 00000000000..f5324f9bf15
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_object.h
@@ -0,0 +1,121 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_
+
+#include <wayland-client-core.h>
+
+#include "base/memory/scoped_ptr.h"
+
+struct wl_buffer;
+struct wl_compositor;
+struct wl_pointer;
+struct wl_registry;
+struct wl_seat;
+struct wl_shm;
+struct wl_shm_pool;
+struct wl_surface;
+struct xdg_shell;
+struct xdg_surface;
+
+namespace wl {
+
+template <typename T>
+struct ObjectTraits;
+
+template <>
+struct ObjectTraits<wl_buffer> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_buffer*);
+};
+
+template <>
+struct ObjectTraits<wl_compositor> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_compositor*);
+};
+
+template <>
+struct ObjectTraits<wl_display> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_display*);
+};
+
+template <>
+struct ObjectTraits<wl_pointer> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_pointer*);
+};
+
+template <>
+struct ObjectTraits<wl_registry> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_registry*);
+};
+
+template <>
+struct ObjectTraits<wl_seat> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_seat*);
+};
+
+template <>
+struct ObjectTraits<wl_shm> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_shm*);
+};
+
+template <>
+struct ObjectTraits<wl_shm_pool> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_shm_pool*);
+};
+
+template <>
+struct ObjectTraits<wl_surface> {
+ static const wl_interface* interface;
+ static void (*deleter)(wl_surface*);
+};
+
+template <>
+struct ObjectTraits<xdg_shell> {
+ static const wl_interface* interface;
+ static void (*deleter)(xdg_shell*);
+};
+
+template <>
+struct ObjectTraits<xdg_surface> {
+ static const wl_interface* interface;
+ static void (*deleter)(xdg_surface*);
+};
+
+struct Deleter {
+ template <typename T>
+ void operator()(T* obj) {
+ ObjectTraits<T>::deleter(obj);
+ }
+};
+
+template <typename T>
+class Object : public scoped_ptr<T, Deleter> {
+ public:
+ Object() {}
+ explicit Object(T* obj) : scoped_ptr<T, Deleter>(obj) {}
+
+ uint32_t id() {
+ return wl_proxy_get_id(
+ reinterpret_cast<wl_proxy*>(scoped_ptr<T, Deleter>::get()));
+ }
+};
+
+template <typename T>
+wl::Object<T> Bind(wl_registry* registry, uint32_t name, uint32_t version) {
+ return wl::Object<T>(static_cast<T*>(
+ wl_registry_bind(registry, name, ObjectTraits<T>::interface, version)));
+}
+
+} // namespace wl
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.cc b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc
new file mode 100644
index 00000000000..7cdb4fbb511
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc
@@ -0,0 +1,143 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_pointer.h"
+
+#include <linux/input.h>
+#include <wayland-client.h>
+
+#include "ui/events/event.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+// TODO(forney): Handle version 5 of wl_pointer.
+
+namespace ui {
+
+WaylandPointer::WaylandPointer(wl_pointer* pointer,
+ const EventDispatchCallback& callback)
+ : obj_(pointer), callback_(callback) {
+ static const wl_pointer_listener listener = {
+ &WaylandPointer::Enter, &WaylandPointer::Leave, &WaylandPointer::Motion,
+ &WaylandPointer::Button, &WaylandPointer::Axis,
+ };
+
+ wl_pointer_add_listener(obj_.get(), &listener, this);
+}
+
+WaylandPointer::~WaylandPointer() {}
+
+// static
+void WaylandPointer::Enter(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ wl_surface* surface,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y) {
+ WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+ pointer->location_.SetPoint(wl_fixed_to_double(surface_x),
+ wl_fixed_to_double(surface_y));
+ if (surface)
+ WaylandWindow::FromSurface(surface)->set_pointer_focus(true);
+}
+
+// static
+void WaylandPointer::Leave(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ wl_surface* surface) {
+ if (surface)
+ WaylandWindow::FromSurface(surface)->set_pointer_focus(false);
+}
+
+// static
+void WaylandPointer::Motion(void* data,
+ wl_pointer* obj,
+ uint32_t time,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y) {
+ WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+ pointer->location_.SetPoint(wl_fixed_to_double(surface_x),
+ wl_fixed_to_double(surface_y));
+ MouseEvent event(ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+ base::TimeDelta::FromMilliseconds(time), pointer->flags_, 0);
+ event.set_location_f(pointer->location_);
+ event.set_root_location_f(pointer->location_);
+ pointer->callback_.Run(&event);
+}
+
+// static
+void WaylandPointer::Button(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state) {
+ WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+ int flag;
+ switch (button) {
+ case BTN_LEFT:
+ flag = EF_LEFT_MOUSE_BUTTON;
+ break;
+ case BTN_MIDDLE:
+ flag = EF_MIDDLE_MOUSE_BUTTON;
+ break;
+ case BTN_RIGHT:
+ flag = EF_RIGHT_MOUSE_BUTTON;
+ break;
+ case BTN_BACK:
+ flag = EF_BACK_MOUSE_BUTTON;
+ break;
+ case BTN_FORWARD:
+ flag = EF_FORWARD_MOUSE_BUTTON;
+ break;
+ default:
+ return;
+ }
+ int flags = pointer->flags_ | flag;
+ EventType type;
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
+ type = ET_MOUSE_PRESSED;
+ pointer->flags_ |= flag;
+ } else {
+ type = ET_MOUSE_RELEASED;
+ pointer->flags_ &= ~flag;
+ }
+ MouseEvent event(type, gfx::Point(), gfx::Point(),
+ base::TimeDelta::FromMilliseconds(time), flags, flag);
+ event.set_location_f(pointer->location_);
+ event.set_root_location_f(pointer->location_);
+ pointer->callback_.Run(&event);
+}
+
+// static
+void WaylandPointer::Axis(void* data,
+ wl_pointer* obj,
+ uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value) {
+ static const double kAxisValueScale = 10.0;
+ WaylandPointer* pointer = static_cast<WaylandPointer*>(data);
+ gfx::Vector2d offset;
+ // Wayland compositors send axis events with values in the surface coordinate
+ // space. They send a value of 10 per mouse wheel click by convention, so
+ // clients (e.g. GTK+) typically scale down by this amount to convert to
+ // discrete step coordinates. wl_pointer version 5 improves the situation by
+ // adding axis sources and discrete axis events.
+ if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+ offset.set_y(-wl_fixed_to_double(value) / kAxisValueScale *
+ MouseWheelEvent::kWheelDelta);
+ else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
+ offset.set_x(wl_fixed_to_double(value) / kAxisValueScale *
+ MouseWheelEvent::kWheelDelta);
+ else
+ return;
+ MouseWheelEvent event(offset, gfx::Point(), gfx::Point(),
+ base::TimeDelta::FromMilliseconds(time),
+ pointer->flags_, 0);
+ event.set_location_f(pointer->location_);
+ event.set_root_location_f(pointer->location_);
+ pointer->callback_.Run(&event);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.h b/chromium/ui/ozone/platform/wayland/wayland_pointer.h
new file mode 100644
index 00000000000..bee75a9e4bb
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.h
@@ -0,0 +1,56 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_POINTER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_POINTER_H_
+
+#include "ui/events/ozone/evdev/event_dispatch_callback.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/ozone/platform/wayland/wayland_object.h"
+
+namespace ui {
+
+class WaylandPointer {
+ public:
+ WaylandPointer(wl_pointer* pointer, const EventDispatchCallback& callback);
+ virtual ~WaylandPointer();
+
+ private:
+ // wl_pointer_listener
+ static void Enter(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ wl_surface* surface,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y);
+ static void Leave(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ wl_surface* surface);
+ static void Motion(void* data,
+ wl_pointer* obj,
+ uint32_t time,
+ wl_fixed_t surface_x,
+ wl_fixed_t surface_y);
+ static void Button(void* data,
+ wl_pointer* obj,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state);
+ static void Axis(void* data,
+ wl_pointer* obj,
+ uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value);
+
+ wl::Object<wl_pointer> obj_;
+ EventDispatchCallback callback_;
+ gfx::PointF location_;
+ int flags_ = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_POINTER_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc
new file mode 100644
index 00000000000..71e28bed3c9
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_pointer_unittest.cc
@@ -0,0 +1,232 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <linux/input.h>
+#include <wayland-server.h>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
+#include "ui/ozone/platform/wayland/wayland_test.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+using ::testing::SaveArg;
+using ::testing::_;
+
+namespace ui {
+
+class WaylandPointerTest : public WaylandTest {
+ public:
+ WaylandPointerTest() {}
+
+ void SetUp() override {
+ WaylandTest::SetUp();
+
+ wl_seat_send_capabilities(server.seat()->resource(),
+ WL_SEAT_CAPABILITY_POINTER);
+
+ Sync();
+
+ pointer = server.seat()->pointer.get();
+ ASSERT_TRUE(pointer);
+ }
+
+ protected:
+ wl::MockPointer* pointer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandPointerTest);
+};
+
+TEST_F(WaylandPointerTest, Leave) {
+ MockPlatformWindowDelegate other_delegate;
+ WaylandWindow other_window(&other_delegate, &display,
+ gfx::Rect(0, 0, 10, 10));
+ gfx::AcceleratedWidget other_widget = gfx::kNullAcceleratedWidget;
+ EXPECT_CALL(other_delegate, OnAcceleratedWidgetAvailable(_, _))
+ .WillOnce(SaveArg<0>(&other_widget));
+ ASSERT_TRUE(other_window.Initialize());
+ ASSERT_NE(other_widget, gfx::kNullAcceleratedWidget);
+
+ Sync();
+
+ wl::MockSurface* other_surface =
+ server.GetObject<wl::MockSurface>(other_widget);
+ ASSERT_TRUE(other_surface);
+
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0);
+ wl_pointer_send_leave(pointer->resource(), 2, surface->resource());
+ wl_pointer_send_enter(pointer->resource(), 3, other_surface->resource(), 0,
+ 0);
+ wl_pointer_send_button(pointer->resource(), 4, 1004, BTN_LEFT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+ EXPECT_CALL(delegate, DispatchEvent(_)).Times(0);
+
+ // Do an extra Sync() here so that we process the second enter event before we
+ // destroy |other_window|.
+ Sync();
+}
+
+ACTION_P(CloneEvent, ptr) {
+ *ptr = Event::Clone(*arg0);
+}
+
+TEST_F(WaylandPointerTest, Motion) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0);
+ wl_pointer_send_motion(pointer->resource(), 1002, wl_fixed_from_double(10.75),
+ wl_fixed_from_double(20.375));
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ auto mouse_event = static_cast<MouseEvent*>(event.get());
+ EXPECT_EQ(ET_MOUSE_MOVED, mouse_event->type());
+ EXPECT_EQ(0, mouse_event->button_flags());
+ EXPECT_EQ(0, mouse_event->changed_button_flags());
+ // TODO(forney): Once crbug.com/337827 is solved, compare with the fractional
+ // coordinates sent above.
+ EXPECT_EQ(gfx::PointF(10, 20), mouse_event->location_f());
+ EXPECT_EQ(gfx::PointF(10, 20), mouse_event->root_location_f());
+}
+
+TEST_F(WaylandPointerTest, MotionDragged) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(), 0, 0);
+ wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_MIDDLE,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ wl_pointer_send_motion(pointer->resource(), 1003, wl_fixed_from_int(400),
+ wl_fixed_from_int(500));
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ auto mouse_event = static_cast<MouseEvent*>(event.get());
+ EXPECT_EQ(ET_MOUSE_DRAGGED, mouse_event->type());
+ EXPECT_EQ(EF_MIDDLE_MOUSE_BUTTON, mouse_event->button_flags());
+ EXPECT_EQ(0, mouse_event->changed_button_flags());
+ EXPECT_EQ(gfx::PointF(400, 500), mouse_event->location_f());
+ EXPECT_EQ(gfx::PointF(400, 500), mouse_event->root_location_f());
+}
+
+TEST_F(WaylandPointerTest, ButtonPress) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(),
+ wl_fixed_from_int(200), wl_fixed_from_int(150));
+ wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_RIGHT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ wl_pointer_send_button(pointer->resource(), 3, 1003, BTN_LEFT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ auto mouse_event = static_cast<MouseEvent*>(event.get());
+ EXPECT_EQ(ET_MOUSE_PRESSED, mouse_event->type());
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON,
+ mouse_event->button_flags());
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, mouse_event->changed_button_flags());
+ EXPECT_EQ(gfx::PointF(200, 150), mouse_event->location_f());
+ EXPECT_EQ(gfx::PointF(200, 150), mouse_event->root_location_f());
+}
+
+TEST_F(WaylandPointerTest, ButtonRelease) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(),
+ wl_fixed_from_int(50), wl_fixed_from_int(50));
+ wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_BACK,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+ wl_pointer_send_button(pointer->resource(), 3, 1003, BTN_LEFT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ wl_pointer_send_button(pointer->resource(), 4, 1004, BTN_LEFT,
+ WL_POINTER_BUTTON_STATE_RELEASED);
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ auto mouse_event = static_cast<MouseEvent*>(event.get());
+ EXPECT_EQ(ET_MOUSE_RELEASED, mouse_event->type());
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_BACK_MOUSE_BUTTON,
+ mouse_event->button_flags());
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, mouse_event->changed_button_flags());
+ EXPECT_EQ(gfx::PointF(50, 50), mouse_event->location_f());
+ EXPECT_EQ(gfx::PointF(50, 50), mouse_event->root_location_f());
+}
+
+TEST_F(WaylandPointerTest, AxisVertical) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(),
+ wl_fixed_from_int(0), wl_fixed_from_int(0));
+ wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_RIGHT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ // Wayland servers typically send a value of 10 per mouse wheel click.
+ wl_pointer_send_axis(pointer->resource(), 1003,
+ WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(20));
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseWheelEvent());
+ auto mouse_wheel_event = static_cast<MouseWheelEvent*>(event.get());
+ EXPECT_EQ(gfx::Vector2d(0, -2 * MouseWheelEvent::kWheelDelta),
+ mouse_wheel_event->offset());
+ EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, mouse_wheel_event->button_flags());
+ EXPECT_EQ(0, mouse_wheel_event->changed_button_flags());
+ EXPECT_EQ(gfx::PointF(), mouse_wheel_event->location_f());
+ EXPECT_EQ(gfx::PointF(), mouse_wheel_event->root_location_f());
+}
+
+TEST_F(WaylandPointerTest, AxisHorizontal) {
+ wl_pointer_send_enter(pointer->resource(), 1, surface->resource(),
+ wl_fixed_from_int(50), wl_fixed_from_int(75));
+ wl_pointer_send_button(pointer->resource(), 2, 1002, BTN_LEFT,
+ WL_POINTER_BUTTON_STATE_PRESSED);
+
+ Sync();
+
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ // Wayland servers typically send a value of 10 per mouse wheel click.
+ wl_pointer_send_axis(pointer->resource(), 1003,
+ WL_POINTER_AXIS_HORIZONTAL_SCROLL,
+ wl_fixed_from_int(10));
+
+ Sync();
+
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseWheelEvent());
+ auto mouse_wheel_event = static_cast<MouseWheelEvent*>(event.get());
+ EXPECT_EQ(gfx::Vector2d(MouseWheelEvent::kWheelDelta, 0),
+ mouse_wheel_event->offset());
+ EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, mouse_wheel_event->button_flags());
+ EXPECT_EQ(0, mouse_wheel_event->changed_button_flags());
+ EXPECT_EQ(gfx::PointF(50, 75), mouse_wheel_event->location_f());
+ EXPECT_EQ(gfx::PointF(50, 75), mouse_wheel_event->root_location_f());
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc
new file mode 100644
index 00000000000..545016f7771
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc
@@ -0,0 +1,170 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_surface_factory.h"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+
+#include "base/memory/shared_memory.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/gfx/vsync_provider.h"
+#include "ui/ozone/platform/wayland/wayland_display.h"
+#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+#include "ui/ozone/public/surface_ozone_canvas.h"
+#include "ui/ozone/public/surface_ozone_egl.h"
+
+namespace ui {
+
+static void DeleteSharedMemory(void* pixels, void* context) {
+ delete static_cast<base::SharedMemory*>(context);
+}
+
+class WaylandCanvasSurface : public SurfaceOzoneCanvas {
+ public:
+ WaylandCanvasSurface(WaylandDisplay* display, WaylandWindow* window_);
+ ~WaylandCanvasSurface() override;
+
+ // SurfaceOzoneCanvas
+ skia::RefPtr<SkSurface> GetSurface() override;
+ void ResizeCanvas(const gfx::Size& viewport_size) override;
+ void PresentCanvas(const gfx::Rect& damage) override;
+ scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override;
+
+ private:
+ WaylandDisplay* display_;
+ WaylandWindow* window_;
+
+ gfx::Size size_;
+ skia::RefPtr<SkSurface> sk_surface_;
+ wl::Object<wl_shm_pool> pool_;
+ wl::Object<wl_buffer> buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandCanvasSurface);
+};
+
+WaylandCanvasSurface::WaylandCanvasSurface(WaylandDisplay* display,
+ WaylandWindow* window)
+ : display_(display), window_(window), size_(window->GetBounds().size()) {}
+
+WaylandCanvasSurface::~WaylandCanvasSurface() {}
+
+skia::RefPtr<SkSurface> WaylandCanvasSurface::GetSurface() {
+ if (sk_surface_)
+ return sk_surface_;
+
+ size_t length = size_.width() * size_.height() * 4;
+ auto shared_memory = make_scoped_ptr(new base::SharedMemory);
+ if (!shared_memory->CreateAndMapAnonymous(length))
+ return nullptr;
+
+ wl::Object<wl_shm_pool> pool(
+ wl_shm_create_pool(display_->shm(), shared_memory->handle().fd, length));
+ if (!pool)
+ return nullptr;
+ wl::Object<wl_buffer> buffer(
+ wl_shm_pool_create_buffer(pool.get(), 0, size_.width(), size_.height(),
+ size_.width() * 4, WL_SHM_FORMAT_ARGB8888));
+ if (!buffer)
+ return nullptr;
+
+ sk_surface_ = skia::AdoptRef(SkSurface::NewRasterDirectReleaseProc(
+ SkImageInfo::MakeN32Premul(size_.width(), size_.height()),
+ shared_memory->memory(), size_.width() * 4, &DeleteSharedMemory,
+ shared_memory.get(), nullptr));
+ if (!sk_surface_)
+ return nullptr;
+ pool_ = std::move(pool);
+ buffer_ = std::move(buffer);
+ (void)shared_memory.release();
+ return sk_surface_;
+}
+
+void WaylandCanvasSurface::ResizeCanvas(const gfx::Size& viewport_size) {
+ if (size_ == viewport_size)
+ return;
+ // TODO(forney): We could implement more efficient resizes by allocating
+ // buffers rounded up to larger sizes, and then reusing them if the new size
+ // still fits (but still reallocate if the new size is much smaller than the
+ // old size).
+ if (sk_surface_) {
+ sk_surface_.clear();
+ buffer_.reset();
+ pool_.reset();
+ }
+ size_ = viewport_size;
+}
+
+void WaylandCanvasSurface::PresentCanvas(const gfx::Rect& damage) {
+ // TODO(forney): This is just a naive implementation that allows chromium to
+ // draw to the buffer at any time, even if it is being used by the Wayland
+ // compositor. Instead, we should track buffer releases and frame callbacks
+ // from Wayland to ensure perfect frames (while minimizing copies).
+ wl_surface* surface = window_->surface();
+ wl_surface_damage(surface, damage.x(), damage.y(), damage.width(),
+ damage.height());
+ wl_surface_attach(surface, buffer_.get(), 0, 0);
+ wl_surface_commit(surface);
+ display_->ScheduleFlush();
+}
+
+scoped_ptr<gfx::VSyncProvider> WaylandCanvasSurface::CreateVSyncProvider() {
+ // TODO(forney): This can be implemented with information from frame
+ // callbacks, and possibly output refresh rate.
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+WaylandSurfaceFactory::WaylandSurfaceFactory(WaylandDisplay* display)
+ : display_(display) {}
+
+WaylandSurfaceFactory::~WaylandSurfaceFactory() {}
+
+intptr_t WaylandSurfaceFactory::GetNativeDisplay() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+bool WaylandSurfaceFactory::LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
+ // This Ozone implementation does not support multi-process rendering so
+ // disable EGL unconditionally for now.
+ return false;
+}
+
+scoped_ptr<SurfaceOzoneCanvas> WaylandSurfaceFactory::CreateCanvasForWidget(
+ gfx::AcceleratedWidget widget) {
+ DCHECK(display_);
+ WaylandWindow* window = display_->GetWindow(widget);
+ DCHECK(window);
+ return make_scoped_ptr(new WaylandCanvasSurface(display_, window));
+}
+
+scoped_ptr<SurfaceOzoneEGL> WaylandSurfaceFactory::CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget widget) {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<NativePixmap> WaylandSurfaceFactory::CreateNativePixmap(
+ gfx::AcceleratedWidget widget,
+ gfx::Size size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+scoped_refptr<NativePixmap> WaylandSurfaceFactory::CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
+ const gfx::NativePixmapHandle& handle) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h
new file mode 100644
index 00000000000..ce1793776ad
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SURFACE_FACTORY_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SURFACE_FACTORY_H_
+
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace ui {
+
+class WaylandDisplay;
+
+class WaylandSurfaceFactory : public SurfaceFactoryOzone {
+ public:
+ explicit WaylandSurfaceFactory(WaylandDisplay* display);
+ ~WaylandSurfaceFactory() override;
+
+ intptr_t GetNativeDisplay() override;
+ bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) override;
+ scoped_ptr<SurfaceOzoneCanvas> CreateCanvasForWidget(
+ gfx::AcceleratedWidget widget) override;
+ scoped_ptr<SurfaceOzoneEGL> CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget w) override;
+ scoped_refptr<NativePixmap> CreateNativePixmap(
+ gfx::AcceleratedWidget widget,
+ gfx::Size size,
+ gfx::BufferFormat format,
+ gfx::BufferUsage usage) override;
+ scoped_refptr<NativePixmap> CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
+ const gfx::NativePixmapHandle& handle) override;
+
+ private:
+ WaylandDisplay* display_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandSurfaceFactory);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SURFACE_FACTORY_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc
new file mode 100644
index 00000000000..d2ef3fd95d3
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
+#include "ui/ozone/platform/wayland/wayland_surface_factory.h"
+#include "ui/ozone/platform/wayland/wayland_test.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+#include "ui/ozone/public/surface_ozone_canvas.h"
+
+using ::testing::Expectation;
+using ::testing::SaveArg;
+using ::testing::_;
+
+namespace ui {
+
+class WaylandSurfaceFactoryTest : public WaylandTest {
+ public:
+ WaylandSurfaceFactoryTest() : surface_factory(&display) {}
+
+ ~WaylandSurfaceFactoryTest() override {}
+
+ void SetUp() override {
+ WaylandTest::SetUp();
+ canvas = surface_factory.CreateCanvasForWidget(widget);
+ ASSERT_TRUE(canvas);
+ }
+
+ protected:
+ WaylandSurfaceFactory surface_factory;
+ scoped_ptr<SurfaceOzoneCanvas> canvas;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandSurfaceFactoryTest);
+};
+
+TEST_F(WaylandSurfaceFactoryTest, Canvas) {
+ canvas->GetSurface();
+ canvas->PresentCanvas(gfx::Rect(5, 10, 20, 15));
+
+ Expectation damage = EXPECT_CALL(*surface, Damage(5, 10, 20, 15));
+ wl_resource* buffer_resource = nullptr;
+ Expectation attach = EXPECT_CALL(*surface, Attach(_, 0, 0))
+ .WillOnce(SaveArg<0>(&buffer_resource));
+ EXPECT_CALL(*surface, Commit()).After(damage, attach);
+
+ Sync();
+
+ ASSERT_TRUE(buffer_resource);
+ wl_shm_buffer* buffer = wl_shm_buffer_get(buffer_resource);
+ ASSERT_TRUE(buffer);
+ EXPECT_EQ(wl_shm_buffer_get_width(buffer), 800);
+ EXPECT_EQ(wl_shm_buffer_get_height(buffer), 600);
+
+ // TODO(forney): We could check that the contents match something drawn to the
+ // SkSurface above.
+}
+
+TEST_F(WaylandSurfaceFactoryTest, CanvasResize) {
+ canvas->GetSurface();
+ canvas->ResizeCanvas(gfx::Size(100, 50));
+ canvas->GetSurface();
+ canvas->PresentCanvas(gfx::Rect(0, 0, 100, 50));
+
+ Expectation damage = EXPECT_CALL(*surface, Damage(0, 0, 100, 50));
+ wl_resource* buffer_resource = nullptr;
+ Expectation attach = EXPECT_CALL(*surface, Attach(_, 0, 0))
+ .WillOnce(SaveArg<0>(&buffer_resource));
+ EXPECT_CALL(*surface, Commit()).After(damage, attach);
+
+ Sync();
+
+ ASSERT_TRUE(buffer_resource);
+ wl_shm_buffer* buffer = wl_shm_buffer_get(buffer_resource);
+ ASSERT_TRUE(buffer);
+ EXPECT_EQ(wl_shm_buffer_get_width(buffer), 100);
+ EXPECT_EQ(wl_shm_buffer_get_height(buffer), 50);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_test.cc b/chromium/ui/ozone/platform/wayland/wayland_test.cc
new file mode 100644
index 00000000000..b5aea4d4a52
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_test.cc
@@ -0,0 +1,56 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_test.h"
+
+#include "base/run_loop.h"
+
+using ::testing::SaveArg;
+using ::testing::_;
+
+namespace ui {
+
+WaylandTest::WaylandTest()
+ : window(&delegate, &display, gfx::Rect(0, 0, 800, 600)) {}
+
+WaylandTest::~WaylandTest() {}
+
+void WaylandTest::SetUp() {
+ ASSERT_TRUE(server.Start());
+ ASSERT_TRUE(display.Initialize());
+ EXPECT_CALL(delegate, OnAcceleratedWidgetAvailable(_, _))
+ .WillOnce(SaveArg<0>(&widget));
+ ASSERT_TRUE(window.Initialize());
+ ASSERT_NE(widget, gfx::kNullAcceleratedWidget);
+
+ // Wait for the client to flush all pending requests from initialization.
+ base::RunLoop().RunUntilIdle();
+
+ // Pause the server after it has responded to all incoming events.
+ server.Pause();
+
+ surface = server.GetObject<wl::MockSurface>(widget);
+ ASSERT_TRUE(surface);
+
+ initialized = true;
+}
+
+void WaylandTest::TearDown() {
+ if (initialized)
+ Sync();
+}
+
+void WaylandTest::Sync() {
+ // Resume the server, flushing its pending events.
+ server.Resume();
+
+ // Wait for the client to finish processing these events.
+ base::RunLoop().RunUntilIdle();
+
+ // Pause the server, after it has finished processing any follow-up requests
+ // from the client.
+ server.Pause();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_test.h b/chromium/ui/ozone/platform/wayland/wayland_test.h
new file mode 100644
index 00000000000..9a12412982a
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_test.h
@@ -0,0 +1,47 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_TEST_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_TEST_H_
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
+#include "ui/ozone/platform/wayland/wayland_display.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+namespace ui {
+
+// WaylandTest is a base class that sets up a display, window, and fake server,
+// and allows easy synchronization between them.
+class WaylandTest : public testing::Test {
+ public:
+ WaylandTest();
+ ~WaylandTest() override;
+
+ void SetUp() override;
+ void TearDown() override;
+
+ void Sync();
+
+ private:
+ bool initialized = false;
+ base::MessageLoopForUI message_loop;
+
+ protected:
+ wl::FakeServer server;
+ wl::MockSurface* surface;
+
+ WaylandDisplay display;
+ MockPlatformWindowDelegate delegate;
+ WaylandWindow window;
+ gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandTest);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_TEST_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.cc b/chromium/ui/ozone/platform/wayland/wayland_window.cc
new file mode 100644
index 00000000000..46c639adc04
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_window.cc
@@ -0,0 +1,183 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+#include <xdg-shell-unstable-v5-client-protocol.h>
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/events/event.h"
+#include "ui/events/ozone/events_ozone.h"
+#include "ui/ozone/platform/wayland/wayland_display.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+namespace ui {
+
+WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate,
+ WaylandDisplay* display,
+ const gfx::Rect& bounds)
+ : delegate_(delegate), display_(display), bounds_(bounds) {}
+
+WaylandWindow::~WaylandWindow() {
+ if (xdg_surface_) {
+ PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
+ display_->RemoveWindow(surface_.id());
+ }
+}
+
+// static
+WaylandWindow* WaylandWindow::FromSurface(wl_surface* surface) {
+ return static_cast<WaylandWindow*>(
+ wl_proxy_get_user_data(reinterpret_cast<wl_proxy*>(surface)));
+}
+
+bool WaylandWindow::Initialize() {
+ static const xdg_surface_listener xdg_surface_listener = {
+ &WaylandWindow::Configure, &WaylandWindow::Close,
+ };
+
+ surface_.reset(wl_compositor_create_surface(display_->compositor()));
+ if (!surface_) {
+ LOG(ERROR) << "Failed to create wl_surface";
+ return false;
+ }
+ wl_surface_set_user_data(surface_.get(), this);
+ xdg_surface_.reset(
+ xdg_shell_get_xdg_surface(display_->shell(), surface_.get()));
+ if (!xdg_surface_) {
+ LOG(ERROR) << "Failed to create xdg_surface";
+ return false;
+ }
+ xdg_surface_add_listener(xdg_surface_.get(), &xdg_surface_listener, this);
+ display_->ScheduleFlush();
+
+ display_->AddWindow(surface_.id(), this);
+ PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
+ delegate_->OnAcceleratedWidgetAvailable(surface_.id(), 1.f);
+
+ return true;
+}
+
+void WaylandWindow::ApplyPendingBounds() {
+ if (pending_bounds_.IsEmpty())
+ return;
+
+ SetBounds(pending_bounds_);
+ DCHECK(xdg_surface_);
+ xdg_surface_ack_configure(xdg_surface_.get(), pending_configure_serial_);
+ pending_bounds_ = gfx::Rect();
+ display_->ScheduleFlush();
+}
+
+void WaylandWindow::Show() {}
+
+void WaylandWindow::Hide() {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::Close() {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::SetBounds(const gfx::Rect& bounds) {
+ if (bounds == bounds_)
+ return;
+ bounds_ = bounds;
+ delegate_->OnBoundsChanged(bounds);
+}
+
+gfx::Rect WaylandWindow::GetBounds() {
+ return bounds_;
+}
+
+void WaylandWindow::SetTitle(const base::string16& title) {
+ DCHECK(xdg_surface_);
+ xdg_surface_set_title(xdg_surface_.get(), UTF16ToUTF8(title).c_str());
+ display_->ScheduleFlush();
+}
+
+void WaylandWindow::SetCapture() {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::ReleaseCapture() {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::ToggleFullscreen() {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::Maximize() {
+ DCHECK(xdg_surface_);
+ xdg_surface_set_maximized(xdg_surface_.get());
+ display_->ScheduleFlush();
+}
+
+void WaylandWindow::Minimize() {
+ DCHECK(xdg_surface_);
+ xdg_surface_set_minimized(xdg_surface_.get());
+ display_->ScheduleFlush();
+}
+
+void WaylandWindow::Restore() {
+ DCHECK(xdg_surface_);
+ xdg_surface_unset_maximized(xdg_surface_.get());
+ display_->ScheduleFlush();
+}
+
+void WaylandWindow::SetCursor(PlatformCursor cursor) {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::MoveCursorTo(const gfx::Point& location) {
+ NOTIMPLEMENTED();
+}
+
+void WaylandWindow::ConfineCursorToBounds(const gfx::Rect& bounds) {
+ NOTIMPLEMENTED();
+}
+
+PlatformImeController* WaylandWindow::GetPlatformImeController() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+bool WaylandWindow::CanDispatchEvent(const PlatformEvent& native_event) {
+ Event* event = static_cast<Event*>(native_event);
+ if (event->IsMouseEvent())
+ return has_pointer_focus_;
+ return false;
+}
+
+uint32_t WaylandWindow::DispatchEvent(const PlatformEvent& native_event) {
+ DispatchEventFromNativeUiEvent(
+ native_event, base::Bind(&PlatformWindowDelegate::DispatchEvent,
+ base::Unretained(delegate_)));
+ return POST_DISPATCH_STOP_PROPAGATION;
+}
+
+// static
+void WaylandWindow::Configure(void* data,
+ xdg_surface* obj,
+ int32_t width,
+ int32_t height,
+ wl_array* states,
+ uint32_t serial) {
+ WaylandWindow* window = static_cast<WaylandWindow*>(data);
+
+ // Rather than call SetBounds here for every configure event, just save the
+ // most recent bounds, and have WaylandDisplay call ApplyPendingBounds when it
+ // has finished processing events. We may get many configure events in a row
+ // during an interactive resize, and only the last one matters.
+ window->pending_bounds_ = gfx::Rect(0, 0, width, height);
+ window->pending_configure_serial_ = serial;
+}
+
+// static
+void WaylandWindow::Close(void* data, xdg_surface* obj) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.h b/chromium/ui/ozone/platform/wayland/wayland_window.h
new file mode 100644
index 00000000000..450df55d05a
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_window.h
@@ -0,0 +1,86 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
+
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/platform_window/platform_window.h"
+
+namespace ui {
+
+class WaylandDisplay;
+
+class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
+ public:
+ WaylandWindow(PlatformWindowDelegate* delegate,
+ WaylandDisplay* display,
+ const gfx::Rect& bounds);
+ ~WaylandWindow() override;
+
+ static WaylandWindow* FromSurface(wl_surface* surface);
+
+ bool Initialize();
+
+ wl_surface* surface() { return surface_.get(); }
+
+ // Apply the bounds specified in the most recent configure event. This should
+ // be called after processing all pending events in the wayland connection.
+ void ApplyPendingBounds();
+
+ // Set whether this window has pointer focus and should dispatch mouse events.
+ void set_pointer_focus(bool focus) { has_pointer_focus_ = focus; }
+
+ // PlatformWindow
+ void Show() override;
+ void Hide() override;
+ void Close() override;
+ void SetBounds(const gfx::Rect& bounds) override;
+ gfx::Rect GetBounds() override;
+ void SetTitle(const base::string16& title) override;
+ void SetCapture() override;
+ void ReleaseCapture() override;
+ void ToggleFullscreen() override;
+ void Maximize() override;
+ void Minimize() override;
+ void Restore() override;
+ void SetCursor(PlatformCursor cursor) override;
+ void MoveCursorTo(const gfx::Point& location) override;
+ void ConfineCursorToBounds(const gfx::Rect& bounds) override;
+ PlatformImeController* GetPlatformImeController() override;
+
+ // PlatformEventDispatcher
+ bool CanDispatchEvent(const PlatformEvent& event) override;
+ uint32_t DispatchEvent(const PlatformEvent& event) override;
+
+ // xdg_surface_listener
+ static void Configure(void* data,
+ xdg_surface* obj,
+ int32_t width,
+ int32_t height,
+ wl_array* states,
+ uint32_t serial);
+ static void Close(void* data, xdg_surface* obj);
+
+ private:
+ PlatformWindowDelegate* delegate_;
+ WaylandDisplay* display_;
+
+ wl::Object<wl_surface> surface_;
+ wl::Object<xdg_surface> xdg_surface_;
+
+ gfx::Rect bounds_;
+ gfx::Rect pending_bounds_;
+ uint32_t pending_configure_serial_;
+ bool has_pointer_focus_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandWindow);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_WINDOW_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc
new file mode 100644
index 00000000000..5fd1dc337c0
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <wayland-server-core.h>
+#include <xdg-shell-unstable-v5-server-protocol.h>
+
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/mock_platform_window_delegate.h"
+#include "ui/ozone/platform/wayland/wayland_test.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+using ::testing::Eq;
+using ::testing::Mock;
+using ::testing::SaveArg;
+using ::testing::StrEq;
+using ::testing::_;
+
+namespace ui {
+
+class WaylandWindowTest : public WaylandTest {
+ public:
+ WaylandWindowTest()
+ : test_mouse_event(ET_MOUSE_PRESSED,
+ gfx::Point(10, 15),
+ gfx::Point(10, 15),
+ base::TimeDelta::FromSeconds(123456),
+ EF_LEFT_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON,
+ EF_LEFT_MOUSE_BUTTON) {}
+
+ void SetUp() override {
+ WaylandTest::SetUp();
+
+ xdg_surface = surface->xdg_surface.get();
+ ASSERT_TRUE(xdg_surface);
+ }
+
+ protected:
+ wl::MockXdgSurface* xdg_surface;
+
+ MouseEvent test_mouse_event;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandWindowTest);
+};
+
+TEST_F(WaylandWindowTest, SetTitle) {
+ EXPECT_CALL(*xdg_surface, SetTitle(StrEq("hello")));
+ window.SetTitle(base::ASCIIToUTF16("hello"));
+}
+
+TEST_F(WaylandWindowTest, Maximize) {
+ EXPECT_CALL(*xdg_surface, SetMaximized());
+ window.Maximize();
+}
+
+TEST_F(WaylandWindowTest, Minimize) {
+ EXPECT_CALL(*xdg_surface, SetMinimized());
+ window.Minimize();
+}
+
+TEST_F(WaylandWindowTest, Restore) {
+ EXPECT_CALL(*xdg_surface, UnsetMaximized());
+ window.Restore();
+}
+
+TEST_F(WaylandWindowTest, CanDispatchMouseEventDefault) {
+ EXPECT_FALSE(window.CanDispatchEvent(&test_mouse_event));
+}
+
+TEST_F(WaylandWindowTest, CanDispatchMouseEventFocus) {
+ window.set_pointer_focus(true);
+ EXPECT_TRUE(window.CanDispatchEvent(&test_mouse_event));
+}
+
+TEST_F(WaylandWindowTest, CanDispatchMouseEventUnfocus) {
+ window.set_pointer_focus(false);
+ EXPECT_FALSE(window.CanDispatchEvent(&test_mouse_event));
+}
+
+ACTION_P(CloneEvent, ptr) {
+ *ptr = Event::Clone(*arg0);
+}
+
+TEST_F(WaylandWindowTest, DispatchEvent) {
+ scoped_ptr<Event> event;
+ EXPECT_CALL(delegate, DispatchEvent(_)).WillOnce(CloneEvent(&event));
+ window.DispatchEvent(&test_mouse_event);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ auto mouse_event = static_cast<MouseEvent*>(event.get());
+ EXPECT_EQ(mouse_event->location_f(), test_mouse_event.location_f());
+ EXPECT_EQ(mouse_event->root_location_f(), test_mouse_event.root_location_f());
+ EXPECT_EQ(mouse_event->time_stamp(), test_mouse_event.time_stamp());
+ EXPECT_EQ(mouse_event->button_flags(), test_mouse_event.button_flags());
+ EXPECT_EQ(mouse_event->changed_button_flags(),
+ test_mouse_event.changed_button_flags());
+}
+
+TEST_F(WaylandWindowTest, ConfigureEvent) {
+ wl_array states;
+ wl_array_init(&states);
+ xdg_surface_send_configure(xdg_surface->resource(), 1000, 1000, &states, 12);
+ xdg_surface_send_configure(xdg_surface->resource(), 1500, 1000, &states, 13);
+
+ // Make sure that the implementation does not call OnBoundsChanged for each
+ // configure event if it receives multiple in a row.
+ EXPECT_CALL(delegate, OnBoundsChanged(Eq(gfx::Rect(0, 0, 1500, 1000))));
+ EXPECT_CALL(*xdg_surface, AckConfigure(13));
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/BUILD.gn b/chromium/ui/ozone/platform/x11/BUILD.gn
new file mode 100644
index 00000000000..31185ddbe55
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+visibility = [ "//ui/ozone/*" ]
+
+source_set("x11") {
+ sources = [
+ "client_native_pixmap_factory_x11.cc",
+ "client_native_pixmap_factory_x11.h",
+ "ozone_platform_x11.cc",
+ "ozone_platform_x11.h",
+ "x11_cursor_factory_ozone.cc",
+ "x11_cursor_factory_ozone.h",
+ "x11_surface_factory.cc",
+ "x11_surface_factory.h",
+ ]
+
+ deps = [
+ "//base",
+ "//skia",
+ "//ui/base",
+ "//ui/display/types",
+ "//ui/display/util",
+ "//ui/events",
+ "//ui/events/devices",
+ "//ui/events/ozone:events_ozone",
+ "//ui/events/platform",
+ "//ui/events/platform/x11",
+ "//ui/events/x",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+ "//ui/gfx/x",
+ "//ui/ozone:ozone_base",
+ "//ui/ozone/common",
+ "//ui/platform_window/x11",
+ ]
+
+ configs += [ "//build/config/linux:x11" ]
+
+ public_configs = [ "//third_party/khronos:khronos_headers" ]
+}
diff --git a/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.cc b/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.cc
new file mode 100644
index 00000000000..b9083e51d91
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.cc
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/client_native_pixmap_factory_x11.h"
+
+#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
+
+namespace ui {
+
+ClientNativePixmapFactory* CreateClientNativePixmapFactoryX11() {
+ return CreateStubClientNativePixmapFactory();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.h b/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.h
new file mode 100644
index 00000000000..b6523dd16a1
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/client_native_pixmap_factory_x11.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_CLIENT_NATIVE_PIXMAP_FACTORY_X11_H_
+#define UI_OZONE_PLATFORM_X11_CLIENT_NATIVE_PIXMAP_FACTORY_X11_H_
+
+namespace ui {
+
+class ClientNativePixmapFactory;
+
+// Constructor hook for use in constructor_list.cc
+ClientNativePixmapFactory* CreateClientNativePixmapFactoryX11();
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_X11_CLIENT_NATIVE_PIXMAP_FACTORY_X11_H_
diff --git a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
new file mode 100644
index 00000000000..7863f8001e9
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -0,0 +1,129 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/ozone_platform_x11.h"
+
+#include <X11/Xlib.h>
+
+#include <utility>
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/events/platform/x11/x11_event_source_libevent.h"
+#include "ui/ozone/common/native_display_delegate_ozone.h"
+#include "ui/ozone/common/stub_overlay_manager.h"
+#include "ui/ozone/platform/x11/x11_cursor_factory_ozone.h"
+#include "ui/ozone/platform/x11/x11_surface_factory.h"
+#include "ui/ozone/public/gpu_platform_support.h"
+#include "ui/ozone/public/gpu_platform_support_host.h"
+#include "ui/ozone/public/input_controller.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/system_input_injector.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/x11/x11_window_manager_ozone.h"
+#include "ui/platform_window/x11/x11_window_ozone.h"
+
+namespace ui {
+
+namespace {
+
+// Returns true if we should operate in Mus mode.
+bool RunningInsideMus() {
+ bool has_channel_handle = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ "mojo-platform-channel-handle");
+ return has_channel_handle;
+}
+
+// Singleton OzonePlatform implementation for Linux X11 platform.
+class OzonePlatformX11 : public OzonePlatform {
+ public:
+ OzonePlatformX11() {
+ // If we're running in Mus mode both the UI and GPU components of Ozone will
+ // be running in the same process. Enable X11 concurrent thread support.
+ if (RunningInsideMus())
+ XInitThreads();
+ }
+
+ ~OzonePlatformX11() override {}
+
+ // OzonePlatform:
+ ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
+ return surface_factory_ozone_.get();
+ }
+
+ ui::OverlayManagerOzone* GetOverlayManager() override {
+ return overlay_manager_.get();
+ }
+
+ CursorFactoryOzone* GetCursorFactoryOzone() override {
+ return cursor_factory_ozone_.get();
+ }
+
+ scoped_ptr<SystemInputInjector> CreateSystemInputInjector() override {
+ return nullptr;
+ }
+
+ InputController* GetInputController() override {
+ return input_controller_.get();
+ }
+
+ GpuPlatformSupport* GetGpuPlatformSupport() override {
+ return gpu_platform_support_.get();
+ }
+
+ GpuPlatformSupportHost* GetGpuPlatformSupportHost() override {
+ return gpu_platform_support_host_.get();
+ }
+
+ scoped_ptr<PlatformWindow> CreatePlatformWindow(
+ PlatformWindowDelegate* delegate,
+ const gfx::Rect& bounds) override {
+ scoped_ptr<X11WindowOzone> window = make_scoped_ptr(new X11WindowOzone(
+ event_source_.get(), window_manager_.get(), delegate));
+ window->SetBounds(bounds);
+ window->Create();
+ return std::move(window);
+ }
+
+ scoped_ptr<NativeDisplayDelegate> CreateNativeDisplayDelegate() override {
+ return make_scoped_ptr(new NativeDisplayDelegateOzone());
+ }
+
+ void InitializeUI() override {
+ window_manager_.reset(new X11WindowManagerOzone);
+ event_source_.reset(new X11EventSourceLibevent(gfx::GetXDisplay()));
+ overlay_manager_.reset(new StubOverlayManager());
+ input_controller_ = CreateStubInputController();
+ cursor_factory_ozone_.reset(new X11CursorFactoryOzone());
+ gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
+ }
+
+ void InitializeGPU() override {
+ surface_factory_ozone_.reset(new X11SurfaceFactory());
+ gpu_platform_support_.reset(CreateStubGpuPlatformSupport());
+ }
+
+ private:
+ // Objects in the Browser process.
+ scoped_ptr<X11WindowManagerOzone> window_manager_;
+ scoped_ptr<X11EventSourceLibevent> event_source_;
+ scoped_ptr<OverlayManagerOzone> overlay_manager_;
+ scoped_ptr<InputController> input_controller_;
+ scoped_ptr<X11CursorFactoryOzone> cursor_factory_ozone_;
+ scoped_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
+
+ // Objects in the GPU process.
+ scoped_ptr<X11SurfaceFactory> surface_factory_ozone_;
+ scoped_ptr<GpuPlatformSupport> gpu_platform_support_;
+
+ DISALLOW_COPY_AND_ASSIGN(OzonePlatformX11);
+};
+
+} // namespace
+
+OzonePlatform* CreateOzonePlatformX11() {
+ return new OzonePlatformX11;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/ozone_platform_x11.h b/chromium/ui/ozone/platform/x11/ozone_platform_x11.h
new file mode 100644
index 00000000000..b1f28a4fc7e
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/ozone_platform_x11.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
+#define UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
+
+namespace ui {
+
+class OzonePlatform;
+
+// Constructor hook for use in ozone_platform_list.cc
+OzonePlatform* CreateOzonePlatformX11();
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_X11_OZONE_PLATFORM_X11_H_
diff --git a/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.cc b/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.cc
new file mode 100644
index 00000000000..50df6919fb4
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.cc
@@ -0,0 +1,100 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/x11_cursor_factory_ozone.h"
+
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursors_aura.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+namespace {
+
+X11CursorOzone* ToX11CursorOzone(PlatformCursor cursor) {
+ return static_cast<X11CursorOzone*>(cursor);
+}
+
+PlatformCursor ToPlatformCursor(X11CursorOzone* cursor) {
+ return static_cast<PlatformCursor>(cursor);
+}
+
+// Gets default aura cursor bitmap/hotspot and creates a X11CursorOzone with it.
+scoped_refptr<X11CursorOzone> CreateAuraX11Cursor(int type) {
+ SkBitmap bitmap;
+ gfx::Point hotspot;
+ if (GetCursorBitmap(type, &bitmap, &hotspot)) {
+ return new X11CursorOzone(bitmap, hotspot);
+ }
+ return nullptr;
+}
+
+} // namespace
+
+X11CursorFactoryOzone::X11CursorFactoryOzone()
+ : invisible_cursor_(X11CursorOzone::CreateInvisible()) {}
+
+X11CursorFactoryOzone::~X11CursorFactoryOzone() {}
+
+PlatformCursor X11CursorFactoryOzone::GetDefaultCursor(int type) {
+ return ToPlatformCursor(GetDefaultCursorInternal(type).get());
+}
+
+PlatformCursor X11CursorFactoryOzone::CreateImageCursor(
+ const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
+ // There is a problem with custom cursors that have no custom data. The
+ // resulting SkBitmap is empty and X crashes when creating a zero size cursor
+ // image. Return invisible cursor here instead.
+ if (bitmap.drawsNothing()) {
+ return ToPlatformCursor(invisible_cursor_.get());
+ }
+
+ X11CursorOzone* cursor = new X11CursorOzone(bitmap, hotspot);
+ cursor->AddRef();
+ return ToPlatformCursor(cursor);
+}
+
+PlatformCursor X11CursorFactoryOzone::CreateAnimatedCursor(
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ int frame_delay_ms) {
+ X11CursorOzone* cursor = new X11CursorOzone(bitmaps, hotspot, frame_delay_ms);
+ cursor->AddRef();
+ return ToPlatformCursor(cursor);
+}
+
+void X11CursorFactoryOzone::RefImageCursor(PlatformCursor cursor) {
+ ToX11CursorOzone(cursor)->AddRef();
+}
+
+void X11CursorFactoryOzone::UnrefImageCursor(PlatformCursor cursor) {
+ ToX11CursorOzone(cursor)->Release();
+}
+
+scoped_refptr<X11CursorOzone> X11CursorFactoryOzone::GetDefaultCursorInternal(
+ int type) {
+ if (type == kCursorNone)
+ return invisible_cursor_;
+
+ // TODO(kylechar): Use predefined X cursors here instead.
+ if (!default_cursors_.count(type)) {
+ // Loads the default aura cursor bitmap for cursor type. Falls back on
+ // pointer cursor then invisible cursor if this fails.
+ scoped_refptr<X11CursorOzone> cursor = CreateAuraX11Cursor(type);
+ if (!cursor.get()) {
+ if (type != kCursorPointer) {
+ cursor = GetDefaultCursorInternal(kCursorPointer);
+ } else {
+ NOTREACHED() << "Failed to load default cursor bitmap";
+ }
+ }
+ default_cursors_[type] = cursor;
+ }
+
+ // Returns owned default cursor for this type.
+ return default_cursors_[type];
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.h b/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.h
new file mode 100644
index 00000000000..2f12ac1ea3d
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_cursor_factory_ozone.h
@@ -0,0 +1,52 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_X11_CURSOR_FACTORY_OZONE_H_
+#define UI_OZONE_PLATFORM_X11_X11_CURSOR_FACTORY_OZONE_H_
+
+#include <X11/X.h>
+
+#include <unordered_map>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/ozone/public/cursor_factory_ozone.h"
+#include "ui/platform_window/x11/x11_cursor_ozone.h"
+
+namespace ui {
+
+// CursorFactoryOzone implementation for X11 cursors.
+class X11CursorFactoryOzone : public CursorFactoryOzone {
+ public:
+ X11CursorFactoryOzone();
+ ~X11CursorFactoryOzone() override;
+
+ // CursorFactoryOzone:
+ PlatformCursor GetDefaultCursor(int type) override;
+ PlatformCursor CreateImageCursor(const SkBitmap& bitmap,
+ const gfx::Point& hotspot) override;
+ PlatformCursor CreateAnimatedCursor(const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ int frame_delay_ms) override;
+ void RefImageCursor(PlatformCursor cursor) override;
+ void UnrefImageCursor(PlatformCursor cursor) override;
+
+ private:
+ // Loads/caches default cursor or returns cached version.
+ scoped_refptr<X11CursorOzone> GetDefaultCursorInternal(int type);
+
+ // Holds a single instance of the invisible cursor. X11 has no way to hide
+ // the cursor so an invisible cursor mimics that.
+ scoped_refptr<X11CursorOzone> invisible_cursor_;
+
+ std::unordered_map<int, scoped_refptr<X11CursorOzone>> default_cursors_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11CursorFactoryOzone);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_X11_X11_CURSOR_FACTORY_OZONE_H_
diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.cc b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
new file mode 100644
index 00000000000..4e96c9b48d3
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.cc
@@ -0,0 +1,133 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/x11/x11_surface_factory.h"
+
+#include <X11/Xlib.h>
+
+#include "base/macros.h"
+#include "third_party/khronos/EGL/egl.h"
+#include "ui/gfx/vsync_provider.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/ozone/common/egl_util.h"
+#include "ui/ozone/public/surface_ozone_egl.h"
+
+namespace ui {
+
+namespace {
+
+class X11SurfaceEGL : public SurfaceOzoneEGL {
+ public:
+ explicit X11SurfaceEGL(gfx::AcceleratedWidget widget) : widget_(widget) {}
+ ~X11SurfaceEGL() override {}
+
+ intptr_t GetNativeWindow() override { return widget_; }
+
+ bool OnSwapBuffers() override { return true; }
+
+ void OnSwapBuffersAsync(const SwapCompletionCallback& callback) override {
+ NOTREACHED();
+ }
+
+ bool ResizeNativeWindow(const gfx::Size& viewport_size) override {
+ return true;
+ }
+
+ scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override {
+ return nullptr;
+ }
+
+ void* /* EGLConfig */ GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) override;
+
+ private:
+ gfx::AcceleratedWidget widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11SurfaceEGL);
+};
+
+void* /* EGLConfig */ X11SurfaceEGL::GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) {
+ // Try matching the window depth with an alpha channel,
+ // because we're worried the destination alpha width could
+ // constrain blending precision.
+ EGLConfig config;
+ const int kBufferSizeOffset = 1;
+ const int kAlphaSizeOffset = 3;
+ EGLint config_attribs[] = {EGL_BUFFER_SIZE,
+ ~0, // To be replaced.
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_RED_SIZE,
+ 8,
+ EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT,
+ EGL_NONE};
+
+ // Get the depth of XWindow for surface
+ XWindowAttributes win_attribs;
+ if (XGetWindowAttributes(gfx::GetXDisplay(), widget_, &win_attribs)) {
+ config_attribs[kBufferSizeOffset] = win_attribs.depth;
+ }
+
+ EGLint num_configs;
+ if (!egl.choose_config.Run(config_attribs, &config, 1, &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << egl.get_last_error_string.Run();
+ return nullptr;
+ }
+ if (num_configs > 0) {
+ EGLint config_depth;
+ if (!egl.get_config_attribute.Run(config, EGL_BUFFER_SIZE, &config_depth)) {
+ LOG(ERROR) << "eglGetConfigAttrib failed with error "
+ << egl.get_last_error_string.Run();
+ return nullptr;
+ }
+ if (config_depth == config_attribs[kBufferSizeOffset]) {
+ return config;
+ }
+ }
+
+ // Try without an alpha channel.
+ config_attribs[kAlphaSizeOffset] = 0;
+ if (!egl.choose_config.Run(config_attribs, &config, 1, &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << egl.get_last_error_string.Run();
+ return nullptr;
+ }
+ if (num_configs == 0) {
+ LOG(ERROR) << "No suitable EGL configs found.";
+ return nullptr;
+ }
+ return config;
+}
+
+} // namespace
+
+X11SurfaceFactory::X11SurfaceFactory() {}
+
+X11SurfaceFactory::~X11SurfaceFactory() {}
+
+scoped_ptr<SurfaceOzoneEGL> X11SurfaceFactory::CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget widget) {
+ return make_scoped_ptr(new X11SurfaceEGL(widget));
+}
+
+bool X11SurfaceFactory::LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) {
+ return LoadDefaultEGLGLES2Bindings(add_gl_library, set_gl_get_proc_address);
+}
+
+intptr_t X11SurfaceFactory::GetNativeDisplay() {
+ return reinterpret_cast<intptr_t>(gfx::GetXDisplay());
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/x11/x11_surface_factory.h b/chromium/ui/ozone/platform/x11/x11_surface_factory.h
new file mode 100644
index 00000000000..344704858ec
--- /dev/null
+++ b/chromium/ui/ozone/platform/x11/x11_surface_factory.h
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
+#define UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace ui {
+
+// Handles creation of EGL and software surfaces for drawing in XWindow.
+class X11SurfaceFactory : public SurfaceFactoryOzone {
+ public:
+ X11SurfaceFactory();
+ ~X11SurfaceFactory() override;
+
+ // SurfaceFactoryOzone:
+
+ scoped_ptr<SurfaceOzoneEGL> CreateEGLSurfaceForWidget(
+ gfx::AcceleratedWidget widget) override;
+ bool LoadEGLGLES2Bindings(
+ AddGLLibraryCallback add_gl_library,
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) override;
+ intptr_t GetNativeDisplay() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(X11SurfaceFactory);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_X11_X11_SURFACE_FACTORY_H_
diff --git a/chromium/ui/ozone/public/client_native_pixmap_factory.h b/chromium/ui/ozone/public/client_native_pixmap_factory.h
index 9973bf6fef1..65aaefd7610 100644
--- a/chromium/ui/ozone/public/client_native_pixmap_factory.h
+++ b/chromium/ui/ozone/public/client_native_pixmap_factory.h
@@ -32,9 +32,6 @@ class OZONE_EXPORT ClientNativePixmapFactory {
virtual ~ClientNativePixmapFactory();
- // Initialize with the given client native pixmap |device_fd|.
- virtual void Initialize(base::ScopedFD device_fd) = 0;
-
// Returns true if format/usage configuration is supported.
virtual bool IsConfigurationSupported(gfx::BufferFormat format,
gfx::BufferUsage usage) const = 0;
diff --git a/chromium/ui/ozone/public/overlay_candidates_ozone.cc b/chromium/ui/ozone/public/overlay_candidates_ozone.cc
index 89777b7f843..d6fdc009edb 100644
--- a/chromium/ui/ozone/public/overlay_candidates_ozone.cc
+++ b/chromium/ui/ozone/public/overlay_candidates_ozone.cc
@@ -11,6 +11,9 @@ namespace ui {
OverlayCandidatesOzone::OverlaySurfaceCandidate::OverlaySurfaceCandidate()
: is_clipped(false) {}
+OverlayCandidatesOzone::OverlaySurfaceCandidate::OverlaySurfaceCandidate(
+ const OverlaySurfaceCandidate& other) = default;
+
OverlayCandidatesOzone::OverlaySurfaceCandidate::~OverlaySurfaceCandidate() {
}
diff --git a/chromium/ui/ozone/public/overlay_candidates_ozone.h b/chromium/ui/ozone/public/overlay_candidates_ozone.h
index cacf562a383..87e18ec93f5 100644
--- a/chromium/ui/ozone/public/overlay_candidates_ozone.h
+++ b/chromium/ui/ozone/public/overlay_candidates_ozone.h
@@ -20,6 +20,7 @@ class OZONE_BASE_EXPORT OverlayCandidatesOzone {
public:
struct OverlaySurfaceCandidate {
OverlaySurfaceCandidate();
+ OverlaySurfaceCandidate(const OverlaySurfaceCandidate& other);
~OverlaySurfaceCandidate();
// Transformation to apply to layer during composition.
diff --git a/chromium/ui/ozone/public/ozone_platform.h b/chromium/ui/ozone/public/ozone_platform.h
index f96915959b1..efa03a6cf10 100644
--- a/chromium/ui/ozone/public/ozone_platform.h
+++ b/chromium/ui/ozone/public/ozone_platform.h
@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PUBLIC_OZONE_PLATFORM_H_
#define UI_OZONE_PUBLIC_OZONE_PLATFORM_H_
-#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/ozone/ozone_export.h"
@@ -70,9 +69,6 @@ class OZONE_EXPORT OzonePlatform {
const gfx::Rect& bounds) = 0;
virtual scoped_ptr<ui::NativeDisplayDelegate>
CreateNativeDisplayDelegate() = 0;
- // Open ClientNativePixmap device file for non-GPU processes to import a
- // ClientNativePixmap.
- virtual base::ScopedFD OpenClientNativePixmapDevice() const = 0;
private:
virtual void InitializeUI() = 0;
diff --git a/chromium/ui/ozone/public/surface_factory_ozone.cc b/chromium/ui/ozone/public/surface_factory_ozone.cc
index b493045353c..c8a28da16b4 100644
--- a/chromium/ui/ozone/public/surface_factory_ozone.cc
+++ b/chromium/ui/ozone/public/surface_factory_ozone.cc
@@ -39,9 +39,9 @@ scoped_ptr<SurfaceOzoneCanvas> SurfaceFactoryOzone::CreateCanvasForWidget(
return nullptr;
}
-const int32_t* SurfaceFactoryOzone::GetEGLSurfaceProperties(
- const int32_t* desired_attributes) {
- return desired_attributes;
+std::vector<gfx::BufferFormat> SurfaceFactoryOzone::GetScanoutFormats(
+ gfx::AcceleratedWidget widget) {
+ return std::vector<gfx::BufferFormat>();
}
scoped_refptr<ui::NativePixmap> SurfaceFactoryOzone::CreateNativePixmap(
@@ -54,6 +54,8 @@ scoped_refptr<ui::NativePixmap> SurfaceFactoryOzone::CreateNativePixmap(
scoped_refptr<ui::NativePixmap>
SurfaceFactoryOzone::CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) {
return nullptr;
}
diff --git a/chromium/ui/ozone/public/surface_factory_ozone.h b/chromium/ui/ozone/public/surface_factory_ozone.h
index eaa353b4bf8..cebf49a48ad 100644
--- a/chromium/ui/ozone/public/surface_factory_ozone.h
+++ b/chromium/ui/ozone/public/surface_factory_ozone.h
@@ -6,6 +6,7 @@
#define UI_OZONE_PUBLIC_SURFACE_FACTORY_OZONE_H_
#include <stdint.h>
+#include <vector>
#include "base/callback.h"
#include "base/macros.h"
@@ -41,8 +42,6 @@ class SurfaceOzoneEGL;
// The following functions are specific to EGL:
// - GetNativeDisplay
// - LoadEGLGLES2Bindings
-// - GetEGLSurfaceProperties (optional if the properties match the default
-// Chromium ones).
// - CreateEGLSurfaceForWidget
//
// 2) Software Drawing (Skia):
@@ -93,12 +92,10 @@ class OZONE_BASE_EXPORT SurfaceFactoryOzone {
AddGLLibraryCallback add_gl_library,
SetGLGetProcAddressProcCallback set_gl_get_proc_address) = 0;
- // Returns an array of EGL properties, which can be used in any EGL function
- // used to select a display configuration. Note that all properties should be
- // immediately followed by the corresponding desired value and array should be
- // terminated with EGL_NONE. Ownership of the array is not transferred to
- // caller. desired_list contains list of desired EGL properties and values.
- virtual const int32_t* GetEGLSurfaceProperties(const int32_t* desired_list);
+ // Returns all scanout formats for |widget| representing a particular display
+ // controller or default display controller for kNullAcceleratedWidget.
+ virtual std::vector<gfx::BufferFormat> GetScanoutFormats(
+ gfx::AcceleratedWidget widget);
// Create a single native buffer to be used for overlay planes or zero copy
// for |widget| representing a particular display controller or default
@@ -113,6 +110,8 @@ class OZONE_BASE_EXPORT SurfaceFactoryOzone {
// Create a single native buffer from an existing handle. Takes ownership of
// |handle| and can be called on any thread.
virtual scoped_refptr<NativePixmap> CreateNativePixmapFromHandle(
+ gfx::Size size,
+ gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle);
protected:
diff --git a/chromium/ui/ozone/public/surface_ozone_canvas.h b/chromium/ui/ozone/public/surface_ozone_canvas.h
index 6cab0b40f0e..31bada38f70 100644
--- a/chromium/ui/ozone/public/surface_ozone_canvas.h
+++ b/chromium/ui/ozone/public/surface_ozone_canvas.h
@@ -27,7 +27,7 @@ class OZONE_BASE_EXPORT SurfaceOzoneCanvas {
virtual ~SurfaceOzoneCanvas() {}
// Returns an SkSurface for drawing on the window.
- virtual skia::RefPtr<SkSurface> GetSurface() = 0;
+ virtual sk_sp<SkSurface> GetSurface() = 0;
// Attempts to resize the canvas to match the viewport size. After
// resizing, the compositor must call GetCanvas() to get the next
diff --git a/chromium/ui/ozone/public/surface_ozone_egl.cc b/chromium/ui/ozone/public/surface_ozone_egl.cc
index 92330f3bf38..ba61f4f1482 100644
--- a/chromium/ui/ozone/public/surface_ozone_egl.cc
+++ b/chromium/ui/ozone/public/surface_ozone_egl.cc
@@ -6,6 +6,13 @@
namespace ui {
+EglConfigCallbacks::EglConfigCallbacks() {}
+
+EglConfigCallbacks::EglConfigCallbacks(const EglConfigCallbacks& other) =
+ default;
+
+EglConfigCallbacks::~EglConfigCallbacks() {}
+
bool SurfaceOzoneEGL::IsUniversalDisplayLinkDevice() {
return false;
}
diff --git a/chromium/ui/ozone/public/surface_ozone_egl.h b/chromium/ui/ozone/public/surface_ozone_egl.h
index f66f354e50c..67424a4bcc8 100644
--- a/chromium/ui/ozone/public/surface_ozone_egl.h
+++ b/chromium/ui/ozone/public/surface_ozone_egl.h
@@ -21,6 +21,22 @@ class NativePixmap;
typedef base::Callback<void(gfx::SwapResult)> SwapCompletionCallback;
+// Holds callbacks to functions for configuring EGL on platform.
+struct OZONE_BASE_EXPORT EglConfigCallbacks {
+ EglConfigCallbacks();
+ EglConfigCallbacks(const EglConfigCallbacks& other);
+ ~EglConfigCallbacks();
+ base::Callback<bool(const int32_t* attribs,
+ void** /* EGLConfig* */ configs,
+ int32_t config_size,
+ int32_t* num_configs)>
+ choose_config;
+ base::Callback<
+ bool(void* /* EGLConfig */ config, int32_t attribute, int32_t* value)>
+ get_config_attribute;
+ base::Callback<const char*()> get_last_error_string;
+};
+
// The platform-specific part of an EGL surface.
//
// This class owns any bits that the ozone implementation needs freed when
@@ -56,6 +72,11 @@ class OZONE_BASE_EXPORT SurfaceOzoneEGL {
// Returns true if the surface is created on a UDL device.
virtual bool IsUniversalDisplayLinkDevice();
+
+ // Returns the EGL configuration to use for this surface. The default EGL
+ // configuration will be used if this returns nullptr.
+ virtual void* /* EGLConfig */ GetEGLSurfaceConfig(
+ const EglConfigCallbacks& egl) = 0;
};
} // namespace ui
diff --git a/chromium/ui/platform_window/BUILD.gn b/chromium/ui/platform_window/BUILD.gn
index fe52aea4767..a9905a80fdc 100644
--- a/chromium/ui/platform_window/BUILD.gn
+++ b/chromium/ui/platform_window/BUILD.gn
@@ -16,7 +16,7 @@ source_set("platform_window") {
deps = [
"//base",
"//ui/base",
- "//ui/base/ime",
+ "//ui/base/ime:text_input_types",
"//ui/gfx",
]
}
diff --git a/chromium/ui/platform_window/stub/stub_window.gyp b/chromium/ui/platform_window/stub/stub_window.gyp
new file mode 100644
index 00000000000..47422f10cf9
--- /dev/null
+++ b/chromium/ui/platform_window/stub/stub_window.gyp
@@ -0,0 +1,24 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+ 'targets': [{
+ 'target_name': 'stub_window',
+ 'type': '<(component)',
+ 'dependencies': [
+ '../../gfx/gfx.gyp:gfx',
+ '../../gfx/gfx.gyp:gfx_geometry',
+ '../platform_window.gyp:platform_window',
+ ],
+ 'defines': [ 'STUB_WINDOW_IMPLEMENTATION' ],
+ 'sources': [
+ 'stub_window.cc',
+ 'stub_window.h',
+ 'stub_window_export.h',
+ ],
+ }],
+}
diff --git a/chromium/ui/platform_window/text_input_state.cc b/chromium/ui/platform_window/text_input_state.cc
index ce6db841857..ffc3e52792a 100644
--- a/chromium/ui/platform_window/text_input_state.cc
+++ b/chromium/ui/platform_window/text_input_state.cc
@@ -32,6 +32,8 @@ TextInputState::TextInputState(TextInputType type,
composition_end(composition_end),
can_compose_inline(can_compose_inline) {}
+TextInputState::TextInputState(const TextInputState& other) = default;
+
bool TextInputState::operator==(const TextInputState& other) const {
return type == other.type &&
flags == other.flags &&
diff --git a/chromium/ui/platform_window/text_input_state.h b/chromium/ui/platform_window/text_input_state.h
index 14d016bcede..c2dff0dc96d 100644
--- a/chromium/ui/platform_window/text_input_state.h
+++ b/chromium/ui/platform_window/text_input_state.h
@@ -23,6 +23,7 @@ struct TextInputState {
int composition_start,
int composition_end,
bool can_compose_inline);
+ TextInputState(const TextInputState& other);
bool operator==(const TextInputState& other) const;
// The type of input field.
diff --git a/chromium/ui/platform_window/win/win_window.cc b/chromium/ui/platform_window/win/win_window.cc
index 802f2d79a21..1282b091308 100644
--- a/chromium/ui/platform_window/win/win_window.cc
+++ b/chromium/ui/platform_window/win/win_window.cc
@@ -74,9 +74,11 @@ void WinWindow::SetBounds(const gfx::Rect& bounds) {
GetWindowLong(hwnd(), GWL_STYLE),
GetWindowLong(hwnd(), GWL_EXSTYLE),
bounds);
+ unsigned int flags = SWP_NOREPOSITION;
+ if (!::IsWindowVisible(hwnd()))
+ flags |= SWP_NOACTIVATE;
SetWindowPos(hwnd(), NULL, window_bounds.x(), window_bounds.y(),
- window_bounds.width(), window_bounds.height(),
- SWP_NOREPOSITION);
+ window_bounds.width(), window_bounds.height(), flags);
}
gfx::Rect WinWindow::GetBounds() {
diff --git a/chromium/ui/platform_window/x11/BUILD.gn b/chromium/ui/platform_window/x11/BUILD.gn
index 4775aa77144..bac1aaa2bae 100644
--- a/chromium/ui/platform_window/x11/BUILD.gn
+++ b/chromium/ui/platform_window/x11/BUILD.gn
@@ -3,8 +3,9 @@
# found in the LICENSE file.
import("//build/config/ui.gni")
+import("//ui/ozone/ozone.gni")
-assert(use_x11)
+assert(use_x11 || ozone_platform_x11)
component("x11") {
output_name = "x11_window"
@@ -25,8 +26,25 @@ component("x11") {
defines = [ "X11_WINDOW_IMPLEMENTATION" ]
sources = [
- "x11_window.cc",
- "x11_window.h",
+ "x11_window_base.cc",
+ "x11_window_base.h",
"x11_window_export.h",
]
+
+ if (ozone_platform_x11) {
+ sources += [
+ "x11_cursor_ozone.cc",
+ "x11_cursor_ozone.h",
+ "x11_window_manager_ozone.cc",
+ "x11_window_manager_ozone.h",
+ "x11_window_ozone.cc",
+ "x11_window_ozone.h",
+ ]
+ deps += [ "//ui/base" ]
+ } else if (use_x11) {
+ sources += [
+ "x11_window.cc",
+ "x11_window.h",
+ ]
+ }
}
diff --git a/chromium/ui/platform_window/x11/DEPS b/chromium/ui/platform_window/x11/DEPS
index 8cb61f5e0a4..9e087417f97 100644
--- a/chromium/ui/platform_window/x11/DEPS
+++ b/chromium/ui/platform_window/x11/DEPS
@@ -1,4 +1,6 @@
include_rules = [
+ "+third_party/skia/include",
+ "+ui/base/x",
"+ui/events",
"+ui/gfx",
]
diff --git a/chromium/ui/platform_window/x11/x11_cursor_ozone.cc b/chromium/ui/platform_window/x11/x11_cursor_ozone.cc
new file mode 100644
index 00000000000..ff185e37560
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_cursor_ozone.cc
@@ -0,0 +1,84 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/platform_window/x11/x11_cursor_ozone.h"
+
+#include <X11/Xcursor/Xcursor.h>
+#include <X11/Xlib.h>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+namespace {
+
+// Converts a SKBitmap to unpremul alpha.
+SkBitmap ConvertSkBitmapToUnpremul(const SkBitmap& bitmap) {
+ DCHECK_NE(bitmap.alphaType(), kUnpremul_SkAlphaType);
+
+ SkImageInfo image_info = SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
+ kUnpremul_SkAlphaType);
+ SkBitmap converted_bitmap;
+ converted_bitmap.allocPixels(image_info);
+ bitmap.readPixels(image_info, converted_bitmap.getPixels(),
+ image_info.minRowBytes(), 0, 0);
+
+ return converted_bitmap;
+}
+
+// Creates an XCursorImage for cursor bitmap.
+XcursorImage* CreateXCursorImage(const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
+ // X11 expects bitmap with unpremul alpha. If bitmap is premul then convert,
+ // otherwise semi-transparent parts of cursor will look strange.
+ if (bitmap.alphaType() != kUnpremul_SkAlphaType) {
+ SkBitmap converted_bitmap = ConvertSkBitmapToUnpremul(bitmap);
+ return SkBitmapToXcursorImage(&converted_bitmap, hotspot);
+ } else {
+ return SkBitmapToXcursorImage(&bitmap, hotspot);
+ }
+}
+
+} // namespace
+
+X11CursorOzone::X11CursorOzone(const SkBitmap& bitmap,
+ const gfx::Point& hotspot) {
+ XcursorImage* image = CreateXCursorImage(bitmap, hotspot);
+ xcursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image);
+ XcursorImageDestroy(image);
+}
+
+X11CursorOzone::X11CursorOzone(const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ int frame_delay_ms) {
+ // Initialize an XCursorImage for each frame, store all of them in
+ // XCursorImages and load the cursor from that.
+ XcursorImages* images = XcursorImagesCreate(bitmaps.size());
+ images->nimage = bitmaps.size();
+ for (size_t frame = 0; frame < bitmaps.size(); ++frame) {
+ XcursorImage* x_image = CreateXCursorImage(bitmaps[frame], hotspot);
+ x_image->delay = frame_delay_ms;
+ images->images[frame] = x_image;
+ }
+
+ xcursor_ = XcursorImagesLoadCursor(gfx::GetXDisplay(), images);
+ XcursorImagesDestroy(images);
+}
+
+scoped_refptr<X11CursorOzone> X11CursorOzone::CreateInvisible() {
+ scoped_refptr<X11CursorOzone> invisible_ = new X11CursorOzone();
+ invisible_->xcursor_ = CreateInvisibleCursor();
+ return invisible_;
+}
+
+X11CursorOzone::X11CursorOzone() {}
+
+X11CursorOzone::~X11CursorOzone() {
+ XFreeCursor(gfx::GetXDisplay(), xcursor_);
+}
+
+} // namespace ui
diff --git a/chromium/ui/platform_window/x11/x11_cursor_ozone.h b/chromium/ui/platform_window/x11/x11_cursor_ozone.h
new file mode 100644
index 00000000000..8a83080e746
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_cursor_ozone.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_PLATFORM_WINDOW_X11_X11_CURSOR_OZONE_H_
+#define UI_PLATFORM_WINDOW_X11_X11_CURSOR_OZONE_H_
+
+#include <X11/X.h>
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/platform_window/x11/x11_window_export.h"
+
+class SkBitmap;
+
+namespace ui {
+
+// Ref counted class to hold an X11 cursor resource. Handles creating X11 cursor
+// resources from SkBitmap/hotspot and clears the X11 resources on destruction.
+class X11_WINDOW_EXPORT X11CursorOzone
+ : public base::RefCounted<X11CursorOzone> {
+ public:
+ X11CursorOzone(const SkBitmap& bitmap, const gfx::Point& hotspot);
+ X11CursorOzone(const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& hotspot,
+ int frame_delay_ms);
+
+ // Creates a new cursor that is invisible.
+ static scoped_refptr<X11CursorOzone> CreateInvisible();
+
+ ::Cursor xcursor() const { return xcursor_; }
+
+ private:
+ friend class base::RefCounted<X11CursorOzone>;
+
+ X11CursorOzone();
+ ~X11CursorOzone();
+
+ ::Cursor xcursor_ = None;
+
+ DISALLOW_COPY_AND_ASSIGN(X11CursorOzone);
+};
+
+} // namespace ui
+#endif // UI_PLATFORM_WINDOW_X11_X11_CURSOR_OZONE_H_
diff --git a/chromium/ui/platform_window/x11/x11_window.cc b/chromium/ui/platform_window/x11/x11_window.cc
index 6900a448915..f54b4166743 100644
--- a/chromium/ui/platform_window/x11/x11_window.cc
+++ b/chromium/ui/platform_window/x11/x11_window.cc
@@ -5,74 +5,30 @@
#include "ui/platform_window/x11/x11_window.h"
#include <X11/extensions/XInput2.h>
-#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include "base/strings/utf_string_conversions.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/x11/x11_event_source.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/gfx/x/x11_types.h"
#include "ui/platform_window/platform_window_delegate.h"
namespace ui {
-namespace {
-
-const char* kAtomsToCache[] = {
- "UTF8_STRING",
- "WM_DELETE_WINDOW",
- "_NET_WM_NAME",
- "_NET_WM_PID",
- "_NET_WM_PING",
- NULL
-};
-
-XID FindXEventTarget(XEvent* xevent) {
- XID target = xevent->xany.window;
- if (xevent->type == GenericEvent)
- target = static_cast<XIDeviceEvent*>(xevent->xcookie.data)->event;
- return target;
-}
-
-bool g_override_redirect = false;
-
-} // namespace
-
X11Window::X11Window(PlatformWindowDelegate* delegate)
- : delegate_(delegate),
- xdisplay_(gfx::GetXDisplay()),
- xwindow_(None),
- xroot_window_(DefaultRootWindow(xdisplay_)),
- atom_cache_(xdisplay_, kAtomsToCache),
- window_mapped_(false) {
- CHECK(delegate_);
- TouchFactory::SetTouchDeviceListFromCommandLine();
+ : X11WindowBase(delegate) {
+ DCHECK(PlatformEventSource::GetInstance());
+ PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
}
X11Window::~X11Window() {
- Destroy();
-}
-
-void X11Window::Destroy() {
- if (xwindow_ == None)
- return;
-
- // Stop processing events.
PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
- XID xwindow = xwindow_;
- XDisplay* xdisplay = xdisplay_;
- xwindow_ = None;
- delegate_->OnClosed();
- // |this| might be deleted because of the above call.
+}
- XDestroyWindow(xdisplay, xwindow);
+void X11Window::SetCursor(PlatformCursor cursor) {
+ XDefineCursor(xdisplay(), xwindow(), cursor);
}
void X11Window::ProcessXInput2Event(XEvent* xev) {
@@ -83,7 +39,7 @@ void X11Window::ProcessXInput2Event(XEvent* xev) {
case ET_KEY_PRESSED:
case ET_KEY_RELEASED: {
KeyEvent key_event(xev);
- delegate_->DispatchEvent(&key_event);
+ delegate()->DispatchEvent(&key_event);
break;
}
case ET_MOUSE_PRESSED:
@@ -91,19 +47,19 @@ void X11Window::ProcessXInput2Event(XEvent* xev) {
case ET_MOUSE_DRAGGED:
case ET_MOUSE_RELEASED: {
MouseEvent mouse_event(xev);
- delegate_->DispatchEvent(&mouse_event);
+ delegate()->DispatchEvent(&mouse_event);
break;
}
case ET_MOUSEWHEEL: {
MouseWheelEvent wheel_event(xev);
- delegate_->DispatchEvent(&wheel_event);
+ delegate()->DispatchEvent(&wheel_event);
break;
}
case ET_SCROLL_FLING_START:
case ET_SCROLL_FLING_CANCEL:
case ET_SCROLL: {
ScrollEvent scroll_event(xev);
- delegate_->DispatchEvent(&scroll_event);
+ delegate()->DispatchEvent(&scroll_event);
break;
}
case ET_TOUCH_MOVED:
@@ -111,7 +67,7 @@ void X11Window::ProcessXInput2Event(XEvent* xev) {
case ET_TOUCH_CANCELLED:
case ET_TOUCH_RELEASED: {
TouchEvent touch_event(xev);
- delegate_->DispatchEvent(&touch_event);
+ delegate()->DispatchEvent(&touch_event);
break;
}
default:
@@ -119,182 +75,8 @@ void X11Window::ProcessXInput2Event(XEvent* xev) {
}
}
-void X11Window::Show() {
- if (window_mapped_)
- return;
-
- CHECK(PlatformEventSource::GetInstance());
- PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
-
- XSetWindowAttributes swa;
- memset(&swa, 0, sizeof(swa));
- swa.background_pixmap = None;
- swa.bit_gravity = NorthWestGravity;
- swa.override_redirect = g_override_redirect;
- xwindow_ = XCreateWindow(xdisplay_,
- xroot_window_,
- requested_bounds_.x(),
- requested_bounds_.y(),
- requested_bounds_.width(),
- requested_bounds_.height(),
- 0, // border width
- CopyFromParent, // depth
- InputOutput,
- CopyFromParent, // visual
- CWBackPixmap | CWBitGravity | CWOverrideRedirect,
- &swa);
-
- long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
- KeyPressMask | KeyReleaseMask | EnterWindowMask |
- LeaveWindowMask | ExposureMask | VisibilityChangeMask |
- StructureNotifyMask | PropertyChangeMask |
- PointerMotionMask;
- XSelectInput(xdisplay_, xwindow_, event_mask);
-
- unsigned char mask[XIMaskLen(XI_LASTEVENT)];
- memset(mask, 0, sizeof(mask));
-
- XISetMask(mask, XI_TouchBegin);
- XISetMask(mask, XI_TouchUpdate);
- XISetMask(mask, XI_TouchEnd);
- XISetMask(mask, XI_ButtonPress);
- XISetMask(mask, XI_ButtonRelease);
- XISetMask(mask, XI_Motion);
- XISetMask(mask, XI_KeyPress);
- XISetMask(mask, XI_KeyRelease);
-
- XIEventMask evmask;
- evmask.deviceid = XIAllDevices;
- evmask.mask_len = sizeof(mask);
- evmask.mask = mask;
- XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
- XFlush(xdisplay_);
-
- ::Atom protocols[2];
- protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
- protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
- XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
-
- // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
- // the desktop environment.
- XSetWMProperties(
- xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
-
- // Likewise, the X server needs to know this window's pid so it knows which
- // program to kill if the window hangs.
- // XChangeProperty() expects "pid" to be long.
- static_assert(sizeof(long) >= sizeof(pid_t),
- "pid_t should not be larger than long");
- long pid = getpid();
- XChangeProperty(xdisplay_,
- xwindow_,
- atom_cache_.GetAtom("_NET_WM_PID"),
- XA_CARDINAL,
- 32,
- PropModeReplace,
- reinterpret_cast<unsigned char*>(&pid),
- 1);
- // Before we map the window, set size hints. Otherwise, some window managers
- // will ignore toplevel XMoveWindow commands.
- XSizeHints size_hints;
- size_hints.flags = PPosition | PWinGravity;
- size_hints.x = requested_bounds_.x();
- size_hints.y = requested_bounds_.y();
- // Set StaticGravity so that the window position is not affected by the
- // frame width when running with window manager.
- size_hints.win_gravity = StaticGravity;
- 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.
- if (X11EventSource::GetInstance())
- X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
- window_mapped_ = true;
-
- // TODO(sky): provide real scale factor.
- delegate_->OnAcceleratedWidgetAvailable(xwindow_, 1.f);
-}
-
-void X11Window::Hide() {
- if (!window_mapped_)
- return;
- XWithdrawWindow(xdisplay_, xwindow_, 0);
- window_mapped_ = false;
-}
-
-void X11Window::Close() {
- Destroy();
-}
-
-void X11Window::SetBounds(const gfx::Rect& bounds) {
- requested_bounds_ = bounds;
- if (!window_mapped_)
- return;
- XWindowChanges changes = {0};
- unsigned value_mask = CWX | CWY | CWWidth | CWHeight;
- changes.x = bounds.x();
- changes.y = bounds.y();
- changes.width = bounds.width();
- changes.height = bounds.height();
- XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
-}
-
-gfx::Rect X11Window::GetBounds() {
- return confirmed_bounds_;
-}
-
-void X11Window::SetTitle(const base::string16& title) {
- if (window_title_ == title)
- return;
- window_title_ = title;
- std::string utf8str = base::UTF16ToUTF8(title);
- XChangeProperty(xdisplay_,
- xwindow_,
- atom_cache_.GetAtom("_NET_WM_NAME"),
- atom_cache_.GetAtom("UTF8_STRING"),
- 8,
- PropModeReplace,
- reinterpret_cast<const unsigned char*>(utf8str.c_str()),
- utf8str.size());
- XTextProperty xtp;
- char *c_utf8_str = const_cast<char *>(utf8str.c_str());
- if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1,
- XUTF8StringStyle, &xtp) == Success) {
- XSetWMName(xdisplay_, xwindow_, &xtp);
- XFree(xtp.value);
- }
-}
-
-void X11Window::SetCapture() {}
-
-void X11Window::ReleaseCapture() {}
-
-void X11Window::ToggleFullscreen() {}
-
-void X11Window::Maximize() {}
-
-void X11Window::Minimize() {}
-
-void X11Window::Restore() {}
-
-void X11Window::SetCursor(PlatformCursor cursor) {
- XDefineCursor(xdisplay_, xwindow_, cursor);
-}
-
-void X11Window::MoveCursorTo(const gfx::Point& location) {}
-
-void X11Window::ConfineCursorToBounds(const gfx::Rect& bounds) {
-}
-
-PlatformImeController* X11Window::GetPlatformImeController() {
- return nullptr;
-}
-
-bool X11Window::CanDispatchEvent(const PlatformEvent& event) {
- return FindXEventTarget(event) == xwindow_;
+bool X11Window::CanDispatchEvent(const PlatformEvent& xev) {
+ return IsEventForXWindow(*xev);
}
uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
@@ -306,28 +88,19 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
MouseEvent mouse_event(xev);
CHECK_EQ(ET_MOUSE_MOVED, mouse_event.type());
mouse_event.set_flags(mouse_event.flags() | EF_IS_SYNTHESIZED);
- delegate_->DispatchEvent(&mouse_event);
+ delegate()->DispatchEvent(&mouse_event);
break;
}
case LeaveNotify: {
MouseEvent mouse_event(xev);
- delegate_->DispatchEvent(&mouse_event);
- break;
- }
-
- case Expose: {
- gfx::Rect damage_rect(xev->xexpose.x,
- xev->xexpose.y,
- xev->xexpose.width,
- xev->xexpose.height);
- delegate_->OnDamageRect(damage_rect);
+ delegate()->DispatchEvent(&mouse_event);
break;
}
case KeyPress:
case KeyRelease: {
KeyEvent key_event(xev);
- delegate_->DispatchEvent(&key_event);
+ delegate()->DispatchEvent(&key_event);
break;
}
@@ -336,13 +109,13 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
switch (EventTypeFromNative(xev)) {
case ET_MOUSEWHEEL: {
MouseWheelEvent mouseev(xev);
- delegate_->DispatchEvent(&mouseev);
+ delegate()->DispatchEvent(&mouseev);
break;
}
case ET_MOUSE_PRESSED:
case ET_MOUSE_RELEASED: {
MouseEvent mouseev(xev);
- delegate_->DispatchEvent(&mouseev);
+ delegate()->DispatchEvent(&mouseev);
break;
}
case ET_UNKNOWN:
@@ -355,40 +128,11 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
break;
}
+ case Expose:
case FocusOut:
- if (xev->xfocus.mode != NotifyGrab)
- delegate_->OnLostCapture();
- break;
-
- case ConfigureNotify: {
- DCHECK_EQ(xwindow_, xev->xconfigure.event);
- DCHECK_EQ(xwindow_, xev->xconfigure.window);
- gfx::Rect bounds(xev->xconfigure.x,
- xev->xconfigure.y,
- xev->xconfigure.width,
- xev->xconfigure.height);
- if (confirmed_bounds_ != bounds) {
- confirmed_bounds_ = bounds;
- delegate_->OnBoundsChanged(confirmed_bounds_);
- }
- break;
- }
-
+ case ConfigureNotify:
case ClientMessage: {
- Atom message = static_cast<Atom>(xev->xclient.data.l[0]);
- if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
- delegate_->OnCloseRequest();
- } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) {
- XEvent reply_event = *xev;
- reply_event.xclient.window = xroot_window_;
-
- XSendEvent(xdisplay_,
- reply_event.xclient.window,
- False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &reply_event);
- XFlush(xdisplay_);
- }
+ ProcessXWindowEvent(xev);
break;
}
@@ -400,11 +144,4 @@ uint32_t X11Window::DispatchEvent(const PlatformEvent& event) {
return POST_DISPATCH_STOP_PROPAGATION;
}
-namespace test {
-
-void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
- g_override_redirect = override_redirect;
-}
-
-} // namespace test
} // namespace ui
diff --git a/chromium/ui/platform_window/x11/x11_window.gyp b/chromium/ui/platform_window/x11/x11_window.gyp
index 0dd840a5e2b..f4b948ae3f7 100644
--- a/chromium/ui/platform_window/x11/x11_window.gyp
+++ b/chromium/ui/platform_window/x11/x11_window.gyp
@@ -26,6 +26,8 @@
'sources': [
'x11_window.cc',
'x11_window.h',
+ 'x11_window_base.cc',
+ 'x11_window_base.h',
'x11_window_export.h',
],
}],
diff --git a/chromium/ui/platform_window/x11/x11_window.h b/chromium/ui/platform_window/x11/x11_window.h
index 54bbed86082..c3f15cf9cdc 100644
--- a/chromium/ui/platform_window/x11/x11_window.h
+++ b/chromium/ui/platform_window/x11/x11_window.h
@@ -5,86 +5,33 @@
#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_
#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_
-#include <stdint.h>
-
#include "base/macros.h"
#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/platform_window/platform_window.h"
-#include "ui/platform_window/platform_window_delegate.h"
+#include "ui/platform_window/x11/x11_window_base.h"
#include "ui/platform_window/x11/x11_window_export.h"
-typedef struct _XDisplay XDisplay;
-typedef unsigned long XID;
-
namespace ui {
-class X11_WINDOW_EXPORT X11Window : public PlatformWindow,
+// PlatformWindow implementation for X11. PlatformEvents are XEvents.
+class X11_WINDOW_EXPORT X11Window : public X11WindowBase,
public PlatformEventDispatcher {
public:
explicit X11Window(PlatformWindowDelegate* delegate);
~X11Window() override;
- private:
- void Destroy();
-
- void ProcessXInput2Event(XEvent* xevent);
-
// PlatformWindow:
- void Show() override;
- void Hide() override;
- void Close() override;
- void SetBounds(const gfx::Rect& bounds) override;
- gfx::Rect GetBounds() override;
- void SetTitle(const base::string16& title) override;
- void SetCapture() override;
- void ReleaseCapture() override;
- void ToggleFullscreen() override;
- void Maximize() override;
- void Minimize() override;
- void Restore() override;
void SetCursor(PlatformCursor cursor) override;
- void MoveCursorTo(const gfx::Point& location) override;
- void ConfineCursorToBounds(const gfx::Rect& bounds) override;
- PlatformImeController* GetPlatformImeController() override;
+
+ private:
+ void ProcessXInput2Event(XEvent* xev);
// PlatformEventDispatcher:
bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override;
- PlatformWindowDelegate* delegate_;
-
- XDisplay* xdisplay_;
- XID xwindow_;
- XID xroot_window_;
- X11AtomCache atom_cache_;
-
- base::string16 window_title_;
-
- // Setting the bounds is an asynchronous operation in X11. |requested_bounds_|
- // is the bounds requested using XConfigureWindow, and |confirmed_bounds_| is
- // the bounds the X11 server has set on the window.
- gfx::Rect requested_bounds_;
- gfx::Rect confirmed_bounds_;
-
- bool window_mapped_;
-
DISALLOW_COPY_AND_ASSIGN(X11Window);
};
-namespace test {
-
-// Sets the value of the |override_redirect| flag when creating an X11 window.
-// It is necessary to set this flag on for various tests, otherwise the call to
-// X11Window::Show() blocks because it never receives the MapNotify event. It is
-// unclear why this is necessary, but might be related to calls to
-// XInitThreads().
-X11_WINDOW_EXPORT void SetUseOverrideRedirectWindowByDefault(
- bool override_redirect);
-
-} // namespace test
-
} // namespace ui
#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_H_
diff --git a/chromium/ui/platform_window/x11/x11_window_base.cc b/chromium/ui/platform_window/x11/x11_window_base.cc
new file mode 100644
index 00000000000..51b19acfd25
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_base.cc
@@ -0,0 +1,288 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/platform_window/x11/x11_window_base.h"
+
+#include <X11/extensions/XInput2.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+#include "ui/events/devices/x11/touch_factory_x11.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/gfx/x/x11_types.h"
+#include "ui/platform_window/platform_window_delegate.h"
+
+namespace ui {
+
+namespace {
+
+const char* kAtomsToCache[] = {"UTF8_STRING", "WM_DELETE_WINDOW",
+ "_NET_WM_NAME", "_NET_WM_PID",
+ "_NET_WM_PING", NULL};
+
+bool g_override_redirect = false;
+
+XID FindXEventTarget(const XEvent& xev) {
+ XID target = xev.xany.window;
+ if (xev.type == GenericEvent)
+ target = static_cast<XIDeviceEvent*>(xev.xcookie.data)->event;
+ return target;
+}
+
+} // namespace
+
+X11WindowBase::X11WindowBase(PlatformWindowDelegate* delegate)
+ : delegate_(delegate),
+ xdisplay_(gfx::GetXDisplay()),
+ xwindow_(None),
+ xroot_window_(DefaultRootWindow(xdisplay_)),
+ atom_cache_(xdisplay_, kAtomsToCache) {
+ DCHECK(delegate_);
+ TouchFactory::SetTouchDeviceListFromCommandLine();
+}
+
+X11WindowBase::~X11WindowBase() {
+ Destroy();
+}
+
+void X11WindowBase::Destroy() {
+ if (xwindow_ == None)
+ return;
+
+ // Stop processing events.
+ XID xwindow = xwindow_;
+ XDisplay* xdisplay = xdisplay_;
+ xwindow_ = None;
+ delegate_->OnClosed();
+ // |this| might be deleted because of the above call.
+
+ XDestroyWindow(xdisplay, xwindow);
+}
+
+void X11WindowBase::Create() {
+ XSetWindowAttributes swa;
+ memset(&swa, 0, sizeof(swa));
+ swa.background_pixmap = None;
+ swa.bit_gravity = NorthWestGravity;
+ swa.override_redirect = g_override_redirect;
+ xwindow_ = XCreateWindow(
+ xdisplay_, xroot_window_, requested_bounds_.x(), requested_bounds_.y(),
+ requested_bounds_.width(), requested_bounds_.height(),
+ 0, // border width
+ CopyFromParent, // depth
+ InputOutput,
+ CopyFromParent, // visual
+ CWBackPixmap | CWBitGravity | CWOverrideRedirect, &swa);
+
+ long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
+ KeyPressMask | KeyReleaseMask | EnterWindowMask |
+ LeaveWindowMask | ExposureMask | VisibilityChangeMask |
+ StructureNotifyMask | PropertyChangeMask |
+ PointerMotionMask;
+ XSelectInput(xdisplay_, xwindow_, event_mask);
+
+ unsigned char mask[XIMaskLen(XI_LASTEVENT)];
+ memset(mask, 0, sizeof(mask));
+
+ XISetMask(mask, XI_TouchBegin);
+ XISetMask(mask, XI_TouchUpdate);
+ XISetMask(mask, XI_TouchEnd);
+ XISetMask(mask, XI_ButtonPress);
+ XISetMask(mask, XI_ButtonRelease);
+ XISetMask(mask, XI_Motion);
+ XISetMask(mask, XI_KeyPress);
+ XISetMask(mask, XI_KeyRelease);
+
+ XIEventMask evmask;
+ evmask.deviceid = XIAllDevices;
+ evmask.mask_len = sizeof(mask);
+ evmask.mask = mask;
+ XISelectEvents(xdisplay_, xwindow_, &evmask, 1);
+ XFlush(xdisplay_);
+
+ ::Atom protocols[2];
+ protocols[0] = atom_cache_.GetAtom("WM_DELETE_WINDOW");
+ protocols[1] = atom_cache_.GetAtom("_NET_WM_PING");
+ XSetWMProtocols(xdisplay_, xwindow_, protocols, 2);
+
+ // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
+ // the desktop environment.
+ XSetWMProperties(xdisplay_, xwindow_, NULL, NULL, NULL, 0, NULL, NULL, NULL);
+
+ // Likewise, the X server needs to know this window's pid so it knows which
+ // program to kill if the window hangs.
+ // XChangeProperty() expects "pid" to be long.
+ static_assert(sizeof(long) >= sizeof(pid_t),
+ "pid_t should not be larger than long");
+ long pid = getpid();
+ XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_PID"),
+ XA_CARDINAL, 32, PropModeReplace,
+ reinterpret_cast<unsigned char*>(&pid), 1);
+ // Before we map the window, set size hints. Otherwise, some window managers
+ // will ignore toplevel XMoveWindow commands.
+ XSizeHints size_hints;
+ size_hints.flags = PPosition | PWinGravity;
+ size_hints.x = requested_bounds_.x();
+ size_hints.y = requested_bounds_.y();
+ // Set StaticGravity so that the window position is not affected by the
+ // frame width when running with window manager.
+ size_hints.win_gravity = StaticGravity;
+ XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
+
+ // TODO(sky): provide real scale factor.
+ delegate_->OnAcceleratedWidgetAvailable(xwindow_, 1.f);
+}
+
+void X11WindowBase::Show() {
+ if (window_mapped_)
+ return;
+ if (xwindow_ == None)
+ Create();
+
+ 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 (X11EventSource::GetInstance())
+ X11EventSource::GetInstance()->BlockUntilWindowMapped(xwindow_);
+ window_mapped_ = true;
+}
+
+void X11WindowBase::Hide() {
+ if (!window_mapped_)
+ return;
+ XWithdrawWindow(xdisplay_, xwindow_, 0);
+ window_mapped_ = false;
+}
+
+void X11WindowBase::Close() {
+ Destroy();
+}
+
+void X11WindowBase::SetBounds(const gfx::Rect& bounds) {
+ requested_bounds_ = bounds;
+ if (!window_mapped_ || bounds == confirmed_bounds_)
+ return;
+ XWindowChanges changes = {0};
+ unsigned value_mask = CWX | CWY | CWWidth | CWHeight;
+ changes.x = bounds.x();
+ changes.y = bounds.y();
+ changes.width = bounds.width();
+ changes.height = bounds.height();
+ XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
+}
+
+gfx::Rect X11WindowBase::GetBounds() {
+ return confirmed_bounds_;
+}
+
+void X11WindowBase::SetTitle(const base::string16& title) {
+ if (window_title_ == title)
+ return;
+ window_title_ = title;
+ std::string utf8str = base::UTF16ToUTF8(title);
+ XChangeProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_NAME"),
+ atom_cache_.GetAtom("UTF8_STRING"), 8, PropModeReplace,
+ reinterpret_cast<const unsigned char*>(utf8str.c_str()),
+ utf8str.size());
+ XTextProperty xtp;
+ char* c_utf8_str = const_cast<char*>(utf8str.c_str());
+ if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle,
+ &xtp) == Success) {
+ XSetWMName(xdisplay_, xwindow_, &xtp);
+ XFree(xtp.value);
+ }
+}
+
+void X11WindowBase::SetCapture() {}
+
+void X11WindowBase::ReleaseCapture() {}
+
+void X11WindowBase::ToggleFullscreen() {}
+
+void X11WindowBase::Maximize() {}
+
+void X11WindowBase::Minimize() {}
+
+void X11WindowBase::Restore() {}
+
+void X11WindowBase::MoveCursorTo(const gfx::Point& location) {
+ XWarpPointer(xdisplay_, None, xroot_window_, 0, 0, 0, 0,
+ confirmed_bounds_.x() + location.x(),
+ confirmed_bounds_.y() + location.y());
+}
+
+void X11WindowBase::ConfineCursorToBounds(const gfx::Rect& bounds) {}
+
+PlatformImeController* X11WindowBase::GetPlatformImeController() {
+ return nullptr;
+}
+
+bool X11WindowBase::IsEventForXWindow(const XEvent& xev) const {
+ return xwindow_ != None && FindXEventTarget(xev) == xwindow_;
+}
+
+void X11WindowBase::ProcessXWindowEvent(XEvent* xev) {
+ switch (xev->type) {
+ case Expose: {
+ gfx::Rect damage_rect(xev->xexpose.x, xev->xexpose.y, xev->xexpose.width,
+ xev->xexpose.height);
+ delegate_->OnDamageRect(damage_rect);
+ break;
+ }
+
+ case FocusOut:
+ if (xev->xfocus.mode != NotifyGrab)
+ delegate_->OnLostCapture();
+ break;
+
+ case ConfigureNotify: {
+ DCHECK_EQ(xwindow_, xev->xconfigure.event);
+ DCHECK_EQ(xwindow_, xev->xconfigure.window);
+ gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
+ xev->xconfigure.width, xev->xconfigure.height);
+ if (confirmed_bounds_ != bounds) {
+ confirmed_bounds_ = bounds;
+ delegate_->OnBoundsChanged(confirmed_bounds_);
+ }
+ break;
+ }
+
+ case ClientMessage: {
+ Atom message = static_cast<Atom>(xev->xclient.data.l[0]);
+ if (message == atom_cache_.GetAtom("WM_DELETE_WINDOW")) {
+ delegate_->OnCloseRequest();
+ } else if (message == atom_cache_.GetAtom("_NET_WM_PING")) {
+ XEvent reply_event = *xev;
+ reply_event.xclient.window = xroot_window_;
+
+ XSendEvent(xdisplay_, reply_event.xclient.window, False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &reply_event);
+ XFlush(xdisplay_);
+ }
+ break;
+ }
+ }
+}
+
+namespace test {
+
+void SetUseOverrideRedirectWindowByDefault(bool override_redirect) {
+ g_override_redirect = override_redirect;
+}
+
+} // namespace test
+} // namespace ui
diff --git a/chromium/ui/platform_window/x11/x11_window_base.h b/chromium/ui/platform_window/x11/x11_window_base.h
new file mode 100644
index 00000000000..da357253612
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_base.h
@@ -0,0 +1,100 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
+#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_delegate.h"
+#include "ui/platform_window/x11/x11_window_export.h"
+
+typedef struct _XDisplay XDisplay;
+typedef unsigned long XID;
+typedef union _XEvent XEvent;
+
+namespace ui {
+
+// Abstract base implementation for a X11 based PlatformWindow. Methods that
+// are platform specific are left unimplemented.
+class X11_WINDOW_EXPORT X11WindowBase : public PlatformWindow {
+ public:
+ explicit X11WindowBase(PlatformWindowDelegate* delegate);
+ ~X11WindowBase() override;
+
+ // Creates new underlying XWindow. Does not map XWindow.
+ void Create();
+
+ // PlatformWindow:
+ void Show() override;
+ void Hide() override;
+ void Close() override;
+ void SetBounds(const gfx::Rect& bounds) override;
+ gfx::Rect GetBounds() override;
+ void SetTitle(const base::string16& title) override;
+ void SetCapture() override;
+ void ReleaseCapture() override;
+ void ToggleFullscreen() override;
+ void Maximize() override;
+ void Minimize() override;
+ void Restore() override;
+ void MoveCursorTo(const gfx::Point& location) override;
+ void ConfineCursorToBounds(const gfx::Rect& bounds) override;
+ PlatformImeController* GetPlatformImeController() override;
+
+ protected:
+ void Destroy();
+
+ PlatformWindowDelegate* delegate() { return delegate_; }
+ XDisplay* xdisplay() { return xdisplay_; }
+ XID xwindow() const { return xwindow_; }
+
+ // Checks if XEvent is for this XWindow.
+ bool IsEventForXWindow(const XEvent& xev) const;
+
+ // Processes events for this XWindow.
+ void ProcessXWindowEvent(XEvent* xev);
+
+ private:
+ PlatformWindowDelegate* delegate_;
+
+ XDisplay* xdisplay_;
+ XID xwindow_;
+ XID xroot_window_;
+ X11AtomCache atom_cache_;
+
+ base::string16 window_title_;
+
+ // Setting the bounds is an asynchronous operation in X11. |requested_bounds_|
+ // is the bounds requested using XConfigureWindow, and |confirmed_bounds_| is
+ // the bounds the X11 server has set on the window.
+ gfx::Rect requested_bounds_;
+ gfx::Rect confirmed_bounds_;
+
+ bool window_mapped_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(X11WindowBase);
+};
+
+namespace test {
+
+// Sets the value of the |override_redirect| flag when creating an X11 window.
+// It is necessary to set this flag on for various tests, otherwise the call to
+// X11WindowBase::Show() blocks because it never receives the MapNotify event.
+// It is
+// unclear why this is necessary, but might be related to calls to
+// XInitThreads().
+X11_WINDOW_EXPORT void SetUseOverrideRedirectWindowByDefault(
+ bool override_redirect);
+
+} // namespace test
+
+} // namespace ui
+
+#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_BASE_H_
diff --git a/chromium/ui/platform_window/x11/x11_window_manager_ozone.cc b/chromium/ui/platform_window/x11/x11_window_manager_ozone.cc
new file mode 100644
index 00000000000..f29cf9e9433
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_manager_ozone.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/platform_window/x11/x11_window_manager_ozone.h"
+
+#include <X11/Xlib.h>
+
+namespace ui {
+
+X11WindowManagerOzone::X11WindowManagerOzone() : event_grabber_(None) {}
+
+X11WindowManagerOzone::~X11WindowManagerOzone() {}
+
+void X11WindowManagerOzone::GrabEvents(XID xwindow) {
+ if (event_grabber_ != None)
+ return;
+ event_grabber_ = xwindow;
+}
+
+void X11WindowManagerOzone::UngrabEvents(XID xwindow) {
+ if (event_grabber_ != xwindow)
+ return;
+ event_grabber_ = None;
+}
+
+} // namespace ui
diff --git a/chromium/ui/platform_window/x11/x11_window_manager_ozone.h b/chromium/ui/platform_window/x11/x11_window_manager_ozone.h
new file mode 100644
index 00000000000..1cb6bd1bacd
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_manager_ozone.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_MANAGER_OZONE_H_
+#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_MANAGER_OZONE_H_
+
+#include "base/macros.h"
+#include "ui/platform_window/x11/x11_window_export.h"
+#include "ui/platform_window/x11/x11_window_ozone.h"
+
+namespace ui {
+
+class X11_WINDOW_EXPORT X11WindowManagerOzone {
+ public:
+ X11WindowManagerOzone();
+ ~X11WindowManagerOzone();
+
+ // Tries to set a given XWindow as the recipient for events. It will fail if
+ // there is already another XWindow as recipient.
+ void GrabEvents(XID xwindow);
+
+ // Unsets a given XWindow as the recipient for events.
+ void UngrabEvents(XID xwindow);
+
+ // Gets the current XWindow recipient of mouse events.
+ XID event_grabber() const { return event_grabber_; }
+
+ private:
+ XID event_grabber_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11WindowManagerOzone);
+};
+
+} // namespace ui
+
+#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_MANAGER_OZONE_H_
diff --git a/chromium/ui/platform_window/x11/x11_window_ozone.cc b/chromium/ui/platform_window/x11/x11_window_ozone.cc
new file mode 100644
index 00000000000..5a8307004f7
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_ozone.cc
@@ -0,0 +1,85 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/platform_window/x11/x11_window_ozone.h"
+
+#include <X11/Xlib.h>
+
+#include "ui/events/event.h"
+#include "ui/events/ozone/events_ozone.h"
+#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/platform_window/x11/x11_cursor_ozone.h"
+#include "ui/platform_window/x11/x11_window_manager_ozone.h"
+
+namespace ui {
+
+X11WindowOzone::X11WindowOzone(X11EventSourceLibevent* event_source,
+ X11WindowManagerOzone* window_manager,
+ PlatformWindowDelegate* delegate)
+ : X11WindowBase(delegate),
+ event_source_(event_source),
+ window_manager_(window_manager) {
+ DCHECK(event_source_);
+ DCHECK(window_manager);
+ event_source_->AddPlatformEventDispatcher(this);
+ event_source_->AddXEventDispatcher(this);
+}
+
+X11WindowOzone::~X11WindowOzone() {
+ event_source_->RemovePlatformEventDispatcher(this);
+ event_source_->RemoveXEventDispatcher(this);
+}
+
+void X11WindowOzone::SetCapture() {
+ window_manager_->GrabEvents(xwindow());
+}
+
+void X11WindowOzone::ReleaseCapture() {
+ window_manager_->UngrabEvents(xwindow());
+}
+
+void X11WindowOzone::SetCursor(PlatformCursor cursor) {
+ X11CursorOzone* cursor_ozone = static_cast<X11CursorOzone*>(cursor);
+ XDefineCursor(xdisplay(), xwindow(), cursor_ozone->xcursor());
+}
+
+bool X11WindowOzone::DispatchXEvent(XEvent* xev) {
+ if (!IsEventForXWindow(*xev))
+ return false;
+
+ ProcessXWindowEvent(xev);
+ return true;
+}
+
+bool X11WindowOzone::CanDispatchEvent(const PlatformEvent& platform_event) {
+ if (xwindow() == None)
+ return false;
+
+ // If there is a grab, capture events here.
+ XID grabber = window_manager_->event_grabber();
+ if (grabber != None)
+ return grabber == xwindow();
+
+ // TODO(kylechar): We may need to do something special for TouchEvents similar
+ // to how DrmWindowHost handles them.
+ if (static_cast<Event*>(platform_event)->IsLocatedEvent()) {
+ const LocatedEvent* event =
+ static_cast<const LocatedEvent*>(platform_event);
+ return GetBounds().Contains(event->root_location());
+ }
+
+ return true;
+}
+
+uint32_t X11WindowOzone::DispatchEvent(const PlatformEvent& platform_event) {
+ // This is unfortunately needed otherwise events that depend on global state
+ // (eg. double click) are broken.
+ DispatchEventFromNativeUiEvent(
+ platform_event, base::Bind(&PlatformWindowDelegate::DispatchEvent,
+ base::Unretained(delegate())));
+ return POST_DISPATCH_STOP_PROPAGATION;
+}
+
+} // namespace ui
diff --git a/chromium/ui/platform_window/x11/x11_window_ozone.h b/chromium/ui/platform_window/x11/x11_window_ozone.h
new file mode 100644
index 00000000000..da847ecc8a1
--- /dev/null
+++ b/chromium/ui/platform_window/x11/x11_window_ozone.h
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_PLATFORM_WINDOW_X11_X11_WINDOW_OZONE_H_
+#define UI_PLATFORM_WINDOW_X11_X11_WINDOW_OZONE_H_
+
+#include "base/macros.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/platform/x11/x11_event_source_libevent.h"
+#include "ui/platform_window/x11/x11_window_base.h"
+#include "ui/platform_window/x11/x11_window_export.h"
+
+namespace ui {
+
+class X11WindowManagerOzone;
+
+// PlatformWindow implementation for X11 Ozone. PlatformEvents are ui::Events.
+class X11_WINDOW_EXPORT X11WindowOzone : public X11WindowBase,
+ public PlatformEventDispatcher,
+ public XEventDispatcher {
+ public:
+ X11WindowOzone(X11EventSourceLibevent* event_source,
+ X11WindowManagerOzone* window_manager,
+ PlatformWindowDelegate* delegate);
+ ~X11WindowOzone() override;
+
+ // PlatformWindow:
+ void SetCapture() override;
+ void ReleaseCapture() override;
+ void SetCursor(PlatformCursor cursor) override;
+
+ // XEventDispatcher:
+ bool DispatchXEvent(XEvent* event) override;
+
+ private:
+ // PlatformEventDispatcher:
+ bool CanDispatchEvent(const PlatformEvent& event) override;
+ uint32_t DispatchEvent(const PlatformEvent& event) override;
+
+ X11EventSourceLibevent* event_source_;
+ X11WindowManagerOzone* window_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(X11WindowOzone);
+};
+
+} // namespace ui
+
+#endif // UI_PLATFORM_WINDOW_X11_X11_WINDOW_OZONE_H_
diff --git a/chromium/ui/resources/BUILD.gn b/chromium/ui/resources/BUILD.gn
index eaf4646b4ea..1b407f3712f 100644
--- a/chromium/ui/resources/BUILD.gn
+++ b/chromium/ui/resources/BUILD.gn
@@ -71,6 +71,60 @@ if (is_ios || is_mac) {
":repack_ui_test_pak",
]
}
+
+ # This needs to be a separate target from ui_test_pak as ui_base_unittests
+ # wants the generate .pak file in the bundle to be named en.lpro/locale.pak
+ # while components_unittests wants it to be named ui_test.pak.
+ bundle_data("ui_test_pak_bundle_data_locale") {
+ testonly = true
+ visibility = [ ":ui_test_pak_bundle_data" ]
+ public_deps = [
+ ":ui_test_pak",
+ ]
+ sources = [
+ "$root_out_dir/ui_test.pak",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/en.lproj/locale.pak",
+ ]
+ }
+
+ bundle_data("ui_test_pak_bundle_data_test_pak") {
+ testonly = true
+ visibility = [ ":ui_test_pak_bundle_data" ]
+ public_deps = [
+ ":ui_test_pak",
+ ]
+ sources = [
+ "$root_out_dir/ui_test.pak",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/ui_test.pak",
+ ]
+ }
+
+ bundle_data("ui_test_pak_bundle_data_100_percent") {
+ testonly = true
+ visibility = [ ":ui_test_pak_bundle_data" ]
+ public_deps = [
+ ":ui_test_pak",
+ ]
+ sources = [
+ "$root_out_dir/ui_test.pak",
+ ]
+ outputs = [
+ "{{bundle_resources_dir}}/chrome_100_percent.pak",
+ ]
+ }
+
+ group("ui_test_pak_bundle_data") {
+ testonly = true
+ public_deps = [
+ ":ui_test_pak_bundle_data_100_percent",
+ ":ui_test_pak_bundle_data_locale",
+ ":ui_test_pak_bundle_data_test_pak",
+ ]
+ }
} else {
copy("ui_test_pak") {
sources = [
diff --git a/chromium/ui/shell_dialogs/BUILD.gn b/chromium/ui/shell_dialogs/BUILD.gn
index 4ecd64c4f47..baadbba665b 100644
--- a/chromium/ui/shell_dialogs/BUILD.gn
+++ b/chromium/ui/shell_dialogs/BUILD.gn
@@ -14,8 +14,6 @@ component("shell_dialogs") {
"base_shell_dialog.h",
"base_shell_dialog_win.cc",
"base_shell_dialog_win.h",
- "linux_shell_dialog.cc",
- "linux_shell_dialog.h",
"select_file_dialog.cc",
"select_file_dialog.h",
"select_file_dialog_factory.cc",
@@ -28,6 +26,8 @@ component("shell_dialogs") {
"select_file_policy.h",
"selected_file_info.cc",
"selected_file_info.h",
+ "shell_dialog_linux.cc",
+ "shell_dialog_linux.h",
]
defines = [ "SHELL_DIALOGS_IMPLEMENTATION" ]
@@ -63,29 +63,21 @@ component("shell_dialogs") {
include_dirs = [ "$root_gen_dir/ui" ]
libs = [ "jnigraphics" ]
}
-
- if (is_android && use_aura) {
- sources += [
- "select_file_dialog_auraandroid.cc",
- "select_file_dialog_auraandroid.h",
- ]
- }
-
- if (is_win) {
- deps += [ "//win8:metro_viewer" ]
- }
}
test("shell_dialogs_unittests") {
sources = [
+ # TODO(karandeepb) : Revisit this once gn gets mac bundle support.
+ # "select_file_dialog_mac_unittest.mm",
+ "run_all_unittests.cc",
"select_file_dialog_win_unittest.cc",
]
deps = [
":shell_dialogs",
"//base",
- "//base/test:run_all_unittests",
"//base/test:test_support",
"//testing/gtest",
+ "//ui/base:base",
]
}
diff --git a/chromium/ui/shell_dialogs/linux_shell_dialog.cc b/chromium/ui/shell_dialogs/linux_shell_dialog.cc
deleted file mode 100644
index 059bb724564..00000000000
--- a/chromium/ui/shell_dialogs/linux_shell_dialog.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/shell_dialogs/linux_shell_dialog.h"
-
-namespace {
-
-ui::LinuxShellDialog* g_linux_shell_dialog = NULL;
-
-} // namespace
-
-namespace ui {
-
-void LinuxShellDialog::SetInstance(LinuxShellDialog* instance) {
- g_linux_shell_dialog = instance;
-}
-
-const LinuxShellDialog* LinuxShellDialog::instance() {
- return g_linux_shell_dialog;
-}
-
-} // namespace ui
diff --git a/chromium/ui/shell_dialogs/run_all_unittests.cc b/chromium/ui/shell_dialogs/run_all_unittests.cc
new file mode 100644
index 00000000000..08996518bc9
--- /dev/null
+++ b/chromium/ui/shell_dialogs/run_all_unittests.cc
@@ -0,0 +1,73 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/test/launcher/unit_test_launcher.h"
+#include "base/test/test_suite.h"
+#include "build/build_config.h"
+
+#if defined(OS_MACOSX)
+#include "base/files/file_path.h"
+#include "base/mac/bundle_locations.h"
+#include "base/path_service.h"
+#include "base/test/mock_chrome_application_mac.h"
+#include "ui/base/resource/resource_bundle.h"
+#endif
+
+namespace {
+
+class ShellDialogsTestSuite : public base::TestSuite {
+ public:
+ ShellDialogsTestSuite(int argc, char** argv);
+
+ protected:
+ // base::TestSuite:
+ void Initialize() override;
+ void Shutdown() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellDialogsTestSuite);
+};
+
+ShellDialogsTestSuite::ShellDialogsTestSuite(int argc, char** argv)
+ : base::TestSuite(argc, argv) {}
+
+void ShellDialogsTestSuite::Initialize() {
+ base::TestSuite::Initialize();
+
+#if defined(OS_MACOSX)
+ mock_cr_app::RegisterMockCrApp();
+
+ // Set up framework bundle so that tests on Mac can access nib files.
+ base::FilePath path;
+ PathService::Get(base::DIR_EXE, &path);
+ // The three DirName() calls strip "Contents/MacOS/<binary>" from the path.
+ path = path.DirName().DirName().DirName();
+ path = path.Append(FILE_PATH_LITERAL("shell_dialogs_unittests.app"));
+ base::mac::SetOverrideFrameworkBundlePath(path);
+
+ // Setup resource bundle.
+ ui::ResourceBundle::InitSharedInstanceWithLocale(
+ "en-US", nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
+#endif
+}
+
+void ShellDialogsTestSuite::Shutdown() {
+#if defined(OS_MACOSX)
+ ui::ResourceBundle::CleanupSharedInstance();
+ base::mac::SetOverrideFrameworkBundle(NULL);
+#endif
+ base::TestSuite::Shutdown();
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ShellDialogsTestSuite test_suite(argc, argv);
+
+ return base::LaunchUnitTests(
+ argc, argv,
+ base::Bind(&ShellDialogsTestSuite::Run, base::Unretained(&test_suite)));
+}
diff --git a/chromium/ui/shell_dialogs/select_file_dialog.cc b/chromium/ui/shell_dialogs/select_file_dialog.cc
index 6249ba8fada..fd2a7cf6ce5 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog.cc
@@ -13,33 +13,21 @@
#include "ui/shell_dialogs/select_file_dialog_factory.h"
#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/shell_dialogs/selected_file_info.h"
-#include "ui/shell_dialogs/shell_dialogs_delegate.h"
-
-#if defined(OS_WIN)
-#include "ui/shell_dialogs/select_file_dialog_win.h"
-#elif defined(OS_MACOSX)
-#include "ui/shell_dialogs/select_file_dialog_mac.h"
-#elif defined(OS_ANDROID)
-#include "ui/shell_dialogs/select_file_dialog_android.h"
-#elif defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#include "ui/shell_dialogs/linux_shell_dialog.h"
-#endif
namespace {
// Optional dialog factory. Leaked.
ui::SelectFileDialogFactory* dialog_factory_ = NULL;
-// The global shell dialogs delegate.
-ui::ShellDialogsDelegate* g_shell_dialogs_delegate_ = NULL;
-
} // namespace
namespace ui {
SelectFileDialog::FileTypeInfo::FileTypeInfo()
- : include_all_files(false),
- support_drive(false) {}
+ : include_all_files(false), allowed_paths(NATIVE_PATH) {}
+
+SelectFileDialog::FileTypeInfo::FileTypeInfo(const FileTypeInfo& other) =
+ default;
SelectFileDialog::FileTypeInfo::~FileTypeInfo() {}
@@ -81,24 +69,7 @@ scoped_refptr<SelectFileDialog> SelectFileDialog::Create(
return dialog;
}
-#if defined(USE_AURA) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
- const ui::LinuxShellDialog* shell_dialogs = ui::LinuxShellDialog::instance();
- if (shell_dialogs)
- return shell_dialogs->CreateSelectFileDialog(listener, policy);
-#endif
-
-#if defined(OS_WIN)
- // TODO(ananta)
- // Fix this for Chrome ASH on Windows.
- return CreateDefaultWinSelectFileDialog(listener, policy);
-#elif defined(OS_MACOSX) && !defined(USE_AURA)
- return CreateMacSelectFileDialog(listener, policy);
-#elif defined(OS_ANDROID)
- return CreateAndroidSelectFileDialog(listener, policy);
-#else
- NOTIMPLEMENTED();
- return NULL;
-#endif
+ return CreateSelectFileDialog(listener, policy);
}
void SelectFileDialog::SelectFile(
@@ -134,11 +105,6 @@ bool SelectFileDialog::HasMultipleFileTypeChoices() {
return HasMultipleFileTypeChoicesImpl();
}
-// static
-void SelectFileDialog::SetShellDialogsDelegate(ShellDialogsDelegate* delegate) {
- g_shell_dialogs_delegate_ = delegate;
-}
-
SelectFileDialog::SelectFileDialog(Listener* listener,
ui::SelectFilePolicy* policy)
: listener_(listener),
@@ -153,8 +119,4 @@ void SelectFileDialog::CancelFileSelection(void* params) {
listener_->FileSelectionCanceled(params);
}
-ShellDialogsDelegate* SelectFileDialog::GetShellDialogsDelegate() {
- return g_shell_dialogs_delegate_;
-}
-
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog.h b/chromium/ui/shell_dialogs/select_file_dialog.h
index bd610f59654..e89f686ceca 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog.h
@@ -109,6 +109,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
// Holds information about allowed extensions on a file save dialog.
struct SHELL_DIALOGS_EXPORT FileTypeInfo {
FileTypeInfo();
+ FileTypeInfo(const FileTypeInfo& other);
~FileTypeInfo();
// A list of allowed extensions. For example, it might be
@@ -127,12 +128,12 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
// Specifies whether there will be a filter added for all files (i.e. *.*).
bool include_all_files;
- // Specifies whether the caller can directly support file paths pointing to
- // files/folders on Google Drive. If the flag is true, the file dialog does
- // nothing special; just returns a Drive path. If it is false, the dialog
- // creates a local replica of the Drive file and returns its path, so that
- // the caller can use it without any difference than when it were local.
- bool support_drive;
+ // Specifies which type of paths the caller can handle. If it is
+ // NATIVE_PATH, the dialog creates a native replica of the non-native file
+ // and returns its path, so that the caller can use it without any
+ // difference than when it were local.
+ enum AllowedPaths { ANY_PATH, NATIVE_PATH, NATIVE_OR_DRIVE_PATH };
+ AllowedPaths allowed_paths;
};
// Selects a File.
@@ -172,9 +173,6 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
void* params);
bool HasMultipleFileTypeChoices();
- // Sets the global ShellDialogsDelegate. Defaults to NULL.
- static void SetShellDialogsDelegate(ShellDialogsDelegate* delegate);
-
protected:
friend class base::RefCountedThreadSafe<SelectFileDialog>;
explicit SelectFileDialog(Listener* listener, SelectFilePolicy* policy);
@@ -194,9 +192,6 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
gfx::NativeWindow owning_window,
void* params) = 0;
- // Returns the global ShellDialogsDelegate instance if any.
- ShellDialogsDelegate* GetShellDialogsDelegate();
-
// The listener to be notified of selection completion.
Listener* listener_;
@@ -218,6 +213,8 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
DISALLOW_COPY_AND_ASSIGN(SelectFileDialog);
};
+SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
+ SelectFilePolicy* policy);
} // namespace ui
#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.cc b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
index b0c75320a91..11b9d4c824b 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
@@ -145,9 +145,8 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
return false;
}
-SelectFileDialog* CreateAndroidSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
+SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
+ SelectFilePolicy* policy) {
return SelectFileDialogImpl::Create(listener, policy);
}
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.h b/chromium/ui/shell_dialogs/select_file_dialog_android.h
index 0dba18e483a..5291cd3c92b 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.h
@@ -65,10 +65,6 @@ class SelectFileDialogImpl : public SelectFileDialog {
DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
};
-SelectFileDialog* CreateAndroidSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy);
-
} // namespace ui
#endif // UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.cc b/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.cc
deleted file mode 100644
index 185f47ed2ca..00000000000
--- a/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "select_file_dialog_auraandroid.h"
-
-#include "base/logging.h"
-
-namespace ui {
-
-// static
-SelectFileDialogImpl* SelectFileDialogImpl::Create(Listener* listener,
- SelectFilePolicy* policy) {
- return new SelectFileDialogImpl(listener, policy);
-}
-
-bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow) const {
- return listener_;
-}
-
-void SelectFileDialogImpl::ListenerDestroyed() {
- listener_ = NULL;
-}
-
-void SelectFileDialogImpl::SelectFileImpl(
- SelectFileDialog::Type type,
- const base::string16& title,
- const base::FilePath& default_path,
- const SelectFileDialog::FileTypeInfo* file_types,
- int file_type_index,
- const std::string& default_extension,
- gfx::NativeWindow owning_window,
- void* params) {
- NOTIMPLEMENTED();
-}
-
-SelectFileDialogImpl::~SelectFileDialogImpl() {
-}
-
-SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
- SelectFilePolicy* policy)
- : SelectFileDialog(listener, policy) {
-}
-
-bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
- NOTIMPLEMENTED();
- return false;
-}
-
-SelectFileDialog* CreateAndroidSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
- return SelectFileDialogImpl::Create(listener, policy);
-}
-
-} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.h b/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.h
deleted file mode 100644
index 5b7a1630974..00000000000
--- a/chromium/ui/shell_dialogs/select_file_dialog_auraandroid.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
-#define UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
-
-#include "base/macros.h"
-#include "ui/shell_dialogs/select_file_dialog.h"
-
-namespace ui {
-
-class SelectFileDialogImpl : public SelectFileDialog {
- public:
- static SelectFileDialogImpl* Create(Listener* listener,
- SelectFilePolicy* policy);
-
- // From SelectFileDialog
- bool IsRunning(gfx::NativeWindow) const override;
- void ListenerDestroyed() override;
- void SelectFileImpl(SelectFileDialog::Type type,
- const base::string16& title,
- const base::FilePath& default_path,
- const SelectFileDialog::FileTypeInfo* file_types,
- int file_type_index,
- const std::string& default_extension,
- gfx::NativeWindow owning_window,
- void* params) override;
-
- protected:
- ~SelectFileDialogImpl() override;
-
- private:
- SelectFileDialogImpl(Listener* listener, SelectFilePolicy* policy);
-
- bool HasMultipleFileTypeChoicesImpl() override;
-
- DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
-};
-
-SelectFileDialog* CreateAndroidSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy);
-
-} // namespace ui
-
-#endif // UI_SHELL_DIALOGS_ANDROID_SELECT_FILE_DIALOG_ANDROID_H_
-
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.h b/chromium/ui/shell_dialogs/select_file_dialog_mac.h
index 8915a0854f1..b3765ef4224 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_mac.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.h
@@ -5,14 +5,100 @@
#ifndef UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_MAC_H_
#define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_MAC_H_
+#import <Cocoa/Cocoa.h>
+
+#include <map>
+#include <set>
+
+#import "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/shell_dialogs_export.h"
+
+@class ExtensionDropdownHandler;
+@class SelectFileDialogBridge;
namespace ui {
-SelectFileDialog* CreateMacSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy);
+namespace test {
+class SelectFileDialogMacTest;
+} // namespace test
+
+// Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a
+// file or folder.
+// Exported for unit tests.
+class SHELL_DIALOGS_EXPORT SelectFileDialogImpl : public ui::SelectFileDialog {
+ public:
+ SelectFileDialogImpl(Listener* listener, ui::SelectFilePolicy* policy);
+
+ // BaseShellDialog implementation.
+ bool IsRunning(gfx::NativeWindow parent_window) const override;
+ void ListenerDestroyed() override;
+
+ // Callback from ObjC bridge.
+ void FileWasSelected(NSSavePanel* dialog,
+ NSWindow* parent_window,
+ bool was_cancelled,
+ bool is_multi,
+ const std::vector<base::FilePath>& files,
+ int index);
+
+ protected:
+ // SelectFileDialog implementation.
+ // |params| is user data we pass back via the Listener interface.
+ void SelectFileImpl(Type type,
+ const base::string16& title,
+ const base::FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const base::FilePath::StringType& default_extension,
+ gfx::NativeWindow owning_window,
+ void* params) override;
+
+ private:
+ friend class test::SelectFileDialogMacTest;
+
+ // Struct to store data associated with a file dialog while it is showing.
+ struct DialogData {
+ DialogData(void* params_,
+ base::scoped_nsobject<ExtensionDropdownHandler> handler);
+ DialogData(const DialogData& other);
+
+ // |params| user data associated with this file dialog.
+ void* params;
+
+ // Extension dropdown handler corresponding to this file dialog.
+ base::scoped_nsobject<ExtensionDropdownHandler> extension_dropdown_handler;
+
+ ~DialogData();
+ };
+
+ ~SelectFileDialogImpl() override;
+
+ // Sets the accessory view for the |dialog| and returns the associated
+ // ExtensionDropdownHandler.
+ static base::scoped_nsobject<ExtensionDropdownHandler> SetAccessoryView(
+ NSSavePanel* dialog,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const base::FilePath::StringType& default_extension);
+
+ bool HasMultipleFileTypeChoicesImpl() override;
+
+ // The bridge for results from Cocoa to return to us.
+ base::scoped_nsobject<SelectFileDialogBridge> bridge_;
+
+ // The set of all parent windows for which we are currently running dialogs.
+ std::set<NSWindow*> parents_;
+
+ // A map from file dialogs to the DialogData associated with them.
+ std::map<NSSavePanel*, DialogData> dialog_data_map_;
+
+ bool hasMultipleFileTypeChoices_;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
+};
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
index 6fe6a62946a..1ac81223630 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
+++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -2,14 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/select_file_dialog_mac.h"
-#import <Cocoa/Cocoa.h>
#include <CoreServices/CoreServices.h>
#include <stddef.h>
-#include <map>
-#include <set>
#include <vector>
#include "base/files/file_util.h"
@@ -18,8 +15,6 @@
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_cftyperef.h"
-#import "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
@@ -55,16 +50,14 @@ NSString* GetDescriptionFromExtension(const base::FilePath::StringType& ext) {
} // namespace
-class SelectFileDialogImpl;
-
// A bridge class to act as the modal delegate to the save/open sheet and send
// the results to the C++ class.
@interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> {
@private
- SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us
+ ui::SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us
}
-- (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s;
+- (id)initWithSelectFileDialogImpl:(ui::SelectFileDialogImpl*)s;
- (void)endedPanel:(NSSavePanel*)panel
didCancel:(bool)did_cancel
type:(ui::SelectFileDialog::Type)type
@@ -92,76 +85,7 @@ class SelectFileDialogImpl;
- (void)popupAction:(id)sender;
@end
-// Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a
-// file or folder.
-class SelectFileDialogImpl : public ui::SelectFileDialog {
- public:
- explicit SelectFileDialogImpl(Listener* listener,
- ui::SelectFilePolicy* policy);
-
- // BaseShellDialog implementation.
- bool IsRunning(gfx::NativeWindow parent_window) const override;
- void ListenerDestroyed() override;
-
- // Callback from ObjC bridge.
- void FileWasSelected(NSSavePanel* dialog,
- NSWindow* parent_window,
- bool was_cancelled,
- bool is_multi,
- const std::vector<base::FilePath>& files,
- int index);
-
- protected:
- // SelectFileDialog implementation.
- // |params| is user data we pass back via the Listener interface.
- void SelectFileImpl(Type type,
- const base::string16& title,
- const base::FilePath& default_path,
- const FileTypeInfo* file_types,
- int file_type_index,
- const base::FilePath::StringType& default_extension,
- gfx::NativeWindow owning_window,
- void* params) override;
-
- private:
- // Struct to store data associated with a file dialog while it is showing.
- struct DialogData {
- DialogData(void* params_,
- base::scoped_nsobject<ExtensionDropdownHandler> handler)
- : params(params_), extension_dropdown_handler(handler) {}
-
- // |params| user data associated with this file dialog.
- void* params;
-
- // Extension dropdown handler corresponding to this file dialog.
- base::scoped_nsobject<ExtensionDropdownHandler> extension_dropdown_handler;
- };
-
- ~SelectFileDialogImpl() override;
-
- // Sets the accessory view for the |dialog| and returns the associated
- // ExtensionDropdownHandler.
- static base::scoped_nsobject<ExtensionDropdownHandler> SetAccessoryView(
- NSSavePanel* dialog,
- const FileTypeInfo* file_types,
- int file_type_index,
- const base::FilePath::StringType& default_extension);
-
- bool HasMultipleFileTypeChoicesImpl() override;
-
- // The bridge for results from Cocoa to return to us.
- base::scoped_nsobject<SelectFileDialogBridge> bridge_;
-
- // The set of all parent windows for which we are currently running dialogs.
- std::set<NSWindow*> parents_;
-
- // A map from file dialogs to the DialogData associated with them.
- std::map<NSSavePanel*, DialogData> dialog_data_map_;
-
- bool hasMultipleFileTypeChoices_;
-
- DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
-};
+namespace ui {
SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
ui::SelectFilePolicy* policy)
@@ -319,6 +243,15 @@ void SelectFileDialogImpl::SelectFileImpl(
}];
}
+SelectFileDialogImpl::DialogData::DialogData(
+ void* params_,
+ base::scoped_nsobject<ExtensionDropdownHandler> handler)
+ : params(params_), extension_dropdown_handler(handler) {}
+
+SelectFileDialogImpl::DialogData::DialogData(const DialogData& other) = default;
+
+SelectFileDialogImpl::DialogData::~DialogData() {}
+
SelectFileDialogImpl::~SelectFileDialogImpl() {
// Walk through the open dialogs and close them all. Use a temporary vector
// to hold the pointers, since we can't delete from the map as we're iterating
@@ -350,6 +283,7 @@ SelectFileDialogImpl::SetAccessoryView(
// Create an array with each item corresponding to an array of different
// extensions in an extension group.
NSMutableArray* file_type_lists = [NSMutableArray array];
+ int default_extension_index = -1;
for (size_t i = 0; i < file_types->extensions.size(); ++i) {
const std::vector<base::FilePath::StringType>& ext_list =
file_types->extensions[i];
@@ -373,6 +307,9 @@ SelectFileDialogImpl::SetAccessoryView(
// Set to store different extensions in the current extension group.
NSMutableSet* file_type_set = [NSMutableSet set];
for (const base::FilePath::StringType& ext : ext_list) {
+ if (ext == default_extension)
+ default_extension_index = i;
+
base::ScopedCFTypeRef<CFStringRef> uti(CreateUTIFromExtension(ext));
[file_type_set addObject:base::mac::CFToNSCast(uti.get())];
@@ -401,14 +338,21 @@ SelectFileDialogImpl::SetAccessoryView(
[popup setTarget:handler];
[popup setAction:@selector(popupAction:)];
- if (default_extension.empty()) {
- // Select the first item.
- [popup selectItemAtIndex:0];
+ // file_type_index uses 1 based indexing.
+ if (file_type_index) {
+ DCHECK_LE(static_cast<size_t>(file_type_index),
+ file_types->extensions.size());
+ DCHECK_GE(file_type_index, 1);
+ [popup selectItemAtIndex:file_type_index - 1];
[handler popupAction:popup];
- } else {
- [popup selectItemAtIndex:-1];
+ } else if (!default_extension.empty() && default_extension_index != -1) {
+ [popup selectItemAtIndex:default_extension_index];
[dialog
setAllowedFileTypes:@[ base::SysUTF8ToNSString(default_extension) ]];
+ } else {
+ // Select the first item.
+ [popup selectItemAtIndex:0];
+ [handler popupAction:popup];
}
return handler;
@@ -418,9 +362,16 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
return hasMultipleFileTypeChoices_;
}
+SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
+ SelectFilePolicy* policy) {
+ return new SelectFileDialogImpl(listener, policy);
+}
+
+} // namespace ui
+
@implementation SelectFileDialogBridge
-- (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s {
+- (id)initWithSelectFileDialogImpl:(ui::SelectFileDialogImpl*)s {
if ((self = [super init])) {
selectFileDialogImpl_ = s;
}
@@ -498,13 +449,3 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
}
@end
-
-namespace ui {
-
-SelectFileDialog* CreateMacSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
- return new SelectFileDialogImpl(listener, policy);
-}
-
-} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm b/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
new file mode 100644
index 00000000000..a9ad635e1a1
--- /dev/null
+++ b/chromium/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
@@ -0,0 +1,470 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/shell_dialogs/select_file_dialog_mac.h"
+
+#include <vector>
+
+#import "base/mac/foundation_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define EXPECT_EQ_BOOL(a, b) \
+ EXPECT_EQ(static_cast<bool>(a), static_cast<bool>(b))
+
+namespace {
+const int kFileTypePopupTag = 1234;
+
+// Returns a vector containing extension descriptions for a given popup.
+std::vector<base::string16> GetExtensionDescriptionList(NSPopUpButton* popup) {
+ std::vector<base::string16> extension_descriptions;
+ for (NSString* description in [popup itemTitles])
+ extension_descriptions.push_back(base::SysNSStringToUTF16(description));
+ return extension_descriptions;
+}
+
+// Fake user event to select the item at the given |index| from the extension
+// dropdown popup.
+void SelectItemAtIndex(NSPopUpButton* popup, int index) {
+ [[popup menu] performActionForItemAtIndex:index];
+}
+
+// Returns the NSPopupButton associated with the given |panel|.
+NSPopUpButton* GetPopup(NSSavePanel* panel) {
+ return [[panel accessoryView] viewWithTag:kFileTypePopupTag];
+}
+
+// Helper method to convert an array to a vector.
+template <typename T, size_t N>
+std::vector<T> GetVectorFromArray(const T (&data)[N]) {
+ return std::vector<T>(data, data + N);
+}
+
+// Helper struct to hold arguments for the call to
+// SelectFileDialogImpl::SelectFileImpl.
+struct FileDialogArguments {
+ ui::SelectFileDialog::Type type;
+ base::string16 title;
+ base::FilePath default_path;
+ ui::SelectFileDialog::FileTypeInfo* file_types;
+ int file_type_index;
+ base::FilePath::StringType default_extension;
+ gfx::NativeWindow owning_window;
+ void* params;
+};
+
+// Helper method to return a FileDialogArguments struct initialized with
+// appropriate default values.
+FileDialogArguments GetDefaultArguments() {
+ return {ui::SelectFileDialog::SELECT_SAVEAS_FILE,
+ base::ASCIIToUTF16(""),
+ base::FilePath(),
+ nullptr,
+ 0,
+ "",
+ nullptr,
+ nullptr};
+}
+
+} // namespace
+
+namespace ui {
+namespace test {
+
+// Helper test base to initialize SelectFileDialogImpl.
+class SelectFileDialogMacTest : public testing::Test,
+ public SelectFileDialog::Listener {
+ public:
+ SelectFileDialogMacTest()
+ : dialog_(new SelectFileDialogImpl(this, nullptr)) {}
+
+ // Overridden from SelectFileDialog::Listener.
+ void FileSelected(const base::FilePath& path,
+ int index,
+ void* params) override {}
+
+ protected:
+ // Helper method to launch a dialog with the given |args|.
+ void SelectFileWithParams(FileDialogArguments args) {
+ dialog_->SelectFile(args.type, args.title, args.default_path,
+ args.file_types, args.file_type_index,
+ args.default_extension, args.owning_window,
+ args.params);
+ }
+
+ // Returns the number of panels currently active.
+ size_t GetActivePanelCount() const {
+ return dialog_->dialog_data_map_.size();
+ }
+
+ // Returns one of the created NSSavePanel. If multiple SelectFile calls were
+ // made on the same |dialog_| object, any of the created NSSavePanel will be
+ // returned.
+ NSSavePanel* GetPanel() const {
+ DCHECK_GE(GetActivePanelCount(), 1lu);
+ return dialog_->dialog_data_map_.begin()->first;
+ }
+
+ void ResetDialog() { dialog_ = new SelectFileDialogImpl(this, nullptr); }
+
+ private:
+ scoped_refptr<SelectFileDialogImpl> dialog_;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogMacTest);
+};
+
+// Verify that the extension popup has the correct description and changing the
+// popup item changes the allowed file types.
+TEST_F(SelectFileDialogMacTest, ExtensionPopup) {
+ const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}};
+ const base::string16 extension_descriptions_arr[] = {
+ base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")};
+
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[0]));
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[1]));
+ file_type_info.extension_description_overrides =
+ GetVectorFromArray<base::string16>(extension_descriptions_arr);
+ file_type_info.include_all_files = false;
+
+ FileDialogArguments args(GetDefaultArguments());
+ args.file_types = &file_type_info;
+
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+
+ NSPopUpButton* popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+
+ // Check that the dropdown list created has the correct description.
+ const std::vector<base::string16> extension_descriptions =
+ GetExtensionDescriptionList(popup);
+ EXPECT_EQ(file_type_info.extension_description_overrides,
+ extension_descriptions);
+
+ // Ensure other file types are not allowed.
+ EXPECT_FALSE([panel allowsOtherFileTypes]);
+
+ // Check that the first item was selected, since a file_type_index of 0 was
+ // passed and no default extension was provided.
+ EXPECT_EQ(0, [popup indexOfSelectedItem]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"htm"]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"html"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"jpg"]);
+
+ // Select the second item.
+ SelectItemAtIndex(popup, 1);
+ EXPECT_EQ(1, [popup indexOfSelectedItem]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"jpg"]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"jpeg"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"html"]);
+}
+
+// Verify file_type_info.include_all_files argument is respected.
+TEST_F(SelectFileDialogMacTest, IncludeAllFiles) {
+ const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}};
+ const base::string16 extension_descriptions_arr[] = {
+ base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")};
+
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[0]));
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[1]));
+ file_type_info.extension_description_overrides =
+ GetVectorFromArray<base::string16>(extension_descriptions_arr);
+ file_type_info.include_all_files = true;
+
+ FileDialogArguments args(GetDefaultArguments());
+ args.file_types = &file_type_info;
+
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+
+ NSPopUpButton* popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+
+ // Check that the dropdown list created has the correct description.
+ const std::vector<base::string16> extension_descriptions =
+ GetExtensionDescriptionList(popup);
+ EXPECT_EQ(3lu, extension_descriptions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("Webpage"), extension_descriptions[0]);
+ EXPECT_EQ(base::ASCIIToUTF16("Image"), extension_descriptions[1]);
+ EXPECT_EQ(base::ASCIIToUTF16("All Files"), extension_descriptions[2]);
+
+ // Ensure other file types are allowed.
+ EXPECT_TRUE([panel allowsOtherFileTypes]);
+
+ // Select the last item i.e. All Files.
+ SelectItemAtIndex(popup, 2);
+
+ // Ensure allowedFileTypes is set to nil, which means any file type can be
+ // used.
+ EXPECT_EQ(2, [popup indexOfSelectedItem]);
+ EXPECT_EQ(nil, [panel allowedFileTypes]);
+}
+
+// Verify that file_type_index and default_extension arguments cause the
+// appropriate extension group to be initially selected.
+TEST_F(SelectFileDialogMacTest, InitialSelection) {
+ const std::string extensions_arr[][2] = {{"html", "htm"}, {"jpeg", "jpg"}};
+ const base::string16 extension_descriptions_arr[] = {
+ base::ASCIIToUTF16("Webpage"), base::ASCIIToUTF16("Image")};
+
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[0]));
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[1]));
+ file_type_info.extension_description_overrides =
+ GetVectorFromArray<base::string16>(extension_descriptions_arr);
+
+ FileDialogArguments args = GetDefaultArguments();
+ args.file_types = &file_type_info;
+
+ args.file_type_index = 2;
+ args.default_extension = "jpg";
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+ NSPopUpButton* popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+ // Verify that the file_type_index causes the second item to be initially
+ // selected.
+ EXPECT_EQ(1, [popup indexOfSelectedItem]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"jpg"]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"jpeg"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"html"]);
+
+ ResetDialog();
+ args.file_type_index = 0;
+ args.default_extension = "pdf";
+ SelectFileWithParams(args);
+ panel = GetPanel();
+ popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+ // Verify that the first item was selected, since the default extension passed
+ // was not present in the extension list.
+ EXPECT_EQ(0, [popup indexOfSelectedItem]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"html"]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"htm"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"pdf"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"jpeg"]);
+
+ ResetDialog();
+ args.file_type_index = 0;
+ args.default_extension = "jpg";
+ SelectFileWithParams(args);
+ panel = GetPanel();
+ popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+ // Verify that the extension group corresponding to the default extension is
+ // initially selected.
+ EXPECT_EQ(1, [popup indexOfSelectedItem]);
+ // The allowed file types should just contain the default extension.
+ EXPECT_EQ(1lu, [[panel allowedFileTypes] count]);
+ EXPECT_TRUE([[panel allowedFileTypes] containsObject:@"jpg"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"jpeg"]);
+ EXPECT_FALSE([[panel allowedFileTypes] containsObject:@"html"]);
+}
+
+// Verify that an appropriate extension description is shown even if an empty
+// extension description is passed for a given extension group.
+TEST_F(SelectFileDialogMacTest, EmptyDescription) {
+ const std::string extensions_arr[][1] = {{"pdf"}, {"jpg"}, {"qqq"}};
+ const base::string16 extension_descriptions_arr[] = {
+ base::ASCIIToUTF16(""), base::ASCIIToUTF16("Image"),
+ base::ASCIIToUTF16("")};
+
+ SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[0]));
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[1]));
+ file_type_info.extensions.push_back(
+ GetVectorFromArray<std::string>(extensions_arr[2]));
+ file_type_info.extension_description_overrides =
+ GetVectorFromArray<base::string16>(extension_descriptions_arr);
+
+ FileDialogArguments args(GetDefaultArguments());
+ args.file_types = &file_type_info;
+
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+ NSPopUpButton* popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+
+ // Check that the dropdown list created has the correct description.
+ const std::vector<base::string16> extension_descriptions =
+ GetExtensionDescriptionList(popup);
+ EXPECT_EQ(3lu, extension_descriptions.size());
+ // Verify that the correct system description is produced for known file types
+ // like pdf if no extension description is provided by the client.
+ EXPECT_EQ(base::ASCIIToUTF16("Portable Document Format (PDF)"),
+ extension_descriptions[0]);
+ EXPECT_EQ(base::ASCIIToUTF16("Image"), extension_descriptions[1]);
+ // Verify the description for unknown file types if no extension description
+ // is provided by the client.
+ EXPECT_EQ(base::ASCIIToUTF16("QQQ File (.qqq)"), extension_descriptions[2]);
+}
+
+// Verify that passing an empty extension list in file_type_info causes the All
+// Files Option to display in the extension dropdown.
+TEST_F(SelectFileDialogMacTest, EmptyExtension) {
+ SelectFileDialog::FileTypeInfo file_type_info;
+
+ FileDialogArguments args(GetDefaultArguments());
+ args.file_types = &file_type_info;
+
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+ NSPopUpButton* popup = GetPopup(panel);
+ EXPECT_TRUE(popup);
+
+ const std::vector<base::string16> extension_descriptions =
+ GetExtensionDescriptionList(popup);
+ EXPECT_EQ(1lu, extension_descriptions.size());
+ EXPECT_EQ(base::ASCIIToUTF16("All Files"), extension_descriptions[0]);
+
+ // Ensure other file types are allowed.
+ EXPECT_TRUE([panel allowsOtherFileTypes]);
+}
+
+// Verify that passing a null file_types value causes no extension dropdown to
+// display.
+TEST_F(SelectFileDialogMacTest, FileTypesNull) {
+ SelectFileWithParams(GetDefaultArguments());
+ NSSavePanel* panel = GetPanel();
+ EXPECT_TRUE([panel allowsOtherFileTypes]);
+ EXPECT_FALSE([panel accessoryView]);
+}
+
+// Verify that appropriate properties are set on the NSSavePanel for different
+// dialog types.
+TEST_F(SelectFileDialogMacTest, SelectionType) {
+ SelectFileDialog::FileTypeInfo file_type_info;
+ FileDialogArguments args = GetDefaultArguments();
+ args.file_types = &file_type_info;
+
+ enum {
+ HAS_ACCESSORY_VIEW = 1,
+ PICK_FILES = 2,
+ PICK_DIRS = 4,
+ CREATE_DIRS = 8,
+ MULTIPLE_SELECTION = 16,
+ };
+
+ struct SelectionTypeTestCase {
+ SelectFileDialog::Type type;
+ unsigned options;
+ std::string prompt;
+ } test_cases[] = {
+ {SelectFileDialog::SELECT_FOLDER, PICK_DIRS | CREATE_DIRS, "Select"},
+ {SelectFileDialog::SELECT_UPLOAD_FOLDER, PICK_DIRS | CREATE_DIRS,
+ "Upload"},
+ {SelectFileDialog::SELECT_SAVEAS_FILE, HAS_ACCESSORY_VIEW | CREATE_DIRS,
+ "Save"},
+ {SelectFileDialog::SELECT_OPEN_FILE, HAS_ACCESSORY_VIEW | PICK_FILES,
+ "Open"},
+ {SelectFileDialog::SELECT_OPEN_MULTI_FILE,
+ HAS_ACCESSORY_VIEW | PICK_FILES | MULTIPLE_SELECTION, "Open"},
+ };
+
+ for (size_t i = 0; i < arraysize(test_cases); i++) {
+ SCOPED_TRACE(
+ base::StringPrintf("i=%lu file_dialog_type=%d", i, test_cases[i].type));
+ args.type = test_cases[i].type;
+ ResetDialog();
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+
+ EXPECT_EQ_BOOL(test_cases[i].options & HAS_ACCESSORY_VIEW,
+ [panel accessoryView]);
+ EXPECT_EQ_BOOL(test_cases[i].options & CREATE_DIRS,
+ [panel canCreateDirectories]);
+ EXPECT_EQ(test_cases[i].prompt, base::SysNSStringToUTF8([panel prompt]));
+
+ if (args.type != SelectFileDialog::SELECT_SAVEAS_FILE) {
+ NSOpenPanel* open_panel = base::mac::ObjCCast<NSOpenPanel>(panel);
+ // Verify that for types other than save file dialogs, an NSOpenPanel is
+ // created.
+ EXPECT_TRUE(open_panel);
+ EXPECT_EQ_BOOL(test_cases[i].options & PICK_FILES,
+ [open_panel canChooseFiles]);
+ EXPECT_EQ_BOOL(test_cases[i].options & PICK_DIRS,
+ [open_panel canChooseDirectories]);
+ EXPECT_EQ_BOOL(test_cases[i].options & MULTIPLE_SELECTION,
+ [open_panel allowsMultipleSelection]);
+ }
+ }
+}
+
+// Verify that the correct message is set on the NSSavePanel.
+TEST_F(SelectFileDialogMacTest, DialogMessage) {
+ const std::string test_title = "test title";
+ FileDialogArguments args = GetDefaultArguments();
+ args.title = base::ASCIIToUTF16(test_title);
+ SelectFileWithParams(args);
+ EXPECT_EQ(test_title, base::SysNSStringToUTF8([GetPanel() message]));
+}
+
+// Verify that multiple file dialogs are corrected handled.
+TEST_F(SelectFileDialogMacTest, MultipleDialogs) {
+ FileDialogArguments args(GetDefaultArguments());
+ SelectFileWithParams(args);
+ SelectFileWithParams(args);
+ EXPECT_EQ(2lu, GetActivePanelCount());
+
+ // Verify closing the panel decreases the panel count.
+ NSSavePanel* panel = GetPanel();
+ [panel cancel:panel];
+ EXPECT_EQ(1lu, GetActivePanelCount());
+
+ panel = GetPanel();
+ [panel ok:panel];
+ EXPECT_EQ(0lu, GetActivePanelCount());
+}
+
+// Verify that the default_path argument is respected.
+TEST_F(SelectFileDialogMacTest, DefaultPath) {
+ const std::string fake_path = "/fake_directory/filename.txt";
+ FileDialogArguments args(GetDefaultArguments());
+ args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path));
+
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+
+ EXPECT_EQ(args.default_path.DirName(),
+ base::mac::NSStringToFilePath([[panel directoryURL] path]));
+ EXPECT_EQ(args.default_path.BaseName(),
+ base::mac::NSStringToFilePath([panel nameFieldStringValue]));
+}
+
+// Verify that the file dialog does not hide extension for filenames with
+// multiple extensions.
+TEST_F(SelectFileDialogMacTest, MultipleExtension) {
+ const std::string fake_path_normal = "/fake_directory/filename.tar";
+ const std::string fake_path_multiple = "/fake_directory/filename.tar.gz";
+ FileDialogArguments args(GetDefaultArguments());
+
+ args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path_normal));
+ SelectFileWithParams(args);
+ NSSavePanel* panel = GetPanel();
+ EXPECT_TRUE([panel canSelectHiddenExtension]);
+
+ ResetDialog();
+ args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path_multiple));
+ SelectFileWithParams(args);
+ panel = GetPanel();
+ EXPECT_FALSE([panel canSelectHiddenExtension]);
+ EXPECT_FALSE([panel isExtensionHidden]);
+}
+
+} // namespace test
+} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
index 40215a344fe..d455f59c5ce 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <set>
+#include <tuple>
#include "base/bind.h"
#include "base/files/file_path.h"
@@ -17,7 +18,6 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
-#include "base/tuple.h"
#include "base/win/registry.h"
#include "base/win/scoped_comptr.h"
#include "base/win/shortcut.h"
@@ -28,9 +28,7 @@
#include "ui/base/win/open_file_name_win.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/base_shell_dialog_win.h"
-#include "ui/shell_dialogs/shell_dialogs_delegate.h"
#include "ui/strings/grit/ui_strings.h"
-#include "win8/viewer/metro_viewer_process_host.h"
namespace {
@@ -328,59 +326,6 @@ void SelectFileDialogImpl::SelectFileImpl(
void* params) {
has_multiple_file_type_choices_ =
file_types ? file_types->extensions.size() > 1 : true;
- // If the owning_window passed in is in metro then we need to forward the
- // file open/save operations to metro.
- if (GetShellDialogsDelegate() &&
- GetShellDialogsDelegate()->IsWindowInMetro(owning_window)) {
- if (type == SELECT_SAVEAS_FILE) {
- win8::MetroViewerProcessHost::HandleSaveFile(
- title,
- default_path,
- GetFilterForFileTypes(file_types),
- file_type_index,
- default_extension,
- base::Bind(&ui::SelectFileDialog::Listener::FileSelected,
- base::Unretained(listener_)),
- base::Bind(&ui::SelectFileDialog::Listener::FileSelectionCanceled,
- base::Unretained(listener_)));
- return;
- } else if (type == SELECT_OPEN_FILE) {
- win8::MetroViewerProcessHost::HandleOpenFile(
- title,
- default_path,
- GetFilterForFileTypes(file_types),
- base::Bind(&ui::SelectFileDialog::Listener::FileSelected,
- base::Unretained(listener_)),
- base::Bind(&ui::SelectFileDialog::Listener::FileSelectionCanceled,
- base::Unretained(listener_)));
- return;
- } else if (type == SELECT_OPEN_MULTI_FILE) {
- win8::MetroViewerProcessHost::HandleOpenMultipleFiles(
- title,
- default_path,
- GetFilterForFileTypes(file_types),
- base::Bind(&ui::SelectFileDialog::Listener::MultiFilesSelected,
- base::Unretained(listener_)),
- base::Bind(&ui::SelectFileDialog::Listener::FileSelectionCanceled,
- base::Unretained(listener_)));
- return;
- } else if (type == SELECT_FOLDER || type == SELECT_UPLOAD_FOLDER) {
- base::string16 title_string = title;
- if (type == SELECT_UPLOAD_FOLDER && title_string.empty()) {
- // If it's for uploading don't use default dialog title to
- // make sure we clearly tell it's for uploading.
- title_string = l10n_util::GetStringUTF16(
- IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE);
- }
- win8::MetroViewerProcessHost::HandleSelectFolder(
- title_string,
- base::Bind(&ui::SelectFileDialog::Listener::FileSelected,
- base::Unretained(listener_)),
- base::Bind(&ui::SelectFileDialog::Listener::FileSelectionCanceled,
- base::Unretained(listener_)));
- return;
- }
- }
HWND owner = owning_window && owning_window->GetRootWindow()
? owning_window->GetHost()->GetAcceleratedWidget() : NULL;
@@ -512,12 +457,12 @@ bool SelectFileDialogImpl::SaveFileAsWithFilter(
// Figure out what filter got selected. The filter index is 1-based.
std::wstring filter_selected;
if (*index > 0) {
- std::vector<base::Tuple<base::string16, base::string16>> filters =
+ std::vector<std::tuple<base::string16, base::string16>> filters =
ui::win::OpenFileName::GetFilters(save_as.GetOPENFILENAME());
if (*index > filters.size())
NOTREACHED() << "Invalid filter index.";
else
- filter_selected = base::get<1>(filters[*index - 1]);
+ filter_selected = std::get<1>(filters[*index - 1]);
}
// Get the extension that was suggested to the user (when the Save As dialog
@@ -739,7 +684,7 @@ std::wstring AppendExtensionIfNeeded(
if (!(filter_selected.empty() || filter_selected == L"*.*") &&
!base::win::RegKey(HKEY_CLASSES_ROOT, key.c_str(), KEY_READ).Valid() &&
file_extension != suggested_ext) {
- if (return_value[return_value.length() - 1] != L'.')
+ if (return_value.back() != L'.')
return_value.append(L".");
return_value.append(suggested_ext);
}
@@ -761,9 +706,8 @@ SelectFileDialog* CreateWinSelectFileDialog(
listener, policy, get_open_file_name_impl, get_save_file_name_impl);
}
-SelectFileDialog* CreateDefaultWinSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
+SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
+ SelectFilePolicy* policy) {
return CreateWinSelectFileDialog(listener,
policy,
base::Bind(&CallBuiltinGetOpenFileName),
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.h b/chromium/ui/shell_dialogs/select_file_dialog_win.h
index 646bdb12b84..e066c65f1d3 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.h
@@ -28,10 +28,6 @@ SHELL_DIALOGS_EXPORT SelectFileDialog* CreateWinSelectFileDialog(
const base::Callback<bool(OPENFILENAME* ofn)>& get_open_file_name_impl,
const base::Callback<bool(OPENFILENAME* ofn)>& get_save_file_name_impl);
-SelectFileDialog* CreateDefaultWinSelectFileDialog(
- SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy);
-
} // namespace ui
#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_WIN_H_
diff --git a/chromium/ui/shell_dialogs/shell_dialog_linux.cc b/chromium/ui/shell_dialogs/shell_dialog_linux.cc
new file mode 100644
index 00000000000..685369c2baa
--- /dev/null
+++ b/chromium/ui/shell_dialogs/shell_dialog_linux.cc
@@ -0,0 +1,34 @@
+// 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/shell_dialogs/shell_dialog_linux.h"
+
+namespace {
+
+ui::ShellDialogLinux* g_shell_dialog_linux = nullptr;
+
+} // namespace
+
+namespace ui {
+
+void ShellDialogLinux::SetInstance(ShellDialogLinux* instance) {
+ g_shell_dialog_linux = instance;
+}
+
+const ShellDialogLinux* ShellDialogLinux::instance() {
+ return g_shell_dialog_linux;
+}
+
+SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
+ SelectFilePolicy* policy) {
+#if defined(USE_AURA) && !defined(OS_CHROMEOS)
+ const ui::ShellDialogLinux* shell_dialogs = ui::ShellDialogLinux::instance();
+ if (shell_dialogs)
+ return shell_dialogs->CreateSelectFileDialog(listener, policy);
+#endif
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/shell_dialogs/linux_shell_dialog.h b/chromium/ui/shell_dialogs/shell_dialog_linux.h
index a503b78ebdd..1dad34d15b5 100644
--- a/chromium/ui/shell_dialogs/linux_shell_dialog.h
+++ b/chromium/ui/shell_dialogs/shell_dialog_linux.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_SHELL_DIALOGS_LINUX_SHELL_DIALOG_H_
-#define UI_SHELL_DIALOGS_LINUX_SHELL_DIALOG_H_
+#ifndef UI_SHELL_DIALOGS_SHELL_DIALOG_LINUX_H_
+#define UI_SHELL_DIALOGS_SHELL_DIALOG_LINUX_H_
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/shell_dialogs_export.h"
@@ -12,21 +12,21 @@ namespace ui {
// An interface that lets different Linux platforms override the
// CreateSelectFileDialog function declared here to return native file dialogs.
-class SHELL_DIALOGS_EXPORT LinuxShellDialog {
+class SHELL_DIALOGS_EXPORT ShellDialogLinux {
public:
- virtual ~LinuxShellDialog() {}
+ virtual ~ShellDialogLinux() {}
// Sets the dynamically loaded singleton that draws the desktop native
// UI. This pointer is not owned, and if this method is called a second time,
// the first instance is not deleted.
- static void SetInstance(LinuxShellDialog* instance);
+ static void SetInstance(ShellDialogLinux* instance);
// Returns a LinuxUI instance for the toolkit used in the user's desktop
// environment.
//
// Can return NULL, in case no toolkit has been set. (For example, if we're
// running with the "--ash" flag.)
- static const LinuxShellDialog* instance();
+ static const ShellDialogLinux* instance();
// Returns a native file selection dialog.
virtual SelectFileDialog* CreateSelectFileDialog(
@@ -36,5 +36,4 @@ class SHELL_DIALOGS_EXPORT LinuxShellDialog {
} // namespace ui
-#endif // UI_SHELL_DIALOGS_LINUX_SHELL_DIALOG_H_
-
+#endif // UI_SHELL_DIALOGS_SHELL_DIALOG_LINUX_H_
diff --git a/chromium/ui/shell_dialogs/shell_dialogs.gyp b/chromium/ui/shell_dialogs/shell_dialogs.gyp
index 0d541fc88e1..8bf623659fe 100644
--- a/chromium/ui/shell_dialogs/shell_dialogs.gyp
+++ b/chromium/ui/shell_dialogs/shell_dialogs.gyp
@@ -29,8 +29,6 @@
'base_shell_dialog.h',
'base_shell_dialog_win.cc',
'base_shell_dialog_win.h',
- 'linux_shell_dialog.cc',
- 'linux_shell_dialog.h',
'select_file_dialog.cc',
'select_file_dialog.h',
'select_file_dialog_android.cc',
@@ -45,6 +43,8 @@
'select_file_policy.h',
'selected_file_info.cc',
'selected_file_info.h',
+ 'shell_dialog_linux.cc',
+ 'shell_dialog_linux.h',
],
'conditions': [
['use_aura==1',
@@ -74,13 +74,6 @@
},
}
],
- ['OS=="win"',
- {
- 'dependencies': [
- '../../win8/win8.gyp:metro_viewer',
- ],
- }
- ],
],
}, # target_name: shell_dialogs
{
@@ -90,14 +83,34 @@
'dependencies': [
'../../base/base.gyp:base',
'../../base/base.gyp:test_support_base',
- '../../base/base.gyp:run_all_unittests',
'../../testing/gtest.gyp:gtest',
+ '../base/ui_base.gyp:ui_base',
'shell_dialogs',
],
'sources': [
# Note: file list duplicated in GN build.
+ 'run_all_unittests.cc',
+ 'select_file_dialog_mac_unittest.mm',
'select_file_dialog_win_unittest.cc',
],
+ 'conditions' : [
+ ['OS=="mac"',
+ {
+ 'mac_bundle': 1,
+ 'mac_bundle_resources' : [
+ '../../chrome/app/nibs/SaveAccessoryView.xib',
+ # The unittest expects a locale.pak file to exist in the bundle
+ # for English-US. Copy it in from where it was generated by
+ # ui_resources.gyp:ui_test_pak.
+ '<(PRODUCT_DIR)/ui/en.lproj/locale.pak',
+ ],
+ 'dependencies': [
+ # Needed to generate locale.pak.
+ '../resources/ui_resources.gyp:ui_test_pak',
+ ],
+ }
+ ],
+ ],
},
],
}
diff --git a/chromium/ui/shell_dialogs/shell_dialogs_delegate.h b/chromium/ui/shell_dialogs/shell_dialogs_delegate.h
deleted file mode 100644
index ca2c57cf2dc..00000000000
--- a/chromium/ui/shell_dialogs/shell_dialogs_delegate.h
+++ /dev/null
@@ -1,24 +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_SHELL_DIALOGS_SELECT_FILE_DIALOG_DELEGATE_H_
-#define UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_DELEGATE_H_
-
-#include "ui/gfx/native_widget_types.h"
-#include "ui/shell_dialogs/shell_dialogs_export.h"
-
-namespace ui {
-
-class SHELL_DIALOGS_EXPORT ShellDialogsDelegate {
- public:
- virtual ~ShellDialogsDelegate() {}
-
- // Returns true if the window passed in is in the Windows 8 metro
- // environment.
- virtual bool IsWindowInMetro(gfx::NativeWindow window) = 0;
-};
-
-} // namespace ui
-
-#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_DELEGATE_H_
diff --git a/chromium/ui/snapshot/BUILD.gn b/chromium/ui/snapshot/BUILD.gn
index c79a70b3aa8..dda02bc3a4f 100644
--- a/chromium/ui/snapshot/BUILD.gn
+++ b/chromium/ui/snapshot/BUILD.gn
@@ -70,7 +70,6 @@ test("snapshot_unittests") {
deps = [
":snapshot",
"//base",
- "//base/allocator",
"//base/test:test_support",
"//skia",
"//testing/gtest",
diff --git a/chromium/ui/snapshot/snapshot.gyp b/chromium/ui/snapshot/snapshot.gyp
index ab78afe8aaa..340668c5c48 100644
--- a/chromium/ui/snapshot/snapshot.gyp
+++ b/chromium/ui/snapshot/snapshot.gyp
@@ -90,12 +90,6 @@
'../wm/wm.gyp:wm',
],
}],
- # See http://crbug.com/162998#c4 for why this is needed.
- ['OS=="linux" and use_allocator!="none"', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
],
},
],
diff --git a/chromium/ui/snapshot/snapshot_android.cc b/chromium/ui/snapshot/snapshot_android.cc
index 0a123b9f2dc..fb7d40d47a6 100644
--- a/chromium/ui/snapshot/snapshot_android.cc
+++ b/chromium/ui/snapshot/snapshot_android.cc
@@ -41,8 +41,7 @@ static void MakeAsyncCopyRequest(
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateBitmapRequest(callback);
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ const gfx::Display& display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
float device_scale_factor = display.device_scale_factor();
gfx::Rect source_rect_in_pixel =
gfx::ScaleToEnclosingRect(source_rect, device_scale_factor);
diff --git a/chromium/ui/snapshot/snapshot_mac.mm b/chromium/ui/snapshot/snapshot_mac.mm
index d1eb698b693..9761cb7f508 100644
--- a/chromium/ui/snapshot/snapshot_mac.mm
+++ b/chromium/ui/snapshot/snapshot_mac.mm
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/mac/sdk_forward_declarations.h"
#include "base/task_runner.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
@@ -26,7 +27,7 @@ bool GrabViewSnapshot(gfx::NativeView view,
// Get the view bounds relative to the screen
NSRect frame = [view convertRect:[view bounds] toView:nil];
- frame.origin = [window convertBaseToScreen:frame.origin];
+ frame = [window convertRectToScreen:frame];
gfx::Rect view_bounds = gfx::Rect(NSRectToCGRect(frame));
diff --git a/chromium/ui/strings/translations/ui_strings_bn.xtb b/chromium/ui/strings/translations/ui_strings_bn.xtb
index ba863f32c65..edb68ba36cb 100644
--- a/chromium/ui/strings/translations/ui_strings_bn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_bn.xtb
@@ -15,7 +15,7 @@
<translation id="1781701194097416995">শব্দকে বামদিকে সরান</translation>
<translation id="1801827354178857021">পূর্ণচ্ছেদ</translation>
<translation id="1809410197924942083"><ph name="QUANTITY" /> MB/s</translation>
-<translation id="1830179671306812954">{HOURS,plural, =1{১ ঘন্টা এবং }one{# ঘন্টা এবং }other{# ঘন্টা এবং }}</translation>
+<translation id="1830179671306812954">{HOURS,plural, =1{১ ঘণ্টা এবং }one{# ঘণ্টা এবং }other{# ঘণ্টা এবং }}</translation>
<translation id="1860796786778352021">বিজ্ঞপ্তি বন্ধ করা হয়েছে</translation>
<translation id="1871244248791675517">Ins</translation>
<translation id="1901303067676059328">&amp;সকল নির্বাচন করুন</translation>
@@ -32,7 +32,7 @@
<translation id="2557207087669398617">লাইনের শুরু পর্যন্ত সরান</translation>
<translation id="2666092431469916601">শীর্ষ</translation>
<translation id="2704295676501803339">বামদিকে সরান</translation>
-<translation id="2743387203779672305">ক্লিপবোর্ডে অনুলিপি করুন</translation>
+<translation id="2743387203779672305">ক্লিপবোর্ডে কপি করুন</translation>
<translation id="2803313416453193357">ফোল্ডার খুলুন</translation>
<translation id="2983818520079887040">সেটিংস...</translation>
<translation id="3036649622769666520">খোলা ফাইল</translation>
@@ -78,7 +78,7 @@
<translation id="5768079895599174203">{DAYS,plural, =1{১ দিন এবং }one{# দিন এবং }other{# দিন এবং }}</translation>
<translation id="5906667377645263094">{SECONDS,plural, =1{১ সেকেন্ড বাকি}one{# সেকেন্ড বাকি}other{# সেকেন্ড বাকি}}</translation>
<translation id="5941711191222866238">ছোট করুন</translation>
-<translation id="5943826764092288734">{HOURS,plural, =1{১ ঘণ্টা}one{# ঘন্টা}other{# ঘন্টা}}</translation>
+<translation id="5943826764092288734">{HOURS,plural, =1{১ ঘণ্টা}one{# ঘণ্টা}other{# ঘণ্টা}}</translation>
<translation id="5948410903763073882">Alt+<ph name="KEY_COMBO_NAME" /></translation>
<translation id="598033046487663418">সমস্ত অ্যাপ্লিকেশান</translation>
<translation id="6040143037577758943">বন্ধ</translation>
@@ -98,7 +98,7 @@
<translation id="6808150112686056157">মিডিয়া থামান</translation>
<translation id="6829324100069873704">বিজ্ঞপ্তিগুলিতে ফিরে যান</translation>
<translation id="6845383723252244143">ফোল্ডার নির্বাচন করুন</translation>
-<translation id="6863590663815976734">{HOURS,plural, =1{১ ঘন্টা বাকি}one{# ঘন্টা বাকি}other{# ঘন্টা বাকি}}</translation>
+<translation id="6863590663815976734">{HOURS,plural, =1{১ ঘণ্টা বাকি}one{# ঘণ্টা বাকি}other{# ঘণ্টা বাকি}}</translation>
<translation id="688711909580084195">শিরোনামহীন ওয়েবপৃষ্ঠা</translation>
<translation id="6903282483217634857">ডানদিকে সরান</translation>
<translation id="6907759265145635167"><ph name="QUANTITY" /> PB/s</translation>
@@ -121,7 +121,7 @@
<translation id="7850320739366109486">বিরক্ত করবেন না</translation>
<translation id="7907591526440419938">খোলা ফাইল</translation>
<translation id="7960078400008666149">এক ঘন্টার জন্য বিরক্ত করবেন না</translation>
-<translation id="8106081041558092062">{HOURS,plural, =1{১ ঘন্টা পূর্বে}one{# ঘন্টা পূর্বে}other{# ঘন্টা পূর্বে}}</translation>
+<translation id="8106081041558092062">{HOURS,plural, =1{১ ঘণ্টা পূর্বে}one{# ঘণ্টা পূর্বে}other{# ঘণ্টা পূর্বে}}</translation>
<translation id="8131263257437993507">{SECONDS,plural, =1{১ সেকেন্ড বাকি}one{# সেকেন্ড বাকি}other{# সেকেন্ড বাকি}}</translation>
<translation id="815598010540052116">নীচে স্ক্রোল করুন</translation>
<translation id="8179976553408161302">Enter</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
index 075fdbb88aa..4bbe7193bf6 100644
--- a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
+++ b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
@@ -144,6 +144,6 @@
<translation id="9044832324875206639">{SECONDS,plural, =1{1 秒}other{# 秒}}</translation>
<translation id="9170848237812810038">撤消(&amp;U)</translation>
<translation id="928465423150706909">移至行末</translation>
-<translation id="932327136139879170">家庭</translation>
+<translation id="932327136139879170">首页</translation>
<translation id="945522503751344254">发送反馈</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/ui/strings/ui_strings.grd b/chromium/ui/strings/ui_strings.grd
index 5e159dd6f5c..59487442d94 100644
--- a/chromium/ui/strings/ui_strings.grd
+++ b/chromium/ui/strings/ui_strings.grd
@@ -9,7 +9,8 @@ need to be translated for each locale.-->
<outputs>
<!-- TODO add each of your output files. Modify the three below, and add
your own for your various languages. See the user's guide
- (http://wiki/Main/GritUsersGuide) for more details.
+ (https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide)
+ for more details.
Note that all output references are relative to the output directory
which is specified at build time. -->
<output filename="grit/ui_strings.h" type="rc_header">
@@ -592,11 +593,9 @@ need to be translated for each locale.-->
</message>
<!-- Message center -->
- <if expr="use_ash">
- <message name="IDS_MESSAGE_CENTER_ACCESSIBLE_NAME" desc="The accessible name for the Notification Center window.">
- Notification Center
- </message>
- </if>
+ <message name="IDS_MESSAGE_CENTER_ACCESSIBLE_NAME" desc="The accessible name for the Notification Center window.">
+ Notification Center
+ </message>
<message name="IDS_MESSAGE_CENTER_NOTIFIER_DISABLE" desc="The menu entry for disabling a notifier from a notification.">
Disable notifications from <ph name="notifier_name">$1<ex>Notification Galore!</ex></ph>
</message>
diff --git a/chromium/ui/surface/BUILD.gn b/chromium/ui/surface/BUILD.gn
index 96130c44d8e..b583c8bee71 100644
--- a/chromium/ui/surface/BUILD.gn
+++ b/chromium/ui/surface/BUILD.gn
@@ -6,8 +6,6 @@ import("//build/config/ui.gni")
component("surface") {
sources = [
- "accelerated_surface_mac.cc",
- "accelerated_surface_mac.h",
"surface_export.h",
"transport_dib.cc",
"transport_dib.h",
@@ -27,12 +25,4 @@ component("surface") {
"//ui/gfx/geometry",
"//ui/gl",
]
-
- if (is_mac) {
- # Required by accelerated_surface_mac.cc.
- libs = [
- "IOSurface.framework",
- "OpenGL.framework",
- ]
- }
}
diff --git a/chromium/ui/surface/OWNERS b/chromium/ui/surface/OWNERS
index 62a309c13fc..8e808054fc0 100644
--- a/chromium/ui/surface/OWNERS
+++ b/chromium/ui/surface/OWNERS
@@ -2,4 +2,3 @@ jbauman@chromium.org
kbr@chromium.org
piman@chromium.org
pinkerton@chromium.org
-stuartmorgan@chromium.org
diff --git a/chromium/ui/surface/accelerated_surface_mac.cc b/chromium/ui/surface/accelerated_surface_mac.cc
deleted file mode 100644
index 630ee7b3271..00000000000
--- a/chromium/ui/surface/accelerated_surface_mac.cc
+++ /dev/null
@@ -1,266 +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/surface/accelerated_surface_mac.h"
-
-#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/gl/scoped_make_current.h"
-
-// Note that this must be included after gl_bindings.h to avoid conflicts.
-#include <OpenGL/CGLIOSurface.h>
-
-AcceleratedSurface::AcceleratedSurface()
- : io_surface_id_(0),
- allocate_fbo_(false),
- texture_(0),
- fbo_(0) {
-}
-
-AcceleratedSurface::~AcceleratedSurface() {}
-
-bool AcceleratedSurface::Initialize(
- gfx::GLContext* share_context,
- bool allocate_fbo,
- gfx::GpuPreference gpu_preference) {
- allocate_fbo_ = allocate_fbo;
-
- // GL should be initialized by content::SupportsCoreAnimationPlugins().
- DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone);
-
- // Drawing to IOSurfaces via OpenGL only works with Apple's GL and
- // not with the OSMesa software renderer.
- if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
- gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
- return false;
-
- gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
- if (!gl_surface_.get()) {
- Destroy();
- return false;
- }
-
- gfx::GLShareGroup* share_group =
- share_context ? share_context->share_group() : NULL;
-
- gl_context_ = gfx::GLContext::CreateGLContext(
- share_group,
- gl_surface_.get(),
- gpu_preference);
- if (!gl_context_.get()) {
- Destroy();
- return false;
- }
-
- // Now we're ready to handle SetSurfaceSize calls, which will
- // allocate and/or reallocate the IOSurface and associated offscreen
- // OpenGL structures for rendering.
- return true;
-}
-
-void AcceleratedSurface::Destroy() {
- // The FBO and texture objects will be destroyed when the OpenGL context,
- // and any other contexts sharing resources with it, is. We don't want to
- // make the context current one last time here just in order to delete
- // these objects.
- gl_context_ = NULL;
- gl_surface_ = NULL;
-}
-
-// Call after making changes to the surface which require a visual update.
-// Makes the rendering show up in other processes.
-void AcceleratedSurface::SwapBuffers() {
- if (io_surface_.get() != NULL) {
- if (allocate_fbo_) {
- // Bind and unbind the framebuffer to make changes to the
- // IOSurface show up in the other process.
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- glFlush();
- } else {
- // Copy the current framebuffer's contents into our "live" texture.
- // Note that the current GL context might not be ours at this point!
- // This is deliberate, so that surrounding code using GL can produce
- // rendering results consumed by the AcceleratedSurface.
- // Need to save and restore OpenGL state around this call.
- GLint current_texture = 0;
- GLenum target_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
- GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- glGetIntegerv(target_binding, &current_texture);
- glBindTexture(target, texture_);
- glCopyTexSubImage2D(target, 0,
- 0, 0,
- 0, 0,
- real_surface_size_.width(),
- real_surface_size_.height());
- glBindTexture(target, current_texture);
- // This flush is absolutely essential -- it guarantees that the
- // rendering results are seen by the other process.
- glFlush();
- }
- }
-}
-
-static void AddBooleanValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- bool value) {
- CFDictionaryAddValue(dictionary, key,
- (value ? kCFBooleanTrue : kCFBooleanFalse));
-}
-
-static void AddIntegerValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- int32_t value) {
- base::ScopedCFTypeRef<CFNumberRef> number(
- CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
- CFDictionaryAddValue(dictionary, key, number.get());
-}
-
-// Creates a new OpenGL texture object bound to the given texture target.
-// Caller owns the returned texture.
-static GLuint CreateTexture(GLenum target) {
- GLuint texture = 0;
- glGenTextures(1, &texture);
- glBindTexture(target, texture);
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- return texture;
-}
-
-void AcceleratedSurface::AllocateRenderBuffers(GLenum target,
- const gfx::Size& size) {
- if (!texture_) {
- // Generate the texture object.
- texture_ = CreateTexture(target);
- // Generate and bind the framebuffer object.
- glGenFramebuffersEXT(1, &fbo_);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- }
-
- // Make sure that subsequent set-up code affects the render texture.
- glBindTexture(target, texture_);
-}
-
-bool AcceleratedSurface::SetupFrameBufferObject(GLenum target) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- GLenum fbo_status;
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texture_,
- 0);
- fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT;
-}
-
-gfx::Size AcceleratedSurface::ClampToValidDimensions(const gfx::Size& size) {
- return gfx::Size(std::max(size.width(), 1), std::max(size.height(), 1));
-}
-
-bool AcceleratedSurface::MakeCurrent() {
- if (!gl_context_.get())
- return false;
- return gl_context_->MakeCurrent(gl_surface_.get());
-}
-
-void AcceleratedSurface::Clear(const gfx::Rect& rect) {
- DCHECK(gl_context_->IsCurrent(gl_surface_.get()));
- glClearColor(0, 0, 0, 0);
- glViewport(0, 0, rect.width(), rect.height());
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, rect.width(), 0, rect.height(), -1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-uint32_t AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) {
- if (surface_size_ == size) {
- // Return 0 to indicate to the caller that no new backing store
- // allocation occurred.
- return 0;
- }
-
- // Only support IO surfaces if the GL implementation is the native desktop GL.
- // IO surfaces will not work with, for example, OSMesa software renderer
- // GL contexts.
- if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL)
- return 0;
-
- ui::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get());
- if (!make_current.Succeeded())
- return 0;
-
- gfx::Size clamped_size = ClampToValidDimensions(size);
-
- // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
- // Mac OS X and is required for IOSurface interoperability.
- GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- if (allocate_fbo_) {
- AllocateRenderBuffers(target, clamped_size);
- } else if (!texture_) {
- // Generate the texture object.
- texture_ = CreateTexture(target);
- }
-
- // Allocate a new IOSurface, which is the GPU resource that can be
- // shared across processes.
- base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
- properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- AddIntegerValue(properties, kIOSurfaceWidth, clamped_size.width());
- AddIntegerValue(properties, kIOSurfaceHeight, clamped_size.height());
- AddIntegerValue(properties, kIOSurfaceBytesPerElement, 4);
- AddBooleanValue(properties, kIOSurfaceIsGlobal, true);
- // I believe we should be able to unreference the IOSurfaces without
- // synchronizing with the browser process because they are
- // ultimately reference counted by the operating system.
- io_surface_.reset(IOSurfaceCreate(properties));
-
- // Don't think we need to identify a plane.
- GLuint plane = 0;
- CGLError error = CGLTexImageIOSurface2D(
- static_cast<CGLContextObj>(gl_context_->GetHandle()),
- target,
- GL_RGBA,
- clamped_size.width(),
- clamped_size.height(),
- GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV,
- io_surface_.get(),
- plane);
- if (error != kCGLNoError) {
- DLOG(ERROR) << "CGL error " << error << " during CGLTexImageIOSurface2D";
- }
- if (allocate_fbo_) {
- // Set up the frame buffer object.
- if (!SetupFrameBufferObject(target)) {
- DLOG(ERROR) << "Failed to set up frame buffer object";
- }
- }
- surface_size_ = size;
- real_surface_size_ = clamped_size;
-
- // Now send back an identifier for the IOSurface. We originally
- // intended to send back a mach port from IOSurfaceCreateMachPort
- // but it looks like Chrome IPC would need to be modified to
- // properly send mach ports between processes. For the time being we
- // make our IOSurfaces global and send back their identifiers. On
- // the browser process side the identifier is reconstituted into an
- // IOSurface for on-screen rendering.
- io_surface_id_ = IOSurfaceGetID(io_surface_);
- return io_surface_id_;
-}
-
-uint32_t AcceleratedSurface::GetSurfaceId() {
- return io_surface_id_;
-}
diff --git a/chromium/ui/surface/accelerated_surface_mac.h b/chromium/ui/surface/accelerated_surface_mac.h
deleted file mode 100644
index 9defa33a9a9..00000000000
--- a/chromium/ui/surface/accelerated_surface_mac.h
+++ /dev/null
@@ -1,147 +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_SURFACE_ACCELERATED_SURFACE_MAC_H_
-#define UI_SURFACE_ACCELERATED_SURFACE_MAC_H_
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOSurface/IOSurface.h>
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/gl/gpu_preference.h"
-#include "ui/surface/surface_export.h"
-
-// Should not include GL headers in a header file. Forward declare these types
-// instead.
-typedef struct _CGLContextObject* CGLContextObj;
-typedef unsigned int GLenum;
-typedef unsigned int GLuint;
-
-namespace gfx {
-class Rect;
-}
-
-// Encapsulates an accelerated GL surface that can be shared across processes
-// on systems that support it (10.6 and above).
-
-class SURFACE_EXPORT AcceleratedSurface {
- public:
- AcceleratedSurface();
- virtual ~AcceleratedSurface();
-
- // Set up internal buffers. |share_context|, if non-NULL, is a context
- // with which the internally created OpenGL context shares textures and
- // other resources. |allocate_fbo| indicates whether or not this surface
- // should allocate an offscreen frame buffer object (FBO) internally. If
- // not, then the user is expected to allocate one. NOTE that allocating
- // an FBO internally does NOT work properly with client code which uses
- // OpenGL (i.e., via GLES2 command buffers), because the GLES2
- // implementation does not know to bind the accelerated surface's
- // internal FBO when the default FBO is bound. |gpu_preference| indicates
- // the GPU preference for the internally allocated GLContext. If
- // |share_context| is non-NULL, then on platforms supporting dual GPUs,
- // its GPU preference must match the passed one. Returns false upon
- // failure.
- bool Initialize(gfx::GLContext* share_context,
- bool allocate_fbo,
- gfx::GpuPreference gpu_preference);
- // Tear down. Must be called before destructor to prevent leaks.
- void Destroy();
-
- // These methods are used only once the accelerated surface is initialized.
-
- // Sets the accelerated surface to the given size, creating a new one if
- // the height or width changes. Returns a unique id of the IOSurface to
- // which the surface is bound, or 0 if no changes were made or an error
- // occurred. MakeCurrent() will have been called on the new surface.
- uint32_t SetSurfaceSize(const gfx::Size& size);
-
- // Returns the id of this surface's IOSurface.
- uint32_t GetSurfaceId();
-
- // Sets the GL context to be the current one for drawing. Returns true if
- // it succeeded.
- bool MakeCurrent();
- // Clear the surface to be transparent. Assumes the caller has already called
- // MakeCurrent().
- void Clear(const gfx::Rect& rect);
- // Call after making changes to the surface which require a visual update.
- // Makes the rendering show up in other processes. Assumes the caller has
- // already called MakeCurrent().
- //
- // If this AcceleratedSurface is configured with its own FBO, then
- // this call causes the color buffer to be transmitted. Otherwise,
- // it causes the frame buffer of the current GL context to be copied
- // into an internal texture via glCopyTexSubImage2D.
- //
- // The size of the rectangle copied is the size last specified via
- // SetSurfaceSize. If another GL context than the one this
- // AcceleratedSurface contains is responsible for the production of
- // the pixels, then when this entry point is called, the color
- // buffer must be in a state where a glCopyTexSubImage2D is
- // legal. (For example, if using multisampled FBOs, the FBO must
- // have been resolved into a non-multisampled color texture.)
- // Additionally, in this situation, the contexts must share
- // server-side GL objects, so that this AcceleratedSurface's texture
- // is a legal name in the namespace of the current context.
- void SwapBuffers();
-
- CGLContextObj context() {
- return static_cast<CGLContextObj>(gl_context_->GetHandle());
- }
-
- // Get the accelerated surface size.
- gfx::Size GetSize() const { return surface_size_; }
-
- private:
- // Helper function to generate names for the backing texture and FBO. On
- // return, the resulting names can be attached to |fbo_|. |target| is
- // the target type for the color buffer.
- void AllocateRenderBuffers(GLenum target, const gfx::Size& size);
-
- // Helper function to attach the buffers previously allocated by a call to
- // AllocateRenderBuffers(). On return, |fbo_| can be used for
- // rendering. |target| must be the same value as used in the call to
- // AllocateRenderBuffers(). Returns |true| if the resulting framebuffer
- // object is valid.
- bool SetupFrameBufferObject(GLenum target);
-
- gfx::Size ClampToValidDimensions(const gfx::Size& size);
-
- // The OpenGL context, and pbuffer drawable, used to transfer data
- // to the shared region (IOSurface).
- scoped_refptr<gfx::GLSurface> gl_surface_;
- scoped_refptr<gfx::GLContext> gl_context_;
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
-
- // The id of |io_surface_| or 0 if that's NULL.
- uint32_t io_surface_id_;
-
- gfx::Size surface_size_;
- // It's important to avoid allocating zero-width or zero-height
- // IOSurfaces and textures on the Mac, so we clamp each to a minimum
- // of 1. This is the real size of the surface; surface_size_ is what
- // the user requested.
- gfx::Size real_surface_size_;
- // TODO(kbr): the FBO management should not be in this class at all.
- // However, if it is factored out, care needs to be taken to not
- // introduce another copy of the color data on the GPU; the direct
- // binding of the internal texture to the IOSurface saves a copy.
- bool allocate_fbo_;
- // This texture object is always allocated, regardless of whether
- // the user requests an FBO be allocated.
- GLuint texture_;
- // The FBO and renderbuffer are only allocated if allocate_fbo_ is
- // true.
- GLuint fbo_;
-};
-
-#endif // UI_SURFACE_ACCELERATED_SURFACE_MAC_H_
diff --git a/chromium/ui/surface/surface.gyp b/chromium/ui/surface/surface.gyp
index a219473e402..e45e2ae888a 100644
--- a/chromium/ui/surface/surface.gyp
+++ b/chromium/ui/surface/surface.gyp
@@ -13,15 +13,6 @@
'../../third_party/khronos',
],
}],
- ['OS == "mac"', {
- # Required by accelerated_surface_mac.cc.
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/IOSurface.framework',
- '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
- ],
- },
- }],
],
},
'targets': [
@@ -37,8 +28,6 @@
'../gl/gl.gyp:gl',
],
'sources': [
- 'accelerated_surface_mac.cc',
- 'accelerated_surface_mac.h',
'surface_export.h',
'transport_dib.cc',
'transport_dib.h',
diff --git a/chromium/ui/surface/transport_dib_posix.cc b/chromium/ui/surface/transport_dib_posix.cc
index be1a37363aa..aada735b530 100644
--- a/chromium/ui/surface/transport_dib_posix.cc
+++ b/chromium/ui/surface/transport_dib_posix.cc
@@ -57,8 +57,7 @@ bool TransportDIB::is_valid_handle(Handle dib) {
return base::SharedMemory::IsHandleValid(dib);
}
-skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h,
- bool opaque) {
+SkCanvas* TransportDIB::GetPlatformCanvas(int w, int h, bool opaque) {
if ((!memory() && !Map()) || !VerifyCanvasSize(w, h))
return NULL;
return skia::CreatePlatformCanvas(w, h, opaque,
diff --git a/chromium/ui/surface/transport_dib_win.cc b/chromium/ui/surface/transport_dib_win.cc
index 82eabf87878..f002f55536d 100644
--- a/chromium/ui/surface/transport_dib_win.cc
+++ b/chromium/ui/surface/transport_dib_win.cc
@@ -58,7 +58,7 @@ bool TransportDIB::is_valid_handle(Handle dib) {
return dib.IsValid();
}
-skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h,
+SkCanvas* TransportDIB::GetPlatformCanvas(int w, int h,
bool opaque) {
// This DIB already mapped the file into this process, but PlatformCanvas
// will map it again.
@@ -67,7 +67,7 @@ skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h,
// We can't check the canvas size before mapping, but it's safe because
// Windows will fail to map the section if the dimensions of the canvas
// are too large.
- skia::PlatformCanvas* canvas = skia::CreatePlatformCanvas(
+ SkCanvas* canvas = skia::CreatePlatformCanvas(
w, h, opaque, shared_memory_.handle().GetHandle(),
skia::RETURN_NULL_ON_FAILURE);
diff --git a/chromium/ui/touch_selection/BUILD.gn b/chromium/ui/touch_selection/BUILD.gn
index 4d69e189228..cc273875a43 100644
--- a/chromium/ui/touch_selection/BUILD.gn
+++ b/chromium/ui/touch_selection/BUILD.gn
@@ -68,15 +68,6 @@ static_library("test_support") {
]
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("ui_touch_selection_unittests_run") {
- testonly = true
- deps = [
- ":ui_touch_selection_unittests",
- ]
-}
-
test("ui_touch_selection_unittests") {
sources = [
"longpress_drag_selector_unittest.cc",
diff --git a/chromium/ui/touch_selection/ui_touch_selection_unittests_apk.isolate b/chromium/ui/touch_selection/ui_touch_selection_unittests_apk.isolate
index a2b39ac5d96..e49c7076f50 100644
--- a/chromium/ui/touch_selection/ui_touch_selection_unittests_apk.isolate
+++ b/chromium/ui/touch_selection/ui_touch_selection_unittests_apk.isolate
@@ -8,6 +8,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_ui_touch_selection_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'<(PRODUCT_DIR)/bin/run_ui_touch_selection_unittests',
diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn
index d506603f175..5b85b89b3cf 100644
--- a/chromium/ui/views/BUILD.gn
+++ b/chromium/ui/views/BUILD.gn
@@ -47,6 +47,7 @@ component("views") {
"//ui/base",
"//ui/base/ime",
"//ui/compositor",
+ "//ui/display",
"//ui/events",
"//ui/events:events_base",
"//ui/events/platform",
@@ -84,6 +85,7 @@ component("views") {
"dwmapi.lib",
"imm32.lib",
"oleacc.lib",
+ "wtsapi32.lib",
]
ldflags = [ "/DELAYLOAD:user32.dll" ]
deps += [
@@ -114,7 +116,7 @@ component("views") {
"//ui/touch_selection",
"//ui/wm",
]
- if (!is_chromeos && !is_android) {
+ if (!is_chromeos) {
sources += gypi_values.views_desktop_aura_sources
if (use_x11) {
sources += gypi_values.views_desktop_aura_x11_sources
@@ -128,9 +130,6 @@ component("views") {
sources += gypi_values.views_desktop_aura_linux_sources
}
}
- if (is_android) {
- sources += gypi_values.views_android_sources
- }
}
if (is_mac) {
@@ -163,6 +162,7 @@ source_set("test_support_internal") {
"//skia",
"//testing/gtest",
"//ui/base",
+ "//ui/base:test_support",
"//ui/base/ime",
"//ui/compositor",
"//ui/compositor:test_support",
@@ -191,7 +191,10 @@ source_set("test_support_internal") {
deps += [ "//ui/gfx/x" ]
}
if (use_ozone || !use_x11) {
- sources -= [ "test/x11_property_change_waiter.cc" ]
+ sources -= [
+ "test/x11_property_change_waiter.cc",
+ "test/x11_property_change_waiter.h",
+ ]
}
}
@@ -202,6 +205,7 @@ static_library("test_support") {
]
sources = [
"test/default_platform_test_helper.cc",
+ "test/native_widget_factory_desktop.cc",
]
}
@@ -212,7 +216,6 @@ test("views_unittests") {
":test_support",
"//base",
"//base:i18n",
- "//base/allocator",
"//base/test:test_support",
"//cc",
"//skia",
@@ -230,13 +233,17 @@ test("views_unittests") {
"//ui/gfx:test_support",
"//ui/gfx/geometry",
"//ui/gl:test_support",
+ "//ui/native_theme",
"//ui/resources",
+ "//ui/resources:ui_test_pak",
"//ui/strings",
"//url",
]
- data_deps = [
- "//ui/resources:ui_test_pak",
+ # TODO(thakis): This should be a data_deps on //ui/resources:ui_test_pak, but
+ # that has no effect. (See similar TODOs elsewhere ui_test.pak is listed)
+ data = [
+ "$root_out_dir/ui_test.pak",
]
if (is_win) {
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
index 3d4850e0bc2..9bd021e1d00 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -6,6 +6,7 @@
#include "base/memory/singleton.h"
#include "base/stl_util.h"
+#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
#include "ui/views/accessibility/ax_view_obj_wrapper.h"
@@ -30,18 +31,27 @@ AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(Widget* widget) {
}
AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(aura::Window* window) {
+ if (!focus_client_) {
+ aura::Window* root_window = window->GetRootWindow();
+ if (root_window) {
+ focus_client_ = aura::client::GetFocusClient(root_window);
+ root_window->AddObserver(this);
+ if (focus_client_)
+ focus_client_->AddObserver(this);
+ }
+ }
return CreateInternal<AXWindowObjWrapper>(window, window_to_id_map_);
}
-int32_t AXAuraObjCache::GetID(View* view) {
+int32_t AXAuraObjCache::GetID(View* view) const {
return GetIDInternal(view, view_to_id_map_);
}
-int32_t AXAuraObjCache::GetID(Widget* widget) {
+int32_t AXAuraObjCache::GetID(Widget* widget) const {
return GetIDInternal(widget, widget_to_id_map_);
}
-int32_t AXAuraObjCache::GetID(aura::Window* window) {
+int32_t AXAuraObjCache::GetID(aura::Window* window) const {
return GetIDInternal(window, window_to_id_map_);
}
@@ -97,7 +107,17 @@ void AXAuraObjCache::GetTopLevelWindows(
}
}
-AXAuraObjCache::AXAuraObjCache() : current_id_(1), is_destroying_(false) {
+AXAuraObjWrapper* AXAuraObjCache::GetFocus() {
+ View* focused_view = GetFocusedView();
+ if (focused_view)
+ return GetOrCreate(focused_view);
+ return nullptr;
+}
+
+AXAuraObjCache::AXAuraObjCache()
+ : current_id_(1),
+ focus_client_(nullptr),
+ is_destroying_(false) {
}
AXAuraObjCache::~AXAuraObjCache() {
@@ -106,6 +126,44 @@ AXAuraObjCache::~AXAuraObjCache() {
cache_.clear();
}
+View* AXAuraObjCache::GetFocusedView() {
+ if (!focus_client_)
+ return nullptr;
+
+ aura::Window* focused_window = focus_client_->GetFocusedWindow();
+ if (!focused_window)
+ return nullptr;
+
+ Widget* focused_widget = Widget::GetWidgetForNativeView(focused_window);
+ while (!focused_widget) {
+ focused_window = focused_window->parent();
+ if (!focused_window)
+ break;
+
+ focused_widget = Widget::GetWidgetForNativeView(focused_window);
+ }
+
+ if (!focused_widget)
+ return nullptr;
+
+ FocusManager* focus_manager = focused_widget->GetFocusManager();
+ if (!focus_manager)
+ return nullptr;
+
+ return focus_manager->GetFocusedView();
+}
+
+void AXAuraObjCache::OnWindowFocused(aura::Window* gained_focus,
+ aura::Window* lost_focus) {
+ View* view = GetFocusedView();
+ if (view)
+ view->NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
+}
+
+void AXAuraObjCache::OnWindowDestroying(aura::Window* window) {
+ focus_client_ = nullptr;
+}
+
template <typename AuraViewWrapper, typename AuraView>
AXAuraObjWrapper* AXAuraObjCache::CreateInternal(
AuraView* aura_view,
@@ -129,13 +187,11 @@ AXAuraObjWrapper* AXAuraObjCache::CreateInternal(
template <typename AuraView>
int32_t AXAuraObjCache::GetIDInternal(
AuraView* aura_view,
- std::map<AuraView*, int32_t>& aura_view_to_id_map) {
+ const std::map<AuraView*, int32_t>& aura_view_to_id_map) const {
if (!aura_view)
return -1;
- typename std::map<AuraView*, int32_t>::iterator it =
- aura_view_to_id_map.find(aura_view);
-
+ auto it = aura_view_to_id_map.find(aura_view);
if (it != aura_view_to_id_map.end())
return it->second;
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.h b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
index a7bb50c99b4..763f8f99171 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.h
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
@@ -11,6 +11,8 @@
#include <vector>
#include "base/macros.h"
+#include "ui/aura/client/focus_change_observer.h"
+#include "ui/aura/window_observer.h"
#include "ui/views/views_export.h"
namespace base {
@@ -18,6 +20,9 @@ template <typename T> struct DefaultSingletonTraits;
}
namespace aura {
+namespace client {
+class FocusClient;
+}
class Window;
} // namespace aura
@@ -27,7 +32,9 @@ class View;
class Widget;
// A cache responsible for assigning id's to a set of interesting Aura views.
-class VIEWS_EXPORT AXAuraObjCache {
+class VIEWS_EXPORT AXAuraObjCache
+ : public aura::client::FocusChangeObserver,
+ public aura::WindowObserver {
public:
// Get the single instance of this class.
static AXAuraObjCache* GetInstance();
@@ -38,9 +45,9 @@ class VIEWS_EXPORT AXAuraObjCache {
AXAuraObjWrapper* GetOrCreate(aura::Window* window);
// Gets an id given an Aura view.
- int32_t GetID(View* view);
- int32_t GetID(Widget* widget);
- int32_t GetID(aura::Window* window);
+ int32_t GetID(View* view) const;
+ int32_t GetID(Widget* widget) const;
+ int32_t GetID(aura::Window* window) const;
// Gets the next unique id for this cache. Useful for non-Aura view backed
// views.
@@ -63,6 +70,9 @@ class VIEWS_EXPORT AXAuraObjCache {
// Get all top level windows this cache knows about.
void GetTopLevelWindows(std::vector<AXAuraObjWrapper*>* children);
+ // Get the object that has focus.
+ AXAuraObjWrapper* GetFocus();
+
// Indicates if this object's currently being destroyed.
bool is_destroying() { return is_destroying_; }
@@ -70,7 +80,16 @@ class VIEWS_EXPORT AXAuraObjCache {
friend struct base::DefaultSingletonTraits<AXAuraObjCache>;
AXAuraObjCache();
- virtual ~AXAuraObjCache();
+ ~AXAuraObjCache() override;
+
+ View* GetFocusedView();
+
+ // aura::client::FocusChangeObserver override.
+ void OnWindowFocused(aura::Window* gained_focus,
+ aura::Window* lost_focus) override;
+
+ // aura::WindowObserver override.
+ void OnWindowDestroying(aura::Window* window) override;
template <typename AuraViewWrapper, typename AuraView>
AXAuraObjWrapper* CreateInternal(
@@ -78,8 +97,9 @@ class VIEWS_EXPORT AXAuraObjCache {
std::map<AuraView*, int32_t>& aura_view_to_id_map);
template <typename AuraView>
- int32_t GetIDInternal(AuraView* aura_view,
- std::map<AuraView*, int32_t>& aura_view_to_id_map);
+ int32_t GetIDInternal(
+ AuraView* aura_view,
+ const std::map<AuraView*, int32_t>& aura_view_to_id_map) const;
template <typename AuraView>
void RemoveInternal(AuraView* aura_view,
@@ -92,6 +112,8 @@ class VIEWS_EXPORT AXAuraObjCache {
std::map<int32_t, AXAuraObjWrapper*> cache_;
int32_t current_id_;
+ aura::client::FocusClient* focus_client_;
+
// True immediately when entering this object's destructor.
bool is_destroying_;
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc
new file mode 100644
index 00000000000..80122369c31
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/test/widget_test.h"
+
+namespace views {
+namespace test {
+
+namespace {
+
+// This class can be used as a deleter for scoped_ptr<Widget>
+// to call function Widget::CloseNow automatically.
+struct WidgetCloser {
+ inline void operator()(Widget* widget) const { widget->CloseNow(); }
+};
+
+using WidgetAutoclosePtr = scoped_ptr<Widget, WidgetCloser>;
+}
+
+class AXAuraObjCacheTest : public WidgetTest {
+ public:
+ AXAuraObjCacheTest() {}
+ ~AXAuraObjCacheTest() override {}
+};
+
+TEST_F(AXAuraObjCacheTest, TestViewRemoval) {
+ WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
+ View* parent = new View();
+ widget->GetRootView()->AddChildView(parent);
+ View* child = new View();
+ parent->AddChildView(child);
+
+ AXAuraObjCache* cache = AXAuraObjCache::GetInstance();
+ AXAuraObjWrapper* ax_widget = cache->GetOrCreate(widget.get());
+ ASSERT_NE(nullptr, ax_widget);
+ AXAuraObjWrapper* ax_parent = cache->GetOrCreate(parent);
+ ASSERT_NE(nullptr, ax_parent);
+ AXAuraObjWrapper* ax_child = cache->GetOrCreate(child);
+ ASSERT_NE(nullptr, ax_child);
+
+ // Everything should have an ID, indicating it's in the cache.
+ ASSERT_GT(cache->GetID(widget.get()), 0);
+ ASSERT_GT(cache->GetID(parent), 0);
+ ASSERT_GT(cache->GetID(child), 0);
+
+ // Removing the parent view should remove both the parent and child
+ // from the cache, but leave the widget.
+ widget->GetRootView()->RemoveChildView(parent);
+ ASSERT_GT(cache->GetID(widget.get()), 0);
+ ASSERT_EQ(-1, cache->GetID(parent));
+ ASSERT_EQ(-1, cache->GetID(child));
+
+ // Explicitly delete |parent| to prevent a memory leak, since calling
+ // RemoveChildView() doesn't delete it.
+ delete parent;
+}
+
+} // namespace test
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc
index 4363d19dc71..3ea1e04efb2 100644
--- a/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -36,6 +36,9 @@ 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) {
+ if (!view_->child_at(i)->visible())
+ continue;
+
AXAuraObjWrapper* child =
AXAuraObjCache::GetInstance()->GetOrCreate(view_->child_at(i));
out_children->push_back(child);
@@ -50,8 +53,6 @@ void AXViewObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
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;
if (!view_->visible())
diff --git a/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc
index 25183a8c22f..628b82fac76 100644
--- a/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_widget_obj_wrapper.cc
@@ -30,6 +30,9 @@ AXAuraObjWrapper* AXWidgetObjWrapper::GetParent() {
void AXWidgetObjWrapper::GetChildren(
std::vector<AXAuraObjWrapper*>* out_children) {
+ if (!widget_->IsVisible() || !widget_->GetRootView()->visible())
+ return;
+
out_children->push_back(
AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetRootView()));
}
@@ -51,7 +54,7 @@ void AXWidgetObjWrapper::OnWidgetDestroying(Widget* widget) {
}
void AXWidgetObjWrapper::OnWillRemoveView(Widget* widget, View* view) {
- AXAuraObjCache::GetInstance()->Remove(view);
+ AXAuraObjCache::GetInstance()->RemoveViewSubtree(view);
}
} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
index 124ae78710d..ebdb650d1a6 100644
--- a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -35,6 +35,8 @@ void AXWindowObjWrapper::GetChildren(
std::vector<AXAuraObjWrapper*>* out_children) {
aura::Window::Windows children = window_->children();
for (size_t i = 0; i < children.size(); ++i) {
+ if (!children[i]->IsVisible())
+ continue;
out_children->push_back(
AXAuraObjCache::GetInstance()->GetOrCreate(children[i]));
}
@@ -64,7 +66,7 @@ int32_t AXWindowObjWrapper::GetID() {
return AXAuraObjCache::GetInstance()->GetID(window_);
}
-void AXWindowObjWrapper::OnWindowDestroying(aura::Window* window) {
+void AXWindowObjWrapper::OnWindowDestroyed(aura::Window* window) {
AXAuraObjCache::GetInstance()->Remove(window);
}
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.h b/chromium/ui/views/accessibility/ax_window_obj_wrapper.h
index 2bc46aaa9cf..bcf35481d73 100644
--- a/chromium/ui/views/accessibility/ax_window_obj_wrapper.h
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.h
@@ -37,7 +37,7 @@ class AXWindowObjWrapper : public AXAuraObjWrapper,
int32_t GetID() override;
// WindowObserver overrides.
- void OnWindowDestroying(aura::Window* window) override;
+ void OnWindowDestroyed(aura::Window* window) override;
private:
aura::Window* window_;
diff --git a/chromium/ui/views/accessibility/native_view_accessibility.cc b/chromium/ui/views/accessibility/native_view_accessibility.cc
index 07406e5b2ed..ab86be128e3 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility.cc
+++ b/chromium/ui/views/accessibility/native_view_accessibility.cc
@@ -74,9 +74,6 @@ const ui::AXNodeData& NativeViewAccessibility::GetData() {
if (!view_->visible())
data_.state |= (1 << ui::AX_STATE_INVISIBLE);
- if (view_->HasFocus())
- data_.state |= (1 << ui::AX_STATE_FOCUSED);
-
return data_;
}
diff --git a/chromium/ui/views/accessible_pane_view_unittest.cc b/chromium/ui/views/accessible_pane_view_unittest.cc
index 303d20623da..864481ff3ff 100644
--- a/chromium/ui/views/accessible_pane_view_unittest.cc
+++ b/chromium/ui/views/accessible_pane_view_unittest.cc
@@ -12,10 +12,6 @@
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
-#if defined(OS_MACOSX)
-#include "ui/base/test/scoped_fake_nswindow_focus.h"
-#endif
-
namespace views {
// TODO(alicet): bring pane rotation into views and add tests.
@@ -105,13 +101,6 @@ TEST_F(AccessiblePaneViewTest, SimpleSetPaneFocus) {
}
TEST_F(AccessiblePaneViewTest, SetPaneFocusAndRestore) {
-#if defined(OS_MACOSX)
- // On Aura platforms, this test creates Ash windows and only interacts with
- // the Ash window manager. On Mac, it creates native windows, but since unit
- // tests cannot gain key status, fake it out here.
- ui::test::ScopedFakeNSWindowFocus fake_focus;
-#endif
-
View* test_view_main = new View();
scoped_ptr<Widget> widget_main(new Widget());
Widget::InitParams params_main = CreateParams(Widget::InitParams::TYPE_POPUP);
diff --git a/chromium/ui/views/animation/OWNERS b/chromium/ui/views/animation/OWNERS
new file mode 100644
index 00000000000..9710b4e0f93
--- /dev/null
+++ b/chromium/ui/views/animation/OWNERS
@@ -0,0 +1 @@
+per-file *ink*=bruthig@chromium.org
diff --git a/chromium/ui/views/animation/bounds_animator.h b/chromium/ui/views/animation/bounds_animator.h
index 68dad46abc6..2840c3dcd73 100644
--- a/chromium/ui/views/animation/bounds_animator.h
+++ b/chromium/ui/views/animation/bounds_animator.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "ui/gfx/animation/animation_container_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
diff --git a/chromium/ui/views/animation/button_ink_drop_delegate.cc b/chromium/ui/views/animation/button_ink_drop_delegate.cc
index 2fa6000574b..73152d77bc5 100644
--- a/chromium/ui/views/animation/button_ink_drop_delegate.cc
+++ b/chromium/ui/views/animation/button_ink_drop_delegate.cc
@@ -25,30 +25,37 @@ ButtonInkDropDelegate::ButtonInkDropDelegate(InkDropHost* ink_drop_host,
ButtonInkDropDelegate::~ButtonInkDropDelegate() {
}
-void ButtonInkDropDelegate::SetInkDropSize(int large_size,
- int large_corner_radius,
- int small_size,
- int small_corner_radius) {
- ink_drop_animation_controller_->SetInkDropSize(
- gfx::Size(large_size, large_size), large_corner_radius,
- gfx::Size(small_size, small_size), small_corner_radius);
+void ButtonInkDropDelegate::OnAction(InkDropState state) {
+ ink_drop_animation_controller_->AnimateToState(state);
}
-void ButtonInkDropDelegate::OnLayout() {
- ink_drop_animation_controller_->SetInkDropCenter(
- ink_drop_host_->CalculateInkDropCenter());
+void ButtonInkDropDelegate::SnapToActivated() {
+ ink_drop_animation_controller_->SnapToActivated();
}
-void ButtonInkDropDelegate::OnAction(InkDropState state) {
- ink_drop_animation_controller_->AnimateToState(state);
+void ButtonInkDropDelegate::SetHovered(bool is_hovered) {
+ ink_drop_animation_controller_->SetHovered(is_hovered);
}
////////////////////////////////////////////////////////////////////////////////
// ui::EventHandler:
+void ButtonInkDropDelegate::OnMouseEvent(ui::MouseEvent* event) {
+ switch (event->type()) {
+ case ui::ET_MOUSE_ENTERED:
+ SetHovered(true);
+ break;
+ case ui::ET_MOUSE_EXITED:
+ SetHovered(false);
+ break;
+ default:
+ return;
+ }
+}
+
void ButtonInkDropDelegate::OnGestureEvent(ui::GestureEvent* event) {
InkDropState current_ink_drop_state =
- ink_drop_animation_controller_->GetInkDropState();
+ ink_drop_animation_controller_->GetTargetInkDropState();
InkDropState ink_drop_state = InkDropState::HIDDEN;
switch (event->type()) {
@@ -59,10 +66,10 @@ void ButtonInkDropDelegate::OnGestureEvent(ui::GestureEvent* event) {
event->SetHandled();
break;
case ui::ET_GESTURE_LONG_PRESS:
- ink_drop_state = InkDropState::SLOW_ACTION_PENDING;
+ ink_drop_state = InkDropState::ALTERNATE_ACTION_PENDING;
break;
case ui::ET_GESTURE_LONG_TAP:
- ink_drop_state = InkDropState::SLOW_ACTION;
+ ink_drop_state = InkDropState::ALTERNATE_ACTION_TRIGGERED;
break;
case ui::ET_GESTURE_END:
if (current_ink_drop_state == InkDropState::ACTIVATED)
@@ -75,9 +82,11 @@ void ButtonInkDropDelegate::OnGestureEvent(ui::GestureEvent* event) {
return;
}
+ last_ink_drop_location_ = event->location();
+
if (ink_drop_state == InkDropState::HIDDEN &&
- (current_ink_drop_state == InkDropState::QUICK_ACTION ||
- current_ink_drop_state == InkDropState::SLOW_ACTION ||
+ (current_ink_drop_state == InkDropState::ACTION_TRIGGERED ||
+ current_ink_drop_state == InkDropState::ALTERNATE_ACTION_TRIGGERED ||
current_ink_drop_state == InkDropState::DEACTIVATED)) {
// These InkDropStates automatically transition to the HIDDEN state so we
// don't make an explicit call. Explicitly animating to HIDDEN in this case
diff --git a/chromium/ui/views/animation/button_ink_drop_delegate.h b/chromium/ui/views/animation/button_ink_drop_delegate.h
index 2e8798daa5a..f4c245ecdc1 100644
--- a/chromium/ui/views/animation/button_ink_drop_delegate.h
+++ b/chromium/ui/views/animation/button_ink_drop_delegate.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/events/event_handler.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/views/animation/ink_drop_delegate.h"
#include "ui/views/views_export.h"
@@ -21,22 +22,27 @@ class InkDropAnimationController;
class InkDropHost;
class View;
-// An InkDropDelegate that handles animations for toolbar buttons.
+// An InkDropDelegate that handles animations for things that act like buttons.
class VIEWS_EXPORT ButtonInkDropDelegate : public InkDropDelegate,
public ui::EventHandler {
public:
ButtonInkDropDelegate(InkDropHost* ink_drop_host, View* view);
~ButtonInkDropDelegate() override;
+ const gfx::Point& last_ink_drop_location() const {
+ return last_ink_drop_location_;
+ }
+ void set_last_ink_drop_location(const gfx::Point& point) {
+ last_ink_drop_location_ = point;
+ }
+
// InkDropDelegate:
- void SetInkDropSize(int large_size,
- int large_corner_radius,
- int small_size,
- int small_corner_radius) override;
- void OnLayout() override;
void OnAction(InkDropState state) override;
+ void SnapToActivated() override;
+ void SetHovered(bool is_hovered) override;
// ui::EventHandler:
+ void OnMouseEvent(ui::MouseEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
private:
@@ -46,6 +52,10 @@ class VIEWS_EXPORT ButtonInkDropDelegate : public InkDropDelegate,
// Parent InkDropHost (typically a View) that hosts the ink ripple animations.
InkDropHost* ink_drop_host_;
+ // Location of the last ink drop triggering event in coordinate system of the
+ // ctor argument |view|.
+ gfx::Point last_ink_drop_location_;
+
// Animation controller for the ink drop ripple effect.
scoped_ptr<InkDropAnimationController> ink_drop_animation_controller_;
diff --git a/chromium/ui/views/animation/flood_fill_ink_drop_animation.cc b/chromium/ui/views/animation/flood_fill_ink_drop_animation.cc
new file mode 100644
index 00000000000..6e177aaff37
--- /dev/null
+++ b/chromium/ui/views/animation/flood_fill_ink_drop_animation.cc
@@ -0,0 +1,327 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/flood_fill_ink_drop_animation.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace {
+
+// The minimum radius to use when scaling the painted layers. Smaller values
+// were causing visual anomalies.
+const float kMinRadius = 1.f;
+
+// All the sub animations that are used to animate each of the InkDropStates.
+// These are used to get time durations with
+// GetAnimationDuration(InkDropSubAnimations). Note that in general a sub
+// animation defines the duration for either a transformation animation or an
+// opacity animation but there are some exceptions where an entire InkDropState
+// animation consists of only 1 sub animation and it defines the duration for
+// both the transformation and opacity animations.
+enum InkDropSubAnimations {
+ // HIDDEN sub animations.
+
+ // The HIDDEN sub animation that is fading out to a hidden opacity.
+ HIDDEN_FADE_OUT,
+
+ // The HIDDEN sub animation that transform the circle to a small one.
+ HIDDEN_TRANSFORM,
+
+ // ACTION_PENDING sub animations.
+
+ // The ACTION_PENDING sub animation that fades in to the visible opacity.
+ ACTION_PENDING_FADE_IN,
+
+ // The ACTION_PENDING sub animation that transforms the circle to fill the
+ // bounds.
+ ACTION_PENDING_TRANSFORM,
+
+ // ACTION_TRIGGERED sub animations.
+
+ // The ACTION_TRIGGERED sub animation that is fading out to a hidden opacity.
+ ACTION_TRIGGERED_FADE_OUT,
+
+ // ALTERNATE_ACTION_PENDING sub animations.
+
+ // The ALTERNATE_ACTION_PENDING animation has only one sub animation which
+ // animates
+ // the circleto fill the bounds at visible opacity.
+ ALTERNATE_ACTION_PENDING,
+
+ // ALTERNATE_ACTION_TRIGGERED sub animations.
+
+ // The ALTERNATE_ACTION_TRIGGERED sub animation that is fading out to a hidden
+ // opacity.
+ ALTERNATE_ACTION_TRIGGERED_FADE_OUT,
+
+ // ACTIVATED sub animations.
+
+ // The ACTIVATED sub animation that is fading in to the visible opacity.
+ ACTIVATED_FADE_IN,
+
+ // The ACTIVATED sub animation that transforms the circle to fill the entire
+ // bounds.
+ ACTIVATED_TRANSFORM,
+
+ // DEACTIVATED sub animations.
+
+ // The DEACTIVATED sub animation that is fading out to a hidden opacity.
+ DEACTIVATED_FADE_OUT,
+};
+
+// Duration constants for InkDropStateSubAnimations. See the
+// InkDropStateSubAnimations enum documentation for more info.
+int kAnimationDurationInMs[] = {
+ 200, // HIDDEN_FADE_OUT
+ 300, // HIDDEN_TRANSFORM
+ 0, // ACTION_PENDING_FADE_IN
+ 240, // ACTION_PENDING_TRANSFORM
+ 300, // ACTION_TRIGGERED_FADE_OUT
+ 200, // ALTERNATE_ACTION_PENDING
+ 300, // ALTERNATE_ACTION_TRIGGERED_FADE_OUT
+ 150, // ACTIVATED_FADE_IN
+ 200, // ACTIVATED_TRANSFORM
+ 300, // DEACTIVATED_FADE_OUT
+};
+
+// Returns the InkDropState sub animation duration for the given |state|.
+base::TimeDelta GetAnimationDuration(InkDropSubAnimations state) {
+ return base::TimeDelta::FromMilliseconds(
+ (views::InkDropAnimation::UseFastAnimations()
+ ? 1
+ : views::InkDropAnimation::kSlowAnimationDurationFactor) *
+ kAnimationDurationInMs[state]);
+}
+
+} // namespace
+
+namespace views {
+
+FloodFillInkDropAnimation::FloodFillInkDropAnimation(
+ const gfx::Rect& clip_bounds,
+ const gfx::Point& center_point,
+ SkColor color)
+ : clip_bounds_(clip_bounds),
+ center_point_(center_point),
+ root_layer_(ui::LAYER_NOT_DRAWN),
+ circle_layer_delegate_(
+ color,
+ std::max(clip_bounds_.width(), clip_bounds_.height()) / 2.f),
+ ink_drop_state_(InkDropState::HIDDEN) {
+ root_layer_.set_name("FloodFillInkDropAnimation:ROOT_LAYER");
+ root_layer_.SetMasksToBounds(true);
+ root_layer_.SetBounds(clip_bounds);
+
+ const int painted_size_length =
+ 2 * std::max(clip_bounds_.width(), clip_bounds_.height());
+
+ painted_layer_.SetBounds(gfx::Rect(painted_size_length, painted_size_length));
+ painted_layer_.SetFillsBoundsOpaquely(false);
+ painted_layer_.set_delegate(&circle_layer_delegate_);
+ painted_layer_.SetVisible(true);
+ painted_layer_.SetOpacity(1.0);
+ painted_layer_.SetMasksToBounds(false);
+ painted_layer_.set_name("FloodFillInkDropAnimation:PAINTED_LAYER");
+
+ root_layer_.Add(&painted_layer_);
+
+ SetStateToHidden();
+}
+
+FloodFillInkDropAnimation::~FloodFillInkDropAnimation() {
+ // Explicitly aborting all the animations ensures all callbacks are invoked
+ // while this instance still exists.
+ AbortAllAnimations();
+}
+
+void FloodFillInkDropAnimation::SnapToActivated() {
+ InkDropAnimation::SnapToActivated();
+ SetOpacity(kVisibleOpacity);
+ painted_layer_.SetTransform(GetMaxSizeTargetTransform());
+}
+
+ui::Layer* FloodFillInkDropAnimation::GetRootLayer() {
+ return &root_layer_;
+}
+
+bool FloodFillInkDropAnimation::IsVisible() const {
+ return root_layer_.visible();
+}
+
+void FloodFillInkDropAnimation::AnimateStateChange(
+ InkDropState old_ink_drop_state,
+ InkDropState new_ink_drop_state,
+ ui::LayerAnimationObserver* animation_observer) {
+ switch (new_ink_drop_state) {
+ case InkDropState::HIDDEN:
+ if (!IsVisible()) {
+ SetStateToHidden();
+ } else {
+ AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(HIDDEN_FADE_OUT),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ const gfx::Transform transform = CalculateTransform(kMinRadius);
+ AnimateToTransform(transform, GetAnimationDuration(HIDDEN_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ }
+ break;
+ case InkDropState::ACTION_PENDING: {
+ DCHECK(old_ink_drop_state == InkDropState::HIDDEN);
+
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_FADE_IN),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM) -
+ GetAnimationDuration(ACTION_PENDING_FADE_IN),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN, animation_observer);
+
+ AnimateToTransform(GetMaxSizeTargetTransform(),
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::FAST_OUT_SLOW_IN, animation_observer);
+ break;
+ }
+ case InkDropState::ACTION_TRIGGERED: {
+ DCHECK(old_ink_drop_state == InkDropState::HIDDEN ||
+ old_ink_drop_state == InkDropState::ACTION_PENDING);
+ if (old_ink_drop_state == InkDropState::HIDDEN) {
+ AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING,
+ animation_observer);
+ }
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(ACTION_TRIGGERED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::ALTERNATE_ACTION_PENDING: {
+ DCHECK(old_ink_drop_state == InkDropState::ACTION_PENDING);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ALTERNATE_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ AnimateToTransform(GetMaxSizeTargetTransform(),
+ GetAnimationDuration(ALTERNATE_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ DCHECK(old_ink_drop_state == InkDropState::ALTERNATE_ACTION_PENDING);
+ AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(
+ ALTERNATE_ACTION_TRIGGERED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ case InkDropState::ACTIVATED: {
+ AnimateToOpacity(kVisibleOpacity, GetAnimationDuration(ACTIVATED_FADE_IN),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ AnimateToTransform(GetMaxSizeTargetTransform(),
+ GetAnimationDuration(ACTIVATED_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::DEACTIVATED:
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(DEACTIVATED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+}
+
+void FloodFillInkDropAnimation::SetStateToHidden() {
+ painted_layer_.SetTransform(CalculateTransform(kMinRadius));
+ root_layer_.SetOpacity(InkDropAnimation::kHiddenOpacity);
+ root_layer_.SetVisible(false);
+}
+
+void FloodFillInkDropAnimation::AbortAllAnimations() {
+ root_layer_.GetAnimator()->AbortAllAnimations();
+ painted_layer_.GetAnimator()->AbortAllAnimations();
+}
+
+void FloodFillInkDropAnimation::AnimateToTransform(
+ const gfx::Transform& transform,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* animation_observer) {
+ ui::LayerAnimator* animator = painted_layer_.GetAnimator();
+ ui::ScopedLayerAnimationSettings animation(animator);
+ animation.SetPreemptionStrategy(preemption_strategy);
+ animation.SetTweenType(tween);
+ ui::LayerAnimationElement* element =
+ ui::LayerAnimationElement::CreateTransformElement(transform, duration);
+ ui::LayerAnimationSequence* sequence =
+ new ui::LayerAnimationSequence(element);
+
+ if (animation_observer)
+ sequence->AddObserver(animation_observer);
+
+ animator->StartAnimation(sequence);
+}
+
+void FloodFillInkDropAnimation::SetOpacity(float opacity) {
+ root_layer_.SetOpacity(opacity);
+}
+
+void FloodFillInkDropAnimation::AnimateToOpacity(
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* animation_observer) {
+ ui::LayerAnimator* animator = root_layer_.GetAnimator();
+ ui::ScopedLayerAnimationSettings animation_settings(animator);
+ animation_settings.SetPreemptionStrategy(preemption_strategy);
+ animation_settings.SetTweenType(tween);
+ ui::LayerAnimationElement* animation_element =
+ ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
+ ui::LayerAnimationSequence* animation_sequence =
+ new ui::LayerAnimationSequence(animation_element);
+
+ if (animation_observer)
+ animation_sequence->AddObserver(animation_observer);
+
+ animator->StartAnimation(animation_sequence);
+}
+
+gfx::Transform FloodFillInkDropAnimation::CalculateTransform(
+ float target_radius) const {
+ const float target_scale = target_radius / circle_layer_delegate_.radius();
+ const gfx::Point drawn_center_point =
+ ToRoundedPoint(circle_layer_delegate_.GetCenterPoint());
+
+ gfx::Transform transform = gfx::Transform();
+ transform.Translate(center_point_.x(), center_point_.y());
+ transform.Scale(target_scale, target_scale);
+ transform.Translate(-drawn_center_point.x() - root_layer_.bounds().x(),
+ -drawn_center_point.y() - root_layer_.bounds().y());
+
+ return transform;
+}
+
+gfx::Transform FloodFillInkDropAnimation::GetMaxSizeTargetTransform() const {
+ // TODO(estade): get rid of this 2, but make the fade out start before the
+ // active/action transform is done.
+ return CalculateTransform(
+ gfx::Vector2dF(clip_bounds_.width(), clip_bounds_.height()).Length() / 2);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/flood_fill_ink_drop_animation.h b/chromium/ui/views/animation/flood_fill_ink_drop_animation.h
new file mode 100644
index 00000000000..2ddde9647af
--- /dev/null
+++ b/chromium/ui/views/animation/flood_fill_ink_drop_animation.h
@@ -0,0 +1,131 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_ANIMATION_H_
+#define UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_ANIMATION_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
+#include "ui/views/animation/ink_drop_animation.h"
+#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class Layer;
+} // namespace ui
+
+namespace views {
+class CircleLayerDelegate;
+
+namespace test {
+class FloodFillInkDropAnimationTestApi;
+} // namespace test
+
+// An ink drop animation that starts as a small circle and flood fills a
+// rectangle of the given size. The circle is clipped to the rectangles bounds.
+//
+// The valid InkDropState transitions are defined below:
+//
+// {All InkDropStates} => HIDDEN
+// HIDDEN => ACTION_PENDING
+// HIDDEN, ACTION_PENDING => ACTION_TRIGGERED
+// ACTION_PENDING => ALTERNATE_ACTION_PENDING
+// ALTERNATE_ACTION_PENDING => ALTERNATE_ACTION_TRIGGERED
+// {All InkDropStates} => ACTIVATED
+// {All InkDropStates} => DEACTIVATED
+//
+class VIEWS_EXPORT FloodFillInkDropAnimation : public InkDropAnimation {
+ public:
+ FloodFillInkDropAnimation(const gfx::Rect& clip_bounds,
+ const gfx::Point& center_point,
+ SkColor color);
+ ~FloodFillInkDropAnimation() override;
+
+ // InkDropAnimation:
+ void SnapToActivated() override;
+ ui::Layer* GetRootLayer() override;
+ bool IsVisible() const override;
+
+ private:
+ friend class test::FloodFillInkDropAnimationTestApi;
+
+ // InkDropAnimation:
+ void AnimateStateChange(InkDropState old_ink_drop_state,
+ InkDropState new_ink_drop_state,
+ ui::LayerAnimationObserver* observer) override;
+ void SetStateToHidden() override;
+ void AbortAllAnimations() override;
+
+ // Animates the |painted_layer_| to the specified |transform|. The animation
+ // will be configured with the given |duration|, |tween|, and
+ // |preemption_strategy| values. The |observer| will be added to all
+ // LayerAnimationSequences if not null.
+ void AnimateToTransform(
+ const gfx::Transform& transform,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* observer);
+
+ // Sets the opacity of the ink drop. Note that this does not perform any
+ // animation.
+ void SetOpacity(float opacity);
+
+ // Animates the |painted_layer_| to the specified |opacity|. The animation
+ // will be configured with the given |duration|, |tween|, and
+ // |preemption_strategy| values. The |observer| will be added to all
+ // LayerAnimationSequences if not null.
+ void AnimateToOpacity(
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* observer);
+
+ // Returns the Transform to be applied to the |painted_layer_| for the given
+ // |target_radius|.
+ gfx::Transform CalculateTransform(float target_radius) const;
+
+ // Returns the target Transform for when the ink drop is fully shown.
+ gfx::Transform GetMaxSizeTargetTransform() const;
+
+ // The clip bounds.
+ const gfx::Rect clip_bounds_;
+
+ // The point where the Center of the ink drop's circle should be drawn.
+ gfx::Point center_point_;
+
+ // The root layer that parents the animating layer. The root layer is used to
+ // manipulate opacity and clipping bounds, and it child is used to manipulate
+ // the different shape of the ink drop.
+ ui::Layer root_layer_;
+
+ // ui::LayerDelegate to paint the |painted_layer_|.
+ CircleLayerDelegate circle_layer_delegate_;
+
+ // Child ui::Layer of |root_layer_|. Used to manipulate the different size
+ // and shape of the ink drop.
+ ui::Layer painted_layer_;
+
+ // The current ink drop state.
+ InkDropState ink_drop_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(FloodFillInkDropAnimation);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_FLOOD_FILL_INK_DROP_ANIMATION_H_
diff --git a/chromium/ui/views/animation/ink_drop_animation.cc b/chromium/ui/views/animation/ink_drop_animation.cc
index cf0c705e7ba..214716da23a 100644
--- a/chromium/ui/views/animation/ink_drop_animation.cc
+++ b/chromium/ui/views/animation/ink_drop_animation.cc
@@ -4,56 +4,18 @@
#include "ui/views/animation/ink_drop_animation.h"
-#include <algorithm>
-
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
-#include "base/logging.h"
-#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/callback_layer_animation_observer.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_animation_sequence.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/transform_util.h"
-#include "ui/views/animation/ink_drop_animation_observer.h"
-#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
-#include "ui/views/view.h"
-
-namespace {
-
-// The minimum scale factor to use when scaling rectangle layers. Smaller values
-// were causing visual anomalies.
-const float kMinimumRectScale = 0.0001f;
-
-// The minimum scale factor to use when scaling circle layers. Smaller values
-// were causing visual anomalies.
-const float kMinimumCircleScale = 0.001f;
-
-// The ink drop color.
-const SkColor kInkDropColor = SK_ColorBLACK;
-
-// The opacity of the ink drop when it is visible.
-const float kVisibleOpacity = 0.14f;
-// The opacity of the ink drop when it is not visible.
-const float kHiddenOpacity = 0.0f;
-
-// Durations for the different InkDropState animations in milliseconds.
-const int kHiddenStateAnimationDurationMs = 1;
-const int kActionPendingStateAnimationDurationMs = 500;
-const int kQuickActionStateAnimationDurationMs = 250;
-const int kSlowActionPendingStateAnimationDurationMs = 500;
-const int kSlowActionStateAnimationDurationMs = 250;
-const int kActivatedStateAnimationDurationMs = 125;
-const int kDeactivatedStateAnimationDurationMs = 250;
+namespace views {
-// A multiplicative factor used to slow down InkDropState animations.
-const int kSlowAnimationDurationFactor = 3;
+const double InkDropAnimation::kSlowAnimationDurationFactor = 3.0;
-// Checks CommandLine switches to determine if the visual feedback should have
-// a fast animations speed.
-bool UseFastAnimations() {
+bool InkDropAnimation::UseFastAnimations() {
static bool fast =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
(::switches::kMaterialDesignInkDropAnimationSpeed)) !=
@@ -61,391 +23,94 @@ bool UseFastAnimations() {
return fast;
}
-// Returns the InkDropState animation duration for the given |state|.
-base::TimeDelta GetAnimationDuration(views::InkDropState state) {
- int duration = 0;
- switch (state) {
- case views::InkDropState::HIDDEN:
- duration = kHiddenStateAnimationDurationMs;
- break;
- case views::InkDropState::ACTION_PENDING:
- duration = kActionPendingStateAnimationDurationMs;
- break;
- case views::InkDropState::QUICK_ACTION:
- duration = kQuickActionStateAnimationDurationMs;
- break;
- case views::InkDropState::SLOW_ACTION_PENDING:
- duration = kSlowActionPendingStateAnimationDurationMs;
- break;
- case views::InkDropState::SLOW_ACTION:
- duration = kSlowActionStateAnimationDurationMs;
- break;
- case views::InkDropState::ACTIVATED:
- duration = kActivatedStateAnimationDurationMs;
- break;
- case views::InkDropState::DEACTIVATED:
- duration = kDeactivatedStateAnimationDurationMs;
- break;
- }
-
- return base::TimeDelta::FromMilliseconds(
- (UseFastAnimations() ? 1 : kSlowAnimationDurationFactor) * duration);
-}
-
-// Calculates a Transform for a circle layer. The transform will be set up to
-// translate the |drawn_center_point| to the origin, scale, and then translate
-// to the target point defined by |target_center_x| and |target_center_y|.
-gfx::Transform CalculateCircleTransform(const gfx::Point& drawn_center_point,
- float scale,
- float target_center_x,
- float target_center_y) {
- gfx::Transform transform;
- transform.Translate(target_center_x, target_center_y);
- transform.Scale(scale, scale);
- transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
- return transform;
-}
-
-// Calculates a Transform for a rectangle layer. The transform will be set up to
-// translate the |drawn_center_point| to the origin and then scale by the
-// |x_scale| and |y_scale| factors.
-gfx::Transform CalculateRectTransform(const gfx::Point& drawn_center_point,
- float x_scale,
- float y_scale) {
- gfx::Transform transform;
- transform.Scale(x_scale, y_scale);
- transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
- return transform;
-}
-
-} // namespace
+const float InkDropAnimation::kHiddenOpacity = 0.f;
+const float InkDropAnimation::kVisibleOpacity = 0.175f;
-namespace views {
+InkDropAnimation::InkDropAnimation()
+ : target_ink_drop_state_(InkDropState::HIDDEN), observer_(nullptr) {}
-InkDropAnimation::InkDropAnimation(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius)
- : large_size_(large_size),
- large_corner_radius_(large_corner_radius),
- small_size_(small_size),
- small_corner_radius_(small_corner_radius),
- circle_layer_delegate_(new CircleLayerDelegate(
- kInkDropColor,
- std::min(large_size_.width(), large_size_.height()) / 2)),
- rect_layer_delegate_(
- new RectangleLayerDelegate(kInkDropColor, large_size_)),
- root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
- ink_drop_state_(InkDropState::HIDDEN) {
- root_layer_->set_name("InkDropAnimation:ROOT_LAYER");
-
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- AddPaintLayer(static_cast<PaintedShape>(i));
-
- root_layer_->SetMasksToBounds(false);
- root_layer_->SetBounds(gfx::Rect(large_size_));
-
- SetStateToHidden();
-}
-
-InkDropAnimation::~InkDropAnimation() {
- // Explicitly aborting all the animations ensures all callbacks are invoked
- // while this instance still exists.
- AbortAllAnimations();
-}
-
-void InkDropAnimation::AddObserver(InkDropAnimationObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void InkDropAnimation::RemoveObserver(InkDropAnimationObserver* observer) {
- observers_.RemoveObserver(observer);
-}
+InkDropAnimation::~InkDropAnimation() {}
void InkDropAnimation::AnimateToState(InkDropState ink_drop_state) {
+ // Does not return early if |target_ink_drop_state_| == |ink_drop_state| for
+ // two reasons.
+ // 1. The attached observers must be notified of all animations started and
+ // ended.
+ // 2. Not all state transitions is are valid, especially no-op transitions,
+ // and these should be detected by DCHECKs in AnimateStateChange().
+
// |animation_observer| will be deleted when AnimationEndedCallback() returns
// true.
+ // TODO(bruthig): Implement a safer ownership model for the
+ // |animation_observer|.
ui::CallbackLayerAnimationObserver* animation_observer =
new ui::CallbackLayerAnimationObserver(
base::Bind(&InkDropAnimation::AnimationStartedCallback,
base::Unretained(this), ink_drop_state),
base::Bind(&InkDropAnimation::AnimationEndedCallback,
base::Unretained(this), ink_drop_state));
- AnimateToStateInternal(ink_drop_state, animation_observer);
- animation_observer->SetActive();
-}
-void InkDropAnimation::SetCenterPoint(const gfx::Point& center_point) {
- gfx::Transform transform;
- transform.Translate(center_point.x(), center_point.y());
- root_layer_->SetTransform(transform);
-}
+ InkDropState old_ink_drop_state = target_ink_drop_state_;
+ // Assign to |target_ink_drop_state_| before calling AnimateStateChange() so
+ // that any observers notified as a side effect of the AnimateStateChange()
+ // will get the target InkDropState when calling GetInkDropState().
+ target_ink_drop_state_ = ink_drop_state;
-std::string InkDropAnimation::ToLayerName(PaintedShape painted_shape) {
- switch (painted_shape) {
- case TOP_LEFT_CIRCLE:
- return "TOP_LEFT_CIRCLE";
- case TOP_RIGHT_CIRCLE:
- return "TOP_RIGHT_CIRCLE";
- case BOTTOM_RIGHT_CIRCLE:
- return "BOTTOM_RIGHT_CIRCLE";
- case BOTTOM_LEFT_CIRCLE:
- return "BOTTOM_LEFT_CIRCLE";
- case HORIZONTAL_RECT:
- return "HORIZONTAL_RECT";
- case VERTICAL_RECT:
- return "VERTICAL_RECT";
- case PAINTED_SHAPE_COUNT:
- NOTREACHED() << "The PAINTED_SHAPE_COUNT value should never be used.";
- return "PAINTED_SHAPE_COUNT";
+ if (old_ink_drop_state == InkDropState::HIDDEN &&
+ target_ink_drop_state_ != InkDropState::HIDDEN) {
+ GetRootLayer()->SetVisible(true);
}
- return "UNKNOWN";
-}
-
-void InkDropAnimation::AnimateToStateInternal(
- InkDropState ink_drop_state,
- ui::LayerAnimationObserver* animation_observer) {
- ink_drop_state_ = ink_drop_state;
-
- if (ink_drop_state_ == InkDropState::HIDDEN) {
- // Animating to the HIDDEN state doesn't actually use any
- // LayerAnimationSequences so we need to explicitly abort any running ones
- // so that observers receive an InkDropAnimationEnded() event for the
- // running animation prior to receiving an InkDropAnimationStarted() event
- // for the HIDDEN 'animation'.
- AbortAllAnimations();
- root_layer_->SetVisible(false);
- SetStateToHidden();
- return;
- }
-
- InkDropTransforms transforms;
- root_layer_->SetVisible(true);
-
- switch (ink_drop_state_) {
- case InkDropState::HIDDEN:
- // This case is handled above in a short circuit return.
- break;
- case InkDropState::ACTION_PENDING:
- CalculateCircleTransforms(large_size_, &transforms);
- AnimateToTransforms(transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::ACTION_PENDING),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- case InkDropState::QUICK_ACTION:
- CalculateCircleTransforms(large_size_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::QUICK_ACTION),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- case InkDropState::SLOW_ACTION_PENDING:
- CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
- AnimateToTransforms(
- transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::SLOW_ACTION_PENDING),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- case InkDropState::SLOW_ACTION:
- CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::SLOW_ACTION),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- case InkDropState::ACTIVATED:
- CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kVisibleOpacity,
- GetAnimationDuration(InkDropState::ACTIVATED),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- case InkDropState::DEACTIVATED:
- CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
- AnimateToTransforms(transforms, kHiddenOpacity,
- GetAnimationDuration(InkDropState::DEACTIVATED),
- ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
- animation_observer);
- break;
- }
-}
-void InkDropAnimation::AnimateToTransforms(
- const InkDropTransforms transforms,
- float opacity,
- base::TimeDelta duration,
- ui::LayerAnimator::PreemptionStrategy preemption_strategy,
- ui::LayerAnimationObserver* animation_observer) {
- ui::LayerAnimator* root_animator = root_layer_->GetAnimator();
- ui::ScopedLayerAnimationSettings root_animation(root_animator);
- root_animation.SetPreemptionStrategy(preemption_strategy);
- ui::LayerAnimationElement* root_element =
- ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
- ui::LayerAnimationSequence* root_sequence =
- new ui::LayerAnimationSequence(root_element);
-
- if (animation_observer)
- root_sequence->AddObserver(animation_observer);
-
- root_animator->StartAnimation(root_sequence);
-
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) {
- ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator();
- ui::ScopedLayerAnimationSettings animation(animator);
- animation.SetPreemptionStrategy(preemption_strategy);
- ui::LayerAnimationElement* element =
- ui::LayerAnimationElement::CreateTransformElement(transforms[i],
- duration);
- ui::LayerAnimationSequence* sequence =
- new ui::LayerAnimationSequence(element);
-
- if (animation_observer)
- sequence->AddObserver(animation_observer);
-
- animator->StartAnimation(sequence);
- }
-}
-
-void InkDropAnimation::SetStateToHidden() {
- InkDropTransforms transforms;
- // Using a size of 0x0 creates visual anomalies.
- CalculateCircleTransforms(gfx::Size(1, 1), &transforms);
- SetTransforms(transforms);
- SetOpacity(kHiddenOpacity);
-}
-
-void InkDropAnimation::SetTransforms(const InkDropTransforms transforms) {
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- painted_layers_[i]->SetTransform(transforms[i]);
-}
-
-void InkDropAnimation::SetOpacity(float opacity) {
- root_layer_->SetOpacity(opacity);
-}
-
-void InkDropAnimation::CalculateCircleTransforms(
- const gfx::Size& size,
- InkDropTransforms* transforms_out) const {
- CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f,
- transforms_out);
-}
-
-void InkDropAnimation::CalculateRectTransforms(
- const gfx::Size& size,
- float corner_radius,
- InkDropTransforms* transforms_out) const {
- DCHECK_GE(size.width() / 2.0f, corner_radius)
- << "The circle's diameter should not be greater than the total width.";
- DCHECK_GE(size.height() / 2.0f, corner_radius)
- << "The circle's diameter should not be greater than the total height.";
-
- // The shapes are drawn such that their center points are not at the origin.
- // Thus we use the CalculateCircleTransform() and CalculateRectTransform()
- // methods to calculate the complex Transforms.
-
- const float circle_scale = std::max(
- kMinimumCircleScale,
- corner_radius / static_cast<float>(circle_layer_delegate_->radius()));
-
- const float circle_target_x_offset = size.width() / 2.0f - corner_radius;
- const float circle_target_y_offset = size.height() / 2.0f - corner_radius;
-
- (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- -circle_target_x_offset, -circle_target_y_offset);
-
- (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- circle_target_x_offset, -circle_target_y_offset);
-
- (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- circle_target_x_offset, circle_target_y_offset);
-
- (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform(
- ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
- -circle_target_x_offset, circle_target_y_offset);
-
- const float rect_delegate_width =
- static_cast<float>(rect_layer_delegate_->size().width());
- const float rect_delegate_height =
- static_cast<float>(rect_layer_delegate_->size().height());
-
- (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform(
- ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
- std::max(kMinimumRectScale, size.width() / rect_delegate_width),
- std::max(kMinimumRectScale,
- (size.height() - 2.0f * corner_radius) / rect_delegate_height));
-
- (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform(
- ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
- std::max(kMinimumRectScale,
- (size.width() - 2.0f * corner_radius) / rect_delegate_width),
- std::max(kMinimumRectScale, size.height() / rect_delegate_height));
+ AnimateStateChange(old_ink_drop_state, target_ink_drop_state_,
+ animation_observer);
+ animation_observer->SetActive();
+ // |this| may be deleted! |animation_observer| might synchronously call
+ // AnimationEndedCallback which can delete |this|.
}
-void InkDropAnimation::GetCurrentTansforms(
- InkDropTransforms* transforms_out) const {
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- (*transforms_out)[i] = painted_layers_[i]->GetTargetTransform();
+void InkDropAnimation::SnapToActivated() {
+ AbortAllAnimations();
+ // |animation_observer| will be deleted when AnimationEndedCallback() returns
+ // true.
+ // TODO(bruthig): Implement a safer ownership model for the
+ // |animation_observer|.
+ ui::CallbackLayerAnimationObserver* animation_observer =
+ new ui::CallbackLayerAnimationObserver(
+ base::Bind(&InkDropAnimation::AnimationStartedCallback,
+ base::Unretained(this), InkDropState::ACTIVATED),
+ base::Bind(&InkDropAnimation::AnimationEndedCallback,
+ base::Unretained(this), InkDropState::ACTIVATED));
+ GetRootLayer()->SetVisible(true);
+ target_ink_drop_state_ = InkDropState::ACTIVATED;
+ animation_observer->SetActive();
}
-void InkDropAnimation::AddPaintLayer(PaintedShape painted_shape) {
- ui::LayerDelegate* delegate = nullptr;
- switch (painted_shape) {
- case TOP_LEFT_CIRCLE:
- case TOP_RIGHT_CIRCLE:
- case BOTTOM_RIGHT_CIRCLE:
- case BOTTOM_LEFT_CIRCLE:
- delegate = circle_layer_delegate_.get();
- break;
- case HORIZONTAL_RECT:
- case VERTICAL_RECT:
- delegate = rect_layer_delegate_.get();
- break;
- case PAINTED_SHAPE_COUNT:
- NOTREACHED() << "PAINTED_SHAPE_COUNT is not an actual shape type.";
- break;
- }
-
- ui::Layer* layer = new ui::Layer();
- root_layer_->Add(layer);
-
- layer->SetBounds(gfx::Rect(large_size_));
- layer->SetFillsBoundsOpaquely(false);
- layer->set_delegate(delegate);
- layer->SetVisible(true);
- layer->SetOpacity(1.0);
- layer->SetMasksToBounds(false);
- layer->set_name("PAINTED_SHAPE_COUNT:" + ToLayerName(painted_shape));
-
- painted_layers_[painted_shape].reset(layer);
+void InkDropAnimation::HideImmediately() {
+ AbortAllAnimations();
+ SetStateToHidden();
+ target_ink_drop_state_ = InkDropState::HIDDEN;
}
-void InkDropAnimation::AbortAllAnimations() {
- root_layer_->GetAnimator()->AbortAllAnimations();
- for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
- painted_layers_[i]->GetAnimator()->AbortAllAnimations();
+test::InkDropAnimationTestApi* InkDropAnimation::GetTestApi() {
+ return nullptr;
}
void InkDropAnimation::AnimationStartedCallback(
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer) {
- FOR_EACH_OBSERVER(InkDropAnimationObserver, observers_,
- InkDropAnimationStarted(ink_drop_state));
+ observer_->AnimationStarted(ink_drop_state);
}
bool InkDropAnimation::AnimationEndedCallback(
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer) {
- FOR_EACH_OBSERVER(
- InkDropAnimationObserver, observers_,
- InkDropAnimationEnded(ink_drop_state,
+ if (ink_drop_state == InkDropState::HIDDEN)
+ SetStateToHidden();
+ observer_->AnimationEnded(ink_drop_state,
observer.aborted_count()
- ? InkDropAnimationObserver::PRE_EMPTED
- : InkDropAnimationObserver::SUCCESS));
+ ? InkDropAnimationEndedReason::PRE_EMPTED
+ : InkDropAnimationEndedReason::SUCCESS);
+ // |this| may be deleted!
return true;
}
diff --git a/chromium/ui/views/animation/ink_drop_animation.h b/chromium/ui/views/animation/ink_drop_animation.h
index abcd48c9cad..b00be7db26f 100644
--- a/chromium/ui/views/animation/ink_drop_animation.h
+++ b/chromium/ui/views/animation/ink_drop_animation.h
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,13 +6,8 @@
#define UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_H_
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "base/time/time.h"
-#include "ui/compositor/layer_animator.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_f.h"
-#include "ui/gfx/transform.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/views/animation/ink_drop_animation_observer.h"
#include "ui/views/animation/ink_drop_state.h"
#include "ui/views/views_export.h"
@@ -20,119 +15,95 @@ namespace ui {
class CallbackLayerAnimationObserver;
class Layer;
class LayerAnimationObserver;
-class LayerDelegate;
} // namespace ui
namespace views {
-class CircleLayerDelegate;
-class InkDropAnimationObserver;
-class RectangleLayerDelegate;
namespace test {
class InkDropAnimationTestApi;
} // namespace test
-// An ink drop animation that smoothly animates between a circle and a rounded
-// rectangle of different sizes for each of the different InkDropStates. The
-// final frame for each InkDropState will be bounded by either a |large_size_|
-// rectangle or a |small_size_| rectangle.
+// Simple base class for animations that provide visual feedback for View state.
+// Manages the attached InkDropAnimationObservers.
//
// TODO(bruthig): Document the ink drop ripple on chromium.org and add a link to
-// it.
+// the doc here.
class VIEWS_EXPORT InkDropAnimation {
public:
- InkDropAnimation(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius);
- ~InkDropAnimation();
+ // TODO(bruthig): Remove UseFastAnimations() and kSlowAnimationDurationFactor.
+ // See http://crbug.com/584681
+
+ // Checks CommandLine switches to determine if the visual feedback should have
+ // a fast animations speed.
+ static bool UseFastAnimations();
+
+ // The factor at which to increase the animation durations if
+ // UseFastAnimations() returns true.
+ static const double kSlowAnimationDurationFactor;
+
+ // The opacity of the ink drop when it is not visible.
+ static const float kHiddenOpacity;
+
+ // The opacity of the ink drop when it is visible.
+ static const float kVisibleOpacity;
+
+ InkDropAnimation();
+ virtual ~InkDropAnimation();
+
+ // In the event that an animation is in progress for ink drop state 's1' and
+ // an animation to a new state 's2' is triggered, then
+ // AnimationEnded(s1, PRE_EMPTED) will be called before
+ // AnimationStarted(s2).
+ void set_observer(InkDropAnimationObserver* observer) {
+ observer_ = observer;
+ }
+
+ // Animates from the current InkDropState to the new |ink_drop_state|.
+ //
+ // NOTE: GetTargetInkDropState() should return the new |ink_drop_state| value
+ // to any observers being notified as a result of the call.
+ void AnimateToState(InkDropState ink_drop_state);
+
+ InkDropState target_ink_drop_state() const { return target_ink_drop_state_; }
+
+ // Immediately aborts all in-progress animations and hides the ink drop.
+ //
+ // NOTE: This will NOT raise InkDropAnimation(Started|Ended) events for the
+ // state transition to HIDDEN!
+ void HideImmediately();
+
+ // Immediately snaps the ink drop to the ACTIVATED target state. All pending
+ // animations are aborted. Events will be raised for the pending animations
+ // as well as the transition to the ACTIVATED state.
+ virtual void SnapToActivated();
// The root Layer that can be added in to a Layer tree.
- ui::Layer* root_layer() { return root_layer_.get(); }
+ virtual ui::Layer* GetRootLayer() = 0;
- InkDropState ink_drop_state() const { return ink_drop_state_; }
+ // Returns true when the ripple is visible. This is different from checking if
+ // the ink_drop_state() == HIDDEN because the ripple may be visible while it
+ // animates to the target HIDDEN state.
+ virtual bool IsVisible() const = 0;
- void AddObserver(InkDropAnimationObserver* observer);
- void RemoveObserver(InkDropAnimationObserver* observer);
+ // Returns a test api to access internals of this. Default implmentations
+ // should return nullptr and test specific subclasses can override to return
+ // an instance.
+ virtual test::InkDropAnimationTestApi* GetTestApi();
- // Animates from the current |ink_drop_state_| to a new |ink_drop_state|. It
- // is possible to animate from any |ink_drop_state_| to any new
- // |ink_drop_state|. Note that some state transitions will also perform an
- // implicit transition to the another state. e.g. AnimateToState(QUICK_ACTION)
- // will implicitly transition to the HIDDEN state.
- void AnimateToState(InkDropState ink_drop_state);
+ protected:
+ // Animates the ripple from the |old_ink_drop_state| to the
+ // |new_ink_drop_state|. |observer| is added to all LayerAnimationSequence's
+ // used if not null.
+ virtual void AnimateStateChange(InkDropState old_ink_drop_state,
+ InkDropState new_ink_drop_state,
+ ui::LayerAnimationObserver* observer) = 0;
- // Sets the |center_point| of the ink drop layer relative to its parent Layer.
- void SetCenterPoint(const gfx::Point& center_point);
+ // Updates the transforms, opacity, and visibility to a HIDDEN state.
+ virtual void SetStateToHidden() = 0;
- private:
- friend class test::InkDropAnimationTestApi;
-
- // Enumeration of the different shapes that compose the ink drop.
- enum PaintedShape {
- TOP_LEFT_CIRCLE = 0,
- TOP_RIGHT_CIRCLE,
- BOTTOM_RIGHT_CIRCLE,
- BOTTOM_LEFT_CIRCLE,
- HORIZONTAL_RECT,
- VERTICAL_RECT,
- // The total number of shapes, not an actual shape.
- PAINTED_SHAPE_COUNT
- };
-
- // Returns a human readable string for the |painted_shape| value.
- static std::string ToLayerName(PaintedShape painted_shape);
-
- // Type that contains a gfx::Tansform for each of the layers required by the
- // ink drop.
- typedef gfx::Transform InkDropTransforms[PAINTED_SHAPE_COUNT];
-
- // Animates the ripple to |ink_drop_state| and attaches |observer| to all
- // LayerAnimationSequence's used.
- void AnimateToStateInternal(InkDropState ink_drop_state,
- ui::LayerAnimationObserver* observer);
-
- // Animates all of the painted shape layers to the specified |transforms| and
- // |opacity|. The animation will use the given |duration| and
- // |preemption_strategy|, and |observer| will be added to all
- // LayerAnimationSequences.
- void AnimateToTransforms(
- const InkDropTransforms transforms,
- float opacity,
- base::TimeDelta duration,
- ui::LayerAnimator::PreemptionStrategy preemption_strategy,
- ui::LayerAnimationObserver* observer);
-
- // Updates the Transforms and opacity to the HIDDEN state.
- void SetStateToHidden();
-
- // Sets the |transforms| on all of the shape layers. Note that this does not
- // perform any animation.
- void SetTransforms(const InkDropTransforms transforms);
-
- // Sets the opacity of the ink drop.
- void SetOpacity(float opacity);
-
- // Updates all of the Transforms in |transforms_out| for a circle of the given
- // |size|.
- void CalculateCircleTransforms(const gfx::Size& size,
- InkDropTransforms* transforms_out) const;
-
- // Updates all of the Transforms in |transforms_out| for a rounded rectangle
- // of the given |size| and |corner_radius|.
- void CalculateRectTransforms(const gfx::Size& size,
- float corner_radius,
- InkDropTransforms* transforms_out) const;
-
- // Updates all of the Transforms in |transforms_out| to the current target
- // Transforms of the Layers.
- void GetCurrentTansforms(InkDropTransforms* transforms_out) const;
-
- // Adds and configures a new |painted_shape| layer to |painted_layers_|.
- void AddPaintLayer(PaintedShape painted_shape);
-
- void AbortAllAnimations();
+ virtual void AbortAllAnimations() = 0;
+ private:
// The Callback invoked when all of the animation sequences for the specific
// |ink_drop_state| animation have started. |observer| is the
// ui::CallbackLayerAnimationObserver which is notifying the callback.
@@ -147,41 +118,10 @@ class VIEWS_EXPORT InkDropAnimation {
InkDropState ink_drop_state,
const ui::CallbackLayerAnimationObserver& observer);
- // Maximum size that an ink drop will be drawn to for any InkDropState whose
- // final frame should be large.
- gfx::Size large_size_;
-
- // Corner radius used to draw the rounded rectangles corner for any
- // InkDropState whose final frame should be large.
- int large_corner_radius_;
-
- // Maximum size that an ink drop will be drawn to for any InkDropState whose
- // final frame should be small.
- gfx::Size small_size_;
-
- // Corner radius used to draw the rounded rectangles corner for any
- // InkDropState whose final frame should be small.
- int small_corner_radius_;
-
- // ui::LayerDelegate to paint circles for all the circle layers.
- scoped_ptr<CircleLayerDelegate> circle_layer_delegate_;
-
- // ui::LayerDelegate to paint rectangles for all the rectangle layers.
- scoped_ptr<RectangleLayerDelegate> rect_layer_delegate_;
-
- // The root layer that parents the animating layers. The root layer is used to
- // manipulate opacity and location, and its children are used to manipulate
- // the different painted shapes that compose the ink drop.
- scoped_ptr<ui::Layer> root_layer_;
-
- // ui::Layers for all of the painted shape layers that compose the ink drop.
- scoped_ptr<ui::Layer> painted_layers_[PAINTED_SHAPE_COUNT];
-
- // The current ink drop state.
- InkDropState ink_drop_state_;
+ // The target InkDropState.
+ InkDropState target_ink_drop_state_;
- // List of observers to notify when animations have finished.
- base::ObserverList<InkDropAnimationObserver> observers_;
+ InkDropAnimationObserver* observer_;
DISALLOW_COPY_AND_ASSIGN(InkDropAnimation);
};
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller.h b/chromium/ui/views/animation/ink_drop_animation_controller.h
index d4d4fce96bb..ec511e21986 100644
--- a/chromium/ui/views/animation/ink_drop_animation_controller.h
+++ b/chromium/ui/views/animation/ink_drop_animation_controller.h
@@ -21,28 +21,30 @@ class Layer;
namespace views {
-// Pure virtual base class that manages an ink drop animation's lifetime and
-// state.
+// Pure virtual base class that manages the lifetime and state of an ink drop
+// animation as well as visual hover state feedback.
class VIEWS_EXPORT InkDropAnimationController {
public:
virtual ~InkDropAnimationController() {}
- // Gets the current state of the ink drop.
- virtual InkDropState GetInkDropState() const = 0;
+ // Gets the target state of the ink drop.
+ virtual InkDropState GetTargetInkDropState() const = 0;
+
+ // Returns true when the ripple is visible, including when animating to
+ // HIDDEN.
+ virtual bool IsVisible() const = 0;
// Animates from the current InkDropState to |ink_drop_state|.
virtual void AnimateToState(InkDropState ink_drop_state) = 0;
- virtual gfx::Size GetInkDropLargeSize() const = 0;
-
- // Sets the different sizes of the ink drop.
- virtual void SetInkDropSize(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius) = 0;
+ // Immediately snaps the InkDropState to ACTIVATED. This more specific
+ // implementation of the non-existent SnapToState(InkDropState) function is
+ // the only one available because it was the only InkDropState that clients
+ // needed to skip animations for.
+ virtual void SnapToActivated() = 0;
- // Sets the |center_point| of the ink drop relative to its parent Layer.
- virtual void SetInkDropCenter(const gfx::Point& center_point) = 0;
+ // Enables or disables the hover state.
+ virtual void SetHovered(bool is_hovered) = 0;
protected:
InkDropAnimationController() {}
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller_factory.cc b/chromium/ui/views/animation/ink_drop_animation_controller_factory.cc
index 6a3f8a37bfc..19bae013b57 100644
--- a/chromium/ui/views/animation/ink_drop_animation_controller_factory.cc
+++ b/chromium/ui/views/animation/ink_drop_animation_controller_factory.cc
@@ -5,7 +5,7 @@
#include "ui/views/animation/ink_drop_animation_controller_factory.h"
#include "base/macros.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/ink_drop_animation_controller.h"
@@ -25,14 +25,11 @@ class InkDropAnimationControllerStub
~InkDropAnimationControllerStub() override;
// InkDropAnimationController:
- InkDropState GetInkDropState() const override;
+ InkDropState GetTargetInkDropState() const override;
+ bool IsVisible() const override;
void AnimateToState(InkDropState state) override;
- gfx::Size GetInkDropLargeSize() const override;
- void SetInkDropSize(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius) override;
- void SetInkDropCenter(const gfx::Point& center_point) override;
+ void SnapToActivated() override;
+ void SetHovered(bool is_hovered) override;
private:
DISALLOW_COPY_AND_ASSIGN(InkDropAnimationControllerStub);
@@ -42,23 +39,19 @@ InkDropAnimationControllerStub::InkDropAnimationControllerStub() {}
InkDropAnimationControllerStub::~InkDropAnimationControllerStub() {}
-InkDropState InkDropAnimationControllerStub::GetInkDropState() const {
+InkDropState InkDropAnimationControllerStub::GetTargetInkDropState() const {
return InkDropState::HIDDEN;
}
-void InkDropAnimationControllerStub::AnimateToState(InkDropState state) {}
-
-gfx::Size InkDropAnimationControllerStub::GetInkDropLargeSize() const {
- return gfx::Size();
+bool InkDropAnimationControllerStub::IsVisible() const {
+ return false;
}
-void InkDropAnimationControllerStub::SetInkDropSize(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius) {}
+void InkDropAnimationControllerStub::AnimateToState(InkDropState state) {}
+
+void InkDropAnimationControllerStub::SnapToActivated() {}
-void InkDropAnimationControllerStub::SetInkDropCenter(
- const gfx::Point& center_point) {}
+void InkDropAnimationControllerStub::SetHovered(bool is_hovered) {}
} // namespace
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller_factory_unittest.cc b/chromium/ui/views/animation/ink_drop_animation_controller_factory_unittest.cc
index 1743c59355d..c75b2c23d7b 100644
--- a/chromium/ui/views/animation/ink_drop_animation_controller_factory_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_animation_controller_factory_unittest.cc
@@ -4,12 +4,16 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/test/material_design_controller_test_api.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/views/animation/ink_drop_animation_controller.h"
#include "ui/views/animation/ink_drop_animation_controller_factory.h"
+#include "ui/views/animation/ink_drop_animation_controller_impl.h"
#include "ui/views/animation/ink_drop_host.h"
#include "ui/views/animation/ink_drop_state.h"
#include "ui/views/animation/test/test_ink_drop_host.h"
@@ -17,7 +21,8 @@
namespace views {
class InkDropAnimationControllerFactoryTest
- : public testing::TestWithParam<ui::MaterialDesignController::Mode> {
+ : public testing::TestWithParam<
+ testing::tuple<ui::MaterialDesignController::Mode>> {
public:
InkDropAnimationControllerFactoryTest();
~InkDropAnimationControllerFactoryTest();
@@ -31,8 +36,14 @@ class InkDropAnimationControllerFactoryTest
scoped_ptr<InkDropAnimationController> ink_drop_animation_controller_;
private:
+ // Extracts and returns the material design mode from the test parameters.
+ ui::MaterialDesignController::Mode GetMaterialMode() const;
+
scoped_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
+ // Required by base::Timer's.
+ scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
+
DISALLOW_COPY_AND_ASSIGN(InkDropAnimationControllerFactoryTest);
};
@@ -42,16 +53,28 @@ InkDropAnimationControllerFactoryTest::InkDropAnimationControllerFactoryTest()
// initialize and cache the mode. This ensures that these tests will run from
// a non-initialized state.
ui::test::MaterialDesignControllerTestAPI::UninitializeMode();
- ui::test::MaterialDesignControllerTestAPI::SetMode(GetParam());
+ ui::test::MaterialDesignControllerTestAPI::SetMode(GetMaterialMode());
ink_drop_animation_controller_.reset(
InkDropAnimationControllerFactory::CreateInkDropAnimationController(
&test_ink_drop_host_)
.release());
- ink_drop_animation_controller_->SetInkDropSize(gfx::Size(10, 10), 4,
- gfx::Size(8, 8), 2);
zero_duration_mode_.reset(new ui::ScopedAnimationDurationScaleMode(
ui::ScopedAnimationDurationScaleMode::ZERO_DURATION));
+
+ switch (GetMaterialMode()) {
+ case ui::MaterialDesignController::NON_MATERIAL:
+ break;
+ case ui::MaterialDesignController::MATERIAL_NORMAL:
+ case ui::MaterialDesignController::MATERIAL_HYBRID:
+ // The Timer's used by the InkDropAnimationControllerImpl class require a
+ // base::ThreadTaskRunnerHandle instance.
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner(
+ new base::TestMockTimeTaskRunner);
+ thread_task_runner_handle_.reset(
+ new base::ThreadTaskRunnerHandle(task_runner));
+ break;
+ }
}
InkDropAnimationControllerFactoryTest::
@@ -59,56 +82,72 @@ InkDropAnimationControllerFactoryTest::
ui::test::MaterialDesignControllerTestAPI::UninitializeMode();
}
+ui::MaterialDesignController::Mode
+InkDropAnimationControllerFactoryTest::GetMaterialMode() const {
+ return testing::get<0>(GetParam());
+}
+
// Note: First argument is optional and intentionally left blank.
// (it's a prefix for the generated test cases)
INSTANTIATE_TEST_CASE_P(
,
InkDropAnimationControllerFactoryTest,
testing::Values(ui::MaterialDesignController::NON_MATERIAL,
- ui::MaterialDesignController::MATERIAL_NORMAL));
+ ui::MaterialDesignController::MATERIAL_NORMAL,
+ ui::MaterialDesignController::MATERIAL_HYBRID));
TEST_P(InkDropAnimationControllerFactoryTest,
- VerifyAllInkDropLayersRemovedAfterDestruction) {
+ VerifyInkDropLayersRemovedAfterDestructionWhenRippleIsActive) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
ink_drop_animation_controller_.reset();
EXPECT_EQ(0, test_ink_drop_host_.num_ink_drop_layers());
}
+TEST_P(InkDropAnimationControllerFactoryTest,
+ VerifyInkDropLayersRemovedAfterDestructionWhenHoverIsActive) {
+ test_ink_drop_host_.set_should_show_hover(true);
+ ink_drop_animation_controller_->SetHovered(true);
+ ink_drop_animation_controller_.reset();
+ EXPECT_EQ(0, test_ink_drop_host_.num_ink_drop_layers());
+}
+
TEST_P(InkDropAnimationControllerFactoryTest, StateIsHiddenInitially) {
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, TypicalQuickAction) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
- ink_drop_animation_controller_->AnimateToState(InkDropState::QUICK_ACTION);
+ ink_drop_animation_controller_->AnimateToState(
+ InkDropState::ACTION_TRIGGERED);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, CancelQuickAction) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(InkDropState::HIDDEN);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, TypicalSlowAction) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(
- InkDropState::SLOW_ACTION_PENDING);
- ink_drop_animation_controller_->AnimateToState(InkDropState::SLOW_ACTION);
+ InkDropState::ALTERNATE_ACTION_PENDING);
+ ink_drop_animation_controller_->AnimateToState(
+ InkDropState::ALTERNATE_ACTION_TRIGGERED);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, CancelSlowAction) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(
- InkDropState::SLOW_ACTION_PENDING);
+ InkDropState::ALTERNATE_ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(InkDropState::HIDDEN);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, TypicalQuickActivated) {
@@ -116,17 +155,17 @@ TEST_P(InkDropAnimationControllerFactoryTest, TypicalQuickActivated) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTIVATED);
ink_drop_animation_controller_->AnimateToState(InkDropState::DEACTIVATED);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
TEST_P(InkDropAnimationControllerFactoryTest, TypicalSlowActivated) {
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(
- InkDropState::SLOW_ACTION_PENDING);
+ InkDropState::ALTERNATE_ACTION_PENDING);
ink_drop_animation_controller_->AnimateToState(InkDropState::ACTIVATED);
ink_drop_animation_controller_->AnimateToState(InkDropState::DEACTIVATED);
EXPECT_EQ(InkDropState::HIDDEN,
- ink_drop_animation_controller_->GetInkDropState());
+ ink_drop_animation_controller_->GetTargetInkDropState());
}
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller_impl.cc b/chromium/ui/views/animation/ink_drop_animation_controller_impl.cc
index 74d681d8d63..62e953ba606 100644
--- a/chromium/ui/views/animation/ink_drop_animation_controller_impl.cc
+++ b/chromium/ui/views/animation/ink_drop_animation_controller_impl.cc
@@ -4,104 +4,256 @@
#include "ui/views/animation/ink_drop_animation_controller_impl.h"
-#include "ui/views/animation/ink_drop_animation.h"
+#include "base/auto_reset.h"
+#include "base/timer/timer.h"
+#include "ui/compositor/layer.h"
#include "ui/views/animation/ink_drop_host.h"
+#include "ui/views/animation/ink_drop_hover.h"
+#include "ui/views/animation/square_ink_drop_animation.h"
namespace views {
+namespace {
+
+// The duration, in milliseconds, of the hover state fade in animation when it
+// is triggered by user input.
+const int kHoverFadeInFromUserInputDurationInMs = 250;
+
+// The duration, in milliseconds, of the hover state fade out animation when it
+// is triggered by user input.
+const int kHoverFadeOutFromUserInputDurationInMs = 250;
+
+// The duration, in milliseconds, of the hover state fade in animation when it
+// is triggered by an ink drop ripple animation ending.
+const int kHoverFadeInAfterAnimationDurationInMs = 250;
+
+// The duration, in milliseconds, of the hover state fade out animation when it
+// is triggered by an ink drop ripple animation starting.
+const int kHoverFadeOutBeforeAnimationDurationInMs = 120;
+
+// The amount of time in milliseconds that |hover_| should delay after a ripple
+// animation before fading in.
+const int kHoverFadeInAfterAnimationDelayInMs = 1000;
+
+// Returns true if an ink drop with the given |ink_drop_state| should
+// automatically transition to the InkDropState::HIDDEN state.
+bool ShouldAnimateToHidden(InkDropState ink_drop_state) {
+ switch (ink_drop_state) {
+ case views::InkDropState::ACTION_TRIGGERED:
+ case views::InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ case views::InkDropState::DEACTIVATED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+} // namespace
+
InkDropAnimationControllerImpl::InkDropAnimationControllerImpl(
InkDropHost* ink_drop_host)
- : ink_drop_host_(ink_drop_host) {}
+ : ink_drop_host_(ink_drop_host),
+ root_layer_(new ui::Layer(ui::LAYER_NOT_DRAWN)),
+ root_layer_added_to_host_(false),
+ is_hovered_(false),
+ hover_after_animation_timer_(nullptr) {
+ root_layer_->set_name("InkDropAnimationControllerImpl:RootLayer");
+}
InkDropAnimationControllerImpl::~InkDropAnimationControllerImpl() {
// Explicitly destroy the InkDropAnimation so that this still exists if
// views::InkDropAnimationObserver methods are called on this.
DestroyInkDropAnimation();
+ DestroyInkDropHover();
}
-InkDropState InkDropAnimationControllerImpl::GetInkDropState() const {
+InkDropState InkDropAnimationControllerImpl::GetTargetInkDropState() const {
if (!ink_drop_animation_)
return InkDropState::HIDDEN;
- return ink_drop_animation_->ink_drop_state();
+ return ink_drop_animation_->target_ink_drop_state();
+}
+
+bool InkDropAnimationControllerImpl::IsVisible() const {
+ return ink_drop_animation_ && ink_drop_animation_->IsVisible();
}
void InkDropAnimationControllerImpl::AnimateToState(
InkDropState ink_drop_state) {
+ DestroyHiddenTargetedAnimations();
if (!ink_drop_animation_)
CreateInkDropAnimation();
+
+ if (ink_drop_state != views::InkDropState::HIDDEN) {
+ SetHoveredInternal(false, base::TimeDelta::FromMilliseconds(
+ kHoverFadeOutBeforeAnimationDurationInMs),
+ true);
+ }
+
ink_drop_animation_->AnimateToState(ink_drop_state);
}
-gfx::Size InkDropAnimationControllerImpl::GetInkDropLargeSize() const {
- return ink_drop_large_size_;
+void InkDropAnimationControllerImpl::SnapToActivated() {
+ DestroyHiddenTargetedAnimations();
+ if (!ink_drop_animation_)
+ CreateInkDropAnimation();
+
+ SetHoveredInternal(false, base::TimeDelta(), false);
+
+ ink_drop_animation_->SnapToActivated();
}
-void InkDropAnimationControllerImpl::SetInkDropSize(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius) {
- // TODO(bruthig): Fix the ink drop animations to work for non-square sizes.
- DCHECK_EQ(large_size.width(), large_size.height())
- << "The ink drop animation does not currently support non-square sizes.";
- DCHECK_EQ(small_size.width(), small_size.height())
- << "The ink drop animation does not currently support non-square sizes.";
- ink_drop_large_size_ = large_size;
- ink_drop_large_corner_radius_ = large_corner_radius;
- ink_drop_small_size_ = small_size;
- ink_drop_small_corner_radius_ = small_corner_radius;
- ink_drop_animation_.reset();
+void InkDropAnimationControllerImpl::SetHovered(bool is_hovered) {
+ is_hovered_ = is_hovered;
+ SetHoveredInternal(is_hovered,
+ is_hovered ? base::TimeDelta::FromMilliseconds(
+ kHoverFadeInFromUserInputDurationInMs)
+ : base::TimeDelta::FromMilliseconds(
+ kHoverFadeOutFromUserInputDurationInMs),
+ false);
}
-void InkDropAnimationControllerImpl::SetInkDropCenter(
- const gfx::Point& center_point) {
- ink_drop_center_ = center_point;
- if (ink_drop_animation_)
- ink_drop_animation_->SetCenterPoint(ink_drop_center_);
+void InkDropAnimationControllerImpl::DestroyHiddenTargetedAnimations() {
+ if (ink_drop_animation_ &&
+ (ink_drop_animation_->target_ink_drop_state() == InkDropState::HIDDEN ||
+ ShouldAnimateToHidden(ink_drop_animation_->target_ink_drop_state()))) {
+ DestroyInkDropAnimation();
+ }
}
void InkDropAnimationControllerImpl::CreateInkDropAnimation() {
DestroyInkDropAnimation();
-
- ink_drop_animation_.reset(new InkDropAnimation(
- ink_drop_large_size_, ink_drop_large_corner_radius_, ink_drop_small_size_,
- ink_drop_small_corner_radius_));
-
- ink_drop_animation_->AddObserver(this);
- ink_drop_animation_->SetCenterPoint(ink_drop_center_);
- ink_drop_host_->AddInkDropLayer(ink_drop_animation_->root_layer());
+ ink_drop_animation_ = ink_drop_host_->CreateInkDropAnimation();
+ ink_drop_animation_->set_observer(this);
+ root_layer_->Add(ink_drop_animation_->GetRootLayer());
+ AddRootLayerToHostIfNeeded();
}
void InkDropAnimationControllerImpl::DestroyInkDropAnimation() {
if (!ink_drop_animation_)
return;
- ink_drop_host_->RemoveInkDropLayer(ink_drop_animation_->root_layer());
- ink_drop_animation_->RemoveObserver(this);
+ root_layer_->Remove(ink_drop_animation_->GetRootLayer());
ink_drop_animation_.reset();
+ RemoveRootLayerFromHostIfNeeded();
+}
+
+void InkDropAnimationControllerImpl::CreateInkDropHover() {
+ DestroyInkDropHover();
+
+ hover_ = ink_drop_host_->CreateInkDropHover();
+ if (!hover_)
+ return;
+ hover_->set_observer(this);
+ root_layer_->Add(hover_->layer());
+ AddRootLayerToHostIfNeeded();
+}
+
+void InkDropAnimationControllerImpl::DestroyInkDropHover() {
+ if (!hover_)
+ return;
+ root_layer_->Remove(hover_->layer());
+ hover_->set_observer(nullptr);
+ hover_.reset();
+ RemoveRootLayerFromHostIfNeeded();
+}
+
+void InkDropAnimationControllerImpl::AddRootLayerToHostIfNeeded() {
+ DCHECK(hover_ || ink_drop_animation_);
+ if (!root_layer_added_to_host_) {
+ root_layer_added_to_host_ = true;
+ ink_drop_host_->AddInkDropLayer(root_layer_.get());
+ }
+}
+
+void InkDropAnimationControllerImpl::RemoveRootLayerFromHostIfNeeded() {
+ if (root_layer_added_to_host_ && !hover_ && !ink_drop_animation_) {
+ root_layer_added_to_host_ = false;
+ ink_drop_host_->RemoveInkDropLayer(root_layer_.get());
+ }
+}
+
+bool InkDropAnimationControllerImpl::IsHoverFadingInOrVisible() const {
+ return hover_ && hover_->IsFadingInOrVisible();
}
-void InkDropAnimationControllerImpl::InkDropAnimationStarted(
+// -----------------------------------------------------------------------------
+// views::InkDropAnimationObserver:
+
+void InkDropAnimationControllerImpl::AnimationStarted(
InkDropState ink_drop_state) {}
-void InkDropAnimationControllerImpl::InkDropAnimationEnded(
+void InkDropAnimationControllerImpl::AnimationEnded(
InkDropState ink_drop_state,
InkDropAnimationEndedReason reason) {
- if (reason != SUCCESS)
+ if (reason != InkDropAnimationEndedReason::SUCCESS)
return;
- switch (ink_drop_state) {
- case views::InkDropState::QUICK_ACTION:
- case views::InkDropState::SLOW_ACTION:
- case views::InkDropState::DEACTIVATED:
- ink_drop_animation_->AnimateToState(views::InkDropState::HIDDEN);
- break;
- case views::InkDropState::HIDDEN:
- // TODO(bruthig): Investigate whether creating and destroying
- // InkDropAnimations is expensive and consider creating an
- // InkDropAnimationPool. See www.crbug.com/522175.
- DestroyInkDropAnimation();
- break;
- default:
- break;
+ if (ShouldAnimateToHidden(ink_drop_state)) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::HIDDEN);
+ } else if (ink_drop_state == views::InkDropState::HIDDEN) {
+ if (is_hovered_)
+ StartHoverAfterAnimationTimer();
+ // TODO(bruthig): Investigate whether creating and destroying
+ // InkDropAnimations is expensive and consider creating an
+ // InkDropAnimationPool. See www.crbug.com/522175.
+ DestroyInkDropAnimation();
}
}
+// -----------------------------------------------------------------------------
+// views::InkDropHoverObserver:
+
+void InkDropAnimationControllerImpl::AnimationStarted(
+ InkDropHover::AnimationType animation_type) {}
+
+void InkDropAnimationControllerImpl::AnimationEnded(
+ InkDropHover::AnimationType animation_type,
+ InkDropAnimationEndedReason reason) {
+ if (animation_type == InkDropHover::FADE_OUT &&
+ reason == InkDropAnimationEndedReason::SUCCESS) {
+ DestroyInkDropHover();
+ }
+}
+
+void InkDropAnimationControllerImpl::SetHoveredInternal(
+ bool is_hovered,
+ base::TimeDelta animation_duration,
+ bool explode) {
+ StopHoverAfterAnimationTimer();
+
+ if (IsHoverFadingInOrVisible() == is_hovered)
+ return;
+
+ if (is_hovered) {
+ CreateInkDropHover();
+ if (hover_ && !IsVisible())
+ hover_->FadeIn(animation_duration);
+ } else {
+ hover_->FadeOut(animation_duration, explode);
+ }
+}
+
+void InkDropAnimationControllerImpl::StartHoverAfterAnimationTimer() {
+ StopHoverAfterAnimationTimer();
+
+ if (!hover_after_animation_timer_)
+ hover_after_animation_timer_.reset(new base::OneShotTimer);
+
+ hover_after_animation_timer_->Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kHoverFadeInAfterAnimationDelayInMs),
+ base::Bind(&InkDropAnimationControllerImpl::HoverAfterAnimationTimerFired,
+ base::Unretained(this)));
+}
+
+void InkDropAnimationControllerImpl::StopHoverAfterAnimationTimer() {
+ if (hover_after_animation_timer_)
+ hover_after_animation_timer_.reset();
+}
+
+void InkDropAnimationControllerImpl::HoverAfterAnimationTimerFired() {
+ SetHoveredInternal(true, base::TimeDelta::FromMilliseconds(
+ kHoverFadeInAfterAnimationDurationInMs),
+ true);
+ hover_after_animation_timer_.reset();
+}
+
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller_impl.h b/chromium/ui/views/animation/ink_drop_animation_controller_impl.h
index c5338835b0d..f39e4b9dd8a 100644
--- a/chromium/ui/views/animation/ink_drop_animation_controller_impl.h
+++ b/chromium/ui/views/animation/ink_drop_animation_controller_impl.h
@@ -11,16 +11,28 @@
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/ink_drop_animation_controller.h"
#include "ui/views/animation/ink_drop_animation_observer.h"
+#include "ui/views/animation/ink_drop_hover_observer.h"
#include "ui/views/views_export.h"
+namespace base {
+class Timer;
+} // namespace base
+
namespace views {
+namespace test {
+class InkDropAnimationControllerImplTestApi;
+} // namespace test
+
class InkDropAnimation;
class InkDropHost;
+class InkDropHover;
+class InkDropAnimationControllerFactoryTest;
// A functional implementation of an InkDropAnimationController.
class VIEWS_EXPORT InkDropAnimationControllerImpl
: public InkDropAnimationController,
- public InkDropAnimationObserver {
+ public InkDropAnimationObserver,
+ public InkDropHoverObserver {
public:
// Constructs an ink drop controller that will attach the ink drop to the
// given |ink_drop_host|.
@@ -28,16 +40,18 @@ class VIEWS_EXPORT InkDropAnimationControllerImpl
~InkDropAnimationControllerImpl() override;
// InkDropAnimationController:
- InkDropState GetInkDropState() const override;
+ InkDropState GetTargetInkDropState() const override;
+ bool IsVisible() const override;
void AnimateToState(InkDropState ink_drop_state) override;
- gfx::Size GetInkDropLargeSize() const override;
- void SetInkDropSize(const gfx::Size& large_size,
- int large_corner_radius,
- const gfx::Size& small_size,
- int small_corner_radius) override;
- void SetInkDropCenter(const gfx::Point& center_point) override;
+ void SnapToActivated() override;
+ void SetHovered(bool is_hovered) override;
private:
+ friend class test::InkDropAnimationControllerImplTestApi;
+
+ // Destroys |ink_drop_animation_| if it's targeted to the HIDDEN state.
+ void DestroyHiddenTargetedAnimations();
+
// Creates a new InkDropAnimation and sets it to |ink_drop_animation_|. If
// |ink_drop_animation_| wasn't null then it will be destroyed using
// DestroyInkDropAnimation().
@@ -46,33 +60,79 @@ class VIEWS_EXPORT InkDropAnimationControllerImpl
// Destroys the current |ink_drop_animation_|.
void DestroyInkDropAnimation();
- // views::InkDropAnimationObserver:
- void InkDropAnimationStarted(InkDropState ink_drop_state) override;
- void InkDropAnimationEnded(InkDropState ink_drop_state,
- InkDropAnimationEndedReason reason) override;
+ // Creates a new InkDropHover and sets it to |hover_|. If |hover_| wasn't null
+ // then it will be destroyed using DestroyInkDropHover().
+ void CreateInkDropHover();
- // The host of the ink drop.
- InkDropHost* ink_drop_host_;
+ // Destroys the current |hover_|.
+ void DestroyInkDropHover();
- // Cached size for the ink drop's large size animations.
- gfx::Size ink_drop_large_size_;
+ // Adds the |root_layer_| to the |ink_drop_host_| if it hasn't already been
+ // added.
+ void AddRootLayerToHostIfNeeded();
- // Cached corner radius for the ink drop's large size animations.
- int ink_drop_large_corner_radius_;
+ // Removes the |root_layer_| from the |ink_drop_host_| if no ink drop ripple
+ // or hover is active.
+ void RemoveRootLayerFromHostIfNeeded();
- // Cached size for the ink drop's small size animations.
- gfx::Size ink_drop_small_size_;
+ // Returns true if the hover animation is in the process of fading in or
+ // is visible.
+ bool IsHoverFadingInOrVisible() const;
- // Cached corner radius for the ink drop's small size animations.
- int ink_drop_small_corner_radius_;
+ // views::InkDropAnimationObserver:
+ void AnimationStarted(InkDropState ink_drop_state) override;
+ void AnimationEnded(InkDropState ink_drop_state,
+ InkDropAnimationEndedReason reason) override;
+
+ // views::InkDropHoverObserver:
+ void AnimationStarted(InkDropHover::AnimationType animation_type) override;
+ void AnimationEnded(InkDropHover::AnimationType animation_type,
+ InkDropAnimationEndedReason reason) override;
+
+ // Enables or disables the hover state based on |is_hovered| and if an
+ // animation is triggered it will be scheduled to have the given
+ // |animation_duration|. If |explode| is true the hover will expand as it
+ // fades out. |explode| is ignored when |is_hovered| is true.
+ void SetHoveredInternal(bool is_hovered,
+ base::TimeDelta animation_duration,
+ bool explode);
+
+ // Starts the |hover_after_animation_timer_| timer. This will stop the current
+ // |hover_after_animation_timer_| instance if it exists.
+ void StartHoverAfterAnimationTimer();
+
+ // Stops and destroys the current |hover_after_animation_timer_| instance.
+ void StopHoverAfterAnimationTimer();
+
+ // Callback for when the |hover_after_animation_timer_| fires.
+ void HoverAfterAnimationTimerFired();
+
+ // The host of the ink drop. Used to poll for information such as whether the
+ // hover should be shown or not.
+ InkDropHost* ink_drop_host_;
+
+ // The root Layer that parents the InkDropAnimation layers and the
+ // InkDropHover layers. The |root_layer_| is the one that is added and removed
+ // from the InkDropHost.
+ scoped_ptr<ui::Layer> root_layer_;
- // Cached center point for the ink drop.
- gfx::Point ink_drop_center_;
+ // True when the |root_layer_| has been added to the |ink_drop_host_|.
+ bool root_layer_added_to_host_;
+
+ // The current InkDropHover. Lazily created using CreateInkDropHover();
+ scoped_ptr<InkDropHover> hover_;
+
+ // Tracks the logical hovered state of |this| as manipulated by the public
+ // SetHovered() function.
+ bool is_hovered_;
// The current InkDropAnimation. Created on demand using
// CreateInkDropAnimation().
scoped_ptr<InkDropAnimation> ink_drop_animation_;
+ // The timer used to delay the hover fade in after an ink drop animation.
+ scoped_ptr<base::Timer> hover_after_animation_timer_;
+
DISALLOW_COPY_AND_ASSIGN(InkDropAnimationControllerImpl);
};
diff --git a/chromium/ui/views/animation/ink_drop_animation_controller_impl_unittest.cc b/chromium/ui/views/animation/ink_drop_animation_controller_impl_unittest.cc
new file mode 100644
index 00000000000..75e1d4cea76
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_animation_controller_impl_unittest.cc
@@ -0,0 +1,241 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_animation_controller_impl.h"
+
+#include "base/macros.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/animation/ink_drop_animation.h"
+#include "ui/views/animation/test/ink_drop_animation_controller_impl_test_api.h"
+#include "ui/views/animation/test/test_ink_drop_host.h"
+
+namespace views {
+
+// NOTE: The InkDropAnimationControllerImpl class is also tested by the
+// InkDropAnimationControllerFactoryTest tests.
+class InkDropAnimationControllerImplTest : public testing::Test {
+ public:
+ InkDropAnimationControllerImplTest();
+ ~InkDropAnimationControllerImplTest() override;
+
+ protected:
+ TestInkDropHost ink_drop_host_;
+
+ // The test target.
+ InkDropAnimationControllerImpl ink_drop_animation_controller_;
+
+ // Allows privileged access to the the |ink_drop_hover_|.
+ test::InkDropAnimationControllerImplTestApi test_api_;
+
+ // Used to control the tasks scheduled by the InkDropAnimationControllerImpl's
+ // Timer.
+ scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+
+ // Required by base::Timer's.
+ scoped_ptr<base::ThreadTaskRunnerHandle> thread_task_runner_handle_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropAnimationControllerImplTest);
+};
+
+InkDropAnimationControllerImplTest::InkDropAnimationControllerImplTest()
+ : ink_drop_animation_controller_(&ink_drop_host_),
+ test_api_(&ink_drop_animation_controller_),
+ task_runner_(new base::TestSimpleTaskRunner),
+ thread_task_runner_handle_(
+ new base::ThreadTaskRunnerHandle(task_runner_)) {
+ ink_drop_host_.set_disable_timers_for_test(true);
+}
+
+InkDropAnimationControllerImplTest::~InkDropAnimationControllerImplTest() {}
+
+TEST_F(InkDropAnimationControllerImplTest, SetHoveredIsFadingInOrVisible) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_TRUE(test_api_.IsHoverFadingInOrVisible());
+
+ test_api_.CompleteAnimations();
+
+ ink_drop_animation_controller_.SetHovered(false);
+ EXPECT_FALSE(test_api_.IsHoverFadingInOrVisible());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ HoverDoesntFadeInAfterAnimationIfHoverNotSet) {
+ ink_drop_host_.set_should_show_hover(true);
+ ink_drop_animation_controller_.SetHovered(false);
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ test_api_.CompleteAnimations();
+
+ EXPECT_FALSE(task_runner_->HasPendingTask());
+ EXPECT_FALSE(test_api_.IsHoverFadingInOrVisible());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ HoverFadesInAfterAnimationWhenHostIsHovered) {
+ ink_drop_host_.set_should_show_hover(true);
+ ink_drop_animation_controller_.SetHovered(true);
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ test_api_.CompleteAnimations();
+
+ EXPECT_TRUE(task_runner_->HasPendingTask());
+
+ task_runner_->RunPendingTasks();
+
+ EXPECT_TRUE(test_api_.IsHoverFadingInOrVisible());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ HoverDoesntFadeInAfterAnimationWhenHostIsNotHovered) {
+ ink_drop_host_.set_should_show_hover(false);
+ ink_drop_animation_controller_.SetHovered(true);
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ test_api_.CompleteAnimations();
+
+ EXPECT_TRUE(task_runner_->HasPendingTask());
+
+ task_runner_->RunPendingTasks();
+
+ EXPECT_FALSE(test_api_.IsHoverFadingInOrVisible());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ HoveredStateNotVisibleOrFadingInAfterAnimateToState) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ ink_drop_animation_controller_.SetHovered(true);
+ test_api_.CompleteAnimations();
+ EXPECT_TRUE(test_api_.IsHoverFadingInOrVisible());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ EXPECT_FALSE(test_api_.IsHoverFadingInOrVisible());
+}
+
+// Verifies that there is not a crash when setting hovered state and the host
+// returns null for the hover.
+TEST_F(InkDropAnimationControllerImplTest,
+ SetHoveredFalseWorksWhenNoInkDropHoverExists) {
+ ink_drop_host_.set_should_show_hover(false);
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_FALSE(test_api_.hover());
+ ink_drop_animation_controller_.SetHovered(false);
+ EXPECT_FALSE(test_api_.hover());
+}
+
+TEST_F(InkDropAnimationControllerImplTest, HoverFadesOutOnSnapToActivated) {
+ ink_drop_host_.set_should_show_hover(true);
+ ink_drop_animation_controller_.SetHovered(true);
+ test_api_.CompleteAnimations();
+
+ EXPECT_TRUE(test_api_.IsHoverFadingInOrVisible());
+
+ ink_drop_animation_controller_.SnapToActivated();
+
+ EXPECT_FALSE(test_api_.IsHoverFadingInOrVisible());
+}
+
+TEST_F(InkDropAnimationControllerImplTest, LayersRemovedFromHostAfterHover) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ test_api_.CompleteAnimations();
+
+ ink_drop_animation_controller_.SetHovered(false);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ test_api_.CompleteAnimations();
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+}
+
+TEST_F(InkDropAnimationControllerImplTest, LayersRemovedFromHostAfterInkDrop) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_PENDING);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::HIDDEN);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ test_api_.CompleteAnimations();
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ LayersAddedToHostWhenHoverOrInkDropVisible) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_PENDING);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::HIDDEN);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ test_api_.CompleteAnimations();
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ EXPECT_TRUE(task_runner_->HasPendingTask());
+ task_runner_->RunPendingTasks();
+
+ // Hover should be fading back in.
+ EXPECT_TRUE(test_api_.HasActiveAnimations());
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ LayersNotAddedToHostWhenHoverTimeFires) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::ACTION_PENDING);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.AnimateToState(InkDropState::HIDDEN);
+ test_api_.CompleteAnimations();
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_host_.set_should_show_hover(false);
+
+ EXPECT_TRUE(task_runner_->HasPendingTask());
+ task_runner_->RunPendingTasks();
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+}
+
+TEST_F(InkDropAnimationControllerImplTest,
+ LayersArentRemovedWhenPreemptingFadeOut) {
+ ink_drop_host_.set_should_show_hover(true);
+
+ EXPECT_EQ(0, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ test_api_.CompleteAnimations();
+
+ ink_drop_animation_controller_.SetHovered(false);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+
+ ink_drop_animation_controller_.SetHovered(true);
+ EXPECT_EQ(1, ink_drop_host_.num_ink_drop_layers());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_animation_ended_reason.cc b/chromium/ui/views/animation/ink_drop_animation_ended_reason.cc
new file mode 100644
index 00000000000..8499995cd34
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_animation_ended_reason.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_animation_ended_reason.h"
+
+#include "base/logging.h"
+
+namespace views {
+
+std::string ToString(InkDropAnimationEndedReason reason) {
+ switch (reason) {
+ case InkDropAnimationEndedReason::SUCCESS:
+ return "SUCCESS";
+ case InkDropAnimationEndedReason::PRE_EMPTED:
+ return "PRE_EMPTED";
+ }
+ NOTREACHED()
+ << "Should never be reached but is necessary for some compilers.";
+ return std::string();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_animation_ended_reason.h b/chromium/ui/views/animation/ink_drop_animation_ended_reason.h
new file mode 100644
index 00000000000..fc2f359cef2
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_animation_ended_reason.h
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_ENDED_REASON_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_ENDED_REASON_H_
+
+#include <string>
+
+namespace views {
+
+// Enumeration of the different reasons why an ink drop animation has finished.
+enum class InkDropAnimationEndedReason {
+ // The animation was completed successfully.
+ SUCCESS,
+ // The animation was stopped prematurely before reaching its final state.
+ PRE_EMPTED
+};
+
+// Returns a human readable string for |reason|. Useful for logging.
+std::string ToString(InkDropAnimationEndedReason reason);
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_ENDED_REASON_H_
diff --git a/chromium/ui/views/animation/ink_drop_animation_observer.cc b/chromium/ui/views/animation/ink_drop_animation_observer.cc
deleted file mode 100644
index c76ffb291b1..00000000000
--- a/chromium/ui/views/animation/ink_drop_animation_observer.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/animation/ink_drop_animation_observer.h"
-
-#include <string>
-
-#include "base/logging.h"
-
-namespace views {
-
-std::string ToString(
- InkDropAnimationObserver::InkDropAnimationEndedReason reason) {
- switch (reason) {
- case InkDropAnimationObserver::SUCCESS:
- return std::string("SUCCESS");
- case InkDropAnimationObserver::PRE_EMPTED:
- return std::string("PRE_EMPTED");
- }
- NOTREACHED()
- << "Should never be reached but is necessary for some compilers.";
- return std::string();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_animation_observer.h b/chromium/ui/views/animation/ink_drop_animation_observer.h
index 3eb3b1d2412..831a6be06b3 100644
--- a/chromium/ui/views/animation/ink_drop_animation_observer.h
+++ b/chromium/ui/views/animation/ink_drop_animation_observer.h
@@ -8,49 +8,34 @@
#include <string>
#include "base/macros.h"
+#include "ui/views/animation/ink_drop_animation_ended_reason.h"
#include "ui/views/animation/ink_drop_state.h"
#include "ui/views/views_export.h"
namespace views {
-// Pure-virtual base class of an observer that can be attached to
-// InkDropAnimations.
+// Observer to attach to an InkDropAnimation.
class VIEWS_EXPORT InkDropAnimationObserver {
public:
- // Enumeration of the different reasons why an InkDropAnimation has finished.
- enum InkDropAnimationEndedReason {
- // The animation was completed successfully.
- SUCCESS,
- // The animation was stopped prematurely before reaching its final state.
- PRE_EMPTED
- };
-
- // Notifies the observer that an animation for |ink_drop_state| has started.
- virtual void InkDropAnimationStarted(InkDropState ink_drop_state) = 0;
-
- // Notifies the observer that an animation for |ink_drop_state| has finished
- // and the reason for completion is given by |reason|. If |reason| is SUCCESS
- // then the animation has progressed to its final frame however if |reason|
- // is |PRE_EMPTED| then the animation was stopped before its final frame. In
- // the event that an animation is in progress for ink drop state 's1' and an
- // animation to a new state 's2' is triggered, then
- // InkDropAnimationEnded(s1, PRE_EMPTED) will be called before
- // InkDropAnimationStarted(s2).
- virtual void InkDropAnimationEnded(InkDropState ink_drop_state,
- InkDropAnimationEndedReason reason) = 0;
+ // An animation for the given |ink_drop_state| has started.
+ virtual void AnimationStarted(InkDropState ink_drop_state) = 0;
+
+ // Notifies the observer that an animation for the given |ink_drop_state| has
+ // finished and the reason for completion is given by |reason|. If |reason| is
+ // SUCCESS then the animation has progressed to its final frame however if
+ // |reason| is |PRE_EMPTED| then the animation was stopped before its final
+ // frame.
+ virtual void AnimationEnded(InkDropState ink_drop_state,
+ InkDropAnimationEndedReason reason) = 0;
protected:
- InkDropAnimationObserver() {}
- virtual ~InkDropAnimationObserver() {}
+ InkDropAnimationObserver() = default;
+ virtual ~InkDropAnimationObserver() = default;
private:
DISALLOW_COPY_AND_ASSIGN(InkDropAnimationObserver);
};
-// Returns a human readable string for |reason|. Useful for logging.
-std::string ToString(
- InkDropAnimationObserver::InkDropAnimationEndedReason reason);
-
} // namespace views
#endif // UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_OBSERVER_H_
diff --git a/chromium/ui/views/animation/ink_drop_animation_unittest.cc b/chromium/ui/views/animation/ink_drop_animation_unittest.cc
index 91f8143416a..e1ff62c456c 100644
--- a/chromium/ui/views/animation/ink_drop_animation_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_animation_unittest.cc
@@ -9,293 +9,343 @@
#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_f.h"
+#include "ui/views/animation/flood_fill_ink_drop_animation.h"
#include "ui/views/animation/ink_drop_animation.h"
+#include "ui/views/animation/ink_drop_animation_observer.h"
#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/animation/square_ink_drop_animation.h"
+#include "ui/views/animation/test/flood_fill_ink_drop_animation_test_api.h"
#include "ui/views/animation/test/ink_drop_animation_test_api.h"
+#include "ui/views/animation/test/square_ink_drop_animation_test_api.h"
+#include "ui/views/animation/test/test_ink_drop_animation_observer.h"
namespace views {
namespace test {
-namespace {
-
-// Transforms a copy of |point| with |transform| and returns it.
-gfx::Point TransformPoint(const gfx::Transform& transform,
- const gfx::Point& point) {
- gfx::Point transformed_point = point;
- transform.TransformPoint(&transformed_point);
- return transformed_point;
-}
-
-} // namespace
+// Represents all the derivatives of the InkDropAnimation class. To be used with
+// the InkDropAnimationTest fixture to test all derviatives.
+enum InkDropAnimationTestTypes {
+ SQUARE_INK_DROP_ANIMATION,
+ FLOOD_FILL_INK_DROP_ANIMATION
+};
-class InkDropAnimationTest : public testing::Test {
+// Test fixture for all InkDropAnimation class derivatives.
+//
+// To add a new derivative:
+// 1. Add a value to the InkDropAnimationTestTypes enum.
+// 2. Implement set up and tear down code for the new enum value in
+// InkDropAnimationTest() and
+// ~InkDropAnimationTest().
+// 3. Add the new enum value to the INSTANTIATE_TEST_CASE_P) Values list.
+class InkDropAnimationTest
+ : public testing::TestWithParam<InkDropAnimationTestTypes> {
public:
- InkDropAnimationTest() {}
- ~InkDropAnimationTest() override {}
+ InkDropAnimationTest();
+ ~InkDropAnimationTest() override;
protected:
- scoped_ptr<InkDropAnimation> CreateInkDropAnimation() const;
+ TestInkDropAnimationObserver observer_;
+
+ scoped_ptr<InkDropAnimation> ink_drop_animation_;
+
+ scoped_ptr<InkDropAnimationTestApi> test_api_;
private:
DISALLOW_COPY_AND_ASSIGN(InkDropAnimationTest);
};
-// Returns a new InkDropAnimation with default parameters.
-scoped_ptr<InkDropAnimation> InkDropAnimationTest::CreateInkDropAnimation()
- const {
- return make_scoped_ptr(
- new InkDropAnimation(gfx::Size(10, 10), 2, gfx::Size(8, 8), 1));
+InkDropAnimationTest::InkDropAnimationTest() {
+ switch (GetParam()) {
+ case SQUARE_INK_DROP_ANIMATION: {
+ SquareInkDropAnimation* square_ink_drop_animation =
+ new SquareInkDropAnimation(gfx::Size(10, 10), 2, gfx::Size(8, 8), 1,
+ gfx::Point(), SK_ColorBLACK);
+ ink_drop_animation_.reset(square_ink_drop_animation);
+ test_api_.reset(
+ new SquareInkDropAnimationTestApi(square_ink_drop_animation));
+ break;
+ }
+ case FLOOD_FILL_INK_DROP_ANIMATION: {
+ FloodFillInkDropAnimation* flood_fill_ink_drop_animation =
+ new FloodFillInkDropAnimation(gfx::Rect(0, 0, 10, 10), gfx::Point(),
+ SK_ColorBLACK);
+ ink_drop_animation_.reset(flood_fill_ink_drop_animation);
+ test_api_.reset(
+ new FloodFillInkDropAnimationTestApi(flood_fill_ink_drop_animation));
+ break;
+ }
+ }
+ ink_drop_animation_->set_observer(&observer_);
+ observer_.set_ink_drop_animation(ink_drop_animation_.get());
+ test_api_->SetDisableAnimationTimers(true);
+}
+
+InkDropAnimationTest::~InkDropAnimationTest() {}
+
+// Note: First argument is optional and intentionally left blank.
+// (it's a prefix for the generated test cases)
+INSTANTIATE_TEST_CASE_P(,
+ InkDropAnimationTest,
+ testing::Values(SQUARE_INK_DROP_ANIMATION,
+ FLOOD_FILL_INK_DROP_ANIMATION));
+
+TEST_P(InkDropAnimationTest, InitialStateAfterConstruction) {
+ EXPECT_EQ(views::InkDropState::HIDDEN,
+ ink_drop_animation_->target_ink_drop_state());
+}
+
+// Verify no animations are used when animating from HIDDEN to HIDDEN.
+TEST_P(InkDropAnimationTest, AnimateToHiddenFromInvisibleState) {
+ EXPECT_EQ(InkDropState::HIDDEN, ink_drop_animation_->target_ink_drop_state());
+
+ ink_drop_animation_->AnimateToState(InkDropState::HIDDEN);
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+ EXPECT_FALSE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest, InitialStateAfterConstruction) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- EXPECT_EQ(views::InkDropState::HIDDEN, ink_drop_animation->ink_drop_state());
+TEST_P(InkDropAnimationTest, AnimateToHiddenFromVisibleState) {
+ ink_drop_animation_->AnimateToState(InkDropState::ACTION_PENDING);
+ test_api_->CompleteAnimations();
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+
+ EXPECT_NE(InkDropState::HIDDEN, ink_drop_animation_->target_ink_drop_state());
+
+ ink_drop_animation_->AnimateToState(InkDropState::HIDDEN);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(3, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(4, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+}
+
+TEST_P(InkDropAnimationTest, ActionPendingOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kVisibleOpacity, test_api_->GetCurrentOpacity());
+}
+
+TEST_P(InkDropAnimationTest, QuickActionOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_TRIGGERED);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+}
+
+TEST_P(InkDropAnimationTest, SlowActionPendingOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(
+ views::InkDropState::ALTERNATE_ACTION_PENDING);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kVisibleOpacity, test_api_->GetCurrentOpacity());
+}
+
+TEST_P(InkDropAnimationTest, SlowActionOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(
+ views::InkDropState::ALTERNATE_ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(
+ views::InkDropState::ALTERNATE_ACTION_TRIGGERED);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+}
+
+TEST_P(InkDropAnimationTest, ActivatedOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTIVATED);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kVisibleOpacity, test_api_->GetCurrentOpacity());
}
-TEST_F(InkDropAnimationTest, AnimateToActionPending) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::ACTION_PENDING);
+TEST_P(InkDropAnimationTest, DeactivatedOpacity) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTIVATED);
+ ink_drop_animation_->AnimateToState(views::InkDropState::DEACTIVATED);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+}
+
+// Verify animations are aborted during deletion and the
+// InkDropAnimationObservers are notified.
+TEST_P(InkDropAnimationTest, AnimationsAbortedDuringDeletion) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_.reset();
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
- ink_drop_animation->ink_drop_state());
+ observer_.last_animation_ended_context());
+ EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
+ observer_.last_animation_ended_reason());
+}
+
+TEST_P(InkDropAnimationTest, VerifyObserversAreNotified) {
+ ink_drop_animation_->AnimateToState(InkDropState::ACTION_PENDING);
+
+ EXPECT_TRUE(test_api_->HasActiveAnimations());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_TRUE(observer_.AnimationHasNotEnded());
+ EXPECT_EQ(InkDropState::ACTION_PENDING,
+ observer_.last_animation_started_context());
+
+ test_api_->CompleteAnimations();
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropState::ACTION_PENDING,
+ observer_.last_animation_ended_context());
+}
+
+TEST_P(InkDropAnimationTest, VerifyObserversAreNotifiedOfSuccessfulAnimations) {
+ ink_drop_animation_->AnimateToState(InkDropState::ACTION_PENDING);
+ test_api_->CompleteAnimations();
+
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropAnimationEndedReason::SUCCESS,
+ observer_.last_animation_ended_reason());
+}
+
+TEST_P(InkDropAnimationTest, VerifyObserversAreNotifiedOfPreemptedAnimations) {
+ ink_drop_animation_->AnimateToState(InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(InkDropState::ALTERNATE_ACTION_PENDING);
+
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
+ observer_.last_animation_ended_reason());
+}
+
+TEST_P(InkDropAnimationTest, InkDropStatesPersistWhenCallingAnimateToState) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTIVATED);
+ EXPECT_EQ(views::InkDropState::ACTIVATED,
+ ink_drop_animation_->target_ink_drop_state());
}
-TEST_F(InkDropAnimationTest, AnimateToQuickAction) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::QUICK_ACTION);
- EXPECT_EQ(views::InkDropState::QUICK_ACTION,
- ink_drop_animation->ink_drop_state());
+TEST_P(InkDropAnimationTest, HideImmediatelyWithoutActiveAnimations) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ test_api_->CompleteAnimations();
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_NE(InkDropState::HIDDEN, ink_drop_animation_->target_ink_drop_state());
+
+ ink_drop_animation_->HideImmediately();
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_EQ(views::InkDropState::HIDDEN,
+ ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+ EXPECT_FALSE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest, AnimateToSlowActionPending) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::SLOW_ACTION_PENDING);
- EXPECT_EQ(views::InkDropState::SLOW_ACTION_PENDING,
- ink_drop_animation->ink_drop_state());
+// Verifies all active animations are aborted and the InkDropState is set to
+// HIDDEN after invoking HideImmediately().
+TEST_P(InkDropAnimationTest, HideImmediatelyWithActiveAnimations) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ EXPECT_TRUE(test_api_->HasActiveAnimations());
+ EXPECT_NE(InkDropState::HIDDEN, ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+
+ ink_drop_animation_->HideImmediately();
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_EQ(views::InkDropState::HIDDEN,
+ ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropState::ACTION_PENDING,
+ observer_.last_animation_ended_context());
+ EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
+ observer_.last_animation_ended_reason());
+
+ EXPECT_EQ(InkDropAnimation::kHiddenOpacity, test_api_->GetCurrentOpacity());
+ EXPECT_FALSE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest, AnimateToSlowAction) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::SLOW_ACTION);
- EXPECT_EQ(views::InkDropState::SLOW_ACTION,
- ink_drop_animation->ink_drop_state());
+TEST_P(InkDropAnimationTest, SnapToActivatedWithoutActiveAnimations) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ test_api_->CompleteAnimations();
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_NE(InkDropState::ACTIVATED,
+ ink_drop_animation_->target_ink_drop_state());
+
+ ink_drop_animation_->SnapToActivated();
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
+ EXPECT_EQ(views::InkDropState::ACTIVATED,
+ ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(3, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(4, observer_.last_animation_ended_ordinal());
+
+ EXPECT_EQ(InkDropAnimation::kVisibleOpacity, test_api_->GetCurrentOpacity());
+ EXPECT_TRUE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest, AnimateToActivated) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::ACTIVATED);
+// Verifies all active animations are aborted and the InkDropState is set to
+// ACTIVATED after invoking SnapToActivated().
+TEST_P(InkDropAnimationTest, SnapToActivatedWithActiveAnimations) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ EXPECT_TRUE(test_api_->HasActiveAnimations());
+ EXPECT_NE(InkDropState::ACTIVATED,
+ ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+
+ ink_drop_animation_->SnapToActivated();
+
+ EXPECT_FALSE(test_api_->HasActiveAnimations());
EXPECT_EQ(views::InkDropState::ACTIVATED,
- ink_drop_animation->ink_drop_state());
+ ink_drop_animation_->target_ink_drop_state());
+ EXPECT_EQ(3, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(4, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropState::ACTIVATED, observer_.last_animation_ended_context());
+ EXPECT_EQ(InkDropAnimationEndedReason::SUCCESS,
+ observer_.last_animation_ended_reason());
+
+ EXPECT_EQ(InkDropAnimation::kVisibleOpacity, test_api_->GetCurrentOpacity());
+ EXPECT_TRUE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest, AnimateToDeactivated) {
- scoped_ptr<InkDropAnimation> ink_drop_animation = CreateInkDropAnimation();
- ink_drop_animation->AnimateToState(views::InkDropState::DEACTIVATED);
- EXPECT_EQ(views::InkDropState::DEACTIVATED,
- ink_drop_animation->ink_drop_state());
+TEST_P(InkDropAnimationTest, AnimateToVisibleFromHidden) {
+ EXPECT_EQ(InkDropState::HIDDEN, ink_drop_animation_->target_ink_drop_state());
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ EXPECT_TRUE(ink_drop_animation_->IsVisible());
}
-TEST_F(InkDropAnimationTest,
- TransformedPointsUsingTransformsFromCalculateCircleTransforms) {
- const int kHalfDrawnSize = 5;
- const int kDrawnSize = 2 * kHalfDrawnSize;
-
- const int kHalfTransformedSize = 100;
- const int kTransformedSize = 2 * kHalfTransformedSize;
-
- // Constant points in the drawn space that will be transformed.
- const gfx::Point center(kHalfDrawnSize, kHalfDrawnSize);
- const gfx::Point mid_left(0, kHalfDrawnSize);
- const gfx::Point mid_right(kDrawnSize, kHalfDrawnSize);
- const gfx::Point top_mid(kHalfDrawnSize, 0);
- const gfx::Point bottom_mid(kHalfDrawnSize, kDrawnSize);
-
- scoped_ptr<InkDropAnimation> ink_drop_animation(
- new InkDropAnimation(gfx::Size(kDrawnSize, kDrawnSize), 2,
- gfx::Size(kHalfDrawnSize, kHalfDrawnSize), 1));
- InkDropAnimationTestApi test_api(ink_drop_animation.get());
-
- InkDropAnimationTestApi::InkDropTransforms transforms;
- test_api.CalculateCircleTransforms(
- gfx::Size(kTransformedSize, kTransformedSize), &transforms);
-
- // Transform variables to reduce verbosity of actual verification code.
- const gfx::Transform kTopLeftTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::TOP_LEFT_CIRCLE];
- const gfx::Transform kTopRightTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::TOP_RIGHT_CIRCLE];
- const gfx::Transform kBottomRightTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::BOTTOM_RIGHT_CIRCLE];
- const gfx::Transform kBottomLeftTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::BOTTOM_LEFT_CIRCLE];
- const gfx::Transform kHorizontalTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::HORIZONTAL_RECT];
- const gfx::Transform kVerticalTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::VERTICAL_RECT];
-
- // Top left circle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kTopLeftTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedSize, 0),
- TransformPoint(kTopLeftTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedSize, 0),
- TransformPoint(kTopLeftTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedSize),
- TransformPoint(kTopLeftTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedSize),
- TransformPoint(kTopLeftTransform, bottom_mid));
-
- // Top right circle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kTopRightTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedSize, 0),
- TransformPoint(kTopRightTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedSize, 0),
- TransformPoint(kTopRightTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedSize),
- TransformPoint(kTopRightTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedSize),
- TransformPoint(kTopRightTransform, bottom_mid));
-
- // Bottom right circle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kBottomRightTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedSize, 0),
- TransformPoint(kBottomRightTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedSize, 0),
- TransformPoint(kBottomRightTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedSize),
- TransformPoint(kBottomRightTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedSize),
- TransformPoint(kBottomRightTransform, bottom_mid));
-
- // Bottom left circle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kBottomLeftTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedSize, 0),
- TransformPoint(kBottomLeftTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedSize, 0),
- TransformPoint(kBottomLeftTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedSize),
- TransformPoint(kBottomLeftTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedSize),
- TransformPoint(kBottomLeftTransform, bottom_mid));
-
- // Horizontal rectangle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kHorizontalTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedSize, 0),
- TransformPoint(kHorizontalTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedSize, 0),
- TransformPoint(kHorizontalTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kHorizontalTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kHorizontalTransform, bottom_mid));
-
- // Vertical rectangle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kVerticalTransform, center));
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kVerticalTransform, mid_left));
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kVerticalTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedSize),
- TransformPoint(kVerticalTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedSize),
- TransformPoint(kVerticalTransform, bottom_mid));
+// Verifies that the value of InkDropAnimation::target_ink_drop_state() returns
+// the most recent value passed to AnimateToState() when notifying observers
+// that an animation has started within the AnimateToState() function call.
+TEST_P(InkDropAnimationTest, TargetInkDropStateOnAnimationStarted) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(views::InkDropState::HIDDEN);
+
+ EXPECT_EQ(3, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(views::InkDropState::HIDDEN,
+ observer_.target_state_at_last_animation_started());
}
-TEST_F(InkDropAnimationTest,
- TransformedPointsUsingTransformsFromCalculateRectTransforms) {
- const int kHalfDrawnSize = 5;
- const int kDrawnSize = 2 * kHalfDrawnSize;
-
- const int kTransformedRadius = 10;
-
- const int kHalfTransformedWidth = 100;
- const int kTransformedWidth = 2 * kHalfTransformedWidth;
-
- const int kHalfTransformedHeight = 100;
- const int kTransformedHeight = 2 * kHalfTransformedHeight;
-
- // Constant points in the drawn space that will be transformed.
- const gfx::Point center(kHalfDrawnSize, kHalfDrawnSize);
- const gfx::Point mid_left(0, kHalfDrawnSize);
- const gfx::Point mid_right(kDrawnSize, kHalfDrawnSize);
- const gfx::Point top_mid(kHalfDrawnSize, 0);
- const gfx::Point bottom_mid(kHalfDrawnSize, kDrawnSize);
-
- scoped_ptr<InkDropAnimation> ink_drop_animation(
- new InkDropAnimation(gfx::Size(kDrawnSize, kDrawnSize), 2,
- gfx::Size(kHalfDrawnSize, kHalfDrawnSize), 1));
- InkDropAnimationTestApi test_api(ink_drop_animation.get());
-
- InkDropAnimationTestApi::InkDropTransforms transforms;
- test_api.CalculateRectTransforms(
- gfx::Size(kTransformedWidth, kTransformedHeight), kTransformedRadius,
- &transforms);
-
- // Transform variables to reduce verbosity of actual verification code.
- const gfx::Transform kTopLeftTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::TOP_LEFT_CIRCLE];
- const gfx::Transform kTopRightTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::TOP_RIGHT_CIRCLE];
- const gfx::Transform kBottomRightTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::BOTTOM_RIGHT_CIRCLE];
- const gfx::Transform kBottomLeftTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::BOTTOM_LEFT_CIRCLE];
- const gfx::Transform kHorizontalTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::HORIZONTAL_RECT];
- const gfx::Transform kVerticalTransform =
- transforms[InkDropAnimationTestApi::PaintedShape::VERTICAL_RECT];
-
- const int x_offset = kHalfTransformedWidth - kTransformedRadius;
- const int y_offset = kHalfTransformedWidth - kTransformedRadius;
-
- // Top left circle
- EXPECT_EQ(gfx::Point(-x_offset, -y_offset),
- TransformPoint(kTopLeftTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedWidth, -y_offset),
- TransformPoint(kTopLeftTransform, mid_left));
- EXPECT_EQ(gfx::Point(-x_offset, -kHalfTransformedHeight),
- TransformPoint(kTopLeftTransform, top_mid));
-
- // Top right circle
- EXPECT_EQ(gfx::Point(x_offset, -y_offset),
- TransformPoint(kTopRightTransform, center));
- EXPECT_EQ(gfx::Point(kHalfTransformedWidth, -y_offset),
- TransformPoint(kTopRightTransform, mid_right));
- EXPECT_EQ(gfx::Point(x_offset, -kHalfTransformedHeight),
- TransformPoint(kTopRightTransform, top_mid));
-
- // Bottom right circle
- EXPECT_EQ(gfx::Point(x_offset, y_offset),
- TransformPoint(kBottomRightTransform, center));
- EXPECT_EQ(gfx::Point(kHalfTransformedWidth, y_offset),
- TransformPoint(kBottomRightTransform, mid_right));
- EXPECT_EQ(gfx::Point(x_offset, kHalfTransformedHeight),
- TransformPoint(kBottomRightTransform, bottom_mid));
-
- // Bottom left circle
- EXPECT_EQ(gfx::Point(-x_offset, y_offset),
- TransformPoint(kBottomLeftTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedWidth, y_offset),
- TransformPoint(kBottomLeftTransform, mid_left));
- EXPECT_EQ(gfx::Point(-x_offset, kHalfTransformedHeight),
- TransformPoint(kBottomLeftTransform, bottom_mid));
-
- // Horizontal rectangle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kHorizontalTransform, center));
- EXPECT_EQ(gfx::Point(-kHalfTransformedWidth, 0),
- TransformPoint(kHorizontalTransform, mid_left));
- EXPECT_EQ(gfx::Point(kHalfTransformedWidth, 0),
- TransformPoint(kHorizontalTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -y_offset),
- TransformPoint(kHorizontalTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, y_offset),
- TransformPoint(kHorizontalTransform, bottom_mid));
-
- // Vertical rectangle
- EXPECT_EQ(gfx::Point(0, 0), TransformPoint(kVerticalTransform, center));
- EXPECT_EQ(gfx::Point(-x_offset, 0),
- TransformPoint(kVerticalTransform, mid_left));
- EXPECT_EQ(gfx::Point(x_offset, 0),
- TransformPoint(kVerticalTransform, mid_right));
- EXPECT_EQ(gfx::Point(0, -kHalfTransformedHeight),
- TransformPoint(kVerticalTransform, top_mid));
- EXPECT_EQ(gfx::Point(0, kHalfTransformedHeight),
- TransformPoint(kVerticalTransform, bottom_mid));
+// Verifies that the value of InkDropAnimation::target_ink_drop_state() returns
+// the most recent value passed to AnimateToState() when notifying observers
+// that an animation has ended within the AnimateToState() function call.
+TEST_P(InkDropAnimationTest, TargetInkDropStateOnAnimationEnded) {
+ ink_drop_animation_->AnimateToState(views::InkDropState::ACTION_PENDING);
+ ink_drop_animation_->AnimateToState(views::InkDropState::HIDDEN);
+
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(views::InkDropState::HIDDEN,
+ observer_.target_state_at_last_animation_ended());
}
} // namespace test
diff --git a/chromium/ui/views/animation/ink_drop_delegate.h b/chromium/ui/views/animation/ink_drop_delegate.h
index 576b742a610..61235241f92 100644
--- a/chromium/ui/views/animation/ink_drop_delegate.h
+++ b/chromium/ui/views/animation/ink_drop_delegate.h
@@ -23,25 +23,18 @@ class VIEWS_EXPORT InkDropDelegate {
InkDropDelegate() {}
virtual ~InkDropDelegate() {}
- // Sets sizes for the animation layers that are squares with |large_size| and
- // |small_size| being the length of each side. When painting rounded squares
- // |large_corner_radius| and |small_corner_radius| are specifying the
- // corner radius.
- virtual void SetInkDropSize(int large_size,
- int large_corner_radius,
- int small_size,
- int small_corner_radius) = 0;
-
- // Called when the bounds or layout of the View changes necessitating change
- // in positioning of ink ripple layers.
- virtual void OnLayout() = 0;
-
// Called when ink ripple state changes.
// TODO(bruthig): Replace the InkDropState parameter with an InkDropAction
// enum. The InkDropAction enum should be a subset of the InkDropState values
// as well as a NONE value.
virtual void OnAction(InkDropState state) = 0;
+ // Immediately snaps the InkDropState to ACTIVATED.
+ virtual void SnapToActivated() = 0;
+
+ // Enables or disables the hover state.
+ virtual void SetHovered(bool is_hovered) = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(InkDropDelegate);
};
diff --git a/chromium/ui/views/animation/ink_drop_host.h b/chromium/ui/views/animation/ink_drop_host.h
index f50fac789d7..570f2710b49 100644
--- a/chromium/ui/views/animation/ink_drop_host.h
+++ b/chromium/ui/views/animation/ink_drop_host.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_ANIMATION_INK_DROP_HOST_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/views_export.h"
@@ -15,6 +16,9 @@ class Layer;
namespace views {
+class InkDropAnimation;
+class InkDropHover;
+
// Used by the InkDropAnimationController to add and remove the ink drop layers
// from a host's layer tree. Typically the ink drop layer is added to a View's
// layer but it can also be added to a View's ancestor layer.
@@ -33,9 +37,11 @@ class VIEWS_EXPORT InkDropHost {
// Removes |ink_drop_layer| from the layer tree.
virtual void RemoveInkDropLayer(ui::Layer* ink_drop_layer) = 0;
- // Returns the Point where the ink drop should be centered.
- // TODO(varkha): This should be moved to InkDropConsumer.
- virtual gfx::Point CalculateInkDropCenter() const = 0;
+ // Creates and returns the effect used for press.
+ virtual scoped_ptr<InkDropAnimation> CreateInkDropAnimation() const = 0;
+
+ // Creates and returns the effect used for hover.
+ virtual scoped_ptr<InkDropHover> CreateInkDropHover() const = 0;
private:
DISALLOW_COPY_AND_ASSIGN(InkDropHost);
diff --git a/chromium/ui/views/animation/ink_drop_host_view.cc b/chromium/ui/views/animation/ink_drop_host_view.cc
new file mode 100644
index 00000000000..317645e6118
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_host_view.cc
@@ -0,0 +1,74 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_host_view.h"
+
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/views/animation/ink_drop_hover.h"
+#include "ui/views/animation/square_ink_drop_animation.h"
+
+namespace views {
+
+// Default sizes for ink drop effects.
+const int kInkDropSize = 24;
+const int kInkDropLargeCornerRadius = 4;
+
+// The scale factor to compute the large ink drop size.
+const float kLargeInkDropScale = 1.333f;
+
+namespace {
+
+gfx::Size CalculateLargeInkDropSize(const gfx::Size small_size) {
+ return gfx::ScaleToCeiledSize(gfx::Size(small_size), kLargeInkDropScale);
+}
+
+} // namespace
+
+// static
+const int InkDropHostView::kInkDropSmallCornerRadius = 2;
+
+InkDropHostView::InkDropHostView()
+ : ink_drop_size_(kInkDropSize, kInkDropSize) {}
+
+InkDropHostView::~InkDropHostView() {}
+
+void InkDropHostView::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+ layer()->Add(ink_drop_layer);
+ layer()->StackAtBottom(ink_drop_layer);
+}
+
+void InkDropHostView::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ layer()->Remove(ink_drop_layer);
+ SetPaintToLayer(false);
+}
+
+scoped_ptr<InkDropAnimation> InkDropHostView::CreateInkDropAnimation() const {
+ scoped_ptr<InkDropAnimation> animation(new SquareInkDropAnimation(
+ CalculateLargeInkDropSize(ink_drop_size_), kInkDropLargeCornerRadius,
+ ink_drop_size_, kInkDropSmallCornerRadius, GetInkDropCenter(),
+ GetInkDropBaseColor()));
+ return animation;
+}
+
+scoped_ptr<InkDropHover> InkDropHostView::CreateInkDropHover() const {
+ scoped_ptr<InkDropHover> hover(
+ new InkDropHover(ink_drop_size_, kInkDropSmallCornerRadius,
+ GetInkDropCenter(), GetInkDropBaseColor()));
+ hover->set_explode_size(CalculateLargeInkDropSize(ink_drop_size_));
+ return hover;
+}
+
+gfx::Point InkDropHostView::GetInkDropCenter() const {
+ return GetLocalBounds().CenterPoint();
+}
+
+SkColor InkDropHostView::GetInkDropBaseColor() const {
+ NOTREACHED();
+ return gfx::kPlaceholderColor;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_host_view.h b/chromium/ui/views/animation/ink_drop_host_view.h
new file mode 100644
index 00000000000..3a3efa6b6ed
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_host_view.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_HOST_VIEW_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_HOST_VIEW_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/animation/ink_drop_host.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+class InkDropAnimation;
+class InkDropHover;
+
+// A view that provides InkDropHost functionality.
+class VIEWS_EXPORT InkDropHostView : public views::View, public InkDropHost {
+ public:
+ InkDropHostView();
+ ~InkDropHostView() override;
+
+ // Overridden from views::InkDropHost:
+ void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
+ void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
+ scoped_ptr<InkDropAnimation> CreateInkDropAnimation() const override;
+ scoped_ptr<InkDropHover> CreateInkDropHover() const override;
+
+ void set_ink_drop_size(const gfx::Size& size) { ink_drop_size_ = size; }
+
+ protected:
+ static const int kInkDropSmallCornerRadius;
+
+ // Overrideable methods to allow views to provide minor tweaks to the default
+ // ink drop.
+ virtual gfx::Point GetInkDropCenter() const;
+ virtual SkColor GetInkDropBaseColor() const;
+
+ private:
+ gfx::Size ink_drop_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(InkDropHostView);
+};
+}
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_HOST_VIEW_H_
diff --git a/chromium/ui/views/animation/ink_drop_hover.cc b/chromium/ui/views/animation/ink_drop_hover.cc
new file mode 100644
index 00000000000..af98e614f59
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_hover.cc
@@ -0,0 +1,146 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_hover.h"
+
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/callback_layer_animation_observer.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/views/animation/ink_drop_hover_observer.h"
+#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
+
+namespace views {
+
+namespace {
+
+// The opacity of the hover when it is visible.
+const float kHoverVisibleOpacity = 0.128f;
+
+// The opacity of the hover when it is not visible.
+const float kHiddenOpacity = 0.0f;
+
+} // namespace
+
+InkDropHover::InkDropHover(const gfx::Size& size,
+ int corner_radius,
+ const gfx::Point& center_point,
+ SkColor color)
+ : size_(size),
+ explode_size_(size),
+ center_point_(center_point),
+ last_animation_initiated_was_fade_in_(false),
+ layer_delegate_(
+ new RoundedRectangleLayerDelegate(color, size, corner_radius)),
+ layer_(new ui::Layer()),
+ observer_(nullptr) {
+ layer_->SetBounds(gfx::Rect(size));
+ layer_->SetFillsBoundsOpaquely(false);
+ layer_->set_delegate(layer_delegate_.get());
+ layer_->SetVisible(false);
+ layer_->SetOpacity(kHoverVisibleOpacity);
+ layer_->SetMasksToBounds(false);
+ layer_->set_name("InkDropHover:layer");
+}
+
+InkDropHover::~InkDropHover() {}
+
+bool InkDropHover::IsFadingInOrVisible() const {
+ return last_animation_initiated_was_fade_in_;
+}
+
+void InkDropHover::FadeIn(const base::TimeDelta& duration) {
+ layer_->SetOpacity(kHiddenOpacity);
+ layer_->SetVisible(true);
+ AnimateFade(FADE_IN, duration, size_, size_);
+}
+
+void InkDropHover::FadeOut(const base::TimeDelta& duration, bool explode) {
+ AnimateFade(FADE_OUT, duration, size_, explode ? explode_size_ : size_);
+}
+
+test::InkDropHoverTestApi* InkDropHover::GetTestApi() {
+ return nullptr;
+}
+
+void InkDropHover::AnimateFade(AnimationType animation_type,
+ const base::TimeDelta& duration,
+ const gfx::Size& initial_size,
+ const gfx::Size& target_size) {
+ last_animation_initiated_was_fade_in_ = animation_type == FADE_IN;
+
+ layer_->SetTransform(CalculateTransform(initial_size));
+
+ // The |animation_observer| will be destroyed when the
+ // AnimationStartedCallback() returns true.
+ ui::CallbackLayerAnimationObserver* animation_observer =
+ new ui::CallbackLayerAnimationObserver(
+ base::Bind(&InkDropHover::AnimationStartedCallback,
+ base::Unretained(this), animation_type),
+ base::Bind(&InkDropHover::AnimationEndedCallback,
+ base::Unretained(this), animation_type));
+
+ ui::LayerAnimator* animator = layer_->GetAnimator();
+ ui::ScopedLayerAnimationSettings animation(animator);
+ animation.SetTweenType(gfx::Tween::EASE_IN_OUT);
+ animation.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+
+ ui::LayerAnimationElement* opacity_element =
+ ui::LayerAnimationElement::CreateOpacityElement(
+ animation_type == FADE_IN ? kHoverVisibleOpacity : kHiddenOpacity,
+ duration);
+ ui::LayerAnimationSequence* opacity_sequence =
+ new ui::LayerAnimationSequence(opacity_element);
+ opacity_sequence->AddObserver(animation_observer);
+ animator->StartAnimation(opacity_sequence);
+
+ if (initial_size != target_size) {
+ ui::LayerAnimationElement* transform_element =
+ ui::LayerAnimationElement::CreateTransformElement(
+ CalculateTransform(target_size), duration);
+ ui::LayerAnimationSequence* transform_sequence =
+ new ui::LayerAnimationSequence(transform_element);
+ transform_sequence->AddObserver(animation_observer);
+ animator->StartAnimation(transform_sequence);
+ }
+
+ animation_observer->SetActive();
+}
+
+gfx::Transform InkDropHover::CalculateTransform(const gfx::Size& size) const {
+ gfx::Transform transform;
+ transform.Translate(center_point_.x(), center_point_.y());
+ transform.Scale(size.width() / size_.width(), size.height() / size_.height());
+ transform.Translate(-layer_delegate_->GetCenterPoint().x(),
+ -layer_delegate_->GetCenterPoint().y());
+ return transform;
+}
+
+void InkDropHover::AnimationStartedCallback(
+ AnimationType animation_type,
+ const ui::CallbackLayerAnimationObserver& observer) {
+ if (observer_)
+ observer_->AnimationStarted(animation_type);
+}
+
+bool InkDropHover::AnimationEndedCallback(
+ AnimationType animation_type,
+ const ui::CallbackLayerAnimationObserver& observer) {
+ // AnimationEndedCallback() may be invoked when this is being destroyed and
+ // |layer_| may be null.
+ if (animation_type == FADE_OUT && layer_)
+ layer_->SetVisible(false);
+
+ if (observer_) {
+ observer_->AnimationEnded(animation_type,
+ observer.aborted_count()
+ ? InkDropAnimationEndedReason::PRE_EMPTED
+ : InkDropAnimationEndedReason::SUCCESS);
+ }
+ return true;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_hover.h b/chromium/ui/views/animation/ink_drop_hover.h
new file mode 100644
index 00000000000..e1cd2d42e5e
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_hover.h
@@ -0,0 +1,117 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_HOVER_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_HOVER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class Layer;
+class CallbackLayerAnimationObserver;
+} // namespace ui
+
+namespace views {
+namespace test {
+class InkDropHoverTestApi;
+} // namespace test
+
+class RoundedRectangleLayerDelegate;
+class InkDropHoverObserver;
+
+// Manages fade in/out animations for a painted Layer that is used to provide
+// visual feedback on ui::Views for mouse hover states.
+class VIEWS_EXPORT InkDropHover {
+ public:
+ enum AnimationType { FADE_IN, FADE_OUT };
+
+ InkDropHover(const gfx::Size& size,
+ int corner_radius,
+ const gfx::Point& center_point,
+ SkColor color);
+ virtual ~InkDropHover();
+
+ void set_observer(InkDropHoverObserver* observer) { observer_ = observer; }
+
+ void set_explode_size(const gfx::Size& size) { explode_size_ = size; }
+
+ // Returns true if the hover animation is either in the process of fading
+ // in or is fully visible.
+ bool IsFadingInOrVisible() const;
+
+ // Fades in the hover visual over the given |duration|.
+ void FadeIn(const base::TimeDelta& duration);
+
+ // Fades out the hover visual over the given |duration|. If |explode| is true
+ // then the hover will animate a size increase in addition to the fade out.
+ void FadeOut(const base::TimeDelta& duration, bool explode);
+
+ // The root Layer that can be added in to a Layer tree.
+ ui::Layer* layer() { return layer_.get(); }
+
+ // Returns a test api to access internals of this. Default implmentations
+ // should return nullptr and test specific subclasses can override to return
+ // an instance.
+ virtual test::InkDropHoverTestApi* GetTestApi();
+
+ private:
+ friend class test::InkDropHoverTestApi;
+
+ // Animates a fade in/out as specified by |animation_type| combined with a
+ // transformation from the |initial_size| to the |target_size| over the given
+ // |duration|.
+ void AnimateFade(AnimationType animation_type,
+ const base::TimeDelta& duration,
+ const gfx::Size& initial_size,
+ const gfx::Size& target_size);
+
+ // Calculates the Transform to apply to |layer_| for the given |size|.
+ gfx::Transform CalculateTransform(const gfx::Size& size) const;
+
+ // The callback that will be invoked when a fade in/out animation is started.
+ void AnimationStartedCallback(
+ AnimationType animation_type,
+ const ui::CallbackLayerAnimationObserver& observer);
+
+ // The callback that will be invoked when a fade in/out animation is complete.
+ bool AnimationEndedCallback(
+ AnimationType animation_type,
+ const ui::CallbackLayerAnimationObserver& observer);
+
+ // The size of the hover shape when fully faded in.
+ gfx::Size size_;
+
+ // The target size of the hover shape when it expands during a fade out
+ // animation.
+ gfx::Size explode_size_;
+
+ // The center point of the hover shape in the parent Layer's coordinate space.
+ gfx::PointF center_point_;
+
+ // True if the last animation to be initiated was a FADE_IN, and false
+ // otherwise.
+ bool last_animation_initiated_was_fade_in_;
+
+ // The LayerDelegate that paints the hover |layer_|.
+ scoped_ptr<RoundedRectangleLayerDelegate> layer_delegate_;
+
+ // The visual hover layer that is painted by |layer_delegate_|.
+ scoped_ptr<ui::Layer> layer_;
+
+ InkDropHoverObserver* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(InkDropHover);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_HOVER_H_
diff --git a/chromium/ui/views/animation/ink_drop_hover_observer.h b/chromium/ui/views/animation/ink_drop_hover_observer.h
new file mode 100644
index 00000000000..4e31bc7a428
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_hover_observer.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_HOVER_OBSERVER_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_HOVER_OBSERVER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "ui/views/animation/ink_drop_animation_ended_reason.h"
+#include "ui/views/animation/ink_drop_hover.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+// Observer to attach to an InkDropHover animation.
+class VIEWS_EXPORT InkDropHoverObserver {
+ public:
+ // An animation for the given |animation_type| has started.
+ virtual void AnimationStarted(InkDropHover::AnimationType animation_type) = 0;
+
+ // Notifies the observer that an animation for the given |animation_type| has
+ // finished and the reason for completion is given by |reason|. If |reason| is
+ // SUCCESS then the animation has progressed to its final frame however if
+ // |reason| is |PRE_EMPTED| then the animation was stopped before its final
+ // frame.
+ virtual void AnimationEnded(InkDropHover::AnimationType animation_type,
+ InkDropAnimationEndedReason reason) = 0;
+
+ protected:
+ InkDropHoverObserver() = default;
+ virtual ~InkDropHoverObserver() = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropHoverObserver);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_HOVER_OBSERVER_H_
diff --git a/chromium/ui/views/animation/ink_drop_hover_unittest.cc b/chromium/ui/views/animation/ink_drop_hover_unittest.cc
new file mode 100644
index 00000000000..5d02ab7f1ed
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_hover_unittest.cc
@@ -0,0 +1,144 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/ink_drop_hover.h"
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/animation/test/ink_drop_hover_test_api.h"
+#include "ui/views/animation/test/test_ink_drop_hover_observer.h"
+
+namespace views {
+namespace test {
+
+class InkDropHoverTest : public testing::Test {
+ public:
+ InkDropHoverTest();
+ ~InkDropHoverTest() override;
+
+ protected:
+ // The test target.
+ scoped_ptr<InkDropHover> ink_drop_hover_;
+
+ // Allows privileged access to the the |ink_drop_hover_|.
+ InkDropHoverTestApi test_api_;
+
+ // Observer of the test target.
+ TestInkDropHoverObserver observer_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropHoverTest);
+};
+
+InkDropHoverTest::InkDropHoverTest()
+ : ink_drop_hover_(
+ new InkDropHover(gfx::Size(10, 10), 3, gfx::Point(), SK_ColorBLACK)),
+ test_api_(ink_drop_hover_.get()) {
+ ink_drop_hover_->set_observer(&observer_);
+
+ test_api_.SetDisableAnimationTimers(true);
+}
+
+InkDropHoverTest::~InkDropHoverTest() {}
+
+TEST_F(InkDropHoverTest, InitialStateAfterConstruction) {
+ EXPECT_FALSE(ink_drop_hover_->IsFadingInOrVisible());
+}
+
+TEST_F(InkDropHoverTest, IsHoveredStateTransitions) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+ EXPECT_TRUE(ink_drop_hover_->IsFadingInOrVisible());
+
+ test_api_.CompleteAnimations();
+ EXPECT_TRUE(ink_drop_hover_->IsFadingInOrVisible());
+
+ ink_drop_hover_->FadeOut(base::TimeDelta::FromSeconds(1),
+ false /* explode */);
+ EXPECT_FALSE(ink_drop_hover_->IsFadingInOrVisible());
+
+ test_api_.CompleteAnimations();
+ EXPECT_FALSE(ink_drop_hover_->IsFadingInOrVisible());
+}
+
+TEST_F(InkDropHoverTest, VerifyObserversAreNotified) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_FALSE(observer_.AnimationHasEnded());
+
+ test_api_.CompleteAnimations();
+
+ EXPECT_TRUE(observer_.AnimationHasEnded());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+}
+
+TEST_F(InkDropHoverTest, VerifyObserversAreNotifiedWithCorrectAnimationType) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+
+ EXPECT_TRUE(observer_.AnimationHasStarted());
+ EXPECT_EQ(InkDropHover::FADE_IN, observer_.last_animation_started_context());
+
+ test_api_.CompleteAnimations();
+ EXPECT_TRUE(observer_.AnimationHasEnded());
+ EXPECT_EQ(InkDropHover::FADE_IN, observer_.last_animation_started_context());
+
+ ink_drop_hover_->FadeOut(base::TimeDelta::FromSeconds(1),
+ false /* explode */);
+ EXPECT_EQ(InkDropHover::FADE_OUT, observer_.last_animation_started_context());
+
+ test_api_.CompleteAnimations();
+ EXPECT_EQ(InkDropHover::FADE_OUT, observer_.last_animation_started_context());
+}
+
+TEST_F(InkDropHoverTest, VerifyObserversAreNotifiedOfSuccessfulAnimations) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+ test_api_.CompleteAnimations();
+
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropAnimationEndedReason::SUCCESS,
+ observer_.last_animation_ended_reason());
+}
+
+TEST_F(InkDropHoverTest, VerifyObserversAreNotifiedOfPreemptedAnimations) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+ ink_drop_hover_->FadeOut(base::TimeDelta::FromSeconds(1),
+ false /* explode */);
+
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropHover::FADE_IN, observer_.last_animation_ended_context());
+ EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
+ observer_.last_animation_ended_reason());
+}
+
+// Confirms there is no crash.
+TEST_F(InkDropHoverTest, NullObserverIsSafe) {
+ ink_drop_hover_->set_observer(nullptr);
+
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+ test_api_.CompleteAnimations();
+
+ ink_drop_hover_->FadeOut(base::TimeDelta::FromMilliseconds(0),
+ false /* explode */);
+ test_api_.CompleteAnimations();
+ EXPECT_FALSE(ink_drop_hover_->IsFadingInOrVisible());
+}
+
+// Verify animations are aborted during deletion and the InkDropHoverObservers
+// are notified.
+TEST_F(InkDropHoverTest, AnimationsAbortedDuringDeletion) {
+ ink_drop_hover_->FadeIn(base::TimeDelta::FromSeconds(1));
+ ink_drop_hover_.reset();
+ EXPECT_EQ(1, observer_.last_animation_started_ordinal());
+ EXPECT_EQ(2, observer_.last_animation_ended_ordinal());
+ EXPECT_EQ(InkDropHover::FADE_IN, observer_.last_animation_ended_context());
+ EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
+ observer_.last_animation_ended_reason());
+}
+
+} // namespace test
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_painted_layer_delegates.cc b/chromium/ui/views/animation/ink_drop_painted_layer_delegates.cc
index bdb79460e49..cb5f7c57053 100644
--- a/chromium/ui/views/animation/ink_drop_painted_layer_delegates.cc
+++ b/chromium/ui/views/animation/ink_drop_painted_layer_delegates.cc
@@ -8,6 +8,7 @@
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
namespace views {
@@ -51,7 +52,7 @@ void CircleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
paint.setFlags(SkPaint::kAntiAlias_Flag);
paint.setStyle(SkPaint::kFill_Style);
- ui::PaintRecorder recorder(context, gfx::Size(radius_, radius_));
+ ui::PaintRecorder recorder(context, gfx::Size(2 * radius_, 2 * radius_));
gfx::Canvas* canvas = recorder.canvas();
canvas->DrawCircle(ToRoundedPoint(GetCenterPoint()), radius_, paint);
@@ -82,4 +83,34 @@ void RectangleLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
canvas->DrawRect(gfx::Rect(size_), paint);
}
+////////////////////////////////////////////////////////////////////////////////
+//
+// RoundedRectangleLayerDelegate
+//
+
+RoundedRectangleLayerDelegate::RoundedRectangleLayerDelegate(SkColor color,
+ gfx::Size size,
+ int corner_radius)
+ : BasePaintedLayerDelegate(color),
+ size_(size),
+ corner_radius_(corner_radius) {}
+
+RoundedRectangleLayerDelegate::~RoundedRectangleLayerDelegate() {}
+
+gfx::PointF RoundedRectangleLayerDelegate::GetCenterPoint() const {
+ return gfx::RectF(gfx::SizeF(size_)).CenterPoint();
+}
+
+void RoundedRectangleLayerDelegate::OnPaintLayer(
+ const ui::PaintContext& context) {
+ SkPaint paint;
+ paint.setColor(color());
+ paint.setFlags(SkPaint::kAntiAlias_Flag);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ ui::PaintRecorder recorder(context, size_);
+ gfx::Canvas* canvas = recorder.canvas();
+ canvas->DrawRoundRect(gfx::Rect(size_), corner_radius_, paint);
+}
+
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_painted_layer_delegates.h b/chromium/ui/views/animation/ink_drop_painted_layer_delegates.h
index feb2921b8a6..59e170495e7 100644
--- a/chromium/ui/views/animation/ink_drop_painted_layer_delegates.h
+++ b/chromium/ui/views/animation/ink_drop_painted_layer_delegates.h
@@ -81,6 +81,31 @@ class RectangleLayerDelegate : public BasePaintedLayerDelegate {
DISALLOW_COPY_AND_ASSIGN(RectangleLayerDelegate);
};
+// A BasePaintedLayerDelegate that paints a rounded rectangle of a specified
+// color, size and corner radius.
+class RoundedRectangleLayerDelegate : public BasePaintedLayerDelegate {
+ public:
+ RoundedRectangleLayerDelegate(SkColor color,
+ gfx::Size size,
+ int corner_radius);
+ ~RoundedRectangleLayerDelegate() override;
+
+ const gfx::Size& size() const { return size_; }
+
+ // BasePaintedLayerDelegate:
+ gfx::PointF GetCenterPoint() const override;
+ void OnPaintLayer(const ui::PaintContext& context) override;
+
+ private:
+ // The size of the rectangle.
+ gfx::Size size_;
+
+ // The radius of the corners.
+ int corner_radius_;
+
+ DISALLOW_COPY_AND_ASSIGN(RoundedRectangleLayerDelegate);
+};
+
} // namespace views
#endif // UI_VIEWS_ANIMATION_INK_DROP_PAINTED_LAYER_DELEGATES_H_
diff --git a/chromium/ui/views/animation/ink_drop_state.cc b/chromium/ui/views/animation/ink_drop_state.cc
index e8ea3806425..adbefae1a22 100644
--- a/chromium/ui/views/animation/ink_drop_state.cc
+++ b/chromium/ui/views/animation/ink_drop_state.cc
@@ -16,12 +16,12 @@ std::string ToString(InkDropState state) {
return std::string("HIDDEN");
case InkDropState::ACTION_PENDING:
return std::string("ACTION_PENDING");
- case InkDropState::QUICK_ACTION:
- return std::string("QUICK_ACTION");
- case InkDropState::SLOW_ACTION_PENDING:
- return std::string("SLOW_ACTION_PENDING");
- case InkDropState::SLOW_ACTION:
- return std::string("SLOW_ACTION");
+ case InkDropState::ACTION_TRIGGERED:
+ return std::string("ACTION_TRIGGERED");
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ return std::string("ALTERNATE_ACTION_PENDING");
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ return std::string("ALTERNATE_ACTION_TRIGGERED");
case InkDropState::ACTIVATED:
return std::string("ACTIVATED");
case InkDropState::DEACTIVATED:
diff --git a/chromium/ui/views/animation/ink_drop_state.h b/chromium/ui/views/animation/ink_drop_state.h
index 16f4fc2bee6..2456455c5da 100644
--- a/chromium/ui/views/animation/ink_drop_state.h
+++ b/chromium/ui/views/animation/ink_drop_state.h
@@ -16,21 +16,21 @@ enum class InkDropState {
// The ink drop is not visible.
HIDDEN,
// The view is being interacted with but the action to be triggered has not
- // yet been determined.
+ // yet been determined, e.g. a mouse button down.
ACTION_PENDING,
- // The quick action for the view has been triggered. e.g. a tap gesture to
- // click a button.
- QUICK_ACTION,
- // A view is being interacted with and the pending action will be a 'slow'
- // action. e.g. a long press that is still active before releasing.
- SLOW_ACTION_PENDING,
- // The slow action for the view has been triggered. e.g. a long press release
- // to bring up a menu.
- SLOW_ACTION,
+ // The quick action for the view has been triggered, e.g. a tap gesture or a
+ // mouse click on a button.
+ ACTION_TRIGGERED,
+ // A view is being interacted with and the pending action will be a secondary
+ // action, e.g. a long press.
+ ALTERNATE_ACTION_PENDING,
+ // The alternate action for the view has been triggered, e.g. a long press
+ // release to bring up a menu.
+ ALTERNATE_ACTION_TRIGGERED,
// An active state for a view that is not currently being interacted with.
// e.g. a pressed button that is showing a menu.
ACTIVATED,
- // A previously active state has been toggled to inactive. e.g. a drop down
+ // A previously active state has been toggled to inactive, e.g. a drop down
// menu is closed.
DEACTIVATED,
};
diff --git a/chromium/ui/views/animation/square_ink_drop_animation.cc b/chromium/ui/views/animation/square_ink_drop_animation.cc
new file mode 100644
index 00000000000..58320aa8246
--- /dev/null
+++ b/chromium/ui/views/animation/square_ink_drop_animation.cc
@@ -0,0 +1,555 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/square_ink_drop_animation.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animation_sequence.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/geometry/point3_f.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/vector3d_f.h"
+#include "ui/gfx/transform_util.h"
+#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
+#include "ui/views/view.h"
+
+namespace {
+
+// The minimum scale factor to use when scaling rectangle layers. Smaller values
+// were causing visual anomalies.
+const float kMinimumRectScale = 0.0001f;
+
+// The minimum scale factor to use when scaling circle layers. Smaller values
+// were causing visual anomalies.
+const float kMinimumCircleScale = 0.001f;
+
+// All the sub animations that are used to animate each of the InkDropStates.
+// These are used to get time durations with
+// GetAnimationDuration(InkDropSubAnimations). Note that in general a sub
+// animation defines the duration for either a transformation animation or an
+// opacity animation but there are some exceptions where an entire InkDropState
+// animation consists of only 1 sub animation and it defines the duration for
+// both the transformation and opacity animations.
+enum InkDropSubAnimations {
+ // HIDDEN sub animations.
+
+ // The HIDDEN sub animation that is fading out to a hidden opacity.
+ HIDDEN_FADE_OUT,
+
+ // The HIDDEN sub animation that transforms the shape to a |small_size_|
+ // circle.
+ HIDDEN_TRANSFORM,
+
+ // ACTION_PENDING sub animations.
+
+ // The ACTION_PENDING sub animation that fades in to the visible opacity.
+ ACTION_PENDING_FADE_IN,
+
+ // The ACTION_PENDING sub animation that transforms the shape to a
+ // |large_size_| circle.
+ ACTION_PENDING_TRANSFORM,
+
+ // ACTION_TRIGGERED sub animations.
+
+ // The ACTION_TRIGGERED sub animation that is fading out to a hidden opacity.
+ ACTION_TRIGGERED_FADE_OUT,
+
+ // The ACTION_TRIGGERED sub animation that transforms the shape to a
+ // |large_size_|
+ // circle.
+ ACTION_TRIGGERED_TRANSFORM,
+
+ // ALTERNATE_ACTION_PENDING sub animations.
+
+ // The ALTERNATE_ACTION_PENDING animation has only one sub animation which
+ // animates
+ // to a |small_size_| rounded rectangle at visible opacity.
+ ALTERNATE_ACTION_PENDING,
+
+ // ALTERNATE_ACTION_TRIGGERED sub animations.
+
+ // The ALTERNATE_ACTION_TRIGGERED sub animation that is fading out to a hidden
+ // opacity.
+ ALTERNATE_ACTION_TRIGGERED_FADE_OUT,
+
+ // The ALTERNATE_ACTION_TRIGGERED sub animation that transforms the shape to a
+ // |large_size_|
+ // rounded rectangle.
+ ALTERNATE_ACTION_TRIGGERED_TRANSFORM,
+
+ // ACTIVATED sub animations.
+
+ // The ACTIVATED sub animation that transforms the shape to a |large_size_|
+ // circle. This is used when the ink drop is in a HIDDEN state prior to
+ // animating to the ACTIVATED state.
+ ACTIVATED_CIRCLE_TRANSFORM,
+
+ // The ACTIVATED sub animation that transforms the shape to a |small_size_|
+ // rounded rectangle.
+ ACTIVATED_RECT_TRANSFORM,
+
+ // DEACTIVATED sub animations.
+
+ // The DEACTIVATED sub animation that is fading out to a hidden opacity.
+ DEACTIVATED_FADE_OUT,
+
+ // The DEACTIVATED sub animation that transforms the shape to a |large_size_|
+ // rounded rectangle.
+ DEACTIVATED_TRANSFORM,
+};
+
+// The scale factor used to burst the ACTION_TRIGGERED bubble as it fades out.
+const float kQuickActionBurstScale = 1.3f;
+
+// Duration constants for InkDropStateSubAnimations. See the
+// InkDropStateSubAnimations enum documentation for more info.
+int kAnimationDurationInMs[] = {
+ 150, // HIDDEN_FADE_OUT
+ 200, // HIDDEN_TRANSFORM
+ 0, // ACTION_PENDING_FADE_IN
+ 160, // ACTION_PENDING_TRANSFORM
+ 150, // ACTION_TRIGGERED_FADE_OUT
+ 160, // ACTION_TRIGGERED_TRANSFORM
+ 200, // ALTERNATE_ACTION_PENDING
+ 150, // ALTERNATE_ACTION_TRIGGERED_FADE_OUT
+ 200, // ALTERNATE_ACTION_TRIGGERED_TRANSFORM
+ 200, // ACTIVATED_CIRCLE_TRANSFORM
+ 160, // ACTIVATED_RECT_TRANSFORM
+ 150, // DEACTIVATED_FADE_OUT
+ 200, // DEACTIVATED_TRANSFORM
+};
+
+// Returns the InkDropState sub animation duration for the given |state|.
+base::TimeDelta GetAnimationDuration(InkDropSubAnimations state) {
+ return base::TimeDelta::FromMilliseconds(
+ (views::InkDropAnimation::UseFastAnimations()
+ ? 1
+ : views::InkDropAnimation::kSlowAnimationDurationFactor) *
+ kAnimationDurationInMs[state]);
+}
+
+// Calculates a Transform for a circle layer. The transform will be set up to
+// translate the |drawn_center_point| to the origin, scale, and then translate
+// to the target point defined by |target_center_x| and |target_center_y|.
+gfx::Transform CalculateCircleTransform(const gfx::Point& drawn_center_point,
+ float scale,
+ float target_center_x,
+ float target_center_y) {
+ gfx::Transform transform;
+ transform.Translate(target_center_x, target_center_y);
+ transform.Scale(scale, scale);
+ transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
+ return transform;
+}
+
+// Calculates a Transform for a rectangle layer. The transform will be set up to
+// translate the |drawn_center_point| to the origin and then scale by the
+// |x_scale| and |y_scale| factors.
+gfx::Transform CalculateRectTransform(const gfx::Point& drawn_center_point,
+ float x_scale,
+ float y_scale) {
+ gfx::Transform transform;
+ transform.Scale(x_scale, y_scale);
+ transform.Translate(-drawn_center_point.x(), -drawn_center_point.y());
+ return transform;
+}
+
+} // namespace
+
+namespace views {
+
+SquareInkDropAnimation::SquareInkDropAnimation(const gfx::Size& large_size,
+ int large_corner_radius,
+ const gfx::Size& small_size,
+ int small_corner_radius,
+ const gfx::Point& center_point,
+ SkColor color)
+ : large_size_(large_size),
+ large_corner_radius_(large_corner_radius),
+ small_size_(small_size),
+ small_corner_radius_(small_corner_radius),
+ circle_layer_delegate_(new CircleLayerDelegate(
+ color,
+ std::min(large_size_.width(), large_size_.height()) / 2)),
+ rect_layer_delegate_(new RectangleLayerDelegate(color, large_size_)),
+ root_layer_(ui::LAYER_NOT_DRAWN) {
+ root_layer_.set_name("SquareInkDropAnimation:ROOT_LAYER");
+
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
+ AddPaintLayer(static_cast<PaintedShape>(i));
+
+ root_layer_.SetMasksToBounds(false);
+ root_layer_.SetBounds(gfx::Rect(large_size_));
+
+ gfx::Transform transform;
+ transform.Translate(center_point.x(), center_point.y());
+ root_layer_.SetTransform(transform);
+
+ SetStateToHidden();
+}
+
+SquareInkDropAnimation::~SquareInkDropAnimation() {
+ // Explicitly aborting all the animations ensures all callbacks are invoked
+ // while this instance still exists.
+ AbortAllAnimations();
+}
+
+void SquareInkDropAnimation::SnapToActivated() {
+ InkDropAnimation::SnapToActivated();
+ SetOpacity(kVisibleOpacity);
+ InkDropTransforms transforms;
+ GetActivatedTargetTransforms(&transforms);
+ SetTransforms(transforms);
+}
+
+ui::Layer* SquareInkDropAnimation::GetRootLayer() {
+ return &root_layer_;
+}
+
+bool SquareInkDropAnimation::IsVisible() const {
+ return root_layer_.visible();
+}
+
+float SquareInkDropAnimation::GetCurrentOpacity() const {
+ return root_layer_.opacity();
+}
+
+std::string SquareInkDropAnimation::ToLayerName(PaintedShape painted_shape) {
+ switch (painted_shape) {
+ case TOP_LEFT_CIRCLE:
+ return "TOP_LEFT_CIRCLE";
+ case TOP_RIGHT_CIRCLE:
+ return "TOP_RIGHT_CIRCLE";
+ case BOTTOM_RIGHT_CIRCLE:
+ return "BOTTOM_RIGHT_CIRCLE";
+ case BOTTOM_LEFT_CIRCLE:
+ return "BOTTOM_LEFT_CIRCLE";
+ case HORIZONTAL_RECT:
+ return "HORIZONTAL_RECT";
+ case VERTICAL_RECT:
+ return "VERTICAL_RECT";
+ case PAINTED_SHAPE_COUNT:
+ NOTREACHED() << "The PAINTED_SHAPE_COUNT value should never be used.";
+ return "PAINTED_SHAPE_COUNT";
+ }
+ return "UNKNOWN";
+}
+
+void SquareInkDropAnimation::AnimateStateChange(
+ InkDropState old_ink_drop_state,
+ InkDropState new_ink_drop_state,
+ ui::LayerAnimationObserver* animation_observer) {
+ InkDropTransforms transforms;
+
+ switch (new_ink_drop_state) {
+ case InkDropState::HIDDEN:
+ if (!IsVisible()) {
+ SetStateToHidden();
+ break;
+ } else {
+ AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(HIDDEN_FADE_OUT),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateCircleTransforms(small_size_, &transforms);
+ AnimateToTransforms(
+ transforms, GetAnimationDuration(HIDDEN_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ }
+ break;
+ case InkDropState::ACTION_PENDING:
+ DCHECK(old_ink_drop_state == InkDropState::HIDDEN);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_FADE_IN),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ CalculateCircleTransforms(large_size_, &transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ACTION_PENDING_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ case InkDropState::ACTION_TRIGGERED: {
+ DCHECK(old_ink_drop_state == InkDropState::HIDDEN ||
+ old_ink_drop_state == InkDropState::ACTION_PENDING);
+ if (old_ink_drop_state == InkDropState::HIDDEN) {
+ AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING,
+ animation_observer);
+ }
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(ACTION_TRIGGERED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ gfx::Size s = ScaleToRoundedSize(large_size_, kQuickActionBurstScale);
+ CalculateCircleTransforms(s, &transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ACTION_TRIGGERED_TRANSFORM),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ DCHECK(old_ink_drop_state == InkDropState::ACTION_PENDING);
+ AnimateToOpacity(kVisibleOpacity,
+ GetAnimationDuration(ALTERNATE_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN, animation_observer);
+ CalculateRectTransforms(small_size_, small_corner_radius_, &transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ALTERNATE_ACTION_PENDING),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED: {
+ DCHECK(old_ink_drop_state == InkDropState::ALTERNATE_ACTION_PENDING);
+ base::TimeDelta visible_duration =
+ GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_TRANSFORM) -
+ GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_FADE_OUT);
+ AnimateToOpacity(kVisibleOpacity, visible_duration,
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(
+ ALTERNATE_ACTION_TRIGGERED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
+ AnimateToTransforms(transforms, GetAnimationDuration(
+ ALTERNATE_ACTION_TRIGGERED_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::ACTIVATED: {
+ // Animate the opacity so that it cancels any opacity animations already
+ // in progress.
+ AnimateToOpacity(kVisibleOpacity, base::TimeDelta(),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+
+ ui::LayerAnimator::PreemptionStrategy rect_transform_preemption_strategy =
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET;
+ if (old_ink_drop_state == InkDropState::HIDDEN) {
+ rect_transform_preemption_strategy =
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION;
+ CalculateCircleTransforms(large_size_, &transforms);
+ AnimateToTransforms(
+ transforms, GetAnimationDuration(ACTIVATED_CIRCLE_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ } else if (old_ink_drop_state == InkDropState::ACTION_PENDING) {
+ rect_transform_preemption_strategy =
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION;
+ }
+
+ GetActivatedTargetTransforms(&transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(ACTIVATED_RECT_TRANSFORM),
+ rect_transform_preemption_strategy,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ case InkDropState::DEACTIVATED: {
+ base::TimeDelta visible_duration =
+ GetAnimationDuration(DEACTIVATED_TRANSFORM) -
+ GetAnimationDuration(DEACTIVATED_FADE_OUT);
+ AnimateToOpacity(kVisibleOpacity, visible_duration,
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
+ AnimateToOpacity(kHiddenOpacity,
+ GetAnimationDuration(DEACTIVATED_FADE_OUT),
+ ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ CalculateRectTransforms(large_size_, large_corner_radius_, &transforms);
+ AnimateToTransforms(transforms,
+ GetAnimationDuration(DEACTIVATED_TRANSFORM),
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
+ gfx::Tween::EASE_IN_OUT, animation_observer);
+ break;
+ }
+ }
+}
+
+void SquareInkDropAnimation::SetStateToHidden() {
+ InkDropTransforms transforms;
+ // Use non-zero size to avoid visual anomalies.
+ CalculateCircleTransforms(gfx::Size(1, 1), &transforms);
+ SetTransforms(transforms);
+ root_layer_.SetOpacity(InkDropAnimation::kHiddenOpacity);
+ root_layer_.SetVisible(false);
+}
+
+void SquareInkDropAnimation::AbortAllAnimations() {
+ root_layer_.GetAnimator()->AbortAllAnimations();
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
+ painted_layers_[i]->GetAnimator()->AbortAllAnimations();
+}
+
+void SquareInkDropAnimation::AnimateToTransforms(
+ const InkDropTransforms transforms,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* animation_observer) {
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i) {
+ ui::LayerAnimator* animator = painted_layers_[i]->GetAnimator();
+ ui::ScopedLayerAnimationSettings animation(animator);
+ animation.SetPreemptionStrategy(preemption_strategy);
+ animation.SetTweenType(tween);
+ ui::LayerAnimationElement* element =
+ ui::LayerAnimationElement::CreateTransformElement(transforms[i],
+ duration);
+ ui::LayerAnimationSequence* sequence =
+ new ui::LayerAnimationSequence(element);
+
+ if (animation_observer)
+ sequence->AddObserver(animation_observer);
+
+ animator->StartAnimation(sequence);
+ }
+}
+
+void SquareInkDropAnimation::SetTransforms(const InkDropTransforms transforms) {
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
+ painted_layers_[i]->SetTransform(transforms[i]);
+}
+
+void SquareInkDropAnimation::SetOpacity(float opacity) {
+ root_layer_.SetOpacity(opacity);
+}
+
+void SquareInkDropAnimation::AnimateToOpacity(
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* animation_observer) {
+ ui::LayerAnimator* animator = root_layer_.GetAnimator();
+ ui::ScopedLayerAnimationSettings animation_settings(animator);
+ animation_settings.SetPreemptionStrategy(preemption_strategy);
+ animation_settings.SetTweenType(tween);
+ ui::LayerAnimationElement* animation_element =
+ ui::LayerAnimationElement::CreateOpacityElement(opacity, duration);
+ ui::LayerAnimationSequence* animation_sequence =
+ new ui::LayerAnimationSequence(animation_element);
+
+ if (animation_observer)
+ animation_sequence->AddObserver(animation_observer);
+
+ animator->StartAnimation(animation_sequence);
+}
+
+void SquareInkDropAnimation::CalculateCircleTransforms(
+ const gfx::Size& size,
+ InkDropTransforms* transforms_out) const {
+ CalculateRectTransforms(size, std::min(size.width(), size.height()) / 2.0f,
+ transforms_out);
+}
+
+void SquareInkDropAnimation::CalculateRectTransforms(
+ const gfx::Size& size,
+ float corner_radius,
+ InkDropTransforms* transforms_out) const {
+ DCHECK_GE(size.width() / 2.0f, corner_radius)
+ << "The circle's diameter should not be greater than the total width.";
+ DCHECK_GE(size.height() / 2.0f, corner_radius)
+ << "The circle's diameter should not be greater than the total height.";
+
+ // The shapes are drawn such that their center points are not at the origin.
+ // Thus we use the CalculateCircleTransform() and CalculateRectTransform()
+ // methods to calculate the complex Transforms.
+
+ const float circle_scale = std::max(
+ kMinimumCircleScale,
+ corner_radius / static_cast<float>(circle_layer_delegate_->radius()));
+
+ const float circle_target_x_offset = size.width() / 2.0f - corner_radius;
+ const float circle_target_y_offset = size.height() / 2.0f - corner_radius;
+
+ (*transforms_out)[TOP_LEFT_CIRCLE] = CalculateCircleTransform(
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
+ -circle_target_x_offset, -circle_target_y_offset);
+
+ (*transforms_out)[TOP_RIGHT_CIRCLE] = CalculateCircleTransform(
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
+ circle_target_x_offset, -circle_target_y_offset);
+
+ (*transforms_out)[BOTTOM_RIGHT_CIRCLE] = CalculateCircleTransform(
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
+ circle_target_x_offset, circle_target_y_offset);
+
+ (*transforms_out)[BOTTOM_LEFT_CIRCLE] = CalculateCircleTransform(
+ ToRoundedPoint(circle_layer_delegate_->GetCenterPoint()), circle_scale,
+ -circle_target_x_offset, circle_target_y_offset);
+
+ const float rect_delegate_width =
+ static_cast<float>(rect_layer_delegate_->size().width());
+ const float rect_delegate_height =
+ static_cast<float>(rect_layer_delegate_->size().height());
+
+ (*transforms_out)[HORIZONTAL_RECT] = CalculateRectTransform(
+ ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
+ std::max(kMinimumRectScale, size.width() / rect_delegate_width),
+ std::max(kMinimumRectScale,
+ (size.height() - 2.0f * corner_radius) / rect_delegate_height));
+
+ (*transforms_out)[VERTICAL_RECT] = CalculateRectTransform(
+ ToRoundedPoint(rect_layer_delegate_->GetCenterPoint()),
+ std::max(kMinimumRectScale,
+ (size.width() - 2.0f * corner_radius) / rect_delegate_width),
+ std::max(kMinimumRectScale, size.height() / rect_delegate_height));
+}
+
+void SquareInkDropAnimation::GetCurrentTransforms(
+ InkDropTransforms* transforms_out) const {
+ for (int i = 0; i < PAINTED_SHAPE_COUNT; ++i)
+ (*transforms_out)[i] = painted_layers_[i]->transform();
+}
+
+void SquareInkDropAnimation::GetActivatedTargetTransforms(
+ InkDropTransforms* transforms_out) const {
+ CalculateRectTransforms(small_size_, small_corner_radius_, transforms_out);
+}
+
+void SquareInkDropAnimation::AddPaintLayer(PaintedShape painted_shape) {
+ ui::LayerDelegate* delegate = nullptr;
+ switch (painted_shape) {
+ case TOP_LEFT_CIRCLE:
+ case TOP_RIGHT_CIRCLE:
+ case BOTTOM_RIGHT_CIRCLE:
+ case BOTTOM_LEFT_CIRCLE:
+ delegate = circle_layer_delegate_.get();
+ break;
+ case HORIZONTAL_RECT:
+ case VERTICAL_RECT:
+ delegate = rect_layer_delegate_.get();
+ break;
+ case PAINTED_SHAPE_COUNT:
+ NOTREACHED() << "PAINTED_SHAPE_COUNT is not an actual shape type.";
+ break;
+ }
+
+ ui::Layer* layer = new ui::Layer();
+ root_layer_.Add(layer);
+
+ layer->SetBounds(gfx::Rect(large_size_));
+ layer->SetFillsBoundsOpaquely(false);
+ layer->set_delegate(delegate);
+ layer->SetVisible(true);
+ layer->SetOpacity(1.0);
+ layer->SetMasksToBounds(false);
+ layer->set_name("PAINTED_SHAPE_COUNT:" + ToLayerName(painted_shape));
+
+ painted_layers_[painted_shape].reset(layer);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/square_ink_drop_animation.h b/chromium/ui/views/animation/square_ink_drop_animation.h
new file mode 100644
index 00000000000..d704e7eb4af
--- /dev/null
+++ b/chromium/ui/views/animation/square_ink_drop_animation.h
@@ -0,0 +1,184 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_SQUARE_INK_DROP_ANIMATION_H_
+#define UI_VIEWS_ANIMATION_SQUARE_INK_DROP_ANIMATION_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
+#include "ui/views/animation/ink_drop_animation.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class Layer;
+} // namespace ui
+
+namespace views {
+class CircleLayerDelegate;
+class RectangleLayerDelegate;
+
+namespace test {
+class SquareInkDropAnimationTestApi;
+} // namespace test
+
+// An ink drop animation that smoothly animates between a circle and a rounded
+// rectangle of different sizes for each of the different InkDropStates. The
+// final frame for each InkDropState will be bounded by either a |large_size_|
+// rectangle or a |small_size_| rectangle.
+//
+// The valid InkDropState transitions are defined below:
+//
+// {All InkDropStates} => HIDDEN
+// HIDDEN => ACTION_PENDING
+// HIDDEN, ACTION_PENDING => ACTION_TRIGGERED
+// ACTION_PENDING => ALTERNATE_ACTION_PENDING
+// ALTERNATE_ACTION_PENDING => ALTERNATE_ACTION_TRIGGERED
+// {All InkDropStates} => ACTIVATED
+// {All InkDropStates} => DEACTIVATED
+//
+class VIEWS_EXPORT SquareInkDropAnimation : public InkDropAnimation {
+ public:
+ SquareInkDropAnimation(const gfx::Size& large_size,
+ int large_corner_radius,
+ const gfx::Size& small_size,
+ int small_corner_radius,
+ const gfx::Point& center_point,
+ SkColor color);
+ ~SquareInkDropAnimation() override;
+
+ // InkDropAnimation:
+ void SnapToActivated() override;
+ ui::Layer* GetRootLayer() override;
+ bool IsVisible() const override;
+
+ private:
+ friend class test::SquareInkDropAnimationTestApi;
+
+ // Enumeration of the different shapes that compose the ink drop.
+ enum PaintedShape {
+ TOP_LEFT_CIRCLE = 0,
+ TOP_RIGHT_CIRCLE,
+ BOTTOM_RIGHT_CIRCLE,
+ BOTTOM_LEFT_CIRCLE,
+ HORIZONTAL_RECT,
+ VERTICAL_RECT,
+ // The total number of shapes, not an actual shape.
+ PAINTED_SHAPE_COUNT
+ };
+
+ // Returns a human readable string for the |painted_shape| value.
+ static std::string ToLayerName(PaintedShape painted_shape);
+
+ // Type that contains a gfx::Tansform for each of the layers required by the
+ // ink drop.
+ typedef gfx::Transform InkDropTransforms[PAINTED_SHAPE_COUNT];
+
+ float GetCurrentOpacity() const;
+
+ // InkDropAnimation:
+ void AnimateStateChange(InkDropState old_ink_drop_state,
+ InkDropState new_ink_drop_state,
+ ui::LayerAnimationObserver* observer) override;
+ void SetStateToHidden() override;
+ void AbortAllAnimations() override;
+
+ // Animates all of the painted shape layers to the specified |transforms|. The
+ // animation will be configured with the given |duration|, |tween|, and
+ // |preemption_strategy| values. The |observer| will be added to all
+ // LayerAnimationSequences if not null.
+ void AnimateToTransforms(
+ const InkDropTransforms transforms,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* observer);
+
+ // Sets the |transforms| on all of the shape layers. Note that this does not
+ // perform any animation.
+ void SetTransforms(const InkDropTransforms transforms);
+
+ // Sets the opacity of the ink drop. Note that this does not perform any
+ // animation.
+ void SetOpacity(float opacity);
+
+ // Animates all of the painted shape layers to the specified |opacity|. The
+ // animation will be configured with the given |duration|, |tween|, and
+ // |preemption_strategy| values. The |observer| will be added to all
+ // LayerAnimationSequences if not null.
+ void AnimateToOpacity(
+ float opacity,
+ base::TimeDelta duration,
+ ui::LayerAnimator::PreemptionStrategy preemption_strategy,
+ gfx::Tween::Type tween,
+ ui::LayerAnimationObserver* observer);
+
+ // Updates all of the Transforms in |transforms_out| for a circle of the given
+ // |size|.
+ void CalculateCircleTransforms(const gfx::Size& size,
+ InkDropTransforms* transforms_out) const;
+
+ // Updates all of the Transforms in |transforms_out| for a rounded rectangle
+ // of the given |size| and |corner_radius|.
+ void CalculateRectTransforms(const gfx::Size& size,
+ float corner_radius,
+ InkDropTransforms* transforms_out) const;
+
+ // Updates all of the Transforms in |transforms_out| to the current Transforms
+ // of the painted shape Layers.
+ void GetCurrentTransforms(InkDropTransforms* transforms_out) const;
+
+ // Updates all of the Transforms in |transforms_out| with the target
+ // Transforms for the ACTIVATED animation.
+ void GetActivatedTargetTransforms(InkDropTransforms* transforms_out) const;
+
+ // Adds and configures a new |painted_shape| layer to |painted_layers_|.
+ void AddPaintLayer(PaintedShape painted_shape);
+
+ // Maximum size that an ink drop will be drawn to for any InkDropState whose
+ // final frame should be large.
+ gfx::Size large_size_;
+
+ // Corner radius used to draw the rounded rectangles corner for any
+ // InkDropState whose final frame should be large.
+ int large_corner_radius_;
+
+ // Maximum size that an ink drop will be drawn to for any InkDropState whose
+ // final frame should be small.
+ gfx::Size small_size_;
+
+ // Corner radius used to draw the rounded rectangles corner for any
+ // InkDropState whose final frame should be small.
+ int small_corner_radius_;
+
+ // ui::LayerDelegate to paint circles for all the circle layers.
+ scoped_ptr<CircleLayerDelegate> circle_layer_delegate_;
+
+ // ui::LayerDelegate to paint rectangles for all the rectangle layers.
+ scoped_ptr<RectangleLayerDelegate> rect_layer_delegate_;
+
+ // The root layer that parents the animating layers. The root layer is used to
+ // manipulate opacity and location, and its children are used to manipulate
+ // the different painted shapes that compose the ink drop.
+ ui::Layer root_layer_;
+
+ // ui::Layers for all of the painted shape layers that compose the ink drop.
+ scoped_ptr<ui::Layer> painted_layers_[PAINTED_SHAPE_COUNT];
+
+ DISALLOW_COPY_AND_ASSIGN(SquareInkDropAnimation);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_SQUARE_INK_DROP_ANIMATION_H_
diff --git a/chromium/ui/views/animation/square_ink_drop_animation_unittest.cc b/chromium/ui/views/animation/square_ink_drop_animation_unittest.cc
new file mode 100644
index 00000000000..0b11630ca5e
--- /dev/null
+++ b/chromium/ui/views/animation/square_ink_drop_animation_unittest.cc
@@ -0,0 +1,248 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_UNITTEST_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_UNITTEST_H_
+
+#include "ui/views/animation/square_ink_drop_animation.h"
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/views/animation/ink_drop_animation_observer.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/animation/test/square_ink_drop_animation_test_api.h"
+#include "ui/views/animation/test/test_ink_drop_animation_observer.h"
+
+namespace views {
+namespace test {
+
+namespace {
+
+using PaintedShape = views::test::SquareInkDropAnimationTestApi::PaintedShape;
+
+// Transforms a copy of |point| with |transform| and returns it.
+gfx::Point TransformPoint(const gfx::Transform& transform,
+ const gfx::Point& point) {
+ gfx::Point transformed_point = point;
+ transform.TransformPoint(&transformed_point);
+ return transformed_point;
+}
+
+class SquareInkDropAnimationCalculateTransformsTest : public testing::Test {
+ public:
+ SquareInkDropAnimationCalculateTransformsTest();
+ ~SquareInkDropAnimationCalculateTransformsTest() override;
+
+ protected:
+ // Half the width/height of the drawn ink drop.
+ static const int kHalfDrawnSize;
+
+ // The full width/height of the drawn ink drop.
+ static const int kDrawnSize;
+
+ // The radius of the rounded rectangle corners.
+ static const int kTransformedRadius;
+
+ // Half the width/height of the transformed ink drop.
+ static const int kHalfTransformedSize;
+
+ // The full width/height of the transformed ink drop.
+ static const int kTransformedSize;
+
+ // Constant points in the drawn space that will be transformed.
+ static const gfx::Point kDrawnCenterPoint;
+ static const gfx::Point kDrawnMidLeftPoint;
+ static const gfx::Point kDrawnMidRightPoint;
+ static const gfx::Point kDrawnTopMidPoint;
+ static const gfx::Point kDrawnBottomMidPoint;
+
+ // The test target.
+ SquareInkDropAnimation ink_drop_animation_;
+
+ // Provides internal access to the test target.
+ SquareInkDropAnimationTestApi test_api_;
+
+ // The gfx::Transforms collection that is populated via the
+ // Calculate*Transforms() calls.
+ SquareInkDropAnimationTestApi::InkDropTransforms transforms_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SquareInkDropAnimationCalculateTransformsTest);
+};
+
+const int SquareInkDropAnimationCalculateTransformsTest::kHalfDrawnSize = 5;
+const int SquareInkDropAnimationCalculateTransformsTest::kDrawnSize =
+ 2 * kHalfDrawnSize;
+
+const int SquareInkDropAnimationCalculateTransformsTest::kTransformedRadius =
+ 10;
+const int SquareInkDropAnimationCalculateTransformsTest::kHalfTransformedSize =
+ 100;
+const int SquareInkDropAnimationCalculateTransformsTest::kTransformedSize =
+ 2 * kHalfTransformedSize;
+
+const gfx::Point
+ SquareInkDropAnimationCalculateTransformsTest::kDrawnCenterPoint =
+ gfx::Point(kHalfDrawnSize, kHalfDrawnSize);
+
+const gfx::Point
+ SquareInkDropAnimationCalculateTransformsTest::kDrawnMidLeftPoint =
+ gfx::Point(0, kHalfDrawnSize);
+
+const gfx::Point
+ SquareInkDropAnimationCalculateTransformsTest::kDrawnMidRightPoint =
+ gfx::Point(kDrawnSize, kHalfDrawnSize);
+
+const gfx::Point
+ SquareInkDropAnimationCalculateTransformsTest::kDrawnTopMidPoint =
+ gfx::Point(kHalfDrawnSize, 0);
+
+const gfx::Point
+ SquareInkDropAnimationCalculateTransformsTest::kDrawnBottomMidPoint =
+ gfx::Point(kHalfDrawnSize, kDrawnSize);
+
+SquareInkDropAnimationCalculateTransformsTest::
+ SquareInkDropAnimationCalculateTransformsTest()
+ : ink_drop_animation_(gfx::Size(kDrawnSize, kDrawnSize),
+ 2,
+ gfx::Size(kHalfDrawnSize, kHalfDrawnSize),
+ 1,
+ gfx::Point(),
+ SK_ColorBLACK),
+ test_api_(&ink_drop_animation_) {}
+
+SquareInkDropAnimationCalculateTransformsTest::
+ ~SquareInkDropAnimationCalculateTransformsTest() {}
+
+} // namespace
+
+TEST_F(SquareInkDropAnimationCalculateTransformsTest,
+ TransformedPointsUsingTransformsFromCalculateCircleTransforms) {
+ test_api_.CalculateCircleTransforms(
+ gfx::Size(kTransformedSize, kTransformedSize), &transforms_);
+
+ struct {
+ PaintedShape shape;
+ gfx::Point center_point;
+ gfx::Point mid_left_point;
+ gfx::Point mid_right_point;
+ gfx::Point top_mid_point;
+ gfx::Point bottom_mid_point;
+ } test_cases[] = {
+ {PaintedShape::TOP_LEFT_CIRCLE, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0),
+ gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)},
+ {PaintedShape::TOP_RIGHT_CIRCLE, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0),
+ gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)},
+ {PaintedShape::BOTTOM_RIGHT_CIRCLE, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0),
+ gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)},
+ {PaintedShape::BOTTOM_LEFT_CIRCLE, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0),
+ gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)},
+ {PaintedShape::HORIZONTAL_RECT, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0), gfx::Point(0, 0), gfx::Point(0, 0)},
+ {PaintedShape::VERTICAL_RECT, gfx::Point(0, 0), gfx::Point(0, 0),
+ gfx::Point(0, 0), gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)}};
+
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ PaintedShape shape = test_cases[i].shape;
+ SCOPED_TRACE(testing::Message() << "i=" << i << " shape=" << shape);
+ gfx::Transform transform = transforms_[shape];
+
+ EXPECT_EQ(test_cases[i].center_point,
+ TransformPoint(transform, kDrawnCenterPoint));
+ EXPECT_EQ(test_cases[i].mid_left_point,
+ TransformPoint(transform, kDrawnMidLeftPoint));
+ EXPECT_EQ(test_cases[i].mid_right_point,
+ TransformPoint(transform, kDrawnMidRightPoint));
+ EXPECT_EQ(test_cases[i].top_mid_point,
+ TransformPoint(transform, kDrawnTopMidPoint));
+ EXPECT_EQ(test_cases[i].bottom_mid_point,
+ TransformPoint(transform, kDrawnBottomMidPoint));
+ }
+}
+
+TEST_F(SquareInkDropAnimationCalculateTransformsTest,
+ TransformedPointsUsingTransformsFromCalculateRectTransforms) {
+ test_api_.CalculateRectTransforms(
+ gfx::Size(kTransformedSize, kTransformedSize), kTransformedRadius,
+ &transforms_);
+
+ const int x_offset = kHalfTransformedSize - kTransformedRadius;
+ const int y_offset = kHalfTransformedSize - kTransformedRadius;
+
+ struct {
+ PaintedShape shape;
+ gfx::Point center_point;
+ gfx::Point mid_left_point;
+ gfx::Point mid_right_point;
+ gfx::Point top_mid_point;
+ gfx::Point bottom_mid_point;
+ } test_cases[] = {
+ {PaintedShape::TOP_LEFT_CIRCLE, gfx::Point(-x_offset, -y_offset),
+ gfx::Point(-kHalfTransformedSize, -y_offset),
+ gfx::Point(-x_offset + kTransformedRadius, -y_offset),
+ gfx::Point(-x_offset, -kHalfTransformedSize),
+ gfx::Point(-x_offset, -y_offset + kTransformedRadius)},
+ {PaintedShape::TOP_RIGHT_CIRCLE, gfx::Point(x_offset, -y_offset),
+ gfx::Point(x_offset - kTransformedRadius, -y_offset),
+ gfx::Point(kHalfTransformedSize, -y_offset),
+ gfx::Point(x_offset, -kHalfTransformedSize),
+ gfx::Point(x_offset, -y_offset + kTransformedRadius)},
+ {PaintedShape::BOTTOM_RIGHT_CIRCLE, gfx::Point(x_offset, y_offset),
+ gfx::Point(x_offset - kTransformedRadius, y_offset),
+ gfx::Point(kHalfTransformedSize, y_offset),
+ gfx::Point(x_offset, y_offset - kTransformedRadius),
+ gfx::Point(x_offset, kHalfTransformedSize)},
+ {PaintedShape::BOTTOM_LEFT_CIRCLE, gfx::Point(-x_offset, y_offset),
+ gfx::Point(-kHalfTransformedSize, y_offset),
+ gfx::Point(-x_offset + kTransformedRadius, y_offset),
+ gfx::Point(-x_offset, y_offset - kTransformedRadius),
+ gfx::Point(-x_offset, kHalfTransformedSize)},
+ {PaintedShape::HORIZONTAL_RECT, gfx::Point(0, 0),
+ gfx::Point(-kHalfTransformedSize, 0),
+ gfx::Point(kHalfTransformedSize, 0), gfx::Point(0, -y_offset),
+ gfx::Point(0, y_offset)},
+ {PaintedShape::VERTICAL_RECT, gfx::Point(0, 0), gfx::Point(-x_offset, 0),
+ gfx::Point(x_offset, 0), gfx::Point(0, -kHalfTransformedSize),
+ gfx::Point(0, kHalfTransformedSize)}};
+
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ PaintedShape shape = test_cases[i].shape;
+ SCOPED_TRACE(testing::Message() << "i=" << i << " shape=" << shape);
+ gfx::Transform transform = transforms_[shape];
+
+ EXPECT_EQ(test_cases[i].center_point,
+ TransformPoint(transform, kDrawnCenterPoint));
+ EXPECT_EQ(test_cases[i].mid_left_point,
+ TransformPoint(transform, kDrawnMidLeftPoint));
+ EXPECT_EQ(test_cases[i].mid_right_point,
+ TransformPoint(transform, kDrawnMidRightPoint));
+ EXPECT_EQ(test_cases[i].top_mid_point,
+ TransformPoint(transform, kDrawnTopMidPoint));
+ EXPECT_EQ(test_cases[i].bottom_mid_point,
+ TransformPoint(transform, kDrawnBottomMidPoint));
+ }
+}
+
+} // namespace test
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_ANIMATION_UNITTEST_H_
diff --git a/chromium/ui/views/background.cc b/chromium/ui/views/background.cc
index 5338f37b2f1..56f1eb36405 100644
--- a/chromium/ui/views/background.cc
+++ b/chromium/ui/views/background.cc
@@ -61,34 +61,16 @@ class BackgroundPainter : public Background {
Background::Background()
: color_(SK_ColorWHITE)
-#if defined(OS_WIN)
- , native_control_brush_(NULL)
-#endif
{
}
Background::~Background() {
-#if defined(OS_WIN)
- DeleteObject(native_control_brush_);
-#endif
}
void Background::SetNativeControlColor(SkColor color) {
color_ = color;
-#if defined(OS_WIN)
- DeleteObject(native_control_brush_);
- native_control_brush_ = NULL;
-#endif
}
-#if defined(OS_WIN)
-HBRUSH Background::GetNativeControlBrush() const {
- if (!native_control_brush_)
- native_control_brush_ = CreateSolidBrush(skia::SkColorToCOLORREF(color_));
- return native_control_brush_;
-}
-#endif
-
// static
Background* Background::CreateSolidBackground(SkColor color) {
return new SolidBackground(color);
diff --git a/chromium/ui/views/background.h b/chromium/ui/views/background.h
index 0d7d65cdcd6..d00418ad453 100644
--- a/chromium/ui/views/background.h
+++ b/chromium/ui/views/background.h
@@ -90,19 +90,8 @@ class VIEWS_EXPORT Background {
// backgrounds, this is not useful (returns a default color).
SkColor get_color() const { return color_; }
-#if defined(OS_WIN)
- // TODO(port): Make GetNativeControlBrush portable (currently uses HBRUSH).
-
- // Get the brush that was specified by SetNativeControlColor
- HBRUSH GetNativeControlBrush() const;
-#endif // defined(OS_WIN)
-
private:
SkColor color_;
-#if defined(OS_WIN)
- // TODO(port): Create portable replacement for HBRUSH.
- mutable HBRUSH native_control_brush_;
-#endif // defined(OS_WIN)
DISALLOW_COPY_AND_ASSIGN(Background);
};
diff --git a/chromium/ui/views/border.cc b/chromium/ui/views/border.cc
index 9b87180e1eb..a7a11440923 100644
--- a/chromium/ui/views/border.cc
+++ b/chromium/ui/views/border.cc
@@ -99,7 +99,7 @@ void RoundedRectBorder::Paint(const View& view, gfx::Canvas* canvas) {
}
gfx::Insets RoundedRectBorder::GetInsets() const {
- return gfx::Insets(thickness_, thickness_, thickness_, thickness_);
+ return gfx::Insets(thickness_);
}
gfx::Size RoundedRectBorder::GetMinimumSize() const {
@@ -184,8 +184,7 @@ scoped_ptr<Border> Border::NullBorder() {
// static
scoped_ptr<Border> Border::CreateSolidBorder(int thickness, SkColor color) {
- return make_scoped_ptr(new SolidSidedBorder(
- gfx::Insets(thickness, thickness, thickness, thickness), color));
+ return make_scoped_ptr(new SolidSidedBorder(gfx::Insets(thickness), color));
}
// static
diff --git a/chromium/ui/views/bubble/bubble_border.cc b/chromium/ui/views/bubble/bubble_border.cc
index c2892ca0fc7..f81bb2d7618 100644
--- a/chromium/ui/views/bubble/bubble_border.cc
+++ b/chromium/ui/views/bubble/bubble_border.cc
@@ -12,6 +12,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/path.h"
#include "ui/gfx/skia_util.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/painter.h"
@@ -144,8 +145,13 @@ BubbleBorder::BubbleBorder(Arrow arrow, Shadow shadow, SkColor color)
shadow_(shadow),
background_color_(color),
use_theme_background_color_(false) {
- DCHECK(shadow < SHADOW_COUNT);
- images_ = GetBorderImages(shadow);
+#if defined(OS_MACOSX)
+ // On Mac, use the NO_ASSETS bubble border. WindowServer on Mac is able to
+ // generate drop shadows for dialogs, hence we don't use raster shadows.
+ shadow_ = NO_ASSETS;
+#endif // OS_MACOSX
+ DCHECK(shadow_ < SHADOW_COUNT);
+ images_ = GetBorderImages(shadow_);
}
BubbleBorder::~BubbleBorder() {}
@@ -158,8 +164,14 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect,
int h = anchor_rect.height();
const gfx::Size size(GetSizeForContentsSize(contents_size));
const int arrow_offset = GetArrowOffset(size);
- const int arrow_size =
+ // |arrow_shift| is necessary to visually align the tip of the bubble arrow
+ // with the anchor point. This shift is an inverse of the shadow thickness.
+ int arrow_shift =
images_->arrow_interior_thickness + kStroke - images_->arrow_thickness;
+ // When arrow is painted transparently the visible border of the bubble needs
+ // to be positioned at the same bounds as when the arrow is shown.
+ if (arrow_paint_type_ == PAINT_TRANSPARENT)
+ arrow_shift += images_->arrow_interior_thickness;
const bool mid_anchor = alignment_ == ALIGN_ARROW_TO_MID_ANCHOR;
// Calculate the bubble coordinates based on the border and arrow settings.
@@ -172,9 +184,11 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect,
x += mid_anchor ? w / 2 + arrow_offset - size.width() :
w - size.width() + GetBorderThickness() - kStroke;
}
- y += is_arrow_on_top(arrow_) ? h + arrow_size : -arrow_size - size.height();
+ y += is_arrow_on_top(arrow_) ? h + arrow_shift
+ : -arrow_shift - size.height();
} else if (has_arrow(arrow_)) {
- x += is_arrow_on_left(arrow_) ? w + arrow_size : -arrow_size - size.width();
+ x += is_arrow_on_left(arrow_) ? w + arrow_shift
+ : -arrow_shift - size.width();
if (is_arrow_on_top(arrow_)) {
y += mid_anchor ? h / 2 - arrow_offset : kStroke - GetBorderThickness();
} else if (is_arrow_at_center(arrow_)) {
@@ -211,6 +225,15 @@ int BubbleBorder::GetArrowOffset(const gfx::Size& border_size) const {
return std::max(min, std::min(arrow_offset_, edge_length - min));
}
+bool BubbleBorder::GetArrowPath(const gfx::Rect& view_bounds,
+ gfx::Path* path) const {
+ if (!has_arrow(arrow_) || arrow_paint_type_ != PAINT_NORMAL)
+ return false;
+
+ GetArrowPathFromArrowBounds(GetArrowRect(view_bounds), path);
+ return true;
+}
+
void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
gfx::Rect bounds(view.GetContentsBounds());
bounds.Inset(-GetBorderThickness(), -GetBorderThickness());
@@ -238,8 +261,8 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
gfx::Insets BubbleBorder::GetInsets() const {
// The insets contain the stroke and shadow pixels outside the bubble fill.
const int inset = GetBorderThickness();
- if ((arrow_paint_type_ == PAINT_NONE) || !has_arrow(arrow_))
- return gfx::Insets(inset, inset, inset, inset);
+ if (arrow_paint_type_ != PAINT_NORMAL || !has_arrow(arrow_))
+ return gfx::Insets(inset);
int first_inset = inset;
int second_inset = std::max(inset, images_->arrow_thickness);
@@ -264,14 +287,16 @@ gfx::Size BubbleBorder::GetSizeForContentsSize(
// Ensure the bubble is large enough to not overlap border and arrow images.
const int min = 2 * images_->border_thickness;
+ // Only take arrow image sizes into account when the bubble tip is shown.
+ if (arrow_paint_type_ != PAINT_NORMAL || !has_arrow(arrow_)) {
+ size.SetToMax(gfx::Size(min, min));
+ return size;
+ }
const int min_with_arrow_width = min + images_->arrow_width;
const int min_with_arrow_thickness = images_->border_thickness +
std::max(images_->arrow_thickness + images_->border_interior_thickness,
images_->border_thickness);
- // Only take arrow image sizes into account when the bubble tip is shown.
- if (arrow_paint_type_ == PAINT_NONE || !has_arrow(arrow_))
- size.SetToMax(gfx::Size(min, min));
- else if (is_arrow_on_horizontal(arrow_))
+ if (is_arrow_on_horizontal(arrow_))
size.SetToMax(gfx::Size(min_with_arrow_width, min_with_arrow_thickness));
else
size.SetToMax(gfx::Size(min_with_arrow_thickness, min_with_arrow_width));
@@ -328,9 +353,8 @@ gfx::Rect BubbleBorder::GetArrowRect(const gfx::Rect& bounds) const {
return gfx::Rect(origin, gfx::Size(width, height));
}
-void BubbleBorder::DrawArrow(gfx::Canvas* canvas,
- const gfx::Rect& arrow_bounds) const {
- canvas->DrawImageInt(*GetArrowImage(), arrow_bounds.x(), arrow_bounds.y());
+void BubbleBorder::GetArrowPathFromArrowBounds(const gfx::Rect& arrow_bounds,
+ SkPath* path) const {
const bool horizontal = is_arrow_on_horizontal(arrow_);
const int thickness = images_->arrow_interior_thickness;
float tip_x = horizontal ? arrow_bounds.CenterPoint().x() :
@@ -344,16 +368,21 @@ void BubbleBorder::DrawArrow(gfx::Canvas* canvas,
const int offset_to_next_vertex = positive_offset ?
images_->arrow_interior_thickness : -images_->arrow_interior_thickness;
- SkPath path;
- path.incReserve(4);
- path.moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y));
- path.lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
- SkDoubleToScalar(tip_y + offset_to_next_vertex));
+ path->incReserve(4);
+ path->moveTo(SkDoubleToScalar(tip_x), SkDoubleToScalar(tip_y));
+ path->lineTo(SkDoubleToScalar(tip_x + offset_to_next_vertex),
+ SkDoubleToScalar(tip_y + offset_to_next_vertex));
const int multiplier = horizontal ? 1 : -1;
- path.lineTo(SkDoubleToScalar(tip_x - multiplier * offset_to_next_vertex),
- SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex));
- path.close();
+ path->lineTo(SkDoubleToScalar(tip_x - multiplier * offset_to_next_vertex),
+ SkDoubleToScalar(tip_y + multiplier * offset_to_next_vertex));
+ path->close();
+}
+void BubbleBorder::DrawArrow(gfx::Canvas* canvas,
+ const gfx::Rect& arrow_bounds) const {
+ canvas->DrawImageInt(*GetArrowImage(), arrow_bounds.x(), arrow_bounds.y());
+ SkPath path;
+ GetArrowPathFromArrowBounds(arrow_bounds, &path);
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(background_color_);
diff --git a/chromium/ui/views/bubble/bubble_border.h b/chromium/ui/views/bubble/bubble_border.h
index fac3a719a47..057459f2539 100644
--- a/chromium/ui/views/bubble/bubble_border.h
+++ b/chromium/ui/views/bubble/bubble_border.h
@@ -13,7 +13,10 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
+class SkPath;
+
namespace gfx {
+class Path;
class Rect;
}
@@ -120,16 +123,6 @@ class VIEWS_EXPORT BubbleBorder : public Border {
BubbleBorder(Arrow arrow, Shadow shadow, SkColor color);
~BubbleBorder() override;
- // Returns the radius of the corner of the border.
- // TODO(xiyuan): Get rid of this since it's part of BorderImages now?
- static int GetCornerRadius() {
- // We can't safely calculate a border radius by comparing the sizes of the
- // side and corner images, because either may have been extended in various
- // directions in order to do more subtle dropshadow fading or other effects.
- // So we hardcode the most accurate value.
- return 4;
- }
-
static bool has_arrow(Arrow a) { return a < NONE; }
static bool is_arrow_on_left(Arrow a) {
@@ -204,6 +197,13 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// Gets the arrow offset to use.
int GetArrowOffset(const gfx::Size& border_size) const;
+ // Retreives the arrow path given |view_bounds|. |view_bounds| should be local
+ // bounds of the view.
+ // Returns false if |path| is unchanged, which is the case when there is no
+ // painted arrow.
+ // The returned path does not account for arrow stroke and shadow.
+ bool GetArrowPath(const gfx::Rect& view_bounds, gfx::Path* path) const;
+
// Overridden from Border:
void Paint(const View& view, gfx::Canvas* canvas) override;
gfx::Insets GetInsets() const override;
@@ -220,6 +220,8 @@ class VIEWS_EXPORT BubbleBorder : public Border {
gfx::Size GetSizeForContentsSize(const gfx::Size& contents_size) const;
gfx::ImageSkia* GetArrowImage() const;
gfx::Rect GetArrowRect(const gfx::Rect& bounds) const;
+ void GetArrowPathFromArrowBounds(const gfx::Rect& arrow_bounds,
+ SkPath* path) const;
void DrawArrow(gfx::Canvas* canvas, const gfx::Rect& arrow_bounds) const;
internal::BorderImages* GetImagesForTest() const;
diff --git a/chromium/ui/views/bubble/bubble_border_unittest.cc b/chromium/ui/views/bubble/bubble_border_unittest.cc
index e472e1b4fbf..31323822936 100644
--- a/chromium/ui/views/bubble/bubble_border_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_border_unittest.cc
@@ -224,7 +224,7 @@ TEST_F(BubbleBorderTest, GetSizeForContentsSizeTest) {
const gfx::Size kMediumSize = gfx::Size(50, 60);
const gfx::Size kSmallHorizArrow(
- 2 * kImages->border_thickness + kImages->top_arrow.width(),
+ 2 * kImages->border_thickness + kImages->arrow_width,
kImages->border_thickness + kImages->arrow_thickness +
kImages->border_interior_thickness);
@@ -309,7 +309,7 @@ TEST_F(BubbleBorderTest, GetSizeForContentsSizeTest) {
border.GetSizeForContentsSize(cases[i].content));
border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
- EXPECT_EQ(cases[i].expected_with_arrow,
+ EXPECT_EQ(cases[i].expected_without_arrow,
border.GetSizeForContentsSize(cases[i].content));
border.set_paint_arrow(BubbleBorder::PAINT_NONE);
@@ -345,19 +345,24 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
const int kArrowOffsetForHorizCenter = kTotalSizeWithHorizArrow.width() / 2;
const int kArrowOffsetForVertCenter = kTotalSizeWithVertArrow.height() / 2;
const int kArrowOffsetForNotCenter =
- kImages->border_thickness + (kImages->top_arrow.width() / 2);
-
- const int kArrowSize =
- kImages->arrow_interior_thickness + BubbleBorder::kStroke -
- kImages->arrow_thickness;
-
- const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowSize;
+ kImages->border_thickness + (kImages->arrow_width / 2);
+
+ const int kArrowThickness = kImages->arrow_interior_thickness;
+ const int kArrowShift =
+ kArrowThickness + BubbleBorder::kStroke - kImages->arrow_thickness;
+ const int kHeightDifference = kTotalSizeWithHorizArrow.height() -
+ kTotalSizeWithNoArrow.height();
+ const int kWidthDifference = kTotalSizeWithVertArrow.width() -
+ kTotalSizeWithNoArrow.width();
+ EXPECT_EQ(kHeightDifference, kWidthDifference);
+ EXPECT_EQ(kHeightDifference, kArrowThickness);
+
+ const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowShift;
const int kBottomHorizArrowY =
- kAnchor.y() - kArrowSize - kTotalSizeWithHorizArrow.height();
-
- const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowSize;
+ kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height();
+ const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowShift;
const int kRightVertArrowX =
- kAnchor.x() - kArrowSize - kTotalSizeWithVertArrow.width();
+ kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width();
struct TestCase {
BubbleBorder::Arrow arrow;
@@ -408,12 +413,43 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
for (size_t i = 0; i < arraysize(cases); ++i) {
SCOPED_TRACE(base::StringPrintf("i=%d arrow=%d alignment=%d",
static_cast<int>(i), cases[i].arrow, cases[i].alignment));
- border.set_arrow(cases[i].arrow);
+ const BubbleBorder::Arrow arrow = cases[i].arrow;
+ border.set_arrow(arrow);
border.set_alignment(cases[i].alignment);
+ border.set_paint_arrow(BubbleBorder::PAINT_NORMAL);
gfx::Point origin = border.GetBounds(kAnchor, kContentSize).origin();
- EXPECT_EQ(cases[i].expected_x, origin.x());
- EXPECT_EQ(cases[i].expected_y, origin.y());
+ int expected_x = cases[i].expected_x;
+ int expected_y = cases[i].expected_y;
+ EXPECT_EQ(expected_x, origin.x());
+ EXPECT_EQ(expected_y, origin.y());
+
+ border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
+ origin = border.GetBounds(kAnchor, kContentSize).origin();
+ if (border.is_arrow_on_horizontal(arrow)) {
+ expected_y += BubbleBorder::is_arrow_on_top(arrow)
+ ? kArrowThickness : (-kArrowThickness + kHeightDifference);
+ } else if (BubbleBorder::has_arrow(arrow)) {
+ expected_x += BubbleBorder::is_arrow_on_left(arrow)
+ ? kArrowThickness : (-kArrowThickness + kWidthDifference);
+ }
+ EXPECT_EQ(expected_x, origin.x());
+ EXPECT_EQ(expected_y, origin.y());
+
+ border.set_paint_arrow(BubbleBorder::PAINT_NONE);
+ origin = border.GetBounds(kAnchor, kContentSize).origin();
+ expected_x = cases[i].expected_x;
+ expected_y = cases[i].expected_y;
+ if (border.is_arrow_on_horizontal(arrow) &&
+ !BubbleBorder::is_arrow_on_top(arrow)) {
+ expected_y += kHeightDifference;
+ } else if (BubbleBorder::has_arrow(arrow) &&
+ !border.is_arrow_on_horizontal(arrow) &&
+ !BubbleBorder::is_arrow_on_left(arrow)) {
+ expected_x += kWidthDifference;
+ }
+ EXPECT_EQ(expected_x, origin.x());
+ EXPECT_EQ(expected_y, origin.y());
}
}
diff --git a/chromium/ui/views/bubble/bubble_delegate.cc b/chromium/ui/views/bubble/bubble_delegate.cc
index fd922e44547..5850c3f827a 100644
--- a/chromium/ui/views/bubble/bubble_delegate.cc
+++ b/chromium/ui/views/bubble/bubble_delegate.cc
@@ -6,12 +6,14 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/default_style.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/focus/view_storage.h"
+#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
@@ -19,9 +21,6 @@
#include "ui/base/win/shell.h"
#endif
-// The defaut margin between the content and the inside border, in pixels.
-static const int kDefaultMargin = 6;
-
namespace views {
namespace {
@@ -63,7 +62,10 @@ BubbleDelegateView::BubbleDelegateView(View* anchor_view,
arrow_(arrow),
shadow_(BubbleBorder::SMALL_SHADOW),
color_explicitly_set_(false),
- margins_(kDefaultMargin, kDefaultMargin, kDefaultMargin, kDefaultMargin),
+ margins_(kPanelVertMargin,
+ kPanelHorizMargin,
+ kPanelVertMargin,
+ kPanelHorizMargin),
accept_events_(true),
border_accepts_events_(true),
adjust_if_offscreen_(true),
@@ -119,10 +121,14 @@ View* BubbleDelegateView::GetContentsView() {
NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView(
Widget* widget) {
- BubbleFrameView* frame = new BubbleFrameView(margins());
+ BubbleFrameView* frame = new BubbleFrameView(
+ gfx::Insets(kPanelVertMargin, kPanelHorizMargin, 0, kPanelHorizMargin),
+ margins());
// Note: In CreateBubble, the call to SizeToContents() will cause
// the relayout that this call requires.
frame->SetTitleFontList(GetTitleFontList());
+ frame->SetFootnoteView(CreateFootnoteView());
+
BubbleBorder::Arrow adjusted_arrow = arrow();
if (base::i18n::IsRTL())
adjusted_arrow = BubbleBorder::horizontal_mirror(adjusted_arrow);
@@ -201,6 +207,15 @@ void BubbleDelegateView::OnBeforeBubbleWidgetInit(Widget::InitParams* params,
Widget* widget) const {
}
+View* BubbleDelegateView::CreateFootnoteView() {
+ return nullptr;
+}
+
+void BubbleDelegateView::UseCompactMargins() {
+ const int kCompactMargin = 6;
+ margins_.Set(kCompactMargin, kCompactMargin, kCompactMargin, kCompactMargin);
+}
+
void BubbleDelegateView::SetAlignment(BubbleBorder::BubbleAlignment alignment) {
GetBubbleFrameView()->bubble_border()->set_alignment(alignment);
SizeToContents();
@@ -287,10 +302,9 @@ gfx::Rect BubbleDelegateView::GetBubbleBounds() {
const gfx::FontList& BubbleDelegateView::GetTitleFontList() const {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- return rb.GetFontList(ui::ResourceBundle::MediumFont);
+ return rb.GetFontListWithDelta(ui::kTitleFontSizeDelta);
}
-
void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
if (!color_explicitly_set_)
color_ = theme->GetSystemColor(ui::NativeTheme::kColorId_BubbleBackground);
@@ -303,10 +317,7 @@ void BubbleDelegateView::UpdateColorsFromTheme(const ui::NativeTheme* theme) {
void BubbleDelegateView::HandleVisibilityChanged(Widget* widget, bool visible) {
if (widget == GetWidget() && anchor_widget() &&
anchor_widget()->GetTopLevelWidget()) {
- if (visible)
- anchor_widget()->GetTopLevelWidget()->DisableInactiveRendering();
- else
- anchor_widget()->GetTopLevelWidget()->EnableInactiveRendering();
+ anchor_widget()->GetTopLevelWidget()->SetAlwaysRenderAsActive(visible);
}
// Fire AX_EVENT_ALERT for bubbles marked as AX_ROLE_ALERT_DIALOG; this
diff --git a/chromium/ui/views/bubble/bubble_delegate.h b/chromium/ui/views/bubble/bubble_delegate.h
index 4bc7f4a9d63..9392251e22d 100644
--- a/chromium/ui/views/bubble/bubble_delegate.h
+++ b/chromium/ui/views/bubble/bubble_delegate.h
@@ -23,6 +23,7 @@ class BubbleFrameView;
// BubbleDelegateView creates frame and client views for bubble Widgets.
// BubbleDelegateView itself is the client's contents view.
+// TODO(estade): remove this in favor of BubbleDialogDelegateView.
class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
public WidgetObserver {
public:
@@ -111,6 +112,12 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
Widget* widget) const;
+ // Creates and returns a view to be displayed at the bottom of the bubble.
+ virtual View* CreateFootnoteView();
+
+ // Sets |margins_| to a default picked for smaller bubbles.
+ void UseCompactMargins();
+
// Sets the bubble alignment relative to the anchor. This may only be called
// after calling CreateBubble.
void SetAlignment(BubbleBorder::BubbleAlignment alignment);
diff --git a/chromium/ui/views/bubble/bubble_delegate_unittest.cc b/chromium/ui/views/bubble/bubble_delegate_unittest.cc
index 92201c0882a..f7656f06151 100644
--- a/chromium/ui/views/bubble/bubble_delegate_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_delegate_unittest.cc
@@ -277,6 +277,7 @@ TEST_F(BubbleDelegateTest, CloseReasons) {
anchor_widget->GetContentsView(), BubbleBorder::NONE);
bubble_delegate->set_close_on_deactivate(true);
Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate);
+ anchor_widget->Show();
bubble_widget->Show();
anchor_widget->Activate();
EXPECT_TRUE(bubble_widget->IsClosed());
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate.cc b/chromium/ui/views/bubble/bubble_dialog_delegate.cc
new file mode 100644
index 00000000000..9673891dc39
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate.cc
@@ -0,0 +1,319 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/bubble/bubble_dialog_delegate.h"
+
+#include "build/build_config.h"
+#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/focus/view_storage.h"
+#include "ui/views/layout/layout_constants.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+#include "ui/views/window/dialog_client_view.h"
+
+#if defined(OS_WIN)
+#include "ui/base/win/shell.h"
+#endif
+
+namespace views {
+
+namespace {
+
+// Create a widget to host the bubble.
+Widget* CreateBubbleWidget(BubbleDialogDelegateView* bubble) {
+ Widget* bubble_widget = new Widget();
+ Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE);
+ bubble_params.delegate = bubble;
+ bubble_params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
+ bubble_params.accept_events = bubble->accept_events();
+ if (bubble->parent_window())
+ bubble_params.parent = bubble->parent_window();
+ else if (bubble->anchor_widget())
+ bubble_params.parent = bubble->anchor_widget()->GetNativeView();
+ bubble_params.activatable = bubble->CanActivate()
+ ? Widget::InitParams::ACTIVATABLE_YES
+ : Widget::InitParams::ACTIVATABLE_NO;
+ bubble->OnBeforeBubbleWidgetInit(&bubble_params, bubble_widget);
+ bubble_widget->Init(bubble_params);
+ if (bubble_params.parent)
+ bubble_widget->StackAbove(bubble_params.parent);
+ return bubble_widget;
+}
+
+} // namespace
+
+// static
+const char BubbleDialogDelegateView::kViewClassName[] =
+ "BubbleDialogDelegateView";
+
+BubbleDialogDelegateView::~BubbleDialogDelegateView() {
+ if (GetWidget())
+ GetWidget()->RemoveObserver(this);
+ SetLayoutManager(NULL);
+ SetAnchorView(NULL);
+}
+
+// static
+Widget* BubbleDialogDelegateView::CreateBubble(
+ BubbleDialogDelegateView* bubble_delegate) {
+ bubble_delegate->Init();
+ // Get the latest anchor widget from the anchor view at bubble creation time.
+ bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView());
+ Widget* bubble_widget = CreateBubbleWidget(bubble_delegate);
+
+#if defined(OS_WIN)
+ // If glass is enabled, the bubble is allowed to extend outside the bounds of
+ // the parent frame and let DWM handle compositing. If not, then we don't
+ // want to allow the bubble to extend the frame because it will be clipped.
+ bubble_delegate->set_adjust_if_offscreen(ui::win::IsAeroGlassEnabled());
+#elif (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
+ // Linux clips bubble windows that extend outside their parent window bounds.
+ // Mac never adjusts.
+ bubble_delegate->set_adjust_if_offscreen(false);
+#endif
+
+ bubble_delegate->SizeToContents();
+ bubble_widget->AddObserver(bubble_delegate);
+ return bubble_widget;
+}
+
+BubbleDialogDelegateView* BubbleDialogDelegateView::AsBubbleDialogDelegate() {
+ return this;
+}
+
+bool BubbleDialogDelegateView::ShouldShowCloseButton() const {
+ return false;
+}
+
+ClientView* BubbleDialogDelegateView::CreateClientView(Widget* widget) {
+ DialogClientView* client = new DialogClientView(widget, GetContentsView());
+ client->set_button_row_insets(gfx::Insets());
+ return client;
+}
+
+NonClientFrameView* BubbleDialogDelegateView::CreateNonClientFrameView(
+ Widget* widget) {
+ BubbleFrameView* frame = new BubbleFrameView(
+ gfx::Insets(kPanelVertMargin, kPanelHorizMargin, 0, kPanelHorizMargin),
+ margins());
+ // Note: In CreateBubble, the call to SizeToContents() will cause
+ // the relayout that this call requires.
+ frame->SetTitleFontList(GetTitleFontList());
+ frame->SetFootnoteView(CreateFootnoteView());
+
+ BubbleBorder::Arrow adjusted_arrow = arrow();
+ if (base::i18n::IsRTL())
+ adjusted_arrow = BubbleBorder::horizontal_mirror(adjusted_arrow);
+ frame->SetBubbleBorder(scoped_ptr<BubbleBorder>(
+ new BubbleBorder(adjusted_arrow, shadow(), color())));
+ return frame;
+}
+
+void BubbleDialogDelegateView::GetAccessibleState(ui::AXViewState* state) {
+ state->role = ui::AX_ROLE_DIALOG;
+}
+
+const char* BubbleDialogDelegateView::GetClassName() const {
+ return kViewClassName;
+}
+
+void BubbleDialogDelegateView::OnWidgetDestroying(Widget* widget) {
+ if (anchor_widget() == widget)
+ SetAnchorView(NULL);
+}
+
+void BubbleDialogDelegateView::OnWidgetVisibilityChanging(Widget* widget,
+ bool visible) {
+#if defined(OS_WIN)
+ // On Windows we need to handle this before the bubble is visible or hidden.
+ // Please see the comment on the OnWidgetVisibilityChanging function. On
+ // other platforms it is fine to handle it after the bubble is shown/hidden.
+ HandleVisibilityChanged(widget, visible);
+#endif
+}
+
+void BubbleDialogDelegateView::OnWidgetVisibilityChanged(Widget* widget,
+ bool visible) {
+#if !defined(OS_WIN)
+ HandleVisibilityChanged(widget, visible);
+#endif
+}
+
+void BubbleDialogDelegateView::OnWidgetActivationChanged(Widget* widget,
+ bool active) {
+ if (close_on_deactivate() && widget == GetWidget() && !active)
+ GetWidget()->Close();
+}
+
+void BubbleDialogDelegateView::OnWidgetBoundsChanged(
+ Widget* widget,
+ const gfx::Rect& new_bounds) {
+ if (GetBubbleFrameView() && anchor_widget() == widget)
+ SizeToContents();
+}
+
+View* BubbleDialogDelegateView::GetAnchorView() const {
+ return ViewStorage::GetInstance()->RetrieveView(anchor_view_storage_id_);
+}
+
+gfx::Rect BubbleDialogDelegateView::GetAnchorRect() const {
+ if (!GetAnchorView())
+ return anchor_rect_;
+
+ anchor_rect_ = GetAnchorView()->GetBoundsInScreen();
+ anchor_rect_.Inset(anchor_view_insets_);
+ return anchor_rect_;
+}
+
+void BubbleDialogDelegateView::OnBeforeBubbleWidgetInit(
+ Widget::InitParams* params,
+ Widget* widget) const {}
+
+void BubbleDialogDelegateView::UseCompactMargins() {
+ const int kCompactMargin = 6;
+ margins_.Set(kCompactMargin, kCompactMargin, kCompactMargin, kCompactMargin);
+}
+
+void BubbleDialogDelegateView::SetAlignment(
+ BubbleBorder::BubbleAlignment alignment) {
+ GetBubbleFrameView()->bubble_border()->set_alignment(alignment);
+ SizeToContents();
+}
+
+void BubbleDialogDelegateView::SetArrowPaintType(
+ BubbleBorder::ArrowPaintType paint_type) {
+ GetBubbleFrameView()->bubble_border()->set_paint_arrow(paint_type);
+ SizeToContents();
+}
+
+void BubbleDialogDelegateView::OnAnchorBoundsChanged() {
+ SizeToContents();
+}
+
+BubbleDialogDelegateView::BubbleDialogDelegateView()
+ : BubbleDialogDelegateView(nullptr, BubbleBorder::TOP_LEFT) {}
+
+BubbleDialogDelegateView::BubbleDialogDelegateView(View* anchor_view,
+ BubbleBorder::Arrow arrow)
+ : close_on_deactivate_(true),
+ anchor_view_storage_id_(ViewStorage::GetInstance()->CreateStorageID()),
+ anchor_widget_(NULL),
+ arrow_(arrow),
+ shadow_(BubbleBorder::SMALL_SHADOW),
+ color_explicitly_set_(false),
+ margins_(kPanelVertMargin,
+ kPanelHorizMargin,
+ kPanelVertMargin,
+ kPanelHorizMargin),
+ accept_events_(true),
+ border_accepts_events_(true),
+ adjust_if_offscreen_(true),
+ parent_window_(NULL) {
+ if (anchor_view)
+ SetAnchorView(anchor_view);
+ UpdateColorsFromTheme(GetNativeTheme());
+}
+
+gfx::Rect BubbleDialogDelegateView::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(), GetWidget()->client_view()->GetPreferredSize(),
+ adjust_if_offscreen_ && !anchor_minimized);
+}
+
+const gfx::FontList& BubbleDialogDelegateView::GetTitleFontList() const {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return rb.GetFontList(ui::ResourceBundle::MediumFont);
+}
+
+void BubbleDialogDelegateView::OnNativeThemeChanged(
+ const ui::NativeTheme* theme) {
+ UpdateColorsFromTheme(theme);
+}
+
+void BubbleDialogDelegateView::Init() {}
+
+void BubbleDialogDelegateView::SetAnchorView(View* anchor_view) {
+ // When the anchor view gets set the associated anchor widget might
+ // change as well.
+ if (!anchor_view || anchor_widget() != anchor_view->GetWidget()) {
+ if (anchor_widget()) {
+ anchor_widget_->RemoveObserver(this);
+ anchor_widget_ = NULL;
+ }
+ if (anchor_view) {
+ anchor_widget_ = anchor_view->GetWidget();
+ if (anchor_widget_)
+ anchor_widget_->AddObserver(this);
+ }
+ }
+
+ // Remove the old storage item and set the new (if there is one).
+ ViewStorage* view_storage = ViewStorage::GetInstance();
+ if (view_storage->RetrieveView(anchor_view_storage_id_))
+ view_storage->RemoveView(anchor_view_storage_id_);
+ if (anchor_view)
+ view_storage->StoreView(anchor_view_storage_id_, anchor_view);
+
+ // 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();
+}
+
+void BubbleDialogDelegateView::SetAnchorRect(const gfx::Rect& rect) {
+ anchor_rect_ = rect;
+ if (GetWidget())
+ OnAnchorBoundsChanged();
+}
+
+void BubbleDialogDelegateView::SizeToContents() {
+ GetWidget()->SetBounds(GetBubbleBounds());
+}
+
+BubbleFrameView* BubbleDialogDelegateView::GetBubbleFrameView() const {
+ const NonClientView* view =
+ GetWidget() ? GetWidget()->non_client_view() : NULL;
+ return view ? static_cast<BubbleFrameView*>(view->frame_view()) : NULL;
+}
+
+void BubbleDialogDelegateView::UpdateColorsFromTheme(
+ const ui::NativeTheme* theme) {
+ if (!color_explicitly_set_)
+ color_ = theme->GetSystemColor(ui::NativeTheme::kColorId_BubbleBackground);
+ set_background(Background::CreateSolidBackground(color()));
+ BubbleFrameView* frame_view = GetBubbleFrameView();
+ if (frame_view)
+ frame_view->bubble_border()->set_background_color(color());
+}
+
+void BubbleDialogDelegateView::HandleVisibilityChanged(Widget* widget,
+ bool visible) {
+ if (widget == GetWidget() && anchor_widget() &&
+ anchor_widget()->GetTopLevelWidget()) {
+ anchor_widget()->GetTopLevelWidget()->SetAlwaysRenderAsActive(visible);
+ }
+
+ // Fire AX_EVENT_ALERT for bubbles marked as AX_ROLE_ALERT_DIALOG; this
+ // instructs accessibility tools to read the bubble in its entirety rather
+ // than just its title and initially focused view. See
+ // http://crbug.com/474622 for details.
+ if (widget == GetWidget() && visible) {
+ ui::AXViewState state;
+ GetAccessibleState(&state);
+ if (state.role == ui::AX_ROLE_ALERT_DIALOG)
+ NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate.h b/chromium/ui/views/bubble/bubble_dialog_delegate.h
new file mode 100644
index 00000000000..13c576efd7e
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate.h
@@ -0,0 +1,205 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_BUBBLE_BUBBLE_DIALOG_DELEGATE_H_
+#define UI_VIEWS_BUBBLE_BUBBLE_DIALOG_DELEGATE_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+#include "ui/views/window/dialog_delegate.h"
+
+namespace gfx {
+class FontList;
+class Rect;
+}
+
+namespace views {
+
+class BubbleFrameView;
+
+// BubbleDialogDelegateView is a special DialogDelegateView for bubbles.
+class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
+ public WidgetObserver {
+ public:
+ // Internal class name.
+ static const char kViewClassName[];
+
+ enum class CloseReason {
+ DEACTIVATION,
+ CLOSE_BUTTON,
+ UNKNOWN,
+ };
+
+ ~BubbleDialogDelegateView() override;
+
+ // Create and initialize the bubble Widget(s) with proper bounds.
+ static Widget* CreateBubble(BubbleDialogDelegateView* bubble_delegate);
+
+ // WidgetDelegateView overrides:
+ BubbleDialogDelegateView* AsBubbleDialogDelegate() override;
+ bool ShouldShowCloseButton() const override;
+ ClientView* CreateClientView(Widget* widget) override;
+ NonClientFrameView* CreateNonClientFrameView(Widget* widget) override;
+ void GetAccessibleState(ui::AXViewState* state) override;
+ const char* GetClassName() const override;
+
+ // WidgetObserver overrides:
+ void OnWidgetDestroying(Widget* widget) override;
+ void OnWidgetVisibilityChanging(Widget* widget, bool visible) override;
+ void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;
+ void OnWidgetActivationChanged(Widget* widget, bool active) override;
+ void OnWidgetBoundsChanged(Widget* widget,
+ const gfx::Rect& new_bounds) override;
+
+ bool close_on_deactivate() const { return close_on_deactivate_; }
+ void set_close_on_deactivate(bool close) { close_on_deactivate_ = close; }
+
+ View* GetAnchorView() const;
+ Widget* anchor_widget() const { return anchor_widget_; }
+
+ // The anchor rect is used in the absence of an assigned anchor view.
+ const gfx::Rect& anchor_rect() const { return anchor_rect_; }
+
+ BubbleBorder::Arrow arrow() const { return arrow_; }
+ void set_arrow(BubbleBorder::Arrow arrow) { arrow_ = arrow; }
+
+ BubbleBorder::Shadow shadow() const { return shadow_; }
+ void set_shadow(BubbleBorder::Shadow shadow) { shadow_ = shadow; }
+
+ SkColor color() const { return color_; }
+ void set_color(SkColor color) {
+ color_ = color;
+ color_explicitly_set_ = true;
+ }
+
+ const gfx::Insets& margins() const { return margins_; }
+ void set_margins(const gfx::Insets& margins) { margins_ = margins; }
+
+ const gfx::Insets& anchor_view_insets() const { return anchor_view_insets_; }
+ void set_anchor_view_insets(const gfx::Insets& i) { anchor_view_insets_ = i; }
+
+ gfx::NativeView parent_window() const { return parent_window_; }
+ void set_parent_window(gfx::NativeView window) { parent_window_ = window; }
+
+ bool accept_events() const { return accept_events_; }
+ void set_accept_events(bool accept_events) { accept_events_ = accept_events; }
+
+ bool border_accepts_events() const { return border_accepts_events_; }
+ void set_border_accepts_events(bool event) { border_accepts_events_ = event; }
+
+ bool adjust_if_offscreen() const { return adjust_if_offscreen_; }
+ void set_adjust_if_offscreen(bool adjust) { adjust_if_offscreen_ = adjust; }
+
+ // Get the arrow's anchor rect in screen space.
+ virtual gfx::Rect GetAnchorRect() const;
+
+ // Allows delegates to provide custom parameters before widget initialization.
+ virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
+ Widget* widget) const;
+
+ // Sets |margins_| to a default picked for smaller bubbles.
+ void UseCompactMargins();
+
+ // Sets the bubble alignment relative to the anchor. This may only be called
+ // after calling CreateBubble.
+ void SetAlignment(BubbleBorder::BubbleAlignment alignment);
+
+ // Sets the bubble arrow paint type.
+ void SetArrowPaintType(BubbleBorder::ArrowPaintType paint_type);
+
+ // Call this method when the anchor bounds have changed to reposition the
+ // bubble. The bubble is automatically repositioned when the anchor view
+ // bounds change as a result of the widget's bounds changing.
+ void OnAnchorBoundsChanged();
+
+ protected:
+ BubbleDialogDelegateView();
+ BubbleDialogDelegateView(View* anchor_view, BubbleBorder::Arrow arrow);
+
+ // Get bubble bounds from the anchor rect and client view's preferred size.
+ virtual gfx::Rect GetBubbleBounds();
+
+ // Return a FontList to use for the title of the bubble.
+ // (The default is MediumFont).
+ virtual const gfx::FontList& GetTitleFontList() const;
+
+ // View overrides:
+ void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
+
+ // Perform view initialization on the contents for bubble sizing.
+ virtual void Init();
+
+ // Sets the anchor view or rect and repositions the bubble. Note that if a
+ // valid view gets passed, the anchor rect will get ignored. If the view gets
+ // deleted, but no new view gets set, the last known anchor postion will get
+ // returned.
+ void SetAnchorView(View* anchor_view);
+ void SetAnchorRect(const gfx::Rect& rect);
+
+ // Resize and potentially move the bubble to fit the content's preferred size.
+ void SizeToContents();
+
+ BubbleFrameView* GetBubbleFrameView() const;
+
+ private:
+ friend class BubbleBorderDelegate;
+ friend class BubbleWindowTargeter;
+
+ FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate);
+ FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest);
+
+ // Update the bubble color from |theme|, unless it was explicitly set.
+ void UpdateColorsFromTheme(const ui::NativeTheme* theme);
+
+ // Handles widget visibility changes.
+ void HandleVisibilityChanged(Widget* widget, bool visible);
+
+ // A flag controlling bubble closure on deactivation.
+ bool close_on_deactivate_;
+
+ // The view and widget to which this bubble is anchored. Since an anchor view
+ // can be deleted without notice, we store it in the ViewStorage and retrieve
+ // it from there. It will make sure that the view is still valid.
+ const int anchor_view_storage_id_;
+ Widget* anchor_widget_;
+
+ // The anchor rect used in the absence of an anchor view.
+ mutable gfx::Rect anchor_rect_;
+
+ // The arrow's location on the bubble.
+ BubbleBorder::Arrow arrow_;
+
+ // Bubble border shadow to use.
+ BubbleBorder::Shadow shadow_;
+
+ // The background color of the bubble; and flag for when it's explicitly set.
+ SkColor color_;
+ bool color_explicitly_set_;
+
+ // The margins between the content and the inside of the border.
+ gfx::Insets margins_;
+
+ // Insets applied to the |anchor_view_| bounds.
+ gfx::Insets anchor_view_insets_;
+
+ // Specifies whether the bubble (or its border) handles mouse events, etc.
+ bool accept_events_;
+ bool border_accepts_events_;
+
+ // If true (defaults to true), the arrow may be mirrored and moved to fit the
+ // bubble on screen better. It would be a no-op if the bubble has no arrow.
+ bool adjust_if_offscreen_;
+
+ // Parent native window of the bubble.
+ gfx::NativeView parent_window_;
+
+ DISALLOW_COPY_AND_ASSIGN(BubbleDialogDelegateView);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_BUBBLE_BUBBLE_DELEGATE2_H_
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc
new file mode 100644
index 00000000000..6c43388c944
--- /dev/null
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc
@@ -0,0 +1,316 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/bubble/bubble_dialog_delegate.h"
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "ui/base/hit_test.h"
+#include "ui/events/event_utils.h"
+#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/test/test_widget_observer.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
+
+namespace views {
+
+namespace {
+
+class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
+ public:
+ TestBubbleDialogDelegateView(View* anchor_view)
+ : BubbleDialogDelegateView(anchor_view, BubbleBorder::TOP_LEFT),
+ view_(new View()) {
+ view_->SetFocusable(true);
+ AddChildView(view_);
+ }
+ ~TestBubbleDialogDelegateView() override {}
+
+ // BubbleDialogDelegateView overrides:
+ View* GetInitiallyFocusedView() override { return view_; }
+ gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); }
+
+ using BubbleDialogDelegateView::SetAnchorRect;
+ using BubbleDialogDelegateView::GetBubbleFrameView;
+
+ private:
+ View* view_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView);
+};
+
+class BubbleDialogDelegateTest : public ViewsTestBase {
+ public:
+ BubbleDialogDelegateTest() {}
+ ~BubbleDialogDelegateTest() override {}
+
+ // Creates a test widget that owns its native widget.
+ Widget* CreateTestWidget() {
+ Widget* widget = new Widget();
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget->Init(params);
+ return widget;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BubbleDialogDelegateTest);
+};
+
+} // namespace
+
+TEST_F(BubbleDialogDelegateTest, CreateDelegate) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ bubble_delegate->set_color(SK_ColorGREEN);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
+ EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
+ test::TestWidgetObserver bubble_observer(bubble_widget);
+ bubble_widget->Show();
+
+ BubbleBorder* border = bubble_delegate->GetBubbleFrameView()->bubble_border();
+ EXPECT_EQ(bubble_delegate->arrow(), border->arrow());
+ EXPECT_EQ(bubble_delegate->color(), border->background_color());
+
+ EXPECT_FALSE(bubble_observer.widget_closed());
+ bubble_widget->CloseNow();
+ EXPECT_TRUE(bubble_observer.widget_closed());
+}
+
+TEST_F(BubbleDialogDelegateTest, CloseAnchorWidget) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ // Preventing close on deactivate should not prevent closing with the anchor.
+ bubble_delegate->set_close_on_deactivate(false);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
+ EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+ test::TestWidgetObserver bubble_observer(bubble_widget);
+ EXPECT_FALSE(bubble_observer.widget_closed());
+
+ bubble_widget->Show();
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+ EXPECT_FALSE(bubble_observer.widget_closed());
+
+ // 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());
+
+ // Ensure that closing the anchor widget also closes the bubble itself.
+ anchor_widget->CloseNow();
+ EXPECT_TRUE(bubble_observer.widget_closed());
+}
+
+// This test checks that the bubble delegate is capable to handle an early
+// destruction of the used anchor view. (Animations and delayed closure of the
+// bubble will call upon the anchor view to get its location).
+TEST_F(BubbleDialogDelegateTest, CloseAnchorViewTest) {
+ // Create an anchor widget and add a view to be used as an anchor view.
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ scoped_ptr<View> anchor_view(new View());
+ anchor_widget->GetContentsView()->AddChildView(anchor_view.get());
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_view.get());
+ // Prevent flakes by avoiding closing on activation changes.
+ bubble_delegate->set_close_on_deactivate(false);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+
+ // Check that the anchor view is correct and set up an anchor view rect.
+ // Make sure that this rect will get ignored (as long as the anchor view is
+ // attached).
+ EXPECT_EQ(anchor_view.get(), bubble_delegate->GetAnchorView());
+ const gfx::Rect set_anchor_rect = gfx::Rect(10, 10, 100, 100);
+ bubble_delegate->SetAnchorRect(set_anchor_rect);
+ const gfx::Rect view_rect = bubble_delegate->GetAnchorRect();
+ EXPECT_NE(view_rect.ToString(), set_anchor_rect.ToString());
+
+ // Create the bubble.
+ bubble_widget->Show();
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+
+ // Remove now the anchor view and make sure that the original found rect
+ // is still kept, so that the bubble does not jump when the view gets deleted.
+ anchor_widget->GetContentsView()->RemoveChildView(anchor_view.get());
+ anchor_view.reset();
+ EXPECT_EQ(NULL, bubble_delegate->GetAnchorView());
+ EXPECT_EQ(view_rect.ToString(), bubble_delegate->GetAnchorRect().ToString());
+}
+
+// Testing that a move of the anchor view will lead to new bubble locations.
+TEST_F(BubbleDialogDelegateTest, TestAnchorRectMovesWithViewTest) {
+ // Create an anchor widget and add a view to be used as anchor view.
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+
+ anchor_widget->GetContentsView()->SetBounds(10, 10, 100, 100);
+ const gfx::Rect view_rect = bubble_delegate->GetAnchorRect();
+
+ anchor_widget->GetContentsView()->SetBounds(20, 10, 100, 100);
+ const gfx::Rect view_rect_2 = bubble_delegate->GetAnchorRect();
+ EXPECT_NE(view_rect.ToString(), view_rect_2.ToString());
+}
+
+TEST_F(BubbleDialogDelegateTest, ResetAnchorWidget) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+
+ // Make sure the bubble widget is parented to a widget other than the anchor
+ // widget so that closing the anchor widget does not close the bubble widget.
+ scoped_ptr<Widget> parent_widget(CreateTestWidget());
+ bubble_delegate->set_parent_window(parent_widget->GetNativeView());
+ // Preventing close on deactivate should not prevent closing with the parent.
+ bubble_delegate->set_close_on_deactivate(false);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
+ EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+ test::TestWidgetObserver bubble_observer(bubble_widget);
+ EXPECT_FALSE(bubble_observer.widget_closed());
+
+ // Showing and hiding the bubble widget should have no effect on its anchor.
+ bubble_widget->Show();
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+ bubble_widget->Hide();
+ EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget());
+
+ // Ensure that closing the anchor widget clears the bubble's reference to that
+ // anchor widget, but the bubble itself does not close.
+ anchor_widget->CloseNow();
+ EXPECT_NE(anchor_widget.get(), bubble_delegate->anchor_widget());
+ EXPECT_FALSE(bubble_observer.widget_closed());
+
+ // 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());
+
+ // Ensure that closing the parent widget also closes the bubble itself.
+ parent_widget->CloseNow();
+ EXPECT_TRUE(bubble_observer.widget_closed());
+}
+
+TEST_F(BubbleDialogDelegateTest, InitiallyFocusedView) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_widget->Show();
+ EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(),
+ bubble_widget->GetFocusManager()->GetFocusedView());
+ bubble_widget->CloseNow();
+}
+
+TEST_F(BubbleDialogDelegateTest, NonClientHitTest) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ BubbleFrameView* frame = bubble_delegate->GetBubbleFrameView();
+ const int border = frame->bubble_border()->GetBorderThickness();
+
+ struct {
+ const int point;
+ const int hit;
+ } cases[] = {
+ {border, HTNOWHERE}, {border + 50, HTCLIENT}, {1000, HTNOWHERE},
+ };
+
+ for (size_t i = 0; i < arraysize(cases); ++i) {
+ gfx::Point point(cases[i].point, cases[i].point);
+ EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point))
+ << " with border: " << border << ", at point " << cases[i].point;
+ }
+}
+
+TEST_F(BubbleDialogDelegateTest, VisibleWhenAnchorWidgetBoundsChanged) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ test::TestWidgetObserver bubble_observer(bubble_widget);
+ EXPECT_FALSE(bubble_observer.widget_closed());
+
+ anchor_widget->Show();
+ bubble_widget->Show();
+ EXPECT_TRUE(bubble_widget->IsVisible());
+ anchor_widget->SetBounds(gfx::Rect(10, 10, 100, 100));
+ EXPECT_TRUE(bubble_widget->IsVisible());
+}
+
+// Test that setting WidgetDelegate::set_can_activate() to false makes the
+// widget created via BubbleDialogDelegateView::CreateBubble() not activatable.
+TEST_F(BubbleDialogDelegateTest, NotActivatable) {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ bubble_delegate->set_can_activate(false);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_widget->Show();
+ EXPECT_FALSE(bubble_widget->CanActivate());
+}
+
+TEST_F(BubbleDialogDelegateTest, CloseMethods) {
+ {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ bubble_delegate->set_close_on_deactivate(true);
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ anchor_widget->Show();
+ bubble_widget->Show();
+ anchor_widget->Activate();
+ EXPECT_TRUE(bubble_widget->IsClosed());
+ }
+
+ {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ BubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_widget->Show();
+
+ ui::KeyEvent escape_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, ui::EF_NONE);
+ bubble_widget->OnKeyEvent(&escape_event);
+ EXPECT_TRUE(bubble_widget->IsClosed());
+ }
+
+ {
+ scoped_ptr<Widget> anchor_widget(CreateTestWidget());
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_widget->Show();
+ BubbleFrameView* frame_view = bubble_delegate->GetBubbleFrameView();
+ LabelButton* close_button = frame_view->close_;
+ ASSERT_TRUE(close_button);
+ frame_view->ButtonPressed(
+ close_button,
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE));
+ EXPECT_TRUE(bubble_widget->IsClosed());
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index b11ee79c6f1..3f8411b22d8 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -8,9 +8,13 @@
#include <utility>
#include "build/build_config.h"
+#include "ui/base/default_style.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/compositor/paint_context.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/path.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/skia_util.h"
@@ -20,21 +24,22 @@
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/image_view.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/layout_constants.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"
+namespace views {
+
namespace {
-// Insets for the title bar views in pixels.
-const int kTitleTopInset = 12;
-const int kTitleLeftInset = 19;
-const int kTitleBottomInset = 12;
-const int kTitleRightInset = 7;
+// Background color of the footnote view.
+const SkColor kFootnoteBackgroundColor = SkColorSetRGB(245, 245, 245);
-// The horizontal padding between the title and the icon.
-const int kTitleHorizontalPadding = 5;
+// Color of the top border of the footnote.
+const SkColor kFootnoteBorderColor = SkColorSetRGB(229, 229, 229);
// Get the |vertical| or horizontal amount that |available_bounds| overflows
// |window_bounds|.
@@ -61,27 +66,28 @@ int GetOffScreenLength(const gfx::Rect& available_bounds,
} // namespace
-namespace views {
-
// static
const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
-BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
+BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins,
+ const gfx::Insets& content_margins)
: bubble_border_(nullptr),
+ title_margins_(title_margins),
content_margins_(content_margins),
title_icon_(new views::ImageView()),
title_(nullptr),
close_(nullptr),
- titlebar_extra_view_(nullptr),
+ footnote_container_(nullptr),
close_button_clicked_(false) {
AddChildView(title_icon_);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
title_ = new Label(base::string16(),
- rb.GetFontList(ui::ResourceBundle::MediumFont));
+ rb.GetFontListWithDelta(ui::kTitleFontSizeDelta));
title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
title_->set_collapse_when_hidden(true);
title_->SetVisible(false);
+ title_->SetMultiLine(true);
AddChildView(title_);
close_ = CreateCloseButton(this);
@@ -92,12 +98,6 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
BubbleFrameView::~BubbleFrameView() {}
// static
-gfx::Insets BubbleFrameView::GetTitleInsets() {
- return gfx::Insets(
- kTitleTopInset, kTitleLeftInset, kTitleBottomInset, kTitleRightInset);
-}
-
-// static
LabelButton* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
LabelButton* close = new LabelButton(listener, base::string16());
@@ -118,9 +118,12 @@ LabelButton* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
}
gfx::Rect BubbleFrameView::GetBoundsForClientView() const {
- gfx::Rect client_bounds = GetLocalBounds();
+ gfx::Rect client_bounds = GetContentsBounds();
client_bounds.Inset(GetInsets());
- client_bounds.Inset(bubble_border_->GetInsets());
+ if (footnote_container_) {
+ client_bounds.set_height(client_bounds.height() -
+ footnote_container_->height());
+ }
return client_bounds;
}
@@ -130,6 +133,20 @@ gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds(
return bubble_border_->GetBounds(gfx::Rect(), size);
}
+bool BubbleFrameView::GetClientMask(const gfx::Size& size,
+ gfx::Path* path) const {
+ const int radius = bubble_border_->GetBorderCornerRadius();
+ gfx::Insets content_insets = GetInsets();
+ // If the client bounds don't touch the edges, no need to mask.
+ if (std::min({content_insets.top(), content_insets.left(),
+ content_insets.bottom(), content_insets.right()}) > radius) {
+ return false;
+ }
+ gfx::RectF rect((gfx::Rect(size)));
+ path->addRoundRect(gfx::RectFToSkRect(rect), radius, radius);
+ return true;
+}
+
int BubbleFrameView::NonClientHitTest(const gfx::Point& point) {
if (!bounds().Contains(point))
return HTNOWHERE;
@@ -137,8 +154,11 @@ int BubbleFrameView::NonClientHitTest(const gfx::Point& point) {
return HTCLOSE;
// Allow dialogs to show the system menu and be dragged.
- if (GetWidget()->widget_delegate()->AsDialogDelegate()) {
- gfx::Rect sys_rect(0, 0, title_->x(), title_->y());
+ if (GetWidget()->widget_delegate()->AsDialogDelegate() &&
+ !GetWidget()->widget_delegate()->AsBubbleDialogDelegate()) {
+ gfx::Rect bounds(GetContentsBounds());
+ bounds.Inset(title_margins_);
+ gfx::Rect sys_rect(0, 0, bounds.x(), bounds.y());
sys_rect.set_origin(gfx::Point(GetMirroredXForRect(sys_rect), 0));
if (sys_rect.Contains(point))
return HTSYSMENU;
@@ -151,30 +171,42 @@ int BubbleFrameView::NonClientHitTest(const gfx::Point& point) {
void BubbleFrameView::GetWindowMask(const gfx::Size& size,
gfx::Path* window_mask) {
- // NOTE: this only provides implementations for the types used by dialogs.
- if ((bubble_border_->arrow() != BubbleBorder::NONE &&
- bubble_border_->arrow() != BubbleBorder::FLOAT) ||
- (bubble_border_->shadow() != BubbleBorder::SMALL_SHADOW &&
- bubble_border_->shadow() != BubbleBorder::NO_SHADOW_OPAQUE_BORDER))
+ if (bubble_border_->shadow() != BubbleBorder::SMALL_SHADOW &&
+ bubble_border_->shadow() != BubbleBorder::NO_SHADOW_OPAQUE_BORDER &&
+ bubble_border_->shadow() != BubbleBorder::NO_ASSETS)
+ return;
+
+ // We don't return a mask for windows with arrows unless they use
+ // BubbleBorder::NO_ASSETS.
+ if (bubble_border_->shadow() != BubbleBorder::NO_ASSETS &&
+ bubble_border_->arrow() != BubbleBorder::NONE &&
+ bubble_border_->arrow() != BubbleBorder::FLOAT)
return;
// Use a window mask roughly matching the border in the image assets.
- static const int kBorderStrokeSize = 1;
- static const SkScalar kCornerRadius = SkIntToScalar(6);
+ const int kBorderStrokeSize =
+ bubble_border_->shadow() == BubbleBorder::NO_ASSETS ? 0 : 1;
+ const SkScalar kCornerRadius =
+ SkIntToScalar(bubble_border_->GetBorderCornerRadius());
const gfx::Insets border_insets = bubble_border_->GetInsets();
- SkRect rect = { SkIntToScalar(border_insets.left() - kBorderStrokeSize),
- SkIntToScalar(border_insets.top() - kBorderStrokeSize),
- SkIntToScalar(size.width() - border_insets.right() +
- kBorderStrokeSize),
- SkIntToScalar(size.height() - border_insets.bottom() +
- kBorderStrokeSize) };
- if (bubble_border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER) {
+ SkRect rect = {
+ SkIntToScalar(border_insets.left() - kBorderStrokeSize),
+ SkIntToScalar(border_insets.top() - kBorderStrokeSize),
+ SkIntToScalar(size.width() - border_insets.right() + kBorderStrokeSize),
+ SkIntToScalar(size.height() - border_insets.bottom() +
+ kBorderStrokeSize)};
+
+ if (bubble_border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER ||
+ bubble_border_->shadow() == BubbleBorder::NO_ASSETS) {
window_mask->addRoundRect(rect, kCornerRadius, kCornerRadius);
} else {
static const int kBottomBorderShadowSize = 2;
rect.fBottom += SkIntToScalar(kBottomBorderShadowSize);
window_mask->addRect(rect);
}
+ gfx::Path arrow_path;
+ if (bubble_border_->GetArrowPath(gfx::Rect(size), &arrow_path))
+ window_mask->addPath(arrow_path, 0, 0);
}
void BubbleFrameView::ResetWindowControls() {
@@ -200,13 +232,17 @@ void BubbleFrameView::SetTitleFontList(const gfx::FontList& font_list) {
title_->SetFontList(font_list);
}
+const char* BubbleFrameView::GetClassName() const {
+ return kViewClassName;
+}
+
gfx::Insets BubbleFrameView::GetInsets() const {
gfx::Insets insets = content_margins_;
const int icon_height = title_icon_->GetPreferredSize().height();
const int label_height = title_->GetPreferredSize().height();
const bool has_title = icon_height > 0 || label_height > 0;
- const int title_padding = has_title ? kTitleTopInset + kTitleBottomInset : 0;
+ const int title_padding = has_title ? title_margins_.height() : 0;
const int title_height = std::max(icon_height, label_height) + title_padding;
const int close_height = close_->visible() ? close_->height() : 0;
insets += gfx::Insets(std::max(title_height, close_height), 0, 0, 0);
@@ -251,62 +287,47 @@ gfx::Size BubbleFrameView::GetMaximumSize() const {
}
void BubbleFrameView::Layout() {
+ // The title margins may not be set, but make sure that's only the case when
+ // there's no title.
+ DCHECK(!title_margins_.IsEmpty() || !title_->visible());
+
gfx::Rect bounds(GetContentsBounds());
- bounds.Inset(GetTitleInsets());
+ bounds.Inset(title_margins_);
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));
+ // The close button is positioned somewhat closer to the edge of the bubble.
+ gfx::Point close_position = GetContentsBounds().top_right();
+ close_position += gfx::Vector2d(-close_->width() - 7, 6);
+ close_->SetPosition(close_position);
- gfx::Size title_icon_size(title_icon_->GetPreferredSize());
- gfx::Size title_label_size(title_->GetPreferredSize());
+ gfx::Size title_icon_pref_size(title_icon_->GetPreferredSize());
int padding = 0;
- if (title_icon_size.width() > 0 && title_label_size.width() > 0)
- padding = kTitleHorizontalPadding;
- const int title_height = std::max(title_icon_size.height(),
- title_label_size.height());
-
- const int title_icon_width = std::max(0, close_->x() - bounds.x());
- title_icon_size.SetToMin(gfx::Size(title_icon_width, title_height));
- gfx::Rect title_icon_bounds(
- bounds.x(), bounds.y(), title_icon_size.width(), title_height);
- title_icon_->SetBoundsRect(title_icon_bounds);
-
- const int title_label_x = title_icon_->bounds().right() + padding;
- const int title_label_width = std::max(0, close_->x() - title_label_x);
- title_label_size.SetToMin(gfx::Size(title_label_width,
- title_label_size.height()));
- gfx::Rect title_label_bounds(
- title_label_x, bounds.y(), title_label_size.width(), title_height);
- title_->SetBoundsRect(title_label_bounds);
-
- bounds.set_width(
- title_icon_size.width() + title_label_size.width() + padding);
- bounds.set_height(title_height);
- if (titlebar_extra_view_) {
- const int extra_width = close_->x() - 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(
- close_->x() - size.width(),
- bounds.y(),
- size.width(),
- bounds.height());
- titlebar_extra_view_bounds.Subtract(bounds);
- titlebar_extra_view_->SetBoundsRect(titlebar_extra_view_bounds);
+ if (title_->visible() && !title_->text().empty()) {
+ if (title_icon_pref_size.width() > 0)
+ padding = title_margins_.left();
+
+ const int title_label_x =
+ bounds.x() + title_icon_pref_size.width() + padding;
+ title_->SizeToFit(std::max(1, close_->x() - title_label_x));
+ title_->SetPosition(gfx::Point(title_label_x, bounds.y()));
}
-}
-const char* BubbleFrameView::GetClassName() const {
- return kViewClassName;
-}
+ const int title_height =
+ std::max(title_icon_pref_size.height(), title_->height());
+ title_icon_->SetBounds(bounds.x(), bounds.y(), title_icon_pref_size.width(),
+ title_height);
+ bounds.set_width(title_->bounds().right() - bounds.x());
+ bounds.set_height(title_height);
-void BubbleFrameView::ChildPreferredSizeChanged(View* child) {
- if (child == titlebar_extra_view_ || child == title_)
- Layout();
+ if (footnote_container_) {
+ gfx::Rect local_bounds = GetContentsBounds();
+ int height = footnote_container_->GetHeightForWidth(local_bounds.width());
+ footnote_container_->SetBounds(local_bounds.x(),
+ local_bounds.bottom() - height,
+ local_bounds.width(), height);
+ }
}
void BubbleFrameView::OnThemeChanged() {
@@ -323,6 +344,19 @@ void BubbleFrameView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
}
}
+void BubbleFrameView::OnPaint(gfx::Canvas* canvas) {
+ OnPaintBackground(canvas);
+ // Border comes after children.
+}
+
+void BubbleFrameView::PaintChildren(const ui::PaintContext& context) {
+ NonClientFrameView::PaintChildren(context);
+
+ ui::PaintCache paint_cache;
+ ui::PaintRecorder recorder(context, size(), &paint_cache);
+ OnPaintBorder(recorder.canvas());
+}
+
void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
if (sender == close_) {
close_button_clicked_ = true;
@@ -338,11 +372,21 @@ void BubbleFrameView::SetBubbleBorder(scoped_ptr<BubbleBorder> border) {
set_background(new views::BubbleBackground(bubble_border_));
}
-void BubbleFrameView::SetTitlebarExtraView(View* view) {
- DCHECK(view);
- DCHECK(!titlebar_extra_view_);
- AddChildView(view);
- titlebar_extra_view_ = view;
+void BubbleFrameView::SetFootnoteView(View* view) {
+ if (!view)
+ return;
+
+ DCHECK(!footnote_container_);
+ footnote_container_ = new views::View();
+ footnote_container_->SetLayoutManager(
+ new BoxLayout(BoxLayout::kVertical, content_margins_.left(),
+ content_margins_.top(), 0));
+ footnote_container_->set_background(
+ Background::CreateSolidBackground(kFootnoteBackgroundColor));
+ footnote_container_->SetBorder(
+ Border::CreateSolidSidedBorder(1, 0, 0, 0, kFootnoteBorderColor));
+ footnote_container_->AddChildView(view);
+ AddChildView(footnote_container_);
}
gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
@@ -370,9 +414,9 @@ gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
gfx::Rect BubbleFrameView::GetAvailableScreenBounds(
const gfx::Rect& rect) const {
// The bubble attempts to fit within the current screen bounds.
- // TODO(scottmg): Native is wrong. http://crbug.com/133312
- return gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(
- rect.CenterPoint()).work_area();
+ return gfx::Screen::GetScreen()
+ ->GetDisplayNearestPoint(rect.CenterPoint())
+ .work_area();
}
bool BubbleFrameView::IsCloseButtonVisible() const {
@@ -453,23 +497,23 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
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();
+ int title_bar_width = title_margins_.width() + border()->GetInsets().width();
gfx::Size title_icon_size = title_icon_->GetPreferredSize();
gfx::Size title_label_size = title_->GetPreferredSize();
- if (title_icon_size.width() > 0 || title_label_size.width() > 0)
- title_bar_width += kTitleLeftInset;
if (title_icon_size.width() > 0 && title_label_size.width() > 0)
- title_bar_width += kTitleHorizontalPadding;
+ title_bar_width += title_margins_.left();
title_bar_width += title_icon_size.width();
- title_bar_width += title_label_size.width();
if (close_->visible())
title_bar_width += close_->width() + 1;
- if (titlebar_extra_view_ != NULL)
- title_bar_width += titlebar_extra_view_->GetPreferredSize().width();
+
gfx::Size size(client_size);
+ gfx::Insets client_insets = GetInsets();
+ size.Enlarge(client_insets.width(), client_insets.height());
size.SetToMax(gfx::Size(title_bar_width, 0));
- const gfx::Insets insets(GetInsets());
- size.Enlarge(insets.width(), insets.height());
+
+ if (footnote_container_)
+ size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width()));
+
return size;
}
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index 6a4a0f30a5a..812c3e77f35 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -30,13 +30,10 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// Internal class name.
static const char kViewClassName[];
- explicit BubbleFrameView(const gfx::Insets& content_margins);
+ BubbleFrameView(const gfx::Insets& title_margins,
+ const gfx::Insets& content_margins);
~BubbleFrameView() override;
- // Insets to make bubble contents align horizontal with the bubble title.
- // NOTE: this does not take into account whether a title actually exists.
- static gfx::Insets GetTitleInsets();
-
// Creates a close button used in the corner of the dialog.
static LabelButton* CreateCloseButton(ButtonListener* listener);
@@ -44,6 +41,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
gfx::Rect GetBoundsForClientView() const override;
gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override;
+ bool GetClientMask(const gfx::Size& size, gfx::Path* path) const override;
int NonClientHitTest(const gfx::Point& point) override;
void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override;
void ResetWindowControls() override;
@@ -56,13 +54,14 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
void SetTitleFontList(const gfx::FontList& font_list);
// View overrides:
+ const char* GetClassName() const override;
gfx::Insets GetInsets() const override;
gfx::Size GetPreferredSize() const override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
void Layout() override;
- const char* GetClassName() const override;
- void ChildPreferredSizeChanged(View* child) override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void PaintChildren(const ui::PaintContext& context) override;
void OnThemeChanged() override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
@@ -75,7 +74,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
gfx::Insets content_margins() const { return content_margins_; }
- void SetTitlebarExtraView(View* view);
+ void SetFootnoteView(View* view);
// Given the size of the contents and the rect to point at, returns the bounds
// of the bubble window. The bubble's arrow location may change if the bubble
@@ -96,6 +95,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
private:
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, GetBoundsForClientView);
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CloseReasons);
+ FRIEND_TEST_ALL_PREFIXES(BubbleDialogDelegateTest, CloseMethods);
// Mirrors the bubble's arrow location on the |vertical| or horizontal axis,
// if the generated window bounds don't fit in the monitor bounds.
@@ -114,6 +114,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// The bubble border.
BubbleBorder* bubble_border_;
+ // Margins around the title label.
+ gfx::Insets title_margins_;
+
// Margins between the content and the inside of the border, in pixels.
gfx::Insets content_margins_;
@@ -122,9 +125,8 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
Label* title_;
LabelButton* close_;
- // When supplied, this view is placed in the titlebar between the title and
- // (x) close button.
- View* titlebar_extra_view_;
+ // A view to contain the footnote view, if it exists.
+ View* footnote_container_;
// Whether the close button was clicked.
bool close_button_clicked_;
diff --git a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
index 908b190340e..d71137f5eb2 100644
--- a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -30,8 +30,11 @@ const int kMaximumClientWidth = 300;
const int kMaximumClientHeight = 300;
const int kPreferredClientWidth = 150;
const int kPreferredClientHeight = 250;
-const int kExpectedBorderWidth = 22;
-const int kExpectedBorderHeight = 29;
+
+// These account for non-client areas like the title bar, footnote etc. However
+// these do not take the bubble border into consideration.
+const int kExpectedAdditionalWidth = 12;
+const int kExpectedAdditionalHeight = 12;
class TestBubbleFrameViewWidgetDelegate : public WidgetDelegate {
public:
@@ -64,7 +67,7 @@ class TestBubbleFrameViewWidgetDelegate : public WidgetDelegate {
class TestBubbleFrameView : public BubbleFrameView {
public:
TestBubbleFrameView(ViewsTestBase* test_base)
- : BubbleFrameView(gfx::Insets(kMargin, kMargin, kMargin, kMargin)),
+ : BubbleFrameView(gfx::Insets(), gfx::Insets(kMargin)),
test_base_(test_base),
available_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
SetBubbleBorder(scoped_ptr<BubbleBorder>(
@@ -417,36 +420,40 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
TEST_F(BubbleFrameViewTest, GetPreferredSize) {
TestBubbleFrameView frame(this);
- gfx::Size preferred_size = frame.GetPreferredSize();
+ gfx::Rect preferred_rect(frame.GetPreferredSize());
// Expect that a border has been added to the preferred size.
- EXPECT_EQ(kPreferredClientWidth + kExpectedBorderWidth,
- preferred_size.width());
- EXPECT_EQ(kPreferredClientHeight + kExpectedBorderHeight,
- preferred_size.height());
+ preferred_rect.Inset(frame.bubble_border()->GetInsets());
+
+ gfx::Size expected_size(kPreferredClientWidth + kExpectedAdditionalWidth,
+ kPreferredClientHeight + kExpectedAdditionalHeight);
+ EXPECT_EQ(expected_size, preferred_rect.size());
}
TEST_F(BubbleFrameViewTest, GetMinimumSize) {
TestBubbleFrameView frame(this);
- gfx::Size minimum_size = frame.GetMinimumSize();
+ gfx::Rect minimum_rect(frame.GetMinimumSize());
// Expect that a border has been added to the minimum size.
- EXPECT_EQ(kMinimumClientWidth + kExpectedBorderWidth, minimum_size.width());
- EXPECT_EQ(kMinimumClientHeight + kExpectedBorderHeight,
- minimum_size.height());
+ minimum_rect.Inset(frame.bubble_border()->GetInsets());
+
+ gfx::Size expected_size(kMinimumClientWidth + kExpectedAdditionalWidth,
+ kMinimumClientHeight + kExpectedAdditionalHeight);
+ EXPECT_EQ(expected_size, minimum_rect.size());
}
TEST_F(BubbleFrameViewTest, GetMaximumSize) {
TestBubbleFrameView frame(this);
- gfx::Size maximum_size = frame.GetMaximumSize();
+ gfx::Rect maximum_rect(frame.GetMaximumSize());
#if defined(OS_WIN)
// On Windows, GetMaximumSize causes problems with DWM, so it should just be 0
// (unlimited). See http://crbug.com/506206.
- EXPECT_EQ(0, maximum_size.width());
- EXPECT_EQ(0, maximum_size.height());
+ EXPECT_EQ(gfx::Size(), maximum_rect.size());
#else
+ maximum_rect.Inset(frame.bubble_border()->GetInsets());
+
// Should ignore the contents view's maximum size and use the preferred size.
- EXPECT_EQ(kPreferredClientWidth + kExpectedBorderWidth, maximum_size.width());
- EXPECT_EQ(kPreferredClientHeight + kExpectedBorderHeight,
- maximum_size.height());
+ gfx::Size expected_size(kPreferredClientWidth + kExpectedAdditionalWidth,
+ kPreferredClientHeight + kExpectedAdditionalHeight);
+ EXPECT_EQ(expected_size, maximum_rect.size());
#endif
}
diff --git a/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc b/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
index 8ae398f4083..f40aa326977 100644
--- a/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
@@ -100,7 +100,7 @@ TEST_F(BubbleWindowTargeterTest, HitTest) {
EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1));
}
{
- bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20));
+ bubble_delegate()->set_margins(gfx::Insets(20));
ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
bubble_bounds.origin(), ui::EventTimeForNow(),
ui::EF_NONE, ui::EF_NONE);
@@ -110,7 +110,7 @@ TEST_F(BubbleWindowTargeterTest, HitTest) {
bubble_window->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
new BubbleWindowTargeter(bubble_delegate())));
{
- bubble_delegate()->set_margins(gfx::Insets(20, 20, 20, 20));
+ bubble_delegate()->set_margins(gfx::Insets(20));
ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
bubble_bounds.origin(), ui::EventTimeForNow(),
ui::EF_NONE, ui::EF_NONE);
diff --git a/chromium/ui/views/bubble/tray_bubble_view.cc b/chromium/ui/views/bubble/tray_bubble_view.cc
index daa24f86811..ad3267fe659 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.cc
+++ b/chromium/ui/views/bubble/tray_bubble_view.cc
@@ -290,6 +290,8 @@ TrayBubbleView::InitParams::InitParams(AnchorType anchor_type,
arrow_alignment(BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE) {
}
+TrayBubbleView::InitParams::InitParams(const InitParams& other) = default;
+
// static
TrayBubbleView* TrayBubbleView::Create(gfx::NativeView parent_window,
View* anchor,
@@ -322,16 +324,15 @@ TrayBubbleView::TrayBubbleView(gfx::NativeView parent_window,
params_(init_params),
delegate_(delegate),
preferred_width_(init_params.min_width),
- bubble_border_(NULL),
+ bubble_border_(new TrayBubbleBorder(this, GetAnchorView(), init_params)),
+ owned_bubble_border_(bubble_border_),
is_gesture_dragging_(false),
mouse_actively_entered_(false) {
set_parent_window(parent_window);
set_notify_enter_exit_on_child(true);
set_close_on_deactivate(init_params.close_on_deactivate);
set_margins(gfx::Insets());
- bubble_border_ = new TrayBubbleBorder(this, GetAnchorView(), params_);
SetPaintToLayer(true);
- SetFillsBoundsOpaquely(true);
bubble_content_mask_.reset(
new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
@@ -409,8 +410,9 @@ bool TrayBubbleView::CanActivate() const {
}
NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(Widget* widget) {
- BubbleFrameView* frame = new BubbleFrameView(margins());
- frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(bubble_border_));
+ BubbleFrameView* frame = static_cast<BubbleFrameView*>(
+ BubbleDelegateView::CreateNonClientFrameView(widget));
+ frame->SetBubbleBorder(std::move(owned_bubble_border_));
return frame;
}
@@ -504,7 +506,6 @@ void TrayBubbleView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
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 db42f4a5107..c0c0c7c2872 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.h
+++ b/chromium/ui/views/bubble/tray_bubble_view.h
@@ -11,11 +11,6 @@
#include "ui/views/mouse_watcher.h"
#include "ui/views/views_export.h"
-// Specialized bubble view for bubbles associated with a tray icon (e.g. the
-// Ash status area). Mostly this handles custom anchor location and arrow and
-// border rendering. This also has its own delegate for handling mouse events
-// and other implementation specific details.
-
namespace ui {
class LocatedEvent;
}
@@ -32,6 +27,10 @@ class TrayBubbleBorder;
class TrayBubbleContentMask;
}
+// Specialized bubble view for bubbles associated with a tray icon (e.g. the
+// Ash status area). Mostly this handles custom anchor location and arrow and
+// border rendering. This also has its own delegate for handling mouse events
+// and other implementation specific details.
class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
public views::MouseWatcherListener {
public:
@@ -96,6 +95,7 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
AnchorAlignment anchor_alignment,
int min_width,
int max_width);
+ InitParams(const InitParams& other);
AnchorType anchor_type;
AnchorAlignment anchor_alignment;
int min_width;
@@ -186,7 +186,10 @@ class VIEWS_EXPORT TrayBubbleView : public views::BubbleDelegateView,
InitParams params_;
Delegate* delegate_;
int preferred_width_;
+ // |bubble_border_| and |owned_bubble_border_| point to the same thing, but
+ // the latter ensures we don't leak it before passing off ownership.
internal::TrayBubbleBorder* bubble_border_;
+ scoped_ptr<views::BubbleBorder> owned_bubble_border_;
scoped_ptr<internal::TrayBubbleContentMask> bubble_content_mask_;
bool is_gesture_dragging_;
diff --git a/chromium/ui/views/button_drag_utils.cc b/chromium/ui/views/button_drag_utils.cc
index 3fb5d12ed61..60bd6e5abca 100644
--- a/chromium/ui/views/button_drag_utils.cc
+++ b/chromium/ui/views/button_drag_utils.cc
@@ -14,7 +14,10 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/image/image.h"
#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/drag_utils.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/widget/widget.h"
@@ -49,13 +52,17 @@ void SetDragImage(const GURL& url,
button.SetTextSubpixelRenderingEnabled(false);
const ui::NativeTheme* theme = widget->GetNativeTheme();
button.SetTextColor(views::Button::STATE_NORMAL,
- theme->GetSystemColor(ui::NativeTheme::kColorId_LabelEnabledColor));
- gfx::ShadowValues shadows(
- 10,
- gfx::ShadowValue(gfx::Vector2d(0, 0), 1.0f,
- theme->GetSystemColor(
- ui::NativeTheme::kColorId_LabelBackgroundColor)));
- button.SetTextShadows(shadows);
+ theme->GetSystemColor(ui::NativeTheme::kColorId_TextfieldDefaultColor));
+
+ SkColor bg_color = theme->GetSystemColor(
+ ui::NativeTheme::kColorId_TextfieldDefaultBackground);
+ if (widget->IsTranslucentWindowOpacitySupported()) {
+ button.SetTextShadows(gfx::ShadowValues(
+ 10, gfx::ShadowValue(gfx::Vector2d(0, 0), 1.0f, bg_color)));
+ } else {
+ button.set_background(views::Background::CreateSolidBackground(bg_color));
+ button.SetBorder(button.CreateDefaultBorder());
+ }
button.SetMaxSize(gfx::Size(kLinkDragImageMaxWidth, 0));
if (icon.isNull()) {
button.SetImage(views::Button::STATE_NORMAL,
diff --git a/chromium/ui/views/cocoa/bridged_content_view.h b/chromium/ui/views/cocoa/bridged_content_view.h
index 9f6fbb50566..f4b6a867cd7 100644
--- a/chromium/ui/views/cocoa/bridged_content_view.h
+++ b/chromium/ui/views/cocoa/bridged_content_view.h
@@ -47,6 +47,9 @@ class View;
// Whether dragging on the view moves the window.
BOOL mouseDownCanMoveWindow_;
+
+ // The cached window mask. Only used for non-rectangular windows on 10.9.
+ base::scoped_nsobject<NSBezierPath> windowMask_;
}
@property(readonly, nonatomic) views::View* hostedView;
@@ -73,6 +76,9 @@ class View;
// contentRect (also this NSView's frame), as given by a ui::LocatedEvent.
- (void)updateTooltipIfRequiredAt:(const gfx::Point&)locationInContent;
+// Update windowMask_ depending on the current view bounds.
+- (void)updateWindowMask;
+
@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
index 718207c4013..6d72fef5cf7 100644
--- a/chromium/ui/views/cocoa/bridged_content_view.mm
+++ b/chromium/ui/views/cocoa/bridged_content_view.mm
@@ -5,9 +5,11 @@
#import "ui/views/cocoa/bridged_content_view.h"
#include "base/logging.h"
+#import "base/mac/mac_util.h"
#import "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "skia/ext/skia_utils_mac.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/compositor/canvas_painter.h"
@@ -17,6 +19,9 @@
#include "ui/gfx/canvas_paint_mac.h"
#include "ui/gfx/geometry/rect.h"
#import "ui/gfx/mac/coordinate_conversion.h"
+#include "ui/gfx/path.h"
+#import "ui/gfx/path_mac.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
@@ -27,6 +32,17 @@ using views::MenuController;
namespace {
+// Returns true if all four corners of |rect| are contained inside |path|.
+bool IsRectInsidePath(NSRect rect, NSBezierPath* path) {
+ return [path containsPoint:rect.origin] &&
+ [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width,
+ rect.origin.y)] &&
+ [path containsPoint:NSMakePoint(rect.origin.x,
+ rect.origin.y + rect.size.height)] &&
+ [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width,
+ rect.origin.y + rect.size.height)];
+}
+
// Convert a |point| in |source_window|'s AppKit coordinate system (origin at
// the bottom left of the window) to |target_window|'s content rect, with the
// origin at the top left of the content area.
@@ -35,10 +51,11 @@ gfx::Point MovePointToWindow(const NSPoint& point,
NSWindow* source_window,
NSWindow* target_window) {
NSPoint point_in_screen = source_window
- ? [source_window convertBaseToScreen:point]
+ ? ui::ConvertPointFromWindowToScreen(source_window, point)
: point;
- NSPoint point_in_window = [target_window convertScreenToBase:point_in_screen];
+ NSPoint point_in_window =
+ ui::ConvertPointFromScreenToWindow(target_window, point_in_screen);
NSRect content_rect =
[target_window contentRectForFrameRect:[target_window frame]];
return gfx::Point(point_in_window.x,
@@ -252,6 +269,30 @@ gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client,
}
}
+- (void)updateWindowMask {
+ DCHECK(![self inLiveResize]);
+ DCHECK(base::mac::IsOSMavericksOrEarlier());
+ DCHECK(hostedView_);
+
+ views::Widget* widget = hostedView_->GetWidget();
+ if (!widget->non_client_view())
+ return;
+
+ const NSRect frameRect = [self bounds];
+ gfx::Path mask;
+ widget->non_client_view()->GetWindowMask(gfx::Size(frameRect.size), &mask);
+ if (mask.isEmpty())
+ return;
+
+ windowMask_.reset([gfx::CreateNSBezierPathFromSkPath(mask) retain]);
+
+ // Convert to AppKit coordinate system.
+ NSAffineTransform* flipTransform = [NSAffineTransform transform];
+ [flipTransform translateXBy:0.0 yBy:frameRect.size.height];
+ [flipTransform scaleXBy:1.0 yBy:-1.0];
+ [windowMask_ transformUsingAffineTransform:flipTransform];
+}
+
// BridgedContentView private implementation.
- (void)handleKeyEvent:(NSEvent*)theEvent {
@@ -368,6 +409,20 @@ gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client,
return YES;
}
+- (BOOL)becomeFirstResponder {
+ BOOL result = [super becomeFirstResponder];
+ if (result && hostedView_)
+ hostedView_->GetWidget()->GetFocusManager()->RestoreFocusedView();
+ return result;
+}
+
+- (BOOL)resignFirstResponder {
+ BOOL result = [super resignFirstResponder];
+ if (result && hostedView_)
+ hostedView_->GetWidget()->GetFocusManager()->StoreFocusedView(true);
+ return result;
+}
+
- (void)viewDidMoveToWindow {
// When this view is added to a window, AppKit calls setFrameSize before it is
// added to the window, so the behavior in setFrameSize is not triggered.
@@ -393,6 +448,18 @@ gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client,
hostedView_->SetSize(gfx::Size(newSize.width, newSize.height));
}
+- (void)viewDidEndLiveResize {
+ [super viewDidEndLiveResize];
+
+ // We prevent updating the window mask and clipping the border around the
+ // view, during a live resize. Hence update the window mask and redraw the
+ // view after resize has completed.
+ if (base::mac::IsOSMavericksOrEarlier()) {
+ [self updateWindowMask];
+ [self setNeedsDisplay:YES];
+ }
+}
+
- (void)drawRect:(NSRect)dirtyRect {
// Note that BridgedNativeWidget uses -[NSWindow setAutodisplay:NO] to
// suppress calls to this when the window is known to be hidden.
@@ -407,6 +474,33 @@ gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client,
yRadius:radius] fill];
}
+ // On OS versions earlier than Yosemite, to generate a drop shadow, we set an
+ // opaque background. This causes windows with non rectangular shapes to have
+ // square corners. To get around this, fill the path outside the window
+ // boundary with clearColor and tell Cococa to regenerate drop shadow. See
+ // crbug.com/543671.
+ if (windowMask_ && ![self inLiveResize] &&
+ !IsRectInsidePath(dirtyRect, windowMask_)) {
+ DCHECK(base::mac::IsOSMavericksOrEarlier());
+ gfx::ScopedNSGraphicsContextSaveGState state;
+
+ // The outer rectangular path corresponding to the window.
+ NSBezierPath* outerPath = [NSBezierPath bezierPathWithRect:[self bounds]];
+
+ [outerPath appendBezierPath:windowMask_];
+ [outerPath setWindingRule:NSEvenOddWindingRule];
+ [[NSGraphicsContext currentContext]
+ setCompositingOperation:NSCompositeCopy];
+ [[NSColor clearColor] set];
+
+ // Fill the region between windowMask_ and its outer rectangular path
+ // with clear color. This causes the window to have the shape described
+ // by windowMask_.
+ [outerPath fill];
+ // Regerate drop shadow around the window boundary.
+ [[self window] invalidateShadow];
+ }
+
// If there's a layer, painting occurs in BridgedNativeWidget::OnPaintLayer().
if (hostedView_->GetWidget()->GetLayer())
return;
@@ -416,6 +510,13 @@ gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client,
ui::CanvasPainter(&canvas, 1.f).context());
}
+// To maximize consistency with the Cocoa browser (mac_views_browser=0), accept
+// mouse clicks immediately so that clicking on Chrome from an inactive window
+// will allow the event to be processed, rather than merely activate the window.
+- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent {
+ return YES;
+}
+
- (NSTextInputContext*)inputContext {
// If the textInputClient_ does not exist, return nil since this view does not
// conform to NSTextInputClient protocol.
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.h b/chromium/ui/views/cocoa/bridged_native_widget.h
index 8f6523042de..fc521597ee7 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.h
+++ b/chromium/ui/views/cocoa/bridged_native_widget.h
@@ -49,6 +49,9 @@ class VIEWS_EXPORT BridgedNativeWidget
public ui::AcceleratedWidgetMacNSView,
public BridgedNativeWidgetOwner {
public:
+ // Contains NativeViewHost->gfx::NativeView associations.
+ using AssociatedViews = std::map<const views::View*, NSView*>;
+
// Ways of changing the visibility of the bridged NSWindow.
enum WindowVisibilityState {
HIDE_WINDOW, // Hides with -[NSWindow orderOut:].
@@ -156,6 +159,12 @@ class VIEWS_EXPORT BridgedNativeWidget
// Creates a ui::Compositor which becomes responsible for drawing the window.
void CreateLayer(ui::LayerType layer_type, bool translucent);
+ // Updates |associated_views_| on NativeViewHost::Attach()/Detach().
+ void SetAssociationForView(const views::View* view, NSView* native_view);
+ void ClearAssociationForView(const views::View* view);
+ // Sorts child NSViews according to NativeViewHosts order in views hierarchy.
+ void ReorderChildViews();
+
NativeWidgetMac* native_widget_mac() { return native_widget_mac_; }
BridgedContentView* ns_view() { return bridged_view_; }
NSWindow* ns_window() { return window_; }
@@ -289,6 +298,8 @@ class VIEWS_EXPORT BridgedNativeWidget
// shadow needs to be invalidated when a frame is received for the new shape.
bool invalidate_shadow_on_frame_swap_ = false;
+ AssociatedViews associated_views_;
+
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidget);
};
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.mm b/chromium/ui/views/cocoa/bridged_native_widget.mm
index 24bba74dd91..0ccff9d15a0 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget.mm
@@ -83,8 +83,20 @@ CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection,
namespace {
+using RankMap = std::map<NSView*, int>;
+
+// SDK 10.11 contains incompatible changes of sortSubviewsUsingFunction.
+// It takes (__kindof NSView*) as comparator argument.
+// https://llvm.org/bugs/show_bug.cgi?id=25149
+#if !defined(MAC_OS_X_VERSION_10_11) || \
+ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
+using NSViewComparatorValue = id;
+#else
+using NSViewComparatorValue = __kindof NSView*;
+#endif
+
const CGFloat kMavericksMenuOpacity = 251.0 / 255.0;
-const CGFloat kYosemiteMenuOpacity = 194.0 / 255.0;
+const CGFloat kYosemiteMenuOpacity = 177.0 / 255.0;
const int kYosemiteMenuBlur = 80;
// Margin at edge and corners of the window that trigger resizing. These match
@@ -96,7 +108,7 @@ int kWindowPropertiesKey;
float GetDeviceScaleFactorFromView(NSView* view) {
gfx::Display display =
- gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(view);
DCHECK(display.is_valid());
return display.device_scale_factor();
}
@@ -263,6 +275,40 @@ scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() {
return task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get();
}
+void RankNSViews(views::View* view,
+ const views::BridgedNativeWidget::AssociatedViews& hosts,
+ RankMap* rank) {
+ auto it = hosts.find(view);
+ if (it != hosts.end())
+ rank->emplace(it->second, rank->size());
+ for (int i = 0; i < view->child_count(); ++i)
+ RankNSViews(view->child_at(i), hosts, rank);
+}
+
+NSComparisonResult SubviewSorter(NSViewComparatorValue lhs,
+ NSViewComparatorValue rhs,
+ void* rank_as_void) {
+ DCHECK_NE(lhs, rhs);
+
+ const RankMap* rank = static_cast<const RankMap*>(rank_as_void);
+ auto left_rank = rank->find(lhs);
+ auto right_rank = rank->find(rhs);
+ bool left_found = left_rank != rank->end();
+ bool right_found = right_rank != rank->end();
+
+ // Sort unassociated views above associated views.
+ if (left_found != right_found)
+ return left_found ? NSOrderedAscending : NSOrderedDescending;
+
+ if (left_found) {
+ return left_rank->second < right_rank->second ? NSOrderedAscending
+ : NSOrderedDescending;
+ }
+
+ // If both are unassociated, consider that order is not important
+ return NSOrderedSame;
+}
+
} // namespace
namespace views {
@@ -293,11 +339,7 @@ BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent)
}
BridgedNativeWidget::~BridgedNativeWidget() {
- RemoveOrDestroyChildren();
- DCHECK(child_windows_.empty());
- SetFocusManager(NULL);
- SetRootView(NULL);
- DestroyCompositor();
+ bool close_window = false;
if ([window_ delegate]) {
// If the delegate is still set on a modal dialog, it means it was not
// closed via [NSApplication endSheet:]. This is probably OK if the widget
@@ -308,12 +350,31 @@ BridgedNativeWidget::~BridgedNativeWidget() {
// So ban it. Modal dialogs should be closed via Widget::Close().
DCHECK(!native_widget_mac_->IsWindowModalSheet());
- // If the delegate is still set, it means OnWindowWillClose has not been
- // called and the window is still open. Calling -[NSWindow close] will
- // synchronously call OnWindowWillClose and notify NativeWidgetMac.
+ // If the delegate is still set, it means OnWindowWillClose() has not been
+ // called and the window is still open. Usually, -[NSWindow close] would
+ // synchronously call OnWindowWillClose() which removes the delegate and
+ // notifies NativeWidgetMac, which then calls this with a nil delegate.
+ // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or
+ // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit
+ // calling back into the bridge. This means OnWindowWillClose() needs to be
+ // invoked manually, which is done below.
+ // Note that if the window has children it can't be closed until the
+ // children are gone, but removing child windows calls into AppKit for the
+ // parent window, so the delegate must be cleared first.
+ [window_ setDelegate:nil];
+ close_window = true;
+ }
+
+ RemoveOrDestroyChildren();
+ DCHECK(child_windows_.empty());
+ SetFocusManager(nullptr);
+ SetRootView(nullptr);
+ DestroyCompositor();
+
+ if (close_window) {
+ OnWindowWillClose();
[window_ close];
}
- DCHECK(![window_ delegate]);
}
void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window,
@@ -645,11 +706,6 @@ void BridgedNativeWidget::ToggleDesiredFullscreenState() {
if (!window_visible_)
SetVisibilityState(SHOW_INACTIVE);
- if (base::mac::IsOSSnowLeopard()) {
- NOTIMPLEMENTED();
- return; // TODO(tapted): Implement this for Snow Leopard.
- }
-
// Enable fullscreen collection behavior because:
// 1: -[NSWindow toggleFullscreen:] would otherwise be ignored,
// 2: the fullscreen button must be enabled so the user can leave fullscreen.
@@ -667,6 +723,14 @@ void BridgedNativeWidget::OnSizeChanged() {
if ([window_ inLiveResize])
MaybeWaitForFrame(new_size);
}
+
+ // 10.9 is unable to generate a window shadow from the composited CALayer, so
+ // use Quartz.
+ // We don't update the window mask during a live resize, instead it is done
+ // after the resize is completed in viewDidEndLiveResize: in
+ // BridgedContentView.
+ if (base::mac::IsOSMavericksOrEarlier() && ![window_ inLiveResize])
+ [bridged_view_ updateWindowMask];
}
void BridgedNativeWidget::OnVisibilityChanged() {
@@ -850,12 +914,42 @@ void BridgedNativeWidget::CreateLayer(ui::LayerType layer_type,
// native shape is what's most appropriate for displaying sheets on Mac.
if (translucent && !native_widget_mac_->IsWindowModalSheet()) {
[window_ setOpaque:NO];
- [window_ setBackgroundColor:[NSColor clearColor]];
+ // For Mac OS versions earlier than Yosemite, the Window server isn't able
+ // to generate a window shadow from the composited CALayer. To get around
+ // this, let the window background remain opaque and clip the window
+ // boundary in drawRect method of BridgedContentView. See crbug.com/543671.
+ if (base::mac::IsOSYosemiteOrLater())
+ [window_ setBackgroundColor:[NSColor clearColor]];
}
UpdateLayerProperties();
}
+void BridgedNativeWidget::SetAssociationForView(const views::View* view,
+ NSView* native_view) {
+ DCHECK_EQ(0u, associated_views_.count(view));
+ associated_views_[view] = native_view;
+ native_widget_mac_->GetWidget()->ReorderNativeViews();
+}
+
+void BridgedNativeWidget::ClearAssociationForView(const views::View* view) {
+ auto it = associated_views_.find(view);
+ DCHECK(it != associated_views_.end());
+ associated_views_.erase(it);
+}
+
+void BridgedNativeWidget::ReorderChildViews() {
+ RankMap rank;
+ Widget* widget = native_widget_mac_->GetWidget();
+ RankNSViews(widget->GetRootView(), associated_views_, &rank);
+ // Unassociated NSViews should be ordered above associated ones. The exception
+ // is the UI compositor's superview, which should always be on the very
+ // bottom, so give it an explicit negative rank.
+ if (compositor_superview_)
+ rank[compositor_superview_] = -1;
+ [bridged_view_ sortSubviewsUsingFunction:&SubviewSorter context:&rank];
+}
+
////////////////////////////////////////////////////////////////////////////////
// BridgedNativeWidget, internal::InputMethodDelegate:
@@ -918,7 +1012,6 @@ void BridgedNativeWidget::OnDeviceScaleFactorChanged(
}
base::Closure BridgedNativeWidget::PrepareForLayerBoundsChange() {
- NOTIMPLEMENTED();
return base::Closure();
}
@@ -1053,11 +1146,7 @@ void BridgedNativeWidget::CreateCompositor() {
AddCompositorSuperview();
- // TODO(tapted): Get this value from GpuDataManagerImpl via ViewsDelegate.
- bool needs_gl_finish_workaround = false;
-
- compositor_widget_.reset(
- new ui::AcceleratedWidgetMac(needs_gl_finish_workaround));
+ compositor_widget_.reset(new ui::AcceleratedWidgetMac());
compositor_.reset(
new ui::Compositor(context_factory, GetCompositorTaskRunner()));
compositor_->SetAcceleratedWidget(compositor_widget_->accelerated_widget());
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
index 5e8579f9034..79fdac10510 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -11,17 +11,40 @@
#include "base/macros.h"
#include "ui/base/hit_test.h"
#import "ui/base/test/nswindow_fullscreen_notification_waiter.h"
+#include "ui/base/test/ui_controls.h"
#import "ui/base/test/windowed_nsnotification_observer.h"
#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/views/test/widget_test.h"
+#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/window/native_frame_view.h"
namespace views {
namespace test {
+namespace {
+
+// Provide a resizable Widget by default. Starting in 10.11, OSX doesn't
+// correctly restore the window size when coming out of fullscreen if the window
+// is not user-sizable.
+class ResizableDelegateView : public WidgetDelegateView {
+ public:
+ ResizableDelegateView() {}
+
+ // WidgetDelgate:
+ bool CanResize() const override { return true; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResizableDelegateView);
+};
+
+} // namespace
class BridgedNativeWidgetUITest : public test::WidgetTest {
public:
- BridgedNativeWidgetUITest() {}
+ BridgedNativeWidgetUITest() {
+ // TODO(tapted): Remove this when these are absorbed into Chrome's
+ // interactive_ui_tests target. See http://crbug.com/403679.
+ ui_controls::EnableUIControls();
+ }
// testing::Test:
void SetUp() override {
@@ -29,6 +52,8 @@ class BridgedNativeWidgetUITest : public test::WidgetTest {
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ init_params.bounds = gfx::Rect(100, 100, 300, 200);
+ init_params.delegate = new ResizableDelegateView;
widget_.reset(new Widget);
widget_->Init(init_params);
}
@@ -52,8 +77,6 @@ class BridgedNativeWidgetUITest : public test::WidgetTest {
// by the Widget code or elsewhere (e.g. by the user).
TEST_F(BridgedNativeWidgetUITest, FullscreenSynchronousState) {
EXPECT_FALSE(widget_->IsFullscreen());
- if (base::mac::IsOSSnowLeopard())
- return;
// Allow user-initiated fullscreen changes on the Window.
[test_window()
@@ -121,11 +144,6 @@ TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) {
EXPECT_FALSE(widget_->IsVisible());
widget_->SetFullscreen(true);
EXPECT_TRUE(widget_->IsVisible());
- if (base::mac::IsOSSnowLeopard()) {
- // On Snow Leopard, SetFullscreen() isn't implemented. But shouldn't crash.
- EXPECT_FALSE(widget_->IsFullscreen());
- return;
- }
EXPECT_TRUE(widget_->IsFullscreen());
EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
@@ -152,9 +170,6 @@ TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) {
// Test that Widget::Restore exits fullscreen.
TEST_F(BridgedNativeWidgetUITest, FullscreenRestore) {
- if (base::mac::IsOSSnowLeopard())
- return;
-
base::scoped_nsobject<NSWindowFullscreenNotificationWaiter> waiter(
[[NSWindowFullscreenNotificationWaiter alloc]
initWithWindow:test_window()]);
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
index d289af52176..3b3eb082631 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -214,8 +214,7 @@ class BridgedNativeWidgetTest : public BridgedNativeWidgetTestBase {
protected:
scoped_ptr<views::View> view_;
- scoped_ptr<BridgedNativeWidget> bridge_;
- BridgedContentView* ns_view_; // Weak. Owned by bridge_.
+ BridgedContentView* ns_view_; // Weak. Owned by bridge().
base::MessageLoopForUI message_loop_;
private:
@@ -280,6 +279,8 @@ void BridgedNativeWidgetTest::SetUp() {
}
void BridgedNativeWidgetTest::TearDown() {
+ if (bridge())
+ bridge()->SetRootView(nullptr);
view_.reset();
BridgedNativeWidgetTestBase::TearDown();
}
@@ -430,22 +431,22 @@ TEST_F(BridgedNativeWidgetTest, InputContext) {
// Test getting complete string using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_GetCompleteString) {
- const std::string kTestString = "foo bar baz";
- InstallTextField(kTestString);
+ const std::string test_string = "foo bar baz";
+ InstallTextField(test_string);
- NSRange range = NSMakeRange(0, kTestString.size());
+ NSRange range = NSMakeRange(0, test_string.size());
NSRange actual_range;
NSAttributedString* text =
[ns_view_ attributedSubstringForProposedRange:range
actualRange:&actual_range];
- EXPECT_EQ(kTestString, SysNSStringToUTF8([text string]));
+ EXPECT_EQ(test_string, SysNSStringToUTF8([text string]));
EXPECT_EQ_RANGE(range, actual_range);
}
// Test getting middle substring using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_GetMiddleSubstring) {
- const std::string kTestString = "foo bar baz";
- InstallTextField(kTestString);
+ const std::string test_string = "foo bar baz";
+ InstallTextField(test_string);
NSRange range = NSMakeRange(4, 3);
NSRange actual_range;
@@ -458,8 +459,8 @@ TEST_F(BridgedNativeWidgetTest, TextInput_GetMiddleSubstring) {
// Test getting ending substring using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_GetEndingSubstring) {
- const std::string kTestString = "foo bar baz";
- InstallTextField(kTestString);
+ const std::string test_string = "foo bar baz";
+ InstallTextField(test_string);
NSRange range = NSMakeRange(8, 100);
NSRange actual_range;
@@ -473,8 +474,8 @@ TEST_F(BridgedNativeWidgetTest, TextInput_GetEndingSubstring) {
// Test getting empty substring using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_GetEmptySubstring) {
- const std::string kTestString = "foo bar baz";
- InstallTextField(kTestString);
+ const std::string test_string = "foo bar baz";
+ InstallTextField(test_string);
NSRange range = EmptyRange();
NSRange actual_range;
@@ -487,21 +488,21 @@ TEST_F(BridgedNativeWidgetTest, TextInput_GetEmptySubstring) {
// Test inserting text using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_InsertText) {
- const std::string kTestString = "foo";
- InstallTextField(kTestString);
+ const std::string test_string = "foo";
+ InstallTextField(test_string);
- [ns_view_ insertText:SysUTF8ToNSString(kTestString)
+ [ns_view_ insertText:SysUTF8ToNSString(test_string)
replacementRange:EmptyRange()];
- gfx::Range range(0, kTestString.size());
+ gfx::Range range(0, test_string.size());
base::string16 text;
EXPECT_TRUE([ns_view_ textInputClient]->GetTextFromRange(range, &text));
- EXPECT_EQ(ASCIIToUTF16(kTestString), text);
+ EXPECT_EQ(ASCIIToUTF16(test_string), text);
}
// Test replacing text using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_ReplaceText) {
- const std::string kTestString = "foo bar";
- InstallTextField(kTestString);
+ const std::string test_string = "foo bar";
+ InstallTextField(test_string);
[ns_view_ insertText:@"baz" replacementRange:NSMakeRange(4, 3)];
EXPECT_EQ("foo baz", GetText());
@@ -509,8 +510,8 @@ TEST_F(BridgedNativeWidgetTest, TextInput_ReplaceText) {
// Test IME composition using text input protocol.
TEST_F(BridgedNativeWidgetTest, TextInput_Compose) {
- const std::string kTestString = "foo ";
- InstallTextField(kTestString);
+ const std::string test_string = "foo ";
+ InstallTextField(test_string);
EXPECT_FALSE([ns_view_ hasMarkedText]);
EXPECT_EQ_RANGE(EmptyRange(), [ns_view_ markedRange]);
@@ -522,9 +523,9 @@ TEST_F(BridgedNativeWidgetTest, TextInput_Compose) {
selectedRange:NSMakeRange(0, 2)
replacementRange:EmptyRange()];
EXPECT_TRUE([ns_view_ hasMarkedText]);
- EXPECT_EQ_RANGE(NSMakeRange(kTestString.size(), compositionLength),
+ EXPECT_EQ_RANGE(NSMakeRange(test_string.size(), compositionLength),
[ns_view_ markedRange]);
- EXPECT_EQ_RANGE(NSMakeRange(kTestString.size(), 2), [ns_view_ selectedRange]);
+ EXPECT_EQ_RANGE(NSMakeRange(test_string.size(), 2), [ns_view_ selectedRange]);
// Confirm composition.
[ns_view_ unmarkText];
@@ -653,16 +654,16 @@ TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange) {
InstallTextField("");
ui::TextInputClient* client = [ns_view_ textInputClient];
- const base::string16 kTestString = base::ASCIIToUTF16("test_str");
+ const base::string16 test_string = base::ASCIIToUTF16("test_str");
const size_t kTextLength = 8;
- SetCompositionText(client, kTestString, 1, nullptr);
+ SetCompositionText(client, test_string, 1, nullptr);
// Query bounds for the whole composition string.
NSRange query_range = NSMakeRange(0, kTextLength);
NSRange actual_range;
NSRect rect = [ns_view_ firstRectForCharacterRange:query_range
actualRange:&actual_range];
- EXPECT_EQ(GetExpectedBoundsForRange(client, kTestString, query_range),
+ EXPECT_EQ(GetExpectedBoundsForRange(client, test_string, query_range),
gfx::ScreenRectFromNSRect(rect));
EXPECT_EQ_RANGE(query_range, actual_range);
@@ -670,7 +671,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_FirstRectForCharacterRange) {
query_range = NSMakeRange(1, 4);
rect = [ns_view_ firstRectForCharacterRange:query_range
actualRange:&actual_range];
- EXPECT_EQ(GetExpectedBoundsForRange(client, kTestString, query_range),
+ EXPECT_EQ(GetExpectedBoundsForRange(client, test_string, query_range),
gfx::ScreenRectFromNSRect(rect));
EXPECT_EQ_RANGE(query_range, actual_range);
}
@@ -683,9 +684,6 @@ typedef BridgedNativeWidgetTestBase BridgedNativeWidgetSimulateFullscreenTest;
// mashing Ctrl+Left/Right to keep OSX in a transition between Spaces to cause
// the fullscreen transition to fail.
TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) {
- if (base::mac::IsOSSnowLeopard())
- return;
-
base::scoped_nsobject<NSWindow> owned_window(
[[BridgedNativeWidgetTestFullScreenWindow alloc]
initWithContentRect:NSMakeRect(50, 50, 400, 300)
diff --git a/chromium/ui/views/cocoa/cocoa_mouse_capture.h b/chromium/ui/views/cocoa/cocoa_mouse_capture.h
index 0adf134295f..55f87ede81c 100644
--- a/chromium/ui/views/cocoa/cocoa_mouse_capture.h
+++ b/chromium/ui/views/cocoa/cocoa_mouse_capture.h
@@ -24,7 +24,7 @@ class VIEWS_EXPORT CocoaMouseCapture {
~CocoaMouseCapture();
// True if the event tap is active (i.e. not stolen by a later instance).
- bool IsActive() const { return active_handle_; }
+ bool IsActive() const { return !!active_handle_; }
private:
class ActiveEventTap;
diff --git a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm b/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
index 678e4d58440..4acbd946877 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
+++ b/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
@@ -5,6 +5,7 @@
#import "ui/views/cocoa/native_widget_mac_nswindow.h"
#include "base/mac/foundation_util.h"
+#import "ui/views/cocoa/bridged_native_widget.h"
#import "ui/base/cocoa/user_interface_item_command_handler.h"
#import "ui/views/cocoa/views_nswindow_delegate.h"
#include "ui/views/controls/menu/menu_controller.h"
@@ -83,9 +84,17 @@
if (![self delegate])
return NO;
- // Dialogs shouldn't take large shadows away from their parent window.
+ // Dialogs and bubbles shouldn't take large shadows away from their parent.
views::Widget* widget = [self viewsWidget];
- return widget->CanActivate() && !widget->IsDialogBox();
+ return widget->CanActivate() &&
+ !views::NativeWidgetMac::GetBridgeForNativeWindow(self)->parent();
+}
+
+// Lets the traffic light buttons on the parent window keep their active state.
+- (BOOL)_sharesParentKeyState {
+ // Follow -canBecomeMainWindow unless the window provides its own buttons.
+ return ([self styleMask] & NSClosableWindowMask) == 0 &&
+ ![self canBecomeMainWindow];
}
// Override sendEvent to allow key events to be forwarded to a toolkit-views
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.h b/chromium/ui/views/cocoa/tooltip_manager_mac.h
index a7977a9aa2f..208fb4e948a 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.h
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.h
@@ -18,8 +18,7 @@ class TooltipManagerMac : public TooltipManager {
~TooltipManagerMac() override;
// TooltipManager:
- int GetMaxWidth(const gfx::Point& location,
- gfx::NativeView context) const override;
+ int GetMaxWidth(const gfx::Point& location) const override;
const gfx::FontList& GetFontList() const override;
void UpdateTooltip() override;
void TooltipTextChanged(View* view) override;
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.mm b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
index b96d1227715..99a1fb5d906 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.mm
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
@@ -4,6 +4,7 @@
#include "ui/views/cocoa/tooltip_manager_mac.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#import "ui/views/cocoa/bridged_content_view.h"
@@ -25,8 +26,7 @@ TooltipManagerMac::TooltipManagerMac(BridgedNativeWidget* widget)
TooltipManagerMac::~TooltipManagerMac() {
}
-int TooltipManagerMac::GetMaxWidth(const gfx::Point& location,
- gfx::NativeView context) const {
+int TooltipManagerMac::GetMaxWidth(const gfx::Point& location) const {
return kTooltipMaxWidthPixels;
}
@@ -40,7 +40,8 @@ void TooltipManagerMac::UpdateTooltip() {
NSWindow* window = widget_->ns_window();
BridgedContentView* view = widget_->ns_view();
- NSPoint nspoint = [window convertScreenToBase:[NSEvent mouseLocation]];
+ NSPoint nspoint =
+ ui::ConvertPointFromScreenToWindow(window, [NSEvent mouseLocation]);
// Note: flip in the view's frame, which matches the window's contentRect.
gfx::Point point(nspoint.x, NSHeight([view frame]) - nspoint.y);
[view updateTooltipIfRequiredAt:point];
diff --git a/chromium/ui/views/cocoa/views_scrollbar_bridge.h b/chromium/ui/views/cocoa/views_scrollbar_bridge.h
new file mode 100644
index 00000000000..eb070a161c5
--- /dev/null
+++ b/chromium/ui/views/cocoa/views_scrollbar_bridge.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_
+#define UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/scoped_nsobject.h"
+#include "ui/views/views_export.h"
+
+// The delegate set to ViewsScrollbarBridge.
+class ViewsScrollbarBridgeDelegate {
+ public:
+ // Invoked by ViewsScrollbarBridge when the system informs the process that
+ // the preferred scroller style has changed
+ virtual void OnScrollerStyleChanged() = 0;
+};
+
+// A bridge to NSScroller managed by NativeCocoaScrollbar. Serves as a helper
+// class to bridge NSScroller notifications and functions to CocoaScrollbar.
+@interface ViewsScrollbarBridge : NSObject {
+ @private
+ ViewsScrollbarBridgeDelegate* delegate_; // Weak. Owns this.
+}
+
+// Initializes with the given delegate and registers for notifications on
+// scroller style changes.
+- (id)initWithDelegate:(ViewsScrollbarBridgeDelegate*)delegate;
+
+// Sets |delegate_| to nullptr.
+-(void)clearDelegate;
+
+// Returns the style of scrollers that OSX is using.
++ (NSScrollerStyle)getPreferredScrollerStyle;
+
+@end
+
+#endif \ No newline at end of file
diff --git a/chromium/ui/views/cocoa/views_scrollbar_bridge.mm b/chromium/ui/views/cocoa/views_scrollbar_bridge.mm
new file mode 100644
index 00000000000..d80dece0e7b
--- /dev/null
+++ b/chromium/ui/views/cocoa/views_scrollbar_bridge.mm
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/cocoa/views_scrollbar_bridge.h"
+
+#import "base/mac/sdk_forward_declarations.h"
+
+@interface ViewsScrollbarBridge ()
+
+// Called when we receive a NSPreferredScrollerStyleDidChangeNotification.
+- (void)onScrollerStyleChanged:(NSNotification*)notification;
+
+@end
+
+@implementation ViewsScrollbarBridge
+
+- (id)initWithDelegate:(ViewsScrollbarBridgeDelegate*)delegate {
+ if ((self = [super init])) {
+ delegate_ = delegate;
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(onScrollerStyleChanged:)
+ name:NSPreferredScrollerStyleDidChangeNotification
+ object:nil];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ DCHECK(!delegate_);
+ [super dealloc];
+}
+
+- (void)clearDelegate {
+ delegate_ = nullptr;
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)onScrollerStyleChanged:(NSNotification*)notification {
+ if (delegate_)
+ delegate_->OnScrollerStyleChanged();
+}
+
++ (NSScrollerStyle)getPreferredScrollerStyle {
+ return [NSScroller preferredScrollerStyle];
+}
+
+@end
diff --git a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm b/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm
index 0fbe5d545c2..d85184ef5a4 100644
--- a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm
+++ b/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm
@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
#include "base/logging.h"
+#include "base/mac/sdk_forward_declarations.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#import "ui/gfx/mac/coordinate_conversion.h"
@@ -72,14 +73,12 @@ NSWindow* WidgetOwnerNSWindowAdapter::GetNSWindow() {
gfx::Vector2d WidgetOwnerNSWindowAdapter::GetChildWindowOffset() const {
NSRect rect_in_window =
[anchor_view_ convertRect:[anchor_view_ bounds] toView:nil];
- // Ensure we anchor off the top-left of |anchor_view_| (rect_in_window.origin
+ NSRect rect_in_screen = [anchor_window_ convertRectToScreen:rect_in_window];
+ // Ensure we anchor off the top-left of |anchor_view_| (rect_in_screen.origin
// is the bottom-left of the view).
- // TODO(tapted): Use -[NSWindow convertRectToScreen:] when we ditch 10.6.
- NSRect rect_in_screen = NSZeroRect;
- rect_in_screen.origin =
- [anchor_window_ convertBaseToScreen:NSMakePoint(NSMinX(rect_in_window),
- NSMaxY(rect_in_window))];
- return gfx::ScreenRectFromNSRect(rect_in_screen).OffsetFromOrigin();
+ NSPoint anchor_in_screen =
+ NSMakePoint(NSMinX(rect_in_screen), NSMaxY(rect_in_screen));
+ return gfx::ScreenPointFromNSPoint(anchor_in_screen).OffsetFromOrigin();
}
bool WidgetOwnerNSWindowAdapter::IsVisibleParent() const {
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc
index 2c63883c617..e0aea825e9e 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_view.cc
@@ -103,11 +103,9 @@ void DrawGradientRect(const gfx::Rect& rect, SkColor start_color,
points[1].iset(rect.width() + 1, 0);
else
points[1].iset(0, rect.height() + 1);
- skia::RefPtr<SkShader> shader(skia::AdoptRef(
- SkGradientShader::CreateLinear(points, colors, NULL, 2,
- SkShader::kClamp_TileMode)));
SkPaint paint;
- paint.setShader(shader.get());
+ paint.setShader(SkGradientShader::MakeLinear(points, colors, NULL, 2,
+ SkShader::kClamp_TileMode));
canvas->DrawRect(rect, paint);
}
diff --git a/chromium/ui/views/controls/button/blue_button.cc b/chromium/ui/views/controls/button/blue_button.cc
index 3740bb11a36..12ea638c160 100644
--- a/chromium/ui/views/controls/button/blue_button.cc
+++ b/chromium/ui/views/controls/button/blue_button.cc
@@ -53,7 +53,7 @@ const char* BlueButton::GetClassName() const {
scoped_ptr<LabelButtonBorder> BlueButton::CreateDefaultBorder() const {
// Insets for splitting the images.
- const gfx::Insets insets(5, 5, 5, 5);
+ const gfx::Insets insets(5);
scoped_ptr<LabelButtonAssetBorder> button_border(
new LabelButtonAssetBorder(style()));
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index 0f1160b11f1..dab4870ad53 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "ui/native_theme/native_theme.h"
-#include "ui/views/view.h"
+#include "ui/views/animation/ink_drop_host_view.h"
namespace views {
@@ -26,7 +26,7 @@ class VIEWS_EXPORT ButtonListener {
// A View representing a button. Depending on the specific type, the button
// could be implemented by a native control or custom rendered.
-class VIEWS_EXPORT Button : public View {
+class VIEWS_EXPORT Button : public InkDropHostView {
public:
~Button() override;
diff --git a/chromium/ui/views/controls/button/custom_button.cc b/chromium/ui/views/controls/button/custom_button.cc
index 86fca746d59..6e80eb12d9f 100644
--- a/chromium/ui/views/controls/button/custom_button.cc
+++ b/chromium/ui/views/controls/button/custom_button.cc
@@ -5,12 +5,17 @@
#include "ui/views/controls/button/custom_button.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/screen.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/views/animation/ink_drop_delegate.h"
+#include "ui/views/animation/ink_drop_hover.h"
#include "ui/views/controls/button/blue_button.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
@@ -26,20 +31,51 @@
namespace views {
+namespace {
+
// How long the hover animation takes if uninterrupted.
-static const int kHoverFadeDurationMs = 150;
+const int kHoverFadeDurationMs = 150;
-// static
-const char CustomButton::kViewClassName[] = "CustomButton";
+// The amount to enlarge the focus border in all directions relative to the
+// button.
+const int kFocusBorderOutset = -2;
+
+// The corner radius of the focus border roundrect.
+const int kFocusBorderCornerRadius = 3;
+
+class MdFocusRing : public views::View {
+ public:
+ MdFocusRing() {
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+
+ // Don't accept input events.
+ SetEnabled(false);
+ }
+ ~MdFocusRing() override {}
+
+ void OnPaint(gfx::Canvas* canvas) override {
+ CustomButton::PaintMdFocusRing(canvas, this);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MdFocusRing);
+};
+
+} // namespace
////////////////////////////////////////////////////////////////////////////////
// CustomButton, public:
// static
+const char CustomButton::kViewClassName[] = "CustomButton";
+
+// static
const CustomButton* CustomButton::AsCustomButton(const views::View* view) {
- return AsCustomButton(const_cast<views::View*>(view));
+ return AsCustomButton(const_cast<View*>(view));
}
+// static
CustomButton* CustomButton::AsCustomButton(views::View* view) {
if (view) {
const char* classname = view->GetClassName();
@@ -55,6 +91,19 @@ CustomButton* CustomButton::AsCustomButton(views::View* view) {
return NULL;
}
+// static
+void CustomButton::PaintMdFocusRing(gfx::Canvas* canvas, views::View* view) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(view->GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_CallToActionColor));
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(1);
+ gfx::RectF rect(view->GetLocalBounds());
+ rect.Inset(gfx::InsetsF(0.5));
+ canvas->DrawRoundRect(rect, kFocusBorderCornerRadius, paint);
+}
+
CustomButton::~CustomButton() {}
void CustomButton::SetState(ButtonState state) {
@@ -106,7 +155,7 @@ void CustomButton::SetHotTracked(bool is_hot_tracked) {
SetState(is_hot_tracked ? STATE_HOVERED : STATE_NORMAL);
if (is_hot_tracked)
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
}
bool CustomButton::IsHotTracked() const {
@@ -116,13 +165,9 @@ bool CustomButton::IsHotTracked() const {
////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides:
-void CustomButton::Layout() {
- Button::Layout();
- if (ink_drop_delegate_)
- ink_drop_delegate_->OnLayout();
-}
-
void CustomButton::OnEnabledChanged() {
+ // TODO(bruthig): Is there any reason we are not calling
+ // Button::OnEnabledChanged() here?
if (enabled() ? (state_ != STATE_DISABLED) : (state_ == STATE_DISABLED))
return;
@@ -130,6 +175,9 @@ void CustomButton::OnEnabledChanged() {
SetState(ShouldEnterHoveredState() ? STATE_HOVERED : STATE_NORMAL);
else
SetState(STATE_DISABLED);
+
+ if (ink_drop_delegate_)
+ ink_drop_delegate_->SetHovered(ShouldShowInkDropHover());
}
const char* CustomButton::GetClassName() const {
@@ -139,7 +187,8 @@ const char* CustomButton::GetClassName() const {
bool CustomButton::OnMousePressed(const ui::MouseEvent& event) {
if (state_ == STATE_DISABLED)
return true;
- if (ShouldEnterPushedState(event) && HitTestPoint(event.location())) {
+ if (state_ != STATE_PRESSED && ShouldEnterPushedState(event) &&
+ HitTestPoint(event.location())) {
SetState(STATE_PRESSED);
if (ink_drop_delegate_)
ink_drop_delegate_->OnAction(views::InkDropState::ACTION_PENDING);
@@ -183,8 +232,12 @@ void CustomButton::OnMouseReleased(const ui::MouseEvent& event) {
}
void CustomButton::OnMouseCaptureLost() {
- // Starting a drag results in a MouseCaptureLost, we need to ignore it.
- if (state_ != STATE_DISABLED && !InDrag())
+ // Starting a drag results in a MouseCaptureLost. Reset button state.
+ // TODO(varkha) While in drag only reset the state with Material Design.
+ // The same logic may applies everywhere so gather any feedback and update.
+ bool reset_button_state =
+ !InDrag() || ui::MaterialDesignController::IsModeMaterial();
+ if (state_ != STATE_DISABLED && reset_button_state)
SetState(STATE_NORMAL);
if (ink_drop_delegate_)
ink_drop_delegate_->OnAction(views::InkDropState::HIDDEN);
@@ -272,6 +325,13 @@ bool CustomButton::AcceleratorPressed(const ui::Accelerator& accelerator) {
return true;
}
+bool CustomButton::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
+ // If this button is focused and the user presses space or enter, don't let
+ // that be treated as an accelerator.
+ return (event.key_code() == ui::VKEY_SPACE) ||
+ (event.key_code() == ui::VKEY_RETURN);
+}
+
void CustomButton::ShowContextMenu(const gfx::Point& p,
ui::MenuSourceType source_type) {
if (!context_menu_controller())
@@ -281,6 +341,10 @@ void CustomButton::ShowContextMenu(const gfx::Point& p,
// we won't get a mouse exited and reset state. Reset it now to be sure.
if (state_ != STATE_DISABLED)
SetState(STATE_NORMAL);
+ if (hide_ink_drop_when_showing_context_menu_ && ink_drop_delegate_) {
+ ink_drop_delegate_->SetHovered(false);
+ ink_drop_delegate_->OnAction(InkDropState::HIDDEN);
+ }
View::ShowContextMenu(p, source_type);
}
@@ -318,6 +382,14 @@ void CustomButton::VisibilityChanged(View* starting_from, bool visible) {
SetState(visible && ShouldEnterHoveredState() ? STATE_HOVERED : STATE_NORMAL);
}
+scoped_ptr<InkDropHover> CustomButton::CreateInkDropHover() const {
+ return ShouldShowInkDropHover() ? Button::CreateInkDropHover() : nullptr;
+}
+
+SkColor CustomButton::GetInkDropBaseColor() const {
+ return ink_drop_base_color_;
+}
+
////////////////////////////////////////////////////////////////////////////////
// CustomButton, gfx::AnimationDelegate implementation:
@@ -326,23 +398,34 @@ void CustomButton::AnimationProgressed(const gfx::Animation* animation) {
}
////////////////////////////////////////////////////////////////////////////////
-// CustomButton, views::InkDropHost implementation:
+// CustomButton, View overrides (public):
-void CustomButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
- SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
- layer()->Add(ink_drop_layer);
- layer()->StackAtBottom(ink_drop_layer);
+void CustomButton::Layout() {
+ Button::Layout();
+ gfx::Rect focus_bounds = GetLocalBounds();
+ focus_bounds.Inset(gfx::Insets(kFocusBorderOutset));
+ if (md_focus_ring_)
+ md_focus_ring_->SetBoundsRect(focus_bounds);
}
-void CustomButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
- layer()->Remove(ink_drop_layer);
- SetFillsBoundsOpaquely(true);
- SetPaintToLayer(false);
+void CustomButton::ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) {
+ if (!details.is_add && state_ != STATE_DISABLED)
+ SetState(STATE_NORMAL);
}
-gfx::Point CustomButton::CalculateInkDropCenter() const {
- return GetLocalBounds().CenterPoint();
+void CustomButton::OnFocus() {
+ Button::OnFocus();
+ if (md_focus_ring_)
+ md_focus_ring_->SetVisible(true);
+}
+
+void CustomButton::OnBlur() {
+ Button::OnBlur();
+ if (IsHotTracked())
+ SetState(STATE_NORMAL);
+ if (md_focus_ring_)
+ md_focus_ring_->SetVisible(false);
}
////////////////////////////////////////////////////////////////////////////////
@@ -359,7 +442,10 @@ CustomButton::CustomButton(ButtonListener* listener)
ink_drop_delegate_(nullptr),
notify_action_(NOTIFY_ON_RELEASE),
has_ink_drop_action_on_click_(false),
- ink_drop_action_on_click_(InkDropState::QUICK_ACTION) {
+ ink_drop_action_on_click_(InkDropState::ACTION_TRIGGERED),
+ hide_ink_drop_when_showing_context_menu_(true),
+ ink_drop_base_color_(gfx::kPlaceholderColor),
+ md_focus_ring_(nullptr) {
hover_animation_.SetSlideDuration(kHoverFadeDurationMs);
}
@@ -377,6 +463,10 @@ bool CustomButton::ShouldEnterPushedState(const ui::Event& event) {
return IsTriggerableEvent(event);
}
+bool CustomButton::ShouldShowInkDropHover() const {
+ return enabled() && IsMouseHovered() && !InDrag();
+}
+
bool CustomButton::ShouldEnterHoveredState() {
if (!visible())
return false;
@@ -401,25 +491,16 @@ bool CustomButton::ShouldEnterHoveredState() {
return check_mouse_position && IsMouseHovered();
}
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, View overrides (protected):
-
-void CustomButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- Button::OnBoundsChanged(previous_bounds);
- if (ink_drop_delegate_)
- ink_drop_delegate_->OnLayout();
+void CustomButton::UseMdFocusRing() {
+ DCHECK(!md_focus_ring_);
+ md_focus_ring_ = new MdFocusRing();
+ AddChildView(md_focus_ring_);
+ md_focus_ring_->SetVisible(false);
+ set_request_focus_on_press(false);
}
-void CustomButton::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (!details.is_add && state_ != STATE_DISABLED)
- SetState(STATE_NORMAL);
-}
-
-void CustomButton::OnBlur() {
- if (IsHotTracked())
- SetState(STATE_NORMAL);
-}
+////////////////////////////////////////////////////////////////////////////////
+// CustomButton, Button overrides (protected):
void CustomButton::NotifyClick(const ui::Event& event) {
if (ink_drop_delegate() && has_ink_drop_action_on_click_)
diff --git a/chromium/ui/views/controls/button/custom_button.h b/chromium/ui/views/controls/button/custom_button.h
index d92f0f04078..cd94e3c3095 100644
--- a/chromium/ui/views/controls/button/custom_button.h
+++ b/chromium/ui/views/controls/button/custom_button.h
@@ -10,7 +10,6 @@
#include "ui/events/event_constants.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/throb_animation.h"
-#include "ui/views/animation/ink_drop_host.h"
#include "ui/views/animation/ink_drop_state.h"
#include "ui/views/controls/button/button.h"
@@ -22,9 +21,7 @@ class InkDropDelegate;
// 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.
-class VIEWS_EXPORT CustomButton : public Button,
- public gfx::AnimationDelegate,
- public views::InkDropHost {
+class VIEWS_EXPORT CustomButton : public Button, public gfx::AnimationDelegate {
public:
// An enum describing the events on which a button should notify its listener.
enum NotifyAction {
@@ -35,8 +32,11 @@ class VIEWS_EXPORT CustomButton : public Button,
// The menu button's class name.
static const char kViewClassName[];
- static const CustomButton* AsCustomButton(const views::View* view);
- static CustomButton* AsCustomButton(views::View* view);
+ static const CustomButton* AsCustomButton(const View* view);
+ static CustomButton* AsCustomButton(View* view);
+
+ // Paint an MD-style focus ring on the given canvas at the given bounds.
+ static void PaintMdFocusRing(gfx::Canvas* canvas, View* view);
~CustomButton() override;
@@ -75,11 +75,18 @@ class VIEWS_EXPORT CustomButton : public Button,
notify_action_ = notify_action;
}
+ void set_hide_ink_drop_when_showing_context_menu(
+ bool hide_ink_drop_when_showing_context_menu) {
+ hide_ink_drop_when_showing_context_menu_ =
+ hide_ink_drop_when_showing_context_menu;
+ }
+
+ void set_ink_drop_base_color(SkColor color) { ink_drop_base_color_ = color; }
+
void SetHotTracked(bool is_hot_tracked);
bool IsHotTracked() const;
// Overridden from View:
- void Layout() override;
void OnEnabledChanged() override;
const char* GetClassName() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
@@ -93,19 +100,26 @@ class VIEWS_EXPORT CustomButton : public Button,
bool OnKeyReleased(const ui::KeyEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
+ bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
void ShowContextMenu(const gfx::Point& p,
ui::MenuSourceType source_type) override;
void OnDragDone() override;
void GetAccessibleState(ui::AXViewState* state) override;
void VisibilityChanged(View* starting_from, bool is_visible) override;
+ scoped_ptr<InkDropHover> CreateInkDropHover() const override;
+ SkColor GetInkDropBaseColor() const override;
// Overridden from gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
- // Overridden from views::InkDropHost:
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
- gfx::Point CalculateInkDropCenter() const override;
+ InkDropDelegate* ink_drop_delegate() const { return ink_drop_delegate_; }
+
+ // Overridden from View:
+ void Layout() override;
+ void ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) override;
+ void OnFocus() override;
+ void OnBlur() override;
protected:
// Construct the Button with a Listener. See comment for Button's ctor.
@@ -126,6 +140,9 @@ class VIEWS_EXPORT CustomButton : public Button,
// we simply return IsTriggerableEvent(event).
virtual bool ShouldEnterPushedState(const ui::Event& event);
+ // Returns true if hover effect should be visible.
+ virtual bool ShouldShowInkDropHover() const;
+
void set_has_ink_drop_action_on_click(bool has_ink_drop_action_on_click) {
has_ink_drop_action_on_click_ = has_ink_drop_action_on_click;
}
@@ -136,16 +153,12 @@ class VIEWS_EXPORT CustomButton : public Button,
// state). This does not take into account enabled state.
bool ShouldEnterHoveredState();
- InkDropDelegate* ink_drop_delegate() const { return ink_drop_delegate_; }
void set_ink_drop_delegate(InkDropDelegate* ink_drop_delegate) {
ink_drop_delegate_ = ink_drop_delegate;
}
- // Overridden from View:
- void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
- void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) override;
- void OnBlur() override;
+ // When called, creates and uses |md_focus_ring_| instead of a focus painter.
+ void UseMdFocusRing();
// Overridden from Button:
void NotifyClick(const ui::Event& event) override;
@@ -189,6 +202,18 @@ class VIEWS_EXPORT CustomButton : public Button,
// is clicked.
InkDropState ink_drop_action_on_click_;
+ // When true, the ink drop ripple and hover will be hidden prior to showing
+ // the context menu.
+ bool hide_ink_drop_when_showing_context_menu_;
+
+ // The color of the ripple and hover.
+ SkColor ink_drop_base_color_;
+
+ // The MD-style focus ring. This is not done via a FocusPainter
+ // because it needs to paint to a layer so it can extend beyond the bounds of
+ // |this|.
+ views::View* md_focus_ring_;
+
DISALLOW_COPY_AND_ASSIGN(CustomButton);
};
diff --git a/chromium/ui/views/controls/button/custom_button_unittest.cc b/chromium/ui/views/controls/button/custom_button_unittest.cc
index 134f7f8db61..bd34cb036c4 100644
--- a/chromium/ui/views/controls/button/custom_button_unittest.cc
+++ b/chromium/ui/views/controls/button/custom_button_unittest.cc
@@ -8,11 +8,15 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/layout.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/screen.h"
#include "ui/views/animation/ink_drop_delegate.h"
#include "ui/views/animation/ink_drop_host.h"
+#include "ui/views/animation/test/test_ink_drop_delegate.h"
+#include "ui/views/animation/test/test_ink_drop_host.h"
+#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h"
@@ -30,8 +34,25 @@
namespace views {
+using test::TestInkDropDelegate;
+
namespace {
+// No-op test double of a ContextMenuController.
+class TestContextMenuController : public ContextMenuController {
+ public:
+ TestContextMenuController() {}
+ ~TestContextMenuController() override {}
+
+ // ContextMenuController:
+ void ShowContextMenuForView(View* source,
+ const gfx::Point& point,
+ ui::MenuSourceType source_type) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
+};
+
class TestCustomButton : public CustomButton, public ButtonListener {
public:
explicit TestCustomButton()
@@ -64,71 +85,58 @@ class TestCustomButton : public CustomButton, public ButtonListener {
};
// An InkDropDelegate that keeps track of ink drop visibility.
-class TestInkDropDelegate : public InkDropDelegate {
+class TestInkDropDelegateThatTracksVisibilty : public InkDropDelegate {
public:
- TestInkDropDelegate(InkDropHost* ink_drop_host,
- bool* ink_shown,
- bool* ink_hidden)
- : ink_drop_host_(ink_drop_host),
- ink_shown_(ink_shown),
- ink_hidden_(ink_hidden) {
- ink_drop_host_->AddInkDropLayer(nullptr);
- }
- ~TestInkDropDelegate() override {}
+ TestInkDropDelegateThatTracksVisibilty(bool* ink_shown, bool* ink_hidden)
+ : ink_shown_(ink_shown), ink_hidden_(ink_hidden) {}
+ ~TestInkDropDelegateThatTracksVisibilty() override {}
// InkDropDelegate:
- void SetInkDropSize(int large_size,
- int large_corner_radius,
- int small_size,
- int small_corner_radius) override {}
- void OnLayout() override {}
void OnAction(InkDropState state) override {
switch (state) {
case InkDropState::ACTION_PENDING:
- case InkDropState::SLOW_ACTION_PENDING:
+ case InkDropState::ALTERNATE_ACTION_PENDING:
case InkDropState::ACTIVATED:
*ink_shown_ = true;
break;
case InkDropState::HIDDEN:
*ink_hidden_ = true;
break;
- case InkDropState::QUICK_ACTION:
- case InkDropState::SLOW_ACTION:
+ case InkDropState::ACTION_TRIGGERED:
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
case InkDropState::DEACTIVATED:
break;
}
}
+ void SnapToActivated() override { *ink_shown_ = true; }
+
+ void SetHovered(bool is_hovered) override {}
+
private:
- InkDropHost* ink_drop_host_;
bool* ink_shown_;
bool* ink_hidden_;
- DISALLOW_COPY_AND_ASSIGN(TestInkDropDelegate);
+ DISALLOW_COPY_AND_ASSIGN(TestInkDropDelegateThatTracksVisibilty);
};
// A test Button class that owns a TestInkDropDelegate.
class TestButtonWithInkDrop : public TestCustomButton {
public:
- TestButtonWithInkDrop(bool* ink_shown, bool* ink_hidden)
- : TestCustomButton(),
- ink_drop_delegate_(
- new TestInkDropDelegate(this, ink_shown, ink_hidden)) {
+ TestButtonWithInkDrop(scoped_ptr<InkDropDelegate> ink_drop_delegate)
+ : TestCustomButton(), ink_drop_delegate_(std::move(ink_drop_delegate)) {
set_ink_drop_delegate(ink_drop_delegate_.get());
}
~TestButtonWithInkDrop() override {}
- // views::InkDropHost:
- void AddInkDropLayer(ui::Layer* ink_drop_layer) override {}
- void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override {}
- gfx::Point CalculateInkDropCenter() const override { return gfx::Point(); }
-
private:
scoped_ptr<views::InkDropDelegate> ink_drop_delegate_;
DISALLOW_COPY_AND_ASSIGN(TestButtonWithInkDrop);
};
+} // namespace
+
class CustomButtonTest : public ViewsTestBase {
public:
CustomButtonTest() {}
@@ -155,42 +163,34 @@ class CustomButtonTest : public ViewsTestBase {
ViewsTestBase::TearDown();
}
- void CreateButtonWithInkDrop() {
+ void CreateButtonWithInkDrop(scoped_ptr<InkDropDelegate> ink_drop_delegate) {
delete button_;
- ink_shown_ = false;
- ink_hidden_ = false;
- button_ = new TestButtonWithInkDrop(&ink_shown_, &ink_hidden_);
+ button_ = new TestButtonWithInkDrop(std::move(ink_drop_delegate));
widget_->SetContentsView(button_);
}
protected:
Widget* widget() { return widget_.get(); }
TestCustomButton* button() { return button_; }
- bool ink_shown() const { return ink_shown_; }
- bool ink_hidden() const { return ink_hidden_; }
+ void SetDraggedView(View* dragged_view) {
+ widget_->dragged_view_ = dragged_view;
+ }
private:
scoped_ptr<Widget> widget_;
TestCustomButton* button_;
- bool ink_shown_ = false;
- bool ink_hidden_ = false;
DISALLOW_COPY_AND_ASSIGN(CustomButtonTest);
};
-} // namespace
-
// Tests that hover state changes correctly when visiblity/enableness changes.
TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
- gfx::Point center(10, 10);
- button()->OnMousePressed(ui::MouseEvent(
- ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
- ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
+
+ generator.PressLeftButton();
EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
- button()->OnMouseReleased(ui::MouseEvent(
- ui::ET_MOUSE_RELEASED, center, center, ui::EventTimeForNow(),
- ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
+ generator.ReleaseLeftButton();
EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
button()->SetEnabled(false);
@@ -372,7 +372,7 @@ TEST_F(CustomButtonTest, AsCustomButton) {
RadioButton radio_button(text, 0);
EXPECT_TRUE(CustomButton::AsCustomButton(&radio_button));
- MenuButton menu_button(NULL, text, NULL, false);
+ MenuButton menu_button(text, NULL, false);
EXPECT_TRUE(CustomButton::AsCustomButton(&menu_button));
Label label;
@@ -390,35 +390,93 @@ TEST_F(CustomButtonTest, AsCustomButton) {
// Note: Ink drop is not hidden upon release because CustomButton descendants
// may enter a different ink drop state.
TEST_F(CustomButtonTest, ButtonClickTogglesInkDrop) {
- gfx::Point old_cursor = gfx::Screen::GetScreenFor(
- widget()->GetNativeView())->GetCursorScreenPoint();
- CreateButtonWithInkDrop();
+ gfx::Point old_cursor = gfx::Screen::GetScreen()->GetCursorScreenPoint();
+ bool ink_shown = false;
+ bool ink_hidden = false;
+ CreateButtonWithInkDrop(make_scoped_ptr(
+ new TestInkDropDelegateThatTracksVisibilty(&ink_shown, &ink_hidden)));
ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
generator.set_current_location(gfx::Point(50, 50));
generator.PressLeftButton();
- EXPECT_TRUE(ink_shown());
- EXPECT_FALSE(ink_hidden());
+ EXPECT_TRUE(ink_shown);
+ EXPECT_FALSE(ink_hidden);
generator.ReleaseLeftButton();
- EXPECT_FALSE(ink_hidden());
+ EXPECT_FALSE(ink_hidden);
}
// Tests that pressing a button shows and releasing capture hides ink drop.
+// Releasing capture should also reset PRESSED button state to NORMAL.
TEST_F(CustomButtonTest, CaptureLossHidesInkDrop) {
- gfx::Point old_cursor = gfx::Screen::GetScreenFor(
- widget()->GetNativeView())->GetCursorScreenPoint();
- CreateButtonWithInkDrop();
+ gfx::Point old_cursor = gfx::Screen::GetScreen()->GetCursorScreenPoint();
+ bool ink_shown = false;
+ bool ink_hidden = false;
+ CreateButtonWithInkDrop(make_scoped_ptr(
+ new TestInkDropDelegateThatTracksVisibilty(&ink_shown, &ink_hidden)));
ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
generator.set_current_location(gfx::Point(50, 50));
generator.PressLeftButton();
- EXPECT_TRUE(ink_shown());
- EXPECT_FALSE(ink_hidden());
+ EXPECT_TRUE(ink_shown);
+ EXPECT_FALSE(ink_hidden);
+ EXPECT_EQ(Button::ButtonState::STATE_PRESSED, button()->state());
+ SetDraggedView(button());
widget()->SetCapture(button());
widget()->ReleaseCapture();
- EXPECT_TRUE(ink_hidden());
+ SetDraggedView(nullptr);
+ EXPECT_TRUE(ink_hidden);
+ EXPECT_EQ(ui::MaterialDesignController::IsModeMaterial()
+ ? Button::ButtonState::STATE_NORMAL
+ : Button::ButtonState::STATE_PRESSED,
+ button()->state());
+}
+
+TEST_F(CustomButtonTest, HideInkDropWhenShowingContextMenu) {
+ TestInkDropDelegate* ink_drop_delegate = new TestInkDropDelegate();
+ CreateButtonWithInkDrop(make_scoped_ptr(ink_drop_delegate));
+ TestContextMenuController context_menu_controller;
+ button()->set_context_menu_controller(&context_menu_controller);
+ button()->set_hide_ink_drop_when_showing_context_menu(true);
+
+ ink_drop_delegate->SetHovered(true);
+ ink_drop_delegate->OnAction(InkDropState::ACTION_PENDING);
+
+ button()->ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE);
+
+ EXPECT_FALSE(ink_drop_delegate->is_hovered());
+ EXPECT_EQ(InkDropState::HIDDEN, ink_drop_delegate->state());
+}
+
+TEST_F(CustomButtonTest, DontHideInkDropWhenShowingContextMenu) {
+ TestInkDropDelegate* ink_drop_delegate = new TestInkDropDelegate();
+ CreateButtonWithInkDrop(make_scoped_ptr(ink_drop_delegate));
+ TestContextMenuController context_menu_controller;
+ button()->set_context_menu_controller(&context_menu_controller);
+ button()->set_hide_ink_drop_when_showing_context_menu(false);
+
+ ink_drop_delegate->SetHovered(true);
+ ink_drop_delegate->OnAction(InkDropState::ACTION_PENDING);
+
+ button()->ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE);
+
+ EXPECT_TRUE(ink_drop_delegate->is_hovered());
+ EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop_delegate->state());
+}
+
+TEST_F(CustomButtonTest, InkDropAfterTryingToShowContextMenu) {
+ TestInkDropDelegate* ink_drop_delegate = new TestInkDropDelegate();
+ CreateButtonWithInkDrop(make_scoped_ptr(ink_drop_delegate));
+ button()->set_context_menu_controller(nullptr);
+
+ ink_drop_delegate->SetHovered(true);
+ ink_drop_delegate->OnAction(InkDropState::ACTION_PENDING);
+
+ button()->ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE);
+
+ EXPECT_TRUE(ink_drop_delegate->is_hovered());
+ EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop_delegate->state());
}
} // namespace views
diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc
index e9d4f36c92b..a79341914de 100644
--- a/chromium/ui/views/controls/button/image_button.cc
+++ b/chromium/ui/views/controls/button/image_button.cc
@@ -47,9 +47,11 @@ const gfx::ImageSkia& ImageButton::GetImage(ButtonState state) const {
return images_[state];
}
-void ImageButton::SetImage(ButtonState state, const gfx::ImageSkia* image) {
- images_[state] = image ? *image : gfx::ImageSkia();
+void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia* image) {
+ images_[for_state] = image ? *image : gfx::ImageSkia();
PreferredSizeChanged();
+ if (state() == for_state)
+ SchedulePaint();
}
void ImageButton::SetBackground(SkColor color,
@@ -134,13 +136,13 @@ void ImageButton::OnPaint(gfx::Canvas* canvas) {
// ImageButton, protected:
void ImageButton::OnFocus() {
- View::OnFocus();
+ CustomButton::OnFocus();
if (focus_painter_.get())
SchedulePaint();
}
void ImageButton::OnBlur() {
- View::OnBlur();
+ CustomButton::OnBlur();
if (focus_painter_.get())
SchedulePaint();
}
diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc
index 978a5afb6e4..6687b6e03c6 100644
--- a/chromium/ui/views/controls/button/label_button.cc
+++ b/chromium/ui/views/controls/button/label_button.cc
@@ -10,6 +10,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/canvas.h"
@@ -17,6 +18,8 @@
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/animation/flood_fill_ink_drop_animation.h"
+#include "ui/views/animation/ink_drop_hover.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/painter.h"
@@ -51,6 +54,21 @@ const gfx::FontList& GetDefaultBoldFontList() {
return font_list.Get();
}
+// Ink drop container view that does not capture any events.
+class InkDropContainerView : public views::View {
+ public:
+ InkDropContainerView() {}
+
+ // View:
+ bool CanProcessEventsWithinSubtree() const override {
+ // Ensure the container View is found as the EventTarget instead of this.
+ return false;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropContainerView);
+};
+
} // namespace
namespace views {
@@ -64,6 +82,7 @@ LabelButton::LabelButton(ButtonListener* listener, const base::string16& text)
: CustomButton(listener),
image_(new ImageView()),
label_(new Label()),
+ ink_drop_container_(new InkDropContainerView()),
cached_normal_font_list_(GetDefaultNormalFontList()),
cached_bold_font_list_(GetDefaultBoldFontList()),
button_state_images_(),
@@ -75,7 +94,12 @@ LabelButton::LabelButton(ButtonListener* listener, const base::string16& text)
image_label_spacing_(kSpacing),
horizontal_alignment_(gfx::ALIGN_LEFT) {
SetAnimationDuration(kHoverAnimationDurationMs);
- SetText(text);
+ SetTextInternal(text);
+
+ AddChildView(ink_drop_container_);
+ ink_drop_container_->SetPaintToLayer(true);
+ ink_drop_container_->layer()->SetFillsBoundsOpaquely(false);
+ ink_drop_container_->SetVisible(false);
AddChildView(image_);
image_->set_interactive(false);
@@ -108,8 +132,7 @@ const base::string16& LabelButton::GetText() const {
}
void LabelButton::SetText(const base::string16& text) {
- SetAccessibleName(text);
- label_->SetText(text);
+ SetTextInternal(text);
}
void LabelButton::SetTextColor(ButtonState for_state, SkColor color) {
@@ -143,10 +166,7 @@ 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_ ?
+ label_->SetFontList(is_default_ ?
cached_bold_font_list_ : cached_normal_font_list_);
}
@@ -171,22 +191,17 @@ void LabelButton::SetMaxSize(const gfx::Size& max_size) {
}
void LabelButton::SetIsDefault(bool is_default) {
+ DCHECK_EQ(STYLE_BUTTON, style_);
if (is_default == is_default_)
return;
+
is_default_ = is_default;
ui::Accelerator accel(ui::VKEY_RETURN, ui::EF_NONE);
is_default_ ? AddAccelerator(accel) : RemoveAccelerator(accel);
- // STYLE_BUTTON uses bold text to indicate default buttons.
- if (style_ == STYLE_BUTTON) {
- label_->SetFontList(
- is_default ? cached_bold_font_list_ : cached_normal_font_list_);
- // Usually this function is called before |this| is attached to a widget,
- // but in the cases where |this| is already shown, we need to re-layout
- // because font boldness affects the label's size.
- if (GetWidget())
- Layout();
- }
+ label_->SetFontList(
+ is_default ? cached_bold_font_list_ : cached_normal_font_list_);
+ InvalidateLayout();
}
void LabelButton::SetStyle(ButtonStyle style) {
@@ -282,6 +297,8 @@ int LabelButton::GetHeightForWidth(int w) const {
}
void LabelButton::Layout() {
+ ink_drop_container_->SetBoundsRect(GetLocalBounds());
+
// By default, GetChildAreaBounds() ignores the top and bottom border, but we
// want the image to respect it.
gfx::Rect child_area(GetChildAreaBounds());
@@ -366,13 +383,13 @@ void LabelButton::OnPaint(gfx::Canvas* canvas) {
}
void LabelButton::OnFocus() {
- View::OnFocus();
+ CustomButton::OnFocus();
// Typically the border renders differently when focused.
SchedulePaint();
}
void LabelButton::OnBlur() {
- View::OnBlur();
+ CustomButton::OnBlur();
// Typically the border renders differently when focused.
SchedulePaint();
}
@@ -384,6 +401,44 @@ void LabelButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
InvalidateLayout();
}
+void LabelButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+ image()->SetPaintToLayer(true);
+ image()->layer()->SetFillsBoundsOpaquely(false);
+ ink_drop_container_->SetVisible(true);
+ ink_drop_container_->layer()->Add(ink_drop_layer);
+}
+
+void LabelButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ image()->SetPaintToLayer(false);
+ ink_drop_container_->layer()->Remove(ink_drop_layer);
+ ink_drop_container_->SetVisible(false);
+}
+
+scoped_ptr<views::InkDropAnimation> LabelButton::CreateInkDropAnimation()
+ const {
+ return GetText().empty()
+ ? CustomButton::CreateInkDropAnimation()
+ : make_scoped_ptr(new views::FloodFillInkDropAnimation(
+ GetLocalBounds(), GetInkDropCenter(),
+ GetInkDropBaseColor()));
+}
+
+scoped_ptr<views::InkDropHover> LabelButton::CreateInkDropHover() const {
+ if (!ShouldShowInkDropHover())
+ return nullptr;
+ return GetText().empty() ? CustomButton::CreateInkDropHover()
+ : make_scoped_ptr(new views::InkDropHover(
+ size(), kInkDropSmallCornerRadius,
+ GetInkDropCenter(), GetInkDropBaseColor()));
+}
+
+gfx::Point LabelButton::GetInkDropCenter() const {
+ // TODO(bruthig): Make the flood fill ink drops centered on the LocatedEvent
+ // that triggered them.
+ return GetText().empty() ? image()->GetMirroredBounds().CenterPoint()
+ : CustomButton::GetInkDropCenter();
+}
+
void LabelButton::StateChanged() {
const gfx::Size previous_image_size(image_->GetPreferredSize());
UpdateImage();
@@ -468,6 +523,11 @@ void LabelButton::UpdateThemedBorder() {
border_is_themed_border_ = true;
}
+void LabelButton::SetTextInternal(const base::string16& text) {
+ SetAccessibleName(text);
+ label_->SetText(text);
+}
+
void LabelButton::ChildPreferredSizeChanged(View* child) {
ResetCachedPreferredSize();
PreferredSizeChanged();
diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h
index 2d69ac5a4c4..a8f419c96fa 100644
--- a/chromium/ui/views/controls/button/label_button.h
+++ b/chromium/ui/views/controls/button/label_button.h
@@ -18,6 +18,8 @@
namespace views {
+class InkDropAnimation;
+class InkDropHover;
class LabelButtonBorder;
class Painter;
@@ -43,7 +45,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
// Gets or sets the text shown on the button.
const base::string16& GetText() const;
- void SetText(const base::string16& text);
+ virtual void SetText(const base::string16& text);
// Sets the text color shown for the specified button |for_state| to |color|.
void SetTextColor(ButtonState for_state, SkColor color);
@@ -99,6 +101,11 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
void Layout() override;
const char* GetClassName() const override;
void EnableCanvasFlippingForRTLUI(bool flip) override;
+ void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
+ void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
+ scoped_ptr<InkDropAnimation> CreateInkDropAnimation() const override;
+ scoped_ptr<InkDropHover> CreateInkDropHover() const override;
+ gfx::Point GetInkDropCenter() const override;
protected:
ImageView* image() const { return image_; }
@@ -141,6 +148,8 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, FontList);
FRIEND_TEST_ALL_PREFIXES(LabelButtonTest, ButtonStyleIsDefaultSize);
+ void SetTextInternal(const base::string16& text);
+
// View:
void ChildPreferredSizeChanged(View* child) override;
@@ -162,6 +171,11 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
ImageView* image_;
Label* label_;
+ // A separate view is necessary to hold the ink drop layer so that it can
+ // be stacked below |image_| and on top of |label_|, without resorting to
+ // drawing |label_| on a layer (which can mess with subpixel anti-aliasing).
+ View* ink_drop_container_;
+
// The cached font lists in the normal and bold style.
gfx::FontList cached_normal_font_list_;
gfx::FontList cached_bold_font_list_;
diff --git a/chromium/ui/views/controls/button/label_button_border.cc b/chromium/ui/views/controls/button/label_button_border.cc
index ab7140821bf..e8347bb9c79 100644
--- a/chromium/ui/views/controls/button/label_button_border.cc
+++ b/chromium/ui/views/controls/button/label_button_border.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/effects/SkLerpXfermode.h"
+#include "third_party/skia/include/effects/SkArithmeticMode.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/canvas.h"
@@ -69,13 +69,10 @@ gfx::Size LabelButtonBorder::GetMinimumSize() const {
}
LabelButtonAssetBorder::LabelButtonAssetBorder(Button::ButtonStyle style) {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- const gfx::Insets insets(kButtonInsets,
- kButtonInsets,
- kButtonInsets,
- kButtonInsets);
-
set_insets(GetDefaultInsetsForStyle(style));
+
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ const gfx::Insets insets(kButtonInsets);
if (style == Button::STYLE_BUTTON) {
SetPainter(false, Button::STATE_NORMAL,
Painter::CreateImagePainter(
@@ -116,9 +113,9 @@ gfx::Insets LabelButtonAssetBorder::GetDefaultInsetsForStyle(
Button::ButtonStyle style) {
gfx::Insets insets;
if (style == Button::STYLE_BUTTON) {
- insets = gfx::Insets(8, 13, 8, 13);
+ insets = gfx::Insets(8, 13);
} else if (style == Button::STYLE_TEXTBUTTON) {
- insets = gfx::Insets(5, 6, 5, 6);
+ insets = gfx::Insets(5, 6);
} else {
NOTREACHED();
}
@@ -148,9 +145,8 @@ void LabelButtonAssetBorder::Paint(const View& view, gfx::Canvas* canvas) {
PaintHelper(this, canvas, state, rect, extra);
SkPaint paint;
- skia::RefPtr<SkXfermode> sk_lerp_xfer =
- skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue()));
- paint.setXfermode(sk_lerp_xfer.get());
+ double scale = animation->GetCurrentValue();
+ paint.setXfermode(SkArithmeticMode::Make(0.0f, scale, 1.0 - scale, 0.0));
canvas->sk_canvas()->saveLayer(&sk_rect, &paint);
state = native_theme_delegate->GetForegroundThemeState(&extra);
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 ef8f52dc6d8..d5b60451e9f 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -8,10 +8,16 @@
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/material_design/material_design_controller.h"
+#include "ui/base/test/material_design_controller_test_api.h"
+#include "ui/events/test/event_generator.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/text_utils.h"
+#include "ui/views/animation/button_ink_drop_delegate.h"
+#include "ui/views/test/views_test_base.h"
#include "ui/views/test/widget_test.h"
using base::ASCIIToUTF16;
@@ -301,4 +307,115 @@ TEST_F(LabelButtonTest, ButtonStyleIsDefaultSize) {
EXPECT_NE(non_default_size, button->label_->size());
}
+// A ButtonInkDropDelegate that tracks the last hover state requested.
+class TestButtonInkDropDelegate : public ButtonInkDropDelegate {
+ public:
+ TestButtonInkDropDelegate(InkDropHost* ink_drop_host, View* view)
+ : ButtonInkDropDelegate(ink_drop_host, view), is_hovered_(false) {}
+
+ ~TestButtonInkDropDelegate() override {}
+
+ bool is_hovered() const { return is_hovered_; }
+
+ // ButtonInkDropDelegate:
+ void SetHovered(bool is_hovered) override {
+ is_hovered_ = is_hovered;
+ ButtonInkDropDelegate::SetHovered(is_hovered);
+ }
+
+ private:
+ // The last |is_hover| value passed to SetHovered().
+ bool is_hovered_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestButtonInkDropDelegate);
+};
+
+// A generic LabelButton configured with an |InkDropDelegate|.
+class InkDropLabelButton : public LabelButton {
+ public:
+ InkDropLabelButton()
+ : LabelButton(nullptr, base::string16()),
+ test_ink_drop_delegate_(this, this) {
+ set_ink_drop_delegate(&test_ink_drop_delegate_);
+ }
+
+ ~InkDropLabelButton() override {}
+
+ TestButtonInkDropDelegate* test_ink_drop_delegate() {
+ return &test_ink_drop_delegate_;
+ }
+
+ private:
+ TestButtonInkDropDelegate test_ink_drop_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(InkDropLabelButton);
+};
+
+// Test fixture for a LabelButton that has an ink drop configured.
+class InkDropLabelButtonTest : public ViewsTestBase {
+ public:
+ InkDropLabelButtonTest() {}
+
+ // ViewsTestBase:
+ void SetUp() override {
+ ui::test::MaterialDesignControllerTestAPI::SetMode(
+ ui::MaterialDesignController::MATERIAL_NORMAL);
+
+ ViewsTestBase::SetUp();
+
+ // Create a widget so that the CustomButton can query the hover state
+ // correctly.
+ widget_.reset(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 20, 20);
+ widget_->Init(params);
+ widget_->Show();
+
+ button_ = new InkDropLabelButton();
+ widget_->SetContentsView(button_);
+ }
+
+ void TearDown() override {
+ widget_.reset();
+ ViewsTestBase::TearDown();
+ ui::test::MaterialDesignControllerTestAPI::UninitializeMode();
+ }
+
+ protected:
+ // Required to host the test target.
+ scoped_ptr<Widget> widget_;
+
+ // The test target.
+ InkDropLabelButton* button_ = nullptr;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropLabelButtonTest);
+};
+
+TEST_F(InkDropLabelButtonTest, HoverStateAfterMouseEnterAndExitEvents) {
+ ui::test::EventGenerator event_generator(GetContext(),
+ widget_->GetNativeWindow());
+ const gfx::Point out_of_bounds_point(button_->bounds().bottom_right() +
+ gfx::Vector2d(1, 1));
+ const gfx::Point in_bounds_point(button_->bounds().CenterPoint());
+
+ event_generator.MoveMouseTo(out_of_bounds_point);
+ EXPECT_FALSE(button_->test_ink_drop_delegate()->is_hovered());
+
+ event_generator.MoveMouseTo(in_bounds_point);
+ EXPECT_TRUE(button_->test_ink_drop_delegate()->is_hovered());
+
+ event_generator.MoveMouseTo(out_of_bounds_point);
+ EXPECT_FALSE(button_->test_ink_drop_delegate()->is_hovered());
+}
+
+// Verifies the target event handler View is the |LabelButton| and not any of
+// the child Views.
+TEST_F(InkDropLabelButtonTest, TargetEventHandler) {
+ View* target_view = widget_->GetRootView()->GetEventHandlerForPoint(
+ button_->bounds().CenterPoint());
+ EXPECT_EQ(button_, target_view);
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/button/md_text_button.cc b/chromium/ui/views/controls/button/md_text_button.cc
index 4cae74f7dfa..bf0c9bd03dd 100644
--- a/chromium/ui/views/controls/button/md_text_button.cc
+++ b/chromium/ui/views/controls/button/md_text_button.cc
@@ -5,8 +5,12 @@
#include "ui/views/controls/button/md_text_button.h"
#include "base/i18n/case_conversion.h"
-#include "ui/gfx/render_text.h"
+#include "ui/base/material_design/material_design_controller.h"
+#include "ui/gfx/color_utils.h"
#include "ui/native_theme/native_theme.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/painter.h"
namespace views {
@@ -19,47 +23,92 @@ const int kVerticalPadding = 6;
// Minimum size to reserve for the button contents.
const int kMinWidth = 48;
-const gfx::FontList& GetFontList() {
- static base::LazyInstance<gfx::FontList>::Leaky font_list =
- LAZY_INSTANCE_INITIALIZER;
- return font_list.Get();
+} // namespace
+
+// static
+LabelButton* MdTextButton::CreateStandardButton(ButtonListener* listener,
+ const base::string16& text) {
+ if (ui::MaterialDesignController::IsModeMaterial())
+ return CreateMdButton(listener, text);
+
+ LabelButton* button = new LabelButton(listener, text);
+ button->SetStyle(STYLE_BUTTON);
+ return button;
}
-} // namespace
+MdTextButton* MdTextButton::CreateMdButton(ButtonListener* listener,
+ const base::string16& text) {
+ MdTextButton* button = new MdTextButton(listener);
+ button->SetText(text);
+ // TODO(estade): can we get rid of the platform style border hoopla if
+ // we apply the MD treatment to all buttons, even GTK buttons?
+ button->SetBorder(
+ Border::CreateEmptyBorder(kVerticalPadding, kHorizontalPadding,
+ kVerticalPadding, kHorizontalPadding));
+ return button;
+}
-MdTextButton::MdTextButton(ButtonListener* listener, const base::string16& text)
- : CustomButton(listener),
- render_text_(gfx::RenderText::CreateInstance()) {
- render_text_->SetFontList(GetFontList());
- render_text_->SetCursorEnabled(false);
- render_text_->SetText(base::i18n::ToUpper(text));
+void MdTextButton::SetCallToAction(CallToAction cta) {
+ if (cta_ == cta)
+ return;
- SetFocusable(true);
+ cta_ = cta;
+ UpdateColorsFromNativeTheme();
}
-MdTextButton::~MdTextButton() {}
+void MdTextButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
+ LabelButton::OnNativeThemeChanged(theme);
+ UpdateColorsFromNativeTheme();
+}
+
+SkColor MdTextButton::GetInkDropBaseColor() const {
+ return color_utils::DeriveDefaultIconColor(label()->enabled_color());
+}
-void MdTextButton::OnPaint(gfx::Canvas* canvas) {
- UpdateColor();
- gfx::Rect rect = GetLocalBounds();
- rect.Inset(kHorizontalPadding, kVerticalPadding);
- render_text_->SetDisplayRect(rect);
- render_text_->Draw(canvas);
+void MdTextButton::SetText(const base::string16& text) {
+ LabelButton::SetText(base::i18n::ToUpper(text));
}
-gfx::Size MdTextButton::GetPreferredSize() const {
- gfx::Size size = render_text_->GetStringSize();
- size.SetToMax(gfx::Size(kMinWidth, 0));
- size.Enlarge(kHorizontalPadding * 2, kVerticalPadding * 2);
- return size;
+MdTextButton::MdTextButton(ButtonListener* listener)
+ : LabelButton(listener, base::string16()),
+ ink_drop_delegate_(this, this),
+ cta_(NO_CALL_TO_ACTION) {
+ set_ink_drop_delegate(&ink_drop_delegate_);
+ set_has_ink_drop_action_on_click(true);
+ SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ SetFocusable(true);
+ SetMinSize(gfx::Size(kMinWidth, 0));
+ SetFocusPainter(nullptr);
+ UseMdFocusRing();
+ label()->SetAutoColorReadabilityEnabled(false);
}
-void MdTextButton::UpdateColor() {
- // TODO(estade): handle call to action theming and other things that can
- // affect the text color.
- render_text_->SetColor(GetNativeTheme()->GetSystemColor(
- enabled() ? ui::NativeTheme::kColorId_MdTextButtonEnabledColor
- : ui::NativeTheme::kColorId_MdTextButtonDisabledColor));
+MdTextButton::~MdTextButton() {}
+
+void MdTextButton::UpdateColorsFromNativeTheme() {
+ ui::NativeTheme::ColorId fg_color_id = ui::NativeTheme::kColorId_NumColors;
+ switch (cta_) {
+ case NO_CALL_TO_ACTION:
+ fg_color_id = ui::NativeTheme::kColorId_ButtonEnabledColor;
+ break;
+ case WEAK_CALL_TO_ACTION:
+ fg_color_id = ui::NativeTheme::kColorId_CallToActionColor;
+ break;
+ case STRONG_CALL_TO_ACTION:
+ fg_color_id = ui::NativeTheme::kColorId_TextOnCallToActionColor;
+ break;
+ }
+ ui::NativeTheme* theme = GetNativeTheme();
+ SetEnabledTextColors(theme->GetSystemColor(fg_color_id));
+
+ set_background(
+ cta_ == STRONG_CALL_TO_ACTION
+ ? Background::CreateBackgroundPainter(
+ true, Painter::CreateSolidRoundRectPainter(
+ theme->GetSystemColor(
+ ui::NativeTheme::kColorId_CallToActionColor),
+ kInkDropSmallCornerRadius))
+ : nullptr);
}
} // namespace views
diff --git a/chromium/ui/views/controls/button/md_text_button.h b/chromium/ui/views/controls/button/md_text_button.h
index ba982a32a93..8350dac7c68 100644
--- a/chromium/ui/views/controls/button/md_text_button.h
+++ b/chromium/ui/views/controls/button/md_text_button.h
@@ -6,28 +6,46 @@
#define UI_VIEWS_CONTROLS_BUTTON_MD_TEXT_BUTTON_H_
#include "base/memory/scoped_ptr.h"
-#include "ui/views/controls/button/custom_button.h"
-
-namespace gfx {
-class RenderText;
-}
+#include "ui/views/animation/button_ink_drop_delegate.h"
+#include "ui/views/controls/button/label_button.h"
namespace views {
// A button class that implements the Material Design text button spec.
-class VIEWS_EXPORT MdTextButton : public CustomButton {
+class VIEWS_EXPORT MdTextButton : public LabelButton {
public:
- MdTextButton(ButtonListener* listener, const base::string16& text);
+ // Describes the presentation of a button. A stronger call to action draws
+ // more attention.
+ enum CallToAction {
+ NO_CALL_TO_ACTION, // Default.
+ WEAK_CALL_TO_ACTION,
+ STRONG_CALL_TO_ACTION,
+ };
+
+ // Creates a normal STYLE_BUTTON LabelButton in pre-MD, or an MdTextButton
+ // in MD mode.
+ static LabelButton* CreateStandardButton(ButtonListener* listener,
+ const base::string16& text);
+ static MdTextButton* CreateMdButton(ButtonListener* listener,
+ const base::string16& text);
+
+ void SetCallToAction(CallToAction cta);
+
+ // LabelButton:
+ void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
+ SkColor GetInkDropBaseColor() const override;
+ void SetText(const base::string16& text) override;
+
+ private:
+ MdTextButton(ButtonListener* listener);
~MdTextButton() override;
- // View:
- void OnPaint(gfx::Canvas* canvas) override;
- gfx::Size GetPreferredSize() const override;
+ void UpdateColorsFromNativeTheme();
- private:
- void UpdateColor();
+ ButtonInkDropDelegate ink_drop_delegate_;
- scoped_ptr<gfx::RenderText> render_text_;
+ // The call to action style for this button.
+ CallToAction cta_;
DISALLOW_COPY_AND_ASSIGN(MdTextButton);
};
diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc
index c7a53389a14..4d1a1b97281 100644
--- a/chromium/ui/views/controls/button/menu_button.cc
+++ b/chromium/ui/views/controls/button/menu_button.cc
@@ -47,8 +47,12 @@ const int MenuButton::kMenuMarkerPaddingRight = -1;
////////////////////////////////////////////////////////////////////////////////
MenuButton::PressedLock::PressedLock(MenuButton* menu_button)
+ : PressedLock(menu_button, false) {}
+
+MenuButton::PressedLock::PressedLock(MenuButton* menu_button,
+ bool is_sibling_menu_show)
: menu_button_(menu_button->weak_factory_.GetWeakPtr()) {
- menu_button_->IncrementPressedLocked();
+ menu_button_->IncrementPressedLocked(is_sibling_menu_show);
}
MenuButton::PressedLock::~PressedLock() {
@@ -62,18 +66,19 @@ MenuButton::PressedLock::~PressedLock() {
//
////////////////////////////////////////////////////////////////////////////////
-MenuButton::MenuButton(ButtonListener* listener,
- const base::string16& text,
+MenuButton::MenuButton(const base::string16& text,
MenuButtonListener* menu_button_listener,
bool show_menu_marker)
- : LabelButton(listener, text),
+ : LabelButton(nullptr, text),
menu_offset_(kDefaultMenuOffsetX, kDefaultMenuOffsetY),
listener_(menu_button_listener),
show_menu_marker_(show_menu_marker),
- menu_marker_(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- IDR_MENU_DROPARROW).ToImageSkia()),
- destroyed_flag_(NULL),
+ menu_marker_(ui::ResourceBundle::GetSharedInstance()
+ .GetImageNamed(IDR_MENU_DROPARROW)
+ .ToImageSkia()),
+ destroyed_flag_(nullptr),
pressed_lock_count_(0),
+ increment_pressed_lock_called_(nullptr),
should_disable_after_press_(false),
weak_factory_(this) {
SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -90,7 +95,7 @@ MenuButton::~MenuButton() {
//
////////////////////////////////////////////////////////////////////////////////
-bool MenuButton::Activate() {
+bool MenuButton::Activate(const ui::Event* event) {
if (listener_) {
gfx::Rect lb = GetLocalBounds();
@@ -117,36 +122,67 @@ bool MenuButton::Activate() {
// matter where the user pressed. To force RootView to recalculate the
// mouse target during the mouse press we explicitly set the mouse handler
// to NULL.
- static_cast<internal::RootView*>(GetWidget()->GetRootView())->
- SetMouseHandler(NULL);
+ static_cast<internal::RootView*>(GetWidget()->GetRootView())
+ ->SetMouseHandler(nullptr);
bool destroyed = false;
destroyed_flag_ = &destroyed;
+ DCHECK(increment_pressed_lock_called_ == nullptr);
+ // Observe if IncrementPressedLocked() was called so we can trigger the
+ // correct ink drop animations.
+ bool increment_pressed_lock_called = false;
+ increment_pressed_lock_called_ = &increment_pressed_lock_called;
+
// We don't set our state here. It's handled in the MenuController code or
// by our click listener.
-
- if (ink_drop_delegate())
- ink_drop_delegate()->OnAction(InkDropState::QUICK_ACTION);
- listener_->OnMenuButtonClicked(this, menu_position);
+ listener_->OnMenuButtonClicked(this, menu_position, event);
if (destroyed) {
// The menu was deleted while showing. Don't attempt any processing.
return false;
}
- destroyed_flag_ = NULL;
+ increment_pressed_lock_called_ = nullptr;
+ destroyed_flag_ = nullptr;
menu_closed_time_ = TimeTicks::Now();
+ if (ink_drop_delegate() && !increment_pressed_lock_called &&
+ pressed_lock_count_ == 0) {
+ ink_drop_delegate()->OnAction(InkDropState::ACTION_TRIGGERED);
+ }
+
// We must return false here so that the RootView does not get stuck
// sending all mouse pressed events to us instead of the appropriate
// target.
return false;
}
+
+ if (ink_drop_delegate())
+ ink_drop_delegate()->OnAction(InkDropState::HIDDEN);
return true;
}
+bool MenuButton::IsTriggerableEventType(const ui::Event& event) {
+ if (event.IsMouseEvent()) {
+ const ui::MouseEvent& mouseev = static_cast<const ui::MouseEvent&>(event);
+ // Active on left mouse button only, to prevent a menu from being activated
+ // when a right-click would also activate a context menu.
+ if (!mouseev.IsOnlyLeftMouseButton())
+ return false;
+ // If dragging is supported activate on release, otherwise activate on
+ // pressed.
+ ui::EventType active_on =
+ GetDragOperations(mouseev.location()) == ui::DragDropTypes::DRAG_NONE
+ ? ui::ET_MOUSE_PRESSED
+ : ui::ET_MOUSE_RELEASED;
+ return event.type() == active_on;
+ }
+
+ return event.type() == ui::ET_GESTURE_TAP;
+}
+
void MenuButton::OnPaint(gfx::Canvas* canvas) {
LabelButton::OnPaint(canvas);
@@ -177,21 +213,18 @@ const char* MenuButton::GetClassName() const {
bool MenuButton::OnMousePressed(const ui::MouseEvent& event) {
if (request_focus_on_press())
RequestFocus();
- if (state() != STATE_DISABLED && ShouldEnterPushedState(event) &&
- HitTestPoint(event.location())) {
- TimeDelta delta = TimeTicks::Now() - menu_closed_time_;
- if (delta.InMilliseconds() > kMinimumMsBetweenButtonClicks)
- return Activate();
- if (ink_drop_delegate())
- ink_drop_delegate()->OnAction(InkDropState::ACTION_PENDING);
+ if (state() != STATE_DISABLED && HitTestPoint(event.location()) &&
+ IsTriggerableEventType(event)) {
+ if (IsTriggerableEvent(event))
+ return Activate(&event);
}
return true;
}
void MenuButton::OnMouseReleased(const ui::MouseEvent& event) {
- if (state() != STATE_DISABLED && ShouldEnterPushedState(event) &&
+ if (state() != STATE_DISABLED && IsTriggerableEvent(event) &&
HitTestPoint(event.location()) && !InDrag()) {
- Activate();
+ Activate(&event);
} else {
if (ink_drop_delegate())
ink_drop_delegate()->OnAction(InkDropState::HIDDEN);
@@ -216,7 +249,7 @@ void MenuButton::OnMouseMoved(const ui::MouseEvent& event) {
void MenuButton::OnGestureEvent(ui::GestureEvent* event) {
if (state() != STATE_DISABLED) {
- if (ShouldEnterPushedState(*event) && !Activate()) {
+ if (IsTriggerableEvent(*event) && !Activate(event)) {
// When |Activate()| returns |false|, it means the click was handled by
// a button listener and has handled the gesture event. So, there is no
// need to further process the gesture event here. However, if the
@@ -251,7 +284,7 @@ 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.
- Activate();
+ Activate(&event);
// 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
@@ -271,13 +304,6 @@ bool MenuButton::OnKeyReleased(const ui::KeyEvent& event) {
return false;
}
-bool MenuButton::AcceleratorPressed(const ui::Accelerator& accelerator) {
- // CustomButton::AcceleratorPressed ends up in NotifyClick, which doesn't work
- // for menu buttons.
- Activate();
- return true;
-}
-
void MenuButton::GetAccessibleState(ui::AXViewState* state) {
CustomButton::GetAccessibleState(state);
state->role = ui::AX_ROLE_POP_UP_BUTTON;
@@ -310,23 +336,19 @@ gfx::Rect MenuButton::GetChildAreaBounds() {
return gfx::Rect(s);
}
-bool MenuButton::ShouldEnterPushedState(const ui::Event& event) {
- if (event.IsMouseEvent()) {
- const ui::MouseEvent& mouseev = static_cast<const ui::MouseEvent&>(event);
- // Active on left mouse button only, to prevent a menu from being activated
- // when a right-click would also activate a context menu.
- if (!mouseev.IsOnlyLeftMouseButton())
- return false;
- // If dragging is supported activate on release, otherwise activate on
- // pressed.
- ui::EventType active_on =
- GetDragOperations(mouseev.location()) == ui::DragDropTypes::DRAG_NONE
- ? ui::ET_MOUSE_PRESSED
- : ui::ET_MOUSE_RELEASED;
- return event.type() == active_on;
- }
+bool MenuButton::IsTriggerableEvent(const ui::Event& event) {
+ if (!IsTriggerableEventType(event))
+ return false;
- return event.type() == ui::ET_GESTURE_TAP;
+ TimeDelta delta = TimeTicks::Now() - menu_closed_time_;
+ if (delta.InMilliseconds() < kMinimumMsBetweenButtonClicks)
+ return false; // Not enough time since the menu closed.
+
+ return true;
+}
+
+bool MenuButton::ShouldEnterPushedState(const ui::Event& event) {
+ return IsTriggerableEventType(event);
}
void MenuButton::StateChanged() {
@@ -344,9 +366,23 @@ void MenuButton::StateChanged() {
}
}
-void MenuButton::IncrementPressedLocked() {
+void MenuButton::NotifyClick(const ui::Event& event) {
+ // We don't forward events to the normal button listener, instead using the
+ // MenuButtonListener.
+ Activate(&event);
+}
+
+void MenuButton::IncrementPressedLocked(bool snap_ink_drop_to_activated) {
++pressed_lock_count_;
+ if (increment_pressed_lock_called_)
+ *increment_pressed_lock_called_ = true;
should_disable_after_press_ = state() == STATE_DISABLED;
+ if (state() != STATE_PRESSED && ink_drop_delegate()) {
+ if (snap_ink_drop_to_activated)
+ ink_drop_delegate()->SnapToActivated();
+ else
+ ink_drop_delegate()->OnAction(InkDropState::ACTIVATED);
+ }
SetState(STATE_PRESSED);
}
@@ -364,6 +400,8 @@ void MenuButton::DecrementPressedLocked() {
desired_state = STATE_HOVERED;
}
SetState(desired_state);
+ if (ink_drop_delegate() && state() != STATE_PRESSED)
+ ink_drop_delegate()->OnAction(InkDropState::DEACTIVATED);
}
}
diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h
index 94c209b96eb..696a94146f3 100644
--- a/chromium/ui/views/controls/button/menu_button.h
+++ b/chromium/ui/views/controls/button/menu_button.h
@@ -32,6 +32,7 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
class VIEWS_EXPORT PressedLock {
public:
explicit PressedLock(MenuButton* menu_button);
+ PressedLock(MenuButton* menu_button, bool is_sibling_menu_show);
~PressedLock();
private:
@@ -47,8 +48,7 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
static const int kMenuMarkerPaddingRight;
// Create a Button.
- MenuButton(ButtonListener* listener,
- const base::string16& text,
+ MenuButton(const base::string16& text,
MenuButtonListener* menu_button_listener,
bool show_menu_marker);
~MenuButton() override;
@@ -62,8 +62,15 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
const gfx::Point& menu_offset() const { return menu_offset_; }
void set_menu_offset(int x, int y) { menu_offset_.SetPoint(x, y); }
- // Activate the button (called when the button is pressed).
- bool Activate();
+ // Activate the button (called when the button is pressed). |event| is the
+ // event triggering the activation, if any.
+ bool Activate(const ui::Event* event);
+
+ // Returns true if the event is of the proper type to potentially trigger an
+ // action. Since MenuButtons have properties other than event type (like
+ // last menu open time) to determine if an event is valid to activate the
+ // menu, this is distinct from IsTriggerableEvent().
+ virtual bool IsTriggerableEventType(const ui::Event& event);
// Overridden from View:
gfx::Size GetPreferredSize() const override;
@@ -77,7 +84,6 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
void OnGestureEvent(ui::GestureEvent* event) override;
bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnKeyReleased(const ui::KeyEvent& event) override;
- bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
void GetAccessibleState(ui::AXViewState* state) override;
protected:
@@ -88,8 +94,10 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
gfx::Rect GetChildAreaBounds() override;
// Overridden from CustomButton:
+ bool IsTriggerableEvent(const ui::Event& event) override;
bool ShouldEnterPushedState(const ui::Event& event) override;
void StateChanged() override;
+ void NotifyClick(const ui::Event& event) override;
// Offset of the associated menu position.
gfx::Point menu_offset_;
@@ -98,8 +106,10 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
friend class PressedLock;
// Increment/decrement the number of "pressed" locks this button has, and
- // set the state accordingly.
- void IncrementPressedLocked();
+ // set the state accordingly. The ink drop is snapped to the final ACTIVATED
+ // state if |snap_ink_drop_to_activated| is true, otherwise the ink drop will
+ // be animated to the ACTIVATED state.
+ void IncrementPressedLocked(bool snap_ink_drop_to_activated);
void DecrementPressedLocked();
// Compute the maximum X coordinate for the current screen. MenuButtons
@@ -130,6 +140,9 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
// The current number of "pressed" locks this button has.
int pressed_lock_count_;
+ // Used to let Activate() know if IncrementPressedLocked() was called.
+ bool* increment_pressed_lock_called_;
+
// True if the button was in a disabled state when a menu was run, and should
// return to it once the press is complete. This can happen if, e.g., we
// programmatically show a menu on a disabled button.
diff --git a/chromium/ui/views/controls/button/menu_button_listener.h b/chromium/ui/views/controls/button/menu_button_listener.h
index 5a20697cffb..d344bb0cf3b 100644
--- a/chromium/ui/views/controls/button/menu_button_listener.h
+++ b/chromium/ui/views/controls/button/menu_button_listener.h
@@ -11,15 +11,24 @@ namespace gfx {
class Point;
}
-namespace views {
+namespace ui {
+class Event;
+}
-class View;
+namespace views {
+class MenuButton;
// An interface implemented by an object to let it know that a menu button was
// clicked.
class VIEWS_EXPORT MenuButtonListener {
public:
- virtual void OnMenuButtonClicked(View* source, const gfx::Point& point) = 0;
+ // Notifies that the MenuButton has been clicked. |point| is the default
+ // point to display the menu, and |event| is the event causing the click, if
+ // any. (Note: "Clicked" refers to any activation, including e.g. accelerators
+ // and key events).
+ virtual void OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) = 0;
protected:
virtual ~MenuButtonListener() {}
diff --git a/chromium/ui/views/controls/button/menu_button_unittest.cc b/chromium/ui/views/controls/button/menu_button_unittest.cc
index 8d554c9e5f7..fdfc4d0a9b4 100644
--- a/chromium/ui/views/controls/button/menu_button_unittest.cc
+++ b/chromium/ui/views/controls/button/menu_button_unittest.cc
@@ -10,6 +10,7 @@
#include "build/build_config.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/events/test/event_generator.h"
+#include "ui/views/animation/test/test_ink_drop_delegate.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/drag_controller.h"
#include "ui/views/test/views_test_base.h"
@@ -23,6 +24,28 @@
using base::ASCIIToUTF16;
namespace views {
+class InkDropDelegate;
+
+namespace test {
+
+// A MenuButton subclass that provides access to some MenuButton internals.
+class TestMenuButton : public MenuButton {
+ public:
+ explicit TestMenuButton(MenuButtonListener* menu_button_listener)
+ : MenuButton(base::string16(ASCIIToUTF16("button")),
+ menu_button_listener,
+ false) {}
+
+ ~TestMenuButton() override {}
+
+ // Accessors to protected MenuButton methods.
+ void set_ink_drop_delegate(InkDropDelegate* ink_drop_delegate) {
+ MenuButton::set_ink_drop_delegate(ink_drop_delegate);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestMenuButton);
+};
class MenuButtonTest : public ViewsTestBase {
public:
@@ -30,6 +53,7 @@ class MenuButtonTest : public ViewsTestBase {
~MenuButtonTest() override {}
void TearDown() override {
+ generator_.reset();
if (widget_ && !widget_->IsClosed())
widget_->Close();
@@ -37,34 +61,31 @@ class MenuButtonTest : public ViewsTestBase {
}
Widget* widget() { return widget_; }
- MenuButton* button() { return button_; }
+ TestMenuButton* button() { return button_; }
+ ui::test::EventGenerator* generator() { return generator_.get(); }
protected:
// Creates a MenuButton with no button listener.
- void CreateMenuButtonWithNoListener() { CreateMenuButton(nullptr, nullptr); }
-
- // Creates a MenuButton with a ButtonListener. In this case, the MenuButton
- // acts like a regular button.
- void CreateMenuButtonWithButtonListener(ButtonListener* button_listener) {
- CreateMenuButton(button_listener, nullptr);
- }
+ void CreateMenuButtonWithNoListener() { CreateMenuButton(nullptr); }
// 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) {
- CreateMenuButton(nullptr, menu_button_listener);
+ CreateMenuButton(menu_button_listener);
}
private:
- void CreateMenuButton(ButtonListener* button_listener,
- MenuButtonListener* menu_button_listener) {
+ void CreateMenuButton(MenuButtonListener* menu_button_listener) {
CreateWidget();
+ generator_.reset(new ui::test::EventGenerator(GetContext(),
+ widget_->GetNativeWindow()));
+ // Set initial mouse location in a consistent way so that the menu button we
+ // are about to create initializes its hover state in a consistent manner.
+ generator_->set_current_location(gfx::Point(10, 10));
- const base::string16 label(ASCIIToUTF16("button"));
- button_ =
- new MenuButton(button_listener, label, menu_button_listener, false);
+ button_ = new TestMenuButton(menu_button_listener);
button_->SetBoundsRect(gfx::Rect(0, 0, 200, 20));
widget_->SetContentsView(button_);
@@ -82,7 +103,10 @@ class MenuButtonTest : public ViewsTestBase {
}
Widget* widget_;
- MenuButton* button_;
+ TestMenuButton* button_;
+ scoped_ptr<ui::test::EventGenerator> generator_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuButtonTest);
};
class TestButtonListener : public ButtonListener {
@@ -119,7 +143,9 @@ class TestMenuButtonListener : public MenuButtonListener {
: last_source_(nullptr), last_source_state_(Button::STATE_NORMAL) {}
~TestMenuButtonListener() override {}
- void OnMenuButtonClicked(View* source, const gfx::Point& /*point*/) override {
+ void OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) override {
last_source_ = source;
CustomButton* custom_button = CustomButton::AsCustomButton(source);
DCHECK(custom_button);
@@ -136,6 +162,36 @@ class TestMenuButtonListener : public MenuButtonListener {
DISALLOW_COPY_AND_ASSIGN(TestMenuButtonListener);
};
+// A MenuButtonListener that will acquire a PressedLock in the
+// OnMenuButtonClicked() method and optionally release it as well.
+class PressStateMenuButtonListener : public MenuButtonListener {
+ public:
+ explicit PressStateMenuButtonListener(bool release_lock)
+ : menu_button_(nullptr), release_lock_(release_lock) {}
+
+ ~PressStateMenuButtonListener() override {}
+
+ void set_menu_button(MenuButton* menu_button) { menu_button_ = menu_button; }
+
+ void OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) override {
+ pressed_lock_.reset(new MenuButton::PressedLock(menu_button_));
+ if (release_lock_)
+ pressed_lock_.reset();
+ }
+
+ private:
+ MenuButton* menu_button_;
+
+ scoped_ptr<MenuButton::PressedLock> pressed_lock_;
+
+ // The |pressed_lock_| will be released when true.
+ bool release_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(PressStateMenuButtonListener);
+};
+
// Basic implementation of a DragController, to test input behaviour for
// MenuButtons that can be dragged.
class TestDragController : public DragController {
@@ -257,7 +313,9 @@ class TestShowSiblingButtonListener : public MenuButtonListener {
TestShowSiblingButtonListener() {}
~TestShowSiblingButtonListener() override {}
- void OnMenuButtonClicked(View* source, const gfx::Point& point) override {
+ void OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) override {
// The MenuButton itself doesn't set the PRESSED state during Activate() or
// OnMenuButtonClicked(). That should be handled by the MenuController or,
// if no menu is shown, the listener.
@@ -268,34 +326,13 @@ class TestShowSiblingButtonListener : public MenuButtonListener {
DISALLOW_COPY_AND_ASSIGN(TestShowSiblingButtonListener);
};
-// Tests if the listener is notified correctly, when a mouse click happens on a
-// MenuButton that has a regular ButtonListener.
-TEST_F(MenuButtonTest, ActivateNonDropDownOnMouseClick) {
- TestButtonListener button_listener;
- CreateMenuButtonWithButtonListener(&button_listener);
-
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
-
- 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 mouse click happens on a
// MenuButton that has a MenuButtonListener.
TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
TestMenuButtonListener menu_button_listener;
CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
-
- generator.set_current_location(gfx::Point(10, 10));
- generator.ClickLeftButton();
+ generator()->ClickLeftButton();
// Check that MenuButton has notified the listener, while it was in pressed
// state.
@@ -304,12 +341,11 @@ TEST_F(MenuButtonTest, ActivateDropDownOnMouseClick) {
}
// Test that the MenuButton stays pressed while there are any PressedLocks.
-TEST_F(MenuButtonTest, MenuButtonPressedLock) {
+TEST_F(MenuButtonTest, ButtonStateForMenuButtonsWithPressedLocks) {
CreateMenuButtonWithNoListener();
// Move the mouse over the button; the button should be in a hovered state.
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
- generator.MoveMouseTo(gfx::Point(10, 10));
+ generator()->MoveMouseTo(gfx::Point(10, 10));
EXPECT_EQ(Button::STATE_HOVERED, button()->state());
// Introduce a PressedLock, which should make the button pressed.
@@ -318,7 +354,7 @@ TEST_F(MenuButtonTest, MenuButtonPressedLock) {
EXPECT_EQ(Button::STATE_PRESSED, button()->state());
// Even if we move the mouse outside of the button, it should remain pressed.
- generator.MoveMouseTo(gfx::Point(300, 10));
+ generator()->MoveMouseTo(gfx::Point(300, 10));
EXPECT_EQ(Button::STATE_PRESSED, button()->state());
// Creating a new lock should obviously keep the button pressed.
@@ -335,7 +371,7 @@ TEST_F(MenuButtonTest, MenuButtonPressedLock) {
EXPECT_EQ(Button::STATE_NORMAL, button()->state());
// ...And it should respond to mouse movement again.
- generator.MoveMouseTo(gfx::Point(10, 10));
+ generator()->MoveMouseTo(gfx::Point(10, 10));
EXPECT_EQ(Button::STATE_HOVERED, button()->state());
// Test that the button returns to the appropriate state after the press; if
@@ -353,7 +389,7 @@ TEST_F(MenuButtonTest, MenuButtonPressedLock) {
pressed_lock1.reset();
EXPECT_EQ(Button::STATE_DISABLED, button()->state());
- generator.MoveMouseTo(gfx::Point(300, 10));
+ generator()->MoveMouseTo(gfx::Point(300, 10));
// Edge case: the button is disabled, a pressed lock is added, and then the
// button is re-enabled. It should be enabled after the lock is removed.
@@ -371,10 +407,9 @@ TEST_F(MenuButtonTest, PressedStateWithSiblingMenu) {
CreateMenuButtonWithMenuButtonListener(&listener);
// Move the mouse over the button; the button should be in a hovered state.
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
- generator.MoveMouseTo(gfx::Point(10, 10));
+ generator()->MoveMouseTo(gfx::Point(10, 10));
EXPECT_EQ(Button::STATE_HOVERED, button()->state());
- generator.ClickLeftButton();
+ generator()->ClickLeftButton();
// Test is continued in TestShowSiblingButtonListener::OnMenuButtonClicked().
}
@@ -386,17 +421,119 @@ TEST_F(MenuButtonTest, DraggableMenuButtonActivatesOnRelease) {
TestDragController drag_controller;
button()->set_drag_controller(&drag_controller);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
-
- generator.set_current_location(gfx::Point(10, 10));
- generator.PressLeftButton();
+ generator()->PressLeftButton();
EXPECT_EQ(nullptr, menu_button_listener.last_source());
- generator.ReleaseLeftButton();
+ generator()->ReleaseLeftButton();
EXPECT_EQ(button(), menu_button_listener.last_source());
EXPECT_EQ(Button::STATE_HOVERED, menu_button_listener.last_source_state());
}
+TEST_F(MenuButtonTest, InkDropStateForMenuButtonActivationsWithoutListener) {
+ CreateMenuButtonWithNoListener();
+ TestInkDropDelegate ink_drop_delegate;
+ ink_drop_delegate.OnAction(InkDropState::ACTION_PENDING);
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+ button()->Activate(nullptr);
+
+ EXPECT_EQ(InkDropState::HIDDEN, ink_drop_delegate.state());
+}
+
+TEST_F(MenuButtonTest,
+ InkDropStateForMenuButtonActivationsWithListenerThatDoesntAcquireALock) {
+ TestMenuButtonListener menu_button_listener;
+ CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+ button()->Activate(nullptr);
+
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, ink_drop_delegate.state());
+}
+
+TEST_F(
+ MenuButtonTest,
+ InkDropStateForMenuButtonActivationsWithListenerThatDontReleaseAllLocks) {
+ PressStateMenuButtonListener menu_button_listener(false);
+ CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
+ menu_button_listener.set_menu_button(button());
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+ button()->Activate(nullptr);
+
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+
+ // Prevent the button from accessing invalid memory during clean up.
+ button()->set_ink_drop_delegate(nullptr);
+}
+
+TEST_F(MenuButtonTest,
+ InkDropStateForMenuButtonActivationsWithListenerThatReleaseAllLocks) {
+ PressStateMenuButtonListener menu_button_listener(true);
+ CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
+ menu_button_listener.set_menu_button(button());
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+ button()->Activate(nullptr);
+
+ EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop_delegate.state());
+}
+
+TEST_F(MenuButtonTest, InkDropStateForMenuButtonsWithPressedLocks) {
+ CreateMenuButtonWithNoListener();
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+
+ scoped_ptr<MenuButton::PressedLock> pressed_lock1(
+ new MenuButton::PressedLock(button()));
+
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+
+ scoped_ptr<MenuButton::PressedLock> pressed_lock2(
+ new MenuButton::PressedLock(button()));
+
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+
+ pressed_lock1.reset();
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+
+ pressed_lock2.reset();
+ EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop_delegate.state());
+}
+
+// Verifies only one ink drop animation is triggered when multiple PressedLocks
+// are attached to a MenuButton.
+TEST_F(MenuButtonTest, OneInkDropAnimationForReentrantPressedLocks) {
+ CreateMenuButtonWithNoListener();
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+
+ scoped_ptr<MenuButton::PressedLock> pressed_lock1(
+ new MenuButton::PressedLock(button()));
+
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+ ink_drop_delegate.OnAction(InkDropState::ACTION_PENDING);
+
+ scoped_ptr<MenuButton::PressedLock> pressed_lock2(
+ new MenuButton::PressedLock(button()));
+
+ EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop_delegate.state());
+}
+
+// Verifies the InkDropState is left as ACTIVATED if a PressedLock is active
+// before another Activation occurs.
+TEST_F(MenuButtonTest,
+ InkDropStateForMenuButtonWithPressedLockBeforeActivation) {
+ TestMenuButtonListener menu_button_listener;
+ CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
+ TestInkDropDelegate ink_drop_delegate;
+ button()->set_ink_drop_delegate(&ink_drop_delegate);
+ MenuButton::PressedLock lock(button());
+
+ button()->Activate(nullptr);
+
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop_delegate.state());
+}
+
#if defined(USE_AURA)
// Tests that the MenuButton does not become pressed if it can be dragged, and a
@@ -411,9 +548,7 @@ TEST_F(MenuButtonTest, DraggableMenuButtonDoesNotActivateOnDrag) {
SetDragDropClient(GetContext(), &drag_client);
button()->PrependPreTargetHandler(&drag_client);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
- generator.set_current_location(gfx::Point(10, 10));
- generator.DragMouseBy(10, 0);
+ generator()->DragMouseBy(10, 0);
EXPECT_EQ(nullptr, menu_button_listener.last_source());
EXPECT_EQ(Button::STATE_NORMAL, menu_button_listener.last_source_state());
}
@@ -424,44 +559,17 @@ TEST_F(MenuButtonTest, DraggableMenuButtonDoesNotActivateOnDrag) {
#if !defined(OS_MACOSX) || defined(USE_AURA)
// Tests if the listener is notified correctly when a gesture tap happens on a
-// MenuButton that has a regular ButtonListener.
-TEST_F(MenuButtonTest, ActivateNonDropDownOnGestureTap) {
- TestButtonListener button_listener;
- CreateMenuButtonWithButtonListener(&button_listener);
-
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
-
- // Move the mouse outside the menu button so that it doesn't impact the
- // button state.
- generator.MoveMouseTo(400, 400);
- EXPECT_FALSE(button()->IsMouseHovered());
-
- 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());
-
- // The button should go back to it's normal state since the gesture ended.
- EXPECT_EQ(Button::STATE_NORMAL, button()->state());
-}
-
-// Tests if the listener is notified correctly when a gesture tap happens on a
// MenuButton that has a MenuButtonListener.
TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) {
TestMenuButtonListener menu_button_listener;
CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
-
// Move the mouse outside the menu button so that it doesn't impact the
// button state.
- generator.MoveMouseTo(400, 400);
+ generator()->MoveMouseTo(400, 400);
EXPECT_FALSE(button()->IsMouseHovered());
- generator.GestureTapAt(gfx::Point(10, 10));
+ generator()->GestureTapAt(gfx::Point(10, 10));
// Check that MenuButton has notified the listener, while it was in pressed
// state.
@@ -477,12 +585,10 @@ TEST_F(MenuButtonTest, ActivateDropDownOnGestureTap) {
TEST_F(MenuButtonTest, TouchFeedbackDuringTap) {
TestMenuButtonListener menu_button_listener;
CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
- generator.set_current_location(gfx::Point(10, 10));
- generator.PressTouch();
+ generator()->PressTouch();
EXPECT_EQ(Button::STATE_HOVERED, button()->state());
- generator.ReleaseTouch();
+ generator()->ReleaseTouch();
EXPECT_EQ(Button::STATE_HOVERED, menu_button_listener.last_source_state());
}
@@ -491,13 +597,11 @@ TEST_F(MenuButtonTest, TouchFeedbackDuringTap) {
TEST_F(MenuButtonTest, TouchFeedbackDuringTapCancel) {
TestMenuButtonListener menu_button_listener;
CreateMenuButtonWithMenuButtonListener(&menu_button_listener);
- ui::test::EventGenerator generator(GetContext(), widget()->GetNativeWindow());
- generator.set_current_location(gfx::Point(10, 10));
- generator.PressTouch();
+ generator()->PressTouch();
EXPECT_EQ(Button::STATE_HOVERED, button()->state());
- generator.MoveTouch(gfx::Point(10, 30));
- generator.ReleaseTouch();
+ generator()->MoveTouch(gfx::Point(10, 30));
+ generator()->ReleaseTouch();
EXPECT_EQ(Button::STATE_NORMAL, button()->state());
EXPECT_EQ(nullptr, menu_button_listener.last_source());
}
@@ -505,3 +609,4 @@ TEST_F(MenuButtonTest, TouchFeedbackDuringTapCancel) {
#endif // !defined(OS_MACOSX) || defined(USE_AURA)
} // namespace views
+} // namespace test
diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc
index fa957ef61d4..3de636fbdc1 100644
--- a/chromium/ui/views/controls/combobox/combobox.cc
+++ b/chromium/ui/views/controls/combobox/combobox.cc
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/default_style.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/models/combobox_model.h"
#include "ui/base/models/combobox_model_observer.h"
@@ -26,6 +27,7 @@
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_aura.h"
#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/background.h"
#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
@@ -37,6 +39,7 @@
#include "ui/views/mouse_constants.h"
#include "ui/views/painter.h"
#include "ui/views/resources/grit/views_resources.h"
+#include "ui/views/style/platform_style.h"
#include "ui/views/widget/widget.h"
namespace views {
@@ -352,6 +355,9 @@ Combobox::Combobox(ui::ComboboxModel* model)
ModelChanged();
SetFocusable(true);
UpdateBorder();
+ // set_background() takes ownership but takes a raw pointer.
+ scoped_ptr<Background> b = PlatformStyle::CreateComboboxBackground();
+ set_background(b.release());
// Initialize the button images.
Button::ButtonState button_states[] = {
@@ -391,7 +397,7 @@ Combobox::~Combobox() {
// static
const gfx::FontList& Combobox::GetFontList() {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- return rb.GetFontList(ui::ResourceBundle::BaseFont);
+ return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta);
}
void Combobox::SetStyle(Style style) {
@@ -455,6 +461,12 @@ void Combobox::SetInvalid(bool invalid) {
SchedulePaint();
}
+int Combobox::GetArrowButtonWidth() const {
+ return GetDisclosureArrowLeftPadding() +
+ ArrowSize().width() +
+ GetDisclosureArrowRightPadding();
+}
+
void Combobox::Layout() {
PrefixDelegate::Layout();
@@ -528,7 +540,7 @@ bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
e.IsShiftDown() || e.IsControlDown() || e.IsAltDown()) {
return false;
}
- return menu_runner_;
+ return !!menu_runner_;
}
bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
@@ -688,7 +700,7 @@ void Combobox::ButtonPressed(Button* sender, const ui::Event& event) {
}
void Combobox::UpdateBorder() {
- scoped_ptr<FocusableBorder> border(new FocusableBorder());
+ scoped_ptr<FocusableBorder> border(PlatformStyle::CreateComboboxBorder());
if (style_ == STYLE_ACTION)
border->SetInsets(5, 10, 5, 10);
if (invalid_)
@@ -711,7 +723,8 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
int y = insets.top();
int text_height = height() - insets.height();
SkColor text_color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor);
+ enabled() ? ui::NativeTheme::kColorId_LabelEnabledColor :
+ ui::NativeTheme::kColorId_LabelDisabledColor);
DCHECK_GE(selected_index_, 0);
DCHECK_LT(selected_index_, model()->GetItemCount());
@@ -739,19 +752,9 @@ void Combobox::PaintText(gfx::Canvas* canvas) {
arrow_size.height());
AdjustBoundsForRTLUI(&arrow_bounds);
- // 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);
- }
+ gfx::ImageSkia arrow_image = PlatformStyle::CreateComboboxArrow(
+ enabled(), style_);
+ canvas->DrawImageInt(arrow_image, arrow_bounds.x(), arrow_bounds.y());
}
void Combobox::PaintButtons(gfx::Canvas* canvas) {
@@ -892,21 +895,7 @@ int Combobox::GetDisclosureArrowRightPadding() const {
}
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::NativeThemeAura::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);
+ return PlatformStyle::CreateComboboxArrow(enabled(), style_).size();
}
gfx::Size Combobox::GetContentSize() const {
diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h
index a0f5b48b161..64e4baa9be1 100644
--- a/chromium/ui/views/controls/combobox/combobox.h
+++ b/chromium/ui/views/controls/combobox/combobox.h
@@ -85,6 +85,10 @@ class VIEWS_EXPORT Combobox : public PrefixDelegate, public ButtonListener {
void SetInvalid(bool invalid);
bool invalid() const { return invalid_; }
+ // Returns the width of the arrow button component of the combobox: the arrow
+ // button itself, and the padding on either side of it.
+ int GetArrowButtonWidth() const;
+
// Overridden from View:
gfx::Size GetPreferredSize() const override;
const char* GetClassName() const override;
diff --git a/chromium/ui/views/controls/focusable_border.cc b/chromium/ui/views/controls/focusable_border.cc
index f92a3009f1e..b3ddd149272 100644
--- a/chromium/ui/views/controls/focusable_border.cc
+++ b/chromium/ui/views/controls/focusable_border.cc
@@ -42,14 +42,8 @@ void FocusableBorder::Paint(const View& view, gfx::Canvas* canvas) {
path.addRect(gfx::RectToSkRect(view.GetLocalBounds()), SkPath::kCW_Direction);
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
- SkColor color = override_color_;
- if (use_default_color_) {
- color = view.GetNativeTheme()->GetSystemColor(
- view.HasFocus() ? ui::NativeTheme::kColorId_FocusedBorderColor :
- ui::NativeTheme::kColorId_UnfocusedBorderColor);
- }
-
- paint.setColor(color);
+
+ paint.setColor(GetCurrentColor(view));
paint.setStrokeWidth(SkIntToScalar(2));
canvas->DrawPath(path, paint);
@@ -67,4 +61,12 @@ void FocusableBorder::SetInsets(int top, int left, int bottom, int right) {
insets_.Set(top, left, bottom, right);
}
+SkColor FocusableBorder::GetCurrentColor(const View& view) const {
+ if (!use_default_color_)
+ return override_color_;
+ return view.GetNativeTheme()->GetSystemColor(
+ view.HasFocus() ? ui::NativeTheme::kColorId_FocusedBorderColor :
+ ui::NativeTheme::kColorId_UnfocusedBorderColor);
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/focusable_border.h b/chromium/ui/views/controls/focusable_border.h
index eb24ca54de3..862049ab185 100644
--- a/chromium/ui/views/controls/focusable_border.h
+++ b/chromium/ui/views/controls/focusable_border.h
@@ -36,6 +36,9 @@ class VIEWS_EXPORT FocusableBorder : public Border {
gfx::Insets GetInsets() const override;
gfx::Size GetMinimumSize() const override;
+ protected:
+ SkColor GetCurrentColor(const View& view) const;
+
private:
gfx::Insets insets_;
diff --git a/chromium/ui/views/controls/focusable_rounded_border_mac.cc b/chromium/ui/views/controls/focusable_rounded_border_mac.cc
new file mode 100644
index 00000000000..ae4522a7c8b
--- /dev/null
+++ b/chromium/ui/views/controls/focusable_rounded_border_mac.cc
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/focusable_rounded_border_mac.h"
+
+#include "ui/gfx/canvas.h"
+#include "ui/native_theme/native_theme_mac.h"
+
+namespace {
+
+const int kThickness = 1;
+
+} // namespace
+
+namespace views {
+
+FocusableRoundedBorder::FocusableRoundedBorder() {
+ // TODO(ellyjones): These insets seem like they shouldn't be big enough, but
+ // they are, and insetting by corner_radius_ instead produces gargantuan
+ // padding. Why is that?
+ SetInsets(kThickness, kThickness, kThickness, kThickness);
+}
+
+FocusableRoundedBorder::~FocusableRoundedBorder() {}
+
+// For now, this is similar to RoundedRectBorder::Paint(), but this method will
+// likely diverge in future.
+// TODO(ellyjones): Diverge it by adding soft focus rings.
+void FocusableRoundedBorder::Paint(const View& view, gfx::Canvas* canvas) {
+ SkPaint paint;
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(kThickness);
+ paint.setColor(GetCurrentColor(view));
+ paint.setAntiAlias(true);
+
+ float half_thickness = kThickness / 2.0f;
+ gfx::RectF bounds(view.GetLocalBounds());
+ bounds.Inset(half_thickness, half_thickness);
+ canvas->DrawRoundRect(bounds, ui::NativeThemeMac::kComboboxCornerRadius,
+ paint);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/focusable_rounded_border_mac.h b/chromium/ui/views/controls/focusable_rounded_border_mac.h
new file mode 100644
index 00000000000..1821cd414da
--- /dev/null
+++ b/chromium/ui/views/controls/focusable_rounded_border_mac.h
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_FOCUSABLE_ROUNDED_BORDER_H_
+#define UI_VIEWS_CONTROLS_FOCUSABLE_ROUNDED_BORDER_H_
+
+#include "base/macros.h"
+#include "ui/views/controls/focusable_border.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+// A Border that changes colors in accordance with the system color scheme when
+// the View it borders is focused.
+class FocusableRoundedBorder : public FocusableBorder {
+ public:
+ FocusableRoundedBorder();
+ ~FocusableRoundedBorder() override;
+
+ // Border:
+ void Paint(const View& view, gfx::Canvas* canvas) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FocusableRoundedBorder);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_FOCUSABLE_ROUNDED_BORDER_H_
diff --git a/chromium/ui/views/controls/glow_hover_controller.cc b/chromium/ui/views/controls/glow_hover_controller.cc
index 9a5fa0bc4ce..ef08308f7e7 100644
--- a/chromium/ui/views/controls/glow_hover_controller.cc
+++ b/chromium/ui/views/controls/glow_hover_controller.cc
@@ -9,8 +9,8 @@
namespace views {
// Amount to scale the opacity.
-static const double kTrackOpacityScale = 0.25;
-static const double kHighlightOpacityScale = 1.0;
+static const double kSubtleOpacityScale = 0.45;
+static const double kPronouncedOpacityScale = 1.0;
// How long the hover state takes.
static const int kTrackHoverDurationMs = 400;
@@ -18,7 +18,7 @@ static const int kTrackHoverDurationMs = 400;
GlowHoverController::GlowHoverController(views::View* view)
: view_(view),
animation_(this),
- opacity_scale_(kTrackOpacityScale) {
+ opacity_scale_(kSubtleOpacityScale) {
animation_.set_delegate(this);
}
@@ -39,13 +39,13 @@ void GlowHoverController::SetLocation(const gfx::Point& location) {
void GlowHoverController::Show(Style style) {
switch (style) {
case SUBTLE:
- opacity_scale_ = kTrackOpacityScale;
+ opacity_scale_ = kSubtleOpacityScale;
animation_.SetSlideDuration(kTrackHoverDurationMs);
animation_.SetTweenType(gfx::Tween::EASE_OUT);
animation_.Show();
break;
case PRONOUNCED:
- opacity_scale_ = kHighlightOpacityScale;
+ opacity_scale_ = kPronouncedOpacityScale;
// Force the end state to show immediately.
animation_.Show();
animation_.End();
@@ -69,8 +69,8 @@ double GlowHoverController::GetAnimationValue() const {
}
SkAlpha GlowHoverController::GetAlpha() const {
- return static_cast<SkAlpha>(gfx::ToFlooredInt(
- 0.5 + animation_.CurrentValueBetween(0., 255 * opacity_scale_)));
+ return static_cast<SkAlpha>(animation_.CurrentValueBetween(
+ 0, gfx::ToRoundedInt(255 * opacity_scale_)));
}
bool GlowHoverController::ShouldDraw() const {
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index 7bda1d17da8..7127ca4f070 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -65,7 +65,7 @@ void ImageView::SetImage(const gfx::ImageSkia* image_skia) {
}
}
-const gfx::ImageSkia& ImageView::GetImage() {
+const gfx::ImageSkia& ImageView::GetImage() const {
return image_;
}
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index 401289a76cc..b3b762bcd43 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -50,9 +50,9 @@ class VIEWS_EXPORT ImageView : public View {
// image.
void SetImage(const gfx::ImageSkia* image_skia);
- // Returns the image currently displayed or NULL of none is currently set.
+ // Returns the image currently displayed, which can be empty if not set.
// The returned image is still owned by the ImageView.
- const gfx::ImageSkia& GetImage();
+ const gfx::ImageSkia& GetImage() const;
// Set the desired image size for the receiving ImageView.
void SetImageSize(const gfx::Size& image_size);
diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc
index 99137e6eb94..d1a6cafa9c1 100644
--- a/chromium/ui/views/controls/label.cc
+++ b/chromium/ui/views/controls/label.cc
@@ -18,6 +18,8 @@
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/default_style.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/insets.h"
@@ -25,17 +27,23 @@
#include "ui/native_theme/native_theme.h"
namespace views {
+namespace {
+
+const gfx::FontList& GetDefaultFontList() {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta);
+}
+
+} // namespace
// static
const char Label::kViewClassName[] = "Label";
const int Label::kFocusBorderPadding = 1;
-Label::Label() {
- Init(base::string16(), gfx::FontList());
+Label::Label() : Label(base::string16()) {
}
-Label::Label(const base::string16& text) {
- Init(text, gfx::FontList());
+Label::Label(const base::string16& text) : Label(text, GetDefaultFontList()) {
}
Label::Label(const base::string16& text, const gfx::FontList& font_list) {
@@ -431,6 +439,7 @@ void Label::MaybeBuildRenderTextLines() {
rect.Inset(kFocusBorderPadding, kFocusBorderPadding);
if (rect.IsEmpty())
return;
+ rect.Inset(-gfx::ShadowValue::GetMargin(shadows()));
gfx::HorizontalAlignment alignment = horizontal_alignment();
gfx::DirectionalityMode directionality = render_text_->directionality_mode();
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index 9d0743341ea..63a12a85c7f 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -322,7 +322,7 @@ TEST_F(LabelTest, TextChangeWithoutLayout) {
TEST_F(LabelTest, EmptyLabelSizing) {
Label label;
- const gfx::Size expected_size(0, gfx::FontList().GetHeight());
+ const gfx::Size expected_size(0, label.font_list().GetHeight());
EXPECT_EQ(expected_size, label.GetPreferredSize());
label.SetMultiLine(!label.multi_line());
EXPECT_EQ(expected_size, label.GetPreferredSize());
diff --git a/chromium/ui/views/controls/link.cc b/chromium/ui/views/controls/link.cc
index adbe647aaf4..ec955b38597 100644
--- a/chromium/ui/views/controls/link.cc
+++ b/chromium/ui/views/controls/link.cc
@@ -10,7 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/cursor/cursor.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
diff --git a/chromium/ui/views/controls/menu/menu_config.cc b/chromium/ui/views/controls/menu/menu_config.cc
index 10b301dcbee..720a69aa707 100644
--- a/chromium/ui/views/controls/menu/menu_config.cc
+++ b/chromium/ui/views/controls/menu/menu_config.cc
@@ -29,6 +29,7 @@ MenuConfig::MenuConfig()
separator_upper_height(3),
separator_lower_height(4),
separator_spacing_height(3),
+ separator_thickness(1),
show_mnemonics(false),
scroll_arrow_height(3),
label_to_minor_text_padding(10),
diff --git a/chromium/ui/views/controls/menu/menu_config.h b/chromium/ui/views/controls/menu/menu_config.h
index 156a86b4d66..a4ecc47839b 100644
--- a/chromium/ui/views/controls/menu/menu_config.h
+++ b/chromium/ui/views/controls/menu/menu_config.h
@@ -77,6 +77,9 @@ struct VIEWS_EXPORT MenuConfig {
// Height of a ui::SPACING_SEPARATOR.
int separator_spacing_height;
+ // Thickness of the drawn separator line in pixels.
+ int separator_thickness;
+
// Are mnemonics shown?
bool show_mnemonics;
diff --git a/chromium/ui/views/controls/menu/menu_config_android.cc b/chromium/ui/views/controls/menu/menu_config_android.cc
deleted file mode 100644
index 9f5c73f7add..00000000000
--- a/chromium/ui/views/controls/menu/menu_config_android.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_config.h"
-
-namespace views {
-
-void MenuConfig::Init() {
- // Android uses the config provided by data member initializers.
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_config_mac.mm b/chromium/ui/views/controls/menu/menu_config_mac.mm
index 18c6fe2dbe4..2e00665c377 100644
--- a/chromium/ui/views/controls/menu/menu_config_mac.mm
+++ b/chromium/ui/views/controls/menu/menu_config_mac.mm
@@ -6,8 +6,18 @@
#import <AppKit/AppKit.h>
+#include "base/mac/mac_util.h"
+
namespace views {
+namespace {
+
+// The height of the menu separator in pixels.
+const int kMenuSeparatorHeight = 2;
+const int kMenuSeparatorHeightMavericks = 1;
+
+} // namespace
+
void MenuConfig::Init() {
font_list = gfx::FontList(gfx::Font([NSFont menuFontOfSize:0.0]));
menu_vertical_border_size = 4;
@@ -21,6 +31,9 @@ void MenuConfig::Init() {
separator_height = 13;
separator_upper_height = 7;
separator_lower_height = 6;
+ separator_thickness = base::mac::IsOSMavericks()
+ ? kMenuSeparatorHeightMavericks
+ : kMenuSeparatorHeight;
align_arrow_and_shortcut = true;
icons_in_label = true;
check_selected_combobox_item = true;
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index 10b2cd914e7..fcc41e8168a 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -45,20 +45,14 @@
#include "ui/views/win/hwnd_util.h"
#endif
+#if defined(USE_AURA)
+#include "ui/views/controls/menu/menu_key_event_handler.h"
+#endif
+
using base::Time;
using base::TimeDelta;
using ui::OSExchangeData;
-// Period of the scroll timer (in milliseconds).
-static const int kScrollTimerMS = 30;
-
-// Amount of time from when the drop exits the menu and the menu is hidden.
-static const int kCloseOnExitTime = 1200;
-
-// If a context menu is invoked by touch, we shift the menu by this offset so
-// that the finger does not obscure the menu.
-static const int kCenteredContextMenuYOffset = -15;
-
namespace views {
namespace {
@@ -66,7 +60,17 @@ namespace {
// When showing context menu on mouse down, the user might accidentally select
// the menu item on the subsequent mouse up. To prevent this, we add the
// following delay before the user is able to select an item.
-static int menu_selection_hold_time_ms = kMinimumMsPressedToActivate;
+int menu_selection_hold_time_ms = kMinimumMsPressedToActivate;
+
+// Period of the scroll timer (in milliseconds).
+const int kScrollTimerMS = 30;
+
+// Amount of time from when the drop exits the menu and the menu is hidden.
+const int kCloseOnExitTime = 1200;
+
+// If a context menu is invoked by touch, we shift the menu by this offset so
+// that the finger does not obscure the menu.
+const int kCenteredContextMenuYOffset = -15;
// The spacing offset for the bubble tip.
const int kBubbleTipSizeLeftRight = 12;
@@ -93,14 +97,12 @@ bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) {
}
// Returns the first descendant of |view| that is hot tracked.
-static CustomButton* GetFirstHotTrackedView(View* view) {
+CustomButton* GetFirstHotTrackedView(View* view) {
if (!view)
return NULL;
CustomButton* button = CustomButton::AsCustomButton(view);
- if (button) {
- if (button->IsHotTracked())
- return button;
- }
+ if (button && button->IsHotTracked())
+ return button;
for (int i = 0; i < view->child_count(); ++i) {
CustomButton* hot_view = GetFirstHotTrackedView(view->child_at(i));
@@ -115,7 +117,7 @@ static CustomButton* GetFirstHotTrackedView(View* view) {
// the first view (if |forward| is false, iterating starts at the last view). If
// |forward| is true the children are considered first to last, otherwise last
// to first.
-static View* GetFirstFocusableView(View* view, int start, bool forward) {
+View* GetFirstFocusableView(View* view, int start, bool forward) {
if (forward) {
for (int i = start == -1 ? 0 : start; i < view->child_count(); ++i) {
View* deepest = GetFirstFocusableView(view->child_at(i), -1, forward);
@@ -133,15 +135,13 @@ static View* GetFirstFocusableView(View* view, int start, bool forward) {
}
// Returns the first child of |start| that is focusable.
-static View* GetInitialFocusableView(View* start, bool forward) {
+View* GetInitialFocusableView(View* start, bool forward) {
return GetFirstFocusableView(start, -1, forward);
}
// Returns the next view after |start_at| that is focusable. Returns NULL if
// there are no focusable children of |ancestor| after |start_at|.
-static View* GetNextFocusableView(View* ancestor,
- View* start_at,
- bool forward) {
+View* GetNextFocusableView(View* ancestor, View* start_at, bool forward) {
DCHECK(ancestor->Contains(start_at));
View* parent = start_at;
do {
@@ -158,6 +158,101 @@ static View* GetNextFocusableView(View* ancestor,
return NULL;
}
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+// Determines the correct cooridinates and window to repost |event| to, if it is
+// a mouse or touch event.
+static void RepostEventImpl(const ui::LocatedEvent* event,
+ const gfx::Point& screen_loc,
+ gfx::NativeView native_view,
+ gfx::NativeWindow window) {
+ if (!event->IsMouseEvent() && !event->IsTouchEvent()) {
+ // TODO(rbyers): Gesture event repost is tricky to get right
+ // crbug.com/170987.
+ DCHECK(event->IsGestureEvent());
+ return;
+ }
+
+ if (!native_view)
+ return;
+
+#if defined(OS_WIN)
+ gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc);
+ HWND target_window = ::WindowFromPoint(screen_loc_pixels.ToPOINT());
+ // If we don't find a native window for the HWND at the current location,
+ // then attempt to find a native window from its parent if one exists.
+ // There are HWNDs created outside views, which don't have associated
+ // native windows.
+ if (!window) {
+ HWND parent = ::GetParent(target_window);
+ if (parent) {
+ aura::WindowTreeHost* host =
+ aura::WindowTreeHost::GetForAcceleratedWidget(parent);
+ if (host) {
+ target_window = parent;
+ window = host->window();
+ }
+ }
+ }
+ // 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.
+ if (event->IsMouseEvent()) {
+ 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
+ // |target_window| and |source_window| were created on the same thread,
+ // else double events can occur and lead to bad behavior.
+ return;
+ }
+
+ // 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;
+ }
+#endif
+ // Non Aura window.
+ if (!window)
+ return;
+
+ MenuMessageLoop::RepostEventToWindow(event, window, screen_loc);
+}
+#endif // defined(OS_WIN) || defined(OS_CHROMEOS)
+
} // namespace
// MenuScrollTask --------------------------------------------------------------
@@ -268,12 +363,15 @@ struct MenuController::SelectByCharDetails {
// MenuController:State ------------------------------------------------------
MenuController::State::State()
- : item(NULL),
+ : item(nullptr),
+ hot_button(nullptr),
submenu_open(false),
anchor(MENU_ANCHOR_TOPLEFT),
context_menu(false) {
}
+MenuController::State::State(const State& other) = default;
+
MenuController::State::~State() {}
// MenuController ------------------------------------------------------------
@@ -327,6 +425,8 @@ MenuItemView* MenuController::Run(Widget* parent,
// blocking/non-blocking shouldn't be needed.
DCHECK(blocking_run_);
+ state_.hot_button = hot_button_;
+ hot_button_ = nullptr;
// We're already showing, push the current state.
menu_stack_.push_back(
std::make_pair(state_, make_linked_ptr(pressed_lock_.release())));
@@ -335,6 +435,12 @@ MenuItemView* MenuController::Run(Widget* parent,
DCHECK_EQ(owner_, parent);
} else {
showing_ = true;
+
+#if defined(USE_AURA)
+ // Only create a MenuKeyEventHandler for non-nested menus. Nested menus will
+ // use the existing one.
+ key_event_handler_.reset(new MenuKeyEventHandler);
+#endif
}
// Reset current state.
@@ -450,9 +556,14 @@ bool MenuController::OnMousePressed(SubmenuView* source,
if (forward_to_root) {
ui::MouseEvent event_for_root(event);
+ // Reset hot-tracking if a different view is getting a mouse press.
ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root);
View* view =
forward_to_root->GetEventHandlerForPoint(event_for_root.location());
+ CustomButton* button = CustomButton::AsCustomButton(view);
+ if (hot_button_ != button)
+ SetHotTrackedButton(button);
+
// Empty menu items are always handled by the menu controller.
if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) {
bool processed = forward_to_root->ProcessMousePressed(event_for_root);
@@ -610,8 +721,21 @@ void MenuController::OnMouseMoved(SubmenuView* source,
}
MenuHostRootView* root_view = GetRootView(source, event.location());
- if (root_view)
+ if (root_view) {
root_view->ProcessMouseMoved(event);
+
+ // Update hot-tracked button when a button state is changed with a mouse
+ // event. It is necessary to track it for accurate hot-tracking when both
+ // mouse and keyboard are used to navigate the menu.
+ ui::MouseEvent event_for_root(event);
+ ConvertLocatedEventForRootView(source, root_view, &event_for_root);
+ View* view =
+ root_view->GetEventHandlerForPoint(event_for_root.location());
+ CustomButton* button = CustomButton::AsCustomButton(view);
+ if (button && button->IsHotTracked())
+ SetHotTrackedButton(button);
+ }
+
HandleMouseLocation(source, event.location());
}
@@ -629,6 +753,18 @@ bool MenuController::OnMouseWheel(SubmenuView* source,
void MenuController::OnGestureEvent(SubmenuView* source,
ui::GestureEvent* event) {
+ MenuHostRootView* root_view = GetRootView(source, event->location());
+ if (root_view) {
+ // Reset hot-tracking if a different view is getting a touch event.
+ ui::GestureEvent event_for_root(*event);
+ ConvertLocatedEventForRootView(source, root_view, &event_for_root);
+ View* view =
+ root_view->GetEventHandlerForPoint(event_for_root.location());
+ CustomButton* button = CustomButton::AsCustomButton(view);
+ if (hot_button_ && hot_button_ != button)
+ SetHotTrackedButton(nullptr);
+ }
+
MenuPart part = GetMenuPart(source, event->location());
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
SetSelectionOnPointerDown(source, event);
@@ -646,8 +782,8 @@ void MenuController::OnGestureEvent(SubmenuView* source,
!(part.menu->HasSubmenu())) {
if (part.menu->GetDelegate()->IsTriggerableEvent(
part.menu, *event)) {
- Accept(part.menu, event->flags());
item_selected_by_touch_ = true;
+ Accept(part.menu, event->flags());
}
event->StopPropagation();
} else if (part.type == MenuPart::MENU_ITEM) {
@@ -695,10 +831,22 @@ View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source,
void MenuController::ViewHierarchyChanged(
SubmenuView* source,
const View::ViewHierarchyChangedDetails& details) {
- // If the current mouse handler is removed, remove it as the handler.
- if (!details.is_add && details.child == current_mouse_event_target_) {
- current_mouse_event_target_ = nullptr;
- current_mouse_pressed_state_ = 0;
+ if (!details.is_add) {
+ // If the current mouse handler is removed, remove it as the handler.
+ if (details.child == current_mouse_event_target_) {
+ current_mouse_event_target_ = nullptr;
+ current_mouse_pressed_state_ = 0;
+ }
+ // Update |hot_button_| (both in |this| and in |menu_stack_| if it gets
+ // removed while a menu is up.
+ if (details.child == hot_button_) {
+ hot_button_ = nullptr;
+ for (auto nested_state : menu_stack_) {
+ State& state = nested_state.first;
+ if (details.child == state.hot_button)
+ state.hot_button = nullptr;
+ }
+ }
}
}
@@ -889,7 +1037,7 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
void MenuController::UpdateSubmenuSelection(SubmenuView* submenu) {
if (submenu->IsShowing()) {
- gfx::Point point = GetScreen()->GetCursorScreenPoint();
+ gfx::Point point = gfx::Screen::GetScreen()->GetCursorScreenPoint();
const SubmenuView* root_submenu =
submenu->GetMenuItem()->GetRootMenuItem()->GetSubmenu();
View::ConvertPointFromScreen(
@@ -926,11 +1074,8 @@ void MenuController::SetSelection(MenuItemView* menu_item,
size_t new_size = new_path.size();
bool pending_item_changed = pending_state_.item != menu_item;
- if (pending_item_changed && pending_state_.item) {
- CustomButton* button = GetFirstHotTrackedView(pending_state_.item);
- if (button)
- button->SetHotTracked(false);
- }
+ if (pending_item_changed && pending_state_.item)
+ SetHotTrackedButton(nullptr);
// Notify the old path it isn't selected.
MenuDelegate* current_delegate =
@@ -973,7 +1118,7 @@ void MenuController::SetSelection(MenuItemView* menu_item,
(MenuDepth(menu_item) != 1 ||
menu_item->GetType() != MenuItemView::SUBMENU)) {
menu_item->NotifyAccessibilityEvent(
- ui::AX_EVENT_FOCUS, true);
+ ui::AX_EVENT_SELECTION, true);
}
}
@@ -1059,7 +1204,9 @@ void MenuController::StartDrag(SubmenuView* source,
}
void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
- DCHECK(blocking_run_);
+ // Do not process while performing drag-and-drop
+ if (!blocking_run_)
+ return;
switch (key_code) {
case ui::VKEY_UP:
@@ -1149,6 +1296,15 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
break;
}
+#if defined(OS_WIN)
+ // On Windows, pressing Alt and F10 keys should hide the menu to match the
+ // OS behavior.
+ case ui::VKEY_MENU:
+ case ui::VKEY_F10:
+ Cancel(EXIT_ALL);
+ break;
+#endif
+
default:
break;
}
@@ -1172,6 +1328,7 @@ MenuController::MenuController(bool blocking,
last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
showing_submenu_(false),
active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
+ hot_button_(nullptr),
delegate_(delegate),
message_loop_depth_(0),
closing_event_time_(base::TimeDelta()),
@@ -1208,7 +1365,7 @@ bool MenuController::SendAcceleratorToHotTrackedView() {
ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE);
hot_view->AcceleratorPressed(accelerator);
CustomButton* button = static_cast<CustomButton*>(hot_view);
- button->SetHotTracked(true);
+ SetHotTrackedButton(button);
return true;
}
@@ -1235,14 +1392,16 @@ void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
// Calculate the bounds of the monitor we'll show menus on. Do this once to
// avoid repeated system queries for the info.
- pending_state_.monitor_bounds = GetScreen()->GetDisplayNearestPoint(
- bounds.origin()).work_area();
+ pending_state_.monitor_bounds = gfx::Screen::GetScreen()
+ ->GetDisplayNearestPoint(bounds.origin())
+ .work_area();
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.
- gfx::Rect monitor_area = GetScreen()->GetDisplayNearestPoint(
- bounds.origin()).bounds();
+ gfx::Rect monitor_area = gfx::Screen::GetScreen()
+ ->GetDisplayNearestPoint(bounds.origin())
+ .bounds();
if (monitor_area.Contains(bounds))
pending_state_.monitor_bounds = monitor_area;
}
@@ -1275,7 +1434,8 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source,
return false;
}
- gfx::NativeWindow window_under_mouse = GetScreen()->GetWindowUnderCursor();
+ gfx::NativeWindow window_under_mouse =
+ gfx::Screen::GetScreen()->GetWindowUnderCursor();
// TODO(oshima): Replace with views only API.
if (!owner_ || window_under_mouse != owner_->GetNativeWindow())
return false;
@@ -1303,7 +1463,8 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source,
// There is a sibling menu, update the button state, hide the current menu
// and show the new one.
- pressed_lock_.reset(new MenuButton::PressedLock(button));
+ pressed_lock_.reset(
+ new MenuButton::PressedLock(button, true /* is_sibling_menu_show */));
// Need to reset capture when we show the menu again, otherwise we aren't
// going to get any events.
@@ -1967,8 +2128,7 @@ void MenuController::IncrementSelection(
// select the first menu item that is visible and enabled.
if (item->GetSubmenu()->GetMenuItemCount()) {
MenuItemView* to_select = FindInitialSelectableMenuItem(item, direction);
- if (to_select)
- SetSelection(to_select, SELECTION_DEFAULT);
+ SetInitialHotTrackedView(to_select, direction);
return;
}
}
@@ -1976,22 +2136,17 @@ void MenuController::IncrementSelection(
if (item->has_children()) {
CustomButton* button = GetFirstHotTrackedView(item);
if (button) {
- button->SetHotTracked(false);
- View* to_make_hot = GetNextFocusableView(
- item, button, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot) {
- button_hot->SetHotTracked(true);
- return;
- }
- } else {
- View* to_make_hot =
- GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot) {
- button_hot->SetHotTracked(true);
- return;
- }
+ DCHECK_EQ(hot_button_, button);
+ SetHotTrackedButton(nullptr);
+ }
+ bool direction_is_down = direction == INCREMENT_SELECTION_DOWN;
+ View* to_make_hot = button
+ ? GetNextFocusableView(item, button, direction_is_down)
+ : GetInitialFocusableView(item, direction_is_down);
+ CustomButton* hot_button = CustomButton::AsCustomButton(to_make_hot);
+ if (hot_button) {
+ SetHotTrackedButton(hot_button);
+ return;
}
}
@@ -2003,14 +2158,7 @@ void MenuController::IncrementSelection(
if (parent->GetSubmenu()->GetMenuItemAt(i) == item) {
MenuItemView* to_select =
FindNextSelectableMenuItem(parent, i, direction);
- if (!to_select)
- break;
- SetSelection(to_select, SELECTION_DEFAULT);
- View* to_make_hot = GetInitialFocusableView(
- to_select, direction == INCREMENT_SELECTION_DOWN);
- CustomButton* button_hot = CustomButton::AsCustomButton(to_make_hot);
- if (button_hot)
- button_hot->SetHotTracked(true);
+ SetInitialHotTrackedView(to_select, direction);
break;
}
}
@@ -2127,6 +2275,9 @@ void MenuController::AcceptOrSelect(MenuItemView* parent,
}
void MenuController::SelectByChar(base::char16 character) {
+ // Do not process while performing drag-and-drop
+ if (!blocking_run_)
+ return;
if (!character)
return;
@@ -2159,127 +2310,46 @@ void MenuController::SelectByChar(base::char16 character) {
}
}
-void MenuController::RepostEvent(SubmenuView* source,
- const ui::LocatedEvent* event,
- const gfx::Point& screen_loc,
- gfx::NativeView native_view,
- gfx::NativeWindow window) {
- if (!event->IsMouseEvent() && !event->IsTouchEvent()) {
- // 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
-
- if (!native_view)
- return;
-
-#if defined(OS_WIN)
- gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc);
- HWND target_window = ::WindowFromPoint(screen_loc_pixels.ToPOINT());
- // If we don't find a native window for the HWND at the current location,
- // then attempt to find a native window from its parent if one exists.
- // There are HWNDs created outside views, which don't have associated
- // native windows.
- if (!window) {
- HWND parent = ::GetParent(target_window);
- if (parent) {
- aura::WindowTreeHost* host =
- aura::WindowTreeHost::GetForAcceleratedWidget(parent);
- if (host) {
- target_window = parent;
- window = host->window();
- }
- }
- }
- // 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.
- if (event->IsMouseEvent()) {
- 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
- // |target_window| and |source_window| were created on the same thread,
- // else double events can occur and lead to bad behavior.
- return;
- }
-
- // 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;
- }
-#endif
- // Non Aura window.
- if (!window)
- return;
-
- MenuMessageLoop::RepostEventToWindow(event, window, screen_loc);
-}
-
void MenuController::RepostEventAndCancel(SubmenuView* source,
const ui::LocatedEvent* event) {
// Cancel can lead to the deletion |source| so we save the view and window to
// be used when reposting the event.
gfx::Point screen_loc(event->location());
View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
+
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
gfx::NativeView native_view = source->GetWidget()->GetNativeView();
gfx::NativeWindow window = nullptr;
if (native_view) {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
window = screen->GetWindowAtScreenPoint(screen_loc);
}
+#endif
#if defined(OS_WIN)
- // We're going to close and we own the event capture. We need to repost the
- // event, otherwise the window the user clicked on won't get the event.
- RepostEvent(source, event, screen_loc, native_view, window);
+ if (event->IsMouseEvent() || event->IsTouchEvent()) {
+ bool async_run = async_run_;
+ if (state_.item) {
+ state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture();
+ RepostEventImpl(event, screen_loc, native_view, window);
+ } else {
+ // 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());
+ }
+
+ // We're going to close and we own the event capture. We need to repost the
+ // event, otherwise the window the user clicked on won't get the event.
+ // RepostEvent(source, event, screen_loc, native_view, window);
+ // MenuController may have been deleted if |async_run_| so check for an
+ // active
+ // instance before accessing member variables.
+ if (!GetActiveInstance()) {
+ DCHECK(async_run);
+ return;
+ }
+ }
#endif
// Determine target to see if a complete or partial close of the menu should
@@ -2300,7 +2370,7 @@ void MenuController::RepostEventAndCancel(SubmenuView* source,
// is handled normally after the context menu has exited. We call
// RepostEvent after Cancel so that event capture has been released so
// that finding the event target is unaffected by the current capture.
- RepostEvent(source, event, screen_loc, native_view, window);
+ RepostEventImpl(event, screen_loc, native_view, window);
#endif
}
@@ -2427,8 +2497,7 @@ View* MenuController::GetActiveMouseView() {
void MenuController::SetExitType(ExitType type) {
exit_type_ = type;
// Exit nested message loops as soon as possible. We do this as
- // MessagePumpDispatcher is only invoked before native events, which means
- // its entirely possible for a Widget::CloseNow() task to be processed before
+ // it's entirely possible for a Widget::CloseNow() task to be processed before
// 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.
@@ -2453,7 +2522,8 @@ void MenuController::ExitAsyncRun() {
MenuItemView* result = ExitMenuRun();
delegate->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
result, accept_event_flags_);
- if (nested && exit_type_ == EXIT_ALL)
+ // MenuController may have been deleted by |delegate|.
+ if (GetActiveInstance() && nested && exit_type_ == EXIT_ALL)
ExitAsyncRun();
}
@@ -2494,6 +2564,7 @@ MenuItemView* MenuController::ExitMenuRun() {
// The menus are already showing, so we don't have to show them.
state_ = menu_stack_.back().first;
pending_state_ = menu_stack_.back().first;
+ hot_button_ = state_.hot_button;
nested_pressed_lock = menu_stack_.back().second;
menu_stack_.pop_back();
// Even though the menus are nested, there may not be nested delegates.
@@ -2503,6 +2574,10 @@ MenuItemView* MenuController::ExitMenuRun() {
async_run_ = delegate_stack_.back().second;
}
} else {
+#if defined(USE_AURA)
+ key_event_handler_.reset();
+#endif
+
showing_ = false;
did_capture_ = false;
}
@@ -2529,9 +2604,11 @@ MenuItemView* MenuController::ExitMenuRun() {
}
}
- // Reset our pressed lock to the previous state's, if there was one.
- // The lock handles the case if the button was destroyed.
+ // Reset our pressed lock and hot-tracked state to the previous state's, if
+ // they were active. The lock handles the case if the button was destroyed.
pressed_lock_.reset(nested_pressed_lock.release());
+ if (hot_button_)
+ hot_button_->SetHotTracked(true);
return result;
}
@@ -2568,10 +2645,29 @@ 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();
+void MenuController::SetInitialHotTrackedView(
+ MenuItemView* item,
+ SelectionIncrementDirectionType direction) {
+ if (!item)
+ return;
+ SetSelection(item, SELECTION_DEFAULT);
+ View* hot_view =
+ GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
+ SetHotTrackedButton(CustomButton::AsCustomButton(hot_view));
+}
+
+void MenuController::SetHotTrackedButton(CustomButton* hot_button) {
+ if (hot_button == hot_button_) {
+ // Hot-tracked state may change outside of the MenuController. Correct it.
+ if (hot_button && !hot_button->IsHotTracked())
+ hot_button->SetHotTracked(true);
+ return;
+ }
+ if (hot_button_)
+ hot_button_->SetHotTracked(false);
+ hot_button_ = hot_button;
+ if (hot_button)
+ hot_button->SetHotTracked(true);
}
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h
index 12af0aa1874..dc21826d6d4 100644
--- a/chromium/ui/views/controls/menu/menu_controller.h
+++ b/chromium/ui/views/controls/menu/menu_controller.h
@@ -26,9 +26,6 @@
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/widget/widget_observer.h"
-namespace base {
-class MessagePumpDispatcher;
-}
namespace gfx {
class Screen;
}
@@ -46,10 +43,12 @@ class MouseEvent;
class SubmenuView;
class View;
+#if defined(USE_AURA)
+class MenuKeyEventHandler;
+#endif
+
namespace internal {
class MenuControllerDelegate;
-class MenuEventDispatcher;
-class MenuMessagePumpDispatcher;
class MenuRunnerImpl;
}
@@ -199,8 +198,6 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
static void TurnOffMenuSelectionHoldForTest();
private:
- friend class internal::MenuEventDispatcher;
- friend class internal::MenuMessagePumpDispatcher;
friend class internal::MenuRunnerImpl;
friend class test::MenuControllerTest;
friend class MenuKeyEventHandler;
@@ -240,11 +237,16 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
// Tracks selection information.
struct State {
State();
+ State(const State& other);
~State();
// The selected menu item.
MenuItemView* item;
+ // Used to capture a hot tracked child button when a nested menu is opened
+ // and to restore the hot tracked state when exiting a nested menu.
+ CustomButton* hot_button;
+
// If item has a submenu this indicates if the submenu is showing.
bool submenu_open;
@@ -497,20 +499,11 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
// the title.
void 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
- // if the context menu had not been present.
- // On non-aura Windows, a new mouse event is generated and posted to
- // the window (if there is one) at the location of the event. On
- // aura, the event is reposted on the RootWindow.
- void RepostEvent(SubmenuView* source,
- const ui::LocatedEvent* event,
- const gfx::Point& screen_loc,
- gfx::NativeView native_view,
- gfx::NativeWindow window);
-
// For Windows and Aura we repost an event which dismisses the |source| menu.
- // The menu is also canceled dependent on the target of the event.
+ // The menu may also be canceled depending on the target of the event. |event|
+ // is then processed without the menu present. On non-aura Windows, a new
+ // mouse event is generated and posted to the window (if there is one) at the
+ // location of the event. On aura, the event is reposted on the RootWindow.
void RepostEventAndCancel(SubmenuView* source, const ui::LocatedEvent* event);
// Sets the drop target to new_item.
@@ -565,8 +558,12 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
void HandleMouseLocation(SubmenuView* source,
const gfx::Point& mouse_location);
- // Retrieve an appropriate Screen.
- gfx::Screen* GetScreen();
+ // Sets hot-tracked state to the first focusable descendant view of |item|.
+ void SetInitialHotTrackedView(MenuItemView* item,
+ SelectionIncrementDirectionType direction);
+
+ // Updates the current |hot_button_| and its hot tracked state.
+ void SetHotTrackedButton(CustomButton* hot_button);
// The active instance.
static MenuController* active_instance_;
@@ -666,6 +663,9 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
// See UpdateActiveMouseView() for details.
const int active_mouse_view_id_;
+ // Current hot tracked child button if any.
+ CustomButton* hot_button_;
+
internal::MenuControllerDelegate* delegate_;
// How deep we are in nested message loops. This should be at most 2 (when
@@ -682,7 +682,7 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
// screen coordinates). Otherwise this will be (0, 0).
gfx::Point menu_start_mouse_press_loc_;
- // Controls behviour differences between an asynchronous run, and other types
+ // Controls behaviour differences between an asynchronous run, and other types
// of run (blocking, drag and drop).
bool async_run_;
@@ -704,6 +704,10 @@ class VIEWS_EXPORT MenuController : public WidgetObserver {
scoped_ptr<MenuMessageLoop> message_loop_;
+#if defined(USE_AURA)
+ scoped_ptr<MenuKeyEventHandler> key_event_handler_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(MenuController);
};
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
index e9074f0704e..ee26fb24200 100644
--- a/chromium/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/views/controls/menu/menu_controller.h"
+#include "base/callback.h"
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -21,16 +22,14 @@
#include "ui/views/controls/menu/menu_delegate.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/test/views_test_base.h"
-#if defined(OS_WIN)
-#include "ui/views/widget/desktop_aura/desktop_dispatcher_client.h"
-#endif
-
#if defined(USE_AURA)
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window.h"
+#include "ui/views/controls/menu/menu_key_event_handler.h"
#endif
#if defined(USE_X11)
@@ -92,6 +91,11 @@ class TestMenuControllerDelegate : public internal::MenuControllerDelegate {
return on_menu_closed_mouse_event_flags_;
}
+ // On a subsequent call to OnMenuClosed |controller| will be deleted.
+ void set_on_menu_closed_callback(const base::Closure& callback) {
+ on_menu_closed_callback_ = callback;
+ }
+
// internal::MenuControllerDelegate:
void OnMenuClosed(NotifyType type,
MenuItemView* menu,
@@ -107,6 +111,9 @@ class TestMenuControllerDelegate : public internal::MenuControllerDelegate {
MenuItemView* on_menu_closed_menu_;
int on_menu_closed_mouse_event_flags_;
+ // Optional callback triggered during OnMenuClosed
+ base::Closure on_menu_closed_callback_;
+
DISALLOW_COPY_AND_ASSIGN(TestMenuControllerDelegate);
};
@@ -114,7 +121,8 @@ TestMenuControllerDelegate::TestMenuControllerDelegate()
: on_menu_closed_called_(0),
on_menu_closed_notify_type_(NOTIFY_DELEGATE),
on_menu_closed_menu_(nullptr),
- on_menu_closed_mouse_event_flags_(0) {}
+ on_menu_closed_mouse_event_flags_(0),
+ on_menu_closed_callback_() {}
void TestMenuControllerDelegate::OnMenuClosed(NotifyType type,
MenuItemView* menu,
@@ -123,6 +131,8 @@ void TestMenuControllerDelegate::OnMenuClosed(NotifyType type,
on_menu_closed_notify_type_ = type;
on_menu_closed_menu_ = menu;
on_menu_closed_mouse_event_flags_ = mouse_event_flags;
+ if (!on_menu_closed_callback_.is_null())
+ on_menu_closed_callback_.Run();
}
void TestMenuControllerDelegate::SiblingMenuCreated(MenuItemView* menu) {}
@@ -240,12 +250,7 @@ class MenuControllerTest : public ViewsTestBase {
void TearDown() override {
owner_->CloseNow();
-
- menu_controller_->showing_ = false;
- menu_controller_->owner_ = nullptr;
- delete menu_controller_;
- menu_controller_ = nullptr;
-
+ DestroyMenuController();
ViewsTestBase::TearDown();
}
@@ -347,6 +352,13 @@ class MenuControllerTest : public ViewsTestBase {
MenuController::INCREMENT_SELECTION_UP);
}
+ void DestroyMenuControllerOnMenuClosed(TestMenuControllerDelegate* delegate) {
+ // Unretained() is safe here as the test should outlive the delegate. If not
+ // we want to know.
+ delegate->set_on_menu_closed_callback(base::Bind(
+ &MenuControllerTest::DestroyMenuController, base::Unretained(this)));
+ }
+
MenuItemView* FindInitialSelectableMenuItemDown(MenuItemView* parent) {
return menu_controller_->FindInitialSelectableMenuItem(
parent, MenuController::INCREMENT_SELECTION_DOWN);
@@ -396,7 +408,17 @@ class MenuControllerTest : public ViewsTestBase {
menu_controller_->SetSelectionOnPointerDown(source, event);
}
+ // Note that coordinates of events passed to MenuController must be in that of
+ // the MenuScrollViewContainer.
+ void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) {
+ menu_controller_->OnMouseMoved(source, event);
+ }
+
void RunMenu() {
+#if defined(USE_AURA)
+ scoped_ptr<MenuKeyEventHandler> key_event_handler(new MenuKeyEventHandler);
+#endif
+
menu_controller_->message_loop_depth_++;
menu_controller_->RunMessageLoop(false);
menu_controller_->message_loop_depth_--;
@@ -426,7 +448,46 @@ class MenuControllerTest : public ViewsTestBase {
return menu_controller_->exit_type_;
}
+ void AddButtonMenuItems() {
+ menu_item()->SetBounds(0, 0, 200, 300);
+ MenuItemView* item_view =
+ menu_item()->AppendMenuItemWithLabel(5, base::ASCIIToUTF16("Five"));
+ for (int i = 0; i < 3; ++i) {
+ LabelButton* button =
+ new LabelButton(nullptr, base::ASCIIToUTF16("Label"));
+ button->SetFocusable(true);
+ item_view->AddChildView(button);
+ }
+ menu_item()->GetSubmenu()->ShowAt(owner(), menu_item()->bounds(), false);
+ }
+
+ CustomButton* GetHotButton() {
+ return menu_controller_->hot_button_;
+ }
+
+ void SetHotTrackedButton(CustomButton* hot_button) {
+ menu_controller_->SetHotTrackedButton(hot_button);
+ }
+
+ void ExitMenuRun() {
+ menu_controller_->SetExitType(MenuController::ExitType::EXIT_OUTERMOST);
+ menu_controller_->ExitMenuRun();
+ }
+
private:
+ void DestroyMenuController() {
+ if (!menu_controller_)
+ return;
+
+ if (!owner_->IsClosed())
+ owner_->RemoveObserver(menu_controller_);
+
+ menu_controller_->showing_ = false;
+ menu_controller_->owner_ = nullptr;
+ delete menu_controller_;
+ menu_controller_ = nullptr;
+ }
+
void Init() {
owner_.reset(new Widget);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -436,14 +497,7 @@ class MenuControllerTest : public ViewsTestBase {
new ui::test::EventGenerator(GetContext(), owner_->GetNativeWindow()));
owner_->Show();
-#if defined(OS_WIN)
- dispatcher_client_.reset(new DesktopDispatcherClient);
- aura::client::SetDispatcherClient(owner_->GetNativeView()->GetRootWindow(),
- dispatcher_client_.get());
-#endif
-
SetupMenuItem();
-
SetupMenuController();
}
@@ -467,10 +521,6 @@ class MenuControllerTest : public ViewsTestBase {
menu_item_->SetController(menu_controller_);
}
-#if defined(OS_WIN)
- scoped_ptr<aura::client::DispatcherClient> dispatcher_client_;
-#endif
-
scoped_ptr<Widget> owner_;
scoped_ptr<ui::test::EventGenerator> event_generator_;
scoped_ptr<TestMenuItemViewShown> menu_item_;
@@ -685,6 +735,176 @@ TEST_F(MenuControllerTest, SelectByChar) {
ResetSelection();
}
+TEST_F(MenuControllerTest, SelectChildButtonView) {
+ AddButtonMenuItems();
+ View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
+ ASSERT_NE(nullptr, buttons_view);
+ CustomButton* button1 =
+ CustomButton::AsCustomButton(buttons_view->child_at(0));
+ ASSERT_NE(nullptr, button1);
+ CustomButton* button2 =
+ CustomButton::AsCustomButton(buttons_view->child_at(1));
+ ASSERT_NE(nullptr, button2);
+ CustomButton* button3 =
+ CustomButton::AsCustomButton(buttons_view->child_at(2));
+ ASSERT_NE(nullptr, button2);
+
+ // Handle searching for 'f'; should find "Four".
+ SelectByChar('f');
+ EXPECT_EQ(4, pending_state_item()->GetCommand());
+
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_FALSE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Move selection to |button1|.
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_TRUE(button1->IsHotTracked());
+ EXPECT_FALSE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Move selection to |button2|.
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Move selection to |button3|.
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_FALSE(button2->IsHotTracked());
+ EXPECT_TRUE(button3->IsHotTracked());
+
+ // Move a mouse to hot track the |button1|.
+ SubmenuView* sub_menu = menu_item()->GetSubmenu();
+ gfx::Point location(button1->GetBoundsInScreen().CenterPoint());
+ View::ConvertPointFromScreen(sub_menu->GetScrollViewContainer(), &location);
+ ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
+ ui::EventTimeForNow(), 0, 0);
+ ProcessMouseMoved(sub_menu, event);
+
+ // Incrementing selection should move hot tracking to the second button (next
+ // after the first button).
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Increment selection twice to wrap around.
+ IncrementSelection();
+ IncrementSelection();
+ EXPECT_EQ(1, pending_state_item()->GetCommand());
+
+ // Clear references in menu controller to the menu item that is going away.
+ ResetSelection();
+}
+
+TEST_F(MenuControllerTest, DeleteChildButtonView) {
+ AddButtonMenuItems();
+
+ // Handle searching for 'f'; should find "Four".
+ SelectByChar('f');
+ EXPECT_EQ(4, pending_state_item()->GetCommand());
+
+ View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
+ ASSERT_NE(nullptr, buttons_view);
+ CustomButton* button1 =
+ CustomButton::AsCustomButton(buttons_view->child_at(0));
+ ASSERT_NE(nullptr, button1);
+ CustomButton* button2 =
+ CustomButton::AsCustomButton(buttons_view->child_at(1));
+ ASSERT_NE(nullptr, button2);
+ CustomButton* button3 =
+ CustomButton::AsCustomButton(buttons_view->child_at(2));
+ ASSERT_NE(nullptr, button2);
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_FALSE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Increment twice to move selection to |button2|.
+ IncrementSelection();
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Delete |button2| while it is hot-tracked.
+ // This should update MenuController via ViewHierarchyChanged and reset
+ // |hot_button_|.
+ delete button2;
+
+ // Incrementing selection should now set hot-tracked item to |button1|.
+ // It should not crash.
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_TRUE(button1->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+}
+
+// Creates a menu with CustomButton child views, simulates running a nested
+// menu and tests that existing the nested run restores hot-tracked child view.
+TEST_F(MenuControllerTest, ChildButtonHotTrackedWhenNested) {
+ AddButtonMenuItems();
+
+ // Handle searching for 'f'; should find "Four".
+ SelectByChar('f');
+ EXPECT_EQ(4, pending_state_item()->GetCommand());
+
+ View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
+ ASSERT_NE(nullptr, buttons_view);
+ CustomButton* button1 =
+ CustomButton::AsCustomButton(buttons_view->child_at(0));
+ ASSERT_NE(nullptr, button1);
+ CustomButton* button2 =
+ CustomButton::AsCustomButton(buttons_view->child_at(1));
+ ASSERT_NE(nullptr, button2);
+ CustomButton* button3 =
+ CustomButton::AsCustomButton(buttons_view->child_at(2));
+ ASSERT_NE(nullptr, button2);
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_FALSE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+
+ // Increment twice to move selection to |button2|.
+ IncrementSelection();
+ IncrementSelection();
+ EXPECT_EQ(5, pending_state_item()->GetCommand());
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_FALSE(button3->IsHotTracked());
+ EXPECT_EQ(button2, GetHotButton());
+
+ MenuController* controller = menu_controller();
+ controller->SetAsyncRun(true);
+ int mouse_event_flags = 0;
+ MenuItemView* run_result =
+ controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
+ MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
+ EXPECT_EQ(run_result, nullptr);
+
+ // |button2| should stay in hot-tracked state but menu controller should not
+ // track it anymore (preventing resetting hot-tracked state when changing
+ // selection while a nested run is active).
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_EQ(nullptr, GetHotButton());
+
+ // Setting hot-tracked button while nested should get reverted when nested
+ // menu run ends.
+ SetHotTrackedButton(button1);
+ EXPECT_TRUE(button1->IsHotTracked());
+ EXPECT_EQ(button1, GetHotButton());
+
+ ExitMenuRun();
+ EXPECT_FALSE(button1->IsHotTracked());
+ EXPECT_TRUE(button2->IsHotTracked());
+ EXPECT_EQ(button2, GetHotButton());
+}
+
// Tests that a menu opened asynchronously, will notify its
// MenuControllerDelegate when Accept is called.
TEST_F(MenuControllerTest, AsynchronousAccept) {
@@ -859,7 +1079,7 @@ TEST_F(MenuControllerTest, AsynchronousRepostEvent) {
false, false, &mouse_event_flags);
EXPECT_EQ(run_result, nullptr);
- // Show a sub menu to targert with a pointer selection. However have the event
+ // Show a sub menu to target with a pointer selection. However have the event
// occur outside of the bounds of the entire menu.
SubmenuView* sub_menu = item->GetSubmenu();
sub_menu->ShowAt(owner(), item->bounds(), false);
@@ -890,7 +1110,7 @@ TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) {
TestMenuControllerDelegate* delegate = menu_controller_delegate();
controller->SetAsyncRun(true);
- // Show a sub menu to targert with a touch event. However have the event occur
+ // Show a sub menu to target with a touch event. However have the event occur
// outside of the bounds of the entire menu.
MenuItemView* item = menu_item();
SubmenuView* sub_menu = item->GetSubmenu();
@@ -936,5 +1156,87 @@ TEST_F(MenuControllerTest, AsynchronousNestedExitOutermost) {
RunMenu();
}
+// Tests that having the MenuController deleted during RepostEvent does not
+// cause a crash. ASAN bots should not detect use-after-free in MenuController.
+TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) {
+ MenuController* controller = menu_controller();
+ scoped_ptr<TestMenuControllerDelegate> nested_delegate(
+ new TestMenuControllerDelegate());
+
+ ASSERT_FALSE(IsAsyncRun());
+
+ controller->AddNestedDelegate(nested_delegate.get());
+ controller->SetAsyncRun(true);
+
+ EXPECT_TRUE(IsAsyncRun());
+ EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
+
+ MenuItemView* item = menu_item();
+ int mouse_event_flags = 0;
+ MenuItemView* run_result =
+ controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
+ false, false, &mouse_event_flags);
+ EXPECT_EQ(run_result, nullptr);
+
+ // Show a sub menu to target with a pointer selection. However have the event
+ // occur outside of the bounds of the entire menu.
+ SubmenuView* sub_menu = item->GetSubmenu();
+ sub_menu->ShowAt(owner(), item->bounds(), true);
+ gfx::Point location(sub_menu->bounds().bottom_right());
+ location.Offset(1, 1);
+ ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location,
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
+
+ // This will lead to MenuController being deleted during the event repost.
+ // The remainder of this test, and TearDown should not crash.
+ DestroyMenuControllerOnMenuClosed(nested_delegate.get());
+ // When attempting to select outside of all menus this should lead to a
+ // shutdown. This should not crash while attempting to repost the event.
+ SetSelectionOnPointerDown(sub_menu, &event);
+
+ // Close to remove observers before test TearDown
+ sub_menu->Close();
+ EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
+}
+
+// Tests that having the MenuController deleted during OnGestureEvent does not
+// cause a crash. ASAN bots should not detect use-after-free in MenuController.
+TEST_F(MenuControllerTest, AsynchronousGestureDeletesController) {
+ MenuController* controller = menu_controller();
+ scoped_ptr<TestMenuControllerDelegate> nested_delegate(
+ new TestMenuControllerDelegate());
+ ASSERT_FALSE(IsAsyncRun());
+
+ controller->AddNestedDelegate(nested_delegate.get());
+ controller->SetAsyncRun(true);
+
+ EXPECT_TRUE(IsAsyncRun());
+ EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
+
+ MenuItemView* item = menu_item();
+ int mouse_event_flags = 0;
+ MenuItemView* run_result =
+ controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
+ false, false, &mouse_event_flags);
+ EXPECT_EQ(run_result, nullptr);
+
+ // Show a sub menu to target with a tap event.
+ SubmenuView* sub_menu = item->GetSubmenu();
+ sub_menu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), true);
+
+ gfx::Point location(sub_menu->bounds().CenterPoint());
+ ui::GestureEvent event(location.x(), location.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_TAP));
+
+ // This will lead to MenuController being deleted during the processing of the
+ // gesture event. The remainder of this test, and TearDown should not crash.
+ DestroyMenuControllerOnMenuClosed(nested_delegate.get());
+ controller->OnGestureEvent(sub_menu, &event);
+
+ // Close to remove observers before test TearDown
+ sub_menu->Close();
+ EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_event_dispatcher.cc b/chromium/ui/views/controls/menu/menu_event_dispatcher.cc
deleted file mode 100644
index 9b7c231b939..00000000000
--- a/chromium/ui/views/controls/menu/menu_event_dispatcher.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_event_dispatcher.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_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 &&
- ui_event && should_process_event) {
- switch (ui_event->type()) {
- case ui::ET_KEY_PRESSED: {
- should_perform_default = false;
-
- ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(ui_event.get());
- menu_controller_->OnKeyDown(key_event->key_code());
- if (menu_controller_->exit_type() != MenuController::EXIT_NONE)
- break;
-
- // Do not check mnemonics if the Alt or Ctrl modifiers are pressed.
- int flags = key_event->flags();
- if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) {
- char c = ui::DomCodeToUsLayoutCharacter(key_event->code(), flags);
- menu_controller_->SelectByChar(c);
- }
- break;
- }
- case ui::ET_KEY_RELEASED:
- should_perform_default = false;
- break;
- case ui::ET_TOUCH_RELEASED:
- case ui::ET_TOUCH_CANCELLED:
- // Don't allow the event copy to clear the native touch id
- // mapping, or we'll lose the mapping before the initial event
- // has finished being dispatched.
- static_cast<ui::TouchEvent*>(ui_event.get())
- ->set_should_remove_native_touch_id_mapping(false);
- break;
- default:
- break;
- }
- }
-
- menu_controller_->TerminateNestedMessageLoopIfNecessary();
-
- 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.h b/chromium/ui/views/controls/menu/menu_event_dispatcher.h
deleted file mode 100644
index 6b9e8e38b04..00000000000
--- a/chromium/ui/views/controls/menu/menu_event_dispatcher.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_MENU_MENU_EVENT_DISPATCHER_H_
-#define UI_VIEWS_CONTROLS_MENU_MENU_EVENT_DISPATCHER_H_
-
-#include <stdint.h>
-
-#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);
- ~MenuEventDispatcher() override;
-
- private:
- // ui::PlatformEventDispatcher:
- bool CanDispatchEvent(const ui::PlatformEvent& event) override;
- uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
-
- MenuController* menu_controller_;
-
- DISALLOW_COPY_AND_ASSIGN(MenuEventDispatcher);
-};
-
-} // namespace internal
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_MENU_MENU_EVENT_DISPATCHER_H_
diff --git a/chromium/ui/views/controls/menu/menu_image_util.cc b/chromium/ui/views/controls/menu/menu_image_util.cc
index f6398865bc0..55f6e551c2f 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.cc
+++ b/chromium/ui/views/controls/menu/menu_image_util.cc
@@ -4,11 +4,10 @@
#include "ui/views/controls/menu/menu_image_util.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
-#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/material_design/material_design_controller.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icons_public.h"
-#include "ui/views/resources/grit/views_resources.h"
namespace views {
@@ -17,10 +16,14 @@ gfx::ImageSkia GetMenuCheckImage(SkColor icon_color) {
icon_color);
}
-gfx::ImageSkia GetRadioButtonImage(bool selected) {
- int image_id = selected ? IDR_MENU_RADIO_SELECTED : IDR_MENU_RADIO_EMPTY;
- return ui::ResourceBundle::GetSharedInstance().GetImageNamed(image_id).
- AsImageSkia();
+gfx::ImageSkia GetRadioButtonImage(bool toggled,
+ bool hovered,
+ SkColor default_icon_color) {
+ gfx::VectorIconId id = toggled ? gfx::VectorIconId::MENU_RADIO_SELECTED
+ : gfx::VectorIconId::MENU_RADIO_EMPTY;
+ SkColor color =
+ toggled && !hovered ? gfx::kGoogleBlue500 : default_icon_color;
+ return gfx::CreateVectorIcon(id, kMenuCheckSize, color);
}
gfx::ImageSkia GetSubmenuArrowImage(SkColor icon_color) {
diff --git a/chromium/ui/views/controls/menu/menu_image_util.h b/chromium/ui/views/controls/menu/menu_image_util.h
index cd7a352f8ff..5097c4852f9 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.h
+++ b/chromium/ui/views/controls/menu/menu_image_util.h
@@ -17,10 +17,13 @@ const int kSubmenuArrowSize = 8;
// Returns the Menu Check box image (always checked).
gfx::ImageSkia GetMenuCheckImage(SkColor icon_color);
-// Return the RadioButton image for given state.
-// It returns the "selected" image when |selected| is
-// true, or the "unselected" image if false.
-gfx::ImageSkia GetRadioButtonImage(bool selected);
+// Return the RadioButton image for given state. |toggled| is true when
+// the radio option is active, |hovered| describes the menu higlight/selection
+// state, and |default_icon_color| is the base color that should be used for
+// the icon (which may be ignored based on the other two flags).
+gfx::ImageSkia GetRadioButtonImage(bool toggled,
+ bool hovered,
+ SkColor default_icon_color);
// Returns the image for submenu arrow for current RTL setting.
gfx::ImageSkia GetSubmenuArrowImage(SkColor icon_color);
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index 5721126cb4c..8e3013b1197 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -12,8 +12,8 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/models/menu_model.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect.h"
@@ -547,7 +547,7 @@ void MenuItemView::Layout() {
continue;
int width = child->GetPreferredSize().width();
child->SetBounds(x - width, 0, width, height());
- x -= width - kChildXPadding;
+ x -= width + kChildXPadding;
}
// Position |icon_view|.
const MenuConfig& config = MenuConfig::instance();
@@ -815,8 +815,8 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
AdjustBoundsForRTLUI(&check_bounds);
canvas->DrawImageInt(check, check_bounds.x(), check_bounds.y());
} else if (type_ == RADIO) {
- gfx::ImageSkia image =
- GetRadioButtonImage(delegate->IsItemChecked(GetCommand()));
+ gfx::ImageSkia image = GetRadioButtonImage(
+ delegate->IsItemChecked(GetCommand()), render_selection, icon_color);
gfx::Rect radio_bounds(icon_x,
top_margin + (available_height - image.height()) / 2,
image.width(),
diff --git a/chromium/ui/views/controls/menu/menu_key_event_handler.cc b/chromium/ui/views/controls/menu/menu_key_event_handler.cc
index fc110b5ab1b..af0566e2af9 100644
--- a/chromium/ui/views/controls/menu/menu_key_event_handler.cc
+++ b/chromium/ui/views/controls/menu/menu_key_event_handler.cc
@@ -5,7 +5,6 @@
#include "ui/views/controls/menu/menu_key_event_handler.h"
#include "ui/aura/env.h"
-#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/views_delegate.h"
@@ -45,16 +44,24 @@ void MenuKeyEventHandler::OnKeyEvent(ui::KeyEvent* event) {
return;
}
+ event->StopPropagation();
+
if (event->type() == ui::ET_KEY_PRESSED) {
menu_controller->OnKeyDown(event->key_code());
+ // Menu controller might have been deleted.
+ if (!MenuController::GetActiveInstance())
+ return;
// Do not check mnemonics if the Alt or Ctrl modifiers are pressed. For
// example Ctrl+<T> is an accelerator, but <T> only is a mnemonic.
const int flags = event->flags();
if (menu_controller->exit_type() == MenuController::EXIT_NONE &&
(flags & kKeyFlagsMask) == 0) {
- char c = ui::DomCodeToUsLayoutCharacter(event->code(), flags);
+ base::char16 c = event->GetCharacter();
menu_controller->SelectByChar(c);
+ // Menu controller might have been deleted.
+ if (!MenuController::GetActiveInstance())
+ return;
}
}
@@ -66,8 +73,6 @@ void MenuKeyEventHandler::OnKeyEvent(ui::KeyEvent* event) {
if (result == ViewsDelegate::ProcessMenuAcceleratorResult::CLOSE_MENU)
menu_controller->CancelAll();
}
-
- event->StopPropagation();
}
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_aura.cc b/chromium/ui/views/controls/menu/menu_message_loop_aura.cc
index 25d531a2be2..f2653751716 100644
--- a/chromium/ui/views/controls/menu/menu_message_loop_aura.cc
+++ b/chromium/ui/views/controls/menu/menu_message_loop_aura.cc
@@ -15,19 +15,12 @@
#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/controls/menu/menu_key_event_handler.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_key_event_handler.h"
-#endif
using aura::client::ScreenPositionClient;
@@ -139,44 +132,18 @@ void MenuMessageLoopAura::Run(MenuController* controller,
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::MessageLoop* loop = base::MessageLoop::current();
- base::MessageLoop::ScopedNestableTaskAllower allow(loop);
- base::RunLoop run_loop(&nested_dispatcher);
- message_loop_quit_ = run_loop.QuitClosure();
- run_loop.Run();
- }
-#else
scoped_ptr<ActivationChangeObserverImpl> observer;
if (root) {
if (!nested_menu)
observer.reset(new ActivationChangeObserverImpl(controller, root));
}
- scoped_ptr<MenuKeyEventHandler> menu_event_filter;
- if (!nested_menu) {
- // If this is a nested menu, then the MenuKeyEventHandler would have been
- // created already in the top parent menu. So no need to recreate it here.
- menu_event_filter.reset(new MenuKeyEventHandler);
- }
-
base::MessageLoop* loop = base::MessageLoop::current();
base::MessageLoop::ScopedNestableTaskAllower allow(loop);
base::RunLoop run_loop;
message_loop_quit_ = run_loop.QuitClosure();
run_loop.Run();
-#endif // defined(OS_WIN)
}
void MenuMessageLoopAura::QuitNow() {
diff --git a/chromium/ui/views/controls/menu/menu_message_loop_aura.h b/chromium/ui/views/controls/menu/menu_message_loop_aura.h
index bdb8352249f..fce8858dd09 100644
--- a/chromium/ui/views/controls/menu/menu_message_loop_aura.h
+++ b/chromium/ui/views/controls/menu/menu_message_loop_aura.h
@@ -11,10 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "ui/views/controls/menu/menu_message_loop.h"
-namespace base {
-class MessagePumpDispatcher;
-}
-
namespace ui {
class ScopedEventDispatcher;
}
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
deleted file mode 100644
index fedb10e85ef..00000000000
--- a/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/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_perform_default = true;
- if (menu_controller_->exit_type() != MenuController::EXIT_ALL &&
- menu_controller_->exit_type() != MenuController::EXIT_DESTROYED) {
- // 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_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: {
- menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(msg));
- TranslateMessage(&msg);
- should_perform_default = false;
- break;
- }
- case WM_CHAR: {
- 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_perform_default = false;
- break;
-
- case WM_CANCELMODE:
- case WM_SYSKEYDOWN:
- // Exit immediately on system keys.
- menu_controller_->Cancel(MenuController::EXIT_ALL);
- should_perform_default = false;
- break;
-
- default:
- break;
- }
- }
-
- menu_controller_->TerminateNestedMessageLoopIfNecessary();
- 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
deleted file mode 100644
index 44a0aade790..00000000000
--- a/chromium/ui/views/controls/menu/menu_message_pump_dispatcher_win.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_WIN_H_
-#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_WIN_H_
-
-#include <stdint.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);
- ~MenuMessagePumpDispatcher() override;
-
- private:
- // base::MessagePumpDispatcher:
- 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 f18d86fd34a..b63f9866774 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter.cc
+++ b/chromium/ui/views/controls/menu/menu_model_adapter.cc
@@ -13,9 +13,14 @@
namespace views {
MenuModelAdapter::MenuModelAdapter(ui::MenuModel* menu_model)
+ : MenuModelAdapter(menu_model, base::Closure() /*null callback*/) {}
+
+MenuModelAdapter::MenuModelAdapter(ui::MenuModel* menu_model,
+ const base::Closure& on_menu_closed_callback)
: menu_model_(menu_model),
triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON |
- ui::EF_RIGHT_MOUSE_BUTTON) {
+ ui::EF_RIGHT_MOUSE_BUTTON),
+ on_menu_closed_callback_(on_menu_closed_callback) {
DCHECK(menu_model);
}
@@ -264,6 +269,12 @@ void MenuModelAdapter::WillHideMenu(MenuItemView* menu) {
NOTREACHED();
}
+void MenuModelAdapter::OnMenuClosed(MenuItemView* menu,
+ MenuRunner::RunResult result) {
+ if (!on_menu_closed_callback_.is_null())
+ on_menu_closed_callback_.Run();
+}
+
// MenuModelAdapter, private:
void MenuModelAdapter::BuildMenuImpl(MenuItemView* menu, ui::MenuModel* model) {
diff --git a/chromium/ui/views/controls/menu/menu_model_adapter.h b/chromium/ui/views/controls/menu/menu_model_adapter.h
index ecc4f1e4c02..c9799daadb3 100644
--- a/chromium/ui/views/controls/menu/menu_model_adapter.h
+++ b/chromium/ui/views/controls/menu/menu_model_adapter.h
@@ -7,6 +7,7 @@
#include <map>
+#include "base/callback.h"
#include "base/macros.h"
#include "ui/views/controls/menu/menu_delegate.h"
@@ -24,6 +25,8 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate {
// The caller retains ownership of the ui::MenuModel instance and
// must ensure it exists for the lifetime of the adapter.
explicit MenuModelAdapter(ui::MenuModel* menu_model);
+ MenuModelAdapter(ui::MenuModel* menu_model,
+ const base::Closure& on_menu_closed_callback);
~MenuModelAdapter() override;
// Populate a MenuItemView menu with the ui::MenuModel items
@@ -75,6 +78,7 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate {
void SelectionChanged(MenuItemView* menu) override;
void WillShowMenu(MenuItemView* menu) override;
void WillHideMenu(MenuItemView* menu) override;
+ void OnMenuClosed(MenuItemView* menu, MenuRunner::RunResult result) override;
private:
// Implementation of BuildMenu().
@@ -91,6 +95,9 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate {
// Map MenuItems to MenuModels. Used to implement WillShowMenu().
std::map<MenuItemView*, ui::MenuModel*> menu_map_;
+ // Optional callback triggered during OnMenuClosed().
+ base::Closure on_menu_closed_callback_;
+
DISALLOW_COPY_AND_ASSIGN(MenuModelAdapter);
};
diff --git a/chromium/ui/views/controls/menu/menu_runner.h b/chromium/ui/views/controls/menu/menu_runner.h
index 4011ece96da..ea2438ee980 100644
--- a/chromium/ui/views/controls/menu/menu_runner.h
+++ b/chromium/ui/views/controls/menu/menu_runner.h
@@ -120,7 +120,7 @@ class VIEWS_EXPORT MenuRunner {
MenuButton* button,
const gfx::Rect& bounds,
MenuAnchorPosition anchor,
- ui::MenuSourceType source_type) WARN_UNUSED_RESULT;
+ ui::MenuSourceType source_type);
// Returns true if we're in a nested message loop running the menu.
bool IsRunning() const;
diff --git a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index d25a6628b47..73e02eca385 100644
--- a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -23,6 +23,10 @@ class TestModel : public ui::SimpleMenuModel {
void set_checked_command(int command) { checked_command_ = command; }
+ void set_menu_open_callback(const base::Closure& callback) {
+ menu_open_callback_ = callback;
+ }
+
private:
class Delegate : public ui::SimpleMenuModel::Delegate {
public:
@@ -37,6 +41,10 @@ class TestModel : public ui::SimpleMenuModel {
}
void ExecuteCommand(int command_id, int event_flags) override {}
+ void MenuWillShow(SimpleMenuModel* source) override {
+ model_->menu_open_callback_.Run();
+ }
+
private:
TestModel* model_;
@@ -46,6 +54,7 @@ class TestModel : public ui::SimpleMenuModel {
private:
int checked_command_ = -1;
Delegate delegate_;
+ base::Closure menu_open_callback_;
DISALLOW_COPY_AND_ASSIGN(TestModel);
};
@@ -89,14 +98,13 @@ class MenuRunnerCocoaTest : public ViewsTestBase {
ViewsTestBase::TearDown();
}
- // Runs the menu after scheduling |block| on the run loop.
- MenuRunner::RunResult RunMenu(dispatch_block_t block) {
- CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{
- EXPECT_TRUE(runner_->IsRunning());
- block();
- });
- return runner_->RunMenuAt(parent_, NULL, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
- MenuRunner::CONTEXT_MENU);
+ // Runs the menu after registering |callback| as the menu open callback.
+ MenuRunner::RunResult RunMenu(const base::Closure& callback) {
+ menu_->set_menu_open_callback(
+ base::Bind(&MenuRunnerCocoaTest::RunMenuWrapperCallback,
+ base::Unretained(this), callback));
+ return runner_->RunMenuAt(parent_, nullptr, gfx::Rect(),
+ MENU_ANCHOR_TOPLEFT, MenuRunner::CONTEXT_MENU);
}
// Runs then cancels a combobox menu and captures the frame of the anchoring
@@ -107,12 +115,10 @@ class MenuRunnerCocoaTest : public ViewsTestBase {
// Should be one child (the compositor layer) before showing, and it should
// go up by one (the anchor view) while the menu is shown.
EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]);
- CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{
- NSArray* subviews = [parent_->GetNativeView() subviews];
- EXPECT_EQ(2u, [subviews count]);
- last_anchor_frame_ = [[subviews objectAtIndex:1] frame];
- runner_->Cancel();
- });
+
+ menu_->set_menu_open_callback(base::Bind(
+ &MenuRunnerCocoaTest::RunMenuAtCallback, base::Unretained(this)));
+
MenuRunner::RunResult result = runner_->RunMenuAt(
parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT, MenuRunner::COMBOBOX);
@@ -121,6 +127,16 @@ class MenuRunnerCocoaTest : public ViewsTestBase {
return result;
}
+ void MenuCancelCallback() {
+ runner_->Cancel();
+ EXPECT_FALSE(runner_->IsRunning());
+ }
+
+ void MenuDeleteCallback() {
+ runner_->Release();
+ runner_ = nullptr;
+ }
+
protected:
scoped_ptr<TestModel> menu_;
internal::MenuRunnerImplCocoa* runner_ = nullptr;
@@ -128,16 +144,26 @@ class MenuRunnerCocoaTest : public ViewsTestBase {
NSRect last_anchor_frame_ = NSZeroRect;
private:
+ void RunMenuWrapperCallback(const base::Closure& callback) {
+ EXPECT_TRUE(runner_->IsRunning());
+ callback.Run();
+ }
+
+ void RunMenuAtCallback() {
+ NSArray* subviews = [parent_->GetNativeView() subviews];
+ EXPECT_EQ(2u, [subviews count]);
+ last_anchor_frame_ = [[subviews objectAtIndex:1] frame];
+ runner_->Cancel();
+ }
+
DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest);
};
TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) {
base::TimeDelta min_time = ui::EventTimeForNow();
- MenuRunner::RunResult result = RunMenu(^{
- runner_->Cancel();
- EXPECT_FALSE(runner_->IsRunning());
- });
+ MenuRunner::RunResult result = RunMenu(base::Bind(
+ &MenuRunnerCocoaTest::MenuCancelCallback, base::Unretained(this)));
EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
EXPECT_FALSE(runner_->IsRunning());
@@ -151,19 +177,15 @@ TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) {
}
TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) {
- MenuRunner::RunResult result = RunMenu(^{
- runner_->Release();
- runner_ = NULL;
- });
-
+ MenuRunner::RunResult result = RunMenu(base::Bind(
+ &MenuRunnerCocoaTest::MenuDeleteCallback, base::Unretained(this)));
EXPECT_EQ(MenuRunner::MENU_DELETED, result);
}
TEST_F(MenuRunnerCocoaTest, RunMenuTwice) {
for (int i = 0; i < 2; ++i) {
- MenuRunner::RunResult result = RunMenu(^{
- runner_->Cancel();
- });
+ MenuRunner::RunResult result = RunMenu(base::Bind(
+ &MenuRunnerCocoaTest::MenuCancelCallback, base::Unretained(this)));
EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
EXPECT_FALSE(runner_->IsRunning());
}
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.cc b/chromium/ui/views/controls/menu/menu_runner_impl.cc
index d02f7de1eff..b48edcdd129 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.cc
@@ -88,8 +88,12 @@ MenuRunner::RunResult MenuRunnerImpl::RunMenuAt(Widget* parent,
if (!controller->IsBlockingRun()) {
controller->CancelAll();
controller = NULL;
+ } else {
+ // Only nest the delegate when not cancelling drag-and-drop. When
+ // cancelling this will become the root delegate of the new
+ // MenuController
+ controller->AddNestedDelegate(this);
}
- controller->AddNestedDelegate(this);
} else {
// There's some other menu open and we're not nested. Cancel the menu.
controller->CancelAll();
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm b/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
index 47547814cf8..454c951817b 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
+++ b/chromium/ui/views/controls/menu/menu_runner_impl_cocoa.mm
@@ -4,6 +4,7 @@
#import "ui/views/controls/menu/menu_runner_impl_cocoa.h"
+#include "base/mac/sdk_forward_declarations.h"
#import "ui/base/cocoa/menu_controller.h"
#include "ui/base/models/menu_model.h"
#include "ui/events/event_utils.h"
@@ -41,7 +42,7 @@ base::scoped_nsobject<NSView> CreateMenuAnchorView(
const gfx::Rect& screen_bounds,
NSMenuItem* checked_item) {
NSRect rect = gfx::ScreenRectToNSRect(screen_bounds);
- rect.origin = [window convertScreenToBase:rect.origin];
+ rect = [window convertRectFromScreen:rect];
rect = [[window contentView] convertRect:rect fromView:nil];
// If there's no checked item (e.g. Combobox::STYLE_ACTION), NSMenu will
diff --git a/chromium/ui/views/controls/menu/menu_runner_unittest.cc b/chromium/ui/views/controls/menu/menu_runner_unittest.cc
index b8e1528931e..49ba8832a1e 100644
--- a/chromium/ui/views/controls/menu/menu_runner_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_unittest.cc
@@ -8,10 +8,13 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
#include "ui/base/ui_base_types.h"
+#include "ui/events/test/event_generator.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_types.h"
+#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
@@ -19,22 +22,28 @@ namespace views {
namespace test {
// Implementation of MenuDelegate that only reports the values of calls to
-// OnMenuClosed.
+// OnMenuClosed and ExecuteCommand.
class TestMenuDelegate : public MenuDelegate {
public:
TestMenuDelegate();
~TestMenuDelegate() override;
- int on_menu_closed_called() { return on_menu_closed_called_; }
- MenuItemView* on_menu_closed_menu() { return on_menu_closed_menu_; }
- MenuRunner::RunResult on_menu_closed_run_result() {
+ int execute_command_id() const { return execute_command_id_; }
+
+ int on_menu_closed_called() const { return on_menu_closed_called_; }
+ MenuItemView* on_menu_closed_menu() const { return on_menu_closed_menu_; }
+ MenuRunner::RunResult on_menu_closed_run_result() const {
return on_menu_closed_run_result_;
}
// MenuDelegate:
+ void ExecuteCommand(int id) override;
void OnMenuClosed(MenuItemView* menu, MenuRunner::RunResult result) override;
private:
+ // ID of last executed command.
+ int execute_command_id_;
+
// The number of times OnMenuClosed was called.
int on_menu_closed_called_;
@@ -46,12 +55,17 @@ class TestMenuDelegate : public MenuDelegate {
};
TestMenuDelegate::TestMenuDelegate()
- : on_menu_closed_called_(0),
+ : execute_command_id_(0),
+ on_menu_closed_called_(0),
on_menu_closed_menu_(nullptr),
on_menu_closed_run_result_(MenuRunner::MENU_DELETED) {}
TestMenuDelegate::~TestMenuDelegate() {}
+void TestMenuDelegate::ExecuteCommand(int id) {
+ execute_command_id_ = id;
+}
+
void TestMenuDelegate::OnMenuClosed(MenuItemView* menu,
MenuRunner::RunResult result) {
on_menu_closed_called_++;
@@ -100,6 +114,9 @@ void MenuRunnerTest::SetUp() {
ViewsTestBase::SetUp();
menu_delegate_.reset(new TestMenuDelegate);
menu_item_view_ = new MenuItemView(menu_delegate_.get());
+ menu_item_view_->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
+ menu_item_view_->AppendMenuItemWithLabel(2,
+ base::WideToUTF16(L"\x062f\x0648"));
owner_.reset(new Widget);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -132,5 +149,91 @@ TEST_F(MenuRunnerTest, AsynchronousRun) {
EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result());
}
+// Tests that when a menu is run asynchronously, key events are handled properly
+// by testing that Escape key closes the menu.
+TEST_F(MenuRunnerTest, AsynchronousKeyEventHandling) {
+ InitMenuRunner(MenuRunner::ASYNC);
+ MenuRunner* runner = menu_runner();
+ MenuRunner::RunResult result = runner->RunMenuAt(
+ owner(), nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
+ EXPECT_TRUE(runner->IsRunning());
+
+ ui::test::EventGenerator generator(GetContext(), owner()->GetNativeWindow());
+ generator.PressKey(ui::VKEY_ESCAPE, 0);
+ EXPECT_FALSE(runner->IsRunning());
+ TestMenuDelegate* delegate = menu_delegate();
+ EXPECT_EQ(1, delegate->on_menu_closed_called());
+ EXPECT_EQ(nullptr, delegate->on_menu_closed_menu());
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result());
+}
+
+// Tests that a key press on a US keyboard layout activates the correct menu
+// item.
+TEST_F(MenuRunnerTest, LatinMnemonic) {
+ InitMenuRunner(MenuRunner::ASYNC);
+ MenuRunner* runner = menu_runner();
+ MenuRunner::RunResult result = runner->RunMenuAt(
+ owner(), nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
+ EXPECT_TRUE(runner->IsRunning());
+
+ ui::test::EventGenerator generator(GetContext(), owner()->GetNativeWindow());
+ generator.PressKey(ui::VKEY_O, 0);
+ EXPECT_FALSE(runner->IsRunning());
+ TestMenuDelegate* delegate = menu_delegate();
+ EXPECT_EQ(1, delegate->execute_command_id());
+ EXPECT_EQ(1, delegate->on_menu_closed_called());
+ EXPECT_NE(nullptr, delegate->on_menu_closed_menu());
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result());
+}
+
+// Tests that a key press on a non-US keyboard layout activates the correct menu
+// item.
+TEST_F(MenuRunnerTest, NonLatinMnemonic) {
+ InitMenuRunner(MenuRunner::ASYNC);
+ MenuRunner* runner = menu_runner();
+ MenuRunner::RunResult result = runner->RunMenuAt(
+ owner(), nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
+ EXPECT_TRUE(runner->IsRunning());
+
+ ui::test::EventGenerator generator(GetContext(), owner()->GetNativeWindow());
+ ui::KeyEvent key_press(0x062f, ui::VKEY_N, 0);
+ generator.Dispatch(&key_press);
+ EXPECT_FALSE(runner->IsRunning());
+ TestMenuDelegate* delegate = menu_delegate();
+ EXPECT_EQ(2, delegate->execute_command_id());
+ EXPECT_EQ(1, delegate->on_menu_closed_called());
+ EXPECT_NE(nullptr, delegate->on_menu_closed_menu());
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result());
+}
+
+// Tests that attempting to nest a menu within a drag-and-drop menu does not
+// cause a crash. Instead the drag and drop action should be canceled, and the
+// new menu should be openned.
+TEST_F(MenuRunnerTest, NestingDuringDrag) {
+ InitMenuRunner(MenuRunner::FOR_DROP);
+ MenuRunner* runner = menu_runner();
+ MenuRunner::RunResult result = runner->RunMenuAt(
+ owner(), nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
+ EXPECT_TRUE(runner->IsRunning());
+
+ scoped_ptr<TestMenuDelegate> nested_delegate(new TestMenuDelegate);
+ MenuItemView* nested_menu = new MenuItemView(nested_delegate.get());
+ scoped_ptr<MenuRunner> nested_runner(
+ new MenuRunner(nested_menu, MenuRunner::IS_NESTED | MenuRunner::ASYNC));
+ result = nested_runner->RunMenuAt(owner(), nullptr, gfx::Rect(),
+ MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, result);
+ EXPECT_TRUE(nested_runner->IsRunning());
+ EXPECT_FALSE(runner->IsRunning());
+ TestMenuDelegate* delegate = menu_delegate();
+ EXPECT_EQ(1, delegate->on_menu_closed_called());
+ EXPECT_NE(nullptr, delegate->on_menu_closed_menu());
+ EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result());
+}
+
} // namespace test
} // namespace views
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 05c8caedb55..381bef70f6f 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -76,7 +76,6 @@ class MenuScrollButton : public View {
// The background.
gfx::Rect item_bounds(0, 0, width(), height());
NativeTheme::ExtraParams extra;
- extra.menu_item.is_selected = false;
GetNativeTheme()->Paint(canvas->sk_canvas(),
NativeTheme::kMenuItemBackground,
NativeTheme::kNormal, item_bounds, extra);
@@ -263,9 +262,6 @@ void MenuScrollViewContainer::GetAccessibleState(
// Now change the role.
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->AddStateFlag(ui::AX_STATE_FOCUSED);
}
void MenuScrollViewContainer::OnBoundsChanged(
diff --git a/chromium/ui/views/controls/menu/menu_separator_views.cc b/chromium/ui/views/controls/menu/menu_separator_views.cc
index 357bad8b646..6baae9280cc 100644
--- a/chromium/ui/views/controls/menu/menu_separator_views.cc
+++ b/chromium/ui/views/controls/menu/menu_separator_views.cc
@@ -10,12 +10,6 @@
#include "ui/native_theme/native_theme.h"
#include "ui/views/controls/menu/menu_config.h"
-namespace {
-
-const int kSeparatorHeight = 1;
-
-} // namespace
-
namespace views {
#if !defined(OS_WIN)
@@ -47,9 +41,11 @@ gfx::Size MenuSeparator::GetPreferredSize() const {
gfx::Rect MenuSeparator::GetPaintBounds() {
int pos = 0;
+ const MenuConfig& menu_config = MenuConfig::instance();
+ int separator_thickness = menu_config.separator_thickness;
switch (type_) {
case ui::LOWER_SEPARATOR:
- pos = height() - kSeparatorHeight;
+ pos = height() - separator_thickness;
break;
case ui::SPACING_SEPARATOR:
return gfx::Rect();
@@ -60,8 +56,8 @@ gfx::Rect MenuSeparator::GetPaintBounds() {
break;
}
- gfx::Rect paint_rect(0, pos, width(), kSeparatorHeight);
- if (MenuConfig::instance().use_outer_border)
+ gfx::Rect paint_rect(0, pos, width(), separator_thickness);
+ if (menu_config.use_outer_border)
paint_rect.Inset(1, 0);
return paint_rect;
}
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 2a7d914d684..6bf4ce8a3db 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -138,7 +138,7 @@ void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
}
bool NativeViewHostAura::HasInstalledClip() {
- return clip_rect_;
+ return !!clip_rect_;
}
void NativeViewHostAura::UninstallClip() {
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.mm b/chromium/ui/views/controls/native/native_view_host_mac.mm
index da057fa743a..b3e0cfcd4b6 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -6,18 +6,16 @@
#import <Cocoa/Cocoa.h>
-#include "base/logging.h"
#include "base/mac/foundation_util.h"
-#import "ui/views/cocoa/bridged_content_view.h"
+#import "ui/views/cocoa/bridged_native_widget.h"
#include "ui/views/controls/native/native_view_host.h"
+#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/widget.h"
namespace views {
namespace {
-// Reparents |native_view| to be a child of the native content view of
-// |new_parent|.
-void ReparentNSView(NSView* native_view, Widget* new_parent) {
+void EnsureNativeViewHasNoChildWidgets(NSView* native_view) {
DCHECK(native_view);
// Mac's NativeViewHost has no support for hosting its own child widgets.
// This check is probably overly restrictive, since the Widget containing the
@@ -29,17 +27,6 @@ void ReparentNSView(NSView* native_view, Widget* new_parent) {
Widget::GetAllChildWidgets(native_view, &child_widgets);
CHECK_GE(1u, child_widgets.size()); // 1 (itself) or 0 if detached.
}
-
- if (!new_parent) {
- [native_view removeFromSuperview];
- return;
- }
-
- BridgedContentView* new_superview =
- base::mac::ObjCCastStrict<BridgedContentView>(
- new_parent->GetNativeView());
- DCHECK(new_superview);
- [new_superview addSubview:native_view];
}
} // namespace
@@ -57,7 +44,13 @@ void NativeViewHostMac::AttachNativeView() {
DCHECK(host_->native_view());
DCHECK(!native_view_);
native_view_.reset([host_->native_view() retain]);
- ReparentNSView(host_->native_view(), host_->GetWidget());
+
+ EnsureNativeViewHasNoChildWidgets(native_view_);
+ BridgedNativeWidget* bridge = NativeWidgetMac::GetBridgeForNativeWindow(
+ host_->GetWidget()->GetNativeWindow());
+ DCHECK(bridge);
+ [bridge->ns_view() addSubview:native_view_];
+ bridge->SetAssociationForView(host_, native_view_);
}
void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
@@ -70,7 +63,15 @@ void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
// NativeViewHost::Detach().
DCHECK(!native_view_ || native_view_ == host_->native_view());
[host_->native_view() setHidden:YES];
- ReparentNSView(host_->native_view(), NULL);
+ [host_->native_view() removeFromSuperview];
+
+ EnsureNativeViewHasNoChildWidgets(host_->native_view());
+ BridgedNativeWidget* bridge = NativeWidgetMac::GetBridgeForNativeWindow(
+ host_->GetWidget()->GetNativeWindow());
+ // BridgedNativeWidget can be null when Widget is closing.
+ if (bridge)
+ bridge->ClearAssociationForView(host_);
+
native_view_.reset();
}
diff --git a/chromium/ui/views/controls/progress_bar.cc b/chromium/ui/views/controls/progress_bar.cc
index 0a9fd12a4a3..0278e5b51b0 100644
--- a/chromium/ui/views/controls/progress_bar.cc
+++ b/chromium/ui/views/controls/progress_bar.cc
@@ -82,9 +82,8 @@ void FillRoundRect(gfx::Canvas* canvas,
} else {
p[1].iset(x, y + h);
}
- skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
- p, colors, points, count, SkShader::kClamp_TileMode));
- paint.setShader(s.get());
+ paint.setShader(SkGradientShader::MakeLinear(p, colors, points, count,
+ SkShader::kClamp_TileMode));
canvas->DrawPath(path, paint);
}
@@ -296,11 +295,9 @@ void ProgressBar::OnPaint(gfx::Canvas* canvas) {
std::max(0, progress_width - kHighlightWidth - kBorderWidth);
p[0].iset(highlight_left, 0);
p[1].iset(progress_width, 0);
- skia::RefPtr<SkShader> s =
- skia::AdoptRef(SkGradientShader::CreateLinear(
- p, highlight_colors, highlight_points,
- arraysize(highlight_colors), SkShader::kClamp_TileMode));
- paint.setShader(s.get());
+ paint.setShader(SkGradientShader::MakeLinear(
+ p, highlight_colors, highlight_points, arraysize(highlight_colors),
+ SkShader::kClamp_TileMode));
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
canvas->DrawRect(gfx::Rect(highlight_left, 0,
kHighlightWidth + kBorderWidth, bar_height),
diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc
index 3dae5a3897d..a3e1e9787a2 100644
--- a/chromium/ui/views/controls/scroll_view.cc
+++ b/chromium/ui/views/controls/scroll_view.cc
@@ -10,7 +10,7 @@
#include "ui/gfx/canvas.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/border.h"
-#include "ui/views/controls/scrollbar/native_scroll_bar.h"
+#include "ui/views/style/platform_style.h"
#include "ui/views/widget/root_view.h"
namespace views {
@@ -124,8 +124,8 @@ ScrollView::ScrollView()
contents_viewport_(new Viewport()),
header_(NULL),
header_viewport_(new Viewport()),
- horiz_sb_(new NativeScrollBar(true)),
- vert_sb_(new NativeScrollBar(false)),
+ horiz_sb_(PlatformStyle::CreateScrollBar(true).release()),
+ vert_sb_(PlatformStyle::CreateScrollBar(false).release()),
corner_view_(new ScrollCornerView()),
min_height_(-1),
max_height_(-1),
@@ -300,26 +300,28 @@ void ScrollView::Layout() {
should_layout_contents = true;
}
+ int height_offset = horiz_sb_required ?
+ horiz_sb_->GetContentOverlapSize() : 0;
+ int width_offset = vert_sb_required ?
+ vert_sb_->GetContentOverlapSize() : 0;
+
if (horiz_sb_required) {
- int height_offset = horiz_sb_->GetContentOverlapSize();
- horiz_sb_->SetBounds(0,
+ horiz_sb_->SetBounds(contents_x,
viewport_bounds.bottom() - height_offset,
- viewport_bounds.right(),
+ viewport_bounds.right() - contents_x - width_offset,
horiz_sb_height + height_offset);
}
if (vert_sb_required) {
int width_offset = vert_sb_->GetContentOverlapSize();
vert_sb_->SetBounds(viewport_bounds.right() - width_offset,
- 0,
+ contents_y,
vert_sb_width + width_offset,
- viewport_bounds.bottom());
+ viewport_bounds.bottom() - contents_y - height_offset);
}
if (corner_view_required) {
// Show the resize corner.
- corner_view_->SetBounds(viewport_bounds.right(),
- viewport_bounds.bottom(),
- vert_sb_width,
- horiz_sb_height);
+ corner_view_->SetBounds(vert_sb_->bounds().x(), horiz_sb_->bounds().y(),
+ vert_sb_width, horiz_sb_height);
}
// Update to the real client size with the visible scrollbars.
diff --git a/chromium/ui/views/controls/scroll_view_unittest.cc b/chromium/ui/views/controls/scroll_view_unittest.cc
index c8137095a94..011f65d38a1 100644
--- a/chromium/ui/views/controls/scroll_view_unittest.cc
+++ b/chromium/ui/views/controls/scroll_view_unittest.cc
@@ -6,9 +6,14 @@
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/border.h"
#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
#include "ui/views/test/test_views.h"
+#if defined(OS_MACOSX)
+#include "ui/base/test/scoped_preferred_scroller_style_mac.h"
+#endif
+
namespace views {
namespace {
@@ -17,6 +22,8 @@ const int kWidth = 100;
const int kMinHeight = 50;
const int kMaxHeight = 100;
+enum ScrollBarOrientation { HORIZONTAL, VERTICAL };
+
// View implementation that allows setting the preferred size.
class CustomView : public View {
public:
@@ -46,6 +53,20 @@ class CustomView : public View {
DISALLOW_COPY_AND_ASSIGN(CustomView);
};
+void CheckScrollbarVisibility(const ScrollView& scroll_view,
+ ScrollBarOrientation orientation,
+ bool should_be_visible) {
+ const ScrollBar* scrollbar = orientation == HORIZONTAL
+ ? scroll_view.horizontal_scroll_bar()
+ : scroll_view.vertical_scroll_bar();
+ if (should_be_visible) {
+ ASSERT_TRUE(scrollbar);
+ EXPECT_TRUE(scrollbar->visible());
+ } else {
+ EXPECT_TRUE(!scrollbar || !scrollbar->visible());
+ }
+}
+
} // namespace
// Verifies the viewport is sized to fit the available space.
@@ -59,7 +80,12 @@ TEST(ScrollViewTest, ViewportSizedToFit) {
}
// Verifies the scrollbars are added as necessary.
+// If on Mac, test the non-overlay scrollbars.
TEST(ScrollViewTest, ScrollBars) {
+#if defined(OS_MACOSX)
+ ui::test::ScopedPreferredScrollerStyle scroller_style_override(false);
+#endif
+
ScrollView scroll_view;
View* contents = new View;
scroll_view.SetContents(contents);
@@ -70,6 +96,8 @@ TEST(ScrollViewTest, ScrollBars) {
scroll_view.Layout();
EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
EXPECT_EQ(100, contents->parent()->height());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, true);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, false);
EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
!scroll_view.horizontal_scroll_bar()->visible());
ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
@@ -81,10 +109,8 @@ TEST(ScrollViewTest, ScrollBars) {
EXPECT_EQ(100, contents->parent()->width());
EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
contents->parent()->height());
- ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
- EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
- EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
- !scroll_view.vertical_scroll_bar()->visible());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, false);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, true);
// Both horizontal and vertical.
contents->SetBounds(0, 0, 300, 400);
@@ -92,10 +118,79 @@ TEST(ScrollViewTest, ScrollBars) {
EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
contents->parent()->height());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, true);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, true);
+
+ // Add a border, test vertical scrollbar.
+ const int kTopPadding = 1;
+ const int kLeftPadding = 2;
+ const int kBottomPadding = 3;
+ const int kRightPadding = 4;
+ scroll_view.SetBorder(Border::CreateEmptyBorder(
+ kTopPadding, kLeftPadding, kBottomPadding, kRightPadding));
+ contents->SetBounds(0, 0, 50, 400);
+ scroll_view.Layout();
+ EXPECT_EQ(
+ 100 - scroll_view.GetScrollBarWidth() - kLeftPadding - kRightPadding,
+ contents->parent()->width());
+ EXPECT_EQ(100 - kTopPadding - kBottomPadding, contents->parent()->height());
+ EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
+ !scroll_view.horizontal_scroll_bar()->visible());
+ ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
+ EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
+ gfx::Rect bounds = scroll_view.vertical_scroll_bar()->bounds();
+ EXPECT_EQ(100 - scroll_view.GetScrollBarWidth() - kRightPadding, bounds.x());
+ EXPECT_EQ(100 - kRightPadding, bounds.right());
+ EXPECT_EQ(kTopPadding, bounds.y());
+ EXPECT_EQ(100 - kBottomPadding, bounds.bottom());
+
+ // Horizontal with border.
+ contents->SetBounds(0, 0, 400, 50);
+ scroll_view.Layout();
+ EXPECT_EQ(100 - kLeftPadding - kRightPadding, contents->parent()->width());
+ EXPECT_EQ(
+ 100 - scroll_view.GetScrollBarHeight() - kTopPadding - kBottomPadding,
+ contents->parent()->height());
ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
+ EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
+ !scroll_view.vertical_scroll_bar()->visible());
+ bounds = scroll_view.horizontal_scroll_bar()->bounds();
+ EXPECT_EQ(kLeftPadding, bounds.x());
+ EXPECT_EQ(100 - kRightPadding, bounds.right());
+ EXPECT_EQ(100 - kBottomPadding - scroll_view.GetScrollBarHeight(),
+ bounds.y());
+ EXPECT_EQ(100 - kBottomPadding, bounds.bottom());
+
+ // Both horizontal and vertical with border.
+ contents->SetBounds(0, 0, 300, 400);
+ scroll_view.Layout();
+ EXPECT_EQ(
+ 100 - scroll_view.GetScrollBarWidth() - kLeftPadding - kRightPadding,
+ contents->parent()->width());
+ EXPECT_EQ(
+ 100 - scroll_view.GetScrollBarHeight() - kTopPadding - kBottomPadding,
+ contents->parent()->height());
+ bounds = scroll_view.horizontal_scroll_bar()->bounds();
+ // Check horiz.
+ ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
+ EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
+ bounds = scroll_view.horizontal_scroll_bar()->bounds();
+ EXPECT_EQ(kLeftPadding, bounds.x());
+ EXPECT_EQ(100 - kRightPadding - scroll_view.GetScrollBarWidth(),
+ bounds.right());
+ EXPECT_EQ(100 - kBottomPadding - scroll_view.GetScrollBarHeight(),
+ bounds.y());
+ EXPECT_EQ(100 - kBottomPadding, bounds.bottom());
+ // Check vert.
ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
+ bounds = scroll_view.vertical_scroll_bar()->bounds();
+ EXPECT_EQ(100 - scroll_view.GetScrollBarWidth() - kRightPadding, bounds.x());
+ EXPECT_EQ(100 - kRightPadding, bounds.right());
+ EXPECT_EQ(kTopPadding, bounds.y());
+ EXPECT_EQ(100 - kBottomPadding - scroll_view.GetScrollBarHeight(),
+ bounds.bottom());
}
// Assertions around adding a header.
@@ -152,6 +247,9 @@ TEST(ScrollViewTest, ScrollBarsWithHeader) {
!scroll_view.horizontal_scroll_bar()->visible());
ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
+ // Make sure the vertical scrollbar overlaps the header.
+ EXPECT_EQ(header->y(), scroll_view.vertical_scroll_bar()->y());
+ EXPECT_EQ(header->y(), contents->y());
// Size the contents such that horizontal scrollbar is needed.
contents->SetBounds(0, 0, 400, 50);
@@ -374,4 +472,63 @@ TEST(ScrollViewTest, CornerViewVisibility) {
EXPECT_TRUE(corner_view->visible());
}
+#if defined(OS_MACOSX)
+// Tests the overlay scrollbars on Mac. Ensure that they show up properly and
+// do not overlap each other.
+TEST(ScrollViewTest, CocoaOverlayScrollBars) {
+ scoped_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_override;
+ scroller_style_override.reset(
+ new ui::test::ScopedPreferredScrollerStyle(true));
+ ScrollView scroll_view;
+ View* contents = new View;
+ scroll_view.SetContents(contents);
+ scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
+
+ // Size the contents such that vertical scrollbar is needed.
+ // Since it is overlaid, the ViewPort size should match the ScrollView.
+ contents->SetBounds(0, 0, 50, 400);
+ scroll_view.Layout();
+ EXPECT_EQ(100, contents->parent()->width());
+ EXPECT_EQ(100, contents->parent()->height());
+ EXPECT_EQ(0, scroll_view.GetScrollBarWidth());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, true);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, false);
+
+ // Size the contents such that horizontal scrollbar is needed.
+ contents->SetBounds(0, 0, 400, 50);
+ scroll_view.Layout();
+ EXPECT_EQ(100, contents->parent()->width());
+ EXPECT_EQ(100, contents->parent()->height());
+ EXPECT_EQ(0, scroll_view.GetScrollBarHeight());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, false);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, true);
+
+ // Both horizontal and vertical scrollbars.
+ contents->SetBounds(0, 0, 300, 400);
+ scroll_view.Layout();
+ EXPECT_EQ(100, contents->parent()->width());
+ EXPECT_EQ(100, contents->parent()->height());
+ EXPECT_EQ(0, scroll_view.GetScrollBarWidth());
+ EXPECT_EQ(0, scroll_view.GetScrollBarHeight());
+ CheckScrollbarVisibility(scroll_view, VERTICAL, true);
+ CheckScrollbarVisibility(scroll_view, HORIZONTAL, true);
+
+ // Make sure the horizontal and vertical scrollbars don't overlap each other.
+ gfx::Rect vert_bounds = scroll_view.vertical_scroll_bar()->bounds();
+ gfx::Rect horiz_bounds = scroll_view.horizontal_scroll_bar()->bounds();
+ EXPECT_EQ(vert_bounds.x(), horiz_bounds.right());
+ EXPECT_EQ(horiz_bounds.y(), vert_bounds.bottom());
+
+ // Switch to the non-overlay style and check that the ViewPort is now sized
+ // to be smaller, and ScrollbarWidth and ScrollbarHeight are non-zero.
+ scroller_style_override.reset(
+ new ui::test::ScopedPreferredScrollerStyle(false));
+ EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
+ EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
+ contents->parent()->height());
+ EXPECT_NE(0, scroll_view.GetScrollBarWidth());
+ EXPECT_NE(0, scroll_view.GetScrollBarHeight());
+}
+#endif
+
} // 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 117fe345dff..e9333e1458c 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.cc
@@ -413,7 +413,8 @@ void BaseScrollBar::Update(int viewport_size,
// Thumb Height and Thumb Pos.
// The height of the thumb is the ratio of the Viewport height to the
// content size multiplied by the height of the thumb track.
- double ratio = static_cast<double>(viewport_size) / contents_size_;
+ double ratio =
+ std::min(1.0, static_cast<double>(viewport_size) / contents_size_);
int thumb_size = static_cast<int>(ratio * GetTrackSize());
thumb_->SetSize(thumb_size);
@@ -495,18 +496,23 @@ int BaseScrollBar::CalculateThumbPosition(int contents_scroll_offset) const {
// In some combination of viewport_size and contents_size_, the result of
// simple division can be rounded and there could be 1 pixel gap even when the
// contents scroll down to the bottom. See crbug.com/244671
- if (contents_scroll_offset + viewport_size_ == contents_size_) {
- int track_size = GetTrackSize();
- return track_size - (viewport_size_ * GetTrackSize() / contents_size_);
- }
- return (contents_scroll_offset * GetTrackSize()) / contents_size_;
+ int thumb_max = GetTrackSize() - thumb_->GetSize();
+ if (contents_scroll_offset + viewport_size_ == contents_size_)
+ return thumb_max;
+ return (contents_scroll_offset * thumb_max) /
+ (contents_size_ - viewport_size_);
}
int BaseScrollBar::CalculateContentsOffset(int thumb_position,
bool scroll_to_middle) const {
+ int thumb_size = thumb_->GetSize();
+ int track_size = GetTrackSize();
+ if (track_size == thumb_size)
+ return 0;
if (scroll_to_middle)
- thumb_position = thumb_position - (thumb_->GetSize() / 2);
- return (thumb_position * contents_size_) / GetTrackSize();
+ thumb_position = thumb_position - (thumb_size / 2);
+ return (thumb_position * (contents_size_ - viewport_size_)) /
+ (track_size - thumb_size);
}
void BaseScrollBar::SetThumbTrackState(CustomButton::ButtonState state) {
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
index f54a8808178..178fdc1e908 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
@@ -115,6 +115,7 @@ class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
private:
FRIEND_TEST_ALL_PREFIXES(NativeScrollBarTest, ScrollBarFitsToBottom);
+ FRIEND_TEST_ALL_PREFIXES(NativeScrollBarTest, ThumbFullLengthOfTrack);
int GetThumbSizeForTest();
// Changes to 'pushed' state and starts a timer to scroll repeatedly.
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 54dbe7501ee..d3fb7071ed8 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -36,9 +36,7 @@ void BaseScrollBarButton::OnMouseCaptureLost() {
void BaseScrollBarButton::RepeaterNotifyClick() {
// TODO(sky): See if we can convert to using |Screen| everywhere.
- // TODO(scottmg): Native is wrong: http://crbug.com/133312
- gfx::Point cursor_point =
- gfx::Screen::GetNativeScreen()->GetCursorScreenPoint();
+ gfx::Point cursor_point = gfx::Screen::GetScreen()->GetCursorScreenPoint();
ui::MouseEvent event(ui::ET_MOUSE_RELEASED, cursor_point, cursor_point,
ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
ui::EF_LEFT_MOUSE_BUTTON);
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
new file mode 100644
index 00000000000..2cca52a6e38
--- /dev/null
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -0,0 +1,121 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_
+#define UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_
+
+#include "base/macros.h"
+#import "base/mac/scoped_nsobject.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/gfx/animation/slide_animation.h"
+#import "ui/views/cocoa/views_scrollbar_bridge.h"
+#include "ui/views/controls/scrollbar/base_scroll_bar.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class CocoaScrollBarThumb;
+
+// The transparent scrollbar for Mac which overlays its contents.
+class VIEWS_EXPORT CocoaScrollBar : public BaseScrollBar,
+ public ViewsScrollbarBridgeDelegate,
+ public ui::ImplicitAnimationObserver,
+ public gfx::AnimationDelegate {
+ public:
+ explicit CocoaScrollBar(bool horizontal);
+ ~CocoaScrollBar() override;
+
+ // BaseScrollBar:
+ void ScrollToPosition(int position) override;
+
+ // ViewsScrollbarBridgeDelegate:
+ void OnScrollerStyleChanged() override;
+
+ // View:
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ void OnMouseReleased(const ui::MouseEvent& event) override;
+ void OnMouseEntered(const ui::MouseEvent& event) override;
+ void OnMouseExited(const ui::MouseEvent& event) override;
+
+ // ui::ImplicitAnimationObserver:
+ void OnImplicitAnimationsCompleted() override;
+
+ // gfx::AnimationDelegate:
+ void AnimationProgressed(const gfx::Animation* animation) override;
+ void AnimationEnded(const gfx::Animation* animation) override;
+
+ // Returns the scroller style.
+ NSScrollerStyle GetScrollerStyle() const { return scroller_style_; }
+
+ // Returns true if the opacity is 0.0.
+ bool IsScrollbarFullyHidden() const;
+
+ protected:
+ // BaseScrollBar:
+ gfx::Rect GetTrackBounds() const override;
+
+ // ScrollBar:
+ int GetLayoutSize() const override;
+ int GetContentOverlapSize() const override;
+
+ // View:
+ void Layout() override;
+ gfx::Size GetPreferredSize() const override;
+ void OnPaint(gfx::Canvas* canvas) override;
+
+ private:
+ // Methods to change the visibility of the scrollbar.
+ void ShowScrollbar();
+ void HideScrollbar();
+
+ // Returns true if the scrollbar is in a hover or pressed state.
+ bool IsHoverOrPressedState() const;
+
+ // Updates the thickness of the scrollbar according to the current state of
+ // the expand animation.
+ void UpdateScrollbarThickness();
+
+ // Resets the scrolltrack and the thickness if the scrollbar is not hidden
+ // and is not in a hover/pressed state.
+ void ResetOverlayScrollbar();
+
+ // Returns the thickness of the scrollbar.
+ int ScrollbarThickness() const;
+
+ // Sets the scrolltrack's visibility and then repaints it.
+ void SetScrolltrackVisible(bool visible);
+
+ // Converts GetThumb() into a CocoaScrollBarThumb object and returns it.
+ CocoaScrollBarThumb* GetCocoaScrollBarThumb() const;
+
+ // Scroller style the scrollbar is using.
+ NSScrollerStyle scroller_style_;
+
+ // Timer that will start the scrollbar's hiding animation when it reaches 0.
+ base::Timer hide_scrollbar_timer_;
+
+ // Slide animation that animates the thickness of an overlay scrollbar.
+ // The animation expands the scrollbar as the showing animation and shrinks
+ // the scrollbar as the hiding animation.
+ gfx::SlideAnimation thickness_animation_;
+
+ // True when the scrollbar is expanded.
+ bool is_expanded_;
+
+ // True when the scrolltrack should be drawn.
+ bool has_scrolltrack_;
+
+ // True when the scrollbar has started dragging since it was last shown.
+ // This is set to false when we begin to hide the scrollbar.
+ bool did_start_dragging_;
+
+ // The bridge for NSScroller.
+ base::scoped_nsobject<ViewsScrollbarBridge> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(CocoaScrollBar);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
new file mode 100644
index 00000000000..f11ea1a237d
--- /dev/null
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -0,0 +1,487 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
+
+#import "base/mac/sdk_forward_declarations.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/gfx/canvas.h"
+#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
+
+namespace views {
+
+namespace {
+
+// The length of the fade animation.
+const int kFadeDurationMs = 240;
+
+// The length of the expand animation.
+const int kExpandDurationMs = 240;
+
+// How long we should wait before hiding the scrollbar.
+const int kScrollbarHideTimeoutMs = 500;
+
+// The thickness of the normal and expanded scrollbars.
+const int kScrollbarThickness = 12;
+const int kExpandedScrollbarThickness = 16;
+
+// The thickness of the scrollbar thumb.
+const int kScrollbarThumbThickness = 8;
+
+// The width of the scroller track border.
+const int kScrollerTrackBorderWidth = 1;
+
+// The amount the thumb is inset from both the ends and the sides of the normal
+// and expanded tracks.
+const int kScrollbarThumbInset = 2;
+const int kExpandedScrollbarThumbInset = 3;
+
+// Scrollbar thumb colors.
+const SkColor kScrollerDefaultThumbColor = SkColorSetARGB(0x38, 0, 0, 0);
+const SkColor kScrollerHoverThumbColor = SkColorSetARGB(0x80, 0, 0, 0);
+
+// Opacity of the overlay scrollbar.
+const float kOverlayOpacity = 0.8f;
+
+// Scroller track colors.
+const SkColor kScrollerTrackGradientColors[] = {
+ SkColorSetRGB(0xEF, 0xEF, 0xEF), SkColorSetRGB(0xF9, 0xF9, 0xF9),
+ SkColorSetRGB(0xFD, 0xFD, 0xFD), SkColorSetRGB(0xF6, 0xF6, 0xF6)};
+const SkColor kScrollerTrackInnerBorderColor = SkColorSetRGB(0xE4, 0xE4, 0xE4);
+const SkColor kScrollerTrackOuterBorderColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
+
+} // namespace
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBarThumb
+
+class CocoaScrollBarThumb : public BaseScrollBarThumb {
+ public:
+ explicit CocoaScrollBarThumb(CocoaScrollBar* scroll_bar);
+ ~CocoaScrollBarThumb() override;
+
+ // Returns true if the thumb is in hovered state.
+ bool IsStateHovered() const;
+
+ // Returns true if the thumb is in pressed state.
+ bool IsStatePressed() const;
+
+ protected:
+ // View:
+ gfx::Size GetPreferredSize() const override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ void OnMouseReleased(const ui::MouseEvent& event) override;
+ void OnMouseEntered(const ui::MouseEvent& event) override;
+ void OnMouseExited(const ui::MouseEvent& event) override;
+
+ private:
+ // Converts scroll_bar() into a CocoaScrollBar object and returns it.
+ CocoaScrollBar* cocoa_scroll_bar() {
+ return static_cast<CocoaScrollBar*>(scroll_bar());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(CocoaScrollBarThumb);
+};
+
+CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar)
+ : BaseScrollBarThumb(scroll_bar) {
+ DCHECK(scroll_bar);
+
+ // This is necessary, otherwise the thumb will be rendered below the views if
+ // those views paint to their own layers.
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+}
+
+CocoaScrollBarThumb::~CocoaScrollBarThumb() {}
+
+bool CocoaScrollBarThumb::IsStateHovered() const {
+ return GetState() == CustomButton::STATE_HOVERED;
+}
+
+bool CocoaScrollBarThumb::IsStatePressed() const {
+ return GetState() == CustomButton::STATE_PRESSED;
+}
+
+gfx::Size CocoaScrollBarThumb::GetPreferredSize() const {
+ return gfx::Size(kScrollbarThumbThickness, kScrollbarThumbThickness);
+}
+
+void CocoaScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
+ SkColor thumb_color = kScrollerDefaultThumbColor;
+ if (cocoa_scroll_bar()->GetScrollerStyle() == NSScrollerStyleOverlay ||
+ IsStateHovered() ||
+ IsStatePressed()) {
+ thumb_color = kScrollerHoverThumbColor;
+ }
+
+ gfx::Rect local_bounds(GetLocalBounds());
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(thumb_color);
+ const SkScalar radius =
+ std::min(local_bounds.width(), local_bounds.height());
+ canvas->DrawRoundRect(local_bounds, radius, paint);
+}
+
+bool CocoaScrollBarThumb::OnMousePressed(const ui::MouseEvent& event) {
+ // Ignore the mouse press if the scrollbar is hidden.
+ if (cocoa_scroll_bar()->IsScrollbarFullyHidden())
+ return false;
+
+ return BaseScrollBarThumb::OnMousePressed(event);
+}
+
+void CocoaScrollBarThumb::OnMouseReleased(const ui::MouseEvent& event) {
+ BaseScrollBarThumb::OnMouseReleased(event);
+ scroll_bar()->OnMouseReleased(event);
+}
+
+void CocoaScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) {
+ BaseScrollBarThumb::OnMouseEntered(event);
+ scroll_bar()->OnMouseEntered(event);
+}
+
+void CocoaScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) {
+ // The thumb should remain pressed when dragged, even if the mouse leaves
+ // the scrollview. The thumb will be set back to its hover or normal state
+ // when the mouse is released.
+ if (GetState() != CustomButton::STATE_PRESSED)
+ SetState(CustomButton::STATE_NORMAL);
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar class
+
+CocoaScrollBar::CocoaScrollBar(bool horizontal)
+ : BaseScrollBar(horizontal, new CocoaScrollBarThumb(this)),
+ hide_scrollbar_timer_(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kScrollbarHideTimeoutMs),
+ base::Bind(&CocoaScrollBar::HideScrollbar, base::Unretained(this)),
+ false),
+ thickness_animation_(this),
+ is_expanded_(false),
+ did_start_dragging_(false) {
+ bridge_.reset([[ViewsScrollbarBridge alloc] initWithDelegate:this]);
+ scroller_style_ = [ViewsScrollbarBridge getPreferredScrollerStyle];
+
+ thickness_animation_.SetSlideDuration(kExpandDurationMs);
+
+ SetPaintToLayer(true);
+ has_scrolltrack_ = scroller_style_ == NSScrollerStyleLegacy;
+ layer()->SetOpacity(scroller_style_ == NSScrollerStyleOverlay ? 0.0f : 1.0f);
+}
+
+CocoaScrollBar::~CocoaScrollBar() {
+ [bridge_ clearDelegate];
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar, BaseScrollBar:
+
+gfx::Rect CocoaScrollBar::GetTrackBounds() const {
+ gfx::Rect local_bounds(GetLocalBounds());
+
+ int inset = kScrollbarThumbInset;
+ if (is_expanded_) {
+ inset = thickness_animation_.CurrentValueBetween(
+ kScrollbarThumbInset, kExpandedScrollbarThumbInset);
+ }
+ local_bounds.Inset(inset, inset);
+
+ gfx::Size track_size = local_bounds.size();
+ track_size.SetToMax(GetThumb()->GetPreferredSize());
+ local_bounds.set_size(track_size);
+ return local_bounds;
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar, ScrollBar:
+
+int CocoaScrollBar::GetLayoutSize() const {
+ return scroller_style_ == NSScrollerStyleOverlay ? 0 : ScrollbarThickness();
+}
+
+int CocoaScrollBar::GetContentOverlapSize() const {
+ return scroller_style_ == NSScrollerStyleLegacy ? 0 : ScrollbarThickness();
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar::View:
+
+void CocoaScrollBar::Layout() {
+ // Set the thickness of the thumb according to the track bounds.
+ // The length of the thumb is set by BaseScrollBar::Update().
+ gfx::Rect thumb_bounds(GetThumb()->bounds());
+ gfx::Rect track_bounds(GetTrackBounds());
+ if (IsHorizontal()) {
+ GetThumb()->SetBounds(thumb_bounds.x(),
+ track_bounds.y(),
+ thumb_bounds.width(),
+ track_bounds.height());
+ } else {
+ GetThumb()->SetBounds(track_bounds.x(),
+ thumb_bounds.y(),
+ track_bounds.width(),
+ thumb_bounds.height());
+ }
+}
+
+gfx::Size CocoaScrollBar::GetPreferredSize() const {
+ return gfx::Size();
+}
+
+void CocoaScrollBar::OnPaint(gfx::Canvas* canvas) {
+ if (!has_scrolltrack_)
+ return;
+
+ // Paint the scrollbar track background.
+ gfx::Rect track_rect = GetLocalBounds();
+
+ SkPoint gradient_bounds[2];
+ if (IsHorizontal()) {
+ gradient_bounds[0].set(track_rect.x(), track_rect.y());
+ gradient_bounds[1].set(track_rect.x(), track_rect.bottom());
+ } else {
+ gradient_bounds[0].set(track_rect.x(), track_rect.y());
+ gradient_bounds[1].set(track_rect.right(), track_rect.y());
+ }
+ SkPaint gradient;
+ gradient.setShader(SkGradientShader::MakeLinear(
+ gradient_bounds, kScrollerTrackGradientColors, nullptr,
+ arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode));
+ canvas->DrawRect(track_rect, gradient);
+
+ // Draw the inner border: top if horizontal, left if vertical.
+ SkPaint paint;
+ paint.setColor(kScrollerTrackInnerBorderColor);
+ gfx::Rect inner_border(track_rect);
+ if (IsHorizontal())
+ inner_border.set_height(kScrollerTrackBorderWidth);
+ else
+ inner_border.set_width(kScrollerTrackBorderWidth);
+ canvas->DrawRect(inner_border, paint);
+
+ // Draw the outer border: bottom if horizontal, right if veritcal.
+ paint.setColor(kScrollerTrackOuterBorderColor);
+ gfx::Rect outer_border(inner_border);
+ if (IsHorizontal())
+ outer_border.set_y(track_rect.bottom());
+ else
+ outer_border.set_x(track_rect.right());
+ canvas->DrawRect(outer_border, paint);
+}
+
+bool CocoaScrollBar::OnMousePressed(const ui::MouseEvent& event) {
+ // Ignore the mouse press if the scrollbar is hidden.
+ if (IsScrollbarFullyHidden())
+ return false;
+
+ return BaseScrollBar::OnMousePressed(event);
+}
+
+void CocoaScrollBar::OnMouseReleased(const ui::MouseEvent& event) {
+ ResetOverlayScrollbar();
+}
+
+void CocoaScrollBar::OnMouseEntered(const ui::MouseEvent& event) {
+ if (scroller_style_ != NSScrollerStyleOverlay)
+ return;
+
+ // If the scrollbar thumb did not completely fade away, then reshow it when
+ // the mouse enters the scrollbar thumb.
+ if (!IsScrollbarFullyHidden())
+ ShowScrollbar();
+
+ // Expand the scrollbar. If the scrollbar is hidden, don't animate it.
+ if (!is_expanded_) {
+ SetScrolltrackVisible(true);
+ is_expanded_ = true;
+ if (IsScrollbarFullyHidden()) {
+ thickness_animation_.Reset(1.0);
+ UpdateScrollbarThickness();
+ } else {
+ thickness_animation_.Show();
+ }
+ }
+
+ hide_scrollbar_timer_.Reset();
+}
+
+void CocoaScrollBar::OnMouseExited(const ui::MouseEvent& event) {
+ ResetOverlayScrollbar();
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar::BaseScrollBar:
+
+void CocoaScrollBar::ScrollToPosition(int position) {
+ BaseScrollBar::ScrollToPosition(position);
+
+ if (GetCocoaScrollBarThumb()->IsStatePressed())
+ did_start_dragging_ = true;
+
+ if (scroller_style_ == NSScrollerStyleOverlay) {
+ ShowScrollbar();
+ hide_scrollbar_timer_.Reset();
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar::ViewsScrollbarBridge:
+
+void CocoaScrollBar::OnScrollerStyleChanged() {
+ NSScrollerStyle scroller_style =
+ [ViewsScrollbarBridge getPreferredScrollerStyle];
+ if (scroller_style_ == scroller_style)
+ return;
+
+ // Cancel all of the animations.
+ thickness_animation_.Reset();
+ layer()->GetAnimator()->AbortAllAnimations();
+
+ scroller_style_ = scroller_style;
+
+ // Ensure that the ScrollView updates the scrollbar's layout.
+ if (parent())
+ parent()->Layout();
+
+ if (scroller_style_ == NSScrollerStyleOverlay) {
+ // Hide the scrollbar, but don't fade out.
+ layer()->SetOpacity(0.0f);
+ ResetOverlayScrollbar();
+ GetThumb()->SchedulePaint();
+ } else {
+ is_expanded_ = false;
+ SetScrolltrackVisible(true);
+ ShowScrollbar();
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar::ImplicitAnimationObserver:
+
+void CocoaScrollBar::OnImplicitAnimationsCompleted() {
+ DCHECK_EQ(scroller_style_, NSScrollerStyleOverlay);
+ ResetOverlayScrollbar();
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar::AnimationDelegate:
+
+void CocoaScrollBar::AnimationProgressed(const gfx::Animation* animation) {
+ DCHECK(is_expanded_);
+ UpdateScrollbarThickness();
+}
+
+void CocoaScrollBar::AnimationEnded(const gfx::Animation* animation) {
+ // Remove the scrolltrack and set |is_expanded| to false at the end of
+ // the shrink animation.
+ if (!thickness_animation_.IsShowing()) {
+ is_expanded_ = false;
+ SetScrolltrackVisible(false);
+ }
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar, public:
+
+bool CocoaScrollBar::IsScrollbarFullyHidden() const {
+ return layer()->opacity() == 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////
+// CocoaScrollBar, private:
+
+void CocoaScrollBar::HideScrollbar() {
+ DCHECK_EQ(scroller_style_, NSScrollerStyleOverlay);
+
+ // Don't disappear if the scrollbar is hovered, or pressed but not dragged.
+ // This behavior matches the Cocoa scrollbars, but differs from the Blink
+ // scrollbars which would just disappear.
+ CocoaScrollBarThumb* thumb = GetCocoaScrollBarThumb();
+ if (IsMouseHovered() || thumb->IsStateHovered() ||
+ (thumb->IsStatePressed() && !did_start_dragging_)) {
+ hide_scrollbar_timer_.Reset();
+ return;
+ }
+
+ did_start_dragging_ = false;
+
+ ui::ScopedLayerAnimationSettings animation(layer()->GetAnimator());
+ animation.SetTransitionDuration(
+ base::TimeDelta::FromMilliseconds(kFadeDurationMs));
+ animation.AddObserver(this);
+ layer()->SetOpacity(0.0f);
+}
+
+void CocoaScrollBar::ShowScrollbar() {
+ // If the scrollbar is still expanded but has not completely faded away,
+ // then shrink it back to its original state.
+ if (is_expanded_ && !IsHoverOrPressedState() &&
+ layer()->GetAnimator()->IsAnimatingProperty(
+ ui::LayerAnimationElement::OPACITY)) {
+ DCHECK_EQ(scroller_style_, NSScrollerStyleOverlay);
+ thickness_animation_.Hide();
+ }
+
+ // Updates the scrolltrack and repaint it, if necessary.
+ double opacity =
+ scroller_style_ == NSScrollerStyleOverlay ? kOverlayOpacity : 1.0f;
+ layer()->SetOpacity(opacity);
+ hide_scrollbar_timer_.Stop();
+}
+
+bool CocoaScrollBar::IsHoverOrPressedState() const {
+ CocoaScrollBarThumb* thumb = GetCocoaScrollBarThumb();
+ return thumb->IsStateHovered() ||
+ thumb->IsStatePressed() ||
+ IsMouseHovered();
+}
+
+void CocoaScrollBar::UpdateScrollbarThickness() {
+ int thickness = ScrollbarThickness();
+ if (IsHorizontal())
+ SetBounds(x(), bounds().bottom() - thickness, width(), thickness);
+ else
+ SetBounds(bounds().right() - thickness, y(), thickness, height());
+}
+
+void CocoaScrollBar::ResetOverlayScrollbar() {
+ if (!IsHoverOrPressedState() && IsScrollbarFullyHidden() &&
+ !thickness_animation_.IsClosing()) {
+ if (is_expanded_) {
+ is_expanded_ = false;
+ thickness_animation_.Reset();
+ UpdateScrollbarThickness();
+ }
+ SetScrolltrackVisible(false);
+ }
+}
+
+int CocoaScrollBar::ScrollbarThickness() const {
+ if (scroller_style_ == NSScrollerStyleLegacy)
+ return kScrollbarThickness;
+
+ return thickness_animation_.CurrentValueBetween(kScrollbarThickness,
+ kExpandedScrollbarThickness);
+}
+
+void CocoaScrollBar::SetScrolltrackVisible(bool visible) {
+ has_scrolltrack_ = visible;
+ SchedulePaint();
+}
+
+CocoaScrollBarThumb* CocoaScrollBar::GetCocoaScrollBarThumb() const {
+ return static_cast<CocoaScrollBarThumb*>(GetThumb());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc
deleted file mode 100644
index 35c81615c48..00000000000
--- a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.cc
+++ /dev/null
@@ -1,108 +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/scrollbar/kennedy_scroll_bar.h"
-
-#include "base/macros.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkXfermode.h"
-#include "ui/gfx/canvas.h"
-#include "ui/views/background.h"
-#include "ui/views/border.h"
-#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
-
-namespace views {
-namespace {
-
-const int kScrollbarWidth = 10;
-const int kThumbMinimumSize = kScrollbarWidth * 2;
-const SkColor kBorderColor = SkColorSetARGB(32, 0, 0, 0);
-const SkColor kThumbHoverColor = SkColorSetARGB(128, 0, 0, 0);
-const SkColor kThumbDefaultColor = SkColorSetARGB(64, 0, 0, 0);
-const SkColor kTrackHoverColor = SkColorSetARGB(32, 0, 0, 0);
-
-class KennedyScrollBarThumb : public BaseScrollBarThumb {
- public:
- explicit KennedyScrollBarThumb(BaseScrollBar* scroll_bar);
- ~KennedyScrollBarThumb() override;
-
- protected:
- // View overrides:
- gfx::Size GetPreferredSize() const override;
- void OnPaint(gfx::Canvas* canvas) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(KennedyScrollBarThumb);
-};
-
-KennedyScrollBarThumb::KennedyScrollBarThumb(BaseScrollBar* scroll_bar)
- : BaseScrollBarThumb(scroll_bar) {
-}
-
-KennedyScrollBarThumb::~KennedyScrollBarThumb() {
-}
-
-gfx::Size KennedyScrollBarThumb::GetPreferredSize() const {
- return gfx::Size(kThumbMinimumSize, kThumbMinimumSize);
-}
-
-void KennedyScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
- gfx::Rect local_bounds(GetLocalBounds());
- canvas->FillRect(local_bounds,
- (GetState() == CustomButton::STATE_HOVERED ||
- GetState() == CustomButton::STATE_PRESSED) ?
- kThumbHoverColor : kThumbDefaultColor);
- canvas->DrawRect(local_bounds, kBorderColor);
-}
-
-} // namespace
-
-KennedyScrollBar::KennedyScrollBar(bool horizontal)
- : BaseScrollBar(horizontal, new KennedyScrollBarThumb(this)) {
- set_notify_enter_exit_on_child(true);
-}
-
-KennedyScrollBar::~KennedyScrollBar() {
-}
-
-gfx::Rect KennedyScrollBar::GetTrackBounds() const {
- gfx::Rect local_bounds(GetLocalBounds());
- gfx::Size track_size = local_bounds.size();
- track_size.SetToMax(GetThumb()->size());
- local_bounds.set_size(track_size);
- return local_bounds;
-}
-
-int KennedyScrollBar::GetLayoutSize() const {
- return kScrollbarWidth;
-}
-
-gfx::Size KennedyScrollBar::GetPreferredSize() const {
- return GetTrackBounds().size();
-}
-
-void KennedyScrollBar::Layout() {
- gfx::Rect thumb_bounds = GetTrackBounds();
- BaseScrollBarThumb* thumb = GetThumb();
- if (IsHorizontal()) {
- thumb_bounds.set_x(thumb->x());
- thumb_bounds.set_width(thumb->width());
- } else {
- thumb_bounds.set_y(thumb->y());
- thumb_bounds.set_height(thumb->height());
- }
- thumb->SetBoundsRect(thumb_bounds);
-}
-
-void KennedyScrollBar::OnPaint(gfx::Canvas* canvas) {
- CustomButton::ButtonState state = GetThumbTrackState();
- if ((state == CustomButton::STATE_HOVERED) ||
- (state == CustomButton::STATE_PRESSED)) {
- gfx::Rect local_bounds(GetLocalBounds());
- canvas->FillRect(local_bounds, kTrackHoverColor);
- canvas->DrawRect(local_bounds, kBorderColor);
- }
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h b/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h
deleted file mode 100644
index f56e4a91da4..00000000000
--- a/chromium/ui/views/controls/scrollbar/kennedy_scroll_bar.h
+++ /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.
-
-#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_KENNEDY_SCROLL_BAR_H_
-#define UI_VIEWS_CONTROLS_SCROLLBAR_KENNEDY_SCROLL_BAR_H_
-
-#include "base/macros.h"
-#include "ui/views/controls/scrollbar/base_scroll_bar.h"
-
-namespace views {
-
-// The scrollbar of kennedy style. Transparent track and grey rectangle
-// thumb. Right now it doesn't have the way to share the background,
-// so it will accept the background color instead.
-class VIEWS_EXPORT KennedyScrollBar : public BaseScrollBar {
- public:
- explicit KennedyScrollBar(bool horizontal);
- ~KennedyScrollBar() override;
-
- protected:
- // BaseScrollBar overrides:
- gfx::Rect GetTrackBounds() const override;
-
- // ScrollBar overrides:
- int GetLayoutSize() const override;
-
- // View overrides:
- gfx::Size GetPreferredSize() const override;
- void Layout() override;
- void OnPaint(gfx::Canvas* canvas) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(KennedyScrollBar);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_SCROLLBAR_KENNEDY_SCROLL_BAR_H_
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index fa72066818e..8da5f7d4290 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -48,7 +48,7 @@ OverlayScrollBarThumb::OverlayScrollBarThumb(BaseScrollBar* scroll_bar)
// This is necessary, otherwise the thumb will be rendered below the views if
// those views paint to their own layers.
SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
+ layer()->SetFillsBoundsOpaquely(false);
}
OverlayScrollBarThumb::~OverlayScrollBarThumb() {
diff --git a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
index 68a6687392f..84471929234 100644
--- a/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
+++ b/chromium/ui/views/controls/scrollbar/scrollbar_unittest.cc
@@ -34,7 +34,7 @@ class TestScrollBarController : public views::ScrollBarController {
return 10;
}
- // We save the last values in order to assert the corectness of the scroll
+ // We save the last values in order to assert the correctness of the scroll
// operation.
views::ScrollBar* last_source;
bool last_is_positive;
@@ -70,7 +70,7 @@ class NativeScrollBarTest : public ViewsTestBase {
scrollbar_ =
static_cast<NativeScrollBarViews*>(native_scrollbar_->native_wrapper_);
scrollbar_->SetBounds(0, 0, 100, 100);
- scrollbar_->Update(100, 200, 0);
+ scrollbar_->Update(100, 1000, 0);
track_size_ = scrollbar_->GetTrackBounds().width();
}
@@ -107,50 +107,58 @@ class NativeScrollBarTest : public ViewsTestBase {
#endif
TEST_F(NativeScrollBarTest, MAYBE_Scrolling) {
- EXPECT_EQ(scrollbar_->GetPosition(), 0);
- EXPECT_EQ(scrollbar_->GetMaxPosition(), 100);
- EXPECT_EQ(scrollbar_->GetMinPosition(), 0);
+ EXPECT_EQ(0, scrollbar_->GetPosition());
+ EXPECT_EQ(900, scrollbar_->GetMaxPosition());
+ EXPECT_EQ(0, scrollbar_->GetMinPosition());
// Scroll to middle.
- scrollbar_->ScrollToThumbPosition(track_size_ / 4, false);
- EXPECT_EQ(controller_->last_position, 50);
- EXPECT_EQ(controller_->last_source, native_scrollbar_);
+ scrollbar_->ScrollToThumbPosition(track_size_ / 2, true);
+ EXPECT_EQ(450, controller_->last_position);
+ EXPECT_EQ(native_scrollbar_, controller_->last_source);
// Scroll to the end.
- scrollbar_->ScrollToThumbPosition(track_size_ / 2, false);
- EXPECT_EQ(controller_->last_position, 100);
+ scrollbar_->ScrollToThumbPosition(track_size_, true);
+ EXPECT_EQ(900, controller_->last_position);
// Overscroll. Last position should be the maximum position.
- scrollbar_->ScrollToThumbPosition(track_size_, false);
- EXPECT_EQ(controller_->last_position, 100);
+ scrollbar_->ScrollToThumbPosition(track_size_ + 100, true);
+ EXPECT_EQ(900, controller_->last_position);
// Underscroll. Last position should be the minimum position.
scrollbar_->ScrollToThumbPosition(-10, false);
- EXPECT_EQ(controller_->last_position, 0);
+ EXPECT_EQ(0, controller_->last_position);
// Test the different fixed scrolling amounts. Generally used by buttons,
// or click on track.
scrollbar_->ScrollToThumbPosition(0, false);
scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_NEXT_LINE);
- EXPECT_EQ(controller_->last_position, 10);
+ EXPECT_EQ(10, controller_->last_position);
scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_PREV_LINE);
- EXPECT_EQ(controller_->last_position, 0);
+ EXPECT_EQ(0, controller_->last_position);
scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_NEXT_PAGE);
- EXPECT_EQ(controller_->last_position, 20);
+ EXPECT_EQ(20, controller_->last_position);
scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_PREV_PAGE);
- EXPECT_EQ(controller_->last_position, 0);
+ EXPECT_EQ(0, controller_->last_position);
}
TEST_F(NativeScrollBarTest, MAYBE_ScrollBarFitsToBottom) {
- scrollbar_->Update(100, 199, 0);
+ scrollbar_->Update(100, 1999, 0);
EXPECT_EQ(0, scrollbar_->GetPosition());
- EXPECT_EQ(99, scrollbar_->GetMaxPosition());
+ EXPECT_EQ(1899, scrollbar_->GetMaxPosition());
EXPECT_EQ(0, scrollbar_->GetMinPosition());
- scrollbar_->Update(100, 199, 99);
+ // Scroll to the midpoint of the document.
+ scrollbar_->Update(100, 1999, 950);
+ EXPECT_EQ((scrollbar_->GetTrackBounds().width() -
+ scrollbar_->GetThumbSizeForTest()) /
+ 2,
+ scrollbar_->GetPosition());
+
+ // Scroll to the end of the document.
+ scrollbar_->Update(100, 1999, 1899);
EXPECT_EQ(
scrollbar_->GetTrackBounds().width() - scrollbar_->GetThumbSizeForTest(),
scrollbar_->GetPosition());
@@ -158,13 +166,37 @@ TEST_F(NativeScrollBarTest, MAYBE_ScrollBarFitsToBottom) {
TEST_F(NativeScrollBarTest, ScrollToEndAfterShrinkAndExpand) {
// Scroll to the end of the content.
- scrollbar_->Update(100, 101, 0);
+ scrollbar_->Update(100, 1001, 0);
EXPECT_TRUE(scrollbar_->ScrollByContentsOffset(-1));
- // Shrink and then re-exapnd the content.
- scrollbar_->Update(100, 100, 0);
- scrollbar_->Update(100, 101, 0);
+ // Shrink and then re-expand the content.
+ scrollbar_->Update(100, 1000, 0);
+ scrollbar_->Update(100, 1001, 0);
// Ensure the scrollbar allows scrolling to the end.
EXPECT_TRUE(scrollbar_->ScrollByContentsOffset(-1));
}
+TEST_F(NativeScrollBarTest, ThumbFullLengthOfTrack) {
+ // Shrink content so that it fits within the viewport.
+ scrollbar_->Update(100, 10, 0);
+ EXPECT_EQ(scrollbar_->GetTrackBounds().width(),
+ scrollbar_->GetThumbSizeForTest());
+ // Emulate a click on the full size scroll bar.
+ scrollbar_->ScrollToThumbPosition(0, false);
+ EXPECT_EQ(0, scrollbar_->GetPosition());
+ // Emulate a key down.
+ scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_NEXT_LINE);
+ EXPECT_EQ(0, scrollbar_->GetPosition());
+
+ // Expand content so that it fits *exactly* within the viewport.
+ scrollbar_->Update(100, 100, 0);
+ EXPECT_EQ(scrollbar_->GetTrackBounds().width(),
+ scrollbar_->GetThumbSizeForTest());
+ // Emulate a click on the full size scroll bar.
+ scrollbar_->ScrollToThumbPosition(0, false);
+ EXPECT_EQ(0, scrollbar_->GetPosition());
+ // Emulate a key down.
+ scrollbar_->ScrollByAmount(BaseScrollBar::SCROLL_NEXT_LINE);
+ EXPECT_EQ(0, scrollbar_->GetPosition());
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/single_split_view.cc b/chromium/ui/views/controls/single_split_view.cc
index c7556916962..354d3e14bb9 100644
--- a/chromium/ui/views/controls/single_split_view.cc
+++ b/chromium/ui/views/controls/single_split_view.cc
@@ -9,6 +9,7 @@
#include "ui/base/cursor/cursor.h"
#include "ui/gfx/canvas.h"
#include "ui/views/background.h"
+#include "ui/views/border.h"
#include "ui/views/controls/single_split_view_listener.h"
#include "ui/views/native_cursor.h"
@@ -45,7 +46,8 @@ SingleSplitView::SingleSplitView(View* leading,
void SingleSplitView::Layout() {
gfx::Rect leading_bounds;
gfx::Rect trailing_bounds;
- CalculateChildrenBounds(bounds(), &leading_bounds, &trailing_bounds);
+ CalculateChildrenBounds(GetContentsBounds(), &leading_bounds,
+ &trailing_bounds);
if (has_children()) {
if (child_at(0)->visible())
@@ -87,6 +89,8 @@ gfx::Size SingleSplitView::GetPreferredSize() const {
width += GetDividerSize();
else
height += GetDividerSize();
+ width += GetInsets().width();
+ height += GetInsets().height();
return gfx::Size(width, height);
}
@@ -123,24 +127,25 @@ void SingleSplitView::CalculateChildrenBounds(
} else if (!is_leading_visible) {
divider_at = 0;
} else {
- divider_at =
- CalculateDividerOffset(divider_offset_, this->bounds(), bounds);
+ divider_at = CalculateDividerOffset(divider_offset_, bounds, bounds);
divider_at = NormalizeDividerOffset(divider_at, bounds);
}
int divider_size = GetDividerSize();
if (is_horizontal_) {
- *leading_bounds = gfx::Rect(0, 0, divider_at, bounds.height());
+ *leading_bounds =
+ gfx::Rect(bounds.x(), bounds.y(), divider_at, bounds.height());
*trailing_bounds =
- gfx::Rect(divider_at + divider_size, 0,
+ gfx::Rect(divider_at + divider_size + bounds.x(), bounds.y(),
std::max(0, bounds.width() - divider_at - divider_size),
bounds.height());
} else {
- *leading_bounds = gfx::Rect(0, 0, bounds.width(), divider_at);
- *trailing_bounds =
- gfx::Rect(0, divider_at + divider_size, bounds.width(),
- std::max(0, bounds.height() - divider_at - divider_size));
+ *leading_bounds =
+ gfx::Rect(bounds.x(), bounds.y(), bounds.width(), divider_at);
+ *trailing_bounds = gfx::Rect(
+ bounds.x(), divider_at + divider_size + bounds.y(), bounds.width(),
+ std::max(0, bounds.height() - divider_at - divider_size));
}
}
@@ -153,7 +158,7 @@ bool SingleSplitView::OnMousePressed(const ui::MouseEvent& event) {
return false;
drag_info_.initial_mouse_offset = GetPrimaryAxisSize(event.x(), event.y());
drag_info_.initial_divider_offset =
- NormalizeDividerOffset(divider_offset_, bounds());
+ NormalizeDividerOffset(divider_offset_, GetContentsBounds());
return true;
}
@@ -196,8 +201,10 @@ void SingleSplitView::OnMouseCaptureLost() {
}
void SingleSplitView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- divider_offset_ = CalculateDividerOffset(divider_offset_, previous_bounds,
- bounds());
+ gfx::Rect previous_content_bounds = previous_bounds;
+ previous_content_bounds.Inset(GetInsets());
+ divider_offset_ = CalculateDividerOffset(
+ divider_offset_, previous_content_bounds, GetContentsBounds());
}
bool SingleSplitView::IsPointInDivider(const gfx::Point& p) {
diff --git a/chromium/ui/views/controls/single_split_view_unittest.cc b/chromium/ui/views/controls/single_split_view_unittest.cc
index 3f3e6a086e6..d2a588e0c74 100644
--- a/chromium/ui/views/controls/single_split_view_unittest.cc
+++ b/chromium/ui/views/controls/single_split_view_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_utils.h"
+#include "ui/views/border.h"
#include "ui/views/controls/single_split_view_listener.h"
namespace {
@@ -31,15 +32,19 @@ static void VerifySplitViewLayout(const views::SingleSplitView& split) {
EXPECT_FALSE(leading->bounds().Intersects(trailing->bounds()));
if (split.orientation() == views::SingleSplitView::HORIZONTAL_SPLIT) {
- EXPECT_EQ(leading->bounds().height(), split.bounds().height());
- EXPECT_EQ(trailing->bounds().height(), split.bounds().height());
+ EXPECT_EQ(leading->bounds().height(),
+ split.bounds().height() - split.GetInsets().height());
+ EXPECT_EQ(trailing->bounds().height(),
+ split.bounds().height() - split.GetInsets().height());
EXPECT_LT(leading->bounds().width() + trailing->bounds().width(),
- split.bounds().width());
+ split.bounds().width() - split.GetInsets().width());
} else if (split.orientation() == views::SingleSplitView::VERTICAL_SPLIT) {
- EXPECT_EQ(leading->bounds().width(), split.bounds().width());
- EXPECT_EQ(trailing->bounds().width(), split.bounds().width());
+ EXPECT_EQ(leading->bounds().width(),
+ split.bounds().width() - split.GetInsets().width());
+ EXPECT_EQ(trailing->bounds().width(),
+ split.bounds().width() - split.GetInsets().width());
EXPECT_LT(leading->bounds().height() + trailing->bounds().height(),
- split.bounds().height());
+ split.bounds().height() - split.GetInsets().height());
} else {
NOTREACHED();
}
@@ -109,47 +114,59 @@ TEST(SingleSplitViewTest, Resize) {
SingleSplitView::VERTICAL_SPLIT
};
+ int borders[][4] = {
+ {0, 0, 0, 0}, {5, 5, 5, 5}, {10, 5, 5, 0},
+ };
+
for (size_t orientation = 0; orientation < arraysize(orientations);
++orientation) {
- // Create a split view.
- SingleSplitView split(
- new View(), new View(), orientations[orientation], NULL);
-
- // Set initial size and divider offset.
- EXPECT_EQ(test_cases[0].primary_axis_size,
- test_cases[0].secondary_axis_size);
- split.SetBounds(0, 0, test_cases[0].primary_axis_size,
- test_cases[0].secondary_axis_size);
- split.set_divider_offset(test_cases[0].divider_offset);
- split.Layout();
-
- // Run all test cases.
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- split.set_resize_leading_on_bounds_change(
- test_cases[i].resize_leading_on_bounds_change);
- if (split.orientation() == SingleSplitView::HORIZONTAL_SPLIT) {
- split.SetBounds(0, 0, test_cases[i].primary_axis_size,
- test_cases[i].secondary_axis_size);
- } else {
- split.SetBounds(0, 0, test_cases[i].secondary_axis_size,
- test_cases[i].primary_axis_size);
+ for (size_t border = 0; border < arraysize(borders); ++border) {
+ // Create a split view.
+ SingleSplitView split(new View(), new View(), orientations[orientation],
+ NULL);
+
+ // Set initial size and divider offset.
+ EXPECT_EQ(test_cases[0].primary_axis_size,
+ test_cases[0].secondary_axis_size);
+ split.SetBounds(0, 0, test_cases[0].primary_axis_size,
+ test_cases[0].secondary_axis_size);
+
+ if (border != 0)
+ split.SetBorder(
+ Border::CreateEmptyBorder(borders[border][0], borders[border][1],
+ borders[border][2], borders[border][3]));
+
+ split.set_divider_offset(test_cases[0].divider_offset);
+ split.Layout();
+
+ // Run all test cases.
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ split.set_resize_leading_on_bounds_change(
+ test_cases[i].resize_leading_on_bounds_change);
+ if (split.orientation() == SingleSplitView::HORIZONTAL_SPLIT) {
+ split.SetBounds(0, 0, test_cases[i].primary_axis_size,
+ test_cases[i].secondary_axis_size);
+ } else {
+ split.SetBounds(0, 0, test_cases[i].secondary_axis_size,
+ test_cases[i].primary_axis_size);
+ }
+
+ EXPECT_EQ(test_cases[i].divider_offset, split.divider_offset());
+ VerifySplitViewLayout(split);
}
- EXPECT_EQ(test_cases[i].divider_offset, split.divider_offset());
- VerifySplitViewLayout(split);
- }
+ // Special cases, one of the child views is hidden.
+ split.child_at(0)->SetVisible(false);
+ split.Layout();
- // Special cases, one of the child views is hidden.
- split.child_at(0)->SetVisible(false);
- split.Layout();
+ EXPECT_EQ(split.GetContentsBounds().size(), split.child_at(1)->size());
- EXPECT_EQ(split.size(), split.child_at(1)->size());
+ split.child_at(0)->SetVisible(true);
+ split.child_at(1)->SetVisible(false);
+ split.Layout();
- split.child_at(0)->SetVisible(true);
- split.child_at(1)->SetVisible(false);
- split.Layout();
-
- EXPECT_EQ(split.size(), split.child_at(0)->size());
+ EXPECT_EQ(split.GetContentsBounds().size(), split.child_at(0)->size());
+ }
}
}
diff --git a/chromium/ui/views/controls/slide_out_view.cc b/chromium/ui/views/controls/slide_out_view.cc
index d3cafecf7eb..2775c0889af 100644
--- a/chromium/ui/views/controls/slide_out_view.cc
+++ b/chromium/ui/views/controls/slide_out_view.cc
@@ -10,23 +10,25 @@
namespace views {
-SlideOutView::SlideOutView()
- : gesture_scroll_amount_(0.f) {
+SlideOutView::SlideOutView() {
// If accelerated compositing is not available, this widget tracks the
// OnSlideOut event but does not render any visible changes.
SetPaintToLayer(true);
- SetFillsBoundsOpaquely(false);
+ layer()->SetFillsBoundsOpaquely(false);
}
SlideOutView::~SlideOutView() {
}
void SlideOutView::OnGestureEvent(ui::GestureEvent* event) {
+ const float kScrollRatioForClosingNotification = 0.5f;
+
if (event->type() == ui::ET_SCROLL_FLING_START) {
// The threshold for the fling velocity is computed empirically.
// The unit is in pixels/second.
const float kFlingThresholdForClose = 800.f;
- if (fabsf(event->details().velocity_x()) > kFlingThresholdForClose) {
+ if (is_slide_out_enabled_ &&
+ fabsf(event->details().velocity_x()) > kFlingThresholdForClose) {
SlideOutAndClose(event->details().velocity_x() < 0 ? SLIDE_LEFT :
SLIDE_RIGHT);
event->StopPropagation();
@@ -40,22 +42,35 @@ void SlideOutView::OnGestureEvent(ui::GestureEvent* event) {
return;
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) {
- gesture_scroll_amount_ = 0.f;
+ gesture_amount_ = 0.f;
} else if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
// The scroll-update events include the incremental scroll amount.
- gesture_scroll_amount_ += event->details().scroll_x();
+ gesture_amount_ += event->details().scroll_x();
+
+ float scroll_amount;
+ if (is_slide_out_enabled_) {
+ scroll_amount = gesture_amount_;
+ layer()->SetOpacity(1.f - std::min(fabsf(scroll_amount) / width(), 1.f));
+ } else {
+ if (gesture_amount_ >= 0) {
+ scroll_amount = std::min(0.5f * gesture_amount_,
+ width() * kScrollRatioForClosingNotification);
+ } else {
+ scroll_amount =
+ std::max(0.5f * gesture_amount_,
+ -1.f * width() * kScrollRatioForClosingNotification);
+ }
+ }
gfx::Transform transform;
- transform.Translate(gesture_scroll_amount_, 0.0);
+ transform.Translate(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;
- float scrolled_ratio = fabsf(gesture_scroll_amount_) / width();
- if (scrolled_ratio >= kScrollRatioForClosingNotification) {
- SlideOutAndClose(gesture_scroll_amount_ < 0 ? SLIDE_LEFT : SLIDE_RIGHT);
+ float scrolled_ratio = fabsf(gesture_amount_) / width();
+ if (is_slide_out_enabled_ &&
+ scrolled_ratio >= kScrollRatioForClosingNotification) {
+ SlideOutAndClose(gesture_amount_ < 0 ? SLIDE_LEFT : SLIDE_RIGHT);
event->StopPropagation();
return;
}
diff --git a/chromium/ui/views/controls/slide_out_view.h b/chromium/ui/views/controls/slide_out_view.h
index 7fdb637cc7b..89962f2d317 100644
--- a/chromium/ui/views/controls/slide_out_view.h
+++ b/chromium/ui/views/controls/slide_out_view.h
@@ -19,6 +19,8 @@ class VIEWS_EXPORT SlideOutView : public views::View,
SlideOutView();
~SlideOutView() override;
+ bool slide_out_enabled() { return is_slide_out_enabled_; }
+
protected:
// Called when user intends to close the View by sliding it out.
virtual void OnSlideOut() = 0;
@@ -26,6 +28,10 @@ class VIEWS_EXPORT SlideOutView : public views::View,
// Overridden from views::View.
void OnGestureEvent(ui::GestureEvent* event) override;
+ void set_slide_out_enabled(bool is_slide_out_enabled) {
+ is_slide_out_enabled_ = is_slide_out_enabled;
+ }
+
private:
enum SlideDirection {
SLIDE_LEFT,
@@ -41,7 +47,8 @@ class VIEWS_EXPORT SlideOutView : public views::View,
// Overridden from ImplicitAnimationObserver.
void OnImplicitAnimationsCompleted() override;
- float gesture_scroll_amount_;
+ float gesture_amount_ = 0.f;
+ bool is_slide_out_enabled_ = true;
DISALLOW_COPY_AND_ASSIGN(SlideOutView);
};
diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc
index 3909e7f021b..9c8f720cee1 100644
--- a/chromium/ui/views/controls/styled_label.cc
+++ b/chromium/ui/views/controls/styled_label.cc
@@ -99,7 +99,8 @@ const char StyledLabel::kViewClassName[] = "StyledLabel";
StyledLabel::StyledLabel(const base::string16& text,
StyledLabelListener* listener)
- : specified_line_height_(0),
+ : font_list_(Label().font_list()),
+ specified_line_height_(0),
listener_(listener),
width_at_last_size_calculation_(0),
width_at_last_layout_(0),
diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc
index 3c0a7e741f0..cae7f67744e 100644
--- a/chromium/ui/views/controls/styled_label_unittest.cc
+++ b/chromium/ui/views/controls/styled_label_unittest.cc
@@ -184,7 +184,8 @@ TEST_F(StyledLabelTest, DontBreakLinks) {
const std::string link_text("and this should be a link");
InitStyledLabel(text + link_text);
styled()->AddStyleRange(
- gfx::Range(text.size(), text.size() + link_text.size()),
+ gfx::Range(static_cast<uint32_t>(text.size()),
+ static_cast<uint32_t>(text.size() + link_text.size())),
StyledLabel::RangeStyleInfo::CreateForLink());
Label label(ASCIIToUTF16(text + link_text.substr(0, link_text.size() / 2)));
@@ -209,7 +210,8 @@ TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) {
StyledLabel::RangeStyleInfo style_info;
style_info.disable_line_wrapping = true;
styled()->AddStyleRange(
- gfx::Range(text.size(), text.size() + unbreakable_text.size()),
+ gfx::Range(static_cast<uint32_t>(text.size()),
+ static_cast<uint32_t>(text.size() + unbreakable_text.size())),
style_info);
Label label(ASCIIToUTF16(
@@ -233,7 +235,8 @@ TEST_F(StyledLabelTest, StyledRangeUnderlined) {
StyledLabel::RangeStyleInfo style_info;
style_info.font_style = gfx::Font::UNDERLINE;
styled()->AddStyleRange(
- gfx::Range(text.size(), text.size() + underlined_text.size()),
+ gfx::Range(static_cast<uint32_t>(text.size()),
+ static_cast<uint32_t>(text.size() + underlined_text.size())),
style_info);
styled()->SetBounds(0, 0, 1000, 1000);
@@ -255,7 +258,8 @@ TEST_F(StyledLabelTest, StyledRangeBold) {
StyledLabel::RangeStyleInfo style_info;
style_info.font_style = gfx::Font::BOLD;
- styled()->AddStyleRange(gfx::Range(0, bold_text.size()), style_info);
+ styled()->AddStyleRange(
+ gfx::Range(0u, static_cast<uint32_t>(bold_text.size())), style_info);
// Calculate the bold text width if it were a pure label view, both with bold
// and normal style.
@@ -315,13 +319,15 @@ TEST_F(StyledLabelTest, Color) {
StyledLabel::RangeStyleInfo style_info_red;
style_info_red.color = SK_ColorRED;
- styled()->AddStyleRange(gfx::Range(0, text_red.size()), style_info_red);
+ styled()->AddStyleRange(
+ gfx::Range(0u, static_cast<uint32_t>(text_red.size())), style_info_red);
StyledLabel::RangeStyleInfo style_info_link =
StyledLabel::RangeStyleInfo::CreateForLink();
- styled()->AddStyleRange(gfx::Range(text_red.size(),
- text_red.size() + text_link.size()),
- style_info_link);
+ styled()->AddStyleRange(
+ gfx::Range(static_cast<uint32_t>(text_red.size()),
+ static_cast<uint32_t>(text_red.size() + text_link.size())),
+ style_info_link);
styled()->SetBounds(0, 0, 1000, 1000);
styled()->Layout();
@@ -377,10 +383,13 @@ TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
StyledLabel::RangeStyleInfo tooltip_style;
tooltip_style.tooltip = ASCIIToUTF16("tooltip");
styled()->AddStyleRange(
- gfx::Range(tooltip_start, tooltip_start + tooltip_text.size()),
+ gfx::Range(static_cast<uint32_t>(tooltip_start),
+ static_cast<uint32_t>(tooltip_start + tooltip_text.size())),
tooltip_style);
- styled()->AddStyleRange(gfx::Range(link_start, link_start + link_text.size()),
- StyledLabel::RangeStyleInfo::CreateForLink());
+ styled()->AddStyleRange(
+ gfx::Range(static_cast<uint32_t>(link_start),
+ static_cast<uint32_t>(link_start + link_text.size())),
+ StyledLabel::RangeStyleInfo::CreateForLink());
// Break line inside the range with the tooltip.
Label label(ASCIIToUTF16(
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
index eb15ac9a3be..5579bb07c04 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -9,6 +9,7 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/accessibility/ax_view_state.h"
+#include "ui/base/default_style.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
@@ -27,6 +28,10 @@ const SkColor kTabTitleColor_Hovered = SK_ColorBLACK;
const SkColor kTabBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8);
const SkScalar kTabBorderThickness = 1.0f;
+const gfx::Font::FontStyle kHoverStyle = gfx::Font::NORMAL;
+const gfx::Font::FontStyle kActiveStyle = gfx::Font::BOLD;
+const gfx::Font::FontStyle kInactiveStyle = gfx::Font::NORMAL;
+
} // namespace
namespace views {
@@ -102,9 +107,11 @@ const char Tab::kViewClassName[] = "Tab";
Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
: tabbed_pane_(tabbed_pane),
- title_(new Label(title,
- ui::ResourceBundle::GetSharedInstance().GetFontList(
- ui::ResourceBundle::BoldFont))),
+ title_(new Label(
+ title,
+ ui::ResourceBundle::GetSharedInstance().GetFontListWithDelta(
+ ui::kLabelFontSizeDelta,
+ kActiveStyle))),
tab_state_(TAB_ACTIVE),
contents_(contents) {
// Calculate this now while the font list is guaranteed to be bold.
@@ -182,15 +189,18 @@ void Tab::SetState(TabState tab_state) {
switch (tab_state) {
case TAB_INACTIVE:
title_->SetEnabledColor(kTabTitleColor_Inactive);
- title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BaseFont));
+ title_->SetFontList(
+ rb.GetFontListWithDelta(ui::kLabelFontSizeDelta, kInactiveStyle));
break;
case TAB_ACTIVE:
title_->SetEnabledColor(kTabTitleColor_Active);
- title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
+ title_->SetFontList(
+ rb.GetFontListWithDelta(ui::kLabelFontSizeDelta, kActiveStyle));
break;
case TAB_HOVERED:
title_->SetEnabledColor(kTabTitleColor_Hovered);
- title_->SetFontList(rb.GetFontList(ui::ResourceBundle::BaseFont));
+ title_->SetFontList(
+ rb.GetFontListWithDelta(ui::kLabelFontSizeDelta, kHoverStyle));
break;
}
SchedulePaint();
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index a115af7d033..74d18b70564 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -12,9 +12,11 @@
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/default_style.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/ime/input_method.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/base/touch/selection_bound.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/compositor/canvas_painter.h"
@@ -239,6 +241,11 @@ int GetViewsCommand(const ui::TextEditCommandAuraLinux& command, bool rtl) {
}
#endif
+const gfx::FontList& GetDefaultFontList() {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta);
+}
+
} // namespace
// static
@@ -284,6 +291,7 @@ Textfield::Textfield()
weak_ptr_factory_(this) {
set_context_menu_controller(this);
set_drag_controller(this);
+ GetRenderText()->SetFontList(GetDefaultFontList());
SetBorder(scoped_ptr<Border>(new FocusableBorder()));
SetFocusable(true);
@@ -1090,8 +1098,8 @@ void Textfield::WriteDragDataForView(View* sender,
label.SetSubpixelRenderingEnabled(false);
gfx::Size size(label.GetPreferredSize());
gfx::NativeView native_view = GetWidget()->GetNativeView();
- gfx::Display display = gfx::Screen::GetScreenFor(native_view)->
- GetDisplayNearestWindow(native_view);
+ gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(native_view);
size.SetToMin(gfx::Size(display.size().width(), height()));
label.SetBoundsRect(gfx::Rect(size));
scoped_ptr<gfx::Canvas> canvas(
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index dd00e40fd86..97595c57cb4 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -436,11 +436,6 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
widget_->Show();
textfield_->RequestFocus();
- // On Mac, activation is asynchronous since desktop widgets are used. We
- // don't want parallel tests to steal active status either, so fake it.
-#if defined(OS_MACOSX) && !defined(USE_AURA)
- fake_activation_ = test::WidgetTest::FakeWidgetIsActiveAlways();
-#endif
event_generator_.reset(
new ui::test::EventGenerator(GetContext(), widget_->GetNativeWindow()));
}
@@ -660,7 +655,6 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
private:
ui::ClipboardType copied_to_clipboard_;
- scoped_ptr<test::WidgetTest::FakeActivation> fake_activation_;
scoped_ptr<ui::test::EventGenerator> event_generator_;
DISALLOW_COPY_AND_ASSIGN(TextfieldTest);
};
@@ -726,6 +720,10 @@ TEST_F(TextfieldTest, KeysWithModifiersTest) {
SendKeyPress(ui::VKEY_2, command);
SendKeyPress(ui::VKEY_3, 0);
SendKeyPress(ui::VKEY_4, 0);
+ SendKeyPress(ui::VKEY_OEM_PLUS, ctrl);
+ SendKeyPress(ui::VKEY_OEM_PLUS, ctrl | shift);
+ SendKeyPress(ui::VKEY_OEM_MINUS, ctrl);
+ SendKeyPress(ui::VKEY_OEM_MINUS, ctrl | shift);
if (TestingNativeCrOs())
EXPECT_STR_EQ("TeTEx34", textfield_->text());
diff --git a/chromium/ui/views/controls/tree/tree_view.cc b/chromium/ui/views/controls/tree/tree_view.cc
index b7918430e50..30428a31cad 100644
--- a/chromium/ui/views/controls/tree/tree_view.cc
+++ b/chromium/ui/views/controls/tree/tree_view.cc
@@ -250,9 +250,8 @@ void TreeView::SetSelectedNode(TreeModelNode* model_node) {
controller_->OnTreeViewSelectionChanged(this);
if (changed) {
- // TODO(dmazzoni): Decide if EVENT_SELECTION_CHANGED is a better choice for
- // sub-item selection event.
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_TEXT_CHANGED, true);
+ NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true);
}
}
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index 9a129c04611..686eeb6ddd4 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -294,7 +294,8 @@ void WebView::DidDestroyFullscreenWidget(int routing_id) {
ReattachForFullscreenChange(false);
}
-void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen) {
+void WebView::DidToggleFullscreenModeForTab(bool entered_fullscreen,
+ bool will_cause_resize) {
if (embed_fullscreen_widget_mode_enabled_)
ReattachForFullscreenChange(entered_fullscreen);
}
@@ -338,24 +339,12 @@ void WebView::AttachWebContents() {
if (focus_manager && focus_manager->GetFocusedView() == this)
OnFocus();
-#if defined(OS_WIN)
- if (!is_embedding_fullscreen_widget_) {
- web_contents()->SetParentNativeViewAccessible(
- parent()->GetNativeViewAccessible());
- }
-#endif
-
OnWebContentsAttached();
}
void WebView::DetachWebContents() {
- if (web_contents()) {
+ if (web_contents())
holder_->Detach();
-#if defined(OS_WIN)
- if (!is_embedding_fullscreen_widget_)
- web_contents()->SetParentNativeViewAccessible(NULL);
-#endif
- }
}
void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
diff --git a/chromium/ui/views/controls/webview/webview.h b/chromium/ui/views/controls/webview/webview.h
index cb8ba7a2b3b..9ff7c7f6091 100644
--- a/chromium/ui/views/controls/webview/webview.h
+++ b/chromium/ui/views/controls/webview/webview.h
@@ -133,7 +133,8 @@ class WEBVIEW_EXPORT WebView : public View,
void WebContentsDestroyed() override;
void DidShowFullscreenWidget(int routing_id) override;
void DidDestroyFullscreenWidget(int routing_id) override;
- void DidToggleFullscreenModeForTab(bool entered_fullscreen) override;
+ void DidToggleFullscreenModeForTab(bool entered_fullscreen,
+ bool will_cause_resize) override;
void DidAttachInterstitialPage() override;
void DidDetachInterstitialPage() override;
// Workaround for MSVC++ linker bug/feature that requires
diff --git a/chromium/ui/views/controls/webview/webview_unittest.cc b/chromium/ui/views/controls/webview/webview_unittest.cc
index bc2a927c5a7..2ecf9578118 100644
--- a/chromium/ui/views/controls/webview/webview_unittest.cc
+++ b/chromium/ui/views/controls/webview/webview_unittest.cc
@@ -14,13 +14,16 @@
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/web_contents_tester.h"
#include "content/test/test_content_browser_client.h"
-#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/test/widget_test.h"
+#if defined(USE_AURA)
+#include "ui/aura/window.h"
+#endif
+
namespace views {
namespace {
@@ -43,7 +46,7 @@ class WebViewTestViewsDelegate : public views::TestViewsDelegate {
DISALLOW_COPY_AND_ASSIGN(WebViewTestViewsDelegate);
};
-// Provides functionaity to observe events on a WebContents like WasShown/
+// Provides functionality to observe events on a WebContents like WasShown/
// WasHidden/WebContentsDestroyed.
class WebViewTestWebContentsObserver : public content::WebContentsObserver {
public:
@@ -51,7 +54,8 @@ class WebViewTestWebContentsObserver : public content::WebContentsObserver {
: web_contents_(web_contents),
was_shown_(false),
shown_count_(0),
- hidden_count_(0) {
+ hidden_count_(0),
+ valid_root_while_shown_(true) {
content::WebContentsObserver::Observe(web_contents);
}
@@ -67,8 +71,10 @@ class WebViewTestWebContentsObserver : public content::WebContentsObserver {
}
void WasShown() override {
+#if defined(USE_AURA)
valid_root_while_shown_ =
web_contents()->GetNativeView()->GetRootWindow() != NULL;
+#endif
was_shown_ = true;
++shown_count_;
}
@@ -197,7 +203,9 @@ TEST_F(WebViewUnitTest, TestWebViewAttachDetachWebContents) {
web_view()->SetWebContents(web_contents1.get());
EXPECT_TRUE(observer1.was_shown());
+#if defined(USE_AURA)
EXPECT_TRUE(web_contents1->GetNativeView()->IsVisible());
+#endif
EXPECT_EQ(observer1.shown_count(), 1);
EXPECT_EQ(observer1.hidden_count(), 0);
EXPECT_TRUE(observer1.valid_root_while_shown());
@@ -235,6 +243,7 @@ TEST_F(WebViewUnitTest, TestWebViewAttachDetachWebContents) {
EXPECT_EQ(1, observer2.shown_count());
EXPECT_EQ(1, observer2.hidden_count());
+#if defined(USE_AURA)
// Case 4: Test that making the webview visible when a window has an invisible
// parent does not make the web contents visible.
top_level_widget()->Hide();
@@ -246,7 +255,18 @@ TEST_F(WebViewUnitTest, TestWebViewAttachDetachWebContents) {
EXPECT_EQ(2, observer1.shown_count());
top_level_widget()->Hide();
EXPECT_EQ(2, observer1.hidden_count());
-
+#else
+ // On Mac, changes to window visibility do not trigger calls to WebContents::
+ // WasShown() or WasHidden(), since the OS does not provide good signals for
+ // window visibility. However, we can still test that moving a visible WebView
+ // whose WebContents is not currently showing to a new, visible window will
+ // show the WebContents. Simulate the "hide window with visible WebView" step
+ // simply by detaching the WebContents.
+ web_view()->SetVisible(true);
+ EXPECT_EQ(2, observer1.shown_count());
+ web_view()->holder()->Detach();
+ EXPECT_EQ(2, observer1.hidden_count());
+#endif
// Case 5: Test that moving from a hidden parent to a visible parent makes the
// web contents visible.
Widget* parent2 = CreateTopLevelFramelessPlatformWidget();
@@ -281,13 +301,13 @@ TEST_F(WebViewUnitTest, EmbeddedFullscreenDuringScreenCapture_Layout) {
// WebView like before.
delegate.set_is_fullscreened(true);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(true);
+ DidToggleFullscreenModeForTab(true, false);
EXPECT_EQ(gfx::Rect(0, 0, 100, 100), holder()->bounds());
// ...and transition back out of fullscreen mode.
delegate.set_is_fullscreened(false);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(false);
+ DidToggleFullscreenModeForTab(false, false);
EXPECT_EQ(gfx::Rect(0, 0, 100, 100), holder()->bounds());
// Now, begin screen capture of the WebContents and then enter fullscreen
@@ -297,7 +317,7 @@ TEST_F(WebViewUnitTest, EmbeddedFullscreenDuringScreenCapture_Layout) {
web_contents->IncrementCapturerCount(capture_size);
delegate.set_is_fullscreened(true);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(true);
+ DidToggleFullscreenModeForTab(true, false);
EXPECT_EQ(gfx::Rect(18, 26, 64, 48), holder()->bounds());
// Resize the WebView so that its width is smaller than the capture width.
@@ -309,7 +329,7 @@ TEST_F(WebViewUnitTest, EmbeddedFullscreenDuringScreenCapture_Layout) {
// of the holder fill the entire WebView once again.
delegate.set_is_fullscreened(false);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(false);
+ DidToggleFullscreenModeForTab(false, false);
EXPECT_EQ(gfx::Rect(0, 0, 32, 32), holder()->bounds());
}
@@ -340,7 +360,7 @@ TEST_F(WebViewUnitTest, EmbeddedFullscreenDuringScreenCapture_Switching) {
web_contents1->IncrementCapturerCount(capture_size);
delegate1.set_is_fullscreened(true);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(true);
+ DidToggleFullscreenModeForTab(true, false);
EXPECT_EQ(web_contents1->GetNativeView(), holder()->native_view());
EXPECT_EQ(gfx::Rect(18, 26, 64, 48), holder()->bounds());
@@ -393,7 +413,7 @@ TEST_F(WebViewUnitTest, EmbeddedFullscreenDuringScreenCapture_ClickToFocus) {
web_contents->IncrementCapturerCount(capture_size);
delegate.set_is_fullscreened(true);
static_cast<content::WebContentsObserver*>(web_view())->
- DidToggleFullscreenModeForTab(true);
+ DidToggleFullscreenModeForTab(true, false);
EXPECT_EQ(gfx::Rect(18, 21, 64, 48), holder()->bounds());
// Focus the other widget.
diff --git a/chromium/ui/views/corewm/cursor_height_provider_win.cc b/chromium/ui/views/corewm/cursor_height_provider_win.cc
index 17a6f83de91..398b009b71b 100644
--- a/chromium/ui/views/corewm/cursor_height_provider_win.cc
+++ b/chromium/ui/views/corewm/cursor_height_provider_win.cc
@@ -35,7 +35,7 @@ PixelData GetBitmapData(HBITMAP handle, const BITMAPINFO& info, HDC hdc) {
// Masks are monochromatic.
DCHECK_EQ(info.bmiHeader.biBitCount, 1);
if (info.bmiHeader.biBitCount != 1)
- return data.Pass();
+ return data;
// When getting pixel data palette is appended to memory pointed by
// BITMAPINFO passed so allocate additional memory to store additional data.
@@ -55,7 +55,7 @@ PixelData GetBitmapData(HBITMAP handle, const BITMAPINFO& info, HDC hdc) {
if (result == 0)
data.reset();
- return data.Pass();
+ return data;
}
// Checks if the specifed row is transparent in provided bitmap.
diff --git a/chromium/ui/views/corewm/tooltip.h b/chromium/ui/views/corewm/tooltip.h
index b8e6803a172..387fa3c51d3 100644
--- a/chromium/ui/views/corewm/tooltip.h
+++ b/chromium/ui/views/corewm/tooltip.h
@@ -26,8 +26,7 @@ class VIEWS_EXPORT Tooltip {
virtual ~Tooltip() {}
// Returns the max width of the tooltip when shown at the specified location.
- virtual int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const = 0;
+ virtual int GetMaxWidth(const gfx::Point& location) const = 0;
// Updates the text on the tooltip and resizes to fit.
virtual void SetText(aura::Window* window,
diff --git a/chromium/ui/views/corewm/tooltip_aura.cc b/chromium/ui/views/corewm/tooltip_aura.cc
index 060d43453fb..80dac9fd8f6 100644
--- a/chromium/ui/views/corewm/tooltip_aura.cc
+++ b/chromium/ui/views/corewm/tooltip_aura.cc
@@ -138,7 +138,7 @@ void TooltipAura::SetTooltipBounds(const gfx::Point& mouse_pos,
const gfx::Size& tooltip_size) {
gfx::Rect tooltip_rect(mouse_pos, tooltip_size);
tooltip_rect.Offset(kCursorOffsetX, kCursorOffsetY);
- gfx::Screen* screen = gfx::Screen::GetScreenFor(tooltip_window_);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
gfx::Rect display_bounds(screen->GetDisplayNearestPoint(mouse_pos).bounds());
// If tooltip is out of bounds on the x axis, we simply shift it
@@ -165,9 +165,8 @@ void TooltipAura::DestroyWidget() {
}
}
-int TooltipAura::GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(context);
+int TooltipAura::GetMaxWidth(const gfx::Point& location) const {
+ gfx::Screen* screen = gfx::Screen::GetScreen();
gfx::Rect display_bounds(screen->GetDisplayNearestPoint(location).bounds());
return std::min(kTooltipMaxWidthPixels, (display_bounds.width() + 1) / 2);
}
@@ -176,7 +175,7 @@ void TooltipAura::SetText(aura::Window* window,
const base::string16& tooltip_text,
const gfx::Point& location) {
tooltip_window_ = window;
- tooltip_view_->SetMaxWidth(GetMaxWidth(location, window));
+ tooltip_view_->SetMaxWidth(GetMaxWidth(location));
tooltip_view_->SetText(tooltip_text);
if (!widget_) {
diff --git a/chromium/ui/views/corewm/tooltip_aura.h b/chromium/ui/views/corewm/tooltip_aura.h
index a905fbbe1ac..781acf97c41 100644
--- a/chromium/ui/views/corewm/tooltip_aura.h
+++ b/chromium/ui/views/corewm/tooltip_aura.h
@@ -7,7 +7,6 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/screen_type_delegate.h"
#include "ui/views/corewm/tooltip.h"
#include "ui/views/widget/widget_observer.h"
@@ -40,8 +39,7 @@ class VIEWS_EXPORT TooltipAura : public Tooltip, public WidgetObserver {
void DestroyWidget();
// Tooltip:
- int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const override;
+ int GetMaxWidth(const gfx::Point& location) const override;
void SetText(aura::Window* window,
const base::string16& tooltip_text,
const gfx::Point& location) override;
diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc
index ca27ffda393..c5dad8c4598 100644
--- a/chromium/ui/views/corewm/tooltip_controller.cc
+++ b/chromium/ui/views/corewm/tooltip_controller.cc
@@ -97,7 +97,7 @@ aura::Window* GetTooltipTarget(const ui::MouseEvent& event,
gfx::Point screen_loc(event.location());
aura::client::GetScreenPositionClient(event_target->GetRootWindow())->
ConvertPointToScreen(event_target, &screen_loc);
- gfx::Screen* screen = gfx::Screen::GetScreenFor(event_target);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc);
if (!target)
return NULL;
@@ -140,9 +140,8 @@ TooltipController::~TooltipController() {
tooltip_window_->RemoveObserver(this);
}
-int TooltipController::GetMaxWidth(const gfx::Point& location,
- gfx::NativeView context) const {
- return tooltip_->GetMaxWidth(location, context);
+int TooltipController::GetMaxWidth(const gfx::Point& location) const {
+ return tooltip_->GetMaxWidth(location);
}
void TooltipController::UpdateTooltip(aura::Window* target) {
@@ -233,6 +232,10 @@ void TooltipController::OnMouseEvent(ui::MouseEvent* event) {
// Hide the tooltip for click, release, drag, wheel events.
if (tooltip_->IsVisible())
tooltip_->Hide();
+
+ // Don't reshow the tooltip during scroll.
+ if (tooltip_timer_.IsRunning())
+ tooltip_timer_.Reset();
break;
default:
break;
diff --git a/chromium/ui/views/corewm/tooltip_controller.h b/chromium/ui/views/corewm/tooltip_controller.h
index ee42e723c92..5171726c5dc 100644
--- a/chromium/ui/views/corewm/tooltip_controller.h
+++ b/chromium/ui/views/corewm/tooltip_controller.h
@@ -39,8 +39,7 @@ class VIEWS_EXPORT TooltipController : public aura::client::TooltipClient,
~TooltipController() override;
// Overridden from aura::client::TooltipClient.
- int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const override;
+ int GetMaxWidth(const gfx::Point& location) const override;
void UpdateTooltip(aura::Window* target) override;
void SetTooltipShownTimeout(aura::Window* target, int timeout_in_ms) override;
void SetTooltipsEnabled(bool enable) override;
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index ca663228077..4fc0bc8e428 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -19,7 +19,6 @@
#include "ui/gfx/font.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/screen.h"
-#include "ui/gfx/screen_type_delegate.h"
#include "ui/gfx/text_elider.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/corewm/tooltip_controller_test_helper.h"
@@ -427,14 +426,13 @@ class TooltipControllerCaptureTest : public TooltipControllerTest {
&screen_position_client_);
#if !defined(OS_CHROMEOS)
desktop_screen_.reset(CreateDesktopScreen());
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
- desktop_screen_.get());
+ gfx::Screen::SetScreenInstance(desktop_screen_.get());
#endif
}
void TearDown() override {
#if !defined(OS_CHROMEOS)
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen());
+ gfx::Screen::SetScreenInstance(test_screen());
desktop_screen_.reset();
#endif
aura::client::SetScreenPositionClient(GetRootWindow(), NULL);
@@ -534,8 +532,7 @@ class TestTooltip : public Tooltip {
const base::string16& tooltip_text() const { return tooltip_text_; }
// Tooltip:
- int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const override {
+ int GetMaxWidth(const gfx::Point& location) const override {
return 100;
}
void SetText(aura::Window* window,
diff --git a/chromium/ui/views/corewm/tooltip_win.cc b/chromium/ui/views/corewm/tooltip_win.cc
index 46635d2ba5d..b892d3871a2 100644
--- a/chromium/ui/views/corewm/tooltip_win.cc
+++ b/chromium/ui/views/corewm/tooltip_win.cc
@@ -77,7 +77,6 @@ bool TooltipWin::EnsureTooltipWindow() {
}
void TooltipWin::PositionTooltip() {
- // This code only runs for non-metro, so GetNativeScreen() is fine.
gfx::Point screen_point = gfx::win::DIPToScreenPoint(location_);
const int cursoroffset = GetCurrentCursorVisibleHeight();
screen_point.Offset(0, cursoroffset);
@@ -87,7 +86,7 @@ void TooltipWin::PositionTooltip() {
const gfx::Size size(LOWORD(tooltip_size), HIWORD(tooltip_size));
const gfx::Display display(
- gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));
+ gfx::Screen::GetScreen()->GetDisplayNearestPoint(screen_point));
gfx::Rect tooltip_bounds(screen_point, size);
tooltip_bounds.AdjustToFit(gfx::win::DIPToScreenRect(display.work_area()));
@@ -95,12 +94,10 @@ void TooltipWin::PositionTooltip() {
0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
-int TooltipWin::GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const {
- // This code only runs for non-metro, so GetNativeScreen() is fine.
+int TooltipWin::GetMaxWidth(const gfx::Point& location) const {
const gfx::Point screen_point = gfx::win::DIPToScreenPoint(location);
gfx::Display display(
- gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(screen_point));
+ gfx::Screen::GetScreen()->GetDisplayNearestPoint(screen_point));
const gfx::Rect monitor_bounds = display.bounds();
return (monitor_bounds.width() + 1) / 2;
}
@@ -126,7 +123,7 @@ void TooltipWin::SetText(aura::Window* window,
SendMessage(tooltip_hwnd_, TTM_SETTOOLINFO, 0,
reinterpret_cast<LPARAM>(&toolinfo_));
- int max_width = GetMaxWidth(location_, window);
+ int max_width = GetMaxWidth(location_);
SendMessage(tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, max_width);
}
diff --git a/chromium/ui/views/corewm/tooltip_win.h b/chromium/ui/views/corewm/tooltip_win.h
index 0b8ea61ecc3..eb9e5209de3 100644
--- a/chromium/ui/views/corewm/tooltip_win.h
+++ b/chromium/ui/views/corewm/tooltip_win.h
@@ -37,8 +37,7 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
void PositionTooltip();
// Tooltip:
- int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const override;
+ int GetMaxWidth(const gfx::Point& location) const override;
void SetText(aura::Window* window,
const base::string16& tooltip_text,
const gfx::Point& location) override;
diff --git a/chromium/ui/views/drag_utils.cc b/chromium/ui/views/drag_utils.cc
index 2597bf2936b..9eae9f6472b 100644
--- a/chromium/ui/views/drag_utils.cc
+++ b/chromium/ui/views/drag_utils.cc
@@ -14,13 +14,10 @@ namespace {
float GetDeviceScaleForNativeView(views::Widget* widget) {
float device_scale = 1.0f;
- // 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.
if (widget && widget->GetNativeView()) {
gfx::NativeView view = widget->GetNativeView();
- gfx::Display display = gfx::Screen::GetScreenFor(view)->
- GetDisplayNearestWindow(view);
+ gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(view);
device_scale = display.device_scale_factor();
}
return device_scale;
diff --git a/chromium/ui/views/event_monitor_mac.mm b/chromium/ui/views/event_monitor_mac.mm
index 45578c9948a..f21aae7cdd3 100644
--- a/chromium/ui/views/event_monitor_mac.mm
+++ b/chromium/ui/views/event_monitor_mac.mm
@@ -10,6 +10,7 @@
#include "ui/events/event.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_utils.h"
+#include "ui/gfx/screen.h"
namespace views {
@@ -28,11 +29,7 @@ scoped_ptr<EventMonitor> EventMonitor::CreateWindowMonitor(
// static
gfx::Point EventMonitor::GetLastMouseLocation() {
- NSPoint mouseLocation = [NSEvent mouseLocation];
- // Flip coordinates to gfx (0,0 in top-left corner) using primary screen.
- NSScreen* screen = [[NSScreen screens] firstObject];
- mouseLocation.y = NSMaxY([screen frame]) - mouseLocation.y;
- return gfx::Point(mouseLocation.x, mouseLocation.y);
+ return gfx::Screen::GetScreen()->GetCursorScreenPoint();
}
EventMonitorMac::EventMonitorMac(ui::EventHandler* event_handler,
diff --git a/chromium/ui/views/examples/button_example.cc b/chromium/ui/views/examples/button_example.cc
index 5b0b1e51365..2cf42afa9e3 100644
--- a/chromium/ui/views/examples/button_example.cc
+++ b/chromium/ui/views/examples/button_example.cc
@@ -65,8 +65,16 @@ void ButtonExample::CreateExampleView(View* container) {
container->AddChildView(new BlueButton(this, ASCIIToUTF16("Blue Button")));
- container->AddChildView(
- new MdTextButton(nullptr, base::ASCIIToUTF16("Material design")));
+ container->AddChildView(MdTextButton::CreateMdButton(
+ nullptr, base::ASCIIToUTF16("Material design")));
+ MdTextButton* md_button = MdTextButton::CreateMdButton(
+ nullptr, base::ASCIIToUTF16("Strong call to action"));
+ md_button->SetCallToAction(MdTextButton::STRONG_CALL_TO_ACTION);
+ container->AddChildView(md_button);
+ md_button = MdTextButton::CreateMdButton(
+ nullptr, base::ASCIIToUTF16("Weak call to action"));
+ md_button->SetCallToAction(MdTextButton::WEAK_CALL_TO_ACTION);
+ container->AddChildView(md_button);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
image_button_ = new ImageButton(this);
diff --git a/chromium/ui/views/examples/combobox_example.cc b/chromium/ui/views/examples/combobox_example.cc
index ed07379b605..4c4fdb300b9 100644
--- a/chromium/ui/views/examples/combobox_example.cc
+++ b/chromium/ui/views/examples/combobox_example.cc
@@ -7,7 +7,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/combobox/combobox.h"
-#include "ui/views/layout/fill_layout.h"
+#include "ui/views/layout/box_layout.h"
namespace views {
namespace examples {
@@ -26,13 +26,17 @@ base::string16 ComboboxModelExample::GetItemAt(int index) {
return base::UTF8ToUTF16(base::StringPrintf("Item %d", index));
}
-ComboboxExample::ComboboxExample() : ExampleBase("Combo Box"), combobox_(NULL) {
+ComboboxExample::ComboboxExample() : ExampleBase("Combo Box") {
}
ComboboxExample::~ComboboxExample() {
// Delete |combobox_| first as it references |combobox_model_|.
delete combobox_;
- combobox_ = NULL;
+ delete disabled_combobox_;
+ delete action_combobox_;
+ combobox_ = nullptr;
+ disabled_combobox_ = nullptr;
+ action_combobox_ = nullptr;
}
void ComboboxExample::CreateExampleView(View* container) {
@@ -40,14 +44,35 @@ void ComboboxExample::CreateExampleView(View* container) {
combobox_->set_listener(this);
combobox_->SetSelectedIndex(3);
- container->SetLayoutManager(new FillLayout);
+ disabled_combobox_ = new Combobox(&combobox_model_);
+ disabled_combobox_->set_listener(this);
+ disabled_combobox_->SetSelectedIndex(4);
+ disabled_combobox_->SetEnabled(false);
+
+ action_combobox_ = new Combobox(&combobox_model_);
+ action_combobox_->set_listener(this);
+ action_combobox_->SetStyle(Combobox::STYLE_ACTION);
+ // Note: STYLE_ACTION comboboxes always have the first item selected by
+ // default.
+
+ container->SetLayoutManager(new BoxLayout(
+ BoxLayout::kVertical,
+ 1, 1, 1));
container->AddChildView(combobox_);
+ container->AddChildView(disabled_combobox_);
+ container->AddChildView(action_combobox_);
}
void ComboboxExample::OnPerformAction(Combobox* combobox) {
- DCHECK_EQ(combobox_, combobox);
- PrintStatus("Selected: %s", base::UTF16ToUTF8(combobox_model_.GetItemAt(
- combobox->selected_index())).c_str());
+ if (combobox == combobox_) {
+ PrintStatus("Selected: %s", base::UTF16ToUTF8(combobox_model_.GetItemAt(
+ combobox->selected_index())).c_str());
+ } else if (combobox == action_combobox_) {
+ PrintStatus("Action: %s", base::UTF16ToUTF8(combobox_model_.GetItemAt(
+ combobox->selected_index())).c_str());
+ } else {
+ NOTREACHED() << "Surprising combobox.";
+ }
}
} // namespace examples
diff --git a/chromium/ui/views/examples/combobox_example.h b/chromium/ui/views/examples/combobox_example.h
index 9c84b75539f..a2448b2fc50 100644
--- a/chromium/ui/views/examples/combobox_example.h
+++ b/chromium/ui/views/examples/combobox_example.h
@@ -41,7 +41,9 @@ class VIEWS_EXAMPLES_EXPORT ComboboxExample : public ExampleBase,
void OnPerformAction(Combobox* combobox) override;
ComboboxModelExample combobox_model_;
- Combobox* combobox_;
+ Combobox* combobox_ = nullptr;
+ Combobox* disabled_combobox_ = nullptr;
+ Combobox* action_combobox_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ComboboxExample);
};
diff --git a/chromium/ui/views/examples/examples.gyp b/chromium/ui/views/examples/examples.gyp
index 1c1c3ddbfce..50790ad639a 100644
--- a/chromium/ui/views/examples/examples.gyp
+++ b/chromium/ui/views/examples/examples.gyp
@@ -161,8 +161,6 @@
'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',
],
@@ -171,6 +169,12 @@
'examples_with_content_main_exe.cc',
],
'conditions': [
+ ['component=="shared_library"', {
+ 'dependencies': [
+ '../../../base/base.gyp:base',
+ '../../../content/content.gyp:content',
+ ],
+ }],
['OS=="win"', {
'link_settings': {
'libraries': [
@@ -193,11 +197,6 @@
'../../../content/content.gyp:sandbox_helper_win',
],
}],
- ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
],
}, # 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 67ed52f5d6a..11096a781c1 100644
--- a/chromium/ui/views/examples/examples_main.cc
+++ b/chromium/ui/views/examples/examples_main.cc
@@ -37,7 +37,7 @@
#endif
#if defined(USE_X11)
-#include "ui/gfx/x/x11_connection.h"
+#include "ui/gfx/x/x11_connection.h" // nogncheck
#endif
int main(int argc, char** argv) {
@@ -93,8 +93,7 @@ int main(int argc, char** argv) {
#endif
#if !defined(OS_CHROMEOS) && defined(USE_AURA)
scoped_ptr<gfx::Screen> desktop_screen(views::CreateDesktopScreen());
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
- desktop_screen.get());
+ gfx::Screen::SetScreenInstance(desktop_screen.get());
#endif
views::examples::ShowExamplesWindow(
diff --git a/chromium/ui/views/examples/menu_example.cc b/chromium/ui/views/examples/menu_example.cc
index effa3e71713..166a792a847 100644
--- a/chromium/ui/views/examples/menu_example.cc
+++ b/chromium/ui/views/examples/menu_example.cc
@@ -65,7 +65,9 @@ class ExampleMenuButton : public MenuButton, public MenuButtonListener {
private:
// MenuButtonListener:
- void OnMenuButtonClicked(View* source, const gfx::Point& point) override;
+ void OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) override;
ui::SimpleMenuModel* GetMenuModel();
@@ -178,14 +180,14 @@ void ExampleMenuModel::ExecuteCommand(int command_id, int event_flags) {
// ExampleMenuButton -----------------------------------------------------------
ExampleMenuButton::ExampleMenuButton(const base::string16& test)
- : MenuButton(NULL, test, this, true) {
-}
+ : MenuButton(test, this, true) {}
ExampleMenuButton::~ExampleMenuButton() {
}
-void ExampleMenuButton::OnMenuButtonClicked(View* source,
- const gfx::Point& point) {
+void ExampleMenuButton::OnMenuButtonClicked(MenuButton* source,
+ const gfx::Point& point,
+ const ui::Event* event) {
menu_runner_.reset(new MenuRunner(GetMenuModel(), MenuRunner::HAS_MNEMONICS));
if (menu_runner_->RunMenuAt(source->GetWidget()->GetTopLevelWidget(),
diff --git a/chromium/ui/views/examples/multiline_example.cc b/chromium/ui/views/examples/multiline_example.cc
index 5ce1a1bddfb..d01b31e2d91 100644
--- a/chromium/ui/views/examples/multiline_example.cc
+++ b/chromium/ui/views/examples/multiline_example.cc
@@ -25,7 +25,7 @@ namespace examples {
namespace {
-gfx::Range ClampRange(gfx::Range range, size_t max) {
+gfx::Range ClampRange(gfx::Range range, uint32_t max) {
range.set_start(std::min(range.start(), max));
range.set_end(std::min(range.end(), max));
return range;
diff --git a/chromium/ui/views/examples/widget_example.cc b/chromium/ui/views/examples/widget_example.cc
index bcfb451aa85..0165de3f9dc 100644
--- a/chromium/ui/views/examples/widget_example.cc
+++ b/chromium/ui/views/examples/widget_example.cc
@@ -28,7 +28,6 @@ class DialogExample : public DialogDelegateView {
~DialogExample() override;
base::string16 GetWindowTitle() const override;
View* CreateExtraView() override;
- View* CreateTitlebarExtraView() override;
View* CreateFootnoteView() override;
};
@@ -61,12 +60,6 @@ View* DialogExample::CreateExtraView() {
return button;
}
-View* DialogExample::CreateTitlebarExtraView() {
- Label* label = new Label(ASCIIToUTF16("Extra view!"));
- label->SetEnabledColor(SK_ColorBLUE);
- return label;
-}
-
View* DialogExample::CreateFootnoteView() {
return new Label(ASCIIToUTF16("Footnote label!"));
}
diff --git a/chromium/ui/views/layout/box_layout.cc b/chromium/ui/views/layout/box_layout.cc
index 10f82b9aa54..9c3922e7e86 100644
--- a/chromium/ui/views/layout/box_layout.cc
+++ b/chromium/ui/views/layout/box_layout.cc
@@ -15,8 +15,6 @@ BoxLayout::BoxLayout(BoxLayout::Orientation orientation,
int between_child_spacing)
: orientation_(orientation),
inside_border_insets_(inside_border_vertical_spacing,
- inside_border_horizontal_spacing,
- inside_border_vertical_spacing,
inside_border_horizontal_spacing),
between_child_spacing_(between_child_spacing),
main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START),
diff --git a/chromium/ui/views/layout/layout_constants.h b/chromium/ui/views/layout/layout_constants.h
index 28d16b71c74..de062dd8aad 100644
--- a/chromium/ui/views/layout/layout_constants.h
+++ b/chromium/ui/views/layout/layout_constants.h
@@ -20,9 +20,6 @@ const int kPanelHorizMargin = 13;
// Top or bottom margin.
const int kPanelVertMargin = 13;
-// If some UI has some sub UI. Indent horizontally by the following value.
-const int kPanelHorizIndentation = 24;
-
// When several controls are aligned vertically, the baseline should be spaced
// by the following number of pixels.
const int kPanelVerticalSpacing = 32;
diff --git a/chromium/ui/views/linux_ui/linux_ui.cc b/chromium/ui/views/linux_ui/linux_ui.cc
index 63c74020c19..9430addaabe 100644
--- a/chromium/ui/views/linux_ui/linux_ui.cc
+++ b/chromium/ui/views/linux_ui/linux_ui.cc
@@ -6,7 +6,7 @@
#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"
+#include "ui/shell_dialogs/shell_dialog_linux.h"
namespace {
@@ -21,7 +21,7 @@ void LinuxUI::SetInstance(LinuxUI* instance) {
g_linux_ui = instance;
LinuxInputMethodContextFactory::SetInstance(instance);
LinuxFontDelegate::SetInstance(instance);
- LinuxShellDialog::SetInstance(instance);
+ ShellDialogLinux::SetInstance(instance);
ui::SetTextEditKeyBindingsDelegate(instance);
}
diff --git a/chromium/ui/views/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h
index 0a28b2e7c49..d795d7c488a 100644
--- a/chromium/ui/views/linux_ui/linux_ui.h
+++ b/chromium/ui/views/linux_ui/linux_ui.h
@@ -12,7 +12,7 @@
#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/shell_dialogs/shell_dialog_linux.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/linux_ui/status_icon_linux.h"
#include "ui/views/views_export.h"
@@ -52,7 +52,7 @@ class WindowButtonOrderObserver;
// liuigtk3.so, etc.
class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
public gfx::LinuxFontDelegate,
- public ui::LinuxShellDialog,
+ public ui::ShellDialogLinux,
public ui::TextEditKeyBindingsDelegateAuraLinux {
public:
// Describes the window management actions that could be taken in response to
diff --git a/chromium/ui/views/mouse_watcher_view_host.cc b/chromium/ui/views/mouse_watcher_view_host.cc
index 54412cf10d5..ac02b3cf4bf 100644
--- a/chromium/ui/views/mouse_watcher_view_host.cc
+++ b/chromium/ui/views/mouse_watcher_view_host.cc
@@ -49,8 +49,8 @@ bool MouseWatcherViewHost::IsMouseOverWindow() {
if (!widget)
return false;
- return gfx::Screen::GetScreenFor(widget->GetNativeView())->
- GetWindowUnderCursor() == widget->GetNativeWindow();
+ return gfx::Screen::GetScreen()->GetWindowUnderCursor() ==
+ widget->GetNativeWindow();
}
} // namespace views
diff --git a/chromium/ui/views/mus/BUILD.gn b/chromium/ui/views/mus/BUILD.gn
index f3863894939..a9005760549 100644
--- a/chromium/ui/views/mus/BUILD.gn
+++ b/chromium/ui/views/mus/BUILD.gn
@@ -23,6 +23,9 @@ component("mus") {
"native_widget_mus.h",
"platform_window_mus.cc",
"platform_window_mus.h",
+ "screen_mus.cc",
+ "screen_mus.h",
+ "screen_mus_delegate.h",
"surface_binding.cc",
"surface_binding.h",
"surface_context_factory.cc",
@@ -59,7 +62,6 @@ component("mus") {
"//mojo/converters/geometry",
"//mojo/converters/ime",
"//mojo/converters/input_events",
- "//mojo/converters/network",
"//mojo/converters/surfaces",
"//mojo/platform_handle:for_component",
"//mojo/public/c/system:for_component",
@@ -129,31 +131,41 @@ group("tests") {
testonly = true
deps = [
- ":views_apptests",
+ ":views_mus_unittests",
]
}
-mojo_native_application("views_apptests") {
+test("views_mus_unittests") {
testonly = true
- configs = [ "//build/config:precompiled_headers" ]
+ configs += [ "//build/config:precompiled_headers" ]
# TODO(sky): add more files.
sources = [
+ "../run_all_unittests.cc",
+ "../run_all_unittests.h",
+ "../test/native_widget_factory_mus.cc",
+ "../view_targeter_unittest.cc",
"../widget/native_widget_unittest.cc",
- "../widget/root_view_unittest.cc",
"../widget/widget_unittest.cc",
+ "native_widget_mus_unittest.cc",
"platform_test_helper_mus.cc",
+ "run_all_unittests_mus.cc",
]
deps = [
":mus",
"//base",
"//base:i18n",
- "//base/allocator",
"//base/test:test_support",
"//cc",
- "//mojo/shell/public/cpp:test_support",
+ "//components/mus/public/cpp",
+ "//components/mus/public/interfaces",
+ "//mojo/shell/background:lib",
+ "//mojo/shell/background:main",
+ "//mojo/shell/background/tests:test_support",
+ "//mojo/shell/public/cpp:sources",
+ "//mojo/shell/runner/host:lib",
"//skia",
"//testing/gtest",
"//third_party/icu",
@@ -182,7 +194,12 @@ mojo_native_application("views_apptests") {
data_deps = [
"//mash/wm",
- "//ui/resources:ui_test_pak",
+ ]
+
+ # TODO(thakis): This should be a data_deps on //ui/resources:ui_test_pak, but
+ # that has no effect. (See similar TODOs elsewhere ui_test.pak is listed)
+ data = [
+ "$root_out_dir/ui_test.pak",
]
if (is_win) {
diff --git a/chromium/ui/views/mus/DEPS b/chromium/ui/views/mus/DEPS
index 22b8edb4b19..a6ef8809458 100644
--- a/chromium/ui/views/mus/DEPS
+++ b/chromium/ui/views/mus/DEPS
@@ -22,3 +22,9 @@ include_rules = [
"+ui/platform_window",
"+ui/wm",
]
+
+specific_include_rules = {
+ "platform_test_helper_mus.cc": [
+ "+mojo/shell/background",
+ ],
+}
diff --git a/chromium/ui/views/mus/aura_init.cc b/chromium/ui/views/mus/aura_init.cc
index f7f30b0f24a..2b08108882e 100644
--- a/chromium/ui/views/mus/aura_init.cc
+++ b/chromium/ui/views/mus/aura_init.cc
@@ -11,7 +11,7 @@
#include "base/path_service.h"
#include "build/build_config.h"
#include "components/resource_provider/public/cpp/resource_loader.h"
-#include "mojo/shell/public/cpp/application_impl.h"
+#include "mojo/shell/public/cpp/connector.h"
#include "ui/aura/env.h"
#include "ui/base/ime/input_method_initializer.h"
#include "ui/base/resource/resource_bundle.h"
@@ -50,12 +50,12 @@ class MusViewsDelegate : public ViewsDelegate {
} // namespace
-AuraInit::AuraInit(mojo::ApplicationImpl* app, const std::string& resource_file)
+AuraInit::AuraInit(mojo::Connector* connector, const std::string& resource_file)
: resource_file_(resource_file),
views_delegate_(new MusViewsDelegate) {
aura::Env::CreateInstance(false);
- InitializeResources(app);
+ InitializeResources(connector);
ui::InitializeInputMethodForTesting();
}
@@ -72,13 +72,12 @@ AuraInit::~AuraInit() {
#endif
}
-void AuraInit::InitializeResources(mojo::ApplicationImpl* app) {
+void AuraInit::InitializeResources(mojo::Connector* connector) {
if (ui::ResourceBundle::HasSharedInstance())
return;
resource_provider::ResourceLoader resource_loader(
- app, GetResourcePaths(resource_file_));
- if (!resource_loader.BlockUntilLoaded())
- return;
+ connector, GetResourcePaths(resource_file_));
+ CHECK(resource_loader.BlockUntilLoaded());
CHECK(resource_loader.loaded());
ui::RegisterPathProvider();
base::File pak_file = resource_loader.ReleaseFile(resource_file_);
@@ -90,7 +89,7 @@ void AuraInit::InitializeResources(mojo::ApplicationImpl* app) {
// Initialize the skia font code to go ask fontconfig underneath.
#if defined(OS_LINUX) && !defined(OS_ANDROID)
- font_loader_ = skia::AdoptRef(new font_service::FontLoader(app->shell()));
+ font_loader_ = skia::AdoptRef(new font_service::FontLoader(connector));
SkFontConfigInterface::SetGlobal(font_loader_.get());
#endif
diff --git a/chromium/ui/views/mus/aura_init.h b/chromium/ui/views/mus/aura_init.h
index bff01716a2f..521acac91ee 100644
--- a/chromium/ui/views/mus/aura_init.h
+++ b/chromium/ui/views/mus/aura_init.h
@@ -18,7 +18,7 @@ class FontLoader;
}
namespace mojo {
-class ApplicationImpl;
+class Connector;
}
namespace views {
@@ -28,11 +28,11 @@ class ViewsDelegate;
// |resource_file| is the path to the apk file containing the resources.
class VIEWS_MUS_EXPORT AuraInit {
public:
- AuraInit(mojo::ApplicationImpl* app, const std::string& resource_file);
+ AuraInit(mojo::Connector* connector, const std::string& resource_file);
~AuraInit();
private:
- void InitializeResources(mojo::ApplicationImpl* app);
+ void InitializeResources(mojo::Connector* connector);
#if defined(OS_LINUX) && !defined(OS_ANDROID)
skia::RefPtr<font_service::FontLoader> font_loader_;
diff --git a/chromium/ui/views/mus/input_method_mus.cc b/chromium/ui/views/mus/input_method_mus.cc
index 3234f8fec7e..cee5ea671f7 100644
--- a/chromium/ui/views/mus/input_method_mus.cc
+++ b/chromium/ui/views/mus/input_method_mus.cc
@@ -103,4 +103,4 @@ void InputMethodMUS::UpdateTextInputType() {
window_->SetTextInputState(std::move(state));
}
-} // namespace mandoline
+} // namespace views
diff --git a/chromium/ui/views/mus/native_widget_mus.cc b/chromium/ui/views/mus/native_widget_mus.cc
index b8038eb0032..70dd986d2c6 100644
--- a/chromium/ui/views/mus/native_widget_mus.cc
+++ b/chromium/ui/views/mus/native_widget_mus.cc
@@ -8,7 +8,9 @@
#include "base/thread_task_runner_handle.h"
#include "components/mus/public/cpp/property_type_converters.h"
#include "components/mus/public/cpp/window.h"
+#include "components/mus/public/cpp/window_observer.h"
#include "components/mus/public/cpp/window_property.h"
+#include "components/mus/public/cpp/window_tree_connection.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/client/window_tree_client.h"
@@ -25,10 +27,12 @@
#include "ui/views/mus/window_manager_constants_converters.h"
#include "ui/views/mus/window_manager_frame_values.h"
#include "ui/views/mus/window_tree_host_mus.h"
+#include "ui/views/widget/native_widget_aura.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/custom_frame_view.h"
#include "ui/wm/core/base_focus_rules.h"
#include "ui/wm/core/capture_controller.h"
+#include "ui/wm/core/default_screen_position_client.h"
#include "ui/wm/core/focus_controller.h"
DECLARE_WINDOW_PROPERTY_TYPE(mus::Window*);
@@ -38,6 +42,8 @@ namespace {
DEFINE_WINDOW_PROPERTY_KEY(mus::Window*, kMusWindow, nullptr);
+MUS_DEFINE_WINDOW_PROPERTY_KEY(NativeWidgetMus*, kNativeWidgetMusKey, nullptr);
+
// TODO: figure out what this should be.
class FocusRulesImpl : public wm::BaseFocusRules {
public:
@@ -149,43 +155,120 @@ class ClientSideNonClientFrameView : public NonClientFrameView {
void SizeConstraintsChanged() override {
// NOTIMPLEMENTED();
}
+ gfx::Size GetPreferredSize() const override {
+ return widget_->non_client_view()
+ ->GetWindowBoundsForClientBounds(
+ gfx::Rect(widget_->client_view()->GetPreferredSize()))
+ .size();
+ }
+ gfx::Size GetMinimumSize() const override {
+ return widget_->non_client_view()
+ ->GetWindowBoundsForClientBounds(
+ gfx::Rect(widget_->client_view()->GetMinimumSize()))
+ .size();
+ }
+ gfx::Size GetMaximumSize() const override {
+ gfx::Size max_size = widget_->client_view()->GetMaximumSize();
+ gfx::Size converted_size =
+ widget_->non_client_view()
+ ->GetWindowBoundsForClientBounds(gfx::Rect(max_size))
+ .size();
+ return gfx::Size(max_size.width() == 0 ? 0 : converted_size.width(),
+ max_size.height() == 0 ? 0 : converted_size.height());
+ }
views::Widget* widget_;
DISALLOW_COPY_AND_ASSIGN(ClientSideNonClientFrameView);
};
-mus::mojom::ResizeBehavior ResizeBehaviorFromDelegate(
- WidgetDelegate* delegate) {
- int32_t behavior = mus::mojom::RESIZE_BEHAVIOR_NONE;
+int ResizeBehaviorFromDelegate(WidgetDelegate* delegate) {
+ if (!delegate)
+ return mus::mojom::kResizeBehaviorNone;
+
+ int32_t behavior = mus::mojom::kResizeBehaviorNone;
if (delegate->CanResize())
- behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_RESIZE;
+ behavior |= mus::mojom::kResizeBehaviorCanResize;
if (delegate->CanMaximize())
- behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_MAXIMIZE;
+ behavior |= mus::mojom::kResizeBehaviorCanMaximize;
if (delegate->CanMinimize())
- behavior |= mus::mojom::RESIZE_BEHAVIOR_CAN_MINIMIZE;
- return static_cast<mus::mojom::ResizeBehavior>(behavior);
+ behavior |= mus::mojom::kResizeBehaviorCanMinimize;
+ return behavior;
+}
+
+// Returns the 1x window app icon or an empty SkBitmap if no icon is available.
+// TODO(jamescook): Support other scale factors.
+SkBitmap AppIconFromDelegate(WidgetDelegate* delegate) {
+ if (!delegate)
+ return SkBitmap();
+ gfx::ImageSkia app_icon = delegate->GetWindowAppIcon();
+ if (app_icon.isNull())
+ return SkBitmap();
+ return app_icon.GetRepresentation(1.f).sk_bitmap();
}
} // namespace
+class NativeWidgetMus::MusWindowObserver : public mus::WindowObserver {
+ public:
+ explicit MusWindowObserver(NativeWidgetMus* native_widget_mus)
+ : native_widget_mus_(native_widget_mus) {
+ native_widget_mus_->window_->AddObserver(this);
+ }
+
+ ~MusWindowObserver() override {
+ native_widget_mus_->window_->RemoveObserver(this);
+ }
+
+ // mus::WindowObserver:
+ void OnWindowVisibilityChanging(mus::Window* window) override {
+ native_widget_mus_->OnMusWindowVisibilityChanging(window);
+ }
+ void OnWindowVisibilityChanged(mus::Window* window) override {
+ native_widget_mus_->OnMusWindowVisibilityChanged(window);
+ }
+
+ private:
+ NativeWidgetMus* native_widget_mus_;
+
+ DISALLOW_COPY_AND_ASSIGN(MusWindowObserver);
+};
+
////////////////////////////////////////////////////////////////////////////////
// NativeWidgetMus, public:
NativeWidgetMus::NativeWidgetMus(internal::NativeWidgetDelegate* delegate,
- mojo::Shell* shell,
+ mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type)
: window_(window),
- shell_(shell),
native_widget_delegate_(delegate),
surface_type_(surface_type),
show_state_before_fullscreen_(ui::PLATFORM_WINDOW_STATE_UNKNOWN),
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
content_(new aura::Window(this)),
close_widget_factory_(this) {
+ mus_window_observer_.reset(new MusWindowObserver(this));
+
// TODO(fsamuel): Figure out lifetime of |window_|.
aura::SetMusWindow(content_, window_);
+
+ window->SetLocalProperty(kNativeWidgetMusKey, this);
+ // WindowTreeHost creates the compositor using the ContextFactory from
+ // aura::Env. Install |context_factory_| there so that |context_factory_| is
+ // picked up.
+ ui::ContextFactory* default_context_factory =
+ aura::Env::GetInstance()->context_factory();
+ // For Chrome, we need the GpuProcessTransportFactory so that renderer and
+ // browser pixels are composited into a single backing
+ // SoftwareOutputDeviceMus.
+ if (!default_context_factory) {
+ context_factory_.reset(
+ new SurfaceContextFactory(connector, window_, surface_type_));
+ aura::Env::GetInstance()->set_context_factory(context_factory_.get());
+ }
+ window_tree_host_.reset(new WindowTreeHostMus(connector, this, window_));
+ aura::Env::GetInstance()->set_context_factory(default_context_factory);
}
NativeWidgetMus::~NativeWidgetMus() {
@@ -195,6 +278,24 @@ NativeWidgetMus::~NativeWidgetMus() {
CloseNow();
}
+// static
+void NativeWidgetMus::NotifyFrameChanged(
+ mus::WindowTreeConnection* connection) {
+ for (mus::Window* window : connection->GetRoots()) {
+ NativeWidgetMus* native_widget =
+ window->GetLocalProperty(kNativeWidgetMusKey);
+ if (native_widget && native_widget->GetWidget()->non_client_view()) {
+ native_widget->GetWidget()->non_client_view()->Layout();
+ native_widget->GetWidget()->non_client_view()->SchedulePaint();
+ native_widget->UpdateClientArea();
+ }
+ }
+}
+
+aura::Window* NativeWidgetMus::GetRootWindow() {
+ return window_tree_host_->window();
+}
+
void NativeWidgetMus::OnPlatformWindowClosed() {
native_widget_delegate_->OnNativeWidgetDestroying();
@@ -204,6 +305,8 @@ void NativeWidgetMus::OnPlatformWindowClosed() {
window_tree_host_->RemoveObserver(this);
window_tree_host_.reset();
+ mus_window_observer_.reset(nullptr);
+
window_ = nullptr;
content_ = nullptr;
@@ -222,6 +325,7 @@ void NativeWidgetMus::OnActivationChanged(bool active) {
native_widget_delegate_->OnNativeBlur();
GetWidget()->GetFocusManager()->StoreFocusedView(true);
}
+ native_widget_delegate_->OnNativeWidgetActivationChanged(active);
}
void NativeWidgetMus::UpdateClientArea() {
@@ -246,19 +350,23 @@ void NativeWidgetMus::ConfigurePropertiesForNewWindow(
std::map<std::string, std::vector<uint8_t>>* properties) {
if (!init_params.bounds.IsEmpty()) {
(*properties)[mus::mojom::WindowManager::kUserSetBounds_Property] =
- mojo::TypeConverter<const std::vector<uint8_t>, gfx::Rect>::Convert(
- init_params.bounds);
+ mojo::ConvertTo<std::vector<uint8_t>>(init_params.bounds);
}
if (!Widget::RequiresNonClientView(init_params.type))
return;
(*properties)[mus::mojom::WindowManager::kWindowType_Property] =
- mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert(
- mojo::ConvertTo<mus::mojom::WindowType>(init_params.type));
+ mojo::ConvertTo<std::vector<uint8_t>>(static_cast<int32_t>(
+ mojo::ConvertTo<mus::mojom::WindowType>(init_params.type)));
(*properties)[mus::mojom::WindowManager::kResizeBehavior_Property] =
- mojo::TypeConverter<const std::vector<uint8_t>, int32_t>::Convert(
+ mojo::ConvertTo<std::vector<uint8_t>>(
ResizeBehaviorFromDelegate(init_params.delegate));
+ SkBitmap app_icon = AppIconFromDelegate(init_params.delegate);
+ if (!app_icon.isNull()) {
+ (*properties)[mus::mojom::WindowManager::kWindowAppIcon_Property] =
+ mojo::ConvertTo<std::vector<uint8_t>>(app_icon);
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -269,30 +377,14 @@ NonClientFrameView* NativeWidgetMus::CreateNonClientFrameView() {
}
void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) {
+ NativeWidgetAura::RegisterNativeWidgetForWindow(this, content_);
+
ownership_ = params.ownership;
window_->SetCanFocus(params.activatable ==
Widget::InitParams::ACTIVATABLE_YES);
- // WindowTreeHost creates the compositor using the ContextFactory from
- // aura::Env. Install |context_factory_| there so that |context_factory_| is
- // picked up.
- ui::ContextFactory* default_context_factory =
- aura::Env::GetInstance()->context_factory();
- // For Chrome, we need the GpuProcessTransportFactory so that renderer and
- // browser pixels are composited into a single backing
- // SoftwareOutputDeviceMus.
- if (!default_context_factory) {
- if (!context_factory_) {
- context_factory_.reset(new SurfaceContextFactory(shell_, window_,
- surface_type_));
- }
- aura::Env::GetInstance()->set_context_factory(context_factory_.get());
- }
- window_tree_host_.reset(
- new WindowTreeHostMus(shell_, this, window_, surface_type_));
window_tree_host_->AddObserver(this);
window_tree_host_->InitHost();
- aura::Env::GetInstance()->set_context_factory(default_context_factory);
window_tree_host_->window()->SetProperty(kMusWindow, window_);
focus_client_.reset(new wm::FocusController(new FocusRulesImpl));
@@ -301,6 +393,10 @@ void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) {
focus_client_.get());
aura::client::SetActivationClient(window_tree_host_->window(),
focus_client_.get());
+ screen_position_client_.reset(new wm::DefaultScreenPositionClient());
+ aura::client::SetScreenPositionClient(window_tree_host_->window(),
+ screen_position_client_.get());
+
window_tree_client_.reset(
new NativeWidgetMusWindowTreeClient(window_tree_host_->window()));
window_tree_host_->window()->AddPreTargetHandler(focus_client_.get());
@@ -311,7 +407,8 @@ void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) {
content_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
content_->Init(ui::LAYER_TEXTURED);
- content_->Show();
+ if (window_->visible())
+ content_->Show();
content_->SetTransparent(true);
content_->SetFillsBoundsCompletely(false);
window_tree_host_->window()->AddChild(content_);
@@ -324,6 +421,10 @@ void NativeWidgetMus::InitNativeWidget(const Widget::InitParams& params) {
parent_mus->AddTransientWindow(window_);
}
+ // TODO(sky): deal with show state.
+ if (!params.bounds.size().IsEmpty())
+ SetBounds(params.bounds);
+
// TODO(beng): much else, see [Desktop]NativeWidgetAura.
native_widget_delegate_->OnNativeWidgetCreated(false);
@@ -356,7 +457,6 @@ Widget* NativeWidgetMus::GetWidget() {
}
const Widget* NativeWidgetMus::GetWidget() const {
- // NOTIMPLEMENTED();
return native_widget_delegate_->AsWidget();
}
@@ -373,11 +473,11 @@ Widget* NativeWidgetMus::GetTopLevelWidget() {
}
const ui::Compositor* NativeWidgetMus::GetCompositor() const {
- return window_tree_host_->window()->layer()->GetCompositor();
+ return window_tree_host_->compositor();
}
const ui::Layer* NativeWidgetMus::GetLayer() const {
- return window_tree_host_->window()->layer();
+ return content_ ? content_->layer() : nullptr;
}
void NativeWidgetMus::ReorderNativeViews() {
@@ -411,15 +511,17 @@ TooltipManager* NativeWidgetMus::GetTooltipManager() const {
}
void NativeWidgetMus::SetCapture() {
- content_->SetCapture();
+ if (content_)
+ content_->SetCapture();
}
void NativeWidgetMus::ReleaseCapture() {
- content_->ReleaseCapture();
+ if (content_)
+ content_->ReleaseCapture();
}
bool NativeWidgetMus::HasCapture() const {
- return content_->HasCapture();
+ return content_ && content_->HasCapture();
}
ui::InputMethod* NativeWidgetMus::GetInputMethod() {
@@ -439,18 +541,39 @@ void NativeWidgetMus::GetWindowPlacement(
}
bool NativeWidgetMus::SetWindowTitle(const base::string16& title) {
- window_->SetSharedProperty<base::string16>(
- mus::mojom::WindowManager::kWindowTitle_Property, title);
+ if (!window_)
+ return false;
+ const char* kWindowTitle_Property =
+ mus::mojom::WindowManager::kWindowTitle_Property;
+ const base::string16 current_title =
+ window_->HasSharedProperty(kWindowTitle_Property)
+ ? window_->GetSharedProperty<base::string16>(kWindowTitle_Property)
+ : base::string16();
+ if (current_title == title)
+ return false;
+ window_->SetSharedProperty<base::string16>(kWindowTitle_Property, title);
return true;
}
void NativeWidgetMus::SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) {
- // NOTIMPLEMENTED();
+ const char* const kWindowAppIcon_Property =
+ mus::mojom::WindowManager::kWindowAppIcon_Property;
+
+ if (!app_icon.isNull()) {
+ // Send the app icon 1x bitmap to the window manager.
+ // TODO(jamescook): Support other scale factors.
+ window_->SetSharedProperty<SkBitmap>(
+ kWindowAppIcon_Property, app_icon.GetRepresentation(1.f).sk_bitmap());
+ } else if (window_->HasSharedProperty(kWindowAppIcon_Property)) {
+ // Remove the existing icon.
+ window_->ClearSharedProperty(kWindowAppIcon_Property);
+ }
}
void NativeWidgetMus::InitModalType(ui::ModalType modal_type) {
- // NOTIMPLEMENTED();
+ if (modal_type != ui::MODAL_TYPE_NONE)
+ window_->SetModal();
}
gfx::Rect NativeWidgetMus::GetWindowBoundsInScreen() const {
@@ -464,15 +587,36 @@ gfx::Rect NativeWidgetMus::GetClientAreaBoundsInScreen() const {
}
gfx::Rect NativeWidgetMus::GetRestoredBounds() const {
- // NOTIMPLEMENTED();
- return gfx::Rect();
+ // Restored bounds should only be relevant if the window is minimized,
+ // maximized, fullscreen or docked. However, in some places the code expects
+ // GetRestoredBounds() to return the current window bounds if the window is
+ // not in either state.
+ if (IsMinimized() || IsMaximized() || IsFullscreen()) {
+ const char* kRestoreBounds_Property =
+ mus::mojom::WindowManager::kRestoreBounds_Property;
+ if (window_->HasSharedProperty(kRestoreBounds_Property))
+ return window_->GetSharedProperty<gfx::Rect>(kRestoreBounds_Property);
+ }
+ return GetWindowBoundsInScreen();
}
void NativeWidgetMus::SetBounds(const gfx::Rect& bounds) {
- window_tree_host_->SetBounds(bounds);
+ if (!window_tree_host_)
+ return;
+
+ gfx::Size size(bounds.size());
+ const gfx::Size min_size = GetMinimumSize();
+ const gfx::Size max_size = GetMaximumSize();
+ if (!max_size.IsEmpty())
+ size.SetToMin(max_size);
+ size.SetToMax(min_size);
+ window_tree_host_->SetBounds(gfx::Rect(bounds.origin(), size));
}
void NativeWidgetMus::SetSize(const gfx::Size& size) {
+ if (!window_tree_host_)
+ return;
+
gfx::Rect bounds = window_tree_host_->GetBounds();
SetBounds(gfx::Rect(bounds.origin(), size));
}
@@ -503,7 +647,9 @@ void NativeWidgetMus::Close() {
}
void NativeWidgetMus::CloseNow() {
- window_->Destroy();
+ // Depending upon ownership |window_| may have been destroyed.
+ if (window_)
+ window_->Destroy();
}
void NativeWidgetMus::Show() {
@@ -511,6 +657,9 @@ void NativeWidgetMus::Show() {
}
void NativeWidgetMus::Hide() {
+ if (!window_tree_host_)
+ return;
+
window_tree_host_->Hide();
GetNativeWindow()->Hide();
}
@@ -521,6 +670,9 @@ void NativeWidgetMus::ShowMaximizedWithBounds(
}
void NativeWidgetMus::ShowWithWindowState(ui::WindowShowState state) {
+ if (!window_tree_host_)
+ return;
+
window_tree_host_->Show();
GetNativeWindow()->Show();
if (state != ui::SHOW_STATE_INACTIVE)
@@ -530,20 +682,23 @@ void NativeWidgetMus::ShowWithWindowState(ui::WindowShowState state) {
bool NativeWidgetMus::IsVisible() const {
// TODO(beng): this should probably be wired thru PlatformWindow.
- return window_->visible();
+ return window_ && window_->visible();
}
void NativeWidgetMus::Activate() {
- window_tree_host_->platform_window()->Activate();
+ if (window_tree_host_)
+ window_tree_host_->platform_window()->Activate();
}
void NativeWidgetMus::Deactivate() {
- // NOTIMPLEMENTED();
+ if (IsActive())
+ window_->connection()->ClearFocus();
}
bool NativeWidgetMus::IsActive() const {
- // NOTIMPLEMENTED();
- return true;
+ mus::Window* focused =
+ window_ ? window_->connection()->GetFocusedWindow() : nullptr;
+ return focused && window_->Contains(focused);
}
void NativeWidgetMus::SetAlwaysOnTop(bool always_on_top) {
@@ -560,27 +715,32 @@ void NativeWidgetMus::SetVisibleOnAllWorkspaces(bool always_visible) {
}
void NativeWidgetMus::Maximize() {
- window_tree_host_->platform_window()->Maximize();
+ if (window_tree_host_)
+ window_tree_host_->platform_window()->Maximize();
}
void NativeWidgetMus::Minimize() {
- window_tree_host_->platform_window()->Minimize();
+ if (window_tree_host_)
+ window_tree_host_->platform_window()->Minimize();
}
bool NativeWidgetMus::IsMaximized() const {
- return window_tree_host_->show_state() == ui::PLATFORM_WINDOW_STATE_MAXIMIZED;
+ return window_tree_host_ &&
+ window_tree_host_->show_state() == ui::PLATFORM_WINDOW_STATE_MAXIMIZED;
}
bool NativeWidgetMus::IsMinimized() const {
- return window_tree_host_->show_state() == ui::PLATFORM_WINDOW_STATE_MINIMIZED;
+ return window_tree_host_ &&
+ window_tree_host_->show_state() == ui::PLATFORM_WINDOW_STATE_MINIMIZED;
}
void NativeWidgetMus::Restore() {
- window_tree_host_->platform_window()->Restore();
+ if (window_tree_host_)
+ window_tree_host_->platform_window()->Restore();
}
void NativeWidgetMus::SetFullscreen(bool fullscreen) {
- if (IsFullscreen() == fullscreen)
+ if (!window_tree_host_ || IsFullscreen() == fullscreen)
return;
if (fullscreen) {
show_state_before_fullscreen_ = window_tree_host_->show_state();
@@ -604,16 +764,14 @@ void NativeWidgetMus::SetFullscreen(bool fullscreen) {
}
bool NativeWidgetMus::IsFullscreen() const {
- return window_tree_host_->show_state() ==
- ui::PLATFORM_WINDOW_STATE_FULLSCREEN;
+ return window_tree_host_ &&
+ window_tree_host_->show_state() ==
+ ui::PLATFORM_WINDOW_STATE_FULLSCREEN;
}
void NativeWidgetMus::SetOpacity(unsigned char opacity) {
- // NOTIMPLEMENTED();
-}
-
-void NativeWidgetMus::SetUseDragFrame(bool use_drag_frame) {
- // NOTIMPLEMENTED();
+ if (window_)
+ window_->SetOpacity(opacity / 255.0);
}
void NativeWidgetMus::FlashFrame(bool flash_frame) {
@@ -635,6 +793,8 @@ void NativeWidgetMus::SchedulePaintInRect(const gfx::Rect& rect) {
}
void NativeWidgetMus::SetCursor(gfx::NativeCursor cursor) {
+ if (!window_tree_host_)
+ return;
// TODO(erg): In aura, our incoming cursor is really two
// parts. cursor.native_type() is an integer for standard cursors and is all
// we support right now. If native_type() == kCursorCustom, than we should
@@ -651,7 +811,12 @@ bool NativeWidgetMus::IsMouseEventsEnabled() const {
}
void NativeWidgetMus::ClearNativeFocus() {
- // NOTIMPLEMENTED();
+ if (!IsActive())
+ return;
+ mus::Window* focused =
+ window_ ? window_->connection()->GetFocusedWindow() : nullptr;
+ if (focused && window_->Contains(focused) && focused != window_)
+ window_->SetFocus();
}
gfx::Rect NativeWidgetMus::GetWorkAreaBoundsInScreen() const {
@@ -699,6 +864,9 @@ bool NativeWidgetMus::IsTranslucentWindowOpacitySupported() const {
}
void NativeWidgetMus::OnSizeConstraintsChanged() {
+ if (!window_)
+ return;
+
window_->SetSharedProperty<int32_t>(
mus::mojom::WindowManager::kResizeBehavior_Property,
ResizeBehaviorFromDelegate(GetWidget()->widget_delegate()));
@@ -813,7 +981,7 @@ void NativeWidgetMus::OnScrollEvent(ui::ScrollEvent* event) {
return;
// Convert unprocessed scroll events into wheel events.
- ui::MouseWheelEvent mwe(*static_cast<ui::ScrollEvent*>(event));
+ ui::MouseWheelEvent mwe(*event->AsScrollEvent());
native_widget_delegate_->OnMouseEvent(&mwe);
if (mwe.handled())
event->SetHandled();
@@ -830,4 +998,19 @@ void NativeWidgetMus::OnHostCloseRequested(const aura::WindowTreeHost* host) {
GetWidget()->Close();
}
+void NativeWidgetMus::OnMusWindowVisibilityChanging(mus::Window* window) {
+ native_widget_delegate_->OnNativeWidgetVisibilityChanging(!window->visible());
+}
+
+void NativeWidgetMus::OnMusWindowVisibilityChanged(mus::Window* window) {
+ if (window->visible()) {
+ window_tree_host_->Show();
+ GetNativeWindow()->Show();
+ } else {
+ window_tree_host_->Hide();
+ GetNativeWindow()->Hide();
+ }
+ native_widget_delegate_->OnNativeWidgetVisibilityChanged(window->visible());
+}
+
} // namespace views
diff --git a/chromium/ui/views/mus/native_widget_mus.h b/chromium/ui/views/mus/native_widget_mus.h
index a940baf9158..3419c064e05 100644
--- a/chromium/ui/views/mus/native_widget_mus.h
+++ b/chromium/ui/views/mus/native_widget_mus.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "components/mus/public/interfaces/window_manager.mojom.h"
+#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/platform_window/platform_window_delegate.h"
@@ -23,21 +23,19 @@
namespace aura {
namespace client {
class DefaultCaptureClient;
+class ScreenPositionClient;
class WindowTreeClient;
}
class Window;
}
namespace mojo {
-class Shell;
+class Connector;
}
namespace mus {
class Window;
-
-namespace mojom {
-class WindowManager;
-}
+class WindowTreeConnection;
}
namespace wm {
@@ -47,7 +45,6 @@ class FocusController;
namespace views {
class SurfaceContextFactory;
class WidgetDelegate;
-struct WindowManagerClientAreaInsets;
class WindowTreeHostMus;
// An implementation of NativeWidget that binds to a mus::Window. Because Aura
@@ -61,7 +58,7 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
public aura::WindowTreeHostObserver {
public:
NativeWidgetMus(internal::NativeWidgetDelegate* delegate,
- mojo::Shell* shell,
+ mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type);
~NativeWidgetMus() override;
@@ -72,8 +69,13 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
const Widget::InitParams& init_params,
std::map<std::string, std::vector<uint8_t>>* properties);
+ // Notifies all widgets the frame constants changed in some way.
+ static void NotifyFrameChanged(mus::WindowTreeConnection* connection);
+
mus::Window* window() { return window_; }
+ aura::Window* GetRootWindow();
+
void OnPlatformWindowClosed();
void OnActivationChanged(bool active);
@@ -141,7 +143,6 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
void SetFullscreen(bool fullscreen) override;
bool IsFullscreen() const override;
void SetOpacity(unsigned char opacity) override;
- void SetUseDragFrame(bool use_drag_frame) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
const ui::OSExchangeData& data,
@@ -198,9 +199,12 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
void OnHostCloseRequested(const aura::WindowTreeHost* host) override;
private:
- mus::Window* window_;
+ class MusWindowObserver;
+
+ void OnMusWindowVisibilityChanging(mus::Window* window);
+ void OnMusWindowVisibilityChanged(mus::Window* window);
- mojo::Shell* shell_;
+ mus::Window* window_;
internal::NativeWidgetDelegate* native_widget_delegate_;
@@ -210,6 +214,10 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
// See class documentation for Widget in widget.h for a note about ownership.
Widget::InitParams::Ownership ownership_;
+ // Functions with the same name require the mus::WindowObserver to be in
+ // a separate class.
+ scoped_ptr<MusWindowObserver> mus_window_observer_;
+
// Aura configuration.
scoped_ptr<SurfaceContextFactory> context_factory_;
scoped_ptr<WindowTreeHostMus> window_tree_host_;
@@ -217,6 +225,7 @@ class VIEWS_MUS_EXPORT NativeWidgetMus : public internal::NativeWidgetPrivate,
scoped_ptr<wm::FocusController> focus_client_;
scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
+ scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_;
base::WeakPtrFactory<NativeWidgetMus> close_widget_factory_;
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMus);
diff --git a/chromium/ui/views/mus/native_widget_mus_unittest.cc b/chromium/ui/views/mus/native_widget_mus_unittest.cc
new file mode 100644
index 00000000000..78155814861
--- /dev/null
+++ b/chromium/ui/views/mus/native_widget_mus_unittest.cc
@@ -0,0 +1,197 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/mus/native_widget_mus.h"
+
+#include "base/macros.h"
+#include "components/mus/public/cpp/property_type_converters.h"
+#include "components/mus/public/cpp/window.h"
+#include "components/mus/public/cpp/window_property.h"
+#include "components/mus/public/interfaces/window_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/aura/window.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/test/focus_manager_test.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/widget/widget_observer.h"
+
+namespace views {
+namespace {
+
+// Returns a small colored bitmap.
+SkBitmap MakeBitmap(SkColor color) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(8, 8);
+ bitmap.eraseColor(color);
+ return bitmap;
+}
+
+// An observer that tracks widget activation changes.
+class WidgetActivationObserver : public WidgetObserver {
+ public:
+ explicit WidgetActivationObserver(Widget* widget) : widget_(widget) {
+ widget_->AddObserver(this);
+ }
+
+ ~WidgetActivationObserver() override {
+ widget_->RemoveObserver(this);
+ }
+
+ const std::vector<bool>& changes() const { return changes_; }
+
+ // WidgetObserver:
+ void OnWidgetActivationChanged(Widget* widget, bool active) override {
+ ASSERT_EQ(widget_, widget);
+ changes_.push_back(active);
+ }
+
+ private:
+ Widget* widget_;
+ std::vector<bool> changes_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetActivationObserver);
+};
+
+// A WidgetDelegate that supplies an app icon.
+class TestWidgetDelegate : public WidgetDelegateView {
+ public:
+ explicit TestWidgetDelegate(const SkBitmap& icon)
+ : app_icon_(gfx::ImageSkia::CreateFrom1xBitmap(icon)) {}
+
+ ~TestWidgetDelegate() override {}
+
+ void SetIcon(const SkBitmap& icon) {
+ app_icon_ = gfx::ImageSkia::CreateFrom1xBitmap(icon);
+ }
+
+ // views::WidgetDelegate:
+ gfx::ImageSkia GetWindowAppIcon() override { return app_icon_; }
+
+ private:
+ gfx::ImageSkia app_icon_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
+};
+
+class NativeWidgetMusTest : public ViewsTestBase {
+ public:
+ NativeWidgetMusTest() {}
+ ~NativeWidgetMusTest() override {}
+
+ // Creates a test widget. Takes ownership of |delegate|.
+ scoped_ptr<Widget> CreateWidget(TestWidgetDelegate* delegate) {
+ scoped_ptr<Widget> widget(new Widget());
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.delegate = delegate;
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(10, 20, 100, 200);
+ widget->Init(params);
+ return widget;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NativeWidgetMusTest);
+};
+
+// Tests communication of activation and focus between Widget and
+// NativeWidgetMus.
+TEST_F(NativeWidgetMusTest, OnActivationChanged) {
+ scoped_ptr<Widget> widget(CreateWidget(nullptr));
+ widget->Show();
+
+ // Track activation, focus and blur events.
+ WidgetActivationObserver activation_observer(widget.get());
+ TestWidgetFocusChangeListener focus_listener;
+ WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
+
+ // Deactivate the Widget, which deactivates the NativeWidgetMus.
+ widget->Deactivate();
+
+ // The widget is blurred and deactivated.
+ ASSERT_EQ(1u, focus_listener.focus_changes().size());
+ EXPECT_EQ(nullptr, focus_listener.focus_changes()[0]);
+ ASSERT_EQ(1u, activation_observer.changes().size());
+ EXPECT_EQ(false, activation_observer.changes()[0]);
+
+ // Re-activate the Widget, which actives the NativeWidgetMus.
+ widget->Activate();
+
+ // The widget is focused and activated.
+ ASSERT_EQ(2u, focus_listener.focus_changes().size());
+ EXPECT_EQ(widget->GetNativeView(), focus_listener.focus_changes()[1]);
+ ASSERT_EQ(2u, activation_observer.changes().size());
+ EXPECT_TRUE(activation_observer.changes()[1]);
+
+ WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
+}
+
+// Tests that a window with an icon sets the mus::Window icon property.
+TEST_F(NativeWidgetMusTest, AppIcon) {
+ // Create a Widget with a bitmap as the icon.
+ SkBitmap source_bitmap = MakeBitmap(SK_ColorRED);
+ scoped_ptr<Widget> widget(
+ CreateWidget(new TestWidgetDelegate(source_bitmap)));
+
+ // The mus::Window has the icon property.
+ mus::Window* window =
+ static_cast<NativeWidgetMus*>(widget->native_widget_private())->window();
+ EXPECT_TRUE(window->HasSharedProperty(
+ mus::mojom::WindowManager::kWindowAppIcon_Property));
+
+ // The icon is the expected icon.
+ SkBitmap icon = window->GetSharedProperty<SkBitmap>(
+ mus::mojom::WindowManager::kWindowAppIcon_Property);
+ EXPECT_TRUE(gfx::BitmapsAreEqual(source_bitmap, icon));
+}
+
+// Tests that a window without an icon does not set the mus::Window icon
+// property.
+TEST_F(NativeWidgetMusTest, NoAppIcon) {
+ // Create a Widget without a special icon.
+ scoped_ptr<Widget> widget(CreateWidget(nullptr));
+
+ // The mus::Window does not have an icon property.
+ mus::Window* window =
+ static_cast<NativeWidgetMus*>(widget->native_widget_private())->window();
+ EXPECT_FALSE(window->HasSharedProperty(
+ mus::mojom::WindowManager::kWindowAppIcon_Property));
+}
+
+// Tests that changing the icon on a Widget updates the mus::Window icon
+// property.
+TEST_F(NativeWidgetMusTest, ChangeAppIcon) {
+ // Create a Widget with an icon.
+ SkBitmap bitmap1 = MakeBitmap(SK_ColorRED);
+ TestWidgetDelegate* delegate = new TestWidgetDelegate(bitmap1);
+ scoped_ptr<Widget> widget(CreateWidget(delegate));
+
+ // Update the icon to a new image.
+ SkBitmap bitmap2 = MakeBitmap(SK_ColorGREEN);
+ delegate->SetIcon(bitmap2);
+ widget->UpdateWindowIcon();
+
+ // The window has the updated icon.
+ mus::Window* window =
+ static_cast<NativeWidgetMus*>(widget->native_widget_private())->window();
+ SkBitmap icon = window->GetSharedProperty<SkBitmap>(
+ mus::mojom::WindowManager::kWindowAppIcon_Property);
+ EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap2, icon));
+}
+
+TEST_F(NativeWidgetMusTest, ValidLayerTree) {
+ scoped_ptr<Widget> widget(CreateWidget(nullptr));
+ View* content = new View;
+ content->SetPaintToLayer(true);
+ widget->GetContentsView()->AddChildView(content);
+ EXPECT_TRUE(widget->GetNativeWindow()->layer()->Contains(content->layer()));
+}
+
+} // namespace
+} // namespace views
diff --git a/chromium/ui/views/mus/platform_test_helper_mus.cc b/chromium/ui/views/mus/platform_test_helper_mus.cc
index 7fc3b2286ab..80e6a74a1ec 100644
--- a/chromium/ui/views/mus/platform_test_helper_mus.cc
+++ b/chromium/ui/views/mus/platform_test_helper_mus.cc
@@ -4,46 +4,97 @@
#include "ui/views/test/platform_test_helper.h"
-#include "base/path_service.h"
-#include "mojo/shell/public/cpp/application_impl.h"
-#include "mojo/shell/public/cpp/application_test_base.h"
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "mojo/shell/background/background_shell.h"
+#include "mojo/shell/background/tests/test_catalog_store.h"
+#include "mojo/shell/public/cpp/connector.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/cpp/shell_connection.h"
#include "ui/aura/env.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/ui_base_paths.h"
-#include "ui/gl/test/gl_surface_test_support.h"
#include "ui/views/mus/window_manager_connection.h"
+#include "ui/views/views_delegate.h"
+
+using mojo::shell::BackgroundShell;
namespace views {
namespace {
+const char kTestName[] = "mojo:test-app";
+
+class DefaultShellClient : public mojo::ShellClient {
+ public:
+ DefaultShellClient() {}
+ ~DefaultShellClient() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DefaultShellClient);
+};
+
+scoped_ptr<mojo::shell::TestCatalogStore> BuildTestCatalogStore() {
+ scoped_ptr<base::ListValue> apps(new base::ListValue);
+ apps->Append(
+ mojo::shell::BuildPermissiveSerializedAppInfo(kTestName, "test"));
+ return make_scoped_ptr(new mojo::shell::TestCatalogStore(std::move(apps)));
+}
+
class PlatformTestHelperMus : public PlatformTestHelper {
public:
PlatformTestHelperMus() {
- gfx::GLSurfaceTestSupport::InitializeOneOff();
+ background_shell_.reset(new BackgroundShell);
+ scoped_ptr<BackgroundShell::InitParams> init_params(
+ new BackgroundShell::InitParams);
+ init_params->catalog_store = BuildTestCatalogStore();
+ background_shell_->Init(std::move(init_params));
+ shell_client_.reset(new DefaultShellClient);
+ shell_connection_.reset(new mojo::ShellConnection(
+ shell_client_.get(),
+ background_shell_->CreateShellClientRequest(kTestName)));
- // TODO(sky): We really shouldn't need to configure ResourceBundle.
- ui::RegisterPathProvider();
- base::FilePath ui_test_pak_path;
- CHECK(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
- ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
- aura::Env::CreateInstance(true);
+ // TODO(rockot): Remove this RunLoop. http://crbug.com/594852.
+ base::RunLoop wait_loop;
+ shell_connection_->set_initialize_handler(wait_loop.QuitClosure());
+ wait_loop.Run();
- mojo_test_helper_.reset(new mojo::test::TestHelper(nullptr));
// ui/views/mus requires a WindowManager running, for now use the desktop
// one.
- mojo_test_helper_->application_impl()->ConnectToApplication(
- "mojo:desktop_wm");
- WindowManagerConnection::Create(mojo_test_helper_->application_impl());
+ mojo::Connector* connector = shell_connection_->connector();
+ connector->Connect("mojo:desktop_wm");
+ WindowManagerConnection::Create(connector);
+
+ // On X we need to reset the ContextFactory before every NativeWidgetMus
+ // is created.
+ // TODO(sad): this is a hack, figure out a better solution.
+ ViewsDelegate::GetInstance()->set_native_widget_factory(base::Bind(
+ &PlatformTestHelperMus::CreateNativeWidgetMus, base::Unretained(this),
+ std::map<std::string, std::vector<uint8_t>>()));
}
~PlatformTestHelperMus() override {
- mojo_test_helper_.reset(nullptr);
- aura::Env::DeleteInstance();
- ui::ResourceBundle::CleanupSharedInstance();
+ WindowManagerConnection::Reset();
+ // |app_| has a reference to us, destroy it while we are still valid.
+ shell_connection_.reset();
}
+ bool IsMus() const override { return true; }
+
private:
- scoped_ptr<mojo::test::TestHelper> mojo_test_helper_;
+ NativeWidget* CreateNativeWidgetMus(
+ const std::map<std::string, std::vector<uint8_t>>& props,
+ const Widget::InitParams& init_params,
+ internal::NativeWidgetDelegate* delegate) {
+ ui::ContextFactory* factory = aura::Env::GetInstance()->context_factory();
+ aura::Env::GetInstance()->set_context_factory(nullptr);
+ NativeWidget* result =
+ WindowManagerConnection::Get()->CreateNativeWidgetMus(
+ props, init_params, delegate);
+ aura::Env::GetInstance()->set_context_factory(factory);
+ return result;
+ }
+
+ scoped_ptr<BackgroundShell> background_shell_;
+ scoped_ptr<mojo::ShellConnection> shell_connection_;
+ scoped_ptr<DefaultShellClient> shell_client_;
DISALLOW_COPY_AND_ASSIGN(PlatformTestHelperMus);
};
diff --git a/chromium/ui/views/mus/platform_window_mus.cc b/chromium/ui/views/mus/platform_window_mus.cc
index 2f29180c893..d42a9a77908 100644
--- a/chromium/ui/views/mus/platform_window_mus.cc
+++ b/chromium/ui/views/mus/platform_window_mus.cc
@@ -5,10 +5,12 @@
#include "ui/views/mus/platform_window_mus.h"
#include "build/build_config.h"
+#include "components/bitmap_uploader/bitmap_uploader.h"
#include "components/mus/public/cpp/property_type_converters.h"
#include "components/mus/public/cpp/window_property.h"
#include "components/mus/public/interfaces/window_manager.mojom.h"
#include "mojo/converters/input_events/input_events_type_converters.h"
+#include "ui/base/view_prop.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/views/mus/window_manager_connection.h"
@@ -20,12 +22,12 @@ static uint32_t accelerated_widget_count = 1;
} // namespace
PlatformWindowMus::PlatformWindowMus(ui::PlatformWindowDelegate* delegate,
+ mojo::Connector* connector,
mus::Window* mus_window)
: delegate_(delegate),
mus_window_(mus_window),
- show_state_(mus::mojom::SHOW_STATE_RESTORED),
- last_cursor_(mus::mojom::CURSOR_NULL),
- has_capture_(false),
+ show_state_(mus::mojom::ShowState::RESTORED),
+ last_cursor_(mus::mojom::Cursor::CURSOR_NULL),
mus_window_destroyed_(false) {
DCHECK(delegate_);
DCHECK(mus_window_);
@@ -36,14 +38,20 @@ PlatformWindowMus::PlatformWindowMus(ui::PlatformWindowDelegate* delegate,
// window and fit in the smallest sizeof(AcceleratedWidget) uint32_t
// has this property.
#if defined(OS_WIN) || defined(OS_ANDROID)
- delegate_->OnAcceleratedWidgetAvailable(
- reinterpret_cast<gfx::AcceleratedWidget>(accelerated_widget_count++),
- mus_window_->viewport_metrics().device_pixel_ratio);
+ gfx::AcceleratedWidget accelerated_widget =
+ reinterpret_cast<gfx::AcceleratedWidget>(accelerated_widget_count++);
#else
- delegate_->OnAcceleratedWidgetAvailable(
- static_cast<gfx::AcceleratedWidget>(accelerated_widget_count++),
- mus_window_->viewport_metrics().device_pixel_ratio);
+ gfx::AcceleratedWidget accelerated_widget =
+ static_cast<gfx::AcceleratedWidget>(accelerated_widget_count++);
#endif
+ delegate_->OnAcceleratedWidgetAvailable(
+ accelerated_widget, mus_window_->viewport_metrics().device_pixel_ratio);
+
+ bitmap_uploader_.reset(new bitmap_uploader::BitmapUploader(mus_window_));
+ bitmap_uploader_->Init(connector);
+ prop_.reset(new ui::ViewProp(
+ accelerated_widget, bitmap_uploader::kBitmapUploaderForAcceleratedWidget,
+ bitmap_uploader_.get()));
}
PlatformWindowMus::~PlatformWindowMus() {
@@ -95,15 +103,11 @@ void PlatformWindowMus::SetTitle(const base::string16& title) {
}
void PlatformWindowMus::SetCapture() {
- // TODO(sky): this is wrong, need real capture api.
- has_capture_ = true;
- NOTIMPLEMENTED();
+ mus_window_->SetCapture();
}
void PlatformWindowMus::ReleaseCapture() {
- // TODO(sky): this is wrong, need real capture api.
- has_capture_ = false;
- NOTIMPLEMENTED();
+ mus_window_->ReleaseCapture();
}
void PlatformWindowMus::ToggleFullscreen() {
@@ -111,15 +115,15 @@ void PlatformWindowMus::ToggleFullscreen() {
}
void PlatformWindowMus::Maximize() {
- SetShowState(mus::mojom::SHOW_STATE_MAXIMIZED);
+ SetShowState(mus::mojom::ShowState::MAXIMIZED);
}
void PlatformWindowMus::Minimize() {
- SetShowState(mus::mojom::SHOW_STATE_MINIMIZED);
+ SetShowState(mus::mojom::ShowState::MINIMIZED);
}
void PlatformWindowMus::Restore() {
- SetShowState(mus::mojom::SHOW_STATE_RESTORED);
+ SetShowState(mus::mojom::ShowState::RESTORED);
}
void PlatformWindowMus::SetCursor(ui::PlatformCursor cursor) {
@@ -140,7 +144,8 @@ ui::PlatformImeController* PlatformWindowMus::GetPlatformImeController() {
void PlatformWindowMus::SetShowState(mus::mojom::ShowState show_state) {
mus_window_->SetSharedProperty<int32_t>(
- mus::mojom::WindowManager::kShowState_Property, show_state);
+ mus::mojom::WindowManager::kShowState_Property,
+ static_cast<int32_t>(show_state));
}
void PlatformWindowMus::OnWindowDestroyed(mus::Window* window) {
@@ -193,17 +198,17 @@ void PlatformWindowMus::OnWindowSharedPropertyChanged(
show_state_ = show_state;
ui::PlatformWindowState state = ui::PLATFORM_WINDOW_STATE_UNKNOWN;
switch (show_state_) {
- case mus::mojom::SHOW_STATE_MINIMIZED:
+ case mus::mojom::ShowState::MINIMIZED:
state = ui::PLATFORM_WINDOW_STATE_MINIMIZED;
break;
- case mus::mojom::SHOW_STATE_MAXIMIZED:
+ case mus::mojom::ShowState::MAXIMIZED:
state = ui::PLATFORM_WINDOW_STATE_MAXIMIZED;
break;
- case mus::mojom::SHOW_STATE_RESTORED:
+ case mus::mojom::ShowState::RESTORED:
state = ui::PLATFORM_WINDOW_STATE_NORMAL;
break;
- case mus::mojom::SHOW_STATE_IMMERSIVE:
- case mus::mojom::SHOW_STATE_PRESENTATION:
+ case mus::mojom::ShowState::IMMERSIVE:
+ case mus::mojom::ShowState::PRESENTATION:
// This may not be sufficient.
state = ui::PLATFORM_WINDOW_STATE_FULLSCREEN;
break;
@@ -217,15 +222,16 @@ void PlatformWindowMus::OnRequestClose(mus::Window* window) {
void PlatformWindowMus::OnWindowInputEvent(
mus::Window* view,
- mus::mojom::EventPtr event,
- scoped_ptr<base::Closure>* ack_callback) {
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback) {
// It's possible dispatching the event will spin a nested message loop. Ack
// the callback now, otherwise we appear unresponsive for the life of the
// nested message loop.
- (*ack_callback)->Run();
+ (*ack_callback)->Run(true);
ack_callback->reset();
- scoped_ptr<ui::Event> ui_event(event.To<scoped_ptr<ui::Event>>());
- delegate_->DispatchEvent(ui_event.get());
+ // TODO(moshayedi): Avoid cloning after updating PlatformWindowDelegate to
+ // accept constant pointers.
+ delegate_->DispatchEvent(ui::Event::Clone(event).get());
}
} // namespace views
diff --git a/chromium/ui/views/mus/platform_window_mus.h b/chromium/ui/views/mus/platform_window_mus.h
index fadd64ff5d5..ba206713f08 100644
--- a/chromium/ui/views/mus/platform_window_mus.h
+++ b/chromium/ui/views/mus/platform_window_mus.h
@@ -16,6 +16,19 @@
#include "ui/platform_window/platform_window.h"
#include "ui/views/mus/mus_export.h"
+namespace bitmap_uploader {
+class BitmapUploader;
+}
+
+namespace mojo {
+class Connector;
+}
+
+namespace ui {
+class Event;
+class ViewProp;
+}
+
namespace views {
class VIEWS_MUS_EXPORT PlatformWindowMus
@@ -24,6 +37,7 @@ class VIEWS_MUS_EXPORT PlatformWindowMus
public NON_EXPORTED_BASE(mus::InputEventHandler) {
public:
PlatformWindowMus(ui::PlatformWindowDelegate* delegate,
+ mojo::Connector* connector,
mus::Window* mus_window);
~PlatformWindowMus() override;
@@ -69,19 +83,21 @@ class VIEWS_MUS_EXPORT PlatformWindowMus
void OnRequestClose(mus::Window* window) override;
// mus::InputEventHandler:
- void OnWindowInputEvent(mus::Window* view,
- mus::mojom::EventPtr event,
- scoped_ptr<base::Closure>* ack_callback) override;
+ void OnWindowInputEvent(
+ mus::Window* view,
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback) override;
ui::PlatformWindowDelegate* delegate_;
mus::Window* mus_window_;
mus::mojom::ShowState show_state_;
mus::mojom::Cursor last_cursor_;
- bool has_capture_;
// True if OnWindowDestroyed() has been received.
bool mus_window_destroyed_;
+ scoped_ptr<bitmap_uploader::BitmapUploader> bitmap_uploader_;
+ scoped_ptr<ui::ViewProp> prop_;
#ifndef NDEBUG
scoped_ptr<base::WeakPtrFactory<PlatformWindowMus>> weak_factory_;
#endif
diff --git a/chromium/ui/views/mus/run_all_unittests_mus.cc b/chromium/ui/views/mus/run_all_unittests_mus.cc
new file mode 100644
index 00000000000..4de8cdb1839
--- /dev/null
+++ b/chromium/ui/views/mus/run_all_unittests_mus.cc
@@ -0,0 +1,9 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/run_all_unittests.h"
+
+int MasterProcessMain(int argc, char** argv) {
+ return views::RunAllUnittests(argc, argv);
+}
diff --git a/chromium/ui/views/mus/screen_mus.cc b/chromium/ui/views/mus/screen_mus.cc
new file mode 100644
index 00000000000..855f475674e
--- /dev/null
+++ b/chromium/ui/views/mus/screen_mus.cc
@@ -0,0 +1,237 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/mus/screen_mus.h"
+
+#include "mojo/converters/geometry/geometry_type_converters.h"
+#include "mojo/shell/public/cpp/connection.h"
+#include "mojo/shell/public/cpp/connector.h"
+#include "ui/gfx/display_finder.h"
+#include "ui/gfx/display_observer.h"
+#include "ui/views/mus/screen_mus_delegate.h"
+#include "ui/views/mus/window_manager_frame_values.h"
+
+namespace mojo {
+
+template <>
+struct TypeConverter<gfx::Display, mus::mojom::DisplayPtr> {
+ static gfx::Display Convert(const mus::mojom::DisplayPtr& input) {
+ gfx::Display result(input->id, input->bounds.To<gfx::Rect>());
+ result.set_work_area(input->work_area.To<gfx::Rect>());
+ result.set_device_scale_factor(input->device_pixel_ratio);
+ switch (input->rotation) {
+ case mus::mojom::Rotation::VALUE_0:
+ result.set_rotation(gfx::Display::ROTATE_0);
+ break;
+ case mus::mojom::Rotation::VALUE_90:
+ result.set_rotation(gfx::Display::ROTATE_90);
+ break;
+ case mus::mojom::Rotation::VALUE_180:
+ result.set_rotation(gfx::Display::ROTATE_180);
+ break;
+ case mus::mojom::Rotation::VALUE_270:
+ result.set_rotation(gfx::Display::ROTATE_270);
+ break;
+ }
+ switch (input->touch_support) {
+ case mus::mojom::TouchSupport::UNKNOWN:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_UNKNOWN);
+ break;
+ case mus::mojom::TouchSupport::AVAILABLE:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_AVAILABLE);
+ break;
+ case mus::mojom::TouchSupport::UNAVAILABLE:
+ result.set_touch_support(gfx::Display::TOUCH_SUPPORT_UNAVAILABLE);
+ break;
+ }
+ return result;
+ }
+};
+
+template <>
+struct TypeConverter<views::WindowManagerFrameValues,
+ mus::mojom::FrameDecorationValuesPtr> {
+ static views::WindowManagerFrameValues Convert(
+ const mus::mojom::FrameDecorationValuesPtr& input) {
+ views::WindowManagerFrameValues result;
+ result.normal_insets = input->normal_client_area_insets.To<gfx::Insets>();
+ result.maximized_insets =
+ input->maximized_client_area_insets.To<gfx::Insets>();
+ result.max_title_bar_button_width = input->max_title_bar_button_width;
+ return result;
+ }
+};
+
+} // namespace mojo
+
+namespace views {
+
+ScreenMus::ScreenMus(ScreenMusDelegate* delegate)
+ : delegate_(delegate),
+ primary_display_index_(0),
+ display_manager_observer_binding_(this) {}
+
+ScreenMus::~ScreenMus() {}
+
+void ScreenMus::Init(mojo::Connector* connector) {
+ gfx::Screen::SetScreenInstance(this);
+
+ connector->ConnectToInterface("mojo:mus", &display_manager_);
+
+ display_manager_->AddObserver(
+ display_manager_observer_binding_.CreateInterfacePtrAndBind());
+
+ // We need the set of displays before we can continue. Wait for it.
+ //
+ // TODO(rockot): Do something better here. This should not have to block tasks
+ // from running on the calling thread. http://crbug.com/594852.
+ display_manager_observer_binding_.WaitForIncomingMethodCall();
+
+ // The WaitForIncomingMethodCall() should have supplied the set of Displays.
+ DCHECK(displays_.size());
+}
+
+int ScreenMus::FindDisplayIndexById(int64_t id) const {
+ for (size_t i = 0; i < displays_.size(); ++i) {
+ if (displays_[i].id() == id)
+ return static_cast<int>(i);
+ }
+ return -1;
+}
+
+void ScreenMus::ProcessDisplayChanged(const gfx::Display& changed_display,
+ bool is_primary) {
+ const int display_index = FindDisplayIndexById(changed_display.id());
+ if (display_index == -1) {
+ displays_.push_back(changed_display);
+ if (is_primary)
+ primary_display_index_ = static_cast<int>(displays_.size()) - 1;
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayAdded(changed_display));
+ return;
+ }
+
+ gfx::Display* local_display = &displays_[display_index];
+ uint32_t changed_values = 0;
+ if (is_primary && display_index != primary_display_index_) {
+ primary_display_index_ = display_index;
+ // ash::DisplayManager only notifies for the Display gaining primary, not
+ // the one losing it.
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_PRIMARY;
+ }
+ if (local_display->bounds() != changed_display.bounds()) {
+ local_display->set_bounds(changed_display.bounds());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS;
+ }
+ if (local_display->work_area() != changed_display.work_area()) {
+ local_display->set_work_area(changed_display.work_area());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+ }
+ if (local_display->rotation() != changed_display.rotation()) {
+ local_display->set_rotation(changed_display.rotation());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION;
+ }
+ if (local_display->device_scale_factor() !=
+ changed_display.device_scale_factor()) {
+ local_display->set_device_scale_factor(
+ changed_display.device_scale_factor());
+ changed_values |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+ }
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayMetricsChanged(*local_display, changed_values));
+}
+
+gfx::Point ScreenMus::GetCursorScreenPoint() {
+ NOTIMPLEMENTED();
+ return gfx::Point();
+}
+
+gfx::NativeWindow ScreenMus::GetWindowUnderCursor() {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+gfx::NativeWindow ScreenMus::GetWindowAtScreenPoint(const gfx::Point& point) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+gfx::Display ScreenMus::GetPrimaryDisplay() const {
+ return displays_[primary_display_index_];
+}
+
+gfx::Display ScreenMus::GetDisplayNearestWindow(gfx::NativeView view) const {
+ //NOTIMPLEMENTED();
+ return GetPrimaryDisplay();
+}
+
+gfx::Display ScreenMus::GetDisplayNearestPoint(const gfx::Point& point) const {
+ return *gfx::FindDisplayNearestPoint(displays_, point);
+}
+
+int ScreenMus::GetNumDisplays() const {
+ return static_cast<int>(displays_.size());
+}
+
+std::vector<gfx::Display> ScreenMus::GetAllDisplays() const {
+ return displays_;
+}
+
+gfx::Display ScreenMus::GetDisplayMatching(const gfx::Rect& match_rect) const {
+ const gfx::Display* match =
+ gfx::FindDisplayWithBiggestIntersection(displays_, match_rect);
+ return match ? *match : GetPrimaryDisplay();
+}
+
+void ScreenMus::AddObserver(gfx::DisplayObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void ScreenMus::RemoveObserver(gfx::DisplayObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void ScreenMus::OnDisplays(mojo::Array<mus::mojom::DisplayPtr> displays) {
+ // This should only be called once from Init() before any observers have been
+ // added.
+ DCHECK(displays_.empty());
+ displays_ = displays.To<std::vector<gfx::Display>>();
+ for (size_t i = 0; i < displays.size(); ++i) {
+ if (displays[i]->is_primary) {
+ primary_display_index_ = static_cast<int>(i);
+ // TODO(sky): Make WindowManagerFrameValues per display.
+ WindowManagerFrameValues frame_values =
+ displays[i]->frame_decoration_values.To<WindowManagerFrameValues>();
+ WindowManagerFrameValues::SetInstance(frame_values);
+ }
+ }
+}
+
+void ScreenMus::OnDisplaysChanged(
+ mojo::Array<mus::mojom::DisplayPtr> transport_displays) {
+ for (size_t i = 0; i < transport_displays.size(); ++i) {
+ const bool is_primary = transport_displays[i]->is_primary;
+ ProcessDisplayChanged(transport_displays[i].To<gfx::Display>(), is_primary);
+ if (is_primary) {
+ WindowManagerFrameValues frame_values =
+ transport_displays[i]
+ ->frame_decoration_values.To<WindowManagerFrameValues>();
+ WindowManagerFrameValues::SetInstance(frame_values);
+ delegate_->OnWindowManagerFrameValuesChanged();
+ }
+ }
+}
+
+void ScreenMus::OnDisplayRemoved(int64_t id) {
+ const int index = FindDisplayIndexById(id);
+ DCHECK_NE(-1, index);
+ // Another display must become primary before the existing primary is
+ // removed.
+ DCHECK_NE(index, primary_display_index_);
+ const gfx::Display display = displays_[index];
+ FOR_EACH_OBSERVER(gfx::DisplayObserver, observers_,
+ OnDisplayRemoved(display));
+}
+
+} // namespace views
diff --git a/chromium/ui/views/mus/screen_mus.h b/chromium/ui/views/mus/screen_mus.h
new file mode 100644
index 00000000000..a6800afd72e
--- /dev/null
+++ b/chromium/ui/views/mus/screen_mus.h
@@ -0,0 +1,75 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_MUS_SCREEN_MUS_H_
+#define UI_VIEWS_MUS_SCREEN_MUS_H_
+
+#include <vector>
+
+#include "base/observer_list.h"
+#include "base/run_loop.h"
+#include "components/mus/public/interfaces/display.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/mus/mus_export.h"
+
+namespace mojo {
+class Connector;
+}
+
+namespace views {
+
+class ScreenMusDelegate;
+
+// Screen implementation backed by mus::mojom::DisplayManager.
+class VIEWS_MUS_EXPORT ScreenMus
+ : public gfx::Screen,
+ public NON_EXPORTED_BASE(mus::mojom::DisplayManagerObserver) {
+ public:
+ explicit ScreenMus(ScreenMusDelegate* delegate);
+ ~ScreenMus() override;
+
+ void Init(mojo::Connector* connector);
+
+ private:
+ int FindDisplayIndexById(int64_t id) const;
+
+ // Invoked when a display changed in some weay, including being added.
+ // If |is_primary| is true, |changed_display| is the primary display.
+ void ProcessDisplayChanged(const gfx::Display& changed_display,
+ bool is_primary);
+
+ // gfx::Screen:
+ gfx::Point GetCursorScreenPoint() override;
+ gfx::NativeWindow GetWindowUnderCursor() override;
+ gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
+ gfx::Display GetPrimaryDisplay() const override;
+ gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override;
+ gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override;
+ int GetNumDisplays() const override;
+ std::vector<gfx::Display> GetAllDisplays() const override;
+ gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
+ void AddObserver(gfx::DisplayObserver* observer) override;
+ void RemoveObserver(gfx::DisplayObserver* observer) override;
+
+ // mus::mojom::DisplayManager:
+ void OnDisplays(mojo::Array<mus::mojom::DisplayPtr> displays) override;
+ void OnDisplaysChanged(mojo::Array<mus::mojom::DisplayPtr> display) override;
+ void OnDisplayRemoved(int64_t id) override;
+
+ ScreenMusDelegate* delegate_;
+ mus::mojom::DisplayManagerPtr display_manager_;
+ std::vector<gfx::Display> displays_;
+ int primary_display_index_;
+ mojo::Binding<mus::mojom::DisplayManagerObserver>
+ display_manager_observer_binding_;
+ base::ObserverList<gfx::DisplayObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenMus);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_MUS_SCREEN_MUS_H_
diff --git a/chromium/ui/views/mus/screen_mus_delegate.h b/chromium/ui/views/mus/screen_mus_delegate.h
new file mode 100644
index 00000000000..4c7940088c5
--- /dev/null
+++ b/chromium/ui/views/mus/screen_mus_delegate.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_MUS_SCREEN_MUS_DELEGATE_H_
+#define UI_VIEWS_MUS_SCREEN_MUS_DELEGATE_H_
+
+#include "ui/views/mus/mus_export.h"
+
+namespace views {
+
+// Screen implementation backed by mus::mojom::DisplayManager.
+class VIEWS_MUS_EXPORT ScreenMusDelegate {
+ public:
+ virtual void OnWindowManagerFrameValuesChanged() = 0;
+
+ protected:
+ virtual ~ScreenMusDelegate() {}
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_MUS_SCREEN_MUS_DELEGATE_H_
diff --git a/chromium/ui/views/mus/surface_binding.cc b/chromium/ui/views/mus/surface_binding.cc
index ed4aedff436..e33e3247bd7 100644
--- a/chromium/ui/views/mus/surface_binding.cc
+++ b/chromium/ui/views/mus/surface_binding.cc
@@ -26,15 +26,10 @@
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/surfaces/surfaces_type_converters.h"
#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/shell/public/cpp/application_impl.h"
-#include "mojo/shell/public/cpp/connect.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/cpp/connector.h"
#include "ui/views/mus/window_tree_host_mus.h"
namespace views {
-namespace {
-void OnGotContentHandlerID(uint32_t content_handler_id) {}
-} // namespace
// PerConnectionState ----------------------------------------------------------
@@ -46,7 +41,7 @@ void OnGotContentHandlerID(uint32_t content_handler_id) {}
class SurfaceBinding::PerConnectionState
: public base::RefCounted<PerConnectionState> {
public:
- static PerConnectionState* Get(mojo::Shell* shell,
+ static PerConnectionState* Get(mojo::Connector* connector,
mus::WindowTreeConnection* connection);
scoped_ptr<cc::OutputSurface> CreateOutputSurface(
@@ -59,7 +54,8 @@ class SurfaceBinding::PerConnectionState
friend class base::RefCounted<PerConnectionState>;
- PerConnectionState(mojo::Shell* shell, mus::WindowTreeConnection* connection);
+ PerConnectionState(mojo::Connector* connector,
+ mus::WindowTreeConnection* connection);
~PerConnectionState();
void Init();
@@ -67,7 +63,7 @@ class SurfaceBinding::PerConnectionState
static base::LazyInstance<
base::ThreadLocalPointer<ConnectionToStateMap>>::Leaky window_states;
- mojo::Shell* shell_;
+ mojo::Connector* connector_;
mus::WindowTreeConnection* connection_;
// Set of state needed to create an OutputSurface.
@@ -83,7 +79,7 @@ base::LazyInstance<base::ThreadLocalPointer<
// static
SurfaceBinding::PerConnectionState* SurfaceBinding::PerConnectionState::Get(
- mojo::Shell* shell,
+ mojo::Connector* connector,
mus::WindowTreeConnection* connection) {
ConnectionToStateMap* window_map = window_states.Pointer()->Get();
if (!window_map) {
@@ -91,7 +87,7 @@ SurfaceBinding::PerConnectionState* SurfaceBinding::PerConnectionState::Get(
window_states.Pointer()->Set(window_map);
}
if (!(*window_map)[connection]) {
- (*window_map)[connection] = new PerConnectionState(shell, connection);
+ (*window_map)[connection] = new PerConnectionState(connector, connection);
(*window_map)[connection]->Init();
}
return (*window_map)[connection];
@@ -113,9 +109,9 @@ SurfaceBinding::PerConnectionState::CreateOutputSurface(
}
SurfaceBinding::PerConnectionState::PerConnectionState(
- mojo::Shell* shell,
+ mojo::Connector* connector,
mus::WindowTreeConnection* connection)
- : shell_(shell), connection_(connection) {}
+ : connector_(connector), connection_(connection) {}
SurfaceBinding::PerConnectionState::~PerConnectionState() {
ConnectionToStateMap* window_map = window_states.Pointer()->Get();
@@ -129,24 +125,17 @@ SurfaceBinding::PerConnectionState::~PerConnectionState() {
}
void SurfaceBinding::PerConnectionState::Init() {
- mojo::ServiceProviderPtr service_provider;
- mojo::URLRequestPtr request(mojo::URLRequest::New());
- request->url = mojo::String::From("mojo:mus");
- shell_->ConnectToApplication(std::move(request), GetProxy(&service_provider),
- nullptr,
- mojo::CreatePermissiveCapabilityFilter(),
- base::Bind(&OnGotContentHandlerID));
- ConnectToService(service_provider.get(), &gpu_);
+ connector_->ConnectToInterface("mojo:mus", &gpu_);
}
// SurfaceBinding --------------------------------------------------------------
-SurfaceBinding::SurfaceBinding(mojo::Shell* shell,
+SurfaceBinding::SurfaceBinding(mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type)
: window_(window),
surface_type_(surface_type),
- state_(PerConnectionState::Get(shell, window->connection())) {}
+ state_(PerConnectionState::Get(connector, window->connection())) {}
SurfaceBinding::~SurfaceBinding() {}
diff --git a/chromium/ui/views/mus/surface_binding.h b/chromium/ui/views/mus/surface_binding.h
index 0b468b574e4..2c6c5b68a33 100644
--- a/chromium/ui/views/mus/surface_binding.h
+++ b/chromium/ui/views/mus/surface_binding.h
@@ -16,7 +16,7 @@ class OutputSurface;
}
namespace mojo {
-class Shell;
+class Connector;
}
namespace mus {
@@ -32,7 +32,7 @@ namespace views {
// connection.
class VIEWS_MUS_EXPORT SurfaceBinding {
public:
- SurfaceBinding(mojo::Shell* shell,
+ SurfaceBinding(mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type);
~SurfaceBinding();
diff --git a/chromium/ui/views/mus/surface_context_factory.cc b/chromium/ui/views/mus/surface_context_factory.cc
index 0d5bfeea57e..bb27a08fb06 100644
--- a/chromium/ui/views/mus/surface_context_factory.cc
+++ b/chromium/ui/views/mus/surface_context_factory.cc
@@ -8,7 +8,7 @@
#include "cc/resources/shared_bitmap_manager.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "components/mus/public/cpp/window.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
#include "ui/compositor/reflector.h"
#include "ui/gl/gl_bindings.h"
@@ -27,10 +27,10 @@ class FakeReflector : public ui::Reflector {
} // namespace
SurfaceContextFactory::SurfaceContextFactory(
- mojo::Shell* shell,
+ mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type)
- : surface_binding_(shell, window, surface_type),
+ : surface_binding_(connector, window, surface_type),
next_surface_id_namespace_(1u) {}
SurfaceContextFactory::~SurfaceContextFactory() {}
diff --git a/chromium/ui/views/mus/surface_context_factory.h b/chromium/ui/views/mus/surface_context_factory.h
index 72c85fde9c0..6399d5a011b 100644
--- a/chromium/ui/views/mus/surface_context_factory.h
+++ b/chromium/ui/views/mus/surface_context_factory.h
@@ -16,7 +16,7 @@
#include "ui/views/mus/surface_binding.h"
namespace mojo {
-class Shell;
+class Connector;
}
namespace mus {
@@ -27,7 +27,7 @@ namespace views {
class VIEWS_MUS_EXPORT SurfaceContextFactory : public ui::ContextFactory {
public:
- SurfaceContextFactory(mojo::Shell* shell,
+ SurfaceContextFactory(mojo::Connector* connector,
mus::Window* window,
mus::mojom::SurfaceType surface_type);
~SurfaceContextFactory() override;
diff --git a/chromium/ui/views/mus/window_manager_connection.cc b/chromium/ui/views/mus/window_manager_connection.cc
index 286534714f1..fc41913602f 100644
--- a/chromium/ui/views/mus/window_manager_connection.cc
+++ b/chromium/ui/views/mus/window_manager_connection.cc
@@ -8,62 +8,16 @@
#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
-#include "base/threading/thread_restrictions.h"
#include "components/mus/public/cpp/window_tree_connection.h"
#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
-#include "mojo/converters/network/network_type_converters.h"
-#include "mojo/shell/public/cpp/application_connection.h"
-#include "mojo/shell/public/cpp/application_impl.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/mojo/init/ui_init.h"
+#include "mojo/shell/public/cpp/connection.h"
+#include "mojo/shell/public/cpp/connector.h"
#include "ui/views/mus/native_widget_mus.h"
-#include "ui/views/mus/window_manager_frame_values.h"
+#include "ui/views/mus/screen_mus.h"
#include "ui/views/views_delegate.h"
-namespace mojo {
-
-gfx::Display::Rotation GFXRotationFromMojomRotation(
- mus::mojom::Rotation input) {
- switch (input) {
- case mus::mojom::ROTATION_VALUE_0:
- return gfx::Display::ROTATE_0;
- case mus::mojom::ROTATION_VALUE_90:
- return gfx::Display::ROTATE_90;
- case mus::mojom::ROTATION_VALUE_180:
- return gfx::Display::ROTATE_180;
- case mus::mojom::ROTATION_VALUE_270:
- return gfx::Display::ROTATE_270;
- }
- return gfx::Display::ROTATE_0;
-}
-
-template <>
-struct TypeConverter<gfx::Display, mus::mojom::DisplayPtr> {
- static gfx::Display Convert(const mus::mojom::DisplayPtr& input) {
- gfx::Display result;
- result.set_id(input->id);
- result.SetScaleAndBounds(input->device_pixel_ratio,
- input->bounds.To<gfx::Rect>());
- gfx::Rect work_area(
- gfx::ScaleToFlooredPoint(
- gfx::Point(input->work_area->x, input->work_area->y),
- 1.0f / input->device_pixel_ratio),
- gfx::ScaleToFlooredSize(
- gfx::Size(input->work_area->width, input->work_area->height),
- 1.0f / input->device_pixel_ratio));
- result.set_work_area(work_area);
- result.set_rotation(GFXRotationFromMojomRotation(input->rotation));
- return result;
- }
-};
-
-} // namespace mojo
-
namespace views {
-
namespace {
using WindowManagerConnectionPtr =
@@ -73,32 +27,12 @@ using WindowManagerConnectionPtr =
base::LazyInstance<WindowManagerConnectionPtr>::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
-std::vector<gfx::Display> GetDisplaysFromWindowManager(
- mus::mojom::WindowManagerPtr* window_manager) {
- WindowManagerFrameValues frame_values;
- std::vector<gfx::Display> displays;
- (*window_manager)
- ->GetConfig([&displays,
- &frame_values](mus::mojom::WindowManagerConfigPtr results) {
- displays = results->displays.To<std::vector<gfx::Display>>();
- frame_values.normal_insets =
- results->normal_client_area_insets.To<gfx::Insets>();
- frame_values.maximized_insets =
- results->maximized_client_area_insets.To<gfx::Insets>();
- frame_values.max_title_bar_button_width =
- results->max_title_bar_button_width;
- });
- CHECK(window_manager->WaitForIncomingResponse());
- WindowManagerFrameValues::SetInstance(frame_values);
- return displays;
-}
-
} // namespace
// static
-void WindowManagerConnection::Create(mojo::ApplicationImpl* app) {
+void WindowManagerConnection::Create(mojo::Connector* connector) {
DCHECK(!lazy_tls_ptr.Pointer()->Get());
- lazy_tls_ptr.Pointer()->Set(new WindowManagerConnection(app));
+ lazy_tls_ptr.Pointer()->Set(new WindowManagerConnection(connector));
}
// static
@@ -108,36 +42,44 @@ WindowManagerConnection* WindowManagerConnection::Get() {
return connection;
}
+// static
+bool WindowManagerConnection::Exists() {
+ return !!lazy_tls_ptr.Pointer()->Get();
+}
+
+// static
+void WindowManagerConnection::Reset() {
+ delete Get();
+ lazy_tls_ptr.Pointer()->Set(nullptr);
+}
+
mus::Window* WindowManagerConnection::NewWindow(
const std::map<std::string, std::vector<uint8_t>>& properties) {
- if (window_tree_connection_)
- return window_tree_connection_->NewTopLevelWindow(&properties);
-
- mus::mojom::WindowTreeClientPtr window_tree_client;
- mojo::InterfaceRequest<mus::mojom::WindowTreeClient>
- window_tree_client_request = GetProxy(&window_tree_client);
- window_manager_->OpenWindow(
- std::move(window_tree_client),
- mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(properties));
-
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- window_tree_connection_.reset(mus::WindowTreeConnection::Create(
- this, std::move(window_tree_client_request),
- mus::WindowTreeConnection::CreateType::WAIT_FOR_EMBED));
- window_tree_connection_->SetDeleteOnNoRoots(false);
- DCHECK_EQ(1u, window_tree_connection_->GetRoots().size());
- return *window_tree_connection_->GetRoots().begin();
+ return window_tree_connection_->NewTopLevelWindow(&properties);
+}
+
+NativeWidget* WindowManagerConnection::CreateNativeWidgetMus(
+ const std::map<std::string, std::vector<uint8_t>>& props,
+ const Widget::InitParams& init_params,
+ internal::NativeWidgetDelegate* delegate) {
+ std::map<std::string, std::vector<uint8_t>> properties = props;
+ NativeWidgetMus::ConfigurePropertiesForNewWindow(init_params, &properties);
+ return new NativeWidgetMus(delegate, connector_, NewWindow(properties),
+ mus::mojom::SurfaceType::DEFAULT);
}
-WindowManagerConnection::WindowManagerConnection(mojo::ApplicationImpl* app)
- : app_(app), window_tree_connection_(nullptr) {
- app->ConnectToService("mojo:mus", &window_manager_);
+WindowManagerConnection::WindowManagerConnection(mojo::Connector* connector)
+ : connector_(connector), window_tree_connection_(nullptr) {
+ window_tree_connection_.reset(
+ mus::WindowTreeConnection::Create(this, connector_));
- ui_init_.reset(new ui::mojo::UIInit(
- GetDisplaysFromWindowManager(&window_manager_)));
- ViewsDelegate::GetInstance()->set_native_widget_factory(
- base::Bind(&WindowManagerConnection::CreateNativeWidget,
- base::Unretained(this)));
+ screen_.reset(new ScreenMus(this));
+ screen_->Init(connector);
+
+ ViewsDelegate::GetInstance()->set_native_widget_factory(base::Bind(
+ &WindowManagerConnection::CreateNativeWidgetMus,
+ base::Unretained(this),
+ std::map<std::string, std::vector<uint8_t>>()));
}
WindowManagerConnection::~WindowManagerConnection() {
@@ -151,13 +93,9 @@ void WindowManagerConnection::OnEmbed(mus::Window* root) {}
void WindowManagerConnection::OnConnectionLost(
mus::WindowTreeConnection* connection) {}
-NativeWidget* WindowManagerConnection::CreateNativeWidget(
- const Widget::InitParams& init_params,
- internal::NativeWidgetDelegate* delegate) {
- std::map<std::string, std::vector<uint8_t>> properties;
- NativeWidgetMus::ConfigurePropertiesForNewWindow(init_params, &properties);
- return new NativeWidgetMus(delegate, app_->shell(), NewWindow(properties),
- mus::mojom::SURFACE_TYPE_DEFAULT);
+void WindowManagerConnection::OnWindowManagerFrameValuesChanged() {
+ if (window_tree_connection_)
+ NativeWidgetMus::NotifyFrameChanged(window_tree_connection_.get());
}
} // namespace views
diff --git a/chromium/ui/views/mus/window_manager_connection.h b/chromium/ui/views/mus/window_manager_connection.h
index ab12a03b05b..69059893346 100644
--- a/chromium/ui/views/mus/window_manager_connection.h
+++ b/chromium/ui/views/mus/window_manager_connection.h
@@ -10,57 +10,63 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "components/mus/public/cpp/window_tree_delegate.h"
-#include "components/mus/public/interfaces/window_manager.mojom.h"
#include "ui/views/mus/mus_export.h"
+#include "ui/views/mus/screen_mus_delegate.h"
#include "ui/views/widget/widget.h"
namespace mojo {
-class ApplicationImpl;
-}
-
-namespace ui {
-namespace mojo {
-class UIInit;
-}
+class Connector;
}
namespace views {
class NativeWidget;
+class ScreenMus;
namespace internal {
class NativeWidgetDelegate;
}
-// Establishes a connection to the window manager for use by views within an
-// application, and performs Aura initialization.
+// Provides configuration to mus in views. This consists of the following:
+// . Provides a Screen implementation backed by mus.
+// . Creates and owns a WindowTreeConnection.
+// . Registers itself as the factory for creating NativeWidgets so that a
+// NativeWidgetMus is created.
+// WindowManagerConnection is a singleton and should be created early on.
+//
+// TODO(sky): this name is now totally confusing. Come up with a better one.
class VIEWS_MUS_EXPORT WindowManagerConnection
- : public NON_EXPORTED_BASE(mus::WindowTreeDelegate) {
+ : public NON_EXPORTED_BASE(mus::WindowTreeDelegate),
+ public ScreenMusDelegate {
public:
- static void Create(mojo::ApplicationImpl* app);
+ static void Create(mojo::Connector* connector);
static WindowManagerConnection* Get();
+ static bool Exists();
+
+ // Destroys the singleton instance.
+ static void Reset();
- mojo::ApplicationImpl* app() { return app_; }
+ mojo::Connector* connector() { return connector_; }
mus::Window* NewWindow(const std::map<std::string,
std::vector<uint8_t>>& properties);
- mus::mojom::WindowManager* window_manager() {
- return window_manager_.get();
- }
+ NativeWidget* CreateNativeWidgetMus(
+ const std::map<std::string, std::vector<uint8_t>>& properties,
+ const Widget::InitParams& init_params,
+ internal::NativeWidgetDelegate* delegate);
private:
- explicit WindowManagerConnection(mojo::ApplicationImpl* app);
+ explicit WindowManagerConnection(mojo::Connector* connector);
~WindowManagerConnection() override;
// mus::WindowTreeDelegate:
void OnEmbed(mus::Window* root) override;
void OnConnectionLost(mus::WindowTreeConnection* connection) override;
- NativeWidget* CreateNativeWidget(const Widget::InitParams& init_params,
- internal::NativeWidgetDelegate* delegate);
+ // ScreenMusDelegate:
+ void OnWindowManagerFrameValuesChanged() override;
- mojo::ApplicationImpl* app_;
- mus::mojom::WindowManagerPtr window_manager_;
- scoped_ptr<ui::mojo::UIInit> ui_init_;
+ mojo::Connector* connector_;
+ scoped_ptr<ScreenMus> screen_;
scoped_ptr<mus::WindowTreeConnection> window_tree_connection_;
DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
diff --git a/chromium/ui/views/mus/window_manager_constants_converters.cc b/chromium/ui/views/mus/window_manager_constants_converters.cc
index 80e6d1f68be..889737698f1 100644
--- a/chromium/ui/views/mus/window_manager_constants_converters.cc
+++ b/chromium/ui/views/mus/window_manager_constants_converters.cc
@@ -12,25 +12,25 @@ TypeConverter<mus::mojom::WindowType, views::Widget::InitParams::Type>::Convert(
views::Widget::InitParams::Type type) {
switch (type) {
case views::Widget::InitParams::TYPE_WINDOW:
- return mus::mojom::WINDOW_TYPE_WINDOW;
+ return mus::mojom::WindowType::WINDOW;
case views::Widget::InitParams::TYPE_PANEL:
- return mus::mojom::WINDOW_TYPE_PANEL;
+ return mus::mojom::WindowType::PANEL;
case views::Widget::InitParams::TYPE_WINDOW_FRAMELESS:
- return mus::mojom::WINDOW_TYPE_WINDOW_FRAMELESS;
+ return mus::mojom::WindowType::WINDOW_FRAMELESS;
case views::Widget::InitParams::TYPE_CONTROL:
- return mus::mojom::WINDOW_TYPE_CONTROL;
+ return mus::mojom::WindowType::CONTROL;
case views::Widget::InitParams::TYPE_POPUP:
- return mus::mojom::WINDOW_TYPE_POPUP;
+ return mus::mojom::WindowType::POPUP;
case views::Widget::InitParams::TYPE_MENU:
- return mus::mojom::WINDOW_TYPE_MENU;
+ return mus::mojom::WindowType::MENU;
case views::Widget::InitParams::TYPE_TOOLTIP:
- return mus::mojom::WINDOW_TYPE_TOOLTIP;
+ return mus::mojom::WindowType::TOOLTIP;
case views::Widget::InitParams::TYPE_BUBBLE:
- return mus::mojom::WINDOW_TYPE_BUBBLE;
+ return mus::mojom::WindowType::BUBBLE;
case views::Widget::InitParams::TYPE_DRAG:
- return mus::mojom::WINDOW_TYPE_DRAG;
+ return mus::mojom::WindowType::DRAG;
}
- return mus::mojom::WINDOW_TYPE_POPUP;
+ return mus::mojom::WindowType::POPUP;
}
} // namespace mojo
diff --git a/chromium/ui/views/mus/window_manager_frame_values.h b/chromium/ui/views/mus/window_manager_frame_values.h
index b0b8e10ee77..50c73f34c0f 100644
--- a/chromium/ui/views/mus/window_manager_frame_values.h
+++ b/chromium/ui/views/mus/window_manager_frame_values.h
@@ -19,6 +19,16 @@ struct VIEWS_MUS_EXPORT WindowManagerFrameValues {
static void SetInstance(const WindowManagerFrameValues& values);
static const WindowManagerFrameValues& instance();
+ bool operator==(const WindowManagerFrameValues& other) const {
+ return normal_insets == other.normal_insets &&
+ maximized_insets == other.maximized_insets &&
+ max_title_bar_button_width == other.max_title_bar_button_width;
+ }
+
+ bool operator!=(const WindowManagerFrameValues& other) const {
+ return !(*this == other);
+ }
+
// Ideal insets the window manager renders non-client frame decorations into.
gfx::Insets normal_insets;
gfx::Insets maximized_insets;
diff --git a/chromium/ui/views/mus/window_tree_host_mus.cc b/chromium/ui/views/mus/window_tree_host_mus.cc
index 6edb53d08aa..2880c0bf480 100644
--- a/chromium/ui/views/mus/window_tree_host_mus.cc
+++ b/chromium/ui/views/mus/window_tree_host_mus.cc
@@ -4,11 +4,8 @@
#include "ui/views/mus/window_tree_host_mus.h"
-#include "components/bitmap_uploader/bitmap_uploader.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
-#include "ui/base/view_prop.h"
#include "ui/events/event.h"
#include "ui/views/mus/input_method_mus.h"
#include "ui/views/mus/native_widget_mus.h"
@@ -19,13 +16,13 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// WindowTreeHostMus, public:
-WindowTreeHostMus::WindowTreeHostMus(mojo::Shell* shell,
+WindowTreeHostMus::WindowTreeHostMus(mojo::Connector* connector,
NativeWidgetMus* native_widget,
- mus::Window* window,
- mus::mojom::SurfaceType surface_type)
+ mus::Window* window)
: native_widget_(native_widget),
show_state_(ui::PLATFORM_WINDOW_STATE_UNKNOWN) {
- SetPlatformWindow(make_scoped_ptr(new PlatformWindowMus(this, window)));
+ SetPlatformWindow(
+ make_scoped_ptr(new PlatformWindowMus(this, connector, window)));
// The location of events is already transformed, and there is no way to
// correctly determine the reverse transform. So, don't attempt to transform
// event locations, else the root location is wrong.
@@ -33,13 +30,6 @@ WindowTreeHostMus::WindowTreeHostMus(mojo::Shell* shell,
dispatcher()->set_transform_events(false);
compositor()->SetHostHasTransparentBackground(true);
- bitmap_uploader_.reset(new bitmap_uploader::BitmapUploader(window));
- bitmap_uploader_->Init(shell);
- prop_.reset(
- new ui::ViewProp(GetAcceleratedWidget(),
- bitmap_uploader::kBitmapUploaderForAcceleratedWidget,
- bitmap_uploader_.get()));
-
input_method_.reset(new InputMethodMUS(this, window));
SetSharedInputMethod(input_method_.get());
}
@@ -56,7 +46,7 @@ PlatformWindowMus* WindowTreeHostMus::platform_window() {
void WindowTreeHostMus::DispatchEvent(ui::Event* event) {
if (event->IsKeyEvent() && GetInputMethod()) {
- GetInputMethod()->DispatchKeyEvent(static_cast<ui::KeyEvent*>(event));
+ GetInputMethod()->DispatchKeyEvent(event->AsKeyEvent());
event->StopPropagation();
return;
}
diff --git a/chromium/ui/views/mus/window_tree_host_mus.h b/chromium/ui/views/mus/window_tree_host_mus.h
index 0116e60b942..0bffe25ea13 100644
--- a/chromium/ui/views/mus/window_tree_host_mus.h
+++ b/chromium/ui/views/mus/window_tree_host_mus.h
@@ -6,29 +6,19 @@
#define UI_VIEWS_MUS_WINDOW_TREE_HOST_MUS_H_
#include "base/macros.h"
-#include "components/mus/public/interfaces/window_tree.mojom.h"
#include "ui/aura/window_tree_host_platform.h"
#include "ui/views/mus/mus_export.h"
class SkBitmap;
-namespace bitmap_uploader {
-class BitmapUploader;
-}
-
namespace mojo {
-class Shell;
+class Connector;
}
namespace mus {
class Window;
}
-namespace ui {
-class Compositor;
-class ViewProp;
-}
-
namespace views {
class InputMethodMUS;
@@ -37,16 +27,12 @@ class PlatformWindowMus;
class VIEWS_MUS_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform {
public:
- WindowTreeHostMus(mojo::Shell* shell,
- NativeWidgetMus* native_widget_,
- mus::Window* window,
- mus::mojom::SurfaceType surface_type);
+ WindowTreeHostMus(mojo::Connector* connector,
+ NativeWidgetMus* native_widget,
+ mus::Window* window);
~WindowTreeHostMus() override;
PlatformWindowMus* platform_window();
- bitmap_uploader::BitmapUploader* bitmap_uploader() {
- return bitmap_uploader_.get();
- }
ui::PlatformWindowState show_state() const { return show_state_; }
private:
@@ -60,8 +46,6 @@ class VIEWS_MUS_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform {
NativeWidgetMus* native_widget_;
scoped_ptr<InputMethodMUS> input_method_;
ui::PlatformWindowState show_state_;
- scoped_ptr<bitmap_uploader::BitmapUploader> bitmap_uploader_;
- scoped_ptr<ui::ViewProp> prop_;
DISALLOW_COPY_AND_ASSIGN(WindowTreeHostMus);
};
diff --git a/chromium/ui/views/painter.cc b/chromium/ui/views/painter.cc
index 0cc1f0d38c5..9a677956f84 100644
--- a/chromium/ui/views/painter.cc
+++ b/chromium/ui/views/painter.cc
@@ -12,7 +12,9 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_operations.h"
@@ -23,6 +25,41 @@ namespace views {
namespace {
+// SolidRoundRectPainter -------------------------------------------------------
+
+class SolidRoundRectPainter : public Painter {
+ public:
+ SolidRoundRectPainter(SkColor color, float radius);
+ ~SolidRoundRectPainter() override;
+
+ // Painter:
+ gfx::Size GetMinimumSize() const override;
+ void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
+
+ private:
+ const SkColor color_;
+ const float radius_;
+
+ DISALLOW_COPY_AND_ASSIGN(SolidRoundRectPainter);
+};
+
+SolidRoundRectPainter::SolidRoundRectPainter(SkColor color, float radius)
+ : color_(color), radius_(radius) {}
+
+SolidRoundRectPainter::~SolidRoundRectPainter() {}
+
+gfx::Size SolidRoundRectPainter::GetMinimumSize() const {
+ return gfx::Size();
+}
+
+void SolidRoundRectPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
+ gfx::RectF rect((gfx::SizeF(size)));
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(color_);
+ canvas->DrawRoundRect(rect, radius_, paint);
+}
+
// DashedFocusPainter ----------------------------------------------------------
class DashedFocusPainter : public Painter {
@@ -151,10 +188,9 @@ void GradientPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
else
p[1].iset(0, size.height());
- skia::RefPtr<SkShader> s = skia::AdoptRef(SkGradientShader::CreateLinear(
+ paint.setShader(SkGradientShader::MakeLinear(
p, colors_.get(), pos_.get(), count_, SkShader::kClamp_TileMode));
paint.setStyle(SkPaint::kFill_Style);
- paint.setShader(s.get());
canvas->sk_canvas()->drawRectCoords(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(size.width()),
@@ -236,6 +272,11 @@ void Painter::PaintFocusPainter(View* view,
}
// static
+Painter* Painter::CreateSolidRoundRectPainter(SkColor color, float radius) {
+ return new SolidRoundRectPainter(color, radius);
+}
+
+// static
Painter* Painter::CreateHorizontalGradient(SkColor c1, SkColor c2) {
SkColor colors[2];
colors[0] = c1;
diff --git a/chromium/ui/views/painter.h b/chromium/ui/views/painter.h
index d75688eb2a2..76cc996f50c 100644
--- a/chromium/ui/views/painter.h
+++ b/chromium/ui/views/painter.h
@@ -46,6 +46,10 @@ class VIEWS_EXPORT Painter {
gfx::Canvas* canvas,
Painter* focus_painter);
+ // Creates a painter that draws a RoundRect with a solid color and given
+ // corner radius.
+ static Painter* CreateSolidRoundRectPainter(SkColor color, float radius);
+
// Creates a painter that draws a gradient between the two colors.
static Painter* CreateHorizontalGradient(SkColor c1, SkColor c2);
static Painter* CreateVerticalGradient(SkColor c1, SkColor c2);
diff --git a/chromium/ui/views/resources/default_100_percent/common/menu_radio_empty.png b/chromium/ui/views/resources/default_100_percent/common/menu_radio_empty.png
deleted file mode 100644
index d2dbe3f87f0..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/menu_radio_empty.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/menu_radio_selected.png b/chromium/ui/views/resources/default_100_percent/common/menu_radio_selected.png
deleted file mode 100644
index 3aa9622048a..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/menu_radio_selected.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/menu_radio_empty.png b/chromium/ui/views/resources/default_200_percent/common/menu_radio_empty.png
deleted file mode 100644
index 9ea7868a903..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/menu_radio_empty.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/menu_radio_selected.png b/chromium/ui/views/resources/default_200_percent/common/menu_radio_selected.png
deleted file mode 100644
index d41e6423a43..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/menu_radio_selected.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/views_resources.grd b/chromium/ui/views/resources/views_resources.grd
index 743cc764472..7d6eb05ee83 100644
--- a/chromium/ui/views/resources/views_resources.grd
+++ b/chromium/ui/views/resources/views_resources.grd
@@ -159,8 +159,6 @@
<if expr="chromeos">
<structure type="chrome_scaled_image" name="IDR_MENU_CHECK" file="cros/menu_check.png" />
</if>
- <structure type="chrome_scaled_image" name="IDR_MENU_RADIO_EMPTY" file="common/menu_radio_empty.png" />
- <structure type="chrome_scaled_image" name="IDR_MENU_RADIO_SELECTED" file="common/menu_radio_selected.png" />
<structure type="chrome_scaled_image" name="IDR_SLIDER_ACTIVE_LEFT" file="slider_left_active.png" />
<structure type="chrome_scaled_image" name="IDR_SLIDER_ACTIVE_RIGHT" file="slider_right_active.png" />
<structure type="chrome_scaled_image" name="IDR_SLIDER_ACTIVE_CENTER" file="slider_center_active.png" />
diff --git a/chromium/ui/views/run_all_unittests.cc b/chromium/ui/views/run_all_unittests.cc
index d90123190e7..922343bdc91 100644
--- a/chromium/ui/views/run_all_unittests.cc
+++ b/chromium/ui/views/run_all_unittests.cc
@@ -17,6 +17,8 @@
#include "ui/aura/env.h"
#endif
+namespace views {
+
class ViewTestSuite : public base::TestSuite {
public:
ViewTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
@@ -47,10 +49,12 @@ class ViewTestSuite : public base::TestSuite {
DISALLOW_COPY_AND_ASSIGN(ViewTestSuite);
};
-int main(int argc, char** argv) {
+int RunAllUnittests(int argc, char** argv) {
ViewTestSuite test_suite(argc, argv);
return base::LaunchUnitTests(
argc, argv, base::Bind(&ViewTestSuite::Run,
base::Unretained(&test_suite)));
}
+
+} // namespace views
diff --git a/chromium/ui/views/run_all_unittests.h b/chromium/ui/views/run_all_unittests.h
new file mode 100644
index 00000000000..43239f80772
--- /dev/null
+++ b/chromium/ui/views/run_all_unittests.h
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_RUN_ALL_UNITTESTS_H_
+#define UI_VIEWS_RUN_ALL_UNITTESTS_H_
+
+namespace views {
+
+int RunAllUnittests(int argc, char** argv);
+
+} // namespace
+
+#endif // UI_VIEWS_RUN_ALL_UNITTESTS_H_
diff --git a/chromium/ui/views/run_all_unittests_main.cc b/chromium/ui/views/run_all_unittests_main.cc
new file mode 100644
index 00000000000..5b26c760050
--- /dev/null
+++ b/chromium/ui/views/run_all_unittests_main.cc
@@ -0,0 +1,9 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/run_all_unittests.h"
+
+int main(int argc, char** argv) {
+ views::RunAllUnittests(argc, argv);
+}
diff --git a/chromium/ui/views/shadow_border.cc b/chromium/ui/views/shadow_border.cc
index fb5888b1e8e..1f19c019c12 100644
--- a/chromium/ui/views/shadow_border.cc
+++ b/chromium/ui/views/shadow_border.cc
@@ -38,8 +38,7 @@ void ShadowBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
SkPaint paint;
std::vector<gfx::ShadowValue> shadows;
shadows.push_back(shadow_value_);
- skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows);
- paint.setLooper(looper.get());
+ paint.setLooper(gfx::CreateShadowDrawLooper(shadows));
paint.setColor(SK_ColorTRANSPARENT);
paint.setStrokeJoin(SkPaint::kRound_Join);
gfx::Rect bounds(view.size());
diff --git a/chromium/ui/views/style/mac/combobox_background_mac.cc b/chromium/ui/views/style/mac/combobox_background_mac.cc
new file mode 100644
index 00000000000..31997b15b78
--- /dev/null
+++ b/chromium/ui/views/style/mac/combobox_background_mac.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/style/mac/combobox_background_mac.h"
+
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkRRect.h"
+#include "ui/gfx/canvas.h"
+#include "ui/native_theme/native_theme_mac.h"
+#include "ui/views/controls/combobox/combobox.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+ComboboxBackgroundMac::ComboboxBackgroundMac() {}
+
+ComboboxBackgroundMac::~ComboboxBackgroundMac() {}
+
+void ComboboxBackgroundMac::Paint(gfx::Canvas* canvas, View* view) const {
+ DCHECK_EQ(view->GetClassName(), Combobox::kViewClassName);
+ Combobox* combobox = static_cast<Combobox*>(view);
+
+ gfx::RectF bounds(combobox->GetLocalBounds());
+ // Inset the left side far enough to draw only the arrow button, and inset the
+ // other three sides by half a pixel so the edge of the background doesn't
+ // paint outside the border.
+ bounds.Inset(bounds.width() - combobox->GetArrowButtonWidth(), 0.5, 0.5, 0.5);
+
+ ui::NativeTheme::State state = ui::NativeTheme::kNormal;
+ if (!combobox->enabled())
+ state = ui::NativeTheme::kDisabled;
+
+ SkPaint paint;
+ paint.setShader(
+ ui::NativeThemeMac::GetButtonBackgroundShader(
+ state,
+ bounds.height()));
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setAntiAlias(true);
+
+ SkPoint no_curve = SkPoint::Make(0, 0);
+ SkPoint curve = SkPoint::Make(
+ ui::NativeThemeMac::kComboboxCornerRadius,
+ ui::NativeThemeMac::kComboboxCornerRadius);
+ SkVector curves[4] = { no_curve, curve, curve, no_curve };
+
+ SkRRect fill_rect;
+ fill_rect.setRectRadii(gfx::RectFToSkRect(bounds), curves);
+
+ SkPath path;
+ path.addRRect(fill_rect);
+
+ canvas->DrawPath(path, paint);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/style/mac/combobox_background_mac.h b/chromium/ui/views/style/mac/combobox_background_mac.h
new file mode 100644
index 00000000000..5be50858d75
--- /dev/null
+++ b/chromium/ui/views/style/mac/combobox_background_mac.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_STYLE_MAC_COMBOBOX_BACKGROUND_MAC_H_
+#define UI_VIEWS_STYLE_MAC_COMBOBOX_BACKGROUND_MAC_H_
+
+#include "base/macros.h"
+#include "ui/views/background.h"
+
+namespace gfx {
+class Canvas;
+}
+
+namespace views {
+
+// This class implements the background of comboboxes. Comboboxes look like
+// this:
+// ---------------------------
+// | Option Text... | Arrows |
+// ---------------------------
+// This class colors the background of the arrows section in accordance with our
+// Mac look and feel.
+class ComboboxBackgroundMac : public Background {
+ public:
+ ComboboxBackgroundMac();
+ ~ComboboxBackgroundMac() override;
+
+ // Background:
+ void Paint(gfx::Canvas* canvas, View* view) const override;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ComboboxBackgroundMac);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_STYLE_MAC_COMBOBOX_BACKGROUND_MAC_H_
diff --git a/chromium/ui/views/style/mac/dialog_button_border_mac.cc b/chromium/ui/views/style/mac/dialog_button_border_mac.cc
index 24cedaec8cb..366fbc28e9c 100644
--- a/chromium/ui/views/style/mac/dialog_button_border_mac.cc
+++ b/chromium/ui/views/style/mac/dialog_button_border_mac.cc
@@ -38,8 +38,8 @@ const double kInnerShadowBlurRadius = 2.0;
const int kPaddingX = 14;
const int kPaddingY = 4;
-skia::RefPtr<SkShader> GetButtonGradient(int height,
- Button::ButtonState state) {
+sk_sp<SkShader> CreateButtonGradient(int height,
+ Button::ButtonState state) {
ColorByState start = {0xFFF0F0F0, 0xFFF4F4F4, 0xFFEBEBEB, 0xFFEDEDED};
ColorByState end = {0xFFE0E0E0, 0xFFE4E4E4, 0xFFDBDBDB, 0xFFDEDEDE};
@@ -50,11 +50,9 @@ skia::RefPtr<SkShader> GetButtonGradient(int height,
SkColor gradient_colors[] = {start[state], start[state], end[state]};
SkScalar gradient_positions[] = {0.0, 0.38, 1.0};
- skia::RefPtr<SkShader> gradient_shader =
- skia::AdoptRef(SkGradientShader::CreateLinear(
+ return SkGradientShader::MakeLinear(
gradient_points, gradient_colors, gradient_positions, 3,
- SkShader::kClamp_TileMode));
- return gradient_shader;
+ SkShader::kClamp_TileMode);
}
void DrawConstrainedButtonBackground(const SkRect& button_rect,
@@ -74,13 +72,10 @@ void DrawConstrainedButtonBackground(const SkRect& button_rect,
std::vector<gfx::ShadowValue> shadows(
1, gfx::ShadowValue(gfx::Vector2d(0, kShadowOffsetY), blur,
shadow[button_state]));
- skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows);
- paint.setLooper(looper.get());
+ paint.setLooper(gfx::CreateShadowDrawLooper(shadows));
// Background.
- skia::RefPtr<SkShader> gradient_shader =
- GetButtonGradient(rect.height(), button_state);
- paint.setShader(gradient_shader.get());
+ paint.setShader(CreateButtonGradient(rect.height(), button_state));
paint.setStyle(SkPaint::kFill_Style);
paint.setFlags(SkPaint::kAntiAlias_Flag);
canvas->drawRoundRect(rect, kCornerRadius, kCornerRadius, paint);
@@ -110,8 +105,7 @@ void DrawRoundRectInnerShadow(const SkRect& rect,
SkPaint paint;
std::vector<gfx::ShadowValue> shadows(
1, gfx::ShadowValue(shadow_offset, kInnerShadowBlurRadius, shadow_color));
- skia::RefPtr<SkDrawLooper> looper = gfx::CreateShadowDrawLooper(shadows);
- paint.setLooper(looper.get());
+ paint.setLooper(gfx::CreateShadowDrawLooper(shadows));
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SK_ColorBLACK); // Note: Entirely clipped.
diff --git a/chromium/ui/views/style/platform_style.cc b/chromium/ui/views/style/platform_style.cc
index 866a1ca72c3..6719c9ba46b 100644
--- a/chromium/ui/views/style/platform_style.cc
+++ b/chromium/ui/views/style/platform_style.cc
@@ -5,13 +5,36 @@
#include "ui/views/style/platform_style.h"
#include "build/build_config.h"
-#include "ui/base/resource/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/background.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/label_button_border.h"
+#include "ui/views/controls/focusable_border.h"
+#include "ui/views/controls/scrollbar/native_scroll_bar.h"
namespace views {
#if !defined(OS_MACOSX)
+
+// static
+gfx::ImageSkia PlatformStyle::CreateComboboxArrow(bool is_enabled,
+ Combobox::Style style) {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return *rb.GetImageSkiaNamed(IDR_MENU_DROPARROW);
+}
+
+// static
+scoped_ptr<FocusableBorder> PlatformStyle::CreateComboboxBorder() {
+ return make_scoped_ptr(new FocusableBorder());
+}
+
+// static
+scoped_ptr<Background> PlatformStyle::CreateComboboxBackground() {
+ return nullptr;
+}
+
// static
scoped_ptr<LabelButtonBorder> PlatformStyle::CreateLabelButtonBorder(
Button::ButtonStyle style) {
@@ -25,6 +48,11 @@ scoped_ptr<LabelButtonBorder> PlatformStyle::CreateLabelButtonBorder(
Button::STYLE_TEXTBUTTON));
return border;
}
+
+// static
+scoped_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
+ return make_scoped_ptr(new NativeScrollBar(is_horizontal));
+}
#endif
#if !defined(OS_LINUX) || defined(OS_CHROMEOS)
diff --git a/chromium/ui/views/style/platform_style.h b/chromium/ui/views/style/platform_style.h
index e56fe0e30ba..3103691642a 100644
--- a/chromium/ui/views/style/platform_style.h
+++ b/chromium/ui/views/style/platform_style.h
@@ -8,16 +8,32 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/combobox/combobox.h"
namespace views {
class Border;
+class FocusableBorder;
class LabelButton;
class LabelButtonBorder;
+class ScrollBar;
// Cross-platform API for providing platform-specific styling for toolkit-views.
class PlatformStyle {
public:
+ // Creates an ImageSkia containing the image to use for the combobox arrow.
+ // The |is_enabled| argument is true if the control the arrow is for is
+ // enabled, and false if the control is disabled. The |style| argument is the
+ // style of the combobox the arrow is being drawn for.
+ static gfx::ImageSkia CreateComboboxArrow(bool is_enabled,
+ Combobox::Style style);
+
+ // Creates the appropriate border for a focusable Combobox.
+ static scoped_ptr<FocusableBorder> CreateComboboxBorder();
+
+ // Creates the appropriate background for a Combobox.
+ static scoped_ptr<Background> CreateComboboxBackground();
+
// Creates the default label button border for the given |style|. Used when a
// custom default border is not provided for a particular LabelButton class.
static scoped_ptr<LabelButtonBorder> CreateLabelButtonBorder(
@@ -26,6 +42,9 @@ class PlatformStyle {
// Applies the current system theme to the default border created by |button|.
static scoped_ptr<Border> CreateThemedLabelButtonBorder(LabelButton* button);
+ // Creates the default scrollbar for the given orientation.
+ static scoped_ptr<ScrollBar> CreateScrollBar(bool is_horizontal);
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformStyle);
};
diff --git a/chromium/ui/views/style/platform_style_mac.cc b/chromium/ui/views/style/platform_style_mac.cc
deleted file mode 100644
index f1038d87842..00000000000
--- a/chromium/ui/views/style/platform_style_mac.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/style/platform_style.h"
-
-#include "ui/views/controls/button/label_button.h"
-#include "ui/views/controls/button/label_button_border.h"
-#include "ui/views/style/mac/dialog_button_border_mac.h"
-
-namespace views {
-
-// static
-scoped_ptr<LabelButtonBorder> PlatformStyle::CreateLabelButtonBorder(
- Button::ButtonStyle style) {
- if (style == Button::STYLE_BUTTON)
- return make_scoped_ptr(new DialogButtonBorderMac());
-
- return make_scoped_ptr(new LabelButtonAssetBorder(style));
-}
-
-} // namespace views
diff --git a/chromium/ui/views/style/platform_style_mac.mm b/chromium/ui/views/style/platform_style_mac.mm
new file mode 100644
index 00000000000..cbe9be51ce1
--- /dev/null
+++ b/chromium/ui/views/style/platform_style_mac.mm
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/style/platform_style.h"
+
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icons.h"
+#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/label_button_border.h"
+#include "ui/views/controls/focusable_rounded_border_mac.h"
+#import "ui/views/controls/scrollbar/cocoa_scroll_bar.h"
+#include "ui/views/style/mac/combobox_background_mac.h"
+#include "ui/views/style/mac/dialog_button_border_mac.h"
+
+namespace views {
+
+// static
+gfx::ImageSkia PlatformStyle::CreateComboboxArrow(bool is_enabled,
+ Combobox::Style style) {
+ // TODO(ellyjones): IDR_MENU_DROPARROW is a cross-platform image that doesn't
+ // look right on Mac. See https://crbug.com/384071.
+ if (style == Combobox::STYLE_ACTION) {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ return *rb.GetImageSkiaNamed(IDR_MENU_DROPARROW);
+ }
+ const int kComboboxArrowWidth = 13;
+ return gfx::CreateVectorIcon(gfx::VectorIconId::COMBOBOX_ARROW_MAC,
+ kComboboxArrowWidth,
+ is_enabled ? SK_ColorWHITE : SK_ColorBLACK);
+}
+
+// static
+scoped_ptr<FocusableBorder> PlatformStyle::CreateComboboxBorder() {
+ return make_scoped_ptr(new FocusableRoundedBorder);
+}
+
+// static
+scoped_ptr<Background> PlatformStyle::CreateComboboxBackground() {
+ return make_scoped_ptr(new ComboboxBackgroundMac);
+}
+
+// static
+scoped_ptr<LabelButtonBorder> PlatformStyle::CreateLabelButtonBorder(
+ Button::ButtonStyle style) {
+ if (style == Button::STYLE_BUTTON)
+ return make_scoped_ptr(new DialogButtonBorderMac());
+
+ return make_scoped_ptr(new LabelButtonAssetBorder(style));
+}
+
+// static
+scoped_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
+ return make_scoped_ptr(new CocoaScrollBar(is_horizontal));
+}
+
+} // namespace views
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 06ab5f4434b..3bdbbd5f6c5 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -553,13 +553,15 @@ TEST_F(TouchSelectionControllerImplTest,
textfield_->OnGestureEvent(&tap);
// Select some text such that one handle is hidden.
- textfield_->SelectRange(gfx::Range(10, textfield_text.length()));
+ textfield_->SelectRange(
+ gfx::Range(10u, static_cast<uint32_t>(textfield_text.length())));
// Check that one selection handle is hidden.
EXPECT_FALSE(IsSelectionHandle1Visible());
EXPECT_TRUE(IsSelectionHandle2Visible());
- EXPECT_EQ(gfx::Range(10, textfield_text.length()),
- textfield_->GetSelectedRange());
+ EXPECT_EQ(
+ gfx::Range(10u, static_cast<uint32_t>(textfield_text.length())),
+ textfield_->GetSelectedRange());
// Drag the visible handle around and make sure the selection end point of the
// invisible handle does not change.
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index 62ab2b1ba7a..d733034153b 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -106,7 +106,6 @@ View::View()
enabled_(true),
notify_enter_exit_on_child_(false),
registered_for_visible_bounds_notification_(false),
- clip_insets_(0, 0, 0, 0),
needs_layout_(true),
snap_layer_to_pixel_boundary_(false),
flip_canvas_on_paint_for_rtl_ui_(false),
@@ -178,11 +177,25 @@ void View::AddChildViewAt(View* view, int index) {
// Sets the prev/next focus views.
InitFocusSiblings(view, index);
- // Let's insert the view.
view->parent_ = this;
children_.insert(children_.begin() + index, view);
- views::Widget* widget = GetWidget();
+ // Ensure the layer tree matches the view tree before calling to any client
+ // code. This way if client code further modifies the view tree we are in a
+ // sane state.
+ const bool did_reparent_any_layers = view->UpdateParentLayers();
+ Widget* widget = GetWidget();
+ if (did_reparent_any_layers && widget)
+ widget->UpdateRootLayers();
+
+ 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
+ // rooted at |this| should be hidden. Otherwise, all the child layers should
+ // inherit the visibility of the owner View.
+ view->UpdateLayerVisibility();
+
if (widget) {
const ui::NativeTheme* new_theme = view->GetNativeTheme();
if (new_theme != old_theme)
@@ -195,23 +208,18 @@ void View::AddChildViewAt(View* view, int index) {
v->ViewHierarchyChangedImpl(false, details);
view->PropagateAddNotifications(details);
+
UpdateTooltip();
+
if (widget) {
RegisterChildrenForVisibleBoundsNotification(view);
+
if (view->visible())
view->SchedulePaint();
}
if (layout_manager_.get())
layout_manager_->ViewAdded(this, view);
-
- 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
- // rooted at |this| should be hidden. Otherwise, all the child layers should
- // inherit the visibility of the owner View.
- UpdateLayerVisibility();
}
void View::ReorderChildView(View* view, int index) {
@@ -319,10 +327,6 @@ gfx::Rect View::GetLocalBounds() const {
return gfx::Rect(size());
}
-gfx::Rect View::GetLayerBoundsInPixel() const {
- return layer()->GetTargetBounds();
-}
-
gfx::Insets View::GetInsets() const {
return border_.get() ? border_->GetInsets() : gfx::Insets();
}
@@ -409,8 +413,10 @@ void View::SetVisible(bool visible) {
AdvanceFocusIfNecessary();
// Notify the parent.
- if (parent_)
+ if (parent_) {
parent_->ChildVisibilityChanged(this);
+ parent_->NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, false);
+ }
// This notifies all sub-views recursively.
PropagateVisibilityNotifications(this, visible_);
@@ -710,7 +716,7 @@ void View::ConvertPointFromScreen(const View* dst, gfx::Point* p) {
if (!widget)
return;
*p -= widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
- views::View::ConvertPointFromWidget(dst, p);
+ ConvertPointFromWidget(dst, p);
}
gfx::Rect View::ConvertRectToParent(const gfx::Rect& rect) const {
@@ -798,16 +804,17 @@ void View::Paint(const ui::PaintContext& parent_context) {
// std::optional once we can do so.
ui::ClipRecorder clip_recorder(parent_context);
if (paint_relative_to_parent) {
- // Set the clip rect to the bounds of this View. Note that the X (or left)
- // position we pass to ClipRect takes into consideration whether or not the
- // View uses a right-to-left layout so that we paint the View in its
- // mirrored position if need be.
- gfx::Rect clip_rect_in_parent = bounds();
- clip_rect_in_parent.Inset(clip_insets_);
- if (parent_)
- clip_rect_in_parent.set_x(
- parent_->GetMirroredXForRect(clip_rect_in_parent));
- clip_recorder.ClipRect(clip_rect_in_parent);
+ // Set the clip rect to the bounds of this View, or |clip_path_| if it's
+ // been set. Note that the X (or left) position we pass to ClipRect takes
+ // into consideration whether or not the View uses a right-to-left layout so
+ // that we paint the View in its mirrored position if need be.
+ if (clip_path_.isEmpty()) {
+ clip_recorder.ClipRect(GetMirroredBounds());
+ } else {
+ gfx::Path clip_path_in_parent = clip_path_;
+ clip_path_in_parent.offset(GetMirroredX(), y());
+ clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent);
+ }
}
ui::TransformRecorder transform_recorder(context);
@@ -946,8 +953,7 @@ bool View::IsMouseHovered() const {
if (!GetWidget()->IsMouseEventsEnabled())
return false;
- gfx::Point cursor_pos(gfx::Screen::GetScreenFor(
- GetWidget()->GetNativeView())->GetCursorScreenPoint());
+ gfx::Point cursor_pos(gfx::Screen::GetScreen()->GetCursorScreenPoint());
ConvertPointFromScreen(this, &cursor_pos);
return HitTestPoint(cursor_pos);
}
@@ -1025,7 +1031,7 @@ void View::OnMouseEvent(ui::MouseEvent* event) {
return;
case ui::ET_MOUSEWHEEL:
- if (OnMouseWheel(*static_cast<ui::MouseWheelEvent*>(event)))
+ if (OnMouseWheel(*event->AsMouseWheelEvent()))
event->SetHandled();
break;
@@ -1436,12 +1442,6 @@ void View::OnPaintBorder(gfx::Canvas* canvas) {
// Accelerated Painting --------------------------------------------------------
-void View::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) {
- // This method should not have the side-effect of creating the layer.
- if (layer())
- layer()->SetFillsBoundsOpaquely(fills_bounds_opaquely);
-}
-
gfx::Vector2d View::CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) {
if (layer()) {
@@ -1805,39 +1805,47 @@ void View::DoRemoveChildView(View* view,
DCHECK(view);
const Views::iterator i(std::find(children_.begin(), children_.end(), view));
+ if (i == children_.end())
+ return;
+
scoped_ptr<View> view_to_be_deleted;
- if (i != children_.end()) {
- if (update_focus_cycle) {
- // Let's remove the view from the focus traversal.
- View* next_focusable = view->next_focusable_view_;
- View* prev_focusable = view->previous_focusable_view_;
- if (prev_focusable)
- prev_focusable->next_focusable_view_ = next_focusable;
- if (next_focusable)
- next_focusable->previous_focusable_view_ = prev_focusable;
- }
+ if (update_focus_cycle) {
+ View* next_focusable = view->next_focusable_view_;
+ View* prev_focusable = view->previous_focusable_view_;
+ if (prev_focusable)
+ prev_focusable->next_focusable_view_ = next_focusable;
+ if (next_focusable)
+ next_focusable->previous_focusable_view_ = prev_focusable;
+ }
- if (GetWidget()) {
- UnregisterChildrenForVisibleBoundsNotification(view);
- if (view->visible())
- view->SchedulePaint();
- GetWidget()->NotifyWillRemoveView(view);
- }
+ Widget* widget = GetWidget();
+ if (widget) {
+ UnregisterChildrenForVisibleBoundsNotification(view);
+ if (view->visible())
+ view->SchedulePaint();
- view->PropagateRemoveNotifications(this, new_parent);
- view->parent_ = NULL;
- view->UpdateLayerVisibility();
+ if (!new_parent || new_parent->GetWidget() != widget)
+ widget->NotifyWillRemoveView(view);
+ }
- if (delete_removed_view && !view->owned_by_client_)
- view_to_be_deleted.reset(view);
+ // Make sure the layers belonging to the subtree rooted at |view| get
+ // removed.
+ view->OrphanLayers();
+ if (widget)
+ widget->UpdateRootLayers();
- children_.erase(i);
- }
+ view->PropagateRemoveNotifications(this, new_parent);
+ view->parent_ = nullptr;
+
+ if (delete_removed_view && !view->owned_by_client_)
+ view_to_be_deleted.reset(view);
+
+ children_.erase(i);
if (update_tool_tip)
UpdateTooltip();
- if (layout_manager_.get())
+ if (layout_manager_)
layout_manager_->ViewRemoved(this, view);
}
@@ -1878,20 +1886,6 @@ void View::ViewHierarchyChangedImpl(
}
}
- if (details.is_add && layer() && !layer()->parent()) {
- UpdateParentLayer();
- Widget* widget = GetWidget();
- if (widget)
- widget->UpdateRootLayers();
- } else if (!details.is_add && details.child == this) {
- // Make sure the layers belonging to the subtree rooted at |child| get
- // removed from layers that do not belong in the same subtree.
- OrphanLayers();
- Widget* widget = GetWidget();
- if (widget)
- widget->UpdateRootLayers();
- }
-
ViewHierarchyChanged(details);
details.parent->needs_layout_ = true;
}
@@ -2116,14 +2110,23 @@ void View::CreateLayer() {
SchedulePaintOnParent();
}
-void View::UpdateParentLayers() {
+bool View::UpdateParentLayers() {
// Attach all top-level un-parented layers.
- if (layer() && !layer()->parent()) {
- UpdateParentLayer();
- } else {
- for (int i = 0, count = child_count(); i < count; ++i)
- child_at(i)->UpdateParentLayers();
+ if (layer()) {
+ if (!layer()->parent()) {
+ UpdateParentLayer();
+ return true;
+ }
+ // The layers of any child views are already in place, so we can stop
+ // iterating here.
+ return false;
}
+ bool result = false;
+ for (int i = 0, count = child_count(); i < count; ++i) {
+ if (child_at(i)->UpdateParentLayers())
+ result = true;
+ }
+ return result;
}
void View::OrphanLayers() {
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index a5ef00dae1d..a85ef3dfa00 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -31,9 +31,11 @@
#include "ui/events/event.h"
#include "ui/events/event_target.h"
#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/path.h"
#include "ui/views/view_targeter.h"
#include "ui/views/views_export.h"
@@ -232,9 +234,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// 0, 0).
gfx::Rect GetLocalBounds() const;
- // Returns the bounds of the layer in its own pixel coordinates.
- gfx::Rect GetLayerBoundsInPixel() const;
-
// Returns the insets of the current border. If there is no border an empty
// insets is returned.
virtual gfx::Insets GetInsets() const;
@@ -294,21 +293,14 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Returns whether the view is enabled.
bool enabled() const { return enabled_; }
- // This indicates that the view completely fills its bounds in an opaque
- // color. This doesn't affect compositing but is a hint to the compositor to
- // optimize painting.
- // Note that this method does not implicitly create a layer if one does not
- // already exist for the View, but is a no-op in that case.
- void SetFillsBoundsOpaquely(bool fills_bounds_opaquely);
-
// Transformations -----------------------------------------------------------
// Methods for setting transformations for a view (e.g. rotation, scaling).
gfx::Transform GetTransform() const;
- // Clipping parameters. Clipping is done relative to the view bounds.
- void set_clip_insets(gfx::Insets clip_insets) { clip_insets_ = clip_insets; }
+ // Clipping is done relative to the view's local bounds.
+ void set_clip_path(const gfx::Path& path) { clip_path_ = path; }
// Sets the transform to the supplied transform.
void SetTransform(const gfx::Transform& transform);
@@ -497,7 +489,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// transformations are applied to it to convert it into the parent coordinate
// system before propagating SchedulePaint up the view hierarchy.
// TODO(beng): Make protected.
- virtual void SchedulePaint();
+ void SchedulePaint();
virtual void SchedulePaintInRect(const gfx::Rect& r);
// Called by the framework to paint a View. Performs translation and clipping
@@ -1347,9 +1339,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Creates the layer and related fields for this view.
void CreateLayer();
- // Parents all un-parented layers within this view's hierarchy to this view's
- // layer.
- void UpdateParentLayers();
+ // Recursively calls UpdateParentLayers() on all descendants, stopping at any
+ // Views that have layers. Calls UpdateParentLayer() for any Views that have
+ // a layer with no parent. If at least one descendant had an unparented layer
+ // true is returned.
+ bool UpdateParentLayers();
// Parents this view's layer to |parent_layer|, and sets its bounds and other
// properties in accordance to |offset|, the view's offset from the
@@ -1492,9 +1486,9 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Transformations -----------------------------------------------------------
- // Clipping parameters. skia transformation matrix does not give us clipping.
- // So we do it ourselves.
- gfx::Insets clip_insets_;
+ // Painting will be clipped to this path. TODO(estade): this doesn't work for
+ // layers.
+ gfx::Path clip_path_;
// Layout --------------------------------------------------------------------
diff --git a/chromium/ui/views/view_targeter.cc b/chromium/ui/views/view_targeter.cc
index 5e52ce9c2d6..641e28672b4 100644
--- a/chromium/ui/views/view_targeter.cc
+++ b/chromium/ui/views/view_targeter.cc
@@ -32,12 +32,10 @@ ui::EventTarget* ViewTargeter::FindTargetForEvent(ui::EventTarget* root,
View* view = static_cast<View*>(root);
if (event->IsKeyEvent())
- return FindTargetForKeyEvent(view, *static_cast<ui::KeyEvent*>(event));
+ return FindTargetForKeyEvent(view, *event->AsKeyEvent());
- if (event->IsScrollEvent()) {
- return FindTargetForScrollEvent(view,
- *static_cast<ui::ScrollEvent*>(event));
- }
+ if (event->IsScrollEvent())
+ return FindTargetForScrollEvent(view, *event->AsScrollEvent());
if (event->IsGestureEvent()) {
ui::GestureEvent* gesture = event->AsGestureEvent();
diff --git a/chromium/ui/views/view_targeter_delegate.h b/chromium/ui/views/view_targeter_delegate.h
index 0ad461abac4..44dd839a481 100644
--- a/chromium/ui/views/view_targeter_delegate.h
+++ b/chromium/ui/views/view_targeter_delegate.h
@@ -16,7 +16,8 @@ namespace views {
class View;
// Defines the default behaviour for hit-testing and event-targeting against a
-// View using a rectangular region representing an event's location. Views
+// View using a rectangular region representing an event's location (i.e., the
+// bounding box of a gesture or a 1x1 rect in the case of a mouse event). Views
// wishing to define custom hit-testing or event-targeting behaviour do so by
// extending ViewTargeterDelegate and then installing a ViewTargeter on
// themselves.
@@ -25,9 +26,12 @@ class VIEWS_EXPORT ViewTargeterDelegate {
ViewTargeterDelegate() {}
virtual ~ViewTargeterDelegate() {}
- // Returns true if the bounds of |target| intersects |rect|, where |rect|
- // is in the local coodinate space of |target|. Overrides of this method by
- // a View subclass should enforce DCHECK_EQ(this, target).
+ // Returns true if |target| should be considered as a candidate target for
+ // an event having |rect| as its location, where |rect| is in the local
+ // coordinate space of |target|. Overrides of this method by a View subclass
+ // should enforce DCHECK_EQ(this, target).
+ // TODO(tdanderson): Consider changing the name of this method to better
+ // reflect its purpose.
virtual bool DoesIntersectRect(const View* target,
const gfx::Rect& rect) const;
diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc
index a852c77d4ff..4b50b319ad2 100644
--- a/chromium/ui/views/view_unittest.cc
+++ b/chromium/ui/views/view_unittest.cc
@@ -31,6 +31,7 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/path.h"
#include "ui/gfx/transform.h"
+#include "ui/native_theme/native_theme.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -2114,7 +2115,7 @@ TEST_F(ViewTest, HandleAccelerator) {
// Create a window and add the view as its child.
scoped_ptr<Widget> widget(new Widget);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = gfx::Rect(0, 0, 100, 100);
widget->Init(params);
View* root = widget->GetRootView();
@@ -2131,6 +2132,10 @@ TEST_F(ViewTest, HandleAccelerator) {
EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]);
#endif
+ // TYPE_POPUP widgets default to non-activatable, so the Show() above wouldn't
+ // have activated the Widget. First, allow activation.
+ widget->widget_delegate()->set_can_activate(true);
+
// When a non-child view is active, it should handle accelerators.
view->accelerator_count_map_[return_accelerator] = 0;
widget->Activate();
@@ -3505,12 +3510,8 @@ TEST_F(ViewTest, GetViewByID) {
View::Views views;
v1.GetViewsInGroup(kGroup, &views);
EXPECT_EQ(2U, views.size());
-
- View::Views::const_iterator i(std::find(views.begin(), views.end(), &v3));
- EXPECT_NE(views.end(), i);
-
- i = std::find(views.begin(), views.end(), &v4);
- EXPECT_NE(views.end(), i);
+ EXPECT_NE(views.cend(), std::find(views.cbegin(), views.cend(), &v3));
+ EXPECT_NE(views.cend(), std::find(views.cbegin(), views.cend(), &v4));
}
TEST_F(ViewTest, AddExistingChild) {
@@ -4477,4 +4478,96 @@ TEST_F(ViewTest, ScopedTargetHandlerReceivesEvents) {
EXPECT_EQ(ui::ET_MOUSE_RELEASED, v->last_mouse_event_type_);
}
+// See comment above test for details.
+class WidgetWithCustomTheme : public Widget {
+ public:
+ explicit WidgetWithCustomTheme(ui::NativeTheme* theme) : theme_(theme) {}
+ ~WidgetWithCustomTheme() override {}
+
+ // Widget:
+ const ui::NativeTheme* GetNativeTheme() const override { return theme_; }
+
+ private:
+ ui::NativeTheme* theme_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetWithCustomTheme);
+};
+
+// See comment above test for details.
+class ViewThatAddsViewInOnNativeThemeChanged : public View {
+ public:
+ ViewThatAddsViewInOnNativeThemeChanged() { SetPaintToLayer(true); }
+ ~ViewThatAddsViewInOnNativeThemeChanged() override {}
+
+ bool on_native_theme_changed_called() const {
+ return on_native_theme_changed_called_;
+ }
+
+ // View:
+ void OnNativeThemeChanged(const ui::NativeTheme* theme) override {
+ on_native_theme_changed_called_ = true;
+ GetWidget()->GetRootView()->AddChildView(new View);
+ }
+
+ private:
+ bool on_native_theme_changed_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewThatAddsViewInOnNativeThemeChanged);
+};
+
+// See comment above test for details.
+class TestNativeTheme : public ui::NativeTheme {
+ public:
+ TestNativeTheme() {}
+ ~TestNativeTheme() override {}
+
+ // ui::NativeTheme:
+ SkColor GetSystemColor(ColorId color_id) const override {
+ return SK_ColorRED;
+ }
+ gfx::Size GetPartSize(Part part,
+ State state,
+ const ExtraParams& extra) const override {
+ return gfx::Size();
+ }
+ void Paint(SkCanvas* canvas,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ExtraParams& extra) const override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestNativeTheme);
+};
+
+// Creates and adds a new child view to |parent| that has a layer.
+void AddViewWithChildLayer(View* parent) {
+ View* child = new View;
+ child->SetPaintToLayer(true);
+ parent->AddChildView(child);
+}
+
+// This test does the following:
+// . creates a couple of views with layers added to the root.
+// . Add a view that overrides OnNativeThemeChanged(). In
+// OnNativeThemeChanged() another view is added.
+// This sequence triggered DCHECKs or crashes previously. This tests verifies
+// that doesn't happen. Reason for crash was OnNativeThemeChanged() was called
+// before the layer hierarchy was updated. OnNativeThemeChanged() should be
+// called after the layer hierarchy matches the view hierarchy.
+TEST_F(ViewTest, CrashOnAddFromFromOnNativeThemeChanged) {
+ TestNativeTheme theme;
+ WidgetWithCustomTheme widget(&theme);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(50, 50, 350, 350);
+ widget.Init(params);
+
+ AddViewWithChildLayer(widget.GetRootView());
+ ViewThatAddsViewInOnNativeThemeChanged* v =
+ new ViewThatAddsViewInOnNativeThemeChanged;
+ widget.GetRootView()->AddChildView(v);
+ EXPECT_TRUE(v->on_native_theme_changed_called());
+}
+
} // namespace views
diff --git a/chromium/ui/views/views.gyp b/chromium/ui/views/views.gyp
index 1530505225a..6f2243320b9 100644
--- a/chromium/ui/views/views.gyp
+++ b/chromium/ui/views/views.gyp
@@ -23,16 +23,26 @@
'animation/ink_drop_animation_controller_factory.h',
'animation/ink_drop_animation_controller_impl.cc',
'animation/ink_drop_animation_controller_impl.h',
- 'animation/ink_drop_animation_observer.cc',
+ 'animation/ink_drop_animation_ended_reason.cc',
+ 'animation/ink_drop_animation_ended_reason.h',
'animation/ink_drop_animation_observer.h',
'animation/ink_drop_delegate.h',
'animation/ink_drop_host.h',
+ 'animation/ink_drop_host_view.cc',
+ 'animation/ink_drop_host_view.h',
+ 'animation/ink_drop_hover.cc',
+ 'animation/ink_drop_hover.h',
+ 'animation/ink_drop_hover_observer.h',
'animation/ink_drop_painted_layer_delegates.cc',
'animation/ink_drop_painted_layer_delegates.h',
'animation/ink_drop_state.cc',
'animation/ink_drop_state.h',
'animation/scroll_animator.cc',
'animation/scroll_animator.h',
+ 'animation/flood_fill_ink_drop_animation.cc',
+ 'animation/flood_fill_ink_drop_animation.h',
+ 'animation/square_ink_drop_animation.cc',
+ 'animation/square_ink_drop_animation.h',
'background.cc',
'background.h',
'border.cc',
@@ -41,6 +51,8 @@
'bubble/bubble_border.h',
'bubble/bubble_delegate.cc',
'bubble/bubble_delegate.h',
+ 'bubble/bubble_dialog_delegate.cc',
+ 'bubble/bubble_dialog_delegate.h',
'bubble/bubble_frame_view.cc',
'bubble/bubble_frame_view.h',
'button_drag_utils.cc',
@@ -59,6 +71,8 @@
'cocoa/tooltip_manager_mac.mm',
'cocoa/views_nswindow_delegate.h',
'cocoa/views_nswindow_delegate.mm',
+ 'cocoa/views_scrollbar_bridge.h',
+ 'cocoa/views_scrollbar_bridge.mm',
'cocoa/widget_owner_nswindow_adapter.h',
'cocoa/widget_owner_nswindow_adapter.mm',
'color_chooser/color_chooser_listener.h',
@@ -91,6 +105,8 @@
'controls/combobox/combobox_listener.h',
'controls/focusable_border.cc',
'controls/focusable_border.h',
+ 'controls/focusable_rounded_border_mac.cc',
+ 'controls/focusable_rounded_border_mac.h',
'controls/glow_hover_controller.cc',
'controls/glow_hover_controller.h',
'controls/image_view.cc',
@@ -126,8 +142,6 @@
'controls/menu/menu_message_loop.h',
'controls/menu/menu_message_loop_mac.cc',
'controls/menu/menu_message_loop_mac.h',
- 'controls/menu/menu_message_pump_dispatcher_win.cc',
- 'controls/menu/menu_message_pump_dispatcher_win.h',
'controls/menu/menu_model_adapter.cc',
'controls/menu/menu_model_adapter.h',
'controls/menu/menu_runner.cc',
@@ -172,6 +186,8 @@
'controls/scrollbar/base_scroll_bar_button.h',
'controls/scrollbar/base_scroll_bar_thumb.cc',
'controls/scrollbar/base_scroll_bar_thumb.h',
+ 'controls/scrollbar/cocoa_scroll_bar.h',
+ 'controls/scrollbar/cocoa_scroll_bar.mm',
'controls/scrollbar/native_scroll_bar.cc',
'controls/scrollbar/native_scroll_bar.h',
'controls/scrollbar/native_scroll_bar_views.cc',
@@ -276,11 +292,13 @@
'round_rect_painter.h',
'shadow_border.cc',
'shadow_border.h',
+ 'style/mac/combobox_background_mac.cc',
+ 'style/mac/combobox_background_mac.h',
'style/mac/dialog_button_border_mac.cc',
'style/mac/dialog_button_border_mac.h',
'style/platform_style.cc',
'style/platform_style.h',
- 'style/platform_style_mac.cc',
+ 'style/platform_style_mac.mm',
'view.cc',
'view.h',
'view_constants.cc',
@@ -374,8 +392,6 @@
'bubble/tray_bubble_view.cc',
'bubble/tray_bubble_view.h',
'controls/menu/display_change_listener_aura.cc',
- 'controls/menu/menu_event_dispatcher.cc',
- 'controls/menu/menu_event_dispatcher.h',
'controls/menu/menu_key_event_handler.cc',
'controls/menu/menu_key_event_handler.h',
'controls/menu/menu_message_loop_aura.cc',
@@ -410,19 +426,10 @@
'widget/window_reorderer.cc',
'widget/window_reorderer.h',
],
- 'views_android_sources': [
- 'controls/menu/menu_config_android.cc',
- 'widget/android/android_focus_rules.cc',
- 'widget/android/android_focus_rules.h',
- 'widget/android/native_widget_android.cc',
- 'widget/android/native_widget_android.h',
- ],
'views_desktop_aura_sources': [
'widget/desktop_aura/desktop_capture_client.cc',
'widget/desktop_aura/desktop_capture_client.h',
'widget/desktop_aura/desktop_cursor_loader_updater.h',
- 'widget/desktop_aura/desktop_dispatcher_client.cc',
- 'widget/desktop_aura/desktop_dispatcher_client.h',
'widget/desktop_aura/desktop_drop_target_win.cc',
'widget/desktop_aura/desktop_drop_target_win.h',
'widget/desktop_aura/desktop_event_client.cc',
@@ -483,10 +490,25 @@
'widget/desktop_aura/desktop_window_tree_host_ozone.cc',
],
'views_test_support_sources': [
+ 'animation/test/flood_fill_ink_drop_animation_test_api.cc',
+ 'animation/test/flood_fill_ink_drop_animation_test_api.h',
'animation/test/ink_drop_animation_test_api.cc',
'animation/test/ink_drop_animation_test_api.h',
+ 'animation/test/ink_drop_animation_controller_impl_test_api.cc',
+ 'animation/test/ink_drop_animation_controller_impl_test_api.h',
+ 'animation/test/ink_drop_hover_test_api.cc',
+ 'animation/test/ink_drop_hover_test_api.h',
+ 'animation/test/square_ink_drop_animation_test_api.cc',
+ 'animation/test/square_ink_drop_animation_test_api.h',
+ 'animation/test/test_ink_drop_animation_observer.cc',
+ 'animation/test/test_ink_drop_animation_observer.h',
+ 'animation/test/test_ink_drop_animation_observer_helper.h',
'animation/test/test_ink_drop_host.cc',
'animation/test/test_ink_drop_host.h',
+ 'animation/test/test_ink_drop_hover_observer.cc',
+ 'animation/test/test_ink_drop_hover_observer.h',
+ 'animation/test/test_ink_drop_delegate.cc',
+ 'animation/test/test_ink_drop_delegate.h',
'controls/textfield/textfield_test_api.cc',
'controls/textfield/textfield_test_api.h',
'test/capture_tracking_view.cc',
@@ -501,6 +523,8 @@
'test/focus_manager_test.h',
'test/menu_runner_test_api.cc',
'test/menu_runner_test_api.h',
+ 'test/native_widget_factory.cc',
+ 'test/native_widget_factory.h',
'test/scoped_views_test_helper.cc',
'test/scoped_views_test_helper.h',
'test/slider_test_api.cc',
@@ -544,9 +568,13 @@
'accessible_pane_view_unittest.cc',
'animation/bounds_animator_unittest.cc',
'animation/ink_drop_animation_controller_factory_unittest.cc',
+ 'animation/ink_drop_animation_controller_impl_unittest.cc',
'animation/ink_drop_animation_unittest.cc',
+ 'animation/ink_drop_hover_unittest.cc',
+ 'animation/square_ink_drop_animation_unittest.cc',
'bubble/bubble_border_unittest.cc',
'bubble/bubble_delegate_unittest.cc',
+ 'bubble/bubble_dialog_delegate_unittest.cc',
'bubble/bubble_frame_view_unittest.cc',
'bubble/bubble_window_targeter_unittest.cc',
'cocoa/bridged_native_widget_unittest.mm',
@@ -589,6 +617,8 @@
'layout/grid_layout_unittest.cc',
'rect_based_targeting_utils_unittest.cc',
'run_all_unittests.cc',
+ 'run_all_unittests.h',
+ 'run_all_unittests_main.cc',
'style/mac/dialog_button_border_mac_unittest.cc',
'view_model_unittest.cc',
'view_model_utils_unittest.cc',
@@ -607,6 +637,7 @@
'widget/desktop_widget_unittest.cc',
],
'views_unittests_aura_sources': [
+ 'accessibility/ax_aura_obj_cache_unittest.cc',
'controls/native/native_view_host_aura_unittest.cc',
'corewm/tooltip_controller_unittest.cc',
'touchui/touch_selection_controller_impl_unittest.cc',
@@ -642,6 +673,7 @@
'../base/ime/ui_base_ime.gyp:ui_base_ime',
'../base/ui_base.gyp:ui_base',
'../compositor/compositor.gyp:compositor',
+ '../display/display.gyp:display',
'../events/events.gyp:events',
'../events/events.gyp:events_base',
'../events/platform/events_platform.gyp:events_platform',
@@ -669,7 +701,7 @@
'<@(views_sources)',
],
'conditions': [
- ['use_ash==0', {
+ ['use_aura==0', {
'sources!': [
'bubble/tray_bubble_view.cc',
'bubble/tray_bubble_view.h',
@@ -715,6 +747,7 @@
'libraries': [
'-limm32.lib',
'-loleacc.lib',
+ '-lwtsapi32.lib',
],
'msvs_settings': {
'VCLinkerTool': {
@@ -795,6 +828,7 @@
'../../testing/gtest.gyp:gtest',
'../base/ime/ui_base_ime.gyp:ui_base_ime',
'../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',
@@ -810,10 +844,10 @@
],
'sources': [
'<@(views_test_support_sources)',
- # These two sources are not listed in views_test_support_sources as
- # they are not used by the gn target that pulls in
- # views_test_support_sources.
+ # These are not listed in views_test_support_sources as they are not
+ # used by the gn target that pulls in views_test_support_sources.
'test/default_platform_test_helper.cc',
+ 'test/native_widget_factory_desktop.cc',
'test/platform_test_helper.h',
],
'conditions': [
@@ -853,6 +887,7 @@
'../events/events.gyp:events_test_support',
'../gfx/gfx.gyp:gfx',
'../gfx/gfx.gyp:gfx_geometry',
+ '../native_theme/native_theme.gyp:native_theme',
'../resources/ui_resources.gyp:ui_resources',
'../resources/ui_resources.gyp:ui_test_pak',
'../strings/ui_strings.gyp:ui_strings',
@@ -889,17 +924,6 @@
},
},
}],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ['OS=="linux" and use_allocator!="none"', {
- # See http://crbug.com/162998#c4 for why this is needed.
- 'dependencies': [
- '../../base/allocator/allocator.gyp:allocator',
- ],
- }],
['use_x11==1', {
'dependencies': [
'../../build/linux/system.gyp:x11',
@@ -948,6 +972,32 @@
}, # target_name: views_unittests
], # targets
'conditions': [
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
+ {
+ 'target_name': 'views_unittests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'views_unittests',
+ ],
+ 'includes': [
+ '../../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'views_unittests.isolate',
+ ],
+ 'conditions': [
+ ['use_x11==1',
+ {
+ 'dependencies': [
+ '../../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+ ],
+ }
+ ],
+ ],
+ },
+ ],
+ }],
['OS=="mac"', {
'targets': [
{
@@ -970,6 +1020,8 @@
'sources': [
'cocoa/bridged_native_widget_interactive_uitest.mm',
'run_all_unittests.cc',
+ 'run_all_unittests.h',
+ 'run_all_unittests_main.cc',
'widget/native_widget_mac_interactive_uitest.mm',
],
'conditions': [
diff --git a/chromium/ui/views/views_unittests.isolate b/chromium/ui/views/views_unittests.isolate
new file mode 100644
index 00000000000..d58415f3942
--- /dev/null
+++ b/chromium/ui/views/views_unittests.isolate
@@ -0,0 +1,70 @@
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'conditions': [
+ ['use_x11==0', {
+ 'variables': {
+ 'command': [
+ '../../testing/test_env.py',
+ '<(PRODUCT_DIR)/views_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ },
+ }],
+ ['use_x11==1', {
+ 'variables': {
+ 'command': [
+ '../../testing/xvfb.py',
+ '<(PRODUCT_DIR)',
+ '<(PRODUCT_DIR)/views_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--msan=<(msan)',
+ '--tsan=<(tsan)',
+ ],
+ 'files': [
+ '../../testing/xvfb.py',
+ '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
+ '../../testing/test_env.py',
+ '<(PRODUCT_DIR)/ui_test.pak',
+ ],
+ },
+ }],
+ ['OS=="linux"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/libosmesa.so',
+ ],
+ },
+ }],
+ ['OS=="mac"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/osmesa.so',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/osmesa.dll',
+ ],
+ },
+ }],
+ ],
+ 'includes': [
+ '../../base/base.isolate',
+ ],
+}
diff --git a/chromium/ui/views/widget/android/android_focus_rules.cc b/chromium/ui/views/widget/android/android_focus_rules.cc
deleted file mode 100644
index c01ace9ca58..00000000000
--- a/chromium/ui/views/widget/android/android_focus_rules.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/android/android_focus_rules.h"
-
-#include "ui/aura/window.h"
-
-namespace views {
-
-AndroidFocusRules::AndroidFocusRules() {}
-
-AndroidFocusRules::~AndroidFocusRules() {}
-
-bool AndroidFocusRules::SupportsChildActivation(aura::Window* window) const {
- return window->IsRootWindow();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/android/android_focus_rules.h b/chromium/ui/views/widget/android/android_focus_rules.h
deleted file mode 100644
index 867d53d4812..00000000000
--- a/chromium/ui/views/widget/android/android_focus_rules.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_
-#define UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_
-
-#include "base/macros.h"
-#include "ui/wm/core/base_focus_rules.h"
-
-namespace views {
-
-// A set of focus rules for Android using aura.
-class AndroidFocusRules : public wm::BaseFocusRules {
- public:
- AndroidFocusRules();
- ~AndroidFocusRules() override;
-
- private:
- // wm::BaseFocusRules:
- bool SupportsChildActivation(aura::Window* window) const override;
-
- DISALLOW_COPY_AND_ASSIGN(AndroidFocusRules);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_ANDROID_ANDROID_FOCUS_RULES_H_
diff --git a/chromium/ui/views/widget/android/native_widget_android.cc b/chromium/ui/views/widget/android/native_widget_android.cc
deleted file mode 100644
index 2aed158559a..00000000000
--- a/chromium/ui/views/widget/android/native_widget_android.cc
+++ /dev/null
@@ -1,841 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/widget/android/native_widget_android.h"
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/string_util.h"
-#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/default_capture_client.h"
-#include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_tree_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/dragdrop/os_exchange_data.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_list.h"
-#include "ui/gfx/screen.h"
-#include "ui/native_theme/native_theme_aura.h"
-#include "ui/views/drag_utils.h"
-#include "ui/views/views_delegate.h"
-#include "ui/views/widget/android/android_focus_rules.h"
-#include "ui/views/widget/native_widget_aura.h"
-#include "ui/views/widget/native_widget_delegate.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/tooltip_manager_aura.h"
-#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/default_activation_client.h"
-#include "ui/wm/core/default_screen_position_client.h"
-#include "ui/wm/core/focus_controller.h"
-#include "ui/wm/core/shadow_types.h"
-#include "ui/wm/core/window_animations.h"
-#include "ui/wm/core/window_util.h"
-#include "ui/wm/public/activation_client.h"
-#include "ui/wm/public/dispatcher_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"
-
-// TODO(bshe): Most of the code is copied from NativeWidgetAura or
-// DesktopNativeWidgetAura. Share more code instead of duplicate code when
-// possible. crbug.com/554961.
-namespace {
-
-class WindowTreeClientImpl : public aura::client::WindowTreeClient {
- public:
- explicit WindowTreeClientImpl(aura::Window* root_window)
- : root_window_(root_window) {
- aura::client::SetWindowTreeClient(root_window_, this);
- }
- ~WindowTreeClientImpl() override {
- aura::client::SetWindowTreeClient(root_window_, nullptr);
- }
-
- // Overridden from client::WindowTreeClient:
- aura::Window* GetDefaultParent(aura::Window* context,
- aura::Window* window,
- const gfx::Rect& bounds) override {
- return root_window_;
- }
-
- private:
- aura::Window* root_window_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowTreeClientImpl);
-};
-
-// TODO(bshe|jonross): Get rid of nested message loop once crbug.com/523680 is
-// fixed.
-class AndroidDispatcherClient : public aura::client::DispatcherClient {
- public:
- AndroidDispatcherClient() {}
- ~AndroidDispatcherClient() override {}
-
- // aura::client::DispatcherClient:
- 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(&AndroidDispatcherClient::RunNestedDispatcher,
- base::Unretained(this), base::Passed(&run_loop), dispatcher);
- }
-
- private:
- void RunNestedDispatcher(scoped_ptr<base::RunLoop> run_loop,
- base::MessagePumpDispatcher* dispatcher) {
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- base::MessageLoop::ScopedNestableTaskAllower allow(loop);
- run_loop->Run();
- }
-
- DISALLOW_COPY_AND_ASSIGN(AndroidDispatcherClient);
-};
-
-} // namespace
-
-namespace views {
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, public
-
-NativeWidgetAndroid::NativeWidgetAndroid(
- internal::NativeWidgetDelegate* delegate)
- : delegate_(delegate),
- window_(new aura::Window(this)),
- ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
- destroying_(false),
- cursor_(gfx::kNullCursor),
- saved_window_state_(ui::SHOW_STATE_DEFAULT),
- close_widget_factory_(this) {
- aura::client::SetFocusChangeObserver(window_, this);
- aura::client::SetActivationChangeObserver(window_, this);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, internal::NativeWidgetPrivate implementation:
-
-void NativeWidgetAndroid::InitNativeWidget(const Widget::InitParams& params) {
- ownership_ = params.ownership;
- NativeWidgetAura::RegisterNativeWidgetForWindow(this, window_);
-
- window_->SetType(GetAuraWindowTypeForWidgetType(params.type));
- window_->Init(params.layer_type);
- wm::SetShadowType(window_, wm::SHADOW_TYPE_NONE);
- window_->Show();
-
- // TODO(bshe): Get rid of the hard coded size. Tracked in crbug.com/551923.
- host_.reset(aura::WindowTreeHost::Create(gfx::Rect(0, 0, 800, 600)));
- host_->InitHost();
- host_->AddObserver(this);
-
- window_tree_client_.reset(new WindowTreeClientImpl(host_->window()));
-
- focus_client_.reset(new wm::FocusController(new AndroidFocusRules));
- aura::client::SetFocusClient(host_->window(), focus_client_.get());
- host_->window()->AddPreTargetHandler(focus_client_.get());
-
- new wm::DefaultActivationClient(host_->window());
-
- capture_client_.reset(
- new aura::client::DefaultCaptureClient(host_->window()));
-
- screen_position_client_.reset(new wm::DefaultScreenPositionClient);
- aura::client::SetScreenPositionClient(host_->window(),
- screen_position_client_.get());
- dispatcher_client_.reset(new AndroidDispatcherClient);
- aura::client::SetDispatcherClient(host_->window(), dispatcher_client_.get());
-
- delegate_->OnNativeWidgetCreated(false);
-
- DCHECK(GetWidget()->GetRootView());
- if (params.type != Widget::InitParams::TYPE_TOOLTIP)
- tooltip_manager_.reset(new views::TooltipManagerAura(GetWidget()));
-
- if (params.type != Widget::InitParams::TYPE_TOOLTIP &&
- params.type != Widget::InitParams::TYPE_POPUP) {
- aura::client::SetDragDropDelegate(window_, this);
- }
-
- aura::client::SetActivationDelegate(window_, this);
-
- host_->window()->AddChild(window_);
- window_reorderer_.reset(
- new WindowReorderer(window_, GetWidget()->GetRootView()));
-
- // TODO(bshe): figure out how to add cursor manager, drag drop client and all
- // the necessary parts that exists in desktop_native_widget_aura.
-}
-
-void NativeWidgetAndroid::OnWidgetInitDone() {}
-
-NonClientFrameView* NativeWidgetAndroid::CreateNonClientFrameView() {
- NOTIMPLEMENTED();
- return nullptr;
-}
-
-bool NativeWidgetAndroid::ShouldUseNativeFrame() const {
- // There is only one frame type for aura.
- return false;
-}
-
-bool NativeWidgetAndroid::ShouldWindowContentsBeTransparent() const {
- NOTIMPLEMENTED();
- return false;
-}
-
-void NativeWidgetAndroid::FrameTypeChanged() {
- NOTIMPLEMENTED();
-}
-
-Widget* NativeWidgetAndroid::GetWidget() {
- return delegate_->AsWidget();
-}
-
-const Widget* NativeWidgetAndroid::GetWidget() const {
- return delegate_->AsWidget();
-}
-
-gfx::NativeView NativeWidgetAndroid::GetNativeView() const {
- return window_;
-}
-
-gfx::NativeWindow NativeWidgetAndroid::GetNativeWindow() const {
- return window_;
-}
-
-Widget* NativeWidgetAndroid::GetTopLevelWidget() {
- return GetWidget();
-}
-
-const ui::Compositor* NativeWidgetAndroid::GetCompositor() const {
- return host_->compositor();
-}
-
-const ui::Layer* NativeWidgetAndroid::GetLayer() const {
- return GetNativeWindow()->layer();
-}
-
-void NativeWidgetAndroid::ReorderNativeViews() {
- window_reorderer_->ReorderChildWindows();
-}
-
-void NativeWidgetAndroid::ViewRemoved(View* view) {
- // TODO(bshe): Implement drag and drop. crbug.com/554029.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::SetNativeWindowProperty(const char* name,
- void* value) {
- GetNativeWindow()->SetNativeWindowProperty(name, value);
-}
-
-void* NativeWidgetAndroid::GetNativeWindowProperty(const char* name) const {
- return GetNativeWindow()->GetNativeWindowProperty(name);
-}
-
-TooltipManager* NativeWidgetAndroid::GetTooltipManager() const {
- return tooltip_manager_.get();
-}
-
-void NativeWidgetAndroid::SetCapture() {
- GetNativeWindow()->SetCapture();
-}
-
-void NativeWidgetAndroid::ReleaseCapture() {
- GetNativeWindow()->ReleaseCapture();
-}
-
-bool NativeWidgetAndroid::HasCapture() const {
- return GetNativeWindow()->HasCapture();
-}
-
-ui::InputMethod* NativeWidgetAndroid::GetInputMethod() {
- return host_->GetInputMethod();
-}
-
-void NativeWidgetAndroid::CenterWindow(const gfx::Size& size) {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::GetWindowPlacement(
- gfx::Rect* bounds,
- ui::WindowShowState* show_state) const {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-bool NativeWidgetAndroid::SetWindowTitle(const base::string16& title) {
- if (GetNativeWindow()->title() == title)
- return false;
- GetNativeWindow()->SetTitle(title);
- return true;
-}
-
-void NativeWidgetAndroid::SetWindowIcons(const gfx::ImageSkia& window_icon,
- const gfx::ImageSkia& app_icon) {
- // TODO(bshe): Implement this. See crbug.com/554953.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::InitModalType(ui::ModalType modal_type) {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-gfx::Rect NativeWidgetAndroid::GetWindowBoundsInScreen() const {
- return GetNativeWindow()->GetBoundsInScreen();
-}
-
-gfx::Rect NativeWidgetAndroid::GetClientAreaBoundsInScreen() const {
- // View-to-screen coordinate system transformations depend on this returning
- // the full window bounds, for example View::ConvertPointToScreen().
- return GetNativeWindow()->GetBoundsInScreen();
-}
-
-gfx::Rect NativeWidgetAndroid::GetRestoredBounds() const {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
- return gfx::Rect();
-}
-
-void NativeWidgetAndroid::SetBounds(const gfx::Rect& bounds) {
- // TODO(bshe): This may not work. We may need to resize SurfaceView too. See
- // crbug.com/554952.
- host_->SetBounds(bounds);
-}
-
-void NativeWidgetAndroid::SetSize(const gfx::Size& size) {
- gfx::Rect bounds = host_->GetBounds();
- SetBounds(gfx::Rect(bounds.origin(), size));
-}
-
-void NativeWidgetAndroid::StackAbove(gfx::NativeView native_view) {
- // TODO(bshe): Implements window stacking logic. See crbug.com/554047
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::StackAtTop() {
- // TODO(bshe): Implements window stacking logic. See crbug.com/554047
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::StackBelow(gfx::NativeView native_view) {
- // TODO(bshe): Implements window stacking logic. See crbug.com/554047
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::SetShape(SkRegion* region) {
- GetNativeWindow()->layer()->SetAlphaShape(make_scoped_ptr(region));
-}
-
-void NativeWidgetAndroid::Close() {
- // TODO(bshe): This might not be right. See crbug.com/554259.
- DCHECK(ownership_ == Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET);
- GetNativeWindow()->SuppressPaint();
- Hide();
- GetNativeWindow()->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_NONE);
-
- if (!close_widget_factory_.HasWeakPtrs()) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&NativeWidgetAndroid::CloseNow,
- close_widget_factory_.GetWeakPtr()));
- }
-}
-
-void NativeWidgetAndroid::CloseNow() {
- // TODO(bshe): This might not be right. See crbug.com/554259.
- host_->RemoveObserver(this);
- host_.reset();
- delete window_;
-}
-
-void NativeWidgetAndroid::Show() {
- host_->Show();
- GetNativeWindow()->Show();
-}
-
-void NativeWidgetAndroid::Hide() {
- host_->Hide();
- GetNativeWindow()->Hide();
-}
-
-void NativeWidgetAndroid::ShowMaximizedWithBounds(
- const gfx::Rect& restored_bounds) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::ShowWithWindowState(ui::WindowShowState state) {
- NOTIMPLEMENTED();
-}
-
-bool NativeWidgetAndroid::IsVisible() const {
- return GetNativeWindow()->IsVisible();
-}
-
-void NativeWidgetAndroid::Activate() {
- aura::client::GetActivationClient(host_->window())
- ->ActivateWindow(GetNativeWindow());
-}
-
-void NativeWidgetAndroid::Deactivate() {
- aura::client::GetActivationClient(host_->window())
- ->DeactivateWindow(GetNativeWindow());
-}
-
-bool NativeWidgetAndroid::IsActive() const {
- return wm::IsActiveWindow(GetNativeWindow());
-}
-
-void NativeWidgetAndroid::SetAlwaysOnTop(bool on_top) {
- GetNativeWindow()->SetProperty(aura::client::kAlwaysOnTopKey, on_top);
-}
-
-bool NativeWidgetAndroid::IsAlwaysOnTop() const {
- return GetNativeWindow()->GetProperty(aura::client::kAlwaysOnTopKey);
-}
-
-void NativeWidgetAndroid::SetVisibleOnAllWorkspaces(bool always_visible) {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::Maximize() {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::Minimize() {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-bool NativeWidgetAndroid::IsMaximized() const {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
- return false;
-}
-
-bool NativeWidgetAndroid::IsMinimized() const {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
- return false;
-}
-
-void NativeWidgetAndroid::Restore() {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::SetFullscreen(bool fullscreen) {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-bool NativeWidgetAndroid::IsFullscreen() const {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
- return false;
-}
-
-void NativeWidgetAndroid::SetOpacity(unsigned char opacity) {
- GetNativeWindow()->layer()->SetOpacity(opacity / 255.0);
-}
-
-void NativeWidgetAndroid::SetUseDragFrame(bool use_drag_frame) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::FlashFrame(bool flash) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::RunShellDrag(
- View* view,
- const ui::OSExchangeData& data,
- const gfx::Point& location,
- int operation,
- ui::DragDropTypes::DragEventSource source) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::SchedulePaintInRect(const gfx::Rect& rect) {
- GetNativeWindow()->SchedulePaintInRect(rect);
-}
-
-void NativeWidgetAndroid::SetCursor(gfx::NativeCursor cursor) {
- cursor_ = cursor;
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(host_->window());
- if (cursor_client)
- cursor_client->SetCursor(cursor);
-}
-
-bool NativeWidgetAndroid::IsMouseEventsEnabled() const {
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(host_->window());
- return cursor_client ? cursor_client->IsMouseEventsEnabled() : true;
-}
-
-void NativeWidgetAndroid::ClearNativeFocus() {
- aura::client::FocusClient* client = aura::client::GetFocusClient(window_);
- if (client && window_->Contains(client->GetFocusedWindow()))
- client->ResetFocusWithinActiveWindow(window_);
-}
-
-gfx::Rect NativeWidgetAndroid::GetWorkAreaBoundsInScreen() const {
- return gfx::Screen::GetScreenFor(window_)
- ->GetDisplayNearestWindow(window_)
- .work_area();
-}
-
-Widget::MoveLoopResult NativeWidgetAndroid::RunMoveLoop(
- const gfx::Vector2d& drag_offset,
- Widget::MoveLoopSource source,
- Widget::MoveLoopEscapeBehavior escape_behavior) {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
- return Widget::MOVE_LOOP_SUCCESSFUL;
-}
-
-void NativeWidgetAndroid::EndMoveLoop() {
- // TODO(bshe): Implement this. See crbug.com/554208.
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetAndroid::SetVisibilityChangedAnimationsEnabled(bool value) {
- GetNativeWindow()->SetProperty(aura::client::kAnimationsDisabledKey, !value);
-}
-
-void NativeWidgetAndroid::SetVisibilityAnimationDuration(
- const base::TimeDelta& duration) {
- wm::SetWindowVisibilityAnimationDuration(GetNativeWindow(), duration);
-}
-
-void NativeWidgetAndroid::SetVisibilityAnimationTransition(
- Widget::VisibilityTransition transition) {
- wm::WindowVisibilityAnimationTransition wm_transition = wm::ANIMATE_NONE;
- switch (transition) {
- case Widget::ANIMATE_SHOW:
- wm_transition = wm::ANIMATE_SHOW;
- break;
- case Widget::ANIMATE_HIDE:
- wm_transition = wm::ANIMATE_HIDE;
- break;
- case Widget::ANIMATE_BOTH:
- wm_transition = wm::ANIMATE_BOTH;
- break;
- case Widget::ANIMATE_NONE:
- wm_transition = wm::ANIMATE_NONE;
- break;
- }
- wm::SetWindowVisibilityAnimationTransition(GetNativeWindow(), wm_transition);
-}
-
-ui::NativeTheme* NativeWidgetAndroid::GetNativeTheme() const {
- return ui::NativeThemeAura::instance();
-}
-
-void NativeWidgetAndroid::OnRootViewLayout() {
- NOTIMPLEMENTED();
-}
-
-bool NativeWidgetAndroid::IsTranslucentWindowOpacitySupported() const {
- return true;
-}
-
-void NativeWidgetAndroid::OnSizeConstraintsChanged() {
- window_->SetProperty(aura::client::kCanMaximizeKey,
- GetWidget()->widget_delegate()->CanMaximize());
- window_->SetProperty(aura::client::kCanMinimizeKey,
- GetWidget()->widget_delegate()->CanMinimize());
- window_->SetProperty(aura::client::kCanResizeKey,
- GetWidget()->widget_delegate()->CanResize());
-}
-
-void NativeWidgetAndroid::RepostNativeEvent(gfx::NativeEvent native_event) {
- OnEvent(native_event);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::WindowDelegate implementation:
-
-gfx::Size NativeWidgetAndroid::GetMinimumSize() const {
- return delegate_->GetMinimumSize();
-}
-
-gfx::Size NativeWidgetAndroid::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 NativeWidgetAndroid::OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) {
- // 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());
-}
-
-gfx::NativeCursor NativeWidgetAndroid::GetCursor(const gfx::Point& point) {
- return cursor_;
-}
-
-int NativeWidgetAndroid::GetNonClientComponent(const gfx::Point& point) const {
- return delegate_->GetNonClientComponent(point);
-}
-
-bool NativeWidgetAndroid::ShouldDescendIntoChildForEventHandling(
- aura::Window* child,
- const gfx::Point& location) {
- views::WidgetDelegate* widget_delegate = GetWidget()->widget_delegate();
- if (widget_delegate &&
- !widget_delegate->ShouldDescendIntoChildForEventHandling(child, location))
- return false;
-
- // Don't descend into |child| if there is a view with a Layer that contains
- // the point and is stacked above |child|s layer.
- typedef std::vector<ui::Layer*> Layers;
- const Layers& root_layers(delegate_->GetRootLayers());
- if (root_layers.empty())
- return true;
-
- Layers::const_iterator child_layer_iter(
- std::find(window_->layer()->children().begin(),
- window_->layer()->children().end(), child->layer()));
- if (child_layer_iter == window_->layer()->children().end())
- return true;
-
- for (std::vector<ui::Layer*>::const_reverse_iterator i = root_layers.rbegin();
- i != root_layers.rend(); ++i) {
- ui::Layer* layer = *i;
- if (layer->visible() && layer->bounds().Contains(location)) {
- Layers::const_iterator root_layer_iter(
- std::find(window_->layer()->children().begin(),
- window_->layer()->children().end(), layer));
- if (root_layer_iter > child_layer_iter)
- return false;
- }
- }
- return true;
-}
-
-bool NativeWidgetAndroid::CanFocus() {
- return ShouldActivate();
-}
-
-void NativeWidgetAndroid::OnCaptureLost() {
- delegate_->OnMouseCaptureLost();
-}
-
-void NativeWidgetAndroid::OnPaint(const ui::PaintContext& context) {
- delegate_->OnNativeWidgetPaint(context);
-}
-
-void NativeWidgetAndroid::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- GetWidget()->DeviceScaleFactorChanged(device_scale_factor);
-}
-
-void NativeWidgetAndroid::OnWindowDestroying(aura::Window* window) {
- delegate_->OnNativeWidgetDestroying();
-
- // If the aura::Window is destroyed, we can no longer show tooltips.
- tooltip_manager_.reset();
-}
-
-void NativeWidgetAndroid::OnWindowDestroyed(aura::Window* window) {
- window_ = nullptr;
- delegate_->OnNativeWidgetDestroyed();
- if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
- delete this;
-}
-
-void NativeWidgetAndroid::OnWindowTargetVisibilityChanged(bool visible) {
- delegate_->OnNativeWidgetVisibilityChanged(visible);
-}
-
-bool NativeWidgetAndroid::HasHitTestMask() const {
- return delegate_->HasHitTestMask();
-}
-
-void NativeWidgetAndroid::GetHitTestMask(gfx::Path* mask) const {
- DCHECK(mask);
- delegate_->GetHitTestMask(mask);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, ui::EventHandler implementation:
-
-void NativeWidgetAndroid::OnKeyEvent(ui::KeyEvent* event) {
- DCHECK(window_);
- // Renderer may send a key event back to us if the key event wasn't handled,
- // and the window may be invisible by that time.
- if (!window_->IsVisible())
- return;
-
- FocusManager* focus_manager = GetWidget()->GetFocusManager();
- delegate_->OnKeyEvent(event);
- if (!event->handled() && focus_manager)
- focus_manager->OnKeyEvent(*event);
- event->SetHandled();
-}
-
-void NativeWidgetAndroid::OnMouseEvent(ui::MouseEvent* event) {
- DCHECK(window_);
- DCHECK(window_->IsVisible());
- if (event->type() == ui::ET_MOUSEWHEEL) {
- delegate_->OnMouseEvent(event);
- if (event->handled())
- return;
- }
-
- if (tooltip_manager_.get())
- tooltip_manager_->UpdateTooltip();
- TooltipManagerAura::UpdateTooltipManagerForCapture(GetWidget());
- delegate_->OnMouseEvent(event);
-}
-
-void NativeWidgetAndroid::OnScrollEvent(ui::ScrollEvent* event) {
- delegate_->OnScrollEvent(event);
-}
-
-void NativeWidgetAndroid::OnGestureEvent(ui::GestureEvent* event) {
- DCHECK(window_);
- DCHECK(window_->IsVisible() || event->IsEndingEvent());
- delegate_->OnGestureEvent(event);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::client::ActivationDelegate implementation:
-
-bool NativeWidgetAndroid::ShouldActivate() const {
- return delegate_->CanActivate();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::client::ActivationChangeObserver
-// implementation:
-
-void NativeWidgetAndroid::OnWindowActivated(
- aura::client::ActivationChangeObserver::ActivationReason,
- aura::Window* gained_active,
- aura::Window* lost_active) {
- DCHECK(window_ == gained_active || window_ == lost_active);
- if (GetWidget()->GetFocusManager()) {
- if (window_ == gained_active)
- GetWidget()->GetFocusManager()->RestoreFocusedView();
- else if (window_ == lost_active)
- GetWidget()->GetFocusManager()->StoreFocusedView(true);
- }
- delegate_->OnNativeWidgetActivationChanged(window_ == gained_active);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::client::FocusChangeObserver:
-
-void NativeWidgetAndroid::OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) {
- if (window_ == gained_focus)
- delegate_->OnNativeFocus();
- else if (window_ == lost_focus)
- delegate_->OnNativeBlur();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::WindowDragDropDelegate implementation:
-
-void NativeWidgetAndroid::OnDragEntered(const ui::DropTargetEvent& event) {
- // TODO: Implement drag and drop. crbug.com/554029.
- NOTIMPLEMENTED();
-}
-
-int NativeWidgetAndroid::OnDragUpdated(const ui::DropTargetEvent& event) {
- // TODO: Implement drag and drop. crbug.com/554029.
- NOTIMPLEMENTED();
- return 0;
-}
-
-void NativeWidgetAndroid::OnDragExited() {
- // TODO: Implement drag and drop. crbug.com/554029.
- NOTIMPLEMENTED();
-}
-
-int NativeWidgetAndroid::OnPerformDrop(const ui::DropTargetEvent& event) {
- // TODO: Implement drag and drop. crbug.com/554029.
- NOTIMPLEMENTED();
- return 0;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, aura::WindowTreeHostObserver implementation:
-
-void NativeWidgetAndroid::OnHostCloseRequested(
- const aura::WindowTreeHost* host) {
- GetWidget()->Close();
-}
-
-void NativeWidgetAndroid::OnHostResized(const aura::WindowTreeHost* host) {
- gfx::Rect new_bounds = gfx::Rect(host_->window()->bounds().size());
- GetNativeWindow()->SetBounds(new_bounds);
- delegate_->OnNativeWidgetSizeChanged(new_bounds.size());
-}
-
-void NativeWidgetAndroid::OnHostMoved(const aura::WindowTreeHost* host,
- const gfx::Point& new_origin) {
- TRACE_EVENT1("views", "NativeWidgetAndroid::OnHostMoved", "new_origin",
- new_origin.ToString());
-
- delegate_->OnNativeWidgetMove();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, protected:
-
-NativeWidgetAndroid::~NativeWidgetAndroid() {
- destroying_ = true;
- if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
- delete delegate_;
- else
- CloseNow();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeWidgetAndroid, private:
-
-bool NativeWidgetAndroid::IsDocked() const {
- NOTIMPLEMENTED();
- return false;
-}
-
-void NativeWidgetAndroid::SetInitialFocus(ui::WindowShowState show_state) {
- // The window does not get keyboard messages unless we focus it.
- if (!GetWidget()->SetInitialFocus(show_state))
- window_->Focus();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/widget/android/native_widget_android.h b/chromium/ui/views/widget/android/native_widget_android.h
deleted file mode 100644
index 8aaa3c470bd..00000000000
--- a/chromium/ui/views/widget/android/native_widget_android.h
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_
-#define UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/aura/client/focus_change_observer.h"
-#include "ui/aura/window_delegate.h"
-#include "ui/aura/window_observer.h"
-#include "ui/aura/window_tree_host_observer.h"
-#include "ui/base/cursor/cursor.h"
-#include "ui/events/event_constants.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;
-class WindowTreeHost;
-namespace client {
-class DefaultCaptureClient;
-class DispatcherClient;
-class ScreenPositionClient;
-class WindowTreeClient;
-}
-}
-namespace gfx {
-class FontList;
-}
-namespace wm {
-class FocusController;
-}
-
-namespace views {
-
-class TooltipManagerAura;
-class WindowReorderer;
-
-// NativeWidgetAndroid creates and hosts the Widget in an Android native window.
-// It is used to create a top level window on Android platform.
-class VIEWS_EXPORT NativeWidgetAndroid
- : public internal::NativeWidgetPrivate,
- public aura::WindowDelegate,
- public aura::client::ActivationDelegate,
- public aura::client::ActivationChangeObserver,
- public aura::client::FocusChangeObserver,
- public aura::client::DragDropDelegate,
- public aura::WindowTreeHostObserver {
- public:
- explicit NativeWidgetAndroid(internal::NativeWidgetDelegate* delegate);
-
- aura::WindowTreeHost* host() { return host_.get(); }
-
- // Overridden from internal::NativeWidgetPrivate:
- void InitNativeWidget(const Widget::InitParams& params) override;
- void OnWidgetInitDone() override;
- NonClientFrameView* CreateNonClientFrameView() override;
- bool ShouldUseNativeFrame() const override;
- bool ShouldWindowContentsBeTransparent() const override;
- void FrameTypeChanged() override;
- Widget* GetWidget() override;
- const Widget* GetWidget() const override;
- gfx::NativeView GetNativeView() const override;
- gfx::NativeWindow GetNativeWindow() const override;
- Widget* GetTopLevelWidget() override;
- const ui::Compositor* GetCompositor() const override;
- const ui::Layer* GetLayer() const override;
- void ReorderNativeViews() override;
- void ViewRemoved(View* view) override;
- void SetNativeWindowProperty(const char* name, void* value) override;
- void* GetNativeWindowProperty(const char* name) const override;
- TooltipManager* GetTooltipManager() const override;
- void SetCapture() override;
- void ReleaseCapture() override;
- bool HasCapture() const override;
- ui::InputMethod* GetInputMethod() override;
- void CenterWindow(const gfx::Size& size) override;
- void GetWindowPlacement(gfx::Rect* bounds,
- ui::WindowShowState* maximized) const override;
- bool SetWindowTitle(const base::string16& title) override;
- void SetWindowIcons(const gfx::ImageSkia& window_icon,
- const gfx::ImageSkia& app_icon) override;
- void InitModalType(ui::ModalType modal_type) override;
- gfx::Rect GetWindowBoundsInScreen() const override;
- gfx::Rect GetClientAreaBoundsInScreen() const override;
- gfx::Rect GetRestoredBounds() const override;
- void SetBounds(const gfx::Rect& bounds) override;
- void SetSize(const gfx::Size& size) override;
- void StackAbove(gfx::NativeView native_view) override;
- void StackAtTop() override;
- void StackBelow(gfx::NativeView native_view) override;
- void SetShape(SkRegion* shape) override;
- void Close() override;
- void CloseNow() override;
- void Show() override;
- void Hide() override;
- void ShowMaximizedWithBounds(const gfx::Rect& restored_bounds) override;
- void ShowWithWindowState(ui::WindowShowState state) override;
- bool IsVisible() const override;
- void Activate() override;
- void Deactivate() override;
- bool IsActive() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
- void SetVisibleOnAllWorkspaces(bool always_visible) override;
- void Maximize() override;
- void Minimize() override;
- bool IsMaximized() const override;
- bool IsMinimized() const override;
- void Restore() override;
- void SetFullscreen(bool fullscreen) override;
- bool IsFullscreen() const override;
- void SetOpacity(unsigned char opacity) override;
- void SetUseDragFrame(bool use_drag_frame) override;
- void FlashFrame(bool flash_frame) override;
- void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
- const gfx::Point& location,
- int operation,
- ui::DragDropTypes::DragEventSource source) override;
- void SchedulePaintInRect(const gfx::Rect& rect) override;
- void SetCursor(gfx::NativeCursor cursor) override;
- bool IsMouseEventsEnabled() const override;
- void ClearNativeFocus() override;
- gfx::Rect GetWorkAreaBoundsInScreen() const override;
- Widget::MoveLoopResult RunMoveLoop(
- const gfx::Vector2d& drag_offset,
- Widget::MoveLoopSource source,
- Widget::MoveLoopEscapeBehavior escape_behavior) override;
- void EndMoveLoop() override;
- void SetVisibilityChangedAnimationsEnabled(bool value) override;
- void SetVisibilityAnimationDuration(const base::TimeDelta& duration) override;
- void SetVisibilityAnimationTransition(
- Widget::VisibilityTransition transition) override;
- ui::NativeTheme* GetNativeTheme() const override;
- void OnRootViewLayout() override;
- bool IsTranslucentWindowOpacitySupported() const override;
- void OnSizeConstraintsChanged() override;
- void RepostNativeEvent(gfx::NativeEvent native_event) override;
-
- // Overridden from aura::WindowDelegate:
- gfx::Size GetMinimumSize() const override;
- gfx::Size GetMaximumSize() const override;
- void OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) override;
- gfx::NativeCursor GetCursor(const gfx::Point& point) override;
- int GetNonClientComponent(const gfx::Point& point) const override;
- bool ShouldDescendIntoChildForEventHandling(
- aura::Window* child,
- const gfx::Point& location) override;
- bool CanFocus() override;
- void OnCaptureLost() override;
- void OnPaint(const ui::PaintContext& context) override;
- void OnDeviceScaleFactorChanged(float device_scale_factor) override;
- void OnWindowDestroying(aura::Window* window) override;
- void OnWindowDestroyed(aura::Window* window) override;
- void OnWindowTargetVisibilityChanged(bool visible) override;
- bool HasHitTestMask() const override;
- void GetHitTestMask(gfx::Path* mask) const override;
-
- // Overridden from ui::EventHandler:
- void OnKeyEvent(ui::KeyEvent* event) override;
- void OnMouseEvent(ui::MouseEvent* event) override;
- void OnScrollEvent(ui::ScrollEvent* event) override;
- void OnGestureEvent(ui::GestureEvent* event) override;
-
- // Overridden from aura::client::ActivationDelegate:
- bool ShouldActivate() const override;
-
- // Overridden from aura::client::ActivationChangeObserver:
- void OnWindowActivated(
- aura::client::ActivationChangeObserver::ActivationReason reason,
- aura::Window* gained_active,
- aura::Window* lost_active) override;
-
- // Overridden from aura::client::FocusChangeObserver:
- void OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) override;
-
- // Overridden from aura::client::DragDropDelegate:
- void OnDragEntered(const ui::DropTargetEvent& event) override;
- int OnDragUpdated(const ui::DropTargetEvent& event) override;
- void OnDragExited() override;
- int OnPerformDrop(const ui::DropTargetEvent& event) override;
-
- // Overridden from aura::WindowTreeHostObserver:
- void OnHostCloseRequested(const aura::WindowTreeHost* host) override;
- void OnHostResized(const aura::WindowTreeHost* host) override;
- void OnHostMoved(const aura::WindowTreeHost* host,
- const gfx::Point& new_origin) override;
-
- protected:
- ~NativeWidgetAndroid() override;
-
- internal::NativeWidgetDelegate* delegate() { return delegate_; }
-
- private:
- class ActiveWindowObserver;
-
- bool IsDocked() const;
- void SetInitialFocus(ui::WindowShowState show_state);
-
- internal::NativeWidgetDelegate* delegate_;
-
- // WARNING: set to NULL when destroyed. As the Widget is not necessarily
- // destroyed along with |window_| all usage of |window_| should first verify
- // non-NULL.
- aura::Window* window_;
-
- // See class documentation for Widget in widget.h for a note about ownership.
- Widget::InitParams::Ownership ownership_;
-
- // Are we in the destructor?
- bool destroying_;
-
- gfx::NativeCursor cursor_;
-
- // The saved window state for exiting full screen state.
- ui::WindowShowState saved_window_state_;
-
- scoped_ptr<TooltipManagerAura> tooltip_manager_;
-
- // Reorders child windows of |window_| associated with a view based on the
- // order of the associated views in the widget's view hierarchy.
- scoped_ptr<WindowReorderer> window_reorderer_;
-
- scoped_ptr<aura::WindowTreeHost> host_;
- scoped_ptr<wm::FocusController> focus_client_;
- scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
- scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
- scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_;
- scoped_ptr<aura::client::DispatcherClient> dispatcher_client_;
-
- // The following factory is used for calls to close the
- // NativeWidgetAndroid instance.
- base::WeakPtrFactory<NativeWidgetAndroid> close_widget_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeWidgetAndroid);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_ANDROID_NATIVE_WIDGET_ANDROID_H_
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc
deleted file mode 100644
index 409057da5f0..00000000000
--- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.cc
+++ /dev/null
@@ -1,34 +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/desktop_aura/desktop_dispatcher_client.h"
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "build/build_config.h"
-
-namespace views {
-
-DesktopDispatcherClient::DesktopDispatcherClient() {
-}
-
-DesktopDispatcherClient::~DesktopDispatcherClient() {
-}
-
-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
deleted file mode 100644
index 3d7f6f42caa..00000000000
--- a/chromium/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
+++ /dev/null
@@ -1,32 +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_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_
-#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "ui/views/views_export.h"
-#include "ui/wm/public/dispatcher_client.h"
-
-namespace views {
-
-// TODO(erg): I won't lie to you; I have no idea what this is or what it does.
-class VIEWS_EXPORT DesktopDispatcherClient
- : public aura::client::DispatcherClient {
- public:
- DesktopDispatcherClient();
- ~DesktopDispatcherClient() override;
-
- void PrepareNestedLoopClosures(base::MessagePumpDispatcher* dispatcher,
- base::Closure* run_closure,
- base::Closure* quit_closure) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DesktopDispatcherClient);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_DISPATCHER_CLIENT_H_
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 3ef11e83603..e9907e2a275 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
@@ -1186,8 +1186,8 @@ void DesktopDragDropClientAuraX11::CreateDragWidget(
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.accept_events = false;
- gfx::Point location = gfx::Screen::GetNativeScreen()->GetCursorScreenPoint() -
- drag_widget_offset_;
+ gfx::Point location =
+ gfx::Screen::GetScreen()->GetCursorScreenPoint() - drag_widget_offset_;
params.bounds = gfx::Rect(location, image.size());
widget->set_focus_on_creation(false);
widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
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 01c1d875c29..f69b839d73a 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
@@ -32,7 +32,6 @@
#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"
@@ -61,7 +60,6 @@
#if defined(OS_WIN)
#include "ui/base/win/shell.h"
-#include "ui/gfx/win/dpi.h"
#endif
DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(VIEWS_EXPORT,
@@ -341,11 +339,6 @@ void DesktopNativeWidgetAura::OnHostClosed() {
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();
-
// 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
@@ -483,10 +476,6 @@ void DesktopNativeWidgetAura::InitNativeWidget(
aura::client::SetActivationClient(host_->window(), focus_controller);
host_->window()->AddPreTargetHandler(focus_controller);
- dispatcher_client_.reset(new DesktopDispatcherClient);
- aura::client::SetDispatcherClient(host_->window(),
- dispatcher_client_.get());
-
position_client_.reset(new DesktopScreenPositionClient(host_->window()));
drag_drop_client_ = desktop_window_tree_host_->CreateDragDropClient(
@@ -689,18 +678,9 @@ gfx::Rect DesktopNativeWidgetAura::GetRestoredBounds() const {
void DesktopNativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
if (!content_window_)
return;
- // 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::OnWindowTreeHostResized function.
- float scale = 1;
aura::Window* root = host_->window();
- if (root) {
- scale = gfx::Screen::GetScreenFor(root)->
- GetDisplayNearestWindow(root).device_scale_factor();
- }
- gfx::Rect bounds_in_pixels =
- gfx::ScaleToEnclosingRect(bounds, scale, scale);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
+ gfx::Rect bounds_in_pixels = screen->DIPToScreenRectInWindow(root, bounds);
desktop_window_tree_host_->AsWindowTreeHost()->SetBounds(bounds_in_pixels);
}
@@ -840,9 +820,6 @@ void DesktopNativeWidgetAura::SetOpacity(unsigned char opacity) {
desktop_window_tree_host_->SetOpacity(opacity);
}
-void DesktopNativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
-}
-
void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) {
if (content_window_)
desktop_window_tree_host_->FlashFrame(flash_frame);
@@ -1069,7 +1046,7 @@ void DesktopNativeWidgetAura::OnScrollEvent(ui::ScrollEvent* event) {
return;
// Convert unprocessed scroll events into wheel events.
- ui::MouseWheelEvent mwe(*static_cast<ui::ScrollEvent*>(event));
+ ui::MouseWheelEvent mwe(*event->AsScrollEvent());
native_widget_delegate_->OnMouseEvent(&mwe);
if (mwe.handled())
event->SetHandled();
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 2a756d9fd72..47f514924bf 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
@@ -42,7 +42,6 @@ namespace corewm {
class TooltipController;
}
class DesktopCaptureClient;
-class DesktopDispatcherClient;
class DesktopEventClient;
class DesktopNativeCursorManager;
class DesktopWindowTreeHost;
@@ -149,7 +148,6 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
void SetFullscreen(bool fullscreen) override;
bool IsFullscreen() const override;
void SetOpacity(unsigned char opacity) override;
- void SetUseDragFrame(bool use_drag_frame) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
const ui::OSExchangeData& data,
@@ -256,7 +254,6 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
internal::NativeWidgetDelegate* native_widget_delegate_;
scoped_ptr<wm::FocusController> focus_client_;
- scoped_ptr<DesktopDispatcherClient> dispatcher_client_;
scoped_ptr<aura::client::ScreenPositionClient> position_client_;
scoped_ptr<aura::client::DragDropClient> drag_drop_client_;
scoped_ptr<aura::client::WindowTreeClient> window_tree_client_;
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 9578951b137..86e60d31fc8 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
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "build/build_config.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
@@ -17,15 +18,17 @@
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/screen.h"
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"
-#include "ui/wm/public/dispatcher_client.h"
#if defined(OS_WIN)
+#include "ui/base/view_prop.h"
+#include "ui/base/win/window_event_target.h"
#include "ui/views/win/hwnd_util.h"
#endif
@@ -231,15 +234,10 @@ TEST_F(DesktopNativeWidgetAuraTest, WidgetCanBeDestroyedFromNestedLoop) {
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::RunLoop run_loop;
base::Closure quit_runloop = run_loop.QuitClosure();
message_loop()->PostTask(FROM_HERE,
base::Bind(&QuitNestedLoopAndCloseWidget,
@@ -434,9 +432,7 @@ TEST_F(DesktopAuraWidgetTest, TopLevelOwnedPopupRepositionTest) {
gfx::Rect new_pos(10, 10, 400, 400);
popup_window.owned_window()->SetBoundsInScreen(
- new_pos,
- gfx::Screen::GetScreenFor(
- popup_window.owned_window())->GetDisplayNearestPoint(gfx::Point()));
+ new_pos, gfx::Screen::GetScreen()->GetDisplayNearestPoint(gfx::Point()));
EXPECT_EQ(new_pos,
popup_window.top_level_widget()->GetWindowBoundsInScreen());
@@ -493,7 +489,8 @@ void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
Widget* widget = new Widget;
Widget::InitParams params =
test->CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(widget);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr);
params.bounds = gfx::Rect(0, 0, 50, 100);
widget->Init(params);
widget->SetContentsView(new CloseWidgetView(last_event_type));
@@ -535,8 +532,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 PlatformDesktopNativeWidget(&top_level_widget);
+ init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ init_params, &top_level_widget, nullptr);
top_level_widget.Init(init_params);
top_level_widget.Show();
EXPECT_TRUE(top_level_widget.IsVisible());
@@ -632,6 +629,32 @@ TEST_F(WidgetTest, WindowModalityActivationTest) {
modal_dialog_widget->CloseNow();
}
+
+// This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR
+// messages via the WindowEventTarget interface implemented by the
+// HWNDMessageHandler class does not cause a crash due to an unprocessed
+// event
+TEST_F(WidgetTest, CharMessagesAsKeyboardMessagesDoesNotCrash) {
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(params);
+ widget.Show();
+
+ ui::WindowEventTarget* target =
+ reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue(
+ widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
+ ui::WindowEventTarget::kWin32InputEventTarget));
+ ASSERT_NE(nullptr, target);
+ bool handled = false;
+ target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled);
+ target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled);
+ target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled);
+ widget.CloseNow();
+}
+
#endif // defined(OS_WIN)
} // namespace test
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 a8e088c92c6..4df7b7ffae5 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.cc
@@ -24,7 +24,7 @@ DesktopScreenWin::~DesktopScreenWin() {
}
////////////////////////////////////////////////////////////////////////////////
-// DesktopScreenWin, gfx::ScreenWin implementation:
+// DesktopScreenWin, display::win::ScreenWin implementation:
gfx::Display DesktopScreenWin::GetDisplayMatching(
const gfx::Rect& match_rect) const {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h
index 8add5bdb3f2..085ba321da1 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_win.h
@@ -6,18 +6,18 @@
#define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_SCREEN_WIN_H_
#include "base/macros.h"
-#include "ui/gfx/screen_win.h"
+#include "ui/display/win/screen_win.h"
#include "ui/views/views_export.h"
namespace views {
-class VIEWS_EXPORT DesktopScreenWin : public gfx::ScreenWin {
+class VIEWS_EXPORT DesktopScreenWin : public display::win::ScreenWin {
public:
DesktopScreenWin();
~DesktopScreenWin() override;
private:
- // Overridden from gfx::ScreenWin:
+ // Overridden from display::win::ScreenWin:
gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override;
HWND GetHWNDFromNativeView(gfx::NativeView window) const override;
gfx::NativeWindow GetNativeWindowFromHWND(HWND hwnd) const override;
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 07bcfca6189..6ffd94a3c89 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -20,6 +20,7 @@
#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/font_render_params.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/native_widget_types.h"
@@ -38,9 +39,12 @@ const int64_t kConfigureDelayMs = 500;
double GetDeviceScaleFactor() {
float device_scale_factor = 1.0f;
- if (views::LinuxUI::instance())
+ if (views::LinuxUI::instance()) {
device_scale_factor =
views::LinuxUI::instance()->GetDeviceScaleFactor();
+ } else if (gfx::Display::HasForceDeviceScaleFactor()) {
+ device_scale_factor = gfx::Display::GetForcedDeviceScaleFactor();
+ }
return device_scale_factor;
}
@@ -104,9 +108,9 @@ DesktopScreenX11::DesktopScreenX11()
RROutputChangeNotifyMask |
RRCrtcChangeNotifyMask);
- displays_ = BuildDisplaysFromXRandRInfo();
+ SetDisplaysInternal(BuildDisplaysFromXRandRInfo());
} else {
- displays_ = GetFallbackDisplayList();
+ SetDisplaysInternal(GetFallbackDisplayList());
}
}
@@ -255,7 +259,7 @@ uint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) {
// static
void DesktopScreenX11::UpdateDeviceScaleFactorForTest() {
DesktopScreenX11* screen =
- static_cast<DesktopScreenX11*>(gfx::Screen::GetNativeScreen());
+ static_cast<DesktopScreenX11*>(gfx::Screen::GetScreen());
screen->ConfigureTimerFired();
}
@@ -310,7 +314,8 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
crtc(XRRGetCrtcInfo(xdisplay_, resources.get(), output_info->crtc));
int64_t display_id = -1;
- if (!ui::GetDisplayId(output_id, static_cast<uint8_t>(i), &display_id)) {
+ if (!ui::EDIDParserX11(output_id).GetDisplayId(static_cast<uint8_t>(i),
+ &display_id)) {
// It isn't ideal, but if we can't parse the EDID data, fallback on the
// display number.
display_id = i;
@@ -362,11 +367,17 @@ std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
void DesktopScreenX11::ConfigureTimerFired() {
std::vector<gfx::Display> old_displays = displays_;
- displays_ = BuildDisplaysFromXRandRInfo();
-
+ SetDisplaysInternal(BuildDisplaysFromXRandRInfo());
change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
}
+void DesktopScreenX11::SetDisplaysInternal(
+ const std::vector<gfx::Display>& displays) {
+ displays_ = displays;
+ gfx::SetFontRenderParamsDeviceScaleFactor(
+ GetPrimaryDisplay().device_scale_factor());
+}
+
////////////////////////////////////////////////////////////////////////////////
gfx::Screen* CreateDesktopScreen() {
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 c49d4daf28b..e96d983ccb2 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "ui/events/platform/platform_event_dispatcher.h"
#include "ui/gfx/display_change_notifier.h"
@@ -70,6 +71,9 @@ class VIEWS_EXPORT DesktopScreenX11 : public gfx::Screen,
// We delay updating the display so we can coalesce events.
void ConfigureTimerFired();
+ // Updates |displays_| and sets FontRenderParams's scale factor.
+ void SetDisplaysInternal(const std::vector<gfx::Display>& displays);
+
Display* xdisplay_;
::Window x_root_window_;
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 c527545c4b0..a2e2d2aed7e 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
@@ -16,6 +16,7 @@
#include "ui/base/x/x11_util.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/display_observer.h"
+#include "ui/gfx/font_render_params.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"
@@ -83,9 +84,10 @@ class DesktopScreenX11Test : public views::ViewsTestBase,
DesktopScreenX11* screen() { return screen_.get(); }
void NotifyDisplaysChanged(const std::vector<gfx::Display>& displays) {
- DesktopScreenX11* screen = screen_.get();
- screen->change_notifier_.NotifyDisplaysChanged(screen->displays_, displays);
- screen->displays_ = displays;
+ std::vector<gfx::Display> old_displays = screen_->displays_;
+ screen_->SetDisplaysInternal(displays);
+ screen_->change_notifier_.NotifyDisplaysChanged(old_displays,
+ screen_->displays_);
}
void ResetDisplayChanges() {
@@ -439,6 +441,7 @@ TEST_F(DesktopScreenX11Test, DeviceScaleFactorChange) {
displays[0].set_device_scale_factor(2.5f);
NotifyDisplaysChanged(displays);
EXPECT_EQ(1u, changed_display_.size());
+ EXPECT_EQ(2.5f, gfx::GetFontRenderParamsDeviceScaleFactor());
displays[1].set_device_scale_factor(2.5f);
NotifyDisplaysChanged(displays);
@@ -456,6 +459,7 @@ TEST_F(DesktopScreenX11Test, DeviceScaleFactorChange) {
displays[1].set_device_scale_factor(1.f);
NotifyDisplaysChanged(displays);
EXPECT_EQ(4u, changed_display_.size());
+ EXPECT_EQ(1.f, gfx::GetFontRenderParamsDeviceScaleFactor());
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index c354154a542..fa9ea48b500 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -125,6 +125,7 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window,
const Widget::InitParams& params) {
// TODO(beng): SetInitParams().
content_window_ = content_window;
+ wants_mouse_events_when_inactive_ = params.wants_mouse_events_when_inactive;
aura::client::SetAnimationHost(content_window_, this);
@@ -136,8 +137,7 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window,
if (params.parent && params.parent->GetHost())
parent_hwnd = params.parent->GetHost()->GetAcceleratedWidget();
- message_handler_->set_remove_standard_frame(params.remove_standard_frame);
-
+ remove_standard_frame_ = params.remove_standard_frame;
has_non_client_view_ = Widget::RequiresNonClientView(params.type);
gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
@@ -587,24 +587,30 @@ void DesktopWindowTreeHostWin::OnWindowHidingAnimationCompleted() {
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostWin, HWNDMessageHandlerDelegate implementation:
-bool DesktopWindowTreeHostWin::IsWidgetWindow() const {
+bool DesktopWindowTreeHostWin::HasNonClientView() const {
return has_non_client_view_;
}
-bool DesktopWindowTreeHostWin::IsUsingCustomFrame() const {
- return !GetWidget()->ShouldUseNativeFrame();
+FrameMode DesktopWindowTreeHostWin::GetFrameMode() const {
+ return GetWidget()->ShouldUseNativeFrame() ? FrameMode::SYSTEM_DRAWN
+ : FrameMode::CUSTOM_DRAWN;
+}
+
+bool DesktopWindowTreeHostWin::HasFrame() const {
+ return !remove_standard_frame_;
}
void DesktopWindowTreeHostWin::SchedulePaint() {
GetWidget()->GetRootView()->SchedulePaint();
}
-void DesktopWindowTreeHostWin::EnableInactiveRendering() {
- native_widget_delegate_->EnableInactiveRendering();
+void DesktopWindowTreeHostWin::SetAlwaysRenderAsActive(
+ bool always_render_as_active) {
+ native_widget_delegate_->SetAlwaysRenderAsActive(always_render_as_active);
}
-bool DesktopWindowTreeHostWin::IsInactiveRenderingDisabled() {
- return native_widget_delegate_->IsInactiveRenderingDisabled();
+bool DesktopWindowTreeHostWin::IsAlwaysRenderAsActive() {
+ return native_widget_delegate_->IsAlwaysRenderAsActive();
}
bool DesktopWindowTreeHostWin::CanResize() const {
@@ -626,7 +632,7 @@ bool DesktopWindowTreeHostWin::CanActivate() const {
}
bool DesktopWindowTreeHostWin::WantsMouseEventsWhenInactive() const {
- return false;
+ return wants_mouse_events_when_inactive_;
}
bool DesktopWindowTreeHostWin::WidgetSizeIsClientSize() const {
@@ -692,7 +698,7 @@ bool DesktopWindowTreeHostWin::ShouldHandleSystemCommands() const {
}
void DesktopWindowTreeHostWin::HandleAppDeactivated() {
- native_widget_delegate_->EnableInactiveRendering();
+ native_widget_delegate_->SetAlwaysRenderAsActive(false);
}
void DesktopWindowTreeHostWin::HandleActivationChanged(bool active) {
@@ -911,9 +917,11 @@ void DesktopWindowTreeHostWin::HandleWindowSizeChanged() {
// changed (can occur on Windows 10 when snapping a window to the side of
// the screen). In that case do a resize to the current size to reenable
// swaps.
- if (compositor())
- compositor()->SetScaleAndSize(compositor()->device_scale_factor(),
- compositor()->size());
+ if (compositor()) {
+ compositor()->SetScaleAndSize(
+ compositor()->device_scale_factor(),
+ message_handler_->GetClientAreaBounds().size());
+ }
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index ad82485eb0c..3465112eac0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -126,11 +126,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void OnWindowHidingAnimationCompleted() override;
// Overridden from HWNDMessageHandlerDelegate:
- bool IsWidgetWindow() const override;
- bool IsUsingCustomFrame() const override;
+ bool HasNonClientView() const override;
+ FrameMode GetFrameMode() const override;
+ bool HasFrame() const override;
void SchedulePaint() override;
- void EnableInactiveRendering() override;
- bool IsInactiveRenderingDisabled() override;
+ void SetAlwaysRenderAsActive(bool always_render_as_active) override;
+ bool IsAlwaysRenderAsActive() override;
bool CanResize() const override;
bool CanMaximize() const override;
bool CanMinimize() const override;
@@ -244,6 +245,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
// Init time, before the Widget has created the NonClientView.
bool has_non_client_view_;
+ // True if the window should have the frame removed.
+ bool remove_standard_frame_;
+
// Owned by TooltipController, but we need to forward events to it so we keep
// a reference.
corewm::TooltipWin* tooltip_;
@@ -256,6 +260,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
scoped_ptr<aura::client::ScopedTooltipDisabler> tooltip_disabler_;
+ // Indicates if current window will receive mouse events when should not
+ // become activated.
+ bool wants_mouse_events_when_inactive_ = false;
+
DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostWin);
};
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index e2fb724b914..cecae1ee81d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -109,7 +109,7 @@ const char* kAtomsToCache[] = {
"_NET_WM_WINDOW_TYPE_NOTIFICATION",
"_NET_WM_WINDOW_TYPE_TOOLTIP",
"XdndActionAsk",
- "XdndActionCopy"
+ "XdndActionCopy",
"XdndActionLink",
"XdndActionList",
"XdndActionMove",
@@ -820,7 +820,7 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
if (fullscreen) {
restored_bounds_in_pixels_ = bounds_in_pixels_;
const gfx::Display display =
- gfx::Screen::GetScreenFor(NULL)->GetDisplayNearestWindow(window());
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window());
bounds_in_pixels_ = ToPixelRect(display.bounds());
} else {
bounds_in_pixels_ = restored_bounds_in_pixels_;
@@ -938,10 +938,10 @@ void DesktopWindowTreeHostX11::SizeConstraintsChanged() {
// DesktopWindowTreeHostX11, aura::WindowTreeHost implementation:
gfx::Transform DesktopWindowTreeHostX11::GetRootTransform() const {
- gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ gfx::Display display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
if (window_mapped_) {
aura::Window* win = const_cast<aura::Window*>(window());
- display = gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(win);
+ display = gfx::Screen::GetScreen()->GetDisplayNearestWindow(win);
}
float scale = display.device_scale_factor();
@@ -1287,7 +1287,7 @@ void DesktopWindowTreeHostX11::InitX11Window(
gfx::Size DesktopWindowTreeHostX11::AdjustSize(
const gfx::Size& requested_size_in_pixels) {
std::vector<gfx::Display> displays =
- gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE)->GetAllDisplays();
+ gfx::Screen::GetScreen()->GetAllDisplays();
// Compare against all monitor sizes. The window manager can move the window
// to whichever monitor it wants.
for (size_t i = 0; i < displays.size(); ++i) {
@@ -1533,9 +1533,9 @@ void DesktopWindowTreeHostX11::ConvertEventToDifferentHost(
DesktopWindowTreeHostX11* host) {
DCHECK_NE(this, host);
const gfx::Display display_src =
- gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(window());
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window());
const gfx::Display display_dest =
- gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(host->window());
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(host->window());
DCHECK_EQ(display_src.device_scale_factor(),
display_dest.device_scale_factor());
gfx::Vector2d offset = GetLocationOnNativeScreen() -
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 759194f6b52..7e842fed086 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -36,7 +36,6 @@ class EventHandler;
namespace views {
class DesktopDragDropClientAuraX11;
-class DesktopDispatcherClient;
class DesktopWindowTreeHostObserverX11;
class X11DesktopWindowMoveClient;
class X11WindowEventFilter;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
index 162cf3c49a3..7c2253493ac 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -24,7 +24,7 @@
#include "ui/base/hit_test.h"
#include "ui/base/x/x11_util.h"
#include "ui/events/devices/x11/touch_factory_x11.h"
-#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/events/platform/x11/x11_event_source_glib.h"
#include "ui/events/test/platform_event_source_test_api.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
@@ -68,11 +68,9 @@ class WMStateWaiter : public X11PropertyChangeWaiter {
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());
+ auto it = std::find(hints.cbegin(), hints.cend(),
+ atom_cache_->GetAtom(hint_));
+ bool hint_set = (it != hints.cend());
return hint_set != wait_till_set_;
}
return true;
diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
index f5343ad5a2b..46357f60f00 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
@@ -55,11 +55,9 @@ class MinimizeWaiter : public X11PropertyChangeWaiter {
bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override {
std::vector<Atom> wm_states;
if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) {
- 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();
+ auto it = std::find(wm_states.cbegin(), wm_states.cend(),
+ atom_cache_->GetAtom("_NET_WM_STATE_HIDDEN"));
+ return it == wm_states.cend();
}
return true;
}
@@ -97,9 +95,8 @@ class StackingClientListWaiter : public X11PropertyChangeWaiter {
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())
+ auto it = std::find(stack.cbegin(), stack.cend(), expected_windows_[i]);
+ if (it == stack.cend())
return true;
}
return false;
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 a33f12ff76e..eca9951d2da 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
@@ -22,6 +22,7 @@
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
+#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/scoped_event_dispatcher.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/views/widget/desktop_aura/x11_pointer_grab.h"
@@ -81,7 +82,7 @@ uint32_t X11WholeScreenMoveLoop::DispatchEvent(const ui::PlatformEvent& event) {
case ui::ET_MOUSE_DRAGGED: {
bool dispatch_mouse_event = !last_motion_in_screen_.get();
last_motion_in_screen_.reset(
- static_cast<ui::MouseEvent*>(ui::EventFromNative(xev).release()));
+ ui::EventFromNative(xev).release()->AsMouseEvent());
last_motion_in_screen_->set_location(
ui::EventSystemLocationFromNative(xev));
if (dispatch_mouse_event) {
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 c8f1065d31e..c0ead5563fd 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
@@ -151,9 +151,8 @@ void X11WindowEventFilter::OnClickedMaximizeButton(ui::MouseEvent* event) {
if (!widget)
return;
- gfx::Screen* screen = gfx::Screen::GetNativeScreen();
gfx::Rect display_work_area =
- screen->GetDisplayNearestWindow(target).work_area();
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(target).work_area();
gfx::Rect bounds = widget->GetWindowBoundsInScreen();
if (event->IsMiddleMouseButton()) {
bounds.set_y(display_work_area.y());
diff --git a/chromium/ui/views/widget/desktop_widget_unittest.cc b/chromium/ui/views/widget/desktop_widget_unittest.cc
index 6bd67c6ee4a..0004ccab265 100644
--- a/chromium/ui/views/widget/desktop_widget_unittest.cc
+++ b/chromium/ui/views/widget/desktop_widget_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
@@ -18,7 +19,8 @@ TEST_F(DesktopScreenPositionClientTest, PositionDialog) {
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 PlatformDesktopNativeWidget(&parent_widget);
+ params.native_widget = test::CreatePlatformDesktopNativeWidgetImpl(
+ params, &parent_widget, nullptr);
parent_widget.Init(params);
// Owned by |dialog|.
@@ -52,7 +54,8 @@ TEST_F(DesktopScreenPositionClientTest, PositionControlWithNonRootParent) {
CreateParams(Widget::InitParams::TYPE_WINDOW);
params1.bounds = gfx::Rect(origin, gfx::Size(700, 600));
params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params1.native_widget = new PlatformDesktopNativeWidget(&widget1);
+ params1.native_widget =
+ test::CreatePlatformDesktopNativeWidgetImpl(params1, &widget1, nullptr);
widget1.Init(params1);
Widget::InitParams params2 =
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index fb2396c8399..4f24e5caced 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -137,8 +137,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
// If a parent is specified but no bounds are given,
// use the origin of the parent's display so that the widget
// will be added to the same display as the parent.
- gfx::Rect bounds = gfx::Screen::GetScreenFor(parent)->
- GetDisplayNearestWindow(parent).bounds();
+ gfx::Rect bounds =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(parent).bounds();
window_bounds.set_origin(bounds.origin());
}
}
@@ -283,8 +283,8 @@ void NativeWidgetAura::CenterWindow(const gfx::Size& size) {
// When centering window, we take the intersection of the host and
// the parent. We assume the root window represents the visible
// rect of a single screen.
- gfx::Rect work_area = gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(window_).work_area();
+ gfx::Rect work_area =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_).work_area();
aura::client::ScreenPositionClient* screen_position_client =
aura::client::GetScreenPositionClient(window_->GetRootWindow());
@@ -404,7 +404,7 @@ void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) {
aura::client::GetScreenPositionClient(root);
if (screen_position_client) {
gfx::Display dst_display =
- gfx::Screen::GetScreenFor(window_)->GetDisplayMatching(bounds);
+ gfx::Screen::GetScreen()->GetDisplayMatching(bounds);
screen_position_client->SetBounds(window_, bounds, dst_display);
return;
}
@@ -495,7 +495,10 @@ void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) {
// SetInitialFocus() should be always be called, even for
// SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
// do the right thing.
- SetInitialFocus(state);
+ // Activate() might fail if the window is non-activatable. In this case, we
+ // should pass SHOW_STATE_INACTIVE to SetInitialFocus() to stop the initial
+ // focused view from getting focused. See crbug.com/515594 for example.
+ SetInitialFocus(IsActive() ? state : ui::SHOW_STATE_INACTIVE);
}
// On desktop aura, a window is activated first even when it is shown as
@@ -595,10 +598,6 @@ void NativeWidgetAura::SetOpacity(unsigned char opacity) {
window_->layer()->SetOpacity(opacity / 255.0);
}
-void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) {
- NOTIMPLEMENTED();
-}
-
void NativeWidgetAura::FlashFrame(bool flash) {
if (window_)
window_->SetProperty(aura::client::kDrawAttentionKey, flash);
@@ -643,8 +642,7 @@ void NativeWidgetAura::ClearNativeFocus() {
gfx::Rect NativeWidgetAura::GetWorkAreaBoundsInScreen() const {
if (!window_)
return gfx::Rect();
- return gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(window_).work_area();
+ return gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_).work_area();
}
Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop(
@@ -875,7 +873,6 @@ void NativeWidgetAura::OnKeyEvent(ui::KeyEvent* event) {
return;
delegate_->OnKeyEvent(event);
- event->SetHandled();
}
void NativeWidgetAura::OnMouseEvent(ui::MouseEvent* event) {
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index 30bf169c784..9e27cca806b 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -42,8 +42,8 @@ class VIEWS_EXPORT NativeWidgetAura
public:
explicit NativeWidgetAura(internal::NativeWidgetDelegate* delegate);
- // Called internally by NativeWidget implementations to associate
- // |native_widget| with |window|.
+ // Called internally by NativeWidgetAura and DesktopNativeWidgetAura to
+ // associate |native_widget| with |window|.
static void RegisterNativeWidgetForWindow(
internal::NativeWidgetPrivate* native_widget,
aura::Window* window);
@@ -108,7 +108,6 @@ class VIEWS_EXPORT NativeWidgetAura
void SetFullscreen(bool fullscreen) override;
bool IsFullscreen() const override;
void SetOpacity(unsigned char opacity) override;
- void SetUseDragFrame(bool use_drag_frame) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
const ui::OSExchangeData& data,
diff --git a/chromium/ui/views/widget/native_widget_aura_unittest.cc b/chromium/ui/views/widget/native_widget_aura_unittest.cc
index f10981f2327..0a626ae45a1 100644
--- a/chromium/ui/views/widget/native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/native_widget_aura_unittest.cc
@@ -19,9 +19,12 @@
#include "ui/events/event_utils.h"
#include "ui/gfx/screen.h"
#include "ui/views/layout/fill_layout.h"
+#include "ui/views/test/widget_test.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/core/base_focus_rules.h"
#include "ui/wm/core/default_activation_client.h"
+#include "ui/wm/core/focus_controller.h"
namespace views {
namespace {
@@ -34,19 +37,50 @@ NativeWidgetAura* Init(aura::Window* parent, Widget* widget) {
return static_cast<NativeWidgetAura*>(widget->native_widget());
}
+// TestFocusRules is intended to provide a way to manually set a window's
+// activatability so that the focus rules can be tested.
+class TestFocusRules : public wm::BaseFocusRules {
+ public:
+ TestFocusRules() {}
+ ~TestFocusRules() override {}
+
+ void set_can_activate(bool can_activate) { can_activate_ = can_activate; }
+
+ // wm::BaseFocusRules overrides:
+ bool SupportsChildActivation(aura::Window* window) const override {
+ return true;
+ }
+
+ bool CanActivateWindow(aura::Window* window) const override {
+ return can_activate_;
+ }
+
+ private:
+ bool can_activate_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(TestFocusRules);
+};
+
class NativeWidgetAuraTest : public aura::test::AuraTestBase {
public:
NativeWidgetAuraTest() {}
~NativeWidgetAuraTest() override {}
+ TestFocusRules* test_focus_rules() { return test_focus_rules_; }
+
// testing::Test overrides:
void SetUp() override {
AuraTestBase::SetUp();
- new wm::DefaultActivationClient(root_window());
+ test_focus_rules_ = new TestFocusRules;
+ focus_controller_.reset(new wm::FocusController(test_focus_rules_));
+ aura::client::SetActivationClient(root_window(), focus_controller_.get());
host()->SetBounds(gfx::Rect(640, 480));
}
private:
+ scoped_ptr<wm::FocusController> focus_controller_;
+ TestFocusRules* test_focus_rules_;
+
DISALLOW_COPY_AND_ASSIGN(NativeWidgetAuraTest);
};
@@ -485,5 +519,20 @@ TEST_F(NativeWidgetAuraTest, OnWidgetMovedInvokedAfterAcquireLayer) {
widget->CloseNow();
}
+// Tests that if a widget has a view which should be initially focused when the
+// widget is shown, this view should not get focused if the associated window
+// can not be activated.
+TEST_F(NativeWidgetAuraTest, PreventFocusOnNonActivableWindow) {
+ test_focus_rules()->set_can_activate(false);
+ views::test::TestInitialFocusWidgetDelegate delegate(root_window());
+ delegate.GetWidget()->Show();
+ EXPECT_FALSE(delegate.view()->HasFocus());
+
+ test_focus_rules()->set_can_activate(true);
+ views::test::TestInitialFocusWidgetDelegate delegate2(root_window());
+ delegate2.GetWidget()->Show();
+ EXPECT_TRUE(delegate2.view()->HasFocus());
+}
+
} // namespace
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_delegate.h b/chromium/ui/views/widget/native_widget_delegate.h
index 224972c2d12..033db2bf107 100644
--- a/chromium/ui/views/widget/native_widget_delegate.h
+++ b/chromium/ui/views/widget/native_widget_delegate.h
@@ -51,8 +51,12 @@ class VIEWS_EXPORT NativeWidgetDelegate {
// Returns true if the window can be activated.
virtual bool CanActivate() const = 0;
- virtual bool IsInactiveRenderingDisabled() const = 0;
- virtual void EnableInactiveRendering() = 0;
+ // Prevents the window from being rendered as deactivated. This state is
+ // reset automatically as soon as the window becomes activated again. There is
+ // no ability to control the state through this API as this leads to sync
+ // problems.
+ virtual void SetAlwaysRenderAsActive(bool always_render_as_active) = 0;
+ virtual bool IsAlwaysRenderAsActive() const = 0;
// Called when the activation state of a window has changed.
virtual void OnNativeWidgetActivationChanged(bool active) = 0;
@@ -113,11 +117,10 @@ class VIEWS_EXPORT NativeWidgetDelegate {
// |point|, in client coordinates.
virtual int GetNonClientComponent(const gfx::Point& point) = 0;
- // Mouse and key event handlers.
+ // Event handlers.
virtual void OnKeyEvent(ui::KeyEvent* event) = 0;
virtual void OnMouseEvent(ui::MouseEvent* event) = 0;
virtual void OnMouseCaptureLost() = 0;
-
virtual void OnScrollEvent(ui::ScrollEvent* event) = 0;
virtual void OnGestureEvent(ui::GestureEvent* event) = 0;
@@ -133,7 +136,6 @@ class VIEWS_EXPORT NativeWidgetDelegate {
// Provides the hit-test mask if HasHitTestMask above returns true.
virtual void GetHitTestMask(gfx::Path* mask) const = 0;
- //
virtual Widget* AsWidget() = 0;
virtual const Widget* AsWidget() const = 0;
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index f2f79181a05..1b7deb2c801 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -107,7 +107,6 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
void SetFullscreen(bool fullscreen) override;
bool IsFullscreen() const override;
void SetOpacity(unsigned char opacity) override;
- void SetUseDragFrame(bool use_drag_frame) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
const ui::OSExchangeData& data,
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index f61ff8171a5..126623ff0e7 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -193,8 +193,10 @@ const ui::Layer* NativeWidgetMac::GetLayer() const {
}
void NativeWidgetMac::ReorderNativeViews() {
- if (bridge_)
+ if (bridge_) {
bridge_->SetRootView(GetWidget()->GetRootView());
+ bridge_->ReorderChildViews();
+ }
}
void NativeWidgetMac::ViewRemoved(View* view) {
@@ -410,6 +412,10 @@ void NativeWidgetMac::ShowWithWindowState(ui::WindowShowState state) {
bridge_->SetVisibilityState(state == ui::SHOW_STATE_INACTIVE
? BridgedNativeWidget::SHOW_INACTIVE
: BridgedNativeWidget::SHOW_AND_ACTIVATE_WINDOW);
+
+ // Ignore the SetInitialFocus() result. BridgedContentView should get
+ // firstResponder status regardless.
+ delegate_->SetInitialFocus(state);
}
bool NativeWidgetMac::IsVisible() const {
@@ -484,11 +490,7 @@ bool NativeWidgetMac::IsFullscreen() const {
}
void NativeWidgetMac::SetOpacity(unsigned char opacity) {
- NOTIMPLEMENTED();
-}
-
-void NativeWidgetMac::SetUseDragFrame(bool use_drag_frame) {
- NOTIMPLEMENTED();
+ [GetNativeWindow() setAlphaValue:opacity / 255.0];
}
void NativeWidgetMac::FlashFrame(bool flash_frame) {
@@ -504,9 +506,15 @@ void NativeWidgetMac::RunShellDrag(View* view,
}
void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
- // TODO(tapted): This should use setNeedsDisplayInRect:, once the coordinate
- // system of |rect| has been converted.
- [GetNativeView() setNeedsDisplay:YES];
+ // |rect| is relative to client area of the window.
+ NSWindow* window = GetNativeWindow();
+ NSRect client_rect = [window contentRectForFrameRect:[window frame]];
+ NSRect target_rect = rect.ToCGRect();
+
+ // Convert to Appkit coordinate system (origin at bottom left).
+ target_rect.origin.y =
+ NSHeight(client_rect) - target_rect.origin.y - NSHeight(target_rect);
+ [GetNativeView() setNeedsDisplayInRect:target_rect];
if (bridge_ && bridge_->layer())
bridge_->layer()->SchedulePaint(rect);
}
diff --git a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
index 8f192662b24..528f67d42a7 100644
--- a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
@@ -6,8 +6,10 @@
#import <Cocoa/Cocoa.h>
+#import "base/mac/mac_util.h"
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
+#include "ui/base/test/ui_controls.h"
#import "ui/base/test/windowed_nsnotification_observer.h"
#include "ui/views/test/test_widget_observer.h"
#include "ui/views/test/widget_test.h"
@@ -24,7 +26,11 @@ class NativeWidgetMacInteractiveUITest
class Observer;
NativeWidgetMacInteractiveUITest()
- : activationCount_(0), deactivationCount_(0) {}
+ : activationCount_(0), deactivationCount_(0) {
+ // TODO(tapted): Remove this when these are absorbed into Chrome's
+ // interactive_ui_tests target. See http://crbug.com/403679.
+ ui_controls::EnableUIControls();
+ }
Widget* MakeWidget() {
return GetParam() ? CreateTopLevelFramelessPlatformWidget()
@@ -133,6 +139,79 @@ TEST_P(NativeWidgetMacInteractiveUITest, ShowInactiveIgnoresKeyStatus) {
widget->CloseNow();
}
+namespace {
+
+// Show |widget| and wait for it to become the key window.
+void ShowKeyWindow(Widget* widget) {
+ base::scoped_nsobject<WindowedNSNotificationObserver> waiter(
+ [[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWindowDidBecomeKeyNotification
+ object:widget->GetNativeWindow()]);
+ widget->Show();
+ EXPECT_TRUE([waiter wait]);
+ EXPECT_TRUE([widget->GetNativeWindow() isKeyWindow]);
+}
+
+NSData* ViewAsTIFF(NSView* view) {
+ NSBitmapImageRep* bitmap =
+ [view bitmapImageRepForCachingDisplayInRect:[view bounds]];
+ [view cacheDisplayInRect:[view bounds] toBitmapImageRep:bitmap];
+ return [bitmap TIFFRepresentation];
+}
+
+} // namespace
+
+// Test that parent windows keep their traffic lights enabled when showing
+// dialogs.
+TEST_F(NativeWidgetMacInteractiveUITest, ParentWindowTrafficLights) {
+ Widget* parent_widget = CreateTopLevelPlatformWidget();
+ parent_widget->SetBounds(gfx::Rect(100, 100, 100, 100));
+ ShowKeyWindow(parent_widget);
+
+ NSWindow* parent = parent_widget->GetNativeWindow();
+ EXPECT_TRUE([parent isMainWindow]);
+
+ NSButton* button = [parent standardWindowButton:NSWindowCloseButton];
+ EXPECT_TRUE(button);
+ NSData* active_button_image = ViewAsTIFF(button);
+ EXPECT_TRUE(active_button_image);
+
+ // Create an activatable frameless child. Frameless so that it doesn't have
+ // traffic lights of its own, and activatable so that it can take key status.
+ Widget* child_widget = new Widget;
+ Widget::InitParams params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.native_widget = new NativeWidgetMac(child_widget);
+ params.bounds = gfx::Rect(130, 130, 100, 100);
+ params.parent = parent_widget->GetNativeView();
+ child_widget->Init(params);
+ ShowKeyWindow(child_widget);
+
+ // Ensure the button instance is still valid.
+ EXPECT_EQ(button, [parent standardWindowButton:NSWindowCloseButton]);
+
+ // Parent window should still be main, and have its traffic lights active.
+ EXPECT_TRUE([parent isMainWindow]);
+ EXPECT_FALSE([parent isKeyWindow]);
+
+ // Enabled status doesn't actually change, but check anyway.
+ EXPECT_TRUE([button isEnabled]);
+ NSData* button_image_with_child = ViewAsTIFF(button);
+ EXPECT_TRUE([active_button_image isEqualToData:button_image_with_child]);
+
+ // Verify that activating some other random window does change the button.
+ Widget* other_widget = CreateTopLevelPlatformWidget();
+ other_widget->SetBounds(gfx::Rect(200, 200, 100, 100));
+ ShowKeyWindow(other_widget);
+ EXPECT_FALSE([parent isMainWindow]);
+ EXPECT_FALSE([parent isKeyWindow]);
+ EXPECT_TRUE([button isEnabled]);
+ NSData* inactive_button_image = ViewAsTIFF(button);
+ EXPECT_FALSE([active_button_image isEqualToData:inactive_button_image]);
+
+ other_widget->CloseNow();
+ parent_widget->CloseNow();
+}
+
INSTANTIATE_TEST_CASE_P(NativeWidgetMacInteractiveUITestInstance,
NativeWidgetMacInteractiveUITest,
::testing::Bool());
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index 5a48f025722..ba095dfbeeb 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -22,13 +22,17 @@
#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/events/test/event_generator.h"
#import "ui/gfx/mac/coordinate_conversion.h"
+#include "ui/views/bubble/bubble_delegate.h"
#import "ui/views/cocoa/bridged_native_widget.h"
#import "ui/views/cocoa/native_widget_mac_nswindow.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
+#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/native_cursor.h"
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_widget_observer.h"
#include "ui/views/test/widget_test.h"
+#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/window/dialog_delegate.h"
@@ -53,6 +57,24 @@
@property(readonly, nonatomic) int invalidateShadowCount;
@end
+// Used to mock BridgedContentView so that calls to drawRect: can be
+// intercepted.
+@interface MockBridgedView : NSView {
+ @private
+ // Number of times -[NSView drawRect:] has been called.
+ NSUInteger drawRectCount_;
+
+ // The dirtyRect parameter passed to last invocation of drawRect:.
+ NSRect lastDirtyRect_;
+}
+
+@property(assign, nonatomic) NSUInteger drawRectCount;
+@property(assign, nonatomic) NSRect lastDirtyRect;
+@end
+
+@interface FocusableTestNSView : NSView
+@end
+
namespace views {
namespace test {
@@ -190,6 +212,30 @@ class WidgetChangeObserver : public TestWidgetObserver {
DISALLOW_COPY_AND_ASSIGN(WidgetChangeObserver);
};
+class NativeHostHolder {
+ public:
+ NativeHostHolder()
+ : view_([[NSView alloc] init]), host_(new NativeViewHost()) {
+ host_->set_owned_by_client();
+ }
+
+ void AttachNativeView() {
+ DCHECK(!host_->native_view());
+ host_->Attach(view_.get());
+ }
+
+ void Detach() { host_->Detach(); }
+
+ gfx::NativeView view() const { return view_.get(); }
+ NativeViewHost* host() const { return host_.get(); }
+
+ private:
+ base::scoped_nsobject<NSView> view_;
+ scoped_ptr<NativeViewHost> host_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeHostHolder);
+};
+
// Test visibility states triggered externally.
TEST_F(NativeWidgetMacTest, HideAndShowExternally) {
Widget* widget = CreateTopLevelPlatformWidget();
@@ -468,8 +514,9 @@ TEST_F(NativeWidgetMacTest, SetCursor) {
EXPECT_NE(arrow, hand);
EXPECT_NE(arrow, ibeam);
- // At the start of the test, the cursor stack should be empty.
- EXPECT_FALSE([NSCursor currentCursor]);
+ // Make arrow the current cursor.
+ [arrow set];
+ EXPECT_EQ(arrow, [NSCursor currentCursor]);
// Use an event generator to ask views code to set the cursor. However, note
// that this does not cause Cocoa to generate tracking rectangle updates.
@@ -477,7 +524,7 @@ TEST_F(NativeWidgetMacTest, SetCursor) {
widget->GetNativeWindow());
// Move the mouse over the first view, then simulate a tracking rectangle
- // update.
+ // update. Verify that the cursor changed from arrow to hand type.
event_generator.MoveMouseTo(gfx::Point(50, 50));
[widget->GetNativeWindow() cursorUpdate:event_in_content];
EXPECT_EQ(hand, [NSCursor currentCursor]);
@@ -534,12 +581,12 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
[[native_parent contentView] addSubview:anchor_view];
// Note: Don't use WidgetTest::CreateChildPlatformWidget because that makes
- // windows of TYPE_CONTROL which are automatically made visible. But still
- // mark it as a child to test window positioning.
+ // windows of TYPE_CONTROL which need a parent Widget to obtain the focus
+ // manager.
Widget* child = new Widget;
Widget::InitParams init_params;
init_params.parent = anchor_view;
- init_params.child = true;
+ init_params.type = Widget::InitParams::TYPE_POPUP;
child->Init(init_params);
TestWidgetObserver child_observer(child);
@@ -556,7 +603,8 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
NativeWidgetMac::GetBridgeForNativeWindow(child->GetNativeWindow());
EXPECT_EQ(native_parent, bridged_native_widget->parent()->GetNSWindow());
- child->SetBounds(gfx::Rect(50, 50, 200, 100));
+ const gfx::Rect child_bounds(50, 50, 200, 100);
+ child->SetBounds(child_bounds);
EXPECT_FALSE(child->IsVisible());
EXPECT_EQ(0u, [[native_parent childWindows] count]);
@@ -567,11 +615,9 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
[[native_parent childWindows] objectAtIndex:0]);
EXPECT_EQ(native_parent, [child->GetNativeWindow() parentWindow]);
- // Child should be positioned on screen relative to the parent, but note we
- // positioned the parent in Cocoa coordinates, so we need to convert.
- gfx::Point parent_origin = gfx::ScreenRectFromNSRect(ParentRect()).origin();
- EXPECT_EQ(gfx::Rect(150, parent_origin.y() + 50, 200, 100),
- child->GetWindowBoundsInScreen());
+ // Only non-toplevel Widgets are positioned relative to the parent, so the
+ // bounds set above should be in screen coordinates.
+ EXPECT_EQ(child_bounds, child->GetWindowBoundsInScreen());
// Removing the anchor_view from its view hierarchy is permitted. This should
// not break the relationship between the two windows.
@@ -918,6 +964,96 @@ TEST_F(NativeWidgetMacTest, NoopReparentNativeView) {
parent_widget->CloseNow();
}
+// Attaches a child window to |parent| that checks its parent's delegate is
+// cleared when the child is destroyed. This assumes the child is destroyed via
+// destruction of its parent.
+class ParentCloseMonitor : public WidgetObserver {
+ public:
+ explicit ParentCloseMonitor(Widget* parent) {
+ Widget* child = new Widget();
+ child->AddObserver(this);
+ Widget::InitParams init_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ init_params.parent = parent->GetNativeView();
+ init_params.bounds = gfx::Rect(100, 100, 100, 100);
+ init_params.native_widget =
+ CreatePlatformNativeWidgetImpl(init_params, child, kStubCapture,
+ nullptr);
+ child->Init(init_params);
+ child->Show();
+
+ // NSWindow parent/child relationship should be established on Show() and
+ // the parent should have a delegate. Retain the parent since it can't be
+ // retrieved from the child while it is being destroyed.
+ parent_nswindow_.reset([[child->GetNativeWindow() parentWindow] retain]);
+ EXPECT_TRUE(parent_nswindow_);
+ EXPECT_TRUE([parent_nswindow_ delegate]);
+ }
+
+ ~ParentCloseMonitor() override {
+ EXPECT_TRUE(child_closed_); // Otherwise the observer wasn't removed.
+ }
+
+ void OnWidgetDestroying(Widget* child) override {
+ // Upon a parent-triggered close, the NSWindow relationship will already be
+ // removed. The parent should still be open (children are always closed
+ // first), but not have a delegate (since it is being torn down).
+ EXPECT_FALSE([child->GetNativeWindow() parentWindow]);
+ EXPECT_TRUE([parent_nswindow_ isVisible]);
+ EXPECT_FALSE([parent_nswindow_ delegate]);
+
+ EXPECT_FALSE(child_closed_);
+ child->RemoveObserver(this);
+ child_closed_ = true;
+ }
+
+ bool child_closed() const { return child_closed_; }
+
+ private:
+ base::scoped_nsobject<NSWindow> parent_nswindow_;
+ bool child_closed_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ParentCloseMonitor);
+};
+
+// Ensures when a parent window is destroyed, and triggers its child windows to
+// be closed, that the child windows (via AppKit) do not attempt to call back
+// into the parent, whilst it's in the process of being destroyed.
+TEST_F(NativeWidgetMacTest, NoParentDelegateDuringTeardown) {
+ // First test "normal" windows and AppKit close.
+ {
+ Widget* parent = CreateTopLevelPlatformWidget();
+ parent->SetBounds(gfx::Rect(100, 100, 300, 200));
+ parent->Show();
+ ParentCloseMonitor monitor(parent);
+ [parent->GetNativeWindow() close];
+ EXPECT_TRUE(monitor.child_closed());
+ }
+
+ // Test the Widget::CloseNow() flow.
+ {
+ Widget* parent = CreateTopLevelPlatformWidget();
+ parent->SetBounds(gfx::Rect(100, 100, 300, 200));
+ parent->Show();
+ ParentCloseMonitor monitor(parent);
+ parent->CloseNow();
+ EXPECT_TRUE(monitor.child_closed());
+ }
+
+ // Test the WIDGET_OWNS_NATIVE_WIDGET flow.
+ {
+ scoped_ptr<Widget> parent(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(100, 100, 300, 200);
+ parent->Init(params);
+ parent->Show();
+
+ ParentCloseMonitor monitor(parent.get());
+ parent.reset();
+ EXPECT_TRUE(monitor.child_closed());
+ }
+}
+
// Tests Cocoa properties that should be given to particular widget types.
TEST_F(NativeWidgetMacTest, NativeProperties) {
// Create a regular widget (TYPE_WINDOW).
@@ -938,6 +1074,20 @@ TEST_F(NativeWidgetMacTest, NativeProperties) {
// Dialogs shouldn't take main status away from their parent.
EXPECT_FALSE([dialog_widget->GetNativeWindow() canBecomeMainWindow]);
+ // Create a bubble widget with a parent: also shouldn't get main.
+ BubbleDelegateView* bubble_view = new BubbleDelegateView();
+ bubble_view->set_parent_window(regular_widget->GetNativeView());
+ Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_view);
+ EXPECT_TRUE([bubble_widget->GetNativeWindow() canBecomeKeyWindow]);
+ EXPECT_FALSE([bubble_widget->GetNativeWindow() canBecomeMainWindow]);
+
+ // But a bubble without a parent should still be able to become main.
+ Widget* toplevel_bubble_widget =
+ BubbleDelegateView::CreateBubble(new BubbleDelegateView());
+ EXPECT_TRUE([toplevel_bubble_widget->GetNativeWindow() canBecomeKeyWindow]);
+ EXPECT_TRUE([toplevel_bubble_widget->GetNativeWindow() canBecomeMainWindow]);
+
+ toplevel_bubble_widget->CloseNow();
regular_widget->CloseNow();
}
@@ -991,7 +1141,8 @@ TEST_F(NativeWidgetMacTest, DoesHideTitle) {
// Same as CreateTopLevelPlatformWidget but with a custom delegate.
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
Widget* widget = new Widget;
- params.native_widget = new NativeWidgetCapture(widget);
+ params.native_widget =
+ CreatePlatformNativeWidgetImpl(params, widget, kStubCapture, nullptr);
CustomTitleWidgetDelegate delegate(widget);
params.delegate = &delegate;
params.bounds = gfx::Rect(0, 0, 800, 600);
@@ -1089,6 +1240,235 @@ TEST_F(NativeWidgetMacTest, GetWorkAreaBoundsInScreen) {
EXPECT_TRUE(NSIsEmptyRect(actual));
}
+// Test that Widget opacity can be changed.
+TEST_F(NativeWidgetMacTest, ChangeOpacity) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+ NSWindow* ns_window = widget->GetNativeWindow();
+
+ CGFloat old_opacity = [ns_window alphaValue];
+ widget->SetOpacity(0xAA);
+ EXPECT_NE(old_opacity, [ns_window alphaValue]);
+ EXPECT_DOUBLE_EQ(0xAA / 255.0, [ns_window alphaValue]);
+
+ widget->CloseNow();
+}
+
+// Test that NativeWidgetMac::SchedulePaintInRect correctly passes the dirtyRect
+// parameter to BridgedContentView::drawRect, for a titled window (window with a
+// toolbar).
+TEST_F(NativeWidgetMacTest, SchedulePaintInRect_Titled) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+
+ gfx::Rect screen_rect(50, 50, 100, 100);
+ widget->SetBounds(screen_rect);
+
+ // Setup the mock content view for the NSWindow, so that we can intercept
+ // drawRect.
+ NSWindow* window = widget->GetNativeWindow();
+ base::scoped_nsobject<MockBridgedView> mock_bridged_view(
+ [[MockBridgedView alloc] init]);
+ [window setContentView:mock_bridged_view];
+
+ // Ensure the initial draw of the window is done.
+ base::RunLoop().RunUntilIdle();
+
+ // Add a dummy view to the widget. This will cause SchedulePaint to be called
+ // on the dummy view.
+ View* dummy_view = new View();
+ gfx::Rect dummy_bounds(25, 30, 10, 15);
+ dummy_view->SetBoundsRect(dummy_bounds);
+ // Reset drawRect count.
+ [mock_bridged_view setDrawRectCount:0];
+ widget->GetContentsView()->AddChildView(dummy_view);
+
+ // SchedulePaint is asyncronous. Wait for drawRect: to be called.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1u, [mock_bridged_view drawRectCount]);
+ int client_area_height = widget->GetClientAreaBoundsInScreen().height();
+ // These are expected dummy_view bounds in AppKit coordinate system. The y
+ // coordinate of rect origin is calculated as:
+ // client_area_height - 30 (dummy_view's y coordinate) - 15 (dummy view's
+ // height).
+ gfx::Rect expected_appkit_bounds(25, client_area_height - 45, 10, 15);
+ EXPECT_NSEQ(expected_appkit_bounds.ToCGRect(),
+ [mock_bridged_view lastDirtyRect]);
+ widget->CloseNow();
+}
+
+// Test that NativeWidgetMac::SchedulePaintInRect correctly passes the dirtyRect
+// parameter to BridgedContentView::drawRect, for a borderless window.
+TEST_F(NativeWidgetMacTest, SchedulePaintInRect_Borderless) {
+ Widget* widget = CreateTopLevelFramelessPlatformWidget();
+
+ gfx::Rect screen_rect(50, 50, 100, 100);
+ widget->SetBounds(screen_rect);
+
+ // Setup the mock content view for the NSWindow, so that we can intercept
+ // drawRect.
+ NSWindow* window = widget->GetNativeWindow();
+ base::scoped_nsobject<MockBridgedView> mock_bridged_view(
+ [[MockBridgedView alloc] init]);
+ [window setContentView:mock_bridged_view];
+
+ // Ensure the initial draw of the window is done.
+ base::RunLoop().RunUntilIdle();
+
+ // Add a dummy view to the widget. This will cause SchedulePaint to be called
+ // on the dummy view.
+ View* dummy_view = new View();
+ gfx::Rect dummy_bounds(25, 30, 10, 15);
+ dummy_view->SetBoundsRect(dummy_bounds);
+ // Reset drawRect count.
+ [mock_bridged_view setDrawRectCount:0];
+ widget->GetRootView()->AddChildView(dummy_view);
+
+ // SchedulePaint is asyncronous. Wait for drawRect: to be called.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(1u, [mock_bridged_view drawRectCount]);
+ // These are expected dummy_view bounds in AppKit coordinate system. The y
+ // coordinate of rect origin is calculated as:
+ // 100(client area height) - 30 (dummy_view's y coordinate) - 15 (dummy view's
+ // height).
+ gfx::Rect expected_appkit_bounds(25, 55, 10, 15);
+ EXPECT_NSEQ(expected_appkit_bounds.ToCGRect(),
+ [mock_bridged_view lastDirtyRect]);
+ widget->CloseNow();
+}
+
+// Ensure traversing NSView focus correctly updates the views::FocusManager.
+TEST_F(NativeWidgetMacTest, ChangeFocusOnChangeFirstResponder) {
+ Widget* widget = CreateTopLevelPlatformWidget();
+ widget->GetRootView()->SetFocusable(true);
+ widget->Show();
+
+ base::scoped_nsobject<NSView> child_view([[FocusableTestNSView alloc]
+ initWithFrame:[widget->GetNativeView() bounds]]);
+ [widget->GetNativeView() addSubview:child_view];
+ EXPECT_TRUE([child_view acceptsFirstResponder]);
+ EXPECT_TRUE(widget->GetRootView()->IsFocusable());
+
+ FocusManager* manager = widget->GetFocusManager();
+ manager->SetFocusedView(widget->GetRootView());
+ EXPECT_EQ(manager->GetFocusedView(), widget->GetRootView());
+
+ [widget->GetNativeWindow() makeFirstResponder:child_view];
+ EXPECT_FALSE(manager->GetFocusedView());
+
+ [widget->GetNativeWindow() makeFirstResponder:widget->GetNativeView()];
+ EXPECT_EQ(manager->GetFocusedView(), widget->GetRootView());
+
+ widget->CloseNow();
+}
+
+class NativeWidgetMacViewsOrderTest : public WidgetTest {
+ public:
+ NativeWidgetMacViewsOrderTest() {}
+
+ protected:
+ // testing::Test:
+ void SetUp() override {
+ WidgetTest::SetUp();
+
+ widget_ = CreateTopLevelPlatformWidget();
+
+ ASSERT_EQ(1u, [[widget_->GetNativeView() subviews] count]);
+ compositor_view_ = [[widget_->GetNativeView() subviews] firstObject];
+
+ native_host_parent_ = new View();
+ widget_->GetContentsView()->AddChildView(native_host_parent_);
+
+ const int kNativeViewCount = 3;
+ for (int i = 0; i < kNativeViewCount; ++i) {
+ scoped_ptr<NativeHostHolder> holder(new NativeHostHolder());
+ native_host_parent_->AddChildView(holder->host());
+ holder->AttachNativeView();
+ hosts_.push_back(std::move(holder));
+ }
+ EXPECT_EQ(kNativeViewCount, native_host_parent_->child_count());
+ EXPECT_TRUE(([[widget_->GetNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view()
+ ]]));
+ }
+
+ void TearDown() override {
+ widget_->CloseNow();
+ WidgetTest::TearDown();
+ }
+
+ NSView* GetContentNativeView() { return widget_->GetNativeView(); }
+
+ Widget* widget_ = nullptr;
+ View* native_host_parent_ = nullptr;
+ NSView* compositor_view_ = nil;
+ std::vector<scoped_ptr<NativeHostHolder>> hosts_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacViewsOrderTest);
+};
+
+// Test that NativeViewHost::Attach()/Detach() method saves the NativeView
+// z-order.
+TEST_F(NativeWidgetMacViewsOrderTest, NativeViewAttached) {
+ hosts_[1]->Detach();
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[2]->view()
+ ]]));
+
+ hosts_[1]->AttachNativeView();
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
+ hosts_[2]->view()
+ ]]));
+}
+
+// Tests that NativeViews order changes according to views::View hierarchy.
+TEST_F(NativeWidgetMacViewsOrderTest, ReorderViews) {
+ native_host_parent_->ReorderChildView(hosts_[2]->host(), 1);
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[2]->view(),
+ hosts_[1]->view()
+ ]]));
+
+ native_host_parent_->RemoveChildView(hosts_[2]->host());
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[1]->view()
+ ]]));
+
+ View* new_parent = new View();
+ native_host_parent_->RemoveChildView(hosts_[1]->host());
+ native_host_parent_->AddChildView(new_parent);
+ new_parent->AddChildView(hosts_[1]->host());
+ new_parent->AddChildView(hosts_[2]->host());
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
+ hosts_[2]->view()
+ ]]));
+
+ native_host_parent_->ReorderChildView(new_parent, 0);
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[1]->view(), hosts_[2]->view(),
+ hosts_[0]->view()
+ ]]));
+}
+
+// Test that unassociated native views stay on top after reordering.
+TEST_F(NativeWidgetMacViewsOrderTest, UnassociatedViewsIsAbove) {
+ base::scoped_nsobject<NSView> child_view([[NSView alloc] init]);
+ [GetContentNativeView() addSubview:child_view];
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
+ hosts_[2]->view(), child_view
+ ]]));
+
+ native_host_parent_->ReorderChildView(hosts_[2]->host(), 1);
+ EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
+ compositor_view_, hosts_[0]->view(), hosts_[2]->view(),
+ hosts_[1]->view(), child_view
+ ]]));
+}
+
} // namespace test
} // namespace views
@@ -1108,3 +1488,21 @@ TEST_F(NativeWidgetMacTest, GetWorkAreaBoundsInScreen) {
}
@end
+
+@implementation MockBridgedView
+
+@synthesize drawRectCount = drawRectCount_;
+@synthesize lastDirtyRect = lastDirtyRect_;
+
+- (void)drawRect:(NSRect)dirtyRect {
+ ++drawRectCount_;
+ lastDirtyRect_ = dirtyRect;
+}
+
+@end
+
+@implementation FocusableTestNSView
+- (BOOL)acceptsFirstResponder {
+ return YES;
+}
+@end
diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h
index 6e52bf66749..777eaa226a4 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -194,7 +194,6 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual void SetFullscreen(bool fullscreen) = 0;
virtual bool IsFullscreen() const = 0;
virtual void SetOpacity(unsigned char opacity) = 0;
- virtual void SetUseDragFrame(bool use_drag_frame) = 0;
virtual void FlashFrame(bool flash) = 0;
virtual void RunShellDrag(View* view,
const ui::OSExchangeData& data,
diff --git a/chromium/ui/views/widget/tooltip_manager.h b/chromium/ui/views/widget/tooltip_manager.h
index 4287fc53d6a..e8074047340 100644
--- a/chromium/ui/views/widget/tooltip_manager.h
+++ b/chromium/ui/views/widget/tooltip_manager.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/strings/string16.h"
-#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
namespace gfx {
@@ -39,10 +38,8 @@ class VIEWS_EXPORT TooltipManager {
virtual ~TooltipManager() {}
// Returns the maximum width of the tooltip. |point| gives the location
- // the tooltip is to be displayed on in screen coordinates. |context| is
- // used to determine which gfx::Screen should be used.
- virtual int GetMaxWidth(const gfx::Point& location,
- gfx::NativeView context) const = 0;
+ // the tooltip is to be displayed on in screen coordinates.
+ virtual int GetMaxWidth(const gfx::Point& location) const = 0;
// Returns the font list used for tooltips.
virtual const gfx::FontList& GetFontList() const = 0;
diff --git a/chromium/ui/views/widget/tooltip_manager_aura.cc b/chromium/ui/views/widget/tooltip_manager_aura.cc
index 1c5bd26c32e..c4bf40ea856 100644
--- a/chromium/ui/views/widget/tooltip_manager_aura.cc
+++ b/chromium/ui/views/widget/tooltip_manager_aura.cc
@@ -49,7 +49,7 @@ void TooltipManagerAura::UpdateTooltipManagerForCapture(Widget* source) {
if (!screen_position_client)
return;
screen_position_client->ConvertPointToScreen(root_window, &screen_loc);
- gfx::Screen* screen = gfx::Screen::GetScreenFor(root_window);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc);
if (!target)
return;
@@ -81,10 +81,10 @@ const gfx::FontList& TooltipManagerAura::GetFontList() const {
return GetDefaultFontList();
}
-int TooltipManagerAura::GetMaxWidth(const gfx::Point& point,
- aura::Window* context) const {
- return aura::client::GetTooltipClient(context->GetRootWindow())->
- GetMaxWidth(point, context);
+int TooltipManagerAura::GetMaxWidth(const gfx::Point& point) const {
+ return aura::client::GetTooltipClient(
+ widget_->GetNativeView()->GetRootWindow())
+ ->GetMaxWidth(point);
}
void TooltipManagerAura::UpdateTooltip() {
diff --git a/chromium/ui/views/widget/tooltip_manager_aura.h b/chromium/ui/views/widget/tooltip_manager_aura.h
index 8d6bd9aff84..f429385525a 100644
--- a/chromium/ui/views/widget/tooltip_manager_aura.h
+++ b/chromium/ui/views/widget/tooltip_manager_aura.h
@@ -39,8 +39,7 @@ class TooltipManagerAura : public TooltipManager {
static const gfx::FontList& GetDefaultFontList();
// TooltipManager:
- int GetMaxWidth(const gfx::Point& location,
- aura::Window* context) const override;
+ int GetMaxWidth(const gfx::Point& location) const override;
const gfx::FontList& GetFontList() const override;
void UpdateTooltip() override;
void TooltipTextChanged(View* view) override;
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 02a570db6da..ffafd0d2bbb 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -10,6 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "ui/base/cursor/cursor.h"
+#include "ui/base/default_style.h"
#include "ui/base/default_theme_provider.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
@@ -110,30 +111,7 @@ class DefaultWidgetDelegate : public WidgetDelegate {
////////////////////////////////////////////////////////////////////////////////
// Widget, InitParams:
-Widget::InitParams::InitParams()
- : type(TYPE_WINDOW),
- delegate(nullptr),
- child(false),
- opacity(INFER_OPACITY),
- accept_events(true),
- activatable(ACTIVATABLE_DEFAULT),
- keep_on_top(false),
- visible_on_all_workspaces(false),
- ownership(NATIVE_WIDGET_OWNS_WIDGET),
- mirror_origin_in_rtl(false),
- shadow_type(SHADOW_TYPE_DEFAULT),
- remove_standard_frame(false),
- use_system_default_icon(false),
- show_state(ui::SHOW_STATE_DEFAULT),
- parent(nullptr),
- native_widget(nullptr),
- native_theme(nullptr),
- desktop_window_tree_host(nullptr),
- layer_type(ui::LAYER_TEXTURED),
- context(nullptr),
- force_show_in_taskbar(false),
- force_software_compositing(false) {
-}
+Widget::InitParams::InitParams() : InitParams(TYPE_WINDOW) {}
Widget::InitParams::InitParams(Type type)
: type(type),
@@ -152,7 +130,6 @@ Widget::InitParams::InitParams(Type type)
show_state(ui::SHOW_STATE_DEFAULT),
parent(nullptr),
native_widget(nullptr),
- native_theme(nullptr),
desktop_window_tree_host(nullptr),
layer_type(ui::LAYER_TEXTURED),
context(nullptr),
@@ -160,6 +137,8 @@ Widget::InitParams::InitParams(Type type)
force_software_compositing(false) {
}
+Widget::InitParams::InitParams(const InitParams& other) = default;
+
Widget::InitParams::~InitParams() {
}
@@ -168,14 +147,13 @@ Widget::InitParams::~InitParams() {
Widget::Widget()
: native_widget_(nullptr),
- native_theme_(nullptr),
widget_delegate_(nullptr),
non_client_view_(nullptr),
dragged_view_(nullptr),
ownership_(InitParams::NATIVE_WIDGET_OWNS_WIDGET),
is_secondary_widget_(true),
frame_type_(FRAME_TYPE_DEFAULT),
- disable_inactive_rendering_(false),
+ always_render_as_active_(false),
widget_closed_(false),
saved_show_state_(ui::SHOW_STATE_DEFAULT),
focus_on_creation_(true),
@@ -203,22 +181,6 @@ Widget::~Widget() {
}
// static
-Widget* Widget::CreateWindow(WidgetDelegate* delegate) {
- return CreateWindowWithBounds(delegate, gfx::Rect());
-}
-
-// static
-Widget* Widget::CreateWindowWithBounds(WidgetDelegate* delegate,
- const gfx::Rect& bounds) {
- Widget* widget = new Widget;
- Widget::InitParams params;
- params.bounds = bounds;
- params.delegate = delegate;
- widget->Init(params);
- return widget;
-}
-
-// static
Widget* Widget::CreateWindowWithParent(WidgetDelegate* delegate,
gfx::NativeView parent) {
return CreateWindowWithParentAndBounds(delegate, parent, gfx::Rect());
@@ -278,7 +240,6 @@ Widget* Widget::GetTopLevelWidgetForNativeView(gfx::NativeView native_view) {
return native_widget ? native_widget->GetWidget() : NULL;
}
-
// static
void Widget::GetAllChildWidgets(gfx::NativeView native_view,
Widgets* children) {
@@ -299,14 +260,16 @@ void Widget::ReparentNativeView(gfx::NativeView native_view,
// static
int Widget::GetLocalizedContentsWidth(int col_resource_id) {
- return ui::GetLocalizedContentsWidthForFont(col_resource_id,
- ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont));
+ return ui::GetLocalizedContentsWidthForFont(
+ col_resource_id, ResourceBundle::GetSharedInstance().GetFontWithDelta(
+ ui::kMessageFontSizeDelta));
}
// static
int Widget::GetLocalizedContentsHeight(int row_resource_id) {
- return ui::GetLocalizedContentsHeightForFont(row_resource_id,
- ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont));
+ return ui::GetLocalizedContentsHeightForFont(
+ row_resource_id, ResourceBundle::GetSharedInstance().GetFontWithDelta(
+ ui::kMessageFontSizeDelta));
}
// static
@@ -369,7 +332,6 @@ void Widget::Init(const InitParams& in_params) {
internal::NativeWidgetPrivate::IsMouseButtonDown();
}
native_widget_->InitNativeWidget(params);
- native_theme_ = params.native_theme;
if (RequiresNonClientView(params.type)) {
non_client_view_ = new NonClientView;
non_client_view_->SetFrameView(CreateNonClientFrameView());
@@ -532,9 +494,9 @@ void Widget::CenterWindow(const gfx::Size& size) {
}
void Widget::SetBoundsConstrained(const gfx::Rect& bounds) {
- gfx::Rect work_area =
- gfx::Screen::GetScreenFor(GetNativeView())->GetDisplayNearestPoint(
- bounds.origin()).work_area();
+ gfx::Rect work_area = gfx::Screen::GetScreen()
+ ->GetDisplayNearestPoint(bounds.origin())
+ .work_area();
if (work_area.IsEmpty()) {
SetBounds(bounds);
} else {
@@ -683,10 +645,6 @@ bool Widget::IsActive() const {
return native_widget_->IsActive();
}
-void Widget::DisableInactiveRendering() {
- SetInactiveRenderingDisabled(true);
-}
-
void Widget::SetAlwaysOnTop(bool on_top) {
native_widget_->SetAlwaysOnTop(on_top);
}
@@ -737,10 +695,6 @@ void Widget::SetOpacity(unsigned char opacity) {
native_widget_->SetOpacity(opacity);
}
-void Widget::SetUseDragFrame(bool use_drag_frame) {
- native_widget_->SetUseDragFrame(use_drag_frame);
-}
-
void Widget::FlashFrame(bool flash) {
native_widget_->FlashFrame(flash);
}
@@ -774,7 +728,7 @@ const ui::ThemeProvider* Widget::GetThemeProvider() const {
}
const ui::NativeTheme* Widget::GetNativeTheme() const {
- return native_theme_? native_theme_ : native_widget_->GetNativeTheme();
+ return native_widget_->GetNativeTheme();
}
FocusManager* Widget::GetFocusManager() {
@@ -1007,7 +961,7 @@ void Widget::SynthesizeMouseMoveEvent() {
// In screen coordinate.
gfx::Point mouse_location = EventMonitor::GetLastMouseLocation();
if (!GetWindowBoundsInScreen().Contains(mouse_location))
- return;
+ return;
// Convert: screen coordinate -> widget coordinate.
View::ConvertPointFromScreen(root_view_.get(), &mouse_location);
@@ -1031,8 +985,7 @@ void Widget::OnSizeConstraintsChanged() {
non_client_view_->SizeConstraintsChanged();
}
-void Widget::OnOwnerClosing() {
-}
+void Widget::OnOwnerClosing() {}
////////////////////////////////////////////////////////////////////////////////
// Widget, NativeWidgetDelegate implementation:
@@ -1049,12 +1002,8 @@ bool Widget::CanActivate() const {
return widget_delegate_->CanActivate();
}
-bool Widget::IsInactiveRenderingDisabled() const {
- return disable_inactive_rendering_;
-}
-
-void Widget::EnableInactiveRendering() {
- SetInactiveRenderingDisabled(false);
+bool Widget::IsAlwaysRenderAsActive() const {
+ return always_render_as_active_;
}
void Widget::OnNativeWidgetActivationChanged(bool active) {
@@ -1067,8 +1016,8 @@ void Widget::OnNativeWidgetActivationChanged(bool active) {
FOR_EACH_OBSERVER(WidgetObserver, observers_,
OnWidgetActivationChanged(this, active));
- if (IsVisible() && non_client_view())
- non_client_view()->frame_view()->SchedulePaint();
+ if (non_client_view())
+ non_client_view()->frame_view()->ActivationChanged(active);
}
void Widget::OnNativeFocus() {
@@ -1338,7 +1287,7 @@ bool Widget::SetInitialFocus(ui::WindowShowState show_state) {
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)
+ if (v && focus_manager_.get())
focus_manager_->SetStoredFocusView(v);
return true;
}
@@ -1401,22 +1350,24 @@ void Widget::DestroyRootView() {
root_view_.reset();
}
-void Widget::OnDragWillStart() {
-}
+void Widget::OnDragWillStart() {}
-void Widget::OnDragComplete() {
-}
+void Widget::OnDragComplete() {}
////////////////////////////////////////////////////////////////////////////////
// Widget, private:
-void Widget::SetInactiveRenderingDisabled(bool value) {
- if (value == disable_inactive_rendering_)
+void Widget::SetAlwaysRenderAsActive(bool always_render_as_active) {
+ if (always_render_as_active_ == always_render_as_active)
return;
- disable_inactive_rendering_ = value;
- if (non_client_view_)
- non_client_view_->SetInactiveRenderingDisabled(value);
+ always_render_as_active_ = always_render_as_active;
+
+ // If active, the frame should already be painted. Otherwise,
+ // |always_render_as_active_| just changed, and the widget is inactive, so
+ // schedule a repaint.
+ if (non_client_view_ && !IsActive())
+ non_client_view_->frame_view()->SchedulePaint();
}
void Widget::SaveWindowPlacement() {
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index 80aaddee1a6..0ceaf825ffb 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -97,8 +97,8 @@ class RootView;
// The Widget instance owns its NativeWidget. This state implies someone
// else wants to control the lifetime of this object. When they destroy
// the Widget it is responsible for destroying the NativeWidget (from its
-// destructor).
-//
+// destructor). This is often used to place a Widget in a scoped_ptr<> or
+// on the stack in a test.
class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
public ui::EventSource,
public FocusTraversable,
@@ -202,25 +202,27 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
InitParams();
explicit InitParams(Type type);
+ InitParams(const InitParams& other);
~InitParams();
Type type;
- // If NULL, a default implementation will be constructed.
+ // If null, a default implementation will be constructed. The default
+ // implementation deletes itself when the Widget closes.
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.
+ // fully opaque.
+ // Default is based on ViewsDelegate::GetOpacityForInitParams(). Defaults
+ // to OPAQUE_WINDOW for non-window widgets.
+ // Translucent windows may not always be supported. Use
+ // IsTranslucentWindowOpacitySupported to determine whether they are.
WindowOpacity opacity;
bool accept_events;
Activatable activatable;
bool keep_on_top;
bool visible_on_all_workspaces;
+ // See Widget class comment above.
Ownership ownership;
bool mirror_origin_in_rtl;
ShadowType shadow_type;
@@ -242,8 +244,6 @@ 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;
- // If provided, sets the native theme for this widget.
- ui::NativeTheme* native_theme;
// 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
@@ -273,23 +273,18 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// If true then the widget uses software compositing. Defaults to false.
// Only used on Windows.
bool force_software_compositing;
+
+ // Used if widget is not activatable to do determine if mouse events should
+ // be sent to the widget.
+ bool wants_mouse_events_when_inactive = false;
};
Widget();
~Widget() override;
- // Creates a toplevel window with no context. These methods should only be
- // used in cases where there is no contextual information because we're
- // creating a toplevel window connected to no other event.
- //
- // If you have any parenting or context information, or can pass that
- // information, prefer the WithParent or WithContext versions of these
- // methods.
- static Widget* CreateWindow(WidgetDelegate* delegate);
- static Widget* CreateWindowWithBounds(WidgetDelegate* delegate,
- const gfx::Rect& bounds);
-
- // Creates a decorated window Widget with the specified properties.
+ // Creates a decorated window Widget with the specified properties. The
+ // returned Widget is owned by its NativeWidget; see Widget class comment for
+ // details.
static Widget* CreateWindowWithParent(WidgetDelegate* delegate,
gfx::NativeView parent);
static Widget* CreateWindowWithParentAndBounds(WidgetDelegate* delegate,
@@ -297,6 +292,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
const gfx::Rect& bounds);
// Creates a decorated window Widget in the same desktop context as |context|.
+ // The returned Widget is owned by its NativeWidget; see Widget class comment
+ // for details.
static Widget* CreateWindowWithContext(WidgetDelegate* delegate,
gfx::NativeWindow context);
static Widget* CreateWindowWithContextAndBounds(WidgetDelegate* delegate,
@@ -498,12 +495,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Returns whether the Widget is the currently active window.
virtual bool IsActive() const;
- // Prevents the window from being rendered as deactivated. This state is
- // reset automatically as soon as the window becomes activated again. There is
- // no ability to control the state through this API as this leads to sync
- // problems.
- void DisableInactiveRendering();
-
// Sets the widget to be on top of all other widgets in the windowing system.
void SetAlwaysOnTop(bool on_top);
@@ -532,10 +523,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// underlying windowing system.
void SetOpacity(unsigned char opacity);
- // Sets whether or not the window should show its frame as a "transient drag
- // frame" - slightly transparent and without the standard window controls.
- void SetUseDragFrame(bool use_drag_frame);
-
// Flashes the frame of the window to draw attention to it. Currently only
// implemented on Windows for non-Aura.
void FlashFrame(bool flash);
@@ -565,7 +552,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
return const_cast<ui::NativeTheme*>(
const_cast<const Widget*>(this)->GetNativeTheme());
}
- const ui::NativeTheme* GetNativeTheme() const;
+ virtual const ui::NativeTheme* GetNativeTheme() const;
// Returns the FocusManager for this widget.
// Note that all widgets in a widget hierarchy share the same focus manager.
@@ -775,8 +762,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
bool IsModal() const override;
bool IsDialogBox() const override;
bool CanActivate() const override;
- bool IsInactiveRenderingDisabled() const override;
- void EnableInactiveRendering() override;
+ bool IsAlwaysRenderAsActive() const override;
+ void SetAlwaysRenderAsActive(bool always_render_as_active) override;
void OnNativeWidgetActivationChanged(bool active) override;
void OnNativeFocus() override;
void OnNativeBlur() override;
@@ -838,12 +825,9 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
private:
friend class ComboboxTest;
+ friend class CustomButtonTest;
friend class TextfieldTest;
- // Sets the value of |disable_inactive_rendering_|. If the value changes,
- // both the NonClientView and WidgetDelegate are notified.
- void SetInactiveRenderingDisabled(bool value);
-
// Persists the window's restored position and "show" state using the
// window delegate.
void SaveWindowPlacement();
@@ -866,10 +850,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
internal::NativeWidgetPrivate* native_widget_;
- // If non-null, the native theme for this widget. Otherwise the native theme
- // comes from |native_widget_|.
- ui::NativeTheme* native_theme_;
-
base::ObserverList<WidgetObserver> observers_;
base::ObserverList<WidgetRemovalsObserver> removals_observers_;
@@ -914,7 +894,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// True when the window should be rendered as active, regardless of whether
// or not it actually is.
- bool disable_inactive_rendering_;
+ bool always_render_as_active_;
// Set to true if the widget is in the process of closing.
bool widget_closed_;
diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc
index e62aa92847e..ced90b6f392 100644
--- a/chromium/ui/views/widget/widget_delegate.cc
+++ b/chromium/ui/views/widget/widget_delegate.cc
@@ -32,15 +32,19 @@ void WidgetDelegate::OnWorkAreaChanged() {
}
View* WidgetDelegate::GetInitiallyFocusedView() {
- return NULL;
+ return nullptr;
}
BubbleDelegateView* WidgetDelegate::AsBubbleDelegate() {
- return NULL;
+ return nullptr;
+}
+
+BubbleDialogDelegateView* WidgetDelegate::AsBubbleDialogDelegate() {
+ return nullptr;
}
DialogDelegate* WidgetDelegate::AsDialogDelegate() {
- return NULL;
+ return nullptr;
}
bool WidgetDelegate::CanResize() const {
@@ -80,7 +84,11 @@ bool WidgetDelegate::ShouldShowWindowTitle() const {
}
bool WidgetDelegate::ShouldShowCloseButton() const {
+#if defined(OS_MACOSX)
+ return false;
+#else
return true;
+#endif
}
bool WidgetDelegate::ShouldHandleSystemCommands() const {
diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h
index 660313d1648..0ec021505b6 100644
--- a/chromium/ui/views/widget/widget_delegate.h
+++ b/chromium/ui/views/widget/widget_delegate.h
@@ -19,6 +19,7 @@ class Rect;
}
namespace views {
+class BubbleDialogDelegateView;
class BubbleDelegateView;
class ClientView;
class DialogDelegate;
@@ -51,6 +52,7 @@ class VIEWS_EXPORT WidgetDelegate {
virtual View* GetInitiallyFocusedView();
virtual BubbleDelegateView* AsBubbleDelegate();
+ virtual BubbleDialogDelegateView* AsBubbleDialogDelegate();
virtual DialogDelegate* AsDialogDelegate();
// Returns true if the window can be resized.
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index fa5fb3954fc..e9f9397c01b 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -26,6 +26,7 @@
#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/test/focus_manager_test.h"
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/touchui/touch_selection_controller_impl.h"
#include "ui/views/widget/widget.h"
@@ -52,7 +53,7 @@ class ExitLoopOnRelease : public View {
~ExitLoopOnRelease() override {}
private:
- // Overridden from View:
+ // View:
void OnMouseReleased(const ui::MouseEvent& event) override {
GetWidget()->Close();
base::MessageLoop::current()->QuitNow();
@@ -68,7 +69,7 @@ class GestureCaptureView : public View {
~GestureCaptureView() override {}
private:
- // Overridden from View:
+ // View:
void OnGestureEvent(ui::GestureEvent* event) override {
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
GetWidget()->SetCapture(this);
@@ -132,7 +133,7 @@ class NestedLoopCaptureView : public View {
~NestedLoopCaptureView() override {}
private:
- // Overridden from View:
+ // View:
bool OnMousePressed(const ui::MouseEvent& event) override {
// Start a nested loop.
widget_->Show();
@@ -654,6 +655,7 @@ TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
}
widget->Show();
+ widget->GetNativeWindow()->GetHost()->Show();
const HWND hwnd = HWNDForWidget(widget);
EXPECT_TRUE(::IsWindow(hwnd));
EXPECT_TRUE(::IsWindowEnabled(hwnd));
@@ -740,6 +742,69 @@ TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
EXPECT_EQ(true, widget1.active());
EXPECT_EQ(false, widget2.active());
}
+
+// On Windows if we create a fullscreen window on a thread, then it affects the
+// way other windows on the thread interact with the taskbar. To workaround
+// this we reduce the bounds of a fullscreen window by 1px when it loses
+// activation. This test verifies the same.
+TEST_F(WidgetTestInteractive, FullscreenBoundsReducedOnActivationLoss) {
+ Widget widget1;
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget = new DesktopNativeWidgetAura(&widget1);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget1.Init(params);
+ widget1.SetBounds(gfx::Rect(0, 0, 200, 200));
+ widget1.Show();
+
+ widget1.Activate();
+ RunPendingMessages();
+ EXPECT_EQ(::GetActiveWindow(),
+ widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
+
+ widget1.SetFullscreen(true);
+ EXPECT_TRUE(widget1.IsFullscreen());
+ // Ensure that the StopIgnoringPosChanges task in HWNDMessageHandler runs.
+ // This task is queued when a widget becomes fullscreen.
+ RunPendingMessages();
+ EXPECT_EQ(::GetActiveWindow(),
+ widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
+ gfx::Rect fullscreen_bounds = widget1.GetWindowBoundsInScreen();
+
+ Widget widget2;
+ params.native_widget = new DesktopNativeWidgetAura(&widget2);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget2.Init(params);
+ widget2.SetBounds(gfx::Rect(0, 0, 200, 200));
+ widget2.Show();
+
+ widget2.Activate();
+ RunPendingMessages();
+ EXPECT_EQ(::GetActiveWindow(),
+ widget2.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
+
+ gfx::Rect fullscreen_bounds_after_activation_loss =
+ widget1.GetWindowBoundsInScreen();
+
+ // After deactivation loss the bounds of the fullscreen widget should be
+ // reduced by 1px.
+ EXPECT_EQ(fullscreen_bounds.height() -
+ fullscreen_bounds_after_activation_loss.height(), 1);
+
+ widget1.Activate();
+ RunPendingMessages();
+ EXPECT_EQ(::GetActiveWindow(),
+ widget1.GetNativeWindow()->GetHost()->GetAcceleratedWidget());
+
+ gfx::Rect fullscreen_bounds_after_activate =
+ widget1.GetWindowBoundsInScreen();
+
+ // After activation the bounds of the fullscreen widget should be restored.
+ EXPECT_EQ(fullscreen_bounds, fullscreen_bounds_after_activate);
+
+ widget1.CloseNow();
+ widget2.CloseNow();
+}
#endif // defined(OS_WIN)
#if !defined(OS_CHROMEOS)
@@ -774,8 +839,8 @@ TEST_F(WidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
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 PlatformDesktopNativeWidget(&top_level_widget);
+ init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ init_params, &top_level_widget, nullptr);
top_level_widget.Init(init_params);
ShowSync(&top_level_widget);
@@ -843,8 +908,8 @@ TEST_F(WidgetTestInteractive, MAYBE_SystemModalWindowReleasesCapture) {
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 PlatformDesktopNativeWidget(&top_level_widget);
+ init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ init_params, &top_level_widget, nullptr);
top_level_widget.Init(init_params);
ShowSync(&top_level_widget);
@@ -881,9 +946,8 @@ TEST_F(WidgetTestInteractive, CanActivateFlagIsHonored) {
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 PlatformDesktopNativeWidget(&widget);
-#endif // !defined(OS_CHROMEOS)
+ init_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr);
widget.Init(init_params);
widget.Show();
@@ -1048,7 +1112,8 @@ TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) {
Widget widget2;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(&widget2);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, &widget2, nullptr);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget2.Init(params);
widget2.Show();
@@ -1107,9 +1172,35 @@ TEST_F(WidgetTestInteractive, MAYBE_ExitFullscreenRestoreState) {
RunPendingMessages();
}
+// Testing initial focus is assigned properly for normal top-level widgets,
+// and subclasses that specify a initially focused child view.
+TEST_F(WidgetTestInteractive, InitialFocus) {
+ // By default, there is no initially focused view (even if there is a
+ // focusable subview).
+ Widget* toplevel(CreateTopLevelPlatformWidget());
+ View* view = new View;
+ view->SetFocusable(true);
+ toplevel->GetContentsView()->AddChildView(view);
+
+ ShowSync(toplevel);
+ toplevel->Show();
+ EXPECT_FALSE(view->HasFocus());
+ EXPECT_FALSE(toplevel->GetFocusManager()->GetStoredFocusView());
+ toplevel->CloseNow();
+
+ // Testing a widget which specifies a initially focused view.
+ TestInitialFocusWidgetDelegate delegate(GetContext());
+
+ Widget* widget = delegate.GetWidget();
+ ShowSync(widget);
+ widget->Show();
+ EXPECT_TRUE(delegate.view()->HasFocus());
+ EXPECT_EQ(delegate.view(), widget->GetFocusManager()->GetStoredFocusView());
+}
+
namespace {
-// Used to veirfy OnMouseCaptureLost() has been invoked.
+// Used to verify OnMouseCaptureLost() has been invoked.
class CaptureLostTrackingWidget : public Widget {
public:
CaptureLostTrackingWidget() : got_capture_lost_(false) {}
@@ -1157,8 +1248,8 @@ class WidgetCaptureTest : public ViewsTestBase {
CaptureLostTrackingWidget widget1;
Widget::InitParams params1 =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
- params1.native_widget = CreateNativeWidget(use_desktop_native_widget,
- &widget1);
+ params1.native_widget =
+ CreateNativeWidget(params1, use_desktop_native_widget, &widget1);
params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget1.Init(params1);
widget1.Show();
@@ -1167,8 +1258,8 @@ class WidgetCaptureTest : public ViewsTestBase {
Widget::InitParams params2 =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params2.native_widget = CreateNativeWidget(use_desktop_native_widget,
- &widget2);
+ params2.native_widget =
+ CreateNativeWidget(params2, use_desktop_native_widget, &widget2);
widget2.Init(params2);
widget2.Show();
@@ -1194,13 +1285,12 @@ class WidgetCaptureTest : public ViewsTestBase {
EXPECT_FALSE(widget2.GetAndClearGotCaptureLost());
}
- NativeWidget* CreateNativeWidget(bool create_desktop_native_widget,
+ NativeWidget* CreateNativeWidget(const Widget::InitParams& params,
+ bool create_desktop_native_widget,
Widget* widget) {
-#if !defined(OS_CHROMEOS)
if (create_desktop_native_widget)
- return new PlatformDesktopNativeWidget(widget);
-#endif
- return NULL;
+ return CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr);
+ return CreatePlatformNativeWidgetImpl(params, widget, kDefault, nullptr);
}
private:
@@ -1266,7 +1356,7 @@ TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) {
Widget widget1;
Widget::InitParams params1 =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params1.native_widget = CreateNativeWidget(true, &widget1);
+ params1.native_widget = CreateNativeWidget(params1, true, &widget1);
params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget1.Init(params1);
MouseView* mouse_view1 = new MouseView;
@@ -1277,7 +1367,7 @@ TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) {
Widget widget2;
Widget::InitParams params2 =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- params2.native_widget = CreateNativeWidget(true, &widget2);
+ params2.native_widget = CreateNativeWidget(params2, true, &widget2);
params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget2.Init(params2);
widget2.Show();
@@ -1329,7 +1419,8 @@ TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) {
Widget toplevel;
Widget::InitParams toplevel_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- toplevel_params.native_widget = CreateNativeWidget(true, &toplevel);
+ toplevel_params.native_widget = CreateNativeWidget(toplevel_params, true,
+ &toplevel);
toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
toplevel.Init(toplevel_params);
toplevel.Show();
diff --git a/chromium/ui/views/widget/widget_removals_observer.h b/chromium/ui/views/widget/widget_removals_observer.h
index e62acab36a4..d7046073c4d 100644
--- a/chromium/ui/views/widget/widget_removals_observer.h
+++ b/chromium/ui/views/widget/widget_removals_observer.h
@@ -18,7 +18,11 @@ class View;
// from |View|.
class VIEWS_EXPORT WidgetRemovalsObserver {
public:
- // Called immediately before a descendant view of |widget| is removed.
+ // Called immediately before a descendant view of |widget| is removed
+ // from this widget. Won't be called if the view is moved within the
+ // same widget, but will be called if it's moved to a different widget.
+ // Only called on the root of a view tree; it implies that all of the
+ // descendants of |view| will be removed.
virtual void OnWillRemoveView(Widget* widget, View* view) {}
protected:
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index 41bbe8198d7..0b8c645a5ea 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -23,12 +23,15 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/test_widget_observer.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/native_widget_delegate.h"
+#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget_deletion_observer.h"
+#include "ui/views/widget/widget_removals_observer.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/window/native_frame_view.h"
@@ -42,7 +45,6 @@
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
-#include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
#endif
namespace views {
@@ -59,15 +61,6 @@ gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) {
return tmp;
}
-// Helper function for Snow Leopard special cases to avoid #ifdef litter.
-bool IsTestingSnowLeopard() {
-#if defined(OS_MACOSX)
- return base::mac::IsOSSnowLeopard();
-#else
- return false;
-#endif
-}
-
// This class can be used as a deleter for scoped_ptr<Widget>
// to call function Widget::CloseNow automatically.
struct WidgetCloser {
@@ -367,44 +360,6 @@ struct OwnershipTestState {
bool native_widget_deleted;
};
-// A platform NativeWidget subclass that updates a bag of state when it is
-// destroyed.
-class OwnershipTestNativeWidget : public PlatformNativeWidget {
- public:
- OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
- OwnershipTestState* state)
- : PlatformNativeWidget(delegate),
- state_(state) {
- }
- ~OwnershipTestNativeWidget() override {
- state_->native_widget_deleted = true;
- }
-
- private:
- OwnershipTestState* state_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget);
-};
-
-// A views NativeWidget subclass that updates a bag of state when it is
-// destroyed.
-class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
- public:
- OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
- OwnershipTestState* state)
- : NativeWidgetCapture(delegate),
- state_(state) {
- }
- ~OwnershipTestNativeWidgetAura() override {
- state_->native_widget_deleted = true;
- }
-
- private:
- OwnershipTestState* state_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura);
-};
-
// A Widget subclass that updates a bag of state when it is destroyed.
class OwnershipTestWidget : public Widget {
public:
@@ -417,6 +372,8 @@ class OwnershipTestWidget : public Widget {
DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget);
};
+// TODO(sky): add coverage of ownership for the desktop variants.
+
// Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
// widget.
TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
@@ -424,8 +381,8 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget.get(), kStubCapture, &state.native_widget_deleted);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -445,8 +402,8 @@ TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget.get(), kStubCapture, &state.native_widget_deleted);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -470,9 +427,9 @@ TEST_F(WidgetOwnershipTest,
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
params.parent = toplevel->GetNativeView();
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget.get(), kStubCapture, &state.native_widget_deleted);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget->Init(params);
@@ -500,8 +457,8 @@ TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget, kStubCapture, &state.native_widget_deleted);
widget->Init(params);
// Now destroy the native widget.
@@ -519,9 +476,9 @@ TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget, kStubCapture, &state.native_widget_deleted);
widget->Init(params);
// Now destroy the native widget. This is achieved by closing the toplevel.
@@ -543,8 +500,8 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget, kStubCapture, &state.native_widget_deleted);
widget->Init(params);
// Now simulate a destroy of the platform native widget from the OS:
@@ -564,9 +521,9 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget, kStubCapture, &state.native_widget_deleted);
widget->Init(params);
// Destroy the widget (achieved by closing the toplevel).
@@ -590,9 +547,9 @@ TEST_F(WidgetOwnershipTest,
Widget* widget = new OwnershipTestWidget(&state);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
params.parent = toplevel->GetNativeView();
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget, kStubCapture, &state.native_widget_deleted);
widget->Init(params);
// Destroy the widget.
@@ -616,8 +573,8 @@ TEST_F(WidgetOwnershipTest,
scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
+ params.native_widget = CreatePlatformNativeWidgetImpl(
+ params, widget.get(), kStubCapture, &state.native_widget_deleted);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.delegate = delegate_view;
widget->Init(params);
@@ -658,7 +615,6 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
widget->Activate();
widget->Deactivate();
widget->IsActive();
- widget->DisableInactiveRendering();
widget->SetAlwaysOnTop(true);
widget->IsAlwaysOnTop();
widget->Maximize();
@@ -667,7 +623,6 @@ class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
widget->IsMaximized();
widget->IsFullscreen();
widget->SetOpacity(0);
- widget->SetUseDragFrame(true);
widget->FlashFrame(true);
widget->IsVisible();
widget->GetThemeProvider();
@@ -706,7 +661,8 @@ TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
{
Widget widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(&widget);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(params);
widget.Show();
@@ -971,6 +927,11 @@ TEST_F(WidgetObserverTest, ClosingOnHiddenParent) {
// Test behavior of NativeWidget*::GetWindowPlacement on the native desktop.
TEST_F(WidgetTest, GetWindowPlacement) {
+ if (IsMus()) {
+ NOTIMPLEMENTED();
+ return;
+ }
+
WidgetAutoclosePtr widget;
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// On desktop-Linux cheat and use non-desktop widgets. On X11, minimize is
@@ -1081,10 +1042,12 @@ TEST_F(WidgetTest, MinimumSizeConstraints) {
widget->SetSize(smaller_size);
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
// TODO(tapted): Desktop Linux ignores size constraints for SetSize. Fix it.
- EXPECT_EQ(smaller_size, widget->GetClientAreaBoundsInScreen().size());
+ const bool use_small_size = IsMus() ? false : true;
#else
- EXPECT_EQ(minimum_size, widget->GetClientAreaBoundsInScreen().size());
+ const bool use_small_size = false;
#endif
+ EXPECT_EQ(use_small_size ? smaller_size : minimum_size,
+ widget->GetClientAreaBoundsInScreen().size());
}
// Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the
@@ -1155,10 +1118,10 @@ TEST_F(WidgetTest, GetWindowBoundsInScreen) {
// Test that GetRestoredBounds() returns the original bounds of the window.
TEST_F(WidgetTest, MAYBE_GetRestoredBounds) {
-#if defined(OS_MACOSX)
- // Fullscreen on Mac requires an interactive UI test, fake them here.
- ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen;
-#endif
+ if (IsMus()) {
+ NOTIMPLEMENTED();
+ return;
+ }
WidgetAutoclosePtr toplevel(CreateNativeDesktopWidget());
toplevel->Show();
@@ -1188,14 +1151,8 @@ TEST_F(WidgetTest, MAYBE_GetRestoredBounds) {
toplevel->SetFullscreen(true);
RunPendingMessages();
- if (IsTestingSnowLeopard()) {
- // Fullscreen not implemented for Snow Leopard.
- EXPECT_EQ(toplevel->GetWindowBoundsInScreen(),
- toplevel->GetRestoredBounds());
- } else {
- EXPECT_NE(toplevel->GetWindowBoundsInScreen(),
- toplevel->GetRestoredBounds());
- }
+ EXPECT_NE(toplevel->GetWindowBoundsInScreen(),
+ toplevel->GetRestoredBounds());
EXPECT_EQ(bounds, toplevel->GetRestoredBounds());
toplevel->SetFullscreen(false);
@@ -1239,7 +1196,8 @@ 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 PlatformDesktopNativeWidget(&widget);
+ init_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr);
#endif
widget.Init(init_params);
widget.SetContentsView(contents_view);
@@ -1301,6 +1259,10 @@ TEST_F(WidgetTest, BubbleControlsResetOnInit) {
// the case for desktop widgets on Windows. Other platforms retain the window
// size while minimized.
TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
+ if (IsMus()) {
+ // This test is testing behavior specific to DesktopWindowTreeHostWin.
+ return;
+ }
// Create a widget.
Widget widget;
Widget::InitParams init_params =
@@ -1309,7 +1271,8 @@ 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 PlatformDesktopNativeWidget(&widget);
+ init_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr);
widget.Init(init_params);
NonClientView* non_client_view = widget.non_client_view();
NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
@@ -1383,7 +1346,8 @@ class DesktopAuraTestValidPaintWidget : public views::Widget {
void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params) {
init_params.bounds = gfx::Rect(0, 0, 200, 200);
init_params.ownership = InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new PlatformDesktopNativeWidget(this);
+ init_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(init_params, this, nullptr);
Init(init_params);
View* contents_view = new View;
@@ -1394,7 +1358,14 @@ void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params) {
Activate();
}
-TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
+#if defined(OS_LINUX)
+// Flaky on Linux rel ng: https://crbug.com/596039.
+#define MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest DISABLED_DesktopNativeWidgetNoPaintAfterCloseTest
+#else
+#define MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest DesktopNativeWidgetNoPaintAfterCloseTest
+#endif
+
+TEST_F(WidgetTest, MAYBE_DesktopNativeWidgetNoPaintAfterCloseTest) {
DesktopAuraTestValidPaintWidget widget;
widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS));
RunPendingMessages();
@@ -1406,7 +1377,12 @@ TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
EXPECT_FALSE(widget.received_paint_while_hidden());
}
-TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) {
+#if defined(OS_LINUX)
+#define MAYBE_DesktopNativeWidgetNoPaintAfterHideTest DISABLED_DesktopNativeWidgetNoPaintAfterHideTest
+#else
+#define MAYBE_DesktopNativeWidgetNoPaintAfterHideTest DesktopNativeWidgetNoPaintAfterHideTest
+#endif
+TEST_F(WidgetTest, MAYBE_DesktopNativeWidgetNoPaintAfterHideTest) {
DesktopAuraTestValidPaintWidget widget;
widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS));
RunPendingMessages();
@@ -1430,7 +1406,8 @@ 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 PlatformDesktopNativeWidget(&widget);
+ init_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(init_params, &widget, nullptr);
widget.Init(init_params);
NonClientView* non_client_view = widget.non_client_view();
NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
@@ -1690,7 +1667,9 @@ TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_MOVED));
gfx::Point cursor_location(5, 5);
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
+ ui::test::EventGenerator generator(
+ IsMus() ? widget->GetNativeWindow() : GetContext(),
+ widget->GetNativeWindow());
generator.MoveMouseTo(cursor_location);
EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_MOVED));
@@ -1734,7 +1713,7 @@ class MousePressEventConsumer : public ui::EventHandler {
// Test that mouse presses and mouse releases are dispatched normally when a
// touch is down.
TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
- WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
+ Widget* widget = CreateTopLevelNativeWidget();
widget->Show();
widget->SetSize(gfx::Size(300, 300));
@@ -1745,12 +1724,17 @@ TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
MousePressEventConsumer consumer;
event_count_view->AddPostTargetHandler(&consumer);
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.PressTouch();
- generator.ClickLeftButton();
+ scoped_ptr<ui::test::EventGenerator> generator(new ui::test::EventGenerator(
+ IsMus() ? widget->GetNativeWindow() : GetContext(),
+ widget->GetNativeWindow()));
+ generator->PressTouch();
+ generator->ClickLeftButton();
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED));
+
+ // For mus it's important we destroy the widget before the EventGenerator.
+ widget->CloseNow();
}
#endif // !defined(OS_MACOSX) || defined(USE_AURA)
@@ -1771,15 +1755,16 @@ class WidgetWindowTitleTest : public WidgetTest {
WidgetAutoclosePtr widget(new Widget()); // Destroyed by CloseNow().
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
- widget->Init(init_params);
#if !defined(OS_CHROMEOS)
if (desktop_native_widget)
- init_params.native_widget = new PlatformDesktopNativeWidget(widget.get());
+ init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ init_params, widget.get(), nullptr);
#else
DCHECK(!desktop_native_widget)
<< "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
#endif
+ widget->Init(init_params);
internal::NativeWidgetPrivate* native_widget =
widget->native_widget_private();
@@ -1821,6 +1806,14 @@ TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
#endif // !OS_CHROMEOS
TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
+ // This test doesn't work in mus as it assumes widget and GetContext()
+ // share an aura hierarchy. Test coverage of deletion from mouse pressed is
+ // important though and should be added, hence the NOTIMPLEMENTED().
+ // http://crbug.com/594260.
+ if (IsMus()) {
+ NOTIMPLEMENTED();
+ return;
+ }
Widget* widget = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
@@ -1844,6 +1837,9 @@ TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
#if !defined(OS_MACOSX) || defined(USE_AURA)
TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
+ // This test doesn't make sense for mus. Force NativeWidgetAura to be used.
+ DisableNativeWidgetMus();
+
Widget* widget = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
@@ -1895,7 +1891,8 @@ bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
params.delegate = new GetNativeThemeFromDestructorView;
#if !defined(OS_CHROMEOS)
if (is_first_run) {
- params.native_widget = new PlatformDesktopNativeWidget(widget.get());
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, widget.get(), nullptr);
needs_second_run = true;
}
#endif
@@ -1979,7 +1976,8 @@ TEST_F(WidgetTest, CloseDestroys) {
CreateParams(views::Widget::InitParams::TYPE_MENU);
params.opacity = Widget::InitParams::OPAQUE_WINDOW;
#if !defined(OS_CHROMEOS)
- params.native_widget = new PlatformDesktopNativeWidget(widget);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, widget, nullptr);
#endif
widget->Init(params);
widget->Show();
@@ -2906,8 +2904,10 @@ class WidgetChildDestructionTest : public WidgetTest {
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
#if !defined(OS_CHROMEOS)
- if (top_level_has_desktop_native_widget_aura)
- params.native_widget = new PlatformDesktopNativeWidget(top_level);
+ if (top_level_has_desktop_native_widget_aura) {
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, top_level, nullptr);
+ }
#endif
top_level->Init(params);
top_level->GetRootView()->AddChildView(
@@ -2919,8 +2919,10 @@ class WidgetChildDestructionTest : public WidgetTest {
CreateParams(views::Widget::InitParams::TYPE_POPUP);
child_params.parent = top_level->GetNativeView();
#if !defined(OS_CHROMEOS)
- if (child_has_desktop_native_widget_aura)
- child_params.native_widget = new PlatformDesktopNativeWidget(child);
+ if (child_has_desktop_native_widget_aura) {
+ child_params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(child_params, child, nullptr);
+ }
#endif
child->Init(child_params);
child->GetRootView()->AddChildView(
@@ -2970,27 +2972,34 @@ TEST_F(WidgetTest, FullscreenStatePropagated) {
init_params.bounds = gfx::Rect(0, 0, 500, 500);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- {
- Widget top_level_widget;
- top_level_widget.Init(init_params);
- top_level_widget.SetFullscreen(true);
- EXPECT_EQ(top_level_widget.IsVisible(),
- IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
- top_level_widget.CloseNow();
- }
+ Widget top_level_widget;
+ top_level_widget.Init(init_params);
+ top_level_widget.SetFullscreen(true);
+ EXPECT_EQ(top_level_widget.IsVisible(),
+ IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
+ top_level_widget.CloseNow();
+}
+
+// Verifies nativeview visbility matches that of Widget visibility when
+// SetFullscreen is invoked, for a widget provided with a desktop widget.
#if !defined(OS_CHROMEOS)
- {
- Widget 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(),
- IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
- top_level_widget.CloseNow();
- }
-#endif
+TEST_F(WidgetTest, FullscreenStatePropagated_DesktopWidget) {
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ init_params.show_state = ui::SHOW_STATE_NORMAL;
+ init_params.bounds = gfx::Rect(0, 0, 500, 500);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ Widget top_level_widget;
+ init_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ init_params, &top_level_widget, nullptr);
+
+ top_level_widget.Init(init_params);
+ top_level_widget.SetFullscreen(true);
+ EXPECT_EQ(top_level_widget.IsVisible(),
+ IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
+ top_level_widget.CloseNow();
}
+#endif
namespace {
@@ -3045,12 +3054,7 @@ TEST_F(WidgetTest, FullscreenFrameLayout) {
widget->Show();
RunPendingMessages();
- if (IsTestingSnowLeopard()) {
- // Fullscreen is currently ignored on Snow Leopard.
- EXPECT_FALSE(frame->fullscreen_layout_called());
- } else {
- EXPECT_TRUE(frame->fullscreen_layout_called());
- }
+ EXPECT_TRUE(frame->fullscreen_layout_called());
}
#if !defined(OS_CHROMEOS)
@@ -3078,7 +3082,8 @@ TEST_F(WidgetTest, IsActiveFromDestroy) {
Widget parent_widget;
Widget::InitParams parent_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
- parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget);
+ parent_params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
+ parent_params, &parent_widget, nullptr);
parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
parent_widget.Init(parent_params);
parent_widget.Show();
@@ -3183,37 +3188,13 @@ TEST_F(WidgetTest, NonClientWindowValidAfterInit) {
}
#if defined(OS_WIN)
-// This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR
-// messages via the WindowEventTarget interface implemented by the
-// HWNDMessageHandler class does not cause a crash due to an unprocessed
-// event
-TEST_F(WidgetTest, CharMessagesAsKeyboardMessagesDoesNotCrash) {
- Widget widget;
- Widget::InitParams params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- params.native_widget = new PlatformDesktopNativeWidget(&widget);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget.Init(params);
- widget.Show();
-
- ui::WindowEventTarget* target =
- reinterpret_cast<ui::WindowEventTarget*>(ui::ViewProp::GetValue(
- widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
- ui::WindowEventTarget::kWin32InputEventTarget));
- EXPECT_NE(nullptr, target);
- bool handled = false;
- target->HandleKeyboardMessage(WM_CHAR, 0, 0, &handled);
- target->HandleKeyboardMessage(WM_SYSCHAR, 0, 0, &handled);
- target->HandleKeyboardMessage(WM_SYSDEADCHAR, 0, 0, &handled);
- widget.CloseNow();
-}
-
// Provides functionality to subclass a window and keep track of messages
// received.
class SubclassWindowHelper {
public:
explicit SubclassWindowHelper(HWND window)
- : window_(window) {
+ : window_(window),
+ message_to_destroy_on_(0) {
EXPECT_EQ(instance_, nullptr);
instance_ = this;
EXPECT_TRUE(Subclass());
@@ -3233,6 +3214,10 @@ class SubclassWindowHelper {
messages_.clear();
}
+ void set_message_to_destroy_on(unsigned int message) {
+ message_to_destroy_on_ = message;
+ }
+
private:
bool Subclass() {
old_proc_ = reinterpret_cast<WNDPROC>(
@@ -3258,14 +3243,20 @@ class SubclassWindowHelper {
// Keep track of messags received for this window.
instance_->messages_.insert(message);
- return ::CallWindowProc(instance_->old_proc_, window, message, w_param,
- l_param);
+ LRESULT ret = ::CallWindowProc(instance_->old_proc_, window, message,
+ w_param, l_param);
+ if (message == instance_->message_to_destroy_on_) {
+ instance_->Unsubclass();
+ ::DestroyWindow(window);
+ }
+ return ret;
}
WNDPROC old_proc_;
HWND window_;
static SubclassWindowHelper* instance_;
std::set<unsigned int> messages_;
+ unsigned int message_to_destroy_on_;
DISALLOW_COPY_AND_ASSIGN(SubclassWindowHelper);
};
@@ -3278,11 +3269,13 @@ SubclassWindowHelper* SubclassWindowHelper::instance_ = nullptr;
// 1. Posting a WM_NCMOUSEMOVE message for a different location.
// 2. Posting a WM_NCMOUSEMOVE message with a different hittest code.
// 3. Posting a WM_MOUSEMOVE message.
-TEST_F(WidgetTest, SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) {
+// Disabled because of flaky timeouts: http://crbug.com/592742
+TEST_F(WidgetTest, DISABLED_SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) {
Widget widget;
Widget::InitParams params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
- params.native_widget = new PlatformDesktopNativeWidget(&widget);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr);
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
widget.Init(params);
widget.SetBounds(gfx::Rect(0, 0, 200, 200));
@@ -3347,10 +3340,49 @@ TEST_F(WidgetTest, SysCommandMoveOnNCLButtonDownOnCaptionAndMoveTest) {
widget.CloseNow();
}
+
+// This test validates that destroying the window in the context of the
+// WM_SYSCOMMAND message with SC_MOVE does not crash.
+// Disabled because of flaky timeouts: http://crbug.com/592742
+TEST_F(WidgetTest, DISABLED_DestroyInSysCommandNCLButtonDownOnCaption) {
+ Widget widget;
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ params.native_widget =
+ CreatePlatformDesktopNativeWidgetImpl(params, &widget, nullptr);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(params);
+ widget.SetBounds(gfx::Rect(0, 0, 200, 200));
+ widget.Show();
+ ::SetCursorPos(500, 500);
+
+ HWND window = widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget();
+
+ SubclassWindowHelper subclass_helper(window);
+
+ // Destroying the window in the context of the WM_SYSCOMMAND message
+ // should not crash.
+ subclass_helper.set_message_to_destroy_on(WM_SYSCOMMAND);
+
+ ::PostMessage(window, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(100, 100));
+ ::PostMessage(window, WM_NCMOUSEMOVE, HTCAPTION, MAKELPARAM(110, 110));
+ RunPendingMessages();
+
+ EXPECT_TRUE(subclass_helper.received_message(WM_NCLBUTTONDOWN));
+ EXPECT_TRUE(subclass_helper.received_message(WM_SYSCOMMAND));
+
+ widget.CloseNow();
+}
+
#endif
// Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent.
TEST_F(WidgetTest, AlwaysOnTop) {
+ if (IsMus()) {
+ NOTIMPLEMENTED();
+ return;
+ }
+
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
EXPECT_FALSE(widget->IsAlwaysOnTop());
widget->SetAlwaysOnTop(true);
@@ -3401,5 +3433,78 @@ TEST_F(WidgetTest, OnDeviceScaleFactorChanged) {
EXPECT_EQ(scale_factor, view->last_scale_factor());
}
+namespace {
+
+class TestWidgetRemovalsObserver : public WidgetRemovalsObserver {
+ public:
+ TestWidgetRemovalsObserver() {}
+ ~TestWidgetRemovalsObserver() override {}
+
+ void OnWillRemoveView(Widget* widget, View* view) override {
+ removed_views_.insert(view);
+ }
+
+ bool DidRemoveView(View* view) {
+ return removed_views_.find(view) != removed_views_.end();
+ }
+
+ private:
+ std::set<View*> removed_views_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWidgetRemovalsObserver);
+};
+
+}
+
+// Test that WidgetRemovalsObserver::OnWillRemoveView is called when deleting
+// a view.
+TEST_F(WidgetTest, WidgetRemovalsObserverCalled) {
+ WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
+ TestWidgetRemovalsObserver removals_observer;
+ widget->AddRemovalsObserver(&removals_observer);
+
+ View* parent = new View();
+ widget->client_view()->AddChildView(parent);
+
+ View* child = new View();
+ parent->AddChildView(child);
+
+ widget->client_view()->RemoveChildView(parent);
+ EXPECT_TRUE(removals_observer.DidRemoveView(parent));
+ EXPECT_FALSE(removals_observer.DidRemoveView(child));
+
+ // Calling RemoveChildView() doesn't delete the view, but deleting
+ // |parent| will automatically delete |child|.
+ delete parent;
+
+ widget->RemoveRemovalsObserver(&removals_observer);
+}
+
+// Test that WidgetRemovalsObserver::OnWillRemoveView is called when moving
+// a view from one widget to another, but not when moving a view within
+// the same widget.
+TEST_F(WidgetTest, WidgetRemovalsObserverCalledWhenMovingBetweenWidgets) {
+ WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
+ TestWidgetRemovalsObserver removals_observer;
+ widget->AddRemovalsObserver(&removals_observer);
+
+ View* parent = new View();
+ widget->client_view()->AddChildView(parent);
+
+ View* child = new View();
+ widget->client_view()->AddChildView(child);
+
+ // Reparenting the child shouldn't call the removals observer.
+ parent->AddChildView(child);
+ EXPECT_FALSE(removals_observer.DidRemoveView(child));
+
+ // Moving the child to a different widget should call the removals observer.
+ WidgetAutoclosePtr widget2(CreateTopLevelPlatformWidget());
+ widget2->client_view()->AddChildView(child);
+ EXPECT_TRUE(removals_observer.DidRemoveView(child));
+
+ widget->RemoveRemovalsObserver(&removals_observer);
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/win/fullscreen_handler.cc b/chromium/ui/views/win/fullscreen_handler.cc
index 2f7d0775caf..0529f6e37d8 100644
--- a/chromium/ui/views/win/fullscreen_handler.cc
+++ b/chromium/ui/views/win/fullscreen_handler.cc
@@ -5,7 +5,9 @@
#include "ui/views/win/fullscreen_handler.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "base/win/win_util.h"
+#include "ui/base/win/shell.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/win/scoped_fullscreen_visibility.h"
@@ -14,11 +16,7 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// FullscreenHandler, public:
-FullscreenHandler::FullscreenHandler()
- : hwnd_(NULL),
- fullscreen_(false),
- metro_snap_(false) {
-}
+FullscreenHandler::FullscreenHandler() : hwnd_(NULL), fullscreen_(false) {}
FullscreenHandler::~FullscreenHandler() {
}
@@ -27,15 +25,7 @@ void FullscreenHandler::SetFullscreen(bool fullscreen) {
if (fullscreen_ == fullscreen)
return;
- SetFullscreenImpl(fullscreen, false);
-}
-
-void FullscreenHandler::SetMetroSnap(bool metro_snap) {
- if (metro_snap_ == metro_snap)
- return;
-
- SetFullscreenImpl(metro_snap, true);
- metro_snap_ = metro_snap;
+ SetFullscreenImpl(fullscreen);
}
gfx::Rect FullscreenHandler::GetRestoreBounds() const {
@@ -45,8 +35,14 @@ gfx::Rect FullscreenHandler::GetRestoreBounds() const {
////////////////////////////////////////////////////////////////////////////////
// FullscreenHandler, private:
-void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
- ScopedFullscreenVisibility visibility(hwnd_);
+void FullscreenHandler::SetFullscreenImpl(bool fullscreen) {
+ scoped_ptr<ScopedFullscreenVisibility> visibility;
+
+ // With Aero enabled disabling the visibility causes the window to disappear
+ // for several frames, which looks worse than doing other updates
+ // non-atomically.
+ if (!ui::win::IsAeroGlassEnabled())
+ visibility.reset(new ScopedFullscreenVisibility(hwnd_));
// Save current window state if not already fullscreen.
if (!fullscreen_) {
@@ -73,16 +69,14 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
// On expand, if we're given a window_rect, grow to it, otherwise do
// not resize.
- if (!for_metro) {
- MONITORINFO monitor_info;
- monitor_info.cbSize = sizeof(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(),
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- }
+ MONITORINFO monitor_info;
+ monitor_info.cbSize = sizeof(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(),
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
} else {
// Reset original window style and size. The multiple window size/moves
// here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
@@ -90,13 +84,11 @@ void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);
SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);
- if (!for_metro) {
- // On restore, resize to the previous saved rect size.
- gfx::Rect new_rect(saved_window_info_.window_rect);
- SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),
- new_rect.width(), new_rect.height(),
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- }
+ // On restore, resize to the previous saved rect size.
+ gfx::Rect new_rect(saved_window_info_.window_rect);
+ SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(), new_rect.width(),
+ new_rect.height(),
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
if (saved_window_info_.maximized)
::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}
diff --git a/chromium/ui/views/win/fullscreen_handler.h b/chromium/ui/views/win/fullscreen_handler.h
index 176cbed5b6f..b23b1421374 100644
--- a/chromium/ui/views/win/fullscreen_handler.h
+++ b/chromium/ui/views/win/fullscreen_handler.h
@@ -25,12 +25,10 @@ class FullscreenHandler {
void set_hwnd(HWND hwnd) { hwnd_ = hwnd; }
void SetFullscreen(bool fullscreen);
- void SetMetroSnap(bool metro_snap);
gfx::Rect GetRestoreBounds() const;
bool fullscreen() const { return fullscreen_; }
- bool metro_snap() const { return metro_snap_; }
private:
// Information saved before going into fullscreen mode, used to restore the
@@ -42,11 +40,10 @@ class FullscreenHandler {
RECT window_rect;
};
- void SetFullscreenImpl(bool fullscreen, bool for_metro);
+ void SetFullscreenImpl(bool fullscreen);
HWND hwnd_;
bool fullscreen_;
- bool metro_snap_;
// Saved window information from before entering fullscreen mode.
// TODO(beng): move to private once GetRestoredBounds() moves onto Widget.
@@ -57,4 +54,4 @@ class FullscreenHandler {
} // namespace views
-#endif // UI_VIEWS_WIN_FULLSCREEN_HANDLER_H_ \ No newline at end of file
+#endif // UI_VIEWS_WIN_FULLSCREEN_HANDLER_H_
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index 0cacffe4a76..74d5cd6eb4b 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -8,7 +8,8 @@
#include <oleacc.h>
#include <shellapi.h>
#include <tchar.h>
-#include <tpcshrd.h>
+
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -37,6 +38,7 @@
#include "ui/gfx/win/direct_manipulation.h"
#include "ui/gfx/win/dpi.h"
#include "ui/gfx/win/hwnd_util.h"
+#include "ui/gfx/win/rendering_window_manager.h"
#include "ui/native_theme/native_theme_win.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/monitor_win.h"
@@ -149,13 +151,10 @@ LRESULT CALLBACK MoveLoopMouseWatcher::KeyHook(int n_code,
WPARAM w_param,
LPARAM l_param) {
if (n_code == HC_ACTION && w_param == VK_ESCAPE) {
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- int value = TRUE;
- DwmSetWindowAttribute(instance_->host_->hwnd(),
- DWMWA_TRANSITIONS_FORCEDISABLED,
- &value,
- sizeof(value));
- }
+ int value = TRUE;
+ DwmSetWindowAttribute(instance_->host_->hwnd(),
+ DWMWA_TRANSITIONS_FORCEDISABLED, &value,
+ sizeof(value));
if (instance_->hide_on_escape_)
instance_->host_->Hide();
}
@@ -313,7 +312,6 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
delegate_(delegate),
fullscreen_handler_(new FullscreenHandler),
waiting_for_close_now_(false),
- remove_standard_frame_(false),
use_system_default_icon_(false),
restored_enabled_(false),
current_cursor_(NULL),
@@ -333,6 +331,7 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
dwm_transition_desired_(false),
sent_window_size_changing_(false),
left_button_down_on_caption_(false),
+ background_fullscreen_hack_(false),
autohide_factory_(this),
weak_factory_(this) {}
@@ -385,16 +384,7 @@ void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) {
direct_manipulation_helper_->Initialize(hwnd());
// Disable pen flicks (http://crbug.com/506977)
- if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
- ATOM atom = ::GlobalAddAtom(MICROSOFT_TABLETPENSERVICE_PROPERTY);
- DCHECK(atom);
-
- ::SetProp(hwnd(), MICROSOFT_TABLETPENSERVICE_PROPERTY,
- reinterpret_cast<HANDLE>(TABLET_DISABLE_FLICKS |
- TABLET_DISABLE_FLICKFALLBACKKEYS));
-
- ::GlobalDeleteAtom(atom);
- }
+ base::win::DisableFlicks(hwnd());
}
void HWNDMessageHandler::InitModalType(ui::ModalType modal_type) {
@@ -421,10 +411,8 @@ void HWNDMessageHandler::Close() {
// they can activate as foreground windows upon this window's destruction.
RestoreEnabledIfNecessary();
- // Remove the property which disables pen flicks (http://crbug.com/506977)
- // for this window.
- if (base::win::GetVersion() >= base::win::VERSION_WIN7)
- ::RemoveProp(hwnd(), MICROSOFT_TABLETPENSERVICE_PROPERTY);
+ // Re-enable flicks which removes the window property.
+ base::win::EnableFlicks(hwnd());
if (!waiting_for_close_now_) {
// And we delay the close so that if we are called from an ATL callback,
@@ -465,7 +453,7 @@ gfx::Rect HWNDMessageHandler::GetClientAreaBoundsInScreen() const {
gfx::Rect HWNDMessageHandler::GetRestoredBounds() const {
// If we're in fullscreen mode, we've changed the normal bounds to the monitor
// rect, so return the saved bounds instead.
- if (fullscreen_handler_->fullscreen())
+ if (IsFullscreen())
return fullscreen_handler_->GetRestoreBounds();
gfx::Rect bounds;
@@ -525,25 +513,8 @@ void HWNDMessageHandler::GetWindowPlacement(
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);
- }
-
- if (direct_manipulation_helper_)
- direct_manipulation_helper_->SetBounds(bounds_in_pixels);
+ background_fullscreen_hack_ = false;
+ SetBoundsInternal(bounds_in_pixels, force_size_changed);
}
void HWNDMessageHandler::SetSize(const gfx::Size& size) {
@@ -715,6 +686,10 @@ bool HWNDMessageHandler::IsMaximized() const {
return !!::IsZoomed(hwnd());
}
+bool HWNDMessageHandler::IsFullscreen() const {
+ return fullscreen_handler_->fullscreen();
+}
+
bool HWNDMessageHandler::IsAlwaysOnTop() const {
return (GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
}
@@ -779,11 +754,9 @@ bool HWNDMessageHandler::HasCapture() const {
}
void HWNDMessageHandler::SetVisibilityChangedAnimationsEnabled(bool enabled) {
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
- int dwm_value = enabled ? FALSE : TRUE;
- DwmSetWindowAttribute(
- hwnd(), DWMWA_TRANSITIONS_FORCEDISABLED, &dwm_value, sizeof(dwm_value));
- }
+ int dwm_value = enabled ? FALSE : TRUE;
+ DwmSetWindowAttribute(hwnd(), DWMWA_TRANSITIONS_FORCEDISABLED, &dwm_value,
+ sizeof(dwm_value));
}
bool HWNDMessageHandler::SetTitle(const base::string16& title) {
@@ -812,38 +785,31 @@ void HWNDMessageHandler::SetCursor(HCURSOR cursor) {
}
void HWNDMessageHandler::FrameTypeChanged() {
- if (base::win::GetVersion() < base::win::VERSION_VISTA) {
- // Don't redraw the window here, because we invalidate the window later.
- ResetWindowRegion(true, false);
- // The non-client view needs to update too.
- delegate_->HandleFrameChanged();
- InvalidateRect(hwnd(), NULL, FALSE);
- } else {
- if (!custom_window_region_.is_valid() && !delegate_->IsUsingCustomFrame())
- dwm_transition_desired_ = true;
- if (!dwm_transition_desired_ || !fullscreen_handler_->fullscreen())
- PerformDwmTransition();
- }
+ if (!custom_window_region_.is_valid() &&
+ delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN)
+ dwm_transition_desired_ = true;
+ if (!dwm_transition_desired_ || !IsFullscreen())
+ PerformDwmTransition();
}
void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon) {
if (!window_icon.isNull()) {
- base::win::ScopedHICON previous_icon = window_icon_.Pass();
- window_icon_ =
- IconUtil::CreateHICONFromSkBitmap(*window_icon.bitmap()).Pass();
+ base::win::ScopedHICON previous_icon = std::move(window_icon_);
+ window_icon_ = IconUtil::CreateHICONFromSkBitmap(*window_icon.bitmap());
SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
reinterpret_cast<LPARAM>(window_icon_.get()));
}
if (!app_icon.isNull()) {
- base::win::ScopedHICON previous_icon = app_icon_.Pass();
- app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap()).Pass();
+ base::win::ScopedHICON previous_icon = std::move(app_icon_);
+ app_icon_ = IconUtil::CreateHICONFromSkBitmap(*app_icon.bitmap());
SendMessage(hwnd(), WM_SETICON, ICON_BIG,
reinterpret_cast<LPARAM>(app_icon_.get()));
}
}
void HWNDMessageHandler::SetFullscreen(bool fullscreen) {
+ background_fullscreen_hack_ = false;
fullscreen_handler()->SetFullscreen(fullscreen);
// If we are out of fullscreen and there was a pending DWM transition for the
// window, then go ahead and do it now.
@@ -875,6 +841,13 @@ void HWNDMessageHandler::SizeConstraintsChanged() {
SetWindowLong(hwnd(), GWL_STYLE, style);
}
+bool HWNDMessageHandler::HasChildRenderingWindow() {
+ // This can change dynamically if the system switches between GPU and
+ // software rendering.
+ return gfx::RenderingWindowManager::GetInstance()->HasValidChildWindow(
+ hwnd());
+}
+
////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, gfx::WindowImpl overrides:
@@ -929,7 +902,8 @@ LRESULT HWNDMessageHandler::OnWndProc(UINT message,
}
if (message == WM_ACTIVATE && IsTopLevelWindow(window))
- PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param));
+ PostProcessActivateMessage(LOWORD(w_param), !!HIWORD(w_param),
+ reinterpret_cast<HWND>(l_param));
return result;
}
@@ -1027,12 +1001,50 @@ void HWNDMessageHandler::SetInitialFocus() {
}
}
-void HWNDMessageHandler::PostProcessActivateMessage(int activation_state,
- bool minimized) {
+void HWNDMessageHandler::PostProcessActivateMessage(
+ int activation_state,
+ bool minimized,
+ HWND window_gaining_or_losing_activation) {
DCHECK(IsTopLevelWindow(hwnd()));
const bool active = activation_state != WA_INACTIVE && !minimized;
if (delegate_->CanActivate())
delegate_->HandleActivationChanged(active);
+
+ if (!::IsWindow(window_gaining_or_losing_activation))
+ window_gaining_or_losing_activation = ::GetForegroundWindow();
+
+ // If the window losing activation is a fullscreen window, we reduce the size
+ // of the window by 1px. i.e. Not fullscreen. This is to work around an
+ // apparent bug in the Windows taskbar where in it tracks fullscreen state on
+ // a per thread basis. This causes it not be a topmost window when any
+ // maximized window on a thread which has a fullscreen window is active. This
+ // affects the way these windows interact with the taskbar, they obscure it
+ // when maximized, autohide does not work correctly, etc.
+ // By reducing the size of the fullscreen window by 1px, we ensure that the
+ // taskbar no longer treats the window and in turn the thread as a fullscreen
+ // thread. This in turn ensures that maximized windows on the same thread
+ /// don't obscure the taskbar, etc.
+ if (!active) {
+ if (IsFullscreen() && ::IsWindow(window_gaining_or_losing_activation)) {
+ // Reduce the bounds of the window by 1px to ensure that Windows does
+ // not treat this like a fullscreen window.
+ MONITORINFO monitor_info = {sizeof(monitor_info)};
+ GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY),
+ &monitor_info);
+ gfx::Rect shrunk_rect(monitor_info.rcMonitor);
+ shrunk_rect.set_height(shrunk_rect.height() - 1);
+ background_fullscreen_hack_ = true;
+ SetBoundsInternal(shrunk_rect, false);
+ }
+ } else if (background_fullscreen_hack_) {
+ // Restore the bounds of the window to fullscreen.
+ DCHECK(IsFullscreen());
+ MONITORINFO monitor_info = {sizeof(monitor_info)};
+ GetMonitorInfo(MonitorFromWindow(hwnd(), MONITOR_DEFAULTTOPRIMARY),
+ &monitor_info);
+ SetBoundsInternal(gfx::Rect(monitor_info.rcMonitor), false);
+ background_fullscreen_hack_ = false;
+ }
}
void HWNDMessageHandler::RestoreEnabledIfNecessary() {
@@ -1078,6 +1090,9 @@ void HWNDMessageHandler::TrackMouseEvents(DWORD mouse_tracking_flags) {
}
void HWNDMessageHandler::ClientAreaSizeChanged() {
+ // Ignore size changes due to fullscreen windows losing activation.
+ if (background_fullscreen_hack_)
+ return;
gfx::Size s = GetClientAreaBounds().size();
delegate_->HandleClientSizeChanged(s);
}
@@ -1089,16 +1104,14 @@ bool HWNDMessageHandler::GetClientAreaInsets(gfx::Insets* insets) const {
// Returning false causes the default handling in OnNCCalcSize() to
// be invoked.
- if (!delegate_->IsWidgetWindow() ||
- (!delegate_->IsUsingCustomFrame() && !remove_standard_frame_)) {
+ if (!delegate_->HasNonClientView() || HasSystemFrame())
return false;
- }
if (IsMaximized()) {
// Windows automatically adds a standard width border to all sides when a
// window is maximized.
int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME);
- if (remove_standard_frame_)
+ if (!delegate_->HasFrame())
border_thickness -= 1;
*insets = gfx::Insets(
border_thickness, border_thickness, border_thickness, border_thickness);
@@ -1118,7 +1131,8 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
// the delegate to allow for a custom hit mask.
if ((window_ex_style() & WS_EX_COMPOSITED) == 0 &&
!custom_window_region_.is_valid() &&
- (!delegate_->IsUsingCustomFrame() || !delegate_->IsWidgetWindow())) {
+ (delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN ||
+ !delegate_->HasNonClientView())) {
if (force)
SetWindowRgn(hwnd(), NULL, redraw);
return;
@@ -1162,14 +1176,12 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
}
void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
- if (base::win::GetVersion() < base::win::VERSION_VISTA)
- return;
-
- if (fullscreen_handler_->fullscreen())
+ if (IsFullscreen())
return;
DWMNCRENDERINGPOLICY policy =
- custom_window_region_.is_valid() || delegate_->IsUsingCustomFrame()
+ custom_window_region_.is_valid() ||
+ delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN
? DWMNCRP_DISABLED
: DWMNCRP_ENABLED;
@@ -1228,14 +1240,19 @@ void HWNDMessageHandler::ForceRedrawWindow(int attempts) {
InvalidateRect(hwnd(), NULL, FALSE);
}
+bool HWNDMessageHandler::HasSystemFrame() const {
+ return delegate_->HasFrame() &&
+ delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN;
+}
+
// Message handlers ------------------------------------------------------------
void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) {
- if (delegate_->IsWidgetWindow() && !active &&
+ if (delegate_->HasNonClientView() && !active &&
thread_id != GetCurrentThreadId()) {
delegate_->HandleAppDeactivated();
// Also update the native frame if it is rendering the non-client area.
- if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame())
+ if (HasSystemFrame())
DefWindowProcWithRedrawLock(WM_NCACTIVATE, FALSE, 0);
}
}
@@ -1277,12 +1294,10 @@ void HWNDMessageHandler::OnCommand(UINT notification_code,
LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
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
- // see the explanation elsewere when we set WS_EX_COMPOSITED style.
- MARGINS margins = {-1,-1,-1,-1};
- DwmExtendFrameIntoClientArea(hwnd(), &margins);
- }
+ // This is part of the magic to emulate layered windows with Aura
+ // see the explanation elsewere when we set WS_EX_COMPOSITED style.
+ MARGINS margins = {-1, -1, -1, -1};
+ DwmExtendFrameIntoClientArea(hwnd(), &margins);
}
fullscreen_handler_->set_hwnd(hwnd());
@@ -1294,7 +1309,7 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
MAKELPARAM(UIS_CLEAR, UISF_HIDEFOCUS),
0);
- if (remove_standard_frame_) {
+ if (!delegate_->HasFrame()) {
SetWindowLong(hwnd(), GWL_STYLE,
GetWindowLong(hwnd(), GWL_STYLE) & ~WS_CAPTION);
SendFrameChanged();
@@ -1303,8 +1318,7 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
// Get access to a modifiable copy of the system menu.
GetSystemMenu(hwnd(), false);
- if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
- ui::AreTouchEventsEnabled())
+ if (ui::AreTouchEventsEnabled())
RegisterTouchWindow(hwnd(), TWF_WANTPALM);
// We need to allow the delegate to size its contents since the window may not
@@ -1330,13 +1344,15 @@ void HWNDMessageHandler::OnDestroy() {
void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
const gfx::Size& screen_size) {
delegate_->HandleDisplayChange();
+ // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide
+ // taskbars correctly.
SendFrameChanged();
}
LRESULT HWNDMessageHandler::OnDwmCompositionChanged(UINT msg,
WPARAM w_param,
LPARAM l_param) {
- if (!delegate_->IsWidgetWindow()) {
+ if (!delegate_->HasNonClientView()) {
SetMsgHandled(FALSE);
return 0;
}
@@ -1457,7 +1473,7 @@ LRESULT HWNDMessageHandler::OnImeMessages(UINT message,
}
void HWNDMessageHandler::OnInitMenu(HMENU menu) {
- bool is_fullscreen = fullscreen_handler_->fullscreen();
+ bool is_fullscreen = IsFullscreen();
bool is_minimized = IsMinimized();
bool is_maximized = IsMaximized();
bool is_restored = !is_fullscreen && !is_minimized && !is_maximized;
@@ -1489,7 +1505,10 @@ LRESULT HWNDMessageHandler::OnKeyEvent(UINT message,
MSG msg = {
hwnd(), message, w_param, l_param, static_cast<DWORD>(GetMessageTime())};
ui::KeyEvent key(msg);
+ base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
delegate_->HandleKeyEvent(&key);
+ if (!ref)
+ return 0;
if (!key.handled())
SetMsgHandled(FALSE);
return 0;
@@ -1519,24 +1538,10 @@ LRESULT HWNDMessageHandler::OnMouseActivate(UINT message,
::RemoveProp(hwnd(), ui::kIgnoreTouchMouseActivateForWindow);
return MA_NOACTIVATE;
}
- // A child window activation should be treated as if we lost activation.
- POINT cursor_pos = {0};
- ::GetCursorPos(&cursor_pos);
- ::ScreenToClient(hwnd(), &cursor_pos);
- // The code below exists for child windows like NPAPI plugins etc which need
- // to be activated whenever we receive a WM_MOUSEACTIVATE message. Don't put
- // transparent child windows in this bucket as they are not supposed to grab
- // activation.
- // TODO(ananta)
- // Get rid of this code when we deprecate NPAPI plugins.
- HWND child = ::RealChildWindowFromPoint(hwnd(), cursor_pos);
- if (::IsWindow(child) && child != hwnd() && ::IsWindowVisible(child) &&
- !(::GetWindowLong(child, GWL_EXSTYLE) & WS_EX_TRANSPARENT))
- PostProcessActivateMessage(WA_INACTIVE, false);
// TODO(beng): resolve this with the GetWindowLong() check on the subsequent
// line.
- if (delegate_->IsWidgetWindow()) {
+ if (delegate_->HasNonClientView()) {
if (delegate_->CanActivate())
return MA_ACTIVATE;
if (delegate_->WantsMouseEventsWhenInactive())
@@ -1575,9 +1580,9 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message,
// cleared before it is converted to BOOL.
BOOL active = static_cast<BOOL>(LOWORD(w_param));
- bool inactive_rendering_disabled = delegate_->IsInactiveRenderingDisabled();
+ bool render_as_active = delegate_->IsAlwaysRenderAsActive();
- if (!delegate_->IsWidgetWindow()) {
+ if (!delegate_->HasNonClientView()) {
SetMsgHandled(FALSE);
return 0;
}
@@ -1586,10 +1591,10 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message,
return TRUE;
// On activation, lift any prior restriction against rendering as inactive.
- if (active && inactive_rendering_disabled)
- delegate_->EnableInactiveRendering();
+ if (active && render_as_active)
+ delegate_->SetAlwaysRenderAsActive(false);
- if (delegate_->IsUsingCustomFrame()) {
+ if (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
// TODO(beng, et al): Hack to redraw this window and child windows
// synchronously upon activation. Not all child windows are redrawing
// themselves leading to issues like http://crbug.com/74604
@@ -1606,16 +1611,13 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message,
if (IsVisible())
delegate_->SchedulePaint();
- // Avoid DefWindowProc non-client rendering over our custom frame on newer
- // Windows versions only (breaks taskbar activation indication on XP/Vista).
- if (delegate_->IsUsingCustomFrame() &&
- base::win::GetVersion() > base::win::VERSION_VISTA) {
+ if (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
SetMsgHandled(TRUE);
return TRUE;
}
return DefWindowProcWithRedrawLock(
- WM_NCACTIVATE, inactive_rendering_disabled || active, 0);
+ WM_NCACTIVATE, render_as_active || active, 0);
}
LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
@@ -1638,8 +1640,7 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
gfx::Insets insets;
bool got_insets = GetClientAreaInsets(&insets);
- if (!got_insets && !fullscreen_handler_->fullscreen() &&
- !(mode && remove_standard_frame_)) {
+ if (!got_insets && !IsFullscreen() && !(mode && !delegate_->HasFrame())) {
SetMsgHandled(FALSE);
return 0;
}
@@ -1678,7 +1679,7 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
if (autohide_edges & ViewsDelegate::EDGE_LEFT)
client_rect->left += kAutoHideTaskbarThicknessPx;
if (autohide_edges & ViewsDelegate::EDGE_TOP) {
- if (!delegate_->IsUsingCustomFrame()) {
+ if (delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN) {
// Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
// WM_NCHITTEST, having any nonclient area atop the window causes the
// caption buttons to draw onscreen but not respond to mouse
@@ -1717,14 +1718,14 @@ LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) {
}
LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) {
- if (!delegate_->IsWidgetWindow()) {
+ if (!delegate_->HasNonClientView()) {
SetMsgHandled(FALSE);
return 0;
}
// If the DWM is rendering the window controls, we need to give the DWM's
// default window procedure first chance to handle hit testing.
- if (!remove_standard_frame_ && !delegate_->IsUsingCustomFrame()) {
+ if (HasSystemFrame()) {
LRESULT result;
if (DwmDefWindowProc(hwnd(), WM_NCHITTEST, 0,
MAKELPARAM(point.x(), point.y()), &result)) {
@@ -1791,32 +1792,8 @@ LRESULT HWNDMessageHandler::OnNCHitTest(const gfx::Point& point) {
}
void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
- // We only do non-client painting if we're not using the native frame.
- // It's required to avoid some native painting artifacts from appearing when
- // the window is resized.
- if (!delegate_->IsWidgetWindow() || !delegate_->IsUsingCustomFrame()) {
- SetMsgHandled(FALSE);
- return;
- }
-
- // 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.
RECT window_rect;
GetWindowRect(hwnd(), &window_rect);
-
- gfx::Size root_view_size = delegate_->GetRootViewSize();
- 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
- // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
- // reset the region of the window which triggers another WM_NCPAINT and
- // all is well.
- return;
- }
-
RECT dirty_region;
// A value of 1 indicates paint all.
if (!rgn || rgn == reinterpret_cast<HRGN>(1)) {
@@ -1827,18 +1804,64 @@ void HWNDMessageHandler::OnNCPaint(HRGN rgn) {
} else {
RECT rgn_bounding_box;
GetRgnBox(rgn, &rgn_bounding_box);
- if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect))
- return; // Dirty region doesn't intersect window bounds, bale.
+ if (!IntersectRect(&dirty_region, &rgn_bounding_box, &window_rect)) {
+ SetMsgHandled(FALSE);
+ return; // Dirty region doesn't intersect window bounds, bail.
+ }
// rgn_bounding_box is in screen coordinates. Map it to window coordinates.
OffsetRect(&dirty_region, -window_rect.left, -window_rect.top);
}
+ // We only do non-client painting if we're not using the system frame.
+ // It's required to avoid some native painting artifacts from appearing when
+ // the window is resized.
+ if (!delegate_->HasNonClientView() ||
+ delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN) {
+ if (ui::win::IsAeroGlassEnabled()) {
+ // The default WM_NCPAINT handler under Aero Glass doesn't clear the
+ // nonclient area, so it'll remain the default white color. That area is
+ // invisible initially (covered by the window border) but can become
+ // temporarily visible on maximizing or fullscreening, so clear it here.
+ HDC dc = GetWindowDC(hwnd());
+ RECT client_rect;
+ ::GetClientRect(hwnd(), &client_rect);
+ ::MapWindowPoints(hwnd(), nullptr, reinterpret_cast<POINT*>(&client_rect),
+ 2);
+ ::OffsetRect(&client_rect, -window_rect.left, -window_rect.top);
+ // client_rect now is in window space.
+
+ base::win::ScopedRegion base(::CreateRectRgnIndirect(&dirty_region));
+ base::win::ScopedRegion client(::CreateRectRgnIndirect(&client_rect));
+ base::win::ScopedRegion nonclient(::CreateRectRgn(0, 0, 0, 0));
+ ::CombineRgn(nonclient.get(), base.get(), client.get(), RGN_DIFF);
+
+ ::SelectClipRgn(dc, nonclient.get());
+ HBRUSH brush = CreateSolidBrush(0);
+ ::FillRect(dc, &dirty_region, brush);
+ ::DeleteObject(brush);
+ ::ReleaseDC(hwnd(), dc);
+ }
+ SetMsgHandled(FALSE);
+ return;
+ }
+
+ gfx::Size root_view_size = delegate_->GetRootViewSize();
+ 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
+ // mass flickering we don't do anything here. Once we get the WM_SIZE we'll
+ // reset the region of the window which triggers another WM_NCPAINT and
+ // all is well.
+ return;
+ }
delegate_->HandlePaintAccelerated(gfx::Rect(dirty_region));
// When using a custom frame, we want to avoid calling DefWindowProc() since
// that may render artifacts.
- SetMsgHandled(delegate_->IsUsingCustomFrame());
+ SetMsgHandled(delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN);
}
LRESULT HWNDMessageHandler::OnNCUAHDrawCaption(UINT message,
@@ -1846,7 +1869,7 @@ LRESULT HWNDMessageHandler::OnNCUAHDrawCaption(UINT message,
LPARAM l_param) {
// See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
// an explanation about why we need to handle this message.
- SetMsgHandled(delegate_->IsUsingCustomFrame());
+ SetMsgHandled(delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN);
return 0;
}
@@ -1855,7 +1878,7 @@ LRESULT HWNDMessageHandler::OnNCUAHDrawFrame(UINT message,
LPARAM l_param) {
// See comment in widget_win.h at the definition of WM_NCUAHDRAWCAPTION for
// an explanation about why we need to handle this message.
- SetMsgHandled(delegate_->IsUsingCustomFrame());
+ SetMsgHandled(delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN);
return 0;
}
@@ -1892,8 +1915,18 @@ void HWNDMessageHandler::OnPaint(HDC dc) {
<< ", GDI peak count: " << peak_gdi_objects;
}
- if (!IsRectEmpty(&ps.rcPaint))
+ if (!IsRectEmpty(&ps.rcPaint)) {
+ if (HasChildRenderingWindow()) {
+ // If there's a child window that's being rendered to then clear the
+ // area outside it (as WS_CLIPCHILDREN is set) with transparent black.
+ // Otherwise, other portions of the backing store for the window can
+ // flicker opaque black. http://crbug.com/586454
+
+ FillRect(ps.hdc, &ps.rcPaint,
+ reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
+ }
delegate_->HandlePaintAccelerated(gfx::Rect(ps.rcPaint));
+ }
EndPaint(hwnd(), &ps);
}
@@ -1988,6 +2021,13 @@ void HWNDMessageHandler::OnSettingChange(UINT flags, const wchar_t* section) {
delegate_->HandleWorkAreaChanged();
SetMsgHandled(FALSE);
}
+
+ // If the work area is changing, then it could be as a result of the taskbar
+ // broadcasting the WM_SETTINGCHANGE message due to changes in auto hide
+ // settings, etc. Force a WM_NCCALCSIZE to occur to ensure that we handle
+ // this correctly.
+ if (flags == SPI_SETWORKAREA)
+ SendFrameChanged();
}
void HWNDMessageHandler::OnSize(UINT param, const gfx::Size& size) {
@@ -2019,12 +2059,11 @@ void HWNDMessageHandler::OnSysCommand(UINT notification_code,
// specific information so we must exclude this when comparing.
static const int sc_mask = 0xFFF0;
// Ignore size/move/maximize in fullscreen mode.
- if (fullscreen_handler_->fullscreen() &&
- (((notification_code & sc_mask) == SC_SIZE) ||
- ((notification_code & sc_mask) == SC_MOVE) ||
- ((notification_code & sc_mask) == SC_MAXIMIZE)))
+ if (IsFullscreen() && (((notification_code & sc_mask) == SC_SIZE) ||
+ ((notification_code & sc_mask) == SC_MOVE) ||
+ ((notification_code & sc_mask) == SC_MAXIMIZE)))
return;
- if (delegate_->IsUsingCustomFrame()) {
+ if (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
if ((notification_code & sc_mask) == SC_MINIMIZE ||
(notification_code & sc_mask) == SC_MAXIMIZE ||
(notification_code & sc_mask) == SC_RESTORE) {
@@ -2170,10 +2209,16 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
GetMonitorAndRects(window_rect, &monitor, &monitor_rect, &work_area)) {
bool work_area_changed = (monitor_rect == last_monitor_rect_) &&
(work_area != last_work_area_);
+ // If the size of a background fullscreen window changes again, then we
+ // should reset the |background_fullscreen_hack_| flag.
+ if (background_fullscreen_hack_ &&
+ (!(window_pos->flags & SWP_NOSIZE) &&
+ (monitor_rect.height() - window_pos->cy != 1))) {
+ background_fullscreen_hack_ = false;
+ }
if (monitor && (monitor == last_monitor_) &&
- ((fullscreen_handler_->fullscreen() &&
- !fullscreen_handler_->metro_snap()) ||
- work_area_changed)) {
+ ((IsFullscreen() && !background_fullscreen_hack_) ||
+ work_area_changed)) {
// A rect for the monitor we're on changed. Normally Windows notifies
// us about this (and thus we're reaching here due to the SetWindowPos()
// call in OnSettingChange() above), but with some software (e.g.
@@ -2183,7 +2228,7 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
// response is to throw away the existing position/size information in
// |window_pos| and recalculate it based on the new work rect.
gfx::Rect new_window_rect;
- if (fullscreen_handler_->fullscreen()) {
+ if (IsFullscreen()) {
new_window_rect = monitor_rect;
} else if (IsMaximized()) {
new_window_rect = work_area;
@@ -2245,7 +2290,7 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
if (DidClientAreaSizeChange(window_pos))
ClientAreaSizeChanged();
- if (remove_standard_frame_ && window_pos->flags & SWP_FRAMECHANGED &&
+ if (!delegate_->HasFrame() && window_pos->flags & SWP_FRAMECHANGED &&
ui::win::IsAeroGlassEnabled() &&
(window_ex_style() & WS_EX_COMPOSITED) == 0) {
MARGINS m = {10, 10, 10, 10};
@@ -2335,7 +2380,8 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
gfx::ShowSystemMenuAtPoint(hwnd(), gfx::Point(screen_point));
return 0;
}
- } else if (message == WM_NCLBUTTONDOWN && delegate_->IsUsingCustomFrame()) {
+ } else if (message == WM_NCLBUTTONDOWN &&
+ delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
switch (w_param) {
case HTCLOSE:
case HTMINBUTTON:
@@ -2406,7 +2452,8 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
}
if (!handled && message == WM_NCLBUTTONDOWN && w_param != HTSYSMENU &&
- w_param != HTCAPTION && delegate_->IsUsingCustomFrame()) {
+ w_param != HTCAPTION &&
+ delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
// 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
@@ -2458,7 +2505,7 @@ void HWNDMessageHandler::PerformDwmTransition() {
// The non-client view needs to update too.
delegate_->HandleFrameChanged();
- if (IsVisible() && !delegate_->IsUsingCustomFrame()) {
+ if (IsVisible() && delegate_->GetFrameMode() == FrameMode::SYSTEM_DRAWN) {
// For some reason, we need to hide the window after we change from a custom
// frame to a native frame. If we don't, the client area will be filled
// with black. This seems to be related to an interaction between DWM and
@@ -2557,12 +2604,15 @@ bool HWNDMessageHandler::HandleMouseInputForCaption(unsigned int message,
// so we need to call it inside a ScopedRedrawLock. This may cause
// other negative side-effects
// (ex/ stifling non-client mouse releases).
- if (delegate_->IsUsingCustomFrame()) {
+ // We may be deleted in the context of DefWindowProc. Don't refer to
+ // any member variables after the DefWindowProc call.
+ left_button_down_on_caption_ = false;
+
+ if (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) {
DefWindowProcWithRedrawLock(WM_NCLBUTTONDOWN, HTCAPTION, l_param);
} else {
DefWindowProc(hwnd(), WM_NCLBUTTONDOWN, HTCAPTION, l_param);
}
- left_button_down_on_caption_ = false;
}
break;
}
@@ -2577,5 +2627,29 @@ bool HWNDMessageHandler::HandleMouseInputForCaption(unsigned int message,
return handled;
}
+void HWNDMessageHandler::SetBoundsInternal(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 &&
+ !background_fullscreen_hack_) {
+ delegate_->HandleClientSizeChanged(GetClientAreaBounds().size());
+ ResetWindowRegion(false, true);
+ }
+
+ if (direct_manipulation_helper_)
+ direct_manipulation_helper_->SetBounds(bounds_in_pixels);
+}
+
} // namespace views
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index 4b7ab4179a0..143b1c61fec 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -163,6 +163,7 @@ class VIEWS_EXPORT HWNDMessageHandler :
bool IsActive() const;
bool IsMinimized() const;
bool IsMaximized() const;
+ bool IsFullscreen() const;
bool IsAlwaysOnTop() const;
bool RunMoveLoop(const gfx::Vector2d& drag_offset, bool hide_on_escape);
@@ -193,10 +194,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
void SetWindowIcons(const gfx::ImageSkia& window_icon,
const gfx::ImageSkia& app_icon);
- void set_remove_standard_frame(bool remove_standard_frame) {
- remove_standard_frame_ = remove_standard_frame;
- }
-
void set_use_system_default_icon(bool use_system_default_icon) {
use_system_default_icon_ = use_system_default_icon;
}
@@ -206,6 +203,10 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Updates the window style to reflect whether it can be resized or maximized.
void SizeConstraintsChanged();
+ // Returns true if content is rendered to a child window instead of directly
+ // to this window.
+ bool HasChildRenderingWindow();
+
private:
typedef std::set<DWORD> TouchIDs;
@@ -255,7 +256,10 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Called after the WM_ACTIVATE message has been processed by the default
// windows procedure.
- void PostProcessActivateMessage(int activation_state, bool minimized);
+ void PostProcessActivateMessage(
+ int activation_state,
+ bool minimized,
+ HWND window_gaining_or_losing_activation);
// Enables disabled owner windows that may have been disabled due to this
// window's modality.
@@ -306,6 +310,8 @@ class VIEWS_EXPORT HWNDMessageHandler :
// onscreen.
void ForceRedrawWindow(int attempts);
+ bool HasSystemFrame() const;
+
// Message Handlers ----------------------------------------------------------
BEGIN_SAFE_MSG_MAP_EX(weak_factory_)
@@ -502,6 +508,11 @@ class VIEWS_EXPORT HWNDMessageHandler :
WPARAM w_param,
LPARAM l_param);
+ // Helper function for setting the bounds of the HWND. For more information
+ // please refer to the SetBounds() function.
+ void SetBoundsInternal(const gfx::Rect& bounds_in_pixels,
+ bool force_size_changed);
+
HWNDMessageHandlerDelegate* delegate_;
scoped_ptr<FullscreenHandler> fullscreen_handler_;
@@ -509,8 +520,6 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Set to true in Close() and false is CloseNow().
bool waiting_for_close_now_;
- bool remove_standard_frame_;
-
bool use_system_default_icon_;
// Whether all ancestors have been enabled. This is only used if is_modal_ is
@@ -632,6 +641,10 @@ class VIEWS_EXPORT HWNDMessageHandler :
// Defaults to false.
bool left_button_down_on_caption_;
+ // Set to true if the window is a background fullscreen window, i.e a
+ // fullscreen window which lost activation. Defaults to false.
+ bool background_fullscreen_hack_;
+
// The WeakPtrFactories below must occur last in the class definition so they
// get destroyed last.
diff --git a/chromium/ui/views/win/hwnd_message_handler_delegate.h b/chromium/ui/views/win/hwnd_message_handler_delegate.h
index 55ac4407197..007157aefe8 100644
--- a/chromium/ui/views/win/hwnd_message_handler_delegate.h
+++ b/chromium/ui/views/win/hwnd_message_handler_delegate.h
@@ -24,21 +24,33 @@ class TouchEvent;
namespace views {
+enum class FrameMode {
+ SYSTEM_DRAWN, // "glass" frame
+ CUSTOM_DRAWN // "opaque" frame
+};
+
class InputMethod;
// Implemented by the object that uses the HWNDMessageHandler to handle
// notifications from the underlying HWND and service requests for data.
class VIEWS_EXPORT HWNDMessageHandlerDelegate {
public:
- virtual bool IsWidgetWindow() const = 0;
+ // True if the widget associated with this window has a non-client view.
+ virtual bool HasNonClientView() const = 0;
+
+ // Returns who we want to be drawing the frame. Either the system (Windows)
+ // will handle it or Chrome will custom draw it.
+ virtual FrameMode GetFrameMode() const = 0;
- // TODO(beng): resolve this more satisfactorily vis-a-vis ShouldUseNativeFrame
- // to avoid confusion.
- virtual bool IsUsingCustomFrame() const = 0;
+ // True if a frame should be drawn. This will return true for some windows
+ // that don't have a visible frame. Those usually have the WS_POPUP style, for
+ // which Windows will remove the frame automatically if the frame mode is
+ // SYSTEM_DRAWN.
+ virtual bool HasFrame() const = 0;
virtual void SchedulePaint() = 0;
- virtual void EnableInactiveRendering() = 0;
- virtual bool IsInactiveRenderingDisabled() = 0;
+ virtual void SetAlwaysRenderAsActive(bool always_render_as_active) = 0;
+ virtual bool IsAlwaysRenderAsActive() = 0;
virtual bool CanResize() const = 0;
virtual bool CanMaximize() const = 0;
diff --git a/chromium/ui/views/win/windows_session_change_observer.cc b/chromium/ui/views/win/windows_session_change_observer.cc
index a96c566517b..6d230d6edd0 100644
--- a/chromium/ui/views/win/windows_session_change_observer.cc
+++ b/chromium/ui/views/win/windows_session_change_observer.cc
@@ -5,7 +5,6 @@
#include "ui/views/win/windows_session_change_observer.h"
#include <wtsapi32.h>
-#pragma comment(lib, "wtsapi32.lib")
#include "base/bind.h"
#include "base/bind_helpers.h"
diff --git a/chromium/ui/views/window/client_view.cc b/chromium/ui/views/window/client_view.cc
index fb7d89fed18..7a87d8decde 100644
--- a/chromium/ui/views/window/client_view.cc
+++ b/chromium/ui/views/window/client_view.cc
@@ -92,6 +92,8 @@ void ClientView::ViewHierarchyChanged(
// Insert |contents_view_| at index 0 so it is first in the focus chain.
// (the OK/Cancel buttons are inserted before contents_view_)
AddChildViewAt(contents_view_, 0);
+ } else if (!details.is_add && details.child == contents_view_) {
+ contents_view_ = nullptr;
}
}
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index 05cb09d0780..720091ec624 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -352,9 +352,9 @@ bool CustomFrameView::ShouldShowClientEdge() const {
void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
frame_background_->set_frame_color(GetFrameColor());
- const gfx::ImageSkia* frame_image = GetFrameImage();
+ const gfx::ImageSkia frame_image = GetFrameImage();
frame_background_->set_theme_image(frame_image);
- frame_background_->set_top_area_height(frame_image->height());
+ frame_background_->set_top_area_height(frame_image.height());
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -373,9 +373,9 @@ void CustomFrameView::PaintRestoredFrameBorder(gfx::Canvas* canvas) {
}
void CustomFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) {
- const gfx::ImageSkia* frame_image = GetFrameImage();
+ const gfx::ImageSkia frame_image = GetFrameImage();
frame_background_->set_theme_image(frame_image);
- frame_background_->set_top_area_height(frame_image->height());
+ frame_background_->set_top_area_height(frame_image.height());
frame_background_->PaintMaximized(canvas, this);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -475,9 +475,11 @@ SkColor CustomFrameView::GetFrameColor() const {
return frame_->IsActive() ? kDefaultColorFrame : kDefaultColorFrameInactive;
}
-const gfx::ImageSkia* CustomFrameView::GetFrameImage() const {
- return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- frame_->IsActive() ? IDR_FRAME : IDR_FRAME_INACTIVE).ToImageSkia();
+gfx::ImageSkia CustomFrameView::GetFrameImage() const {
+ return *ui::ResourceBundle::GetSharedInstance()
+ .GetImageNamed(frame_->IsActive() ? IDR_FRAME
+ : IDR_FRAME_INACTIVE)
+ .ToImageSkia();
}
void CustomFrameView::LayoutWindowControls() {
diff --git a/chromium/ui/views/window/custom_frame_view.h b/chromium/ui/views/window/custom_frame_view.h
index cb2413125f0..db77648a273 100644
--- a/chromium/ui/views/window/custom_frame_view.h
+++ b/chromium/ui/views/window/custom_frame_view.h
@@ -8,14 +8,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/image/image_skia.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 {
-class ImageSkia;
-}
-
namespace views {
class FrameBackground;
@@ -105,7 +102,7 @@ class VIEWS_EXPORT CustomFrameView : public NonClientFrameView,
// Compute aspects of the frame needed to paint the frame background.
SkColor GetFrameColor() const;
- const gfx::ImageSkia* GetFrameImage() const;
+ gfx::ImageSkia GetFrameImage() const;
// Performs the layout for the window control buttons based on the
// configuration specified in WindowButtonOrderProvider. The sizing and
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index 04f9b2fc4da..5b65adb73bd 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -54,50 +54,48 @@ void LayoutButton(LabelButton* button, gfx::Rect* row_bounds) {
DialogClientView::DialogClientView(Widget* owner, View* contents_view)
: ClientView(owner, contents_view),
+ button_row_insets_(0,
+ kButtonHEdgeMarginNew,
+ kButtonVEdgeMarginNew,
+ kButtonHEdgeMarginNew),
ok_button_(NULL),
cancel_button_(NULL),
- default_button_(NULL),
- focus_manager_(NULL),
extra_view_(NULL),
- footnote_view_(NULL),
- notified_delegate_(false) {
+ delegate_allowed_close_(false) {
+ // Doing this now ensures this accelerator will have lower priority than
+ // one set by the contents view.
+ AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
}
DialogClientView::~DialogClientView() {
}
void DialogClientView::AcceptWindow() {
- // Only notify the delegate once. See |notified_delegate_|'s comment.
- if (!notified_delegate_ && GetDialogDelegate()->Accept(false)) {
- notified_delegate_ = true;
- Close();
+ // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
+ if (!delegate_allowed_close_ && GetDialogDelegate()->Accept()) {
+ delegate_allowed_close_ = true;
+ GetWidget()->Close();
}
}
void DialogClientView::CancelWindow() {
- // Only notify the delegate once. See |notified_delegate_|'s comment.
- if (!notified_delegate_ && GetDialogDelegate()->Cancel()) {
- notified_delegate_ = true;
- Close();
+ // Only notify the delegate once. See |delegate_allowed_close_|'s comment.
+ if (!delegate_allowed_close_ && GetDialogDelegate()->Cancel()) {
+ delegate_allowed_close_ = true;
+ GetWidget()->Close();
}
}
void DialogClientView::UpdateDialogButtons() {
const int buttons = GetDialogDelegate()->GetDialogButtons();
- ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
- if (default_button_)
- default_button_->SetIsDefault(false);
- default_button_ = NULL;
if (buttons & ui::DIALOG_BUTTON_OK) {
if (!ok_button_) {
ok_button_ = CreateDialogButton(ui::DIALOG_BUTTON_OK);
- if (!(buttons & ui::DIALOG_BUTTON_CANCEL))
- ok_button_->AddAccelerator(escape);
AddChildView(ok_button_);
}
- UpdateButton(ok_button_, ui::DIALOG_BUTTON_OK);
+ GetDialogDelegate()->UpdateButton(ok_button_, ui::DIALOG_BUTTON_OK);
} else if (ok_button_) {
delete ok_button_;
ok_button_ = NULL;
@@ -106,38 +104,27 @@ void DialogClientView::UpdateDialogButtons() {
if (buttons & ui::DIALOG_BUTTON_CANCEL) {
if (!cancel_button_) {
cancel_button_ = CreateDialogButton(ui::DIALOG_BUTTON_CANCEL);
- cancel_button_->AddAccelerator(escape);
AddChildView(cancel_button_);
}
- UpdateButton(cancel_button_, ui::DIALOG_BUTTON_CANCEL);
+ GetDialogDelegate()->UpdateButton(cancel_button_, ui::DIALOG_BUTTON_CANCEL);
} else if (cancel_button_) {
delete cancel_button_;
cancel_button_ = NULL;
}
- // Use the escape key to close the window if there are no dialog buttons.
- if (!has_dialog_buttons())
- AddAccelerator(escape);
- else
- ResetAccelerators();
+ SetupFocusChain();
}
///////////////////////////////////////////////////////////////////////////////
// DialogClientView, ClientView overrides:
bool DialogClientView::CanClose() {
- if (notified_delegate_)
- return true;
-
- // The dialog is closing but no Accept or Cancel action has been performed
- // before: it's a Close action.
- if (GetDialogDelegate()->Close()) {
- notified_delegate_ = true;
- GetDialogDelegate()->OnClosed();
- return true;
- }
- return false;
+ // If the dialog is closing but no Accept or Cancel action has been performed
+ // before, it's a Close action.
+ if (!delegate_allowed_close_)
+ delegate_allowed_close_ = GetDialogDelegate()->Close();
+ return delegate_allowed_close_;
}
DialogClientView* DialogClientView::AsDialogClientView() {
@@ -148,31 +135,6 @@ const DialogClientView* DialogClientView::AsDialogClientView() const {
return this;
}
-void DialogClientView::OnWillChangeFocus(View* focused_before,
- View* focused_now) {
- // Make the newly focused button default or restore the dialog's default.
- const int default_button = GetDialogDelegate()->GetDefaultDialogButton();
- LabelButton* new_default_button = NULL;
- if (focused_now &&
- !strcmp(focused_now->GetClassName(), LabelButton::kViewClassName)) {
- new_default_button = static_cast<LabelButton*>(focused_now);
- } else if (default_button == ui::DIALOG_BUTTON_OK && ok_button_) {
- new_default_button = ok_button_;
- } else if (default_button == ui::DIALOG_BUTTON_CANCEL && cancel_button_) {
- new_default_button = cancel_button_;
- }
-
- if (default_button_ && default_button_ != new_default_button)
- default_button_->SetIsDefault(false);
- default_button_ = new_default_button;
- if (default_button_ && !default_button_->is_default())
- default_button_->SetIsDefault(true);
-}
-
-void DialogClientView::OnDidChangeFocus(View* focused_before,
- View* focused_now) {
-}
-
////////////////////////////////////////////////////////////////////////////////
// DialogClientView, View overrides:
@@ -204,31 +166,12 @@ gfx::Size DialogClientView::GetPreferredSize() const {
size.Enlarge(0, contents_size.height());
size.set_width(std::max(size.width(), contents_size.width()));
- // Increase the size as needed to fit the footnote view.
- if (ShouldShow(footnote_view_)) {
- gfx::Size footnote_size = footnote_view_->GetPreferredSize();
- if (!footnote_size.IsEmpty())
- size.set_width(std::max(size.width(), footnote_size.width()));
-
- int footnote_height = footnote_view_->GetHeightForWidth(size.width());
- size.Enlarge(0, footnote_height);
- }
-
return size;
}
void DialogClientView::Layout() {
gfx::Rect bounds = GetContentsBounds();
- // Layout the footnote view.
- if (ShouldShow(footnote_view_)) {
- const int height = footnote_view_->GetHeightForWidth(bounds.width());
- footnote_view_->SetBounds(bounds.x(), bounds.bottom() - height,
- bounds.width(), height);
- if (height != 0)
- bounds.Inset(0, 0, 0, height);
- }
-
// Layout the row containing the buttons and the extra view.
if (has_dialog_buttons() || ShouldShow(extra_view_)) {
bounds.Inset(GetButtonRowInsets());
@@ -269,7 +212,12 @@ void DialogClientView::Layout() {
bool DialogClientView::AcceleratorPressed(const ui::Accelerator& accelerator) {
DCHECK_EQ(accelerator.key_code(), ui::VKEY_ESCAPE);
- Close();
+
+ // If there's a cancel button, it handles escape.
+ if (cancel_button_)
+ return cancel_button_->AcceleratorPressed(accelerator);
+
+ GetWidget()->Close();
return true;
}
@@ -277,35 +225,15 @@ void DialogClientView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
ClientView::ViewHierarchyChanged(details);
if (details.is_add && details.child == this) {
- focus_manager_ = GetFocusManager();
- if (focus_manager_)
- GetFocusManager()->AddFocusChangeListener(this);
-
UpdateDialogButtons();
CreateExtraView();
- CreateFootnoteView();
- } else if (!details.is_add && details.child == this) {
- if (focus_manager_)
- focus_manager_->RemoveFocusChangeListener(this);
- focus_manager_ = NULL;
- } else if (!details.is_add) {
- if (details.child == default_button_)
- default_button_ = NULL;
+ } else if (!details.is_add && details.child != this) {
if (details.child == ok_button_)
- ok_button_ = NULL;
- if (details.child == cancel_button_)
- cancel_button_ = NULL;
- }
-}
-
-void DialogClientView::NativeViewHierarchyChanged() {
- FocusManager* focus_manager = GetFocusManager();
- if (focus_manager_ != focus_manager) {
- if (focus_manager_)
- focus_manager_->RemoveFocusChangeListener(this);
- focus_manager_ = focus_manager;
- if (focus_manager_)
- focus_manager_->AddFocusChangeListener(this);
+ ok_button_ = nullptr;
+ else if (details.child == cancel_button_)
+ cancel_button_ = nullptr;
+ else if (details.child == extra_view_)
+ extra_view_ = nullptr;
}
}
@@ -343,11 +271,8 @@ DialogClientView::DialogClientView(View* contents_view)
: ClientView(NULL, contents_view),
ok_button_(NULL),
cancel_button_(NULL),
- default_button_(NULL),
- focus_manager_(NULL),
extra_view_(NULL),
- footnote_view_(NULL),
- notified_delegate_(false) {}
+ delegate_allowed_close_(false) {}
DialogDelegate* DialogClientView::GetDialogDelegate() const {
return GetWidget()->widget_delegate()->AsDialogDelegate();
@@ -361,20 +286,12 @@ void DialogClientView::CreateExtraView() {
if (extra_view_) {
extra_view_->SetGroup(kButtonGroup);
AddChildView(extra_view_);
+ SetupFocusChain();
}
}
-void DialogClientView::CreateFootnoteView() {
- if (footnote_view_)
- return;
-
- footnote_view_ = GetDialogDelegate()->CreateFootnoteView();
- if (footnote_view_)
- AddChildView(footnote_view_);
-}
-
void DialogClientView::ChildPreferredSizeChanged(View* child) {
- if (child == footnote_view_ || child == extra_view_)
+ if (child == extra_view_)
Layout();
}
@@ -404,18 +321,6 @@ LabelButton* DialogClientView::CreateDialogButton(ui::DialogButton type) {
return button;
}
-void DialogClientView::UpdateButton(LabelButton* button,
- ui::DialogButton type) {
- DialogDelegate* dialog = GetDialogDelegate();
- button->SetText(dialog->GetDialogButtonLabel(type));
- button->SetEnabled(dialog->IsDialogButtonEnabled(type));
-
- if (type == dialog->GetDefaultDialogButton()) {
- default_button_ = button;
- button->SetIsDefault(true);
- }
-}
-
int DialogClientView::GetButtonsAndExtraViewRowHeight() const {
int extra_view_height = ShouldShow(extra_view_) ?
extra_view_->GetPreferredSize().height() : 0;
@@ -426,15 +331,32 @@ int DialogClientView::GetButtonsAndExtraViewRowHeight() const {
}
gfx::Insets DialogClientView::GetButtonRowInsets() const {
- // NOTE: The insets only apply to the buttons, extra view, and footnote view.
- return GetButtonsAndExtraViewRowHeight() == 0 ? gfx::Insets() :
- gfx::Insets(0, kButtonHEdgeMarginNew,
- kButtonVEdgeMarginNew, kButtonHEdgeMarginNew);
+ return GetButtonsAndExtraViewRowHeight() == 0 ? gfx::Insets()
+ : button_row_insets_;
}
-void DialogClientView::Close() {
- GetWidget()->Close();
- GetDialogDelegate()->OnClosed();
+void DialogClientView::SetupFocusChain() {
+ // Create a vector of child views in the order of intended focus.
+ std::vector<View*> child_views;
+ child_views.push_back(contents_view());
+ child_views.push_back(extra_view_);
+ if (kIsOkButtonOnLeftSide) {
+ child_views.push_back(ok_button_);
+ child_views.push_back(cancel_button_);
+ } else {
+ child_views.push_back(cancel_button_);
+ child_views.push_back(ok_button_);
+ }
+
+ // Remove all null views from the vector.
+ child_views.erase(
+ std::remove(child_views.begin(), child_views.end(), nullptr),
+ child_views.end());
+
+ // Setup focus by reordering views. It is not safe to use SetNextFocusableView
+ // since child views may be added externally to this view.
+ for (size_t i = 0; i < child_views.size(); i++)
+ ReorderChildView(child_views[i], i);
}
} // namespace views
diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h
index 05e14b433ac..60080b00c8c 100644
--- a/chromium/ui/views/window/dialog_client_view.h
+++ b/chromium/ui/views/window/dialog_client_view.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/controls/button/button.h"
-#include "ui/views/focus/focus_manager.h"
#include "ui/views/window/client_view.h"
namespace views {
@@ -20,18 +19,16 @@ class Widget;
// DialogClientView provides adornments for a dialog's content view, including
// custom-labeled [OK] and [Cancel] buttons with [Enter] and [Esc] accelerators.
-// The view also displays the delegate's extra view alongside the buttons and
-// the delegate's footnote view below the buttons. The view appears like below.
-// NOTE: The contents view is not inset on the top or side client view edges.
+// The view also displays the delegate's extra view alongside the buttons. The
+// view appears like below. NOTE: The contents view is not inset on the top or
+// side client view edges.
// +------------------------------+
// | Contents View |
// +------------------------------+
// | [Extra View] [OK] [Cancel] |
-// | [ Footnote View ] |
// +------------------------------+
class VIEWS_EXPORT DialogClientView : public ClientView,
- public ButtonListener,
- public FocusChangeListener {
+ public ButtonListener {
public:
DialogClientView(Widget* widget, View* contents_view);
~DialogClientView() override;
@@ -52,22 +49,21 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
DialogClientView* AsDialogClientView() override;
const DialogClientView* AsDialogClientView() const override;
- // FocusChangeListener implementation:
- void OnWillChangeFocus(View* focused_before, View* focused_now) override;
- void OnDidChangeFocus(View* focused_before, View* focused_now) override;
-
// View implementation:
gfx::Size GetPreferredSize() const override;
void Layout() override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
- void NativeViewHierarchyChanged() override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
// ButtonListener implementation:
void ButtonPressed(Button* sender, const ui::Event& event) override;
+ void set_button_row_insets(const gfx::Insets& insets) {
+ button_row_insets_ = insets;
+ }
+
protected:
// For testing.
explicit DialogClientView(View* contents_view);
@@ -78,16 +74,11 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
// Create and add the extra view, if supplied by the delegate.
void CreateExtraView();
- // Creates and adds the footnote view, if supplied by the delegate.
- void CreateFootnoteView();
-
// View implementation.
void ChildPreferredSizeChanged(View* child) override;
void ChildVisibilityChanged(View* child) override;
private:
- FRIEND_TEST_ALL_PREFIXES(DialogClientViewTest, FocusManager);
-
bool has_dialog_buttons() const { return ok_button_ || cancel_button_; }
// Create a dialog button of the appropriate type.
@@ -102,30 +93,25 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
// Returns the insets for the buttons and extra view.
gfx::Insets GetButtonRowInsets() const;
- // Closes the widget.
- void Close();
+ // How much to inset the button row.
+ gfx::Insets button_row_insets_;
+
+ // Sets up the focus chain for the child views. This is required since the
+ // delegate may choose to add/remove views at any time.
+ void SetupFocusChain();
// The dialog buttons.
LabelButton* ok_button_;
LabelButton* cancel_button_;
- // The button that is currently default; may be NULL.
- LabelButton* default_button_;
-
- // Observe |focus_manager_| to update the default button with focus changes.
- FocusManager* focus_manager_;
-
// The extra view shown in the row of buttons; may be NULL.
View* extra_view_;
- // The footnote view shown below the buttons; may be NULL.
- View* footnote_view_;
-
// True if we've notified the delegate the window is closing and the delegate
- // allosed the close. In some situations it's possible to get two closes (see
+ // allowed the close. In some situations it's possible to get two closes (see
// http://crbug.com/71940). This is used to avoid notifying the delegate
// twice, which can have bad consequences.
- bool notified_delegate_;
+ bool delegate_allowed_close_;
DISALLOW_COPY_AND_ASSIGN(DialogClientView);
};
diff --git a/chromium/ui/views/window/dialog_client_view_unittest.cc b/chromium/ui/views/window/dialog_client_view_unittest.cc
index 2a08f3e684f..9078aba9f17 100644
--- a/chromium/ui/views/window/dialog_client_view_unittest.cc
+++ b/chromium/ui/views/window/dialog_client_view_unittest.cc
@@ -17,55 +17,55 @@ namespace views {
class TestDialogClientView : public DialogClientView {
public:
- TestDialogClientView(View* contents_view,
- DialogDelegate* dialog_delegate)
- : DialogClientView(contents_view),
- dialog_(dialog_delegate) {}
+ explicit TestDialogClientView(DialogDelegateView* dialog_delegate_view)
+ : DialogClientView(dialog_delegate_view),
+ dialog_delegate_view_(dialog_delegate_view) {}
~TestDialogClientView() override {}
// DialogClientView implementation.
- DialogDelegate* GetDialogDelegate() const override { return dialog_; }
+ DialogDelegate* GetDialogDelegate() const override {
+ return dialog_delegate_view_;
+ }
View* GetContentsView() { return contents_view(); }
void CreateExtraViews() {
CreateExtraView();
- CreateFootnoteView();
}
private:
- DialogDelegate* dialog_;
+ DialogDelegateView* dialog_delegate_view_;
DISALLOW_COPY_AND_ASSIGN(TestDialogClientView);
};
+// Base class for tests. Also acts as the dialog delegate and contents view for
+// TestDialogClientView.
class DialogClientViewTest : public ViewsTestBase,
public DialogDelegateView {
public:
DialogClientViewTest()
: dialog_buttons_(ui::DIALOG_BUTTON_NONE),
- extra_view_(NULL),
- footnote_view_(NULL) {}
+ extra_view_(nullptr) {}
~DialogClientViewTest() override {}
// testing::Test implementation.
void SetUp() override {
dialog_buttons_ = ui::DIALOG_BUTTON_NONE;
- contents_.reset(new StaticSizedView(gfx::Size(100, 200)));
- client_view_.reset(new TestDialogClientView(contents_.get(), this));
-
+ client_view_.reset(new TestDialogClientView(this));
+ // Add this i.e. the contents view as a child of |client_view_|. This is
+ // generally done when the client view is added to the view hierarchy.
+ client_view_->AddChildViewAt(this, 0);
ViewsTestBase::SetUp();
}
// DialogDelegateView implementation.
- View* GetContentsView() override { return contents_.get(); }
View* CreateExtraView() override { return extra_view_; }
bool GetExtraViewPadding(int* padding) override {
if (extra_view_padding_)
*padding = *extra_view_padding_;
return extra_view_padding_.get() != nullptr;
}
- View* CreateFootnoteView() override { return footnote_view_; }
int GetDialogButtons() const override { return dialog_buttons_; }
protected:
@@ -79,11 +79,11 @@ class DialogClientViewTest : public ViewsTestBase,
// the requested amount, but height should always match exactly.
void CheckContentsIsSetToPreferredSize() {
const gfx::Rect client_bounds = GetUpdatedClientBounds();
- const gfx::Size preferred_size = contents_->GetPreferredSize();
- EXPECT_EQ(preferred_size.height(), contents_->bounds().height());
- EXPECT_LE(preferred_size.width(), contents_->bounds().width());
- EXPECT_EQ(contents_->bounds().origin(), client_bounds.origin());
- EXPECT_EQ(contents_->bounds().right(), client_bounds.right());
+ const gfx::Size preferred_size = this->GetPreferredSize();
+ EXPECT_EQ(preferred_size.height(), this->bounds().height());
+ EXPECT_LE(preferred_size.width(), this->bounds().width());
+ EXPECT_EQ(this->bounds().origin(), client_bounds.origin());
+ EXPECT_EQ(this->bounds().right(), client_bounds.right());
}
// Sets the buttons to show in the dialog and refreshes the dialog.
@@ -106,25 +106,15 @@ class DialogClientViewTest : public ViewsTestBase,
client_view_->Layout();
}
- // Sets the footnote view.
- void SetFootnoteView(View* view) {
- DCHECK(!footnote_view_);
- footnote_view_ = view;
- client_view_->CreateExtraViews();
- }
-
TestDialogClientView* client_view() { return client_view_.get(); }
private:
- // The contents of the dialog.
- scoped_ptr<View> contents_;
// The DialogClientView that's being tested.
scoped_ptr<TestDialogClientView> client_view_;
// The bitmask of buttons to show in the dialog.
int dialog_buttons_;
View* extra_view_; // weak
scoped_ptr<int> extra_view_padding_; // Null by default.
- View* footnote_view_; // weak
DISALLOW_COPY_AND_ASSIGN(DialogClientViewTest);
};
@@ -176,6 +166,50 @@ TEST_F(DialogClientViewTest, RemoveAndUpdateButtons) {
EXPECT_FALSE(client_view()->cancel_button()->is_default());
}
+// Test that views inside the dialog client view have the correct focus order.
+TEST_F(DialogClientViewTest, SetupFocusChain) {
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+ const bool kIsOkButtonOnLeftSide = true;
+#else
+ const bool kIsOkButtonOnLeftSide = false;
+#endif
+
+ // Initially the dialog client view only contains the content view.
+ EXPECT_EQ(nullptr, client_view()->GetContentsView()->GetNextFocusableView());
+
+ // Add OK and cancel buttons.
+ SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
+
+ if (kIsOkButtonOnLeftSide) {
+ EXPECT_EQ(client_view()->ok_button(),
+ client_view()->GetContentsView()->GetNextFocusableView());
+ EXPECT_EQ(client_view()->cancel_button(),
+ client_view()->ok_button()->GetNextFocusableView());
+ EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView());
+ } else {
+ EXPECT_EQ(client_view()->cancel_button(),
+ client_view()->GetContentsView()->GetNextFocusableView());
+ EXPECT_EQ(client_view()->ok_button(),
+ client_view()->cancel_button()->GetNextFocusableView());
+ EXPECT_EQ(nullptr, client_view()->ok_button()->GetNextFocusableView());
+ }
+
+ // Add extra view and remove OK button.
+ View* extra_view = new StaticSizedView(gfx::Size(200, 200));
+ SetExtraView(extra_view);
+ SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
+
+ EXPECT_EQ(extra_view,
+ client_view()->GetContentsView()->GetNextFocusableView());
+ EXPECT_EQ(client_view()->cancel_button(), extra_view->GetNextFocusableView());
+ EXPECT_EQ(nullptr, client_view()->cancel_button()->GetNextFocusableView());
+
+ // Add a dummy view to the client view.
+ View* dummy_view = new StaticSizedView(gfx::Size(200, 200));
+ client_view()->AddChildView(dummy_view);
+ EXPECT_EQ(dummy_view, client_view()->cancel_button()->GetNextFocusableView());
+}
+
// Test that the contents view gets its preferred size in the basic dialog
// configuration.
TEST_F(DialogClientViewTest, ContentsSize) {
@@ -217,103 +251,4 @@ TEST_F(DialogClientViewTest, LayoutWithButtons) {
EXPECT_GT(width_of_extra_view, extra_view->bounds().width());
}
-// Test the effect of the footnote view on layout.
-TEST_F(DialogClientViewTest, LayoutWithFootnote) {
- CheckContentsIsSetToPreferredSize();
- gfx::Size no_footnote_size = client_view()->bounds().size();
-
- View* footnote_view = new StaticSizedView(gfx::Size(200, 200));
- SetFootnoteView(footnote_view);
- CheckContentsIsSetToPreferredSize();
- EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
- EXPECT_EQ(200, footnote_view->bounds().height());
- gfx::Size with_footnote_size = client_view()->bounds().size();
- EXPECT_EQ(with_footnote_size.width(), footnote_view->bounds().width());
-
- SetDialogButtons(ui::DIALOG_BUTTON_CANCEL);
- CheckContentsIsSetToPreferredSize();
- EXPECT_LE(with_footnote_size.height(), client_view()->bounds().height());
- EXPECT_LE(with_footnote_size.width(), client_view()->bounds().width());
- gfx::Size with_footnote_and_button_size = client_view()->bounds().size();
-
- SetDialogButtons(ui::DIALOG_BUTTON_NONE);
- footnote_view->SetVisible(false);
- CheckContentsIsSetToPreferredSize();
- EXPECT_EQ(no_footnote_size.height(), client_view()->bounds().height());
- EXPECT_EQ(no_footnote_size.width(), client_view()->bounds().width());
-}
-
-// Test that GetHeightForWidth is respected for the footnote view.
-TEST_F(DialogClientViewTest, LayoutWithFootnoteHeightForWidth) {
- CheckContentsIsSetToPreferredSize();
- gfx::Size no_footnote_size = client_view()->bounds().size();
-
- View* footnote_view = new ProportionallySizedView(3);
- SetFootnoteView(footnote_view);
- CheckContentsIsSetToPreferredSize();
- EXPECT_GT(client_view()->bounds().height(), no_footnote_size.height());
- EXPECT_EQ(footnote_view->bounds().width() * 3,
- footnote_view->bounds().height());
-}
-
-// No ReparentNativeView on Mac. See http://crbug.com/514920.
-#if defined(OS_MACOSX) && !defined(USE_AURA)
-#define MAYBE_FocusManager DISABLED_FocusManager
-#else
-#define MAYBE_FocusManager FocusManager
-#endif
-
-// Test that the DialogClientView's FocusManager is properly updated when the
-// DialogClientView belongs to a non top level widget and the widget is
-// reparented. The DialogClientView belongs to a non top level widget in the
-// case of constrained windows. The constrained window's widget is reparented
-// when a browser tab is dragged to a different browser window.
-TEST_F(DialogClientViewTest, MAYBE_FocusManager) {
- scoped_ptr<Widget> toplevel1(new Widget);
- Widget::InitParams toplevel1_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- toplevel1->Init(toplevel1_params);
-
- scoped_ptr<Widget> toplevel2(new Widget);
- Widget::InitParams toplevel2_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- toplevel2->Init(toplevel2_params);
-
- Widget* dialog = new Widget;
- Widget::InitParams dialog_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- dialog_params.child = true;
- dialog_params.delegate = new DialogDelegateView();
- dialog_params.parent = toplevel1->GetNativeView();
- dialog->Init(dialog_params);
-
- // Test that the FocusManager has been properly set when the DialogClientView
- // was parented to |dialog|.
- DialogClientView* client_view =
- static_cast<DialogClientView*>(dialog->client_view());
- EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
-
- // Test that the FocusManager is properly updated when the DialogClientView's
- // top level widget is changed.
- Widget::ReparentNativeView(dialog->GetNativeView(), NULL);
- EXPECT_EQ(NULL, client_view->focus_manager_);
- Widget::ReparentNativeView(dialog->GetNativeView(),
- toplevel2->GetNativeView());
- EXPECT_EQ(toplevel2->GetFocusManager(), client_view->focus_manager_);
- Widget::ReparentNativeView(dialog->GetNativeView(),
- toplevel1->GetNativeView());
- EXPECT_NE(toplevel1->GetFocusManager(), toplevel2->GetFocusManager());
- EXPECT_EQ(toplevel1->GetFocusManager(), client_view->focus_manager_);
-
- // Test that the FocusManager is properly cleared when the DialogClientView is
- // removed from |dialog| during the widget's destruction.
- client_view->set_owned_by_client();
- scoped_ptr<DialogClientView> owned_client_view(client_view);
- toplevel1->CloseNow();
- toplevel2->CloseNow();
- EXPECT_EQ(NULL, owned_client_view->focus_manager_);
-}
-
} // namespace views
diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc
index 8f292ecec82..84ed6b9fc2e 100644
--- a/chromium/ui/views/window/dialog_delegate.cc
+++ b/chromium/ui/views/window/dialog_delegate.cc
@@ -15,6 +15,7 @@
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/button/label_button.h"
+#include "ui/views/layout/layout_constants.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/dialog_client_view.h"
@@ -28,11 +29,9 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// DialogDelegate:
-DialogDelegate::DialogDelegate() : supports_new_style_(true) {
-}
+DialogDelegate::DialogDelegate() : supports_new_style_(true) {}
-DialogDelegate::~DialogDelegate() {
-}
+DialogDelegate::~DialogDelegate() {}
// static
Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
@@ -93,10 +92,6 @@ bool DialogDelegate::GetExtraViewPadding(int* padding) {
return false;
}
-View* DialogDelegate::CreateTitlebarExtraView() {
- return NULL;
-}
-
View* DialogDelegate::CreateFootnoteView() {
return NULL;
}
@@ -105,10 +100,6 @@ bool DialogDelegate::Cancel() {
return true;
}
-bool DialogDelegate::Accept(bool window_closing) {
- return Accept();
-}
-
bool DialogDelegate::Accept() {
return true;
}
@@ -119,11 +110,13 @@ bool DialogDelegate::Close() {
(buttons == ui::DIALOG_BUTTON_NONE)) {
return Cancel();
}
- return Accept(true);
+ return Accept();
}
-base::string16 DialogDelegate::GetDialogTitle() const {
- return GetWindowTitle();
+void DialogDelegate::UpdateButton(LabelButton* button, ui::DialogButton type) {
+ button->SetText(GetDialogButtonLabel(type));
+ button->SetEnabled(IsDialogButtonEnabled(type));
+ button->SetIsDefault(type == GetDefaultDialogButton());
}
int DialogDelegate::GetDialogButtons() const {
@@ -195,23 +188,18 @@ NonClientFrameView* DialogDelegate::CreateNonClientFrameView(Widget* widget) {
// static
NonClientFrameView* DialogDelegate::CreateDialogFrameView(Widget* widget) {
- BubbleFrameView* frame = new BubbleFrameView(gfx::Insets());
-#if defined(OS_MACOSX)
- // On Mac, dialogs have no border stroke and use a shadow provided by the OS.
- const BubbleBorder::Shadow kShadow = BubbleBorder::NO_ASSETS;
-#else
+ BubbleFrameView* frame =
+ new BubbleFrameView(gfx::Insets(kPanelVertMargin, kButtonHEdgeMarginNew,
+ 0, kButtonHEdgeMarginNew),
+ gfx::Insets());
const BubbleBorder::Shadow kShadow = BubbleBorder::SMALL_SHADOW;
-#endif
scoped_ptr<BubbleBorder> border(
new BubbleBorder(BubbleBorder::FLOAT, kShadow, gfx::kPlaceholderColor));
border->set_use_theme_background_color(true);
frame->SetBubbleBorder(std::move(border));
DialogDelegate* delegate = widget->widget_delegate()->AsDialogDelegate();
- if (delegate) {
- View* titlebar_view = delegate->CreateTitlebarExtraView();
- if (titlebar_view)
- frame->SetTitlebarExtraView(titlebar_view);
- }
+ if (delegate)
+ frame->SetFootnoteView(delegate->CreateFootnoteView());
return frame;
}
@@ -258,7 +246,7 @@ View* DialogDelegateView::GetContentsView() {
}
void DialogDelegateView::GetAccessibleState(ui::AXViewState* state) {
- state->name = GetDialogTitle();
+ state->name = GetWindowTitle();
state->role = ui::AX_ROLE_DIALOG;
}
diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h
index dc9f89a1aac..06c9bbe6b93 100644
--- a/chromium/ui/views/window/dialog_delegate.h
+++ b/chromium/ui/views/window/dialog_delegate.h
@@ -16,6 +16,7 @@
namespace views {
class DialogClientView;
+class LabelButton;
///////////////////////////////////////////////////////////////////////////////
//
@@ -56,11 +57,6 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// If a custom padding should be used, returns true and populates |padding|.
virtual bool GetExtraViewPadding(int* padding);
- // Override this function to display an extra view in the titlebar.
- // Overrides may construct the view; this will only be called once per dialog.
- // Note: this only works for new style dialogs.
- virtual View* CreateTitlebarExtraView();
-
// Override this function to display a footnote view below the buttons.
// Overrides may construct the view; this will only be called once per dialog.
virtual View* CreateFootnoteView();
@@ -76,10 +72,6 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// or the Enter key. It can also be called on a close action if |Close|
// has not been overridden. This function should return true if the window
// can be closed after it returns, or false if it must remain open.
- // If |window_closing| is true, it means that this handler is
- // being called because the window is being closed (e.g. by Window::Close)
- // and there is no Cancel handler, so Accept is being called instead.
- virtual bool Accept(bool window_closing);
virtual bool Accept();
// Called when the user closes the window without selecting an option,
@@ -89,8 +81,12 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// window can be closed after it returns, or false if it must remain open.
virtual bool Close();
+ // Updates the properties and appearance of |button| which has been created
+ // for type |type|. Override to do special initialization above and beyond
+ // the typical.
+ virtual void UpdateButton(LabelButton* button, ui::DialogButton type);
+
// Overridden from ui::DialogModel:
- base::string16 GetDialogTitle() const override;
int GetDialogButtons() const override;
int GetDefaultDialogButton() const override;
bool ShouldDefaultButtonBeBlue() const override;
@@ -109,9 +105,6 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// Returns whether this particular dialog should use the new dialog style.
virtual bool UseNewStyleForThisDialog() const;
- // Called when the window has been closed.
- virtual void OnClosed() {}
-
// A helper for accessing the DialogClientView object contained by this
// delegate's Window.
const DialogClientView* GetDialogClientView() const;
diff --git a/chromium/ui/views/window/dialog_delegate_unittest.cc b/chromium/ui/views/window/dialog_delegate_unittest.cc
index 3499426b10f..86e957ddcb1 100644
--- a/chromium/ui/views/window/dialog_delegate_unittest.cc
+++ b/chromium/ui/views/window/dialog_delegate_unittest.cc
@@ -7,10 +7,12 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/hit_test.h"
+#include "ui/events/event_processor.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_client_view.h"
@@ -23,12 +25,24 @@ namespace {
class TestDialog : public DialogDelegateView, public ButtonListener {
public:
TestDialog()
- : canceled_(false),
+ : input_(new views::Textfield()),
+ canceled_(false),
accepted_(false),
closeable_(false),
- last_pressed_button_(NULL) {}
+ last_pressed_button_(nullptr),
+ should_handle_escape_(false) {
+ AddChildView(input_);
+ }
~TestDialog() override {}
+ void Init() {
+ // Add the accelerator before being added to the widget hierarchy (before
+ // DCV has registered its accelerator) to make sure accelerator handling is
+ // not dependent on the order of AddAccelerator calls.
+ EXPECT_FALSE(GetWidget());
+ AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
+ }
+
// WidgetDelegate overrides:
bool ShouldShowWindowTitle() const override {
return !title_.empty();
@@ -46,7 +60,11 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
// DialogDelegateView overrides:
gfx::Size GetPreferredSize() const override { return gfx::Size(200, 200); }
+ bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
+ return should_handle_escape_;
+ }
base::string16 GetWindowTitle() const override { return title_; }
+ View* GetInitiallyFocusedView() override { return input_; }
bool UseNewStyleForThisDialog() const override { return true; }
// ButtonListener override:
@@ -56,25 +74,13 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
Button* last_pressed_button() const { return last_pressed_button_; }
- void PressEnterAndCheckStates(Button* button) {
- ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE);
- GetFocusManager()->OnKeyEvent(key_event);
- const DialogClientView* client_view = GetDialogClientView();
- EXPECT_EQ(canceled_, client_view->cancel_button()->is_default());
- EXPECT_EQ(accepted_, client_view->ok_button()->is_default());
- // This view does not listen for ok or cancel clicks, DialogClientView does.
- CheckAndResetStates(button == client_view->cancel_button(),
- button == client_view->ok_button(),
- (canceled_ || accepted_ ) ? NULL : button);
- }
-
void CheckAndResetStates(bool canceled, bool accepted, Button* last_pressed) {
EXPECT_EQ(canceled, canceled_);
canceled_ = false;
EXPECT_EQ(accepted, accepted_);
accepted_ = false;
EXPECT_EQ(last_pressed, last_pressed_button_);
- last_pressed_button_ = NULL;
+ last_pressed_button_ = nullptr;
}
void TearDown() {
@@ -83,27 +89,35 @@ class TestDialog : public DialogDelegateView, public ButtonListener {
}
void set_title(const base::string16& title) { title_ = title; }
+ void set_should_handle_escape(bool should_handle_escape) {
+ should_handle_escape_ = should_handle_escape;
+ }
+
+ views::Textfield* input() { return input_; }
private:
+ views::Textfield* input_;
bool canceled_;
bool accepted_;
// Prevent the dialog from closing, for repeated ok and cancel button clicks.
bool closeable_;
Button* last_pressed_button_;
base::string16 title_;
+ bool should_handle_escape_;
DISALLOW_COPY_AND_ASSIGN(TestDialog);
};
class DialogTest : public ViewsTestBase {
public:
- DialogTest() : dialog_(NULL) {}
+ DialogTest() : dialog_(nullptr) {}
~DialogTest() override {}
void SetUp() override {
ViewsTestBase::SetUp();
dialog_ = new TestDialog();
- DialogDelegate::CreateDialogWidget(dialog_, GetContext(), NULL)->Show();
+ dialog_->Init();
+ DialogDelegate::CreateDialogWidget(dialog_, GetContext(), nullptr)->Show();
}
void TearDown() override {
@@ -111,6 +125,12 @@ class DialogTest : public ViewsTestBase {
ViewsTestBase::TearDown();
}
+ void SimulateKeyEvent(const ui::KeyEvent& event) {
+ ui::KeyEvent event_copy = event;
+ if (dialog()->GetFocusManager()->OnKeyEvent(event_copy))
+ dialog()->GetWidget()->OnKeyEvent(&event_copy);
+ }
+
TestDialog* dialog() const { return dialog_; }
private:
@@ -121,68 +141,38 @@ class DialogTest : public ViewsTestBase {
} // namespace
-TEST_F(DialogTest, DefaultButtons) {
- DialogClientView* client_view = dialog()->GetDialogClientView();
- LabelButton* ok_button = client_view->ok_button();
-
- // DialogDelegate's default button (ok) should be default (and handle enter).
- EXPECT_EQ(ui::DIALOG_BUTTON_OK, dialog()->GetDefaultDialogButton());
- dialog()->PressEnterAndCheckStates(ok_button);
-
- // Focus another button in the dialog, it should become the default.
- 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(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(), base::string16());
- client_view->AddChildView(button_2);
- client_view->OnWillChangeFocus(checkbox, button_2);
- EXPECT_FALSE(button_1->is_default());
- EXPECT_TRUE(button_2->is_default());
- dialog()->PressEnterAndCheckStates(button_2);
-
- // Focus nothing, OK should become the default again.
- client_view->OnWillChangeFocus(button_2, NULL);
- EXPECT_FALSE(button_1->is_default());
- EXPECT_FALSE(button_2->is_default());
- dialog()->PressEnterAndCheckStates(ok_button);
-}
-
TEST_F(DialogTest, AcceptAndCancel) {
DialogClientView* client_view = dialog()->GetDialogClientView();
LabelButton* ok_button = client_view->ok_button();
LabelButton* cancel_button = client_view->cancel_button();
// Check that return/escape accelerators accept/cancel dialogs.
- const ui::KeyEvent return_key(
+ EXPECT_EQ(dialog()->input(), dialog()->GetFocusManager()->GetFocusedView());
+ const ui::KeyEvent return_event(
ui::ET_KEY_PRESSED, ui::VKEY_RETURN, ui::EF_NONE);
- dialog()->GetFocusManager()->OnKeyEvent(return_key);
- dialog()->CheckAndResetStates(false, true, NULL);
- const ui::KeyEvent escape_key(
+ SimulateKeyEvent(return_event);
+ dialog()->CheckAndResetStates(false, true, nullptr);
+ const ui::KeyEvent escape_event(
ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, ui::EF_NONE);
- dialog()->GetFocusManager()->OnKeyEvent(escape_key);
- dialog()->CheckAndResetStates(true, false, NULL);
+ SimulateKeyEvent(escape_event);
+ dialog()->CheckAndResetStates(true, false, nullptr);
// Check ok and cancel button behavior on a directed return key events.
- ok_button->OnKeyPressed(return_key);
- dialog()->CheckAndResetStates(false, true, NULL);
- cancel_button->OnKeyPressed(return_key);
- dialog()->CheckAndResetStates(true, false, NULL);
+ ok_button->OnKeyPressed(return_event);
+ dialog()->CheckAndResetStates(false, true, nullptr);
+ cancel_button->OnKeyPressed(return_event);
+ dialog()->CheckAndResetStates(true, false, nullptr);
// Check that return accelerators cancel dialogs if cancel is focused.
cancel_button->RequestFocus();
- dialog()->GetFocusManager()->OnKeyEvent(return_key);
- dialog()->CheckAndResetStates(true, false, NULL);
+ EXPECT_EQ(cancel_button, dialog()->GetFocusManager()->GetFocusedView());
+ SimulateKeyEvent(return_event);
+ dialog()->CheckAndResetStates(true, false, nullptr);
+
+ // Check that escape can be overridden.
+ dialog()->set_should_handle_escape(true);
+ SimulateKeyEvent(escape_event);
+ dialog()->CheckAndResetStates(false, false, nullptr);
}
TEST_F(DialogTest, RemoveDefaultButton) {
@@ -212,7 +202,8 @@ TEST_F(DialogTest, HitTest_HiddenTitle) {
for (size_t i = 0; i < arraysize(cases); ++i) {
gfx::Point point(cases[i].point, cases[i].point);
EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point))
- << " with border: " << border << ", at point " << cases[i].point;
+ << " case " << i << " with border: " << border << ", at point "
+ << cases[i].point;
}
}
@@ -246,7 +237,7 @@ TEST_F(DialogTest, HitTest_WithTitle) {
TEST_F(DialogTest, BoundsAccommodateTitle) {
TestDialog* dialog2(new TestDialog());
dialog2->set_title(base::ASCIIToUTF16("Title"));
- DialogDelegate::CreateDialogWidget(dialog2, GetContext(), NULL);
+ DialogDelegate::CreateDialogWidget(dialog2, GetContext(), nullptr);
// Titled dialogs have taller initial frame bounds than untitled dialogs.
View* frame1 = dialog()->GetWidget()->non_client_view()->frame_view();
@@ -263,4 +254,10 @@ TEST_F(DialogTest, BoundsAccommodateTitle) {
dialog2->TearDown();
}
+// Tests default focus is assigned correctly when showing a new dialog.
+TEST_F(DialogTest, InitialFocus) {
+ EXPECT_TRUE(dialog()->input()->HasFocus());
+ EXPECT_EQ(dialog()->input(), dialog()->GetFocusManager()->GetFocusedView());
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/frame_background.cc b/chromium/ui/views/window/frame_background.cc
index a325dbf9b3d..3e0e4ff5c06 100644
--- a/chromium/ui/views/window/frame_background.cc
+++ b/chromium/ui/views/window/frame_background.cc
@@ -13,20 +13,17 @@
namespace views {
FrameBackground::FrameBackground()
- : frame_color_(0),
- theme_image_(NULL),
- theme_overlay_image_(NULL),
- top_area_height_(0),
- left_edge_(NULL),
- top_edge_(NULL),
- right_edge_(NULL),
- bottom_edge_(NULL),
- top_left_corner_(NULL),
- top_right_corner_(NULL),
- bottom_left_corner_(NULL),
- bottom_right_corner_(NULL),
- maximized_top_inset_(0) {
-}
+ : frame_color_(0),
+ top_area_height_(0),
+ left_edge_(nullptr),
+ top_edge_(nullptr),
+ right_edge_(nullptr),
+ bottom_edge_(nullptr),
+ top_left_corner_(nullptr),
+ top_right_corner_(nullptr),
+ bottom_left_corner_(nullptr),
+ bottom_right_corner_(nullptr),
+ maximized_top_inset_(0) {}
FrameBackground::~FrameBackground() {
}
@@ -51,18 +48,19 @@ void FrameBackground::SetCornerImages(const gfx::ImageSkia* top_left,
bottom_right_corner_ = bottom_right;
}
-void FrameBackground::PaintRestored(gfx::Canvas* canvas, View* view) const {
+void FrameBackground::PaintRestored(gfx::Canvas* canvas,
+ const View* view) const {
// Fill with the frame color first so we have a constant background for
// areas not covered by the theme image.
PaintFrameColor(canvas, view);
- // Draw the theme frame.
- canvas->TileImageInt(*theme_image_,
- 0, 0, view->width(), theme_image_->height());
-
- // Draw the theme frame overlay, if available.
- if (theme_overlay_image_)
- canvas->DrawImageInt(*theme_overlay_image_, 0, 0);
+ // Draw the theme frame and overlay, if available.
+ if (!theme_image_.isNull()) {
+ canvas->TileImageInt(theme_image_, 0, 0, view->width(),
+ theme_image_.height());
+ }
+ if (!theme_overlay_image_.isNull())
+ canvas->DrawImageInt(theme_overlay_image_, 0, 0);
// Draw the top corners and edge, scaling the corner images down if they
// are too big and relative to the vertical space available.
@@ -119,29 +117,31 @@ void FrameBackground::PaintRestored(gfx::Canvas* canvas, View* view) const {
left_edge_->width(), left_edge_height);
}
-void FrameBackground::PaintMaximized(gfx::Canvas* canvas, View* view) const {
+void FrameBackground::PaintMaximized(gfx::Canvas* canvas,
+ const View* view) const {
// We will be painting from -|maximized_top_inset_| to
- // -|maximized_top_inset_| + |theme_image_|->height(). If this is less than
+ // -|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();
+ int theme_frame_bottom = -maximized_top_inset_ +
+ (theme_image_.isNull() ? 0 : theme_image_.height());
if (top_area_height_ > theme_frame_bottom) {
canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_),
frame_color_);
}
// Draw the theme frame.
- canvas->TileImageInt(*theme_image_,
- 0,
- -maximized_top_inset_,
- view->width(),
- theme_image_->height());
+ if (!theme_image_.isNull()) {
+ canvas->TileImageInt(theme_image_, 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, -maximized_top_inset_);
+ if (!theme_overlay_image_.isNull())
+ canvas->DrawImageInt(theme_overlay_image_, 0, -maximized_top_inset_);
}
-void FrameBackground::PaintFrameColor(gfx::Canvas* canvas, View* view) const {
+void FrameBackground::PaintFrameColor(gfx::Canvas* canvas,
+ const View* view) const {
// Fill the top area.
canvas->FillRect(gfx::Rect(0, 0, view->width(), top_area_height_),
frame_color_);
diff --git a/chromium/ui/views/window/frame_background.h b/chromium/ui/views/window/frame_background.h
index c2278c10c96..a420de556cf 100644
--- a/chromium/ui/views/window/frame_background.h
+++ b/chromium/ui/views/window/frame_background.h
@@ -7,11 +7,11 @@
#include "base/macros.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/views/views_export.h"
namespace gfx {
class Canvas;
-class ImageSkia;
}
namespace views {
@@ -29,14 +29,14 @@ class VIEWS_EXPORT FrameBackground {
// Sets the color to draw under the frame images.
void set_frame_color(SkColor color) { frame_color_ = color; }
- // Sets the theme image for the top of the window. May be NULL.
+ // Sets the theme image for the top of the window. May be null (empty).
// Memory is owned by the caller.
- void set_theme_image(const gfx::ImageSkia* image) { theme_image_ = image; }
+ void set_theme_image(const gfx::ImageSkia& image) { theme_image_ = image; }
// Sets an image that overlays the top window image. Usually used to add
- // edge highlighting to provide the illusion of depth. May be NULL.
+ // edge highlighting to provide the illusion of depth. May be null (empty).
// Memory is owned by the caller.
- void set_theme_overlay_image(gfx::ImageSkia* image) {
+ void set_theme_overlay_image(const gfx::ImageSkia& image) {
theme_overlay_image_ = image;
}
@@ -64,19 +64,19 @@ class VIEWS_EXPORT FrameBackground {
// Paints the border for a standard, non-maximized window. Also paints the
// background of the title bar area, since the top frame border and the
// title bar background are a contiguous component.
- void PaintRestored(gfx::Canvas* canvas, View* view) const;
+ void PaintRestored(gfx::Canvas* canvas, const View* view) const;
// Paints the border for a maximized window, which does not include the
// window edges.
- void PaintMaximized(gfx::Canvas* canvas, View* view) const;
+ void PaintMaximized(gfx::Canvas* canvas, const View* view) const;
private:
// Fills the frame area with the frame color.
- void PaintFrameColor(gfx::Canvas* canvas, View* view) const;
+ void PaintFrameColor(gfx::Canvas* canvas, const View* view) const;
SkColor frame_color_;
- const gfx::ImageSkia* theme_image_;
- gfx::ImageSkia* theme_overlay_image_;
+ gfx::ImageSkia theme_image_;
+ gfx::ImageSkia theme_overlay_image_;
int top_area_height_;
// Images for the sides of the frame.
diff --git a/chromium/ui/views/window/non_client_view.cc b/chromium/ui/views/window/non_client_view.cc
index 7670a2eb5a2..a6d38a24f4c 100644
--- a/chromium/ui/views/window/non_client_view.cc
+++ b/chromium/ui/views/window/non_client_view.cc
@@ -31,11 +31,19 @@ static const int kClientViewIndex = 1;
// The overlay view is always on top (index == child_count() - 1).
////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameView, default implementations:
+
+bool NonClientFrameView::GetClientMask(const gfx::Size& size,
+ gfx::Path* mask) const {
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// NonClientView, public:
NonClientView::NonClientView()
- : client_view_(NULL),
- overlay_view_(NULL) {
+ : client_view_(nullptr),
+ overlay_view_(nullptr) {
SetEventTargeter(
scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
}
@@ -84,10 +92,6 @@ void NonClientView::UpdateFrame() {
SchedulePaint();
}
-void NonClientView::SetInactiveRenderingDisabled(bool disable) {
- frame_view_->SetInactiveRenderingDisabled(disable);
-}
-
gfx::Rect NonClientView::GetWindowBoundsForClientBounds(
const gfx::Rect client_bounds) const {
return frame_view_->GetWindowBoundsForClientBounds(client_bounds);
@@ -163,6 +167,10 @@ void NonClientView::Layout() {
// Then layout the ClientView, using those bounds.
client_view_->SetBoundsRect(frame_view_->GetBoundsForClientView());
+ gfx::Path client_clip;
+ if (frame_view_->GetClientMask(client_view_->size(), &client_clip))
+ client_view_->set_clip_path(client_clip);
+
// We need to manually call Layout on the ClientView as well for the same
// reason as above.
client_view_->Layout();
@@ -244,20 +252,10 @@ View* NonClientView::TargetForRect(View* root, const gfx::Rect& rect) {
NonClientFrameView::~NonClientFrameView() {
}
-void NonClientFrameView::SetInactiveRenderingDisabled(bool disable) {
- if (inactive_rendering_disabled_ == disable)
- return;
-
- 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();
+ return GetWidget()->IsAlwaysRenderAsActive() ||
+ (active_state_override_ ? *active_state_override_
+ : GetWidget()->IsActive());
}
int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point,
@@ -309,6 +307,9 @@ int NonClientFrameView::GetHTComponentForFrame(const gfx::Point& point,
return can_resize ? component : HTBORDER;
}
+void NonClientFrameView::ActivationChanged(bool active) {
+}
+
void NonClientFrameView::GetAccessibleState(ui::AXViewState* state) {
state->role = ui::AX_ROLE_CLIENT;
}
@@ -320,7 +321,8 @@ const char* NonClientFrameView::GetClassName() const {
////////////////////////////////////////////////////////////////////////////////
// NonClientFrameView, protected:
-NonClientFrameView::NonClientFrameView() : inactive_rendering_disabled_(false) {
+NonClientFrameView::NonClientFrameView()
+ : active_state_override_(nullptr) {
SetEventTargeter(
scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
}
diff --git a/chromium/ui/views/window/non_client_view.h b/chromium/ui/views/window/non_client_view.h
index 65ac395e63c..40000243b30 100644
--- a/chromium/ui/views/window/non_client_view.h
+++ b/chromium/ui/views/window/non_client_view.h
@@ -42,14 +42,9 @@ class VIEWS_EXPORT NonClientFrameView : public View,
~NonClientFrameView() override;
- // 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_|.
+ // window's actual active state and whether the widget should be rendered as
+ // active.
bool ShouldPaintAsActive() const;
// Helper for non-client view implementations to determine which area of the
@@ -70,6 +65,12 @@ class VIEWS_EXPORT NonClientFrameView : public View,
virtual gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const = 0;
+ // Gets the clip mask (in this View's parent's coordinates) that should be
+ // applied to the client view. Returns false if no special clip should be
+ // used.
+ virtual bool GetClientMask(const gfx::Size& size,
+ gfx::Path* mask) const;
+
// This function must ask the ClientView to do a hittest. We don't do this in
// the parent NonClientView because that makes it more difficult to calculate
// hittests for regions that are partially obscured by the ClientView, e.g.
@@ -89,6 +90,9 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// Whether the widget can be resized or maximized has changed.
virtual void SizeConstraintsChanged() = 0;
+ // The widget's activation state has changed to |active|.
+ virtual void ActivationChanged(bool active);
+
// View:
void GetAccessibleState(ui::AXViewState* state) override;
const char* GetClassName() const override;
@@ -103,10 +107,17 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// View:
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+ void set_active_state_override(bool* active_state_override) {
+ active_state_override_ = active_state_override;
+ }
+
private:
- // Prevents the non-client frame view from being rendered as inactive when
- // true.
- bool inactive_rendering_disabled_;
+ // Used to force ShouldPaintAsActive() to treat the active state a particular
+ // way. This is normally null; when non-null, its value will override the
+ // normal "active" value computed by the function.
+ bool* active_state_override_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonClientFrameView);
};
////////////////////////////////////////////////////////////////////////////////
@@ -174,11 +185,6 @@ class VIEWS_EXPORT NonClientView : public View, public ViewTargeterDelegate {
// or frame style.
void UpdateFrame();
- // 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.
- void SetInactiveRenderingDisabled(bool disable);
-
// Returns the bounds of the window required to display the content area at
// the specified bounds.
gfx::Rect GetWindowBoundsForClientBounds(const gfx::Rect client_bounds) const;
diff --git a/chromium/ui/views_content_client/views_content_browser_client.cc b/chromium/ui/views_content_client/views_content_browser_client.cc
index e5f4f38807e..29b6decd0be 100644
--- a/chromium/ui/views_content_client/views_content_browser_client.cc
+++ b/chromium/ui/views_content_client/views_content_browser_client.cc
@@ -4,9 +4,6 @@
#include "ui/views_content_client/views_content_browser_client.h"
-#include <utility>
-
-#include "content/shell/browser/shell_browser_context.h"
#include "ui/views_content_client/views_content_client_main_parts.h"
namespace ui {
@@ -27,15 +24,4 @@ content::BrowserMainParts* ViewsContentBrowserClient::CreateBrowserMainParts(
return views_content_main_parts_;
}
-net::URLRequestContextGetter*
-ViewsContentBrowserClient::CreateRequestContext(
- content::BrowserContext* content_browser_context,
- content::ProtocolHandlerMap* protocol_handlers,
- content::URLRequestInterceptorScopedVector request_interceptors) {
- content::ShellBrowserContext* shell_context =
- views_content_main_parts_->browser_context();
- return shell_context->CreateRequestContext(protocol_handlers,
- std::move(request_interceptors));
-}
-
} // namespace ui
diff --git a/chromium/ui/views_content_client/views_content_browser_client.h b/chromium/ui/views_content_client/views_content_browser_client.h
index 98d9ee41b7c..408fb8afdbd 100644
--- a/chromium/ui/views_content_client/views_content_browser_client.h
+++ b/chromium/ui/views_content_client/views_content_browser_client.h
@@ -8,10 +8,6 @@
#include "base/macros.h"
#include "content/public/browser/content_browser_client.h"
-namespace content {
-class ShellBrowserContext;
-}
-
namespace ui {
class ViewsContentClient;
@@ -26,10 +22,6 @@ class ViewsContentBrowserClient : public content::ContentBrowserClient {
// content::ContentBrowserClient:
content::BrowserMainParts* CreateBrowserMainParts(
const content::MainFunctionParams& parameters) override;
- net::URLRequestContextGetter* CreateRequestContext(
- content::BrowserContext* browser_context,
- content::ProtocolHandlerMap* protocol_handlers,
- content::URLRequestInterceptorScopedVector request_interceptors) override;
private:
ViewsContentClientMainParts* views_content_main_parts_;
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts_chromeos.cc b/chromium/ui/views_content_client/views_content_client_main_parts_chromeos.cc
index d13997147b5..36d24429a40 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts_chromeos.cc
+++ b/chromium/ui/views_content_client/views_content_client_main_parts_chromeos.cc
@@ -10,29 +10,12 @@
#include "ui/gfx/screen.h"
#include "ui/views_content_client/views_content_client.h"
#include "ui/views_content_client/views_content_client_main_parts_aura.h"
-#include "ui/wm/core/nested_accelerator_controller.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
#include "ui/wm/test/wm_test_helper.h"
namespace ui {
namespace {
-// A dummy version of the delegate usually provided by the Ash Shell.
-class NestedAcceleratorDelegate : public ::wm::NestedAcceleratorDelegate {
- public:
- NestedAcceleratorDelegate() {}
- ~NestedAcceleratorDelegate() override {}
-
- // ::wm::NestedAcceleratorDelegate:
- Result ProcessAccelerator(const ui::Accelerator& accelerator) override {
- return RESULT_NOT_PROCESSED;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDelegate);
-};
-
class ViewsContentClientMainPartsChromeOS
: public ViewsContentClientMainPartsAura {
public:
@@ -49,7 +32,6 @@ class ViewsContentClientMainPartsChromeOS
// Enable a minimal set of views::corewm to be initialized.
scoped_ptr<gfx::Screen> test_screen_;
scoped_ptr< ::wm::WMTestHelper> wm_test_helper_;
- scoped_ptr< ::wm::NestedAcceleratorController> nested_accelerator_controller_;
DISALLOW_COPY_AND_ASSIGN(ViewsContentClientMainPartsChromeOS);
};
@@ -65,7 +47,7 @@ void ViewsContentClientMainPartsChromeOS::PreMainMessageLoopRun() {
gfx::Size host_size(800, 600);
test_screen_.reset(aura::TestScreen::Create(host_size));
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
+ gfx::Screen::SetScreenInstance(test_screen_.get());
// Set up basic pieces of views::corewm.
wm_test_helper_.reset(
new ::wm::WMTestHelper(host_size, content::GetContextFactory()));
@@ -75,16 +57,9 @@ void ViewsContentClientMainPartsChromeOS::PreMainMessageLoopRun() {
// Ensure Aura knows where to open new windows.
aura::Window* root_window = wm_test_helper_->host()->window();
views_content_client()->task().Run(browser_context(), root_window);
-
- nested_accelerator_controller_.reset(
- new ::wm::NestedAcceleratorController(new NestedAcceleratorDelegate));
- aura::client::SetDispatcherClient(root_window,
- nested_accelerator_controller_.get());
}
void ViewsContentClientMainPartsChromeOS::PostMainMessageLoopRun() {
- aura::client::SetDispatcherClient(wm_test_helper_->host()->window(), NULL);
- nested_accelerator_controller_.reset();
wm_test_helper_.reset();
test_screen_.reset();
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc b/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
index 1ac04ecbb53..c7a3d0c7ee3 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
+++ b/chromium/ui/views_content_client/views_content_client_main_parts_desktop_aura.cc
@@ -39,8 +39,7 @@ void ViewsContentClientMainPartsDesktopAura::PreMainMessageLoopRun() {
ViewsContentClientMainPartsAura::PreMainMessageLoopRun();
aura::Env::CreateInstance(true);
- gfx::Screen::SetScreenInstance(
- gfx::SCREEN_TYPE_NATIVE, views::CreateDesktopScreen());
+ gfx::Screen::SetScreenInstance(views::CreateDesktopScreen());
views_content_client()->task().Run(browser_context(), NULL);
}
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm b/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
index 3def22c7a94..bc0c85ef866 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
+++ b/chromium/ui/views_content_client/views_content_client_main_parts_mac.mm
@@ -54,10 +54,6 @@ ViewsContentClientMainPartsMac::ViewsContentClientMainPartsMac(
base::FilePath child_process_exe;
PathService::Get(content::CHILD_PROCESS_EXE, &child_process_exe);
- // Disable plugin discovery since NPAPI plugin support on Mac requires this to
- // be done in a utility process type which isn't bundled with this executable.
- content::PluginService::GetInstance()->DisablePluginsDiscoveryForTesting();
-
app_controller_.reset([[ViewsContentClientAppController alloc] init]);
[[NSApplication sharedApplication] setDelegate:app_controller_];
}
diff --git a/chromium/ui/webui/resources/cr_elements/compiled_resources.gyp b/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp
index 7b24a067bda..cbd32348c3b 100644
--- a/chromium/ui/webui/resources/cr_elements/compiled_resources.gyp
+++ b/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp
@@ -7,8 +7,8 @@
'target_name': 'cr_elements_resources',
'type': 'none',
'dependencies': [
- 'network/compiled_resources.gyp:*',
- 'policy/compiled_resources.gyp:*',
+ 'network/compiled_resources2.gyp:*',
+ 'policy/compiled_resources2.gyp:*',
],
},
]
diff --git a/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.html b/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.html
index fc17728bd78..f726fe3f366 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<dom-module id="cr-events">
<script src="cr_events.js"></script>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.js b/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.js
index 99d083791b5..dc82d6d71ba 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_events/cr_events.js
@@ -13,8 +13,6 @@
* Usage:
*
* this.$.events.forward(this.$.element, ['change']);
- *
- * @element cr-events
*/
Polymer({
is: 'cr-events',
diff --git a/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
index 26b367027d2..edcdd597f1a 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
diff --git a/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js b/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js
index c75d3622b73..a3a5cc20581 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js
@@ -10,9 +10,6 @@
* Example:
*
* <cr-expand-button expanded="{{sectionIsExpanded}}"></cr-expand-button>
- *
- * @group Chrome Elements
- * @element cr-expand-button
*/
Polymer({
is: 'cr-expand-button',
diff --git a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html
index f8d203cc80e..8524c94860b 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html
@@ -1,5 +1,5 @@
<link rel="import" href="chrome://resources/html/assert.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
diff --git a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js
index e24e3093538..a507fc34f66 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.js
@@ -29,21 +29,63 @@ var SearchField = Polymer({
showingSearch_: {
type: Boolean,
value: false,
+ observer: 'showingSearchChanged_',
},
},
+ /**
+ * Returns the value of the search field.
+ * @return {string}
+ */
+ getValue: function() {
+ var searchInput = this.getSearchInput_();
+ return searchInput ? searchInput.value : '';
+ },
+
+ /**
+ * Sets the value of the search field, if it exists.
+ * @param {string} value
+ */
+ setValue: function(value) {
+ var searchInput = this.getSearchInput_();
+ if (searchInput)
+ searchInput.value = value;
+ },
+
/** @param {SearchFieldDelegate} delegate */
setDelegate: function(delegate) {
this.delegate_ = delegate;
},
+ /** @return {Promise<boolean>} */
+ showAndFocus: function() {
+ this.showingSearch_ = true;
+ return this.focus_();
+ },
+
/**
- * Returns the value of the search field.
- * @return {string}
+ * @return {Promise<boolean>}
+ * @private
*/
- getValue: function() {
- var searchInput = this.$$('#search-input');
- return searchInput ? searchInput.value : '';
+ focus_: function() {
+ return new Promise(function(resolve) {
+ this.async(function() {
+ if (this.showingSearch_) {
+ var searchInput = this.getSearchInput_();
+ if (searchInput)
+ searchInput.focus();
+ }
+ resolve(this.showingSearch_);
+ });
+ }.bind(this));
+ },
+
+ /**
+ * @return {?Element}
+ * @private
+ */
+ getSearchInput_: function() {
+ return this.$$('#search-input');
},
/** @private */
@@ -54,22 +96,27 @@ var SearchField = Polymer({
/** @private */
onSearchTermKeydown_: function(e) {
- assert(this.showingSearch_);
if (e.keyIdentifier == 'U+001B') // Escape.
- this.toggleShowingSearch_();
+ this.showingSearch_ = false;
+ },
+
+ /** @private */
+ showingSearchChanged_: function() {
+ if (this.showingSearch_) {
+ this.focus_();
+ return;
+ }
+
+ var searchInput = this.getSearchInput_();
+ if (!searchInput)
+ return;
+
+ searchInput.value = '';
+ this.onSearchTermSearch_();
},
/** @private */
toggleShowingSearch_: function() {
this.showingSearch_ = !this.showingSearch_;
- this.async(function() {
- var searchInput = this.$$('#search-input');
- if (this.showingSearch_) {
- searchInput.focus();
- } else {
- searchInput.value = '';
- this.onSearchTermSearch_();
- }
- });
},
});
diff --git a/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources.gyp b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources.gyp
new file mode 100644
index 00000000000..ee4ebfb21af
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources.gyp
@@ -0,0 +1,20 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'cr_shared_menu',
+ 'variables': {
+ 'depends': [
+ '../../../../../third_party/polymer/v1_0/components-chromium/iron-list/iron-list-extracted.js',
+ '../../js/assert.js',
+ '../../js/cr.js',
+ '../../js/cr/ui/position_util.js',
+ '../../js/util.js',
+ ],
+ },
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
new file mode 100644
index 00000000000..bcfaa7c1381
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
@@ -0,0 +1,17 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'targets': [
+ {
+ 'target_name': 'cr_shared_menu',
+ 'dependencies': [
+ '../../js/compiled_resources2.gyp:assert',
+ '../../js/compiled_resources2.gyp:cr',
+ '../../js/compiled_resources2.gyp:util',
+ '../../js/cr/ui/compiled_resources2.gyp:position_util',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
new file mode 100644
index 00000000000..6ff5f550d4d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
@@ -0,0 +1,27 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/cr/ui/position_util.html">
+<link rel="import" href="chrome://resources/html/util.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html">
+
+<dom-module id="cr-shared-menu">
+ <template>
+ <style>
+ :host {
+ @apply(--shadow-elevation-2dp);
+ display: none;
+ position: absolute;
+ }
+
+ :host([menu-open]) {
+ display: block;
+ }
+ </style>
+ <paper-listbox id="menu">
+ <content></content>
+ </paper-listbox>
+ </template>
+ <script src="cr_shared_menu.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
new file mode 100644
index 00000000000..9833a30a6b4
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
@@ -0,0 +1,90 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer({
+ is: 'cr-shared-menu',
+
+ properties: {
+ menuOpen: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true
+ },
+
+ /**
+ * The contextual item that this menu was clicked for.
+ * e.g. the data used to render an item in an <iron-list> or <dom-repeat>
+ * @type {?Object}
+ */
+ itemData: {
+ type: Object,
+ value: null,
+ },
+ },
+
+ /**
+ * The last anchor that was used to open a menu. It's necessary for toggling.
+ * @type {?Element}
+ */
+ lastAnchor_: null,
+
+ /**
+ * Adds listeners to the window in order to dismiss the menu on resize and
+ * when escape is pressed.
+ */
+ attached: function() {
+ window.addEventListener('resize', this.closeMenu.bind(this));
+ window.addEventListener('keydown', function(e) {
+ // Escape button on keyboard
+ if (e.keyCode == 27)
+ this.closeMenu();
+ }.bind(this));
+ },
+
+ /** Closes the menu. */
+ closeMenu: function() {
+ this.menuOpen = false;
+ this.itemData = null;
+ },
+
+ /**
+ * Opens the menu at the anchor location.
+ * @param {!Element} anchor The location to display the menu.
+ * @param {!Object} itemData The contextual item's data.
+ */
+ openMenu: function(anchor, itemData) {
+ this.menuOpen = true;
+ this.itemData = itemData;
+ this.lastAnchor_ = anchor;
+
+ // Move the menu to the anchor.
+ var anchorRect = anchor.getBoundingClientRect();
+ var parentRect = this.offsetParent.getBoundingClientRect();
+
+ var left = (isRTL() ? anchorRect.left : anchorRect.right) - parentRect.left;
+ var top = anchorRect.top - parentRect.top;
+
+ cr.ui.positionPopupAtPoint(left, top, this, cr.ui.AnchorType.BEFORE);
+
+ // Handle the bottom of the screen.
+ if (this.getBoundingClientRect().top != anchorRect.top) {
+ var bottom = anchorRect.bottom - parentRect.top;
+ cr.ui.positionPopupAtPoint(left, bottom, this, cr.ui.AnchorType.BEFORE);
+ }
+
+ this.$.menu.focus();
+ },
+
+ /**
+ * Toggles the menu for the anchor that is passed in.
+ * @param {!Element} anchor The location to display the menu.
+ * @param {!Object} itemData The contextual item's data.
+ */
+ toggleMenu: function(anchor, itemData) {
+ if (anchor == this.lastAnchor_ && this.menuOpen)
+ this.closeMenu();
+ else
+ this.openMenu(anchor, itemData);
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_elements/demo_element.html b/chromium/ui/webui/resources/cr_elements/demo_element.html
index 440d82ecffc..220741c82c9 100644
--- a/chromium/ui/webui/resources/cr_elements/demo_element.html
+++ b/chromium/ui/webui/resources/cr_elements/demo_element.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
diff --git a/chromium/ui/webui/resources/cr_elements/network/compiled_resources.gyp b/chromium/ui/webui/resources/cr_elements/network/compiled_resources.gyp
deleted file mode 100644
index 601aead59fd..00000000000
--- a/chromium/ui/webui/resources/cr_elements/network/compiled_resources.gyp
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
- 'targets': [
- {
- 'target_name': 'cr_network_icon',
- 'variables': {
- 'depends': [
- 'cr_onc_types.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/networking_private.js'
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_network_list',
- 'variables': {
- 'depends': [
- '../../../../../third_party/jstemplate/compiled_resources.gyp:jstemplate',
- 'cr_onc_types.js',
- 'cr_network_list_item.js',
- '../../../../../ui/webui/resources/js/load_time_data.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/networking_private.js'
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_network_select',
- 'variables': {
- 'depends': [
- 'compiled_resources.gyp:cr_network_list',
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- ],
-}
diff --git a/chromium/ui/webui/resources/cr_elements/network/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/network/compiled_resources2.gyp
new file mode 100644
index 00000000000..2a193a33100
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/network/compiled_resources2.gyp
@@ -0,0 +1,48 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'cr_network_icon',
+ 'dependencies': [
+ 'cr_onc_types',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_network_icon_externs',
+ 'includes': ['../../../../../third_party/closure_compiler/include_js.gypi'],
+ },
+ {
+ 'target_name': 'cr_network_list',
+ 'dependencies': [
+ 'cr_onc_types',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_network_list_item',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'cr_onc_types',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_network_select',
+ 'dependencies': [
+ '<(EXTERNS_GYP):networking_private',
+ 'cr_onc_types',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_onc_types',
+ 'dependencies': [
+ '<(EXTERNS_GYP):networking_private',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.html b/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.html
index ca8fd04730f..cb82c74b60e 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.html
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html">
<dom-module id="cr-network-icon">
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.js b/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.js
index d6ee5537f1a..13a3d6da9e0 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.js
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_icon.js
@@ -46,7 +46,6 @@ function getIconTypeFromNetworkType(networkType) {
/**
* Polymer class definition for 'cr-network-icon'.
- * @element cr-network-icon
*/
Polymer({
is: 'cr-network-icon',
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_list.html b/chromium/ui/webui/resources/cr_elements/network/cr_network_list.html
index 7f2878604ed..2b8f82c58b2 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_list.html
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_list.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list_item.html">
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_list.js b/chromium/ui/webui/resources/cr_elements/network/cr_network_list.js
index 04962be36ad..24178c4e6c4 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_list.js
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_list.js
@@ -11,7 +11,6 @@
/**
* Polymer class definition for 'cr-network-list'.
* TODO(stevenjb): Update with iron-list(?) once implemented in Polymer 1.0.
- * @element cr-network-list
*/
Polymer({
is: 'cr-network-list',
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.html b/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.html
index 6be1c16ecb2..3fe72aafd28 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.html
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.js b/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.js
index 84d2c1375e6..b362f8ae202 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.js
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_list_item.js
@@ -66,7 +66,6 @@ function getNetworkName(network) {
/**
* Polymer class definition for 'cr-network-list-item'.
- * @element cr-network-list-item
*/
Polymer({
is: 'cr-network-list-item',
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_select.html b/chromium/ui/webui/resources/cr_elements/network/cr_network_select.html
index bc703bcb914..b085806efb1 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_select.html
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_select.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html">
<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
<link rel="import" href="chrome://resources/cr_elements/network/cr_network_list.html">
diff --git a/chromium/ui/webui/resources/cr_elements/network/cr_network_select.js b/chromium/ui/webui/resources/cr_elements/network/cr_network_select.js
index 6bc77b40ae7..ecf439385f5 100644
--- a/chromium/ui/webui/resources/cr_elements/network/cr_network_select.js
+++ b/chromium/ui/webui/resources/cr_elements/network/cr_network_select.js
@@ -7,9 +7,6 @@
* networkingPrivate calls to populate it.
*/
-/**
- * @element cr-network-select
- */
Polymer({
is: 'cr-network-select',
diff --git a/chromium/ui/webui/resources/cr_elements/policy/compiled_resources.gyp b/chromium/ui/webui/resources/cr_elements/policy/compiled_resources.gyp
deleted file mode 100644
index 4d3578649ab..00000000000
--- a/chromium/ui/webui/resources/cr_elements/policy/compiled_resources.gyp
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
- 'targets': [
- {
- 'target_name': 'cr_policy_indicator_behavior',
- 'variables': {
- 'depends': [
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_policy_pref_behavior',
- 'variables': {
- 'depends': [
- '../../../../../third_party/polymer/v1_0/components-chromium/iron-iconset-svg/iron-iconset-svg-extracted.js',
- '../../../../../third_party/polymer/v1_0/components-chromium/iron-meta/iron-meta-extracted.js',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- 'cr_policy_indicator_behavior.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/settings_private.js'
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_policy_pref_indicator',
- 'variables': {
- 'depends': [
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- 'cr_policy_indicator_behavior.js',
- 'cr_policy_pref_behavior.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/settings_private.js'
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_policy_network_behavior',
- 'variables': {
- 'depends': [
- '../../../../../third_party/polymer/v1_0/components-chromium/iron-iconset-svg/iron-iconset-svg-extracted.js',
- '../../../../../third_party/polymer/v1_0/components-chromium/iron-meta/iron-meta-extracted.js',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- '../network/cr_onc_types.js',
- 'cr_policy_indicator_behavior.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/networking_private.js',
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
- 'target_name': 'cr_policy_network_indicator',
- 'variables': {
- 'depends': [
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:assert',
- '../../../../../ui/webui/resources/js/compiled_resources.gyp:load_time_data',
- '../network/cr_onc_types.js',
- 'cr_policy_indicator_behavior.js',
- 'cr_policy_network_behavior.js',
- ],
- 'externs': [
- '../../../../../third_party/closure_compiler/externs/networking_private.js',
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- ],
-}
diff --git a/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
new file mode 100644
index 00000000000..7e71e2bdb5e
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
@@ -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.
+{
+ 'targets': [
+ {
+ 'target_name': 'cr_policy_indicator_behavior',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_policy_pref_behavior',
+ 'dependencies': [
+ 'cr_policy_indicator_behavior',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_policy_pref_indicator',
+ 'dependencies': [
+ '<(EXTERNS_GYP):settings_private',
+ 'cr_policy_indicator_behavior',
+ 'cr_policy_pref_behavior',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_policy_network_behavior',
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'cr_policy_network_indicator',
+ 'dependencies': [
+ '../network/compiled_resources2.gyp:cr_onc_types',
+ 'cr_policy_indicator_behavior',
+ 'cr_policy_network_behavior',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
index 377786542ed..3c86d9937c5 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/social-icons.html">
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.js b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.js
index d036c06973b..29c09719c33 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.js
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.js
@@ -7,7 +7,6 @@
* properties.
*/
-/** @element cr-policy-network-indicator */
Polymer({
is: 'cr-policy-network-indicator',
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
index 49edb142edc..9fa274a89cc 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
@@ -1,4 +1,4 @@
-<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/social-icons.html">
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
index 769ba62f791..cd2562b1713 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -5,8 +5,6 @@
/**
* @fileoverview Polymer element for indicating policies that apply to an
* element controlling a settings preference.
- *
- * @element cr-policy-pref-indicator
*/
Polymer({
is: 'cr-policy-pref-indicator',
diff --git a/chromium/ui/webui/resources/cr_elements_resources.grdp b/chromium/ui/webui/resources/cr_elements_resources.grdp
index 66b50842c66..368f5a997df 100644
--- a/chromium/ui/webui/resources/cr_elements_resources.grdp
+++ b/chromium/ui/webui/resources/cr_elements_resources.grdp
@@ -117,6 +117,12 @@
<structure name="IDR_CR_ELEMENTS_CR_SEARCH_FIELD_JS"
file="../../webui/resources/cr_elements/cr_search_field/cr_search_field.js"
type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_SHARED_MENU_HTML"
+ file="../../webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html"
+ type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_SHARED_MENU_JS"
+ file="../../webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js"
+ type="chrome_html" />
<structure name="IDR_CR_ELEMENTS_SHARED_CSS"
file="../../webui/resources/cr_elements/shared.css"
type="chrome_html" />
diff --git a/chromium/ui/webui/resources/css/bubble.css b/chromium/ui/webui/resources/css/bubble.css
index b0092e5e45c..52e0d102a53 100644
--- a/chromium/ui/webui/resources/css/bubble.css
+++ b/chromium/ui/webui/resources/css/bubble.css
@@ -68,7 +68,7 @@ html[dir='rtl'] .bubble-close {
}
.bubble-arrow {
- -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.15);
height: 15px;
position: absolute;
diff --git a/chromium/ui/webui/resources/css/dialogs.css b/chromium/ui/webui/resources/css/dialogs.css
index 9c16aca557b..fde32aab91e 100644
--- a/chromium/ui/webui/resources/css/dialogs.css
+++ b/chromium/ui/webui/resources/css/dialogs.css
@@ -38,16 +38,16 @@
@-webkit-keyframes pulse {
0% {
- -webkit-transform: scale(1);
+ transform: scale(1);
}
40% {
- -webkit-transform: scale(1.02);
+ transform: scale(1.02);
}
60% {
- -webkit-transform: scale(1.02);
+ transform: scale(1.02);
}
100% {
- -webkit-transform: scale(1);
+ transform: scale(1);
}
}
@@ -59,13 +59,13 @@
}
.shown > .cr-dialog-frame {
- -webkit-transform: perspective(500px) scale(1)
+ transform: perspective(500px) scale(1)
translateY(0) rotateX(0);
opacity: 1;
}
.cr-dialog-frame {
- -webkit-transform: perspective(500px) scale(0.99)
+ transform: perspective(500px) scale(0.99)
translateY(-20px) rotateX(5deg);
-webkit-transition: all 180ms;
-webkit-transition-duration: 250ms;
diff --git a/chromium/ui/webui/resources/css/overlay.css b/chromium/ui/webui/resources/css/overlay.css
index 361fb8218ad..3b3340d26de 100644
--- a/chromium/ui/webui/resources/css/overlay.css
+++ b/chromium/ui/webui/resources/css/overlay.css
@@ -25,14 +25,14 @@
.overlay.transparent .page {
/* TODO(flackr): Add perspective(500px) rotateX(5deg) when accelerated
* compositing is enabled on chrome:// pages. See http://crbug.com/116800. */
- -webkit-transform: scale(0.99) translateY(-20px);
+ transform: scale(0.99) translateY(-20px);
}
/* The foreground dialog. */
.overlay .page {
-webkit-border-radius: 3px;
-webkit-box-orient: vertical;
- -webkit-transition: 200ms -webkit-transform;
+ -webkit-transition: 200ms transform;
background: white;
box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
color: #333;
@@ -52,16 +52,16 @@
/* keyframes used to pulse the overlay */
@-webkit-keyframes pulse {
0% {
- -webkit-transform: scale(1);
+ transform: scale(1);
}
40% {
- -webkit-transform: scale(1.02);
+ transform: scale(1.02);
}
60% {
- -webkit-transform: scale(1.02);
+ transform: scale(1.02);
}
100% {
- -webkit-transform: scale(1);
+ transform: scale(1);
}
}
diff --git a/chromium/ui/webui/resources/css/text_defaults.css b/chromium/ui/webui/resources/css/text_defaults.css
index 037ade7efb1..ac989687c0f 100644
--- a/chromium/ui/webui/resources/css/text_defaults.css
+++ b/chromium/ui/webui/resources/css/text_defaults.css
@@ -13,17 +13,17 @@
*
* 2. via the webui::AppendWebUICSSTextDefaults() method to directly append it
* to an HTML string.
- * Otherwise its $placeholders won't be expanded. */
+ * Otherwise its placeholders won't be expanded. */
html {
- direction: ${textDirection};
+ direction: $i18n{textDirection};
}
body {
- font-family: ${fontFamily};
- font-size: ${fontSize};
+ font-family: $i18nRaw{fontFamily};
+ font-size: $i18n{fontSize};
}
button {
- font-family: ${fontFamily};
+ font-family: $i18nRaw{fontFamily};
}
diff --git a/chromium/ui/webui/resources/css/text_defaults_md.css b/chromium/ui/webui/resources/css/text_defaults_md.css
index a2b2022667a..b378ba293f0 100644
--- a/chromium/ui/webui/resources/css/text_defaults_md.css
+++ b/chromium/ui/webui/resources/css/text_defaults_md.css
@@ -13,19 +13,19 @@
*
* 2. via the webui::AppendWebUICSSTextDefaultsMd() method to directly append it
* to an HTML string.
- * Otherwise its $placeholders won't be expanded. */
+ * Otherwise its placeholders won't be expanded. */
@import url(chrome://resources/css/roboto.css);
html {
- direction: ${textDirection};
+ direction: $i18n{textDirection};
}
body {
- font-family: Roboto, ${fontFamily};
- font-size: ${fontSize};
+ font-family: Roboto, $i18nRaw{fontFamily};
+ font-size: 81.25%
}
button {
- font-family: Roboto, ${fontFamily};
+ font-family: Roboto, $i18nRaw{fontFamily};
}
diff --git a/chromium/ui/webui/resources/css/trash.css b/chromium/ui/webui/resources/css/trash.css
index fb06e9aa5b7..dfe66dc0c3f 100644
--- a/chromium/ui/webui/resources/css/trash.css
+++ b/chromium/ui/webui/resources/css/trash.css
@@ -29,7 +29,7 @@
.trash > .lid {
-webkit-transform-origin: -7% 100%;
- -webkit-transition: -webkit-transform 150ms;
+ -webkit-transition: transform 150ms;
height: 6px;
width: 14px;
}
@@ -39,12 +39,12 @@ html[dir='rtl'] .trash > .lid {
}
.trash:-webkit-any(:focus, :hover, .open) > .lid {
- -webkit-transform: rotate(-45deg);
- -webkit-transition: -webkit-transform 250ms;
+ transform: rotate(-45deg);
+ -webkit-transition: transform 250ms;
}
html[dir='rtl'] .trash:-webkit-any(:focus, :hover, .open) > .lid {
- -webkit-transform: rotate(45deg);
+ transform: rotate(45deg);
}
.trash > .can {
diff --git a/chromium/ui/webui/resources/css/tree.css b/chromium/ui/webui/resources/css/tree.css
index a47735a1f3f..a86baba5b08 100644
--- a/chromium/ui/webui/resources/css/tree.css
+++ b/chromium/ui/webui/resources/css/tree.css
@@ -22,7 +22,7 @@ tree {
}
.expand-icon {
- -webkit-transform: rotate(-90deg);
+ transform: rotate(-90deg);
-webkit-transition: all 150ms;
background: url(../images/tree_triangle.svg) no-repeat center center;
background-size: 8px 5px;
@@ -36,11 +36,11 @@ tree {
}
html[dir=rtl] .expand-icon {
- -webkit-transform: rotate(90deg);
+ transform: rotate(90deg);
}
.tree-item[expanded] > .tree-row > .expand-icon {
- -webkit-transform: rotate(0);
+ transform: rotate(0);
background-image: url(../images/tree_triangle.svg);
opacity: .5;
}
diff --git a/chromium/ui/webui/resources/css/widgets.css b/chromium/ui/webui/resources/css/widgets.css
index 4897138a2a4..5a5dbc21c69 100644
--- a/chromium/ui/webui/resources/css/widgets.css
+++ b/chromium/ui/webui/resources/css/widgets.css
@@ -145,6 +145,7 @@ input[type='radio']:checked::before {
top: 3px;
}
+<if expr="not is_ios">
/* Hover **********************************************************************/
:enabled:hover:-webkit-any(
@@ -167,6 +168,7 @@ input[type='radio']:checked::before {
background-image: url(../images/select.png),
-webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);
}
+</if>
/* Active *********************************************************************/
diff --git a/chromium/ui/webui/resources/html/cr.html b/chromium/ui/webui/resources/html/cr.html
index 6e7b3b83471..df43b18b41a 100644
--- a/chromium/ui/webui/resources/html/cr.html
+++ b/chromium/ui/webui/resources/html/cr.html
@@ -1 +1,2 @@
+<link rel="import" href="chrome://resources/html/promise_resolver.html">
<script src="chrome://resources/js/cr.js"></script>
diff --git a/chromium/ui/webui/resources/html/polymer.html b/chromium/ui/webui/resources/html/polymer.html
new file mode 100644
index 00000000000..4b9e0414092
--- /dev/null
+++ b/chromium/ui/webui/resources/html/polymer.html
@@ -0,0 +1,2 @@
+<script src="chrome://resources/js/polymer_config.js"></script>
+<link rel="import" href="chrome://resources/polymer/v1_0/polymer/polymer.html">
diff --git a/chromium/ui/webui/resources/html/polymer_config.html b/chromium/ui/webui/resources/html/polymer_config.html
deleted file mode 100644
index d805abd7ba7..00000000000
--- a/chromium/ui/webui/resources/html/polymer_config.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="chrome://resources/js/polymer_config.js"></script>
diff --git a/chromium/ui/webui/resources/html/promise_resolver.html b/chromium/ui/webui/resources/html/promise_resolver.html
new file mode 100644
index 00000000000..3a171fa9e64
--- /dev/null
+++ b/chromium/ui/webui/resources/html/promise_resolver.html
@@ -0,0 +1 @@
+<script src="chrome://resources/js/promise_resolver.js"></script>
diff --git a/chromium/ui/webui/resources/html/web_ui_listener_behavior.html b/chromium/ui/webui/resources/html/web_ui_listener_behavior.html
new file mode 100644
index 00000000000..1c1906de592
--- /dev/null
+++ b/chromium/ui/webui/resources/html/web_ui_listener_behavior.html
@@ -0,0 +1,2 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://resources/js/web_ui_listener_behavior.js"></script>
diff --git a/chromium/ui/webui/resources/images/2x/otr_icon_standalone.png b/chromium/ui/webui/resources/images/2x/otr_icon_standalone.png
deleted file mode 100644
index af06732e608..00000000000
--- a/chromium/ui/webui/resources/images/2x/otr_icon_standalone.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/webui/resources/images/icon_bookmarks.svg b/chromium/ui/webui/resources/images/icon_bookmarks.svg
new file mode 100644
index 00000000000..cc93d8cbc65
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_bookmarks.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/>
+ <path d="M0 0h24v24H0z" fill="none"/>
+</svg>
diff --git a/chromium/ui/webui/resources/images/icon_extensions.svg b/chromium/ui/webui/resources/images/icon_extensions.svg
new file mode 100644
index 00000000000..e678d5839bb
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_extensions.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 0h24v24H0z" fill="none"/>
+ <path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/>
+</svg>
diff --git a/chromium/ui/webui/resources/images/icon_history.svg b/chromium/ui/webui/resources/images/icon_history.svg
new file mode 100644
index 00000000000..8c0d7762881
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_history.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 0h24v24H0z" fill="none"/>
+ <path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/>
+</svg>
diff --git a/chromium/ui/webui/resources/images/icon_passwords.svg b/chromium/ui/webui/resources/images/icon_passwords.svg
new file mode 100644
index 00000000000..246a9dbeee8
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_passwords.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="40" height="30" viewBox="0 0 40 30">
+ <path d="M3 5.005v19.99C3 26.103 3.895 27 5 27h30c1.108 0 2-.898 2-2.005V5.005C37 3.897 36.105 3 35 3H5c-1.108 0-2 .898-2 2.005zm-3 0C0 2.242 2.234 0 5 0h30c2.763 0 5 2.242 5 5.005v19.99C40 27.758 37.766 30 35 30H5c-2.763 0-5-2.242-5-5.005V5.005zM29 8h3v13h-3V8zm-6 6.14l-.632-1.834-.147.046-3.195.98V10H16.98v3.33l-3.2-.978-.148-.046L13 14.14l.146.045 3.21.984-1.987 2.58-.09.115L15.93 19l.09-.118L18 16.316l1.978 2.566.09.118 1.655-1.133-.09-.117-1.988-2.58 3.21-.985.145-.045zM7.222 12.352l-3.2.98V10H3v6.316l1.977 2.566.09.118 1.654-1.133-.09-.117-1.985-2.58 3.21-.985L8 14.14l-.63-1.834-.148.046z" fill-rule="evenodd"/>
+</svg>
diff --git a/chromium/ui/webui/resources/images/icon_tabs.svg b/chromium/ui/webui/resources/images/icon_tabs.svg
new file mode 100644
index 00000000000..9fbe81c7f88
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_tabs.svg
@@ -0,0 +1,6 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <g fill="none" fill-rule="evenodd">
+ <path d="M0 0h24v24H0V0z"/>
+ <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm-1 7V3.5L18.5 9H13zM6 4h5v16H6V4zm5 7h7v9h-7v-9z" fill="#000"/>
+ </g>
+</svg>
diff --git a/chromium/ui/webui/resources/images/icon_themes.svg b/chromium/ui/webui/resources/images/icon_themes.svg
new file mode 100644
index 00000000000..6e225fdfe91
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_themes.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="30" viewBox="0 0 32 30">
+ <path d="M20.04 16.74L12.776 24l-2.42-2.42c-.668-.668 0-2.42 0-2.42l1.21-3.632c.302-.91.364-2.057 0-2.422-3.63-3.63-8.472-6.05-9.684-7.26-1.337-1.338-1.337-3.507 0-4.842 1.34-1.34 3.506-1.34 4.842 0 1.21 1.21 3.63 6.05 7.263 9.682.363.363 1.512.303 2.42 0l3.63-1.21s1.754-.668 2.422 0l2.42 2.42-4.84 4.843zM3.657 2.44c-.586.585-.586 1.535 0 2.12.585.586 1.535.586 2.122 0 .582-.585.582-1.535 0-2.12-.59-.587-1.54-.587-2.125 0zM24.32 24.9h-3.4v3.4l-1.7 1.7-5.1-5.1L26.02 13l5.1 5.1-6.8 6.8z" fill-rule="evenodd"/>
+</svg>
diff --git a/chromium/ui/webui/resources/images/otr_icon_standalone.png b/chromium/ui/webui/resources/images/otr_icon_standalone.png
deleted file mode 100644
index 27d3dc44045..00000000000
--- a/chromium/ui/webui/resources/images/otr_icon_standalone.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/webui/resources/images/throbber_medium.svg b/chromium/ui/webui/resources/images/throbber_medium.svg
index 2a7aaca7af9..c6f51b277eb 100644
--- a/chromium/ui/webui/resources/images/throbber_medium.svg
+++ b/chromium/ui/webui/resources/images/throbber_medium.svg
@@ -42,8 +42,8 @@
/* Rotating the whole thing */
@-webkit-keyframes rotate {
- from {-webkit-transform: rotate(0deg);}
- to {-webkit-transform: rotate(360deg);}
+ from {transform: rotate(0deg);}
+ to {transform: rotate(360deg);}
}
.qp-circular-loader {
-webkit-animation-name: rotate;
@@ -68,10 +68,10 @@
}
@-webkit-keyframes rot {
from {
- -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
}
to {
- -webkit-transform: rotate(-360deg);
+ transform: rotate(-360deg);
}
}
@-webkit-keyframes colors {
diff --git a/chromium/ui/webui/resources/images/throbber_small.svg b/chromium/ui/webui/resources/images/throbber_small.svg
index 0cf4db122e9..6f31d493fd8 100644
--- a/chromium/ui/webui/resources/images/throbber_small.svg
+++ b/chromium/ui/webui/resources/images/throbber_small.svg
@@ -43,8 +43,8 @@
/* Rotating the whole thing */
@-webkit-keyframes rotate {
- from {-webkit-transform: rotate(0deg);}
- to {-webkit-transform: rotate(360deg);}
+ from {transform: rotate(0deg);}
+ to {transform: rotate(360deg);}
}
.qp-circular-loader {
-webkit-animation-name: rotate;
@@ -69,10 +69,10 @@
}
@-webkit-keyframes rot {
from {
- -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
}
to {
- -webkit-transform: rotate(-360deg);
+ transform: rotate(-360deg);
}
}
@-webkit-keyframes colors {
diff --git a/chromium/ui/webui/resources/js/action_link.js b/chromium/ui/webui/resources/js/action_link.js
index bd607f524b1..70b89e728a6 100644
--- a/chromium/ui/webui/resources/js/action_link.js
+++ b/chromium/ui/webui/resources/js/action_link.js
@@ -44,7 +44,7 @@ var ActionLink = document.registerElement('action-link', {
this.setAttribute('role', 'link');
this.addEventListener('keydown', function(e) {
- if (!this.disabled && e.keyIdentifier == 'Enter') {
+ if (!this.disabled && e.keyIdentifier == 'Enter' && !this.href) {
// Schedule a click asynchronously because other 'keydown' handlers
// may still run later (e.g. document.addEventListener('keydown')).
// Specifically options dialogs break when this timeout isn't here.
diff --git a/chromium/ui/webui/resources/js/assert.js b/chromium/ui/webui/resources/js/assert.js
index 9b0be57b318..94f25358294 100644
--- a/chromium/ui/webui/resources/js/assert.js
+++ b/chromium/ui/webui/resources/js/assert.js
@@ -62,7 +62,11 @@ function assertNotReached(opt_message) {
* @template T
*/
function assertInstanceof(value, type, opt_message) {
- assert(value instanceof type,
- opt_message || value + ' is not a[n] ' + (type.name || typeof type));
+ // We don't use assert immediately here so that we avoid constructing an error
+ // message if we don't have to.
+ if (!(value instanceof type)) {
+ assertNotReached(opt_message || 'Value ' + value +
+ ' is not a[n] ' + (type.name || typeof type));
+ }
return value;
}
diff --git a/chromium/ui/webui/resources/js/chromeos/compiled_resources.gyp b/chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp
index 05e7e0a9be9..a363475a954 100644
--- a/chromium/ui/webui/resources/js/chromeos/compiled_resources.gyp
+++ b/chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp
@@ -5,13 +5,11 @@
'targets': [
{
'target_name': 'ui_account_tweaks',
- 'variables': {
- 'depends': [
- '../compiled_resources.gyp:cr',
- '../compiled_resources.gyp:load_time_data',
- ],
- },
- 'includes': ['../../../../../third_party/closure_compiler/compile_js.gypi'],
+ 'dependencies': [
+ '../compiled_resources2.gyp:cr',
+ '../compiled_resources2.gyp:load_time_data',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
]
}
diff --git a/chromium/ui/webui/resources/js/compiled_resources.gyp b/chromium/ui/webui/resources/js/compiled_resources.gyp
index cbfeab6278a..d679f4c32a2 100644
--- a/chromium/ui/webui/resources/js/compiled_resources.gyp
+++ b/chromium/ui/webui/resources/js/compiled_resources.gyp
@@ -10,6 +10,7 @@
{
'target_name': 'cr',
'variables': {
+ 'depends': ['compiled_resources.gyp:promise_resolver'],
'externs': ['../../../../third_party/closure_compiler/externs/chrome_send.js'],
},
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
@@ -19,6 +20,22 @@
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
},
{
+ 'target_name': 'i18n_template_no_process',
+ 'variables': {
+ 'depends': ['compiled_resources.gyp:load_time_data'],
+ 'externs': ['../../../../third_party/closure_compiler/externs/pending_compiler_externs.js'],
+ },
+ 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
+ },
+ {
+ 'target_name': 'i18n_template',
+ 'variables': {
+ 'depends': ['compiled_resources.gyp:load_time_data'],
+ 'externs': ['../../../../third_party/closure_compiler/externs/pending_compiler_externs.js'],
+ },
+ 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
+ },
+ {
'target_name': 'load_time_data',
'variables': {
'depends': [
@@ -30,31 +47,19 @@
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
},
{
- 'target_name': 'util',
- 'variables': {
- 'depends': ['compiled_resources.gyp:cr'],
- # TODO(jlklein): Get <(VARIABLES) in transient externs/depends working.
- 'externs': ['../../../../third_party/closure_compiler/externs/chrome_send.js'],
- },
- 'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
- },
- {
'target_name': 'parse_html_subset',
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
},
{
- 'target_name': 'i18n_template_no_process',
- 'variables': {
- 'depends': ['compiled_resources.gyp:load_time_data'],
- 'externs': ['../../../../third_party/closure_compiler/externs/pending_compiler_externs.js'],
- },
+ 'target_name': 'promise_resolver',
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
},
{
- 'target_name': 'i18n_template',
+ 'target_name': 'util',
'variables': {
- 'depends': ['compiled_resources.gyp:load_time_data'],
- 'externs': ['../../../../third_party/closure_compiler/externs/pending_compiler_externs.js'],
+ 'depends': ['compiled_resources.gyp:cr', 'assert.js'],
+ # TODO(jlklein): Get <(VARIABLES) in transient externs/depends working.
+ 'externs': ['../../../../third_party/closure_compiler/externs/chrome_send.js'],
},
'includes': ['../../../../third_party/closure_compiler/compile_js.gypi'],
},
diff --git a/chromium/ui/webui/resources/js/compiled_resources2.gyp b/chromium/ui/webui/resources/js/compiled_resources2.gyp
index 2d0ce6627ae..e24ce72d519 100644
--- a/chromium/ui/webui/resources/js/compiled_resources2.gyp
+++ b/chromium/ui/webui/resources/js/compiled_resources2.gyp
@@ -14,47 +14,66 @@
{
'target_name': 'cr',
'dependencies': [
+ 'promise_resolver',
'<(EXTERNS_GYP):chrome_send',
'assert',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'load_time_data',
- 'dependencies': ['<(DEPTH)/third_party/jstemplate/compiled_resources2.gyp:jstemplate'],
+ 'target_name': 'event_tracker',
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'event_tracker',
+ 'target_name': 'i18n_template_no_process',
+ 'dependencies': [
+ 'load_time_data',
+ '<(EXTERNS_GYP):pending_compiler_externs',
+ ],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'util',
+ 'target_name': 'i18n_template',
'dependencies': [
- '<(EXTERNS_GYP):chrome_send',
- 'cr',
+ 'load_time_data',
+ # Ideally, <include> would automatically import externs as well, but
+ # it current doesn't and that sounds hard. Let's just kill <include>.
+ '<(EXTERNS_GYP):pending_compiler_externs',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'i18n_behavior',
+ 'dependencies': [
+ 'load_time_data',
+ ],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'load_time_data',
+ 'dependencies': ['<(DEPTH)/third_party/jstemplate/compiled_resources2.gyp:jstemplate'],
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'parse_html_subset',
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'i18n_template_no_process',
+ 'target_name': 'promise_resolver',
+ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'util',
'dependencies': [
- 'load_time_data',
- '<(EXTERNS_GYP):pending_compiler_externs',
+ '<(EXTERNS_GYP):chrome_send',
+ 'cr',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
- 'target_name': 'i18n_template',
+ 'target_name': 'web_ui_listener_behavior',
'dependencies': [
- 'load_time_data',
- # Ideally, <include> would automatically import externs as well, but
- # it current doesn't and that sounds hard. Let's just kill <include>.
- '<(EXTERNS_GYP):pending_compiler_externs',
+ 'cr',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
diff --git a/chromium/ui/webui/resources/js/cr.js b/chromium/ui/webui/resources/js/cr.js
index a38c59f8473..090cfd94f7d 100644
--- a/chromium/ui/webui/resources/js/cr.js
+++ b/chromium/ui/webui/resources/js/cr.js
@@ -9,8 +9,11 @@
*/
var global = this;
+/** @typedef {{eventName: string, uid: number}} */
+var WebUIListener;
+
/** Platform, package, object property, and Event support. **/
-var cr = function() {
+var cr = cr || function() {
'use strict';
/**
@@ -22,6 +25,8 @@ var cr = function() {
* @param {*=} opt_object The object to expose at the end of the path.
* @param {Object=} opt_objectToExportTo The object to add the path to;
* default is {@code global}.
+ * @return {!Object} The last object exported (i.e. exportPath('cr.ui')
+ * returns a reference to the ui property of window.cr).
* @private
*/
function exportPath(name, opt_object, opt_objectToExportTo) {
@@ -39,7 +44,7 @@ var cr = function() {
}
}
return cur;
- };
+ }
/**
* Fires a property change event on the target.
@@ -313,56 +318,62 @@ var cr = function() {
}
/**
- * The mapping used by the sendWithCallback mechanism to tie the callback
- * supplied to an invocation of sendWithCallback with the WebUI response
- * sent by the browser in response to the chrome.send call. The mapping is
- * from ID to callback function; the ID is generated by sendWithCallback and
- * is unique across all invocations of said method.
- * @type {!Object<Function>}
+ * The mapping used by the sendWithPromise mechanism to tie the Promise
+ * returned to callers with the corresponding WebUI response. The mapping is
+ * from ID to the PromiseResolver helper; the ID is generated by
+ * sendWithPromise and is unique across all invocations of said method.
+ * @type {!Object<!PromiseResolver>}
*/
- var chromeSendCallbackMap = Object.create(null);
+ var chromeSendResolverMap = {};
/**
* The named method the WebUI handler calls directly in response to a
- * chrome.send call that expects a callback. The handler requires no knowledge
+ * chrome.send call that expects a response. The handler requires no knowledge
* of the specific name of this method, as the name is passed to the handler
* as the first argument in the arguments list of chrome.send. The handler
* must pass the ID, also sent via the chrome.send arguments list, as the
* first argument of the JS invocation; additionally, the handler may
- * supply any number of other arguments that will be forwarded to the
- * callback.
- * @param {string} id The unique ID identifying the callback method this
- * response is tied to.
+ * supply any number of other arguments that will be included in the response.
+ * @param {string} id The unique ID identifying the Promise this response is
+ * tied to.
+ * @param {boolean} isSuccess Whether the request was successful.
+ * @param {*} response The response as sent from C++.
*/
- function webUIResponse(id) {
- chromeSendCallbackMap[id].apply(
- null, Array.prototype.slice.call(arguments, 1));
- delete chromeSendCallbackMap[id];
+ function webUIResponse(id, isSuccess, response) {
+ var resolver = chromeSendResolverMap[id];
+ delete chromeSendResolverMap[id];
+
+ if (isSuccess)
+ resolver.resolve(response);
+ else
+ resolver.reject(response);
}
/**
- * A variation of chrome.send which allows the client to receive a direct
- * callback without requiring the handler to have specific knowledge of any
- * JS internal method names or state. The callback will be removed from the
- * mapping once it has fired.
+ * A variation of chrome.send, suitable for messages that expect a single
+ * response from C++.
* @param {string} methodName The name of the WebUI handler API.
- * @param {Array|undefined} args Arguments for the method call sent to the
- * WebUI handler. Pass undefined if no args should be sent to the handler.
- * @param {Function} callback A callback function which is called (indirectly)
- * by the WebUI handler.
+ * @param {...*} var_args Varibale number of arguments to be forwarded to the
+ * C++ call.
+ * @return {!Promise}
*/
- function sendWithCallback(methodName, args, callback) {
- var id = methodName + createUid();
- chromeSendCallbackMap[id] = callback;
- chrome.send(methodName, ['cr.webUIResponse', id].concat(args || []));
+ function sendWithPromise(methodName, var_args) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var promiseResolver = new PromiseResolver();
+ var id = methodName + '_' + createUid();
+ chromeSendResolverMap[id] = promiseResolver;
+ chrome.send(methodName, [id].concat(args));
+ return promiseResolver.promise;
}
/**
- * A registry of callbacks keyed by event name. Used by addWebUIListener to
- * register listeners.
- * @type {!Object<Array<Function>>}
+ * A map of maps associating event names with listeners. The 2nd level map
+ * associates a listener ID with the callback function, such that individual
+ * listeners can be removed from an event without affecting other listeners of
+ * the same event.
+ * @type {!Object<!Object<!Function>>}
*/
- var webUIListenerMap = Object.create(null);
+ var webUIListenerMap = {};
/**
* The named method the WebUI handler calls directly when an event occurs.
@@ -370,26 +381,52 @@ var cr = function() {
* of the JS invocation; additionally, the handler may supply any number of
* other arguments that will be forwarded to the listener callbacks.
* @param {string} event The name of the event that has occurred.
+ * @param {...*} var_args Additional arguments passed from C++.
*/
- function webUIListenerCallback(event) {
- var listenerCallbacks = webUIListenerMap[event];
- for (var i = 0; i < listenerCallbacks.length; i++) {
- var callback = listenerCallbacks[i];
- callback.apply(null, Array.prototype.slice.call(arguments, 1));
+ function webUIListenerCallback(event, var_args) {
+ var eventListenersMap = webUIListenerMap[event];
+ if (!eventListenersMap) {
+ // C++ event sent for an event that has no listeners.
+ // TODO(dpapad): Should a warning be displayed here?
+ return;
+ }
+
+ var args = Array.prototype.slice.call(arguments, 1);
+ for (var listenerId in eventListenersMap) {
+ eventListenersMap[listenerId].apply(null, args);
}
}
/**
* Registers a listener for an event fired from WebUI handlers. Any number of
* listeners may register for a single event.
- * @param {string} event The event to listen to.
- * @param {Function} callback The callback run when the event is fired.
+ * @param {string} eventName The event to listen to.
+ * @param {!Function} callback The callback run when the event is fired.
+ * @return {!WebUIListener} An object to be used for removing a listener via
+ * cr.removeWebUIListener. Should be treated as read-only.
*/
- function addWebUIListener(event, callback) {
- if (event in webUIListenerMap)
- webUIListenerMap[event].push(callback);
- else
- webUIListenerMap[event] = [callback];
+ function addWebUIListener(eventName, callback) {
+ webUIListenerMap[eventName] = webUIListenerMap[eventName] || {};
+ var uid = createUid();
+ webUIListenerMap[eventName][uid] = callback;
+ return {eventName: eventName, uid: uid};
+ }
+
+ /**
+ * Removes a listener. Does nothing if the specified listener is not found.
+ * @param {!WebUIListener} listener The listener to be removed (as returned by
+ * addWebUIListener).
+ * @return {boolean} Whether the given listener was found and actually
+ * removed.
+ */
+ function removeWebUIListener(listener) {
+ var listenerExists = webUIListenerMap[listener.eventName] &&
+ webUIListenerMap[listener.eventName][listener.uid];
+ if (listenerExists) {
+ delete webUIListenerMap[listener.eventName][listener.uid];
+ return true;
+ }
+ return false;
}
return {
@@ -402,12 +439,15 @@ var cr = function() {
exportPath: exportPath,
getUid: getUid,
makePublic: makePublic,
- webUIResponse: webUIResponse,
- sendWithCallback: sendWithCallback,
- webUIListenerCallback: webUIListenerCallback,
- addWebUIListener: addWebUIListener,
PropertyKind: PropertyKind,
+ // C++ <-> JS communication related methods.
+ addWebUIListener: addWebUIListener,
+ removeWebUIListener: removeWebUIListener,
+ sendWithPromise: sendWithPromise,
+ webUIListenerCallback: webUIListenerCallback,
+ webUIResponse: webUIResponse,
+
get doc() {
return document;
},
@@ -431,5 +471,10 @@ var cr = function() {
get isLinux() {
return /Linux/.test(navigator.userAgent);
},
+
+ /** Whether this is on Android. */
+ get isAndroid() {
+ return /Android/.test(navigator.userAgent);
+ }
};
}();
diff --git a/chromium/ui/webui/resources/js/cr/ui/card_slider.js b/chromium/ui/webui/resources/js/cr/ui/card_slider.js
index b8684228962..f19199125a1 100644
--- a/chromium/ui/webui/resources/js/cr/ui/card_slider.js
+++ b/chromium/ui/webui/resources/js/cr/ui/card_slider.js
@@ -328,7 +328,7 @@ cr.define('cr.ui', function() {
},
/**
- * Handles the ends of -webkit-transitions on -webkit-transform (animated
+ * Handles the ends of -webkit-transitions on transform (animated
* card switches).
* @param {Event} e The webkitTransitionEnd event.
* @private
@@ -381,11 +381,10 @@ cr.define('cr.ui', function() {
/**
* Append a card to the end of the list.
- * @param {!Node} card A card to add at the end of the card slider.
+ * @param {!Element} card A card to add at the end of the card slider.
*/
appendCard: function(card) {
- assert(card instanceof Node, '|card| isn\'t a Node');
- this.cards_.push(card);
+ this.cards_.push(assertInstanceof(card, Element));
this.fireAddedEvent_(card, this.cards_.length - 1);
},
@@ -419,11 +418,11 @@ cr.define('cr.ui', function() {
* Removes a card by index from the card slider. If the card to be removed
* is the current card or in front of the current card, the current card
* will be updated (to current card - 1).
- * @param {!Node} card A card to be removed.
+ * @param {!Element} card A card to be removed.
*/
removeCard: function(card) {
- assert(card instanceof Node, '|card| isn\'t a Node');
- this.removeCardAtIndex(this.cards_.indexOf(card));
+ this.removeCardAtIndex(
+ this.cards_.indexOf(assertInstanceof(card, Element)));
},
/**
@@ -460,7 +459,7 @@ cr.define('cr.ui', function() {
},
/**
- * This re-syncs the -webkit-transform that's used to position the frame in
+ * This re-syncs the transform that's used to position the frame in
* the likely event it needs to be updated by a card being inserted or
* removed in the flow.
*/
@@ -534,7 +533,7 @@ cr.define('cr.ui', function() {
/**
* Selects a card from the stack. Passes through to selectCard.
- * @param {Node} newCard The card that should be selected.
+ * @param {!Element} newCard The card that should be selected.
* @param {boolean=} opt_animate Whether to animate.
*/
selectCardByValue: function(newCard, opt_animate) {
@@ -567,7 +566,7 @@ cr.define('cr.ui', function() {
// enough to change cards.
var transition = '';
if (opt_animate) {
- transition = '-webkit-transform ' + CardSlider.TRANSITION_TIME_ +
+ transition = 'transform ' + CardSlider.TRANSITION_TIME_ +
'ms ease-in-out';
}
this.container_.style.WebkitTransition = transition;
@@ -582,12 +581,12 @@ cr.define('cr.ui', function() {
* @private
*/
translateTo_: function(x) {
- // We use a webkitTransform to slide because this is GPU accelerated on
+ // We use a transform to slide because this is GPU accelerated on
// Chrome and iOS. Once Chrome does GPU acceleration on the position
// fixed-layout elements we could simply set the element's position to
// fixed and modify 'left' instead.
this.deltaX_ = x - this.currentLeft_;
- this.container_.style.WebkitTransform = 'translate3d(' + x + 'px, 0, 0)';
+ this.container_.style.transform = 'translate3d(' + x + 'px, 0, 0)';
},
/* Touch ******************************************************************/
diff --git a/chromium/ui/webui/resources/js/cr/ui/compiled_resources.gyp b/chromium/ui/webui/resources/js/cr/ui/compiled_resources.gyp
index 1d4cde6a5bb..8f06cd10f02 100644
--- a/chromium/ui/webui/resources/js/cr/ui/compiled_resources.gyp
+++ b/chromium/ui/webui/resources/js/cr/ui/compiled_resources.gyp
@@ -18,6 +18,7 @@
'variables': {
'depends': [
'../../cr.js',
+ '../../promise_resolver.js',
'../../util.js',
],
'externs': [
diff --git a/chromium/ui/webui/resources/js/cr/ui/compiled_resources2.gyp b/chromium/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
index a420949cea1..1bc7c7fcb1e 100644
--- a/chromium/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
+++ b/chromium/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
@@ -4,10 +4,18 @@
{
'targets': [
{
+ 'target_name': 'alert_overlay',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:cr',
+ '../../compiled_resources2.gyp:util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'command',
'dependencies': [
- '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
- '<(DEPTH)/ui/webui/resources/js/cr/compiled_resources2.gyp:ui',
+ '../../compiled_resources2.gyp:cr',
+ '../compiled_resources2.gyp:ui',
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
@@ -27,6 +35,11 @@
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'focus_outline_manager',
+ 'dependencies': ['../../compiled_resources2.gyp:cr'],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'focus_row',
'dependencies': [
'../../compiled_resources2.gyp:assert',
@@ -37,6 +50,39 @@
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
+ 'target_name': 'menu_button',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:assert',
+ '../../compiled_resources2.gyp:cr',
+ '../../compiled_resources2.gyp:event_tracker',
+ '../compiled_resources2.gyp:ui',
+ 'menu',
+ 'menu_item',
+ 'position_util',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'menu_item',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:cr',
+ '../../compiled_resources2.gyp:load_time_data',
+ '../compiled_resources2.gyp:ui',
+ 'command',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'menu',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:assert',
+ '../../compiled_resources2.gyp:cr',
+ '../compiled_resources2.gyp:ui',
+ 'menu_item',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
'target_name': 'overlay',
'dependencies': [
'../../compiled_resources2.gyp:cr',
@@ -44,5 +90,12 @@
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'position_util',
+ 'dependencies': [
+ '../../compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
],
}
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
index 5e9590883f9..4eda10b6af0 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
@@ -82,7 +82,7 @@ cr.define('cr.ui', function() {
},
/**
- * @param {Node} target A target item to find in this grid.
+ * @param {!Element} target A target item to find in this grid.
* @return {number} The row index. -1 if not found.
*/
getRowIndexForTarget: function(target) {
@@ -122,7 +122,7 @@ cr.define('cr.ui', function() {
addRowBefore: function(row, nextRow) {
row.delegate = row.delegate || this;
- var nextRowIndex = this.rows.indexOf(nextRow);
+ var nextRowIndex = nextRow ? this.rows.indexOf(nextRow) : -1;
if (nextRowIndex == -1)
this.rows.push(row);
else
@@ -134,7 +134,7 @@ cr.define('cr.ui', function() {
* @param {cr.ui.FocusRow} row The row that needs to be removed.
*/
removeRow: function(row) {
- var nextRowIndex = this.rows.indexOf(row);
+ var nextRowIndex = row ? this.rows.indexOf(row) : -1;
if (nextRowIndex > -1)
this.rows.splice(nextRowIndex, 1);
},
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_row.js b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
index bb5471e9761..a545d14d7be 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_row.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
@@ -17,7 +17,8 @@ cr.define('cr.ui', function() {
*
* @param {!Element} root The root of this focus row. Focus classes are
* applied to |root| and all added elements must live within |root|.
- * @param {?Node} boundary Focus events are ignored outside of this node.
+ * @param {?Element} boundary Focus events are ignored outside of this
+ * element.
* @param {cr.ui.FocusRow.Delegate=} opt_delegate An optional event delegate.
* @constructor
*/
@@ -25,8 +26,8 @@ cr.define('cr.ui', function() {
/** @type {!Element} */
this.root = root;
- /** @private {!Node} */
- this.boundary_ = boundary || document;
+ /** @private {!Element} */
+ this.boundary_ = boundary || document.documentElement;
/** @type {cr.ui.FocusRow.Delegate|undefined} */
this.delegate = opt_delegate;
@@ -221,10 +222,11 @@ cr.define('cr.ui', function() {
* @private
*/
onBlur_: function(e) {
- if (!this.boundary_.contains(/** @type {Node} */(e.relatedTarget)))
+ if (!this.boundary_.contains(/** @type {Element} */(e.relatedTarget)))
return;
- if (this.getFocusableElements().indexOf(e.currentTarget) >= 0)
+ var currentTarget = /** @type {!Element} */(e.currentTarget);
+ if (this.getFocusableElements().indexOf(currentTarget) >= 0)
this.makeActive(false);
},
@@ -257,7 +259,8 @@ cr.define('cr.ui', function() {
*/
onKeydown_: function(e) {
var elements = this.getFocusableElements();
- var elementIndex = elements.indexOf(e.currentTarget);
+ var currentElement = /** @type {!Element} */(e.currentTarget);
+ var elementIndex = elements.indexOf(currentElement);
assert(elementIndex >= 0);
if (this.delegate && this.delegate.onKeydown(this, e))
diff --git a/chromium/ui/webui/resources/js/cr/ui/list_selection_model.js b/chromium/ui/webui/resources/js/cr/ui/list_selection_model.js
index 550f4b52614..f9aca63c668 100644
--- a/chromium/ui/webui/resources/js/cr/ui/list_selection_model.js
+++ b/chromium/ui/webui/resources/js/cr/ui/list_selection_model.js
@@ -65,6 +65,7 @@ cr.define('cr.ui', function() {
}
for (var index in unselected) {
+ index = +index;
delete this.selectedIndexes_[index];
// Mark the index as changed. If previously marked, then unmark,
// since it just got reverted to the original state.
diff --git a/chromium/ui/webui/resources/js/cr/ui/menu_item.js b/chromium/ui/webui/resources/js/cr/ui/menu_item.js
index 2b8b12339b7..b4726f282f9 100644
--- a/chromium/ui/webui/resources/js/cr/ui/menu_item.js
+++ b/chromium/ui/webui/resources/js/cr/ui/menu_item.js
@@ -161,10 +161,12 @@ cr.define('cr.ui', function() {
var shortcutText = '';
// TODO(zvorygin): if more cornercases appear - optimize following
- // code. Currently 'Enter' keystroke is passed as 'Enter', and 'Space'
- // is passed as 'U+0020'
+ // code. Currently 'Enter' keystroke is passed as 'Enter', but 'Space'
+ // and 'Backspace' are passed as 'U+0020' and 'U+0008'.
if (ident == 'U+0020')
ident = 'Space';
+ else if (ident == 'U+0008')
+ ident = 'Backspace';
['CTRL', 'ALT', 'SHIFT', 'META'].forEach(function(mod) {
if (mods[mod])
@@ -197,7 +199,8 @@ cr.define('cr.ui', function() {
if (!this.disabled && !this.isSeparator() && this.selected) {
// Store |contextElement| since it'll be removed by {Menu} on handling
// 'activate' event.
- var contextElement = this.parentNode.contextElement;
+ var contextElement = /** @type {{contextElement: Element}} */(
+ this.parentNode).contextElement;
var activationEvent = cr.doc.createEvent('Event');
activationEvent.initEvent('activate', true, true);
activationEvent.originalEvent = e;
diff --git a/chromium/ui/webui/resources/js/cr/ui/overlay.js b/chromium/ui/webui/resources/js/cr/ui/overlay.js
index 56f339f1b1d..7d02f13999b 100644
--- a/chromium/ui/webui/resources/js/cr/ui/overlay.js
+++ b/chromium/ui/webui/resources/js/cr/ui/overlay.js
@@ -13,7 +13,8 @@ cr.define('cr.ui.overlay', function() {
* @return {HTMLElement} The overlay.
*/
function getTopOverlay() {
- var overlays = document.querySelectorAll('.overlay:not([hidden])');
+ var overlays = /** @type !NodeList<!HTMLElement> */(
+ document.querySelectorAll('.overlay:not([hidden])'));
return overlays[overlays.length - 1];
}
@@ -26,8 +27,8 @@ cr.define('cr.ui.overlay', function() {
*/
function getDefaultButton(overlay) {
function isHidden(node) { return node.hidden; }
- var defaultButtons =
- overlay.querySelectorAll('.page .button-strip > .default-button');
+ var defaultButtons = /** @type !NodeList<!HTMLElement> */(
+ overlay.querySelectorAll('.page .button-strip > .default-button'));
for (var i = 0; i < defaultButtons.length; i++) {
if (!findAncestor(defaultButtons[i], isHidden))
return defaultButtons[i];
diff --git a/chromium/ui/webui/resources/js/cr/ui/page_manager/page_manager.js b/chromium/ui/webui/resources/js/cr/ui/page_manager/page_manager.js
index 8fafc82c4f3..9d2492b3d02 100644
--- a/chromium/ui/webui/resources/js/cr/ui/page_manager/page_manager.js
+++ b/chromium/ui/webui/resources/js/cr/ui/page_manager/page_manager.js
@@ -61,7 +61,8 @@ cr.define('cr.ui.pageManager', function() {
this.handleScroll_();
// Shake the dialog if the user clicks outside the dialog bounds.
- var containers = document.querySelectorAll('body > .overlay');
+ var containers = /** @type {!NodeList<!HTMLElement>} */(
+ document.querySelectorAll('body > .overlay'));
for (var i = 0; i < containers.length; i++) {
var overlay = containers[i];
cr.ui.overlay.setupOverlay(overlay);
diff --git a/chromium/ui/webui/resources/js/cr/ui/position_util.js b/chromium/ui/webui/resources/js/cr/ui/position_util.js
index 14b29d92d97..c0c483b9196 100644
--- a/chromium/ui/webui/resources/js/cr/ui/position_util.js
+++ b/chromium/ui/webui/resources/js/cr/ui/position_util.js
@@ -226,8 +226,9 @@ cr.define('cr.ui', function() {
* @param {number} x The client x position.
* @param {number} y The client y position.
* @param {!HTMLElement} popupElement The popup element we are positioning.
+ * @param {cr.ui.AnchorType=} opt_anchorType The type of anchoring we want.
*/
- function positionPopupAtPoint(x, y, popupElement) {
+ function positionPopupAtPoint(x, y, popupElement, opt_anchorType) {
var rect = {
left: x,
top: y,
@@ -236,7 +237,9 @@ cr.define('cr.ui', function() {
right: x,
bottom: y
};
- positionPopupAroundRect(rect, popupElement, AnchorType.BELOW);
+
+ var anchorType = opt_anchorType || AnchorType.BELOW;
+ positionPopupAroundRect(rect, popupElement, anchorType);
}
// Export
diff --git a/chromium/ui/webui/resources/js/cr/ui/splitter.js b/chromium/ui/webui/resources/js/cr/ui/splitter.js
index 2c1799e4f22..c457e421e9e 100644
--- a/chromium/ui/webui/resources/js/cr/ui/splitter.js
+++ b/chromium/ui/webui/resources/js/cr/ui/splitter.js
@@ -71,6 +71,15 @@ cr.define('cr.ui', function() {
true);
this.addEventListener('touchstart', this.handleTouchStart_.bind(this),
true);
+ this.resizeNextElement_ = false;
+ },
+
+ /**
+ * @param {boolean} resizeNext True if resize the next element.
+ * By default, splitter resizes previous (left) element.
+ */
+ set resizeNextElement(resizeNext) {
+ this.resizeNextElement_ = resizeNext;
},
/**
@@ -129,12 +138,33 @@ cr.define('cr.ui', function() {
},
/**
+ * @return {Element}
+ * @private
+ */
+ getResizeTarget_: function() {
+ return this.resizeNextElement_ ? this.nextElementSibling :
+ this.previousElementSibling;
+ },
+
+ /**
+ * Calculate width to resize target element.
+ * @param {number} deltaX horizontal drag amount
+ * @return {number}
+ * @private
+ */
+ calcDeltaX_: function(deltaX) {
+ return this.resizeNextElement_ ? -deltaX : deltaX;
+ },
+
+ /**
* Handles the mousedown event which starts the dragging of the splitter.
* @param {!Event} e The mouse event.
* @private
*/
handleMouseDown_: function(e) {
e = /** @type {!MouseEvent} */(e);
+ if (e.button)
+ return;
this.startDrag(e.clientX, false);
// Default action is to start selection and to move focus.
e.preventDefault();
@@ -203,10 +233,10 @@ cr.define('cr.ui', function() {
handleSplitterDragStart: function() {
// Use the computed width style as the base so that we can ignore what
// box sizing the element has.
- var leftComponent = this.previousElementSibling;
- var doc = leftComponent.ownerDocument;
+ var targetElement = this.getResizeTarget_();
+ var doc = targetElement.ownerDocument;
this.startWidth_ = parseFloat(
- doc.defaultView.getComputedStyle(leftComponent).width);
+ doc.defaultView.getComputedStyle(targetElement).width);
},
/**
@@ -215,8 +245,9 @@ cr.define('cr.ui', function() {
* @protected
*/
handleSplitterDragMove: function(deltaX) {
- var leftComponent = this.previousElementSibling;
- leftComponent.style.width = this.startWidth_ + deltaX + 'px';
+ var targetElement = this.getResizeTarget_();
+ var newWidth = this.startWidth_ + this.calcDeltaX_(deltaX);
+ targetElement.style.width = newWidth + 'px';
},
/**
@@ -226,10 +257,10 @@ cr.define('cr.ui', function() {
*/
handleSplitterDragEnd: function() {
// Check if the size changed.
- var leftComponent = this.previousElementSibling;
- var doc = leftComponent.ownerDocument;
+ var targetElement = this.getResizeTarget_();
+ var doc = targetElement.ownerDocument;
var computedWidth = parseFloat(
- doc.defaultView.getComputedStyle(leftComponent).width);
+ doc.defaultView.getComputedStyle(targetElement).width);
if (this.startWidth_ != computedWidth)
cr.dispatchSimpleEvent(this, 'resize');
},
diff --git a/chromium/ui/webui/resources/js/event_tracker.js b/chromium/ui/webui/resources/js/event_tracker.js
index f2ec3e207c7..126c6f5b247 100644
--- a/chromium/ui/webui/resources/js/event_tracker.js
+++ b/chromium/ui/webui/resources/js/event_tracker.js
@@ -17,7 +17,7 @@
* is fixed.
* @typedef {{target: !EventTarget,
* eventType: string,
- * listener: Function,
+ * listener: (EventListener|Function),
* capture: boolean}}
*/
var EventTrackerEntry;
diff --git a/chromium/ui/webui/resources/js/i18n_behavior.js b/chromium/ui/webui/resources/js/i18n_behavior.js
index 98cf154ac32..64dd57c4253 100644
--- a/chromium/ui/webui/resources/js/i18n_behavior.js
+++ b/chromium/ui/webui/resources/js/i18n_behavior.js
@@ -11,18 +11,17 @@
* behaviors: [
* I18nBehavior,
* ],
- *
- * @group Chrome UI Behavior
*/
/** @polymerBehavior */
var I18nBehavior = {
/**
* @param {string} id The ID of the string to translate.
- * @param {...string} var_args Placeholders required by the string ($1-9).
+ * @param {...string} var_args Placeholders required by the string ($0-9).
* @return {string} A translated, substituted string.
*/
i18n: function(id, var_args) {
- return loadTimeData.getStringF.apply(loadTimeData, arguments);
+ return arguments.length == 1 ? loadTimeData.getString(id) :
+ loadTimeData.getStringF.apply(loadTimeData, arguments);
},
};
diff --git a/chromium/ui/webui/resources/js/promise_resolver.js b/chromium/ui/webui/resources/js/promise_resolver.js
new file mode 100644
index 00000000000..0759c955584
--- /dev/null
+++ b/chromium/ui/webui/resources/js/promise_resolver.js
@@ -0,0 +1,35 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview PromiseResolver is a helper class that allows creating a
+ * Promise that will be fulfilled (resolved or rejected) some time later.
+ *
+ * Example:
+ * var resolver = new PromiseResolver();
+ * resolver.promise.then(function(result) {
+ * console.log('resolved with', result);
+ * });
+ * ...
+ * ...
+ * resolver.resolve({hello: 'world'});
+ */
+
+/**
+ * @constructor @struct
+ * @template T
+ */
+function PromiseResolver() {
+ /** @type {function(T): void} */
+ this.resolve;
+
+ /** @type {function(*=): void} */
+ this.reject;
+
+ /** @type {!Promise<T>} */
+ this.promise = new Promise(function(resolve, reject) {
+ this.resolve = resolve;
+ this.reject = reject;
+ }.bind(this));
+}
diff --git a/chromium/ui/webui/resources/js/util.js b/chromium/ui/webui/resources/js/util.js
index 3907c5215aa..82a4e50328d 100644
--- a/chromium/ui/webui/resources/js/util.js
+++ b/chromium/ui/webui/resources/js/util.js
@@ -5,12 +5,25 @@
// <include src="assert.js">
/**
- * Alias for document.getElementById.
+ * Alias for document.getElementById. Found elements must be HTMLElements.
* @param {string} id The ID of the element to find.
* @return {HTMLElement} The found element or null if not found.
*/
function $(id) {
- return document.getElementById(id);
+ var el = document.getElementById(id);
+ return el ? assertInstanceof(el, HTMLElement) : null;
+}
+
+// TODO(devlin): This should return SVGElement, but closure compiler is missing
+// those externs.
+/**
+ * Alias for document.getElementById. Found elements must be SVGElements.
+ * @param {string} id The ID of the element to find.
+ * @return {Element} The found element or null if not found.
+ */
+function getSVGElement(id) {
+ var el = document.getElementById(id);
+ return el ? assertInstanceof(el, Element) : null;
}
/**
@@ -33,25 +46,6 @@ function announceAccessibleMessage(msg) {
}
/**
- * Calls chrome.send with a callback and restores the original afterwards.
- * @param {string} name The name of the message to send.
- * @param {!Array} params The parameters to send.
- * @param {string} callbackName The name of the function that the backend calls.
- * @param {!Function} callback The function to call.
- */
-function chromeSend(name, params, callbackName, callback) {
- var old = global[callbackName];
- global[callbackName] = function() {
- // restore
- global[callbackName] = old;
-
- var args = Array.prototype.slice.call(arguments);
- return callback.apply(global, args);
- };
- chrome.send(name, params);
-}
-
-/**
* Returns the scale factors supported by this platform for webui
* resources.
* @return {Array} The supported scale factors.
@@ -380,10 +374,19 @@ function createElementWithClassName(type, className) {
* or when no paint happens during the animation). This function sets up
* a timer and emulate the event if it is not fired when the timer expires.
* @param {!HTMLElement} el The element to watch for webkitTransitionEnd.
- * @param {number} timeOut The maximum wait time in milliseconds for the
- * webkitTransitionEnd to happen.
+ * @param {number=} opt_timeOut The maximum wait time in milliseconds for the
+ * webkitTransitionEnd to happen. If not specified, it is fetched from |el|
+ * using the transitionDuration style value.
*/
-function ensureTransitionEndEvent(el, timeOut) {
+function ensureTransitionEndEvent(el, opt_timeOut) {
+ if (opt_timeOut === undefined) {
+ var style = getComputedStyle(el);
+ opt_timeOut = parseFloat(style.transitionDuration) * 1000;
+
+ // Give an additional 50ms buffer for the animation to complete.
+ opt_timeOut += 50;
+ }
+
var fired = false;
el.addEventListener('webkitTransitionEnd', function f(e) {
el.removeEventListener('webkitTransitionEnd', f);
@@ -392,7 +395,7 @@ function ensureTransitionEndEvent(el, timeOut) {
window.setTimeout(function() {
if (!fired)
cr.dispatchSimpleEvent(el, 'webkitTransitionEnd', true);
- }, timeOut);
+ }, opt_timeOut);
}
/**
@@ -462,3 +465,12 @@ function elide(original, maxLength) {
return original;
return original.substring(0, maxLength - 1) + '\u2026';
}
+
+/**
+ * Quote a string so it can be used in a regular expression.
+ * @param {string} str The source string.
+ * @return {string} The escaped string.
+ */
+function quoteString(str) {
+ return str.replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
+}
diff --git a/chromium/ui/webui/resources/js/web_ui_listener_behavior.js b/chromium/ui/webui/resources/js/web_ui_listener_behavior.js
new file mode 100644
index 00000000000..d7fc56b5fff
--- /dev/null
+++ b/chromium/ui/webui/resources/js/web_ui_listener_behavior.js
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Behavior to be used by Polymer elements that want to
+ * automatically remove WebUI listeners when detached.
+ */
+
+/** @polymerBehavior */
+var WebUIListenerBehavior = {
+ properties: {
+ /**
+ * Holds WebUI listeners that need to be removed when this element is
+ * destroyed.
+ * @private {!Array<!WebUIListener>}
+ */
+ webUIListeners_: {
+ type: Array,
+ value: function() { return []; },
+ },
+ },
+
+ /**
+ * Adds a WebUI listener and registers it for automatic removal when this
+ * element is detached.
+ * Note: Do not use this method if you intend to remove this listener
+ * manually (use cr.addWebUIListener directly instead).
+ *
+ * @param {string} eventName The event to listen to.
+ * @param {!Function} callback The callback run when the event is fired.
+ */
+ addWebUIListener: function(eventName, callback) {
+ this.webUIListeners_.push(cr.addWebUIListener(eventName, callback));
+ },
+
+ /** @override */
+ detached: function() {
+ while (this.webUIListeners_.length > 0) {
+ cr.removeWebUIListener(this.webUIListeners_.pop());
+ }
+ },
+};
diff --git a/chromium/ui/webui/resources/polymer_resources.grdp b/chromium/ui/webui/resources/polymer_resources.grdp
index 59fd3245d66..562f6b0c1ca 100644
--- a/chromium/ui/webui/resources/polymer_resources.grdp
+++ b/chromium/ui/webui/resources/polymer_resources.grdp
@@ -80,9 +80,15 @@
<structure name="IDR_POLYMER_1_0_IRON_FLEX_LAYOUT_CLASSES_IRON_FLEX_LAYOUT_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-flex-layout.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_FLEX_LAYOUT_CLASSES_IRON_FLEX_LAYOUT_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-flex-layout-extracted.js"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_IRON_FLEX_LAYOUT_CLASSES_IRON_SHADOW_FLEX_LAYOUT_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_FLEX_LAYOUT_CLASSES_IRON_SHADOW_FLEX_LAYOUT_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-flex-layout/classes/iron-shadow-flex-layout-extracted.js"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_IRON_FLEX_LAYOUT_IRON_FLEX_LAYOUT_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-flex-layout/iron-flex-layout.html"
type="chrome_html" />
@@ -131,6 +137,12 @@
<structure name="IDR_POLYMER_1_0_IRON_ICONSET_SVG_IRON_ICONSET_SVG_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-iconset-svg/iron-iconset-svg.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_IMAGE_IRON_IMAGE_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-image/iron-image-extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_IMAGE_IRON_IMAGE_HTML"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-image/iron-image.html"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_IRON_INPUT_IRON_INPUT_EXTRACTED_JS"
file="../../../third_party/polymer/v1_0/components-chromium/iron-input/iron-input-extracted.js"
type="chrome_html" />
@@ -203,6 +215,12 @@
<structure name="IDR_POLYMER_1_0_IRON_RESIZABLE_BEHAVIOR_IRON_RESIZABLE_BEHAVIOR_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/iron-resizable-behavior.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_SCROLL_TARGET_BEHAVIOR_IRON_SCROLL_TARGET_BEHAVIOR_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-scroll-target-behavior/iron-scroll-target-behavior-extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_IRON_SCROLL_TARGET_BEHAVIOR_IRON_SCROLL_TARGET_BEHAVIOR_HTML"
+ file="../../../third_party/polymer/v1_0/components-chromium/iron-scroll-target-behavior/iron-scroll-target-behavior.html"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_IRON_SELECTOR_IRON_MULTI_SELECTABLE_EXTRACTED_JS"
file="../../../third_party/polymer/v1_0/components-chromium/iron-selector/iron-multi-selectable-extracted.js"
type="chrome_html" />
@@ -227,9 +245,6 @@
<structure name="IDR_POLYMER_1_0_IRON_SELECTOR_IRON_SELECTOR_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-selector/iron-selector.html"
type="chrome_html" />
- <structure name="IDR_POLYMER_1_0_IRON_TEST_HELPERS_IRON_TEST_HELPERS_EXTRACTED_JS"
- file="../../../third_party/polymer/v1_0/components-chromium/iron-test-helpers/iron-test-helpers-extracted.js"
- type="chrome_html" />
<structure name="IDR_POLYMER_1_0_IRON_TEST_HELPERS_IRON_TEST_HELPERS_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/iron-test-helpers/iron-test-helpers.html"
type="chrome_html" />
@@ -281,6 +296,12 @@
<structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_DOWN_ANIMATION_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-down-animation.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_BOTTOM_ANIMATION_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-bottom-animation-extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_BOTTOM_ANIMATION_HTML"
+ file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-bottom-animation.html"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_LEFT_ANIMATION_EXTRACTED_JS"
file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-left-animation-extracted.js"
type="chrome_html" />
@@ -293,6 +314,12 @@
<structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_RIGHT_ANIMATION_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-right-animation.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_TOP_ANIMATION_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-top-animation-extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_FROM_TOP_ANIMATION_HTML"
+ file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-from-top-animation.html"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_NEON_ANIMATION_ANIMATIONS_SLIDE_LEFT_ANIMATION_EXTRACTED_JS"
file="../../../third_party/polymer/v1_0/components-chromium/neon-animation/animations/slide-left-animation-extracted.js"
type="chrome_html" />
@@ -515,6 +542,12 @@
<structure name="IDR_POLYMER_1_0_PAPER_ITEM_PAPER_ITEM_HTML"
file="../../../third_party/polymer/v1_0/components-chromium/paper-item/paper-item.html"
type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_PAPER_LISTBOX_PAPER_LISTBOX_EXTRACTED_JS"
+ file="../../../third_party/polymer/v1_0/components-chromium/paper-listbox/paper-listbox-extracted.js"
+ type="chrome_html" />
+ <structure name="IDR_POLYMER_1_0_PAPER_LISTBOX_PAPER_LISTBOX_HTML"
+ file="../../../third_party/polymer/v1_0/components-chromium/paper-listbox/paper-listbox.html"
+ type="chrome_html" />
<structure name="IDR_POLYMER_1_0_PAPER_MATERIAL_PAPER_MATERIAL_EXTRACTED_JS"
file="../../../third_party/polymer/v1_0/components-chromium/paper-material/paper-material-extracted.js"
type="chrome_html" />
diff --git a/chromium/ui/webui/resources/webui_resources.grd b/chromium/ui/webui/resources/webui_resources.grd
index df687b739aa..aadc894027f 100644
--- a/chromium/ui/webui/resources/webui_resources.grd
+++ b/chromium/ui/webui/resources/webui_resources.grd
@@ -260,6 +260,8 @@ without changes to the corresponding grd file. -->
file="html/action_link.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_ASSERT"
file="html/assert.html" type="chrome_html" />
+ <structure name="IDR_WEBUI_HTML_PROMISE_RESOLVER"
+ file="html/promise_resolver.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_CR"
file="html/cr.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_CR_EVENT_TARGET"
@@ -301,17 +303,21 @@ without changes to the corresponding grd file. -->
file="html/i18n_template.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_LOAD_TIME_DATA"
file="html/load_time_data.html" type="chrome_html" />
- <structure name="IDR_WEBUI_HTML_POLYMER_CONFIG"
- file="html/polymer_config.html" type="chrome_html" />
+ <structure name="IDR_WEBUI_HTML_POLYMER"
+ file="html/polymer.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_I18N_BEHAVIOR"
file="html/i18n_behavior.html" type="chrome_html" />
<structure name="IDR_WEBUI_HTML_UTIL"
file="html/util.html" type="chrome_html" />
+ <structure name="IDR_WEBUI_HTML_WEBUI_LISTENER_BEHAVIOR"
+ file="html/web_ui_listener_behavior.html" type="chrome_html" />
<structure name="IDR_WEBUI_JS_ACTION_LINK"
file="js/action_link.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_ASSERT"
file="js/assert.js" type="chrome_html" />
+ <structure name="IDR_WEBUI_JS_PROMISE_RESOLVER"
+ file="js/promise_resolver.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_CR"
file="js/cr.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_CR_EVENT_TARGET"
@@ -434,6 +440,8 @@ without changes to the corresponding grd file. -->
file="js/i18n_behavior.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_UTIL"
file="js/util.js" type="chrome_html" flattenhtml="true" />
+ <structure name="IDR_WEBUI_JS_WEBUI_LISTENER_BEHAVIOR"
+ file="js/web_ui_listener_behavior.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_WEBUI_RESOURCE_TEST"
file="js/webui_resource_test.js" type="chrome_html" />
<if expr="chromeos">
@@ -448,7 +456,9 @@ without changes to the corresponding grd file. -->
type="chrome_html" />
</if>
<part file="cr_elements_resources.grdp" />
- <part file="polymer_resources.grdp" />
+ <if expr="not is_android">
+ <part file="polymer_resources.grdp" />
+ </if>
</structures>
</release>
</grit>
diff --git a/chromium/ui/wm/BUILD.gn b/chromium/ui/wm/BUILD.gn
index 858183e7bc1..3be6e2d8d63 100644
--- a/chromium/ui/wm/BUILD.gn
+++ b/chromium/ui/wm/BUILD.gn
@@ -35,13 +35,6 @@ component("wm") {
"core/masked_window_targeter.h",
"core/native_cursor_manager.h",
"core/native_cursor_manager_delegate.h",
- "core/nested_accelerator_controller.cc",
- "core/nested_accelerator_controller.h",
- "core/nested_accelerator_delegate.h",
- "core/nested_accelerator_dispatcher.cc",
- "core/nested_accelerator_dispatcher.h",
- "core/nested_accelerator_dispatcher_linux.cc",
- "core/nested_accelerator_dispatcher_win.cc",
"core/shadow.cc",
"core/shadow.h",
"core/shadow_controller.cc",
@@ -93,16 +86,6 @@ component("wm") {
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
}
-
- if (is_android) {
- sources -= [
- "core/nested_accelerator_controller.cc",
- "core/nested_accelerator_controller.h",
- "core/nested_accelerator_delegate.h",
- "core/nested_accelerator_dispatcher.cc",
- "core/nested_accelerator_dispatcher.h",
- ]
- }
}
static_library("test_support") {
@@ -124,15 +107,6 @@ static_library("test_support") {
]
}
-# TODO(GYP): Delete this after we've converted everything to GN.
-# The _run targets exist only for compatibility w/ GYP.
-group("wm_unittests_run") {
- testonly = true
- deps = [
- ":wm_unittests",
- ]
-}
-
test("wm_unittests") {
sources = [
"core/capture_controller_unittest.cc",
@@ -140,7 +114,6 @@ test("wm_unittests") {
"core/cursor_manager_unittest.cc",
"core/focus_controller_unittest.cc",
"core/image_grid_unittest.cc",
- "core/nested_accelerator_controller_unittest.cc",
"core/shadow_controller_unittest.cc",
"core/shadow_unittest.cc",
"core/transient_window_manager_unittest.cc",
diff --git a/chromium/ui/wm/core/cursor_manager.cc b/chromium/ui/wm/core/cursor_manager.cc
index 51a30ac6f20..607614b6131 100644
--- a/chromium/ui/wm/core/cursor_manager.cc
+++ b/chromium/ui/wm/core/cursor_manager.cc
@@ -73,11 +73,16 @@ class CursorState {
} // namespace internal
+bool CursorManager::last_cursor_visibility_state_ = true;
+
CursorManager::CursorManager(scoped_ptr<NativeCursorManager> delegate)
: delegate_(std::move(delegate)),
cursor_lock_count_(0),
current_state_(new internal::CursorState),
- state_on_unlock_(new internal::CursorState) {}
+ state_on_unlock_(new internal::CursorState) {
+ // Restore the last cursor visibility state.
+ current_state_->SetVisible(last_cursor_visibility_state_);
+}
CursorManager::~CursorManager() {
}
@@ -95,6 +100,7 @@ gfx::NativeCursor CursorManager::GetCursor() const {
}
void CursorManager::ShowCursor() {
+ last_cursor_visibility_state_ = true;
state_on_unlock_->SetVisible(true);
if (cursor_lock_count_ == 0 &&
IsCursorVisible() != state_on_unlock_->visible()) {
@@ -105,6 +111,7 @@ void CursorManager::ShowCursor() {
}
void CursorManager::HideCursor() {
+ last_cursor_visibility_state_ = false;
state_on_unlock_->SetVisible(false);
if (cursor_lock_count_ == 0 &&
IsCursorVisible() != state_on_unlock_->visible()) {
diff --git a/chromium/ui/wm/core/cursor_manager.h b/chromium/ui/wm/core/cursor_manager.h
index a3afdd39deb..3e2b86b213d 100644
--- a/chromium/ui/wm/core/cursor_manager.h
+++ b/chromium/ui/wm/core/cursor_manager.h
@@ -82,6 +82,12 @@ class WM_EXPORT CursorManager : public aura::client::CursorClient,
base::ObserverList<aura::client::CursorClientObserver> observers_;
+ // This flag holds the cursor visibility state for the duration of the
+ // process. Defaults to true. This flag helps ensure that when a
+ // CursorManager instance is created it gets populated with the correct
+ // cursor visibility state.
+ static bool last_cursor_visibility_state_;
+
DISALLOW_COPY_AND_ASSIGN(CursorManager);
};
diff --git a/chromium/ui/wm/core/cursor_manager_unittest.cc b/chromium/ui/wm/core/cursor_manager_unittest.cc
index 7add106969a..e4f5429309a 100644
--- a/chromium/ui/wm/core/cursor_manager_unittest.cc
+++ b/chromium/ui/wm/core/cursor_manager_unittest.cc
@@ -325,3 +325,38 @@ TEST_F(CursorManagerTest, TestCursorClientObserver) {
EXPECT_FALSE(observer_b.did_visibility_change());
EXPECT_TRUE(observer_a.is_cursor_visible());
}
+
+// This test validates that the cursor visiblity state is restored when a
+// CursorManager instance is destroyed and recreated.
+TEST(CursorManagerCreateDestroyTest, VisibilityTest) {
+ // This block ensures that the cursor is hidden when the CursorManager
+ // instance is destroyed.
+ {
+ wm::CursorManager cursor_manager1(
+ scoped_ptr<wm::NativeCursorManager>(new TestingCursorManager));
+ cursor_manager1.ShowCursor();
+ EXPECT_TRUE(cursor_manager1.IsCursorVisible());
+ cursor_manager1.HideCursor();
+ EXPECT_FALSE(cursor_manager1.IsCursorVisible());
+ }
+
+ // This block validates that the cursor is hidden initially. It ensures that
+ // the cursor is visible when the CursorManager instance is destroyed.
+ {
+ wm::CursorManager cursor_manager2(
+ scoped_ptr<wm::NativeCursorManager>(new TestingCursorManager));
+ EXPECT_FALSE(cursor_manager2.IsCursorVisible());
+ cursor_manager2.ShowCursor();
+ EXPECT_TRUE(cursor_manager2.IsCursorVisible());
+ }
+
+ // This block validates that the cursor is visible initially. It then
+ // performs normal cursor visibility operations.
+ {
+ wm::CursorManager cursor_manager3(
+ scoped_ptr<wm::NativeCursorManager>(new TestingCursorManager));
+ EXPECT_TRUE(cursor_manager3.IsCursorVisible());
+ cursor_manager3.HideCursor();
+ EXPECT_FALSE(cursor_manager3.IsCursorVisible());
+ }
+}
diff --git a/chromium/ui/wm/core/default_screen_position_client.cc b/chromium/ui/wm/core/default_screen_position_client.cc
index d26a91ed9c8..092b2da6b43 100644
--- a/chromium/ui/wm/core/default_screen_position_client.cc
+++ b/chromium/ui/wm/core/default_screen_position_client.cc
@@ -7,6 +7,7 @@
#include "ui/aura/window_tree_host.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
namespace wm {
@@ -19,11 +20,11 @@ DefaultScreenPositionClient::~DefaultScreenPositionClient() {
gfx::Point DefaultScreenPositionClient::GetOriginInScreen(
const aura::Window* root_window) {
- 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::ScaleToFlooredPoint(origin_in_pixels, 1.0f / scale);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
+ gfx::Rect screen_bounds = root_window->GetHost()->GetBounds();
+ gfx::Rect dip_bounds = screen->ScreenToDIPRectInWindow(window, screen_bounds);
+ return dip_bounds.origin();
}
void DefaultScreenPositionClient::ConvertPointToScreen(
diff --git a/chromium/ui/wm/core/image_grid.cc b/chromium/ui/wm/core/image_grid.cc
index 553e442d50b..82ca0e3af1e 100644
--- a/chromium/ui/wm/core/image_grid.cc
+++ b/chromium/ui/wm/core/image_grid.cc
@@ -29,18 +29,20 @@ namespace {
// 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 ScaleWidth(const gfx::Size& center,
+ ui::Layer* layer,
+ gfx::Transform* transform) {
float layer_width = layer->bounds().width() * layer->device_scale_factor();
float scale = static_cast<float>(center.width()) / layer_width;
- transform.Scale(scale, 1.0);
+ transform->Scale(scale, 1.0);
}
-void ScaleHeight(gfx::Size center,
+void ScaleHeight(const gfx::Size& center,
ui::Layer* layer,
- gfx::Transform& transform) {
+ gfx::Transform* transform) {
float layer_height = layer->bounds().height() * layer->device_scale_factor();
float scale = static_cast<float>(center.height()) / layer_height;
- transform.Scale(1.0, scale);
+ transform->Scale(1.0, scale);
}
// Returns the dimensions of |image| if non-NULL or gfx::Size(0, 0) otherwise.
@@ -153,7 +155,7 @@ void ImageGrid::SetSize(const gfx::Size& size) {
if (center_width > 0) {
gfx::Transform transform;
transform.Translate(left, 0);
- ScaleWidth(center_size_in_pixels, top_layer_.get(), transform);
+ ScaleWidth(center_size_in_pixels, top_layer_.get(), &transform);
top_layer_->SetTransform(transform);
}
top_layer_->SetVisible(center_width > 0);
@@ -163,7 +165,7 @@ void ImageGrid::SetSize(const gfx::Size& size) {
gfx::Transform transform;
transform.Translate(
left, size.height() - bottom_layer_->bounds().height());
- ScaleWidth(center_size_in_pixels, bottom_layer_.get(), transform);
+ ScaleWidth(center_size_in_pixels, bottom_layer_.get(), &transform);
bottom_layer_->SetTransform(transform);
}
bottom_layer_->SetVisible(center_width > 0);
@@ -172,7 +174,7 @@ void ImageGrid::SetSize(const gfx::Size& size) {
if (center_height > 0) {
gfx::Transform transform;
transform.Translate(0, top);
- ScaleHeight(center_size_in_pixels, left_layer_.get(), transform);
+ ScaleHeight(center_size_in_pixels, left_layer_.get(), &transform);
left_layer_->SetTransform(transform);
}
left_layer_->SetVisible(center_height > 0);
@@ -182,7 +184,7 @@ void ImageGrid::SetSize(const gfx::Size& size) {
gfx::Transform transform;
transform.Translate(
size.width() - right_layer_->bounds().width(), top);
- ScaleHeight(center_size_in_pixels, right_layer_.get(), transform);
+ ScaleHeight(center_size_in_pixels, right_layer_.get(), &transform);
right_layer_->SetTransform(transform);
}
right_layer_->SetVisible(center_height > 0);
@@ -268,7 +270,7 @@ void ImageGrid::ImagePainter::SetClipRect(const gfx::Rect& clip_rect,
}
void ImageGrid::ImagePainter::OnPaintLayer(const ui::PaintContext& context) {
- gfx::Size bounding_size(clip_rect_.right(), clip_rect_.bottom());
+ gfx::Size bounding_size(image_.width(), image_.height());
ui::PaintRecorder recorder(context, bounding_size);
if (!clip_rect_.IsEmpty())
recorder.canvas()->ClipRect(clip_rect_);
@@ -298,8 +300,6 @@ void ImageGrid::SetImage(const gfx::Image* image,
const int kMinimumSize = 20;
// Clean out old layers and painters.
- if (layer_ptr->get())
- layer_->Remove(layer_ptr->get());
layer_ptr->reset();
painter_ptr->reset();
diff --git a/chromium/ui/wm/core/nested_accelerator_controller.cc b/chromium/ui/wm/core/nested_accelerator_controller.cc
deleted file mode 100644
index 42ace4e9617..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_controller.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/core/nested_accelerator_controller.h"
-
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
-#include "ui/wm/core/nested_accelerator_dispatcher.h"
-
-namespace wm {
-
-NestedAcceleratorController::NestedAcceleratorController(
- NestedAcceleratorDelegate* delegate)
- : dispatcher_delegate_(delegate) {
- DCHECK(delegate);
-}
-
-NestedAcceleratorController::~NestedAcceleratorController() {
-}
-
-void NestedAcceleratorController::PrepareNestedLoopClosures(
- base::MessagePumpDispatcher* nested_dispatcher,
- base::Closure* run_closure,
- base::Closure* quit_closure) {
- scoped_ptr<NestedAcceleratorDispatcher> old_accelerator_dispatcher =
- std::move(accelerator_dispatcher_);
- accelerator_dispatcher_ = NestedAcceleratorDispatcher::Create(
- dispatcher_delegate_.get(), nested_dispatcher);
-
- scoped_ptr<base::RunLoop> run_loop = accelerator_dispatcher_->CreateRunLoop();
- *quit_closure =
- base::Bind(&NestedAcceleratorController::QuitNestedMessageLoop,
- base::Unretained(this),
- run_loop->QuitClosure());
- *run_closure = base::Bind(&NestedAcceleratorController::RunNestedMessageLoop,
- base::Unretained(this),
- base::Passed(&run_loop),
- base::Passed(&old_accelerator_dispatcher));
-}
-
-void NestedAcceleratorController::RunNestedMessageLoop(
- scoped_ptr<base::RunLoop> run_loop,
- scoped_ptr<NestedAcceleratorDispatcher> old_accelerator_dispatcher) {
- run_loop->Run();
- accelerator_dispatcher_ = std::move(old_accelerator_dispatcher);
-}
-
-void NestedAcceleratorController::QuitNestedMessageLoop(
- const base::Closure& quit_runloop) {
- quit_runloop.Run();
- accelerator_dispatcher_.reset();
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/nested_accelerator_controller.h b/chromium/ui/wm/core/nested_accelerator_controller.h
deleted file mode 100644
index 27cb8de392b..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_controller.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_WM_CORE_NESTED_ACCELERATOR_CONTROLLER_H_
-#define UI_WM_CORE_NESTED_ACCELERATOR_CONTROLLER_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "ui/wm/public/dispatcher_client.h"
-#include "ui/wm/wm_export.h"
-
-namespace wm {
-
-class NestedAcceleratorDelegate;
-class NestedAcceleratorDispatcher;
-
-// Creates a dispatcher which wraps another dispatcher.
-// The outer dispatcher runs first and performs ash specific handling.
-// If it does not consume the event it forwards the event to the nested
-// dispatcher.
-class WM_EXPORT NestedAcceleratorController
- : public aura::client::DispatcherClient {
- public:
- explicit NestedAcceleratorController(NestedAcceleratorDelegate* delegate);
- ~NestedAcceleratorController() override;
-
- // aura::client::DispatcherClient:
- void PrepareNestedLoopClosures(base::MessagePumpDispatcher* dispatcher,
- base::Closure* run_closure,
- base::Closure* quit_closure) override;
-
- private:
- void RunNestedMessageLoop(scoped_ptr<base::RunLoop> run_loop,
- scoped_ptr<NestedAcceleratorDispatcher> dispatcher);
- void QuitNestedMessageLoop(const base::Closure& quit_runloop);
-
- scoped_ptr<NestedAcceleratorDispatcher> accelerator_dispatcher_;
- scoped_ptr<NestedAcceleratorDelegate> dispatcher_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorController);
-};
-
-} // namespace wm
-
-#endif // UI_WM_CORE_NESTED_ACCELERATOR_CONTROLLER_H_
diff --git a/chromium/ui/wm/core/nested_accelerator_controller_unittest.cc b/chromium/ui/wm/core/nested_accelerator_controller_unittest.cc
deleted file mode 100644
index 0266999a046..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_controller_unittest.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/core/nested_accelerator_controller.h"
-
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/event_types.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "build/build_config.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/base/accelerators/accelerator.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/accelerators/accelerator_manager.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/events/platform/scoped_event_dispatcher.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
-#include "ui/wm/public/dispatcher_client.h"
-
-#if defined(USE_X11)
-#include <X11/Xlib.h>
-#include "ui/aura/test/x11_event_sender.h"
-#include "ui/events/test/events_test_utils_x11.h"
-#endif // USE_X11
-
-namespace wm {
-namespace test {
-
-namespace {
-
-class MockDispatcher : public ui::PlatformEventDispatcher {
- public:
- MockDispatcher() : num_key_events_dispatched_(0) {}
-
- int num_key_events_dispatched() { return num_key_events_dispatched_; }
-
- private:
- // ui::PlatformEventDispatcher:
- bool CanDispatchEvent(const ui::PlatformEvent& event) override {
- return true;
- }
- uint32_t DispatchEvent(const ui::PlatformEvent& event) override {
- if (ui::EventTypeFromNative(event) == ui::ET_KEY_RELEASED)
- num_key_events_dispatched_++;
- return ui::POST_DISPATCH_NONE;
- }
-
- int num_key_events_dispatched_;
-
- DISALLOW_COPY_AND_ASSIGN(MockDispatcher);
-};
-
-class TestTarget : public ui::AcceleratorTarget {
- public:
- TestTarget() : accelerator_pressed_count_(0) {}
- ~TestTarget() override {}
-
- int accelerator_pressed_count() const { return accelerator_pressed_count_; }
-
- // Overridden from ui::AcceleratorTarget:
- bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
- accelerator_pressed_count_++;
- return true;
- }
- bool CanHandleAccelerators() const override { return true; }
-
- private:
- int accelerator_pressed_count_;
-
- DISALLOW_COPY_AND_ASSIGN(TestTarget);
-};
-
-void DispatchKeyReleaseA(aura::Window* root_window) {
-// Sending both keydown and keyup is necessary here because the accelerator
-// manager only checks a keyup event following a keydown event. See
-// ShouldHandle() in ui/base/accelerators/accelerator_manager.cc for details.
-#if defined(OS_WIN)
- aura::WindowTreeHost* host = root_window->GetHost();
- HWND hwnd = host->GetAcceleratedWidget();
- ::PostMessage(hwnd, WM_KEYDOWN, ui::VKEY_A, 0);
- ::PostMessage(hwnd, WM_KEYUP, ui::VKEY_A, 0);
-#elif defined(USE_X11)
- ui::ScopedXI2Event native_event;
- native_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
- aura::WindowTreeHost* host = root_window->GetHost();
- aura::test::PostEventToWindowTreeHost(*native_event, host);
- native_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0);
- aura::test::PostEventToWindowTreeHost(*native_event, host);
-#endif
- // Make sure the inner message-loop terminates after dispatching the events.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::MessageLoop::current()->QuitWhenIdleClosure());
-}
-
-class MockNestedAcceleratorDelegate : public NestedAcceleratorDelegate {
- public:
- MockNestedAcceleratorDelegate()
- : accelerator_manager_(new ui::AcceleratorManager) {}
- ~MockNestedAcceleratorDelegate() override {}
-
- // NestedAcceleratorDelegate:
- Result ProcessAccelerator(const ui::Accelerator& accelerator) override {
- return accelerator_manager_->Process(accelerator) ?
- RESULT_PROCESSED : RESULT_NOT_PROCESSED;
- }
-
- void Register(const ui::Accelerator& accelerator,
- ui::AcceleratorTarget* target) {
- accelerator_manager_->Register(
- accelerator, ui::AcceleratorManager::kNormalPriority, target);
- }
-
- private:
- scoped_ptr<ui::AcceleratorManager> accelerator_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(MockNestedAcceleratorDelegate);
-};
-
-class NestedAcceleratorTest : public aura::test::AuraTestBase {
- public:
- NestedAcceleratorTest() {}
- ~NestedAcceleratorTest() override {}
-
- void SetUp() override {
- AuraTestBase::SetUp();
- delegate_ = new MockNestedAcceleratorDelegate();
- nested_accelerator_controller_.reset(
- new NestedAcceleratorController(delegate_));
- aura::client::SetDispatcherClient(root_window(),
- nested_accelerator_controller_.get());
- }
-
- void TearDown() override {
- aura::client::SetDispatcherClient(root_window(), NULL);
- AuraTestBase::TearDown();
- delegate_ = NULL;
- nested_accelerator_controller_.reset();
- }
-
- MockNestedAcceleratorDelegate* delegate() { return delegate_; }
-
- private:
- scoped_ptr<NestedAcceleratorController> nested_accelerator_controller_;
- MockNestedAcceleratorDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorTest);
-};
-
-} // namespace
-
-// Aura window above lock screen in z order.
-// http://crbug.com/396494
-TEST_F(NestedAcceleratorTest, DISABLED_AssociatedWindowAboveLockScreen) {
- // TODO(oshima|sadrul): remove when Win implements PES.
- if (!ui::PlatformEventSource::GetInstance())
- return;
- MockDispatcher inner_dispatcher;
- scoped_ptr<aura::Window> mock_lock_container(
- CreateNormalWindow(0, root_window(), NULL));
- aura::test::CreateTestWindowWithId(1, mock_lock_container.get());
-
- scoped_ptr<aura::Window> associated_window(
- CreateNormalWindow(2, root_window(), NULL));
- EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(),
- mock_lock_container.get()));
-
- DispatchKeyReleaseA(root_window());
- scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher =
- ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
- &inner_dispatcher);
- aura::client::DispatcherRunLoop run_loop(
- aura::client::GetDispatcherClient(root_window()), NULL);
- run_loop.Run();
- EXPECT_EQ(1, inner_dispatcher.num_key_events_dispatched());
-}
-
-// Test that the nested dispatcher handles accelerators.
-// http://crbug.com/396494
-TEST_F(NestedAcceleratorTest, DISABLED_AcceleratorsHandled) {
- // TODO(oshima|sadrul): remove when Win implements PES.
- if (!ui::PlatformEventSource::GetInstance())
- return;
- MockDispatcher inner_dispatcher;
- ui::Accelerator accelerator(ui::VKEY_A, ui::EF_NONE);
- accelerator.set_type(ui::ET_KEY_RELEASED);
- TestTarget target;
- delegate()->Register(accelerator, &target);
-
- DispatchKeyReleaseA(root_window());
- scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher =
- ui::PlatformEventSource::GetInstance()->OverrideDispatcher(
- &inner_dispatcher);
- aura::client::DispatcherRunLoop run_loop(
- aura::client::GetDispatcherClient(root_window()), NULL);
- run_loop.Run();
- EXPECT_EQ(0, inner_dispatcher.num_key_events_dispatched());
- EXPECT_EQ(1, target.accelerator_pressed_count());
-}
-
-} // namespace test
-} // namespace wm
diff --git a/chromium/ui/wm/core/nested_accelerator_delegate.h b/chromium/ui/wm/core/nested_accelerator_delegate.h
deleted file mode 100644
index 4b13c0d882b..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_delegate.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_WM_CORE_NESTED_ACCELERATOR_DELEGATE_H_
-#define UI_WM_CORE_NESTED_ACCELERATOR_DELEGATE_H_
-
-namespace ui {
-class Accelerator;
-}
-
-namespace wm {
-
-// A delegate interface that implements the behavior of nested accelerator
-// handling.
-class NestedAcceleratorDelegate {
- public:
- enum Result {
- RESULT_PROCESSED,
- RESULT_NOT_PROCESSED,
- // The key event should be ignored now and instead be reposted so that
- // next event loop.
- RESULT_PROCESS_LATER,
- };
-
- virtual ~NestedAcceleratorDelegate() {}
-
- // Attempts to process the |accelerator|.
- virtual Result ProcessAccelerator(const ui::Accelerator& accelerator) = 0;
-};
-
-} // namespace wm
-
-#endif // UI_WM_CORE_NESTED_ACCELERATOR_DELEGATE_H_
diff --git a/chromium/ui/wm/core/nested_accelerator_dispatcher.cc b/chromium/ui/wm/core/nested_accelerator_dispatcher.cc
deleted file mode 100644
index d37c93c796f..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_dispatcher.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/core/nested_accelerator_dispatcher.h"
-
-#include "base/logging.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
-
-namespace wm {
-
-NestedAcceleratorDispatcher::NestedAcceleratorDispatcher(
- NestedAcceleratorDelegate* delegate)
- : delegate_(delegate) {
- DCHECK(delegate);
-}
-
-NestedAcceleratorDispatcher::~NestedAcceleratorDispatcher() {
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/nested_accelerator_dispatcher.h b/chromium/ui/wm/core/nested_accelerator_dispatcher.h
deleted file mode 100644
index df5dd0862d9..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_dispatcher.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_WM_CORE_NESTED_ACCELERATOR_DISPATCHER_H_
-#define UI_WM_CORE_NESTED_ACCELERATOR_DISPATCHER_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/wm/wm_export.h"
-
-namespace base {
-class MessagePumpDispatcher;
-class RunLoop;
-}
-
-namespace ui {
-class KeyEvent;
-}
-
-namespace wm {
-
-class NestedAcceleratorDelegate;
-
-// Dispatcher for handling accelerators from menu.
-//
-// Wraps a nested dispatcher to which control is passed if no accelerator key
-// has been pressed. If the nested dispatcher is NULL, then the control is
-// passed back to the default dispatcher.
-// TODO(pkotwicz): Add support for a |nested_dispatcher| which sends
-// events to a system IME.
-class WM_EXPORT NestedAcceleratorDispatcher {
- public:
- virtual ~NestedAcceleratorDispatcher();
-
- static scoped_ptr<NestedAcceleratorDispatcher> Create(
- NestedAcceleratorDelegate* dispatcher_delegate,
- base::MessagePumpDispatcher* nested_dispatcher);
-
- // Creates a base::RunLoop object to run a nested message loop.
- virtual scoped_ptr<base::RunLoop> CreateRunLoop() = 0;
-
- protected:
- explicit NestedAcceleratorDispatcher(NestedAcceleratorDelegate* delegate);
-
- NestedAcceleratorDelegate*
- delegate_; // Owned by NestedAcceleratorController.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDispatcher);
-};
-
-} // namespace wm
-
-#endif // UI_WM_CORE_NESTED_ACCELERATOR_DISPATCHER_H_
diff --git a/chromium/ui/wm/core/nested_accelerator_dispatcher_linux.cc b/chromium/ui/wm/core/nested_accelerator_dispatcher_linux.cc
deleted file mode 100644
index d9060041d4f..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_dispatcher_linux.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/core/nested_accelerator_dispatcher.h"
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/run_loop.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/events/event.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/events/platform/scoped_event_dispatcher.h"
-#include "ui/wm/core/accelerator_filter.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
-
-#if defined(USE_X11)
-#include <X11/Xlib.h>
-#endif
-
-namespace wm {
-
-namespace {
-
-#if defined(USE_OZONE)
-bool IsKeyEvent(const base::NativeEvent& native_event) {
- const ui::KeyEvent* event = static_cast<const ui::KeyEvent*>(native_event);
- return event->IsKeyEvent();
-}
-#elif defined(USE_X11)
-bool IsKeyEvent(const XEvent* xev) {
- return xev->type == KeyPress || xev->type == KeyRelease;
-}
-#else
-#error Unknown build platform: you should have either use_ozone or use_x11.
-#endif
-
-scoped_ptr<ui::ScopedEventDispatcher> OverrideDispatcher(
- ui::PlatformEventDispatcher* dispatcher) {
- ui::PlatformEventSource* source = ui::PlatformEventSource::GetInstance();
- return source ? source->OverrideDispatcher(dispatcher) : nullptr;
-}
-
-} // namespace
-
-class NestedAcceleratorDispatcherLinux : public NestedAcceleratorDispatcher,
- public ui::PlatformEventDispatcher {
- public:
- explicit NestedAcceleratorDispatcherLinux(NestedAcceleratorDelegate* delegate)
- : NestedAcceleratorDispatcher(delegate),
- restore_dispatcher_(OverrideDispatcher(this)) {}
-
- ~NestedAcceleratorDispatcherLinux() override {}
-
- private:
- // AcceleratorDispatcher:
- scoped_ptr<base::RunLoop> CreateRunLoop() override {
- return make_scoped_ptr(new base::RunLoop());
- }
-
- // ui::PlatformEventDispatcher:
- bool CanDispatchEvent(const ui::PlatformEvent& event) override {
- return true;
- }
-
- uint32_t DispatchEvent(const ui::PlatformEvent& event) override {
- if (IsKeyEvent(event)) {
- ui::Accelerator accelerator((ui::KeyEvent(event)));
-
- switch (delegate_->ProcessAccelerator(accelerator)) {
- case NestedAcceleratorDelegate::RESULT_PROCESS_LATER:
-#if defined(USE_X11)
- XPutBackEvent(event->xany.display, event);
-#else
- NOTIMPLEMENTED();
-#endif
- return ui::POST_DISPATCH_NONE;
- case NestedAcceleratorDelegate::RESULT_PROCESSED:
- return ui::POST_DISPATCH_NONE;
- case NestedAcceleratorDelegate::RESULT_NOT_PROCESSED:
- break;
- }
- }
- ui::PlatformEventDispatcher* prev = *restore_dispatcher_;
-
- uint32_t perform_default = ui::POST_DISPATCH_PERFORM_DEFAULT;
- return prev ? prev->DispatchEvent(event) : perform_default;
- }
-
- scoped_ptr<ui::ScopedEventDispatcher> restore_dispatcher_;
-
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDispatcherLinux);
-};
-
-scoped_ptr<NestedAcceleratorDispatcher> NestedAcceleratorDispatcher::Create(
- NestedAcceleratorDelegate* delegate,
- base::MessagePumpDispatcher* nested_dispatcher) {
- return make_scoped_ptr(new NestedAcceleratorDispatcherLinux(delegate));
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/nested_accelerator_dispatcher_win.cc b/chromium/ui/wm/core/nested_accelerator_dispatcher_win.cc
deleted file mode 100644
index 1b59d689017..00000000000
--- a/chromium/ui/wm/core/nested_accelerator_dispatcher_win.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/core/nested_accelerator_dispatcher.h"
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_pump_dispatcher.h"
-#include "base/run_loop.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/events/event.h"
-#include "ui/wm/core/accelerator_filter.h"
-#include "ui/wm/core/nested_accelerator_delegate.h"
-
-using base::MessagePumpDispatcher;
-
-namespace wm {
-
-namespace {
-
-bool IsKeyEvent(const MSG& msg) {
- return msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN ||
- msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP;
-}
-
-} // namespace
-
-class NestedAcceleratorDispatcherWin : public NestedAcceleratorDispatcher,
- public MessagePumpDispatcher {
- public:
- NestedAcceleratorDispatcherWin(NestedAcceleratorDelegate* delegate,
- MessagePumpDispatcher* nested)
- : NestedAcceleratorDispatcher(delegate), nested_dispatcher_(nested) {}
- ~NestedAcceleratorDispatcherWin() override {}
-
- private:
- // NestedAcceleratorDispatcher:
- scoped_ptr<base::RunLoop> CreateRunLoop() override {
- return make_scoped_ptr(new base::RunLoop(this));
- }
-
- // MessagePumpDispatcher:
- uint32_t Dispatch(const MSG& event) override {
- if (IsKeyEvent(event)) {
- ui::Accelerator accelerator((ui::KeyEvent(event)));
-
- switch (delegate_->ProcessAccelerator(accelerator)) {
- case NestedAcceleratorDelegate::RESULT_PROCESS_LATER:
- return POST_DISPATCH_QUIT_LOOP;
- case NestedAcceleratorDelegate::RESULT_PROCESSED:
- return POST_DISPATCH_NONE;
- case NestedAcceleratorDelegate::RESULT_NOT_PROCESSED:
- break;
- }
- }
-
- return nested_dispatcher_ ? nested_dispatcher_->Dispatch(event)
- : POST_DISPATCH_PERFORM_DEFAULT;
- }
-
- MessagePumpDispatcher* nested_dispatcher_;
-
- DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDispatcherWin);
-};
-
-scoped_ptr<NestedAcceleratorDispatcher> NestedAcceleratorDispatcher::Create(
- NestedAcceleratorDelegate* delegate,
- MessagePumpDispatcher* nested_dispatcher) {
- return make_scoped_ptr(
- new NestedAcceleratorDispatcherWin(delegate, nested_dispatcher));
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/shadow_unittest.cc b/chromium/ui/wm/core/shadow_unittest.cc
index 14236874cab..f69095e5133 100644
--- a/chromium/ui/wm/core/shadow_unittest.cc
+++ b/chromium/ui/wm/core/shadow_unittest.cc
@@ -60,8 +60,7 @@ class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate {
return gfx::Image();
}
}
- gfx::Image GetNativeImageNamed(int resource_id,
- ui::ResourceBundle::ImageRTL rtl) override {
+ gfx::Image GetNativeImageNamed(int resource_id) override {
return gfx::Image();
}
base::RefCountedStaticMemory* LoadDataResourceBytes(
@@ -77,9 +76,6 @@ class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate {
bool GetLocalizedString(int message_id, base::string16* value) override {
return false;
}
- scoped_ptr<gfx::Font> GetFont(ui::ResourceBundle::FontStyle style) override {
- return nullptr;
- }
int last_resource_id() const { return last_resource_id_; }
diff --git a/chromium/ui/wm/public/dispatcher_client.cc b/chromium/ui/wm/public/dispatcher_client.cc
deleted file mode 100644
index e3be7ca848b..00000000000
--- a/chromium/ui/wm/public/dispatcher_client.cc
+++ /dev/null
@@ -1,52 +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/wm/public/dispatcher_client.h"
-
-#include "base/callback.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DispatcherClient*);
-
-namespace aura {
-namespace client {
-
-DispatcherRunLoop::DispatcherRunLoop(DispatcherClient* client,
- base::MessagePumpDispatcher* dispatcher) {
- client->PrepareNestedLoopClosures(dispatcher, &run_closure_, &quit_closure_);
-}
-
-DispatcherRunLoop::~DispatcherRunLoop() {
-}
-
-void DispatcherRunLoop::Run() {
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
- run_closure_.Run();
-}
-
-base::Closure DispatcherRunLoop::QuitClosure() {
- return quit_closure_;
-}
-
-void DispatcherRunLoop::Quit() {
- quit_closure_.Run();
-}
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(DispatcherClient*, kDispatcherClientKey, NULL);
-
-void SetDispatcherClient(Window* root_window, DispatcherClient* client) {
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- root_window->SetProperty(kDispatcherClientKey, client);
-}
-
-DispatcherClient* GetDispatcherClient(Window* root_window) {
- if (root_window)
- DCHECK_EQ(root_window->GetRootWindow(), root_window);
- return root_window ? root_window->GetProperty(kDispatcherClientKey) : NULL;
-}
-
-} // namespace client
-} // namespace aura
diff --git a/chromium/ui/wm/public/dispatcher_client.h b/chromium/ui/wm/public/dispatcher_client.h
deleted file mode 100644
index a301e92dd55..00000000000
--- a/chromium/ui/wm/public/dispatcher_client.h
+++ /dev/null
@@ -1,59 +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_WM_PUBLIC_DISPATCHER_CLIENT_H_
-#define UI_WM_PUBLIC_DISPATCHER_CLIENT_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/message_loop/message_pump_dispatcher.h"
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-class DispatcherClient;
-
-// A base::RunLoop like object for running a nested message-loop with a
-// specified DispatcherClient and a MessagePumpDispatcher.
-class AURA_EXPORT DispatcherRunLoop {
- public:
- DispatcherRunLoop(DispatcherClient* client,
- base::MessagePumpDispatcher* dispatcher);
- ~DispatcherRunLoop();
-
- void Run();
- base::Closure QuitClosure();
- void Quit();
-
- private:
- base::Closure run_closure_;
- base::Closure quit_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(DispatcherRunLoop);
-};
-
-// An interface implemented by an object which handles nested dispatchers.
-class AURA_EXPORT DispatcherClient {
- public:
- virtual ~DispatcherClient() {}
-
- protected:
- friend class DispatcherRunLoop;
-
- virtual void PrepareNestedLoopClosures(
- base::MessagePumpDispatcher* dispatcher,
- base::Closure* run_closure,
- base::Closure* quit_closure) = 0;
-};
-
-AURA_EXPORT void SetDispatcherClient(Window* root_window,
- DispatcherClient* client);
-AURA_EXPORT DispatcherClient* GetDispatcherClient(Window* root_window);
-
-} // namespace client
-} // namespace aura
-
-#endif // UI_WM_PUBLIC_DISPATCHER_CLIENT_H_
diff --git a/chromium/ui/wm/public/tooltip_client.h b/chromium/ui/wm/public/tooltip_client.h
index f58a63e12a6..77095153b6e 100644
--- a/chromium/ui/wm/public/tooltip_client.h
+++ b/chromium/ui/wm/public/tooltip_client.h
@@ -21,8 +21,7 @@ class ScopedTooltipDisabler;
class AURA_EXPORT TooltipClient {
public:
// Returns the max width of the tooltip when shown at the specified location.
- virtual int GetMaxWidth(const gfx::Point& point,
- aura::Window* context) const = 0;
+ virtual int GetMaxWidth(const gfx::Point& point) const = 0;
// Informs the shell tooltip manager of change in tooltip for window |target|.
virtual void UpdateTooltip(Window* target) = 0;
diff --git a/chromium/ui/wm/wm.gyp b/chromium/ui/wm/wm.gyp
index 28a8cb28f4e..685c9769add 100644
--- a/chromium/ui/wm/wm.gyp
+++ b/chromium/ui/wm/wm.gyp
@@ -60,13 +60,6 @@
'core/masked_window_targeter.h',
'core/native_cursor_manager.h',
'core/native_cursor_manager_delegate.h',
- 'core/nested_accelerator_controller.cc',
- 'core/nested_accelerator_controller.h',
- 'core/nested_accelerator_delegate.h',
- 'core/nested_accelerator_dispatcher.cc',
- 'core/nested_accelerator_dispatcher.h',
- 'core/nested_accelerator_dispatcher_linux.cc',
- 'core/nested_accelerator_dispatcher_win.cc',
'core/shadow.cc',
'core/shadow.h',
'core/shadow_controller.cc',
@@ -100,15 +93,6 @@
'../../build/linux/system.gyp:x11',
],
}],
- ['OS=="android"', {
- 'sources!': [
- 'core/nested_accelerator_controller.cc',
- 'core/nested_accelerator_controller.h',
- 'core/nested_accelerator_delegate.h',
- 'core/nested_accelerator_dispatcher.cc',
- 'core/nested_accelerator_dispatcher.h',
- ],
- }],
],
},
{
@@ -154,7 +138,6 @@
'core/cursor_manager_unittest.cc',
'core/focus_controller_unittest.cc',
'core/image_grid_unittest.cc',
- 'core/nested_accelerator_controller_unittest.cc',
'core/shadow_controller_unittest.cc',
'core/shadow_unittest.cc',
'core/transient_window_manager_unittest.cc',