diff options
Diffstat (limited to 'chromium/ui/base')
316 files changed, 6018 insertions, 4974 deletions
diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn index 547ecab34e4..1179753aeff 100644 --- a/chromium/ui/base/BUILD.gn +++ b/chromium/ui/base/BUILD.gn @@ -3,6 +3,7 @@ # found in the LICENSE file. import("//build/buildflag_header.gni") +import("//build/config/chromeos/ui_mode.gni") import("//build/config/compiler/compiler.gni") import("//build/config/dcheck_always_on.gni") import("//build/config/jumbo.gni") @@ -66,6 +67,7 @@ buildflag_header("buildflags") { flags = [ "ENABLE_HIDPI=$enable_hidpi", "ENABLE_MESSAGE_CENTER=$enable_message_center", + "LACROS=$chromeos_is_browser_only", "USE_ATK=$use_atk", "USE_XKBCOMMON=$use_xkbcommon", "HAS_NATIVE_ACCESSIBILITY=$has_native_accessibility", @@ -93,9 +95,6 @@ jumbo_component("base") { sources = [ "class_property.cc", "class_property.h", - "cursor/cursor_loader.h", - "cursor/cursor_lookup.cc", - "cursor/cursor_lookup.h", "default_style.h", "device_form_factor.h", "device_form_factor_desktop.cc", @@ -158,7 +157,6 @@ jumbo_component("base") { "template_expressions.h", "theme_provider.cc", "theme_provider.h", - "ui_base_export.h", "ui_base_exports.cc", "ui_base_paths.cc", "ui_base_paths.h", @@ -178,6 +176,8 @@ jumbo_component("base") { "window_open_disposition.h", ] + libs = [] + if (is_android) { sources += [ "device_form_factor_android.cc", @@ -207,6 +207,8 @@ jumbo_component("base") { "win/accessibility_misc_utils.cc", "win/accessibility_misc_utils.h", "win/atl_module.h", + "win/event_creation_utils.cc", + "win/event_creation_utils.h", "win/foreground_helper.cc", "win/foreground_helper.h", "win/hidden_window.cc", @@ -234,6 +236,11 @@ jumbo_component("base") { "win/window_event_target.cc", "win/window_event_target.h", ] + ldflags = [ "/DELAYLOAD:dwmapi.dll" ] + libs += [ + "dwmapi.lib", + "wtsapi32.lib", + ] } if (is_mac) { @@ -333,8 +340,6 @@ jumbo_component("base") { "accelerators/system_media_controls_media_keys_listener.h", "base_window.cc", "base_window.h", - "cursor/cursor_util.cc", - "cursor/cursor_util.h", "emoji/emoji_panel_helper.h", "pointer/pointer_device.h", "pointer/pointer_device_util.cc", @@ -416,7 +421,7 @@ jumbo_component("base") { configs += [ "//build/config/compiler:wexit_time_destructors" ] - defines = [ "UI_BASE_IMPLEMENTATION" ] + defines = [ "IS_UI_BASE_IMPL" ] public_deps = [ ":buildflags", @@ -425,11 +430,10 @@ jumbo_component("base") { ":ui_data_pack", "//base", "//skia", - "//ui/base/cursor", - "//ui/base/cursor/mojom:cursor_type", "//ui/gfx", "//ui/gfx/geometry", ] + deps = [ "//base:base_static", "//base:i18n", @@ -445,7 +449,7 @@ jumbo_component("base") { "//ui/display", "//ui/events", "//ui/events/devices", - "//ui/resources", + "//ui/resources:webui_resources_grd", "//ui/strings", "//url", ] @@ -479,7 +483,7 @@ jumbo_component("base") { deps += [ "//ui/events" ] } - if (is_desktop_linux && (use_x11 || ozone_platform_x11)) { + if ((is_desktop_linux || is_chromeos) && (use_x11 || ozone_platform_x11)) { public_deps += [ "//ui/base/x" ] # X11 drag and drop wants to use common drag and drop types. @@ -494,8 +498,6 @@ jumbo_component("base") { if (use_x11 && use_aura) { sources += [ - "cursor/cursor_loader_x11.cc", - "cursor/cursor_loader_x11.h", "x/selection_requestor.cc", "x/selection_requestor.h", ] @@ -521,14 +523,6 @@ jumbo_component("base") { deps += [ "//third_party/fontconfig" ] } - if (is_desktop_linux) { - sources += [ - "cursor/cursor_theme_manager_linux.cc", - "cursor/cursor_theme_manager_linux.h", - "cursor/cursor_theme_manager_linux_observer.h", - ] - } - if (use_glib) { configs += [ "//build/config/linux:glib" ] sources += [ @@ -540,8 +534,8 @@ jumbo_component("base") { if (is_chromeos || (use_aura && is_linux && !use_x11)) { sources += [ - "dragdrop/os_exchange_data_provider_aura.cc", - "dragdrop/os_exchange_data_provider_aura.h", + "dragdrop/os_exchange_data_provider_non_backed.cc", + "dragdrop/os_exchange_data_provider_non_backed.h", ] } @@ -549,37 +543,11 @@ jumbo_component("base") { deps += [ "//ui/base/clipboard" ] } - libs = [] - if (is_win) { - sources += [ - "cursor/cursor_loader_win.cc", - "cursor/cursor_loader_win.h", - ] - deps += [ "//third_party/wtl" ] - cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()), - # which is uninteresting. - - ldflags = [ - "/DELAYLOAD:d2d1.dll", - "/DELAYLOAD:d3d10_1.dll", - "/DELAYLOAD:dwmapi.dll", - ] - libs += [ - "d2d1.lib", - "d3d10_1.lib", - "dwmapi.lib", - "d2d1.lib", - "dwmapi.lib", - "oleacc.lib", - "wtsapi32.lib", + if (!use_aura) { + sources -= [ + "view_prop.cc", + "view_prop.h", ] - } else { - if (!use_aura) { - sources -= [ - "view_prop.cc", - "view_prop.h", - ] - } } if (is_mac) { @@ -596,20 +564,6 @@ jumbo_component("base") { ] } - if (use_ozone) { - sources += [ - "cursor/cursor_loader_ozone.cc", - "cursor/cursor_loader_ozone.h", - "cursor/ozone/bitmap_cursor_factory_ozone.cc", - "cursor/ozone/bitmap_cursor_factory_ozone.h", - ] - - deps += [ - "//ui/events/ozone/layout", - "//ui/ozone:ozone_base", - ] - } - if (!toolkit_views && !use_aura) { sources -= [ "dragdrop/drag_drop_types.h", @@ -637,16 +591,6 @@ jumbo_component("base") { ] } - if (use_aura) { - # Cursor - sources += [ - "cursor/cursors_aura.cc", - "cursor/cursors_aura.h", - "cursor/image_cursors.cc", - "cursor/image_cursors.h", - ] - } - if (is_android || is_ios) { sources -= [ "device_form_factor_desktop.cc" ] } @@ -690,10 +634,13 @@ component("features") { ] } +# TODO(crbug.com/1091985): Support CrOS. if (is_win || is_mac || (is_linux && !is_chromeos)) { jumbo_static_library("pixel_diff_test_support") { testonly = true sources = [ + "test/skia_gold_matching_algorithm.cc", + "test/skia_gold_matching_algorithm.h", "test/skia_gold_pixel_diff.cc", "test/skia_gold_pixel_diff.h", ] @@ -969,6 +916,7 @@ test("ui_base_unittests") { "//ui/base:ui_data_pack", "//ui/base/clipboard:clipboard_test", "//ui/base/clipboard:clipboard_types", + "//ui/base/cursor:unittests", "//ui/display", "//ui/events:events_base", "//ui/events:test_support", @@ -999,18 +947,13 @@ test("ui_base_unittests") { "accelerators/accelerator_unittest.cc", "accelerators/menu_label_accelerator_util_unittest.cc", "accelerators/system_media_controls_media_keys_listener_unittest.cc", - "cursor/cursor_unittest.cc", - "cursor/cursor_util_unittest.cc", "models/list_model_unittest.cc", "models/list_selection_model_unittest.cc", "models/tree_node_model_unittest.cc", "text/bytes_formatting_unittest.cc", "webui/web_ui_util_unittest.cc", ] - deps += [ - "//components/system_media_controls:test_support", - "//ui/base/cursor/mojom:cursor_type", - ] + deps += [ "//components/system_media_controls:test_support" ] if (is_linux) { sources += @@ -1033,8 +976,12 @@ test("ui_base_unittests") { } } + # TODO(crbug.com/1091985): Support CrOS. if (is_win || is_mac || (is_linux && !is_chromeos)) { - sources += [ "test/skia_gold_pixel_diff_unittest.cc" ] + sources += [ + "test/skia_gold_matching_algorithm_unittest.cc", + "test/skia_gold_pixel_diff_unittest.cc", + ] deps += [ ":pixel_diff_test_support" ] } @@ -1114,23 +1061,9 @@ test("ui_base_unittests") { if (is_win) { sources += [ "dragdrop/os_exchange_data_win_unittest.cc", + "view_prop_unittest.cc", "win/hwnd_subclass_unittest.cc", ] - - ldflags = [ - "/DELAYLOAD:d2d1.dll", - "/DELAYLOAD:d3d10_1.dll", - ] - libs = [ - "d2d1.lib", - "d3d10_1.lib", - "imm32.lib", - "oleacc.lib", - ] - } - - if (is_win) { - sources += [ "view_prop_unittest.cc" ] } if (is_android) { @@ -1146,6 +1079,7 @@ test("ui_base_unittests") { if (use_x11) { deps += [ + "//ui/base/x:unittests", "//ui/events/platform/x11", "//ui/gfx/x", ] @@ -1173,6 +1107,7 @@ test("ui_base_unittests") { "dragdrop/os_exchange_data_provider_x11_unittest.cc", "x/selection_requestor_unittest.cc", ] + deps += [ "//ui/gfx/x:unit_test" ] } if (is_chromeos) { diff --git a/chromium/ui/base/DEPS b/chromium/ui/base/DEPS index 9179ffdd1b2..10a3245a323 100644 --- a/chromium/ui/base/DEPS +++ b/chromium/ui/base/DEPS @@ -15,4 +15,5 @@ include_rules = [ "+ui/resources/grit/webui_resources.h", "+ui/strings/grit/app_locale_settings.h", "+ui/strings/grit/ui_strings.h", + "+url" ] diff --git a/chromium/ui/base/accelerators/accelerator.cc b/chromium/ui/base/accelerators/accelerator.cc index 2ab364badbe..7f26ef86fe9 100644 --- a/chromium/ui/base/accelerators/accelerator.cc +++ b/chromium/ui/base/accelerators/accelerator.cc @@ -135,17 +135,11 @@ Accelerator::Accelerator(const KeyEvent& key_event) #endif } -Accelerator::Accelerator(const Accelerator& accelerator) { - key_code_ = accelerator.key_code_; - key_state_ = accelerator.key_state_; - modifiers_ = accelerator.modifiers_; - time_stamp_ = accelerator.time_stamp_; - interrupted_by_mouse_event_ = accelerator.interrupted_by_mouse_event_; - source_device_id_ = accelerator.source_device_id_; -} +Accelerator::Accelerator(const Accelerator& accelerator) = default; -Accelerator::~Accelerator() { -} +Accelerator& Accelerator::operator=(const Accelerator& accelerator) = default; + +Accelerator::~Accelerator() = default; // static int Accelerator::MaskOutKeyEventFlags(int flags) { @@ -159,17 +153,6 @@ KeyEvent Accelerator::ToKeyEvent() const { key_code(), modifiers(), time_stamp()); } -Accelerator& Accelerator::operator=(const Accelerator& accelerator) { - if (this != &accelerator) { - key_code_ = accelerator.key_code_; - key_state_ = accelerator.key_state_; - modifiers_ = accelerator.modifiers_; - time_stamp_ = accelerator.time_stamp_; - interrupted_by_mouse_event_ = accelerator.interrupted_by_mouse_event_; - } - return *this; -} - bool Accelerator::operator <(const Accelerator& rhs) const { const int modifiers_with_mask = MaskOutKeyEventFlags(modifiers_); const int rhs_modifiers_with_mask = MaskOutKeyEventFlags(rhs.modifiers_); diff --git a/chromium/ui/base/accelerators/accelerator.h b/chromium/ui/base/accelerators/accelerator.h index d4b97e5b6ee..6111a3bf550 100644 --- a/chromium/ui/base/accelerators/accelerator.h +++ b/chromium/ui/base/accelerators/accelerator.h @@ -14,10 +14,10 @@ #include <memory> #include <utility> +#include "base/component_export.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -30,7 +30,7 @@ class KeyEvent; // for a particular KeyEvent matches an accelerator with or without the repeat // flag. A side effect of this is that == (and <) does not consider the // repeat flag in its comparison. -class UI_BASE_EXPORT Accelerator { +class COMPONENT_EXPORT(UI_BASE) Accelerator { public: enum class KeyState { PRESSED, @@ -48,6 +48,7 @@ class UI_BASE_EXPORT Accelerator { base::TimeTicks time_stamp = base::TimeTicks()); explicit Accelerator(const KeyEvent& key_event); Accelerator(const Accelerator& accelerator); + Accelerator& operator=(const Accelerator& accelerator); ~Accelerator(); // Masks out all the non-modifiers KeyEvent |flags| and returns only the @@ -56,8 +57,6 @@ class UI_BASE_EXPORT Accelerator { KeyEvent ToKeyEvent() const; - Accelerator& operator=(const Accelerator& accelerator); - // Define the < operator so that the KeyboardShortcut can be used as a key in // a std::map. bool operator <(const Accelerator& rhs) const; @@ -129,7 +128,7 @@ class UI_BASE_EXPORT Accelerator { // An interface that classes that want to register for keyboard accelerators // should implement. -class UI_BASE_EXPORT AcceleratorTarget { +class COMPONENT_EXPORT(UI_BASE) AcceleratorTarget { public: // Should return true if the accelerator was processed. virtual bool AcceleratorPressed(const Accelerator& accelerator) = 0; diff --git a/chromium/ui/base/accelerators/accelerator_history.h b/chromium/ui/base/accelerators/accelerator_history.h index e9413773dbb..5d5ece78516 100644 --- a/chromium/ui/base/accelerators/accelerator_history.h +++ b/chromium/ui/base/accelerators/accelerator_history.h @@ -7,15 +7,15 @@ #include <set> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/ui_base_export.h" namespace ui { // Keeps track of the system-wide current and the most recent previous // key accelerators. -class UI_BASE_EXPORT AcceleratorHistory { +class COMPONENT_EXPORT(UI_BASE) AcceleratorHistory { public: AcceleratorHistory(); ~AcceleratorHistory(); diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h index 9eeec5ce99e..6d7c88604a0 100644 --- a/chromium/ui/base/accelerators/accelerator_manager.h +++ b/chromium/ui/base/accelerators/accelerator_manager.h @@ -10,16 +10,16 @@ #include <utility> #include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/ui_base_export.h" #include "ui/events/event_constants.h" namespace ui { // AcceleratorManger handles processing of accelerators. A delegate may be // supplied which is notified as unique accelerators are added and removed. -class UI_BASE_EXPORT AcceleratorManager { +class COMPONENT_EXPORT(UI_BASE) AcceleratorManager { public: enum HandlerPriority { kNormalPriority, diff --git a/chromium/ui/base/accelerators/global_media_keys_listener_win.h b/chromium/ui/base/accelerators/global_media_keys_listener_win.h index 8de4946c61c..2f20ba52397 100644 --- a/chromium/ui/base/accelerators/global_media_keys_listener_win.h +++ b/chromium/ui/base/accelerators/global_media_keys_listener_win.h @@ -5,10 +5,10 @@ #ifndef UI_BASE_ACCELERATORS_GLOBAL_MEDIA_KEYS_LISTENER_WIN_H_ #define UI_BASE_ACCELERATORS_GLOBAL_MEDIA_KEYS_LISTENER_WIN_H_ +#include "base/component_export.h" #include "base/containers/flat_map.h" #include "base/win/windows_types.h" #include "ui/base/accelerators/media_keys_listener.h" -#include "ui/base/ui_base_export.h" #include "ui/events/keycodes/keyboard_codes.h" namespace gfx { @@ -22,7 +22,8 @@ namespace ui { // Implementation of MediaKeysListener that uses RegisterHotKey to globally // listen for media key presses. It only allows for a single instance to be // created in order to prevent conflicts form multiple listeners. -class UI_BASE_EXPORT GlobalMediaKeysListenerWin : public MediaKeysListener { +class COMPONENT_EXPORT(UI_BASE) GlobalMediaKeysListenerWin + : public MediaKeysListener { public: explicit GlobalMediaKeysListenerWin(MediaKeysListener::Delegate* delegate); ~GlobalMediaKeysListenerWin() override; diff --git a/chromium/ui/base/accelerators/media_keys_listener.h b/chromium/ui/base/accelerators/media_keys_listener.h index 997718d8aff..6787fa39da1 100644 --- a/chromium/ui/base/accelerators/media_keys_listener.h +++ b/chromium/ui/base/accelerators/media_keys_listener.h @@ -8,8 +8,8 @@ #include <memory> #include "base/callback.h" +#include "base/component_export.h" #include "base/observer_list_types.h" -#include "ui/base/ui_base_export.h" #include "ui/events/keycodes/keyboard_codes.h" namespace ui { @@ -17,7 +17,7 @@ namespace ui { class Accelerator; // Create MediaKeyListener to receive accelerators on media keys. -class UI_BASE_EXPORT MediaKeysListener { +class COMPONENT_EXPORT(UI_BASE) MediaKeysListener { public: enum class Scope { kGlobal, // Listener works whenever application in focus or not. @@ -25,7 +25,7 @@ class UI_BASE_EXPORT MediaKeysListener { }; // Media keys accelerators receiver. - class UI_BASE_EXPORT Delegate : public base::CheckedObserver { + class COMPONENT_EXPORT(UI_BASE) Delegate : public base::CheckedObserver { public: ~Delegate() override; diff --git a/chromium/ui/base/accelerators/media_keys_listener_mac.mm b/chromium/ui/base/accelerators/media_keys_listener_mac.mm index 85378bb565d..6052fd13ff3 100644 --- a/chromium/ui/base/accelerators/media_keys_listener_mac.mm +++ b/chromium/ui/base/accelerators/media_keys_listener_mac.mm @@ -11,6 +11,7 @@ #include <IOKit/hidsystem/ev_keymap.h> #include "base/containers/flat_set.h" +#include "base/logging.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/system_media_controls_media_keys_listener.h" diff --git a/chromium/ui/base/accelerators/media_keys_util.h b/chromium/ui/base/accelerators/media_keys_util.h index 95a98d58598..029a9572f7f 100644 --- a/chromium/ui/base/accelerators/media_keys_util.h +++ b/chromium/ui/base/accelerators/media_keys_util.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_ACCELERATORS_MEDIA_KEYS_UTIL_H_ #define UI_BASE_ACCELERATORS_MEDIA_KEYS_UTIL_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -24,12 +24,13 @@ enum class MediaHardwareKeyAction { }; // The name of the histogram that records |MediaHardwareKeyAction|. -UI_BASE_EXPORT extern const char kMediaHardwareKeyActionHistogramName[]; +COMPONENT_EXPORT(UI_BASE) +extern const char kMediaHardwareKeyActionHistogramName[]; // Records a media hardware key action to the // |kMediaHardwareKeyActionHistogramName| histogram. -UI_BASE_EXPORT void RecordMediaHardwareKeyAction( - ui::MediaHardwareKeyAction action); +COMPONENT_EXPORT(UI_BASE) +void RecordMediaHardwareKeyAction(ui::MediaHardwareKeyAction action); } // namespace ui diff --git a/chromium/ui/base/accelerators/menu_label_accelerator_util.h b/chromium/ui/base/accelerators/menu_label_accelerator_util.h index d70b21b6a34..fcdcd206a09 100644 --- a/chromium/ui/base/accelerators/menu_label_accelerator_util.h +++ b/chromium/ui/base/accelerators/menu_label_accelerator_util.h @@ -7,17 +7,17 @@ #include <string> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace ui { -UI_BASE_EXPORT base::char16 GetMnemonic(const base::string16& label); +COMPONENT_EXPORT(UI_BASE) base::char16 GetMnemonic(const base::string16& label); // This function escapes every '&' in label by replacing it with '&&', to avoid // having single ampersands in user-provided strings treated as accelerators. -UI_BASE_EXPORT base::string16 EscapeMenuLabelAmpersands( - const base::string16& label); +COMPONENT_EXPORT(UI_BASE) +base::string16 EscapeMenuLabelAmpersands(const base::string16& label); } // namespace ui diff --git a/chromium/ui/base/accelerators/menu_label_accelerator_util_linux.h b/chromium/ui/base/accelerators/menu_label_accelerator_util_linux.h index 3d1c5d073f5..d799fb5ec28 100644 --- a/chromium/ui/base/accelerators/menu_label_accelerator_util_linux.h +++ b/chromium/ui/base/accelerators/menu_label_accelerator_util_linux.h @@ -7,18 +7,18 @@ #include <string> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Change windows accelerator style to GTK style. (GTK uses _ for // accelerators. Windows uses & with && as an escape for &.) -UI_BASE_EXPORT std::string ConvertAcceleratorsFromWindowsStyle( - const std::string& label); +COMPONENT_EXPORT(UI_BASE) +std::string ConvertAcceleratorsFromWindowsStyle(const std::string& label); // Removes the "&" accelerators from a Windows label. -UI_BASE_EXPORT std::string RemoveWindowsStyleAccelerators( - const std::string& label); +COMPONENT_EXPORT(UI_BASE) +std::string RemoveWindowsStyleAccelerators(const std::string& label); } // namespace ui diff --git a/chromium/ui/base/accelerators/platform_accelerator_cocoa.h b/chromium/ui/base/accelerators/platform_accelerator_cocoa.h index 9feb15fab9a..26e93bd6f08 100644 --- a/chromium/ui/base/accelerators/platform_accelerator_cocoa.h +++ b/chromium/ui/base/accelerators/platform_accelerator_cocoa.h @@ -7,8 +7,8 @@ #import <Foundation/Foundation.h> +#include "base/component_export.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -19,7 +19,8 @@ namespace ui { // accelerators have an associated NSMenuItem. Each NSMenuItem is specified with // a |key_equivalent| and |modifier_mask|. This function takes a ui::Accelerator // and returns the associated |key_equivalent| and |modifier_mask|. -UI_BASE_EXPORT void GetKeyEquivalentAndModifierMaskFromAccelerator( +COMPONENT_EXPORT(UI_BASE) +void GetKeyEquivalentAndModifierMaskFromAccelerator( const ui::Accelerator& accelerator, NSString** key_equivalent, NSUInteger* modifier_mask); diff --git a/chromium/ui/base/accelerators/system_media_controls_media_keys_listener.h b/chromium/ui/base/accelerators/system_media_controls_media_keys_listener.h index 2159509caa6..847669a515e 100644 --- a/chromium/ui/base/accelerators/system_media_controls_media_keys_listener.h +++ b/chromium/ui/base/accelerators/system_media_controls_media_keys_listener.h @@ -5,10 +5,10 @@ #ifndef UI_BASE_ACCELERATORS_SYSTEM_MEDIA_CONTROLS_MEDIA_KEYS_LISTENER_H_ #define UI_BASE_ACCELERATORS_SYSTEM_MEDIA_CONTROLS_MEDIA_KEYS_LISTENER_H_ +#include "base/component_export.h" #include "base/containers/flat_set.h" #include "components/system_media_controls/system_media_controls_observer.h" #include "ui/base/accelerators/media_keys_listener.h" -#include "ui/base/ui_base_export.h" #include "ui/events/keycodes/keyboard_codes.h" namespace system_media_controls { @@ -20,7 +20,7 @@ namespace ui { // Implementation of MediaKeysListener that uses the SystemMediaControls API to // listen for media key presses. It only allows for a single instance to be // created in order to prevent conflicts from multiple listeners. -class UI_BASE_EXPORT SystemMediaControlsMediaKeysListener +class COMPONENT_EXPORT(UI_BASE) SystemMediaControlsMediaKeysListener : public MediaKeysListener, public system_media_controls::SystemMediaControlsObserver { public: diff --git a/chromium/ui/base/base_window.h b/chromium/ui/base/base_window.h index 1719233015b..c4695328177 100644 --- a/chromium/ui/base/base_window.h +++ b/chromium/ui/base/base_window.h @@ -6,6 +6,7 @@ #define UI_BASE_BASE_WINDOW_H_ #include "base/compiler_specific.h" +#include "base/component_export.h" #include "build/build_config.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/native_widget_types.h" @@ -18,7 +19,7 @@ namespace ui { // Provides an interface to perform actions on windows, and query window // state. -class UI_BASE_EXPORT BaseWindow { +class COMPONENT_EXPORT(UI_BASE) BaseWindow { public: // Returns true if the window is currently the active/focused window. virtual bool IsActive() const = 0; diff --git a/chromium/ui/base/class_property.h b/chromium/ui/base/class_property.h index d7fcf47d318..4af52aef43d 100644 --- a/chromium/ui/base/class_property.h +++ b/chromium/ui/base/class_property.h @@ -10,8 +10,8 @@ #include <map> #include <set> +#include "base/component_export.h" #include "base/time/time.h" -#include "ui/base/ui_base_export.h" #include "ui/base/ui_base_types.h" // This header should be included by code that defines ClassProperties. @@ -64,7 +64,7 @@ class PropertyHelper; } -class UI_BASE_EXPORT PropertyHandler { +class COMPONENT_EXPORT(UI_BASE) PropertyHandler { public: PropertyHandler(); PropertyHandler(PropertyHandler&& other); @@ -166,7 +166,7 @@ class ClassPropertyCaster<base::TimeDelta> { namespace subtle { -class UI_BASE_EXPORT PropertyHelper { +class COMPONENT_EXPORT(UI_BASE) PropertyHelper { public: template<typename T> static void Set(::ui::PropertyHandler* handler, diff --git a/chromium/ui/base/clipboard/BUILD.gn b/chromium/ui/base/clipboard/BUILD.gn index 61570cc1f2e..b36512c4c36 100644 --- a/chromium/ui/base/clipboard/BUILD.gn +++ b/chromium/ui/base/clipboard/BUILD.gn @@ -20,29 +20,30 @@ jumbo_component("clipboard_types") { "clipboard_constants.h", ] + if (!is_ios) { + sources += [ "clipboard_format_type.h" ] + } + if (is_android) { sources += [ "clipboard_format_type_android.cc" ] } if (is_mac) { - sources += [ - "clipboard_constants_mac.mm", - "clipboard_format_type_mac.mm", - ] + sources += [ "clipboard_format_type_mac.mm" ] + } + + if (is_mac || is_ios) { + sources += [ "clipboard_constants_mac.mm" ] } if (is_win) { sources += [ "clipboard_format_type_win.cc" ] } - if (!is_ios) { - if (use_aura) { - if ((use_x11 && is_desktop_linux) || !is_win) { - sources += [ "clipboard_format_type_aura.cc" ] - } + if (use_aura) { + if ((use_x11 && is_desktop_linux) || !is_win) { + sources += [ "clipboard_format_type_aura.cc" ] } - - sources += [ "clipboard_format_type.h" ] } defines = [ "IS_UI_BASE_CLIPBOARD_TYPES_IMPL" ] @@ -50,11 +51,11 @@ jumbo_component("clipboard_types") { deps = [ "//base" ] libs = [] + if (is_mac || is_ios) { + libs += [ "Foundation.framework" ] + } if (is_mac) { - libs += [ - "AppKit.framework", - "CoreFoundation.framework", - ] + libs += [ "AppKit.framework" ] } } @@ -64,6 +65,8 @@ jumbo_component("clipboard") { sources = [ "clipboard.cc", "clipboard.h", + "clipboard_metrics.cc", + "clipboard_metrics.h", "clipboard_monitor.cc", "clipboard_monitor.h", "clipboard_observer.h", @@ -112,16 +115,17 @@ jumbo_component("clipboard") { public_deps = [ ":clipboard_types" ] if (use_aura) { - # Aura clipboard. - # Chromecast uses clipboard_aura now. + # Linux clipboard implementations. if (is_desktop_linux && !is_chromecast) { + sources += [ "clipboard_linux.cc" ] if (use_ozone) { sources += [ "clipboard_ozone.cc", "clipboard_ozone.h", ] deps += [ "//ui/base" ] - } else if (use_x11) { + } + if (use_x11) { sources += [ "clipboard_x11.cc", "clipboard_x11.h", @@ -136,20 +140,20 @@ jumbo_component("clipboard") { ] } } else if (is_chromeos && ozone_platform_x11) { - # linux-chromeos uses aura clipboard by default, but supports ozone x11 - # with flag --use-system-clipbboard. + # linux-chromeos uses non-backed clipboard by default, but supports ozone + # x11 with flag --use-system-clipbboard. sources += [ - "clipboard_aura.cc", - "clipboard_aura.h", + "clipboard_non_backed.cc", + "clipboard_non_backed.h", "clipboard_ozone.cc", "clipboard_ozone.h", ] deps += [ "//ui/base" ] } else if (!is_win) { - # This file is used for all non-X11, non-Windows aura Builds. + # This file is used for all builds not backed by an underlying platform. sources += [ - "clipboard_aura.cc", - "clipboard_aura.h", + "clipboard_non_backed.cc", + "clipboard_non_backed.h", ] } } @@ -181,10 +185,10 @@ jumbo_source_set("clipboard_test_support") { "test/test_clipboard.cc", "test/test_clipboard.h", ] + } - if (is_android) { - sources += [ "clipboard_android_test_support.cc" ] - } + if (is_android) { + sources += [ "clipboard_android_test_support.cc" ] } public_deps = [ @@ -206,17 +210,17 @@ source_set("clipboard_test") { sources = [] output_name = "ui_base_clipboard_test" - if (is_mac) { + if (!is_ios) { sources += [ - "clipboard_mac_unittest.mm", - "clipboard_util_mac_unittest.mm", + "custom_data_helper_unittest.cc", + "test/test_clipboard_unittest.cc", ] } - if (!is_ios) { + if (is_mac) { sources += [ - "custom_data_helper_unittest.cc", - "test/test_clipboard_unittest.cc", + "clipboard_mac_unittest.mm", + "clipboard_util_mac_unittest.mm", ] } diff --git a/chromium/ui/base/clipboard/clipboard.cc b/chromium/ui/base/clipboard/clipboard.cc index a91de7c9517..a7722e261c1 100644 --- a/chromium/ui/base/clipboard/clipboard.cc +++ b/chromium/ui/base/clipboard/clipboard.cc @@ -203,4 +203,10 @@ base::Lock& Clipboard::ClipboardMapLock() { return *clipboard_map_lock; } +bool Clipboard::IsMarkedByOriginatorAsConfidential() const { + return false; +} + +void Clipboard::MarkAsConfidential() {} + } // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h index 40f0e4d5e0d..1a69e8420d8 100644 --- a/chromium/ui/base/clipboard/clipboard.h +++ b/chromium/ui/base/clipboard/clipboard.h @@ -110,6 +110,17 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) Clipboard virtual bool IsFormatAvailable(const ClipboardFormatType& format, ClipboardBuffer buffer) const = 0; + // Returns whether the clipboard has data that is marked by its originator as + // confidential. This is available for opt-in checking by the user of this API + // as confidential information, like passwords, might legitimately need to be + // manipulated. + virtual bool IsMarkedByOriginatorAsConfidential() const; + + // Mark the data on the clipboard as being confidential. This isn't + // implemented for all platforms yet, but this call should be made on every + // platform so that when it is implemented on other platforms it is picked up. + virtual void MarkAsConfidential(); + // Clear the clipboard data. virtual void Clear(ClipboardBuffer buffer) = 0; diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc index 501d191e961..917d0d9d135 100644 --- a/chromium/ui/base/clipboard/clipboard_android.cc +++ b/chromium/ui/base/clipboard/clipboard_android.cc @@ -21,10 +21,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" #include "base/task/post_task.h" +#include "base/task/thread_pool.h" #include "base/thread_annotations.h" #include "base/time/time.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/ui_base_jni_headers/Clipboard_jni.h" #include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/image/image.h" @@ -149,9 +151,8 @@ std::string ClipboardMap::Get(const std::string& format) { } void ClipboardMap::GetImage(ReadImageCallback callback) { - base::PostTaskAndReplyWithResult( - FROM_HERE, - {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING}, + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, base::BindOnce(&GetImageData, clipboard_manager_), std::move(callback)); } @@ -432,6 +433,7 @@ void ClipboardAndroid::ReadAsciiText(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kText); *result = g_map.Get().Get(ClipboardFormatType::GetPlainTextType().GetName()); } @@ -443,6 +445,7 @@ void ClipboardAndroid::ReadHTML(ClipboardBuffer buffer, uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kHtml); if (src_url) src_url->clear(); @@ -464,6 +467,7 @@ void ClipboardAndroid::ReadImage(ClipboardBuffer buffer, ReadImageCallback callback) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kImage); g_map.Get().GetImage(std::move(callback)); } @@ -483,6 +487,7 @@ void ClipboardAndroid::ReadBookmark(base::string16* title, void ClipboardAndroid::ReadData(const ClipboardFormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kData); *result = g_map.Get().Get(format.GetName()); } diff --git a/chromium/ui/base/clipboard/clipboard_constants.h b/chromium/ui/base/clipboard/clipboard_constants.h index 52048077f19..f57524d56b6 100644 --- a/chromium/ui/base/clipboard/clipboard_constants.h +++ b/chromium/ui/base/clipboard/clipboard_constants.h @@ -44,13 +44,20 @@ extern const char kMimeTypePepperCustomData[]; // Pickled data. COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern NSString* const kWebCustomDataPboardType; + // Tells us if WebKit was the last to write to the pasteboard. There's no // actual data associated with this type. COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern NSString* const kWebSmartPastePboardType; + // Pepper custom data format type. COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) extern NSString* const kPepperCustomDataPboardType; + +// Data format used to tag the current data as confidential. +COMPONENT_EXPORT(UI_BASE_CLIPBOARD_TYPES) +extern NSString* const kUTTypeConfidentialData; + #endif // defined(OS_MACOSX) #if defined(OS_ANDROID) diff --git a/chromium/ui/base/clipboard/clipboard_constants_mac.mm b/chromium/ui/base/clipboard/clipboard_constants_mac.mm index 4f3029f6200..8633a201234 100644 --- a/chromium/ui/base/clipboard/clipboard_constants_mac.mm +++ b/chromium/ui/base/clipboard/clipboard_constants_mac.mm @@ -14,4 +14,9 @@ NSString* const kWebSmartPastePboardType = @"NeXT smart paste pasteboard type"; NSString* const kPepperCustomDataPboardType = @"org.chromium.pepper-custom-data"; +// It is the common convention on the Mac and on iOS that password managers tag +// confidential data with the flavor "org.nspasteboard.ConcealedType". Obey this +// convention. See http://nspasteboard.org/ for more info. +NSString* const kUTTypeConfidentialData = @"org.nspasteboard.ConcealedType"; + } // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_linux.cc b/chromium/ui/base/clipboard/clipboard_linux.cc new file mode 100644 index 00000000000..ef42052ed5d --- /dev/null +++ b/chromium/ui/base/clipboard/clipboard_linux.cc @@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All 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.h" + +#if defined(USE_OZONE) +#include "ui/base/clipboard/clipboard_ozone.h" +#include "ui/base/ui_base_features.h" +#endif + +#if defined(USE_X11) +#include "ui/base/clipboard/clipboard_x11.h" +#endif + +namespace ui { + +// Clipboard factory method. +Clipboard* Clipboard::Create() { +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) + return new ClipboardOzone(); +#endif + +#if defined(USE_X11) + return new ClipboardX11(); +#else + NOTREACHED(); + return nullptr; +#endif +} + +} // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_mac.h b/chromium/ui/base/clipboard/clipboard_mac.h index 9ebd21cd157..507a7f8c786 100644 --- a/chromium/ui/base/clipboard/clipboard_mac.h +++ b/chromium/ui/base/clipboard/clipboard_mac.h @@ -33,6 +33,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ClipboardMac : public Clipboard { uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override; bool IsFormatAvailable(const ClipboardFormatType& format, ClipboardBuffer buffer) const override; + bool IsMarkedByOriginatorAsConfidential() const override; + void MarkAsConfidential() override; void Clear(ClipboardBuffer buffer) override; void ReadAvailableTypes(ClipboardBuffer buffer, std::vector<base::string16>* types) const override; diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm index 4c8e0e874b0..c396f9effea 100644 --- a/chromium/ui/base/clipboard/clipboard_mac.mm +++ b/chromium/ui/base/clipboard/clipboard_mac.mm @@ -24,6 +24,7 @@ #import "third_party/mozilla/NSPasteboard+Utils.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_util_mac.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/canvas.h" @@ -85,6 +86,27 @@ bool ClipboardMac::IsFormatAvailable(const ClipboardFormatType& format, return [types containsObject:format.ToNSString()]; } +bool ClipboardMac::IsMarkedByOriginatorAsConfidential() const { + DCHECK(CalledOnValidThread()); + + NSPasteboard* pb = GetPasteboard(); + NSPasteboardType type = + [pb availableTypeFromArray:@[ kUTTypeConfidentialData ]]; + + if (type) + return true; + + return false; +} + +void ClipboardMac::MarkAsConfidential() { + DCHECK(CalledOnValidThread()); + + NSPasteboard* pb = GetPasteboard(); + [pb addTypes:@[ kUTTypeConfidentialData ] owner:nil]; + [pb setData:nil forType:kUTTypeConfidentialData]; +} + void ClipboardMac::Clear(ClipboardBuffer buffer) { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); @@ -138,6 +160,7 @@ void ClipboardMac::ReadText(ClipboardBuffer buffer, base::string16* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kText); NSPasteboard* pb = GetPasteboard(); NSString* contents = [pb stringForType:NSPasteboardTypeString]; @@ -148,6 +171,7 @@ void ClipboardMac::ReadAsciiText(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kText); NSPasteboard* pb = GetPasteboard(); NSString* contents = [pb stringForType:NSPasteboardTypeString]; @@ -164,6 +188,7 @@ void ClipboardMac::ReadHTML(ClipboardBuffer buffer, uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kHtml); // TODO(avi): src_url? markup->clear(); @@ -191,12 +216,14 @@ void ClipboardMac::ReadHTML(ClipboardBuffer buffer, void ClipboardMac::ReadRTF(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kRtf); return ReadData(ClipboardFormatType::GetRtfType(), result); } void ClipboardMac::ReadImage(ClipboardBuffer buffer, ReadImageCallback callback) const { + RecordRead(ClipboardFormatMetric::kImage); std::move(callback).Run(ReadImageInternal(buffer, GetPasteboard())); } @@ -205,6 +232,7 @@ void ClipboardMac::ReadCustomData(ClipboardBuffer buffer, base::string16* result) const { DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kCustomData); NSPasteboard* pb = GetPasteboard(); if ([[pb types] containsObject:kWebCustomDataPboardType]) { @@ -216,6 +244,7 @@ void ClipboardMac::ReadCustomData(ClipboardBuffer buffer, void ClipboardMac::ReadBookmark(base::string16* title, std::string* url) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kBookmark); NSPasteboard* pb = GetPasteboard(); if (title) { @@ -235,6 +264,7 @@ void ClipboardMac::ReadBookmark(base::string16* title, std::string* url) const { void ClipboardMac::ReadData(const ClipboardFormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kData); NSPasteboard* pb = GetPasteboard(); NSData* data = [pb dataForType:format.ToNSString()]; if ([data length]) diff --git a/chromium/ui/base/clipboard/clipboard_metrics.cc b/chromium/ui/base/clipboard/clipboard_metrics.cc new file mode 100644 index 00000000000..dc52ad67926 --- /dev/null +++ b/chromium/ui/base/clipboard/clipboard_metrics.cc @@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All 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_metrics.h" + +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" + +namespace ui { + +void RecordRead(ClipboardFormatMetric metric) { + base::UmaHistogramEnumeration("Clipboard.Read", metric); +} + +void RecordWrite(ClipboardFormatMetric metric) { + base::UmaHistogramEnumeration("Clipboard.Write", metric); +} + +} // namespace ui diff --git a/chromium/ui/base/clipboard/clipboard_metrics.h b/chromium/ui/base/clipboard/clipboard_metrics.h new file mode 100644 index 00000000000..5077043bafe --- /dev/null +++ b/chromium/ui/base/clipboard/clipboard_metrics.h @@ -0,0 +1,30 @@ +// Copyright 2020 The Chromium Authors. All 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_METRICS_H_ +#define UI_BASE_CLIPBOARD_CLIPBOARD_METRICS_H_ + +namespace ui { + +// Used to log formats read/written from/to the platform clipboard. +// +// This enum's values are persisted to logs. Do not reuse or renumber values. +enum class ClipboardFormatMetric { + kText = 0, // On applicable platforms, includes both UNICODE and ANSI text. + kHtml = 1, + kRtf = 2, + kImage = 3, + kBookmark = 4, + kData = 5, + kCustomData = 6, + kWebSmartPaste = 7, // Only used on write. + kMaxValue = kWebSmartPaste, +}; + +void RecordRead(ClipboardFormatMetric metric); +void RecordWrite(ClipboardFormatMetric metric); + +} // namespace ui + +#endif // UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_ diff --git a/chromium/ui/base/clipboard/clipboard_aura.cc b/chromium/ui/base/clipboard/clipboard_non_backed.cc index 9f4ae70a5ed..2b827891f6d 100644 --- a/chromium/ui/base/clipboard/clipboard_aura.cc +++ b/chromium/ui/base/clipboard/clipboard_non_backed.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/clipboard/clipboard_aura.h" +#include "ui/base/clipboard/clipboard_non_backed.h" #include <stdint.h> @@ -22,6 +22,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/clipboard_format_type.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_monitor.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/geometry/size.h" @@ -33,8 +34,8 @@ namespace { const size_t kMaxClipboardSize = 1; -// Clipboard data format used by AuraClipboard. -enum class AuraClipboardFormat { +// Clipboard data format used by ClipboardInternal. +enum class ClipboardInternalFormat { kText = 1 << 0, kHtml = 1 << 1, kRtf = 1 << 2, @@ -48,49 +49,47 @@ enum class AuraClipboardFormat { // It mostly just provides APIs to cleanly access and manipulate this data. class ClipboardData { public: - ClipboardData() - : web_smart_paste_(false), - format_(0) {} + ClipboardData() : web_smart_paste_(false), format_(0) {} virtual ~ClipboardData() = default; - // Bitmask of AuraClipboardFormat types. + // Bitmask of ClipboardInternalFormat types. int format() const { return format_; } const std::string& text() const { return text_; } void set_text(const std::string& text) { text_ = text; - format_ |= static_cast<int>(AuraClipboardFormat::kText); + format_ |= static_cast<int>(ClipboardInternalFormat::kText); } const std::string& markup_data() const { return markup_data_; } void set_markup_data(const std::string& markup_data) { markup_data_ = markup_data; - format_ |= static_cast<int>(AuraClipboardFormat::kHtml); + format_ |= static_cast<int>(ClipboardInternalFormat::kHtml); } const std::string& rtf_data() const { return rtf_data_; } void SetRTFData(const std::string& rtf_data) { rtf_data_ = rtf_data; - format_ |= static_cast<int>(AuraClipboardFormat::kRtf); + format_ |= static_cast<int>(ClipboardInternalFormat::kRtf); } const std::string& url() const { return url_; } void set_url(const std::string& url) { url_ = url; - format_ |= static_cast<int>(AuraClipboardFormat::kHtml); + format_ |= static_cast<int>(ClipboardInternalFormat::kHtml); } const std::string& bookmark_title() const { return bookmark_title_; } void set_bookmark_title(const std::string& bookmark_title) { bookmark_title_ = bookmark_title; - format_ |= static_cast<int>(AuraClipboardFormat::kBookmark); + format_ |= static_cast<int>(ClipboardInternalFormat::kBookmark); } const std::string& bookmark_url() const { return bookmark_url_; } void set_bookmark_url(const std::string& bookmark_url) { bookmark_url_ = bookmark_url; - format_ |= static_cast<int>(AuraClipboardFormat::kBookmark); + format_ |= static_cast<int>(ClipboardInternalFormat::kBookmark); } const SkBitmap& bitmap() const { return bitmap_; } @@ -99,7 +98,7 @@ class ClipboardData { NOTREACHED() << "Unable to convert bitmap for clipboard"; return; } - format_ |= static_cast<int>(AuraClipboardFormat::kBitmap); + format_ |= static_cast<int>(ClipboardInternalFormat::kBitmap); } const std::string& custom_data_format() const { return custom_data_format_; } @@ -113,13 +112,13 @@ class ClipboardData { } custom_data_data_ = data_data; custom_data_format_ = data_format; - format_ |= static_cast<int>(AuraClipboardFormat::kCustom); + format_ |= static_cast<int>(ClipboardInternalFormat::kCustom); } bool web_smart_paste() const { return web_smart_paste_; } void set_web_smart_paste(bool web_smart_paste) { web_smart_paste_ = web_smart_paste; - format_ |= static_cast<int>(AuraClipboardFormat::kWeb); + format_ |= static_cast<int>(ClipboardInternalFormat::kWeb); } private: @@ -157,16 +156,13 @@ class ClipboardData { } // namespace -// Platform clipboard implementation for Aura. This handles things like format -// conversion, versioning of clipboard items etc. The goal is to roughly provide -// a substitute to platform clipboards on other platforms such as GtkClipboard -// on gtk or winapi clipboard on win. -class AuraClipboard { +// Simple, internal implementation of a clipboard, handling things like format +// conversion, versioning, etc. +class ClipboardInternal { public: - AuraClipboard() : sequence_number_(0) { - } + ClipboardInternal() : sequence_number_(0) {} - ~AuraClipboard() = default; + ~ClipboardInternal() = default; void Clear() { sequence_number_++; @@ -174,9 +170,7 @@ class AuraClipboard { ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged(); } - uint64_t sequence_number() const { - return sequence_number_; - } + uint64_t sequence_number() const { return sequence_number_; } // Returns the data currently on the top of the clipboard stack, nullptr if // the clipboard stack is empty. @@ -188,11 +182,11 @@ class AuraClipboard { // Returns true if the data on top of the clipboard stack has format |format| // or another format that can be converted to |format|. - bool IsFormatAvailable(AuraClipboardFormat format) const { + bool IsFormatAvailable(ClipboardInternalFormat format) const { switch (format) { - case AuraClipboardFormat::kText: - return HasFormat(AuraClipboardFormat::kText) || - HasFormat(AuraClipboardFormat::kBookmark); + case ClipboardInternalFormat::kText: + return HasFormat(ClipboardInternalFormat::kText) || + HasFormat(ClipboardInternalFormat::kBookmark); default: return HasFormat(format); } @@ -211,11 +205,11 @@ class AuraClipboard { const ClipboardData* data = GetData(); if (!data) return; - if (HasFormat(AuraClipboardFormat::kText)) + if (HasFormat(ClipboardInternalFormat::kText)) *result = data->text(); - else if (HasFormat(AuraClipboardFormat::kHtml)) + else if (HasFormat(ClipboardInternalFormat::kHtml)) *result = data->markup_data(); - else if (HasFormat(AuraClipboardFormat::kBookmark)) + else if (HasFormat(ClipboardInternalFormat::kBookmark)) *result = data->bookmark_url(); } @@ -230,7 +224,7 @@ class AuraClipboard { *fragment_start = 0; *fragment_end = 0; - if (!HasFormat(AuraClipboardFormat::kHtml)) + if (!HasFormat(ClipboardInternalFormat::kHtml)) return; const ClipboardData* data = GetData(); @@ -246,7 +240,7 @@ class AuraClipboard { void ReadRTF(std::string* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(AuraClipboardFormat::kRtf)) + if (!HasFormat(ClipboardInternalFormat::kRtf)) return; *result = data->rtf_data(); @@ -255,7 +249,7 @@ class AuraClipboard { // Reads image from the data at the top of clipboard stack. SkBitmap ReadImage() const { SkBitmap img; - if (!HasFormat(AuraClipboardFormat::kBitmap)) + if (!HasFormat(ClipboardInternalFormat::kBitmap)) return img; // A shallow copy should be fine here, but just to be safe... @@ -272,7 +266,7 @@ class AuraClipboard { base::string16* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(AuraClipboardFormat::kCustom)) + if (!HasFormat(ClipboardInternalFormat::kCustom)) return; ReadCustomDataForType(data->custom_data_data().c_str(), @@ -285,7 +279,7 @@ class AuraClipboard { title->clear(); if (url) url->clear(); - if (!HasFormat(AuraClipboardFormat::kBookmark)) + if (!HasFormat(ClipboardInternalFormat::kBookmark)) return; const ClipboardData* data = GetData(); @@ -298,7 +292,7 @@ class AuraClipboard { void ReadData(const std::string& type, std::string* result) const { result->clear(); const ClipboardData* data = GetData(); - if (!HasFormat(AuraClipboardFormat::kCustom) || + if (!HasFormat(ClipboardInternalFormat::kCustom) || type != data->custom_data_format()) return; @@ -314,7 +308,7 @@ class AuraClipboard { private: // True if the data on top of the clipboard stack has format |format|. - bool HasFormat(AuraClipboardFormat format) const { + bool HasFormat(ClipboardInternalFormat format) const { const ClipboardData* data = GetData(); return data ? data->format() & static_cast<int>(format) : false; } @@ -337,13 +331,13 @@ class AuraClipboard { // Sequence number uniquely identifying clipboard state. uint64_t sequence_number_; - DISALLOW_COPY_AND_ASSIGN(AuraClipboard); + DISALLOW_COPY_AND_ASSIGN(ClipboardInternal); }; // Helper class to build a ClipboardData object and write it to clipboard. class ClipboardDataBuilder { public: - static void CommitToClipboard(AuraClipboard* clipboard) { + static void CommitToClipboard(ClipboardInternal* clipboard) { clipboard->WriteData(TakeCurrentData()); } @@ -411,58 +405,63 @@ class ClipboardDataBuilder { ClipboardData* ClipboardDataBuilder::current_data_ = nullptr; -// linux-chromeos uses aura clipboard by default, but supports ozone x11 +// linux-chromeos uses non-backed clipboard by default, but supports ozone x11 // with flag --use-system-clipbboard. #if !defined(OS_CHROMEOS) || !BUILDFLAG(OZONE_PLATFORM_X11) // Clipboard factory method. Clipboard* Clipboard::Create() { - return new ClipboardAura; + return new ClipboardNonBacked; } #endif -// ClipboardAura implementation. -ClipboardAura::ClipboardAura() - : clipboard_internal_(std::make_unique<AuraClipboard>()) { +// ClipboardNonBacked implementation. +ClipboardNonBacked::ClipboardNonBacked() + : clipboard_internal_(std::make_unique<ClipboardInternal>()) { DCHECK(CalledOnValidThread()); } -ClipboardAura::~ClipboardAura() { +ClipboardNonBacked::~ClipboardNonBacked() { DCHECK(CalledOnValidThread()); } -void ClipboardAura::OnPreShutdown() {} +void ClipboardNonBacked::OnPreShutdown() {} -uint64_t ClipboardAura::GetSequenceNumber(ClipboardBuffer buffer) const { +uint64_t ClipboardNonBacked::GetSequenceNumber(ClipboardBuffer buffer) const { DCHECK(CalledOnValidThread()); return clipboard_internal_->sequence_number(); } -bool ClipboardAura::IsFormatAvailable(const ClipboardFormatType& format, - ClipboardBuffer buffer) const { +bool ClipboardNonBacked::IsFormatAvailable(const ClipboardFormatType& format, + ClipboardBuffer buffer) const { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); if (ClipboardFormatType::GetPlainTextType().Equals(format) || ClipboardFormatType::GetUrlType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kText); + return clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kText); if (ClipboardFormatType::GetHtmlType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kHtml); + return clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kHtml); if (ClipboardFormatType::GetRtfType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kRtf); + return clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kRtf); if (ClipboardFormatType::GetBitmapType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kBitmap); + return clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kBitmap); if (ClipboardFormatType::GetWebKitSmartPasteType().Equals(format)) - return clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kWeb); + return clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kWeb); const ClipboardData* data = clipboard_internal_->GetData(); return data && data->custom_data_format() == format.GetName(); } -void ClipboardAura::Clear(ClipboardBuffer buffer) { +void ClipboardNonBacked::Clear(ClipboardBuffer buffer) { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); clipboard_internal_->Clear(); } -void ClipboardAura::ReadAvailableTypes( +void ClipboardNonBacked::ReadAvailableTypes( ClipboardBuffer buffer, std::vector<base::string16>* types) const { DCHECK(CalledOnValidThread()); @@ -481,7 +480,8 @@ void ClipboardAura::ReadAvailableTypes( if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer)) types->push_back(base::UTF8ToUTF16(kMimeTypePNG)); - if (clipboard_internal_->IsFormatAvailable(AuraClipboardFormat::kCustom) && + if (clipboard_internal_->IsFormatAvailable( + ClipboardInternalFormat::kCustom) && clipboard_internal_->GetData()) { ReadCustomDataTypes( clipboard_internal_->GetData()->custom_data_data().c_str(), @@ -490,7 +490,7 @@ void ClipboardAura::ReadAvailableTypes( } std::vector<base::string16> -ClipboardAura::ReadAvailablePlatformSpecificFormatNames( +ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames( ClipboardBuffer buffer) const { DCHECK(CalledOnValidThread()); @@ -516,59 +516,69 @@ ClipboardAura::ReadAvailablePlatformSpecificFormatNames( return types; } -void ClipboardAura::ReadText(ClipboardBuffer buffer, - base::string16* result) const { +void ClipboardNonBacked::ReadText(ClipboardBuffer buffer, + base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); clipboard_internal_->ReadText(result); } -void ClipboardAura::ReadAsciiText(ClipboardBuffer buffer, - std::string* result) const { +void ClipboardNonBacked::ReadAsciiText(ClipboardBuffer buffer, + std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); clipboard_internal_->ReadAsciiText(result); } -void ClipboardAura::ReadHTML(ClipboardBuffer buffer, - base::string16* markup, - std::string* src_url, - uint32_t* fragment_start, - uint32_t* fragment_end) const { +void ClipboardNonBacked::ReadHTML(ClipboardBuffer buffer, + base::string16* markup, + std::string* src_url, + uint32_t* fragment_start, + uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kHtml); clipboard_internal_->ReadHTML(markup, src_url, fragment_start, fragment_end); } -void ClipboardAura::ReadRTF(ClipboardBuffer buffer, std::string* result) const { +void ClipboardNonBacked::ReadRTF(ClipboardBuffer buffer, + std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kRtf); clipboard_internal_->ReadRTF(result); } -void ClipboardAura::ReadImage(ClipboardBuffer buffer, - ReadImageCallback callback) const { +void ClipboardNonBacked::ReadImage(ClipboardBuffer buffer, + ReadImageCallback callback) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kImage); std::move(callback).Run(clipboard_internal_->ReadImage()); } -void ClipboardAura::ReadCustomData(ClipboardBuffer buffer, - const base::string16& type, - base::string16* result) const { +void ClipboardNonBacked::ReadCustomData(ClipboardBuffer buffer, + const base::string16& type, + base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kCustomData); clipboard_internal_->ReadCustomData(type, result); } -void ClipboardAura::ReadBookmark(base::string16* title, - std::string* url) const { +void ClipboardNonBacked::ReadBookmark(base::string16* title, + std::string* url) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kBookmark); clipboard_internal_->ReadBookmark(title, url); } -void ClipboardAura::ReadData(const ClipboardFormatType& format, - std::string* result) const { +void ClipboardNonBacked::ReadData(const ClipboardFormatType& format, + std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kData); clipboard_internal_->ReadData(format.GetName(), result); } -void ClipboardAura::WritePortableRepresentations(ClipboardBuffer buffer, - const ObjectMap& objects) { +void ClipboardNonBacked::WritePortableRepresentations( + ClipboardBuffer buffer, + const ObjectMap& objects) { DCHECK(CalledOnValidThread()); DCHECK(IsSupportedClipboardBuffer(buffer)); for (const auto& object : objects) @@ -576,7 +586,7 @@ void ClipboardAura::WritePortableRepresentations(ClipboardBuffer buffer, ClipboardDataBuilder::CommitToClipboard(clipboard_internal_.get()); } -void ClipboardAura::WritePlatformRepresentations( +void ClipboardNonBacked::WritePlatformRepresentations( ClipboardBuffer buffer, std::vector<Clipboard::PlatformRepresentation> platform_representations) { DCHECK(CalledOnValidThread()); @@ -587,39 +597,39 @@ void ClipboardAura::WritePlatformRepresentations( ClipboardDataBuilder::CommitToClipboard(clipboard_internal_.get()); } -void ClipboardAura::WriteText(const char* text_data, size_t text_len) { +void ClipboardNonBacked::WriteText(const char* text_data, size_t text_len) { ClipboardDataBuilder::WriteText(text_data, text_len); } -void ClipboardAura::WriteHTML(const char* markup_data, - size_t markup_len, - const char* url_data, - size_t url_len) { +void ClipboardNonBacked::WriteHTML(const char* markup_data, + size_t markup_len, + const char* url_data, + size_t url_len) { ClipboardDataBuilder::WriteHTML(markup_data, markup_len, url_data, url_len); } -void ClipboardAura::WriteRTF(const char* rtf_data, size_t data_len) { +void ClipboardNonBacked::WriteRTF(const char* rtf_data, size_t data_len) { ClipboardDataBuilder::WriteRTF(rtf_data, data_len); } -void ClipboardAura::WriteBookmark(const char* title_data, - size_t title_len, - const char* url_data, - size_t url_len) { +void ClipboardNonBacked::WriteBookmark(const char* title_data, + size_t title_len, + const char* url_data, + size_t url_len) { ClipboardDataBuilder::WriteBookmark(title_data, title_len, url_data, url_len); } -void ClipboardAura::WriteWebSmartPaste() { +void ClipboardNonBacked::WriteWebSmartPaste() { ClipboardDataBuilder::WriteWebSmartPaste(); } -void ClipboardAura::WriteBitmap(const SkBitmap& bitmap) { +void ClipboardNonBacked::WriteBitmap(const SkBitmap& bitmap) { ClipboardDataBuilder::WriteBitmap(bitmap); } -void ClipboardAura::WriteData(const ClipboardFormatType& format, - const char* data_data, - size_t data_len) { +void ClipboardNonBacked::WriteData(const ClipboardFormatType& format, + const char* data_data, + size_t data_len) { ClipboardDataBuilder::WriteData(format.GetName(), data_data, data_len); } diff --git a/chromium/ui/base/clipboard/clipboard_aura.h b/chromium/ui/base/clipboard/clipboard_non_backed.h index 6a6862ba688..8f57aca1e25 100644 --- a/chromium/ui/base/clipboard/clipboard_aura.h +++ b/chromium/ui/base/clipboard/clipboard_non_backed.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_CLIPBOARD_CLIPBOARD_AURA_H_ -#define UI_BASE_CLIPBOARD_CLIPBOARD_AURA_H_ +#ifndef UI_BASE_CLIPBOARD_CLIPBOARD_NON_BACKED_H_ +#define UI_BASE_CLIPBOARD_CLIPBOARD_NON_BACKED_H_ #include <stddef.h> #include <stdint.h> @@ -13,13 +13,19 @@ namespace ui { -class AuraClipboard; +class ClipboardInternal; -class ClipboardAura : public Clipboard { +// In-memory clipboard implementation not backed by an underlying platform. +// This clipboard can be used where there's no need to sync the clipboard with +// an underlying platform, and can substitute platform clipboards like +// ClipboardWin on Windows or ClipboardMac on MacOS. As this isn't backed by an +// underlying platform, the clipboard data isn't persisted after an instance +// goes away. +class ClipboardNonBacked : public Clipboard { private: friend class Clipboard; - ClipboardAura(); - ~ClipboardAura() override; + ClipboardNonBacked(); + ~ClipboardNonBacked() override; // Clipboard overrides: void OnPreShutdown() override; @@ -70,11 +76,11 @@ class ClipboardAura : public Clipboard { const char* data_data, size_t data_len) override; - const std::unique_ptr<AuraClipboard> clipboard_internal_; + const std::unique_ptr<ClipboardInternal> clipboard_internal_; - DISALLOW_COPY_AND_ASSIGN(ClipboardAura); + DISALLOW_COPY_AND_ASSIGN(ClipboardNonBacked); }; } // namespace ui -#endif // UI_BASE_CLIPBOARD_CLIPBOARD_AURA_H_ +#endif // UI_BASE_CLIPBOARD_CLIPBOARD_NON_BACKED_H_ diff --git a/chromium/ui/base/clipboard/clipboard_ozone.cc b/chromium/ui/base/clipboard/clipboard_ozone.cc index bb5b7ad7182..a41bc2f5798 100644 --- a/chromium/ui/base/clipboard/clipboard_ozone.cc +++ b/chromium/ui/base/clipboard/clipboard_ozone.cc @@ -15,9 +15,11 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_monitor.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/codec/png_codec.h" @@ -27,7 +29,7 @@ #if defined(OS_CHROMEOS) && BUILDFLAG(OZONE_PLATFORM_X11) #include "base/command_line.h" -#include "ui/base/clipboard/clipboard_aura.h" +#include "ui/base/clipboard/clipboard_non_backed.h" #include "ui/base/ui_base_switches.h" #endif @@ -294,18 +296,21 @@ class ClipboardOzone::AsyncClipboardOzone { DISALLOW_COPY_AND_ASSIGN(AsyncClipboardOzone); }; +// Uses the factory in the clipboard_linux otherwise. +#if defined(OS_CHROMEOS) || !defined(OS_LINUX) // Clipboard factory method. Clipboard* Clipboard::Create() { -// linux-chromeos uses aura clipboard by default, but supports ozone x11 +// linux-chromeos uses non-backed clipboard by default, but supports ozone x11 // with flag --use-system-clipbboard. #if defined(OS_CHROMEOS) && BUILDFLAG(OZONE_PLATFORM_X11) if (!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseSystemClipboard)) { - return new ClipboardAura; + return new ClipboardNonBacked; } #endif return new ClipboardOzone; } +#endif // ClipboardOzone implementation. ClipboardOzone::ClipboardOzone() { @@ -383,6 +388,7 @@ ClipboardOzone::ReadAvailablePlatformSpecificFormatNames( void ClipboardOzone::ReadText(ClipboardBuffer buffer, base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); auto clipboard_data = async_clipboard_ozone_->ReadClipboardDataAndWait(buffer, kMimeTypeText); @@ -393,6 +399,7 @@ void ClipboardOzone::ReadText(ClipboardBuffer buffer, void ClipboardOzone::ReadAsciiText(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); auto clipboard_data = async_clipboard_ozone_->ReadClipboardDataAndWait(buffer, kMimeTypeText); @@ -405,6 +412,7 @@ void ClipboardOzone::ReadHTML(ClipboardBuffer buffer, uint32_t* fragment_start, uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kHtml); markup->clear(); if (src_url) @@ -423,6 +431,7 @@ void ClipboardOzone::ReadHTML(ClipboardBuffer buffer, void ClipboardOzone::ReadRTF(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kRtf); auto clipboard_data = async_clipboard_ozone_->ReadClipboardDataAndWait(buffer, kMimeTypeRTF); @@ -431,6 +440,7 @@ void ClipboardOzone::ReadRTF(ClipboardBuffer buffer, void ClipboardOzone::ReadImage(ClipboardBuffer buffer, ReadImageCallback callback) const { + RecordRead(ClipboardFormatMetric::kImage); std::move(callback).Run(ReadImageInternal(buffer)); } @@ -438,6 +448,7 @@ void ClipboardOzone::ReadCustomData(ClipboardBuffer buffer, const base::string16& type, base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kCustomData); auto custom_data = async_clipboard_ozone_->ReadClipboardDataAndWait( buffer, kMimeTypeWebCustomData); @@ -454,6 +465,7 @@ void ClipboardOzone::ReadBookmark(base::string16* title, void ClipboardOzone::ReadData(const ClipboardFormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kData); auto clipboard_data = async_clipboard_ozone_->ReadClipboardDataAndWait( ClipboardBuffer::kCopyPaste, format.GetName()); @@ -469,8 +481,8 @@ void ClipboardOzone::WritePortableRepresentations(ClipboardBuffer buffer, async_clipboard_ozone_->OfferData(buffer); - // Just like Aura/X11 implementation does, copy text data from the copy/paste - // selection to the primary selection. + // Just like Non-Backed/X11 implementation does, copy text data from the + // copy/paste selection to the primary selection. if (buffer == ClipboardBuffer::kCopyPaste) { auto text_iter = objects.find(PortableFormat::kText); if (text_iter != objects.end()) { diff --git a/chromium/ui/base/clipboard/clipboard_test_template.h b/chromium/ui/base/clipboard/clipboard_test_template.h index f31c2594b7d..279252ce350 100644 --- a/chromium/ui/base/clipboard/clipboard_test_template.h +++ b/chromium/ui/base/clipboard/clipboard_test_template.h @@ -46,6 +46,7 @@ #endif #if defined(USE_X11) +#include "ui/base/ui_base_features.h" #include "ui/events/platform/platform_event_source.h" #endif @@ -67,7 +68,8 @@ class ClipboardTest : public PlatformTest { void SetUp() override { PlatformTest::SetUp(); #if defined(USE_X11) - event_source_ = ClipboardTraits::GetEventSource(); + if (!features::IsUsingOzonePlatform()) + event_source_ = ClipboardTraits::GetEventSource(); #endif clipboard_ = ClipboardTraits::Create(); } @@ -653,8 +655,8 @@ TYPED_TEST(ClipboardTest, DataTest) { } // TODO(https://crbug.com/1032161): Implement multiple raw types for -// AuraClipboard. This test currently doesn't run on AuraClipboard because -// AuraClipboard only supports one raw type. +// ClipboardInternal. This test currently doesn't run on ClipboardInternal +// because ClipboardInternal only supports one raw type. #if (!defined(USE_AURA) || defined(OS_WIN) || defined(USE_OZONE) || \ defined(USE_X11)) && \ !defined(OS_CHROMEOS) @@ -739,17 +741,38 @@ TYPED_TEST(ClipboardTest, ReadAvailablePlatformSpecificFormatNamesTest) { #endif } -// Test that a platform-specific write works. +// Test that platform-specific functionality works, with a predefined format in +// On X11 Linux, this test uses a simple MIME type, text/plain. +// On Windows, this test uses a pre-defined ANSI format, CF_TEXT, and tests that +// the Windows implicitly converts this to UNICODE as expected. +#if defined(OS_WIN) || defined(USE_X11) +TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) { + // We're testing platform-specific behavior, so use PlatformClipboardTest. + // TODO(https://crbug.com/1083050): The template shouldn't know about its + // instantiations. Move this information up using a flag, virtual method, or + // creating separate test files for different platforms. + std::string test_suite_name = ::testing::UnitTest::GetInstance() + ->current_test_info() + ->test_suite_name(); + if (test_suite_name != std::string("ClipboardTest/PlatformClipboardTest")) + return; + + const std::string text = "test string"; #if defined(OS_WIN) -TYPED_TEST(ClipboardTest, WindowsPredefinedFormatWriteDataTest) { + // Windows pre-defined ANSI text format. const std::string kFormatString = "CF_TEXT"; - const std::string text = "test string"; + // Windows requires an extra '\0' at the end for a raw write. + const std::string kPlatformSpecificText = text + '\0'; +#elif defined(USE_X11) + const std::string kFormatString = "text/plain"; // X11 text format + const std::string kPlatformSpecificText = text; +#endif base::span<const uint8_t> text_span( - reinterpret_cast<const uint8_t*>(text.data()), text.size() + 1); - + reinterpret_cast<const uint8_t*>(kPlatformSpecificText.data()), + kPlatformSpecificText.size()); { ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste); - clipboard_writer.WriteData(UTF8ToUTF16(kFormatString), + clipboard_writer.WriteData(ASCIIToUTF16(kFormatString), mojo_base::BigBuffer(text_span)); } @@ -758,27 +781,32 @@ TYPED_TEST(ClipboardTest, WindowsPredefinedFormatWriteDataTest) { ClipboardBuffer::kCopyPaste); EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kFormatString))); + +#if defined(OS_WIN) + // Only Windows ClipboardFormatType recognizes ANSI formats. EXPECT_TRUE(this->clipboard().IsFormatAvailable( ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste)); +#endif // defined(OS_WIN) - // Only ClipboardWin recognizes the Windows-specific CF_TEXT. - std::string test_suite_name = ::testing::UnitTest::GetInstance() - ->current_test_info() - ->test_suite_name(); - if (test_suite_name == std::string("ClipboardTest/PlatformClipboardTest")) { - std::string text_result; - this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &text_result); - EXPECT_EQ(text, text_result); - - // Windows will automatically convert CF_TEXT to its UNICODE version. - EXPECT_TRUE(this->clipboard().IsFormatAvailable( - ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste)); - base::string16 text_result16; - this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result16); - EXPECT_EQ(base::ASCIIToUTF16(text), text_result16); - } + EXPECT_TRUE(this->clipboard().IsFormatAvailable( + ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste)); + + std::string text_result; + this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &text_result); + EXPECT_EQ(text_result, text); + // Note: Windows will automatically convert CF_TEXT to its UNICODE version. + EXPECT_TRUE(this->clipboard().IsFormatAvailable( + ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste)); + base::string16 text_result16; + this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result16); + EXPECT_EQ(text_result16, base::ASCIIToUTF16(text)); + + std::string platform_specific_result; + this->clipboard().ReadData(ClipboardFormatType::GetType(kFormatString), + &platform_specific_result); + EXPECT_EQ(platform_specific_result, kPlatformSpecificText); } -#endif +#endif // defined(OS_WIN) || defined(USE_X11) #if !defined(OS_MACOSX) && !defined(OS_ANDROID) TYPED_TEST(ClipboardTest, HyperlinkTest) { diff --git a/chromium/ui/base/clipboard/clipboard_util_mac.mm b/chromium/ui/base/clipboard/clipboard_util_mac.mm index a748d4af65a..8db45d20a2a 100644 --- a/chromium/ui/base/clipboard/clipboard_util_mac.mm +++ b/chromium/ui/base/clipboard/clipboard_util_mac.mm @@ -7,6 +7,7 @@ #include "base/mac/foundation_util.h" #import "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" +#include "base/notreached.h" namespace ui { diff --git a/chromium/ui/base/clipboard/clipboard_win.cc b/chromium/ui/base/clipboard/clipboard_win.cc index 9bfabd34eab..421f22eaaf6 100644 --- a/chromium/ui/base/clipboard/clipboard_win.cc +++ b/chromium/ui/base/clipboard/clipboard_win.cc @@ -30,6 +30,7 @@ #include "skia/ext/skia_utils_win.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_util_win.h" #include "ui/base/clipboard/custom_data_helper.h" #include "ui/gfx/canvas.h" @@ -319,6 +320,7 @@ ClipboardWin::ReadAvailablePlatformSpecificFormatNames( void ClipboardWin::ReadText(ClipboardBuffer buffer, base::string16* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kText); if (!result) { NOTREACHED(); return; @@ -344,6 +346,7 @@ void ClipboardWin::ReadText(ClipboardBuffer buffer, void ClipboardWin::ReadAsciiText(ClipboardBuffer buffer, std::string* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kText); if (!result) { NOTREACHED(); return; @@ -372,6 +375,7 @@ void ClipboardWin::ReadHTML(ClipboardBuffer buffer, uint32_t* fragment_start, uint32_t* fragment_end) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kHtml); markup->clear(); // TODO(dcheng): Remove these checks, I don't think they should be optional. @@ -425,6 +429,7 @@ void ClipboardWin::ReadHTML(ClipboardBuffer buffer, void ClipboardWin::ReadRTF(ClipboardBuffer buffer, std::string* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kRtf); ReadData(ClipboardFormatType::GetRtfType(), result); TrimAfterNull(result); @@ -432,6 +437,7 @@ void ClipboardWin::ReadRTF(ClipboardBuffer buffer, std::string* result) const { void ClipboardWin::ReadImage(ClipboardBuffer buffer, ReadImageCallback callback) const { + RecordRead(ClipboardFormatMetric::kImage); std::move(callback).Run(ReadImageInternal(buffer)); } @@ -439,6 +445,7 @@ void ClipboardWin::ReadCustomData(ClipboardBuffer buffer, const base::string16& type, base::string16* result) const { DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); + RecordRead(ClipboardFormatMetric::kCustomData); // Acquire the clipboard. ScopedClipboard clipboard; @@ -455,6 +462,7 @@ void ClipboardWin::ReadCustomData(ClipboardBuffer buffer, } void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const { + RecordRead(ClipboardFormatMetric::kBookmark); if (title) title->clear(); @@ -481,6 +489,7 @@ void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const { void ClipboardWin::ReadData(const ClipboardFormatType& format, std::string* result) const { + RecordRead(ClipboardFormatMetric::kData); if (!result) { NOTREACHED(); return; diff --git a/chromium/ui/base/clipboard/clipboard_x11.cc b/chromium/ui/base/clipboard/clipboard_x11.cc index 95e2caff21a..c2f3620584b 100644 --- a/chromium/ui/base/clipboard/clipboard_x11.cc +++ b/chromium/ui/base/clipboard/clipboard_x11.cc @@ -22,8 +22,10 @@ #include "base/strings/utf_string_conversions.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/clipboard/clipboard_constants.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/base/clipboard/clipboard_monitor.h" #include "ui/base/clipboard/custom_data_helper.h" +#include "ui/base/nine_image_painter_factory.h" #include "ui/base/x/selection_owner.h" #include "ui/base/x/selection_requestor.h" #include "ui/base/x/selection_utils.h" @@ -32,8 +34,12 @@ #include "ui/events/x/x11_window_event_manager.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/xfixes.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -61,63 +67,57 @@ class SelectionChangeObserver : public XEventObserver { ~SelectionChangeObserver() override; // XEventObserver: - void WillProcessXEvent(XEvent* xev) override; - void DidProcessXEvent(XEvent* xev) override {} + void WillProcessXEvent(x11::Event* xev) override; + void DidProcessXEvent(x11::Event* xev) override {} - int event_base_; - Atom clipboard_atom_; - uint64_t clipboard_sequence_number_; - uint64_t primary_sequence_number_; + x11::Atom clipboard_atom_{}; + uint64_t clipboard_sequence_number_{}; + uint64_t primary_sequence_number_{}; DISALLOW_COPY_AND_ASSIGN(SelectionChangeObserver); }; -SelectionChangeObserver::SelectionChangeObserver() - : event_base_(-1), - clipboard_atom_(x11::None), - clipboard_sequence_number_(0), - primary_sequence_number_(0) { - int ignored; - if (XFixesQueryExtension(gfx::GetXDisplay(), &event_base_, &ignored)) { - clipboard_atom_ = gfx::GetAtom(kClipboard); - XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), - clipboard_atom_, - XFixesSetSelectionOwnerNotifyMask | - XFixesSelectionWindowDestroyNotifyMask | - XFixesSelectionClientCloseNotifyMask); - // This seems to be semi-optional. For some reason, registering for any - // selection notify events seems to subscribe us to events for both the - // primary and the clipboard buffers. Register anyway just to be safe. - XFixesSelectSelectionInput(gfx::GetXDisplay(), GetX11RootWindow(), - XA_PRIMARY, - XFixesSetSelectionOwnerNotifyMask | - XFixesSelectionWindowDestroyNotifyMask | - XFixesSelectionClientCloseNotifyMask); - - X11EventSource::GetInstance()->AddXEventObserver(this); - } -} +SelectionChangeObserver::SelectionChangeObserver() { + auto& xfixes = x11::Connection::Get()->xfixes(); + // Let the server know the client version. No need to sync since we don't + // care what version is running on the server. + xfixes.QueryVersion({x11::XFixes::major_version, x11::XFixes::minor_version}); + if (!xfixes.present()) + return; + + clipboard_atom_ = gfx::GetAtom(kClipboard); + auto mask = x11::XFixes::SelectionEventMask::SetSelectionOwner | + x11::XFixes::SelectionEventMask::SelectionWindowDestroy | + x11::XFixes::SelectionEventMask::SelectionClientClose; + xfixes.SelectSelectionInput({GetX11RootWindow(), clipboard_atom_, mask}); + // This seems to be semi-optional. For some reason, registering for any + // selection notify events seems to subscribe us to events for both the + // primary and the clipboard buffers. Register anyway just to be safe. + xfixes.SelectSelectionInput({GetX11RootWindow(), x11::Atom::PRIMARY, mask}); -SelectionChangeObserver::~SelectionChangeObserver() { - // We are a singleton; we will outlive the event source. + X11EventSource::GetInstance()->AddXEventObserver(this); } +// We are a singleton; we will outlive the event source. +SelectionChangeObserver::~SelectionChangeObserver() = default; + SelectionChangeObserver* SelectionChangeObserver::GetInstance() { return base::Singleton<SelectionChangeObserver>::get(); } -void SelectionChangeObserver::WillProcessXEvent(XEvent* xev) { - if (xev->type == event_base_ + XFixesSelectionNotify) { - XFixesSelectionNotifyEvent* ev = - reinterpret_cast<XFixesSelectionNotifyEvent*>(xev); - if (ev->selection == clipboard_atom_) { - clipboard_sequence_number_++; - ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged(); - } else if (ev->selection == XA_PRIMARY) { - primary_sequence_number_++; - } else { - DLOG(ERROR) << "Unexpected selection atom: " << ev->selection; - } +void SelectionChangeObserver::WillProcessXEvent(x11::Event* xev) { + auto* ev = xev->As<x11::XFixes::SelectionNotifyEvent>(); + if (!ev) + return; + + if (static_cast<x11::Atom>(ev->selection) == clipboard_atom_) { + clipboard_sequence_number_++; + ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged(); + } else if (ev->selection == x11::Atom::PRIMARY) { + primary_sequence_number_++; + } else { + DLOG(ERROR) << "Unexpected selection atom: " + << static_cast<uint32_t>(ev->selection); } } @@ -126,7 +126,7 @@ void SelectionChangeObserver::WillProcessXEvent(XEvent* xev) { // Represents a list of possible return types. Copy constructable. class TargetList { public: - using AtomVector = std::vector<::Atom>; + using AtomVector = std::vector<x11::Atom>; explicit TargetList(const AtomVector& target_list); @@ -134,7 +134,7 @@ class TargetList { bool ContainsText() const; bool ContainsFormat(const ClipboardFormatType& format_type) const; - bool ContainsAtom(::Atom atom) const; + bool ContainsAtom(x11::Atom atom) const; private: AtomVector target_list_; @@ -144,7 +144,7 @@ TargetList::TargetList(const AtomVector& target_list) : target_list_(target_list) {} bool TargetList::ContainsText() const { - std::vector<::Atom> atoms = GetTextAtomsFrom(); + std::vector<x11::Atom> atoms = GetTextAtomsFrom(); for (const auto& atom : atoms) { if (ContainsAtom(atom)) return true; @@ -154,14 +154,19 @@ bool TargetList::ContainsText() const { } bool TargetList::ContainsFormat(const ClipboardFormatType& format_type) const { - ::Atom atom = gfx::GetAtom(format_type.GetName().c_str()); + x11::Atom atom = gfx::GetAtom(format_type.GetName().c_str()); return ContainsAtom(atom); } -bool TargetList::ContainsAtom(::Atom atom) const { +bool TargetList::ContainsAtom(x11::Atom atom) const { return base::Contains(target_list_, atom); } +x11::Window GetSelectionOwner(x11::Atom selection) { + auto response = x11::Connection::Get()->GetSelectionOwner({selection}).Sync(); + return response ? response->owner : x11::Window::None; +} + } // namespace /////////////////////////////////////////////////////////////////////////////// @@ -176,14 +181,14 @@ class ClipboardX11::X11Details : public XEventDispatcher { // Returns the X11 selection atom that we pass to various XSelection functions // for the given buffer. - ::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const; + x11::Atom LookupSelectionForClipboardBuffer(ClipboardBuffer buffer) const; // Returns the X11 selection atom that we pass to various XSelection functions // for ClipboardBuffer::kCopyPaste. - ::Atom GetCopyPasteSelection() const; + x11::Atom GetCopyPasteSelection() const; // Finds the SelectionFormatMap for the incoming selection atom. - const SelectionFormatMap& LookupStorageForAtom(::Atom atom); + const SelectionFormatMap& LookupStorageForAtom(x11::Atom atom); // As we need to collect all the data types before we tell X11 that we own a // particular selection, we create a temporary clipboard mapping that @@ -208,7 +213,7 @@ class ClipboardX11::X11Details : public XEventDispatcher { // and do the asynchronous dance with whatever application is holding the // selection. SelectionData RequestAndWaitForTypes(ClipboardBuffer buffer, - const std::vector<::Atom>& types); + const std::vector<x11::Atom>& types); // Retrieves the list of possible data types the current clipboard owner has. // @@ -217,10 +222,10 @@ class ClipboardX11::X11Details : public XEventDispatcher { TargetList WaitAndGetTargetsList(ClipboardBuffer buffer); // Returns a list of all text atoms that we handle. - std::vector<::Atom> GetTextAtoms() const; + std::vector<x11::Atom> GetTextAtoms() const; // Returns a vector with a |format| converted to an X11 atom. - std::vector<::Atom> GetAtomsForFormat(const ClipboardFormatType& format); + std::vector<x11::Atom> GetAtomsForFormat(const ClipboardFormatType& format); // Clears a certain clipboard buffer, whether we own it or not. void Clear(ClipboardBuffer buffer); @@ -231,16 +236,14 @@ class ClipboardX11::X11Details : public XEventDispatcher { private: // XEventDispatcher: - bool DispatchXEvent(XEvent* xev) override; - - bool CanDispatchXEvent(XEvent* xev); + bool DispatchXEvent(x11::Event* xev) override; // Our X11 state. - Display* x_display_; - ::Window x_root_window_; + x11::Connection* connection_; + x11::Window x_root_window_; // Input-only window used as a selection owner. - ::Window x_window_; + x11::Window x_window_; // Events selected on |x_window_|. std::unique_ptr<XScopedEventSelector> x_window_events_; @@ -259,26 +262,16 @@ class ClipboardX11::X11Details : public XEventDispatcher { }; ClipboardX11::X11Details::X11Details() - : x_display_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(x_display_)), - x_window_(XCreateWindow(x_display_, - x_root_window_, - -100, - -100, - 10, - 10, // x, y, width, height - 0, // border width - CopyFromParent, // depth - InputOnly, - CopyFromParent, // visual - 0, - nullptr)), - selection_requestor_(x_display_, x_window_, this), - clipboard_owner_(x_display_, x_window_, gfx::GetAtom(kClipboard)), - primary_owner_(x_display_, x_window_, XA_PRIMARY) { - XStoreName(x_display_, x_window_, "Chromium clipboard"); - x_window_events_.reset( - new XScopedEventSelector(x_window_, PropertyChangeMask)); + : connection_(x11::Connection::Get()), + x_root_window_(ui::GetX11RootWindow()), + x_window_(CreateDummyWindow("Chromium Clipboard Window")), + selection_requestor_(x_window_, this), + clipboard_owner_(connection_, x_window_, gfx::GetAtom(kClipboard)), + primary_owner_(connection_, x_window_, x11::Atom::PRIMARY) { + SetStringProperty(x_window_, x11::Atom::WM_NAME, x11::Atom::STRING, + "Chromium clipboard"); + x_window_events_ = + std::make_unique<XScopedEventSelector>(x_window_, PropertyChangeMask); if (X11EventSource::GetInstance()) X11EventSource::GetInstance()->AddXEventDispatcher(this); @@ -288,24 +281,24 @@ ClipboardX11::X11Details::~X11Details() { if (X11EventSource::GetInstance()) X11EventSource::GetInstance()->RemoveXEventDispatcher(this); - XDestroyWindow(x_display_, x_window_); + connection_->DestroyWindow({x_window_}); } -::Atom ClipboardX11::X11Details::LookupSelectionForClipboardBuffer( +x11::Atom ClipboardX11::X11Details::LookupSelectionForClipboardBuffer( ClipboardBuffer buffer) const { if (buffer == ClipboardBuffer::kCopyPaste) return GetCopyPasteSelection(); - return XA_PRIMARY; + return x11::Atom::PRIMARY; } -::Atom ClipboardX11::X11Details::GetCopyPasteSelection() const { +x11::Atom ClipboardX11::X11Details::GetCopyPasteSelection() const { return gfx::GetAtom(kClipboard); } const SelectionFormatMap& ClipboardX11::X11Details::LookupStorageForAtom( - ::Atom atom) { - if (atom == XA_PRIMARY) + x11::Atom atom) { + if (atom == x11::Atom::PRIMARY) return primary_owner_.selection_format_map(); DCHECK_EQ(GetCopyPasteSelection(), atom); @@ -319,7 +312,7 @@ void ClipboardX11::X11Details::CreateNewClipboardData() { void ClipboardX11::X11Details::InsertMapping( const std::string& key, const scoped_refptr<base::RefCountedMemory>& memory) { - ::Atom atom_key = gfx::GetAtom(key.c_str()); + x11::Atom atom_key = gfx::GetAtom(key.c_str()); clipboard_data_.Insert(atom_key, memory); } @@ -333,9 +326,9 @@ void ClipboardX11::X11Details::TakeOwnershipOfSelection( SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes( ClipboardBuffer buffer, - const std::vector<::Atom>& types) { - ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { + const std::vector<x11::Atom>& types) { + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + if (GetSelectionOwner(selection_name) == x_window_) { // We can local fastpath instead of playing the nested run loop game // with the X server. const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); @@ -348,8 +341,8 @@ SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes( } else { TargetList targets = WaitAndGetTargetsList(buffer); - ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - std::vector<::Atom> intersection; + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + std::vector<x11::Atom> intersection; GetAtomIntersection(types, targets.target_list(), &intersection); return selection_requestor_.RequestAndWaitForTypes(selection_name, intersection); @@ -360,27 +353,25 @@ SelectionData ClipboardX11::X11Details::RequestAndWaitForTypes( TargetList ClipboardX11::X11Details::WaitAndGetTargetsList( ClipboardBuffer buffer) { - ::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); - std::vector<::Atom> out; - if (XGetSelectionOwner(x_display_, selection_name) == x_window_) { + x11::Atom selection_name = LookupSelectionForClipboardBuffer(buffer); + std::vector<x11::Atom> out; + if (GetSelectionOwner(selection_name) == x_window_) { // We can local fastpath and return the list of local targets. const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name); for (const auto& format : format_map) out.push_back(format.first); } else { - scoped_refptr<base::RefCountedMemory> data; - size_t out_data_items = 0; - ::Atom out_type = x11::None; + std::vector<uint8_t> data; + x11::Atom out_type = x11::Atom::None; if (selection_requestor_.PerformBlockingConvertSelection( - selection_name, gfx::GetAtom(kTargets), &data, &out_data_items, - &out_type)) { + selection_name, gfx::GetAtom(kTargets), &data, &out_type)) { // Some apps return an |out_type| of "TARGETS". (crbug.com/377893) - if (out_type == XA_ATOM || out_type == gfx::GetAtom(kTargets)) { - const ::Atom* atom_array = - reinterpret_cast<const ::Atom*>(data->front()); - for (size_t i = 0; i < out_data_items; ++i) + if (out_type == x11::Atom::ATOM || out_type == gfx::GetAtom(kTargets)) { + const x11::Atom* atom_array = + reinterpret_cast<const x11::Atom*>(data.data()); + for (size_t i = 0; i < data.size() / sizeof(x11::Atom); ++i) out.push_back(atom_array[i]); } } else { @@ -390,11 +381,11 @@ TargetList ClipboardX11::X11Details::WaitAndGetTargetsList( // text. This is pretty unfortunate since it means we have to actually // copy the data to see if it is available, but at least this path // shouldn't be hit for conforming programs. - std::vector<::Atom> types = GetTextAtoms(); + std::vector<x11::Atom> types = GetTextAtoms(); for (const auto& text_atom : types) { - ::Atom type = x11::None; + x11::Atom type = x11::Atom::None; if (selection_requestor_.PerformBlockingConvertSelection( - selection_name, text_atom, nullptr, nullptr, &type) && + selection_name, text_atom, nullptr, &type) && type == text_atom) { out.push_back(text_atom); } @@ -405,11 +396,11 @@ TargetList ClipboardX11::X11Details::WaitAndGetTargetsList( return TargetList(out); } -std::vector<::Atom> ClipboardX11::X11Details::GetTextAtoms() const { +std::vector<x11::Atom> ClipboardX11::X11Details::GetTextAtoms() const { return GetTextAtomsFrom(); } -std::vector<::Atom> ClipboardX11::X11Details::GetAtomsForFormat( +std::vector<x11::Atom> ClipboardX11::X11Details::GetAtomsForFormat( const ClipboardFormatType& format) { return {gfx::GetAtom(format.GetName().c_str())}; } @@ -422,18 +413,18 @@ void ClipboardX11::X11Details::Clear(ClipboardBuffer buffer) { } void ClipboardX11::X11Details::StoreCopyPasteDataAndWait() { - ::Atom selection = GetCopyPasteSelection(); - if (XGetSelectionOwner(x_display_, selection) != x_window_) + x11::Atom selection = GetCopyPasteSelection(); + if (GetSelectionOwner(selection) != x_window_) return; - ::Atom clipboard_manager_atom = gfx::GetAtom(kClipboardManager); - if (XGetSelectionOwner(x_display_, clipboard_manager_atom) == x11::None) + x11::Atom clipboard_manager_atom = gfx::GetAtom(kClipboardManager); + if (GetSelectionOwner(clipboard_manager_atom) == x11::Window::None) return; const SelectionFormatMap& format_map = LookupStorageForAtom(selection); if (format_map.size() == 0) return; - std::vector<Atom> targets = format_map.GetTypes(); + std::vector<x11::Atom> targets = format_map.GetTypes(); base::TimeTicks start = base::TimeTicks::Now(); selection_requestor_.PerformBlockingConvertSelectionWithParameter( @@ -442,71 +433,45 @@ void ClipboardX11::X11Details::StoreCopyPasteDataAndWait() { base::TimeTicks::Now() - start); } -bool ClipboardX11::X11Details::CanDispatchXEvent(XEvent* xev) { - if (xev->xany.window == x_window_) - return true; - - if (xev->type == PropertyNotify) { - return primary_owner_.CanDispatchPropertyEvent(*xev) || - clipboard_owner_.CanDispatchPropertyEvent(*xev) || - selection_requestor_.CanDispatchPropertyEvent(*xev); - } - return false; -} - -bool ClipboardX11::X11Details::DispatchXEvent(XEvent* xev) { - if (!CanDispatchXEvent(xev)) - return false; - - switch (xev->type) { - case SelectionRequest: { - if (xev->xselectionrequest.selection == XA_PRIMARY) { - primary_owner_.OnSelectionRequest(*xev); - } else { - // We should not get requests for the CLIPBOARD_MANAGER selection - // because we never take ownership of it. - DCHECK_EQ(GetCopyPasteSelection(), xev->xselectionrequest.selection); - clipboard_owner_.OnSelectionRequest(*xev); - } - break; - } - case SelectionNotify: { - selection_requestor_.OnSelectionNotify(*xev); - break; - } - case SelectionClear: { - if (xev->xselectionclear.selection == XA_PRIMARY) { - primary_owner_.OnSelectionClear(*xev); - } else { - // We should not get requests for the CLIPBOARD_MANAGER selection - // because we never take ownership of it. - DCHECK_EQ(GetCopyPasteSelection(), xev->xselection.selection); - clipboard_owner_.OnSelectionClear(*xev); - } - break; +bool ClipboardX11::X11Details::DispatchXEvent(x11::Event* xev) { + if (auto* request = xev->As<x11::SelectionRequestEvent>()) { + if (request->owner != x_window_) + return false; + if (request->selection == x11::Atom::PRIMARY) { + primary_owner_.OnSelectionRequest(*xev); + } else { + // We should not get requests for the CLIPBOARD_MANAGER selection + // because we never take ownership of it. + DCHECK_EQ(GetCopyPasteSelection(), request->selection); + clipboard_owner_.OnSelectionRequest(*xev); } - case PropertyNotify: { - if (primary_owner_.CanDispatchPropertyEvent(*xev)) - primary_owner_.OnPropertyEvent(*xev); - if (clipboard_owner_.CanDispatchPropertyEvent(*xev)) - clipboard_owner_.OnPropertyEvent(*xev); - if (selection_requestor_.CanDispatchPropertyEvent(*xev)) - selection_requestor_.OnPropertyEvent(*xev); - break; + } else if (auto* notify = xev->As<x11::SelectionNotifyEvent>()) { + if (notify->requestor != x_window_) + return false; + selection_requestor_.OnSelectionNotify(*notify); + } else if (auto* clear = xev->As<x11::SelectionClearEvent>()) { + if (clear->owner != x_window_) + return false; + if (clear->selection == x11::Atom::PRIMARY) { + primary_owner_.OnSelectionClear(*xev); + } else { + // We should not get requests for the CLIPBOARD_MANAGER selection + // because we never take ownership of it. + DCHECK_EQ(GetCopyPasteSelection(), clear->selection); + clipboard_owner_.OnSelectionClear(*xev); } - default: - break; + } else if (auto* prop = xev->As<x11::PropertyNotifyEvent>()) { + if (primary_owner_.CanDispatchPropertyEvent(*xev)) + primary_owner_.OnPropertyEvent(*xev); + if (clipboard_owner_.CanDispatchPropertyEvent(*xev)) + clipboard_owner_.OnPropertyEvent(*xev); + if (selection_requestor_.CanDispatchPropertyEvent(*xev)) + selection_requestor_.OnPropertyEvent(*xev); } return false; } /////////////////////////////////////////////////////////////////////////////// -// Clipboard factory method. -Clipboard* Clipboard::Create() { - return new ClipboardX11; -} - -/////////////////////////////////////////////////////////////////////////////// // ClipboardX11 ClipboardX11::ClipboardX11() : x11_details_(new X11Details) { @@ -586,17 +551,16 @@ ClipboardX11::ReadAvailablePlatformSpecificFormatNames( if (target_list.empty()) return {}; - std::vector<char*> types_buffer(target_list.size()); - // Call XGetAtomNames to minimize trips to the X11 server. - int status = XGetAtomNames(gfx::GetXDisplay(), target_list.data(), - target_list.size(), types_buffer.data()); - DCHECK(status) << "XGetAtomNames failed! An invalid Atom was passed in."; - + std::vector<x11::Future<x11::GetAtomNameReply>> futures; + for (x11::Atom target : target_list) + futures.push_back(x11::Connection::Get()->GetAtomName({target})); std::vector<base::string16> types; types.reserve(target_list.size()); - for (char* type : types_buffer) { - types.push_back(base::UTF8ToUTF16(type)); - XFree(type); + for (auto& future : futures) { + if (auto response = future.Sync()) + types.push_back(base::UTF8ToUTF16(response->name)); + else + types.emplace_back(); } return types; @@ -605,6 +569,7 @@ ClipboardX11::ReadAvailablePlatformSpecificFormatNames( void ClipboardX11::ReadText(ClipboardBuffer buffer, base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); SelectionData data(x11_details_->RequestAndWaitForTypes( buffer, x11_details_->GetTextAtoms())); @@ -617,6 +582,7 @@ void ClipboardX11::ReadText(ClipboardBuffer buffer, void ClipboardX11::ReadAsciiText(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kText); SelectionData data(x11_details_->RequestAndWaitForTypes( buffer, x11_details_->GetTextAtoms())); @@ -632,6 +598,7 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer, uint32_t* fragment_start, uint32_t* fragment_end) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kHtml); markup->clear(); if (src_url) src_url->clear(); @@ -652,6 +619,7 @@ void ClipboardX11::ReadHTML(ClipboardBuffer buffer, void ClipboardX11::ReadRTF(ClipboardBuffer buffer, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kRtf); SelectionData data(x11_details_->RequestAndWaitForTypes( buffer, @@ -663,6 +631,7 @@ void ClipboardX11::ReadRTF(ClipboardBuffer buffer, std::string* result) const { void ClipboardX11::ReadImage(ClipboardBuffer buffer, ReadImageCallback callback) const { DCHECK(IsSupportedClipboardBuffer(buffer)); + RecordRead(ClipboardFormatMetric::kImage); std::move(callback).Run(ReadImageInternal(buffer)); } @@ -670,6 +639,7 @@ void ClipboardX11::ReadCustomData(ClipboardBuffer buffer, const base::string16& type, base::string16* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kCustomData); SelectionData data(x11_details_->RequestAndWaitForTypes( buffer, x11_details_->GetAtomsForFormat( @@ -687,6 +657,7 @@ void ClipboardX11::ReadBookmark(base::string16* title, std::string* url) const { void ClipboardX11::ReadData(const ClipboardFormatType& format, std::string* result) const { DCHECK(CalledOnValidThread()); + RecordRead(ClipboardFormatMetric::kData); SelectionData data(x11_details_->RequestAndWaitForTypes( ClipboardBuffer::kCopyPaste, x11_details_->GetAtomsForFormat(format))); diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc index 1b8312f5fc5..c723b0d2e33 100644 --- a/chromium/ui/base/clipboard/scoped_clipboard_writer.cc +++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.cc @@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "net/base/escape.h" #include "ui/base/clipboard/clipboard_format_type.h" +#include "ui/base/clipboard/clipboard_metrics.h" #include "ui/gfx/geometry/size.h" // Documentation on the format of the parameters for each clipboard target can @@ -31,9 +32,12 @@ ScopedClipboardWriter::~ScopedClipboardWriter() { Clipboard::GetForCurrentThread()->WritePlatformRepresentations( buffer_, std::move(platform_representations_)); } + if (confidential_) + Clipboard::GetForCurrentThread()->MarkAsConfidential(); } void ScopedClipboardWriter::WriteText(const base::string16& text) { + RecordWrite(ClipboardFormatMetric::kText); std::string utf8_text = base::UTF16ToUTF8(text); Clipboard::ObjectMapParams parameters; @@ -44,6 +48,7 @@ void ScopedClipboardWriter::WriteText(const base::string16& text) { void ScopedClipboardWriter::WriteHTML(const base::string16& markup, const std::string& source_url) { + RecordWrite(ClipboardFormatMetric::kHtml); std::string utf8_markup = base::UTF16ToUTF8(markup); Clipboard::ObjectMapParams parameters; @@ -59,6 +64,7 @@ void ScopedClipboardWriter::WriteHTML(const base::string16& markup, } void ScopedClipboardWriter::WriteRTF(const std::string& rtf_data) { + RecordWrite(ClipboardFormatMetric::kRtf); Clipboard::ObjectMapParams parameters; parameters.push_back(Clipboard::ObjectMapParam(rtf_data.begin(), rtf_data.end())); @@ -69,6 +75,7 @@ void ScopedClipboardWriter::WriteBookmark(const base::string16& bookmark_title, const std::string& url) { if (bookmark_title.empty() || url.empty()) return; + RecordWrite(ClipboardFormatMetric::kBookmark); std::string utf8_markup = base::UTF16ToUTF8(bookmark_title); @@ -94,6 +101,7 @@ void ScopedClipboardWriter::WriteHyperlink(const base::string16& anchor_text, } void ScopedClipboardWriter::WriteWebSmartPaste() { + RecordWrite(ClipboardFormatMetric::kWebSmartPaste); objects_[Clipboard::PortableFormat::kWebkit] = Clipboard::ObjectMapParams(); } @@ -101,6 +109,7 @@ void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) { if (bitmap.drawsNothing()) return; DCHECK(bitmap.getPixels()); + RecordWrite(ClipboardFormatMetric::kImage); bitmap_ = bitmap; // TODO(dcheng): This is slightly less horrible than what we used to do, but @@ -114,9 +123,14 @@ void ScopedClipboardWriter::WriteImage(const SkBitmap& bitmap) { objects_[Clipboard::PortableFormat::kBitmap] = parameters; } +void ScopedClipboardWriter::MarkAsConfidential() { + confidential_ = true; +} + void ScopedClipboardWriter::WritePickledData( const base::Pickle& pickle, const ClipboardFormatType& format) { + RecordWrite(ClipboardFormatMetric::kCustomData); std::string format_string = format.Serialize(); Clipboard::ObjectMapParam format_parameter(format_string.begin(), format_string.end()); @@ -134,6 +148,7 @@ void ScopedClipboardWriter::WritePickledData( void ScopedClipboardWriter::WriteData(const base::string16& format, mojo_base::BigBuffer data) { + RecordWrite(ClipboardFormatMetric::kData); platform_representations_.push_back( {base::UTF16ToUTF8(format), std::move(data)}); } @@ -142,6 +157,7 @@ void ScopedClipboardWriter::Reset() { objects_.clear(); platform_representations_.clear(); bitmap_.reset(); + confidential_ = false; } } // namespace ui diff --git a/chromium/ui/base/clipboard/scoped_clipboard_writer.h b/chromium/ui/base/clipboard/scoped_clipboard_writer.h index d0e5cfb3e3e..d2ed3736ce2 100644 --- a/chromium/ui/base/clipboard/scoped_clipboard_writer.h +++ b/chromium/ui/base/clipboard/scoped_clipboard_writer.h @@ -67,6 +67,9 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter { void WriteImage(const SkBitmap& bitmap); + // Mark the data to be written as confidential. + void MarkAsConfidential(); + // Removes all objects that would be written to the clipboard. void Reset(); @@ -83,6 +86,8 @@ class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) ScopedClipboardWriter { SkBitmap bitmap_; + bool confidential_ = false; + DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriter); }; diff --git a/chromium/ui/base/cocoa/accessibility_focus_overrider.h b/chromium/ui/base/cocoa/accessibility_focus_overrider.h index d8b6def31a2..7d3b88d04a7 100644 --- a/chromium/ui/base/cocoa/accessibility_focus_overrider.h +++ b/chromium/ui/base/cocoa/accessibility_focus_overrider.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_ #define UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -28,7 +28,7 @@ namespace ui { // The above-required overriding of focus is done by instantiating an // AccessibilityFocusOverrider and updating its state when the NSView in the // PWA process is focused. -class UI_BASE_EXPORT AccessibilityFocusOverrider { +class COMPONENT_EXPORT(UI_BASE) AccessibilityFocusOverrider { public: class Client { public: diff --git a/chromium/ui/base/cocoa/appkit_utils.h b/chromium/ui/base/cocoa/appkit_utils.h index 14f6c55070e..a3b46d13329 100644 --- a/chromium/ui/base/cocoa/appkit_utils.h +++ b/chromium/ui/base/cocoa/appkit_utils.h @@ -7,15 +7,15 @@ #import <Cocoa/Cocoa.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Whether a force-click event on the touchpad should invoke Quick Look. -UI_BASE_EXPORT bool ForceClickInvokesQuickLook(); +COMPONENT_EXPORT(UI_BASE) bool ForceClickInvokesQuickLook(); // Returns true if both CGFloat values are equal. -UI_BASE_EXPORT bool IsCGFloatEqual(CGFloat a, CGFloat b); +COMPONENT_EXPORT(UI_BASE) bool IsCGFloatEqual(CGFloat a, CGFloat b); } // namespace ui diff --git a/chromium/ui/base/cocoa/base_view.h b/chromium/ui/base/cocoa/base_view.h index d9194c2f629..989196e8e19 100644 --- a/chromium/ui/base/cocoa/base_view.h +++ b/chromium/ui/base/cocoa/base_view.h @@ -7,16 +7,16 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" #import "ui/base/cocoa/tracking_area.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/geometry/rect.h" // A view that provides common functionality that many views will need: // - Automatic registration for mouse-moved events. // - Funneling of mouse and key events to two methods // - Coordinate conversion utilities -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface BaseView : NSView { @public enum EventHandled { @@ -57,7 +57,7 @@ UI_BASE_EXPORT // The name is |kViewDidBecomeFirstResponder|, the object is the view, and the // NSSelectionDirection is wrapped in an NSNumber under the key // |kSelectionDirection|. -UI_BASE_EXPORT extern NSString* kViewDidBecomeFirstResponder; -UI_BASE_EXPORT extern NSString* kSelectionDirection; +COMPONENT_EXPORT(UI_BASE) extern NSString* kViewDidBecomeFirstResponder; +COMPONENT_EXPORT(UI_BASE) extern NSString* kSelectionDirection; #endif // UI_BASE_COCOA_BASE_VIEW_H_ diff --git a/chromium/ui/base/cocoa/base_view.mm b/chromium/ui/base/cocoa/base_view.mm index 55ecf52defd..05ac7edca8b 100644 --- a/chromium/ui/base/cocoa/base_view.mm +++ b/chromium/ui/base/cocoa/base_view.mm @@ -4,6 +4,7 @@ #include "ui/base/cocoa/base_view.h" +#include "base/check_op.h" #include "base/mac/mac_util.h" NSString* kViewDidBecomeFirstResponder = diff --git a/chromium/ui/base/cocoa/bubble_closer.h b/chromium/ui/base/cocoa/bubble_closer.h index 39a2f450d5a..806d7352726 100644 --- a/chromium/ui/base/cocoa/bubble_closer.h +++ b/chromium/ui/base/cocoa/bubble_closer.h @@ -8,9 +8,9 @@ #include <objc/objc.h> #include "base/callback.h" +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/cocoa/weak_ptr_nsobject.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/native_widget_types.h" namespace ui { @@ -18,7 +18,7 @@ namespace ui { // Monitors mouse events to allow a regular window to have menu-like popup // behavior when clicking outside the window. This is needed because macOS // suppresses window activation events when clicking rapidly. -class UI_BASE_EXPORT BubbleCloser { +class COMPONENT_EXPORT(UI_BASE) BubbleCloser { public: // Installs an event monitor watching for mouse clicks outside of |window| or // any of its child windows. Invokes |on_click_outside| on each event. diff --git a/chromium/ui/base/cocoa/cocoa_base_utils.h b/chromium/ui/base/cocoa/cocoa_base_utils.h index 627fe3ba325..05c7526f8d4 100644 --- a/chromium/ui/base/cocoa/cocoa_base_utils.h +++ b/chromium/ui/base/cocoa/cocoa_base_utils.h @@ -7,7 +7,7 @@ #import <Cocoa/Cocoa.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include "ui/base/window_open_disposition.h" namespace ui { @@ -15,24 +15,26 @@ namespace ui { // Retrieves the WindowOpenDisposition used to open a link from a user gesture // represented by |event|. For example, a Cmd+Click would mean open the // associated link in a background tab. -UI_BASE_EXPORT WindowOpenDisposition - WindowOpenDispositionFromNSEvent(NSEvent* event); +COMPONENT_EXPORT(UI_BASE) +WindowOpenDisposition WindowOpenDispositionFromNSEvent(NSEvent* event); // Retrieves the WindowOpenDisposition used to open a link from a user gesture // represented by |event|, but instead use the modifier flags given by |flags|, // which is the same format as |-NSEvent modifierFlags|. This allows // substitution of the modifiers without having to create a new event from // scratch. -UI_BASE_EXPORT WindowOpenDisposition - WindowOpenDispositionFromNSEventWithFlags(NSEvent* event, NSUInteger flags); +COMPONENT_EXPORT(UI_BASE) +WindowOpenDisposition WindowOpenDispositionFromNSEventWithFlags( + NSEvent* event, + NSUInteger flags); // Converts a point from window coordinates to screen coordinates. -UI_BASE_EXPORT NSPoint ConvertPointFromWindowToScreen(NSWindow* window, - NSPoint point); +COMPONENT_EXPORT(UI_BASE) +NSPoint ConvertPointFromWindowToScreen(NSWindow* window, NSPoint point); // Converts a point from screen coordinates to window coordinates. -UI_BASE_EXPORT NSPoint ConvertPointFromScreenToWindow(NSWindow* window, - NSPoint point); +COMPONENT_EXPORT(UI_BASE) +NSPoint ConvertPointFromScreenToWindow(NSWindow* window, NSPoint point); } // namespace ui diff --git a/chromium/ui/base/cocoa/command_dispatcher.h b/chromium/ui/base/cocoa/command_dispatcher.h index 0fca8887e6a..1203c0a4df2 100644 --- a/chromium/ui/base/cocoa/command_dispatcher.h +++ b/chromium/ui/base/cocoa/command_dispatcher.h @@ -7,8 +7,8 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #import "base/mac/scoped_nsobject.h" -#include "ui/base/ui_base_export.h" @protocol CommandDispatcherDelegate; @protocol CommandDispatchingWindow; @@ -21,7 +21,7 @@ // NSWindow can use CommandDispatcher by implementing CommandDispatchingWindow // and overriding -[NSWindow performKeyEquivalent:] and -[NSWindow sendEvent:] // to call the respective CommandDispatcher methods. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface CommandDispatcher : NSObject @property(assign, nonatomic) id<CommandDispatcherDelegate> delegate; diff --git a/chromium/ui/base/cocoa/command_dispatcher.mm b/chromium/ui/base/cocoa/command_dispatcher.mm index efe7a1862ce..1ae7b1707a7 100644 --- a/chromium/ui/base/cocoa/command_dispatcher.mm +++ b/chromium/ui/base/cocoa/command_dispatcher.mm @@ -23,6 +23,44 @@ - (NSWindow<CommandDispatchingWindow>*)bubbleParent; @end +namespace { + +// Duplicate the given key event, but changing the associated window. +NSEvent* KeyEventForWindow(NSWindow* window, NSEvent* event) { + NSEventType event_type = [event type]; + + // Convert the event's location from the original window's coordinates into + // our own. + NSPoint location = [event locationInWindow]; + location = ui::ConvertPointFromWindowToScreen([event window], location); + location = ui::ConvertPointFromScreenToWindow(window, location); + + // Various things *only* apply to key down/up. + bool is_a_repeat = false; + NSString* characters = nil; + NSString* charactors_ignoring_modifiers = nil; + if (event_type == NSKeyDown || event_type == NSKeyUp) { + is_a_repeat = [event isARepeat]; + characters = [event characters]; + charactors_ignoring_modifiers = [event charactersIgnoringModifiers]; + } + + // This synthesis may be slightly imperfect: we provide nil for the context, + // since I (viettrungluu) am sceptical that putting in the original context + // (if one is given) is valid. + return [NSEvent keyEventWithType:event_type + location:location + modifierFlags:[event modifierFlags] + timestamp:[event timestamp] + windowNumber:[window windowNumber] + context:nil + characters:characters + charactersIgnoringModifiers:charactors_ignoring_modifiers + isARepeat:is_a_repeat + keyCode:[event keyCode]]; +} + +} // namespace @implementation CommandDispatcher { @private @@ -169,10 +207,13 @@ return YES; // Pretend it's been handled in an effort to limit damage. } - // TODO(lgrey): This is a temporary sanity check since the code that was - // here previously did *not* assume this. Remove shortly after this lands if - // nothing blew up. - DCHECK_EQ([event window], _owner); + // Sometimes, an event will be redispatched from a child window to a parent + // window to allow the parent window a chance to handle it. In that case, fix + // up the native event to reference the correct window. Failure to do this can + // cause infinite redispatch loops; see https://crbug.com/1085578 for more + // details. + if ([event window] != _owner) + event = KeyEventForWindow(_owner, event); // Redispatch the event. _eventHandled = YES; diff --git a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.h b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.h index 2bc672c9840..8942102b232 100644 --- a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.h +++ b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.h @@ -7,11 +7,11 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" -#include "ui/base/ui_base_export.h" // Base class for all constrained window animation classes. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ConstrainedWindowAnimationBase : NSAnimation { @protected base::scoped_nsobject<NSWindow> _window; @@ -22,17 +22,17 @@ UI_BASE_EXPORT @end // An animation to show a window. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ConstrainedWindowAnimationShow : ConstrainedWindowAnimationBase @end // An animation to hide a window. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ConstrainedWindowAnimationHide : ConstrainedWindowAnimationBase @end // An animation that pulses the window by growing it then shrinking it back. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ConstrainedWindowAnimationPulse : ConstrainedWindowAnimationBase @end diff --git a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm index ce16e17dfcb..c8ce99f708b 100644 --- a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm +++ b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm @@ -11,6 +11,7 @@ #include "base/location.h" #import "base/mac/foundation_util.h" #include "base/native_library.h" +#include "base/notreached.h" #include "base/stl_util.h" #include "ui/gfx/animation/tween.h" diff --git a/chromium/ui/base/cocoa/controls/button_utils.h b/chromium/ui/base/cocoa/controls/button_utils.h index 740c914140a..d9b039f0fa9 100644 --- a/chromium/ui/base/cocoa/controls/button_utils.h +++ b/chromium/ui/base/cocoa/controls/button_utils.h @@ -5,11 +5,11 @@ #ifndef UI_BASE_COCOA_CONTROLS_BUTTON_UTILS_H_ #define UI_BASE_COCOA_CONTROLS_BUTTON_UTILS_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include <Cocoa/Cocoa.h> -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ButtonUtils : NSObject // These methods are a polyfill for convenience constructors that exist on diff --git a/chromium/ui/base/cocoa/controls/textfield_utils.h b/chromium/ui/base/cocoa/controls/textfield_utils.h index dea04b87f0e..4fd54c6c0ea 100644 --- a/chromium/ui/base/cocoa/controls/textfield_utils.h +++ b/chromium/ui/base/cocoa/controls/textfield_utils.h @@ -5,11 +5,11 @@ #ifndef UI_BASE_COCOA_CONTROLS_TEXTFIELD_UTILS_H_ #define UI_BASE_COCOA_CONTROLS_TEXTFIELD_UTILS_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include <Cocoa/Cocoa.h> -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface TextFieldUtils : NSObject // This method is a polyfill for a method on NSTextField on macOS 10.12+. diff --git a/chromium/ui/base/cocoa/defaults_utils.h b/chromium/ui/base/cocoa/defaults_utils.h index ff68374f8a0..7845045d5c4 100644 --- a/chromium/ui/base/cocoa/defaults_utils.h +++ b/chromium/ui/base/cocoa/defaults_utils.h @@ -5,15 +5,15 @@ #ifndef UI_BASE_COCOA_DEFAULTS_UTILS_H_ #define UI_BASE_COCOA_DEFAULTS_UTILS_H_ +#include "base/component_export.h" #include "base/time/time.h" -#include "ui/base/ui_base_export.h" namespace ui { // Returns the text insertion caret blink period, if one is configured in // NSUserDefaults. -UI_BASE_EXPORT bool TextInsertionCaretBlinkPeriod(base::TimeDelta* period); - +COMPONENT_EXPORT(UI_BASE) +bool TextInsertionCaretBlinkPeriod(base::TimeDelta* period); } #endif diff --git a/chromium/ui/base/cocoa/find_pasteboard.h b/chromium/ui/base/cocoa/find_pasteboard.h index 4cda454dbc2..3dc0867ca8e 100644 --- a/chromium/ui/base/cocoa/find_pasteboard.h +++ b/chromium/ui/base/cocoa/find_pasteboard.h @@ -11,10 +11,10 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" -#include "ui/base/ui_base_export.h" -UI_BASE_EXPORT extern NSString* kFindPasteboardChangedNotification; +COMPONENT_EXPORT(UI_BASE) extern NSString* kFindPasteboardChangedNotification; // Manages the find pasteboard. Use this to copy text to the find pasteboard, // to get the text currently on the find pasteboard, and to receive @@ -25,7 +25,7 @@ UI_BASE_EXPORT extern NSString* kFindPasteboardChangedNotification; // This is not thread-safe and must be used on the main thread. // // This is supposed to be a singleton. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface FindPasteboard : NSObject { @private base::scoped_nsobject<NSString> _findText; @@ -54,6 +54,6 @@ UI_BASE_EXPORT #endif // __OBJC__ // Also provide a c++ interface -UI_BASE_EXPORT base::string16 GetFindPboardText(); +COMPONENT_EXPORT(UI_BASE) base::string16 GetFindPboardText(); #endif // UI_BASE_COCOA_FIND_PASTEBOARD_H_ diff --git a/chromium/ui/base/cocoa/flipped_view.h b/chromium/ui/base/cocoa/flipped_view.h index 7bc117779d8..c5dce1a553d 100644 --- a/chromium/ui/base/cocoa/flipped_view.h +++ b/chromium/ui/base/cocoa/flipped_view.h @@ -7,13 +7,13 @@ #import <Cocoa/Cocoa.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" // A view where the Y axis is flipped such that the origin is at the top left // and Y value increases downwards. Drawing is flipped so that layout of the // sections is easier. Apple recommends flipping the coordinate origin when // doing a lot of text layout because it's more natural. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface FlippedView : NSView @end diff --git a/chromium/ui/base/cocoa/focus_tracker.h b/chromium/ui/base/cocoa/focus_tracker.h index f77559ea098..a676e08ef15 100644 --- a/chromium/ui/base/cocoa/focus_tracker.h +++ b/chromium/ui/base/cocoa/focus_tracker.h @@ -4,15 +4,15 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" -#include "ui/base/ui_base_export.h" // A class that handles saving and restoring focus. An instance of // this class snapshots the currently focused view when it is // constructed, and callers can use restoreFocus to return focus to // that view. FocusTracker will not restore focus to views that are // no longer in the view hierarchy or are not in the correct window. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface FocusTracker : NSObject { @private base::scoped_nsobject<NSView> _focusedView; diff --git a/chromium/ui/base/cocoa/focus_window_set.h b/chromium/ui/base/cocoa/focus_window_set.h index e4b6d9f0471..820195f6978 100644 --- a/chromium/ui/base/cocoa/focus_window_set.h +++ b/chromium/ui/base/cocoa/focus_window_set.h @@ -7,7 +7,7 @@ #include <set> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include "ui/gfx/native_widget_types.h" namespace ui { @@ -15,7 +15,8 @@ namespace ui { // Brings a group of windows to the front without changing their order, and // makes the frontmost one key and main. If none are visible, the frontmost // miniaturized window is deminiaturized. -UI_BASE_EXPORT void FocusWindowSet(const std::set<gfx::NativeWindow>& windows); +COMPONENT_EXPORT(UI_BASE) +void FocusWindowSet(const std::set<gfx::NativeWindow>& windows); // Brings a group of windows to the front without changing their // order, and makes the frontmost one key and main. If none are @@ -24,8 +25,8 @@ UI_BASE_EXPORT void FocusWindowSet(const std::set<gfx::NativeWindow>& windows); // behavior. Unlike FocusWindowSet, only windows on the current space // are considered. It also ignores the hidden state of windows; the // window system may be in the middle of unhiding the application. -UI_BASE_EXPORT void FocusWindowSetOnCurrentSpace( - const std::set<gfx::NativeWindow>& windows); +COMPONENT_EXPORT(UI_BASE) +void FocusWindowSetOnCurrentSpace(const std::set<gfx::NativeWindow>& windows); } // namespace ui diff --git a/chromium/ui/base/cocoa/focus_window_set.mm b/chromium/ui/base/cocoa/focus_window_set.mm index 498df6e2951..06e7223ded8 100644 --- a/chromium/ui/base/cocoa/focus_window_set.mm +++ b/chromium/ui/base/cocoa/focus_window_set.mm @@ -4,6 +4,7 @@ #import <Cocoa/Cocoa.h> +#include "base/check.h" #include "ui/base/cocoa/focus_window_set.h" namespace ui { diff --git a/chromium/ui/base/cocoa/menu_controller.h b/chromium/ui/base/cocoa/menu_controller.h index d6dd4f0ced2..8dc3cdb50a5 100644 --- a/chromium/ui/base/cocoa/menu_controller.h +++ b/chromium/ui/base/cocoa/menu_controller.h @@ -7,9 +7,9 @@ #import <Cocoa/Cocoa.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace ui { class MenuModel; @@ -21,7 +21,7 @@ class MenuModel; // allow for hierarchical menus). The tag is the index into that model for // that particular item. It is important that the model outlives this object // as it only maintains weak references. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface MenuControllerCocoa : NSObject<NSMenuDelegate, NSUserInterfaceValidations> diff --git a/chromium/ui/base/cocoa/permissions_utils.h b/chromium/ui/base/cocoa/permissions_utils.h index 14355053988..a8ec034cdf2 100644 --- a/chromium/ui/base/cocoa/permissions_utils.h +++ b/chromium/ui/base/cocoa/permissions_utils.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_COCOA_PERMISSIONS_UTILS_H_ #define UI_BASE_COCOA_PERMISSIONS_UTILS_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -14,7 +14,7 @@ namespace ui { // requires a permission authorization. There is no direct way to query the // permission state, so this uses a heuristic to evaluate whether the permission // has been granted. -UI_BASE_EXPORT bool IsScreenCaptureAllowed(); +COMPONENT_EXPORT(UI_BASE) bool IsScreenCaptureAllowed(); } // namespace ui diff --git a/chromium/ui/base/cocoa/quartz_util.h b/chromium/ui/base/cocoa/quartz_util.h index dd3201fe925..bba1f2016e5 100644 --- a/chromium/ui/base/cocoa/quartz_util.h +++ b/chromium/ui/base/cocoa/quartz_util.h @@ -5,15 +5,15 @@ #ifndef UI_BASE_COCOA_QUARTZ_UTIL_H_ #define UI_BASE_COCOA_QUARTZ_UTIL_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Calls +[CATransaction begin]. -UI_BASE_EXPORT void BeginCATransaction(); +COMPONENT_EXPORT(UI_BASE) void BeginCATransaction(); // Calls +[CATransaction commit]. -UI_BASE_EXPORT void CommitCATransaction(); +COMPONENT_EXPORT(UI_BASE) void CommitCATransaction(); } // namespace ui diff --git a/chromium/ui/base/cocoa/remote_accessibility_api.h b/chromium/ui/base/cocoa/remote_accessibility_api.h index 2a58aebabb2..e7adfee3210 100644 --- a/chromium/ui/base/cocoa/remote_accessibility_api.h +++ b/chromium/ui/base/cocoa/remote_accessibility_api.h @@ -8,8 +8,8 @@ #import <Cocoa/Cocoa.h> #include <vector> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" -#include "ui/base/ui_base_export.h" @interface NSAccessibilityRemoteUIElement : NSObject + (void)registerRemoteUIProcessIdentifier:(int)pid; @@ -23,7 +23,7 @@ namespace ui { // Helper functions to implement the above functions using std::vectors intsead // of NSData. -class UI_BASE_EXPORT RemoteAccessibility { +class COMPONENT_EXPORT(UI_BASE) RemoteAccessibility { public: static std::vector<uint8_t> GetTokenForLocalElement(id element); static base::scoped_nsobject<NSAccessibilityRemoteUIElement> diff --git a/chromium/ui/base/cocoa/remote_layer_api.h b/chromium/ui/base/cocoa/remote_layer_api.h index 2057fe69d1b..d684614589c 100644 --- a/chromium/ui/base/cocoa/remote_layer_api.h +++ b/chromium/ui/base/cocoa/remote_layer_api.h @@ -11,7 +11,7 @@ #include <stdint.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" // The CGSConnectionID is used to create the CAContext in the process that is // going to share the CALayers that it is rendering to another process to @@ -54,7 +54,7 @@ namespace ui { // This function will check if all of the interfaces listed above are supported // on the system, and return true if they are. -bool UI_BASE_EXPORT RemoteLayerAPISupported(); +bool COMPONENT_EXPORT(UI_BASE) RemoteLayerAPISupported(); } // namespace ui diff --git a/chromium/ui/base/cocoa/secure_password_input.h b/chromium/ui/base/cocoa/secure_password_input.h index ca90d3964a5..d272cd1bd6a 100644 --- a/chromium/ui/base/cocoa/secure_password_input.h +++ b/chromium/ui/base/cocoa/secure_password_input.h @@ -5,13 +5,13 @@ #ifndef UI_BASE_COCOA_SECURE_PASSWORD_INPUT_H_ #define UI_BASE_COCOA_SECURE_PASSWORD_INPUT_H_ +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" namespace ui { // Enables the secure password input mode while in scope. -class UI_BASE_EXPORT ScopedPasswordInputEnabler { +class COMPONENT_EXPORT(UI_BASE) ScopedPasswordInputEnabler { public: ScopedPasswordInputEnabler(); ~ScopedPasswordInputEnabler(); diff --git a/chromium/ui/base/cocoa/text_services_context_menu.cc b/chromium/ui/base/cocoa/text_services_context_menu.cc index d149dd8df63..0dcfe6db2b4 100644 --- a/chromium/ui/base/cocoa/text_services_context_menu.cc +++ b/chromium/ui/base/cocoa/text_services_context_menu.cc @@ -17,22 +17,6 @@ namespace { -enum MenuCommands { - // These must not overlap with the command IDs used by other menus that - // incorporate text services. - // TODO(ellyjones): This is an ugly global dependency, especially on - // //ui/views. What can we do about this? Can we get rid of the global - // implicit namespace of command IDs? - kSpeechMenu = 100, - kSpeechStartSpeaking, - kSpeechStopSpeaking, - - kWritingDirectionMenu, - kWritingDirectionDefault, - kWritingDirectionLtr, - kWritingDirectionRtl, -}; - // The speech channel used for speaking. This is shared to check if a speech // channel is currently speaking. SpeechChannel g_speech_channel; @@ -41,11 +25,11 @@ SpeechChannel g_speech_channel; // |command_id|. base::i18n::TextDirection GetTextDirectionFromCommandId(int command_id) { switch (command_id) { - case kWritingDirectionDefault: + case ui::TextServicesContextMenu::kWritingDirectionDefault: return base::i18n::UNKNOWN_DIRECTION; - case kWritingDirectionLtr: + case ui::TextServicesContextMenu::kWritingDirectionLtr: return base::i18n::LEFT_TO_RIGHT; - case kWritingDirectionRtl: + case ui::TextServicesContextMenu::kWritingDirectionRtl: return base::i18n::RIGHT_TO_LEFT; default: NOTREACHED(); diff --git a/chromium/ui/base/cocoa/text_services_context_menu.h b/chromium/ui/base/cocoa/text_services_context_menu.h index e9d48efa68c..a32b76f9523 100644 --- a/chromium/ui/base/cocoa/text_services_context_menu.h +++ b/chromium/ui/base/cocoa/text_services_context_menu.h @@ -5,20 +5,36 @@ #ifndef UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ #define UI_BASE_COCOA_TEXT_SERVICES_CONTEXT_MENU_H_ +#include "base/component_export.h" #include "base/i18n/rtl.h" #include "base/macros.h" #include "base/strings/string16.h" #include "ui/base/models/simple_menu_model.h" -#include "ui/base/ui_base_export.h" namespace ui { // This class is used to append and handle the Speech and BiDi submenu for the // context menu. -class UI_BASE_EXPORT TextServicesContextMenu +class COMPONENT_EXPORT(UI_BASE) TextServicesContextMenu : public SimpleMenuModel::Delegate { public: - class UI_BASE_EXPORT Delegate { + enum MenuCommands { + // These must not overlap with the command IDs used by other menus that + // incorporate text services. + // TODO(ellyjones): This is an ugly global dependency, especially on + // //ui/views. What can we do about this? Can we get rid of the global + // implicit namespace of command IDs? + kSpeechMenu = 100, + kSpeechStartSpeaking, + kSpeechStopSpeaking, + + kWritingDirectionMenu, + kWritingDirectionDefault, + kWritingDirectionLtr, + kWritingDirectionRtl, + }; + + class COMPONENT_EXPORT(UI_BASE) Delegate { public: // Returns the selected text. virtual base::string16 GetSelectedText() const = 0; diff --git a/chromium/ui/base/cocoa/tool_tip_base_view.h b/chromium/ui/base/cocoa/tool_tip_base_view.h index 086530a4894..32d354fd525 100644 --- a/chromium/ui/base/cocoa/tool_tip_base_view.h +++ b/chromium/ui/base/cocoa/tool_tip_base_view.h @@ -7,12 +7,13 @@ #import <AppKit/AppKit.h> +#include "base/component_export.h" #import "ui/base/cocoa/base_view.h" // An NSiew that allows tooltip text to be set at the current mouse location. It // can take effect immediately, but won't appear unless the tooltip delay has // elapsed. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface ToolTipBaseView : BaseView { @private // These are part of the magic tooltip code from WebKit's WebHTMLView: diff --git a/chromium/ui/base/cocoa/touch_bar_util.h b/chromium/ui/base/cocoa/touch_bar_util.h index 457099bd9a5..f69d2a392f1 100644 --- a/chromium/ui/base/cocoa/touch_bar_util.h +++ b/chromium/ui/base/cocoa/touch_bar_util.h @@ -8,7 +8,7 @@ #import <Cocoa/Cocoa.h> #include <os/availability.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -29,30 +29,29 @@ enum TouchBarAction { }; // Logs the sample's UMA metrics into the DefaultTouchBar.Metrics histogram. -UI_BASE_EXPORT void LogTouchBarUMA(TouchBarAction command); +COMPONENT_EXPORT(UI_BASE) void LogTouchBarUMA(TouchBarAction command); // Returns the NSTouchBar Class. -UI_BASE_EXPORT Class NSTouchBar(); +COMPONENT_EXPORT(UI_BASE) Class NSTouchBar(); // Returns the NSCustomTouchBarItem Class. -UI_BASE_EXPORT Class NSCustomTouchBarItem(); +COMPONENT_EXPORT(UI_BASE) Class NSCustomTouchBarItem(); // Returns the NSGroupTouchBarItem Class. -UI_BASE_EXPORT Class NSGroupTouchBarItem(); +COMPONENT_EXPORT(UI_BASE) Class NSGroupTouchBarItem(); // Returns a stylized blue button for the touch bar. The button performs // |action| from the |target|. API_AVAILABLE(macosx(10.12.2)) -UI_BASE_EXPORT NSButton* GetBlueTouchBarButton(NSString* title, - id target, - SEL action); +COMPONENT_EXPORT(UI_BASE) +NSButton* GetBlueTouchBarButton(NSString* title, id target, SEL action); // Creates a touch bar identifier with the given |id|. -UI_BASE_EXPORT NSString* GetTouchBarId(NSString* touch_bar_id); +COMPONENT_EXPORT(UI_BASE) NSString* GetTouchBarId(NSString* touch_bar_id); // Creates a touch Bar jtem identifier. -UI_BASE_EXPORT NSString* GetTouchBarItemId(NSString* touch_bar_id, - NSString* item_id); +COMPONENT_EXPORT(UI_BASE) +NSString* GetTouchBarItemId(NSString* touch_bar_id, NSString* item_id); } // namespace ui diff --git a/chromium/ui/base/cocoa/tracking_area.h b/chromium/ui/base/cocoa/tracking_area.h index 4d7cd334e72..9d4c1c42783 100644 --- a/chromium/ui/base/cocoa/tracking_area.h +++ b/chromium/ui/base/cocoa/tracking_area.h @@ -7,15 +7,15 @@ #import <AppKit/AppKit.h> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" @class CrTrackingAreaOwnerProxy; // The CrTrackingArea can be used in place of an NSTrackingArea to shut off // messaging to the |owner| at a specific point in time. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface CrTrackingArea : NSTrackingArea { @private base::scoped_nsobject<CrTrackingAreaOwnerProxy> _ownerProxy; @@ -39,7 +39,7 @@ namespace ui { // Use an instance of this class to call |-clearOwner| on the |tracking_area_| // when this goes out of scope. -class UI_BASE_EXPORT ScopedCrTrackingArea { +class COMPONENT_EXPORT(UI_BASE) ScopedCrTrackingArea { public: // Takes ownership of |tracking_area| without retaining it. explicit ScopedCrTrackingArea(CrTrackingArea* tracking_area = nil); diff --git a/chromium/ui/base/cocoa/underlay_opengl_hosting_window.h b/chromium/ui/base/cocoa/underlay_opengl_hosting_window.h index d673c31a0f3..ec1c6c972ee 100644 --- a/chromium/ui/base/cocoa/underlay_opengl_hosting_window.h +++ b/chromium/ui/base/cocoa/underlay_opengl_hosting_window.h @@ -7,12 +7,12 @@ #import <Cocoa/Cocoa.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" // Common base class for windows that host a OpenGL surface that renders under // the window. Previously contained methods related to hole punching, now just // contains common asserts. -UI_BASE_EXPORT +COMPONENT_EXPORT(UI_BASE) @interface UnderlayOpenGLHostingWindow : NSWindow @end diff --git a/chromium/ui/base/cocoa/views_hostable.h b/chromium/ui/base/cocoa/views_hostable.h index 46f0277491f..9a9ae9324a5 100644 --- a/chromium/ui/base/cocoa/views_hostable.h +++ b/chromium/ui/base/cocoa/views_hostable.h @@ -7,7 +7,7 @@ #import <objc/objc.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" diff --git a/chromium/ui/base/cocoa/weak_ptr_nsobject.h b/chromium/ui/base/cocoa/weak_ptr_nsobject.h index fa9580e94ec..6d50aa00b9e 100644 --- a/chromium/ui/base/cocoa/weak_ptr_nsobject.h +++ b/chromium/ui/base/cocoa/weak_ptr_nsobject.h @@ -5,8 +5,8 @@ #ifndef UI_BASE_COCOA_WEAK_PTR_NSOBJECT_H_ #define UI_BASE_COCOA_WEAK_PTR_NSOBJECT_H_ +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" #if defined(__OBJC__) @class WeakPtrNSObject; @@ -20,7 +20,7 @@ namespace internal { // Non-templatized base for WeakPtrNSObjectFactory with utility functions. This // mainly serves to hide the objective-C code from the header, so it can be // included in cc files. -class UI_BASE_EXPORT WeakPtrNSObjectFactoryBase { +class COMPONENT_EXPORT(UI_BASE) WeakPtrNSObjectFactoryBase { protected: static WeakPtrNSObject* Create(void* owner); static void* UnWrap(WeakPtrNSObject* handle); diff --git a/chromium/ui/base/cocoa/window_size_constants.h b/chromium/ui/base/cocoa/window_size_constants.h index bb94018fd53..0f096c95629 100644 --- a/chromium/ui/base/cocoa/window_size_constants.h +++ b/chromium/ui/base/cocoa/window_size_constants.h @@ -5,14 +5,14 @@ #ifndef UI_BASE_COCOA_WINDOW_SIZE_CONSTANTS_H_ #define UI_BASE_COCOA_WINDOW_SIZE_CONSTANTS_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #import <Foundation/Foundation.h> namespace ui { // It is not valid to make a zero-sized window. Use this constant instead. -UI_BASE_EXPORT extern const NSRect kWindowSizeDeterminedLater; +COMPONENT_EXPORT(UI_BASE) extern const NSRect kWindowSizeDeterminedLater; } // namespace ui diff --git a/chromium/ui/base/cursor/BUILD.gn b/chromium/ui/base/cursor/BUILD.gn index e69e571c44b..f16386ecf4a 100644 --- a/chromium/ui/base/cursor/BUILD.gn +++ b/chromium/ui/base/cursor/BUILD.gn @@ -4,39 +4,123 @@ import("//build/config/ui.gni") -component("cursor") { - output_name = "ui_base_cursor" - +# This component was split from :cursor to allow Blink to depend on it without +# bringing all of //ui/base/cursor. +component("cursor_base") { + output_name = "ui_base_cursor_base" sources = [ "cursor.cc", "cursor.h", + "cursor_factory.cc", + "cursor_factory.h", "cursor_size.h", ] - - defines = [ "IS_UI_BASE_CURSOR_IMPL" ] - + defines = [ "IS_UI_BASE_CURSOR_BASE_IMPL" ] public_deps = [ "//base", "//skia", "//ui/base/cursor/mojom:cursor_type", "//ui/gfx/geometry", ] - deps = [ "//ui/gfx:geometry_skia" ] - if (use_x11 && use_aura) { - sources += [ "cursor_x11.cc" ] - - deps += [ "//ui/base/x" ] + if (is_win) { + sources += [ "cursor_win.cc" ] } - if (use_ozone) { + if (use_x11 || use_ozone) { sources += [ "cursor_ozone.cc" ] + } +} + +source_set("theme_manager") { + sources = [ + "cursor_theme_manager.cc", + "cursor_theme_manager.h", + "cursor_theme_manager_observer.h", + ] + deps = [ "//base" ] +} - deps += [ "//ui/ozone:ozone_base" ] +if (use_aura) { + component("cursor") { + output_name = "ui_base_cursor" + sources = [ + "cursor_loader.h", + "cursor_lookup.cc", + "cursor_lookup.h", + "cursor_util.cc", + "cursor_util.h", + "cursors_aura.cc", + "cursors_aura.h", + "image_cursors.cc", + "image_cursors.h", + ] + defines = [ "IS_UI_BASE_CURSOR_IMPL" ] + public_deps = [ + ":cursor_base", + "//base", + "//ui/base/cursor/mojom:cursor_type", + "//ui/display", + "//ui/gfx:native_widget_types", + ] + deps = [ + "//skia", + "//ui/base", + "//ui/gfx", + "//ui/gfx:geometry_skia", + "//ui/gfx/geometry", + "//ui/resources:ui_resources_grd", + ] + + if (is_win) { + sources += [ + "cursor_loader_win.cc", + "cursor_loader_win.h", + ] + deps += [ "//ui/resources:ui_unscaled_resources_grd" ] + } + + if (use_ozone) { + sources += [ + "ozone/bitmap_cursor_factory_ozone.cc", + "ozone/bitmap_cursor_factory_ozone.h", + ] + public_deps += [ + "//skia", + "//ui/gfx/geometry", + ] + } + + if (use_x11 || use_ozone) { + sources += [ + "cursor_loader_ozone.cc", + "cursor_loader_ozone.h", + ] + } } +} - if (is_win) { - sources += [ "cursor_win.cc" ] +source_set("unittests") { + testonly = true + sources = [] + deps = [ + "//skia", + "//testing/gtest", + "//ui/gfx/geometry", + ] + + if (!is_ios) { + sources += [ "cursor_unittest.cc" ] + deps += [ + ":cursor_base", + "//ui/base/cursor/mojom:cursor_type", + "//ui/gfx:geometry_skia", + ] + } + + if (use_aura) { + sources += [ "cursor_util_unittest.cc" ] + deps += [ ":cursor" ] } } diff --git a/chromium/ui/base/cursor/DEPS b/chromium/ui/base/cursor/DEPS deleted file mode 100644 index de08167e272..00000000000 --- a/chromium/ui/base/cursor/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+ui/ozone/public", -] diff --git a/chromium/ui/base/cursor/cursor.h b/chromium/ui/base/cursor/cursor.h index 095798ce964..835027a9ac4 100644 --- a/chromium/ui/base/cursor/cursor.h +++ b/chromium/ui/base/cursor/cursor.h @@ -21,14 +21,12 @@ namespace ui { #if defined(OS_WIN) typedef ::HCURSOR PlatformCursor; -#elif defined(USE_X11) -typedef unsigned long PlatformCursor; #else typedef void* PlatformCursor; #endif // Ref-counted cursor that supports both default and custom cursors. -class COMPONENT_EXPORT(UI_BASE_CURSOR) Cursor { +class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) Cursor { public: Cursor(); diff --git a/chromium/ui/base/cursor/cursor_factory.cc b/chromium/ui/base/cursor/cursor_factory.cc new file mode 100644 index 00000000000..43645a5d446 --- /dev/null +++ b/chromium/ui/base/cursor/cursor_factory.cc @@ -0,0 +1,68 @@ +// 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/base/cursor/cursor_factory.h" + +#include <ostream> + +#include "base/check.h" +#include "base/check_op.h" +#include "base/notreached.h" + +namespace ui { + +namespace { + +CursorFactory* g_instance = nullptr; + +} // namespace + +CursorFactory::CursorFactory() { + DCHECK(!g_instance) << "There should only be a single CursorFactory."; + g_instance = this; +} + +CursorFactory::~CursorFactory() { + DCHECK_EQ(g_instance, this); + g_instance = nullptr; +} + +CursorFactory* CursorFactory::GetInstance() { + DCHECK(g_instance); + return g_instance; +} + +base::Optional<PlatformCursor> CursorFactory::GetDefaultCursor( + mojom::CursorType type) { + NOTIMPLEMENTED(); + return base::nullopt; +} + +PlatformCursor CursorFactory::CreateImageCursor(const SkBitmap& bitmap, + const gfx::Point& hotspot) { + NOTIMPLEMENTED(); + return 0; +} + +PlatformCursor CursorFactory::CreateAnimatedCursor( + const std::vector<SkBitmap>& bitmaps, + const gfx::Point& hotspot, + int frame_delay_ms) { + NOTIMPLEMENTED(); + return 0; +} + +void CursorFactory::RefImageCursor(PlatformCursor cursor) { + NOTIMPLEMENTED(); +} + +void CursorFactory::UnrefImageCursor(PlatformCursor cursor) { + NOTIMPLEMENTED(); +} + +void CursorFactory::ObserveThemeChanges() { + NOTIMPLEMENTED(); +} + +} // namespace ui diff --git a/chromium/ui/base/cursor/cursor_factory.h b/chromium/ui/base/cursor/cursor_factory.h new file mode 100644 index 00000000000..f038a422819 --- /dev/null +++ b/chromium/ui/base/cursor/cursor_factory.h @@ -0,0 +1,67 @@ +// 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_BASE_CURSOR_CURSOR_FACTORY_H_ +#define UI_BASE_CURSOR_CURSOR_FACTORY_H_ + +#include <vector> + +#include "base/component_export.h" +#include "base/optional.h" +#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" + +class SkBitmap; + +namespace gfx { +class Point; +} + +namespace ui { +using PlatformCursor = void*; + +class COMPONENT_EXPORT(UI_BASE_CURSOR_BASE) CursorFactory { + public: + CursorFactory(); + virtual ~CursorFactory(); + + // Returns the thread-local instance. + static CursorFactory* GetInstance(); + + // Return the default cursor of the specified type. The types are listed in + // ui/base/cursor/cursor.h. Default cursors are managed by the implementation + // and must live indefinitely; there's no way to know when to free them. + // nullptr may be a valid value for the hidden cursor. When a default cursor + // is not available, base::nullopt is returned. + virtual base::Optional<PlatformCursor> GetDefaultCursor( + mojom::CursorType type); + + // Return a image cursor from the specified image & hotspot. Image cursors + // are referenced counted and have an initial refcount of 1. Therefore, each + // CreateImageCursor call must be matched with a call to UnrefImageCursor. + virtual PlatformCursor CreateImageCursor(const SkBitmap& bitmap, + const gfx::Point& hotspot); + + // Return a animated cursor from the specified image & hotspot. Animated + // cursors are referenced counted and have an initial refcount of 1. + // Therefore, each CreateAnimatedCursor call must be matched with a call to + // UnrefImageCursor. + virtual PlatformCursor CreateAnimatedCursor( + const std::vector<SkBitmap>& bitmaps, + const gfx::Point& hotspot, + int frame_delay_ms); + + // Increment platform image cursor refcount. + virtual void RefImageCursor(PlatformCursor cursor); + + // Decrement platform image cursor refcount. + virtual void UnrefImageCursor(PlatformCursor cursor); + + // Called after CursorThemeManager is initialized, to be able to track + // cursor theme and size changes. + virtual void ObserveThemeChanges(); +}; + +} // namespace ui + +#endif // UI_BASE_CURSOR_CURSOR_FACTORY_H_ diff --git a/chromium/ui/base/cursor/cursor_loader.h b/chromium/ui/base/cursor/cursor_loader.h index 95141089ffe..2553c54e488 100644 --- a/chromium/ui/base/cursor/cursor_loader.h +++ b/chromium/ui/base/cursor/cursor_loader.h @@ -5,18 +5,19 @@ #ifndef UI_BASE_CURSOR_CURSOR_LOADER_H_ #define UI_BASE_CURSOR_CURSOR_LOADER_H_ -#include "base/logging.h" +#include "base/component_export.h" #include "base/macros.h" -#include "base/strings/string16.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" -#include "ui/base/ui_base_export.h" #include "ui/display/display.h" -#include "ui/gfx/geometry/point.h" #include "ui/gfx/native_widget_types.h" +namespace gfx { +class Point; +} + namespace ui { -class UI_BASE_EXPORT CursorLoader { +class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoader { public: CursorLoader() : scale_(1.f), rotation_(display::Display::ROTATE_0) {} virtual ~CursorLoader() {} diff --git a/chromium/ui/base/cursor/cursor_loader_ozone.cc b/chromium/ui/base/cursor/cursor_loader_ozone.cc index 8668095578e..6df16b5f1e7 100644 --- a/chromium/ui/base/cursor/cursor_loader_ozone.cc +++ b/chromium/ui/base/cursor/cursor_loader_ozone.cc @@ -6,15 +6,16 @@ #include <vector> -#include "ui/base/cursor/cursor.h" +#include "ui/base/cursor/cursor_factory.h" +#include "ui/base/cursor/cursor_size.h" #include "ui/base/cursor/cursor_util.h" +#include "ui/base/cursor/cursors_aura.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" -#include "ui/ozone/public/cursor_factory_ozone.h" namespace ui { CursorLoaderOzone::CursorLoaderOzone() { - factory_ = CursorFactoryOzone::GetInstance(); + factory_ = CursorFactory::GetInstance(); } CursorLoaderOzone::~CursorLoaderOzone() { @@ -29,7 +30,7 @@ void CursorLoaderOzone::LoadImageCursor(mojom::CursorType id, GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap); - image_cursors_[id] = factory_->CreateImageCursor(bitmap, hotspot, scale()); + image_cursors_[id] = factory_->CreateImageCursor(bitmap, hotspot); } void CursorLoaderOzone::LoadAnimatedCursor(mojom::CursorType id, @@ -43,7 +44,7 @@ void CursorLoaderOzone::LoadAnimatedCursor(mojom::CursorType id, resource_id, scale(), rotation(), &hotspot, &bitmaps); image_cursors_[id] = - factory_->CreateAnimatedCursor(bitmaps, hotspot, frame_delay_ms, scale()); + factory_->CreateAnimatedCursor(bitmaps, hotspot, frame_delay_ms); } void CursorLoaderOzone::UnloadAll() { @@ -53,22 +54,48 @@ void CursorLoaderOzone::UnloadAll() { } void CursorLoaderOzone::SetPlatformCursor(gfx::NativeCursor* cursor) { - mojom::CursorType native_type = cursor->type(); - PlatformCursor platform; - - if (image_cursors_.count(native_type)) { - // An image cursor is loaded for this type. - platform = image_cursors_[native_type]; - } else if (native_type == mojom::CursorType::kCustom) { - // The platform cursor was already set via WebCursor::GetPlatformCursor. - platform = cursor->platform(); - } else { - // Use default cursor of this type. - platform = factory_->GetDefaultCursor(native_type); - } + DCHECK(cursor); + // The platform cursor was already set via WebCursor::GetPlatformCursor. + if (cursor->type() == mojom::CursorType::kCustom) + return; cursor->set_image_scale_factor(scale()); - cursor->SetPlatformCursor(platform); + cursor->SetPlatformCursor(CursorFromType(cursor->type())); +} + +PlatformCursor CursorLoaderOzone::CursorFromType(mojom::CursorType type) { + // An image cursor is loaded for this type. + if (image_cursors_.count(type)) + return image_cursors_[type]; + + // Check if there's a default platform cursor available. + base::Optional<PlatformCursor> default_cursor = + factory_->GetDefaultCursor(type); + if (default_cursor) + return *default_cursor; + + // Loads the default Aura cursor bitmap for the cursor type. Falls back on + // pointer cursor if this fails. + PlatformCursor platform = CreateFallbackCursor(type); + if (!platform && type != mojom::CursorType::kPointer) { + platform = CursorFromType(mojom::CursorType::kPointer); + factory_->RefImageCursor(platform); + image_cursors_[type] = platform; + } + DCHECK(platform) << "Failed to load a fallback bitmap for cursor " << type; + return platform; +} + +// Gets default Aura cursor bitmap/hotspot and creates a PlatformCursor with it. +PlatformCursor CursorLoaderOzone::CreateFallbackCursor(mojom::CursorType type) { + int resource_id; + gfx::Point point; + if (ui::GetCursorDataFor(ui::CursorSize::kNormal, type, scale(), &resource_id, + &point)) { + LoadImageCursor(type, resource_id, point); + return image_cursors_[type]; + } + return nullptr; } CursorLoader* CursorLoader::Create() { diff --git a/chromium/ui/base/cursor/cursor_loader_ozone.h b/chromium/ui/base/cursor/cursor_loader_ozone.h index 9d561727761..ccd23a3c9e0 100644 --- a/chromium/ui/base/cursor/cursor_loader_ozone.h +++ b/chromium/ui/base/cursor/cursor_loader_ozone.h @@ -7,19 +7,17 @@ #include <map> +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor_loader.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" namespace ui { +class CursorFactory; -class CursorFactoryOzone; - -class UI_BASE_EXPORT CursorLoaderOzone : public CursorLoader { +class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoaderOzone : public CursorLoader { public: - // CursorLoaderOzone will use CursorFactoryOzone corresponding to the thread - // it was constructed on. CursorLoaderOzone(); ~CursorLoaderOzone() override; @@ -35,9 +33,12 @@ class UI_BASE_EXPORT CursorLoaderOzone : public CursorLoader { void SetPlatformCursor(gfx::NativeCursor* cursor) override; private: + PlatformCursor CursorFromType(mojom::CursorType type); + PlatformCursor CreateFallbackCursor(mojom::CursorType type); + // Pointers are owned by ResourceBundle and must not be freed here. std::map<mojom::CursorType, PlatformCursor> image_cursors_; - CursorFactoryOzone* factory_ = nullptr; + CursorFactory* factory_ = nullptr; DISALLOW_COPY_AND_ASSIGN(CursorLoaderOzone); }; diff --git a/chromium/ui/base/cursor/cursor_loader_win.cc b/chromium/ui/base/cursor/cursor_loader_win.cc index d981eb79cda..735568dddc0 100644 --- a/chromium/ui/base/cursor/cursor_loader_win.cc +++ b/chromium/ui/base/cursor/cursor_loader_win.cc @@ -7,7 +7,7 @@ #include <windows.h> #include "base/lazy_instance.h" -#include "base/strings/string16.h" +#include "base/notreached.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/resources/grit/ui_unscaled_resources.h" diff --git a/chromium/ui/base/cursor/cursor_loader_win.h b/chromium/ui/base/cursor/cursor_loader_win.h index f17ca9f965b..bf3ec63c961 100644 --- a/chromium/ui/base/cursor/cursor_loader_win.h +++ b/chromium/ui/base/cursor/cursor_loader_win.h @@ -5,13 +5,14 @@ #ifndef UI_BASE_CURSOR_CURSOR_LOADER_WIN_H_ #define UI_BASE_CURSOR_CURSOR_LOADER_WIN_H_ -#include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" +#include "base/strings/string16.h" #include "ui/base/cursor/cursor_loader.h" namespace ui { -class UI_BASE_EXPORT CursorLoaderWin : public CursorLoader { +class COMPONENT_EXPORT(UI_BASE_CURSOR) CursorLoaderWin : public CursorLoader { public: CursorLoaderWin(); ~CursorLoaderWin() override; diff --git a/chromium/ui/base/cursor/cursor_loader_x11.cc b/chromium/ui/base/cursor/cursor_loader_x11.cc deleted file mode 100644 index e0b52555d62..00000000000 --- a/chromium/ui/base/cursor/cursor_loader_x11.cc +++ /dev/null @@ -1,310 +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/base/cursor/cursor_loader_x11.h" - -#include <float.h> - -#include "base/check.h" -#include "base/notreached.h" -#include "build/build_config.h" -#include "skia/ext/image_operations.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/cursor/cursor_size.h" -#include "ui/base/cursor/cursor_util.h" -#include "ui/base/cursor/cursors_aura.h" -#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" -#include "ui/base/x/x11_util.h" -#include "ui/display/display.h" -#include "ui/gfx/geometry/point_conversions.h" -#include "ui/gfx/geometry/size_conversions.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/skbitmap_operations.h" -#include "ui/gfx/skia_util.h" - -namespace ui { - -namespace { - -// Load a cursor with a list of css names or shapes in order of decreasing -// priority. -::Cursor LoadFontCursor() { - return x11::None; -} - -template <typename... Ts> -::Cursor LoadFontCursor(int shape, Ts... ts); - -template <typename... Ts> -::Cursor LoadFontCursor(const char* name, Ts... ts) { - ::Cursor cursor = XcursorLibraryLoadCursor(gfx::GetXDisplay(), name); - if (cursor != x11::None) - return cursor; - return LoadFontCursor(ts...); -} - -template <typename... Ts> -::Cursor LoadFontCursor(int shape, Ts... ts) { - ::Cursor cursor = XCreateFontCursor(gfx::GetXDisplay(), shape); - if (cursor != x11::None) - return cursor; - return LoadFontCursor(ts...); -} - -::Cursor LoadFontCursorForCursorType(mojom::CursorType id) { - switch (id) { - case mojom::CursorType::kMiddlePanning: - return LoadFontCursor("all-scroll", XC_fleur); - case mojom::CursorType::kMiddlePanningVertical: - return LoadFontCursor("v-scroll"); - case mojom::CursorType::kMiddlePanningHorizontal: - return LoadFontCursor("h-scroll"); - case mojom::CursorType::kNone: - return LoadFontCursor("none"); - case mojom::CursorType::kGrab: - return LoadFontCursor("openhand", "grab"); - case mojom::CursorType::kGrabbing: - return LoadFontCursor("closedhand", "grabbing", XC_hand2); - case mojom::CursorType::kNull: - case mojom::CursorType::kPointer: - return LoadFontCursor("left_ptr", XC_left_ptr); - case mojom::CursorType::kMove: - return LoadFontCursor("all-scroll", XC_fleur); - case mojom::CursorType::kCross: - return LoadFontCursor("crosshair", XC_cross); - case mojom::CursorType::kHand: - return LoadFontCursor("pointer", "hand", XC_hand2); - case mojom::CursorType::kIBeam: - return LoadFontCursor("text", XC_xterm); - case mojom::CursorType::kProgress: - return LoadFontCursor("progress", "left_ptr_watch", XC_watch); - case mojom::CursorType::kWait: - return LoadFontCursor("wait", XC_watch); - case mojom::CursorType::kHelp: - return LoadFontCursor("help"); - case mojom::CursorType::kEastResize: - case mojom::CursorType::kEastPanning: - return LoadFontCursor("e-resize", XC_right_side); - case mojom::CursorType::kNorthResize: - case mojom::CursorType::kNorthPanning: - return LoadFontCursor("n-resize", XC_top_side); - case mojom::CursorType::kNorthEastResize: - case mojom::CursorType::kNorthEastPanning: - return LoadFontCursor("ne-resize", XC_top_right_corner); - case mojom::CursorType::kNorthWestResize: - case mojom::CursorType::kNorthWestPanning: - return LoadFontCursor("nw-resize", XC_top_left_corner); - case mojom::CursorType::kSouthResize: - case mojom::CursorType::kSouthPanning: - return LoadFontCursor("s-resize", XC_bottom_side); - case mojom::CursorType::kSouthEastResize: - case mojom::CursorType::kSouthEastPanning: - return LoadFontCursor("se-resize", XC_bottom_right_corner); - case mojom::CursorType::kSouthWestResize: - case mojom::CursorType::kSouthWestPanning: - return LoadFontCursor("sw-resize", XC_bottom_left_corner); - case mojom::CursorType::kWestResize: - case mojom::CursorType::kWestPanning: - return LoadFontCursor("w-resize", XC_right_side); - case mojom::CursorType::kNorthSouthResize: - return LoadFontCursor(XC_sb_v_double_arrow, "ns-resize"); - case mojom::CursorType::kEastWestResize: - return LoadFontCursor(XC_sb_h_double_arrow, "ew-resize"); - case mojom::CursorType::kColumnResize: - return LoadFontCursor("col-resize", XC_sb_h_double_arrow); - case mojom::CursorType::kRowResize: - return LoadFontCursor("row-resize", XC_sb_v_double_arrow); - case mojom::CursorType::kNorthEastSouthWestResize: - return LoadFontCursor("size_bdiag", "nesw-resize", "fd_double_arrow"); - case mojom::CursorType::kNorthWestSouthEastResize: - return LoadFontCursor("size_fdiag", "nwse-resize", "bd_double_arrow"); - case mojom::CursorType::kVerticalText: - return LoadFontCursor("vertical-text"); - case mojom::CursorType::kZoomIn: - return LoadFontCursor("zoom-in"); - case mojom::CursorType::kZoomOut: - return LoadFontCursor("zoom-out"); - case mojom::CursorType::kCell: - return LoadFontCursor("cell", XC_plus); - case mojom::CursorType::kContextMenu: - return LoadFontCursor("context-menu"); - case mojom::CursorType::kAlias: - return LoadFontCursor("alias"); - case mojom::CursorType::kNoDrop: - return LoadFontCursor("no-drop"); - case mojom::CursorType::kCopy: - return LoadFontCursor("copy"); - case mojom::CursorType::kNotAllowed: - return LoadFontCursor("not-allowed", "crossed_circle"); - case mojom::CursorType::kDndNone: - return LoadFontCursor("dnd-none", XC_hand2); - case mojom::CursorType::kDndMove: - return LoadFontCursor("dnd-move", XC_hand2); - case mojom::CursorType::kDndCopy: - return LoadFontCursor("dnd-copy", XC_hand2); - case mojom::CursorType::kDndLink: - return LoadFontCursor("dnd-link", XC_hand2); - case mojom::CursorType::kCustom: - NOTREACHED(); - return LoadFontCursor(); - } - NOTREACHED() << "Case not handled for " << static_cast<int>(id); - return LoadFontCursor(); -} - -} // namespace - -CursorLoader* CursorLoader::Create() { - return new CursorLoaderX11; -} - -CursorLoaderX11::ImageCursor::ImageCursor(XcursorImage* x_image, - float scale, - display::Display::Rotation rotation) - : scale(scale), rotation(rotation) { - cursor = CreateReffedCustomXCursor(x_image); -} - -CursorLoaderX11::ImageCursor::~ImageCursor() { - UnrefCustomXCursor(cursor); -} - -CursorLoaderX11::CursorLoaderX11() - : display_(gfx::GetXDisplay()), - invisible_cursor_(CreateInvisibleCursor(), gfx::GetXDisplay()) { - auto* cursor_theme_manager = CursorThemeManagerLinux::GetInstance(); - if (cursor_theme_manager) - cursor_theme_observer_.Add(cursor_theme_manager); -} - -CursorLoaderX11::~CursorLoaderX11() { - UnloadAll(); -} - -void CursorLoaderX11::LoadImageCursor(mojom::CursorType id, - int resource_id, - const gfx::Point& hot) { - SkBitmap bitmap; - gfx::Point hotspot = hot; - - GetImageCursorBitmap(resource_id, scale(), rotation(), &hotspot, &bitmap); - XcursorImage* x_image = SkBitmapToXcursorImage(bitmap, hotspot); - image_cursors_[id] = - std::make_unique<ImageCursor>(x_image, scale(), rotation()); -} - -void CursorLoaderX11::LoadAnimatedCursor(mojom::CursorType id, - int resource_id, - const gfx::Point& hot, - int frame_delay_ms) { - std::vector<SkBitmap> bitmaps; - gfx::Point hotspot = hot; - - GetAnimatedCursorBitmaps(resource_id, scale(), rotation(), &hotspot, - &bitmaps); - - XcursorImages* x_images = XcursorImagesCreate(bitmaps.size()); - x_images->nimage = bitmaps.size(); - - for (unsigned int frame = 0; frame < bitmaps.size(); ++frame) { - XcursorImage* x_image = SkBitmapToXcursorImage(bitmaps[frame], hotspot); - x_image->delay = frame_delay_ms; - x_images->images[frame] = x_image; - } - - animated_cursors_[id] = std::make_pair( - XcursorImagesLoadCursor(gfx::GetXDisplay(), x_images), x_images); -} - -void CursorLoaderX11::UnloadAll() { - image_cursors_.clear(); - - // Free animated cursors and images. - for (const auto& cursor : animated_cursors_) { - XcursorImagesDestroy( - cursor.second.second); // also frees individual frames. - XFreeCursor(gfx::GetXDisplay(), cursor.second.first); - } -} - -void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) { - DCHECK(cursor); - - if (*cursor == mojom::CursorType::kNone) { - cursor->SetPlatformCursor(invisible_cursor_.get()); - return; - } - - if (*cursor == mojom::CursorType::kCustom) - return; - - cursor->set_image_scale_factor(scale()); - cursor->SetPlatformCursor(CursorFromId(cursor->type())); -} - -const XcursorImage* CursorLoaderX11::GetXcursorImageForTest( - mojom::CursorType id) { - return test::GetCachedXcursorImage(image_cursors_[id]->cursor); -} - -void CursorLoaderX11::OnCursorThemeNameChanged( - const std::string& cursor_theme_name) { - XcursorSetTheme(display_, cursor_theme_name.c_str()); - ClearThemeCursors(); -} - -void CursorLoaderX11::OnCursorThemeSizeChanged(int cursor_theme_size) { - XcursorSetDefaultSize(display_, cursor_theme_size); - ClearThemeCursors(); -} - -bool CursorLoaderX11::IsImageCursor(gfx::NativeCursor native_cursor) { - mojom::CursorType type = native_cursor.type(); - return image_cursors_.count(type) || animated_cursors_.count(type); -} - -::Cursor CursorLoaderX11::CursorFromId(mojom::CursorType id) { - auto font_it = font_cursors_.find(id); - if (font_it != font_cursors_.end()) - return font_it->second; - auto image_it = image_cursors_.find(id); - if (image_it != image_cursors_.end()) { - if (image_it->second->scale == scale() && - image_it->second->rotation == rotation()) { - return image_it->second->cursor; - } else { - image_cursors_.erase(image_it); - } - } - - // First try to load the cursor directly. - ::Cursor cursor = LoadFontCursorForCursorType(id); - if (cursor != x11::None) { - font_cursors_[id] = cursor; - return cursor; - } - - // If the theme is missing the desired cursor, use a chromium-supplied - // fallback icon. - int resource_id; - gfx::Point point; - if (ui::GetCursorDataFor(ui::CursorSize::kNormal, id, scale(), &resource_id, - &point)) { - LoadImageCursor(id, resource_id, point); - return image_cursors_[id]->cursor; - } - - // As a last resort, return a left pointer. - cursor = XCreateFontCursor(display_, XC_left_ptr); - DCHECK(cursor); - font_cursors_[id] = cursor; - return cursor; -} - -void CursorLoaderX11::ClearThemeCursors() { - font_cursors_.clear(); - image_cursors_.clear(); -} - -} // namespace ui diff --git a/chromium/ui/base/cursor/cursor_loader_x11.h b/chromium/ui/base/cursor/cursor_loader_x11.h deleted file mode 100644 index 26870d09e03..00000000000 --- a/chromium/ui/base/cursor/cursor_loader_x11.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ -#define UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ - -#include <map> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/scoped_observer.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/cursor/cursor_loader.h" -#include "ui/base/cursor/cursor_theme_manager_linux.h" -#include "ui/base/cursor/cursor_theme_manager_linux_observer.h" -#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" -#include "ui/base/ui_base_export.h" -#include "ui/base/x/x11_util.h" -#include "ui/gfx/x/x11.h" - -namespace ui { - -class UI_BASE_EXPORT CursorLoaderX11 : public CursorLoader, - public CursorThemeManagerLinuxObserver { - public: - CursorLoaderX11(); - ~CursorLoaderX11() override; - - // Overridden from CursorLoader: - void LoadImageCursor(mojom::CursorType id, - int resource_id, - const gfx::Point& hot) override; - void LoadAnimatedCursor(mojom::CursorType id, - int resource_id, - const gfx::Point& hot, - int frame_delay_ms) override; - void UnloadAll() override; - void SetPlatformCursor(gfx::NativeCursor* cursor) override; - - const XcursorImage* GetXcursorImageForTest(mojom::CursorType id); - - protected: - // CursorThemeManagerLinux: - void OnCursorThemeNameChanged(const std::string& cursor_theme_name) override; - void OnCursorThemeSizeChanged(int cursor_theme_size) override; - - private: - struct ImageCursor { - ImageCursor(XcursorImage* x_image, - float scale, - display::Display::Rotation rotation); - ~ImageCursor(); - - ::Cursor cursor; - float scale; - display::Display::Rotation rotation; - }; - - // Returns true if we have an image resource loaded for the |native_cursor|. - bool IsImageCursor(gfx::NativeCursor native_cursor); - - // Loads a new cursor corresponding to |id|. - ::Cursor CursorFromId(mojom::CursorType id); - - void ClearThemeCursors(); - - XDisplay* display_; - - // A map from a cursor native type to X cursor. - std::map<mojom::CursorType, ::Cursor> font_cursors_; - - // A map to hold all image cursors. It maps the cursor ID to the X Cursor, the - // display's scale factor, and the display's rotation. - std::map<mojom::CursorType, std::unique_ptr<ImageCursor>> image_cursors_; - - // A map to hold all animated cursors. It maps the cursor ID to the pair of - // the X Cursor and the corresponding XcursorImages. We need a pointer to the - // images so that we can free them on destruction. - std::map<mojom::CursorType, std::pair<::Cursor, XcursorImages*>> - animated_cursors_; - - const XScopedCursor invisible_cursor_; - - ScopedObserver<CursorThemeManagerLinux, CursorThemeManagerLinuxObserver> - cursor_theme_observer_{this}; - - DISALLOW_COPY_AND_ASSIGN(CursorLoaderX11); -}; - -} // namespace ui - -#endif // UI_BASE_CURSOR_CURSOR_LOADER_X11_H_ diff --git a/chromium/ui/base/cursor/cursor_lookup.h b/chromium/ui/base/cursor/cursor_lookup.h index 47aefe22f6c..82f908422a1 100644 --- a/chromium/ui/base/cursor/cursor_lookup.h +++ b/chromium/ui/base/cursor/cursor_lookup.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_CURSOR_CURSOR_LOOKUP_H_ #define UI_BASE_CURSOR_CURSOR_LOOKUP_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" class SkBitmap; @@ -16,9 +16,11 @@ class Point; namespace ui { class Cursor; -SkBitmap UI_BASE_EXPORT GetCursorBitmap(const Cursor& cursor); +COMPONENT_EXPORT(UI_BASE_CURSOR) +SkBitmap GetCursorBitmap(const Cursor& cursor); -gfx::Point UI_BASE_EXPORT GetCursorHotspot(const Cursor& cursor); +COMPONENT_EXPORT(UI_BASE_CURSOR) +gfx::Point GetCursorHotspot(const Cursor& cursor); } // namespace ui diff --git a/chromium/ui/base/cursor/cursor_ozone.cc b/chromium/ui/base/cursor/cursor_ozone.cc index c4ef8c4d45e..b41f4ca3b67 100644 --- a/chromium/ui/base/cursor/cursor_ozone.cc +++ b/chromium/ui/base/cursor/cursor_ozone.cc @@ -4,18 +4,18 @@ #include "ui/base/cursor/cursor.h" -#include "ui/ozone/public/cursor_factory_ozone.h" +#include "ui/base/cursor/cursor_factory.h" namespace ui { void Cursor::RefCustomCursor() { if (platform_cursor_) - CursorFactoryOzone::GetInstance()->RefImageCursor(platform_cursor_); + CursorFactory::GetInstance()->RefImageCursor(platform_cursor_); } void Cursor::UnrefCustomCursor() { if (platform_cursor_) - CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_); + CursorFactory::GetInstance()->UnrefImageCursor(platform_cursor_); } } // namespace ui diff --git a/chromium/ui/base/cursor/cursor_theme_manager.cc b/chromium/ui/base/cursor/cursor_theme_manager.cc new file mode 100644 index 00000000000..665725a1c27 --- /dev/null +++ b/chromium/ui/base/cursor/cursor_theme_manager.cc @@ -0,0 +1,47 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/cursor/cursor_theme_manager.h" + +#include "base/check.h" +#include "base/check_op.h" + +namespace ui { + +namespace { + +CursorThemeManager* g_instance = nullptr; + +} + +CursorThemeManager::~CursorThemeManager() { + DCHECK_EQ(g_instance, this); + g_instance = nullptr; +} + +// static +CursorThemeManager* CursorThemeManager::GetInstance() { + return g_instance; +} + +void CursorThemeManager::AddObserver(CursorThemeManagerObserver* observer) { + cursor_theme_observers_.AddObserver(observer); + std::string name = GetCursorThemeName(); + if (!name.empty()) + observer->OnCursorThemeNameChanged(name); + int size = GetCursorThemeSize(); + if (size) + observer->OnCursorThemeSizeChanged(size); +} + +void CursorThemeManager::RemoveObserver(CursorThemeManagerObserver* observer) { + cursor_theme_observers_.RemoveObserver(observer); +} + +CursorThemeManager::CursorThemeManager() { + DCHECK(!g_instance); + g_instance = this; +} + +} // namespace ui diff --git a/chromium/ui/base/cursor/cursor_theme_manager.h b/chromium/ui/base/cursor/cursor_theme_manager.h new file mode 100644 index 00000000000..a6d09f04945 --- /dev/null +++ b/chromium/ui/base/cursor/cursor_theme_manager.h @@ -0,0 +1,46 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_CURSOR_CURSOR_THEME_MANAGER_H_ +#define UI_BASE_CURSOR_CURSOR_THEME_MANAGER_H_ + +#include <string> + +#include "base/observer_list.h" +#include "ui/base/cursor/cursor_theme_manager_observer.h" + +namespace ui { + +class CursorThemeManager { + public: + CursorThemeManager(const CursorThemeManager&) = delete; + CursorThemeManager& operator=(const CursorThemeManager&) = delete; + virtual ~CursorThemeManager(); + + static CursorThemeManager* GetInstance(); + + // Adds |observer| and makes initial OnCursorThemNameChanged() and/or + // OnCursorThemeSizeChanged() calls if the respective settings were set. + void AddObserver(CursorThemeManagerObserver* observer); + + void RemoveObserver(CursorThemeManagerObserver* observer); + + protected: + CursorThemeManager(); + + const base::ObserverList<CursorThemeManagerObserver>& + cursor_theme_observers() { + return cursor_theme_observers_; + } + + virtual std::string GetCursorThemeName() = 0; + virtual int GetCursorThemeSize() = 0; + + private: + base::ObserverList<CursorThemeManagerObserver> cursor_theme_observers_; +}; + +} // namespace ui + +#endif // UI_BASE_CURSOR_CURSOR_THEME_MANAGER_H_ diff --git a/chromium/ui/base/cursor/cursor_theme_manager_linux.cc b/chromium/ui/base/cursor/cursor_theme_manager_linux.cc deleted file mode 100644 index f825b745f5d..00000000000 --- a/chromium/ui/base/cursor/cursor_theme_manager_linux.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/base/cursor/cursor_theme_manager_linux.h" - -namespace ui { - -// static -CursorThemeManagerLinux* CursorThemeManagerLinux::instance_ = nullptr; - -// static -void CursorThemeManagerLinux::SetInstance(CursorThemeManagerLinux* instance) { - instance_ = instance; -} - -// static -CursorThemeManagerLinux* CursorThemeManagerLinux::GetInstance() { - return instance_; -} - -CursorThemeManagerLinux::CursorThemeManagerLinux() = default; - -CursorThemeManagerLinux::~CursorThemeManagerLinux() = default; - -void CursorThemeManagerLinux::AddObserver( - CursorThemeManagerLinuxObserver* observer) { - cursor_theme_observers_.AddObserver(observer); - std::string name = GetCursorThemeName(); - if (!name.empty()) - observer->OnCursorThemeNameChanged(name); - int size = GetCursorThemeSize(); - if (size) - observer->OnCursorThemeSizeChanged(size); -} - -void CursorThemeManagerLinux::RemoveObserver( - CursorThemeManagerLinuxObserver* observer) { - cursor_theme_observers_.RemoveObserver(observer); -} - -} // namespace ui diff --git a/chromium/ui/base/cursor/cursor_theme_manager_linux.h b/chromium/ui/base/cursor/cursor_theme_manager_linux.h deleted file mode 100644 index 464d397cec5..00000000000 --- a/chromium/ui/base/cursor/cursor_theme_manager_linux.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_H_ -#define UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_H_ - -#include <string> - -#include "base/macros.h" -#include "base/observer_list.h" -#include "ui/base/cursor/cursor_theme_manager_linux_observer.h" -#include "ui/base/ui_base_export.h" - -namespace ui { - -class UI_BASE_EXPORT CursorThemeManagerLinux { - public: - virtual ~CursorThemeManagerLinux(); - - static void SetInstance(CursorThemeManagerLinux* instance); - - static CursorThemeManagerLinux* GetInstance(); - - // Adds |observer| and makes initial OnCursorThemNameChanged() and/or - // OnCursorThemeSizeChanged() calls if the respective settings were set. - void AddObserver(CursorThemeManagerLinuxObserver* observer); - - void RemoveObserver(CursorThemeManagerLinuxObserver* observer); - - protected: - CursorThemeManagerLinux(); - - const base::ObserverList<CursorThemeManagerLinuxObserver>& - cursor_theme_observers() { - return cursor_theme_observers_; - } - - virtual std::string GetCursorThemeName() = 0; - virtual int GetCursorThemeSize() = 0; - - private: - static CursorThemeManagerLinux* instance_; - - base::ObserverList<CursorThemeManagerLinuxObserver> cursor_theme_observers_; - - DISALLOW_COPY_AND_ASSIGN(CursorThemeManagerLinux); -}; - -} // namespace ui - -#endif // UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_H_ diff --git a/chromium/ui/base/cursor/cursor_theme_manager_linux_observer.h b/chromium/ui/base/cursor/cursor_theme_manager_observer.h index 73a3b42f343..028a8bb7dfe 100644 --- a/chromium/ui/base/cursor/cursor_theme_manager_linux_observer.h +++ b/chromium/ui/base/cursor/cursor_theme_manager_observer.h @@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_OBSERVER_H_ -#define UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_OBSERVER_H_ +#ifndef UI_BASE_CURSOR_CURSOR_THEME_MANAGER_OBSERVER_H_ +#define UI_BASE_CURSOR_CURSOR_THEME_MANAGER_OBSERVER_H_ #include <string> #include "base/observer_list_types.h" -#include "ui/base/ui_base_export.h" namespace ui { -class UI_BASE_EXPORT CursorThemeManagerLinuxObserver - : public base::CheckedObserver { +class CursorThemeManagerObserver : public base::CheckedObserver { public: // |cursor_theme_name| will be nonempty. virtual void OnCursorThemeNameChanged( @@ -23,9 +21,9 @@ class UI_BASE_EXPORT CursorThemeManagerLinuxObserver virtual void OnCursorThemeSizeChanged(int cursor_theme_size) = 0; protected: - ~CursorThemeManagerLinuxObserver() override = default; + ~CursorThemeManagerObserver() override = default; }; } // namespace ui -#endif // UI_BASE_CURSOR_CURSOR_THEME_MANAGER_LINUX_OBSERVER_H_ +#endif // UI_BASE_CURSOR_CURSOR_THEME_MANAGER_OBSERVER_H_ diff --git a/chromium/ui/base/cursor/cursor_unittest.cc b/chromium/ui/base/cursor/cursor_unittest.cc index ef2d9e1e58f..d69ecfcc2cd 100644 --- a/chromium/ui/base/cursor/cursor_unittest.cc +++ b/chromium/ui/base/cursor/cursor_unittest.cc @@ -4,12 +4,10 @@ #include "ui/base/cursor/cursor.h" -#include <algorithm> - #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/cursor/cursor_lookup.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/skia_util.h" namespace ui { @@ -38,22 +36,21 @@ TEST(CursorTest, CustomType) { const gfx::Point kHotspot = gfx::Point(5, 2); cursor.set_custom_hotspot(kHotspot); - EXPECT_EQ(kHotspot, GetCursorHotspot(cursor)); + EXPECT_EQ(kHotspot, cursor.custom_hotspot()); SkBitmap bitmap; bitmap.allocN32Pixels(10, 10); bitmap.eraseColor(SK_ColorRED); cursor.set_custom_bitmap(bitmap); - EXPECT_EQ(bitmap.getGenerationID(), - GetCursorBitmap(cursor).getGenerationID()); - EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, GetCursorBitmap(cursor))); + EXPECT_EQ(bitmap.getGenerationID(), cursor.custom_bitmap().getGenerationID()); + EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, cursor.custom_bitmap())); Cursor copy(cursor); - EXPECT_EQ(GetCursorBitmap(cursor).getGenerationID(), - GetCursorBitmap(copy).getGenerationID()); + EXPECT_EQ(cursor.custom_bitmap().getGenerationID(), + copy.custom_bitmap().getGenerationID()); EXPECT_TRUE( - gfx::BitmapsAreEqual(GetCursorBitmap(cursor), GetCursorBitmap(copy))); + gfx::BitmapsAreEqual(cursor.custom_bitmap(), copy.custom_bitmap())); EXPECT_EQ(cursor, copy); } @@ -71,10 +68,10 @@ TEST(CursorTest, CustomTypeComparesBitmapPixels) { bitmap2.eraseColor(SK_ColorRED); cursor2.set_custom_bitmap(bitmap2); - EXPECT_NE(GetCursorBitmap(cursor1).getGenerationID(), - GetCursorBitmap(cursor2).getGenerationID()); + EXPECT_NE(cursor1.custom_bitmap().getGenerationID(), + cursor2.custom_bitmap().getGenerationID()); EXPECT_TRUE( - gfx::BitmapsAreEqual(GetCursorBitmap(cursor1), GetCursorBitmap(cursor2))); + gfx::BitmapsAreEqual(cursor1.custom_bitmap(), cursor2.custom_bitmap())); EXPECT_EQ(cursor1, cursor2); } diff --git a/chromium/ui/base/cursor/cursor_util.cc b/chromium/ui/base/cursor/cursor_util.cc index 4af26e57833..a19a4ddcf1e 100644 --- a/chromium/ui/base/cursor/cursor_util.cc +++ b/chromium/ui/base/cursor/cursor_util.cc @@ -6,8 +6,11 @@ #include "base/check_op.h" #include "base/notreached.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_conversions.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/skbitmap_operations.h" diff --git a/chromium/ui/base/cursor/cursor_util.h b/chromium/ui/base/cursor/cursor_util.h index fc93f2150f4..1fe3277c509 100644 --- a/chromium/ui/base/cursor/cursor_util.h +++ b/chromium/ui/base/cursor/cursor_util.h @@ -7,22 +7,25 @@ #include <vector> -#include "base/compiler_specific.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include "ui/display/display.h" -#include "ui/gfx/geometry/point.h" + +class SkBitmap; + +namespace gfx { +class Point; +} namespace ui { // Scale and rotate the cursor's bitmap and hotpoint. // |bitmap_in_out| and |hotpoint_in_out| are used as // both input and output. -UI_BASE_EXPORT void ScaleAndRotateCursorBitmapAndHotpoint( - float scale, - display::Display::Rotation rotation, - SkBitmap* bitmap_in_out, - gfx::Point* hotpoint_in_out); +COMPONENT_EXPORT(UI_BASE_CURSOR) +void ScaleAndRotateCursorBitmapAndHotpoint(float scale, + display::Display::Rotation rotation, + SkBitmap* bitmap_in_out, + gfx::Point* hotpoint_in_out); // Helpers for CursorLoader. void GetImageCursorBitmap(int resource_id, diff --git a/chromium/ui/base/cursor/cursor_util_unittest.cc b/chromium/ui/base/cursor/cursor_util_unittest.cc index 1e2d55f6385..89cb58fc873 100644 --- a/chromium/ui/base/cursor/cursor_util_unittest.cc +++ b/chromium/ui/base/cursor/cursor_util_unittest.cc @@ -6,6 +6,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/geometry/point.h" namespace ui { namespace { diff --git a/chromium/ui/base/cursor/cursor_x11.cc b/chromium/ui/base/cursor/cursor_x11.cc deleted file mode 100644 index edf6c9bb6ba..00000000000 --- a/chromium/ui/base/cursor/cursor_x11.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/base/cursor/cursor.h" - -#include "ui/base/x/x11_util.h" - -namespace ui { - -void Cursor::RefCustomCursor() { - if (platform_cursor_) - ui::RefCustomXCursor(platform_cursor_); -} - -void Cursor::UnrefCustomCursor() { - if (platform_cursor_) - ui::UnrefCustomXCursor(platform_cursor_); -} - -} // namespace ui diff --git a/chromium/ui/base/cursor/cursors_aura.cc b/chromium/ui/base/cursor/cursors_aura.cc index 2a7ba7784c1..710fb8dba11 100644 --- a/chromium/ui/base/cursor/cursors_aura.cc +++ b/chromium/ui/base/cursor/cursors_aura.cc @@ -9,6 +9,7 @@ #include "base/stl_util.h" #include "build/build_config.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor_size.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/base/resource/resource_bundle.h" @@ -22,6 +23,7 @@ #endif namespace ui { + namespace { struct HotPoint { @@ -282,120 +284,6 @@ bool SearchTable(const CursorData* table, } // namespace -const char* CursorCssNameFromId(mojom::CursorType id) { - switch (id) { - case mojom::CursorType::kMiddlePanning: - return "all-scroll"; - case mojom::CursorType::kMiddlePanningVertical: - return "v-scroll"; - case mojom::CursorType::kMiddlePanningHorizontal: - return "h-scroll"; - case mojom::CursorType::kEastPanning: - return "e-resize"; - case mojom::CursorType::kNorthPanning: - return "n-resize"; - case mojom::CursorType::kNorthEastPanning: - return "ne-resize"; - case mojom::CursorType::kNorthWestPanning: - return "nw-resize"; - case mojom::CursorType::kSouthPanning: - return "s-resize"; - case mojom::CursorType::kSouthEastPanning: - return "se-resize"; - case mojom::CursorType::kSouthWestPanning: - return "sw-resize"; - case mojom::CursorType::kWestPanning: - return "w-resize"; - case mojom::CursorType::kNone: - return "none"; - case mojom::CursorType::kGrab: - return "grab"; - case mojom::CursorType::kGrabbing: - return "grabbing"; - case mojom::CursorType::kNull: - return "left_ptr"; - case mojom::CursorType::kPointer: - return "left_ptr"; - case mojom::CursorType::kMove: - // Returning "move" is the correct thing here, but Blink doesn't - // make a distinction between move and all-scroll. Other - // platforms use a cursor more consistent with all-scroll, so - // use that. - return "all-scroll"; - case mojom::CursorType::kCross: - return "crosshair"; - case mojom::CursorType::kHand: - return "pointer"; - case mojom::CursorType::kIBeam: - return "text"; - case mojom::CursorType::kProgress: - return "progress"; - case mojom::CursorType::kWait: - return "wait"; - case mojom::CursorType::kHelp: - return "help"; - case mojom::CursorType::kEastResize: - return "e-resize"; - case mojom::CursorType::kNorthResize: - return "n-resize"; - case mojom::CursorType::kNorthEastResize: - return "ne-resize"; - case mojom::CursorType::kNorthWestResize: - return "nw-resize"; - case mojom::CursorType::kSouthResize: - return "s-resize"; - case mojom::CursorType::kSouthEastResize: - return "se-resize"; - case mojom::CursorType::kSouthWestResize: - return "sw-resize"; - case mojom::CursorType::kWestResize: - return "w-resize"; - case mojom::CursorType::kNorthSouthResize: - return "ns-resize"; - case mojom::CursorType::kEastWestResize: - return "ew-resize"; - case mojom::CursorType::kColumnResize: - return "col-resize"; - case mojom::CursorType::kRowResize: - return "row-resize"; - case mojom::CursorType::kNorthEastSouthWestResize: - return "nesw-resize"; - case mojom::CursorType::kNorthWestSouthEastResize: - return "nwse-resize"; - case mojom::CursorType::kVerticalText: - return "vertical-text"; - case mojom::CursorType::kZoomIn: - return "zoom-in"; - case mojom::CursorType::kZoomOut: - return "zoom-out"; - case mojom::CursorType::kCell: - return "cell"; - case mojom::CursorType::kContextMenu: - return "context-menu"; - case mojom::CursorType::kAlias: - return "alias"; - case mojom::CursorType::kNoDrop: - return "no-drop"; - case mojom::CursorType::kCopy: - return "copy"; - case mojom::CursorType::kNotAllowed: - return "not-allowed"; - case mojom::CursorType::kDndNone: - return "dnd-none"; - case mojom::CursorType::kDndMove: - return "dnd-move"; - case mojom::CursorType::kDndCopy: - return "dnd-copy"; - case mojom::CursorType::kDndLink: - return "dnd-link"; - case mojom::CursorType::kCustom: - NOTREACHED(); - return "left_ptr"; - } - NOTREACHED() << "Case not handled for " << static_cast<int>(id); - return "left_ptr"; -} - bool GetCursorDataFor(CursorSize cursor_size, mojom::CursorType id, float scale_factor, diff --git a/chromium/ui/base/cursor/cursors_aura.h b/chromium/ui/base/cursor/cursors_aura.h index 778a5d3c871..cc82d976546 100644 --- a/chromium/ui/base/cursor/cursors_aura.h +++ b/chromium/ui/base/cursor/cursors_aura.h @@ -5,9 +5,8 @@ #ifndef UI_BASE_CURSOR_CURSORS_AURA_H_ #define UI_BASE_CURSOR_CURSORS_AURA_H_ -#include "ui/base/cursor/cursor.h" +#include "base/component_export.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" -#include "ui/base/ui_base_export.h" class SkBitmap; @@ -16,29 +15,29 @@ class Point; } namespace ui { +class Cursor; enum class CursorSize; const int kAnimatedCursorFrameDelayMs = 25; -// Returns CSS cursor name from an Aura cursor ID. -UI_BASE_EXPORT const char* CursorCssNameFromId(mojom::CursorType id); - // Returns data about |id|, where id is a cursor constant like // ui::mojom::CursorType::kHelp. The IDR will be placed in |resource_id| and // the hotspots for the different DPIs will be placed in |hot_1x| and // |hot_2x|. Returns false if |id| is invalid. -UI_BASE_EXPORT bool GetCursorDataFor(CursorSize cursor_size, - mojom::CursorType id, - float scale_factor, - int* resource_id, - gfx::Point* point); +COMPONENT_EXPORT(UI_BASE_CURSOR) +bool GetCursorDataFor(CursorSize cursor_size, + mojom::CursorType id, + float scale_factor, + int* resource_id, + gfx::Point* point); // Like above, but for animated cursors. -UI_BASE_EXPORT bool GetAnimatedCursorDataFor(CursorSize cursor_size, - mojom::CursorType id, - float scale_factor, - int* resource_id, - gfx::Point* point); +COMPONENT_EXPORT(UI_BASE_CURSOR) +bool GetAnimatedCursorDataFor(CursorSize cursor_size, + mojom::CursorType id, + float scale_factor, + int* resource_id, + gfx::Point* point); SkBitmap GetDefaultBitmap(const Cursor& cursor); diff --git a/chromium/ui/base/cursor/image_cursors.cc b/chromium/ui/base/cursor/image_cursors.cc index 4612bedb350..42fd3249684 100644 --- a/chromium/ui/base/cursor/image_cursors.cc +++ b/chromium/ui/base/cursor/image_cursors.cc @@ -4,25 +4,17 @@ #include "ui/base/cursor/image_cursors.h" -#include <float.h> -#include <stddef.h> - #include "base/check.h" -#include "base/notreached.h" -#include "base/stl_util.h" -#include "base/strings/string16.h" -#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor_loader.h" #include "ui/base/cursor/cursors_aura.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" -#include "ui/display/display.h" #include "ui/gfx/geometry/point.h" namespace ui { namespace { -const mojom::CursorType kImageCursorIds[] = { +constexpr mojom::CursorType kImageCursorIds[] = { mojom::CursorType::kNull, mojom::CursorType::kPointer, mojom::CursorType::kNoDrop, @@ -57,49 +49,30 @@ const mojom::CursorType kImageCursorIds[] = { mojom::CursorType::kGrabbing, }; -const mojom::CursorType kAnimatedCursorIds[] = {mojom::CursorType::kWait, - mojom::CursorType::kProgress}; +constexpr mojom::CursorType kAnimatedCursorIds[] = { + mojom::CursorType::kWait, mojom::CursorType::kProgress}; } // namespace -ImageCursors::ImageCursors() : cursor_size_(CursorSize::kNormal) {} +ImageCursors::ImageCursors() + : cursor_loader_(CursorLoader::Create()), + cursor_size_(CursorSize::kNormal) {} -ImageCursors::~ImageCursors() { -} - -void ImageCursors::Initialize() { - if (!cursor_loader_) - cursor_loader_.reset(CursorLoader::Create()); -} +ImageCursors::~ImageCursors() = default; float ImageCursors::GetScale() const { - if (!cursor_loader_) { - NOTREACHED(); - // Returning default on release build as it's not serious enough to crash - // even if this ever happens. - return 1.0f; - } return cursor_loader_->scale(); } display::Display::Rotation ImageCursors::GetRotation() const { - if (!cursor_loader_) { - NOTREACHED(); - // Returning default on release build as it's not serious enough to crash - // even if this ever happens. - return display::Display::ROTATE_0; - } return cursor_loader_->rotation(); } bool ImageCursors::SetDisplay(const display::Display& display, float scale_factor) { - if (!cursor_loader_) { - cursor_loader_.reset(CursorLoader::Create()); - } else if (cursor_loader_->rotation() == display.panel_rotation() && - cursor_loader_->scale() == scale_factor) { + if (cursor_loader_->rotation() == display.panel_rotation() && + cursor_loader_->scale() == scale_factor) return false; - } cursor_loader_->set_rotation(display.panel_rotation()); cursor_loader_->set_scale(scale_factor); @@ -112,25 +85,21 @@ void ImageCursors::ReloadCursors() { cursor_loader_->UnloadAll(); - for (size_t i = 0; i < base::size(kImageCursorIds); ++i) { + for (auto cursor_id : kImageCursorIds) { int resource_id = -1; gfx::Point hot_point; - bool success = - GetCursorDataFor(cursor_size_, kImageCursorIds[i], device_scale_factor, - &resource_id, &hot_point); + bool success = GetCursorDataFor( + cursor_size_, cursor_id, device_scale_factor, &resource_id, &hot_point); DCHECK(success); - cursor_loader_->LoadImageCursor(kImageCursorIds[i], resource_id, hot_point); + cursor_loader_->LoadImageCursor(cursor_id, resource_id, hot_point); } - for (size_t i = 0; i < base::size(kAnimatedCursorIds); ++i) { + for (auto cursor_id : kAnimatedCursorIds) { int resource_id = -1; gfx::Point hot_point; - bool success = - GetAnimatedCursorDataFor(cursor_size_, kAnimatedCursorIds[i], - device_scale_factor, &resource_id, &hot_point); + bool success = GetAnimatedCursorDataFor( + cursor_size_, cursor_id, device_scale_factor, &resource_id, &hot_point); DCHECK(success); - cursor_loader_->LoadAnimatedCursor(kAnimatedCursorIds[i], - resource_id, - hot_point, + cursor_loader_->LoadAnimatedCursor(cursor_id, resource_id, hot_point, kAnimatedCursorFrameDelayMs); } } @@ -141,16 +110,11 @@ void ImageCursors::SetCursorSize(CursorSize cursor_size) { cursor_size_ = cursor_size; - if (cursor_loader_.get()) - ReloadCursors(); + ReloadCursors(); } void ImageCursors::SetPlatformCursor(gfx::NativeCursor* cursor) { cursor_loader_->SetPlatformCursor(cursor); } -base::WeakPtr<ImageCursors> ImageCursors::GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} - } // namespace ui diff --git a/chromium/ui/base/cursor/image_cursors.h b/chromium/ui/base/cursor/image_cursors.h index 0855bfff15e..b5b5ec274dd 100644 --- a/chromium/ui/base/cursor/image_cursors.h +++ b/chromium/ui/base/cursor/image_cursors.h @@ -7,12 +7,8 @@ #include <memory> -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/strings/string16.h" -#include "ui/base/cursor/cursor.h" +#include "base/component_export.h" #include "ui/base/cursor/cursor_size.h" -#include "ui/base/ui_base_export.h" #include "ui/display/display.h" #include "ui/gfx/native_widget_types.h" @@ -22,19 +18,13 @@ class CursorLoader; // A utility class that provides cursors for NativeCursors for which we have // image resources. -class UI_BASE_EXPORT ImageCursors { +class COMPONENT_EXPORT(UI_BASE_CURSOR) ImageCursors { public: ImageCursors(); + ImageCursors(const ImageCursors&) = delete; + ImageCursors& operator=(const ImageCursors&) = delete; ~ImageCursors(); - // Creates the |cursor_loader_|. This is optional as |cursor_loader_| is - // lazily created if Initialize() isn't explictly called. - // However note that it matters which thread is used to create - // |cursor_loader_| (see CursorLoaderOzone, crbug.com/741106). Thus explicit - // call to Initialize may be useful to ensure initialization happens on the - // right thread. - void Initialize(); - // Returns the scale and rotation of the currently loaded cursor. float GetScale() const; display::Display::Rotation GetRotation() const; @@ -49,17 +39,12 @@ class UI_BASE_EXPORT ImageCursors { // Sets the platform cursor based on the native type of |cursor|. void SetPlatformCursor(gfx::NativeCursor* cursor); - base::WeakPtr<ImageCursors> GetWeakPtr(); - private: // Reloads the all loaded cursors in the cursor loader. void ReloadCursors(); std::unique_ptr<CursorLoader> cursor_loader_; CursorSize cursor_size_; - base::WeakPtrFactory<ImageCursors> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(ImageCursors); }; } // namespace ui diff --git a/chromium/ui/base/cursor/mojom/BUILD.gn b/chromium/ui/base/cursor/mojom/BUILD.gn index 042d2160861..588e828c29d 100644 --- a/chromium/ui/base/cursor/mojom/BUILD.gn +++ b/chromium/ui/base/cursor/mojom/BUILD.gn @@ -33,7 +33,7 @@ source_set("mojom_traits") { ] public_deps = [ ":mojom_shared", - "//ui/base/cursor", + "//ui/base/cursor:cursor_base", ] deps = [ "//skia", @@ -56,7 +56,7 @@ source_set("unittests") { ":mojom_traits", "//testing/gtest", "//ui/base", - "//ui/base/cursor", + "//ui/base/cursor:cursor_base", "//ui/gfx:geometry_skia", "//ui/gfx/geometry/mojom:mojom_traits", ] diff --git a/chromium/ui/base/cursor/mojom/cursor_mojom_traits_unittest.cc b/chromium/ui/base/cursor/mojom/cursor_mojom_traits_unittest.cc index d3b1aee2f12..88f888b2709 100644 --- a/chromium/ui/base/cursor/mojom/cursor_mojom_traits_unittest.cc +++ b/chromium/ui/base/cursor/mojom/cursor_mojom_traits_unittest.cc @@ -7,7 +7,6 @@ #include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/cursor/cursor.h" -#include "ui/base/cursor/cursor_lookup.h" #include "ui/base/cursor/mojom/cursor.mojom.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" @@ -59,18 +58,18 @@ TEST_F(CursorStructTraitsTest, TestBitmapCursor) { EXPECT_EQ(ui::mojom::CursorType::kCustom, output.type()); EXPECT_EQ(kScale, output.image_scale_factor()); - EXPECT_EQ(kHotspot, GetCursorHotspot(output)); + EXPECT_EQ(kHotspot, output.custom_hotspot()); // Even though the pixel data is the same, the bitmap generation ids differ. EXPECT_TRUE( - gfx::BitmapsAreEqual(GetCursorBitmap(input), GetCursorBitmap(output))); - EXPECT_NE(GetCursorBitmap(input).getGenerationID(), - GetCursorBitmap(output).getGenerationID()); + gfx::BitmapsAreEqual(input.custom_bitmap(), output.custom_bitmap())); + EXPECT_NE(input.custom_bitmap().getGenerationID(), + output.custom_bitmap().getGenerationID()); // Make a copy of output; the bitmap generation ids should be the same. ui::Cursor copy = output; - EXPECT_EQ(GetCursorBitmap(output).getGenerationID(), - GetCursorBitmap(copy).getGenerationID()); + EXPECT_EQ(output.custom_bitmap().getGenerationID(), + copy.custom_bitmap().getGenerationID()); EXPECT_EQ(input, output); } @@ -88,7 +87,7 @@ TEST_F(CursorStructTraitsTest, TestEmptyCursor) { ui::Cursor output; ASSERT_TRUE(EchoCursor(input, &output)); - EXPECT_TRUE(GetCursorBitmap(output).empty()); + EXPECT_TRUE(output.custom_bitmap().empty()); } // Test that various device scale factors are passed correctly over the wire. diff --git a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc index 44037bc6142..e86f70ea603 100644 --- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc +++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc @@ -7,10 +7,6 @@ #include <algorithm> #include "base/check_op.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/cursor/cursor_lookup.h" -#include "ui/base/cursor/cursors_aura.h" -#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" namespace ui { @@ -24,20 +20,6 @@ PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) { return static_cast<PlatformCursor>(cursor); } -scoped_refptr<BitmapCursorOzone> CreateDefaultBitmapCursor( - mojom::CursorType type) { - Cursor cursor(type); - // Ozone must honor the lowest possible scale value, which is 1.0f. Otherwise, - // it can happen that cursor chooses wrong hotspots if max scaling value is - // set to 200p, for example. - cursor.set_image_scale_factor(1.0f); - SkBitmap bitmap = GetCursorBitmap(cursor); - gfx::Point hotspot = GetCursorHotspot(cursor); - if (!bitmap.isNull()) - return new BitmapCursorOzone(bitmap, hotspot); - return nullptr; -} - } // namespace BitmapCursorOzone::BitmapCursorOzone(const SkBitmap& bitmap, @@ -89,15 +71,16 @@ scoped_refptr<BitmapCursorOzone> BitmapCursorFactoryOzone::GetBitmapCursor( return base::WrapRefCounted(ToBitmapCursorOzone(platform_cursor)); } -PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor( +base::Optional<PlatformCursor> BitmapCursorFactoryOzone::GetDefaultCursor( mojom::CursorType type) { - return GetDefaultCursorInternal(type).get(); + if (type == mojom::CursorType::kNone) + return nullptr; // nullptr is used for the hidden cursor. + return base::nullopt; } PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor( const SkBitmap& bitmap, - const gfx::Point& hotspot, - float bitmap_dpi) { + const gfx::Point& hotspot) { BitmapCursorOzone* cursor = new BitmapCursorOzone(bitmap, hotspot); cursor->AddRef(); // Balanced by UnrefImageCursor. return ToPlatformCursor(cursor); @@ -106,8 +89,7 @@ PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor( PlatformCursor BitmapCursorFactoryOzone::CreateAnimatedCursor( const std::vector<SkBitmap>& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms, - float bitmap_dpi) { + int frame_delay_ms) { DCHECK_LT(0U, bitmaps.size()); BitmapCursorOzone* cursor = new BitmapCursorOzone(bitmaps, hotspot, frame_delay_ms); @@ -123,23 +105,4 @@ void BitmapCursorFactoryOzone::UnrefImageCursor(PlatformCursor cursor) { ToBitmapCursorOzone(cursor)->Release(); } -scoped_refptr<BitmapCursorOzone> -BitmapCursorFactoryOzone::GetDefaultCursorInternal(mojom::CursorType type) { - if (type == mojom::CursorType::kNone) - return nullptr; // Null is used for hidden cursor. - - if (!default_cursors_.count(type)) { - // Create new image cursor from default aura bitmap for this type. We hold a - // ref forever because clients do not do refcounting for default cursors. - scoped_refptr<BitmapCursorOzone> cursor = CreateDefaultBitmapCursor(type); - if (!cursor.get() && type != mojom::CursorType::kPointer) - cursor = GetDefaultCursorInternal(mojom::CursorType::kPointer); - DCHECK(cursor.get()) << "Failed to load default cursor bitmap"; - default_cursors_[type] = cursor; - } - - // Returned owned default cursor for this type. - return default_cursors_[type]; -} - } // namespace ui diff --git a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h index 95ed10b051b..b489e099ad0 100644 --- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h +++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h @@ -5,21 +5,20 @@ #ifndef UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_ #define UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_ -#include <map> +#include <vector> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/cursor/cursor.h" -#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" -#include "ui/base/ui_base_export.h" +#include "ui/base/cursor/cursor_factory.h" #include "ui/gfx/geometry/point.h" -#include "ui/ozone/public/cursor_factory_ozone.h" namespace ui { // A cursor that is an SkBitmap combined with a gfx::Point hotspot. -class UI_BASE_EXPORT BitmapCursorOzone +class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorOzone : public base::RefCounted<BitmapCursorOzone> { public: BitmapCursorOzone(const SkBitmap& bitmap, const gfx::Point& hotspot); @@ -45,14 +44,15 @@ class UI_BASE_EXPORT BitmapCursorOzone DISALLOW_COPY_AND_ASSIGN(BitmapCursorOzone); }; -// CursorFactoryOzone implementation for bitmapped cursors. +// CursorFactory implementation for bitmapped cursors. // // This is a base class for platforms where PlatformCursor is an SkBitmap // combined with a gfx::Point for the hotspot. // // Subclasses need only implement SetBitmapCursor() as everything else is // implemented here. -class UI_BASE_EXPORT BitmapCursorFactoryOzone : public CursorFactoryOzone { +class COMPONENT_EXPORT(UI_BASE_CURSOR) BitmapCursorFactoryOzone + : public CursorFactory { public: BitmapCursorFactoryOzone(); ~BitmapCursorFactoryOzone() override; @@ -62,26 +62,17 @@ class UI_BASE_EXPORT BitmapCursorFactoryOzone : public CursorFactoryOzone { PlatformCursor platform_cursor); // CursorFactoryOzone: - PlatformCursor GetDefaultCursor(mojom::CursorType type) override; + base::Optional<PlatformCursor> GetDefaultCursor( + mojom::CursorType type) override; PlatformCursor CreateImageCursor(const SkBitmap& bitmap, - const gfx::Point& hotspot, - float bitmap_dpi) override; + const gfx::Point& hotspot) override; PlatformCursor CreateAnimatedCursor(const std::vector<SkBitmap>& bitmaps, const gfx::Point& hotspot, - int frame_delay_ms, - float bitmap_dpi) override; + int frame_delay_ms) override; void RefImageCursor(PlatformCursor cursor) override; void UnrefImageCursor(PlatformCursor cursor) override; private: - // Get cached BitmapCursorOzone for a default cursor. - scoped_refptr<BitmapCursorOzone> GetDefaultCursorInternal( - mojom::CursorType type); - - // Default cursors are cached & owned by the factory. - std::map<mojom::CursorType, scoped_refptr<BitmapCursorOzone>> - default_cursors_; - DISALLOW_COPY_AND_ASSIGN(BitmapCursorFactoryOzone); }; diff --git a/chromium/ui/base/device_form_factor.h b/chromium/ui/base/device_form_factor.h index f87ceca159f..e7c52c28897 100644 --- a/chromium/ui/base/device_form_factor.h +++ b/chromium/ui/base/device_form_factor.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_DEVICE_FORM_FACTOR_H_ #define UI_BASE_DEVICE_FORM_FACTOR_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -17,7 +17,7 @@ enum DeviceFormFactor { // Returns the form factor of current device. For platforms other than Android // and iOS, DEVICE_FORM_FACTOR_DESKTOP is always returned. -UI_BASE_EXPORT DeviceFormFactor GetDeviceFormFactor(); +COMPONENT_EXPORT(UI_BASE) DeviceFormFactor GetDeviceFormFactor(); } // namespace ui diff --git a/chromium/ui/base/dragdrop/cocoa_dnd_util.h b/chromium/ui/base/dragdrop/cocoa_dnd_util.h index 1945c177293..1daf898b21c 100644 --- a/chromium/ui/base/dragdrop/cocoa_dnd_util.h +++ b/chromium/ui/base/dragdrop/cocoa_dnd_util.h @@ -9,8 +9,8 @@ #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" class GURL; @@ -20,24 +20,25 @@ namespace ui { // any data associated with this type; it's only used to ensure that Chrome // supports any drag initiated inside of Chrome, whether or not data has been // associated with it. -UI_BASE_EXPORT extern NSString* const kChromeDragDummyPboardType; +COMPONENT_EXPORT(UI_BASE) extern NSString* const kChromeDragDummyPboardType; // Mail.app and TextEdit accept drags that have both HTML and image flavors on // them, but don't process them correctly <http://crbug.com/55879>. Therefore, // if there is an image flavor, don't put the HTML data on as HTML, but rather // put it on as this Chrome-only flavor. External apps won't see HTML but // Chrome will know enough to read it as HTML. <http://crbug.com/55879> -UI_BASE_EXPORT extern NSString* const kChromeDragImageHTMLPboardType; +COMPONENT_EXPORT(UI_BASE) extern NSString* const kChromeDragImageHTMLPboardType; // Populates the |url| and |title| with URL data in |pboard|. There may be more // than one, but we only handle dropping the first. |url| must not be |NULL|; // |title| is an optional parameter. Returns |YES| if URL data was obtained from // the pasteboard, |NO| otherwise. If |convert_filenames| is |YES|, the function // will also attempt to convert filenames in |pboard| to file URLs. -UI_BASE_EXPORT BOOL PopulateURLAndTitleFromPasteboard(GURL* url, - base::string16* title, - NSPasteboard* pboard, - BOOL convert_filenames); +COMPONENT_EXPORT(UI_BASE) +BOOL PopulateURLAndTitleFromPasteboard(GURL* url, + base::string16* title, + NSPasteboard* pboard, + BOOL convert_filenames); } // namespace ui diff --git a/chromium/ui/base/dragdrop/drag_drop_types.h b/chromium/ui/base/dragdrop/drag_drop_types.h index ddb726fe53a..af2fad11112 100644 --- a/chromium/ui/base/dragdrop/drag_drop_types.h +++ b/chromium/ui/base/dragdrop/drag_drop_types.h @@ -7,12 +7,12 @@ #include <stdint.h> +#include "base/component_export.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" namespace ui { -class UI_BASE_EXPORT DragDropTypes { +class COMPONENT_EXPORT(UI_BASE) DragDropTypes { public: enum DragOperation { DRAG_NONE = 0, diff --git a/chromium/ui/base/dragdrop/drag_source_win.cc b/chromium/ui/base/dragdrop/drag_source_win.cc index fe201a8d9c1..c27409139ee 100644 --- a/chromium/ui/base/dragdrop/drag_source_win.cc +++ b/chromium/ui/base/dragdrop/drag_source_win.cc @@ -24,7 +24,7 @@ HRESULT DragSourceWin::QueryContinueDrag(BOOL escape_pressed, DWORD key_state) { return DRAGDROP_S_CANCEL; } - if (!(key_state & MK_LBUTTON)) { + if (!(key_state & MK_LBUTTON) && !(key_state & MK_RBUTTON)) { OnDragSourceDrop(); return DRAGDROP_S_DROP; } diff --git a/chromium/ui/base/dragdrop/drag_source_win.h b/chromium/ui/base/dragdrop/drag_source_win.h index 5634d7082c1..466ec9672ad 100644 --- a/chromium/ui/base/dragdrop/drag_source_win.h +++ b/chromium/ui/base/dragdrop/drag_source_win.h @@ -8,9 +8,9 @@ #include <objidl.h> #include <wrl/implements.h> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -26,7 +26,8 @@ class DragSourceWin IDropSource> { public: // Factory method to avoid exporting the class and all it derives from. - static UI_BASE_EXPORT Microsoft::WRL::ComPtr<DragSourceWin> Create(); + static COMPONENT_EXPORT( + UI_BASE) Microsoft::WRL::ComPtr<DragSourceWin> Create(); // Use Create() to construct these objects. Direct calls to the constructor // are an error - it is only public because a WRL helper function creates the diff --git a/chromium/ui/base/dragdrop/drop_target_event.h b/chromium/ui/base/dragdrop/drop_target_event.h index 47f1b4e09ae..5a8abf1f40c 100644 --- a/chromium/ui/base/dragdrop/drop_target_event.h +++ b/chromium/ui/base/dragdrop/drop_target_event.h @@ -5,6 +5,7 @@ #ifndef UI_BASE_DRAGDROP_DROP_TARGET_EVENT_H_ #define UI_BASE_DRAGDROP_DROP_TARGET_EVENT_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/events/event.h" @@ -13,7 +14,7 @@ namespace ui { // Note: This object must not outlive the OSExchangeData used to construct it, // as it stores that by reference. -class UI_BASE_EXPORT DropTargetEvent : public LocatedEvent { +class COMPONENT_EXPORT(UI_BASE) DropTargetEvent : public LocatedEvent { public: DropTargetEvent(const OSExchangeData& data, const gfx::PointF& location, diff --git a/chromium/ui/base/dragdrop/drop_target_win.h b/chromium/ui/base/dragdrop/drop_target_win.h index 6470b34c891..18409b41d36 100644 --- a/chromium/ui/base/dragdrop/drop_target_win.h +++ b/chromium/ui/base/dragdrop/drop_target_win.h @@ -7,9 +7,9 @@ #include <objidl.h> +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "ui/base/ui_base_export.h" // Windows interface. struct IDropTargetHelper; @@ -25,7 +25,7 @@ namespace ui { // before the HWND is deleted too. // // This class is meant to be used in a STA and is not multithread-safe. -class UI_BASE_EXPORT DropTargetWin : public IDropTarget { +class COMPONENT_EXPORT(UI_BASE) DropTargetWin : public IDropTarget { public: DropTargetWin(); virtual ~DropTargetWin(); diff --git a/chromium/ui/base/dragdrop/os_exchange_data.cc b/chromium/ui/base/dragdrop/os_exchange_data.cc index 727deb75a01..f8c4f3e8929 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data.cc @@ -99,7 +99,7 @@ bool OSExchangeData::HasAnyFormat( const std::set<ClipboardFormatType>& format_types) const { if ((formats & STRING) != 0 && HasString()) return true; - if ((formats & URL) != 0 && HasURL(CONVERT_FILENAMES)) + if ((formats & URL) != 0 && HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)) return true; #if defined(OS_WIN) if ((formats & FILE_CONTENTS) != 0 && provider_->HasFileContents()) diff --git a/chromium/ui/base/dragdrop/os_exchange_data.h b/chromium/ui/base/dragdrop/os_exchange_data.h index 58b160be349..bd851a065fc 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data.h +++ b/chromium/ui/base/dragdrop/os_exchange_data.h @@ -18,10 +18,10 @@ #endif #include "base/callback_forward.h" +#include "base/component_export.h" #include "base/files/file_path.h" #include "base/macros.h" #include "ui/base/dragdrop/os_exchange_data_provider.h" -#include "ui/base/ui_base_export.h" class GURL; @@ -48,7 +48,7 @@ struct FileInfo; // TabContentsViewGtk uses a different class to handle drag support that does // not use OSExchangeData. As such, file contents and html support is only // compiled on windows. -class UI_BASE_EXPORT OSExchangeData { +class COMPONENT_EXPORT(UI_BASE) OSExchangeData { public: // Enumeration of the known formats. enum Format { diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider.h b/chromium/ui/base/dragdrop/os_exchange_data_provider.h index 2e45ee878fb..b945ec9180f 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider.h @@ -33,8 +33,7 @@ namespace ui { // Controls whether or not filenames should be converted to file: URLs when // getting a URL. -// TODO(crbug.com/1070138): convert to enum class. -enum FilenameToURLPolicy { +enum class FilenameToURLPolicy { CONVERT_FILENAMES, DO_NOT_CONVERT_FILENAMES, }; diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc index 52efa7c8e6a..fcf63aac986 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc @@ -13,7 +13,7 @@ #if defined(USE_OZONE) #include "ui/base/dragdrop/os_exchange_data_provider_factory_ozone.h" #endif -#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" +#include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h" #elif defined(OS_MACOSX) #include "ui/base/dragdrop/os_exchange_data_provider_builder_mac.h" #elif defined(OS_WIN) @@ -39,7 +39,7 @@ OSExchangeDataProviderFactory::CreateProvider() { return provider; } #endif - return std::make_unique<OSExchangeDataProviderAura>(); + return std::make_unique<OSExchangeDataProviderNonBacked>(); #elif defined(OS_MACOSX) return BuildOSExchangeDataProviderMac(); #elif defined(OS_WIN) diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.h index b3fbd31a564..72ac48751a5 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.h @@ -7,13 +7,13 @@ #include <memory> +#include "base/component_export.h" #include "ui/base/dragdrop/os_exchange_data_provider.h" -#include "ui/base/ui_base_export.h" namespace ui { // Builds platform specific OSExchangeDataProviders. -class UI_BASE_EXPORT OSExchangeDataProviderFactory { +class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderFactory { public: // Creates a Provider based on the current platform. static std::unique_ptr<OSExchangeDataProvider> CreateProvider(); 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 11465f8cc86..8fb6a3ad5c6 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h @@ -7,6 +7,7 @@ #include <memory> +#include "base/component_export.h" #include "base/mac/scoped_nsobject.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -25,7 +26,8 @@ namespace ui { // OSExchangeDataProvider implementation for Mac. -class UI_BASE_EXPORT OSExchangeDataProviderMac : public OSExchangeDataProvider { +class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderMac + : public OSExchangeDataProvider { public: ~OSExchangeDataProviderMac() override; 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 4c7cbf41185..b7f144452f3 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm @@ -193,7 +193,8 @@ bool OSExchangeDataProviderMac::GetString(base::string16* data) const { // There was no NSString, check for an NSURL. GURL url; base::string16 title; - bool result = GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &url, &title); + bool result = GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, + &url, &title); if (result) *data = base::UTF8ToUTF16(url.spec()); @@ -218,7 +219,8 @@ bool OSExchangeDataProviderMac::GetURLAndTitle(FilenameToURLPolicy policy, // the trailing slashes off of paths and always returns the last path element // as the title whereas no path conversion nor title is wanted. base::FilePath path; - if (policy != DO_NOT_CONVERT_FILENAMES && GetFilename(&path)) { + if (policy != FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES && + GetFilename(&path)) { NSURL* fileUrl = [NSURL fileURLWithPath:base::SysUTF8ToNSString(path.value())]; *url = diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc index 7131bc01992..a4964922b00 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.cc @@ -2,49 +2,53 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/dragdrop/os_exchange_data_provider_aura.h" +#include "ui/base/dragdrop/os_exchange_data_provider_non_backed.h" + +#include <memory> #include "base/check.h" -#include "base/memory/ptr_util.h" +#include "base/files/file_path.h" +#include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "net/base/filename_util.h" #include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/dragdrop/file_info/file_info.h" +#include "ui/base/dragdrop/os_exchange_data.h" +#include "url/gurl.h" namespace ui { -OSExchangeDataProviderAura::OSExchangeDataProviderAura() - : formats_(0) { -} +OSExchangeDataProviderNonBacked::OSExchangeDataProviderNonBacked() = default; -OSExchangeDataProviderAura::~OSExchangeDataProviderAura() = default; +OSExchangeDataProviderNonBacked::~OSExchangeDataProviderNonBacked() = default; -std::unique_ptr<OSExchangeDataProvider> OSExchangeDataProviderAura::Clone() +std::unique_ptr<OSExchangeDataProvider> OSExchangeDataProviderNonBacked::Clone() const { - OSExchangeDataProviderAura* ret = new OSExchangeDataProviderAura(); - ret->formats_ = formats_; - ret->string_ = string_; - ret->url_ = url_; - ret->title_ = title_; - ret->filenames_ = filenames_; - ret->pickle_data_ = pickle_data_; + auto clone = std::make_unique<OSExchangeDataProviderNonBacked>(); + + clone->formats_ = formats_; + clone->string_ = string_; + clone->url_ = url_; + clone->title_ = title_; + clone->filenames_ = filenames_; + clone->pickle_data_ = pickle_data_; // We skip copying the drag images. - ret->html_ = html_; - ret->base_url_ = base_url_; + clone->html_ = html_; + clone->base_url_ = base_url_; - return base::WrapUnique<OSExchangeDataProvider>(ret); + return clone; } -void OSExchangeDataProviderAura::MarkOriginatedFromRenderer() { +void OSExchangeDataProviderNonBacked::MarkOriginatedFromRenderer() { // TODO(dcheng): Currently unneeded because ChromeOS Aura correctly separates // URL and filename metadata, and does not implement the DownloadURL protocol. } -bool OSExchangeDataProviderAura::DidOriginateFromRenderer() const { +bool OSExchangeDataProviderNonBacked::DidOriginateFromRenderer() const { return false; } -void OSExchangeDataProviderAura::SetString(const base::string16& data) { +void OSExchangeDataProviderNonBacked::SetString(const base::string16& data) { if (HasString()) return; @@ -52,8 +56,8 @@ void OSExchangeDataProviderAura::SetString(const base::string16& data) { formats_ |= OSExchangeData::STRING; } -void OSExchangeDataProviderAura::SetURL(const GURL& url, - const base::string16& title) { +void OSExchangeDataProviderNonBacked::SetURL(const GURL& url, + const base::string16& title) { url_ = url; title_ = title; formats_ |= OSExchangeData::URL; @@ -61,39 +65,41 @@ void OSExchangeDataProviderAura::SetURL(const GURL& url, SetString(base::UTF8ToUTF16(url.spec())); } -void OSExchangeDataProviderAura::SetFilename(const base::FilePath& path) { +void OSExchangeDataProviderNonBacked::SetFilename(const base::FilePath& path) { filenames_.clear(); filenames_.push_back(FileInfo(path, base::FilePath())); formats_ |= OSExchangeData::FILE_NAME; } -void OSExchangeDataProviderAura::SetFilenames( +void OSExchangeDataProviderNonBacked::SetFilenames( const std::vector<FileInfo>& filenames) { filenames_ = filenames; formats_ |= OSExchangeData::FILE_NAME; } -void OSExchangeDataProviderAura::SetPickledData( +void OSExchangeDataProviderNonBacked::SetPickledData( const ClipboardFormatType& format, const base::Pickle& data) { pickle_data_[format] = data; formats_ |= OSExchangeData::PICKLED_DATA; } -bool OSExchangeDataProviderAura::GetString(base::string16* data) const { +bool OSExchangeDataProviderNonBacked::GetString(base::string16* data) const { if ((formats_ & OSExchangeData::STRING) == 0) return false; *data = string_; return true; } -bool OSExchangeDataProviderAura::GetURLAndTitle(FilenameToURLPolicy policy, - GURL* url, - base::string16* title) const { +bool OSExchangeDataProviderNonBacked::GetURLAndTitle( + FilenameToURLPolicy policy, + GURL* url, + base::string16* title) const { if ((formats_ & OSExchangeData::URL) == 0) { title->clear(); return GetPlainTextURL(url) || - (policy == CONVERT_FILENAMES && GetFileURL(url)); + (policy == FilenameToURLPolicy::CONVERT_FILENAMES && + GetFileURL(url)); } if (!url_.is_valid()) @@ -104,7 +110,7 @@ bool OSExchangeDataProviderAura::GetURLAndTitle(FilenameToURLPolicy policy, return true; } -bool OSExchangeDataProviderAura::GetFilename(base::FilePath* path) const { +bool OSExchangeDataProviderNonBacked::GetFilename(base::FilePath* path) const { if ((formats_ & OSExchangeData::FILE_NAME) == 0) return false; DCHECK(!filenames_.empty()); @@ -112,7 +118,7 @@ bool OSExchangeDataProviderAura::GetFilename(base::FilePath* path) const { return true; } -bool OSExchangeDataProviderAura::GetFilenames( +bool OSExchangeDataProviderNonBacked::GetFilenames( std::vector<FileInfo>* filenames) const { if ((formats_ & OSExchangeData::FILE_NAME) == 0) return false; @@ -120,10 +126,10 @@ bool OSExchangeDataProviderAura::GetFilenames( return true; } -bool OSExchangeDataProviderAura::GetPickledData( +bool OSExchangeDataProviderNonBacked::GetPickledData( const ClipboardFormatType& format, base::Pickle* data) const { - PickleData::const_iterator i = pickle_data_.find(format); + const auto i = pickle_data_.find(format); if (i == pickle_data_.end()) return false; @@ -131,37 +137,38 @@ bool OSExchangeDataProviderAura::GetPickledData( return true; } -bool OSExchangeDataProviderAura::HasString() const { +bool OSExchangeDataProviderNonBacked::HasString() const { return (formats_ & OSExchangeData::STRING) != 0; } -bool OSExchangeDataProviderAura::HasURL(FilenameToURLPolicy policy) const { +bool OSExchangeDataProviderNonBacked::HasURL(FilenameToURLPolicy policy) const { if ((formats_ & OSExchangeData::URL) != 0) { return true; } // No URL, see if we have plain text that can be parsed as a URL. - return GetPlainTextURL(NULL) || - (policy == CONVERT_FILENAMES && GetFileURL(nullptr)); + return GetPlainTextURL(nullptr) || + (policy == FilenameToURLPolicy::CONVERT_FILENAMES && + GetFileURL(nullptr)); } -bool OSExchangeDataProviderAura::HasFile() const { +bool OSExchangeDataProviderNonBacked::HasFile() const { return (formats_ & OSExchangeData::FILE_NAME) != 0; } -bool OSExchangeDataProviderAura::HasCustomFormat( +bool OSExchangeDataProviderNonBacked::HasCustomFormat( const ClipboardFormatType& format) const { return base::Contains(pickle_data_, format); } -void OSExchangeDataProviderAura::SetHtml(const base::string16& html, - const GURL& base_url) { +void OSExchangeDataProviderNonBacked::SetHtml(const base::string16& html, + const GURL& base_url) { formats_ |= OSExchangeData::HTML; html_ = html; base_url_ = base_url; } -bool OSExchangeDataProviderAura::GetHtml(base::string16* html, - GURL* base_url) const { +bool OSExchangeDataProviderNonBacked::GetHtml(base::string16* html, + GURL* base_url) const { if ((formats_ & OSExchangeData::HTML) == 0) return false; *html = html_; @@ -169,26 +176,26 @@ bool OSExchangeDataProviderAura::GetHtml(base::string16* html, return true; } -bool OSExchangeDataProviderAura::HasHtml() const { +bool OSExchangeDataProviderNonBacked::HasHtml() const { return ((formats_ & OSExchangeData::HTML) != 0); } -void OSExchangeDataProviderAura::SetDragImage( +void OSExchangeDataProviderNonBacked::SetDragImage( const gfx::ImageSkia& image, const gfx::Vector2d& cursor_offset) { drag_image_ = image; drag_image_offset_ = cursor_offset; } -gfx::ImageSkia OSExchangeDataProviderAura::GetDragImage() const { +gfx::ImageSkia OSExchangeDataProviderNonBacked::GetDragImage() const { return drag_image_; } -gfx::Vector2d OSExchangeDataProviderAura::GetDragImageOffset() const { +gfx::Vector2d OSExchangeDataProviderNonBacked::GetDragImageOffset() const { return drag_image_offset_; } -bool OSExchangeDataProviderAura::GetFileURL(GURL* url) const { +bool OSExchangeDataProviderNonBacked::GetFileURL(GURL* url) const { base::FilePath file_path; if (!GetFilename(&file_path)) return false; @@ -202,7 +209,7 @@ bool OSExchangeDataProviderAura::GetFileURL(GURL* url) const { return true; } -bool OSExchangeDataProviderAura::GetPlainTextURL(GURL* url) const { +bool OSExchangeDataProviderNonBacked::GetPlainTextURL(GURL* url) const { if ((formats_ & OSExchangeData::STRING) == 0) return false; diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h index c535f08666a..6a15a8df69d 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aura.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_non_backed.h @@ -2,29 +2,39 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_AURA_H_ -#define UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_AURA_H_ +#ifndef UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_NON_BACKED_H_ +#define UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_NON_BACKED_H_ #include <map> -#include "base/files/file_path.h" -#include "base/macros.h" +#include "base/component_export.h" #include "base/pickle.h" -#include "ui/base/dragdrop/os_exchange_data.h" +#include "ui/base/dragdrop/file_info/file_info.h" +#include "ui/base/dragdrop/os_exchange_data_provider.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/image/image_skia.h" #include "url/gurl.h" +namespace base { +class FilePath; +} // namespace base + namespace ui { class ClipboardFormatType; -// OSExchangeDataProvider implementation for aura on linux. -class UI_BASE_EXPORT OSExchangeDataProviderAura +// Simple OSExchangeDataProvider implementation for aura-based ports with no +// actual platform integration. So data managed by this class is exchangeable +// only among Chromium windows and is available only while it is alive. +class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderNonBacked : public OSExchangeDataProvider { public: - OSExchangeDataProviderAura(); - ~OSExchangeDataProviderAura() override; + OSExchangeDataProviderNonBacked(); + OSExchangeDataProviderNonBacked(const OSExchangeDataProviderNonBacked&) = + delete; + OSExchangeDataProviderNonBacked& operator=( + const OSExchangeDataProviderNonBacked&) = delete; + ~OSExchangeDataProviderNonBacked() override; // Overridden from OSExchangeDataProvider: std::unique_ptr<OSExchangeDataProvider> Clone() const override; @@ -58,8 +68,6 @@ class UI_BASE_EXPORT OSExchangeDataProviderAura gfx::Vector2d GetDragImageOffset() const override; private: - typedef std::map<ClipboardFormatType, base::Pickle> PickleData; - // Returns true if |formats_| contains a file format and the file name can be // parsed as a URL. bool GetFileURL(GURL* url) const; @@ -68,9 +76,9 @@ class UI_BASE_EXPORT OSExchangeDataProviderAura // parsed as a URL. bool GetPlainTextURL(GURL* url) const; - // Actual formats that have been set. See comment above |known_formats_| + // Actual formats that have been set. // for details. - int formats_; + int formats_ = 0; // String contents. base::string16 string_; @@ -83,7 +91,7 @@ class UI_BASE_EXPORT OSExchangeDataProviderAura std::vector<FileInfo> filenames_; // PICKLED_DATA contents. - PickleData pickle_data_; + std::map<ClipboardFormatType, base::Pickle> pickle_data_; // Drag image and offset data. gfx::ImageSkia drag_image_; @@ -92,10 +100,8 @@ class UI_BASE_EXPORT OSExchangeDataProviderAura // For HTML format base::string16 html_; GURL base_url_; - - DISALLOW_COPY_AND_ASSIGN(OSExchangeDataProviderAura); }; } // namespace ui -#endif // UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_AURA_H_ +#endif // UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_NON_BACKED_H_ diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc index 9be3da2f9de..b51a0161fdf 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc @@ -542,9 +542,9 @@ bool OSExchangeDataProviderWin::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, base::string16* title) const { base::string16 url_str; - bool success = - ClipboardUtil::GetUrl(source_object_.Get(), url, title, - policy == CONVERT_FILENAMES ? true : false); + bool success = ClipboardUtil::GetUrl( + source_object_.Get(), url, title, + policy == FilenameToURLPolicy::CONVERT_FILENAMES ? true : false); if (success) { DCHECK(url->is_valid()); return true; @@ -658,7 +658,9 @@ bool OSExchangeDataProviderWin::HasString() const { bool OSExchangeDataProviderWin::HasURL(FilenameToURLPolicy policy) const { return (ClipboardUtil::HasUrl(source_object_.Get(), - policy == CONVERT_FILENAMES ? true : false) || + policy == FilenameToURLPolicy::CONVERT_FILENAMES + ? true + : false) || HasPlainTextURL(source_object_.Get())); } diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h index 481e18f4ab2..f160602b2da 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.h @@ -23,10 +23,10 @@ #define IDataObjectAsyncCapability IAsyncOperation #endif +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/image/image_skia.h" @@ -115,7 +115,8 @@ class DataObjectImpl : public DownloadFileObserver, bool async_operation_started_; }; -class UI_BASE_EXPORT OSExchangeDataProviderWin : public OSExchangeDataProvider { +class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderWin + : public OSExchangeDataProvider { public: // Returns true if source has plain text that is a valid url. static bool HasPlainTextURL(IDataObject* source); diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.cc index f336655478b..fdb28d24631 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.cc @@ -11,11 +11,12 @@ #include "ui/base/x/selection_utils.h" #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/xproto.h" namespace ui { OSExchangeDataProviderX11::OSExchangeDataProviderX11( - XID x_window, + x11::Window x_window, const SelectionFormatMap& selection) : XOSExchangeDataProvider(x_window, selection) {} @@ -69,8 +70,9 @@ void OSExchangeDataProviderX11::SetFileContents( base::RefCountedString::TakeString(&file_contents_copy))); } -bool OSExchangeDataProviderX11::DispatchXEvent(XEvent* xev) { - if (xev->type == SelectionRequest && xev->xany.window == x_window()) { +bool OSExchangeDataProviderX11::DispatchXEvent(x11::Event* xev) { + auto* selection = xev->As<x11::SelectionRequestEvent>(); + if (selection && selection->owner == x_window()) { selection_owner().OnSelectionRequest(*xev); return true; } diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.h b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.h index 980b384c3c5..024152eb474 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.h +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11.h @@ -5,18 +5,22 @@ #ifndef UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_X11_H_ #define UI_BASE_DRAGDROP_OS_EXCHANGE_DATA_PROVIDER_X11_H_ +#include "base/component_export.h" #include "ui/base/x/x11_os_exchange_data_provider.h" #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/x/event.h" namespace ui { // OSExchangeDataProvider implementation for x11 linux. -class UI_BASE_EXPORT OSExchangeDataProviderX11 : public XOSExchangeDataProvider, - public XEventDispatcher { +class COMPONENT_EXPORT(UI_BASE) OSExchangeDataProviderX11 + : public XOSExchangeDataProvider, + public XEventDispatcher { public: // |x_window| is the window the cursor is over, and |selection| is the set of // data being offered. - OSExchangeDataProviderX11(XID x_window, const SelectionFormatMap& selection); + OSExchangeDataProviderX11(x11::Window x_window, + const SelectionFormatMap& selection); // Creates a Provider for sending drag information. This creates its own, // hidden X11 window to own send data. @@ -34,7 +38,7 @@ class UI_BASE_EXPORT OSExchangeDataProviderX11 : public XOSExchangeDataProvider, const std::string& file_contents) override; // XEventDispatcher: - bool DispatchXEvent(XEvent* xev) override; + bool DispatchXEvent(x11::Event* xev) override; private: friend class OSExchangeDataProviderX11Test; diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc index 82f9c71aabd..11a7fd89a44 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_x11_unittest.cc @@ -47,8 +47,8 @@ TEST_F(OSExchangeDataProviderX11Test, MozillaURL) { { GURL out_gurl; base::string16 out_str; - EXPECT_TRUE( - provider.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); + EXPECT_TRUE(provider.GetURLAndTitle( + FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); EXPECT_EQ(base::ASCIIToUTF16(kGoogleTitle), out_str); EXPECT_EQ(kGoogleURL, out_gurl.spec()); } @@ -58,8 +58,8 @@ TEST_F(OSExchangeDataProviderX11Test, MozillaURL) { { GURL out_gurl; base::string16 out_str; - EXPECT_TRUE( - provider.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); + EXPECT_TRUE(provider.GetURLAndTitle( + FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); EXPECT_EQ(base::string16(), out_str); EXPECT_EQ(kGoogleURL, out_gurl.spec()); } @@ -69,24 +69,24 @@ TEST_F(OSExchangeDataProviderX11Test, FilesArentURLs) { AddURLList(kFileURL); EXPECT_TRUE(provider.HasFile()); - EXPECT_TRUE(provider.HasURL(ui::CONVERT_FILENAMES)); - EXPECT_FALSE(provider.HasURL(ui::DO_NOT_CONVERT_FILENAMES)); + EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); + EXPECT_FALSE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); } TEST_F(OSExchangeDataProviderX11Test, HTTPURLsArentFiles) { AddURLList(kGoogleURL); EXPECT_FALSE(provider.HasFile()); - EXPECT_TRUE(provider.HasURL(ui::CONVERT_FILENAMES)); - EXPECT_TRUE(provider.HasURL(ui::DO_NOT_CONVERT_FILENAMES)); + EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); + EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); } TEST_F(OSExchangeDataProviderX11Test, URIListWithBoth) { AddURLList("file:///home/user/file.txt\nhttp://www.google.com"); EXPECT_TRUE(provider.HasFile()); - EXPECT_TRUE(provider.HasURL(ui::CONVERT_FILENAMES)); - EXPECT_TRUE(provider.HasURL(ui::DO_NOT_CONVERT_FILENAMES)); + EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); + EXPECT_TRUE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); // We should only receive the file from GetFilenames(). std::vector<FileInfo> filenames; @@ -97,8 +97,8 @@ TEST_F(OSExchangeDataProviderX11Test, URIListWithBoth) { // We should only receive the URL here. GURL out_gurl; base::string16 out_str; - EXPECT_TRUE( - provider.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); + EXPECT_TRUE(provider.GetURLAndTitle( + FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &out_gurl, &out_str)); EXPECT_EQ(base::string16(), out_str); EXPECT_EQ(kGoogleURL, out_gurl.spec()); } @@ -108,7 +108,7 @@ TEST_F(OSExchangeDataProviderX11Test, OnlyStringURLIsUnfiltered) { provider.SetString(file_url); EXPECT_TRUE(provider.HasString()); - EXPECT_FALSE(provider.HasURL(ui::DO_NOT_CONVERT_FILENAMES)); + EXPECT_FALSE(provider.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); } TEST_F(OSExchangeDataProviderX11Test, StringAndURIListFilterString) { diff --git a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc index 3c000b0f0a7..e57cc2eb849 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc @@ -48,7 +48,8 @@ TEST_F(OSExchangeDataTest, StringDataGetAndSet) { std::string url_spec = "http://www.goats.com/"; GURL url(url_spec); base::string16 title; - EXPECT_FALSE(data2.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &url, &title)); + EXPECT_FALSE(data2.GetURLAndTitle( + FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &url, &title)); // No URLs in |data|, so url should be untouched. EXPECT_EQ(url_spec, url.spec()); } @@ -58,9 +59,9 @@ TEST_F(OSExchangeDataTest, TestURLExchangeFormats) { std::string url_spec = "http://www.google.com/"; GURL url(url_spec); base::string16 url_title = base::ASCIIToUTF16("www.google.com"); - EXPECT_FALSE(data.HasURL(DO_NOT_CONVERT_FILENAMES)); + EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); data.SetURL(url, url_title); - EXPECT_TRUE(data.HasURL(DO_NOT_CONVERT_FILENAMES)); + EXPECT_TRUE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); OSExchangeData data2( std::unique_ptr<OSExchangeDataProvider>(data.provider().Clone())); @@ -68,9 +69,10 @@ TEST_F(OSExchangeDataTest, TestURLExchangeFormats) { // URL spec and title should match GURL output_url; base::string16 output_title; - EXPECT_TRUE(data2.HasURL(DO_NOT_CONVERT_FILENAMES)); - EXPECT_TRUE(data2.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &output_url, - &output_title)); + EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); + EXPECT_TRUE( + data2.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, + &output_url, &output_title)); EXPECT_EQ(url_spec, output_url.spec()); EXPECT_EQ(url_title, output_title); base::string16 output_string; @@ -96,16 +98,16 @@ TEST_F(OSExchangeDataTest, URLAndString) { GURL output_url; base::string16 output_title; - EXPECT_TRUE(data.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &output_url, - &output_title)); + EXPECT_TRUE(data.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, + &output_url, &output_title)); EXPECT_EQ(url_spec, output_url.spec()); EXPECT_EQ(url_title, output_title); } TEST_F(OSExchangeDataTest, TestFileToURLConversion) { OSExchangeData data; - EXPECT_FALSE(data.HasURL(DO_NOT_CONVERT_FILENAMES)); - EXPECT_FALSE(data.HasURL(CONVERT_FILENAMES)); + EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); + EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); EXPECT_FALSE(data.HasFile()); base::FilePath current_directory; @@ -114,21 +116,22 @@ TEST_F(OSExchangeDataTest, TestFileToURLConversion) { data.SetFilename(current_directory); { - EXPECT_FALSE(data.HasURL(DO_NOT_CONVERT_FILENAMES)); + EXPECT_FALSE(data.HasURL(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES)); GURL actual_url; base::string16 actual_title; - EXPECT_FALSE(data.GetURLAndTitle(DO_NOT_CONVERT_FILENAMES, &actual_url, - &actual_title)); + EXPECT_FALSE( + data.GetURLAndTitle(FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, + &actual_url, &actual_title)); EXPECT_EQ(GURL(), actual_url); EXPECT_EQ(base::string16(), actual_title); } { - EXPECT_TRUE(data.HasURL(CONVERT_FILENAMES)); + EXPECT_TRUE(data.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL actual_url; base::string16 actual_title; - EXPECT_TRUE( - data.GetURLAndTitle(CONVERT_FILENAMES, &actual_url, &actual_title)); + EXPECT_TRUE(data.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, + &actual_url, &actual_title)); // Some Mac OS versions return the URL in file://localhost form instead // of file:///, so we compare the url's path not its absolute string. EXPECT_EQ(net::FilePathToFileURL(current_directory).path(), diff --git a/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc index 750fd72ea75..1bc955e3806 100644 --- a/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc +++ b/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc @@ -100,10 +100,11 @@ TEST_F(OSExchangeDataWinTest, StringDataWritingViaCOM) { // Construct a new object with the old object so that we can use our access // APIs. OSExchangeData data2(data.provider().Clone()); - EXPECT_TRUE(data2.HasURL(CONVERT_FILENAMES)); + EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL url_from_data; std::wstring title; - EXPECT_TRUE(data2.GetURLAndTitle(CONVERT_FILENAMES, &url_from_data, &title)); + EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, + &url_from_data, &title)); GURL reference_url(input); EXPECT_EQ(reference_url.spec(), url_from_data.spec()); } @@ -147,10 +148,11 @@ TEST_F(OSExchangeDataWinTest, RemoveData) { // Construct a new object with the old object so that we can use our access // APIs. OSExchangeData data2(data.provider().Clone()); - EXPECT_TRUE(data2.HasURL(CONVERT_FILENAMES)); + EXPECT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL url_from_data; std::wstring title; - EXPECT_TRUE(data2.GetURLAndTitle(CONVERT_FILENAMES, &url_from_data, &title)); + EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, + &url_from_data, &title)); EXPECT_EQ(GURL(input2).spec(), url_from_data.spec()); } @@ -853,10 +855,11 @@ TEST_F(OSExchangeDataWinTest, ProvideURLForPlainTextURL) { data.SetString(L"http://google.com"); OSExchangeData data2(data.provider().Clone()); - ASSERT_TRUE(data2.HasURL(CONVERT_FILENAMES)); + ASSERT_TRUE(data2.HasURL(FilenameToURLPolicy::CONVERT_FILENAMES)); GURL read_url; std::wstring title; - EXPECT_TRUE(data2.GetURLAndTitle(CONVERT_FILENAMES, &read_url, &title)); + EXPECT_TRUE(data2.GetURLAndTitle(FilenameToURLPolicy::CONVERT_FILENAMES, + &read_url, &title)); EXPECT_EQ(GURL("http://google.com"), read_url); } diff --git a/chromium/ui/base/emoji/emoji_panel_helper.h b/chromium/ui/base/emoji/emoji_panel_helper.h index 344316b629f..df37ef0162f 100644 --- a/chromium/ui/base/emoji/emoji_panel_helper.h +++ b/chromium/ui/base/emoji/emoji_panel_helper.h @@ -6,22 +6,22 @@ #define UI_BASE_EMOJI_EMOJI_PANEL_HELPER_H_ #include "base/callback.h" +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" namespace ui { // Returns whether showing the Emoji Panel is supported on this version of // the operating system. -UI_BASE_EXPORT bool IsEmojiPanelSupported(); +COMPONENT_EXPORT(UI_BASE) bool IsEmojiPanelSupported(); // Invokes the commands to show the Emoji Panel. -UI_BASE_EXPORT void ShowEmojiPanel(); +COMPONENT_EXPORT(UI_BASE) void ShowEmojiPanel(); #if defined(OS_CHROMEOS) // Sets a callback to show the emoji panel (ChromeOS only). -UI_BASE_EXPORT void SetShowEmojiKeyboardCallback( - base::RepeatingClosure callback); +COMPONENT_EXPORT(UI_BASE) +void SetShowEmojiKeyboardCallback(base::RepeatingClosure callback); #endif } // namespace ui diff --git a/chromium/ui/base/idle/BUILD.gn b/chromium/ui/base/idle/BUILD.gn index 9120a2df91e..8e76844e5b6 100644 --- a/chromium/ui/base/idle/BUILD.gn +++ b/chromium/ui/base/idle/BUILD.gn @@ -61,7 +61,6 @@ component("idle") { } if (use_x11 && !is_chromeos) { - configs += [ "//build/config/linux:xscrnsaver" ] deps += [ "//ui/gfx/x" ] sources += [ "idle_query_x11.cc", diff --git a/chromium/ui/base/idle/idle_query_x11.cc b/chromium/ui/base/idle/idle_query_x11.cc index ee676686f36..569c57a2d71 100644 --- a/chromium/ui/base/idle/idle_query_x11.cc +++ b/chromium/ui/base/idle/idle_query_x11.cc @@ -4,43 +4,28 @@ #include "ui/base/idle/idle_query_x11.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/screensaver.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_types.h" namespace ui { -class IdleData { - public: - IdleData() { - int event_base; - int error_base; - if (XScreenSaverQueryExtension(gfx::GetXDisplay(), &event_base, - &error_base)) { - mit_info.reset(XScreenSaverAllocInfo()); - } - } - - ~IdleData() { - } - - gfx::XScopedPtr<XScreenSaverInfo> mit_info; -}; - -IdleQueryX11::IdleQueryX11() : idle_data_(new IdleData()) {} +IdleQueryX11::IdleQueryX11() : connection_(x11::Connection::Get()) { + // Let the server know the client version before making any requests. + connection_->screensaver().QueryVersion( + {x11::ScreenSaver::major_version, x11::ScreenSaver::minor_version}); +} -IdleQueryX11::~IdleQueryX11() {} +IdleQueryX11::~IdleQueryX11() = default; int IdleQueryX11::IdleTime() { - if (!idle_data_->mit_info) - return 0; - - if (XScreenSaverQueryInfo(gfx::GetXDisplay(), - XRootWindow(gfx::GetXDisplay(), 0), - idle_data_->mit_info.get())) { - return (idle_data_->mit_info->idle) / 1000; - } else { - return 0; + if (auto reply = connection_->screensaver() + .QueryInfo({connection_->default_root()}) + .Sync()) { + return reply->ms_since_user_input / 1000; } + return 0; } } // namespace ui diff --git a/chromium/ui/base/idle/idle_query_x11.h b/chromium/ui/base/idle/idle_query_x11.h index 0857418897e..457aada6a1e 100644 --- a/chromium/ui/base/idle/idle_query_x11.h +++ b/chromium/ui/base/idle/idle_query_x11.h @@ -9,9 +9,11 @@ #include "base/macros.h" -namespace ui { +namespace x11 { +class Connection; +} -class IdleData; +namespace ui { class IdleQueryX11 { public: @@ -21,7 +23,7 @@ class IdleQueryX11 { int IdleTime(); private: - std::unique_ptr<IdleData> idle_data_; + x11::Connection* connection_; DISALLOW_COPY_AND_ASSIGN(IdleQueryX11); }; diff --git a/chromium/ui/base/idle/screensaver_window_finder_x11.cc b/chromium/ui/base/idle/screensaver_window_finder_x11.cc index 74f1a5f6fcd..45342ff5383 100644 --- a/chromium/ui/base/idle/screensaver_window_finder_x11.cc +++ b/chromium/ui/base/idle/screensaver_window_finder_x11.cc @@ -5,26 +5,27 @@ #include "ui/base/idle/screensaver_window_finder_x11.h" #include "ui/base/x/x11_util.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/screensaver.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_error_tracker.h" namespace ui { -ScreensaverWindowFinder::ScreensaverWindowFinder() - : exists_(false) { -} +ScreensaverWindowFinder::ScreensaverWindowFinder() : exists_(false) {} bool ScreensaverWindowFinder::ScreensaverWindowExists() { - XScreenSaverInfo info; - XDisplay* display = gfx::GetXDisplay(); - XID root = DefaultRootWindow(display); - static int xss_event_base; - static int xss_error_base; - static bool have_xss = - XScreenSaverQueryExtension(display, &xss_event_base, &xss_error_base); - if (have_xss && XScreenSaverQueryInfo(display, root, &info) && - info.state == ScreenSaverOn) { + auto* connection = x11::Connection::Get(); + + // Let the server know the client version before making any requests. + connection->screensaver().QueryVersion( + {x11::ScreenSaver::major_version, x11::ScreenSaver::minor_version}); + + auto reply = + connection->screensaver().QueryInfo({connection->default_root()}).Sync(); + if (reply && static_cast<x11::ScreenSaver::State>(reply->state) == + x11::ScreenSaver::State::On) { return true; } @@ -32,9 +33,10 @@ bool ScreensaverWindowFinder::ScreensaverWindowExists() { // info.state == ScreenSaverOff or info.state == ScreenSaverDisabled does not // necessarily mean that a screensaver is not active, so add a special check // for xscreensaver. - XAtom lock_atom = gfx::GetAtom("LOCK"); + x11::Atom lock_atom = gfx::GetAtom("LOCK"); std::vector<int> atom_properties; - if (GetIntArrayProperty(root, "_SCREENSAVER_STATUS", &atom_properties) && + if (GetIntArrayProperty(GetX11RootWindow(), "_SCREENSAVER_STATUS", + &atom_properties) && atom_properties.size() > 0) { if (atom_properties[0] == static_cast<int>(lock_atom)) { return true; @@ -48,14 +50,14 @@ bool ScreensaverWindowFinder::ScreensaverWindowExists() { return finder.exists_ && !err_tracker.FoundNewError(); } -bool ScreensaverWindowFinder::ShouldStopIterating(XID window) { +bool ScreensaverWindowFinder::ShouldStopIterating(x11::Window window) { if (!ui::IsWindowVisible(window) || !IsScreensaverWindow(window)) return false; exists_ = true; return true; } -bool ScreensaverWindowFinder::IsScreensaverWindow(XID window) const { +bool ScreensaverWindowFinder::IsScreensaverWindow(x11::Window window) const { // It should occupy the full screen. if (!ui::IsX11WindowFullScreen(window)) return false; diff --git a/chromium/ui/base/idle/screensaver_window_finder_x11.h b/chromium/ui/base/idle/screensaver_window_finder_x11.h index dad3d209510..a502daa6fbe 100644 --- a/chromium/ui/base/idle/screensaver_window_finder_x11.h +++ b/chromium/ui/base/idle/screensaver_window_finder_x11.h @@ -16,12 +16,12 @@ class ScreensaverWindowFinder : public ui::EnumerateWindowsDelegate { static bool ScreensaverWindowExists(); protected: - bool ShouldStopIterating(XID window) override; + bool ShouldStopIterating(x11::Window window) override; private: ScreensaverWindowFinder(); - bool IsScreensaverWindow(XID window) const; + bool IsScreensaverWindow(x11::Window window) const; bool exists_; diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn index 2a0670796c0..5ab39cdea54 100644 --- a/chromium/ui/base/ime/BUILD.gn +++ b/chromium/ui/base/ime/BUILD.gn @@ -58,8 +58,6 @@ jumbo_component("ime") { "constants.cc", "constants.h", "ime_assistive_window_handler_interface.h", - "ime_bridge.cc", - "ime_bridge.h", "ime_candidate_window_handler_interface.h", "ime_engine_handler_interface.h", "ime_input_context_handler_interface.h", @@ -81,7 +79,6 @@ jumbo_component("ime") { "text_edit_commands.h", "text_input_client.cc", "text_input_client.h", - "virtual_keyboard_visibility_request.h", ] defines = [ "IS_UI_BASE_IME_IMPL" ] diff --git a/chromium/ui/base/ime/chromeos/BUILD.gn b/chromium/ui/base/ime/chromeos/BUILD.gn index 4baf9294a95..03f91b5ea59 100644 --- a/chromium/ui/base/ime/chromeos/BUILD.gn +++ b/chromium/ui/base/ime/chromeos/BUILD.gn @@ -22,6 +22,8 @@ jumbo_component("chromeos") { "fake_ime_keyboard.h", "fake_input_method_delegate.cc", "fake_input_method_delegate.h", + "ime_bridge.cc", + "ime_bridge.h", "ime_keyboard.cc", "ime_keyboard_impl.cc", "ime_keyboard_impl.h", diff --git a/chromium/ui/base/ime/dummy_input_method.cc b/chromium/ui/base/ime/dummy_input_method.cc index 4e3dff450b2..da32e766c9c 100644 --- a/chromium/ui/base/ime/dummy_input_method.cc +++ b/chromium/ui/base/ime/dummy_input_method.cc @@ -98,9 +98,4 @@ DummyInputMethod::GetInputMethodKeyboardController() { return nullptr; } -const std::vector<std::unique_ptr<KeyEvent>>& -DummyInputMethod::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/dummy_input_method.h b/chromium/ui/base/ime/dummy_input_method.h index 9865876b0ad..fba6e76cdb2 100644 --- a/chromium/ui/base/ime/dummy_input_method.h +++ b/chromium/ui/base/ime/dummy_input_method.h @@ -49,11 +49,7 @@ class DummyInputMethod : public InputMethod { void RemoveObserver(InputMethodObserver* observer) override; InputMethodKeyboardController* GetInputMethodKeyboardController() override; - const std::vector<std::unique_ptr<KeyEvent>>& GetKeyEventsForTesting() - override; - private: - std::vector<std::unique_ptr<KeyEvent>> key_events_for_testing_; DISALLOW_COPY_AND_ASSIGN(DummyInputMethod); }; diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc index 2ed42e851b2..a286b663259 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.cc +++ b/chromium/ui/base/ime/dummy_text_input_client.cc @@ -152,6 +152,14 @@ bool DummyTextInputClient::SetCompositionFromExistingText( } #endif +#if defined(OS_CHROMEOS) +bool DummyTextInputClient::SetAutocorrectRange( + const base::string16& autocorrect_text, + const gfx::Range& range) { + return false; +} +#endif + #if defined(OS_WIN) void DummyTextInputClient::GetActiveTextInputControlLayoutBounds( base::Optional<gfx::Rect>* control_bounds, diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h index e145feda8f6..af8f0ad48fc 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.h +++ b/chromium/ui/base/ime/dummy_text_input_client.h @@ -62,6 +62,12 @@ class DummyTextInputClient : public TextInputClient { const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override; #endif +#if defined(OS_CHROMEOS) + // Set the autocorrect range + bool SetAutocorrectRange(const base::string16& autocorrect_text, + const gfx::Range& range) override; +#endif + #if defined(OS_WIN) void GetActiveTextInputControlLayoutBounds( base::Optional<gfx::Rect>* control_bounds, diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc index 2d205c8d182..9959fa3d031 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc @@ -9,7 +9,7 @@ #include <memory> #include <utility> -#include "base/fuchsia/default_context.h" +#include "base/fuchsia/process_context.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/base_event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -22,7 +22,7 @@ InputMethodFuchsia::InputMethodFuchsia(internal::InputMethodDelegate* delegate, : InputMethodBase(delegate), event_converter_(this), ime_client_binding_(this), - ime_service_(base::fuchsia::ComponentContextForCurrentProcess() + ime_service_(base::ComponentContextForProcess() ->svc() ->Connect<fuchsia::ui::input::ImeService>()), virtual_keyboard_controller_(ime_service_.get()) {} diff --git a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc index c284253ad9b..6a6271b471e 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc @@ -7,9 +7,11 @@ #include <lib/sys/cpp/component_context.h> #include <utility> +#include "base/check.h" #include "base/fuchsia/default_context.h" #include "base/fuchsia/fuchsia_logging.h" -#include "base/logging.h" +#include "base/fuchsia/process_context.h" +#include "base/notreached.h" namespace ui { @@ -17,7 +19,7 @@ InputMethodKeyboardControllerFuchsia::InputMethodKeyboardControllerFuchsia( fuchsia::ui::input::ImeService* ime_service) : ime_service_(ime_service), ime_visibility_( - base::fuchsia::ComponentContextForCurrentProcess() + base::ComponentContextForProcess() ->svc() ->Connect<fuchsia::ui::input::ImeVisibilityService>()) { DCHECK(ime_service_); diff --git a/chromium/ui/base/ime/ime_assistive_window_handler_interface.h b/chromium/ui/base/ime/ime_assistive_window_handler_interface.h index 8807731e9a0..d400f291dff 100644 --- a/chromium/ui/base/ime/ime_assistive_window_handler_interface.h +++ b/chromium/ui/base/ime/ime_assistive_window_handler_interface.h @@ -14,6 +14,13 @@ namespace gfx { class Rect; } // namespace gfx +namespace ui { +namespace ime { +struct AssistiveWindowButton; +struct SuggestionDetails; +} // namespace ime +} // namespace ui + namespace chromeos { struct AssistiveWindowProperties; @@ -27,9 +34,19 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEAssistiveWindowHandlerInterface { virtual void SetAssistiveWindowProperties( const AssistiveWindowProperties& window) {} - virtual void ShowSuggestion(const base::string16& text, - const size_t confirmed_length, - const bool show_tab) {} + virtual void ShowSuggestion(const ui::ime::SuggestionDetails& details) {} + + virtual void ShowMultipleSuggestions( + const std::vector<base::string16>& suggestions) {} + + // Highlights or unhighlights a given assistive button based on the given + // parameters. + virtual void SetButtonHighlighted( + const ui::ime::AssistiveWindowButton& button, + bool highlighted) {} + + virtual void AcceptSuggestion(const base::string16& suggestion) {} + virtual void HideSuggestion() {} // Called to get the current suggestion text. diff --git a/chromium/ui/base/ime/ime_bridge.cc b/chromium/ui/base/ime/ime_bridge.cc deleted file mode 100644 index 5e44712f9a0..00000000000 --- a/chromium/ui/base/ime/ime_bridge.cc +++ /dev/null @@ -1,146 +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/base/ime/ime_bridge.h" - -#include <map> - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/observer_list.h" -#include "build/build_config.h" - -namespace ui { - -static IMEBridge* g_ime_bridge = nullptr; - -// An implementation of IMEBridge. -class IMEBridgeImpl : public IMEBridge { - public: - IMEBridgeImpl() - : current_input_context_(ui::TEXT_INPUT_TYPE_NONE, - ui::TEXT_INPUT_MODE_DEFAULT, - 0, - ui::TextInputClient::FOCUS_REASON_NONE, - false /* should_do_learning */) {} - - ~IMEBridgeImpl() override {} - - // IMEBridge override. - IMEInputContextHandlerInterface* GetInputContextHandler() const override { - return input_context_handler_; - } - - // IMEBridge override. - void SetInputContextHandler( - IMEInputContextHandlerInterface* handler) override { - input_context_handler_ = handler; - for (auto& observer : observers_) - observer.OnInputContextHandlerChanged(); - } - - // IMEBridge override. - void SetCurrentEngineHandler(IMEEngineHandlerInterface* handler) override { - engine_handler_ = handler; - } - - // IMEBridge override. - IMEEngineHandlerInterface* GetCurrentEngineHandler() const override { - return engine_handler_; - } - - // IMEBridge override. - void SetCurrentInputContext( - const IMEEngineHandlerInterface::InputContext& input_context) override { - current_input_context_ = input_context; - } - - // IMEBridge override. - const IMEEngineHandlerInterface::InputContext& GetCurrentInputContext() - const override { - return current_input_context_; - } - - // IMEBridge override. - void AddObserver(ui::IMEBridgeObserver* observer) override { - observers_.AddObserver(observer); - } - - // IMEBridge override. - void RemoveObserver(ui::IMEBridgeObserver* observer) override { - observers_.RemoveObserver(observer); - } - - // IMEBridge override. - void MaybeSwitchEngine() override { - for (auto& observer : observers_) - observer.OnRequestSwitchEngine(); - } - -#if defined(OS_CHROMEOS) - // IMEBridge override. - void SetCandidateWindowHandler( - chromeos::IMECandidateWindowHandlerInterface* handler) override { - candidate_window_handler_ = handler; - } - - // IMEBridge override. - chromeos::IMECandidateWindowHandlerInterface* GetCandidateWindowHandler() - const override { - return candidate_window_handler_; - } - - // IMEBridge override. - void SetAssistiveWindowHandler( - chromeos::IMEAssistiveWindowHandlerInterface* handler) override { - assistive_window_handler_ = handler; - } - - // IMEBridge override. - chromeos::IMEAssistiveWindowHandlerInterface* GetAssistiveWindowHandler() - const override { - return assistive_window_handler_; - } -#endif - - private: - IMEInputContextHandlerInterface* input_context_handler_ = nullptr; - IMEEngineHandlerInterface* engine_handler_ = nullptr; - base::ObserverList<IMEBridgeObserver> observers_; - IMEEngineHandlerInterface::InputContext current_input_context_; - -#if defined(OS_CHROMEOS) - chromeos::IMECandidateWindowHandlerInterface* candidate_window_handler_ = - nullptr; - chromeos::IMEAssistiveWindowHandlerInterface* assistive_window_handler_ = - nullptr; -#endif - - DISALLOW_COPY_AND_ASSIGN(IMEBridgeImpl); -}; - -/////////////////////////////////////////////////////////////////////////////// -// IMEBridge -IMEBridge::IMEBridge() {} - -IMEBridge::~IMEBridge() {} - -// static. -void IMEBridge::Initialize() { - if (!g_ime_bridge) - g_ime_bridge = new IMEBridgeImpl(); -} - -// static. -void IMEBridge::Shutdown() { - delete g_ime_bridge; - g_ime_bridge = nullptr; -} - -// static. -IMEBridge* IMEBridge::Get() { - return g_ime_bridge; -} - -} // namespace ui diff --git a/chromium/ui/base/ime/ime_bridge.h b/chromium/ui/base/ime/ime_bridge.h deleted file mode 100644 index 9fade0b1944..00000000000 --- a/chromium/ui/base/ime/ime_bridge.h +++ /dev/null @@ -1,102 +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_BASE_IME_IME_BRIDGE_H_ -#define UI_BASE_IME_IME_BRIDGE_H_ - -#include "base/component_export.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "ui/base/ime/ime_bridge_observer.h" -#include "ui/base/ime/ime_engine_handler_interface.h" -#include "ui/base/ime/ime_input_context_handler_interface.h" - -#if defined(OS_CHROMEOS) -#include "ui/base/ime/ime_assistive_window_handler_interface.h" -#include "ui/base/ime/ime_candidate_window_handler_interface.h" - -namespace chromeos { -class IMECandidateWindowHandlerInterface; -class IMEAssistiveWindowHandlerInterface; -} -#endif - -namespace ui { - -// IMEBridge provides access of each IME related handler. This class -// is used for IME implementation. -class COMPONENT_EXPORT(UI_BASE_IME) IMEBridge { - public: - virtual ~IMEBridge(); - - // Allocates the global instance. Must be called before any calls to Get(). - static void Initialize(); - - // Releases the global instance. - static void Shutdown(); - - // Returns IMEBridge global instance. Initialize() must be called first. - static IMEBridge* Get(); - - // Returns current InputContextHandler. This function returns NULL if input - // context is not ready to use. - virtual IMEInputContextHandlerInterface* GetInputContextHandler() const = 0; - - // Updates current InputContextHandler. If there is no active input context, - // pass NULL for |handler|. Caller must release |handler|. - virtual void SetInputContextHandler( - IMEInputContextHandlerInterface* handler) = 0; - - // Updates current EngineHandler. If there is no active engine service, pass - // NULL for |handler|. Caller must release |handler|. - virtual void SetCurrentEngineHandler(IMEEngineHandlerInterface* handler) = 0; - - // Returns current EngineHandler. This function returns NULL if current engine - // is not ready to use. - virtual IMEEngineHandlerInterface* GetCurrentEngineHandler() const = 0; - - // Updates the current input context. - // This is called from InputMethodChromeOS. - virtual void SetCurrentInputContext( - const IMEEngineHandlerInterface::InputContext& input_context) = 0; - - // Returns the current input context. - // This is called from InputMethodEngine. - virtual const IMEEngineHandlerInterface::InputContext& - GetCurrentInputContext() const = 0; - - // Add or remove observers of events such as switching engines, etc. - virtual void AddObserver(ui::IMEBridgeObserver* observer) = 0; - virtual void RemoveObserver(ui::IMEBridgeObserver* observer) = 0; - - // Switches the engine handler upon top level window focus change. - virtual void MaybeSwitchEngine() = 0; - -#if defined(OS_CHROMEOS) - // Returns current CandidateWindowHandler. This function returns NULL if - // current candidate window is not ready to use. - virtual chromeos::IMECandidateWindowHandlerInterface* - GetCandidateWindowHandler() const = 0; - - // Updates current CandidatWindowHandler. If there is no active candidate - // window service, pass NULL for |handler|. Caller must release |handler|. - virtual void SetCandidateWindowHandler( - chromeos::IMECandidateWindowHandlerInterface* handler) = 0; - - virtual chromeos::IMEAssistiveWindowHandlerInterface* - GetAssistiveWindowHandler() const = 0; - virtual void SetAssistiveWindowHandler( - chromeos::IMEAssistiveWindowHandlerInterface* handler) = 0; -#endif - - protected: - IMEBridge(); - - private: - DISALLOW_COPY_AND_ASSIGN(IMEBridge); -}; - -} // namespace ui - -#endif // UI_BASE_IME_IME_BRIDGE_H_ diff --git a/chromium/ui/base/ime/ime_engine_handler_interface.h b/chromium/ui/base/ime/ime_engine_handler_interface.h index 4eb49c6ecf0..4895587e81c 100644 --- a/chromium/ui/base/ime/ime_engine_handler_interface.h +++ b/chromium/ui/base/ime/ime_engine_handler_interface.h @@ -24,8 +24,15 @@ class Rect; namespace ui { +class InputMethodKeyboardController; class KeyEvent; +#if defined(OS_CHROMEOS) +namespace ime { +struct AssistiveWindowButton; +} // namespace ime +#endif // defined(OS_CHROMEOS) + // A interface to handle the engine handler method call. class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { public: @@ -114,6 +121,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { // Called when the composition bounds changed. virtual void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) = 0; + // Gets the implementation of the keyboard controller. + virtual ui::InputMethodKeyboardController* GetInputMethodKeyboardController() + const = 0; + #if defined(OS_CHROMEOS) // Called when a property is activated or changed. @@ -123,6 +134,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { // based candidate index in lookup table. virtual void CandidateClicked(uint32_t index) = 0; + // Called when assistive window is clicked. + virtual void AssistiveWindowButtonClicked( + const ui::ime::AssistiveWindowButton& button) {} + // Sets the mirroring/casting enable states. virtual void SetMirroringEnabled(bool mirroring_enabled) = 0; virtual void SetCastingEnabled(bool casting_enabled) = 0; 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 5387c7b7b0e..46fd1fef8ea 100644 --- a/chromium/ui/base/ime/ime_input_context_handler_interface.h +++ b/chromium/ui/base/ime/ime_input_context_handler_interface.h @@ -33,6 +33,11 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEInputContextHandlerInterface { uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) = 0; + // Set the autocorrect range with text. + virtual bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) = 0; + // Called when the engine changes the selection range. // Returns true if the operation was successful. virtual bool SetSelectionRange(uint32_t start, uint32_t end) = 0; diff --git a/chromium/ui/base/ime/ime_text_span.h b/chromium/ui/base/ime/ime_text_span.h index c76734e2e4f..62bdfb8cbac 100644 --- a/chromium/ui/base/ime/ime_text_span.h +++ b/chromium/ui/base/ime/ime_text_span.h @@ -15,9 +15,6 @@ namespace ui { -// Intentionally keep sync with blink::WebImeTextSpan defined in: -// third_party/WebKit/public/web/WebImeTextSpan.h - struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { enum class Type { // Creates a composition marker. @@ -29,6 +26,8 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { // replacement, and will be ignored if added to an element with spell // checking disabled. kMisspellingSuggestion, + // Creates an autocorrect marker that isn't cleared by itself. + kAutocorrect, }; enum class Thickness { @@ -72,6 +71,7 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { rhs.suggestion_highlight_color) && (this->remove_on_finish_composing == rhs.remove_on_finish_composing) && + (this->interim_char_selection == rhs.interim_char_selection) && (this->suggestions == rhs.suggestions); } @@ -87,6 +87,7 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { SkColor background_color; SkColor suggestion_highlight_color; bool remove_on_finish_composing = false; + bool interim_char_selection = false; std::vector<std::string> suggestions; }; diff --git a/chromium/ui/base/ime/init/BUILD.gn b/chromium/ui/base/ime/init/BUILD.gn index 0aad80f4551..26e7a60f901 100644 --- a/chromium/ui/base/ime/init/BUILD.gn +++ b/chromium/ui/base/ime/init/BUILD.gn @@ -31,6 +31,9 @@ jumbo_component("init") { if (is_mac) { deps += [ "//ui/base/ime/mac" ] } + if (is_chromeos) { + deps += [ "//ui/base/ime/chromeos" ] + } if (is_linux && !is_chromeos) { deps += [ "//ui/base/ime/linux" ] } diff --git a/chromium/ui/base/ime/init/input_method_factory.cc b/chromium/ui/base/ime/init/input_method_factory.cc index 5e98636a36c..d923c6b2331 100644 --- a/chromium/ui/base/ime/init/input_method_factory.cc +++ b/chromium/ui/base/ime/init/input_method_factory.cc @@ -5,6 +5,7 @@ #include "ui/base/ime/init/input_method_factory.h" #include "base/command_line.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/win/windows_version.h" #include "build/build_config.h" @@ -17,10 +18,15 @@ #include "ui/base/ime/win/input_method_win_tsf.h" #elif defined(OS_MACOSX) #include "ui/base/ime/mac/input_method_mac.h" -#elif defined(USE_X11) -#include "ui/base/ime/linux/input_method_auralinux.h" -#elif defined(USE_OZONE) +#elif defined(USE_X11) || defined(USE_OZONE) +#if defined(USE_X11) +// TODO(crbug.com/1085700): Remove nogncheck when we can build both Ozone +// Wayland and X11 on Linux codesearch-gen bots. +#include "ui/base/ime/linux/input_method_auralinux.h" // nogncheck +#endif // defined(USE_X11) +#if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" +#endif // defined(USE_OZONE) #else #include "ui/base/ime/input_method_minimal.h" #endif @@ -63,10 +69,18 @@ std::unique_ptr<InputMethod> CreateInputMethod( return std::make_unique<InputMethodWinImm32>(delegate, widget); #elif defined(OS_MACOSX) return std::make_unique<InputMethodMac>(delegate); -#elif defined(USE_X11) - return std::make_unique<InputMethodAuraLinux>(delegate); -#elif defined(USE_OZONE) - return ui::OzonePlatform::GetInstance()->CreateInputMethod(delegate, widget); +#elif defined(USE_X11) || defined(USE_OZONE) +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) { + return ui::OzonePlatform::GetInstance()->CreateInputMethod(delegate, + widget); + } +#endif // defined(USE_OZONE) +#if defined(USE_X11) + return std::make_unique<ui::InputMethodAuraLinux>(delegate); +#endif // defined(USE_X11) + NOTREACHED(); + return nullptr; #else return std::make_unique<InputMethodMinimal>(delegate); #endif diff --git a/chromium/ui/base/ime/init/input_method_initializer.cc b/chromium/ui/base/ime/init/input_method_initializer.cc index 1a453109dbc..1bfc48a8005 100644 --- a/chromium/ui/base/ime/init/input_method_initializer.cc +++ b/chromium/ui/base/ime/init/input_method_initializer.cc @@ -9,10 +9,12 @@ #include "build/build_config.h" #if defined(OS_CHROMEOS) -#include "ui/base/ime/ime_bridge.h" +#include "ui/base/ime/chromeos/ime_bridge.h" #elif defined(USE_AURA) && defined(OS_LINUX) #include "base/check.h" -#include "ui/base/ime/linux/fake_input_method_context_factory.h" +// TODO(crbug.com/1085700): Remove nogncheck when we can build both Ozone +// Wayland and X11 on Linux codesearch-gen bots. +#include "ui/base/ime/linux/fake_input_method_context_factory.h" // nogncheck #elif defined(OS_WIN) #include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/win/tsf_bridge.h" diff --git a/chromium/ui/base/ime/input_method.h b/chromium/ui/base/ime/input_method.h index b400ece46ac..9ead7fa666e 100644 --- a/chromium/ui/base/ime/input_method.h +++ b/chromium/ui/base/ime/input_method.h @@ -18,10 +18,6 @@ #include "ui/events/platform_event.h" #include "ui/gfx/geometry/rect.h" -namespace extensions { -class InputImeApiTest; -} // namespace extensions - namespace ui { namespace internal { @@ -57,8 +53,6 @@ class TextInputClient; // ui::InputMethod and owns it. class InputMethod { public: - InputMethod() : track_key_events_for_testing_(false) {} - #if defined(OS_WIN) typedef LRESULT NativeEventResult; #else @@ -174,16 +168,6 @@ class InputMethod { // Return the keyboard controller; used only on Windows. virtual InputMethodKeyboardController* GetInputMethodKeyboardController() = 0; - - protected: - friend class extensions::InputImeApiTest; - - // Gets the tracked key events of using input.ime.sendKeyEvents API. - virtual const std::vector<std::unique_ptr<ui::KeyEvent>>& - GetKeyEventsForTesting() = 0; - - // Whether the key events will be tracked. Only used for testing. - bool track_key_events_for_testing_; }; } // namespace ui diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc index 6051072ddb7..b5f26b6bf9d 100644 --- a/chromium/ui/base/ime/input_method_base.cc +++ b/chromium/ui/base/ime/input_method_base.cc @@ -9,7 +9,6 @@ #include "base/check.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/input_method_keyboard_controller_stub.h" #include "ui/base/ime/input_method_observer.h" @@ -18,11 +17,6 @@ namespace ui { -ui::IMEEngineHandlerInterface* InputMethodBase::GetEngine() { - auto* bridge = ui::IMEBridge::Get(); - return bridge ? bridge->GetCurrentEngineHandler() : nullptr; -} - InputMethodBase::InputMethodBase(internal::InputMethodDelegate* delegate) : InputMethodBase(delegate, nullptr) {} @@ -35,9 +29,6 @@ InputMethodBase::InputMethodBase( InputMethodBase::~InputMethodBase() { for (InputMethodObserver& observer : observer_list_) observer.OnInputMethodDestroyed(this); - if (ui::IMEBridge::Get() && - ui::IMEBridge::Get()->GetInputContextHandler() == this) - ui::IMEBridge::Get()->SetInputContextHandler(nullptr); } void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { @@ -45,17 +36,9 @@ void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { } void InputMethodBase::OnFocus() { - ui::IMEBridge* bridge = ui::IMEBridge::Get(); - if (bridge) { - bridge->SetInputContextHandler(this); - bridge->MaybeSwitchEngine(); - } } void InputMethodBase::OnBlur() { - if (ui::IMEBridge::Get() && - ui::IMEBridge::Get()->GetInputContextHandler() == this) - ui::IMEBridge::Get()->SetInputContextHandler(nullptr); } #if defined(OS_WIN) @@ -251,6 +234,13 @@ bool InputMethodBase::SetCompositionRange( return false; } +bool InputMethodBase::SetAutocorrectRange( + const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) { + return false; +} + bool InputMethodBase::SetSelectionRange(uint32_t start, uint32_t end) { return false; } @@ -275,9 +265,6 @@ SurroundingTextInfo InputMethodBase::GetSurroundingTextInfo() { } void InputMethodBase::SendKeyEvent(KeyEvent* event) { - if (track_key_events_for_testing_) { - key_events_for_testing_.push_back(std::make_unique<KeyEvent>(*event)); - } ui::EventDispatchDetails details = DispatchKeyEvent(event); DCHECK(!details.dispatcher_destroyed); } @@ -298,9 +285,4 @@ bool InputMethodBase::HasCompositionText() { return client && client->HasCompositionText(); } -const std::vector<std::unique_ptr<ui::KeyEvent>>& -InputMethodBase::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h index 7d182e01975..e87cdcab71e 100644 --- a/chromium/ui/base/ime/input_method_base.h +++ b/chromium/ui/base/ime/input_method_base.h @@ -92,6 +92,9 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase uint32_t before, uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) override; + bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) override; bool SetSelectionRange(uint32_t start, uint32_t end) override; #endif @@ -134,23 +137,15 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase internal::InputMethodDelegate* delegate() const { return delegate_; } - static IMEEngineHandlerInterface* GetEngine(); - private: internal::InputMethodDelegate* delegate_; - // InputMethod: - const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEventsForTesting() - override; - void SetFocusedTextInputClientInternal(TextInputClient* client); TextInputClient* text_input_client_ = nullptr; base::ObserverList<InputMethodObserver>::Unchecked observer_list_; - std::vector<std::unique_ptr<ui::KeyEvent>> key_events_for_testing_; - // Screen bounds of a on-screen keyboard. gfx::Rect keyboard_bounds_; diff --git a/chromium/ui/base/ime/linux/BUILD.gn b/chromium/ui/base/ime/linux/BUILD.gn index 01c9b24e6a7..dbef616118c 100644 --- a/chromium/ui/base/ime/linux/BUILD.gn +++ b/chromium/ui/base/ime/linux/BUILD.gn @@ -5,7 +5,14 @@ import("//build/config/jumbo.gni") import("//build/config/linux/pangocairo/pangocairo.gni") -assert(is_linux && !is_chromeos) +# Allows base/ime/linux to be built if it's just for making kythe annotations. +# This is used to generate cross references in codesearch. References are +# generated by building the ozone wayland backend on ChromiumOS, which +# normally we would not want to compile base/ime/linux for. We can't build +# both ozone and x11 on Linux yet, but when we can we should remove this. +# TODO(crbug.com/1085700): Remove || enable_kythe_annotations here. +import("//build/toolchain/kythe.gni") +assert((is_linux && !is_chromeos) || enable_kythe_annotations) jumbo_component("linux") { output_name = "ui_base_ime_linux" diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.cc b/chromium/ui/base/ime/linux/input_method_auralinux.cc index 3f3663c3a51..de49a5b15f1 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux.cc @@ -8,8 +8,6 @@ #include "base/bind.h" #include "base/environment.h" #include "ui/base/ime/constants.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" @@ -88,42 +86,9 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent( } } - // 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() && - (!filtered || NeedInsertChar())) { - ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = - base::BindOnce(&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, std::move(callback)); - return ui::EventDispatchDetails(); - } - return 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_ = *composition; - result_text_ = *result_text; - ignore_result(ProcessKeyEventDone(event, filtered, is_handled)); -} - ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone( ui::KeyEvent* event, bool filtered, @@ -248,22 +213,6 @@ 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::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); - 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( @@ -286,19 +235,12 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) { client->GetEditableSelectionRange(&selection_range)) { context_->SetSurroundingText(text, selection_range); } - - 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(); } @@ -457,8 +399,6 @@ void InputMethodAuraLinux::ConfirmCompositionText(bool reset_engine, NOTIMPLEMENTED_LOG_ONCE(); } InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection); - if (reset_engine && GetEngine()) - GetEngine()->Reset(); ResetContext(); } diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.h b/chromium/ui/base/ime/linux/input_method_auralinux.h index 294979dec2d..e560171df5b 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux.h +++ b/chromium/ui/base/ime/linux/input_method_auralinux.h @@ -65,18 +65,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux bool is_handled) WARN_UNUSED_RESULT; - // 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); - std::unique_ptr<LinuxInputMethodContext> context_; std::unique_ptr<LinuxInputMethodContext> context_simple_; diff --git a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc index 02819b93d51..c7d29003977 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc @@ -271,19 +271,19 @@ class TextInputClientForTesting : public DummyTextInputClient { class InputMethodAuraLinuxTest : public testing::Test { protected: InputMethodAuraLinuxTest() - : factory_(NULL), - input_method_auralinux_(NULL), - delegate_(NULL), - context_(NULL), - context_simple_(NULL) { + : factory_(nullptr), + input_method_auralinux_(nullptr), + delegate_(nullptr), + context_(nullptr), + context_simple_(nullptr) { factory_ = new LinuxInputMethodContextFactoryForTesting(); LinuxInputMethodContextFactory::SetInstance(factory_); test_result_ = TestResult::GetInstance(); } ~InputMethodAuraLinuxTest() override { delete factory_; - factory_ = NULL; - test_result_ = NULL; + factory_ = nullptr; + test_result_ = nullptr; } void SetUp() override { @@ -303,13 +303,13 @@ class InputMethodAuraLinuxTest : public testing::Test { context_simple_->SetSyncMode(false); context_simple_->SetEatKey(false); - context_ = NULL; - context_simple_ = NULL; + context_ = nullptr; + context_simple_ = nullptr; delete input_method_auralinux_; - input_method_auralinux_ = NULL; + input_method_auralinux_ = nullptr; delete delegate_; - delegate_ = NULL; + delegate_ = nullptr; } LinuxInputMethodContextFactoryForTesting* factory_; diff --git a/chromium/ui/base/ime/mock_ime_input_context_handler.cc b/chromium/ui/base/ime/mock_ime_input_context_handler.cc index f6d7cf6decb..f2ba25fbeb6 100644 --- a/chromium/ui/base/ime/mock_ime_input_context_handler.cc +++ b/chromium/ui/base/ime/mock_ime_input_context_handler.cc @@ -5,6 +5,7 @@ #include "ui/base/ime/mock_ime_input_context_handler.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/input_method.h" @@ -16,8 +17,7 @@ MockIMEInputContextHandler::MockIMEInputContextHandler() : commit_text_call_count_(0), set_selection_range_call_count_(0), update_preedit_text_call_count_(0), - delete_surrounding_text_call_count_(0), - last_sent_key_event_(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0) {} + delete_surrounding_text_call_count_(0) {} MockIMEInputContextHandler::~MockIMEInputContextHandler() {} @@ -47,6 +47,14 @@ bool MockIMEInputContextHandler::SetCompositionRange( return true; } +bool MockIMEInputContextHandler::SetAutocorrectRange( + const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) { + // TODO(crbug.com/1091088): Implement function. + return false; +} + bool MockIMEInputContextHandler::SetSelectionRange(uint32_t start, uint32_t end) { ++set_selection_range_call_count_; @@ -72,11 +80,11 @@ void MockIMEInputContextHandler::Reset() { update_preedit_text_call_count_ = 0; delete_surrounding_text_call_count_ = 0; last_commit_text_.clear(); - last_sent_key_event_ = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0); + sent_key_events_.clear(); } void MockIMEInputContextHandler::SendKeyEvent(KeyEvent* event) { - last_sent_key_event_ = *event; + sent_key_events_.emplace_back(*event); } InputMethod* MockIMEInputContextHandler::GetInputMethod() { diff --git a/chromium/ui/base/ime/mock_ime_input_context_handler.h b/chromium/ui/base/ime/mock_ime_input_context_handler.h index e13c67f0b9d..6890e6b538a 100644 --- a/chromium/ui/base/ime/mock_ime_input_context_handler.h +++ b/chromium/ui/base/ime/mock_ime_input_context_handler.h @@ -44,6 +44,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) override; + bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) override; + bool SetSelectionRange(uint32_t start, uint32_t end) override; #endif @@ -66,6 +70,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler return delete_surrounding_text_call_count_; } + int send_key_event_call_count() const { return sent_key_events_.size(); } + const std::string& last_commit_text() const { return last_commit_text_; } const UpdateCompositionTextArg& last_update_composition_arg() const { @@ -76,8 +82,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler return last_delete_surrounding_text_arg_; } - const ui::KeyEvent& last_sent_key_event() const { - return last_sent_key_event_; + const std::vector<ui::KeyEvent>& sent_key_events() const { + return sent_key_events_; } // Resets all call count. @@ -89,7 +95,7 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler int update_preedit_text_call_count_; int delete_surrounding_text_call_count_; std::string last_commit_text_; - ui::KeyEvent last_sent_key_event_; + std::vector<ui::KeyEvent> sent_key_events_; UpdateCompositionTextArg last_update_composition_arg_; DeleteSurroundingTextArg last_delete_surrounding_text_arg_; }; diff --git a/chromium/ui/base/ime/mock_input_method.cc b/chromium/ui/base/ime/mock_input_method.cc index 17555ca526f..5cd43dd5165 100644 --- a/chromium/ui/base/ime/mock_input_method.cc +++ b/chromium/ui/base/ime/mock_input_method.cc @@ -13,8 +13,7 @@ namespace ui { MockInputMethod::MockInputMethod(internal::InputMethodDelegate* delegate) - : text_input_client_(NULL), delegate_(delegate) { -} + : text_input_client_(nullptr), delegate_(delegate) {} MockInputMethod::~MockInputMethod() { for (InputMethodObserver& observer : observer_list_) @@ -35,7 +34,7 @@ void MockInputMethod::SetFocusedTextInputClient(TextInputClient* client) { void MockInputMethod::DetachTextInputClient(TextInputClient* client) { if (text_input_client_ == client) { - text_input_client_ = NULL; + text_input_client_ = nullptr; } } @@ -129,9 +128,4 @@ MockInputMethod::GetInputMethodKeyboardController() { return &keyboard_controller_; } -const std::vector<std::unique_ptr<ui::KeyEvent>>& -MockInputMethod::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h index 2d72e99a4bc..3cbfa920c9a 100644 --- a/chromium/ui/base/ime/mock_input_method.h +++ b/chromium/ui/base/ime/mock_input_method.h @@ -61,15 +61,11 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod { InputMethodKeyboardController* GetInputMethodKeyboardController() override; private: - // InputMethod: - const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEventsForTesting() - override; TextInputClient* text_input_client_; base::ObserverList<InputMethodObserver>::Unchecked observer_list_; internal::InputMethodDelegate* delegate_; - std::vector<std::unique_ptr<ui::KeyEvent>> key_events_for_testing_; InputMethodKeyboardControllerStub keyboard_controller_; DISALLOW_COPY_AND_ASSIGN(MockInputMethod); diff --git a/chromium/ui/base/ime/mojom/BUILD.gn b/chromium/ui/base/ime/mojom/BUILD.gn index dd96cc53288..c69ea02d7a9 100644 --- a/chromium/ui/base/ime/mojom/BUILD.gn +++ b/chromium/ui/base/ime/mojom/BUILD.gn @@ -4,11 +4,33 @@ import("//mojo/public/tools/bindings/mojom.gni") +component("shared_mojom_traits") { + output_name = "ime_shared_mojom_traits" + defines = [ "IS_IME_SHARED_MOJOM_TRAITS_IMPL" ] + sources = [ + "ime_types_mojom_traits.cc", + "ime_types_mojom_traits.h", + ] + public_deps = [ + ":mojom_shared", + "//ipc:param_traits", + "//ui/base/ime:ime_types", + ] +} + mojom("mojom") { generate_java = true - sources = [ "ime_types.mojom" ] + sources = [ + "ime_types.mojom", + "text_input_state.mojom", + "virtual_keyboard_types.mojom", + ] - public_deps = [ "//mojo/public/mojom/base" ] + public_deps = [ + "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojom", + "//ui/gfx/range/mojom", + ] cpp_typemaps = [ { @@ -26,19 +48,30 @@ mojom("mojom") { cpp = "::ui::ImeTextSpan::UnderlineStyle" }, { + mojom = "ui.mojom.TextInputAction" + cpp = "::ui::TextInputAction" + }, + { + mojom = "ui.mojom.TextInputMode" + cpp = "::ui::TextInputMode" + }, + { mojom = "ui.mojom.TextInputType" cpp = "::ui::TextInputType" }, ] - traits_sources = [ "ime_types_mojom_traits.cc" ] traits_headers = [ "ime_types_mojom_traits.h" ] traits_public_deps = [ - "//ui/base/ime:ime_types", + ":shared_mojom_traits", "//ui/gfx/range", ] }, ] + blink_cpp_typemaps = cpp_typemaps + export_class_attribute_blink = "BLINK_PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/public/platform/web_common.h" } mojom("test_interfaces") { diff --git a/chromium/ui/base/ime/mojom/ime_types.mojom b/chromium/ui/base/ime/mojom/ime_types.mojom index 57b07029fa3..0c04bbfa900 100644 --- a/chromium/ui/base/ime/mojom/ime_types.mojom +++ b/chromium/ui/base/ime/mojom/ime_types.mojom @@ -6,6 +6,29 @@ module ui.mojom; import "mojo/public/mojom/base/string16.mojom"; +enum TextInputMode { + kDefault, + kNone, + kText, + kTel, + kUrl, + kEmail, + kNumeric, + kDecimal, + kSearch, +}; + +enum TextInputAction { + kDefault, + kEnter, + kDone, + kGo, + kNext, + kPrevious, + kSearch, + kSend, +}; + // Text input type which is based on blink::WebTextInputType. enum TextInputType { NONE, @@ -34,6 +57,7 @@ enum ImeTextSpanType { kComposition, kSuggestion, kMisspellingSuggestion, + kAutocorrect, }; // This enum represents the thickness of an underline segment of text, @@ -76,5 +100,6 @@ struct ImeTextSpan { uint32 background_color; uint32 suggestion_highlight_color; bool remove_on_finish_composing; + bool interim_char_selection; array<string> suggestions; }; diff --git a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc index 694959deddd..e09781c80e8 100644 --- a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc +++ b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc @@ -6,6 +6,99 @@ namespace mojo { +#define UI_TO_MOJO_ACTION_CASE(name) \ + case ui::TextInputAction::name: \ + return ui::mojom::TextInputAction::name + +// static +ui::mojom::TextInputAction +EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction>::ToMojom( + ui::TextInputAction text_input_action) { + switch (text_input_action) { + UI_TO_MOJO_ACTION_CASE(kDefault); + UI_TO_MOJO_ACTION_CASE(kEnter); + UI_TO_MOJO_ACTION_CASE(kDone); + UI_TO_MOJO_ACTION_CASE(kGo); + UI_TO_MOJO_ACTION_CASE(kNext); + UI_TO_MOJO_ACTION_CASE(kPrevious); + UI_TO_MOJO_ACTION_CASE(kSearch); + UI_TO_MOJO_ACTION_CASE(kSend); + } +} + +#undef UI_TO_MOJO_ACTION_CASE + +#define MOJO_TO_UI_ACTION_CASE(name) \ + case ui::mojom::TextInputAction::name: \ + *out = ui::TextInputAction::name; \ + return true; + +// static +bool EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction>::FromMojom( + ui::mojom::TextInputAction input, + ui::TextInputAction* out) { + switch (input) { + MOJO_TO_UI_ACTION_CASE(kDefault); + MOJO_TO_UI_ACTION_CASE(kEnter); + MOJO_TO_UI_ACTION_CASE(kDone); + MOJO_TO_UI_ACTION_CASE(kGo); + MOJO_TO_UI_ACTION_CASE(kNext); + MOJO_TO_UI_ACTION_CASE(kPrevious); + MOJO_TO_UI_ACTION_CASE(kSearch); + MOJO_TO_UI_ACTION_CASE(kSend); + } + return false; +} + +#undef MOJO_TO_UI_ACTION_CASE + +#define UI_TO_MOJO_MODE_CASE(name, mojo_name) \ + case ui::TextInputMode::TEXT_INPUT_MODE_##name: \ + return ui::mojom::TextInputMode::mojo_name + +// static +ui::mojom::TextInputMode +EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode>::ToMojom( + ui::TextInputMode text_input_mode) { + switch (text_input_mode) { + UI_TO_MOJO_MODE_CASE(DEFAULT, kDefault); + UI_TO_MOJO_MODE_CASE(NONE, kNone); + UI_TO_MOJO_MODE_CASE(TEXT, kText); + UI_TO_MOJO_MODE_CASE(TEL, kTel); + UI_TO_MOJO_MODE_CASE(URL, kUrl); + UI_TO_MOJO_MODE_CASE(EMAIL, kEmail); + UI_TO_MOJO_MODE_CASE(NUMERIC, kNumeric); + UI_TO_MOJO_MODE_CASE(DECIMAL, kDecimal); + UI_TO_MOJO_MODE_CASE(SEARCH, kSearch); + } +} + +#undef UI_TO_MOJO_MODE_CASE + +#define MOJO_TO_UI_MODE_CASE(name, mojo_name) \ + case ui::mojom::TextInputMode::mojo_name: \ + *out = ui::TextInputMode::TEXT_INPUT_MODE_##name; \ + return true; + +// static +bool EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode>::FromMojom( + ui::mojom::TextInputMode input, + ui::TextInputMode* out) { + switch (input) { + MOJO_TO_UI_MODE_CASE(DEFAULT, kDefault); + MOJO_TO_UI_MODE_CASE(NONE, kNone); + MOJO_TO_UI_MODE_CASE(TEXT, kText); + MOJO_TO_UI_MODE_CASE(TEL, kTel); + MOJO_TO_UI_MODE_CASE(URL, kUrl); + MOJO_TO_UI_MODE_CASE(EMAIL, kEmail); + MOJO_TO_UI_MODE_CASE(NUMERIC, kNumeric); + MOJO_TO_UI_MODE_CASE(DECIMAL, kDecimal); + MOJO_TO_UI_MODE_CASE(SEARCH, kSearch); + } +} + +#undef MOJO_TO_UI_MODE_CASE + #define UI_TO_MOJO_TYPE_CASE(name) \ case ui::TEXT_INPUT_TYPE_##name: \ return ui::mojom::TextInputType::name @@ -97,6 +190,7 @@ bool StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan>::Read( out->background_color = data.background_color(); out->suggestion_highlight_color = data.suggestion_highlight_color(); out->remove_on_finish_composing = data.remove_on_finish_composing(); + out->interim_char_selection = data.interim_char_selection(); if (!data.ReadSuggestions(&out->suggestions)) return false; return true; @@ -113,6 +207,8 @@ EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::ToMojom( return ui::mojom::ImeTextSpanType::kSuggestion; case ui::ImeTextSpan::Type::kMisspellingSuggestion: return ui::mojom::ImeTextSpanType::kMisspellingSuggestion; + case ui::ImeTextSpan::Type::kAutocorrect: + return ui::mojom::ImeTextSpanType::kAutocorrect; } NOTREACHED(); @@ -133,6 +229,9 @@ bool EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::FromMojom( case ui::mojom::ImeTextSpanType::kMisspellingSuggestion: *out = ui::ImeTextSpan::Type::kMisspellingSuggestion; return true; + case ui::mojom::ImeTextSpanType::kAutocorrect: + *out = ui::ImeTextSpan::Type::kAutocorrect; + return true; } NOTREACHED(); diff --git a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h index 58d192e2910..50489fadc75 100644 --- a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h +++ b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h @@ -7,20 +7,41 @@ #include <vector> +#include "base/component_export.h" #include "ui/base/ime/ime_text_span.h" -#include "ui/base/ime/mojom/ime_types.mojom.h" +#include "ui/base/ime/mojom/ime_types.mojom-shared.h" +#include "ui/base/ime/text_input_action.h" +#include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" namespace mojo { template <> -struct EnumTraits<ui::mojom::TextInputType, ui::TextInputType> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode> { + static ui::mojom::TextInputMode ToMojom(ui::TextInputMode text_input_mode); + static bool FromMojom(ui::mojom::TextInputMode input, ui::TextInputMode* out); +}; + +template <> +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction> { + static ui::mojom::TextInputAction ToMojom( + ui::TextInputAction text_input_action); + static bool FromMojom(ui::mojom::TextInputAction input, + ui::TextInputAction* out); +}; + +template <> +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputType, ui::TextInputType> { static ui::mojom::TextInputType ToMojom(ui::TextInputType text_input_type); static bool FromMojom(ui::mojom::TextInputType input, ui::TextInputType* out); }; template <> -struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { static ui::ImeTextSpan::Type type(const ui::ImeTextSpan& c) { return c.type; } static uint32_t start_offset(const ui::ImeTextSpan& c) { return c.start_offset; @@ -46,6 +67,9 @@ struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { static bool remove_on_finish_composing(const ui::ImeTextSpan& c) { return c.remove_on_finish_composing; } + static bool interim_char_selection(const ui::ImeTextSpan& c) { + return c.interim_char_selection; + } static std::vector<std::string> suggestions(const ui::ImeTextSpan& c) { return c.suggestions; } @@ -53,7 +77,8 @@ struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { static ui::mojom::ImeTextSpanType ToMojom( ui::ImeTextSpan::Type ime_text_span_type); static bool FromMojom(ui::mojom::ImeTextSpanType input, @@ -61,7 +86,8 @@ struct EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { static ui::mojom::ImeTextSpanThickness ToMojom( ui::ImeTextSpan::Thickness thickness); static bool FromMojom(ui::mojom::ImeTextSpanThickness input, @@ -69,8 +95,9 @@ struct EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanUnderlineStyle, - ui::ImeTextSpan::UnderlineStyle> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanUnderlineStyle, + ui::ImeTextSpan::UnderlineStyle> { static ui::mojom::ImeTextSpanUnderlineStyle ToMojom( ui::ImeTextSpan::UnderlineStyle underline_style); static bool FromMojom(ui::mojom::ImeTextSpanUnderlineStyle input, diff --git a/chromium/ui/base/ime/mojom/text_input_state.mojom b/chromium/ui/base/ime/mojom/text_input_state.mojom new file mode 100644 index 00000000000..63746cb4d67 --- /dev/null +++ b/chromium/ui/base/ime/mojom/text_input_state.mojom @@ -0,0 +1,68 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ui.mojom; + +import "mojo/public/mojom/base/string16.mojom"; +import "mojo/public/mojom/base/text_direction.mojom"; +import "ui/base/ime/mojom/ime_types.mojom"; +import "ui/base/ime/mojom/virtual_keyboard_types.mojom"; +import "ui/gfx/geometry/mojom/geometry.mojom"; +import "ui/gfx/range/mojom/range.mojom"; + +// This structure represents the current editing state. +struct TextInputState { + // Type of the input field. + ui.mojom.TextInputType type = ui.mojom.TextInputType.NONE; + + // The mode of input field. + ui.mojom.TextInputMode mode = ui.mojom.TextInputMode.kDefault; + + // The action of the input field. + ui.mojom.TextInputAction action = ui.mojom.TextInputAction.kDefault; + + // The flags of input field (autocorrect, autocomplete, etc.) + // See ui/base/ime/text_input_flags.h for definitions. + uint32 flags; + + // The value of input field. + mojo_base.mojom.String16? value; + + // The current selection range, or the caret position if nothing is selected. + gfx.mojom.Range selection; + + // The current composition range if there is one. + gfx.mojom.Range? composition; + + // Whether or not inline composition can be performed for the current input. + bool can_compose_inline = true; + + // Whether or not the IME should be shown as a result of this update. Even if + // true, the IME will only be shown if the input is appropriate (e.g. not + // TEXT_INPUT_TYPE_NONE). + bool show_ime_if_needed; + + // Whether or not the IME should always be hidden as a result of this update. + bool always_hide_ime; + + // Whether or not this is a reply to a request from IME. + bool reply_to_request; + + // Store control and selection bounds of EditContext. + // These optionals will be nullopts if there isn't any active EditContext. + // For non EditContext scenarios, the bounds are returned via + // |GetCompositionCharacterBounds| + gfx.mojom.Rect? edit_context_control_bounds; + gfx.mojom.Rect? edit_context_selection_bounds; + + // The virtualkeyboardpolicy of the input field. + ui.mojom.VirtualKeyboardPolicy vk_policy = + ui.mojom.VirtualKeyboardPolicy.AUTO; + + // Whether or not show()/hide() API is called from VirtualKeyboard by web + // authors when the virtualkeyboardpolicy is manual. + ui.mojom.VirtualKeyboardVisibilityRequest last_vk_visibility_request = + ui.mojom.VirtualKeyboardVisibilityRequest.NONE; +}; + diff --git a/chromium/ui/base/ime/virtual_keyboard_visibility_request.h b/chromium/ui/base/ime/mojom/virtual_keyboard_types.mojom index 65cee20f299..d1cd8d038f7 100644 --- a/chromium/ui/base/ime/virtual_keyboard_visibility_request.h +++ b/chromium/ui/base/ime/mojom/virtual_keyboard_types.mojom @@ -2,20 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ -#define UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ +module ui.mojom; -namespace ui { +// This mode corresponds to virtualkeyboardpolicy +// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/VirtualKeyboardPolicy/explainer.md +enum VirtualKeyboardPolicy { + AUTO, + MANUAL, +}; // This mode corresponds to VirtualKeyboard API show/hide. // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/VirtualKeyboardPolicy/explainer.md -enum class VirtualKeyboardVisibilityRequest { +enum VirtualKeyboardVisibilityRequest { SHOW, HIDE, NONE, - MAX = NONE, }; - -} // namespace ui - -#endif // UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ diff --git a/chromium/ui/base/ime/text_input_client.h b/chromium/ui/base/ime/text_input_client.h index 7fc2d584a94..b6302623328 100644 --- a/chromium/ui/base/ime/text_input_client.h +++ b/chromium/ui/base/ime/text_input_client.h @@ -217,6 +217,13 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) = 0; #endif +#if defined(OS_CHROMEOS) + // Set the autocorrect range and return if it has been set correctly as a + // boolean value. + virtual bool SetAutocorrectRange(const base::string16& autocorrect_text, + const gfx::Range& range) = 0; +#endif + #if defined(OS_WIN) // Returns false if either the focused editable element or the EditContext // bounds is not available, else it returns true with the control and diff --git a/chromium/ui/base/ime/win/input_method_win_base.cc b/chromium/ui/base/ime/win/input_method_win_base.cc index 83850840d83..fc9c8d3a0f2 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.cc +++ b/chromium/ui/base/ime/win/input_method_win_base.cc @@ -13,8 +13,6 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/win/windows_version.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/on_screen_keyboard_display_manager_input_pane.h" #include "ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h" @@ -237,21 +235,6 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent( !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 (char_msgs.size() <= 1 && GetEngine()) { - ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = - base::BindOnce(&InputMethodWinBase::ProcessKeyEventDone, - weak_ptr_factory_.GetWeakPtr(), - base::Owned(new ui::KeyEvent(*event)), - base::Owned(new std::vector<MSG>(char_msgs))); - GetEngine()->ProcessKeyEvent(*event, std::move(callback)); - return ui::EventDispatchDetails(); - } - return ProcessUnhandledKeyEvent(event, &char_msgs); } @@ -506,48 +489,4 @@ ui::EventDispatchDetails InputMethodWinBase::ProcessUnhandledKeyEvent( return details; } -void InputMethodWinBase::UpdateCompositionBoundsForEngine( - const TextInputClient* client) { - TextInputType text_input_type = GetTextInputType(); - if (client == GetTextInputClient() && - text_input_type != TEXT_INPUT_TYPE_NONE && - text_input_type != TEXT_INPUT_TYPE_PASSWORD && GetEngine()) { - GetEngine()->SetCompositionBounds(GetCompositionBounds(client)); - } -} - -void InputMethodWinBase::ResetEngine() { - if (GetEngine()) - GetEngine()->Reset(); -} - -void InputMethodWinBase::CancelCompositionForEngine() { - TextInputType text_input_type = GetTextInputType(); - if (text_input_type != TEXT_INPUT_TYPE_NONE && - text_input_type != TEXT_INPUT_TYPE_PASSWORD) { - InputMethodWinBase::ResetEngine(); - } -} - -void InputMethodWinBase::UpdateEngineFocusAndInputContext() { - 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::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); - ui::IMEBridge::Get()->SetCurrentInputContext(context); - - // Update IME Engine state. - 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/win/input_method_win_base.h b/chromium/ui/base/ime/win/input_method_win_base.h index 139d966dc0e..c788c6b5f35 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.h +++ b/chromium/ui/base/ime/win/input_method_win_base.h @@ -62,19 +62,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase ui::KeyEvent* event, const std::vector<MSG>* char_msgs); - // Update composition bounds for Chromium IME extension. - void UpdateCompositionBoundsForEngine(const TextInputClient* client); - - // Reset composition status for Chromium IME extension. - void ResetEngine(); - - // Cancel composition for Chromium IME extension. - void CancelCompositionForEngine(); - - // Update focus state for Chromium IME extension and update input context in - // ui::IMEBridge. - void UpdateEngineFocusAndInputContext(); - // The toplevel window handle. const HWND toplevel_window_handle_; diff --git a/chromium/ui/base/ime/win/input_method_win_imm32.cc b/chromium/ui/base/ime/win/input_method_win_imm32.cc index 7c0ee3ee966..324a6bc91fb 100644 --- a/chromium/ui/base/ime/win/input_method_win_imm32.cc +++ b/chromium/ui/base/ime/win/input_method_win_imm32.cc @@ -12,8 +12,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/metrics/histogram_macros.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/display/win/screen_win.h" @@ -101,7 +99,6 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) return; NotifyTextInputCaretBoundsChanged(client); - InputMethodWinBase::UpdateCompositionBoundsForEngine(client); if (!enabled_) return; @@ -126,13 +123,8 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { } void InputMethodWinImm32::CancelComposition(const TextInputClient* client) { - if (IsTextInputClientFocused(client)) { - // |enabled_| == false could be faked, and the engine should rely on the - // real type get from GetTextInputType(). - InputMethodWinBase::CancelCompositionForEngine(); - - if (enabled_) - imm32_manager_.CancelIME(toplevel_window_handle_); + if (IsTextInputClientFocused(client) && enabled_) { + imm32_manager_.CancelIME(toplevel_window_handle_); } } @@ -326,8 +318,6 @@ void InputMethodWinImm32::RefreshInputLanguage() { void InputMethodWinImm32::ConfirmCompositionText(bool reset_engine, bool keep_selection) { InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection); - if (reset_engine) - InputMethodWinBase::ResetEngine(); // Makes sure the native IME app can be informed about the composition is // cleared, so that it can clean up its internal states. @@ -339,8 +329,7 @@ void InputMethodWinImm32::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 = - GetEngine() ? TEXT_INPUT_TYPE_NONE : GetTextInputType(); + const TextInputType text_input_type = GetTextInputType(); const TextInputMode text_input_mode = GetTextInputMode(); switch (text_input_type) { case ui::TEXT_INPUT_TYPE_NONE: @@ -357,8 +346,6 @@ void InputMethodWinImm32::UpdateIMEState() { imm32_manager_.SetTextInputMode(window_handle, text_input_mode); tsf_inputscope::SetInputScopeForTsfUnawareWindow( window_handle, text_input_type, text_input_mode); - - InputMethodWinBase::UpdateEngineFocusAndInputContext(); } } // namespace ui diff --git a/chromium/ui/base/ime/win/input_method_win_tsf.cc b/chromium/ui/base/ime/win/input_method_win_tsf.cc index 58926e51a7f..b4e4fcc2e67 100644 --- a/chromium/ui/base/ime/win/input_method_win_tsf.cc +++ b/chromium/ui/base/ime/win/input_method_win_tsf.cc @@ -100,7 +100,6 @@ void InputMethodWinTSF::OnTextInputTypeChanged(const TextInputClient* client) { } ui::TSFBridge::GetInstance()->CancelComposition(); ui::TSFBridge::GetInstance()->OnTextInputTypeChanged(client); - InputMethodWinBase::UpdateEngineFocusAndInputContext(); } void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) { @@ -110,14 +109,12 @@ void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) { } NotifyTextInputCaretBoundsChanged(client); ui::TSFBridge::GetInstance()->OnTextLayoutChanged(); - InputMethodWinBase::UpdateCompositionBoundsForEngine(client); } void InputMethodWinTSF::CancelComposition(const TextInputClient* client) { if (ui::TSFBridge::GetInstance() && IsTextInputClientFocused(client) && IsWindowFocused(client)) { ui::TSFBridge::GetInstance()->CancelComposition(); - InputMethodWinBase::CancelCompositionForEngine(); } } @@ -181,8 +178,6 @@ void InputMethodWinTSF::ConfirmCompositionText(bool reset_engine, if (IsTextInputTypeNone()) return; - if (reset_engine && GetTextInputClient()->HasCompositionText()) - InputMethodWinBase::ResetEngine(); if (ui::TSFBridge::GetInstance()) ui::TSFBridge::GetInstance()->ConfirmComposition(); } diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc index cf2caabef7d..5c19abd64d6 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc @@ -222,7 +222,7 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { // Execute show() or hide() on the background thread after the debounce // expires. switch (last_vk_visibility_request_) { - case VirtualKeyboardVisibilityRequest::SHOW: { + case mojom::VirtualKeyboardVisibilityRequest::SHOW: { background_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -231,7 +231,7 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { base::RetainedRef(virtual_keyboard_input_pane_), hwnd_)); break; } - case VirtualKeyboardVisibilityRequest::HIDE: { + case mojom::VirtualKeyboardVisibilityRequest::HIDE: { background_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -240,18 +240,18 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { base::RetainedRef(virtual_keyboard_input_pane_), hwnd_)); break; } - case VirtualKeyboardVisibilityRequest::NONE: { + case mojom::VirtualKeyboardVisibilityRequest::NONE: { break; } } // Reset the VK visibility state to none so we can keep track of subsequent // API calls. - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::NONE; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::NONE; } bool OnScreenKeyboardDisplayManagerInputPane::DisplayVirtualKeyboard() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::SHOW; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::SHOW; debouncer_->RequestRun(base::BindOnce( &OnScreenKeyboardDisplayManagerInputPane::Run, base::Unretained(this))); return true; @@ -259,7 +259,7 @@ bool OnScreenKeyboardDisplayManagerInputPane::DisplayVirtualKeyboard() { void OnScreenKeyboardDisplayManagerInputPane::DismissVirtualKeyboard() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::HIDE; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::HIDE; debouncer_->RequestRun(base::BindOnce( &OnScreenKeyboardDisplayManagerInputPane::Run, base::Unretained(this))); } diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h index 40c8578cb79..68b15c27f21 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h @@ -18,7 +18,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/win/windows_types.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/virtual_keyboard_visibility_request.h" +#include "ui/base/ime/mojom/virtual_keyboard_types.mojom-shared.h" #include "ui/base/ime/win/virtual_keyboard_debounce_timer.h" #include "ui/gfx/geometry/rect.h" @@ -47,8 +47,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) pane); // Returns whether show/hide VK API is called from // InputMethodKeyboardController or not. - VirtualKeyboardVisibilityRequest GetLastVirtualKeyboardVisibilityRequest() - const { + mojom::VirtualKeyboardVisibilityRequest + GetLastVirtualKeyboardVisibilityRequest() const { return last_vk_visibility_request_; } @@ -69,8 +69,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) const scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_; scoped_refptr<VirtualKeyboardInputPane> virtual_keyboard_input_pane_; bool is_keyboard_visible_; - VirtualKeyboardVisibilityRequest last_vk_visibility_request_ = - VirtualKeyboardVisibilityRequest::NONE; + mojom::VirtualKeyboardVisibilityRequest last_vk_visibility_request_ = + mojom::VirtualKeyboardVisibilityRequest::NONE; std::unique_ptr<VirtualKeyboardDebounceTimer> debouncer_; base::WeakPtrFactory<OnScreenKeyboardDisplayManagerInputPane> weak_factory_{ this}; diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h index c32989e65b7..f718926d662 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h @@ -11,7 +11,6 @@ #include "base/observer_list.h" #include "base/strings/string16.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/geometry/rect.h" namespace ui { diff --git a/chromium/ui/base/ime/win/tsf_bridge.cc b/chromium/ui/base/ime/win/tsf_bridge.cc index 778f19bb853..f5c8c7155d4 100644 --- a/chromium/ui/base/ime/win/tsf_bridge.cc +++ b/chromium/ui/base/ime/win/tsf_bridge.cc @@ -111,6 +111,10 @@ class TSFBridgeImpl : public TSFBridge { // An ITfThreadMgr object to be used in focus and document management. Microsoft::WRL::ComPtr<ITfThreadMgr> thread_manager_; + // An ITfInputProcessorProfiles object to be used to get current language + // locale profile. + Microsoft::WRL::ComPtr<ITfInputProcessorProfiles> input_processor_profiles_; + // A map from TextInputType to an editable document for TSF. We use multiple // TSF documents that have different InputScopes and TSF attributes based on // the TextInputType associated with the target document. For a TextInputType @@ -134,6 +138,9 @@ class TSFBridgeImpl : public TSFBridge { // Handle to ITfKeyTraceEventSink. DWORD key_trace_sink_cookie_ = 0; + // Handle to ITfLanguageProfileNotifySink + DWORD language_profile_cookie_ = 0; + DISALLOW_COPY_AND_ASSIGN(TSFBridgeImpl); }; @@ -149,6 +156,11 @@ TSFBridgeImpl::~TSFBridgeImpl() { if (SUCCEEDED(thread_manager_->QueryInterface(IID_PPV_ARGS(&source)))) { source->UnadviseSink(key_trace_sink_cookie_); } + Microsoft::WRL::ComPtr<ITfSource> language_source; + if (SUCCEEDED(input_processor_profiles_->QueryInterface( + IID_PPV_ARGS(&language_source)))) { + language_source->UnadviseSink(language_profile_cookie_); + } } for (TSFDocumentMap::iterator it = tsf_document_map_.begin(); @@ -174,6 +186,13 @@ bool TSFBridgeImpl::Initialize() { return false; } + if (FAILED(::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, + CLSCTX_ALL, + IID_PPV_ARGS(&input_processor_profiles_)))) { + DVLOG(1) << "Failed to create InputProcessorProfiles instance."; + return false; + } + if (FAILED(::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&thread_manager_)))) { DVLOG(1) << "Failed to create ThreadManager instance."; @@ -309,7 +328,8 @@ void TSFBridgeImpl::SetFocusedClient(HWND focused_window, void TSFBridgeImpl::RemoveFocusedClient(TextInputClient* client) { DCHECK(base::MessageLoopCurrentForUI::IsSet()); - DCHECK(IsInitialized()); + if (!IsInitialized()) + return; if (client_ != client) return; ClearAssociateFocus(); @@ -422,6 +442,21 @@ bool TSFBridgeImpl::CreateDocumentManager(TSFTextStore* text_store, return false; } + Microsoft::WRL::ComPtr<ITfSource> language_source; + if (FAILED(input_processor_profiles_->QueryInterface( + IID_PPV_ARGS(&language_source)))) { + DVLOG(1) << "Failed to get source_ITfInputProcessorProfiles."; + return false; + } + + if (FAILED( + language_source->AdviseSink(IID_ITfLanguageProfileNotifySink, + static_cast<ITfTextEditSink*>(text_store), + &language_profile_cookie_))) { + DVLOG(1) << "AdviseSink for language profile notify sink failed."; + return false; + } + if (*source_cookie == TF_INVALID_COOKIE) { DVLOG(1) << "The result of cookie is invalid."; return false; diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc index 22f43ff72b0..98ca302320d 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.cc +++ b/chromium/ui/base/ime/win/tsf_text_store.cc @@ -11,6 +11,7 @@ #include <algorithm> +#include "base/logging.h" #include "base/numerics/ranges.h" #include "base/win/scoped_variant.h" #include "ui/base/ime/text_input_client.h" @@ -80,6 +81,8 @@ HRESULT TSFTextStore::QueryInterface(REFIID iid, void** result) { *result = static_cast<ITextStoreACP*>(this); } else if (iid == IID_ITfContextOwnerCompositionSink) { *result = static_cast<ITfContextOwnerCompositionSink*>(this); + } else if (iid == IID_ITfLanguageProfileNotifySink) { + *result = static_cast<ITfLanguageProfileNotifySink*>(this); } else if (iid == IID_ITfTextEditSink) { *result = static_cast<ITfTextEditSink*>(this); } else if (iid == IID_ITfKeyTraceEventSink) { @@ -647,9 +650,7 @@ HRESULT TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) { // 3. User commits current composition text. if (((new_composition_start > last_composition_start && text_input_client_->HasCompositionText()) || - (wparam_keydown_fired_ == 0 && !has_composition_range_ && - !text_input_client_->HasCompositionText()) || - (wparam_keydown_fired_ != 0 && !has_composition_range_)) && + !has_composition_range_) && text_input_client_) { CommitTextAndEndCompositionIfAny(last_composition_start, new_composition_start); @@ -694,6 +695,7 @@ HRESULT TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) { // reset the flag since we've already inserted/replaced the text. new_text_inserted_ = false; + is_selection_interim_char_ = false; // reset string_buffer_ if composition is no longer active. if (!text_input_client_->HasCompositionText()) { @@ -760,6 +762,7 @@ HRESULT TSFTextStore::SetSelection(ULONG selection_buffer_size, } selection_.set_start(start_pos); selection_.set_end(end_pos); + is_selection_interim_char_ = selection_buffer[0].style.fInterimChar; } return S_OK; } @@ -829,6 +832,15 @@ HRESULT TSFTextStore::OnEndComposition(ITfCompositionView* composition_view) { return S_OK; } +HRESULT TSFTextStore::OnLanguageChange(LANGID langid, BOOL* pfAccept) { + return S_OK; +} +HRESULT TSFTextStore::OnLanguageChanged() { + if (text_input_client_) + text_input_client_->OnInputMethodChanged(); + return S_OK; +} + HRESULT TSFTextStore::OnKeyTraceDown(WPARAM wParam, LPARAM lParam) { // fire the event right away if we're in composition if (has_composition_range_) { @@ -1052,6 +1064,10 @@ bool TSFTextStore::GetCompositionStatus( span.end_offset = start_pos + length; span.underline_color = SK_ColorBLACK; span.background_color = SK_ColorTRANSPARENT; + if (selection_.EqualsIgnoringDirection( + gfx::Range(span.start_offset, span.end_offset))) { + span.interim_char_selection = is_selection_interim_char_; + } if (has_display_attribute) GetStyle(display_attribute, &span); spans->push_back(span); @@ -1355,8 +1371,11 @@ void TSFTextStore::CommitTextAndEndCompositionIfAny(size_t old_size, : new_committed_string_size); // TODO(crbug.com/978678): Unify the behavior of // |TextInputClient::InsertText(text)| for the empty text. - if (!new_committed_string.empty()) + if (!new_committed_string.empty()) { text_input_client_->InsertText(new_committed_string); + } else { + text_input_client_->ClearCompositionText(); + } // Notify accessibility about this committed composition text_input_client_->SetActiveCompositionForAccessibility( replace_text_range_, new_committed_string, diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h index 10bbae5a50e..bf02704ffff 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.h +++ b/chromium/ui/base/ime/win/tsf_text_store.h @@ -102,6 +102,7 @@ class TextInputClient; class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore : public ITextStoreACP, public ITfContextOwnerCompositionSink, + public ITfLanguageProfileNotifySink, public ITfKeyTraceEventSink, public ITfTextEditSink { public: @@ -216,6 +217,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore IFACEMETHODIMP OnEndComposition( ITfCompositionView* composition_view) override; + // ITfLanguageProfileNotifySink: + IFACEMETHODIMP OnLanguageChange(LANGID langid, BOOL* pfAccept) override; + IFACEMETHODIMP OnLanguageChanged() override; + // ITfTextEditSink: IFACEMETHODIMP OnEndEdit(ITfContext* context, TfEditCookie read_only_edit_cookie, @@ -391,6 +396,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // |selection_.end()|: 4 gfx::Range selection_; + // Indicates if the selection is an interim character. Please refer to + // https://docs.microsoft.com/en-us/windows/win32/api/textstor/ns-textstor-ts_selectionstyle + bool is_selection_interim_char_ = false; + // |start_offset| and |end_offset| of |text_spans_| indicates // the offsets in |string_buffer_document_|. // Example: "aoi" is committed. There are two underlines in "umi" and "no". diff --git a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc index 081809d75a1..4e81d7c1012 100644 --- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc +++ b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc @@ -3394,5 +3394,92 @@ TEST_F(TSFTextStoreTest, RegressionTest7) { EXPECT_EQ(S_OK, result); } +// regression tests for crbug.com/1091069. +// We should allow inserting empty compositon string to cancel composition. +class RegressionTest8Callback : public TSFTextStoreTestCallback { + public: + explicit RegressionTest8Callback(TSFTextStore* text_store) + : TSFTextStoreTestCallback(text_store) {} + + HRESULT LockGranted1(DWORD flags) { + SetTextTest(0, 0, L"bbbb", S_OK); + SetSelectionTest(0, 4, S_OK); + + text_spans()->clear(); + ImeTextSpan text_span_1; + text_span_1.start_offset = 0; + text_span_1.end_offset = 4; + text_span_1.underline_color = SK_ColorBLACK; + text_span_1.thickness = ImeTextSpan::Thickness::kThin; + text_span_1.background_color = SK_ColorTRANSPARENT; + text_spans()->push_back(text_span_1); + + *edit_flag() = true; + *composition_start() = 0; + composition_range()->set_start(0); + composition_range()->set_end(4); + *has_composition_range() = true; + + text_store_->OnKeyTraceDown(65u, 1966081u); + return S_OK; + } + + void SetCompositionText1(const ui::CompositionText& composition) { + EXPECT_EQ(L"bbbb", composition.text); + EXPECT_EQ(0u, composition.selection.start()); + EXPECT_EQ(4u, composition.selection.end()); + ASSERT_EQ(1u, composition.ime_text_spans.size()); + EXPECT_EQ(0u, composition.ime_text_spans[0].start_offset); + EXPECT_EQ(4u, composition.ime_text_spans[0].end_offset); + SetHasCompositionText(true); + } + + HRESULT LockGranted2(DWORD flags) { + GetTextTest(0, -1, L"bbbb", 4); + SetTextTest(0, 4, L"", S_OK); + + text_spans()->clear(); + *edit_flag() = true; + *composition_start() = 0; + composition_range()->set_start(0); + composition_range()->set_end(0); + + *has_composition_range() = false; + text_store_->OnKeyTraceUp(65u, 1966081u); + return S_OK; + } + + void ClearCompositionText2() { EXPECT_EQ(false, *has_composition_range()); } + + private: + DISALLOW_COPY_AND_ASSIGN(RegressionTest8Callback); +}; + +TEST_F(TSFTextStoreTest, RegressionTest8) { + RegressionTest8Callback callback(text_store_.get()); + EXPECT_CALL(text_input_client_, SetCompositionText(_)) + .WillOnce( + Invoke(&callback, &RegressionTest8Callback::SetCompositionText1)); + + EXPECT_CALL(text_input_client_, ClearCompositionText()) + .WillOnce( + Invoke(&callback, &RegressionTest8Callback::ClearCompositionText2)); + + EXPECT_CALL(*sink_, OnLockGranted(_)) + .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted1)) + .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted2)); + + ON_CALL(text_input_client_, HasCompositionText()) + .WillByDefault( + Invoke(&callback, &TSFTextStoreTestCallback::HasCompositionText)); + + HRESULT result = kInvalidResult; + EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); + result = kInvalidResult; + EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); +} + } // namespace } // namespace ui diff --git a/chromium/ui/base/l10n/formatter.cc b/chromium/ui/base/l10n/formatter.cc index 72ed375005f..e4446d4786f 100644 --- a/chromium/ui/base/l10n/formatter.cc +++ b/chromium/ui/base/l10n/formatter.cc @@ -7,9 +7,11 @@ #include <limits.h> #include <memory> +#include <ostream> #include <vector> #include "base/check.h" +#include "base/component_export.h" #include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/i18n/unicode/msgfmt.h" #include "ui/base/l10n/l10n_util.h" @@ -17,7 +19,7 @@ namespace ui { -UI_BASE_EXPORT bool formatter_force_fallback = false; +COMPONENT_EXPORT(UI_BASE) bool formatter_force_fallback = false; struct Pluralities { int id; diff --git a/chromium/ui/base/l10n/formatter.h b/chromium/ui/base/l10n/formatter.h index 17ff00e9d2f..7d9478a48f9 100644 --- a/chromium/ui/base/l10n/formatter.h +++ b/chromium/ui/base/l10n/formatter.h @@ -10,13 +10,13 @@ #include <memory> +#include "base/component_export.h" #include "base/lazy_instance.h" #include "base/macros.h" #include "third_party/icu/source/common/unicode/unistr.h" #include "third_party/icu/source/i18n/unicode/msgfmt.h" #include "third_party/icu/source/i18n/unicode/plurrule.h" #include "ui/base/l10n/time_format.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -87,7 +87,7 @@ class Formatter { }; // Class to hold all Formatters, intended to be used in a global LazyInstance. -class UI_BASE_EXPORT FormatterContainer { +class COMPONENT_EXPORT(UI_BASE) FormatterContainer { public: FormatterContainer(); ~FormatterContainer(); @@ -112,10 +112,11 @@ class UI_BASE_EXPORT FormatterContainer { // Windows compilation requires full definition of FormatterContainer before // LazyInstance<FormatterContainter> may be declared. -extern UI_BASE_EXPORT base::LazyInstance<FormatterContainer>::Leaky g_container; +extern COMPONENT_EXPORT(UI_BASE) base::LazyInstance<FormatterContainer>::Leaky + g_container; // For use in unit tests only. -extern UI_BASE_EXPORT bool formatter_force_fallback; +extern COMPONENT_EXPORT(UI_BASE) bool formatter_force_fallback; } // namespace ui diff --git a/chromium/ui/base/l10n/l10n_font_util.h b/chromium/ui/base/l10n/l10n_font_util.h index 8036566e879..81dffd348f1 100644 --- a/chromium/ui/base/l10n/l10n_font_util.h +++ b/chromium/ui/base/l10n/l10n_font_util.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_L10N_FONT_UTIL_H_ #define UI_BASE_L10N_FONT_UTIL_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" #include "ui/gfx/geometry/size.h" namespace gfx { @@ -18,13 +18,16 @@ namespace ui { // its localized size data and the given font. The width in cols is held in a // localized string resource identified by |col_resource_id|, the height in the // same fashion. -UI_BASE_EXPORT int GetLocalizedContentsWidthForFont(int col_resource_id, - const gfx::Font& font); -UI_BASE_EXPORT int GetLocalizedContentsHeightForFont(int row_resource_id, - const gfx::Font& font); -UI_BASE_EXPORT gfx::Size GetLocalizedContentsSizeForFont(int col_resource_id, - int row_resource_id, - const gfx::Font& font); +COMPONENT_EXPORT(UI_BASE) +int GetLocalizedContentsWidthForFont(int col_resource_id, + const gfx::Font& font); +COMPONENT_EXPORT(UI_BASE) +int GetLocalizedContentsHeightForFont(int row_resource_id, + const gfx::Font& font); +COMPONENT_EXPORT(UI_BASE) +gfx::Size GetLocalizedContentsSizeForFont(int col_resource_id, + int row_resource_id, + const gfx::Font& font); } // namespace ui diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc index 489cde62132..29deb4da711 100644 --- a/chromium/ui/base/l10n/l10n_util.cc +++ b/chromium/ui/base/l10n/l10n_util.cc @@ -45,6 +45,7 @@ #endif #if defined(OS_WIN) +#include "base/logging.h" #include "ui/base/l10n/l10n_util_win.h" #endif // OS_WIN diff --git a/chromium/ui/base/l10n/l10n_util.h b/chromium/ui/base/l10n/l10n_util.h index 21de14825df..6a9af307289 100644 --- a/chromium/ui/base/l10n/l10n_util.h +++ b/chromium/ui/base/l10n/l10n_util.h @@ -14,9 +14,9 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" #if defined(OS_MACOSX) #include "ui/base/l10n/l10n_util_mac.h" @@ -25,12 +25,13 @@ namespace l10n_util { // Takes normalized locale as |locale|. Returns language part (before '-'). -UI_BASE_EXPORT std::string GetLanguage(const std::string& locale); +COMPONENT_EXPORT(UI_BASE) std::string GetLanguage(const std::string& locale); // This method translates a generic locale name to one of the locally defined // ones. This method returns true if it succeeds. -UI_BASE_EXPORT bool CheckAndResolveLocale(const std::string& locale, - std::string* resolved_locale); +COMPONENT_EXPORT(UI_BASE) +bool CheckAndResolveLocale(const std::string& locale, + std::string* resolved_locale); // This method is responsible for determining the locale as defined below. In // nearly all cases you shouldn't call this, rather use GetApplicationLocale @@ -42,17 +43,20 @@ UI_BASE_EXPORT bool CheckAndResolveLocale(const std::string& locale, // a value if there's a corresponding resource DLL for the locale. Otherwise, // we fall back to en-us. |set_icu_locale| determines whether the resulting // locale is set as the default ICU locale before returning it. -UI_BASE_EXPORT std::string GetApplicationLocale(const std::string& pref_locale, - bool set_icu_locale); +COMPONENT_EXPORT(UI_BASE) +std::string GetApplicationLocale(const std::string& pref_locale, + bool set_icu_locale); // Convenience version of GetApplicationLocale() that sets the resulting locale // as the default ICU locale before returning it. -UI_BASE_EXPORT std::string GetApplicationLocale(const std::string& pref_locale); +COMPONENT_EXPORT(UI_BASE) +std::string GetApplicationLocale(const std::string& pref_locale); // Returns true if a display name for |locale| is available in the locale // |display_locale|. -UI_BASE_EXPORT bool IsLocaleNameTranslated(const char* locale, - const std::string& display_locale); +COMPONENT_EXPORT(UI_BASE) +bool IsLocaleNameTranslated(const char* locale, + const std::string& display_locale); // Given a locale code, return true if the OS is capable of supporting it. // For instance, Oriya is not well supported on Windows XP and we return @@ -68,25 +72,27 @@ bool IsLocaleSupportedByOS(const std::string& locale); // in the UI thread. // If |is_for_ui| is true, U+200F is appended so that it can be // rendered properly in a RTL Chrome. -UI_BASE_EXPORT base::string16 GetDisplayNameForLocale( - const std::string& locale, - const std::string& display_locale, - bool is_for_ui, - bool disallow_default = false); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetDisplayNameForLocale(const std::string& locale, + const std::string& display_locale, + bool is_for_ui, + bool disallow_default = false); // Returns the display name of the |country_code| in |display_locale|. -UI_BASE_EXPORT base::string16 GetDisplayNameForCountry( - const std::string& country_code, - const std::string& display_locale); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetDisplayNameForCountry(const std::string& country_code, + const std::string& display_locale); // Converts all - into _, to be consistent with ICU and file system names. -UI_BASE_EXPORT std::string NormalizeLocale(const std::string& locale); +COMPONENT_EXPORT(UI_BASE) +std::string NormalizeLocale(const std::string& locale); // Produce a vector of parent locales for given locale. // It includes the current locale in the result. // sr_Cyrl_RS generates sr_Cyrl_RS, sr_Cyrl and sr. -UI_BASE_EXPORT void GetParentLocales(const std::string& current_locale, - std::vector<std::string>* parent_locales); +COMPONENT_EXPORT(UI_BASE) +void GetParentLocales(const std::string& current_locale, + std::vector<std::string>* parent_locales); // Checks if a string is plausibly a syntactically-valid locale string, // for cases where we want the valid input to be a locale string such as @@ -96,72 +102,81 @@ UI_BASE_EXPORT void GetParentLocales(const std::string& current_locale, // accepted, but 'z', 'German', 'en-$1', or 'abcd-1234' should not. // Case-insensitive. Based on BCP 47, see: // http://unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers -UI_BASE_EXPORT bool IsValidLocaleSyntax(const std::string& locale); +COMPONENT_EXPORT(UI_BASE) bool IsValidLocaleSyntax(const std::string& locale); // // Mac Note: See l10n_util_mac.h for some NSString versions and other support. // // Pulls resource string from the string bundle and returns it. -UI_BASE_EXPORT std::string GetStringUTF8(int message_id); -UI_BASE_EXPORT base::string16 GetStringUTF16(int message_id); +COMPONENT_EXPORT(UI_BASE) std::string GetStringUTF8(int message_id); +COMPONENT_EXPORT(UI_BASE) base::string16 GetStringUTF16(int message_id); // Get a resource string and replace $i with replacements[i] for all // i < replacements.size(). Additionally, $$ is replaced by $. // If non-NULL |offsets| will be replaced with the start points of the replaced // strings. -UI_BASE_EXPORT base::string16 GetStringFUTF16( - int message_id, - const std::vector<base::string16>& replacements, - std::vector<size_t>* offsets); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const std::vector<base::string16>& replacements, + std::vector<size_t>* offsets); // Convenience wrappers for the above. -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a); -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b); -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e); -UI_BASE_EXPORT std::string GetStringFUTF8(int message_id, - const base::string16& a); -UI_BASE_EXPORT std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b); -UI_BASE_EXPORT std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); -UI_BASE_EXPORT std::string GetStringFUTF8(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, const base::string16& a); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + const base::string16& b); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d, + const base::string16& e); +COMPONENT_EXPORT(UI_BASE) +std::string GetStringFUTF8(int message_id, const base::string16& a); +COMPONENT_EXPORT(UI_BASE) +std::string GetStringFUTF8(int message_id, + const base::string16& a, + const base::string16& b); +COMPONENT_EXPORT(UI_BASE) +std::string GetStringFUTF8(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c); +COMPONENT_EXPORT(UI_BASE) +std::string GetStringFUTF8(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d); // Variants that return the offset(s) of the replaced parameters. The // vector based version returns offsets ordered by parameter. For example if // invoked with a and b offsets[0] gives the offset for a and offsets[1] the // offset of b regardless of where the parameters end up in the string. -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - size_t* offset); -UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, - const base::string16& a, - const base::string16& b, - std::vector<size_t>* offsets); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + size_t* offset); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16(int message_id, + const base::string16& a, + const base::string16& b, + std::vector<size_t>* offsets); // Convenience functions to get a string with a single integer as a parameter. // The result will use non-ASCII(native) digits if required by a locale @@ -174,7 +189,8 @@ UI_BASE_EXPORT base::string16 GetStringFUTF16(int message_id, // // Note that native digits have to be used in UI in general. // base::{Int*,Double}ToString convert a number to a string with // ASCII digits in non-UI strings. -UI_BASE_EXPORT base::string16 GetStringFUTF16Int(int message_id, int a); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetStringFUTF16Int(int message_id, int a); base::string16 GetStringFUTF16Int(int message_id, int64_t a); // Convenience functions to format a string with a single number that requires @@ -188,45 +204,51 @@ base::string16 GetStringFUTF16Int(int message_id, int64_t a); // double, time, string; e.g. "At 3:45 on Feb 3, 2016, 5 files are downloaded // at 3 MB/s."), use base::i18n::MessageFormatter. // message_format_unittests.cc also has more examples of plural formatting. -UI_BASE_EXPORT base::string16 GetPluralStringFUTF16(int message_id, int number); -UI_BASE_EXPORT std::string GetPluralStringFUTF8(int message_id, int number); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetPluralStringFUTF16(int message_id, int number); +COMPONENT_EXPORT(UI_BASE) +std::string GetPluralStringFUTF8(int message_id, int number); // Get a string when you only care about 'single vs multiple' distinction. // The message pointed to by |message_id| should be in ICU syntax // (see the references above for Plural) with 'single', 'multiple', and // 'other' (fallback) instead of 'male', 'female', and 'other' (fallback). -UI_BASE_EXPORT base::string16 GetSingleOrMultipleStringUTF16(int message_id, - bool is_multiple); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetSingleOrMultipleStringUTF16(int message_id, bool is_multiple); // In place sorting of base::string16 strings using collation rules for // |locale|. -UI_BASE_EXPORT void SortStrings16(const std::string& locale, - std::vector<base::string16>* strings); +COMPONENT_EXPORT(UI_BASE) +void SortStrings16(const std::string& locale, + std::vector<base::string16>* strings); // Returns a vector of available locale codes. E.g., a vector containing // en-US, es, fr, fi, pt-PT, pt-BR, etc. -UI_BASE_EXPORT const std::vector<std::string>& GetAvailableLocales(); +COMPONENT_EXPORT(UI_BASE) const std::vector<std::string>& GetAvailableLocales(); // Returns a vector of locale codes usable for accept-languages. -UI_BASE_EXPORT void GetAcceptLanguagesForLocale( - const std::string& display_locale, - std::vector<std::string>* locale_codes); +COMPONENT_EXPORT(UI_BASE) +void GetAcceptLanguagesForLocale(const std::string& display_locale, + std::vector<std::string>* locale_codes); // Returns a vector of untranslated locale codes usable for accept-languages. -UI_BASE_EXPORT void GetAcceptLanguages(std::vector<std::string>* locale_codes); +COMPONENT_EXPORT(UI_BASE) +void GetAcceptLanguages(std::vector<std::string>* locale_codes); // Returns true if |locale| is in a predefined AcceptLanguageList and // a display name for the |locale| is available in the locale |display_locale|. -UI_BASE_EXPORT bool IsLanguageAccepted(const std::string& display_locale, - const std::string& locale); +COMPONENT_EXPORT(UI_BASE) +bool IsLanguageAccepted(const std::string& display_locale, + const std::string& locale); // Returns the preferred size of the contents view of a window based on // designer given constraints which might dependent on the language used. -UI_BASE_EXPORT int GetLocalizedContentsWidthInPixels(int pixel_resource_id); +COMPONENT_EXPORT(UI_BASE) +int GetLocalizedContentsWidthInPixels(int pixel_resource_id); -UI_BASE_EXPORT const char* const* GetAcceptLanguageListForTesting(); +COMPONENT_EXPORT(UI_BASE) const char* const* GetAcceptLanguageListForTesting(); -UI_BASE_EXPORT size_t GetAcceptLanguageListSizeForTesting(); +COMPONENT_EXPORT(UI_BASE) size_t GetAcceptLanguageListSizeForTesting(); } // namespace l10n_util diff --git a/chromium/ui/base/l10n/l10n_util_android.h b/chromium/ui/base/l10n/l10n_util_android.h index 38592e9c58e..23fd7b1a937 100644 --- a/chromium/ui/base/l10n/l10n_util_android.h +++ b/chromium/ui/base/l10n/l10n_util_android.h @@ -9,16 +9,16 @@ #include <string> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace l10n_util { -UI_BASE_EXPORT base::string16 GetDisplayNameForLocale( - const std::string& locale, - const std::string& display_locale); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetDisplayNameForLocale(const std::string& locale, + const std::string& display_locale); -UI_BASE_EXPORT bool IsLayoutRtl(); +COMPONENT_EXPORT(UI_BASE) bool IsLayoutRtl(); } // namespace l10n_util diff --git a/chromium/ui/base/l10n/l10n_util_collator.h b/chromium/ui/base/l10n/l10n_util_collator.h index db3fa11481a..a6ac539ccfd 100644 --- a/chromium/ui/base/l10n/l10n_util_collator.h +++ b/chromium/ui/base/l10n/l10n_util_collator.h @@ -13,9 +13,9 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/i18n/string_compare.h" #include "third_party/icu/source/i18n/unicode/coll.h" -#include "ui/base/ui_base_export.h" namespace l10n_util { @@ -105,7 +105,8 @@ class StringComparator { // Specialization of operator() method for base::string16 version. template <> -UI_BASE_EXPORT inline bool StringComparator<base::string16>::operator()( +COMPONENT_EXPORT(UI_BASE) +inline bool StringComparator<base::string16>::operator()( const base::string16& lhs, const base::string16& rhs) const { // If we can not get collator instance for specified locale, just do simple diff --git a/chromium/ui/base/l10n/l10n_util_mac.h b/chromium/ui/base/l10n/l10n_util_mac.h index 9d7c42e19e4..0d9cb8683b3 100644 --- a/chromium/ui/base/l10n/l10n_util_mac.h +++ b/chromium/ui/base/l10n/l10n_util_mac.h @@ -10,8 +10,8 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" #ifdef __OBJC__ @class NSString; @@ -27,77 +27,88 @@ namespace l10n_util { // language and script by the - token and reformatted as // "$lowercase_language ($UPPERCASE_SCRIPT)". If the - token is not found, the // lowercase version of |locale| will be returned. -UI_BASE_EXPORT base::string16 GetDisplayNameForLocale( - const std::string& locale, - const std::string& display_locale); +COMPONENT_EXPORT(UI_BASE) +base::string16 GetDisplayNameForLocale(const std::string& locale, + const std::string& display_locale); // Remove the Windows-style accelerator marker (for labels, menuitems, etc.) // and change "..." into an ellipsis. // Returns the result in an autoreleased NSString. -UI_BASE_EXPORT NSString* FixUpWindowsStyleLabel(const base::string16& label); +COMPONENT_EXPORT(UI_BASE) +NSString* FixUpWindowsStyleLabel(const base::string16& label); // Pulls resource string from the string bundle and returns it. -UI_BASE_EXPORT NSString* GetNSString(int message_id); +COMPONENT_EXPORT(UI_BASE) NSString* GetNSString(int message_id); // Get a resource string and replace $1-$2-$3 with |a| and |b| // respectively. Additionally, $$ is replaced by $. -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, const base::string16& a); -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b); -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d, - const base::string16& e); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, const base::string16& a); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, + const base::string16& a, + const base::string16& b); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d, + const base::string16& e); // Variants that return the offset(s) of the replaced parameters. (See // app/l10n_util.h for more details.) -UI_BASE_EXPORT NSString* GetNSStringF(int message_id, - const base::string16& a, - const base::string16& b, - std::vector<size_t>* offsets); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringF(int message_id, + const base::string16& a, + const base::string16& b, + std::vector<size_t>* offsets); // Same as GetNSString, but runs the result through FixUpWindowsStyleLabel // before returning it. -UI_BASE_EXPORT NSString* GetNSStringWithFixup(int message_id); +COMPONENT_EXPORT(UI_BASE) NSString* GetNSStringWithFixup(int message_id); // Same as GetNSStringF, but runs the result through FixUpWindowsStyleLabel // before returning it. -UI_BASE_EXPORT NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a); -UI_BASE_EXPORT NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b); -UI_BASE_EXPORT NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c); -UI_BASE_EXPORT NSString* GetNSStringFWithFixup(int message_id, - const base::string16& a, - const base::string16& b, - const base::string16& c, - const base::string16& d); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringFWithFixup(int message_id, const base::string16& a); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringFWithFixup(int message_id, + const base::string16& a, + const base::string16& b); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringFWithFixup(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c); +COMPONENT_EXPORT(UI_BASE) +NSString* GetNSStringFWithFixup(int message_id, + const base::string16& a, + const base::string16& b, + const base::string16& c, + const base::string16& d); // Get a resource string using |number| with a locale-specific plural rule. // |message_id| points to a message in the ICU syntax. // See http://userguide.icu-project.org/formatparse/messages and // go/plurals (Google internal). -UI_BASE_EXPORT NSString* GetPluralNSStringF(int message_id, int number); +COMPONENT_EXPORT(UI_BASE) +NSString* GetPluralNSStringF(int message_id, int number); // Support the override of the locale with the value from Cocoa. -UI_BASE_EXPORT void OverrideLocaleWithCocoaLocale(); -UI_BASE_EXPORT const std::string& GetLocaleOverride(); +COMPONENT_EXPORT(UI_BASE) void OverrideLocaleWithCocoaLocale(); +COMPONENT_EXPORT(UI_BASE) const std::string& GetLocaleOverride(); } // namespace l10n_util diff --git a/chromium/ui/base/l10n/l10n_util_win.h b/chromium/ui/base/l10n/l10n_util_win.h index a245ec91764..70a7be88046 100644 --- a/chromium/ui/base/l10n/l10n_util_win.h +++ b/chromium/ui/base/l10n/l10n_util_win.h @@ -9,8 +9,8 @@ #include <string> #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace l10n_util { @@ -19,17 +19,17 @@ namespace l10n_util { // (e.g. WS_EX_LAYOUTRTL, WS_EX_RTLREADING, etc.) when creating a window. // Callers should OR this value into their extended style value when creating // a window. -UI_BASE_EXPORT int GetExtendedStyles(); +COMPONENT_EXPORT(UI_BASE) int GetExtendedStyles(); // TODO(xji): // This is a temporary name, it will eventually replace GetExtendedStyles -UI_BASE_EXPORT int GetExtendedTooltipStyles(); +COMPONENT_EXPORT(UI_BASE) int GetExtendedTooltipStyles(); // Give an HWND, this function sets the WS_EX_LAYOUTRTL extended style for the // underlying window. When this style is set, the UI for the window is going to // be mirrored. This is generally done for the UI of right-to-left languages // such as Hebrew. -UI_BASE_EXPORT void HWNDSetRTLLayout(HWND hwnd); +COMPONENT_EXPORT(UI_BASE) void HWNDSetRTLLayout(HWND hwnd); // See http://blogs.msdn.com/oldnewthing/archive/2005/09/15/467598.aspx // and http://blogs.msdn.com/oldnewthing/archive/2006/06/26/647365.aspx @@ -40,18 +40,18 @@ UI_BASE_EXPORT void HWNDSetRTLLayout(HWND hwnd); // override_font_family and font_size_scaler are not null, they'll be // filled with the font family name and the size scaler. The output // parameters are not modified if the return value is false. -UI_BASE_EXPORT bool NeedOverrideDefaultUIFont( - base::string16* override_font_family, - double* font_size_scaler); +COMPONENT_EXPORT(UI_BASE) +bool NeedOverrideDefaultUIFont(base::string16* override_font_family, + double* font_size_scaler); // Allow processes to override the configured locale with the user's Windows UI // languages. This function should generally be called once early in // Application startup. -UI_BASE_EXPORT void OverrideLocaleWithUILanguageList(); +COMPONENT_EXPORT(UI_BASE) void OverrideLocaleWithUILanguageList(); // Retrieve the locale override, or an empty vector if the locale has not been // or failed to be overridden. -UI_BASE_EXPORT const std::vector<std::string>& GetLocaleOverrides(); +COMPONENT_EXPORT(UI_BASE) const std::vector<std::string>& GetLocaleOverrides(); } // namespace l10n_util diff --git a/chromium/ui/base/l10n/time_format.cc b/chromium/ui/base/l10n/time_format.cc index c5a98fc850d..25b4336923f 100644 --- a/chromium/ui/base/l10n/time_format.cc +++ b/chromium/ui/base/l10n/time_format.cc @@ -7,6 +7,7 @@ #include <limits> #include "base/check_op.h" +#include "base/component_export.h" #include "base/lazy_instance.h" #include "base/notreached.h" #include "base/strings/string_util.h" @@ -14,7 +15,6 @@ #include "third_party/icu/source/common/unicode/unistr.h" #include "ui/base/l10n/formatter.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/ui_base_export.h" #include "ui/strings/grit/ui_strings.h" using base::TimeDelta; @@ -22,7 +22,8 @@ using ui::TimeFormat; namespace ui { -UI_BASE_EXPORT base::LazyInstance<FormatterContainer>::Leaky g_container = +COMPONENT_EXPORT(UI_BASE) +base::LazyInstance<FormatterContainer>::Leaky g_container = LAZY_INSTANCE_INITIALIZER; // static diff --git a/chromium/ui/base/l10n/time_format.h b/chromium/ui/base/l10n/time_format.h index 69617a66ddf..d1691441eb2 100644 --- a/chromium/ui/base/l10n/time_format.h +++ b/chromium/ui/base/l10n/time_format.h @@ -5,9 +5,9 @@ #ifndef UI_BASE_L10N_TIME_FORMAT_H_ #define UI_BASE_L10N_TIME_FORMAT_H_ +#include "base/component_export.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace base { class Time; @@ -17,7 +17,7 @@ class TimeDelta; namespace ui { // Methods to format time values as strings. -class UI_BASE_EXPORT TimeFormat { +class COMPONENT_EXPORT(UI_BASE) TimeFormat { public: enum Format { FORMAT_DURATION, // Plain duration, e.g. in English: "2 minutes". diff --git a/chromium/ui/base/layout.cc b/chromium/ui/base/layout.cc index fce80d356ce..d984586ceee 100644 --- a/chromium/ui/base/layout.cc +++ b/chromium/ui/base/layout.cc @@ -22,13 +22,13 @@ namespace ui { namespace { -std::vector<ScaleFactor>* g_supported_scale_factors = NULL; +std::vector<ScaleFactor>* g_supported_scale_factors = nullptr; } // namespace void SetSupportedScaleFactors( const std::vector<ui::ScaleFactor>& scale_factors) { - if (g_supported_scale_factors != NULL) + if (g_supported_scale_factors != nullptr) delete g_supported_scale_factors; g_supported_scale_factors = new std::vector<ScaleFactor>(scale_factors); @@ -49,12 +49,12 @@ void SetSupportedScaleFactors( } const std::vector<ScaleFactor>& GetSupportedScaleFactors() { - DCHECK(g_supported_scale_factors != NULL); + DCHECK(g_supported_scale_factors != nullptr); return *g_supported_scale_factors; } ScaleFactor GetSupportedScaleFactor(float scale) { - DCHECK(g_supported_scale_factors != NULL); + DCHECK(g_supported_scale_factors != nullptr); ScaleFactor closest_match = SCALE_FACTOR_100P; float smallest_diff = std::numeric_limits<float>::max(); for (size_t i = 0; i < g_supported_scale_factors->size(); ++i) { @@ -85,7 +85,7 @@ ScopedSetSupportedScaleFactors::ScopedSetSupportedScaleFactors( original_scale_factors_ = new std::vector<ScaleFactor>(*g_supported_scale_factors); } else { - original_scale_factors_ = NULL; + original_scale_factors_ = nullptr; } SetSupportedScaleFactors(new_scale_factors); } @@ -96,7 +96,7 @@ ScopedSetSupportedScaleFactors::~ScopedSetSupportedScaleFactors() { delete original_scale_factors_; } else { delete g_supported_scale_factors; - g_supported_scale_factors = NULL; + g_supported_scale_factors = nullptr; } } diff --git a/chromium/ui/base/layout.h b/chromium/ui/base/layout.h index fd2627bbc50..e25289b3a48 100644 --- a/chromium/ui/base/layout.h +++ b/chromium/ui/base/layout.h @@ -7,10 +7,10 @@ #include <vector> +#include "base/component_export.h" #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 { @@ -18,29 +18,32 @@ namespace ui { // Changes the value of GetSupportedScaleFactors() to |scale_factors|. // Use ScopedSetSupportedScaleFactors for unit tests as not to affect the // state of other tests. -UI_BASE_EXPORT void SetSupportedScaleFactors( - const std::vector<ScaleFactor>& scale_factors); +COMPONENT_EXPORT(UI_BASE) +void SetSupportedScaleFactors(const std::vector<ScaleFactor>& scale_factors); // Returns a vector with the scale factors which are supported by this // platform, in ascending order. -UI_BASE_EXPORT const std::vector<ScaleFactor>& GetSupportedScaleFactors(); +COMPONENT_EXPORT(UI_BASE) +const std::vector<ScaleFactor>& GetSupportedScaleFactors(); // Returns the supported ScaleFactor which most closely matches |scale|. // Converting from float to ScaleFactor is inefficient and should be done as // little as possible. -UI_BASE_EXPORT ScaleFactor GetSupportedScaleFactor(float image_scale); +COMPONENT_EXPORT(UI_BASE) +ScaleFactor GetSupportedScaleFactor(float image_scale); // Returns the ScaleFactor used by |view|. -UI_BASE_EXPORT float GetScaleFactorForNativeView(gfx::NativeView view); +COMPONENT_EXPORT(UI_BASE) +float GetScaleFactorForNativeView(gfx::NativeView view); // Returns true if the scale passed in is the list of supported scales for // the platform. -UI_BASE_EXPORT bool IsSupportedScale(float scale); +COMPONENT_EXPORT(UI_BASE) bool IsSupportedScale(float scale); namespace test { // Class which changes the value of GetSupportedScaleFactors() to // |new_scale_factors| for the duration of its lifetime. -class UI_BASE_EXPORT ScopedSetSupportedScaleFactors { +class COMPONENT_EXPORT(UI_BASE) ScopedSetSupportedScaleFactors { public: explicit ScopedSetSupportedScaleFactors( const std::vector<ui::ScaleFactor>& new_scale_factors); diff --git a/chromium/ui/base/models/button_menu_item_model.h b/chromium/ui/base/models/button_menu_item_model.h index eabf45695aa..7772052fda8 100644 --- a/chromium/ui/base/models/button_menu_item_model.h +++ b/chromium/ui/base/models/button_menu_item_model.h @@ -8,16 +8,16 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/strings/string16.h" #include "ui/base/accelerators/accelerator.h" -#include "ui/base/ui_base_export.h" namespace ui { // A model representing the rows of buttons that should be inserted in a button // containing menu item. -class UI_BASE_EXPORT ButtonMenuItemModel { +class COMPONENT_EXPORT(UI_BASE) ButtonMenuItemModel { public: // Types of buttons. enum ButtonType { @@ -26,7 +26,7 @@ class UI_BASE_EXPORT ButtonMenuItemModel { TYPE_BUTTON_LABEL }; - class UI_BASE_EXPORT Delegate : public AcceleratorProvider { + class COMPONENT_EXPORT(UI_BASE) Delegate : public AcceleratorProvider { public: // Some command ids have labels that change over time. virtual bool IsItemForCommandIdDynamic(int command_id) const; diff --git a/chromium/ui/base/models/combobox_model.cc b/chromium/ui/base/models/combobox_model.cc index c6913da55e5..a6a311fc465 100644 --- a/chromium/ui/base/models/combobox_model.cc +++ b/chromium/ui/base/models/combobox_model.cc @@ -4,9 +4,27 @@ #include "ui/base/models/combobox_model.h" +#include "ui/base/models/image_model.h" + namespace ui { -bool ComboboxModel::IsItemSeparatorAt(int index) { +base::string16 ComboboxModel::GetDropDownTextAt(int index) const { + return GetItemAt(index); +} + +base::string16 ComboboxModel::GetDropDownSecondaryTextAt(int index) const { + return base::string16(); +} + +ImageModel ComboboxModel::GetIconAt(int index) const { + return ui::ImageModel(); +} + +ImageModel ComboboxModel::GetDropDownIconAt(int index) const { + return GetIconAt(index); +} + +bool ComboboxModel::IsItemSeparatorAt(int index) const { return false; } diff --git a/chromium/ui/base/models/combobox_model.h b/chromium/ui/base/models/combobox_model.h index 2fcd7b69029..994ac2bbef7 100644 --- a/chromium/ui/base/models/combobox_model.h +++ b/chromium/ui/base/models/combobox_model.h @@ -5,15 +5,16 @@ #ifndef UI_BASE_MODELS_COMBOBOX_MODEL_H_ #define UI_BASE_MODELS_COMBOBOX_MODEL_H_ +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace ui { class ComboboxModelObserver; +class ImageModel; // A data model for a combo box. -class UI_BASE_EXPORT ComboboxModel { +class COMPONENT_EXPORT(UI_BASE) ComboboxModel { public: virtual ~ComboboxModel() {} @@ -21,11 +22,27 @@ class UI_BASE_EXPORT ComboboxModel { virtual int GetItemCount() const = 0; // Returns the string at the specified index. - virtual base::string16 GetItemAt(int index) = 0; + virtual base::string16 GetItemAt(int index) const = 0; + + // Returns the string to be shown in the dropdown for the item at |index|. By + // default, it returns GetItemAt(index). + virtual base::string16 GetDropDownTextAt(int index) const; + + // Returns the secondary string at the specified index. Secondary strings are + // displayed in a second line inside every menu item. + virtual base::string16 GetDropDownSecondaryTextAt(int index) const; + + // Gets the icon for the item at the specified index. ImageModel is empty if + // there is no icon. + virtual ImageModel GetIconAt(int index) const; + + // Gets the icon for the item at |index|. ImageModel is empty if there is no + // icon. By default, it returns GetIconAt(index). + virtual ImageModel GetDropDownIconAt(int index) const; // Should return true if the item at |index| is a non-selectable separator // item. - virtual bool IsItemSeparatorAt(int index); + virtual bool IsItemSeparatorAt(int index) const; // The index of the item that is selected by default (before user // interaction). diff --git a/chromium/ui/base/models/combobox_model_observer.h b/chromium/ui/base/models/combobox_model_observer.h index 42d15bdc0e0..5e00ab68a0c 100644 --- a/chromium/ui/base/models/combobox_model_observer.h +++ b/chromium/ui/base/models/combobox_model_observer.h @@ -5,15 +5,16 @@ #ifndef UI_BASE_MODELS_COMBOBOX_MODEL_OBSERVER_H_ #define UI_BASE_MODELS_COMBOBOX_MODEL_OBSERVER_H_ +#include "base/component_export.h" #include "base/observer_list_types.h" -#include "ui/base/ui_base_export.h" namespace ui { class ComboboxModel; // Observer for the ComboboxModel. -class UI_BASE_EXPORT ComboboxModelObserver : public base::CheckedObserver { +class COMPONENT_EXPORT(UI_BASE) ComboboxModelObserver + : public base::CheckedObserver { public: // Invoked when |model| has changed in some way. The observer should assume // everything changed. diff --git a/chromium/ui/base/models/image_model.cc b/chromium/ui/base/models/image_model.cc index 501f8dc9495..9578759666b 100644 --- a/chromium/ui/base/models/image_model.cc +++ b/chromium/ui/base/models/image_model.cc @@ -84,6 +84,14 @@ bool ImageModel::IsImage() const { return image_ && !image_.value().IsEmpty(); } +gfx::Size ImageModel::Size() const { + if (IsVectorIcon()) { + const int icon_size = GetVectorIcon().icon_size(); + return gfx::Size(icon_size, icon_size); + } + return IsImage() ? GetImage().Size() : gfx::Size(); +} + const VectorIconModel ImageModel::GetVectorIcon() const { DCHECK(IsVectorIcon()); return vector_icon_model_.value(); diff --git a/chromium/ui/base/models/image_model.h b/chromium/ui/base/models/image_model.h index 098a92ed42d..dbc4cf8b01d 100644 --- a/chromium/ui/base/models/image_model.h +++ b/chromium/ui/base/models/image_model.h @@ -6,9 +6,9 @@ #define UI_BASE_MODELS_IMAGE_MODEL_H_ #include "base/callback.h" +#include "base/component_export.h" #include "base/optional.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" @@ -28,7 +28,7 @@ namespace ui { // is only used internal to ImageModel and should never be instantiated except // by ImageModel. -class UI_BASE_EXPORT VectorIconModel { +class COMPONENT_EXPORT(UI_BASE) VectorIconModel { public: VectorIconModel(); VectorIconModel(const VectorIconModel&); @@ -71,7 +71,7 @@ class UI_BASE_EXPORT VectorIconModel { // of the two may be specified at a given time. This class is instantiated via // the FromXXXX static factory functions. -class UI_BASE_EXPORT ImageModel { +class COMPONENT_EXPORT(UI_BASE) ImageModel { public: ImageModel(); ImageModel(const ImageModel&); @@ -92,6 +92,7 @@ class UI_BASE_EXPORT ImageModel { bool IsEmpty() const; bool IsVectorIcon() const; bool IsImage() const; + gfx::Size Size() const; // Only valid if IsVectorIcon() or IsImage() return true, respectively. const VectorIconModel GetVectorIcon() const; const gfx::Image GetImage() const; diff --git a/chromium/ui/base/models/image_model_unittest.cc b/chromium/ui/base/models/image_model_unittest.cc index 3b494797afc..8bb31fc06a1 100644 --- a/chromium/ui/base/models/image_model_unittest.cc +++ b/chromium/ui/base/models/image_model_unittest.cc @@ -54,6 +54,14 @@ TEST(ImageModelTest, CheckForImage) { EXPECT_TRUE(image_model.IsImage()); } +TEST(ImageModelTest, Size) { + EXPECT_EQ(gfx::Size(), ImageModel().Size()); + EXPECT_EQ(gfx::Size(16, 16), + ImageModel::FromVectorIcon(GetVectorIcon(), -1, 16).Size()); + EXPECT_EQ(gfx::Size(16, 16), + ImageModel::FromImage(gfx::test::CreateImage(16, 16)).Size()); +} + TEST(ImageModelTest, CheckAssignVectorIcon) { VectorIconModel vector_icon_model_dest; VectorIconModel vector_icon_model_src = diff --git a/chromium/ui/base/models/list_model.h b/chromium/ui/base/models/list_model.h index 3187ee5fd86..ed5217d99d9 100644 --- a/chromium/ui/base/models/list_model.h +++ b/chromium/ui/base/models/list_model.h @@ -11,7 +11,7 @@ #include <utility> #include <vector> -#include "base/logging.h" +#include "base/check_op.h" #include "base/macros.h" #include "base/observer_list.h" #include "ui/base/models/list_model_observer.h" diff --git a/chromium/ui/base/models/list_model_observer.h b/chromium/ui/base/models/list_model_observer.h index cc8be0f6e0a..c7d42310504 100644 --- a/chromium/ui/base/models/list_model_observer.h +++ b/chromium/ui/base/models/list_model_observer.h @@ -7,11 +7,11 @@ #include <stddef.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { -class UI_BASE_EXPORT ListModelObserver { +class COMPONENT_EXPORT(UI_BASE) ListModelObserver { public: // Invoked after items has been added to the model. virtual void ListItemsAdded(size_t start, size_t count) = 0; diff --git a/chromium/ui/base/models/list_selection_model.h b/chromium/ui/base/models/list_selection_model.h index e4e25150351..4c98ae9f645 100644 --- a/chromium/ui/base/models/list_selection_model.h +++ b/chromium/ui/base/models/list_selection_model.h @@ -9,7 +9,7 @@ #include <vector> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -25,7 +25,7 @@ namespace ui { // // Typically there is only one selected item, in which case the anchor and // active index correspond to the same thing. -class UI_BASE_EXPORT ListSelectionModel { +class COMPONENT_EXPORT(UI_BASE) ListSelectionModel { public: using SelectedIndices = std::vector<int>; diff --git a/chromium/ui/base/models/menu_model.cc b/chromium/ui/base/models/menu_model.cc index 90a350cf9ce..32070758287 100644 --- a/chromium/ui/base/models/menu_model.cc +++ b/chromium/ui/base/models/menu_model.cc @@ -19,6 +19,14 @@ bool MenuModel::IsVisibleAt(int index) const { return true; } +bool MenuModel::IsAlertedAt(int index) const { + return false; +} + +bool MenuModel::IsNewFeatureAt(int index) const { + return false; +} + // static bool MenuModel::GetModelAndIndexForCommandId(int command_id, MenuModel** model, @@ -52,6 +60,10 @@ base::string16 MenuModel::GetMinorTextAt(int index) const { return base::string16(); } +base::string16 MenuModel::GetSecondaryLabelAt(int index) const { + return base::string16(); +} + ImageModel MenuModel::GetMinorIconAt(int index) const { return ImageModel(); } diff --git a/chromium/ui/base/models/menu_model.h b/chromium/ui/base/models/menu_model.h index 887eee64e27..c746b37d627 100644 --- a/chromium/ui/base/models/menu_model.h +++ b/chromium/ui/base/models/menu_model.h @@ -5,11 +5,11 @@ #ifndef UI_BASE_MODELS_MENU_MODEL_H_ #define UI_BASE_MODELS_MENU_MODEL_H_ +#include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "ui/base/models/menu_model_delegate.h" #include "ui/base/models/menu_separator_types.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/native_widget_types.h" namespace gfx { @@ -23,7 +23,8 @@ class ButtonMenuItemModel; class ImageModel; // An interface implemented by an object that provides the content of a menu. -class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> { +class COMPONENT_EXPORT(UI_BASE) MenuModel + : public base::SupportsWeakPtr<MenuModel> { public: // The type of item. enum ItemType { @@ -65,6 +66,10 @@ class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> { // Returns the label of the item at the specified index. virtual base::string16 GetLabelAt(int index) const = 0; + // Returns the secondary label of the item at the specified index. Secondary + // label is shown below the label. + virtual base::string16 GetSecondaryLabelAt(int index) const; + // Returns the minor text of the item at the specified index. The minor text // is rendered to the right of the label and using the font GetLabelFontAt(). virtual base::string16 GetMinorTextAt(int index) const; @@ -108,6 +113,15 @@ class UI_BASE_EXPORT MenuModel : public base::SupportsWeakPtr<MenuModel> { // Returns true if the menu item is visible. virtual bool IsVisibleAt(int index) const; + // Returns true if the item is rendered specially to draw attention + // for in-product help. + virtual bool IsAlertedAt(int index) const; + + // Returns true if the menu item grants access to a new feature that we want + // to show off to users (items marked as new will receive a "New" badge when + // the appropriate flag is enabled). + virtual bool IsNewFeatureAt(int index) const; + // Returns the model for the submenu at the specified index. virtual MenuModel* GetSubmenuModelAt(int index) const = 0; diff --git a/chromium/ui/base/models/simple_combobox_model.cc b/chromium/ui/base/models/simple_combobox_model.cc index ff4f04f8036..64e05588544 100644 --- a/chromium/ui/base/models/simple_combobox_model.cc +++ b/chromium/ui/base/models/simple_combobox_model.cc @@ -18,11 +18,11 @@ int SimpleComboboxModel::GetItemCount() const { return items_.size(); } -base::string16 SimpleComboboxModel::GetItemAt(int index) { +base::string16 SimpleComboboxModel::GetItemAt(int index) const { return items_[index]; } -bool SimpleComboboxModel::IsItemSeparatorAt(int index) { +bool SimpleComboboxModel::IsItemSeparatorAt(int index) const { return items_[index].empty(); } diff --git a/chromium/ui/base/models/simple_combobox_model.h b/chromium/ui/base/models/simple_combobox_model.h index a50373a5cf5..140760a604b 100644 --- a/chromium/ui/base/models/simple_combobox_model.h +++ b/chromium/ui/base/models/simple_combobox_model.h @@ -5,6 +5,7 @@ #ifndef UI_BASE_MODELS_SIMPLE_COMBOBOX_MODEL_H_ #define UI_BASE_MODELS_SIMPLE_COMBOBOX_MODEL_H_ +#include "base/component_export.h" #include "base/macros.h" #include "ui/base/models/combobox_model.h" @@ -14,15 +15,15 @@ namespace ui { // A simple data model for a combobox that takes a string16 vector as the items. // An empty string will be a separator. -class UI_BASE_EXPORT SimpleComboboxModel : public ComboboxModel { +class COMPONENT_EXPORT(UI_BASE) SimpleComboboxModel : public ComboboxModel { public: explicit SimpleComboboxModel(std::vector<base::string16> items); ~SimpleComboboxModel() override; // ui::ComboboxModel: int GetItemCount() const override; - base::string16 GetItemAt(int index) override; - bool IsItemSeparatorAt(int index) override; + base::string16 GetItemAt(int index) const override; + bool IsItemSeparatorAt(int index) const override; int GetDefaultIndex() const override; private: diff --git a/chromium/ui/base/models/simple_menu_model.cc b/chromium/ui/base/models/simple_menu_model.cc index 88053e9d501..0c37f6e2cae 100644 --- a/chromium/ui/base/models/simple_menu_model.cc +++ b/chromium/ui/base/models/simple_menu_model.cc @@ -39,6 +39,10 @@ bool SimpleMenuModel::Delegate::IsCommandIdVisible(int command_id) const { return true; } +bool SimpleMenuModel::Delegate::IsCommandIdAlerted(int command_id) const { + return false; +} + bool SimpleMenuModel::Delegate::IsItemForCommandIdDynamic( int command_id) const { return false; @@ -317,6 +321,10 @@ void SimpleMenuModel::SetVisibleAt(int index, bool visible) { MenuItemsChanged(); } +void SimpleMenuModel::SetIsNewFeatureAt(int index, bool is_new_feature) { + items_[ValidateItemIndex(index)].is_new_feature = is_new_feature; +} + void SimpleMenuModel::Clear() { items_.clear(); MenuItemsChanged(); @@ -432,6 +440,18 @@ bool SimpleMenuModel::IsVisibleAt(int index) const { items_[ValidateItemIndex(index)].visible; } +bool SimpleMenuModel::IsAlertedAt(int index) const { + const int command_id = GetCommandIdAt(index); + if (!delegate_ || command_id == kSeparatorId || command_id == kTitleId) + return false; + + return delegate_->IsCommandIdAlerted(command_id); +} + +bool SimpleMenuModel::IsNewFeatureAt(int index) const { + return items_[ValidateItemIndex(index)].is_new_feature; +} + void SimpleMenuModel::ActivatedAt(int index) { ActivatedAt(index, 0); } diff --git a/chromium/ui/base/models/simple_menu_model.h b/chromium/ui/base/models/simple_menu_model.h index 2b06f3f4a03..5f1116ba19b 100644 --- a/chromium/ui/base/models/simple_menu_model.h +++ b/chromium/ui/base/models/simple_menu_model.h @@ -9,6 +9,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" @@ -24,9 +25,9 @@ class ButtonMenuItemModel; // items. This makes it easy to construct fixed menus. Menus populated by // dynamic data sources may be better off implementing MenuModel directly. // The breadth of MenuModel is not exposed through this API. -class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { +class COMPONENT_EXPORT(UI_BASE) SimpleMenuModel : public MenuModel { public: - class UI_BASE_EXPORT Delegate : public AcceleratorProvider { + class COMPONENT_EXPORT(UI_BASE) Delegate : public AcceleratorProvider { public: ~Delegate() override {} @@ -40,6 +41,10 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { // Delegate should return true if |command_id| should be visible. virtual bool IsCommandIdVisible(int command_id) const; + // Determines if |command_id| should be rendered with an alert for + // in-product help. + virtual bool IsCommandIdAlerted(int command_id) const; + // Some command ids have labels and icons that change over time. virtual bool IsItemForCommandIdDynamic(int command_id) const; virtual base::string16 GetLabelForCommandId(int command_id) const; @@ -158,6 +163,9 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { // Sets whether the item at |index| is visible. void SetVisibleAt(int index, bool visible); + // Sets whether the item at |index| is new. + void SetIsNewFeatureAt(int index, bool is_new_feature); + // Clears all items. Note that it does not free MenuModel of submenu. void Clear(); @@ -182,6 +190,8 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { ui::ButtonMenuItemModel* GetButtonMenuItemAt(int index) const override; bool IsEnabledAt(int index) const override; bool IsVisibleAt(int index) const override; + bool IsAlertedAt(int index) const override; + bool IsNewFeatureAt(int index) const override; void ActivatedAt(int index) override; void ActivatedAt(int index, int event_flags) override; MenuModel* GetSubmenuModelAt(int index) const override; @@ -215,6 +225,7 @@ class UI_BASE_EXPORT SimpleMenuModel : public MenuModel { MenuSeparatorType separator_type = NORMAL_SEPARATOR; bool enabled = true; bool visible = true; + bool is_new_feature = false; }; typedef std::vector<Item> ItemVector; diff --git a/chromium/ui/base/models/simple_menu_model_unittest.cc b/chromium/ui/base/models/simple_menu_model_unittest.cc index 4fe768d11b9..b38debbc855 100644 --- a/chromium/ui/base/models/simple_menu_model_unittest.cc +++ b/chromium/ui/base/models/simple_menu_model_unittest.cc @@ -16,6 +16,8 @@ namespace ui { namespace { +constexpr int kAlertedCommandId = 2; + class DelegateBase : public SimpleMenuModel::Delegate { public: DelegateBase() : SimpleMenuModel::Delegate() {} @@ -37,6 +39,10 @@ class DelegateBase : public SimpleMenuModel::Delegate { return command_id < 100; } + bool IsCommandIdAlerted(int command_id) const override { + return command_id == kAlertedCommandId; + } + void ExecuteCommand(int command_id, int event_flags) override {} bool IsItemForCommandIdDynamic(int command_id) const override { @@ -147,6 +153,32 @@ TEST(SimpleMenuModelTest, IsVisibleAtWithDelegateAndCommandNotVisible) { ASSERT_FALSE(simple_menu_model.IsEnabledAt(0)); } +TEST(SimpleMenuModelTest, IsAlertedAtViaDelegate) { + DelegateBase delegate; + SimpleMenuModel simple_menu_model(&delegate); + simple_menu_model.AddItem(kAlertedCommandId, + base::ASCIIToUTF16("alerted item")); + simple_menu_model.AddItem(kAlertedCommandId + 1, + base::ASCIIToUTF16("non-alerted item")); + + EXPECT_TRUE(simple_menu_model.IsAlertedAt(0)); + EXPECT_FALSE(simple_menu_model.IsAlertedAt(1)); +} + +TEST(SimpleMenuModelTest, SetIsNewFeatureAt) { + SimpleMenuModel simple_menu_model(nullptr); + simple_menu_model.AddItem(/*command_id*/ 5, + base::ASCIIToUTF16("menu item 0")); + simple_menu_model.AddItem(/*command_id*/ 6, + base::ASCIIToUTF16("menu item 1")); + + simple_menu_model.SetIsNewFeatureAt(/*index*/ 0, false); + simple_menu_model.SetIsNewFeatureAt(/*index*/ 1, true); + + ASSERT_FALSE(simple_menu_model.IsNewFeatureAt(0)); + ASSERT_TRUE(simple_menu_model.IsNewFeatureAt(1)); +} + TEST(SimpleMenuModelTest, HasIconsViaDelegate) { DelegateBase delegate; SimpleMenuModel simple_menu_model(&delegate); diff --git a/chromium/ui/base/models/table_model.h b/chromium/ui/base/models/table_model.h index 088cda5a42d..6e098fbe8dc 100644 --- a/chromium/ui/base/models/table_model.h +++ b/chromium/ui/base/models/table_model.h @@ -7,9 +7,9 @@ #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" #include "third_party/icu/source/i18n/unicode/coll.h" -#include "ui/base/ui_base_export.h" namespace gfx { class ImageSkia; @@ -20,7 +20,7 @@ namespace ui { class TableModelObserver; // The model driving the TableView. -class UI_BASE_EXPORT TableModel { +class COMPONENT_EXPORT(UI_BASE) TableModel { public: // Size of the table row icon, if used. static constexpr int kIconSize = 16; @@ -65,7 +65,7 @@ class UI_BASE_EXPORT TableModel { }; // TableColumn specifies the title, alignment and size of a particular column. -struct UI_BASE_EXPORT TableColumn { +struct COMPONENT_EXPORT(UI_BASE) TableColumn { enum Alignment { LEFT, RIGHT, CENTER }; diff --git a/chromium/ui/base/models/table_model_observer.h b/chromium/ui/base/models/table_model_observer.h index 20b5c7f0e13..eaff0750819 100644 --- a/chromium/ui/base/models/table_model_observer.h +++ b/chromium/ui/base/models/table_model_observer.h @@ -5,13 +5,13 @@ #ifndef UI_BASE_MODELS_TABLE_MODEL_OBSERVER_H_ #define UI_BASE_MODELS_TABLE_MODEL_OBSERVER_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Observer for a TableModel. Anytime the model changes, it must notify its // observer. -class UI_BASE_EXPORT TableModelObserver { +class COMPONENT_EXPORT(UI_BASE) TableModelObserver { public: // Invoked when the model has been completely changed. virtual void OnModelChanged() = 0; diff --git a/chromium/ui/base/models/tree_model.h b/chromium/ui/base/models/tree_model.h index 815cebbdea9..20dc6cdef24 100644 --- a/chromium/ui/base/models/tree_model.h +++ b/chromium/ui/base/models/tree_model.h @@ -7,8 +7,8 @@ #include <vector> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace gfx { class ImageSkia; @@ -34,7 +34,7 @@ class TreeModelNode { }; // Observer for the TreeModel. Notified of significant events to the model. -class UI_BASE_EXPORT TreeModelObserver { +class COMPONENT_EXPORT(UI_BASE) TreeModelObserver { public: // Notification that nodes were added to the specified parent. virtual void TreeNodesAdded(TreeModel* model, @@ -61,7 +61,7 @@ class UI_BASE_EXPORT TreeModelObserver { // of bookkeeping for the tree to be implemented. Generally you will want to // use TreeNodeModel which provides a standard implementation for basic // hierarchy and observer notification. See tree_node_model.h. -class UI_BASE_EXPORT TreeModel { +class COMPONENT_EXPORT(UI_BASE) TreeModel { public: using Nodes = std::vector<TreeModelNode*>; diff --git a/chromium/ui/base/models/tree_node_iterator.h b/chromium/ui/base/models/tree_node_iterator.h index 4f84b20e2b9..931e2606e0d 100644 --- a/chromium/ui/base/models/tree_node_iterator.h +++ b/chromium/ui/base/models/tree_node_iterator.h @@ -6,8 +6,8 @@ #define UI_BASE_MODELS_TREE_NODE_ITERATOR_H_ #include "base/callback.h" +#include "base/check.h" #include "base/containers/stack.h" -#include "base/logging.h" #include "base/macros.h" namespace ui { diff --git a/chromium/ui/base/models/tree_node_model.h b/chromium/ui/base/models/tree_node_model.h index b1213ba67a5..d21bf9a66d0 100644 --- a/chromium/ui/base/models/tree_node_model.h +++ b/chromium/ui/base/models/tree_node_model.h @@ -11,7 +11,7 @@ #include <memory> #include <vector> -#include "base/logging.h" +#include "base/check_op.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/strings/string16.h" diff --git a/chromium/ui/base/mojom/BUILD.gn b/chromium/ui/base/mojom/BUILD.gn index 8b330d88d52..49ea535072d 100644 --- a/chromium/ui/base/mojom/BUILD.gn +++ b/chromium/ui/base/mojom/BUILD.gn @@ -10,6 +10,15 @@ mojom("mojom") { "ui_base_types.mojom", "window_open_disposition.mojom", ] + + if (is_mac) { + sources += [ "attributed_string.mojom" ] + public_deps = [ + "//mojo/public/mojom/base", + "//ui/gfx/range/mojom", + ] + } + cpp_typemaps = [ { types = [ diff --git a/chromium/ui/base/mojom/attributed_string.mojom b/chromium/ui/base/mojom/attributed_string.mojom new file mode 100644 index 00000000000..18969f51079 --- /dev/null +++ b/chromium/ui/base/mojom/attributed_string.mojom @@ -0,0 +1,32 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module ui.mojom; + +import "mojo/public/mojom/base/string16.mojom"; +import "ui/gfx/range/mojom/range.mojom"; + +// This will serialize the font information of an NSAttributedString so that +// it can be sent over mojo. This only stores the information of the +// NSFontAttributeName. The motive is that of security: using NSArchiver and +// friends to send objects from the renderer to the browser could lead to +// deserialization of arbitrary objects. This restricts serialization to a +// specific object class and specific attributes of that object. + +// A C++ mojo-friendly representation of the NSFontAttributeName attribute +// set. +struct FontAttribute { + mojo_base.mojom.String16 font_name; + float font_point_size; + gfx.mojom.Range effective_range; +}; + +// A struct that contains the pertinent information from an NSAttributedString, +// which can be serialized over mojo. +struct AttributedString { + // The plain-text string. + mojo_base.mojom.String16 string; + // The set of attributes that style |string|. + array<FontAttribute> attributes; +}; diff --git a/chromium/ui/base/mojom/window_open_disposition_mojom_traits.h b/chromium/ui/base/mojom/window_open_disposition_mojom_traits.h index 84b7c86f102..a9862b8d62d 100644 --- a/chromium/ui/base/mojom/window_open_disposition_mojom_traits.h +++ b/chromium/ui/base/mojom/window_open_disposition_mojom_traits.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_MOJOM_WINDOW_OPEN_DISPOSITION_MOJOM_TRAITS_H_ #define UI_BASE_MOJOM_WINDOW_OPEN_DISPOSITION_MOJOM_TRAITS_H_ -#include "base/logging.h" +#include "base/notreached.h" #include "mojo/public/cpp/bindings/enum_traits.h" #include "ui/base/mojom/window_open_disposition.mojom.h" #include "ui/base/window_open_disposition.h" diff --git a/chromium/ui/base/nine_image_painter_factory.h b/chromium/ui/base/nine_image_painter_factory.h index af4b13c3dbb..dd4e7052952 100644 --- a/chromium/ui/base/nine_image_painter_factory.h +++ b/chromium/ui/base/nine_image_painter_factory.h @@ -7,7 +7,7 @@ #include <memory> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" // A macro to define arrays of IDR constants used with CreateImageGridPainter. #define IMAGE_GRID(x) { x ## _TOP_LEFT, x ## _TOP, x ## _TOP_RIGHT, \ @@ -44,7 +44,8 @@ namespace ui { // Creates a NineImagePainter from an array of image ids. It's expected the // array came from the IMAGE_GRID macro. -UI_BASE_EXPORT std::unique_ptr<gfx::NineImagePainter> CreateNineImagePainter( +COMPONENT_EXPORT(UI_BASE) +std::unique_ptr<gfx::NineImagePainter> CreateNineImagePainter( const int image_ids[]); } // namespace ui diff --git a/chromium/ui/base/page_transition_types.h b/chromium/ui/base/page_transition_types.h index 21773ad6241..ea8632c706e 100644 --- a/chromium/ui/base/page_transition_types.h +++ b/chromium/ui/base/page_transition_types.h @@ -7,7 +7,7 @@ #include <stdint.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -150,43 +150,47 @@ enum PageTransition { // Compares two PageTransition types ignoring qualifiers. |rhs| is taken to // be a compile time constant, and hence must not contain any qualifiers. -UI_BASE_EXPORT bool PageTransitionCoreTypeIs(PageTransition lhs, - PageTransition rhs); +COMPONENT_EXPORT(UI_BASE) +bool PageTransitionCoreTypeIs(PageTransition lhs, PageTransition rhs); // Compares two PageTransition types including qualifiers. Rarely useful, // PageTransitionCoreTypeIs() is more likely what you need. -UI_BASE_EXPORT bool PageTransitionTypeIncludingQualifiersIs(PageTransition lhs, - PageTransition rhs); +COMPONENT_EXPORT(UI_BASE) +bool PageTransitionTypeIncludingQualifiersIs(PageTransition lhs, + PageTransition rhs); // Simplifies the provided transition by removing any qualifier -UI_BASE_EXPORT PageTransition PageTransitionStripQualifier( - PageTransition type); +COMPONENT_EXPORT(UI_BASE) +PageTransition PageTransitionStripQualifier(PageTransition type); -UI_BASE_EXPORT bool PageTransitionIsValidType(int32_t type); +COMPONENT_EXPORT(UI_BASE) bool PageTransitionIsValidType(int32_t type); -UI_BASE_EXPORT PageTransition PageTransitionFromInt(int32_t type); +COMPONENT_EXPORT(UI_BASE) PageTransition PageTransitionFromInt(int32_t type); // Returns true if the given transition is a top-level frame transition, or // false if the transition was for a subframe. -UI_BASE_EXPORT bool PageTransitionIsMainFrame(PageTransition type); +COMPONENT_EXPORT(UI_BASE) bool PageTransitionIsMainFrame(PageTransition type); // Returns whether a transition involves a redirection -UI_BASE_EXPORT bool PageTransitionIsRedirect(PageTransition type); +COMPONENT_EXPORT(UI_BASE) bool PageTransitionIsRedirect(PageTransition type); // Returns whether a transition is a new navigation (rather than a return // to a previously committed navigation). -UI_BASE_EXPORT bool PageTransitionIsNewNavigation(PageTransition type); +COMPONENT_EXPORT(UI_BASE) +bool PageTransitionIsNewNavigation(PageTransition type); // Return the qualifier -UI_BASE_EXPORT int32_t PageTransitionGetQualifier(PageTransition type); +COMPONENT_EXPORT(UI_BASE) +int32_t PageTransitionGetQualifier(PageTransition type); // Returns true if the transition can be triggered by the web instead of // through UI or similar. -UI_BASE_EXPORT bool PageTransitionIsWebTriggerable(PageTransition type); +COMPONENT_EXPORT(UI_BASE) +bool PageTransitionIsWebTriggerable(PageTransition type); // Return a string version of the core type values. -UI_BASE_EXPORT const char* PageTransitionGetCoreTransitionString( - PageTransition type); +COMPONENT_EXPORT(UI_BASE) +const char* PageTransitionGetCoreTransitionString(PageTransition type); // Declare a dummy class that is intentionally never defined. class DontUseOperatorEquals; diff --git a/chromium/ui/base/pointer/pointer_device.h b/chromium/ui/base/pointer/pointer_device.h index 19765542fb3..c50fdde7fe7 100644 --- a/chromium/ui/base/pointer/pointer_device.h +++ b/chromium/ui/base/pointer/pointer_device.h @@ -7,8 +7,8 @@ #include <tuple> +#include "base/component_export.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" #if defined(OS_ANDROID) #include <jni.h> @@ -22,7 +22,8 @@ enum class TouchScreensAvailability { DISABLED, // Touch screens are present and disabled. }; -UI_BASE_EXPORT TouchScreensAvailability GetTouchScreensAvailability(); +COMPONENT_EXPORT(UI_BASE) +TouchScreensAvailability GetTouchScreensAvailability(); // Returns the maximum number of simultaneous touch contacts supported // by the device. In the case of devices with multiple digitizers (e.g. @@ -31,7 +32,7 @@ UI_BASE_EXPORT TouchScreensAvailability GetTouchScreensAvailability(); // For example, suppose a device has 3 touchscreens, which support 2, 5, // and 10 simultaneous touch contacts, respectively. This returns 10. // http://www.w3.org/TR/pointerevents/#widl-Navigator-maxTouchPoints -UI_BASE_EXPORT int MaxTouchPoints(); +COMPONENT_EXPORT(UI_BASE) int MaxTouchPoints(); // Bit field values indicating available pointer types. Identical to // blink::PointerType enums, enforced by compile-time assertions in @@ -60,12 +61,15 @@ enum HoverType { int GetAvailablePointerTypes(); int GetAvailableHoverTypes(); -UI_BASE_EXPORT std::pair<int, int> GetAvailablePointerAndHoverTypes(); -UI_BASE_EXPORT void SetAvailablePointerAndHoverTypesForTesting( - int available_pointer_types, - int available_hover_types); -UI_BASE_EXPORT PointerType GetPrimaryPointerType(int available_pointer_types); -UI_BASE_EXPORT HoverType GetPrimaryHoverType(int available_hover_types); +COMPONENT_EXPORT(UI_BASE) +std::pair<int, int> GetAvailablePointerAndHoverTypes(); +COMPONENT_EXPORT(UI_BASE) +void SetAvailablePointerAndHoverTypesForTesting(int available_pointer_types, + int available_hover_types); +COMPONENT_EXPORT(UI_BASE) +PointerType GetPrimaryPointerType(int available_pointer_types); +COMPONENT_EXPORT(UI_BASE) +HoverType GetPrimaryHoverType(int available_hover_types); } // namespace ui diff --git a/chromium/ui/base/pointer/touch_editing_controller.h b/chromium/ui/base/pointer/touch_editing_controller.h index e55fb3c9be1..0797a4017af 100644 --- a/chromium/ui/base/pointer/touch_editing_controller.h +++ b/chromium/ui/base/pointer/touch_editing_controller.h @@ -5,6 +5,7 @@ #ifndef UI_BASE_POINTER_TOUCH_EDITING_CONTROLLER_H_ #define UI_BASE_POINTER_TOUCH_EDITING_CONTROLLER_H_ +#include "base/component_export.h" #include "ui/base/models/simple_menu_model.h" namespace gfx { @@ -17,7 +18,8 @@ namespace ui { // An interface implemented by widget that has text that can be selected/edited // using touch. -class UI_BASE_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { +class COMPONENT_EXPORT(UI_BASE) TouchEditable + : public ui::SimpleMenuModel::Delegate { public: // Commands that all TouchEditables support: enum MenuCommands { @@ -79,7 +81,7 @@ class UI_BASE_EXPORT TouchEditable : public ui::SimpleMenuModel::Delegate { // This defines the callback interface for other code to be notified of changes // in the state of a TouchEditable. -class UI_BASE_EXPORT TouchEditingControllerDeprecated { +class COMPONENT_EXPORT(UI_BASE) TouchEditingControllerDeprecated { public: virtual ~TouchEditingControllerDeprecated() {} @@ -89,16 +91,9 @@ class UI_BASE_EXPORT TouchEditingControllerDeprecated { // Notifies the controller that the selection has changed. virtual void SelectionChanged() = 0; - - // Returns true if the user is currently dragging one of the handles. - virtual bool IsHandleDragInProgress() = 0; - - // Hides visible handles. According to the value of |quick|, handles might - // fade out quickly or slowly. - virtual void HideHandles(bool quick) = 0; }; -class UI_BASE_EXPORT TouchEditingControllerFactory { +class COMPONENT_EXPORT(UI_BASE) TouchEditingControllerFactory { public: virtual ~TouchEditingControllerFactory() {} diff --git a/chromium/ui/base/pointer/touch_ui_controller.cc b/chromium/ui/base/pointer/touch_ui_controller.cc index f594a6db23c..326da1df5d9 100644 --- a/chromium/ui/base/pointer/touch_ui_controller.cc +++ b/chromium/ui/base/pointer/touch_ui_controller.cc @@ -4,11 +4,13 @@ #include "ui/base/pointer/touch_ui_controller.h" +#include <memory> #include <string> #include "base/bind.h" #include "base/command_line.h" #include "base/message_loop/message_loop_current.h" +#include "base/metrics/user_metrics.h" #include "base/no_destructor.h" #include "base/trace_event/trace_event.h" #include "ui/base/ui_base_switches.h" @@ -22,17 +24,27 @@ namespace ui { -#if defined(OS_WIN) namespace { +#if defined(OS_WIN) + bool IsTabletMode() { return base::win::IsWindows10TabletMode( gfx::SingletonHwnd::GetInstance()->hwnd()); } -} // namespace #endif // defined(OS_WIN) +void RecordEnteredTouchMode() { + base::RecordAction(base::UserMetricsAction("TouchMode.EnteredTouchMode")); +} + +void RecordEnteredNonTouchMode() { + base::RecordAction(base::UserMetricsAction("TouchMode.EnteredNonTouchMode")); +} + +} // namespace + TouchUiController::TouchUiScoperForTesting::TouchUiScoperForTesting( bool enabled, TouchUiController* controller) @@ -44,6 +56,11 @@ TouchUiController::TouchUiScoperForTesting::~TouchUiScoperForTesting() { controller_->SetTouchUiState(old_state_); } +void TouchUiController::TouchUiScoperForTesting::UpdateState(bool enabled) { + controller_->SetTouchUiState(enabled ? TouchUiState::kEnabled + : TouchUiState::kDisabled); +} + // static TouchUiController* TouchUiController::Get() { static base::NoDestructor<TouchUiController> instance([] { @@ -72,6 +89,11 @@ TouchUiController::TouchUiController(TouchUiState touch_ui_state) tablet_mode_ = IsTabletMode(); } #endif + + if (touch_ui()) + RecordEnteredTouchMode(); + else + RecordEnteredNonTouchMode(); } TouchUiController::~TouchUiController() = default; @@ -79,10 +101,8 @@ TouchUiController::~TouchUiController() = default; void TouchUiController::OnTabletModeToggled(bool enabled) { const bool was_touch_ui = touch_ui(); tablet_mode_ = enabled; - if (touch_ui() != was_touch_ui) { - TRACE_EVENT0("ui", "TouchUiController.NotifyListeners"); - callback_list_.Notify(); - } + if (touch_ui() != was_touch_ui) + TouchUiChanged(); } std::unique_ptr<TouchUiController::Subscription> @@ -94,11 +114,19 @@ TouchUiController::TouchUiState TouchUiController::SetTouchUiState( TouchUiState touch_ui_state) { const bool was_touch_ui = touch_ui(); const TouchUiState old_state = std::exchange(touch_ui_state_, touch_ui_state); - if (touch_ui() != was_touch_ui) { - TRACE_EVENT0("ui", "TouchUiController.NotifyListeners"); - callback_list_.Notify(); - } + if (touch_ui() != was_touch_ui) + TouchUiChanged(); return old_state; } +void TouchUiController::TouchUiChanged() { + if (touch_ui()) + RecordEnteredTouchMode(); + else + RecordEnteredNonTouchMode(); + + TRACE_EVENT0("ui", "TouchUiController.NotifyListeners"); + callback_list_.Notify(); +} + } // namespace ui diff --git a/chromium/ui/base/pointer/touch_ui_controller.h b/chromium/ui/base/pointer/touch_ui_controller.h index cecd4ddcc69..0240f4eaef3 100644 --- a/chromium/ui/base/pointer/touch_ui_controller.h +++ b/chromium/ui/base/pointer/touch_ui_controller.h @@ -5,11 +5,12 @@ #ifndef UI_BASE_POINTER_TOUCH_UI_CONTROLLER_H_ #define UI_BASE_POINTER_TOUCH_UI_CONTROLLER_H_ +#include <memory> #include <string> #include "base/callback_list.h" +#include "base/component_export.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" #if defined(OS_WIN) namespace gfx { @@ -20,7 +21,7 @@ class SingletonHwndObserver; namespace ui { // Central controller to handle touch UI modes. -class UI_BASE_EXPORT TouchUiController { +class COMPONENT_EXPORT(UI_BASE) TouchUiController { public: using CallbackList = base::CallbackList<void()>; using Subscription = CallbackList::Subscription; @@ -31,7 +32,7 @@ class UI_BASE_EXPORT TouchUiController { kEnabled, }; - class UI_BASE_EXPORT TouchUiScoperForTesting { + class COMPONENT_EXPORT(UI_BASE) TouchUiScoperForTesting { public: explicit TouchUiScoperForTesting(bool enabled, TouchUiController* controller = Get()); @@ -39,6 +40,11 @@ class UI_BASE_EXPORT TouchUiController { TouchUiScoperForTesting& operator=(const TouchUiScoperForTesting&) = delete; ~TouchUiScoperForTesting(); + // Update the current touch mode state but still roll back to the + // original state at destruction. Allows a test to change the mode + // multiple times without creating multiple instances. + void UpdateState(bool enabled); + private: TouchUiController* const controller_; const TouchUiState old_state_; @@ -64,6 +70,8 @@ class UI_BASE_EXPORT TouchUiController { private: TouchUiState SetTouchUiState(TouchUiState touch_ui_state); + void TouchUiChanged(); + bool tablet_mode_ = false; TouchUiState touch_ui_state_; diff --git a/chromium/ui/base/resource/data_pack.cc b/chromium/ui/base/resource/data_pack.cc index 618204dfcda..09513e6aed2 100644 --- a/chromium/ui/base/resource/data_pack.cc +++ b/chromium/ui/base/resource/data_pack.cc @@ -10,6 +10,7 @@ #include <utility> #include "base/command_line.h" +#include "base/files/file.h" #include "base/files/file_util.h" #include "base/files/memory_mapped_file.h" #include "base/logging.h" @@ -41,8 +42,11 @@ static const size_t kHeaderLengthV5 = // We're crashing when trying to load a pak file on Windows. Add some error // codes for logging. // http://crbug.com/58056 +// These values are logged to UMA. Entries should not be renumbered and +// numeric values should never be reused. Keep in sync with "DataPackLoadErrors" +// in src/tools/metrics/histograms/enums.xml. enum LoadErrors { - INIT_FAILED = 1, + INIT_FAILED_OBSOLETE = 1, BAD_VERSION, INDEX_TRUNCATED, ENTRY_NOT_FOUND, @@ -50,6 +54,8 @@ enum LoadErrors { WRONG_ENCODING, INIT_FAILED_FROM_FILE, UNZIP_FAILED, + OPEN_FAILED, + MAP_FAILED, LOAD_ERRORS_COUNT, }; @@ -274,9 +280,20 @@ DataPack::~DataPack() { bool DataPack::LoadFromPath(const base::FilePath& path) { std::unique_ptr<base::MemoryMappedFile> mmap = std::make_unique<base::MemoryMappedFile>(); - if (!mmap->Initialize(path)) { + // Open the file for reading; allowing other consumers to also open it for + // reading and deleting. Do not allow others to write to it. + base::File data_file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | + base::File::FLAG_EXCLUSIVE_WRITE | + base::File::FLAG_SHARE_DELETE); + if (!data_file.IsValid()) { + DLOG(ERROR) << "Failed to open datapack with base::File::Error " + << data_file.error_details(); + LogDataPackError(OPEN_FAILED); + return false; + } + if (!mmap->Initialize(std::move(data_file))) { DLOG(ERROR) << "Failed to mmap datapack"; - LogDataPackError(INIT_FAILED); + LogDataPackError(MAP_FAILED); return false; } if (MmapHasGzipHeader(mmap.get())) { diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc index 133540ca848..eeb09546b45 100644 --- a/chromium/ui/base/resource/resource_bundle.cc +++ b/chromium/ui/base/resource/resource_bundle.cc @@ -12,10 +12,12 @@ #include "base/big_endian.h" #include "base/command_line.h" +#include "base/debug/alias.h" #include "base/files/file.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" +#include "base/notreached.h" #include "base/path_service.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -45,6 +47,7 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_source.h" #include "ui/strings/grit/app_locale_settings.h" +#include "url/gurl.h" #if defined(OS_ANDROID) #include "base/android/build_info.h" @@ -257,7 +260,9 @@ std::string ResourceBundle::InitSharedInstanceWithLocale( InitSharedInstance(delegate); if (load_resources == LOAD_COMMON_RESOURCES) g_shared_instance_->LoadCommonResources(); - std::string result = g_shared_instance_->LoadLocaleResources(pref_locale); + std::string result = + g_shared_instance_->LoadLocaleResources(pref_locale, + /*crash_on_failure=*/true); g_shared_instance_->InitDefaultFontList(); return result; } @@ -326,7 +331,8 @@ void ResourceBundle::LoadSecondaryLocaleDataWithPakFileRegion( #if !defined(OS_ANDROID) // static bool ResourceBundle::LocaleDataPakExists(const std::string& locale) { - return !GetLocaleFilePath(locale).empty(); + const auto path = GetLocaleFilePath(locale); + return !path.empty() && base::PathExists(path); } #endif // !defined(OS_ANDROID) @@ -378,10 +384,7 @@ base::FilePath ResourceBundle::GetLocaleFilePath( return base::FilePath(); base::FilePath locale_file_path; - - base::PathService::Get(ui::DIR_LOCALES, &locale_file_path); - - if (!locale_file_path.empty()) { + if (base::PathService::Get(ui::DIR_LOCALES, &locale_file_path)) { #if defined(OS_ANDROID) if (locale_file_path.value().find("chromium_tests") == std::string::npos) { std::string extracted_file_suffix = @@ -410,20 +413,14 @@ base::FilePath ResourceBundle::GetLocaleFilePath( locale_file_path, app_locale); } - // Don't try to load empty values or values that are not absolute paths. - if (locale_file_path.empty() || !locale_file_path.IsAbsolute()) - return base::FilePath(); - - if (base::PathExists(locale_file_path)) - return locale_file_path; - - return base::FilePath(); + // Don't try to load from paths that are not absolute. + return locale_file_path.IsAbsolute() ? locale_file_path : base::FilePath(); } #endif #if !defined(OS_ANDROID) -std::string ResourceBundle::LoadLocaleResources( - const std::string& pref_locale) { +std::string ResourceBundle::LoadLocaleResources(const std::string& pref_locale, + bool crash_on_failure) { DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded"; std::string app_locale = l10n_util::GetApplicationLocale(pref_locale); base::FilePath locale_file_path = GetOverriddenPakPath(); @@ -437,10 +434,18 @@ std::string ResourceBundle::LoadLocaleResources( } std::unique_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P)); - if (!data_pack->LoadFromPath(locale_file_path)) { - LOG(ERROR) << "failed to load locale file: " << locale_file_path; - NOTREACHED(); - return std::string(); + if (!data_pack->LoadFromPath(locale_file_path) && crash_on_failure) { + // https://crbug.com/1076423: Chrome can't start when the locale file cannot + // be loaded. Crash early and gather some data. +#if defined(OS_WIN) + const auto last_error = ::GetLastError(); + base::debug::Alias(&last_error); + wchar_t path_copy[MAX_PATH]; + base::wcslcpy(path_copy, locale_file_path.value().c_str(), + base::size(path_copy)); + base::debug::Alias(path_copy); +#endif // defined(OS_WIN) + CHECK(false); } locale_resources_data_ = std::move(data_pack); @@ -500,6 +505,12 @@ base::string16 ResourceBundle::MaybeMangleLocalizedString( if (base::StringToInt(str, &ignored)) return str; + // IDS_WEBSTORE_URL and some other resources are localization "strings" that + // are actually URLs, where the "localized" part is actually just the language + // code embedded in the URL. Don't mangle any URL. + if (GURL(str).is_valid()) + return str; + // For a string S, produce [[ --- S --- ]], where the number of dashes is 1/4 // of the number of characters in S. This makes S something around 50-75% // longer, except for extremely short strings, which get > 100% longer. @@ -518,7 +529,7 @@ std::string ResourceBundle::ReloadLocaleResources( overridden_locale_strings_.clear(); UnloadLocaleResources(); - return LoadLocaleResources(pref_locale); + return LoadLocaleResources(pref_locale, /*crash_on_failure=*/false); } gfx::ImageSkia* ResourceBundle::GetImageSkiaNamed(int resource_id) { diff --git a/chromium/ui/base/resource/resource_bundle.h b/chromium/ui/base/resource/resource_bundle.h index 0b62c5dba94..9cbc1d512ac 100644 --- a/chromium/ui/base/resource/resource_bundle.h +++ b/chromium/ui/base/resource/resource_bundle.h @@ -13,6 +13,7 @@ #include <unordered_map> #include <vector> +#include "base/component_export.h" #include "base/files/file_path.h" #include "base/files/memory_mapped_file.h" #include "base/gtest_prod_util.h" @@ -21,7 +22,6 @@ #include "base/strings/string16.h" #include "base/strings/string_piece.h" #include "ui/base/layout.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/font_list.h" #include "ui/gfx/image/image.h" #include "ui/gfx/native_widget_types.h" @@ -41,7 +41,7 @@ class ResourceHandle; // ResourceBundle is a central facility to load images and other resources, // such as theme graphics. Every resource is loaded only once. -class UI_BASE_EXPORT ResourceBundle { +class COMPONENT_EXPORT(UI_BASE) ResourceBundle { public: // Legacy font size deltas. Consider these to be magic numbers. New code // should declare their own size delta constant using an identifier that @@ -121,9 +121,10 @@ class UI_BASE_EXPORT ResourceBundle { // Initialize the ResourceBundle for this process. Does not take ownership of // the |delegate| value. Returns the language selected or an empty string if - // initialization failed (e.g. resource bundle not found or corrupted). - // NOTE: Mac ignores this and always loads up resources for the language - // defined by the Cocoa UI (i.e., NSBundle does the language work). + // no candidate bundle file could be determined, or crashes the process if a + // candidate could not be loaded (e.g., file not found or corrupted). NOTE: + // Mac ignores this and always loads up resources for the language defined by + // the Cocoa UI (i.e., NSBundle does the language work). // // TODO(sergeyu): This method also loads common resources (i.e. chrome.pak). // There is no way to specify which resource files are loaded, i.e. names of @@ -323,8 +324,10 @@ class UI_BASE_EXPORT ResourceBundle { const base::string16& string); // Returns the full pathname of the locale file to load, which may be a - // compressed locale file ending in .gz. Returns an empty string if no locale - // data files are found. + // compressed locale file ending in .gz. Returns an empty path if |app_locale| + // is empty, the directory of locale files cannot be determined, or if the + // path to the directory of locale files is relative. If not empty, the + // returned path is not guaranteed to reference an existing file. // Used on Android to load the local file in the browser process and pass it // to the sandboxed renderer process. static base::FilePath GetLocaleFilePath(const std::string& app_locale); @@ -396,8 +399,11 @@ class UI_BASE_EXPORT ResourceBundle { void AddDataPack(std::unique_ptr<DataPack> data_pack); // Try to load the locale specific strings from an external data module. - // Returns the locale that is loaded. - std::string LoadLocaleResources(const std::string& pref_locale); + // Returns the locale that is loaded or an empty string if no resources were + // loaded. If |crash_on_failure| is true on non-Android platforms, the process + // is terminated if a candidate locale file could not be loaded. + std::string LoadLocaleResources(const std::string& pref_locale, + bool crash_on_failure); // Load test resources in given paths. If either path is empty an empty // resource pack is loaded. diff --git a/chromium/ui/base/resource/resource_bundle_android.cc b/chromium/ui/base/resource/resource_bundle_android.cc index c86a3bfa2bd..e8cf7b78c66 100644 --- a/chromium/ui/base/resource/resource_bundle_android.cc +++ b/chromium/ui/base/resource/resource_bundle_android.cc @@ -4,10 +4,14 @@ #include "ui/base/resource/resource_bundle_android.h" +#include <utility> + #include "base/android/apk_assets.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/files/file_util.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/path_service.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/data_pack.h" @@ -56,11 +60,10 @@ bool LoadFromApkOrFile(const char* apk_path, int LoadLocalePakFromApk(const std::string& app_locale, bool in_split, base::MemoryMappedFile::Region* out_region) { + bool log_error = true; std::string locale_path_within_apk = - GetPathForAndroidLocalePakWithinApk(app_locale, in_split); + GetPathForAndroidLocalePakWithinApk(app_locale, in_split, log_error); if (locale_path_within_apk.empty()) { - LOG(WARNING) << "locale_path_within_apk.empty() for locale " - << app_locale; return -1; } return base::android::OpenApkAsset(locale_path_within_apk, out_region); @@ -95,16 +98,20 @@ void ResourceBundle::LoadCommonResources() { // static bool ResourceBundle::LocaleDataPakExists(const std::string& locale) { - if (g_locale_paks_in_apk) { - return !GetPathForAndroidLocalePakWithinApk(locale, false).empty(); + bool log_error = false; + bool in_split = !g_locale_paks_in_apk; + if (!in_split) { + return !GetPathForAndroidLocalePakWithinApk(locale, in_split, log_error) + .empty(); } - if (!GetPathForAndroidLocalePakWithinApk(locale, true).empty()) + if (!GetPathForAndroidLocalePakWithinApk(locale, in_split, log_error).empty()) return true; - return !GetLocaleFilePath(locale).empty(); + const auto path = GetLocaleFilePath(locale); + return !path.empty() && base::PathExists(path); } -std::string ResourceBundle::LoadLocaleResources( - const std::string& pref_locale) { +std::string ResourceBundle::LoadLocaleResources(const std::string& pref_locale, + bool crash_on_failure) { DCHECK(!locale_resources_data_.get() && !secondary_locale_resources_data_.get()) << "locale.pak already loaded"; @@ -166,8 +173,11 @@ std::string ResourceBundle::LoadLocaleResources( } if (g_locale_pack_fd < 0) { // Otherwise, try to locate the extracted locale .pak file. - if (locale_file_path.empty()) - locale_file_path = GetLocaleFilePath(app_locale); + if (locale_file_path.empty()) { + auto path = GetLocaleFilePath(app_locale); + if (base::PathExists(path)) + locale_file_path = std::move(path); + } if (locale_file_path.empty()) { // It's possible that there is no locale.pak. @@ -260,11 +270,13 @@ int GetSecondaryLocalePackFd(base::MemoryMappedFile::Region* out_region) { } std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale, - bool in_bundle) { + bool in_bundle, + bool log_error) { JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef<jstring> ret = Java_ResourceBundle_getLocalePakResourcePath( - env, base::android::ConvertUTF8ToJavaString(env, locale), in_bundle); + env, base::android::ConvertUTF8ToJavaString(env, locale), in_bundle, + log_error); if (ret.obj() == nullptr) { return std::string(); } diff --git a/chromium/ui/base/resource/resource_bundle_android.h b/chromium/ui/base/resource/resource_bundle_android.h index e02fc11568f..99096888fc9 100644 --- a/chromium/ui/base/resource/resource_bundle_android.h +++ b/chromium/ui/base/resource/resource_bundle_android.h @@ -8,55 +8,57 @@ #include <jni.h> #include <string> +#include "base/component_export.h" #include "base/files/memory_mapped_file.h" -#include "ui/base/ui_base_export.h" namespace ui { // Loads "resources.apk" from the .apk. Falls back to loading from disk, which // is necessary for tests. -UI_BASE_EXPORT void LoadMainAndroidPackFile( - const char* path_within_apk, - const base::FilePath& disk_file_path); +COMPONENT_EXPORT(UI_BASE) +void LoadMainAndroidPackFile(const char* path_within_apk, + const base::FilePath& disk_file_path); // Loads a PAK file from the APK and makes the contained resources accessible. -UI_BASE_EXPORT void LoadPackFileFromApk(const std::string& path); +COMPONENT_EXPORT(UI_BASE) void LoadPackFileFromApk(const std::string& path); // Returns the file descriptor and region for resources.pak. -UI_BASE_EXPORT int GetMainAndroidPackFd( - base::MemoryMappedFile::Region* out_region); +COMPONENT_EXPORT(UI_BASE) +int GetMainAndroidPackFd(base::MemoryMappedFile::Region* out_region); // Returns the file descriptor and region for chrome_100_percent.pak. -UI_BASE_EXPORT int GetCommonResourcesPackFd( - base::MemoryMappedFile::Region* out_region); +COMPONENT_EXPORT(UI_BASE) +int GetCommonResourcesPackFd(base::MemoryMappedFile::Region* out_region); // Returns the file descriptor and region for the locale .pak file. -UI_BASE_EXPORT int GetLocalePackFd( - base::MemoryMappedFile::Region* out_region); +COMPONENT_EXPORT(UI_BASE) +int GetLocalePackFd(base::MemoryMappedFile::Region* out_region); // Returns the file descriptor and region for the secondary locale .pak file. -UI_BASE_EXPORT int GetSecondaryLocalePackFd( - base::MemoryMappedFile::Region* out_region); +COMPONENT_EXPORT(UI_BASE) +int GetSecondaryLocalePackFd(base::MemoryMappedFile::Region* out_region); // Tell ResourceBundle to locate locale pak files via // GetPathForAndroidLocalePakWithinApk rather than looking for them on disk. -UI_BASE_EXPORT void SetLocalePaksStoredInApk(bool value); +COMPONENT_EXPORT(UI_BASE) void SetLocalePaksStoredInApk(bool value); // Tell ResourceBundle to load secondary locale .pak files. -UI_BASE_EXPORT void SetLoadSecondaryLocalePaks(bool value); +COMPONENT_EXPORT(UI_BASE) void SetLoadSecondaryLocalePaks(bool value); // Returns the path within the apk for the given locale's .pak file, or an // empty string if it doesn't exist. // Only locale paks for the active Android language can be retrieved. -// If |inSplit| is true, look into bundle split-specific location (e.g. +// If |in_split| is true, look into bundle split-specific location (e.g. // 'assets/locales#lang_<lang>/<locale>.pak', otherwise use the default // WebView-related location, i.e. 'assets/stored-locales/<locale>.pak'. -UI_BASE_EXPORT std::string GetPathForAndroidLocalePakWithinApk( - const std::string& locale, - bool in_split = false); +// If |log_error|, logs the path to logcat, but does not abort. +COMPONENT_EXPORT(UI_BASE) +std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale, + bool in_split, + bool log_error); // Called in test when there are no locale pak files available. -UI_BASE_EXPORT void SetNoAvailableLocalePaksForTest(); +COMPONENT_EXPORT(UI_BASE) void SetNoAvailableLocalePaksForTest(); // Get the density of the primary display. Use this instead of using Display // to avoid initializing Display in child processes. diff --git a/chromium/ui/base/resource/resource_bundle_ios.mm b/chromium/ui/base/resource/resource_bundle_ios.mm index 111786882c6..f623bdf562d 100644 --- a/chromium/ui/base/resource/resource_bundle_ios.mm +++ b/chromium/ui/base/resource/resource_bundle_ios.mm @@ -13,6 +13,7 @@ #include "base/mac/foundation_util.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted_memory.h" +#include "base/notreached.h" #include "base/strings/sys_string_conversions.h" #include "base/synchronization/lock.h" #include "ui/base/resource/resource_handle.h" @@ -80,14 +81,8 @@ base::FilePath ResourceBundle::GetLocaleFilePath( locale_file_path, app_locale); } - // Don't try to load empty values or values that are not absolute paths. - if (locale_file_path.empty() || !locale_file_path.IsAbsolute()) - return base::FilePath(); - - if (!base::PathExists(locale_file_path)) - return base::FilePath(); - - return locale_file_path; + // Don't try to load from paths that are not absolute. + return locale_file_path.IsAbsolute() ? locale_file_path : base::FilePath(); } gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { diff --git a/chromium/ui/base/resource/resource_bundle_mac.mm b/chromium/ui/base/resource/resource_bundle_mac.mm index 6bd9d7aff19..87921ce6c6b 100644 --- a/chromium/ui/base/resource/resource_bundle_mac.mm +++ b/chromium/ui/base/resource/resource_bundle_mac.mm @@ -9,9 +9,11 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/logging.h" #include "base/mac/bundle_locations.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted_memory.h" +#include "base/notreached.h" #include "base/strings/sys_string_conversions.h" #include "base/synchronization/lock.h" #include "ui/base/resource/resource_handle.h" @@ -80,14 +82,8 @@ base::FilePath ResourceBundle::GetLocaleFilePath( locale_file_path, app_locale); } - // Don't try to load empty values or values that are not absolute paths. - if (locale_file_path.empty() || !locale_file_path.IsAbsolute()) - return base::FilePath(); - - if (!base::PathExists(locale_file_path)) - return base::FilePath(); - - return locale_file_path; + // Don't try to load from paths that are not absolute. + return locale_file_path.IsAbsolute() ? locale_file_path : base::FilePath(); } gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id) { diff --git a/chromium/ui/base/resource/resource_bundle_unittest.cc b/chromium/ui/base/resource/resource_bundle_unittest.cc index 904695c9291..bfa3dab5e80 100644 --- a/chromium/ui/base/resource/resource_bundle_unittest.cc +++ b/chromium/ui/base/resource/resource_bundle_unittest.cc @@ -163,16 +163,16 @@ TEST_F(ResourceBundleTest, DelegateGetPathForLocalePack) { .RetiresOnSaturation(); EXPECT_FALSE(ResourceBundle::LocaleDataPakExists(locale)); - EXPECT_EQ("", - ResourceBundle::GetSharedInstance().LoadLocaleResources(locale)); + EXPECT_EQ("", ResourceBundle::GetSharedInstance().LoadLocaleResources( + locale, /*crash_on_failure=*/false)); // Allow the load to proceed. EXPECT_CALL(delegate, GetPathForLocalePack(_, _)) .WillRepeatedly(ReturnArg<0>()); EXPECT_TRUE(ResourceBundle::LocaleDataPakExists(locale)); - EXPECT_EQ(locale, - ResourceBundle::GetSharedInstance().LoadLocaleResources(locale)); + EXPECT_EQ(locale, ResourceBundle::GetSharedInstance().LoadLocaleResources( + locale, /*crash_on_failure=*/false)); ResourceBundle::CleanupSharedInstance(); ResourceBundle::SwapSharedInstanceForTesting(orig_instance); diff --git a/chromium/ui/base/resource/resource_bundle_win.h b/chromium/ui/base/resource/resource_bundle_win.h index 92590eaff97..167f40c1ce3 100644 --- a/chromium/ui/base/resource/resource_bundle_win.h +++ b/chromium/ui/base/resource/resource_bundle_win.h @@ -9,16 +9,16 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // NOTE: This needs to be called before initializing ResourceBundle if your // resources are not stored in the executable. -UI_BASE_EXPORT void SetResourcesDataDLL(HINSTANCE handle); +COMPONENT_EXPORT(UI_BASE) void SetResourcesDataDLL(HINSTANCE handle); // Loads and returns an icon from the app module. -UI_BASE_EXPORT HICON LoadThemeIconFromResourcesDataDLL(int icon_id); +COMPONENT_EXPORT(UI_BASE) HICON LoadThemeIconFromResourcesDataDLL(int icon_id); } // namespace ui diff --git a/chromium/ui/base/scoped_visibility_tracker.h b/chromium/ui/base/scoped_visibility_tracker.h index b351b57099e..2f53bc552b3 100644 --- a/chromium/ui/base/scoped_visibility_tracker.h +++ b/chromium/ui/base/scoped_visibility_tracker.h @@ -7,8 +7,8 @@ #include <memory> +#include "base/component_export.h" #include "base/time/time.h" -#include "ui/base/ui_base_export.h" namespace base { class TickClock; @@ -18,7 +18,7 @@ namespace ui { // This class tracks the total time it is visible, based on receiving // OnShown/OnHidden notifications, which are logically idempotent. -class UI_BASE_EXPORT ScopedVisibilityTracker { +class COMPONENT_EXPORT(UI_BASE) ScopedVisibilityTracker { public: // |tick_clock| must outlive this object. ScopedVisibilityTracker(const base::TickClock* tick_clock, bool is_shown); diff --git a/chromium/ui/base/template_expressions.cc b/chromium/ui/base/template_expressions.cc index 2d7af5e5bc4..2f6573447c6 100644 --- a/chromium/ui/base/template_expressions.cc +++ b/chromium/ui/base/template_expressions.cc @@ -6,6 +6,8 @@ #include <stddef.h> +#include <ostream> + #include "base/check_op.h" #include "base/optional.h" #include "base/stl_util.h" diff --git a/chromium/ui/base/template_expressions.h b/chromium/ui/base/template_expressions.h index a12f5b2fad8..470d54b3734 100644 --- a/chromium/ui/base/template_expressions.h +++ b/chromium/ui/base/template_expressions.h @@ -11,8 +11,8 @@ #include <map> #include <string> +#include "base/component_export.h" #include "base/strings/string_piece.h" -#include "ui/base/ui_base_export.h" namespace base { class DictionaryValue; @@ -26,14 +26,16 @@ typedef std::map<const std::string, std::string> TemplateReplacements; // Convert a dictionary to a replacement map. This helper function is to assist // migration to using TemplateReplacements directly (which is preferred). // TODO(dschuyler): remove this function by using TemplateReplacements directly. -UI_BASE_EXPORT void TemplateReplacementsFromDictionaryValue( +COMPONENT_EXPORT(UI_BASE) +void TemplateReplacementsFromDictionaryValue( const base::DictionaryValue& dictionary, TemplateReplacements* replacements); // Replace $i18n*{foo} in the format string with the value for the foo key in // |replacements|. If the key is not found in the |replacements| that item will // be unaltered. -UI_BASE_EXPORT std::string ReplaceTemplateExpressions( +COMPONENT_EXPORT(UI_BASE) +std::string ReplaceTemplateExpressions( base::StringPiece source, const TemplateReplacements& replacements, bool skip_unexpected_placeholder_check = false); @@ -51,10 +53,10 @@ UI_BASE_EXPORT std::string ReplaceTemplateExpressions( // backticks or "${" within the HTML string). // Note: Currently, this only supports the legacy Polymer syntax, i.e.: // _template: html` ... `, -UI_BASE_EXPORT bool ReplaceTemplateExpressionsInJS( - base::StringPiece source, - const TemplateReplacements& replacements, - std::string* output); +COMPONENT_EXPORT(UI_BASE) +bool ReplaceTemplateExpressionsInJS(base::StringPiece source, + const TemplateReplacements& replacements, + std::string* output); } // namespace ui diff --git a/chromium/ui/base/text/bytes_formatting.h b/chromium/ui/base/text/bytes_formatting.h index 7cb6e45ce62..424d5297435 100644 --- a/chromium/ui/base/text/bytes_formatting.h +++ b/chromium/ui/base/text/bytes_formatting.h @@ -7,8 +7,8 @@ #include <stdint.h> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -17,12 +17,12 @@ namespace ui { // Simple call to return a byte quantity as a string in human-readable format. // Ex: FormatBytes(512) => "512 B" // Ex: FormatBytes(101479) => "99.1 kB" -UI_BASE_EXPORT base::string16 FormatBytes(int64_t bytes); +COMPONENT_EXPORT(UI_BASE) base::string16 FormatBytes(int64_t bytes); // Simple call to return a speed as a string in human-readable format. // Ex: FormatSpeed(512) => "512 B/s" // Ex: FormatSpeed(101479) => "99.1 kB/s" -UI_BASE_EXPORT base::string16 FormatSpeed(int64_t bytes); +COMPONENT_EXPORT(UI_BASE) base::string16 FormatSpeed(int64_t bytes); // Less-Simple API ------------------------------------------------------------- @@ -38,15 +38,16 @@ enum DataUnits { // Return the unit type that is appropriate for displaying the amount of bytes // passed in. Most of the time, an explicit call to this isn't necessary; just // use FormatBytes()/FormatSpeed() above. -UI_BASE_EXPORT DataUnits GetByteDisplayUnits(int64_t bytes); +COMPONENT_EXPORT(UI_BASE) DataUnits GetByteDisplayUnits(int64_t bytes); // Return a byte quantity as a string in human-readable format with an optional // unit suffix. Specify in the |units| argument the units to be used. // Ex: FormatBytes(512, DATA_UNITS_KIBIBYTE, true) => "0.5 kB" // Ex: FormatBytes(10*1024, DATA_UNITS_MEBIBYTE, false) => "0.1" -UI_BASE_EXPORT base::string16 FormatBytesWithUnits(int64_t bytes, - DataUnits units, - bool show_units); +COMPONENT_EXPORT(UI_BASE) +base::string16 FormatBytesWithUnits(int64_t bytes, + DataUnits units, + bool show_units); // As above, but with "/s" units for speed values. // Ex: FormatSpeed(512, DATA_UNITS_KIBIBYTE, true) => "0.5 kB/s" diff --git a/chromium/ui/base/theme_provider.h b/chromium/ui/base/theme_provider.h index 514a9ae4545..f47a724d56d 100644 --- a/chromium/ui/base/theme_provider.h +++ b/chromium/ui/base/theme_provider.h @@ -5,9 +5,9 @@ #ifndef UI_BASE_THEME_PROVIDER_H_ #define UI_BASE_THEME_PROVIDER_H_ +#include "base/component_export.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/layout.h" -#include "ui/base/ui_base_export.h" namespace base { class RefCountedMemory; @@ -32,7 +32,7 @@ namespace ui { // //////////////////////////////////////////////////////////////////////////////// -class UI_BASE_EXPORT ThemeProvider { +class COMPONENT_EXPORT(UI_BASE) ThemeProvider { public: virtual ~ThemeProvider(); diff --git a/chromium/ui/base/ui_base_export.h b/chromium/ui/base/ui_base_export.h deleted file mode 100644 index dba9b898029..00000000000 --- a/chromium/ui/base/ui_base_export.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_UI_BASE_EXPORT_H_ -#define UI_BASE_UI_BASE_EXPORT_H_ - -// Defines UI_BASE_EXPORT so that functionality implemented by the UI module -// can be exported to consumers. - -#if defined(COMPONENT_BUILD) - -#if defined(WIN32) - -#if defined(UI_BASE_IMPLEMENTATION) -#define UI_BASE_EXPORT __declspec(dllexport) -#else -#define UI_BASE_EXPORT __declspec(dllimport) -#endif - -#else // !defined(WIN32) - -#if defined(UI_BASE_IMPLEMENTATION) -#define UI_BASE_EXPORT __attribute__((visibility("default"))) -#else -#define UI_BASE_EXPORT -#endif - -#endif - -#else // !defined(COMPONENT_BUILD) - -#define UI_BASE_EXPORT - -#endif - -#endif // UI_BASE_UI_BASE_EXPORT_H_ diff --git a/chromium/ui/base/ui_base_features.cc b/chromium/ui/base/ui_base_features.cc index 7050729f302..3a6ee833e13 100644 --- a/chromium/ui/base/ui_base_features.cc +++ b/chromium/ui/base/ui_base_features.cc @@ -161,6 +161,18 @@ bool IsEyeDropperEnabled() { base::FeatureList::IsEnabled(features::kEyeDropper); } +// Enable the CSSColorSchemeUARendering feature for Windows, ChromeOS, Linux, +// and Mac. This feature will be released for Android in later milestones. See +// crbug.com/1086530 for the Desktop launch bug. +const base::Feature kCSSColorSchemeUARendering = { + "CSSColorSchemeUARendering", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsCSSColorSchemeUARenderingEnabled() { + static const bool css_color_scheme_ua_rendering_enabled = + base::FeatureList::IsEnabled(features::kCSSColorSchemeUARendering); + return css_color_scheme_ua_rendering_enabled; +} + // Enable the FormControlsRefresh feature for Windows, ChromeOS, Linux, and Mac. // This feature will be released for Android in later milestones. See // crbug.com/1012106 for the Windows launch bug, and crbug.com/1012108 for the @@ -188,13 +200,9 @@ bool IsUseCommonSelectPopupEnabled() { return base::FeatureList::IsEnabled(features::kUseCommonSelectPopup); } -// Enable WebUI accessibility enhancements for review and testing. -const base::Feature kWebUIA11yEnhancements{"WebUIA11yEnhancements", - base::FEATURE_DISABLED_BY_DEFAULT}; - #if defined(OS_CHROMEOS) const base::Feature kHandwritingGesture = {"HandwritingGesture", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #endif const base::Feature kSynchronousPageFlipTesting{ @@ -204,4 +212,30 @@ bool IsSynchronousPageFlipTestingEnabled() { return base::FeatureList::IsEnabled(kSynchronousPageFlipTesting); } +#if defined(USE_X11) || defined(USE_OZONE) +const base::Feature kUseOzonePlatform { + "UseOzonePlatform", +#if defined(USE_X11) + base::FEATURE_DISABLED_BY_DEFAULT +}; +#else + base::FEATURE_ENABLED_BY_DEFAULT +}; +#endif + +bool IsUsingOzonePlatform() { + // Only allow enabling and disabling the OzonePlatform on USE_X11 && USE_OZONE + // builds. +#if defined(USE_X11) && defined(USE_OZONE) + return base::FeatureList::IsEnabled(kUseOzonePlatform); +#elif defined(USE_X11) && !defined(USE_OZONE) + // This shouldn't be switchable for pure X11 builds. + return false; +#else + // All the other platforms must use Ozone by default and can't disable that. + return true; +#endif +} +#endif // defined(USE_X11) || defined(USE_OZONE) + } // namespace features diff --git a/chromium/ui/base/ui_base_features.h b/chromium/ui/base/ui_base_features.h index 83d7157f8d0..61f75131c9f 100644 --- a/chromium/ui/base/ui_base_features.h +++ b/chromium/ui/base/ui_base_features.h @@ -73,6 +73,11 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsForcedColorsEnabled(); COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kEyeDropper; COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsEyeDropperEnabled(); +// Used to enable form controls and scrollbar dark mode rendering. +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kCSSColorSchemeUARendering; +COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsCSSColorSchemeUARenderingEnabled(); + // Used to enable the new controls UI. COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kFormControlsRefresh; @@ -94,9 +99,6 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsNewShortcutMappingEnabled(); #endif -COMPONENT_EXPORT(UI_BASE_FEATURES) -extern const base::Feature kWebUIA11yEnhancements; - // Indicates whether DrmOverlayManager should used the synchronous API to // perform pageflip tests. COMPONENT_EXPORT(UI_BASE_FEATURES) @@ -105,6 +107,21 @@ extern const base::Feature kSynchronousPageFlipTesting; COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsSynchronousPageFlipTestingEnabled(); +#if defined(USE_X11) || defined(USE_OZONE) +// Indicates whether the OzonePlatform feature is used on Linux. Although, it is +// available for all Ozone platforms, this always resolves to true for +// non-desktop Linux builds. The reason why it is needed for all Ozone builds is +// that we have many places in the code that Ozone takes independently of the +// platform, and it's highly important that when USE_X11 && USE_OZONE are true +// and the OzonePlatform feature is not enabled, the Ozone path is never taken. +// This will be removed as soon as Ozone/Linux is default and USE_X11 is +// removed. More info at +// https://docs.google.com/document/d/1PvKquOHWySbvbe4bgduAcpW0Pda4BBhXI7xphtyDtPQ +COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kUseOzonePlatform; + +COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsUsingOzonePlatform(); +#endif + } // namespace features #endif // UI_BASE_UI_BASE_FEATURES_H_ diff --git a/chromium/ui/base/ui_base_paths.h b/chromium/ui/base/ui_base_paths.h index cf5e0041e6f..fa61416237d 100644 --- a/chromium/ui/base/ui_base_paths.h +++ b/chromium/ui/base/ui_base_paths.h @@ -5,8 +5,8 @@ #ifndef UI_BASE_UI_BASE_PATHS_H_ #define UI_BASE_UI_BASE_PATHS_H_ +#include "base/component_export.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" // This file declares path keys for various special directories. These can be // used with the PathService to access these directories and files. @@ -31,7 +31,7 @@ enum { }; // Call once to register the provider for the path keys defined above. -UI_BASE_EXPORT void RegisterPathProvider(); +COMPONENT_EXPORT(UI_BASE) void RegisterPathProvider(); } // namespace ui diff --git a/chromium/ui/base/ui_base_switches.h b/chromium/ui/base/ui_base_switches.h index 26b8dbf13a1..8e7fb9e0c93 100644 --- a/chromium/ui/base/ui_base_switches.h +++ b/chromium/ui/base/ui_base_switches.h @@ -7,41 +7,41 @@ #ifndef UI_BASE_UI_BASE_SWITCHES_H_ #define UI_BASE_UI_BASE_SWITCHES_H_ +#include "base/component_export.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" namespace switches { #if defined(OS_MACOSX) && !defined(OS_IOS) -UI_BASE_EXPORT extern const char kDisableAVFoundationOverlays[]; -UI_BASE_EXPORT extern const char kDisableMacOverlays[]; -UI_BASE_EXPORT extern const char kDisableModalAnimations[]; -UI_BASE_EXPORT extern const char kDisableRemoteCoreAnimation[]; -UI_BASE_EXPORT extern const char kShowMacOverlayBorders[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableAVFoundationOverlays[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableMacOverlays[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableModalAnimations[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableRemoteCoreAnimation[]; +COMPONENT_EXPORT(UI_BASE) extern const char kShowMacOverlayBorders[]; #endif -UI_BASE_EXPORT extern const char kDisableCompositedAntialiasing[]; -UI_BASE_EXPORT extern const char kDisableDwmComposition[]; -UI_BASE_EXPORT extern const char kDisableTouchAdjustment[]; -UI_BASE_EXPORT extern const char kDisableTouchDragDrop[]; -UI_BASE_EXPORT extern const char kEnableTouchDragDrop[]; -UI_BASE_EXPORT extern const char kForceCaptionStyle[]; -UI_BASE_EXPORT extern const char kForceDarkMode[]; -UI_BASE_EXPORT extern const char kForceHighContrast[]; -UI_BASE_EXPORT extern const char kLang[]; -UI_BASE_EXPORT extern const char kShowOverdrawFeedback[]; -UI_BASE_EXPORT extern const char kSlowDownCompositingScaleFactor[]; -UI_BASE_EXPORT extern const char kTintGlCompositedContent[]; -UI_BASE_EXPORT extern const char kTopChromeTouchUi[]; -UI_BASE_EXPORT extern const char kTopChromeTouchUiAuto[]; -UI_BASE_EXPORT extern const char kTopChromeTouchUiDisabled[]; -UI_BASE_EXPORT extern const char kTopChromeTouchUiEnabled[]; -UI_BASE_EXPORT extern const char kUIDisablePartialSwap[]; -UI_BASE_EXPORT extern const char kUseSystemClipboard[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableCompositedAntialiasing[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableDwmComposition[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableTouchAdjustment[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisableTouchDragDrop[]; +COMPONENT_EXPORT(UI_BASE) extern const char kEnableTouchDragDrop[]; +COMPONENT_EXPORT(UI_BASE) extern const char kForceCaptionStyle[]; +COMPONENT_EXPORT(UI_BASE) extern const char kForceDarkMode[]; +COMPONENT_EXPORT(UI_BASE) extern const char kForceHighContrast[]; +COMPONENT_EXPORT(UI_BASE) extern const char kLang[]; +COMPONENT_EXPORT(UI_BASE) extern const char kShowOverdrawFeedback[]; +COMPONENT_EXPORT(UI_BASE) extern const char kSlowDownCompositingScaleFactor[]; +COMPONENT_EXPORT(UI_BASE) extern const char kTintGlCompositedContent[]; +COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUi[]; +COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiAuto[]; +COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiDisabled[]; +COMPONENT_EXPORT(UI_BASE) extern const char kTopChromeTouchUiEnabled[]; +COMPONENT_EXPORT(UI_BASE) extern const char kUIDisablePartialSwap[]; +COMPONENT_EXPORT(UI_BASE) extern const char kUseSystemClipboard[]; // Test related. -UI_BASE_EXPORT extern const char kDisallowNonExactResourceReuse[]; -UI_BASE_EXPORT extern const char kMangleLocalizedStrings[]; +COMPONENT_EXPORT(UI_BASE) extern const char kDisallowNonExactResourceReuse[]; +COMPONENT_EXPORT(UI_BASE) extern const char kMangleLocalizedStrings[]; } // namespace switches diff --git a/chromium/ui/base/ui_base_switches_util.h b/chromium/ui/base/ui_base_switches_util.h index 2b6af8c1088..9928e56708b 100644 --- a/chromium/ui/base/ui_base_switches_util.h +++ b/chromium/ui/base/ui_base_switches_util.h @@ -5,11 +5,11 @@ #ifndef UI_BASE_UI_BASE_SWITCHES_UTIL_H_ #define UI_BASE_UI_BASE_SWITCHES_UTIL_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace switches { -UI_BASE_EXPORT bool IsTouchDragDropEnabled(); +COMPONENT_EXPORT(UI_BASE) bool IsTouchDragDropEnabled(); } // namespace switches diff --git a/chromium/ui/base/ui_base_types.h b/chromium/ui/base/ui_base_types.h index f79b03aaeb2..f290701526d 100644 --- a/chromium/ui/base/ui_base_types.h +++ b/chromium/ui/base/ui_base_types.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_UI_BASE_TYPES_H_ #define UI_BASE_UI_BASE_TYPES_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -93,7 +93,8 @@ enum MenuSourceType { MENU_SOURCE_TYPE_LAST = MENU_SOURCE_ADJUST_SELECTION_RESET }; -UI_BASE_EXPORT MenuSourceType GetMenuSourceTypeForEvent(const ui::Event& event); +COMPONENT_EXPORT(UI_BASE) +MenuSourceType GetMenuSourceTypeForEvent(const ui::Event& event); } // namespace ui diff --git a/chromium/ui/base/user_activity/user_activity_detector.h b/chromium/ui/base/user_activity/user_activity_detector.h index 0f2a9a9ec4b..caffb50fdf8 100644 --- a/chromium/ui/base/user_activity/user_activity_detector.h +++ b/chromium/ui/base/user_activity/user_activity_detector.h @@ -6,10 +6,10 @@ #define UI_BASE_USER_ACTIVITY_USER_ACTIVITY_DETECTOR_H_ #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/observer_list.h" #include "base/time/time.h" -#include "ui/base/ui_base_export.h" #include "ui/events/event.h" #include "ui/events/platform/platform_event_observer.h" @@ -18,7 +18,8 @@ namespace ui { class UserActivityObserver; // Watches for input events and notifies observers that the user is active. -class UI_BASE_EXPORT UserActivityDetector : public PlatformEventObserver { +class COMPONENT_EXPORT(UI_BASE) UserActivityDetector + : public PlatformEventObserver { public: // Minimum amount of time between notifications to observers. static const int kNotifyIntervalMs; diff --git a/chromium/ui/base/user_activity/user_activity_observer.h b/chromium/ui/base/user_activity/user_activity_observer.h index f6b98d210af..a83c8affd8e 100644 --- a/chromium/ui/base/user_activity/user_activity_observer.h +++ b/chromium/ui/base/user_activity/user_activity_observer.h @@ -5,8 +5,8 @@ #ifndef UI_BASE_USER_ACTIVITY_USER_ACTIVITY_OBSERVER_H_ #define UI_BASE_USER_ACTIVITY_USER_ACTIVITY_OBSERVER_H_ +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" namespace ui { class Event; @@ -16,7 +16,7 @@ namespace ui { // Interface for classes that want to be notified about user activity. // Implementations should register themselves with UserActivityDetector. -class UI_BASE_EXPORT UserActivityObserver { +class COMPONENT_EXPORT(UI_BASE) UserActivityObserver { public: // Invoked periodically while the user is active (i.e. generating input // events). |event| is the event that triggered the notification; it may diff --git a/chromium/ui/base/view_prop.cc b/chromium/ui/base/view_prop.cc index 45185f5ffbe..33b38a2ff04 100644 --- a/chromium/ui/base/view_prop.cc +++ b/chromium/ui/base/view_prop.cc @@ -53,9 +53,7 @@ class ViewProp::Data : public base::RefCounted<ViewProp::Data> { typedef std::set<Data*, DataComparator> DataSet; Data(gfx::AcceleratedWidget view, const char* key) - : view_(view), - key_(key), - data_(NULL) {} + : view_(view), key_(key), data_(nullptr) {} ~Data() { auto i = data_set_->find(this); diff --git a/chromium/ui/base/view_prop.h b/chromium/ui/base/view_prop.h index c81e995b0ba..c15007ae06a 100644 --- a/chromium/ui/base/view_prop.h +++ b/chromium/ui/base/view_prop.h @@ -5,10 +5,10 @@ #ifndef UI_BASE_VIEW_PROP_H_ #define UI_BASE_VIEW_PROP_H_ +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/native_widget_types.h" #if !defined(OS_WIN) && !defined(USE_AURA) @@ -21,7 +21,7 @@ namespace ui { // designed as a replacement for the Win32's SetProp, but does not make use of // window manager memory. ViewProp shares similar semantics as SetProp, the // value for a particular view/key pair comes from the last ViewProp created. -class UI_BASE_EXPORT ViewProp { +class COMPONENT_EXPORT(UI_BASE) ViewProp { public: // Associates data with a view/key pair. If a ViewProp has already been // created for the specified pair |data| replaces the current value. diff --git a/chromium/ui/base/webui/i18n_source_stream.h b/chromium/ui/base/webui/i18n_source_stream.h index 994ac6ce4ba..bba7a13c27e 100644 --- a/chromium/ui/base/webui/i18n_source_stream.h +++ b/chromium/ui/base/webui/i18n_source_stream.h @@ -8,14 +8,15 @@ #include <memory> #include <string> +#include "base/component_export.h" #include "base/macros.h" #include "net/filter/filter_source_stream.h" #include "ui/base/template_expressions.h" -#include "ui/base/ui_base_export.h" namespace ui { -class UI_BASE_EXPORT I18nSourceStream : public net::FilterSourceStream { +class COMPONENT_EXPORT(UI_BASE) I18nSourceStream + : public net::FilterSourceStream { public: ~I18nSourceStream() override; diff --git a/chromium/ui/base/webui/jstemplate_builder.cc b/chromium/ui/base/webui/jstemplate_builder.cc index b2b2b142275..50c52507d00 100644 --- a/chromium/ui/base/webui/jstemplate_builder.cc +++ b/chromium/ui/base/webui/jstemplate_builder.cc @@ -123,7 +123,7 @@ void AppendJsonJS(const base::DictionaryValue* json, // If the script is being imported as a module, import |loadTimeData| in // order to allow assigning the localized strings to loadTimeData.data. output->append("import {loadTimeData} from "); - output->append("'chrome://resources/js/load_time_data.m.js';\n"); + output->append("'//resources/js/load_time_data.m.js';\n"); } std::string jstext; diff --git a/chromium/ui/base/webui/jstemplate_builder.h b/chromium/ui/base/webui/jstemplate_builder.h index 5b1c1170690..97a4a558a2d 100644 --- a/chromium/ui/base/webui/jstemplate_builder.h +++ b/chromium/ui/base/webui/jstemplate_builder.h @@ -15,8 +15,8 @@ #include <string> +#include "base/component_export.h" #include "base/strings/string_piece.h" -#include "ui/base/ui_base_export.h" namespace base { class DictionaryValue; @@ -27,22 +27,23 @@ namespace webui { // A helper function that generates a string of HTML to be loaded. The // string includes the HTML and the javascript code necessary to generate the // full page with support for i18n Templates. -UI_BASE_EXPORT std::string GetI18nTemplateHtml( - const base::StringPiece& html_template, - const base::DictionaryValue* json); +COMPONENT_EXPORT(UI_BASE) +std::string GetI18nTemplateHtml(const base::StringPiece& html_template, + const base::DictionaryValue* json); // A helper function that generates a string of HTML to be loaded. The // string includes the HTML and the javascript code necessary to generate the // full page with support for both i18n Templates and JsTemplates. -UI_BASE_EXPORT std::string GetTemplatesHtml( - const base::StringPiece& html_template, - const base::DictionaryValue* json, - const base::StringPiece& template_id); +COMPONENT_EXPORT(UI_BASE) +std::string GetTemplatesHtml(const base::StringPiece& html_template, + const base::DictionaryValue* json, + const base::StringPiece& template_id); // Assigns the given json data into |loadTimeData|, without a <script> tag. -UI_BASE_EXPORT void AppendJsonJS(const base::DictionaryValue* json, - std::string* output, - bool from_js_module); +COMPONENT_EXPORT(UI_BASE) +void AppendJsonJS(const base::DictionaryValue* json, + std::string* output, + bool from_js_module); } // namespace webui diff --git a/chromium/ui/base/webui/web_ui_util.cc b/chromium/ui/base/webui/web_ui_util.cc index 6b6ea2d9bb7..ffc30f61a7a 100644 --- a/chromium/ui/base/webui/web_ui_util.cc +++ b/chromium/ui/base/webui/web_ui_util.cc @@ -189,7 +189,6 @@ void ParsePathAndFrame(const GURL& url, std::string* path, int* frame_index) { void SetLoadTimeDataDefaults(const std::string& app_locale, base::DictionaryValue* localized_strings) { - localized_strings->SetString("a11yenhanced", GetA11yEnhanced()); localized_strings->SetString("fontfamily", GetFontFamily()); localized_strings->SetString("fontsize", GetFontSize()); localized_strings->SetString("language", l10n_util::GetLanguage(app_locale)); @@ -198,7 +197,6 @@ void SetLoadTimeDataDefaults(const std::string& app_locale, void SetLoadTimeDataDefaults(const std::string& app_locale, ui::TemplateReplacements* replacements) { - (*replacements)["a11yenhanced"] = GetA11yEnhanced(); (*replacements)["fontfamily"] = GetFontFamily(); (*replacements)["fontsize"] = GetFontSize(); (*replacements)["language"] = l10n_util::GetLanguage(app_locale); @@ -225,12 +223,6 @@ void AppendWebUiCssTextDefaults(std::string* html) { html->append("</style>"); } -std::string GetA11yEnhanced() { - return base::FeatureList::IsEnabled(features::kWebUIA11yEnhancements) - ? "a11y-enhanced" - : ""; -} - std::string GetFontFamily() { std::string font_family = l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY); diff --git a/chromium/ui/base/webui/web_ui_util.h b/chromium/ui/base/webui/web_ui_util.h index 77e20e282e8..1aa12627756 100644 --- a/chromium/ui/base/webui/web_ui_util.h +++ b/chromium/ui/base/webui/web_ui_util.h @@ -9,10 +9,10 @@ #include <string> +#include "base/component_export.h" #include "base/strings/string_piece.h" #include "base/values.h" #include "ui/base/template_expressions.h" -#include "ui/base/ui_base_export.h" #include "ui/base/window_open_disposition.h" class GURL; @@ -27,21 +27,22 @@ struct LocalizedString { // Convenience routine to convert SkBitmap object to data url // so that it can be used in WebUI. -UI_BASE_EXPORT std::string GetBitmapDataUrl(const SkBitmap& bitmap); +COMPONENT_EXPORT(UI_BASE) std::string GetBitmapDataUrl(const SkBitmap& bitmap); // Convenience routine to convert an in-memory PNG to a data url for WebUI use. -UI_BASE_EXPORT std::string GetPngDataUrl(const unsigned char* data, - size_t size); +COMPONENT_EXPORT(UI_BASE) +std::string GetPngDataUrl(const unsigned char* data, size_t size); // Extracts a disposition from click event arguments. |args| should contain // an integer button and booleans alt key, ctrl key, meta key, and shift key // (in that order), starting at |start_index|. -UI_BASE_EXPORT WindowOpenDisposition - GetDispositionFromClick(const base::ListValue* args, int start_index); +COMPONENT_EXPORT(UI_BASE) +WindowOpenDisposition GetDispositionFromClick(const base::ListValue* args, + int start_index); // Parse a formatted scale factor string into float and sets to |scale_factor|. -UI_BASE_EXPORT bool ParseScaleFactor(const base::StringPiece& identifier, - float* scale_factor); +COMPONENT_EXPORT(UI_BASE) +bool ParseScaleFactor(const base::StringPiece& identifier, float* scale_factor); // Parses a URL containing some path [{frame}]@{scale}x. If it contains a // scale factor then it is returned and the associated part of the URL is @@ -50,49 +51,47 @@ UI_BASE_EXPORT bool ParseScaleFactor(const base::StringPiece& identifier, // is returned and the associated part of the URL is removed from the // returned |path|, otherwise the default frame index is returned and |path| // is left intact. -UI_BASE_EXPORT void ParsePathAndImageSpec(const GURL& url, - std::string* path, - float* scale_factor, - int* frame_index); +COMPONENT_EXPORT(UI_BASE) +void ParsePathAndImageSpec(const GURL& url, + std::string* path, + float* scale_factor, + int* frame_index); // Parses a URL containing some path @{scale}x. If it does not contain a scale // factor then the default scale factor is returned. -UI_BASE_EXPORT void ParsePathAndScale(const GURL& url, - std::string* path, - float* scale_factor); +COMPONENT_EXPORT(UI_BASE) +void ParsePathAndScale(const GURL& url, std::string* path, float* scale_factor); // Parses a URL containing some path [{frame}]. If it does not contain a frame // index then the default frame index is returned. -UI_BASE_EXPORT void ParsePathAndFrame(const GURL& url, - std::string* path, - int* frame_index); +COMPONENT_EXPORT(UI_BASE) +void ParsePathAndFrame(const GURL& url, std::string* path, int* frame_index); // Helper function to set some default values (e.g., font family, size, // language, and text direction) into the given dictionary. Requires an // application locale (i.e. g_browser_process->GetApplicationLocale()). -UI_BASE_EXPORT void SetLoadTimeDataDefaults( - const std::string& app_locale, - base::DictionaryValue* localized_strings); -UI_BASE_EXPORT void SetLoadTimeDataDefaults( - const std::string& app_locale, - ui::TemplateReplacements* replacements); +COMPONENT_EXPORT(UI_BASE) +void SetLoadTimeDataDefaults(const std::string& app_locale, + base::DictionaryValue* localized_strings); +COMPONENT_EXPORT(UI_BASE) +void SetLoadTimeDataDefaults(const std::string& app_locale, + ui::TemplateReplacements* replacements); // Get a CSS declaration for common text styles for all of Web UI. -UI_BASE_EXPORT std::string GetWebUiCssTextDefaults(); +COMPONENT_EXPORT(UI_BASE) std::string GetWebUiCssTextDefaults(); // Get a CSS declaration for common text styles for Web UI using // Material Design. -UI_BASE_EXPORT std::string GetWebUiCssTextDefaultsMd(); +COMPONENT_EXPORT(UI_BASE) std::string GetWebUiCssTextDefaultsMd(); // Appends the CSS declaration returned by GetWebUiCssTextDefaults() as an // inline stylesheet. -UI_BASE_EXPORT void AppendWebUiCssTextDefaults(std::string* html); +COMPONENT_EXPORT(UI_BASE) void AppendWebUiCssTextDefaults(std::string* html); -UI_BASE_EXPORT std::string GetA11yEnhanced(); // Get some common font styles for all of WebUI. -UI_BASE_EXPORT std::string GetFontFamily(); -UI_BASE_EXPORT std::string GetFontSize(); -UI_BASE_EXPORT std::string GetTextDirection(); +COMPONENT_EXPORT(UI_BASE) std::string GetFontFamily(); +COMPONENT_EXPORT(UI_BASE) std::string GetFontSize(); +COMPONENT_EXPORT(UI_BASE) std::string GetTextDirection(); } // namespace webui diff --git a/chromium/ui/base/win/accessibility_misc_utils.h b/chromium/ui/base/win/accessibility_misc_utils.h index ec493a3cad2..98116875245 100644 --- a/chromium/ui/base/win/accessibility_misc_utils.h +++ b/chromium/ui/base/win/accessibility_misc_utils.h @@ -9,14 +9,14 @@ #include <UIAutomationCore.h> #include "base/compiler_specific.h" +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace base { namespace win { // UIA Text provider implementation for edit controls. -class UI_BASE_EXPORT UIATextProvider +class COMPONENT_EXPORT(UI_BASE) UIATextProvider : public CComObjectRootEx<CComMultiThreadModel>, public ITextProvider { public: diff --git a/chromium/ui/base/win/event_creation_utils.cc b/chromium/ui/base/win/event_creation_utils.cc new file mode 100644 index 00000000000..29efc62b3cc --- /dev/null +++ b/chromium/ui/base/win/event_creation_utils.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2020 The Chromium Authors. All 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/win/event_creation_utils.h" + +#include <windows.h> +#include <winuser.h> + +#include <algorithm> + +#include "base/numerics/ranges.h" +#include "ui/gfx/geometry/point.h" + +namespace ui { + +bool SendMouseEvent(const gfx::Point& point, int flags) { + INPUT input = {INPUT_MOUSE}; + // Get the max screen coordinate for use in computing the normalized absolute + // coordinates required by SendInput. + const int max_x = ::GetSystemMetrics(SM_CXSCREEN) - 1; + const int max_y = ::GetSystemMetrics(SM_CYSCREEN) - 1; + int screen_x = base::ClampToRange(point.x(), 0, max_x); + int screen_y = base::ClampToRange(point.y(), 0, max_y); + + // Form the input data containing the normalized absolute coordinates. As of + // Windows 10 Fall Creators Update, moving to an absolute position of zero + // does not work. It seems that moving to 1,1 does, though. + input.mi.dx = + static_cast<LONG>(std::max(1.0, std::ceil(screen_x * (65535.0 / max_x)))); + input.mi.dy = + static_cast<LONG>(std::max(1.0, std::ceil(screen_y * (65535.0 / max_y)))); + input.mi.dwFlags = flags; + return ::SendInput(1, &input, sizeof(input)) == 1; +} + +} // namespace ui diff --git a/chromium/ui/base/win/event_creation_utils.h b/chromium/ui/base/win/event_creation_utils.h new file mode 100644 index 00000000000..cb893f240a2 --- /dev/null +++ b/chromium/ui/base/win/event_creation_utils.h @@ -0,0 +1,23 @@ +// Copyright (c) 2020 The Chromium Authors. All 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_WIN_EVENT_CREATION_UTILS_H_ +#define UI_BASE_WIN_EVENT_CREATION_UTILS_H_ + +#include "base/component_export.h" + +namespace gfx { +class Point; +} // namespace gfx + +namespace ui { + +// Send a mouse event to Windows input queue using ::SendInput, to screen +// point |point|. Returns true if the mouse event was sent, false if not. +COMPONENT_EXPORT(UI_BASE) +bool SendMouseEvent(const gfx::Point& point, int flags); + +} // namespace ui + +#endif // UI_BASE_WIN_EVENT_CREATION_UTILS_H_ diff --git a/chromium/ui/base/win/foreground_helper.h b/chromium/ui/base/win/foreground_helper.h index 38dcdbab9f2..333b87531d9 100644 --- a/chromium/ui/base/win/foreground_helper.h +++ b/chromium/ui/base/win/foreground_helper.h @@ -5,9 +5,9 @@ #ifndef UI_BASE_WIN_FOREGROUND_HELPER_H_ #define UI_BASE_WIN_FOREGROUND_HELPER_H_ -#include "base/logging.h" +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" +#include "base/notreached.h" #include "ui/gfx/win/window_impl.h" #include <windows.h> @@ -21,7 +21,7 @@ namespace ui { // to be capable of moving to the foreground. // // This is probably leveraging a windows bug. -class UI_BASE_EXPORT ForegroundHelper : public gfx::WindowImpl { +class COMPONENT_EXPORT(UI_BASE) ForegroundHelper : public gfx::WindowImpl { public: ForegroundHelper(); ~ForegroundHelper() override; diff --git a/chromium/ui/base/win/hidden_window.cc b/chromium/ui/base/win/hidden_window.cc index 3312dde6b26..accdea3bf6d 100644 --- a/chromium/ui/base/win/hidden_window.cc +++ b/chromium/ui/base/win/hidden_window.cc @@ -4,6 +4,7 @@ #include "ui/base/win/hidden_window.h" +#include "base/notreached.h" #include "ui/gfx/win/window_impl.h" namespace ui { diff --git a/chromium/ui/base/win/hidden_window.h b/chromium/ui/base/win/hidden_window.h index 6cc2fd0dd6d..8524f1dafe4 100644 --- a/chromium/ui/base/win/hidden_window.h +++ b/chromium/ui/base/win/hidden_window.h @@ -7,13 +7,13 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Returns an HWND that can be used as a temporary parent. The returned HWND is // never destroyed. -UI_BASE_EXPORT HWND GetHiddenWindow(); +COMPONENT_EXPORT(UI_BASE) HWND GetHiddenWindow(); } // namespace ui diff --git a/chromium/ui/base/win/hwnd_metrics.h b/chromium/ui/base/win/hwnd_metrics.h index 22ec6f9c85e..bc171aaebb9 100644 --- a/chromium/ui/base/win/hwnd_metrics.h +++ b/chromium/ui/base/win/hwnd_metrics.h @@ -7,12 +7,12 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // The size, in pixels, of the non-client frame around a window on |monitor|. -UI_BASE_EXPORT int GetFrameThickness(HMONITOR monitor); +COMPONENT_EXPORT(UI_BASE) int GetFrameThickness(HMONITOR monitor); } // namespace ui diff --git a/chromium/ui/base/win/hwnd_subclass.h b/chromium/ui/base/win/hwnd_subclass.h index 56bced1b34d..6628f7b8d68 100644 --- a/chromium/ui/base/win/hwnd_subclass.h +++ b/chromium/ui/base/win/hwnd_subclass.h @@ -10,15 +10,15 @@ #include <memory> #include <vector> +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" #include "ui/base/view_prop.h" namespace ui { // Classes implementing this interface get the opportunity to handle and consume // messages before they are sent to their target HWND. -class UI_BASE_EXPORT HWNDMessageFilter { +class COMPONENT_EXPORT(UI_BASE) HWNDMessageFilter { public: virtual ~HWNDMessageFilter(); @@ -39,7 +39,7 @@ class UI_BASE_EXPORT HWNDMessageFilter { // An object that instance-subclasses a window. If the window has already been // instance-subclassed, that subclassing is lost. -class UI_BASE_EXPORT HWNDSubclass { +class COMPONENT_EXPORT(UI_BASE) HWNDSubclass { public: ~HWNDSubclass(); diff --git a/chromium/ui/base/win/internal_constants.h b/chromium/ui/base/win/internal_constants.h index 65f025f397a..c34541f5cbb 100644 --- a/chromium/ui/base/win/internal_constants.h +++ b/chromium/ui/base/win/internal_constants.h @@ -5,18 +5,19 @@ #ifndef UI_BASE_WIN_INTERNAL_CONSTANTS_H_ #define UI_BASE_WIN_INTERNAL_CONSTANTS_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // This window property if set on the window does not activate the window for a // touch based WM_MOUSEACTIVATE message. -UI_BASE_EXPORT extern const wchar_t kIgnoreTouchMouseActivateForWindow[]; +COMPONENT_EXPORT(UI_BASE) +extern const wchar_t kIgnoreTouchMouseActivateForWindow[]; // This property is put on an HWND so the compositor output knows to treat it // as transparent and draw to it using WS_EX_LAYERED (if using the software // compositor). -UI_BASE_EXPORT extern const wchar_t kWindowTranslucent[]; +COMPONENT_EXPORT(UI_BASE) extern const wchar_t kWindowTranslucent[]; } // namespace ui diff --git a/chromium/ui/base/win/lock_state.h b/chromium/ui/base/win/lock_state.h index 02a7a2d72df..c596b5a2e08 100644 --- a/chromium/ui/base/win/lock_state.h +++ b/chromium/ui/base/win/lock_state.h @@ -5,12 +5,12 @@ #ifndef UI_BASE_WIN_LOCK_STATE_H_ #define UI_BASE_WIN_LOCK_STATE_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Returns true if the screen is currently locked. -UI_BASE_EXPORT bool IsWorkstationLocked(); +COMPONENT_EXPORT(UI_BASE) bool IsWorkstationLocked(); } // namespace ui diff --git a/chromium/ui/base/win/message_box_win.h b/chromium/ui/base/win/message_box_win.h index f48bec3e4fa..f19bb39e6fa 100644 --- a/chromium/ui/base/win/message_box_win.h +++ b/chromium/ui/base/win/message_box_win.h @@ -7,8 +7,8 @@ #include <windows.h> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -16,10 +16,11 @@ namespace ui { // MessageBox function allows us to control certain RTL locale flags so that // callers don't have to worry about adding these flags when running in a // right-to-left locale. -UI_BASE_EXPORT int MessageBox(HWND hwnd, - const base::string16& text, - const base::string16& caption, - UINT flags); +COMPONENT_EXPORT(UI_BASE) +int MessageBox(HWND hwnd, + const base::string16& text, + const base::string16& caption, + UINT flags); } // namespace ui diff --git a/chromium/ui/base/win/mouse_wheel_util.h b/chromium/ui/base/win/mouse_wheel_util.h index b9f5872b0c4..7dc76d2a1f8 100644 --- a/chromium/ui/base/win/mouse_wheel_util.h +++ b/chromium/ui/base/win/mouse_wheel_util.h @@ -7,7 +7,7 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { @@ -17,7 +17,8 @@ class ViewProp; // We reroute the mouse wheel messages to such HWND when they are under the // mouse pointer (but are not the active window). Callers own the returned // object. -UI_BASE_EXPORT ViewProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd); +COMPONENT_EXPORT(UI_BASE) +ViewProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd); // Forwards mouse wheel messages to the window under it. // Windows sends mouse wheel messages to the currently active window. @@ -26,9 +27,8 @@ UI_BASE_EXPORT ViewProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd); // mouse wheel in order to scroll that window. This is arguably a better user // experience. The returns value says whether the mouse wheel message was // successfully redirected. -UI_BASE_EXPORT bool RerouteMouseWheel(HWND window, - WPARAM w_param, - LPARAM l_param); +COMPONENT_EXPORT(UI_BASE) +bool RerouteMouseWheel(HWND window, WPARAM w_param, LPARAM l_param); } // namespace ui diff --git a/chromium/ui/base/win/scoped_ole_initializer.h b/chromium/ui/base/win/scoped_ole_initializer.h index 28085f5f022..c82b1e1ddf7 100644 --- a/chromium/ui/base/win/scoped_ole_initializer.h +++ b/chromium/ui/base/win/scoped_ole_initializer.h @@ -5,14 +5,14 @@ #ifndef UI_BASE_WIN_SCOPED_OLE_INITIALIZER_H_ #define UI_BASE_WIN_SCOPED_OLE_INITIALIZER_H_ +#include "base/component_export.h" #include "base/macros.h" #include "base/threading/thread_checker.h" #include "base/win/windows_types.h" -#include "ui/base/ui_base_export.h" namespace ui { -class UI_BASE_EXPORT ScopedOleInitializer { +class COMPONENT_EXPORT(UI_BASE) ScopedOleInitializer { public: ScopedOleInitializer(); ~ScopedOleInitializer(); diff --git a/chromium/ui/base/win/session_change_observer.h b/chromium/ui/base/win/session_change_observer.h index b2b73f8a351..8ebb68d27d8 100644 --- a/chromium/ui/base/win/session_change_observer.h +++ b/chromium/ui/base/win/session_change_observer.h @@ -8,8 +8,8 @@ #include <windows.h> #include "base/callback.h" +#include "base/component_export.h" #include "base/macros.h" -#include "ui/base/ui_base_export.h" namespace ui { @@ -17,7 +17,7 @@ namespace ui { // managing the tricky business of observing a singleton object. Only // WTS_SESSION_LOCK and WTS_SESSION_UNLOCK events trigger the callback // because those are the only events existing observers handle. -class UI_BASE_EXPORT SessionChangeObserver { +class COMPONENT_EXPORT(UI_BASE) SessionChangeObserver { public: // WPARAM is the wparam passed to the OnWndProc when message is // WM_WTSSESSION_CHANGE. The bool indicates whether the session diff --git a/chromium/ui/base/win/shell.h b/chromium/ui/base/win/shell.h index 5a91276fe65..758c354bb09 100644 --- a/chromium/ui/base/win/shell.h +++ b/chromium/ui/base/win/shell.h @@ -7,8 +7,8 @@ #include <windows.h> +#include "base/component_export.h" #include "base/strings/string16.h" -#include "ui/base/ui_base_export.h" namespace base { class FilePath; @@ -21,7 +21,8 @@ namespace win { // |full_path| does not refer to a folder. // // Note: Must be called on a thread that allows blocking. -UI_BASE_EXPORT bool OpenFolderViaShell(const base::FilePath& full_path); +COMPONENT_EXPORT(UI_BASE) +bool OpenFolderViaShell(const base::FilePath& full_path); // Invokes the default verb on the file specified by |full_path| via the Windows // shell. Usually, the default verb is "open" unless specified otherwise for the @@ -32,53 +33,56 @@ UI_BASE_EXPORT bool OpenFolderViaShell(const base::FilePath& full_path); // |true| on success. // // Note: Must be called on a thread that allows blocking. -UI_BASE_EXPORT bool OpenFileViaShell(const base::FilePath& full_path); +COMPONENT_EXPORT(UI_BASE) +bool OpenFileViaShell(const base::FilePath& full_path); // Disables the ability of the specified window to be pinned to the taskbar or // the Start menu. This will remove "Pin this program to taskbar" from the // taskbar menu of the specified window. -UI_BASE_EXPORT bool PreventWindowFromPinning(HWND hwnd); +COMPONENT_EXPORT(UI_BASE) bool PreventWindowFromPinning(HWND hwnd); // Sets the application id, app icon, relaunch command and relaunch display name // 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::FilePath& app_icon_path, - int app_icon_index, - const base::string16& relaunch_command, - const base::string16& relaunch_display_name, - HWND hwnd); +COMPONENT_EXPORT(UI_BASE) +void SetAppDetailsForWindow(const base::string16& app_id, + const base::FilePath& app_icon_path, + int app_icon_index, + const base::string16& relaunch_command, + const base::string16& relaunch_display_name, + HWND hwnd); // Sets the application id given as the Application Model ID for the window // specified. This method is used to insure that different web applications // do not group together on the Win7 task bar. -UI_BASE_EXPORT void SetAppIdForWindow(const base::string16& app_id, HWND hwnd); +COMPONENT_EXPORT(UI_BASE) +void SetAppIdForWindow(const base::string16& app_id, HWND hwnd); // Sets the application icon for the window specified. -UI_BASE_EXPORT void SetAppIconForWindow(const base::FilePath& app_icon_path, - int app_icon_index, - HWND hwnd); +COMPONENT_EXPORT(UI_BASE) +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. // Windows will use this information for grouping on the taskbar, and to create // a shortcut if the window is pinned to the taskbar. -UI_BASE_EXPORT void SetRelaunchDetailsForWindow( - const base::string16& relaunch_command, - const base::string16& display_name, - HWND hwnd); +COMPONENT_EXPORT(UI_BASE) +void SetRelaunchDetailsForWindow(const base::string16& relaunch_command, + const base::string16& display_name, + HWND hwnd); // Clears the Window Property Store on an HWND. -UI_BASE_EXPORT void ClearWindowPropertyStore(HWND hwnd); +COMPONENT_EXPORT(UI_BASE) void ClearWindowPropertyStore(HWND hwnd); // Returns true if dwm composition is available and turned on on the current // platform. // This method supports a command-line override for testing. -UI_BASE_EXPORT bool IsAeroGlassEnabled(); +COMPONENT_EXPORT(UI_BASE) bool IsAeroGlassEnabled(); // Returns true if dwm composition is available and turned on on the current // platform. -UI_BASE_EXPORT bool IsDwmCompositionEnabled(); +COMPONENT_EXPORT(UI_BASE) bool IsDwmCompositionEnabled(); } // namespace win } // namespace ui diff --git a/chromium/ui/base/win/touch_input.h b/chromium/ui/base/win/touch_input.h index f113ec5b463..83457080a39 100644 --- a/chromium/ui/base/win/touch_input.h +++ b/chromium/ui/base/win/touch_input.h @@ -7,16 +7,17 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // Wrapper for GetTouchInputInfo, which is not defined before Win7. For // earlier OS's, this function returns FALSE. -UI_BASE_EXPORT BOOL GetTouchInputInfoWrapper(HTOUCHINPUT handle, - UINT count, - PTOUCHINPUT pointer, - int size); +COMPONENT_EXPORT(UI_BASE) +BOOL GetTouchInputInfoWrapper(HTOUCHINPUT handle, + UINT count, + PTOUCHINPUT pointer, + int size); } // namespace ui diff --git a/chromium/ui/base/win/window_event_target.h b/chromium/ui/base/win/window_event_target.h index 52cfa8d3ad9..61478cb28dd 100644 --- a/chromium/ui/base/win/window_event_target.h +++ b/chromium/ui/base/win/window_event_target.h @@ -7,14 +7,14 @@ #include <windows.h> -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" namespace ui { // This interface is implemented by classes who get input events forwarded to // them from others. E.g. would be a win32 parent child relationship where the // child forwards input events to the parent after doing minimal processing. -class UI_BASE_EXPORT WindowEventTarget { +class COMPONENT_EXPORT(UI_BASE) WindowEventTarget { public: static const char kWin32InputEventTarget[]; diff --git a/chromium/ui/base/window_open_disposition.h b/chromium/ui/base/window_open_disposition.h index 930024e8300..ef07e966a05 100644 --- a/chromium/ui/base/window_open_disposition.h +++ b/chromium/ui/base/window_open_disposition.h @@ -5,7 +5,7 @@ #ifndef UI_BASE_WINDOW_OPEN_DISPOSITION_H_ #define UI_BASE_WINDOW_OPEN_DISPOSITION_H_ -#include "ui/base/ui_base_export.h" +#include "base/component_export.h" // DEPRECATED: Instead of introducing new references to this enum, use // the generated ui::mojom::WindowOpenDisposition in @@ -41,20 +41,22 @@ namespace ui { // suggest opening in the current tab; for example, a caller could set this to // NEW_FOREGROUND_TAB to prevent a click from overwriting the current tab by // default. -UI_BASE_EXPORT WindowOpenDisposition -DispositionFromClick(bool middle_button, - bool alt_key, - bool ctrl_key, - bool meta_key, - bool shift_key, - WindowOpenDisposition disposition_for_current_tab = - WindowOpenDisposition::CURRENT_TAB); +COMPONENT_EXPORT(UI_BASE) +WindowOpenDisposition DispositionFromClick( + bool middle_button, + bool alt_key, + bool ctrl_key, + bool meta_key, + bool shift_key, + WindowOpenDisposition disposition_for_current_tab = + WindowOpenDisposition::CURRENT_TAB); // As with DispositionFromClick(), but using |event_flags| as in ui::MouseEvent. -UI_BASE_EXPORT WindowOpenDisposition -DispositionFromEventFlags(int event_flags, - WindowOpenDisposition disposition_for_current_tab = - WindowOpenDisposition::CURRENT_TAB); +COMPONENT_EXPORT(UI_BASE) +WindowOpenDisposition DispositionFromEventFlags( + int event_flags, + WindowOpenDisposition disposition_for_current_tab = + WindowOpenDisposition::CURRENT_TAB); } // namespace ui diff --git a/chromium/ui/base/x/BUILD.gn b/chromium/ui/base/x/BUILD.gn index 0daf5090985..2737a66ff79 100644 --- a/chromium/ui/base/x/BUILD.gn +++ b/chromium/ui/base/x/BUILD.gn @@ -15,12 +15,18 @@ jumbo_component("x") { sources = [ "selection_utils.cc", "selection_utils.h", + "x11_cursor.cc", + "x11_cursor.h", + "x11_cursor_factory.cc", + "x11_cursor_factory.h", "x11_desktop_window_move_client.cc", "x11_desktop_window_move_client.h", "x11_display_manager.cc", "x11_display_manager.h", "x11_display_util.cc", "x11_display_util.h", + "x11_error_handler.cc", + "x11_error_handler.h", "x11_menu_list.cc", "x11_menu_list.h", "x11_menu_registrar.cc", @@ -46,7 +52,7 @@ jumbo_component("x") { "x11_workspace_handler.h", ] - if (is_desktop_linux) { + if (is_desktop_linux || is_chromeos) { sources += [ "selection_owner.cc", "selection_owner.h", @@ -59,8 +65,6 @@ jumbo_component("x") { ] } - public_configs = [ "//build/config/linux:xrandr" ] - defines = [ "IS_UI_BASE_X_IMPL" ] deps = [ @@ -72,6 +76,9 @@ jumbo_component("x") { "//ui/base:hit_test", "//ui/base:wm_role_names", "//ui/base/clipboard:clipboard_types", + "//ui/base/cursor:cursor_base", + "//ui/base/cursor:theme_manager", + "//ui/base/cursor/mojom:cursor_type", "//ui/base/dragdrop/file_info", "//ui/display/util", "//ui/events", @@ -80,6 +87,7 @@ jumbo_component("x") { "//ui/events/platform/x11", "//ui/events/x:x", "//ui/gfx", + "//ui/gfx/geometry", "//ui/gfx/x", "//ui/platform_window/common", ] @@ -115,3 +123,14 @@ source_set("test_support") { "//ui/gfx/x", ] } + +source_set("unittests") { + testonly = true + sources = [ "x11_cursor_factory_unittest.cc" ] + deps = [ + ":x", + "//skia", + "//testing/gtest", + "//ui/gfx/geometry", + ] +} diff --git a/chromium/ui/base/x/selection_owner.cc b/chromium/ui/base/x/selection_owner.cc index 76d95fdd45a..755b502b20a 100644 --- a/chromium/ui/base/x/selection_owner.cc +++ b/chromium/ui/base/x/selection_owner.cc @@ -7,11 +7,14 @@ #include <algorithm> #include "base/logging.h" +#include "base/memory/ref_counted_memory.h" #include "ui/base/x/selection_utils.h" +#include "ui/base/x/x11_util.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/events/x/x11_window_event_manager.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -38,152 +41,142 @@ static_assert(KSelectionOwnerTimerPeriodMs <= kIncrementalTransferTimeoutMs, // Returns a conservative max size of the data we can pass into // XChangeProperty(). Copied from GTK. -size_t GetMaxRequestSize(XDisplay* display) { - long extended_max_size = XExtendedMaxRequestSize(display); +size_t GetMaxRequestSize(x11::Connection* connection) { + long extended_max_size = connection->extended_max_request_length(); long max_size = - (extended_max_size ? extended_max_size : XMaxRequestSize(display)) - 100; + (extended_max_size ? extended_max_size + : connection->setup().maximum_request_length) - + 100; return std::min(static_cast<long>(0x40000), std::max(static_cast<long>(0), max_size)); } // Gets the value of an atom pair array property. On success, true is returned // and the value is stored in |value|. -bool GetAtomPairArrayProperty(XID window, - XAtom property, - std::vector<std::pair<XAtom,XAtom> >* value) { - XAtom type = x11::None; - int format = 0; // size in bits of each item in 'property' - unsigned long num_items = 0; - unsigned char* properties = nullptr; - unsigned long remaining_bytes = 0; - - int result = XGetWindowProperty(gfx::GetXDisplay(), window, property, - 0, // offset into property data to - // read - (~0L), // entire array - x11::False, // deleted - AnyPropertyType, &type, &format, &num_items, - &remaining_bytes, &properties); - gfx::XScopedPtr<unsigned char> scoped_properties(properties); - - if (result != x11::Success) +bool GetAtomPairArrayProperty( + x11::Window window, + x11::Atom property, + std::vector<std::pair<x11::Atom, x11::Atom>>* value) { + std::vector<x11::Atom> atoms; + // Since this is an array of atom pairs, ensure ensure |atoms| + // has an element count that's a multiple of 2. + if (!ui::GetArrayProperty(window, property, &atoms) || atoms.size() % 2 != 0) return false; - // GTK does not require |type| to be kAtomPair. - if (format != 32 || num_items % 2 != 0) - return false; - - XAtom* atom_properties = reinterpret_cast<XAtom*>(properties); value->clear(); - for (size_t i = 0; i < num_items; i+=2) - value->push_back(std::make_pair(atom_properties[i], atom_properties[i+1])); + for (size_t i = 0; i < atoms.size(); i += 2) + value->push_back(std::make_pair(atoms[i], atoms[i + 1])); return true; } +x11::Window GetSelectionOwner(x11::Atom selection) { + auto response = x11::Connection::Get()->GetSelectionOwner({selection}).Sync(); + return response ? response->owner : x11::Window::None; +} + +void SetSelectionOwner(x11::Window window, + x11::Atom selection, + x11::Time time = x11::Time::CurrentTime) { + x11::Connection::Get()->SetSelectionOwner({window, selection, time}); +} + } // namespace -SelectionOwner::SelectionOwner(XDisplay* x_display, - XID x_window, - XAtom selection_name) - : x_display_(x_display), - x_window_(x_window), +SelectionOwner::SelectionOwner(x11::Connection* connection, + x11::Window x_window, + x11::Atom selection_name) + : x_window_(x_window), selection_name_(selection_name), - max_request_size_(GetMaxRequestSize(x_display)) {} + max_request_size_(GetMaxRequestSize(connection)) {} SelectionOwner::~SelectionOwner() { // If we are the selection owner, we need to release the selection so we // don't receive further events. However, we don't call ClearSelectionOwner() // because we don't want to do this indiscriminately. - if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) - XSetSelectionOwner(x_display_, selection_name_, x11::None, - x11::CurrentTime); + if (GetSelectionOwner(selection_name_) == x_window_) + SetSelectionOwner(x11::Window::None, selection_name_); } -void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) { +void SelectionOwner::RetrieveTargets(std::vector<x11::Atom>* targets) { for (const auto& format_target : format_map_) targets->push_back(format_target.first); } -void SelectionOwner::TakeOwnershipOfSelection( - const SelectionFormatMap& data) { +void SelectionOwner::TakeOwnershipOfSelection(const SelectionFormatMap& data) { acquired_selection_timestamp_ = X11EventSource::GetInstance()->GetTimestamp(); - XSetSelectionOwner(x_display_, selection_name_, x_window_, - acquired_selection_timestamp_); + SetSelectionOwner(x_window_, selection_name_, + static_cast<x11::Time>(acquired_selection_timestamp_)); - if (XGetSelectionOwner(x_display_, selection_name_) == x_window_) { + if (GetSelectionOwner(selection_name_) == x_window_) { // The X server agrees that we are the selection owner. Commit our data. format_map_ = data; } } void SelectionOwner::ClearSelectionOwner() { - XSetSelectionOwner(x_display_, selection_name_, x11::None, x11::CurrentTime); + SetSelectionOwner(x11::Window::None, selection_name_); format_map_ = SelectionFormatMap(); } -void SelectionOwner::OnSelectionRequest(const XEvent& event) { - XID requestor = event.xselectionrequest.requestor; - XAtom requested_target = event.xselectionrequest.target; - XAtom requested_property = event.xselectionrequest.property; +void SelectionOwner::OnSelectionRequest(const x11::Event& x11_event) { + auto& request = *x11_event.As<x11::SelectionRequestEvent>(); + auto requestor = request.requestor; + x11::Atom requested_target = request.target; + x11::Atom requested_property = request.property; // Incrementally build our selection. By default this is a refusal, and we'll // override the parts indicating success in the different cases. - XEvent reply; - reply.xselection.type = SelectionNotify; - reply.xselection.requestor = requestor; - reply.xselection.selection = event.xselectionrequest.selection; - reply.xselection.target = requested_target; - reply.xselection.property = x11::None; // Indicates failure - reply.xselection.time = event.xselectionrequest.time; + x11::SelectionNotifyEvent reply{ + .time = request.time, + .requestor = requestor, + .selection = request.selection, + .target = requested_target, + .property = x11::Atom::None, // Indicates failure + }; if (requested_target == gfx::GetAtom(kMultiple)) { // The contents of |requested_property| should be a list of // <target,property> pairs. - std::vector<std::pair<XAtom,XAtom> > conversions; - if (GetAtomPairArrayProperty(requestor, - requested_property, - &conversions)) { - std::vector<XAtom> conversion_results; - for (const std::pair<XAtom, XAtom>& conversion : conversions) { + std::vector<std::pair<x11::Atom, x11::Atom>> conversions; + if (GetAtomPairArrayProperty(requestor, requested_property, &conversions)) { + std::vector<x11::Atom> conversion_results; + for (const std::pair<x11::Atom, x11::Atom>& conversion : conversions) { bool conversion_successful = ProcessTarget(conversion.first, requestor, conversion.second); conversion_results.push_back(conversion.first); conversion_results.push_back(conversion_successful ? conversion.second - : x11::None); + : x11::Atom::None); } // Set the property to indicate which conversions succeeded. This matches // what GTK does. - XChangeProperty( - x_display_, requestor, requested_property, gfx::GetAtom(kAtomPair), - 32, PropModeReplace, - reinterpret_cast<const unsigned char*>(&conversion_results.front()), - conversion_results.size()); + ui::SetArrayProperty(requestor, requested_property, + gfx::GetAtom(kAtomPair), conversion_results); - reply.xselection.property = requested_property; + reply.property = requested_property; } } else { if (ProcessTarget(requested_target, requestor, requested_property)) - reply.xselection.property = requested_property; + reply.property = requested_property; } // Send off the reply. - XSendEvent(x_display_, requestor, x11::False, 0, &reply); + ui::SendEvent(reply, requestor, x11::EventMask::NoEvent); } -void SelectionOwner::OnSelectionClear(const XEvent& event) { +void SelectionOwner::OnSelectionClear(const x11::Event& event) { DLOG(ERROR) << "SelectionClear"; // TODO(erg): If we receive a SelectionClear event while we're handling data, // we need to delay clearing. } -bool SelectionOwner::CanDispatchPropertyEvent(const XEvent& event) { - return event.xproperty.state == PropertyDelete && +bool SelectionOwner::CanDispatchPropertyEvent(const x11::Event& event) { + return event.As<x11::PropertyNotifyEvent>()->state == x11::Property::Delete && FindIncrementalTransferForEvent(event) != incremental_transfers_.end(); } -void SelectionOwner::OnPropertyEvent(const XEvent& event) { +void SelectionOwner::OnPropertyEvent(const x11::Event& event) { auto it = FindIncrementalTransferForEvent(event); if (it == incremental_transfers_.end()) return; @@ -193,35 +186,31 @@ void SelectionOwner::OnPropertyEvent(const XEvent& event) { CompleteIncrementalTransfer(it); } -bool SelectionOwner::ProcessTarget(XAtom target, - XID requestor, - XAtom property) { - XAtom multiple_atom = gfx::GetAtom(kMultiple); - XAtom save_targets_atom = gfx::GetAtom(kSaveTargets); - XAtom targets_atom = gfx::GetAtom(kTargets); - XAtom timestamp_atom = gfx::GetAtom(kTimestamp); +bool SelectionOwner::ProcessTarget(x11::Atom target, + x11::Window requestor, + x11::Atom property) { + x11::Atom multiple_atom = gfx::GetAtom(kMultiple); + x11::Atom save_targets_atom = gfx::GetAtom(kSaveTargets); + x11::Atom targets_atom = gfx::GetAtom(kTargets); + x11::Atom timestamp_atom = gfx::GetAtom(kTimestamp); if (target == multiple_atom || target == save_targets_atom) return false; if (target == timestamp_atom) { - XChangeProperty( - x_display_, requestor, property, XA_INTEGER, 32, PropModeReplace, - reinterpret_cast<unsigned char*>(&acquired_selection_timestamp_), 1); + ui::SetProperty(requestor, property, x11::Atom::INTEGER, + acquired_selection_timestamp_); return true; } if (target == targets_atom) { // We have been asked for TARGETS. Send an atom array back with the data // types we support. - std::vector<XAtom> targets = {timestamp_atom, targets_atom, - save_targets_atom, multiple_atom}; + std::vector<x11::Atom> targets = {timestamp_atom, targets_atom, + save_targets_atom, multiple_atom}; RetrieveTargets(&targets); - XChangeProperty(x_display_, requestor, property, XA_ATOM, 32, - PropModeReplace, - reinterpret_cast<unsigned char*>(&targets.front()), - targets.size()); + ui::SetArrayProperty(requestor, property, x11::Atom::ATOM, targets); return true; } @@ -232,10 +221,8 @@ bool SelectionOwner::ProcessTarget(XAtom target, // We must send the data back in several chunks due to a limitation in // the size of X requests. Notify the selection requestor that the data // will be sent incrementally by returning data of type "INCR". - long length = it->second->size(); - XChangeProperty(x_display_, requestor, property, gfx::GetAtom(kIncr), 32, - PropModeReplace, - reinterpret_cast<unsigned char*>(&length), 1); + uint32_t length = it->second->size(); + ui::SetProperty(requestor, property, gfx::GetAtom(kIncr), length); // Wait for the selection requestor to indicate that it has processed // the selection result before sending the first chunk of data. The @@ -243,10 +230,10 @@ bool SelectionOwner::ProcessTarget(XAtom target, base::TimeTicks timeout = base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs); - incremental_transfers_.push_back(IncrementalTransfer( + incremental_transfers_.emplace_back( requestor, target, property, std::make_unique<XScopedEventSelector>(requestor, PropertyChangeMask), - it->second, 0, timeout)); + it->second, 0, timeout); // Start a timer to abort the data transfer in case that the selection // requestor does not support the INCR property or gets destroyed during @@ -258,15 +245,9 @@ bool SelectionOwner::ProcessTarget(XAtom target, this, &SelectionOwner::AbortStaleIncrementalTransfers); } } else { - XChangeProperty( - x_display_, - requestor, - property, - target, - 8, - PropModeReplace, - const_cast<unsigned char*>(it->second->front()), - it->second->size()); + auto& mem = it->second; + std::vector<uint8_t> data(mem->data(), mem->data() + mem->size()); + ui::SetArrayProperty(requestor, property, target, data); } return true; } @@ -279,17 +260,13 @@ bool SelectionOwner::ProcessTarget(XAtom target, void SelectionOwner::ProcessIncrementalTransfer(IncrementalTransfer* transfer) { size_t remaining = transfer->data->size() - transfer->offset; size_t chunk_length = std::min(remaining, max_request_size_); - XChangeProperty( - x_display_, - transfer->window, - transfer->property, - transfer->target, - 8, - PropModeReplace, - const_cast<unsigned char*>(transfer->data->front() + transfer->offset), - chunk_length); + const uint8_t* data = transfer->data->front() + transfer->offset; + std::vector<uint8_t> buf(data, data + chunk_length); + ui::SetArrayProperty(transfer->window, transfer->property, transfer->target, + buf); transfer->offset += chunk_length; - transfer->timeout = base::TimeTicks::Now() + + transfer->timeout = + base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(kIncrementalTransferTimeoutMs); // When offset == data->size(), we still need to transfer a zero-sized chunk @@ -302,8 +279,8 @@ void SelectionOwner::ProcessIncrementalTransfer(IncrementalTransfer* transfer) { void SelectionOwner::AbortStaleIncrementalTransfers() { base::TimeTicks now = base::TimeTicks::Now(); - for (int i = static_cast<int>(incremental_transfers_.size()) - 1; - i >= 0; --i) { + for (int i = static_cast<int>(incremental_transfers_.size()) - 1; i >= 0; + --i) { if (incremental_transfers_[i].timeout <= now) CompleteIncrementalTransfer(incremental_transfers_.begin() + i); } @@ -318,21 +295,20 @@ void SelectionOwner::CompleteIncrementalTransfer( } std::vector<SelectionOwner::IncrementalTransfer>::iterator - SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) { +SelectionOwner::FindIncrementalTransferForEvent(const x11::Event& event) { for (auto it = incremental_transfers_.begin(); it != incremental_transfers_.end(); ++it) { - if (it->window == event.xproperty.window && - it->property == event.xproperty.atom) { + const auto* prop = event.As<x11::PropertyNotifyEvent>(); + if (it->window == prop->window && it->property == prop->atom) return it; - } } return incremental_transfers_.end(); } SelectionOwner::IncrementalTransfer::IncrementalTransfer( - XID window, - XAtom target, - XAtom property, + x11::Window window, + x11::Atom target, + x11::Atom property, std::unique_ptr<XScopedEventSelector> event_selector, const scoped_refptr<base::RefCountedMemory>& data, int offset, @@ -348,10 +324,9 @@ SelectionOwner::IncrementalTransfer::IncrementalTransfer( SelectionOwner::IncrementalTransfer::IncrementalTransfer( IncrementalTransfer&& other) = default; -SelectionOwner::IncrementalTransfer& SelectionOwner::IncrementalTransfer:: -operator=(IncrementalTransfer&&) = default; +SelectionOwner::IncrementalTransfer& +SelectionOwner::IncrementalTransfer::operator=(IncrementalTransfer&&) = default; -SelectionOwner::IncrementalTransfer::~IncrementalTransfer() { -} +SelectionOwner::IncrementalTransfer::~IncrementalTransfer() = default; } // namespace ui diff --git a/chromium/ui/base/x/selection_owner.h b/chromium/ui/base/x/selection_owner.h index a048133b9dd..0c715bd53d0 100644 --- a/chromium/ui/base/x/selection_owner.h +++ b/chromium/ui/base/x/selection_owner.h @@ -16,6 +16,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "ui/base/x/selection_utils.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11_types.h" namespace ui { @@ -33,16 +34,16 @@ COMPONENT_EXPORT(UI_BASE_X) extern const char kTargets[]; // processes. class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner { public: - SelectionOwner(XDisplay* xdisplay, - XID xwindow, - XAtom selection_name); + SelectionOwner(x11::Connection* connection, + x11::Window xwindow, + x11::Atom selection_name); ~SelectionOwner(); // Returns the current selection data. Useful for fast paths. const SelectionFormatMap& selection_format_map() { return format_map_; } // Appends a list of types we're offering to |targets|. - void RetrieveTargets(std::vector<XAtom>* targets); + void RetrieveTargets(std::vector<x11::Atom>* targets); // Attempts to take ownership of the selection. If we're successful, present // |data| to other windows. @@ -53,21 +54,21 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner { void ClearSelectionOwner(); // It is our owner's responsibility to plumb X11 events on |xwindow_| to us. - void OnSelectionRequest(const XEvent& event); - void OnSelectionClear(const XEvent& event); + void OnSelectionRequest(const x11::Event& event); + void OnSelectionClear(const x11::Event& event); // Returns true if SelectionOwner can process the XPropertyEvent event, // |event|. - bool CanDispatchPropertyEvent(const XEvent& event); + bool CanDispatchPropertyEvent(const x11::Event& event); - void OnPropertyEvent(const XEvent& event); + void OnPropertyEvent(const x11::Event& event); private: // Holds state related to an incremental data transfer. struct IncrementalTransfer { - IncrementalTransfer(XID window, - XAtom target, - XAtom property, + IncrementalTransfer(x11::Window window, + x11::Atom target, + x11::Atom property, std::unique_ptr<XScopedEventSelector> event_selector, const scoped_refptr<base::RefCountedMemory>& data, int offset, @@ -80,9 +81,9 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner { // Parameters from the XSelectionRequest. The data is transferred over // |property| on |window|. - XID window; - XAtom target; - XAtom property; + x11::Window window; + x11::Atom target; + x11::Atom property; // Selects events on |window|. std::unique_ptr<XScopedEventSelector> event_selector; @@ -105,7 +106,9 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner { // Attempts to convert the selection to |target|. If the conversion is // successful, true is returned and the result is stored in the |property| // of |requestor|. - bool ProcessTarget(XAtom target, XID requestor, XAtom property); + bool ProcessTarget(x11::Atom target, + x11::Window requestor, + x11::Atom property); // Sends the next chunk of data for given the incremental data transfer. void ProcessIncrementalTransfer(IncrementalTransfer* transfer); @@ -120,17 +123,16 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionOwner { // Returns the incremental data transfer, if any, which was waiting for // |event|. std::vector<IncrementalTransfer>::iterator FindIncrementalTransferForEvent( - const XEvent& event); + const x11::Event& event); // Our X11 state. - XDisplay* x_display_; - XID x_window_; + x11::Window x_window_; // The X11 selection that this instance communicates on. - XAtom selection_name_; + x11::Atom selection_name_; // The time that this instance took ownership of its selection. - Time acquired_selection_timestamp_; + uint32_t acquired_selection_timestamp_; // The maximum size of data we can put in XChangeProperty(). size_t max_request_size_; diff --git a/chromium/ui/base/x/selection_requestor.cc b/chromium/ui/base/x/selection_requestor.cc index c94e955d363..3e2173b4498 100644 --- a/chromium/ui/base/x/selection_requestor.cc +++ b/chromium/ui/base/x/selection_requestor.cc @@ -6,15 +6,16 @@ #include <algorithm> +#include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" #include "ui/base/x/selection_owner.h" #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" #include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/x11/x11_event_source.h" -#include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_types.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -32,46 +33,40 @@ const int kRequestTimeoutMs = 10000; static_assert(KSelectionRequestorTimerPeriodMs <= kRequestTimeoutMs, "timer period must be <= request timeout"); -// Combines |data| into a single RefCountedMemory object. -scoped_refptr<base::RefCountedMemory> CombineRefCountedMemory( - const std::vector<scoped_refptr<base::RefCountedMemory> >& data) { +// Combines |data| into a single std::vector<uint8_t>. +std::vector<uint8_t> CombineData( + const std::vector<std::vector<uint8_t>>& data) { if (data.size() == 1u) return data[0]; - size_t combined_length = 0; + size_t bytes = 0; for (const auto& datum : data) - combined_length += datum->size(); - std::vector<unsigned char> combined_data; - combined_data.reserve(combined_length); - - for (const auto& datum : data) { - combined_data.insert(combined_data.end(), datum->front(), - datum->front() + datum->size()); - } - return base::RefCountedBytes::TakeVector(&combined_data); + bytes += datum.size(); + std::vector<uint8_t> combined; + combined.reserve(bytes); + for (const auto& datum : data) + std::copy(datum.begin(), datum.end(), std::back_inserter(combined)); + return combined; } } // namespace -SelectionRequestor::SelectionRequestor(XDisplay* x_display, - XID x_window, +SelectionRequestor::SelectionRequestor(x11::Window x_window, XEventDispatcher* dispatcher) - : x_display_(x_display), - x_window_(x_window), - x_property_(x11::None), + : x_window_(x_window), + x_property_(x11::Atom::None), dispatcher_(dispatcher), current_request_index_(0u) { x_property_ = gfx::GetAtom(kChromeSelection); } -SelectionRequestor::~SelectionRequestor() {} +SelectionRequestor::~SelectionRequestor() = default; bool SelectionRequestor::PerformBlockingConvertSelection( - XAtom selection, - XAtom target, - scoped_refptr<base::RefCountedMemory>* out_data, - size_t* out_data_items, - XAtom* out_type) { + x11::Atom selection, + x11::Atom target, + std::vector<uint8_t>* out_data, + x11::Atom* out_type) { base::TimeTicks timeout = base::TimeTicks::Now() + base::TimeDelta::FromMilliseconds(kRequestTimeoutMs); @@ -94,9 +89,7 @@ bool SelectionRequestor::PerformBlockingConvertSelection( if (request.success) { if (out_data) - *out_data = CombineRefCountedMemory(request.out_data); - if (out_data_items) - *out_data_items = request.out_data_items; + *out_data = CombineData(request.out_data); if (out_type) *out_type = request.out_type; } @@ -104,109 +97,100 @@ bool SelectionRequestor::PerformBlockingConvertSelection( } void SelectionRequestor::PerformBlockingConvertSelectionWithParameter( - XAtom selection, - XAtom target, - const std::vector<XAtom>& parameter) { + x11::Atom selection, + x11::Atom target, + const std::vector<x11::Atom>& parameter) { SetAtomArrayProperty(x_window_, kChromeSelection, "ATOM", parameter); - PerformBlockingConvertSelection(selection, target, nullptr, nullptr, nullptr); + PerformBlockingConvertSelection(selection, target, nullptr, nullptr); } SelectionData SelectionRequestor::RequestAndWaitForTypes( - XAtom selection, - const std::vector<XAtom>& types) { - for (const XAtom& item : types) { - scoped_refptr<base::RefCountedMemory> data; - XAtom type = x11::None; - if (PerformBlockingConvertSelection(selection, item, &data, nullptr, - &type) && type == item) { - return SelectionData(type, data); + x11::Atom selection, + const std::vector<x11::Atom>& types) { + for (const x11::Atom& item : types) { + std::vector<uint8_t> data; + x11::Atom type = x11::Atom::None; + if (PerformBlockingConvertSelection(selection, item, &data, &type) && + type == item) { + return SelectionData(type, base::RefCountedBytes::TakeVector(&data)); } } return SelectionData(); } -void SelectionRequestor::OnSelectionNotify(const XEvent& event) { +void SelectionRequestor::OnSelectionNotify( + const x11::SelectionNotifyEvent& selection) { Request* request = GetCurrentRequest(); - XAtom event_property = event.xselection.property; - if (!request || - request->completed || - request->selection != event.xselection.selection || - request->target != event.xselection.target) { + x11::Atom event_property = selection.property; + if (!request || request->completed || + request->selection != selection.selection || + request->target != selection.target) { // ICCCM requires us to delete the property passed into SelectionNotify. - if (event_property != x11::None) - XDeleteProperty(x_display_, x_window_, event_property); + if (event_property != x11::Atom::None) + ui::DeleteProperty(x_window_, event_property); return; } bool success = false; if (event_property == x_property_) { - scoped_refptr<base::RefCountedMemory> out_data; - success = ui::GetRawBytesOfProperty(x_window_, - x_property_, - &out_data, - &request->out_data_items, + std::vector<uint8_t> out_data; + success = ui::GetRawBytesOfProperty(x_window_, x_property_, &out_data, &request->out_type); if (success) { request->out_data.clear(); request->out_data.push_back(out_data); } } - if (event_property != x11::None) - XDeleteProperty(x_display_, x_window_, event_property); + if (event_property != x11::Atom::None) + ui::DeleteProperty(x_window_, event_property); if (request->out_type == gfx::GetAtom(kIncr)) { request->data_sent_incrementally = true; request->out_data.clear(); - request->out_data_items = 0u; - request->out_type = x11::None; + request->out_type = x11::Atom::None; request->timeout = base::TimeTicks::Now() + - base::TimeDelta::FromMilliseconds(kRequestTimeoutMs); + base::TimeDelta::FromMilliseconds(kRequestTimeoutMs); } else { CompleteRequest(current_request_index_, success); } } -bool SelectionRequestor::CanDispatchPropertyEvent(const XEvent& event) { - return event.xproperty.window == x_window_ && - event.xproperty.atom == x_property_ && - event.xproperty.state == PropertyNewValue; +bool SelectionRequestor::CanDispatchPropertyEvent(const x11::Event& event) { + const auto* prop = event.As<x11::PropertyNotifyEvent>(); + return prop->window == x_window_ && prop->atom == x_property_ && + prop->state == x11::Property::NewValue; } -void SelectionRequestor::OnPropertyEvent(const XEvent& event) { +void SelectionRequestor::OnPropertyEvent(const x11::Event& event) { Request* request = GetCurrentRequest(); if (!request || !request->data_sent_incrementally) return; - scoped_refptr<base::RefCountedMemory> out_data; - size_t out_data_items = 0u; - Atom out_type = x11::None; - bool success = ui::GetRawBytesOfProperty(x_window_, - x_property_, - &out_data, - &out_data_items, - &out_type); + std::vector<uint8_t> out_data; + x11::Atom out_type = x11::Atom::None; + bool success = + ui::GetRawBytesOfProperty(x_window_, x_property_, &out_data, &out_type); if (!success) { CompleteRequest(current_request_index_, false); return; } - if (request->out_type != x11::None && request->out_type != out_type) { + if (request->out_type != x11::Atom::None && request->out_type != out_type) { CompleteRequest(current_request_index_, false); return; } request->out_data.push_back(out_data); - request->out_data_items += out_data_items; request->out_type = out_type; // Delete the property to tell the selection owner to send the next chunk. - XDeleteProperty(x_display_, x_window_, x_property_); + ui::DeleteProperty(x_window_, x_property_); request->timeout = base::TimeTicks::Now() + - base::TimeDelta::FromMilliseconds(kRequestTimeoutMs); + base::TimeDelta::FromMilliseconds(kRequestTimeoutMs); - if (out_data->size() == 0u) + if (out_data.empty()) CompleteRequest(current_request_index_, true); } @@ -219,8 +203,8 @@ void SelectionRequestor::AbortStaleRequests() { } void SelectionRequestor::CompleteRequest(size_t index, bool success) { - if (index >= requests_.size()) - return; + if (index >= requests_.size()) + return; Request* request = requests_[index]; if (request->completed) @@ -241,8 +225,13 @@ void SelectionRequestor::CompleteRequest(size_t index, bool success) { void SelectionRequestor::ConvertSelectionForCurrentRequest() { Request* request = GetCurrentRequest(); if (request) { - XConvertSelection(x_display_, request->selection, request->target, - x_property_, x_window_, x11::CurrentTime); + x11::Connection::Get()->ConvertSelection({ + .requestor = static_cast<x11::Window>(x_window_), + .selection = request->selection, + .target = request->target, + .property = x_property_, + .time = x11::Time::CurrentTime, + }); } } @@ -266,11 +255,14 @@ void SelectionRequestor::BlockTillSelectionNotifyForRequest(Request* request) { } else { // This occurs if PerformBlockingConvertSelection() is called during // shutdown and the X11EventSource has already been destroyed. - while (!request->completed && - request->timeout > base::TimeTicks::Now()) { - if (XPending(x_display_)) { - XEvent event; - XNextEvent(x_display_, &event); + auto* conn = x11::Connection::Get(); + auto& events = conn->events(); + while (!request->completed && request->timeout > base::TimeTicks::Now()) { + conn->Flush(); + conn->ReadResponses(); + if (!conn->events().empty()) { + x11::Event event = std::move(events.front()); + events.pop_front(); dispatcher_->DispatchXEvent(&event); } } @@ -283,19 +275,17 @@ SelectionRequestor::Request* SelectionRequestor::GetCurrentRequest() { : requests_[current_request_index_]; } -SelectionRequestor::Request::Request(XAtom selection, - XAtom target, +SelectionRequestor::Request::Request(x11::Atom selection, + x11::Atom target, base::TimeTicks timeout) : selection(selection), target(target), data_sent_incrementally(false), - out_data_items(0u), - out_type(x11::None), + out_type(x11::Atom::None), success(false), timeout(timeout), completed(false) {} -SelectionRequestor::Request::~Request() { -} +SelectionRequestor::Request::~Request() = default; } // namespace ui diff --git a/chromium/ui/base/x/selection_requestor.h b/chromium/ui/base/x/selection_requestor.h index aa5f7a14b3b..9b97d24ff58 100644 --- a/chromium/ui/base/x/selection_requestor.h +++ b/chromium/ui/base/x/selection_requestor.h @@ -10,12 +10,14 @@ #include <vector> #include "base/callback.h" +#include "base/component_export.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "ui/base/ui_base_export.h" #include "ui/events/platform_event.h" +#include "ui/gfx/x/event.h" +#include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_types.h" namespace ui { @@ -29,67 +31,62 @@ class SelectionData; // drop. This class interprets messages from the stateful selection request // API. SelectionRequestor should only deal with the X11 details; it does not // implement per-component fast-paths. -class UI_BASE_EXPORT SelectionRequestor { +class COMPONENT_EXPORT(UI_BASE) SelectionRequestor { public: - SelectionRequestor(XDisplay* xdisplay, - XID xwindow, - XEventDispatcher* dispatcher); + SelectionRequestor(x11::Window xwindow, XEventDispatcher* dispatcher); ~SelectionRequestor(); // Does the work of requesting |target| from |selection|, spinning up the // nested run loop, and reading the resulting data back. The result is // stored in |out_data|. // |out_data_items| is the length of |out_data| in |out_type| items. - bool PerformBlockingConvertSelection( - XAtom selection, - XAtom target, - scoped_refptr<base::RefCountedMemory>* out_data, - size_t* out_data_items, - XAtom* out_type); + bool PerformBlockingConvertSelection(x11::Atom selection, + x11::Atom target, + std::vector<uint8_t>* out_data, + x11::Atom* out_type); // Requests |target| from |selection|, passing |parameter| as a parameter to // XConvertSelection(). void PerformBlockingConvertSelectionWithParameter( - XAtom selection, - XAtom target, - const std::vector<XAtom>& parameter); + x11::Atom selection, + x11::Atom target, + const std::vector<x11::Atom>& parameter); // Returns the first of |types| offered by the current owner of |selection|. // Returns an empty SelectionData object if none of |types| are available. - SelectionData RequestAndWaitForTypes(XAtom selection, - const std::vector<XAtom>& types); + SelectionData RequestAndWaitForTypes(x11::Atom selection, + const std::vector<x11::Atom>& types); // It is our owner's responsibility to plumb X11 SelectionNotify events on // |xwindow_| to us. - void OnSelectionNotify(const XEvent& event); + void OnSelectionNotify(const x11::SelectionNotifyEvent& event); // Returns true if SelectionOwner can process the XChangeProperty event, // |event|. - bool CanDispatchPropertyEvent(const XEvent& event); + bool CanDispatchPropertyEvent(const x11::Event& event); - void OnPropertyEvent(const XEvent& event); + void OnPropertyEvent(const x11::Event& event); private: friend class SelectionRequestorTest; // A request that has been issued. struct Request { - Request(XAtom selection, XAtom target, base::TimeTicks timeout); + Request(x11::Atom selection, x11::Atom target, base::TimeTicks timeout); ~Request(); // The target and selection requested in the XConvertSelection() request. // Used for error detection. - XAtom selection; - XAtom target; + x11::Atom selection; + x11::Atom target; // Whether the result of the XConvertSelection() request is being sent // incrementally. bool data_sent_incrementally; // The result data for the XConvertSelection() request. - std::vector<scoped_refptr<base::RefCountedMemory> > out_data; - size_t out_data_items; - XAtom out_type; + std::vector<std::vector<uint8_t>> out_data; + x11::Atom out_type; // Whether the XConvertSelection() request was successful. bool success; @@ -122,12 +119,11 @@ class UI_BASE_EXPORT SelectionRequestor { Request* GetCurrentRequest(); // Our X11 state. - XDisplay* x_display_; - XID x_window_; + x11::Window x_window_; // The property on |x_window_| set by the selection owner with the value of // the selection. - XAtom x_property_; + x11::Atom x_property_; // Dispatcher which handles SelectionNotify and SelectionRequest for // |selection_name_|. PerformBlockingConvertSelection() calls the diff --git a/chromium/ui/base/x/selection_requestor_unittest.cc b/chromium/ui/base/x/selection_requestor_unittest.cc index f4d547e2668..ac538ae6d25 100644 --- a/chromium/ui/base/x/selection_requestor_unittest.cc +++ b/chromium/ui/base/x/selection_requestor_unittest.cc @@ -5,6 +5,8 @@ #include "ui/base/x/selection_requestor.h" #include <stddef.h> +#include <xcb/xcb.h> + #include <memory> #include "base/bind.h" @@ -17,40 +19,44 @@ #include "ui/base/x/selection_utils.h" #include "ui/base/x/x11_util.h" #include "ui/events/platform/platform_event_source.h" +#include "ui/gfx/x/connection.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_types.h" +#include "ui/gfx/x/xproto.h" namespace ui { class SelectionRequestorTest : public testing::Test { public: - SelectionRequestorTest() - : x_display_(gfx::GetXDisplay()), x_window_(x11::None) {} + SelectionRequestorTest() : x_display_(gfx::GetXDisplay()) {} - ~SelectionRequestorTest() override {} + ~SelectionRequestorTest() override = default; // Responds to the SelectionRequestor's XConvertSelection() request by // - Setting the property passed into the XConvertSelection() request to // |value|. // - Sending a SelectionNotify event. - void SendSelectionNotify(XAtom selection, - XAtom target, + void SendSelectionNotify(x11::Atom selection, + x11::Atom target, const std::string& value) { ui::SetStringProperty(x_window_, requestor_->x_property_, gfx::GetAtom("STRING"), value); - XEvent xev; - xev.type = SelectionNotify; - xev.xselection.serial = 0u; - xev.xselection.display = x_display_; - xev.xselection.requestor = x_window_; - xev.xselection.selection = selection; - xev.xselection.target = target; - xev.xselection.property = requestor_->x_property_; - xev.xselection.time = x11::CurrentTime; - xev.xselection.type = SelectionNotify; - requestor_->OnSelectionNotify(xev); + xcb_generic_event_t ge; + memset(&ge, 0, sizeof(ge)); + auto* event = reinterpret_cast<xcb_selection_notify_event_t*>(&ge); + event->response_type = x11::SelectionNotifyEvent::opcode; + event->sequence = 0; + event->requestor = static_cast<uint32_t>(x_window_); + event->selection = static_cast<uint32_t>(selection); + event->target = static_cast<uint32_t>(target); + event->property = static_cast<uint32_t>(requestor_->x_property_); + event->time = x11::CurrentTime; + + x11::Event xev(&ge, x11::Connection::Get()); + requestor_->OnSelectionNotify(*xev.As<x11::SelectionNotifyEvent>()); } protected: @@ -59,33 +65,31 @@ class SelectionRequestorTest : public testing::Test { XSynchronize(x_display_, x11::True); // Create a window for the selection requestor to use. - x_window_ = XCreateWindow(x_display_, - DefaultRootWindow(x_display_), - 0, 0, 10, 10, // x, y, width, height - 0, // border width - CopyFromParent, // depth - InputOnly, - CopyFromParent, // visual - 0, - nullptr); + x_window_ = static_cast<x11::Window>(XCreateWindow( + x_display_, DefaultRootWindow(x_display_), 0, 0, 10, + 10, // x, y, width, height + 0, // border width + static_cast<int>(x11::WindowClass::CopyFromParent), // depth + static_cast<int>(x11::WindowClass::InputOnly), + nullptr, // visual + 0, nullptr)); event_source_ = PlatformEventSource::CreateDefault(); CHECK(PlatformEventSource::GetInstance()); - requestor_ = - std::make_unique<SelectionRequestor>(x_display_, x_window_, nullptr); + requestor_ = std::make_unique<SelectionRequestor>(x_window_, nullptr); } void TearDown() override { requestor_.reset(); event_source_.reset(); - XDestroyWindow(x_display_, x_window_); + XDestroyWindow(x_display_, static_cast<uint32_t>(x_window_)); XSynchronize(x_display_, x11::False); } Display* x_display_; // |requestor_|'s window. - XID x_window_; + x11::Window x_window_ = x11::Window::None; std::unique_ptr<PlatformEventSource> event_source_; std::unique_ptr<SelectionRequestor> requestor_; @@ -101,16 +105,16 @@ namespace { // Converts |selection| to |target| and checks the returned values. void PerformBlockingConvertSelection(SelectionRequestor* requestor, - XAtom selection, - XAtom target, + x11::Atom selection, + x11::Atom target, const std::string& expected_data) { - scoped_refptr<base::RefCountedMemory> out_data; - size_t out_data_items = 0u; - XAtom out_type = x11::None; - EXPECT_TRUE(requestor->PerformBlockingConvertSelection( - selection, target, &out_data, &out_data_items, &out_type)); - EXPECT_EQ(expected_data, ui::RefCountedMemoryToString(out_data)); - EXPECT_EQ(expected_data.size(), out_data_items); + std::vector<uint8_t> out_data; + x11::Atom out_type = x11::Atom::None; + EXPECT_TRUE(requestor->PerformBlockingConvertSelection(selection, target, + &out_data, &out_type)); + EXPECT_EQ(expected_data.size(), out_data.size()); + EXPECT_EQ(expected_data, ui::RefCountedMemoryToString( + base::RefCountedBytes::TakeVector(&out_data))); EXPECT_EQ(gfx::GetAtom("STRING"), out_type); } @@ -122,10 +126,10 @@ TEST_F(SelectionRequestorTest, NestedRequests) { // Assume that |selection| will have no owner. If there is an owner, the owner // will set the property passed into the XConvertSelection() request which is // undesirable. - XAtom selection = gfx::GetAtom("FAKE_SELECTION"); + x11::Atom selection = gfx::GetAtom("FAKE_SELECTION"); - XAtom target1 = gfx::GetAtom("TARGET1"); - XAtom target2 = gfx::GetAtom("TARGET2"); + x11::Atom target1 = gfx::GetAtom("TARGET1"); + x11::Atom target2 = gfx::GetAtom("TARGET2"); base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PerformBlockingConvertSelection, diff --git a/chromium/ui/base/x/selection_utils.cc b/chromium/ui/base/x/selection_utils.cc index a5eaa7443e0..34533b97d69 100644 --- a/chromium/ui/base/x/selection_utils.cc +++ b/chromium/ui/base/x/selection_utils.cc @@ -25,8 +25,8 @@ const char kTextPlain[] = "text/plain"; const char kTextPlainUtf8[] = "text/plain;charset=utf-8"; const char kUtf8String[] = "UTF8_STRING"; -std::vector<::Atom> GetTextAtomsFrom() { - std::vector< ::Atom> atoms; +std::vector<x11::Atom> GetTextAtomsFrom() { + std::vector<x11::Atom> atoms; atoms.push_back(gfx::GetAtom(kUtf8String)); atoms.push_back(gfx::GetAtom(kString)); atoms.push_back(gfx::GetAtom(kText)); @@ -35,22 +35,22 @@ std::vector<::Atom> GetTextAtomsFrom() { return atoms; } -std::vector<::Atom> GetURLAtomsFrom() { - std::vector< ::Atom> atoms; +std::vector<x11::Atom> GetURLAtomsFrom() { + std::vector<x11::Atom> atoms; atoms.push_back(gfx::GetAtom(kMimeTypeURIList)); atoms.push_back(gfx::GetAtom(kMimeTypeMozillaURL)); return atoms; } -std::vector<::Atom> GetURIListAtomsFrom() { - std::vector< ::Atom> atoms; +std::vector<x11::Atom> GetURIListAtomsFrom() { + std::vector<x11::Atom> atoms; atoms.push_back(gfx::GetAtom(kMimeTypeURIList)); return atoms; } -void GetAtomIntersection(const std::vector< ::Atom>& desired, - const std::vector< ::Atom>& offered, - std::vector< ::Atom>* output) { +void GetAtomIntersection(const std::vector<x11::Atom>& desired, + const std::vector<x11::Atom>& offered, + std::vector<x11::Atom>* output) { for (const auto& desired_atom : desired) { if (base::Contains(offered, desired_atom)) output->push_back(desired_atom); @@ -68,8 +68,8 @@ std::vector<std::string> ParseURIList(const SelectionData& data) { // uri-lists are newline separated file lists in URL encoding. std::string unparsed; data.AssignTo(&unparsed); - return base::SplitString( - unparsed, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + return base::SplitString(unparsed, "\n", base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); } std::string RefCountedMemoryToString( @@ -104,22 +104,22 @@ base::string16 RefCountedMemoryToString16( /////////////////////////////////////////////////////////////////////////////// -SelectionFormatMap::SelectionFormatMap() {} +SelectionFormatMap::SelectionFormatMap() = default; SelectionFormatMap::SelectionFormatMap(const SelectionFormatMap& other) = default; -SelectionFormatMap::~SelectionFormatMap() {} +SelectionFormatMap::~SelectionFormatMap() = default; void SelectionFormatMap::Insert( - ::Atom atom, + x11::Atom atom, const scoped_refptr<base::RefCountedMemory>& item) { data_.erase(atom); data_.emplace(atom, item); } ui::SelectionData SelectionFormatMap::GetFirstOf( - const std::vector< ::Atom>& requested_types) const { + const std::vector<x11::Atom>& requested_types) const { for (const auto& requested_type : requested_types) { auto data_it = data_.find(requested_type); if (data_it != data_.end()) { @@ -130,8 +130,8 @@ ui::SelectionData SelectionFormatMap::GetFirstOf( return SelectionData(); } -std::vector< ::Atom> SelectionFormatMap::GetTypes() const { - std::vector< ::Atom> atoms; +std::vector<x11::Atom> SelectionFormatMap::GetTypes() const { + std::vector<x11::Atom> atoms; for (const auto& datum : data_) atoms.push_back(datum.first); @@ -140,17 +140,16 @@ std::vector< ::Atom> SelectionFormatMap::GetTypes() const { /////////////////////////////////////////////////////////////////////////////// -SelectionData::SelectionData() : type_(x11::None) {} +SelectionData::SelectionData() : type_(x11::Atom::None) {} SelectionData::SelectionData( - ::Atom type, + x11::Atom type, const scoped_refptr<base::RefCountedMemory>& memory) : type_(type), memory_(memory) {} -SelectionData::SelectionData(const SelectionData& rhs) - : type_(rhs.type_), memory_(rhs.memory_) {} +SelectionData::SelectionData(const SelectionData& rhs) = default; -SelectionData::~SelectionData() {} +SelectionData::~SelectionData() = default; SelectionData& SelectionData::operator=(const SelectionData& rhs) { type_ = rhs.type_; @@ -161,10 +160,10 @@ SelectionData& SelectionData::operator=(const SelectionData& rhs) { } bool SelectionData::IsValid() const { - return type_ != x11::None; + return type_ != x11::Atom::None; } -::Atom SelectionData::GetType() const { +x11::Atom SelectionData::GetType() const { return type_; } @@ -184,8 +183,7 @@ std::string SelectionData::GetText() const { type_ == gfx::GetAtom(kTextPlain)) { std::string result; base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_), - base::kCodepageLatin1, - &result); + base::kCodepageLatin1, &result); return result; } else { // BTW, I looked at COMPOUND_TEXT, and there's no way we're going to @@ -204,8 +202,7 @@ base::string16 SelectionData::GetHtml() const { // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is // UTF-16, otherwise assume UTF-8. - if (size >= 2 && - reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) { + if (size >= 2 && reinterpret_cast<const uint16_t*>(data)[0] == 0xFEFF) { markup.assign(reinterpret_cast<const uint16_t*>(data) + 1, (size / 2) - 1); } else { diff --git a/chromium/ui/base/x/selection_utils.h b/chromium/ui/base/x/selection_utils.h index 5be34cd6414..9ca25b373a0 100644 --- a/chromium/ui/base/x/selection_utils.h +++ b/chromium/ui/base/x/selection_utils.h @@ -20,17 +20,17 @@ COMPONENT_EXPORT(UI_BASE_X) extern const char kText[]; COMPONENT_EXPORT(UI_BASE_X) extern const char kUtf8String[]; // Returns a list of all text atoms that we handle. -COMPONENT_EXPORT(UI_BASE_X) std::vector<::Atom> GetTextAtomsFrom(); +COMPONENT_EXPORT(UI_BASE_X) std::vector<x11::Atom> GetTextAtomsFrom(); -COMPONENT_EXPORT(UI_BASE_X) std::vector<::Atom> GetURLAtomsFrom(); +COMPONENT_EXPORT(UI_BASE_X) std::vector<x11::Atom> GetURLAtomsFrom(); -COMPONENT_EXPORT(UI_BASE_X) std::vector<::Atom> GetURIListAtomsFrom(); +COMPONENT_EXPORT(UI_BASE_X) std::vector<x11::Atom> GetURIListAtomsFrom(); // Places the intersection of |desired| and |offered| into |output|. COMPONENT_EXPORT(UI_BASE_X) -void GetAtomIntersection(const std::vector<::Atom>& desired, - const std::vector<::Atom>& offered, - std::vector<::Atom>* output); +void GetAtomIntersection(const std::vector<x11::Atom>& desired, + const std::vector<x11::Atom>& offered, + std::vector<x11::Atom>* output); // Takes the raw bytes of the base::string16 and copies them into |bytes|. COMPONENT_EXPORT(UI_BASE_X) @@ -56,8 +56,9 @@ base::string16 RefCountedMemoryToString16( class COMPONENT_EXPORT(UI_BASE_X) SelectionFormatMap { public: // Our internal data store, which we only expose through iterators. - typedef std::map< ::Atom, scoped_refptr<base::RefCountedMemory> > InternalMap; - typedef InternalMap::const_iterator const_iterator; + using InternalMap = + std::map<x11::Atom, scoped_refptr<base::RefCountedMemory>>; + using const_iterator = InternalMap::const_iterator; SelectionFormatMap(); SelectionFormatMap(const SelectionFormatMap& other); @@ -66,19 +67,20 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionFormatMap { // Adds the selection in the format |atom|. Ownership of |data| is passed to // us. - void Insert(::Atom atom, const scoped_refptr<base::RefCountedMemory>& item); + void Insert(x11::Atom atom, + const scoped_refptr<base::RefCountedMemory>& item); // Returns the first of the requested_types or NULL if missing. ui::SelectionData GetFirstOf( - const std::vector< ::Atom>& requested_types) const; + const std::vector<x11::Atom>& requested_types) const; // Returns all the selected types. - std::vector< ::Atom> GetTypes() const; + std::vector<x11::Atom> GetTypes() const; // Pass through to STL map. Only allow non-mutation access. const_iterator begin() const { return data_.begin(); } const_iterator end() const { return data_.end(); } - const_iterator find(::Atom atom) const { return data_.find(atom); } + const_iterator find(x11::Atom atom) const { return data_.find(atom); } size_t size() const { return data_.size(); } private: @@ -92,14 +94,14 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionData { public: // |atom_cache| is still owned by caller. SelectionData(); - SelectionData(::Atom type, + SelectionData(x11::Atom type, const scoped_refptr<base::RefCountedMemory>& memory); SelectionData(const SelectionData& rhs); ~SelectionData(); SelectionData& operator=(const SelectionData& rhs); bool IsValid() const; - ::Atom GetType() const; + x11::Atom GetType() const; const unsigned char* GetData() const; size_t GetSize() const; @@ -115,7 +117,7 @@ class COMPONENT_EXPORT(UI_BASE_X) SelectionData { void AssignTo(base::string16* result) const; private: - ::Atom type_; + x11::Atom type_; scoped_refptr<base::RefCountedMemory> memory_; }; diff --git a/chromium/ui/base/x/x11_cursor.cc b/chromium/ui/base/x/x11_cursor.cc new file mode 100644 index 00000000000..9d55c5db524 --- /dev/null +++ b/chromium/ui/base/x/x11_cursor.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 "ui/base/x/x11_cursor.h" + +#include "base/check_op.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/geometry/point.h" + +namespace ui { + +X11Cursor::X11Cursor(const SkBitmap& bitmap, const gfx::Point& hotspot) { + XcursorImage* image = SkBitmapToXcursorImage(bitmap, hotspot); + xcursor_ = XcursorImageLoadCursor(gfx::GetXDisplay(), image); + XcursorImageDestroy(image); +} + +X11Cursor::X11Cursor(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 = SkBitmapToXcursorImage(bitmaps[frame], hotspot); + x_image->delay = frame_delay_ms; + images->images[frame] = x_image; + } + + xcursor_ = XcursorImagesLoadCursor(gfx::GetXDisplay(), images); + XcursorImagesDestroy(images); +} + +X11Cursor::X11Cursor(::Cursor xcursor) : xcursor_(xcursor) {} + +// static +scoped_refptr<X11Cursor> X11Cursor::CreateInvisible() { + return base::MakeRefCounted<X11Cursor>(CreateInvisibleCursor()); +} + +X11Cursor::~X11Cursor() { + XFreeCursor(gfx::GetXDisplay(), xcursor_); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_cursor.h b/chromium/ui/base/x/x11_cursor.h new file mode 100644 index 00000000000..1711b947970 --- /dev/null +++ b/chromium/ui/base/x/x11_cursor.h @@ -0,0 +1,55 @@ +// 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_X_X11_CURSOR_H_ +#define UI_BASE_X_X11_CURSOR_H_ + +#include <vector> + +#include "base/component_export.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "ui/gfx/x/x11.h" + +class SkBitmap; + +namespace gfx { +class Point; +} + +namespace ui { + +// Ref counted class to hold an X11 cursor resource. Clears the X11 resources +// on destruction +class COMPONENT_EXPORT(UI_BASE_X) X11Cursor + : public base::RefCounted<X11Cursor> { + public: + REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); + + // Handles creating X11 cursor resources from SkBitmap/hotspot. + X11Cursor(const SkBitmap& bitmap, const gfx::Point& hotspot); + X11Cursor(const X11Cursor&) = delete; + X11Cursor& operator=(const X11Cursor&) = delete; + X11Cursor(const std::vector<SkBitmap>& bitmaps, + const gfx::Point& hotspot, + int frame_delay_ms); + // Wraps an X11 cursor |xcursor|. + explicit X11Cursor(::Cursor xcursor); + + // Creates a new cursor that is invisible. + static scoped_refptr<X11Cursor> CreateInvisible(); + + ::Cursor xcursor() const { return xcursor_; } + + private: + friend class base::RefCounted<X11Cursor>; + + ~X11Cursor(); + + ::Cursor xcursor_ = x11::None; +}; + +} // namespace ui + +#endif // UI_BASE_X_X11_CURSOR_H_ diff --git a/chromium/ui/base/x/x11_cursor_factory.cc b/chromium/ui/base/x/x11_cursor_factory.cc new file mode 100644 index 00000000000..26624776290 --- /dev/null +++ b/chromium/ui/base/x/x11_cursor_factory.cc @@ -0,0 +1,118 @@ +// 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/x/x11_cursor_factory.h" + +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" +#include "ui/base/x/x11_cursor.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/x/x11.h" + +namespace ui { + +namespace { + +X11Cursor* ToX11Cursor(PlatformCursor cursor) { + return static_cast<X11Cursor*>(cursor); +} + +PlatformCursor ToPlatformCursor(X11Cursor* cursor) { + return static_cast<PlatformCursor>(cursor); +} + +} // namespace + +X11CursorFactory::X11CursorFactory() + : invisible_cursor_(X11Cursor::CreateInvisible()) {} + +X11CursorFactory::~X11CursorFactory() = default; + +base::Optional<PlatformCursor> X11CursorFactory::GetDefaultCursor( + mojom::CursorType type) { + auto cursor = GetDefaultCursorInternal(type); + if (!cursor) + return base::nullopt; + return ToPlatformCursor(cursor.get()); +} + +PlatformCursor X11CursorFactory::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()) { + // The result of |invisible_cursor_| is owned by the caller, and will be + // Unref()ed by code far away. (Usually in web_cursor.cc in content, among + // others.) If we don't manually add another reference before we cast this + // to a void*, we can end up with |invisible_cursor_| being freed out from + // under us. + invisible_cursor_->AddRef(); + return ToPlatformCursor(invisible_cursor_.get()); + } + + auto cursor = base::MakeRefCounted<X11Cursor>(bitmap, hotspot); + cursor->AddRef(); + return ToPlatformCursor(cursor.get()); +} + +PlatformCursor X11CursorFactory::CreateAnimatedCursor( + const std::vector<SkBitmap>& bitmaps, + const gfx::Point& hotspot, + int frame_delay_ms) { + auto cursor = + base::MakeRefCounted<X11Cursor>(bitmaps, hotspot, frame_delay_ms); + cursor->AddRef(); + return ToPlatformCursor(cursor.get()); +} + +void X11CursorFactory::RefImageCursor(PlatformCursor cursor) { + ToX11Cursor(cursor)->AddRef(); +} + +void X11CursorFactory::UnrefImageCursor(PlatformCursor cursor) { + ToX11Cursor(cursor)->Release(); +} + +void X11CursorFactory::ObserveThemeChanges() { + auto* cursor_theme_manager = CursorThemeManager::GetInstance(); + if (cursor_theme_manager) + cursor_theme_observer_.Add(cursor_theme_manager); +} + +void X11CursorFactory::OnCursorThemeNameChanged( + const std::string& cursor_theme_name) { + XcursorSetTheme(gfx::GetXDisplay(), cursor_theme_name.c_str()); + ClearThemeCursors(); +} + +void X11CursorFactory::OnCursorThemeSizeChanged(int cursor_theme_size) { + XcursorSetDefaultSize(gfx::GetXDisplay(), cursor_theme_size); + ClearThemeCursors(); +} + +scoped_refptr<X11Cursor> X11CursorFactory::GetDefaultCursorInternal( + mojom::CursorType type) { + if (type == mojom::CursorType::kNone) + return invisible_cursor_; + + if (!default_cursors_.count(type)) { + // Try to load a predefined X11 cursor. + ::Cursor xcursor = LoadCursorFromType(type); + if (xcursor == x11::None) + return nullptr; + auto cursor = base::MakeRefCounted<X11Cursor>(xcursor); + default_cursors_[type] = cursor; + } + + // Returns owned default cursor for this type. + return default_cursors_[type]; +} + +void X11CursorFactory::ClearThemeCursors() { + default_cursors_.clear(); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_cursor_factory.h b/chromium/ui/base/x/x11_cursor_factory.h new file mode 100644 index 00000000000..424511854ef --- /dev/null +++ b/chromium/ui/base/x/x11_cursor_factory.h @@ -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. + +#ifndef UI_BASE_X_X11_CURSOR_FACTORY_H_ +#define UI_BASE_X_X11_CURSOR_FACTORY_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/component_export.h" +#include "base/memory/scoped_refptr.h" +#include "base/scoped_observer.h" +#include "ui/base/cursor/cursor_factory.h" +#include "ui/base/cursor/cursor_theme_manager.h" +#include "ui/base/cursor/cursor_theme_manager_observer.h" +#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" + +namespace ui { +class X11Cursor; + +// CursorFactoryOzone implementation for X11 cursors. +class COMPONENT_EXPORT(UI_BASE_X) X11CursorFactory + : public CursorFactory, + public CursorThemeManagerObserver { + public: + X11CursorFactory(); + X11CursorFactory(const X11CursorFactory&) = delete; + X11CursorFactory& operator=(const X11CursorFactory&) = delete; + ~X11CursorFactory() override; + + // CursorFactoryOzone: + base::Optional<PlatformCursor> GetDefaultCursor( + mojom::CursorType 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; + void ObserveThemeChanges() override; + + private: + // CusorThemeManagerObserver: + void OnCursorThemeNameChanged(const std::string& cursor_theme_name) override; + void OnCursorThemeSizeChanged(int cursor_theme_size) override; + + void ClearThemeCursors(); + + // Loads/caches default cursor or returns cached version. + scoped_refptr<X11Cursor> GetDefaultCursorInternal(mojom::CursorType 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<X11Cursor> invisible_cursor_; + + std::map<mojom::CursorType, scoped_refptr<X11Cursor>> default_cursors_; + + ScopedObserver<CursorThemeManager, CursorThemeManagerObserver> + cursor_theme_observer_{this}; +}; + +} // namespace ui + +#endif // UI_BASE_X_X11_CURSOR_FACTORY_H_ diff --git a/chromium/ui/base/x/x11_cursor_factory_unittest.cc b/chromium/ui/base/x/x11_cursor_factory_unittest.cc new file mode 100644 index 00000000000..8c317fba402 --- /dev/null +++ b/chromium/ui/base/x/x11_cursor_factory_unittest.cc @@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/x/x11_cursor_factory.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/x/x11_cursor.h" +#include "ui/gfx/geometry/point.h" + +namespace ui { + +TEST(X11CursorFactoryTest, InvisibleRefcount) { + X11CursorFactory factory; + + // Building an image cursor with an invalid SkBitmap should return the + // invisible cursor in X11. The invisible cursor instance should have more + // than a single reference since the factory should hold a reference and + // CreateImageCursor should return an incremented refcount. + auto* invisible_cursor = static_cast<X11Cursor*>( + factory.CreateImageCursor(SkBitmap(), gfx::Point())); + ASSERT_FALSE(invisible_cursor->HasOneRef()); + + // Release our refcount on the cursor + factory.UnrefImageCursor(invisible_cursor); + + // The invisible cursor should still exist. + EXPECT_TRUE(invisible_cursor->HasOneRef()); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_display_manager.cc b/chromium/ui/base/x/x11_display_manager.cc index 5d2475a3315..623d809dd02 100644 --- a/chromium/ui/base/x/x11_display_manager.cc +++ b/chromium/ui/base/x/x11_display_manager.cc @@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/base/x/x11_display_util.h" +#include "ui/gfx/x/randr.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" @@ -22,21 +23,22 @@ constexpr int kMinXrandrVersion = 103; // Need at least xrandr version 1.3 XDisplayManager::XDisplayManager(Delegate* delegate) : delegate_(delegate), - xdisplay_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(xdisplay_)), - xrandr_version_(GetXrandrVersion(xdisplay_)), + connection_(x11::Connection::Get()), + x_root_window_(connection_->default_screen().root), + xrandr_version_(GetXrandrVersion()), workspace_handler_(this) {} XDisplayManager::~XDisplayManager() = default; void XDisplayManager::Init() { if (IsXrandrAvailable()) { - int error_base_ignored = 0; - XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); + auto& randr = connection_->randr(); + xrandr_event_base_ = randr.first_event(); - XRRSelectInput(xdisplay_, x_root_window_, - RRScreenChangeNotifyMask | RROutputChangeNotifyMask | - RRCrtcChangeNotifyMask); + randr.SelectInput( + {x_root_window_, x11::RandR::NotifyMask::ScreenChange | + x11::RandR::NotifyMask::OutputChange | + x11::RandR::NotifyMask::CrtcChange}); } FetchDisplayList(); } @@ -59,25 +61,25 @@ void XDisplayManager::RemoveObserver(display::DisplayObserver* observer) { change_notifier_.RemoveObserver(observer); } -bool XDisplayManager::CanProcessEvent(const XEvent& xev) { - return xev.type - xrandr_event_base_ == RRScreenChangeNotify || - xev.type - xrandr_event_base_ == RRNotify || +bool XDisplayManager::CanProcessEvent(const x11::Event& x11_event) { + const XEvent& xev = x11_event.xlib_event(); + return xev.type - xrandr_event_base_ == + x11::RandR::ScreenChangeNotifyEvent::opcode || + xev.type - xrandr_event_base_ == x11::RandR::NotifyEvent::opcode || (xev.type == PropertyNotify && - xev.xproperty.window == x_root_window_ && - xev.xproperty.atom == gfx::GetAtom("_NET_WORKAREA")); + static_cast<x11::Window>(xev.xproperty.window) == x_root_window_ && + xev.xproperty.atom == + static_cast<uint32_t>(gfx::GetAtom("_NET_WORKAREA"))); } -bool XDisplayManager::ProcessEvent(XEvent* xev) { - DCHECK(xev); +bool XDisplayManager::ProcessEvent(x11::Event* x11_event) { + DCHECK(x11_event); + XEvent* xev = &x11_event->xlib_event(); int ev_type = xev->type - xrandr_event_base_; - if (ev_type == RRScreenChangeNotify) { - // Pass the event through to xlib. - XRRUpdateConfiguration(xev); - return true; - } - if (ev_type == RRNotify || + if (ev_type == x11::RandR::NotifyEvent::opcode || (xev->type == PropertyNotify && - xev->xproperty.atom == gfx::GetAtom("_NET_WORKAREA"))) { + xev->xproperty.atom == + static_cast<uint32_t>(gfx::GetAtom("_NET_WORKAREA")))) { DispatchDelayedDisplayListUpdate(); return true; } @@ -123,13 +125,9 @@ void XDisplayManager::DispatchDelayedDisplayListUpdate() { } gfx::Point XDisplayManager::GetCursorLocation() const { - XID root, child; - int root_x, root_y, win_x, win_y; - unsigned int mask; - XQueryPointer(xdisplay_, x_root_window_, &root, &child, &root_x, &root_y, - &win_x, &win_y, &mask); - - return gfx::Point(root_x, root_y); + if (auto response = connection_->QueryPointer({x_root_window_}).Sync()) + return {response->root_x, response->root_y}; + return {}; } std::string XDisplayManager::GetCurrentWorkspace() { diff --git a/chromium/ui/base/x/x11_display_manager.h b/chromium/ui/base/x/x11_display_manager.h index 257467daef0..d638460ad1b 100644 --- a/chromium/ui/base/x/x11_display_manager.h +++ b/chromium/ui/base/x/x11_display_manager.h @@ -14,6 +14,7 @@ #include "ui/display/display.h" #include "ui/display/display_change_notifier.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11_types.h" namespace views { @@ -34,7 +35,7 @@ class X11ScreenOzoneTest; // Scale Factor information and simple hooks are delegated to API clients // through |XDisplayManager::Delegate| interface. To get notifications about // dynamic display changes, clients must register |DisplayObserver| instances -// and feed |XDisplayManager| with |XEvent|s. +// and feed |XDisplayManager| with |x11::Event|s. // // All bounds and size values are assumed to be expressed in pixels. class COMPONENT_EXPORT(UI_BASE_X) XDisplayManager @@ -47,8 +48,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XDisplayManager void Init(); bool IsXrandrAvailable() const; - bool CanProcessEvent(const XEvent& xev); - bool ProcessEvent(XEvent* xev); + bool CanProcessEvent(const x11::Event& xev); + bool ProcessEvent(x11::Event* xev); void UpdateDisplayList(); void DispatchDelayedDisplayListUpdate(); display::Display GetPrimaryDisplay() const; @@ -76,8 +77,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XDisplayManager std::vector<display::Display> displays_; display::DisplayChangeNotifier change_notifier_; - XDisplay* const xdisplay_; - XID x_root_window_; + x11::Connection* const connection_; + x11::Window x_root_window_; int64_t primary_display_index_ = 0; // XRandR version. MAJOR * 100 + MINOR. Zero if no xrandr is present. diff --git a/chromium/ui/base/x/x11_display_util.cc b/chromium/ui/base/x/x11_display_util.cc index fe73b11b30d..0376b5ef9b3 100644 --- a/chromium/ui/base/x/x11_display_util.cc +++ b/chromium/ui/base/x/x11_display_util.cc @@ -18,6 +18,7 @@ #include "ui/gfx/geometry/matrix3_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector3d_f.h" +#include "ui/gfx/x/randr.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" @@ -27,32 +28,17 @@ namespace { constexpr int kMinVersionXrandr = 103; // Need at least xrandr version 1.3. -typedef XRRMonitorInfo* (*XRRGetMonitors)(::Display*, Window, bool, int*); -typedef void (*XRRFreeMonitors)(XRRMonitorInfo*); +constexpr const char kRandrEdidProperty[] = "EDID"; -NO_SANITIZE("cfi-icall") -std::map<RROutput, int> GetMonitors(int version, - XDisplay* xdisplay, - GLXWindow window) { - std::map<RROutput, int> output_to_monitor; +std::map<x11::RandR::Output, int> GetMonitors(int version, + x11::RandR* randr, + x11::Window window) { + std::map<x11::RandR::Output, int> output_to_monitor; if (version >= 105) { - void* xrandr_lib = dlopen(nullptr, RTLD_NOW); - if (xrandr_lib) { - static XRRGetMonitors XRRGetMonitors_ptr = - reinterpret_cast<XRRGetMonitors>(dlsym(xrandr_lib, "XRRGetMonitors")); - static XRRFreeMonitors XRRFreeMonitors_ptr = - reinterpret_cast<XRRFreeMonitors>( - dlsym(xrandr_lib, "XRRFreeMonitors")); - if (XRRGetMonitors_ptr && XRRFreeMonitors_ptr) { - int nmonitors = 0; - XRRMonitorInfo* monitors = - XRRGetMonitors_ptr(xdisplay, window, false, &nmonitors); - for (int monitor = 0; monitor < nmonitors; monitor++) { - for (int j = 0; j < monitors[monitor].noutput; j++) { - output_to_monitor[monitors[monitor].outputs[j]] = monitor; - } - } - XRRFreeMonitors_ptr(monitors); + if (auto reply = randr->GetMonitors({window}).Sync()) { + for (size_t monitor = 0; monitor < reply->monitors.size(); monitor++) { + for (x11::RandR::Output output : reply->monitors[monitor].outputs) + output_to_monitor[output] = monitor; } } } @@ -65,8 +51,7 @@ std::map<RROutput, int> GetMonitors(int version, void ClipWorkArea(std::vector<display::Display>* displays, int64_t primary_display_index, float scale) { - XDisplay* xdisplay = gfx::GetXDisplay(); - GLXWindow x_root_window = DefaultRootWindow(xdisplay); + x11::Window x_root_window = ui::GetX11RootWindow(); std::vector<int> value; if (!ui::GetIntArrayProperty(x_root_window, "_NET_WORKAREA", &value) || @@ -103,126 +88,89 @@ void ClipWorkArea(std::vector<display::Display>* displays, primary.set_work_area(work_area); } -float GetRefreshRateFromXRRModeInfo(XRRModeInfo* modes, - int num_of_mode, - RRMode current_mode_id) { - for (int i = 0; i < num_of_mode; i++) { - XRRModeInfo mode_info = modes[i]; - if (mode_info.id != current_mode_id) +float GetRefreshRateFromXRRModeInfo( + const std::vector<x11::RandR::ModeInfo>& modes, + x11::RandR::Mode current_mode_id) { + for (const auto& mode_info : modes) { + if (static_cast<x11::RandR::Mode>(mode_info.id) != current_mode_id) continue; - if (!mode_info.hTotal || !mode_info.vTotal) + if (!mode_info.htotal || !mode_info.vtotal) return 0; // Refresh Rate = Pixel Clock / (Horizontal Total * Vertical Total) - return mode_info.dotClock / - static_cast<float>(mode_info.hTotal * mode_info.vTotal); + return mode_info.dot_clock / + static_cast<float>(mode_info.htotal * mode_info.vtotal); } return 0; } -int DefaultScreenDepth(XDisplay* xdisplay) { - return DefaultDepth(xdisplay, DefaultScreen(xdisplay)); -} - -int DefaultBitsPerComponent(XDisplay* xdisplay) { - Visual* visual = DefaultVisual(xdisplay, DefaultScreen(xdisplay)); +int DefaultBitsPerComponent() { + auto* connection = x11::Connection::Get(); + const x11::VisualType& visual = connection->default_root_visual(); // The mask fields are only valid for DirectColor and TrueColor classes. - if (visual->c_class == DirectColor || visual->c_class == TrueColor) { + if (visual.c_class == x11::VisualClass::DirectColor || + visual.c_class == x11::VisualClass::TrueColor) { // RGB components are packed into fixed size integers for each visual. The // layout of bits in the packing is given by - // |visual->{red,green,blue}_mask|. Count the number of bits to get the + // |visual.{red,green,blue}_mask|. Count the number of bits to get the // number of bits per component. auto bits = [](auto mask) { return std::bitset<sizeof(mask) * 8>{mask}.count(); }; - size_t red_bits = bits(visual->red_mask); - size_t green_bits = bits(visual->green_mask); - size_t blue_bits = bits(visual->blue_mask); + size_t red_bits = bits(visual.red_mask); + size_t green_bits = bits(visual.green_mask); + size_t blue_bits = bits(visual.blue_mask); if (red_bits == green_bits && red_bits == blue_bits) return red_bits; } // Next, try getting the number of colormap entries per subfield. If it's a // power of 2, log2 is a possible guess for the number of bits per component. - if (base::bits::IsPowerOfTwo(visual->map_entries)) - return base::bits::Log2Ceiling(visual->map_entries); + if (base::bits::IsPowerOfTwo(visual.colormap_entries)) + return base::bits::Log2Ceiling(visual.colormap_entries); // |bits_per_rgb| can sometimes be unreliable (may be 11 for 30bpp visuals), // so only use it as a last resort. - return visual->bits_per_rgb; -} - -bool IsRandRAvailable() { - int randr_version_major = 0; - int randr_version_minor = 0; - static bool is_randr_available = XRRQueryVersion( - gfx::GetXDisplay(), &randr_version_major, &randr_version_minor); - return is_randr_available; + return visual.bits_per_rgb_value; } // Get the EDID data from the |output| and stores to |edid|. -void GetEDIDProperty(XID output, std::vector<uint8_t>* edid) { - if (!IsRandRAvailable()) - return; - - Display* display = gfx::GetXDisplay(); - - Atom edid_property = gfx::GetAtom(RR_PROPERTY_RANDR_EDID); - - bool has_edid_property = false; - int num_properties = 0; - gfx::XScopedPtr<Atom[]> properties( - XRRListOutputProperties(display, output, &num_properties)); - for (int i = 0; i < num_properties; ++i) { - if (properties[i] == edid_property) { - has_edid_property = true; - break; - } - } - if (!has_edid_property) - return; - - Atom actual_type; - int actual_format; - unsigned long bytes_after; - unsigned long nitems = 0; - unsigned char* prop = nullptr; - XRRGetOutputProperty(display, output, edid_property, - 0, // offset - 128, // length - false, // _delete - false, // pending - AnyPropertyType, // req_type - &actual_type, &actual_format, &nitems, &bytes_after, - &prop); - DCHECK_EQ(XA_INTEGER, actual_type); - DCHECK_EQ(8, actual_format); - edid->assign(prop, prop + nitems); - XFree(prop); +std::vector<uint8_t> GetEDIDProperty(x11::RandR* randr, + x11::RandR::Output output) { + auto future = randr->GetOutputProperty({ + .output = output, + .property = gfx::GetAtom(kRandrEdidProperty), + .long_length = 128, + }); + auto response = future.Sync(); + std::vector<uint8_t> edid; + if (response && response->format == 8 && response->type != x11::Atom::None) + edid = std::move(response->data); + return edid; } } // namespace -int GetXrandrVersion(XDisplay* xdisplay) { - int xrandr_version = 0; - // We only support 1.3+. There were library changes before this and we should - // use the new interface instead of the 1.2 one. - int randr_version_major = 0; - int randr_version_minor = 0; - if (XRRQueryVersion(xdisplay, &randr_version_major, &randr_version_minor)) { - xrandr_version = randr_version_major * 100 + randr_version_minor; - } - return xrandr_version; +int GetXrandrVersion() { + auto impl = []() -> int { + auto future = x11::Connection::Get()->randr().QueryVersion( + {x11::RandR::major_version, x11::RandR::minor_version}); + if (auto response = future.Sync()) + return response->major_version * 100 + response->minor_version; + return 0; + }; + static int version = impl(); + return version; } std::vector<display::Display> GetFallbackDisplayList(float scale) { - XDisplay* display = gfx::GetXDisplay(); - ::Screen* screen = DefaultScreenOfDisplay(display); - gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen)); + const auto& screen = x11::Connection::Get()->default_screen(); + gfx::Size physical_size(screen.width_in_millimeters, + screen.height_in_millimeters); - int width = WidthOfScreen(screen); - int height = HeightOfScreen(screen); + int width = screen.width_in_pixels; + int height = screen.height_in_pixels; gfx::Rect bounds_in_pixels(0, 0, width, height); display::Display gfx_display(0, bounds_in_pixels); @@ -236,8 +184,8 @@ std::vector<display::Display> GetFallbackDisplayList(float scale) { scale = 1; } - gfx_display.set_color_depth(DefaultScreenDepth(display)); - gfx_display.set_depth_per_component(DefaultBitsPerComponent(display)); + gfx_display.set_color_depth(screen.root_depth); + gfx_display.set_depth_per_component(DefaultBitsPerComponent()); std::vector<display::Display> displays{gfx_display}; ClipWorkArea(&displays, 0, scale); @@ -250,125 +198,129 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo( int64_t* primary_display_index_out) { DCHECK(primary_display_index_out); DCHECK_GE(version, kMinVersionXrandr); - XDisplay* xdisplay = gfx::GetXDisplay(); - GLXWindow x_root_window = DefaultRootWindow(xdisplay); + auto* connection = x11::Connection::Get(); + auto& randr = connection->randr(); + auto x_root_window = static_cast<x11::Window>(ui::GetX11RootWindow()); std::vector<display::Display> displays; - gfx::XScopedPtr< - XRRScreenResources, - gfx::XObjectDeleter<XRRScreenResources, void, XRRFreeScreenResources>> - resources(XRRGetScreenResourcesCurrent(xdisplay, x_root_window)); + auto resources = randr.GetScreenResourcesCurrent({x_root_window}).Sync(); if (!resources) { LOG(ERROR) << "XRandR returned no displays; falling back to root window"; return GetFallbackDisplayList(scale); } - const int depth = DefaultScreenDepth(xdisplay); - const int bits_per_component = DefaultBitsPerComponent(xdisplay); + const int depth = connection->default_screen().root_depth; + const int bits_per_component = DefaultBitsPerComponent(); - std::map<RROutput, int> output_to_monitor = - GetMonitors(version, xdisplay, x_root_window); + std::map<x11::RandR::Output, int> output_to_monitor = + GetMonitors(version, &randr, x_root_window); *primary_display_index_out = 0; - RROutput primary_display_id = XRRGetOutputPrimary(xdisplay, x_root_window); + auto output_primary = randr.GetOutputPrimary({x_root_window}).Sync(); + if (!output_primary) + return GetFallbackDisplayList(scale); + x11::RandR::Output primary_display_id = output_primary->output; int explicit_primary_display_index = -1; int monitor_order_primary_display_index = -1; // As per-display scale factor is not supported right now, // the X11 root window's scale factor is always used. - for (int i = 0; i < resources->noutput; ++i) { - RROutput output_id = resources->outputs[i]; - gfx::XScopedPtr<XRROutputInfo, - gfx::XObjectDeleter<XRROutputInfo, void, XRRFreeOutputInfo>> - output_info(XRRGetOutputInfo(xdisplay, resources.get(), output_id)); - - // XRRGetOutputInfo returns null in some cases: https://crbug.com/921490 + for (size_t i = 0; i < resources->outputs.size(); i++) { + x11::RandR::Output output_id = resources->outputs[i]; + auto output_info = + randr.GetOutputInfo({output_id, resources->config_timestamp}).Sync(); if (!output_info) continue; - bool is_connected = (output_info->connection == RR_Connected); - if (!is_connected) + if (output_info->connection != x11::RandR::RandRConnection::Connected) continue; bool is_primary_display = (output_id == primary_display_id); - if (output_info->crtc) { - gfx::XScopedPtr<XRRCrtcInfo, - gfx::XObjectDeleter<XRRCrtcInfo, void, XRRFreeCrtcInfo>> - crtc(XRRGetCrtcInfo(xdisplay, resources.get(), output_info->crtc)); - - std::vector<uint8_t> edid_bytes; - GetEDIDProperty(output_id, &edid_bytes); - display::EdidParser edid_parser(edid_bytes); - int64_t display_id = edid_parser.GetDisplayId(output_id); - // It isn't ideal, but if we can't parse the EDID data, fall back on the - // display number. - if (!display_id) - display_id = i; - - gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height); - display::Display display(display_id, crtc_bounds); - - if (!display::Display::HasForceDeviceScaleFactor()) { - display.SetScaleAndBounds(scale, crtc_bounds); - display.set_work_area( - gfx::ScaleToEnclosingRect(crtc_bounds, 1.0f / scale)); - } - - switch (crtc->rotation) { - case RR_Rotate_0: - display.set_rotation(display::Display::ROTATE_0); - break; - case RR_Rotate_90: - display.set_rotation(display::Display::ROTATE_90); - break; - case RR_Rotate_180: - display.set_rotation(display::Display::ROTATE_180); - break; - case RR_Rotate_270: - display.set_rotation(display::Display::ROTATE_270); - break; - } + if (output_info->crtc == static_cast<x11::RandR::Crtc>(0)) + continue; - if (is_primary_display) - explicit_primary_display_index = displays.size(); + auto crtc = + randr.GetCrtcInfo({output_info->crtc, resources->config_timestamp}) + .Sync(); + if (!crtc) + continue; - auto monitor_iter = output_to_monitor.find(output_id); - if (monitor_iter != output_to_monitor.end() && monitor_iter->second == 0) - monitor_order_primary_display_index = displays.size(); + display::EdidParser edid_parser( + GetEDIDProperty(&randr, static_cast<x11::RandR::Output>(output_id))); + auto output_32 = static_cast<uint32_t>(output_id); + int64_t display_id = + output_32 > 0xff ? 0 : edid_parser.GetDisplayId(output_32); + // It isn't ideal, but if we can't parse the EDID data, fall back on the + // display number. + if (!display_id) + display_id = i; + + gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height); + display::Display display(display_id, crtc_bounds); + + if (!display::Display::HasForceDeviceScaleFactor()) { + display.SetScaleAndBounds(scale, crtc_bounds); + display.set_work_area( + gfx::ScaleToEnclosingRect(crtc_bounds, 1.0f / scale)); + } - if (!display::Display::HasForceDisplayColorProfile()) { - gfx::ICCProfile icc_profile = ui::GetICCProfileForMonitor( - monitor_iter == output_to_monitor.end() ? 0 : monitor_iter->second); - gfx::ColorSpace color_space = icc_profile.GetPrimariesOnlyColorSpace(); + switch (crtc->rotation) { + case x11::RandR::Rotation::Rotate_0: + display.set_rotation(display::Display::ROTATE_0); + break; + case x11::RandR::Rotation::Rotate_90: + display.set_rotation(display::Display::ROTATE_90); + break; + case x11::RandR::Rotation::Rotate_180: + display.set_rotation(display::Display::ROTATE_180); + break; + case x11::RandR::Rotation::Rotate_270: + display.set_rotation(display::Display::ROTATE_270); + break; + case x11::RandR::Rotation::Reflect_X: + case x11::RandR::Rotation::Reflect_Y: + NOTIMPLEMENTED(); + } - // Most folks do not have an ICC profile set up, but we still want to - // detect if a display has a wide color gamut so that HDR videos can be - // enabled. Only do this if |bits_per_component| > 8 or else SDR - // screens may have washed out colors. - if (bits_per_component > 8 && !color_space.IsValid()) - color_space = display::GetColorSpaceFromEdid(edid_parser); + if (is_primary_display) + explicit_primary_display_index = displays.size(); - display.set_color_spaces( - gfx::DisplayColorSpaces(color_space, gfx::BufferFormat::BGRA_8888)); - } + auto monitor_iter = + output_to_monitor.find(static_cast<x11::RandR::Output>(output_id)); + if (monitor_iter != output_to_monitor.end() && monitor_iter->second == 0) + monitor_order_primary_display_index = displays.size(); - display.set_color_depth(depth); - display.set_depth_per_component(bits_per_component); + if (!display::Display::HasForceDisplayColorProfile()) { + gfx::ICCProfile icc_profile = ui::GetICCProfileForMonitor( + monitor_iter == output_to_monitor.end() ? 0 : monitor_iter->second); + gfx::ColorSpace color_space = icc_profile.GetPrimariesOnlyColorSpace(); - // Set monitor refresh rate - int refresh_rate = static_cast<int>(GetRefreshRateFromXRRModeInfo( - resources->modes, resources->nmode, crtc->mode)); - display.set_display_frequency(refresh_rate); + // Most folks do not have an ICC profile set up, but we still want to + // detect if a display has a wide color gamut so that HDR videos can be + // enabled. Only do this if |bits_per_component| > 8 or else SDR + // screens may have washed out colors. + if (bits_per_component > 8 && !color_space.IsValid()) + color_space = display::GetColorSpaceFromEdid(edid_parser); - displays.push_back(display); + display.set_color_spaces( + gfx::DisplayColorSpaces(color_space, gfx::BufferFormat::BGRA_8888)); } + + display.set_color_depth(depth); + display.set_depth_per_component(bits_per_component); + + // Set monitor refresh rate + int refresh_rate = static_cast<int>( + GetRefreshRateFromXRRModeInfo(resources->modes, crtc->mode)); + display.set_display_frequency(refresh_rate); + + displays.push_back(display); } - if (explicit_primary_display_index != -1) { + if (explicit_primary_display_index != -1) *primary_display_index_out = explicit_primary_display_index; - } else if (monitor_order_primary_display_index != -1) { + else if (monitor_order_primary_display_index != -1) *primary_display_index_out = monitor_order_primary_display_index; - } if (displays.empty()) return GetFallbackDisplayList(scale); @@ -377,32 +329,33 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo( return displays; } -base::TimeDelta GetPrimaryDisplayRefreshIntervalFromXrandr(Display* display) { +base::TimeDelta GetPrimaryDisplayRefreshIntervalFromXrandr() { constexpr base::TimeDelta kDefaultInterval = base::TimeDelta::FromSecondsD(1. / 60); - GLXWindow root = DefaultRootWindow(display); - gfx::XScopedPtr< - XRRScreenResources, - gfx::XObjectDeleter<XRRScreenResources, void, XRRFreeScreenResources>> - resources(XRRGetScreenResourcesCurrent(display, root)); + x11::RandR randr = x11::Connection::Get()->randr(); + auto root = static_cast<x11::Window>(ui::GetX11RootWindow()); + auto resources = randr.GetScreenResourcesCurrent({root}).Sync(); if (!resources) return kDefaultInterval; // TODO(crbug.com/726842): It might make sense here to pick the output that // the window is on. On the other hand, if compositing is enabled, all drawing // might be synced to the primary output anyway. Needs investigation. - RROutput primary_output = XRRGetOutputPrimary(display, root); + auto output_primary = randr.GetOutputPrimary({root}).Sync(); + if (!output_primary) + return kDefaultInterval; + x11::RandR::Output primary_output = output_primary->output; bool disconnected_primary = false; - for (int i = 0; i < resources->noutput; i++) { + for (size_t i = 0; i < resources->outputs.size(); i++) { if (!disconnected_primary && resources->outputs[i] != primary_output) continue; - gfx::XScopedPtr<XRROutputInfo, - gfx::XObjectDeleter<XRROutputInfo, void, XRRFreeOutputInfo>> - output_info(XRRGetOutputInfo(display, resources.get(), primary_output)); + auto output_info = + randr.GetOutputInfo({primary_output, resources->config_timestamp}) + .Sync(); if (!output_info) continue; - if (output_info->connection != RR_Connected) { + if (output_info->connection != x11::RandR::RandRConnection::Connected) { // If the primary monitor is disconnected, then start over and choose the // first connected monitor instead. if (!disconnected_primary) { @@ -411,13 +364,13 @@ base::TimeDelta GetPrimaryDisplayRefreshIntervalFromXrandr(Display* display) { } continue; } - gfx::XScopedPtr<XRRCrtcInfo, - gfx::XObjectDeleter<XRRCrtcInfo, void, XRRFreeCrtcInfo>> - crtc(XRRGetCrtcInfo(display, resources.get(), output_info->crtc)); + auto crtc = + randr.GetCrtcInfo({output_info->crtc, resources->config_timestamp}) + .Sync(); if (!crtc) continue; - float refresh_rate = GetRefreshRateFromXRRModeInfo( - resources->modes, resources->nmode, crtc->mode); + float refresh_rate = + GetRefreshRateFromXRRModeInfo(resources->modes, crtc->mode); if (refresh_rate == 0) continue; diff --git a/chromium/ui/base/x/x11_display_util.h b/chromium/ui/base/x/x11_display_util.h index 825d840bab7..7a128004483 100644 --- a/chromium/ui/base/x/x11_display_util.h +++ b/chromium/ui/base/x/x11_display_util.h @@ -16,7 +16,7 @@ namespace ui { // Return the version for xrandr. It multiplies the major number by 100 and // adds the minor like MAJOR * 100 + MINOR. It returns zero if no xrandr is // present. -COMPONENT_EXPORT(UI_BASE_X) int GetXrandrVersion(XDisplay* xdisplay); +COMPONENT_EXPORT(UI_BASE_X) int GetXrandrVersion(); // Builds a list of displays for fallback. COMPONENT_EXPORT(UI_BASE_X) @@ -33,7 +33,7 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo( // Returns the refresh interval of the primary display. If there is no connected // primary display, returns the refresh interval of the first connected display. COMPONENT_EXPORT(UI_BASE_X) -base::TimeDelta GetPrimaryDisplayRefreshIntervalFromXrandr(Display* display); +base::TimeDelta GetPrimaryDisplayRefreshIntervalFromXrandr(); } // namespace ui diff --git a/chromium/ui/base/x/x11_drag_context.cc b/chromium/ui/base/x/x11_drag_context.cc index 3ed9e98b2a2..bdb6df1fd5c 100644 --- a/chromium/ui/base/x/x11_drag_context.cc +++ b/chromium/ui/base/x/x11_drag_context.cc @@ -4,11 +4,15 @@ #include "ui/base/x/x11_drag_context.h" +#include "base/logging.h" +#include "base/memory/ref_counted_memory.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/x/x11_drag_drop_client.h" #include "ui/base/x/x11_util.h" #include "ui/events/platform/platform_event_source.h" +#include "ui/gfx/x/connection.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -36,15 +40,15 @@ const char kChromiumDragReciever[] = "_CHROMIUM_DRAG_RECEIVER"; } // namespace -XDragContext::XDragContext(XID local_window, - const XClientMessageEvent& event, +XDragContext::XDragContext(x11::Window local_window, + const x11::ClientMessageEvent& event, XDragDropClient* source_client, const SelectionFormatMap& data) : local_window_(local_window), - source_window_(event.data.l[0]), + source_window_(static_cast<x11::Window>(event.data.data32[0])), source_client_(source_client) { if (!source_client_) { - bool get_types_from_property = ((event.data.l[1] & 1) != 0); + bool get_types_from_property = ((event.data.data32[1] & 1) != 0); if (get_types_from_property) { if (!GetAtomArrayProperty(source_window_, kXdndTypeList, @@ -54,20 +58,22 @@ XDragContext::XDragContext(XID local_window, } else { // data.l[2,3,4] contain the first three types. Unused slots can be None. for (size_t i = 2; i < 5; ++i) { - if (event.data.l[i] != x11::None) - unfetched_targets_.push_back(event.data.l[i]); + if (event.data.data32[i]) { + unfetched_targets_.push_back( + static_cast<x11::Atom>(event.data.data32[i])); + } } } #if DCHECK_IS_ON() DVLOG(1) << "XdndEnter has " << unfetched_targets_.size() << " data types"; - for (Atom target : unfetched_targets_) - DVLOG(1) << "XdndEnter data type: " << target; + for (x11::Atom target : unfetched_targets_) + DVLOG(1) << "XdndEnter data type: " << static_cast<uint32_t>(target); #endif // DCHECK_IS_ON() // We must perform a full sync here because we could be racing // |source_window_|. - XSync(gfx::GetXDisplay(), x11::False); + x11::Connection::Get()->Sync(); } else { // This drag originates from an aura window within our process. This means // that we can shortcut the X11 server and ask the owning SelectionOwner @@ -81,9 +87,9 @@ XDragContext::XDragContext(XID local_window, XDragContext::~XDragContext() = default; void XDragContext::OnXdndPositionMessage(XDragDropClient* client, - Atom suggested_action, - XID source_window, - Time time_stamp, + x11::Atom suggested_action, + x11::Window source_window, + x11::Time time_stamp, const gfx::Point& screen_point) { DCHECK_EQ(source_window_, source_window); suggested_action_ = suggested_action; @@ -108,15 +114,15 @@ void XDragContext::RequestNextTarget() { DCHECK(drag_drop_client_); DCHECK(waiting_to_handle_position_); - Atom target = unfetched_targets_.back(); + x11::Atom target = unfetched_targets_.back(); unfetched_targets_.pop_back(); - XConvertSelection(gfx::GetXDisplay(), gfx::GetAtom(kXdndSelection), target, - gfx::GetAtom(kChromiumDragReciever), local_window_, - position_time_stamp_); + x11::Connection::Get()->ConvertSelection( + {local_window_, gfx::GetAtom(kXdndSelection), target, + gfx::GetAtom(kChromiumDragReciever), position_time_stamp_}); } -void XDragContext::OnSelectionNotify(const XSelectionEvent& event) { +void XDragContext::OnSelectionNotify(const x11::SelectionNotifyEvent& event) { if (!waiting_to_handle_position_) { // A misbehaved window may send SelectionNotify without us requesting data // via XConvertSelection(). @@ -124,23 +130,24 @@ void XDragContext::OnSelectionNotify(const XSelectionEvent& event) { } DCHECK(drag_drop_client_); - DVLOG(1) << "SelectionNotify, format " << event.target; + DVLOG(1) << "SelectionNotify, format " << static_cast<uint32_t>(event.target); - if (event.property != x11::None) { - DCHECK_EQ(event.property, gfx::GetAtom(kChromiumDragReciever)); + auto property = static_cast<x11::Atom>(event.property); + auto target = static_cast<x11::Atom>(event.target); - scoped_refptr<base::RefCountedMemory> data; - Atom type = x11::None; - if (GetRawBytesOfProperty(local_window_, event.property, &data, nullptr, - &type)) { - fetched_targets_.Insert(event.target, data); - } + if (event.property != x11::Atom::None) { + DCHECK_EQ(property, gfx::GetAtom(kChromiumDragReciever)); + + std::vector<uint8_t> data; + x11::Atom type = x11::Atom::None; + if (GetRawBytesOfProperty(local_window_, property, &data, &type)) + fetched_targets_.Insert(target, base::RefCountedBytes::TakeVector(&data)); } else { // The source failed to convert the drop data to the format (target in X11 // parlance) that we asked for. This happens, even though we only ask for // the formats advertised by the source. http://crbug.com/628099 LOG(ERROR) << "XConvertSelection failed for source-advertised target " - << event.target; + << static_cast<uint32_t>(event.target); } if (!unfetched_targets_.empty()) { @@ -154,7 +161,7 @@ void XDragContext::OnSelectionNotify(const XSelectionEvent& event) { void XDragContext::ReadActions() { if (!source_client_) { - std::vector<Atom> atom_array; + std::vector<x11::Atom> atom_array; if (!GetAtomArrayProperty(source_window_, kXdndActionList, &atom_array)) actions_.clear(); else @@ -177,7 +184,7 @@ int XDragContext::GetDragOperation() const { return drag_operation; } -void XDragContext::MaskOperation(Atom xdnd_operation, +void XDragContext::MaskOperation(x11::Atom xdnd_operation, int* drag_operation) const { if (xdnd_operation == gfx::GetAtom(kXdndActionCopy)) *drag_operation |= DragDropTypes::DRAG_COPY; @@ -187,9 +194,9 @@ void XDragContext::MaskOperation(Atom xdnd_operation, *drag_operation |= DragDropTypes::DRAG_LINK; } -bool XDragContext::DispatchXEvent(XEvent* xev) { - if (xev->type == PropertyNotify && - xev->xproperty.atom == gfx::GetAtom(kXdndActionList)) { +bool XDragContext::DispatchPropertyNotifyEvent( + const x11::PropertyNotifyEvent& prop) { + if (prop.atom == gfx::GetAtom(kXdndActionList)) { ReadActions(); return true; } diff --git a/chromium/ui/base/x/x11_drag_context.h b/chromium/ui/base/x/x11_drag_context.h index 386ca2810e6..33cfea53651 100644 --- a/chromium/ui/base/x/x11_drag_context.h +++ b/chromium/ui/base/x/x11_drag_context.h @@ -12,7 +12,9 @@ #include "ui/base/x/selection_utils.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -20,8 +22,8 @@ class XDragDropClient; class COMPONENT_EXPORT(UI_BASE_X) XDragContext { public: - XDragContext(XID local_window, - const XClientMessageEvent& event, + XDragContext(x11::Window local_window, + const x11::ClientMessageEvent& event, XDragDropClient* source_client, const SelectionFormatMap& data); ~XDragContext(); @@ -29,7 +31,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragContext { XDragContext(const XDragContext&) = delete; XDragContext& operator=(const XDragContext&) = delete; - XID source_window() const { return source_window_; } + x11::Window source_window() const { return source_window_; } XDragDropClient* source_client() { return source_client_; } const SelectionFormatMap& fetched_targets() const { return fetched_targets_; } @@ -38,13 +40,13 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragContext { // message. If we have that data already, dispatch immediately. Otherwise, // delay dispatching until we do. void OnXdndPositionMessage(XDragDropClient* client, - Atom suggested_action, - XID source_window, - Time time_stamp, + x11::Atom suggested_action, + x11::Window source_window, + x11::Time time_stamp, const gfx::Point& screen_point); // Called when XSelection data has been copied to our process. - void OnSelectionNotify(const XSelectionEvent& xselection); + void OnSelectionNotify(const x11::SelectionNotifyEvent& xselection); // Reads the kXdndActionList property from |source_window_| and copies it // into |actions_|. @@ -54,7 +56,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragContext { // action list. int GetDragOperation() const; - bool DispatchXEvent(XEvent* event); + bool DispatchPropertyNotifyEvent(const x11::PropertyNotifyEvent& event); private: // Called to request the next target from the source window. This is only @@ -64,13 +66,13 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragContext { // Masks the X11 atom |xdnd_operation|'s views representation onto // |drag_operation|. - void MaskOperation(Atom xdnd_operation, int* drag_operation) const; + void MaskOperation(x11::Atom xdnd_operation, int* drag_operation) const; - // The XID of our chrome local aura window handling our events. - XID local_window_; + // The x11::Window of our chrome local aura window handling our events. + x11::Window local_window_; - // The XID of the window that initiated the drag. - XID source_window_; + // The x11::Window of the window that initiated the drag. + x11::Window source_window_; // The DesktopDragDropClientAuraX11 for |source_window_| if |source_window_| // belongs to a Chrome window. @@ -89,21 +91,21 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragContext { // The time stamp of the last XdndPosition event we received. The XDND // specification mandates that we use this time stamp when querying the source // about the drag and drop data. - Time position_time_stamp_; + x11::Time position_time_stamp_; // A SelectionFormatMap of data that we have in our process. SelectionFormatMap fetched_targets_; // The names of various data types offered by the other window that we // haven't fetched and put in |fetched_targets_| yet. - std::vector<Atom> unfetched_targets_; + std::vector<x11::Atom> unfetched_targets_; // XdndPosition messages have a suggested action. Qt applications exclusively // use this, instead of the XdndActionList which is backed by |actions_|. - Atom suggested_action_ = x11::None; + x11::Atom suggested_action_ = x11::Atom::None; // Possible actions. - std::vector<Atom> actions_; + std::vector<x11::Atom> actions_; }; } // namespace ui diff --git a/chromium/ui/base/x/x11_drag_drop_client.cc b/chromium/ui/base/x/x11_drag_drop_client.cc index 6329bd377f0..3eccf0b276d 100644 --- a/chromium/ui/base/x/x11_drag_drop_client.cc +++ b/chromium/ui/base/x/x11_drag_drop_client.cc @@ -5,11 +5,14 @@ #include "ui/base/x/x11_drag_drop_client.h" #include "base/lazy_instance.h" +#include "base/logging.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/x/x11_os_exchange_data_provider.h" #include "ui/base/x/x11_util.h" +#include "ui/gfx/x/connection.h" #include "ui/gfx/x/x11_atom_cache.h" +#include "ui/gfx/x/xproto.h" // Reading recommended for understanding the implementation in this file: // @@ -112,12 +115,12 @@ const char kXdndPosition[] = "XdndPosition"; // action will be taken if the drop is accepted. const char kXdndStatus[] = "XdndStatus"; -static base::LazyInstance<std::map<XID, XDragDropClient*>>::Leaky +static base::LazyInstance<std::map<x11::Window, XDragDropClient*>>::Leaky g_live_client_map = LAZY_INSTANCE_INITIALIZER; // Converts a bitfield of actions into an Atom that represents what action // we're most likely to take on drop. -Atom XDragOperationToAtom(int drag_operation) { +x11::Atom XDragOperationToAtom(int drag_operation) { if (drag_operation & DragDropTypes::DRAG_COPY) return gfx::GetAtom(kXdndActionCopy); if (drag_operation & DragDropTypes::DRAG_MOVE) @@ -125,11 +128,11 @@ Atom XDragOperationToAtom(int drag_operation) { if (drag_operation & DragDropTypes::DRAG_LINK) return gfx::GetAtom(kXdndActionLink); - return x11::None; + return x11::Atom::None; } // Converts a single action atom to a drag operation. -DragDropTypes::DragOperation XAtomToDragOperation(Atom atom) { +DragDropTypes::DragOperation AtomToDragOperation(x11::Atom atom) { if (atom == gfx::GetAtom(kXdndActionCopy)) return DragDropTypes::DRAG_COPY; if (atom == gfx::GetAtom(kXdndActionMove)) @@ -143,34 +146,34 @@ DragDropTypes::DragOperation XAtomToDragOperation(Atom atom) { } // namespace int XGetMaskAsEventFlags() { - XDisplay* display = gfx::GetXDisplay(); + x11::KeyButMask mask{}; + auto* connection = x11::Connection::Get(); + if (auto reply = + connection->QueryPointer({connection->default_root()}).Sync()) { + mask = reply->mask; + } - XID root, child; - int root_x, root_y, win_x, win_y; - unsigned int mask; - XQueryPointer(display, DefaultRootWindow(display), &root, &child, &root_x, - &root_y, &win_x, &win_y, &mask); int modifiers = ui::EF_NONE; - if (mask & ShiftMask) + if (static_cast<bool>(mask & x11::KeyButMask::Shift)) modifiers |= ui::EF_SHIFT_DOWN; - if (mask & ControlMask) + if (static_cast<bool>(mask & x11::KeyButMask::Control)) modifiers |= ui::EF_CONTROL_DOWN; - if (mask & Mod1Mask) + if (static_cast<bool>(mask & x11::KeyButMask::Mod1)) modifiers |= ui::EF_ALT_DOWN; - if (mask & Mod4Mask) + if (static_cast<bool>(mask & x11::KeyButMask::Mod4)) modifiers |= ui::EF_COMMAND_DOWN; - if (mask & Button1Mask) + if (static_cast<bool>(mask & x11::KeyButMask::Button1)) modifiers |= ui::EF_LEFT_MOUSE_BUTTON; - if (mask & Button2Mask) + if (static_cast<bool>(mask & x11::KeyButMask::Button2)) modifiers |= ui::EF_MIDDLE_MOUSE_BUTTON; - if (mask & Button3Mask) + if (static_cast<bool>(mask & x11::KeyButMask::Button3)) modifiers |= ui::EF_RIGHT_MOUSE_BUTTON; return modifiers; } // static -XDragDropClient* XDragDropClient::GetForWindow(XID window) { - std::map<XID, XDragDropClient*>::const_iterator it = +XDragDropClient* XDragDropClient::GetForWindow(x11::Window window) { + std::map<x11::Window, XDragDropClient*>::const_iterator it = g_live_client_map.Get().find(window); if (it == g_live_client_map.Get().end()) return nullptr; @@ -178,16 +181,14 @@ XDragDropClient* XDragDropClient::GetForWindow(XID window) { } XDragDropClient::XDragDropClient(XDragDropClient::Delegate* delegate, - Display* xdisplay, - XID xwindow) - : delegate_(delegate), xdisplay_(xdisplay), xwindow_(xwindow) { + x11::Window xwindow) + : delegate_(delegate), xwindow_(xwindow) { DCHECK(delegate_); // Mark that we are aware of drag and drop concepts. - unsigned long xdnd_version = kMaxXdndVersion; - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndAware), XA_ATOM, 32, - PropModeReplace, - reinterpret_cast<unsigned char*>(&xdnd_version), 1); + uint32_t xdnd_version = kMaxXdndVersion; + ui::SetProperty(xwindow_, gfx::GetAtom(kXdndAware), x11::Atom::ATOM, + xdnd_version); // Some tests change the DesktopDragDropClientAuraX11 associated with an // |xwindow|. @@ -198,8 +199,8 @@ XDragDropClient::~XDragDropClient() { g_live_client_map.Get().erase(xwindow()); } -std::vector<Atom> XDragDropClient::GetOfferedDragOperations() const { - std::vector<Atom> operations; +std::vector<x11::Atom> XDragDropClient::GetOfferedDragOperations() const { + std::vector<x11::Atom> operations; if (drag_operation_ & DragDropTypes::DRAG_COPY) operations.push_back(gfx::GetAtom(kXdndActionCopy)); if (drag_operation_ & DragDropTypes::DRAG_MOVE) @@ -209,7 +210,7 @@ std::vector<Atom> XDragDropClient::GetOfferedDragOperations() const { return operations; } -void XDragDropClient::CompleteXdndPosition(XID source_window, +void XDragDropClient::CompleteXdndPosition(x11::Window source_window, const gfx::Point& screen_point) { int drag_operation = delegate_->UpdateDrag(screen_point); @@ -219,11 +220,12 @@ void XDragDropClient::CompleteXdndPosition(XID source_window, // actually making use of this. A client can return (0, 0) and/or set the // first bit of l[1] to disable the feature, and it appears that gtk neither // sets this nor respects it if set. - XEvent xev = PrepareXdndClientMessage(kXdndStatus, source_window); - xev.xclient.data.l[1] = + auto xev = PrepareXdndClientMessage(kXdndStatus, source_window); + xev.data.data32[1] = (drag_operation != 0) ? (kWantFurtherPosEvents | kWillAcceptDrop) : 0; - xev.xclient.data.l[4] = XDragOperationToAtom(drag_operation); - SendXClientEvent(source_window, &xev); + xev.data.data32[4] = + static_cast<uint32_t>(XDragOperationToAtom(drag_operation)); + SendXClientEvent(source_window, xev); } void XDragDropClient::ProcessMouseMove(const gfx::Point& screen_point, @@ -232,26 +234,26 @@ void XDragDropClient::ProcessMouseMove(const gfx::Point& screen_point, return; // Find the current window the cursor is over. - XID dest_window = FindWindowFor(screen_point); + x11::Window dest_window = FindWindowFor(screen_point); - if (source_current_window_ != dest_window) { - if (source_current_window_ != x11::None) - SendXdndLeave(source_current_window_); + if (target_current_window_ != dest_window) { + if (target_current_window_ != x11::Window::None) + SendXdndLeave(target_current_window_); - source_current_window_ = dest_window; + target_current_window_ = dest_window; waiting_on_status_ = false; next_position_message_.reset(); status_received_since_enter_ = false; negotiated_operation_ = DragDropTypes::DRAG_NONE; - if (source_current_window_ != x11::None) { - std::vector<Atom> targets; + if (target_current_window_ != x11::Window::None) { + std::vector<x11::Atom> targets; source_provider_->RetrieveTargets(&targets); - SendXdndEnter(source_current_window_, targets); + SendXdndEnter(target_current_window_, targets); } } - if (source_current_window_ != x11::None) { + if (target_current_window_ != x11::Window::None) { if (waiting_on_status_) { next_position_message_ = std::make_unique<std::pair<gfx::Point, unsigned long>>(screen_point, @@ -262,30 +264,30 @@ void XDragDropClient::ProcessMouseMove(const gfx::Point& screen_point, } } -bool XDragDropClient::HandleXdndEvent(const XClientMessageEvent& event) { - Atom message_type = event.message_type; - if (message_type == gfx::GetAtom("XdndEnter")) { +bool XDragDropClient::HandleXdndEvent(const x11::ClientMessageEvent& event) { + x11::Atom message_type = event.type; + if (message_type == gfx::GetAtom("XdndEnter")) OnXdndEnter(event); - } else if (message_type == gfx::GetAtom("XdndLeave")) { + else if (message_type == gfx::GetAtom("XdndLeave")) OnXdndLeave(event); - } else if (message_type == gfx::GetAtom("XdndPosition")) { + else if (message_type == gfx::GetAtom("XdndPosition")) OnXdndPosition(event); - } else if (message_type == gfx::GetAtom("XdndStatus")) { + else if (message_type == gfx::GetAtom("XdndStatus")) OnXdndStatus(event); - } else if (message_type == gfx::GetAtom("XdndFinished")) { + else if (message_type == gfx::GetAtom("XdndFinished")) OnXdndFinished(event); - } else if (message_type == gfx::GetAtom("XdndDrop")) { + else if (message_type == gfx::GetAtom("XdndDrop")) OnXdndDrop(event); - } else { + else return false; - } return true; } -void XDragDropClient::OnXdndEnter(const XClientMessageEvent& event) { - DVLOG(1) << "OnXdndEnter, version " << ((event.data.l[1] & 0xff000000) >> 24); +void XDragDropClient::OnXdndEnter(const x11::ClientMessageEvent& event) { + DVLOG(1) << "OnXdndEnter, version " + << ((event.data.data32[1] & 0xff000000) >> 24); - int version = (event.data.l[1] & 0xff000000) >> 24; + int version = (event.data.data32[1] & 0xff000000) >> 24; if (version < kMinXdndVersion) { // This protocol version is not documented in the XDND standard (last // revised in 1999), so we don't support it. Since don't understand the @@ -303,7 +305,8 @@ void XDragDropClient::OnXdndEnter(const XClientMessageEvent& event) { // Make sure that we've run ~X11DragContext() before creating another one. ResetDragContext(); - auto* source_client = GetForWindow(event.data.l[0]); + auto* source_client = + GetForWindow(static_cast<x11::Window>(event.data.data32[0])); DCHECK(!source_client || source_client->source_provider_); target_current_context_ = std::make_unique<XDragContext>( xwindow_, event, source_client, @@ -313,7 +316,8 @@ void XDragDropClient::OnXdndEnter(const XClientMessageEvent& event) { if (!target_current_context()->source_client()) { // The window doesn't have a DesktopDragDropClientAuraX11, which means it's // created by some other process. Listen for messages on it. - delegate_->OnBeginForeignDrag(event.data.l[0]); + delegate_->OnBeginForeignDrag( + static_cast<x11::Window>(event.data.data32[0])); } // In the Windows implementation, we immediately call DesktopDropTargetWin:: @@ -322,14 +326,14 @@ void XDragDropClient::OnXdndEnter(const XClientMessageEvent& event) { // XdndStatus message. } -void XDragDropClient::OnXdndPosition(const XClientMessageEvent& event) { +void XDragDropClient::OnXdndPosition(const x11::ClientMessageEvent& event) { DVLOG(1) << "OnXdndPosition"; - XID source_window = event.data.l[0]; - int x_root_window = event.data.l[2] >> 16; - int y_root_window = event.data.l[2] & 0xffff; - Time time_stamp = event.data.l[3]; - Atom suggested_action = event.data.l[4]; + auto source_window = static_cast<x11::Window>(event.data.data32[0]); + int x_root_window = event.data.data32[2] >> 16; + int y_root_window = event.data.data32[2] & 0xffff; + x11::Time time_stamp = static_cast<x11::Time>(event.data.data32[3]); + x11::Atom suggested_action = static_cast<x11::Atom>(event.data.data32[4]); if (!target_current_context()) { NOTREACHED(); @@ -341,12 +345,12 @@ void XDragDropClient::OnXdndPosition(const XClientMessageEvent& event) { gfx::Point(x_root_window, y_root_window)); } -void XDragDropClient::OnXdndStatus(const XClientMessageEvent& event) { +void XDragDropClient::OnXdndStatus(const x11::ClientMessageEvent& event) { DVLOG(1) << "OnXdndStatus"; - XID source_window = event.data.l[0]; + auto source_window = static_cast<x11::Window>(event.data.data32[0]); - if (source_window != source_current_window_) + if (source_window != target_current_window_) return; if (source_state_ != SourceState::kPendingDrop && @@ -357,9 +361,9 @@ void XDragDropClient::OnXdndStatus(const XClientMessageEvent& event) { waiting_on_status_ = false; status_received_since_enter_ = true; - if (event.data.l[1] & 1) { - Atom atom_operation = event.data.l[4]; - negotiated_operation_ = XAtomToDragOperation(atom_operation); + if (event.data.data32[1] & 1) { + x11::Atom atom_operation = static_cast<x11::Atom>(event.data.data32[4]); + negotiated_operation_ = AtomToDragOperation(atom_operation); } else { negotiated_operation_ = DragDropTypes::DRAG_NONE; } @@ -394,53 +398,55 @@ void XDragDropClient::OnXdndStatus(const XClientMessageEvent& event) { } } -void XDragDropClient::OnXdndLeave(const XClientMessageEvent& event) { +void XDragDropClient::OnXdndLeave(const x11::ClientMessageEvent& event) { DVLOG(1) << "OnXdndLeave"; delegate_->OnBeforeDragLeave(); ResetDragContext(); } -void XDragDropClient::OnXdndDrop(const XClientMessageEvent& event) { +void XDragDropClient::OnXdndDrop(const x11::ClientMessageEvent& event) { DVLOG(1) << "OnXdndDrop"; - XID source_window = event.data.l[0]; + auto source_window = static_cast<x11::Window>(event.data.data32[0]); int drag_operation = delegate_->PerformDrop(); - XEvent xev = PrepareXdndClientMessage(kXdndFinished, source_window); - xev.xclient.data.l[1] = (drag_operation != 0) ? 1 : 0; - xev.xclient.data.l[2] = XDragOperationToAtom(drag_operation); - SendXClientEvent(source_window, &xev); + auto xev = PrepareXdndClientMessage(kXdndFinished, source_window); + xev.data.data32[1] = (drag_operation != 0) ? 1 : 0; + xev.data.data32[2] = + static_cast<uint32_t>(XDragOperationToAtom(drag_operation)); + SendXClientEvent(source_window, xev); } -void XDragDropClient::OnXdndFinished(const XClientMessageEvent& event) { +void XDragDropClient::OnXdndFinished(const x11::ClientMessageEvent& event) { DVLOG(1) << "OnXdndFinished"; - XID source_window = event.data.l[0]; - if (source_current_window_ != source_window) + auto source_window = static_cast<x11::Window>(event.data.data32[0]); + if (target_current_window_ != source_window) return; // Clear |negotiated_operation_| if the drag was rejected. - if ((event.data.l[1] & 1) == 0) + if ((event.data.data32[1] & 1) == 0) negotiated_operation_ = DragDropTypes::DRAG_NONE; - // Clear |source_current_window_| to avoid sending XdndLeave upon ending the + // Clear |target_current_window_| to avoid sending XdndLeave upon ending the // move loop. - source_current_window_ = x11::None; + target_current_window_ = x11::Window::None; EndMoveLoop(); } -void XDragDropClient::OnSelectionNotify(const XSelectionEvent& xselection) { +void XDragDropClient::OnSelectionNotify( + const x11::SelectionNotifyEvent& xselection) { DVLOG(1) << "OnSelectionNotify"; if (target_current_context_) target_current_context_->OnSelectionNotify(xselection); // ICCCM requires us to delete the property passed into SelectionNotify. - if (xselection.property != x11::None) - XDeleteProperty(xdisplay_, xwindow_, xselection.property); + if (xselection.property != x11::Atom::None) + ui::DeleteProperty(xwindow_, xselection.property); } void XDragDropClient::InitDrag(int operation, const OSExchangeData* data) { - source_current_window_ = x11::None; + target_current_window_ = x11::Window::None; source_state_ = SourceState::kOther; waiting_on_status_ = false; next_position_message_.reset(); @@ -452,7 +458,7 @@ void XDragDropClient::InitDrag(int operation, const OSExchangeData* data) { static_cast<const XOSExchangeDataProvider*>(&data->provider()); source_provider_->TakeOwnershipOfSelection(); - std::vector<Atom> actions = GetOfferedDragOperations(); + std::vector<x11::Atom> actions = GetOfferedDragOperations(); if (!source_provider_->file_contents_name().empty()) { actions.push_back(gfx::GetAtom(kXdndActionDirectSave)); SetStringProperty(xwindow_, gfx::GetAtom(kXdndDirectSave0), @@ -464,8 +470,8 @@ void XDragDropClient::InitDrag(int operation, const OSExchangeData* data) { void XDragDropClient::CleanupDrag() { source_provider_ = nullptr; - XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndActionList)); - XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom(kXdndDirectSave0)); + ui::DeleteProperty(xwindow_, gfx::GetAtom(kXdndActionList)); + ui::DeleteProperty(xwindow_, gfx::GetAtom(kXdndDirectSave0)); } void XDragDropClient::UpdateModifierState(int flags) { @@ -516,7 +522,7 @@ void XDragDropClient::HandleMouseReleased() { return; } - if (source_current_window_ != x11::None) { + if (target_current_window_ != x11::Window::None) { if (waiting_on_status_) { if (status_received_since_enter_) { // If we are waiting for an XdndStatus message, we need to wait for it @@ -543,8 +549,12 @@ void XDragDropClient::HandleMouseReleased() { // We have negotiated an action with the other end. source_state_ = SourceState::kDropped; - SendXdndDrop(source_current_window_); + SendXdndDrop(target_current_window_); return; + } else { + // No transfer is negotiated. We need to tell the target window that we + // are leaving. + SendXdndLeave(target_current_window_); } } @@ -552,36 +562,33 @@ void XDragDropClient::HandleMouseReleased() { } void XDragDropClient::HandleMoveLoopEnded() { - if (source_current_window_ != x11::None) { - SendXdndLeave(source_current_window_); - source_current_window_ = x11::None; + if (target_current_window_ != x11::Window::None) { + SendXdndLeave(target_current_window_); + target_current_window_ = x11::Window::None; } ResetDragContext(); StopRepeatMouseMoveTimer(); StopEndMoveLoopTimer(); } -XEvent XDragDropClient::PrepareXdndClientMessage(const char* message, - XID recipient) const { - XEvent xev; - xev.xclient.type = ClientMessage; - xev.xclient.message_type = gfx::GetAtom(message); - xev.xclient.format = 32; - xev.xclient.window = recipient; - xev.xclient.data.l[0] = xwindow_; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - xev.xclient.data.l[4] = 0; +x11::ClientMessageEvent XDragDropClient::PrepareXdndClientMessage( + const char* message, + x11::Window recipient) const { + x11::ClientMessageEvent xev; + xev.type = gfx::GetAtom(message); + xev.window = recipient; + xev.format = 32; + xev.data.data32.fill(0); + xev.data.data32[0] = static_cast<uint32_t>(xwindow_); return xev; } -XID XDragDropClient::FindWindowFor(const gfx::Point& screen_point) { +x11::Window XDragDropClient::FindWindowFor(const gfx::Point& screen_point) { auto finder = delegate_->CreateWindowFinder(); - XID target = finder->FindWindowAt(screen_point); + x11::Window target = finder->FindWindowAt(screen_point); - if (target == x11::None) - return x11::None; + if (target == x11::Window::None) + return x11::Window::None; // TODO(crbug/651775): The proxy window should be reported separately from the // target window. XDND messages should be sent to the proxy, and their @@ -590,22 +597,21 @@ XID XDragDropClient::FindWindowFor(const gfx::Point& screen_point) { // Figure out which window we should test as XdndAware. If |target| has // XdndProxy, it will set that proxy on target, and if not, |target|'s // original value will remain. - GetXIDProperty(target, kXdndProxy, &target); + GetProperty(target, gfx::GetAtom(kXdndProxy), &target); int version; if (GetIntProperty(target, kXdndAware, &version) && version >= kMaxXdndVersion) { return target; } - return x11::None; + return x11::Window::None; } -void XDragDropClient::SendXClientEvent(XID xid, XEvent* xev) { - DCHECK_EQ(ClientMessage, xev->type); - +void XDragDropClient::SendXClientEvent(x11::Window window, + const x11::ClientMessageEvent& xev) { // Don't send messages to the X11 message queue if we can help it. - XDragDropClient* short_circuit = GetForWindow(xid); - if (short_circuit && short_circuit->HandleXdndEvent(xev->xclient)) + XDragDropClient* short_circuit = GetForWindow(window); + if (short_circuit && short_circuit->HandleXdndEvent(xev)) return; // I don't understand why the GTK+ code is doing what it's doing here. It @@ -617,36 +623,37 @@ void XDragDropClient::SendXClientEvent(XID xid, XEvent* xev) { // // I'm unsure if I have to jump through those hoops, or if XSendEvent is // sufficient. - XSendEvent(xdisplay_, xid, x11::False, 0, xev); + ui::SendEvent(xev, window, x11::EventMask::NoEvent); } -void XDragDropClient::SendXdndEnter(XID dest_window, - const std::vector<Atom>& targets) { - XEvent xev = PrepareXdndClientMessage(kXdndEnter, dest_window); - xev.xclient.data.l[1] = (kMaxXdndVersion << 24); // The version number. +void XDragDropClient::SendXdndEnter(x11::Window dest_window, + const std::vector<x11::Atom>& targets) { + auto xev = PrepareXdndClientMessage(kXdndEnter, dest_window); + xev.data.data32[1] = (kMaxXdndVersion << 24); // The version number. if (targets.size() > 3) { - xev.xclient.data.l[1] |= 1; + xev.data.data32[1] |= 1; SetAtomArrayProperty(xwindow(), kXdndTypeList, "ATOM", targets); } else { // Pack the targets into the enter message. for (size_t i = 0; i < targets.size(); ++i) - xev.xclient.data.l[2 + i] = targets[i]; + xev.data.data32[2 + i] = static_cast<uint32_t>(targets[i]); } - SendXClientEvent(dest_window, &xev); + SendXClientEvent(dest_window, xev); } -void XDragDropClient::SendXdndPosition(XID dest_window, +void XDragDropClient::SendXdndPosition(x11::Window dest_window, const gfx::Point& screen_point, unsigned long event_time) { waiting_on_status_ = true; - XEvent xev = PrepareXdndClientMessage(kXdndPosition, dest_window); - xev.xclient.data.l[2] = (screen_point.x() << 16) | screen_point.y(); - xev.xclient.data.l[3] = event_time; - xev.xclient.data.l[4] = XDragOperationToAtom(drag_operation_); - SendXClientEvent(dest_window, &xev); + auto xev = PrepareXdndClientMessage(kXdndPosition, dest_window); + xev.data.data32[2] = (screen_point.x() << 16) | screen_point.y(); + xev.data.data32[3] = event_time; + xev.data.data32[4] = + static_cast<uint32_t>(XDragOperationToAtom(drag_operation_)); + SendXClientEvent(dest_window, xev); // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html and // the Xdnd protocol both recommend that drag events should be sent @@ -657,20 +664,20 @@ void XDragDropClient::SendXdndPosition(XID dest_window, screen_point, event_time)); } -void XDragDropClient::SendXdndLeave(XID dest_window) { - XEvent xev = PrepareXdndClientMessage(kXdndLeave, dest_window); - SendXClientEvent(dest_window, &xev); +void XDragDropClient::SendXdndLeave(x11::Window dest_window) { + auto xev = PrepareXdndClientMessage(kXdndLeave, dest_window); + SendXClientEvent(dest_window, xev); } -void XDragDropClient::SendXdndDrop(XID dest_window) { - XEvent xev = PrepareXdndClientMessage(kXdndDrop, dest_window); - xev.xclient.data.l[2] = x11::CurrentTime; - SendXClientEvent(dest_window, &xev); +void XDragDropClient::SendXdndDrop(x11::Window dest_window) { + auto xev = PrepareXdndClientMessage(kXdndDrop, dest_window); + xev.data.data32[2] = x11::CurrentTime; + SendXClientEvent(dest_window, xev); } void XDragDropClient::EndMoveLoop() { StopEndMoveLoopTimer(); - delegate_->EndMoveLoop(); + delegate_->EndDragLoop(); } } // namespace ui diff --git a/chromium/ui/base/x/x11_drag_drop_client.h b/chromium/ui/base/x/x11_drag_drop_client.h index 9a0df14cf71..1d7e6a32caf 100644 --- a/chromium/ui/base/x/x11_drag_drop_client.h +++ b/chromium/ui/base/x/x11_drag_drop_client.h @@ -15,6 +15,7 @@ #include "ui/base/x/x11_topmost_window_finder.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/x/x11.h" +#include "ui/gfx/x/xproto.h" namespace ui { @@ -49,7 +50,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { DragDropTypes::DragOperation negotiated_operation) = 0; // Called when data from another application enters the window. - virtual void OnBeginForeignDrag(XID window) = 0; + virtual void OnBeginForeignDrag(x11::Window window) = 0; // Called when data from another application is about to leave the window. virtual void OnEndForeignDrag() = 0; @@ -60,19 +61,19 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { // Drops data at the current location and returns the resulting operation. virtual int PerformDrop() = 0; - // Called to end the move loop that is maintained by the subclass. - virtual void EndMoveLoop() = 0; + // Called to end the drag loop that is maintained by the subclass. + virtual void EndDragLoop() = 0; protected: virtual ~Delegate() = default; }; - XDragDropClient(Delegate* delegate, Display* xdisplay, XID xwindow); + XDragDropClient(Delegate* delegate, x11::Window xwindow); virtual ~XDragDropClient(); XDragDropClient(const XDragDropClient&) = delete; XDragDropClient& operator=(const XDragDropClient&) = delete; - XID xwindow() const { return xwindow_; } + x11::Window xwindow() const { return xwindow_; } XDragContext* target_current_context() { return target_current_context_.get(); } @@ -84,7 +85,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { // Handling XdndPosition can be paused while waiting for more data; this is // called either synchronously from OnXdndPosition, or asynchronously after // we've received data requested from the other window. - void CompleteXdndPosition(XID source_window, const gfx::Point& screen_point); + void CompleteXdndPosition(x11::Window source_window, + const gfx::Point& screen_point); void ProcessMouseMove(const gfx::Point& screen_point, unsigned long event_time); @@ -92,12 +94,12 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { // During the blocking StartDragAndDrop() call, this converts the views-style // |drag_operation_| bitfield into a vector of Atoms to offer to other // processes. - std::vector<Atom> GetOfferedDragOperations() const; + std::vector<x11::Atom> GetOfferedDragOperations() const; // Tries to handle the XDND event. Returns true for all known event types: // XdndEnter, XdndLeave, XdndPosition, XdndStatus, XdndDrop, and XdndFinished; // returns false if an event of an unexpected type has been passed. - bool HandleXdndEvent(const XClientMessageEvent& event); + bool HandleXdndEvent(const x11::ClientMessageEvent& event); // These |Handle...| methods essentially implement the // views::X11MoveLoopDelegate interface. @@ -108,7 +110,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { void HandleMoveLoopEnded(); // Called when XSelection data has been copied to our process. - void OnSelectionNotify(const XSelectionEvent& xselection); + void OnSelectionNotify(const x11::SelectionNotifyEvent& xselection); // Resets the drag state so the object is ready to handle the drag. Sets // X window properties so that the desktop environment is aware of available @@ -156,53 +158,54 @@ class COMPONENT_EXPORT(UI_BASE_X) XDragDropClient { private: // These methods handle the various X11 client messages from the platform. - void OnXdndEnter(const XClientMessageEvent& event); - void OnXdndPosition(const XClientMessageEvent& event); - void OnXdndStatus(const XClientMessageEvent& event); - void OnXdndLeave(const XClientMessageEvent& event); - void OnXdndDrop(const XClientMessageEvent& event); - void OnXdndFinished(const XClientMessageEvent& event); + void OnXdndEnter(const x11::ClientMessageEvent& event); + void OnXdndPosition(const x11::ClientMessageEvent& event); + void OnXdndStatus(const x11::ClientMessageEvent& event); + void OnXdndLeave(const x11::ClientMessageEvent& event); + void OnXdndDrop(const x11::ClientMessageEvent& event); + void OnXdndFinished(const x11::ClientMessageEvent& event); // Creates an XEvent and fills it in with values typical for XDND messages: // the type of event is set to ClientMessage, the format is set to 32 (longs), // and the zero member of data payload is set to |xwindow_|. All other data // members are zeroed, as per XDND specification. - XEvent PrepareXdndClientMessage(const char* message, XID recipient) const; + x11::ClientMessageEvent PrepareXdndClientMessage(const char* message, + x11::Window recipient) const; // Finds the topmost X11 window at |screen_point| and returns it if it is // Xdnd aware. Returns x11::None otherwise. // Virtual for testing. - virtual XID FindWindowFor(const gfx::Point& screen_point); + virtual x11::Window FindWindowFor(const gfx::Point& screen_point); - // Sends |xev| to |xid|, optionally short circuiting the round trip to the X - // server. - // Virtual for testing. - virtual void SendXClientEvent(XID xid, XEvent* xev); + // Sends |xev| to |window|, optionally short circuiting the round trip to the + // X server. Virtual for testing. + virtual void SendXClientEvent(x11::Window window, + const x11::ClientMessageEvent& xev); - void SendXdndEnter(XID dest_window, const std::vector<Atom>& targets); - void SendXdndPosition(XID dest_window, + void SendXdndEnter(x11::Window dest_window, + const std::vector<x11::Atom>& targets); + void SendXdndPosition(x11::Window dest_window, const gfx::Point& screen_point, unsigned long event_time); - void SendXdndLeave(XID dest_window); - void SendXdndDrop(XID dest_window); + void SendXdndLeave(x11::Window dest_window); + void SendXdndDrop(x11::Window dest_window); // We maintain a mapping of live XDragDropClient objects to their X11 windows, // so that we'd able to short circuit sending X11 messages to windows in our // process. - static XDragDropClient* GetForWindow(XID window); + static XDragDropClient* GetForWindow(x11::Window window); void EndMoveLoop(); Delegate* const delegate_; - Display* const xdisplay_; - const XID xwindow_; + const x11::Window xwindow_; // Target side information. + x11::Window target_current_window_ = x11::Window::None; std::unique_ptr<XDragContext> target_current_context_; // Source side information. - XID source_current_window_ = x11::None; SourceState source_state_ = SourceState::kOther; const XOSExchangeDataProvider* source_provider_ = nullptr; diff --git a/chromium/ui/base/x/x11_error_handler.cc b/chromium/ui/base/x/x11_error_handler.cc new file mode 100644 index 00000000000..d1babb0bcbd --- /dev/null +++ b/chromium/ui/base/x/x11_error_handler.cc @@ -0,0 +1,104 @@ +// Copyright 2020 The Chromium Authors. All 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/x/x11_error_handler.h" + +#include "base/check.h" +#include "base/compiler_specific.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/message_loop/message_loop_current.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "ui/base/x/x11_util.h" +#include "ui/base/x/x11_util_internal.h" +#include "ui/gfx/x/xproto_util.h" + +namespace ui { + +namespace { + +// Indicates that we're currently responding to an IO error (by shutting down). +bool g_in_x11_io_error_handler = false; + +base::LazyInstance<base::OnceClosure>::Leaky g_shutdown_cb = + LAZY_INSTANCE_INITIALIZER; + +// Number of seconds to wait for UI thread to get an IO error if we get it on +// the background thread. +const int kWaitForUIThreadSeconds = 10; + +int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) { + if (!g_in_x11_io_error_handler) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&x11::LogErrorEventDescription, *error)); + } + return 0; +} + +// This function is used to help us diagnose crash dumps that happen +// during the shutdown process. +NOINLINE void WaitingForUIThreadToHandleIOError() { + // Ensure function isn't optimized away. + asm(""); + sleep(kWaitForUIThreadSeconds); +} + +int BrowserX11IOErrorHandler(Display* d) { + if (!base::MessageLoopCurrentForUI::IsSet()) { + // Wait for the UI thread (which has a different connection to the X server) + // to get the error. We can't call shutdown from this thread without + // tripping an error. Doing it through a function so that we'll be able + // to see it in any crash dumps. + WaitingForUIThreadToHandleIOError(); + return 0; + } + + // If there's an IO error it likely means the X server has gone away. + // If this CHECK fails, then that means SessionEnding() below triggered some + // code that tried to talk to the X server, resulting in yet another error. + CHECK(!g_in_x11_io_error_handler); + + g_in_x11_io_error_handler = true; + LOG(ERROR) << "X IO error received (X server probably went away)"; + DCHECK(!g_shutdown_cb.Get().is_null()); + std::move(g_shutdown_cb.Get()).Run(); + + return 0; +} + +int X11EmptyErrorHandler(Display* d, XErrorEvent* error) { + return 0; +} + +int X11EmptyIOErrorHandler(Display* d) { + return 0; +} + +} // namespace + +void SetNullErrorHandlers() { + // Installs the X11 error handlers for the browser process used during + // startup. They simply print error messages and exit because + // we can't shutdown properly while creating and initializing services. + ui::SetX11ErrorHandlers(nullptr, nullptr); +} + +void SetErrorHandlers(base::OnceCallback<void()> shutdown_cb) { + // Installs the X11 error handlers for the browser process after the + // main message loop has started. This will allow us to exit cleanly + // if X exits before we do. + DCHECK(g_shutdown_cb.Get().is_null()); + g_shutdown_cb.Get() = std::move(shutdown_cb); + ui::SetX11ErrorHandlers(BrowserX11ErrorHandler, BrowserX11IOErrorHandler); +} + +void SetEmptyErrorHandlers() { + // Unset the X11 error handlers. The X11 error handlers log the errors using a + // |PostTask()| on the message-loop. But since the message-loop is in the + // process of terminating, this can cause errors. + ui::SetX11ErrorHandlers(X11EmptyErrorHandler, X11EmptyIOErrorHandler); +} + +} // namespace ui diff --git a/chromium/ui/base/x/x11_error_handler.h b/chromium/ui/base/x/x11_error_handler.h new file mode 100644 index 00000000000..49011beb3d8 --- /dev/null +++ b/chromium/ui/base/x/x11_error_handler.h @@ -0,0 +1,26 @@ +// Copyright 2020 The Chromium Authors. All 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_X_X11_ERROR_HANDLER_H_ +#define UI_BASE_X_X11_ERROR_HANDLER_H_ + +#include "base/callback.h" +#include "base/component_export.h" + +namespace ui { + +// Sets null error handlers that just catch error messages. +COMPONENT_EXPORT(UI_BASE_X) void SetNullErrorHandlers(); + +// Sets error handlers that catch the error messages on ui thread, waits until +// errors are received on io thread, and stops the browser. +COMPONENT_EXPORT(UI_BASE_X) +void SetErrorHandlers(base::OnceCallback<void()> shutdown_cb); + +// Unsets the error handlers. +COMPONENT_EXPORT(UI_BASE_X) void SetEmptyErrorHandlers(); + +} // namespace ui + +#endif // UI_BASE_X_X11_ERROR_HANDLER_H_ diff --git a/chromium/ui/base/x/x11_gl_egl_utility.cc b/chromium/ui/base/x/x11_gl_egl_utility.cc index 2a7fd03779f..197f8e4c553 100644 --- a/chromium/ui/base/x/x11_gl_egl_utility.cc +++ b/chromium/ui/base/x/x11_gl_egl_utility.cc @@ -25,11 +25,11 @@ void GetPlatformExtraDisplayAttribs(EGLenum platform_type, // ANGLE_NULL doesn't use the visual, and may run without X11 where we can't // get it anyway. if (platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) { - Visual* visual; - ui::XVisualManager::GetInstance()->ChooseVisualForWindow( - true, &visual, nullptr, nullptr, nullptr); + x11::VisualId visual_id; + ui::XVisualManager::GetInstance()->ChooseVisualForWindow(true, &visual_id, + nullptr, nullptr); attributes->push_back(EGL_X11_VISUAL_ID_ANGLE); - attributes->push_back(static_cast<EGLAttrib>(XVisualIDFromVisual(visual))); + attributes->push_back(static_cast<EGLAttrib>(visual_id)); } } @@ -38,8 +38,10 @@ void ChoosePlatformCustomAlphaAndBufferSize(EGLint* alpha_size, // If we're using ANGLE_NULL, we may not have a display, in which case we // can't use XVisualManager. if (gl::GLSurfaceEGL::GetNativeDisplay() != EGL_DEFAULT_DISPLAY) { - ui::XVisualManager::GetInstance()->ChooseVisualForWindow( - true, nullptr, buffer_size, nullptr, nullptr); + uint8_t depth; + ui::XVisualManager::GetInstance()->ChooseVisualForWindow(true, nullptr, + &depth, nullptr); + *buffer_size = depth; *alpha_size = *buffer_size == 32 ? 8 : 0; } } diff --git a/chromium/ui/base/x/x11_menu_list.cc b/chromium/ui/base/x/x11_menu_list.cc index 83a5522437b..5cea1a41421 100644 --- a/chromium/ui/base/x/x11_menu_list.cc +++ b/chromium/ui/base/x/x11_menu_list.cc @@ -24,23 +24,23 @@ XMenuList::~XMenuList() { menus_.clear(); } -void XMenuList::MaybeRegisterMenu(XID menu) { +void XMenuList::MaybeRegisterMenu(x11::Window menu) { int value = 0; if (!GetIntProperty(menu, "_NET_WM_WINDOW_TYPE", &value) || - static_cast<XAtom>(value) != menu_type_atom_) { + static_cast<x11::Atom>(value) != menu_type_atom_) { return; } menus_.push_back(menu); } -void XMenuList::MaybeUnregisterMenu(XID menu) { +void XMenuList::MaybeUnregisterMenu(x11::Window menu) { auto iter = std::find(menus_.begin(), menus_.end(), menu); if (iter == menus_.end()) return; menus_.erase(iter); } -void XMenuList::InsertMenuWindowXIDs(std::vector<XID>* stack) { +void XMenuList::InsertMenuWindows(std::vector<x11::Window>* stack) { stack->insert(stack->begin(), menus_.begin(), menus_.end()); } diff --git a/chromium/ui/base/x/x11_menu_list.h b/chromium/ui/base/x/x11_menu_list.h index f4882b8dcb0..8f45b83e50d 100644 --- a/chromium/ui/base/x/x11_menu_list.h +++ b/chromium/ui/base/x/x11_menu_list.h @@ -13,7 +13,8 @@ // A process wide singleton cache for X menus. namespace base { -template <typename T> struct DefaultSingletonTraits; +template <typename T> +struct DefaultSingletonTraits; } namespace ui { @@ -25,21 +26,21 @@ class COMPONENT_EXPORT(UI_BASE_X) XMenuList { // Checks if |menu| has _NET_WM_WINDOW_TYPE property set to // "_NET_WM_WINDOW_TYPE_MENU" atom and if so caches it. - void MaybeRegisterMenu(XID menu); + void MaybeRegisterMenu(x11::Window menu); // Finds |menu| in cache and if found removes it. - void MaybeUnregisterMenu(XID menu); + void MaybeUnregisterMenu(x11::Window menu); - // Inserts cached menu XIDs at the beginning of |stack|. - void InsertMenuWindowXIDs(std::vector<XID>* stack); + // Inserts cached menu x11::Windows at the beginning of |stack|. + void InsertMenuWindows(std::vector<x11::Window>* stack); private: friend struct base::DefaultSingletonTraits<XMenuList>; XMenuList(); ~XMenuList(); - std::vector<XID> menus_; - XAtom menu_type_atom_; + std::vector<x11::Window> menus_; + x11::Atom menu_type_atom_; DISALLOW_COPY_AND_ASSIGN(XMenuList); }; diff --git a/chromium/ui/base/x/x11_menu_registrar.cc b/chromium/ui/base/x/x11_menu_registrar.cc index 2d1d23ff714..2264b4b465b 100644 --- a/chromium/ui/base/x/x11_menu_registrar.cc +++ b/chromium/ui/base/x/x11_menu_registrar.cc @@ -32,8 +32,7 @@ X11MenuRegistrar* X11MenuRegistrar::Get() { } X11MenuRegistrar::X11MenuRegistrar() - : xdisplay_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(xdisplay_)) { + : xdisplay_(gfx::GetXDisplay()), x_root_window_(ui::GetX11RootWindow()) { if (ui::X11EventSource::HasInstance()) ui::X11EventSource::GetInstance()->AddXEventDispatcher(this); @@ -46,16 +45,19 @@ X11MenuRegistrar::~X11MenuRegistrar() { ui::X11EventSource::GetInstance()->RemoveXEventDispatcher(this); } -bool X11MenuRegistrar::DispatchXEvent(XEvent* event) { +bool X11MenuRegistrar::DispatchXEvent(x11::Event* x11_event) { + XEvent* event = &x11_event->xlib_event(); if (event->type != CreateNotify && event->type != DestroyNotify) { return false; } switch (event->type) { case CreateNotify: - OnWindowCreatedOrDestroyed(event->type, event->xcreatewindow.window); + OnWindowCreatedOrDestroyed( + event->type, x11_event->As<x11::CreateNotifyEvent>()->window); break; case DestroyNotify: - OnWindowCreatedOrDestroyed(event->type, event->xdestroywindow.window); + OnWindowCreatedOrDestroyed( + event->type, x11_event->As<x11::DestroyNotifyEvent>()->window); break; default: NOTREACHED(); @@ -63,7 +65,8 @@ bool X11MenuRegistrar::DispatchXEvent(XEvent* event) { return false; } -void X11MenuRegistrar::OnWindowCreatedOrDestroyed(int event_type, XID window) { +void X11MenuRegistrar::OnWindowCreatedOrDestroyed(int event_type, + x11::Window window) { // Menus created by Chrome can be drag and drop targets. Since they are // direct children of the screen root window and have override_redirect // we cannot use regular _NET_CLIENT_LIST_STACKING property to find them diff --git a/chromium/ui/base/x/x11_menu_registrar.h b/chromium/ui/base/x/x11_menu_registrar.h index b3a30a24167..0fe0a83e727 100644 --- a/chromium/ui/base/x/x11_menu_registrar.h +++ b/chromium/ui/base/x/x11_menu_registrar.h @@ -12,6 +12,7 @@ #include <vector> #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_types.h" @@ -29,7 +30,7 @@ class X11MenuRegistrar : public ui::XEventDispatcher { static X11MenuRegistrar* Get(); // ui::XEventDispatcher - bool DispatchXEvent(XEvent* event) override; + bool DispatchXEvent(x11::Event* event) override; private: X11MenuRegistrar(); @@ -37,13 +38,13 @@ class X11MenuRegistrar : public ui::XEventDispatcher { // Called when |window| has been created or destroyed. |window| may not be // managed by Chrome. - void OnWindowCreatedOrDestroyed(int event_type, XID window); + void OnWindowCreatedOrDestroyed(int event_type, x11::Window window); // The display and the native X window hosting the root window. XDisplay* xdisplay_; // The native root window. - ::Window x_root_window_; + x11::Window x_root_window_; // Events selected on |x_root_window_|. std::unique_ptr<ui::XScopedEventSelector> x_root_window_events_; diff --git a/chromium/ui/base/x/x11_os_exchange_data_provider.cc b/chromium/ui/base/x/x11_os_exchange_data_provider.cc index 88a24bab57b..5a38c3f841b 100644 --- a/chromium/ui/base/x/x11_os_exchange_data_provider.cc +++ b/chromium/ui/base/x/x11_os_exchange_data_provider.cc @@ -15,6 +15,7 @@ #include "ui/base/clipboard/clipboard_format_type.h" #include "ui/base/dragdrop/file_info/file_info.h" #include "ui/base/x/selection_utils.h" +#include "ui/base/x/x11_util.h" #include "ui/gfx/x/x11_atom_cache.h" // Note: the GetBlah() methods are used immediately by the @@ -34,38 +35,25 @@ const char kNetscapeURL[] = "_NETSCAPE_URL"; } // namespace XOSExchangeDataProvider::XOSExchangeDataProvider( - XID x_window, + x11::Window x_window, const SelectionFormatMap& selection) - : x_display_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(x_display_)), + : connection_(x11::Connection::Get()), + x_root_window_(ui::GetX11RootWindow()), own_window_(false), x_window_(x_window), format_map_(selection), - selection_owner_(x_display_, x_window_, gfx::GetAtom(kDndSelection)) {} + selection_owner_(connection_, x_window_, gfx::GetAtom(kDndSelection)) {} XOSExchangeDataProvider::XOSExchangeDataProvider() - : x_display_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(x_display_)), + : connection_(x11::Connection::Get()), + x_root_window_(ui::GetX11RootWindow()), own_window_(true), - x_window_(XCreateWindow(x_display_, - x_root_window_, - -100, // x - -100, // y - 10, // width - 10, // height - 0, // border width - CopyFromParent, // depth - InputOnly, - CopyFromParent, // visual - 0, - nullptr)), - selection_owner_(x_display_, x_window_, gfx::GetAtom(kDndSelection)) { - XStoreName(x_display_, x_window_, "Chromium Drag & Drop Window"); -} + x_window_(CreateDummyWindow("Chromium Drag & Drop Window")), + selection_owner_(connection_, x_window_, gfx::GetAtom(kDndSelection)) {} XOSExchangeDataProvider::~XOSExchangeDataProvider() { if (own_window_) - XDestroyWindow(x_display_, x_window_); + connection_->DestroyWindow({x_window_}); } void XOSExchangeDataProvider::TakeOwnershipOfSelection() const { @@ -73,7 +61,7 @@ void XOSExchangeDataProvider::TakeOwnershipOfSelection() const { } void XOSExchangeDataProvider::RetrieveTargets( - std::vector<Atom>* targets) const { + std::vector<x11::Atom>* targets) const { selection_owner_.RetrieveTargets(targets); } @@ -159,7 +147,7 @@ void XOSExchangeDataProvider::SetURL(const GURL& url, void XOSExchangeDataProvider::SetFilename(const base::FilePath& path) { std::vector<FileInfo> data; - data.push_back(FileInfo(path, base::FilePath())); + data.emplace_back(path, base::FilePath()); SetFilenames(data); } @@ -199,8 +187,8 @@ bool XOSExchangeDataProvider::GetString(base::string16* result) const { return false; } - std::vector<Atom> text_atoms = ui::GetTextAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> text_atoms = ui::GetTextAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(text_atoms, GetTargets(), &requested_types); ui::SelectionData data(format_map_.GetFirstOf(requested_types)); @@ -216,8 +204,8 @@ bool XOSExchangeDataProvider::GetString(base::string16* result) const { bool XOSExchangeDataProvider::GetURLAndTitle(FilenameToURLPolicy policy, GURL* url, base::string16* title) const { - std::vector<Atom> url_atoms = ui::GetURLAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> url_atoms = ui::GetURLAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); ui::SelectionData data(format_map_.GetFirstOf(requested_types)); @@ -247,7 +235,8 @@ bool XOSExchangeDataProvider::GetURLAndTitle(FilenameToURLPolicy policy, std::vector<std::string> tokens = ui::ParseURIList(data); for (const std::string& token : tokens) { GURL test_url(token); - if (!test_url.SchemeIsFile() || policy == CONVERT_FILENAMES) { + if (!test_url.SchemeIsFile() || + policy == FilenameToURLPolicy::CONVERT_FILENAMES) { *url = test_url; *title = base::string16(); return true; @@ -271,8 +260,8 @@ bool XOSExchangeDataProvider::GetFilename(base::FilePath* path) const { bool XOSExchangeDataProvider::GetFilenames( std::vector<FileInfo>* filenames) const { - std::vector<Atom> url_atoms = ui::GetURIListAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> url_atoms = ui::GetURIListAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); filenames->clear(); @@ -293,7 +282,7 @@ bool XOSExchangeDataProvider::GetFilenames( bool XOSExchangeDataProvider::GetPickledData(const ClipboardFormatType& format, base::Pickle* pickle) const { - std::vector<Atom> requested_types; + std::vector<x11::Atom> requested_types; requested_types.push_back(gfx::GetAtom(format.GetName().c_str())); ui::SelectionData data(format_map_.GetFirstOf(requested_types)); @@ -309,15 +298,15 @@ bool XOSExchangeDataProvider::GetPickledData(const ClipboardFormatType& format, } bool XOSExchangeDataProvider::HasString() const { - std::vector<Atom> text_atoms = ui::GetTextAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> text_atoms = ui::GetTextAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(text_atoms, GetTargets(), &requested_types); return !requested_types.empty() && !HasFile(); } bool XOSExchangeDataProvider::HasURL(FilenameToURLPolicy policy) const { - std::vector<Atom> url_atoms = ui::GetURLAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> url_atoms = ui::GetURLAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); if (requested_types.empty()) @@ -333,7 +322,8 @@ bool XOSExchangeDataProvider::HasURL(FilenameToURLPolicy policy) const { } else if (data.GetType() == gfx::GetAtom(ui::kMimeTypeURIList)) { std::vector<std::string> tokens = ui::ParseURIList(data); for (const std::string& token : tokens) { - if (!GURL(token).SchemeIsFile() || policy == CONVERT_FILENAMES) + if (!GURL(token).SchemeIsFile() || + policy == FilenameToURLPolicy::CONVERT_FILENAMES) return true; } @@ -345,8 +335,8 @@ bool XOSExchangeDataProvider::HasURL(FilenameToURLPolicy policy) const { } bool XOSExchangeDataProvider::HasFile() const { - std::vector<Atom> url_atoms = ui::GetURIListAtomsFrom(); - std::vector<Atom> requested_types; + std::vector<x11::Atom> url_atoms = ui::GetURIListAtomsFrom(); + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); if (requested_types.empty()) @@ -371,9 +361,9 @@ bool XOSExchangeDataProvider::HasFile() const { bool XOSExchangeDataProvider::HasCustomFormat( const ClipboardFormatType& format) const { - std::vector<Atom> url_atoms; + std::vector<x11::Atom> url_atoms; url_atoms.push_back(gfx::GetAtom(format.GetName().c_str())); - std::vector<Atom> requested_types; + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); return !requested_types.empty(); @@ -395,9 +385,9 @@ void XOSExchangeDataProvider::SetHtml(const base::string16& html, bool XOSExchangeDataProvider::GetHtml(base::string16* html, GURL* base_url) const { - std::vector<Atom> url_atoms; + std::vector<x11::Atom> url_atoms; url_atoms.push_back(gfx::GetAtom(kMimeTypeHTML)); - std::vector<Atom> requested_types; + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); ui::SelectionData data(format_map_.GetFirstOf(requested_types)); @@ -411,9 +401,9 @@ bool XOSExchangeDataProvider::GetHtml(base::string16* html, } bool XOSExchangeDataProvider::HasHtml() const { - std::vector<Atom> url_atoms; + std::vector<x11::Atom> url_atoms; url_atoms.push_back(gfx::GetAtom(kMimeTypeHTML)); - std::vector<Atom> requested_types; + std::vector<x11::Atom> requested_types; GetAtomIntersection(url_atoms, GetTargets(), &requested_types); return !requested_types.empty(); @@ -446,12 +436,12 @@ bool XOSExchangeDataProvider::GetPlainTextURL(GURL* url) const { return false; } -std::vector<Atom> XOSExchangeDataProvider::GetTargets() const { +std::vector<x11::Atom> XOSExchangeDataProvider::GetTargets() const { return format_map_.GetTypes(); } void XOSExchangeDataProvider::InsertData( - Atom format, + x11::Atom format, const scoped_refptr<base::RefCountedMemory>& data) { format_map_.Insert(format, data); } diff --git a/chromium/ui/base/x/x11_os_exchange_data_provider.h b/chromium/ui/base/x/x11_os_exchange_data_provider.h index 6763eb0aea7..214bf950ba1 100644 --- a/chromium/ui/base/x/x11_os_exchange_data_provider.h +++ b/chromium/ui/base/x/x11_os_exchange_data_provider.h @@ -33,7 +33,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider public: // |x_window| is the window the cursor is over, and |selection| is the set of // data being offered. - XOSExchangeDataProvider(XID x_window, const SelectionFormatMap& selection); + XOSExchangeDataProvider(x11::Window x_window, + const SelectionFormatMap& selection); // Creates a Provider for sending drag information. This creates its own, // hidden X11 window to own send data. @@ -50,7 +51,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider // Retrieves a list of types we're offering. Noop if we haven't taken the // selection. - void RetrieveTargets(std::vector<Atom>* targets) const; + void RetrieveTargets(std::vector<x11::Atom>* targets) const; // Makes a copy of the format map currently being offered. SelectionFormatMap GetFormatMap() const; @@ -97,7 +98,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider using PickleData = std::map<ClipboardFormatType, base::Pickle>; bool own_window() const { return own_window_; } - XID x_window() const { return x_window_; } + x11::Window x_window() const { return x_window_; } const SelectionFormatMap& format_map() const { return format_map_; } void set_format_map(const SelectionFormatMap& format_map) { format_map_ = format_map; @@ -112,10 +113,10 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider bool GetPlainTextURL(GURL* url) const; // Returns the targets in |format_map_|. - std::vector<Atom> GetTargets() const; + std::vector<x11::Atom> GetTargets() const; // Inserts data into the format map. - void InsertData(Atom format, + void InsertData(x11::Atom format, const scoped_refptr<base::RefCountedMemory>& data); private: @@ -124,8 +125,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider gfx::Vector2d drag_image_offset_; // Our X11 state. - Display* x_display_; - XID x_root_window_; + x11::Connection* connection_; + x11::Window x_root_window_; // In X11, because the IPC parts of drag operations are implemented by // XSelection, we require an x11 window to receive drag messages on. The @@ -135,7 +136,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XOSExchangeDataProvider // our own xwindow just to receive events on it. const bool own_window_; - XID x_window_; + x11::Window x_window_; // A representation of data. This is either passed to us from the other // process, or built up through a sequence of Set*() calls. It can be passed diff --git a/chromium/ui/base/x/x11_pointer_grab.cc b/chromium/ui/base/x/x11_pointer_grab.cc index 01c0efb666b..b7a65240c02 100644 --- a/chromium/ui/base/x/x11_pointer_grab.cc +++ b/chromium/ui/base/x/x11_pointer_grab.cc @@ -14,14 +14,14 @@ namespace ui { namespace { // The grab window. None if there are no active pointer grabs. -XID g_grab_window = x11::None; +x11::Window g_grab_window = x11::Window::None; // The "owner events" parameter used to grab the pointer. bool g_owner_events = false; } // namespace -int GrabPointer(XID window, bool owner_events, ::Cursor cursor) { +int GrabPointer(x11::Window window, bool owner_events, ::Cursor cursor) { int result = GrabInvalidTime; if (ui::IsXInput2Available()) { // Do an XInput2 pointer grab. If there is an active XInput2 pointer grab @@ -42,9 +42,10 @@ int GrabPointer(XID window, bool owner_events, ::Cursor cursor) { ui::DeviceDataManagerX11::GetInstance()->master_pointers(); for (int master_pointer : master_pointers) { evmask.deviceid = master_pointer; - result = XIGrabDevice(gfx::GetXDisplay(), master_pointer, window, - x11::CurrentTime, cursor, GrabModeAsync, - GrabModeAsync, owner_events, &evmask); + result = + XIGrabDevice(gfx::GetXDisplay(), master_pointer, + static_cast<uint32_t>(window), x11::CurrentTime, cursor, + GrabModeAsync, GrabModeAsync, owner_events, &evmask); // Assume that the grab will succeed on either all or none of the master // pointers. if (result != GrabSuccess) { @@ -56,9 +57,9 @@ int GrabPointer(XID window, bool owner_events, ::Cursor cursor) { if (result != GrabSuccess) { int event_mask = PointerMotionMask | ButtonReleaseMask | ButtonPressMask; - result = XGrabPointer(gfx::GetXDisplay(), window, owner_events, event_mask, - GrabModeAsync, GrabModeAsync, x11::None, cursor, - x11::CurrentTime); + result = XGrabPointer(gfx::GetXDisplay(), static_cast<uint32_t>(window), + owner_events, event_mask, GrabModeAsync, + GrabModeAsync, x11::None, cursor, x11::CurrentTime); } if (result == GrabSuccess) { @@ -69,12 +70,12 @@ int GrabPointer(XID window, bool owner_events, ::Cursor cursor) { } void ChangeActivePointerGrabCursor(::Cursor cursor) { - DCHECK(g_grab_window != x11::None); + DCHECK(g_grab_window != x11::Window::None); GrabPointer(g_grab_window, g_owner_events, cursor); } void UngrabPointer() { - g_grab_window = x11::None; + g_grab_window = x11::Window::None; if (ui::IsXInput2Available()) { const std::vector<int>& master_pointers = ui::DeviceDataManagerX11::GetInstance()->master_pointers(); diff --git a/chromium/ui/base/x/x11_pointer_grab.h b/chromium/ui/base/x/x11_pointer_grab.h index 9f34e28193c..8df814098e3 100644 --- a/chromium/ui/base/x/x11_pointer_grab.h +++ b/chromium/ui/base/x/x11_pointer_grab.h @@ -15,7 +15,7 @@ namespace ui { // Grabs the pointer. It is unnecessary to ungrab the pointer prior to grabbing // it. COMPONENT_EXPORT(UI_BASE_X) -int GrabPointer(XID window, bool owner_events, ::Cursor cursor); +int GrabPointer(x11::Window window, bool owner_events, ::Cursor cursor); // Sets the cursor to use for the duration of the active pointer grab. COMPONENT_EXPORT(UI_BASE_X) void ChangeActivePointerGrabCursor(::Cursor cursor); diff --git a/chromium/ui/base/x/x11_shm_image_pool.cc b/chromium/ui/base/x/x11_shm_image_pool.cc index 4719fbf261c..1824426e5bb 100644 --- a/chromium/ui/base/x/x11_shm_image_pool.cc +++ b/chromium/ui/base/x/x11_shm_image_pool.cc @@ -116,7 +116,7 @@ XShmImagePool::XShmImagePool( scoped_refptr<base::SequencedTaskRunner> host_task_runner, scoped_refptr<base::SequencedTaskRunner> event_task_runner, XDisplay* display, - XID drawable, + x11::Drawable drawable, Visual* visual, int depth, std::size_t frames_pending) @@ -163,9 +163,9 @@ bool XShmImagePool::Resize(const gfx::Size& pixel_size) { std::size_t needed_frame_bytes; for (std::size_t i = 0; i < frame_states_.size(); ++i) { FrameState& state = frame_states_[i]; - state.image.reset(XShmCreateImage(display_, visual_, depth_, ZPixmap, - nullptr, &state.shminfo_, - pixel_size.width(), pixel_size.height())); + state.image.reset(XShmCreateImage( + display_, visual_, depth_, static_cast<int>(x11::ImageFormat::ZPixmap), + nullptr, &state.shminfo_, pixel_size.width(), pixel_size.height())); if (!state.image) return false; std::size_t current_frame_bytes = @@ -312,18 +312,20 @@ void XShmImagePool::DispatchShmCompletionEvent(XShmCompletionEvent event) { } } -bool XShmImagePool::CanDispatchXEvent(XEvent* xev) { +bool XShmImagePool::CanDispatchXEvent(x11::Event* x11_event) { + const XEvent* xev = &x11_event->xlib_event(); DCHECK(event_task_runner_->RunsTasksInCurrentSequence()); if (xev->type != ui::ShmEventBase() + ShmCompletion) return false; - XShmCompletionEvent* shm_event = reinterpret_cast<XShmCompletionEvent*>(xev); - return shm_event->drawable == drawable_; + const auto* shm_event = reinterpret_cast<const XShmCompletionEvent*>(xev); + return shm_event->drawable == drawable_.value; } -bool XShmImagePool::DispatchXEvent(XEvent* xev) { - if (!CanDispatchXEvent(xev)) +bool XShmImagePool::DispatchXEvent(x11::Event* x11_event) { + XEvent* xev = &x11_event->xlib_event(); + if (!CanDispatchXEvent(x11_event)) return false; XShmCompletionEvent* shm_event = reinterpret_cast<XShmCompletionEvent*>(xev); diff --git a/chromium/ui/base/x/x11_shm_image_pool.h b/chromium/ui/base/x/x11_shm_image_pool.h index c74ff171d34..b50331d5c9b 100644 --- a/chromium/ui/base/x/x11_shm_image_pool.h +++ b/chromium/ui/base/x/x11_shm_image_pool.h @@ -19,6 +19,7 @@ #include "ui/base/x/x11_util.h" #include "ui/events/platform/x11/x11_event_source.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" namespace ui { @@ -34,7 +35,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool XShmImagePool(scoped_refptr<base::SequencedTaskRunner> host_task_runner, scoped_refptr<base::SequencedTaskRunner> event_task_runner, XDisplay* display, - XID drawable, + x11::Drawable drawable, Visual* visual, int depth, std::size_t max_frames_pending); @@ -66,7 +67,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool void DispatchShmCompletionEvent(XShmCompletionEvent event); - bool CanDispatchXEvent(XEvent* xev); + bool CanDispatchXEvent(x11::Event* xev); const scoped_refptr<base::SequencedTaskRunner> host_task_runner_; const scoped_refptr<base::SequencedTaskRunner> event_task_runner_; @@ -98,7 +99,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool }; // XEventDispatcher: - bool DispatchXEvent(XEvent* xev) override; + bool DispatchXEvent(x11::Event* xev) override; void InitializeOnGpu(); void TeardownOnGpu(); @@ -106,7 +107,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool void Cleanup(); XDisplay* const display_; - const XID drawable_; + const x11::Drawable drawable_; Visual* const visual_; const int depth_; diff --git a/chromium/ui/base/x/x11_software_bitmap_presenter.cc b/chromium/ui/base/x/x11_software_bitmap_presenter.cc index f72b5b3ac6b..1974c5bfac8 100644 --- a/chromium/ui/base/x/x11_software_bitmap_presenter.cc +++ b/chromium/ui/base/x/x11_software_bitmap_presenter.cc @@ -13,6 +13,7 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" #include "base/macros.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImageInfo.h" @@ -20,6 +21,7 @@ #include "ui/base/x/x11_shm_image_pool.h" #include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util_internal.h" +#include "ui/gfx/native_widget_types.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_error_tracker.h" #include "ui/gfx/x/x11_types.h" @@ -65,8 +67,8 @@ bool X11SoftwareBitmapPresenter::CompositeBitmap(XDisplay* display, ui::XScopedImage bg; { gfx::X11ErrorTracker ignore_x_errors; - bg.reset( - XGetImage(display, widget, x, y, width, height, AllPlanes, ZPixmap)); + bg.reset(XGetImage(display, widget, x, y, width, height, AllPlanes, + static_cast<int>(x11::ImageFormat::ZPixmap))); } // XGetImage() may fail if the drawable is a window and the window is not @@ -78,27 +80,28 @@ bool X11SoftwareBitmapPresenter::CompositeBitmap(XDisplay* display, return false; XGCValues gcv; - gcv.subwindow_mode = IncludeInferiors; + gcv.subwindow_mode = static_cast<int>(x11::SubwindowMode::IncludeInferiors); XChangeGC(display, gc, GCSubwindowMode, &gcv); XCopyArea(display, widget, pixmap, gc, x, y, width, height, 0, 0); - gcv.subwindow_mode = ClipByChildren; + gcv.subwindow_mode = static_cast<int>(x11::SubwindowMode::ClipByChildren); XChangeGC(display, gc, GCSubwindowMode, &gcv); - bg.reset( - XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap)); + bg.reset(XGetImage(display, pixmap, 0, 0, width, height, AllPlanes, + static_cast<int>(x11::ImageFormat::ZPixmap))); } if (!bg) return false; SkBitmap bg_bitmap; - SkImageInfo image_info = - SkImageInfo::Make(bg->width, bg->height, - bg->byte_order == LSBFirst ? kBGRA_8888_SkColorType - : kRGBA_8888_SkColorType, - kPremul_SkAlphaType); + SkImageInfo image_info = SkImageInfo::Make( + bg->width, bg->height, + bg->byte_order == static_cast<int>(x11::ImageOrder::LSBFirst) + ? kBGRA_8888_SkColorType + : kRGBA_8888_SkColorType, + kPremul_SkAlphaType); if (!bg_bitmap.installPixels(image_info, bg->data, bg->bytes_per_line)) return false; SkCanvas canvas(bg_bitmap); @@ -120,16 +123,18 @@ X11SoftwareBitmapPresenter::X11SoftwareBitmapPresenter( gfx::AcceleratedWidget widget, scoped_refptr<base::SequencedTaskRunner> host_task_runner, scoped_refptr<base::SequencedTaskRunner> event_task_runner) - : widget_(widget), + : widget_(static_cast<x11::Window>(widget)), display_(gfx::GetXDisplay()), gc_(nullptr), host_task_runner_(host_task_runner), event_task_runner_(event_task_runner) { - DCHECK_NE(widget_, gfx::kNullAcceleratedWidget); - gc_ = XCreateGC(display_, widget_, 0, nullptr); + DCHECK(widget_ != x11::Window::None); + gc_ = XCreateGC(display_, static_cast<uint32_t>(widget_), 0, nullptr); memset(&attributes_, 0, sizeof(attributes_)); - if (!XGetWindowAttributes(display_, widget_, &attributes_)) { - LOG(ERROR) << "XGetWindowAttributes failed for window " << widget_; + if (!XGetWindowAttributes(display_, static_cast<uint32_t>(widget_), + &attributes_)) { + LOG(ERROR) << "XGetWindowAttributes failed for window " + << static_cast<uint32_t>(widget_); return; } @@ -219,9 +224,9 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) { if (ShmPoolReady()) { // TODO(thomasanderson): Investigate direct rendering with DRI3 to avoid any // unnecessary X11 IPC or buffer copying. - if (XShmPutImage(display_, widget_, gc_, shm_pool_->CurrentImage(), - rect.x(), rect.y(), rect.x(), rect.y(), rect.width(), - rect.height(), x11::True)) { + if (XShmPutImage(display_, static_cast<uint32_t>(widget_), gc_, + shm_pool_->CurrentImage(), rect.x(), rect.y(), rect.x(), + rect.y(), rect.width(), rect.height(), x11::True)) { needs_swap_ = true; FlushAfterPutImage(); return; @@ -231,10 +236,13 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) { surface_->peekPixels(&skia_pixmap); } + if (!skia_pixmap.addr()) + return; + if (composite_ && - CompositeBitmap(display_, widget_, rect.x(), rect.y(), rect.width(), - rect.height(), attributes_.depth, gc_, - skia_pixmap.addr())) { + CompositeBitmap(display_, static_cast<uint32_t>(widget_), rect.x(), + rect.y(), rect.width(), rect.height(), attributes_.depth, + gc_, skia_pixmap.addr())) { FlushAfterPutImage(); return; } @@ -242,10 +250,10 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) { XImage image = {}; image.width = viewport_pixel_size_.width(); image.height = viewport_pixel_size_.height(); - image.format = ZPixmap; - image.byte_order = LSBFirst; + image.format = static_cast<int>(x11::ImageFormat::ZPixmap); + image.byte_order = static_cast<int>(x11::ImageOrder::LSBFirst); image.bitmap_unit = 8; - image.bitmap_bit_order = LSBFirst; + image.bitmap_bit_order = static_cast<int>(x11::ImageOrder::LSBFirst); image.depth = attributes_.depth; image.bits_per_pixel = attributes_.visual->bits_per_rgb; @@ -257,8 +265,8 @@ void X11SoftwareBitmapPresenter::EndPaint(const gfx::Rect& damage_rect) { image.blue_mask = attributes_.visual->blue_mask; image.data = reinterpret_cast<char*>(const_cast<void*>(skia_pixmap.addr())); - XPutImage(display_, widget_, gc_, &image, rect.x(), rect.y(), rect.x(), - rect.y(), rect.width(), rect.height()); + XPutImage(display_, static_cast<uint32_t>(widget_), gc_, &image, rect.x(), + rect.y(), rect.x(), rect.y(), rect.width(), rect.height()); FlushAfterPutImage(); } diff --git a/chromium/ui/base/x/x11_software_bitmap_presenter.h b/chromium/ui/base/x/x11_software_bitmap_presenter.h index c100fddc463..4f405653b19 100644 --- a/chromium/ui/base/x/x11_software_bitmap_presenter.h +++ b/chromium/ui/base/x/x11_software_bitmap_presenter.h @@ -58,7 +58,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11SoftwareBitmapPresenter { void FlushAfterPutImage(); - gfx::AcceleratedWidget widget_; + x11::Window widget_; XDisplay* display_; GC gc_; XWindowAttributes attributes_; diff --git a/chromium/ui/base/x/x11_topmost_window_finder.h b/chromium/ui/base/x/x11_topmost_window_finder.h index fd5305da988..8099ce8bbcb 100644 --- a/chromium/ui/base/x/x11_topmost_window_finder.h +++ b/chromium/ui/base/x/x11_topmost_window_finder.h @@ -19,7 +19,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XTopmostWindowFinder { virtual ~XTopmostWindowFinder(); // Returns the topmost window at |screen_loc_px|. - virtual XID FindWindowAt(const gfx::Point& screen_loc_px) = 0; + virtual x11::Window FindWindowAt(const gfx::Point& screen_loc_px) = 0; }; } // namespace ui diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc index 4f35d362363..e09f75b75c0 100644 --- a/chromium/ui/base/x/x11_util.cc +++ b/chromium/ui/base/x/x11_util.cc @@ -21,12 +21,14 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/singleton.h" #include "base/message_loop/message_loop_current.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" @@ -42,6 +44,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkTypes.h" +#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/base/x/x11_menu_list.h" #include "ui/base/x/x11_util_internal.h" #include "ui/events/devices/x11/device_data_manager_x11.h" @@ -62,6 +65,7 @@ #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_error_tracker.h" +#include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto_util.h" #if defined(OS_FREEBSD) @@ -84,10 +88,6 @@ namespace { constexpr int kNetWMStateAdd = 1; constexpr int kNetWMStateRemove = 0; -// Length in 32-bit multiples of the data to be retrieved for -// XGetWindowProperty. -constexpr int kLongLength = 0x1FFFFFFF; /* MAXINT32 / 4 */ - int DefaultX11ErrorHandler(XDisplay* d, XErrorEvent* e) { // This callback can be invoked by drivers very late in thread destruction, // when Chrome TLS is no longer usable. https://crbug.com/849225. @@ -113,58 +113,15 @@ int DefaultX11IOErrorHandler(XDisplay* d) { _exit(1); } -template <typename T> -bool GetProperty(XID window, const std::string& property_name, T* value) { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, ""); - auto response = x11::Connection::Get() - ->GetProperty({ - .window = static_cast<x11::Window>(window), - .property = static_cast<x11::Atom>( - gfx::GetAtom(property_name.c_str())), - .long_length = std::max<uint32_t>(1, sizeof(T) / 4), - }) - .Sync(); - if (!response || response->format != 8 * sizeof(T) || - response->value.size() != sizeof(T)) { - return false; - } - - DCHECK_EQ(response->format / 8 * response->value_len, response->value.size()); - memcpy(value, response->value.data(), sizeof(T)); - return true; -} - -template <typename T> -bool GetArrayProperty(XID window, - const std::string& property_name, - std::vector<T>* value) { - static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, ""); - auto response = x11::Connection::Get() - ->GetProperty({ - .window = static_cast<x11::Window>(window), - .property = static_cast<x11::Atom>( - gfx::GetAtom(property_name.c_str())), - .long_length = std::numeric_limits<uint32_t>::max(), - }) - .Sync(); - if (!response || response->format != 8 * sizeof(T)) - return false; - - DCHECK_EQ(response->format / 8 * response->value_len, response->value.size()); - value->resize(response->value_len); - memcpy(value->data(), response->value.data(), response->value.size()); - return true; -} - bool SupportsEWMH() { static bool supports_ewmh = false; static bool supports_ewmh_cached = false; if (!supports_ewmh_cached) { supports_ewmh_cached = true; - int wm_window = 0u; - if (!GetIntProperty(GetX11RootWindow(), "_NET_SUPPORTING_WM_CHECK", - &wm_window)) { + x11::Window wm_window = x11::Window::None; + if (!GetProperty(GetX11RootWindow(), + gfx::GetAtom("_NET_SUPPORTING_WM_CHECK"), &wm_window)) { supports_ewmh = false; return false; } @@ -179,9 +136,10 @@ bool SupportsEWMH() { // property referencing an ID that's been recycled for another window), so // we check that too. gfx::X11ErrorTracker err_tracker; - int wm_window_property = 0; - bool result = GetIntProperty(wm_window, "_NET_SUPPORTING_WM_CHECK", - &wm_window_property); + x11::Window wm_window_property = x11::Window::None; + bool result = + GetProperty(wm_window, gfx::GetAtom("_NET_SUPPORTING_WM_CHECK"), + &wm_window_property); supports_ewmh = !err_tracker.FoundNewError() && result && wm_window_property == wm_window; } @@ -194,32 +152,29 @@ bool GetWindowManagerName(std::string* wm_name) { if (!SupportsEWMH()) return false; - int wm_window = 0; - if (!GetIntProperty(GetX11RootWindow(), "_NET_SUPPORTING_WM_CHECK", - &wm_window)) { + x11::Window wm_window = x11::Window::None; + if (!GetProperty(GetX11RootWindow(), gfx::GetAtom("_NET_SUPPORTING_WM_CHECK"), + &wm_window)) { return false; } gfx::X11ErrorTracker err_tracker; - bool result = - GetStringProperty(static_cast<XID>(wm_window), "_NET_WM_NAME", wm_name); + bool result = GetStringProperty(wm_window, "_NET_WM_NAME", wm_name); return !err_tracker.FoundNewError() && result; } unsigned int GetMaxCursorSize() { - // Although XQueryBestCursor() takes unsigned ints, the width and height will - // be sent over the wire as 16 bit integers. constexpr unsigned int kQuerySize = std::numeric_limits<uint16_t>::max(); - XDisplay* display = gfx::GetXDisplay(); - unsigned int width = 0; - unsigned int height = 0; - XQueryBestCursor(display, DefaultRootWindow(display), kQuerySize, kQuerySize, - &width, &height); - unsigned int min_dimension = std::min(width, height); + auto* connection = x11::Connection::Get(); + x11::QueryBestSizeRequest request{ + x11::QueryShapeOf::LargestCursor, + static_cast<x11::Window>(GetX11RootWindow()), kQuerySize, kQuerySize}; + if (auto response = connection->QueryBestSize(request).Sync()) + return std::min(response->width, response->height); // libXcursor defines MAX_BITMAP_CURSOR_SIZE to 64 in src/xcursorint.h, so use // this as a fallback in case the X server returns zero size, which can happen // on some buggy implementations of XWayland/XMir. - return min_dimension > 0 ? min_dimension : 64; + return 64; } // A process wide singleton cache for custom X cursors. @@ -308,8 +263,235 @@ SkBitmap ConvertSkBitmapToUnpremul(const SkBitmap& bitmap) { return converted_bitmap; } +// Returns a cursor name, compatible with either X11 or the FreeDesktop.org +// cursor spec +// (https://www.x.org/releases/current/doc/libX11/libX11/libX11.html#x_font_cursors +// and https://www.freedesktop.org/wiki/Specifications/cursor-spec/), followed +// by fallbacks that can work as replacements in some environments where the +// original may not be available (e.g. desktop environments other than +// GNOME and KDE). +// TODO(hferreiro): each list starts with the FreeDesktop.org icon name but +// "ns-resize", "ew-resize", "nesw-resize", "nwse-resize", "grab", "grabbing", +// which were not available in older versions of Breeze, the default KDE theme. +std::vector<const char*> CursorNamesFromType(mojom::CursorType type) { + switch (type) { + case mojom::CursorType::kMove: + // Returning "move" is the correct thing here, but Blink doesn't make a + // distinction between move and all-scroll. Other platforms use a cursor + // more consistent with all-scroll, so use that. + case mojom::CursorType::kMiddlePanning: + case mojom::CursorType::kMiddlePanningVertical: + case mojom::CursorType::kMiddlePanningHorizontal: + return {"all-scroll", "fleur"}; + case mojom::CursorType::kEastPanning: + case mojom::CursorType::kEastResize: + return {"e-resize", "right_side"}; + case mojom::CursorType::kNorthPanning: + case mojom::CursorType::kNorthResize: + return {"n-resize", "top_side"}; + case mojom::CursorType::kNorthEastPanning: + case mojom::CursorType::kNorthEastResize: + return {"ne-resize", "top_right_corner"}; + case mojom::CursorType::kNorthWestPanning: + case mojom::CursorType::kNorthWestResize: + return {"nw-resize", "top_left_corner"}; + case mojom::CursorType::kSouthPanning: + case mojom::CursorType::kSouthResize: + return {"s-resize", "bottom_side"}; + case mojom::CursorType::kSouthEastPanning: + case mojom::CursorType::kSouthEastResize: + return {"se-resize", "bottom_right_corner"}; + case mojom::CursorType::kSouthWestPanning: + case mojom::CursorType::kSouthWestResize: + return {"sw-resize", "bottom_left_corner"}; + case mojom::CursorType::kWestPanning: + case mojom::CursorType::kWestResize: + return {"w-resize", "left_side"}; + case mojom::CursorType::kNone: + return {"none"}; + case mojom::CursorType::kGrab: + return {"openhand", "grab"}; + case mojom::CursorType::kGrabbing: + return {"closedhand", "grabbing", "hand2"}; + case mojom::CursorType::kCross: + return {"crosshair", "cross"}; + case mojom::CursorType::kHand: + return {"pointer", "hand", "hand2"}; + case mojom::CursorType::kIBeam: + return {"text", "xterm"}; + case mojom::CursorType::kProgress: + return {"progress", "left_ptr_watch", "watch"}; + case mojom::CursorType::kWait: + return {"wait", "watch"}; + case mojom::CursorType::kHelp: + return {"help"}; + case mojom::CursorType::kNorthSouthResize: + return {"sb_v_double_arrow", "ns-resize"}; + case mojom::CursorType::kEastWestResize: + return {"sb_h_double_arrow", "ew-resize"}; + case mojom::CursorType::kColumnResize: + return {"col-resize", "sb_h_double_arrow"}; + case mojom::CursorType::kRowResize: + return {"row-resize", "sb_v_double_arrow"}; + case mojom::CursorType::kNorthEastSouthWestResize: + return {"size_bdiag", "nesw-resize", "fd_double_arrow"}; + case mojom::CursorType::kNorthWestSouthEastResize: + return {"size_fdiag", "nwse-resize", "bd_double_arrow"}; + case mojom::CursorType::kVerticalText: + return {"vertical-text"}; + case mojom::CursorType::kZoomIn: + return {"zoom-in"}; + case mojom::CursorType::kZoomOut: + return {"zoom-out"}; + case mojom::CursorType::kCell: + return {"cell", "plus"}; + case mojom::CursorType::kContextMenu: + return {"context-menu"}; + case mojom::CursorType::kAlias: + return {"alias"}; + case mojom::CursorType::kNoDrop: + return {"no-drop"}; + case mojom::CursorType::kCopy: + return {"copy"}; + case mojom::CursorType::kNotAllowed: + return {"not-allowed", "crossed_circle"}; + case mojom::CursorType::kDndNone: + return {"dnd-none", "hand2"}; + case mojom::CursorType::kDndMove: + return {"dnd-move", "hand2"}; + case mojom::CursorType::kDndCopy: + return {"dnd-copy", "hand2"}; + case mojom::CursorType::kDndLink: + return {"dnd-link", "hand2"}; + case mojom::CursorType::kCustom: + // kCustom is for custom image cursors. The platform cursor will be set + // at WebCursor::GetPlatformCursor(). + NOTREACHED(); + FALLTHROUGH; + case mojom::CursorType::kNull: + case mojom::CursorType::kPointer: + return {"left_ptr"}; + } + NOTREACHED(); + return {"left_ptr"}; +} + } // namespace +void DeleteProperty(x11::Window window, x11::Atom name) { + x11::Connection::Get()->DeleteProperty({ + .window = static_cast<x11::Window>(window), + .property = name, + }); +} + +bool GetWmNormalHints(x11::Window window, SizeHints* hints) { + std::vector<uint32_t> hints32; + if (!GetArrayProperty(window, gfx::GetAtom("WM_NORMAL_HINTS"), &hints32)) + return false; + if (hints32.size() != sizeof(SizeHints) / 4) + return false; + memcpy(hints, hints32.data(), sizeof(*hints)); + return true; +} + +void SetWmNormalHints(x11::Window window, const SizeHints& hints) { + std::vector<uint32_t> hints32(sizeof(SizeHints) / 4); + memcpy(hints32.data(), &hints, sizeof(SizeHints)); + ui::SetArrayProperty(window, gfx::GetAtom("WM_NORMAL_HINTS"), + gfx::GetAtom("WM_SIZE_HINTS"), hints32); +} + +bool GetWmHints(x11::Window window, WmHints* hints) { + std::vector<uint32_t> hints32; + if (!GetArrayProperty(window, gfx::GetAtom("WM_HINTS"), &hints32)) + return false; + if (hints32.size() != sizeof(WmHints) / 4) + return false; + memcpy(hints, hints32.data(), sizeof(*hints)); + return true; +} + +void SetWmHints(x11::Window window, const WmHints& hints) { + std::vector<uint32_t> hints32(sizeof(WmHints) / 4); + memcpy(hints32.data(), &hints, sizeof(WmHints)); + ui::SetArrayProperty(window, gfx::GetAtom("WM_HINTS"), + gfx::GetAtom("WM_HINTS"), hints32); +} + +void WithdrawWindow(x11::Window window) { + auto* connection = x11::Connection::Get(); + connection->UnmapWindow({window}); + + auto root = connection->default_root(); + x11::UnmapNotifyEvent event{.event = root, .window = window}; + auto event_bytes = x11::Write(event); + event_bytes.resize(32); + + auto mask = + x11::EventMask::SubstructureNotify | x11::EventMask::SubstructureRedirect; + x11::SendEventRequest request{false, root, mask}; + std::copy(event_bytes.begin(), event_bytes.end(), request.event.begin()); + connection->SendEvent(request); +} + +void RaiseWindow(x11::Window window) { + x11::Connection::Get()->ConfigureWindow( + {.window = window, .stack_mode = x11::StackMode::Above}); +} + +void LowerWindow(x11::Window window) { + x11::Connection::Get()->ConfigureWindow( + {.window = window, .stack_mode = x11::StackMode::Below}); +} + +void DefineCursor(x11::Window window, x11::Cursor cursor) { + // TODO(https://crbug.com/1066670): Sync() should be removed. It's added for + // now because Xlib's XDefineCursor() sync'ed and removing it perturbs the + // timing on BookmarkBarViewTest8.DNDBackToOriginatingMenu on + // linux-chromeos-rel, causing it to flake. + x11::Connection::Get() + ->ChangeWindowAttributes({.window = window, .cursor = cursor}) + .Sync(); +} + +x11::Window CreateDummyWindow(const std::string& name) { + auto* connection = x11::Connection::Get(); + auto window = connection->GenerateId<x11::Window>(); + connection->CreateWindow({ + .wid = window, + .parent = connection->default_root(), + .x = -100, + .y = -100, + .width = 10, + .height = 10, + .c_class = x11::WindowClass::InputOnly, + .override_redirect = x11::Bool32(true), + }); + if (!name.empty()) + SetStringProperty(window, x11::Atom::WM_NAME, x11::Atom::STRING, name); + return window; +} + +x11::KeyCode KeysymToKeycode(x11::Connection* connection, x11::KeySym keysym) { + uint8_t min_keycode = static_cast<uint8_t>(connection->setup().min_keycode); + uint8_t max_keycode = static_cast<uint8_t>(connection->setup().max_keycode); + uint8_t count = max_keycode - min_keycode + 1; + auto future = + connection->GetKeyboardMapping({connection->setup().min_keycode, count}); + if (auto reply = future.Sync()) { + DCHECK_EQ(count * reply->keysyms_per_keycode, + static_cast<int>(reply->keysyms.size())); + for (size_t i = 0; i < reply->keysyms.size(); i++) { + if (reply->keysyms[i] == keysym) { + return static_cast<x11::KeyCode>(min_keycode + + i / reply->keysyms_per_keycode); + } + } + } + return {}; +} + bool IsXInput2Available() { return DeviceDataManagerX11::GetInstance()->IsXInput2Available(); } @@ -396,24 +578,37 @@ XcursorImage* SkBitmapToXcursorImage(const SkBitmap& cursor_image, return image; } -int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { - DCHECK(xev->type == MotionNotify || xev->type == GenericEvent); - XDisplay* display = xev->xany.display; - XEvent next_event; +::Cursor LoadCursorFromType(mojom::CursorType type) { + for (auto* name : CursorNamesFromType(type)) { + ::Cursor cursor = XcursorLibraryLoadCursor(gfx::GetXDisplay(), name); + if (cursor != x11::None) + return cursor; + } + return x11::None; +} + +int CoalescePendingMotionEvents(const x11::Event* x11_event, + x11::Event* last_event) { + const XEvent* xev = &x11_event->xlib_event(); + DCHECK(xev->type == x11::MotionNotifyEvent::opcode || + xev->type == x11::GeGenericEvent::opcode); + auto* conn = x11::Connection::Get(); bool is_motion = false; int num_coalesced = 0; - if (xev->type == MotionNotify) { + conn->ReadResponses(); + if (xev->type == x11::MotionNotifyEvent::opcode) { is_motion = true; - while (XPending(display)) { - XPeekEvent(xev->xany.display, &next_event); + for (auto it = conn->events().begin(); it != conn->events().end();) { + const auto& next_event = it->xlib_event(); // Discard all but the most recent motion event that targets the same // window with unchanged state. - if (next_event.type == MotionNotify && + if (next_event.type == x11::MotionNotifyEvent::opcode && next_event.xmotion.window == xev->xmotion.window && next_event.xmotion.subwindow == xev->xmotion.subwindow && next_event.xmotion.state == xev->xmotion.state) { - XNextEvent(xev->xany.display, last_event); + *last_event = std::move(*it); + it = conn->events().erase(it); } else { break; } @@ -424,12 +619,14 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { DCHECK(event_type == XI_Motion || event_type == XI_TouchUpdate); is_motion = event_type == XI_Motion; - while (XPending(display)) { - XPeekEvent(display, &next_event); + auto* ddmx11 = ui::DeviceDataManagerX11::GetInstance(); + for (auto it = conn->events().begin(); it != conn->events().end();) { + auto& next_event = it->xlib_event(); - // If we can't get the cookie, abort the check. - if (!XGetEventData(next_event.xgeneric.display, &next_event.xcookie)) - return num_coalesced; + if (next_event.type != x11::GeGenericEvent::opcode || + !next_event.xcookie.data) { + break; + } // If this isn't from a valid device, throw the event away, as // that's what the message pump would do. Device events come in pairs @@ -437,17 +634,14 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { // always be at least one pending. if (!ui::TouchFactory::GetInstance()->ShouldProcessXI2Event( &next_event)) { - XFreeEventData(display, &next_event.xcookie); - XNextEvent(display, &next_event); + it = conn->events().erase(it); continue; } - if (next_event.type == GenericEvent && + if (next_event.type == x11::GeGenericEvent::opcode && next_event.xgeneric.evtype == event_type && - !ui::DeviceDataManagerX11::GetInstance()->IsCMTGestureEvent( - next_event) && - ui::DeviceDataManagerX11::GetInstance()->GetScrollClassEventDetail( - next_event) == SCROLL_TYPE_NO_SCROLL) { + !ddmx11->IsCMTGestureEvent(*it) && + ddmx11->GetScrollClassEventDetail(*it) == SCROLL_TYPE_NO_SCROLL) { XIDeviceEvent* next_xievent = static_cast<XIDeviceEvent*>(next_event.xcookie.data); // Confirm that the motion event is targeted at the same window @@ -462,25 +656,16 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) { xievent->mods.latched == next_xievent->mods.latched && xievent->mods.locked == next_xievent->mods.locked && xievent->mods.effective == next_xievent->mods.effective) { - XFreeEventData(display, &next_event.xcookie); - // Free the previous cookie. - if (num_coalesced > 0) - XFreeEventData(display, &last_event->xcookie); - // Get the event and its cookie data. - XNextEvent(display, last_event); - XGetEventData(display, &last_event->xcookie); - ++num_coalesced; + *last_event = std::move(*it); + it = conn->events().erase(it); + num_coalesced++; continue; } } - // This isn't an event we want so free its cookie data. - XFreeEventData(display, &next_event.xcookie); break; } } - if (is_motion && num_coalesced > 0) - UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced); return num_coalesced; } @@ -505,62 +690,53 @@ void HideHostCursor() { return invisible_cursor; } -void SetUseOSWindowFrame(XID window, bool use_os_window_frame) { +void SetUseOSWindowFrame(x11::Window window, bool use_os_window_frame) { // This data structure represents additional hints that we send to the window // manager and has a direct lineage back to Motif, which defined this de facto - // standard. This struct doesn't seem 64-bit safe though, but it's what GDK - // does. + // standard. We define this struct to match the wire-format (32-bit fields) + // rather than the Xlib API (XChangeProperty) format (long fields). typedef struct { - unsigned long flags; - unsigned long functions; - unsigned long decorations; - long input_mode; - unsigned long status; + uint32_t flags; + uint32_t functions; + uint32_t decorations; + int32_t input_mode; + uint32_t status; } MotifWmHints; MotifWmHints motif_hints; memset(&motif_hints, 0, sizeof(motif_hints)); // Signals that the reader of the _MOTIF_WM_HINTS property should pay // attention to the value of |decorations|. - motif_hints.flags = (1L << 1); + motif_hints.flags = (1u << 1); motif_hints.decorations = use_os_window_frame ? 1 : 0; - XAtom hint_atom = gfx::GetAtom("_MOTIF_WM_HINTS"); - XChangeProperty(gfx::GetXDisplay(), window, hint_atom, hint_atom, 32, - PropModeReplace, - reinterpret_cast<unsigned char*>(&motif_hints), - sizeof(MotifWmHints) / sizeof(long)); + std::vector<uint32_t> hints(sizeof(MotifWmHints) / sizeof(uint32_t)); + memcpy(hints.data(), &motif_hints, sizeof(MotifWmHints)); + x11::Atom hint_atom = gfx::GetAtom("_MOTIF_WM_HINTS"); + SetArrayProperty(window, hint_atom, hint_atom, hints); } bool IsShapeExtensionAvailable() { - int dummy; - static bool is_shape_available = - XShapeQueryExtension(gfx::GetXDisplay(), &dummy, &dummy); - return is_shape_available; + return x11::Connection::Get()->shape().present(); } -XID GetX11RootWindow() { - return DefaultRootWindow(gfx::GetXDisplay()); +x11::Window GetX11RootWindow() { + return x11::Connection::Get()->default_screen().root; } bool GetCurrentDesktop(int* desktop) { return GetIntProperty(GetX11RootWindow(), "_NET_CURRENT_DESKTOP", desktop); } -void SetHideTitlebarWhenMaximizedProperty(XID window, +void SetHideTitlebarWhenMaximizedProperty(x11::Window window, HideTitlebarWhenMaximized property) { - // XChangeProperty() expects "hide" to be long. - unsigned long hide = property; - XChangeProperty(gfx::GetXDisplay(), window, - gfx::GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), - XA_CARDINAL, - 32, // size in bits - PropModeReplace, reinterpret_cast<unsigned char*>(&hide), 1); + SetProperty(window, gfx::GetAtom("_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"), + x11::Atom::CARDINAL, static_cast<uint32_t>(property)); } void ClearX11DefaultRootWindow() { XDisplay* display = gfx::GetXDisplay(); - XID root_window = GetX11RootWindow(); + x11::Window root_window = GetX11RootWindow(); gfx::Rect root_bounds; if (!GetOuterWindowBounds(root_window, &root_bounds)) { LOG(ERROR) << "Failed to get the bounds of the X11 root window"; @@ -569,25 +745,27 @@ void ClearX11DefaultRootWindow() { XGCValues gc_values = {0}; gc_values.foreground = BlackPixel(display, DefaultScreen(display)); - GC gc = XCreateGC(display, root_window, GCForeground, &gc_values); - XFillRectangle(display, root_window, gc, root_bounds.x(), root_bounds.y(), - root_bounds.width(), root_bounds.height()); + GC gc = XCreateGC(display, static_cast<uint32_t>(root_window), GCForeground, + &gc_values); + XFillRectangle(display, static_cast<uint32_t>(root_window), gc, + root_bounds.x(), root_bounds.y(), root_bounds.width(), + root_bounds.height()); XFreeGC(display, gc); } -bool IsWindowVisible(XID window) { +bool IsWindowVisible(x11::Window window) { TRACE_EVENT0("ui", "IsWindowVisible"); - XWindowAttributes win_attributes; - if (!XGetWindowAttributes(gfx::GetXDisplay(), window, &win_attributes)) - return false; - if (win_attributes.map_state != IsViewable) + auto x11_window = static_cast<x11::Window>(window); + auto* connection = x11::Connection::Get(); + auto response = connection->GetWindowAttributes({x11_window}).Sync(); + if (!response || response->map_state != x11::MapState::Viewable) return false; // Minimized windows are not visible. - std::vector<XAtom> wm_states; + std::vector<x11::Atom> wm_states; if (GetAtomArrayProperty(window, "_NET_WM_STATE", &wm_states)) { - XAtom hidden_atom = gfx::GetAtom("_NET_WM_STATE_HIDDEN"); + x11::Atom hidden_atom = gfx::GetAtom("_NET_WM_STATE_HIDDEN"); if (base::Contains(wm_states, hidden_atom)) return false; } @@ -600,26 +778,27 @@ bool IsWindowVisible(XID window) { window_desktop == kAllDesktops || window_desktop == current_desktop); } -bool GetInnerWindowBounds(XID window, gfx::Rect* rect) { - Window root, child; - int x, y; - unsigned int width, height; - unsigned int border_width, depth; +bool GetInnerWindowBounds(x11::Window window, gfx::Rect* rect) { + auto x11_window = static_cast<x11::Window>(window); + auto root = static_cast<x11::Window>(GetX11RootWindow()); - if (!XGetGeometry(gfx::GetXDisplay(), window, &root, &x, &y, &width, &height, - &border_width, &depth)) - return false; + x11::Connection* connection = x11::Connection::Get(); + auto get_geometry = connection->GetGeometry({x11_window}); + auto translate_coords = connection->TranslateCoordinates({x11_window, root}); - if (!XTranslateCoordinates(gfx::GetXDisplay(), window, root, 0, 0, &x, &y, - &child)) - return false; + // Sync after making both requests so only one round-trip is made. + auto geometry = get_geometry.Sync(); + auto coords = translate_coords.Sync(); - *rect = gfx::Rect(x, y, width, height); + if (!geometry || !coords) + return false; + *rect = gfx::Rect(coords->dst_x, coords->dst_y, geometry->width, + geometry->height); return true; } -bool GetWindowExtents(XID window, gfx::Insets* extents) { +bool GetWindowExtents(x11::Window window, gfx::Insets* extents) { std::vector<int> insets; if (!GetIntArrayProperty(window, "_NET_FRAME_EXTENTS", &insets)) return false; @@ -634,7 +813,7 @@ bool GetWindowExtents(XID window, gfx::Insets* extents) { return true; } -bool GetOuterWindowBounds(XID window, gfx::Rect* rect) { +bool GetOuterWindowBounds(x11::Window window, gfx::Rect* rect) { if (!GetInnerWindowBounds(window, rect)) return false; @@ -647,7 +826,7 @@ bool GetOuterWindowBounds(XID window, gfx::Rect* rect) { return true; } -bool WindowContainsPoint(XID window, gfx::Point screen_loc) { +bool WindowContainsPoint(x11::Window window, gfx::Point screen_loc) { TRACE_EVENT0("ui", "WindowContainsPoint"); gfx::Rect window_rect; @@ -673,22 +852,21 @@ bool WindowContainsPoint(XID window, gfx::Point screen_loc) { // client bounding region. Any portion of the client input region that is not // included in both the default input region and the client bounding region // will not be included in the effective input region on the screen. - int rectangle_kind[] = {ShapeInput, ShapeBounding}; - for (int kind_index : rectangle_kind) { - int dummy; - int shape_rects_size = 0; - gfx::XScopedPtr<XRectangle[]> shape_rects(XShapeGetRectangles( - gfx::GetXDisplay(), window, kind_index, &shape_rects_size, &dummy)); - if (!shape_rects) { - // The shape is empty. This can occur when |window| is minimized. - DCHECK_EQ(0, shape_rects_size); + x11::Shape::Sk rectangle_kind[] = {x11::Shape::Sk::Input, + x11::Shape::Sk::Bounding}; + for (auto kind : rectangle_kind) { + auto shape = + x11::Connection::Get()->shape().GetRectangles({window, kind}).Sync(); + if (!shape) + return true; + if (shape->rectangles.empty()) { + // The shape can be empty when |window| is minimized. return false; } bool is_in_shape_rects = false; - for (int i = 0; i < shape_rects_size; ++i) { + for (const auto& rect : shape->rectangles) { // The ShapeInput and ShapeBounding rects are to be in window space, so we // have to translate by the window_rect's offset to map to screen space. - const XRectangle& rect = shape_rects[i]; gfx::Rect shape_rect = gfx::Rect(rect.x + window_rect.x(), rect.y + window_rect.y(), rect.width, rect.height); @@ -703,182 +881,105 @@ bool WindowContainsPoint(XID window, gfx::Point screen_loc) { return true; } -bool PropertyExists(XID window, const std::string& property_name) { +bool PropertyExists(x11::Window window, const std::string& property_name) { auto response = x11::Connection::Get() ->GetProperty({ .window = static_cast<x11::Window>(window), - .property = static_cast<x11::Atom>( - gfx::GetAtom(property_name.c_str())), + .property = gfx::GetAtom(property_name), .long_length = 1, }) .Sync(); return response && response->format; } -bool GetRawBytesOfProperty(XID window, - XAtom property, - scoped_refptr<base::RefCountedMemory>* out_data, - size_t* out_data_items, - XAtom* out_type) { - // Retrieve the data from our window. - unsigned long nitems = 0; - unsigned long nbytes = 0; - XAtom prop_type = x11::None; - int prop_format = 0; - unsigned char* property_data = nullptr; - if (XGetWindowProperty(gfx::GetXDisplay(), window, property, 0, kLongLength, - x11::False, AnyPropertyType, &prop_type, &prop_format, - &nitems, &nbytes, &property_data) != x11::Success) { - return false; - } - gfx::XScopedPtr<unsigned char> scoped_property(property_data); - - if (prop_type == x11::None) +bool GetRawBytesOfProperty(x11::Window window, + x11::Atom property, + std::vector<uint8_t>* out_data, + x11::Atom* out_type) { + auto future = x11::Connection::Get()->GetProperty({ + .window = static_cast<x11::Window>(window), + .property = property, + // Don't limit the amount of returned data. + .long_length = std::numeric_limits<uint32_t>::max(), + }); + auto response = future.Sync(); + if (!response || !response->format) return false; - - size_t bytes = 0; - // So even though we should theoretically have nbytes (and we can't - // pass nullptr there), we need to manually calculate the byte length here - // because nbytes always returns zero. - switch (prop_format) { - case 8: - bytes = nitems; - break; - case 16: - bytes = sizeof(short) * nitems; - break; - case 32: - bytes = sizeof(long) * nitems; - break; - default: - NOTREACHED(); - break; - } - - if (out_data) - *out_data = new XRefcountedMemory(scoped_property.release(), bytes); - - if (out_data_items) - *out_data_items = nitems; - + *out_data = std::move(response->value); if (out_type) - *out_type = prop_type; - + *out_type = response->type; return true; } -bool GetIntProperty(XID window, const std::string& property_name, int* value) { - return GetProperty(window, property_name, value); +bool GetIntProperty(x11::Window window, + const std::string& property_name, + int* value) { + return GetProperty(window, gfx::GetAtom(property_name), value); } -bool GetXIDProperty(XID window, const std::string& property_name, XID* value) { - uint32_t xid; - if (!GetProperty(window, property_name, &xid)) - return false; - *value = xid; - return true; -} - -bool GetIntArrayProperty(XID window, +bool GetIntArrayProperty(x11::Window window, const std::string& property_name, - std::vector<int>* value) { - return GetArrayProperty(window, property_name, value); + std::vector<int32_t>* value) { + return GetArrayProperty(window, gfx::GetAtom(property_name), value); } -bool GetAtomArrayProperty(XID window, +bool GetAtomArrayProperty(x11::Window window, const std::string& property_name, - std::vector<XAtom>* value) { - std::vector<uint32_t> value32; - if (!GetArrayProperty(window, property_name, &value32)) - return false; - *value = std::vector<XAtom>(value32.begin(), value32.end()); - return true; + std::vector<x11::Atom>* value) { + return GetArrayProperty(window, gfx::GetAtom(property_name), value); } -bool GetStringProperty(XID window, +bool GetStringProperty(x11::Window window, const std::string& property_name, std::string* value) { std::vector<char> str; - if (!GetArrayProperty(window, property_name, &str)) + if (!GetArrayProperty(window, gfx::GetAtom(property_name), &str)) return false; value->assign(str.data(), str.size()); return true; } -bool SetIntProperty(XID window, +void SetIntProperty(x11::Window window, const std::string& name, const std::string& type, - int value) { + int32_t value) { std::vector<int> values(1, value); return SetIntArrayProperty(window, name, type, values); } -bool SetIntArrayProperty(XID window, +void SetIntArrayProperty(x11::Window window, const std::string& name, const std::string& type, - const std::vector<int>& value) { - DCHECK(!value.empty()); - XAtom name_atom = gfx::GetAtom(name.c_str()); - XAtom type_atom = gfx::GetAtom(type.c_str()); - - // XChangeProperty() expects values of type 32 to be longs. - std::unique_ptr<long[]> data(new long[value.size()]); - for (size_t i = 0; i < value.size(); ++i) - data[i] = value[i]; - - gfx::X11ErrorTracker err_tracker; - XChangeProperty(gfx::GetXDisplay(), window, name_atom, type_atom, - 32, // size in bits of items in 'value' - PropModeReplace, - reinterpret_cast<const unsigned char*>(data.get()), - value.size()); // num items - return !err_tracker.FoundNewError(); + const std::vector<int32_t>& value) { + SetArrayProperty(window, gfx::GetAtom(name), gfx::GetAtom(type), value); } -bool SetAtomProperty(XID window, +void SetAtomProperty(x11::Window window, const std::string& name, const std::string& type, - XAtom value) { - std::vector<XAtom> values(1, value); + x11::Atom value) { + std::vector<x11::Atom> values(1, value); return SetAtomArrayProperty(window, name, type, values); } -bool SetAtomArrayProperty(XID window, +void SetAtomArrayProperty(x11::Window window, const std::string& name, const std::string& type, - const std::vector<XAtom>& value) { - DCHECK(!value.empty()); - XAtom name_atom = gfx::GetAtom(name.c_str()); - XAtom type_atom = gfx::GetAtom(type.c_str()); - - // XChangeProperty() expects values of type 32 to be longs. - std::unique_ptr<XAtom[]> data(new XAtom[value.size()]); - for (size_t i = 0; i < value.size(); ++i) - data[i] = value[i]; - - gfx::X11ErrorTracker err_tracker; - XChangeProperty(gfx::GetXDisplay(), window, name_atom, type_atom, - 32, // size in bits of items in 'value' - PropModeReplace, - reinterpret_cast<const unsigned char*>(data.get()), - value.size()); // num items - return !err_tracker.FoundNewError(); + const std::vector<x11::Atom>& value) { + SetArrayProperty(window, gfx::GetAtom(name), gfx::GetAtom(type), value); } -bool SetStringProperty(XID window, - XAtom property, - XAtom type, +void SetStringProperty(x11::Window window, + x11::Atom property, + x11::Atom type, const std::string& value) { - gfx::X11ErrorTracker err_tracker; - XChangeProperty( - gfx::GetXDisplay(), window, property, type, 8, PropModeReplace, - reinterpret_cast<const unsigned char*>(value.c_str()), value.size()); - return !err_tracker.FoundNewError(); + std::vector<char> str(value.begin(), value.end()); + SetArrayProperty(window, property, type, str); } -void SetWindowClassHint(XDisplay* display, - XID window, +void SetWindowClassHint(x11::Connection* connection, + x11::Window window, const std::string& res_name, const std::string& res_class) { XClassHint class_hints; @@ -887,66 +988,45 @@ void SetWindowClassHint(XDisplay* display, // not const references. class_hints.res_name = const_cast<char*>(res_name.c_str()); class_hints.res_class = const_cast<char*>(res_class.c_str()); - XSetClassHint(display, window, &class_hints); + XSetClassHint(connection->display(), static_cast<uint32_t>(window), + &class_hints); } -void SetWindowRole(XDisplay* display, XID window, const std::string& role) { - if (role.empty()) { - XDeleteProperty(display, window, gfx::GetAtom("WM_WINDOW_ROLE")); - } else { - char* role_c = const_cast<char*>(role.c_str()); - XChangeProperty(display, window, gfx::GetAtom("WM_WINDOW_ROLE"), XA_STRING, - 8, PropModeReplace, - reinterpret_cast<unsigned char*>(role_c), role.size()); - } +void SetWindowRole(x11::Window window, const std::string& role) { + x11::Atom prop = gfx::GetAtom("WM_WINDOW_ROLE"); + if (role.empty()) + DeleteProperty(window, prop); + else + SetStringProperty(window, prop, x11::Atom::STRING, role); +} + +void SetWMSpecState(x11::Window window, + bool enabled, + x11::Atom state1, + x11::Atom state2) { + SendClientMessage( + window, GetX11RootWindow(), gfx::GetAtom("_NET_WM_STATE"), + {enabled ? kNetWMStateAdd : kNetWMStateRemove, + static_cast<uint32_t>(state1), static_cast<uint32_t>(state2), 1, 0}); } -void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2) { - XEvent xclient; - memset(&xclient, 0, sizeof(xclient)); - xclient.type = ClientMessage; - xclient.xclient.window = window; - xclient.xclient.message_type = gfx::GetAtom("_NET_WM_STATE"); - // The data should be viewed as a list of longs, because XAtom is a typedef of - // long. - xclient.xclient.format = 32; - xclient.xclient.data.l[0] = enabled ? kNetWMStateAdd : kNetWMStateRemove; - xclient.xclient.data.l[1] = state1; - xclient.xclient.data.l[2] = state2; - xclient.xclient.data.l[3] = 1; - xclient.xclient.data.l[4] = 0; - - XSendEvent(gfx::GetXDisplay(), GetX11RootWindow(), x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, &xclient); -} - -void DoWMMoveResize(XDisplay* display, - XID root_window, - XID window, +void DoWMMoveResize(x11::Connection* connection, + x11::Window root_window, + x11::Window window, const gfx::Point& location_px, int direction) { // This handler is usually sent when the window has the implicit grab. We // need to dump it because what we're about to do is tell the window manager // that it's now responsible for moving the window around; it immediately // grabs when it receives the event below. - XUngrabPointer(display, x11::CurrentTime); + connection->UngrabPointer({x11::Time::CurrentTime}); - XEvent event; - memset(&event, 0, sizeof(event)); - event.xclient.type = ClientMessage; - event.xclient.display = display; - event.xclient.window = window; - event.xclient.message_type = gfx::GetAtom("_NET_WM_MOVERESIZE"); - event.xclient.format = 32; - event.xclient.data.l[0] = location_px.x(); - event.xclient.data.l[1] = location_px.y(); - event.xclient.data.l[2] = direction; - - XSendEvent(display, root_window, x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, &event); + SendClientMessage(window, root_window, gfx::GetAtom("_NET_WM_MOVERESIZE"), + {location_px.x(), location_px.y(), direction, 0, 0}); } -bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom) { +bool HasWMSpecProperty(const base::flat_set<x11::Atom>& properties, + x11::Atom atom) { return properties.find(atom) != properties.end(); } @@ -1014,7 +1094,7 @@ bool IsWmTiling(WindowManagerName window_manager) { } } -bool GetWindowDesktop(XID window, int* desktop) { +bool GetWindowDesktop(x11::Window window, int* desktop) { return GetIntProperty(window, "_NET_WM_DESKTOP", desktop); } @@ -1025,26 +1105,21 @@ std::string GetX11ErrorString(XDisplay* display, int err) { } // Returns true if |window| is a named window. -bool IsWindowNamed(XID window) { - XTextProperty prop; - if (!XGetWMName(gfx::GetXDisplay(), window, &prop) || !prop.value) - return false; - - XFree(prop.value); - return true; +bool IsWindowNamed(x11::Window window) { + return PropertyExists(window, "WM_NAME"); } bool EnumerateChildren(EnumerateWindowsDelegate* delegate, - XID window, + x11::Window window, const int max_depth, int depth) { if (depth > max_depth) return false; - std::vector<XID> windows; - std::vector<XID>::iterator iter; + std::vector<x11::Window> windows; + std::vector<x11::Window>::iterator iter; if (depth == 0) { - XMenuList::GetInstance()->InsertMenuWindowXIDs(&windows); + XMenuList::GetInstance()->InsertMenuWindows(&windows); // Enumerate the menus first. for (iter = windows.begin(); iter != windows.end(); iter++) { if (delegate->ShouldStopIterating(*iter)) @@ -1053,17 +1128,10 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, windows.clear(); } - XID root, parent, *children; - unsigned int num_children; - int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children, - &num_children); - if (status == 0) + auto query_tree = x11::Connection::Get()->QueryTree({window}).Sync(); + if (!query_tree) return false; - - for (int i = static_cast<int>(num_children) - 1; i >= 0; i--) - windows.push_back(children[i]); - - XFree(children); + windows = std::move(query_tree->children); // XQueryTree returns the children of |window| in bottom-to-top order, so // reverse-iterate the list to check the windows from top-to-bottom. @@ -1087,12 +1155,12 @@ bool EnumerateChildren(EnumerateWindowsDelegate* delegate, } bool EnumerateAllWindows(EnumerateWindowsDelegate* delegate, int max_depth) { - XID root = GetX11RootWindow(); + x11::Window root = GetX11RootWindow(); return EnumerateChildren(delegate, root, max_depth, 0); } void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) { - std::vector<XID> stack; + std::vector<x11::Window> stack; if (!ui::GetXWindowStack(ui::GetX11RootWindow(), &stack)) { // Window Manager doesn't support _NET_CLIENT_LIST_STACKING, so fall back // to old school enumeration of all X windows. Some WMs parent 'top-level' @@ -1102,22 +1170,23 @@ void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate) { ui::EnumerateAllWindows(delegate, kMaxSearchDepth); return; } - XMenuList::GetInstance()->InsertMenuWindowXIDs(&stack); + XMenuList::GetInstance()->InsertMenuWindows(&stack); - std::vector<XID>::iterator iter; + std::vector<x11::Window>::iterator iter; for (iter = stack.begin(); iter != stack.end(); iter++) { if (delegate->ShouldStopIterating(*iter)) return; } } -bool GetXWindowStack(Window window, std::vector<XID>* windows) { - std::vector<uint32_t> value32; - if (!GetArrayProperty(window, "_NET_CLIENT_LIST_STACKING", &value32)) +bool GetXWindowStack(x11::Window window, std::vector<x11::Window>* windows) { + if (!GetArrayProperty(window, gfx::GetAtom("_NET_CLIENT_LIST_STACKING"), + windows)) { return false; + } // It's more common to iterate from lowest window to highest, // so reverse the vector. - *windows = std::vector<XID>(value32.rbegin(), value32.rend()); + std::reverse(windows->begin(), windows->end()); return true; } @@ -1181,9 +1250,15 @@ std::string GuessWindowManagerName() { } bool IsCompositingManagerPresent() { + auto is_compositing_manager_present_impl = []() { + auto response = x11::Connection::Get() + ->GetSelectionOwner({gfx::GetAtom("_NET_WM_CM_S0")}) + .Sync(); + return response && response->owner != x11::Window::None; + }; + static bool is_compositing_manager_present = - XGetSelectionOwner(gfx::GetXDisplay(), gfx::GetAtom("_NET_WM_CM_S0")) != - x11::None; + is_compositing_manager_present_impl(); return is_compositing_manager_present; } @@ -1191,13 +1266,13 @@ void SetDefaultX11ErrorHandlers() { SetX11ErrorHandlers(nullptr, nullptr); } -bool IsX11WindowFullScreen(XID window) { +bool IsX11WindowFullScreen(x11::Window window) { // If _NET_WM_STATE_FULLSCREEN is in _NET_SUPPORTED, use the presence or // absence of _NET_WM_STATE_FULLSCREEN in _NET_WM_STATE to determine // whether we're fullscreen. - XAtom fullscreen_atom = gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"); + x11::Atom fullscreen_atom = gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"); if (WmSupportsHint(fullscreen_atom)) { - std::vector<XAtom> atom_properties; + std::vector<x11::Atom> atom_properties; if (GetAtomArrayProperty(window, "_NET_WM_STATE", &atom_properties)) { return base::Contains(atom_properties, fullscreen_atom); } @@ -1207,23 +1282,20 @@ bool IsX11WindowFullScreen(XID window) { if (!ui::GetOuterWindowBounds(window, &window_rect)) return false; - // We can't use display::Screen here because we don't have an aura::Window. So - // instead just look at the size of the default display. - // - // TODO(erg): Actually doing this correctly would require pulling out xrandr, - // which we don't even do in the desktop screen yet. - ::XDisplay* display = gfx::GetXDisplay(); - ::Screen* screen = DefaultScreenOfDisplay(display); - int width = WidthOfScreen(screen); - int height = HeightOfScreen(screen); + // TODO(thomasanderson): We should use + // display::Screen::GetDisplayNearestWindow() instead of using the + // connection screen size, which encompasses all displays. + auto* connection = x11::Connection::Get(); + int width = connection->default_screen().width_in_pixels; + int height = connection->default_screen().height_in_pixels; return window_rect.size() == gfx::Size(width, height); } -bool WmSupportsHint(XAtom atom) { +bool WmSupportsHint(x11::Atom atom) { if (!SupportsEWMH()) return false; - std::vector<XAtom> supported_atoms; + std::vector<x11::Atom> supported_atoms; if (!GetAtomArrayProperty(GetX11RootWindow(), "_NET_SUPPORTED", &supported_atoms)) { return false; @@ -1236,27 +1308,13 @@ gfx::ICCProfile GetICCProfileForMonitor(int monitor) { gfx::ICCProfile icc_profile; if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) return icc_profile; - std::string atom_name; - if (monitor == 0) { - atom_name = "_ICC_PROFILE"; - } else { - atom_name = base::StringPrintf("_ICC_PROFILE_%d", monitor); - } - Atom property = gfx::GetAtom(atom_name.c_str()); - if (property != x11::None) { - Atom prop_type = x11::None; - int prop_format = 0; - unsigned long nitems = 0; - unsigned long nbytes = 0; - char* property_data = nullptr; - int result = XGetWindowProperty( - gfx::GetXDisplay(), DefaultRootWindow(gfx::GetXDisplay()), property, 0, - kLongLength, x11::False, AnyPropertyType, &prop_type, &prop_format, - &nitems, &nbytes, reinterpret_cast<unsigned char**>(&property_data)); - if (result == x11::Success) { - icc_profile = gfx::ICCProfile::FromData(property_data, nitems); - XFree(property_data); - } + std::string atom_name = monitor == 0 + ? "_ICC_PROFILE" + : base::StringPrintf("_ICC_PROFILE_%d", monitor); + std::vector<uint8_t> data; + if (GetRawBytesOfProperty(GetX11RootWindow(), gfx::GetAtom(atom_name), &data, + nullptr)) { + icc_profile = gfx::ICCProfile::FromData(data.data(), data.size()); } return icc_profile; } @@ -1298,7 +1356,7 @@ SkColorType ColorTypeForVisual(void* visual) { }; Visual* vis = reinterpret_cast<Visual*>(visual); // When running under Xvfb, a visual may not be set. - if (!vis->red_mask && !vis->green_mask && !vis->blue_mask) + if (!vis || !vis->red_mask || !vis->green_mask || !vis->blue_mask) return kUnknown_SkColorType; for (const auto& color_info : color_infos) { if (vis->red_mask == color_info.red_mask && @@ -1314,6 +1372,22 @@ SkColorType ColorTypeForVisual(void* visual) { return kUnknown_SkColorType; } +x11::Future<void> SendClientMessage(x11::Window window, + x11::Window target, + x11::Atom type, + const std::array<uint32_t, 5> data, + x11::EventMask event_mask) { + x11::ClientMessageEvent event{.format = 32, .window = window, .type = type}; + event.data.data32 = data; + auto event_bytes = x11::Write(event); + DCHECK_EQ(event_bytes.size(), 32ul); + + auto* connection = x11::Connection::Get(); + x11::SendEventRequest request{false, target, event_mask}; + std::copy(event_bytes.begin(), event_bytes.end(), request.event.begin()); + return connection->SendEvent(request); +} + XRefcountedMemory::XRefcountedMemory(unsigned char* x11_data, size_t length) : x11_data_(length ? x11_data : nullptr), length_(length) {} @@ -1404,32 +1478,20 @@ XVisualManager* XVisualManager::GetInstance() { return base::Singleton<XVisualManager>::get(); } -XVisualManager::XVisualManager() - : display_(gfx::GetXDisplay()), - default_visual_id_(0), - system_visual_id_(0), - transparent_visual_id_(0), - using_software_rendering_(false), - have_gpu_argb_visual_(false) { +XVisualManager::XVisualManager() : connection_(x11::Connection::Get()) { base::AutoLock lock(lock_); - int visuals_len = 0; - XVisualInfo visual_template; - visual_template.screen = DefaultScreen(display_); - gfx::XScopedPtr<XVisualInfo[]> visual_list(XGetVisualInfo( - display_, VisualScreenMask, &visual_template, &visuals_len)); - for (int i = 0; i < visuals_len; ++i) - visuals_[visual_list[i].visualid] = - std::make_unique<XVisualData>(visual_list[i]); - - XAtom NET_WM_CM_S0 = gfx::GetAtom("_NET_WM_CM_S0"); - using_compositing_wm_ = - XGetSelectionOwner(display_, NET_WM_CM_S0) != x11::None; + + for (const auto& depth : connection_->default_screen().allowed_depths) { + for (const auto& visual : depth.visuals) { + visuals_[visual.visual_id] = + std::make_unique<XVisualData>(depth.depth, &visual); + } + } // Choose the opaque visual. - default_visual_id_ = - XVisualIDFromVisual(DefaultVisual(display_, DefaultScreen(display_))); + default_visual_id_ = connection_->default_screen().root_visual; system_visual_id_ = default_visual_id_; - DCHECK(system_visual_id_); + DCHECK_NE(system_visual_id_, x11::VisualId{}); DCHECK(visuals_.find(system_visual_id_) != visuals_.end()); // Choose the transparent visual. @@ -1437,119 +1499,98 @@ XVisualManager::XVisualManager() // Why support only 8888 ARGB? Because it's all that GTK+ supports. In // gdkvisual-x11.cc, they look for this specific visual and use it for // all their alpha channel using needs. - const XVisualInfo& info = pair.second->visual_info; - if (info.depth == 32 && info.visual->red_mask == 0xff0000 && - info.visual->green_mask == 0x00ff00 && - info.visual->blue_mask == 0x0000ff) { - transparent_visual_id_ = info.visualid; + const auto& data = *pair.second; + if (data.depth == 32 && data.info->red_mask == 0xff0000 && + data.info->green_mask == 0x00ff00 && data.info->blue_mask == 0x0000ff) { + transparent_visual_id_ = pair.first; break; } } - if (transparent_visual_id_) + if (transparent_visual_id_ != x11::VisualId{}) DCHECK(visuals_.find(transparent_visual_id_) != visuals_.end()); } XVisualManager::~XVisualManager() = default; void XVisualManager::ChooseVisualForWindow(bool want_argb_visual, - Visual** visual, - int* depth, - Colormap* colormap, + x11::VisualId* visual_id, + uint8_t* depth, bool* visual_has_alpha) { base::AutoLock lock(lock_); - bool use_argb = want_argb_visual && using_compositing_wm_ && + bool use_argb = want_argb_visual && IsCompositingManagerPresent() && (using_software_rendering_ || have_gpu_argb_visual_); - VisualID visual_id = use_argb && transparent_visual_id_ - ? transparent_visual_id_ - : system_visual_id_; + x11::VisualId visual = use_argb && transparent_visual_id_ != x11::VisualId{} + ? transparent_visual_id_ + : system_visual_id_; - bool success = - GetVisualInfoImpl(visual_id, visual, depth, colormap, visual_has_alpha); + if (visual_id) + *visual_id = visual; + bool success = GetVisualInfoImpl(visual, depth, visual_has_alpha); DCHECK(success); } -bool XVisualManager::GetVisualInfo(VisualID visual_id, - Visual** visual, - int* depth, - Colormap* colormap, +bool XVisualManager::GetVisualInfo(x11::VisualId visual_id, + uint8_t* depth, bool* visual_has_alpha) { base::AutoLock lock(lock_); - return GetVisualInfoImpl(visual_id, visual, depth, colormap, - visual_has_alpha); + return GetVisualInfoImpl(visual_id, depth, visual_has_alpha); } bool XVisualManager::OnGPUInfoChanged(bool software_rendering, - VisualID system_visual_id, - VisualID transparent_visual_id) { + x11::VisualId system_visual_id, + x11::VisualId transparent_visual_id) { base::AutoLock lock(lock_); // TODO(thomasanderson): Cache these visual IDs as a property of the root // window so that newly created browser processes can get them immediately. - if ((system_visual_id && !visuals_.count(system_visual_id)) || - (transparent_visual_id && !visuals_.count(transparent_visual_id))) + if ((system_visual_id != x11::VisualId{} && + !visuals_.count(system_visual_id)) || + (transparent_visual_id != x11::VisualId{} && + !visuals_.count(transparent_visual_id))) return false; using_software_rendering_ = software_rendering; - have_gpu_argb_visual_ = have_gpu_argb_visual_ || transparent_visual_id; - if (system_visual_id) + have_gpu_argb_visual_ = + have_gpu_argb_visual_ || transparent_visual_id != x11::VisualId{}; + if (system_visual_id != x11::VisualId{}) system_visual_id_ = system_visual_id; - if (transparent_visual_id) + if (transparent_visual_id != x11::VisualId{}) transparent_visual_id_ = transparent_visual_id; return true; } bool XVisualManager::ArgbVisualAvailable() const { base::AutoLock lock(lock_); - return using_compositing_wm_ && + return IsCompositingManagerPresent() && (using_software_rendering_ || have_gpu_argb_visual_); } -bool XVisualManager::GetVisualInfoImpl(VisualID visual_id, - Visual** visual, - int* depth, - Colormap* colormap, +bool XVisualManager::GetVisualInfoImpl(x11::VisualId visual_id, + uint8_t* depth, bool* visual_has_alpha) { auto it = visuals_.find(visual_id); if (it == visuals_.end()) return false; - XVisualData& visual_data = *it->second; - const XVisualInfo& visual_info = visual_data.visual_info; - - bool is_default_visual = visual_id == default_visual_id_; + XVisualData& data = *it->second; + const x11::VisualType& info = *data.info; - if (visual) - *visual = visual_info.visual; if (depth) - *depth = visual_info.depth; - if (colormap) - *colormap = - is_default_visual ? 0 /* CopyFromParent */ : visual_data.GetColormap(); + *depth = data.depth; if (visual_has_alpha) { auto popcount = [](auto x) { return std::bitset<8 * sizeof(decltype(x))>(x).count(); }; - *visual_has_alpha = popcount(visual_info.red_mask) + - popcount(visual_info.green_mask) + - popcount(visual_info.blue_mask) < - static_cast<std::size_t>(visual_info.depth); + *visual_has_alpha = popcount(info.red_mask) + popcount(info.green_mask) + + popcount(info.blue_mask) < + static_cast<std::size_t>(data.depth); } return true; } -XVisualManager::XVisualData::XVisualData(XVisualInfo visual_info) - : visual_info(visual_info), colormap_(0 /* CopyFromParent */) {} +XVisualManager::XVisualData::XVisualData(uint8_t depth, + const x11::VisualType* info) + : depth(depth), info(info) {} -// Do not XFreeColormap as this would uninstall the colormap even for -// non-Chromium clients. XVisualManager::XVisualData::~XVisualData() = default; -Colormap XVisualManager::XVisualData::GetColormap() { - XDisplay* display = gfx::GetXDisplay(); - if (colormap_ == 0 /* CopyFromParent */) { - colormap_ = XCreateColormap(display, DefaultRootWindow(display), - visual_info.visual, AllocNone); - } - return colormap_; -} - // ---------------------------------------------------------------------------- // End of x11_util_internal.h diff --git a/chromium/ui/base/x/x11_util.h b/chromium/ui/base/x/x11_util.h index ff1dd2c5635..4c7c574a921 100644 --- a/chromium/ui/base/x/x11_util.h +++ b/chromium/ui/base/x/x11_util.h @@ -21,10 +21,12 @@ #include "base/containers/flat_set.h" #include "base/macros.h" #include "base/memory/ref_counted_memory.h" +#include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/platform_event.h" #include "ui/gfx/icc_profile.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11_types.h" typedef unsigned long Cursor; @@ -38,9 +40,195 @@ class SkBitmap; namespace ui { +enum WmState : uint32_t { + WM_STATE_WITHDRAWN = 0, + WM_STATE_NORMAL = 1, + WM_STATE_ICONIC = 3, +}; + +enum SizeHintsFlags : int32_t { + SIZE_HINT_US_POSITION = 1 << 0, + SIZE_HINT_US_SIZE = 1 << 1, + SIZE_HINT_P_POSITION = 1 << 2, + SIZE_HINT_P_SIZE = 1 << 3, + SIZE_HINT_P_MIN_SIZE = 1 << 4, + SIZE_HINT_P_MAX_SIZE = 1 << 5, + SIZE_HINT_P_RESIZE_INC = 1 << 6, + SIZE_HINT_P_ASPECT = 1 << 7, + SIZE_HINT_BASE_SIZE = 1 << 8, + SIZE_HINT_P_WIN_GRAVITY = 1 << 9, +}; + +struct SizeHints { + // User specified flags + int32_t flags; + // User-specified position + int32_t x, y; + // User-specified size + int32_t width, height; + // Program-specified minimum size + int32_t min_width, min_height; + // Program-specified maximum size + int32_t max_width, max_height; + // Program-specified resize increments + int32_t width_inc, height_inc; + // Program-specified minimum aspect ratios + int32_t min_aspect_num, min_aspect_den; + // Program-specified maximum aspect ratios + int32_t max_aspect_num, max_aspect_den; + // Program-specified base size + int32_t base_width, base_height; + // Program-specified window gravity + uint32_t win_gravity; +}; + +enum WmHintsFlags : uint32_t { + WM_HINT_INPUT = 1L << 0, + WM_HINT_STATE = 1L << 1, + WM_HINT_ICON_PIXMAP = 1L << 2, + WM_HINT_ICON_WINDOW = 1L << 3, + WM_HINT_ICON_POSITION = 1L << 4, + WM_HINT_ICON_MASK = 1L << 5, + WM_HINT_WINDOW_GROUP = 1L << 6, + // 1L << 7 doesn't have any defined meaning + WM_HINT_X_URGENCY = 1L << 8 +}; + +struct WmHints { + // Marks which fields in this structure are defined + int32_t flags; + // Does this application rely on the window manager to get keyboard input? + uint32_t input; + // See below + int32_t initial_state; + // Pixmap to be used as icon + xcb_pixmap_t icon_pixmap; + // Window to be used as icon + xcb_window_t icon_window; + // Initial position of icon + int32_t icon_x, icon_y; + // Icon mask bitmap + xcb_pixmap_t icon_mask; + // Identifier of related window group + xcb_window_t window_group; +}; + // These functions use the default display and this /must/ be called from // the UI thread. Thus, they don't support multiple displays. +template <typename T> +bool GetArrayProperty(x11::Window window, + x11::Atom name, + std::vector<T>* value, + x11::Atom* out_type = nullptr, + size_t amount = 0) { + static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, ""); + + size_t bytes = amount * sizeof(T); + // The length field specifies the maximum amount of data we would like the + // server to give us. It's specified in units of 4 bytes, so divide by 4. + // Add 3 before division to round up. + size_t length = (bytes + 3) / 4; + using lentype = decltype(x11::GetPropertyRequest::long_length); + auto response = + x11::Connection::Get() + ->GetProperty( + {.window = static_cast<x11::Window>(window), + .property = name, + .long_length = + amount ? length : std::numeric_limits<lentype>::max()}) + .Sync(); + if (!response || response->format != CHAR_BIT * sizeof(T)) + return false; + + DCHECK_EQ(response->format / CHAR_BIT * response->value_len, + response->value.size()); + value->resize(response->value_len); + memcpy(value->data(), response->value.data(), response->value.size()); + if (out_type) + *out_type = response->type; + return true; +} + +template <typename T> +bool GetProperty(x11::Window window, const x11::Atom name, T* value) { + std::vector<T> values; + if (!GetArrayProperty(window, name, &values, nullptr, 1) || values.empty()) + return false; + *value = values[0]; + return true; +} + +template <typename T> +void SetArrayProperty(x11::Window window, + x11::Atom name, + x11::Atom type, + const std::vector<T>& values) { + static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4, ""); + std::vector<uint8_t> data(sizeof(T) * values.size()); + memcpy(data.data(), values.data(), sizeof(T) * values.size()); + x11::Connection::Get()->ChangeProperty( + {.window = static_cast<x11::Window>(window), + .property = name, + .type = type, + .format = CHAR_BIT * sizeof(T), + .data_len = values.size(), + .data = data}); +} + +template <typename T> +void SetProperty(x11::Window window, + x11::Atom name, + x11::Atom type, + const T& value) { + SetArrayProperty(window, name, type, std::vector<T>{value}); +} + +template <typename T> +void SendEvent(const T& event, x11::Window target, x11::EventMask mask) { + static_assert(T::type_id > 0, "T must be an x11::*Event type"); + auto event_bytes = x11::Write(event); + DCHECK_LE(event_bytes.size(), 32ul); + event_bytes.resize(32); + + x11::SendEventRequest send_event{false, target, mask}; + std::copy(event_bytes.begin(), event_bytes.end(), send_event.event.begin()); + x11::Connection::Get()->SendEvent(send_event); +} + +COMPONENT_EXPORT(UI_BASE_X) +void DeleteProperty(x11::Window window, x11::Atom name); + +COMPONENT_EXPORT(UI_BASE_X) +bool GetWmNormalHints(x11::Window window, SizeHints* hints); + +COMPONENT_EXPORT(UI_BASE_X) +void SetWmNormalHints(x11::Window window, const SizeHints& hints); + +COMPONENT_EXPORT(UI_BASE_X) +bool GetWmHints(x11::Window window, WmHints* hints); + +COMPONENT_EXPORT(UI_BASE_X) +void SetWmHints(x11::Window window, const WmHints& hints); + +COMPONENT_EXPORT(UI_BASE_X) +void WithdrawWindow(x11::Window window); + +COMPONENT_EXPORT(UI_BASE_X) +void RaiseWindow(x11::Window window); + +COMPONENT_EXPORT(UI_BASE_X) +void LowerWindow(x11::Window window); + +COMPONENT_EXPORT(UI_BASE_X) +void DefineCursor(x11::Window window, x11::Cursor cursor); + +COMPONENT_EXPORT(UI_BASE_X) +x11::Window CreateDummyWindow(const std::string& name = ""); + +COMPONENT_EXPORT(UI_BASE_X) +x11::KeyCode KeysymToKeycode(x11::Connection* connection, x11::KeySym keysym); + // These functions cache their results --------------------------------- // Returns true if the system supports XINPUT2. @@ -73,11 +261,16 @@ COMPONENT_EXPORT(UI_BASE_X) XcursorImage* SkBitmapToXcursorImage(const SkBitmap& bitmap, const gfx::Point& hotspot); +// Loads and returns an X11 cursor, trying to find one that matches |type|. If +// unavailable, x11::None is returned. +COMPONENT_EXPORT(UI_BASE_X) +::Cursor LoadCursorFromType(mojom::CursorType type); + // Coalesce all pending motion events (touch or mouse) that are at the top of // the queue, and return the number eliminated, storing the last one in // |last_event|. COMPONENT_EXPORT(UI_BASE_X) -int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event); +int CoalescePendingMotionEvents(const x11::Event* xev, x11::Event* last_event); // Hides the host cursor. COMPONENT_EXPORT(UI_BASE_X) void HideHostCursor(); @@ -87,7 +280,7 @@ COMPONENT_EXPORT(UI_BASE_X)::Cursor CreateInvisibleCursor(); // Sets whether |window| should use the OS window frame. COMPONENT_EXPORT(UI_BASE_X) -void SetUseOSWindowFrame(XID window, bool use_os_window_frame); +void SetUseOSWindowFrame(x11::Window window, bool use_os_window_frame); // These functions do not cache their results -------------------------- @@ -95,122 +288,123 @@ void SetUseOSWindowFrame(XID window, bool use_os_window_frame); COMPONENT_EXPORT(UI_BASE_X) bool IsShapeExtensionAvailable(); // Get the X window id for the default root window -COMPONENT_EXPORT(UI_BASE_X) XID GetX11RootWindow(); +COMPONENT_EXPORT(UI_BASE_X) x11::Window GetX11RootWindow(); // Returns the user's current desktop. COMPONENT_EXPORT(UI_BASE_X) bool GetCurrentDesktop(int* desktop); -enum HideTitlebarWhenMaximized { +enum HideTitlebarWhenMaximized : uint32_t { SHOW_TITLEBAR_WHEN_MAXIMIZED = 0, HIDE_TITLEBAR_WHEN_MAXIMIZED = 1, }; // Sets _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED on |window|. COMPONENT_EXPORT(UI_BASE_X) -void SetHideTitlebarWhenMaximizedProperty(XID window, +void SetHideTitlebarWhenMaximizedProperty(x11::Window window, HideTitlebarWhenMaximized property); // Clears all regions of X11's default root window by filling black pixels. COMPONENT_EXPORT(UI_BASE_X) void ClearX11DefaultRootWindow(); // Returns true if |window| is visible. -COMPONENT_EXPORT(UI_BASE_X) bool IsWindowVisible(XID window); +COMPONENT_EXPORT(UI_BASE_X) bool IsWindowVisible(x11::Window window); // Returns the inner bounds of |window| (excluding the non-client area). COMPONENT_EXPORT(UI_BASE_X) -bool GetInnerWindowBounds(XID window, gfx::Rect* rect); +bool GetInnerWindowBounds(x11::Window window, gfx::Rect* rect); // Returns the non-client area extents of |window|. This is a negative inset; it // represents the negative size of the window border on all sides. // InnerWindowBounds.Inset(WindowExtents) = OuterWindowBounds. // Returns false if the window manager does not provide extents information. COMPONENT_EXPORT(UI_BASE_X) -bool GetWindowExtents(XID window, gfx::Insets* extents); +bool GetWindowExtents(x11::Window window, gfx::Insets* extents); // Returns the outer bounds of |window| (including the non-client area). COMPONENT_EXPORT(UI_BASE_X) -bool GetOuterWindowBounds(XID window, gfx::Rect* rect); +bool GetOuterWindowBounds(x11::Window window, gfx::Rect* rect); // Returns true if |window| contains the point |screen_loc|. COMPONENT_EXPORT(UI_BASE_X) -bool WindowContainsPoint(XID window, gfx::Point screen_loc); +bool WindowContainsPoint(x11::Window window, gfx::Point screen_loc); // Return true if |window| has any property with |property_name|. COMPONENT_EXPORT(UI_BASE_X) -bool PropertyExists(XID window, const std::string& property_name); +bool PropertyExists(x11::Window window, const std::string& property_name); // Returns the raw bytes from a property with minimal // interpretation. |out_data| should be freed by XFree() after use. COMPONENT_EXPORT(UI_BASE_X) -bool GetRawBytesOfProperty(XID window, - XAtom property, - scoped_refptr<base::RefCountedMemory>* out_data, - size_t* out_data_items, - XAtom* out_type); +bool GetRawBytesOfProperty(x11::Window window, + x11::Atom property, + std::vector<uint8_t>* out_data, + x11::Atom* out_type); // Get the value of an int, int array, atom array or string property. On // success, true is returned and the value is stored in |value|. // -// TODO(erg): Once we remove the gtk port and are 100% aura, all of these -// should accept an XAtom instead of a string. -COMPONENT_EXPORT(UI_BASE_X) -bool GetIntProperty(XID window, const std::string& property_name, int* value); +// These functions should no longer be used. TODO(thomasanderson): migrate +// existing callers to {Set,Get}{,Array}Property<> instead. COMPONENT_EXPORT(UI_BASE_X) -bool GetXIDProperty(XID window, const std::string& property_name, XID* value); +bool GetIntProperty(x11::Window window, + const std::string& property_name, + int32_t* value); COMPONENT_EXPORT(UI_BASE_X) -bool GetIntArrayProperty(XID window, +bool GetIntArrayProperty(x11::Window window, const std::string& property_name, - std::vector<int>* value); + std::vector<int32_t>* value); COMPONENT_EXPORT(UI_BASE_X) -bool GetAtomArrayProperty(XID window, +bool GetAtomArrayProperty(x11::Window window, const std::string& property_name, - std::vector<XAtom>* value); + std::vector<x11::Atom>* value); COMPONENT_EXPORT(UI_BASE_X) -bool GetStringProperty(XID window, +bool GetStringProperty(x11::Window window, const std::string& property_name, std::string* value); -// These setters all make round trips. COMPONENT_EXPORT(UI_BASE_X) -bool SetIntProperty(XID window, +void SetIntProperty(x11::Window window, const std::string& name, const std::string& type, - int value); + int32_t value); COMPONENT_EXPORT(UI_BASE_X) -bool SetIntArrayProperty(XID window, +void SetIntArrayProperty(x11::Window window, const std::string& name, const std::string& type, - const std::vector<int>& value); + const std::vector<int32_t>& value); COMPONENT_EXPORT(UI_BASE_X) -bool SetAtomProperty(XID window, +void SetAtomProperty(x11::Window window, const std::string& name, const std::string& type, - XAtom value); + x11::Atom value); COMPONENT_EXPORT(UI_BASE_X) -bool SetAtomArrayProperty(XID window, +void SetAtomArrayProperty(x11::Window window, const std::string& name, const std::string& type, - const std::vector<XAtom>& value); + const std::vector<x11::Atom>& value); COMPONENT_EXPORT(UI_BASE_X) -bool SetStringProperty(XID window, - XAtom property, - XAtom type, +void SetStringProperty(x11::Window window, + x11::Atom property, + x11::Atom type, const std::string& value); // Sets the WM_CLASS attribute for a given X11 window. COMPONENT_EXPORT(UI_BASE_X) -void SetWindowClassHint(XDisplay* display, - XID window, +void SetWindowClassHint(x11::Connection* connection, + x11::Window window, const std::string& res_name, const std::string& res_class); // Sets the WM_WINDOW_ROLE attribute for a given X11 window. COMPONENT_EXPORT(UI_BASE_X) -void SetWindowRole(XDisplay* display, XID window, const std::string& role); +void SetWindowRole(x11::Window window, const std::string& role); // Sends a message to the x11 window manager, enabling or disabling the // states |state1| and |state2|. COMPONENT_EXPORT(UI_BASE_X) -void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2); +void SetWMSpecState(x11::Window window, + bool enabled, + x11::Atom state1, + x11::Atom state2); // Sends a NET_WM_MOVERESIZE message to the x11 window manager, enabling the // move/resize mode. As per NET_WM_MOVERESIZE spec, |location| is the position @@ -218,15 +412,16 @@ void SetWMSpecState(XID window, bool enabled, XAtom state1, XAtom state2); // |direction| indicates whether this is a move or resize event, and if it is a // resize event, which edges of the window the size grip applies to. COMPONENT_EXPORT(UI_BASE_X) -void DoWMMoveResize(XDisplay* display, - XID root_window, - XID window, +void DoWMMoveResize(x11::Connection* connection, + x11::Window root_window, + x11::Window window, const gfx::Point& location_px, int direction); // Checks if the window manager has set a specific state. COMPONENT_EXPORT(UI_BASE_X) -bool HasWMSpecProperty(const base::flat_set<XAtom>& properties, XAtom atom); +bool HasWMSpecProperty(const base::flat_set<x11::Atom>& properties, + x11::Atom atom); // Determine whether we should default to native decorations or the custom // frame based on the currently-running window manager. @@ -235,7 +430,8 @@ COMPONENT_EXPORT(UI_BASE_X) bool GetCustomFramePrefDefault(); static const int kAllDesktops = -1; // Queries the desktop |window| is on, kAllDesktops if sticky. Returns false if // property not found. -COMPONENT_EXPORT(UI_BASE_X) bool GetWindowDesktop(XID window, int* desktop); +COMPONENT_EXPORT(UI_BASE_X) +bool GetWindowDesktop(x11::Window window, int* desktop); // Translates an X11 error code into a printable string. COMPONENT_EXPORT(UI_BASE_X) @@ -245,12 +441,12 @@ std::string GetX11ErrorString(XDisplay* display, int err); // the main display. class EnumerateWindowsDelegate { public: - // |xid| is the X Window ID of the enumerated window. Return true to stop + // |window| is the X Window ID of the enumerated window. Return true to stop // further iteration. - virtual bool ShouldStopIterating(XID xid) = 0; + virtual bool ShouldStopIterating(x11::Window window) = 0; protected: - virtual ~EnumerateWindowsDelegate() {} + virtual ~EnumerateWindowsDelegate() = default; }; // Enumerates all windows in the current display. Will recurse into child @@ -265,7 +461,7 @@ void EnumerateTopLevelWindows(ui::EnumerateWindowsDelegate* delegate); // Returns all children windows of a given window in top-to-bottom stacking // order. COMPONENT_EXPORT(UI_BASE_X) -bool GetXWindowStack(XID window, std::vector<XID>* windows); +bool GetXWindowStack(x11::Window window, std::vector<x11::Window>* windows); enum WindowManagerName { WM_OTHER, // We were able to obtain the WM's name, but there is @@ -316,10 +512,10 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsCompositingManagerPresent(); COMPONENT_EXPORT(UI_BASE_X) void SetDefaultX11ErrorHandlers(); // Returns true if a given window is in full-screen mode. -COMPONENT_EXPORT(UI_BASE_X) bool IsX11WindowFullScreen(XID window); +COMPONENT_EXPORT(UI_BASE_X) bool IsX11WindowFullScreen(x11::Window window); // Returns true if the window manager supports the given hint. -COMPONENT_EXPORT(UI_BASE_X) bool WmSupportsHint(XAtom atom); +COMPONENT_EXPORT(UI_BASE_X) bool WmSupportsHint(x11::Atom atom); // Returns the ICCProfile corresponding to |monitor| using XGetWindowProperty. COMPONENT_EXPORT(UI_BASE_X) @@ -333,6 +529,15 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsSyncExtensionAvailable(); COMPONENT_EXPORT(UI_BASE_X) SkColorType ColorTypeForVisual(void* visual); +COMPONENT_EXPORT(UI_BASE_X) +x11::Future<void> SendClientMessage( + x11::Window window, + x11::Window target, + x11::Atom type, + const std::array<uint32_t, 5> data, + x11::EventMask event_mask = x11::EventMask::SubstructureNotify | + x11::EventMask::SubstructureRedirect); + // Manages a piece of X11 allocated memory as a RefCountedMemory segment. This // object takes ownership over the passed in memory and will free it with the // X11 allocator when done. diff --git a/chromium/ui/base/x/x11_util_internal.h b/chromium/ui/base/x/x11_util_internal.h index cd97da64e02..705c606c7b5 100644 --- a/chromium/ui/base/x/x11_util_internal.h +++ b/chromium/ui/base/x/x11_util_internal.h @@ -55,18 +55,14 @@ class COMPONENT_EXPORT(UI_BASE_X) XVisualManager { public: static XVisualManager* GetInstance(); - // Picks the best argb or opaque visual given |want_argb_visual|. If the - // default visual is returned, |colormap| is set to CopyFromParent. + // Picks the best argb or opaque visual given |want_argb_visual|. void ChooseVisualForWindow(bool want_argb_visual, - Visual** visual, - int* depth, - Colormap* colormap, + x11::VisualId* visual_id, + uint8_t* depth, bool* visual_has_alpha); - bool GetVisualInfo(VisualID visual_id, - Visual** visual, - int* depth, - Colormap* colormap, + bool GetVisualInfo(x11::VisualId visual_id, + uint8_t* depth, bool* visual_has_alpha); // Called by GpuDataManagerImplPrivate when GPUInfo becomes available. It is @@ -74,8 +70,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XVisualManager { // because we don't want to load GL in the browser process. Returns false iff // |default_visual_id| or |transparent_visual_id| are invalid. bool OnGPUInfoChanged(bool software_rendering, - VisualID default_visual_id, - VisualID transparent_visual_id); + x11::VisualId default_visual_id, + x11::VisualId transparent_visual_id); // Are all of the system requirements met for using transparent visuals? bool ArgbVisualAvailable() const; @@ -87,41 +83,34 @@ class COMPONENT_EXPORT(UI_BASE_X) XVisualManager { class XVisualData { public: - explicit XVisualData(XVisualInfo visual_info); + XVisualData(uint8_t depth, const x11::VisualType* info); ~XVisualData(); - Colormap GetColormap(); - - const XVisualInfo visual_info; - - private: - Colormap colormap_; + uint8_t depth = 0; + const x11::VisualType* info = nullptr; }; XVisualManager(); - bool GetVisualInfoImpl(VisualID visual_id, - Visual** visual, - int* depth, - Colormap* colormap, + bool GetVisualInfoImpl(x11::VisualId visual_id, + uint8_t* depth, bool* visual_has_alpha); mutable base::Lock lock_; - std::unordered_map<VisualID, std::unique_ptr<XVisualData>> visuals_; + std::unordered_map<x11::VisualId, std::unique_ptr<XVisualData>> visuals_; - XDisplay* display_; + x11::Connection* const connection_; - VisualID default_visual_id_; + x11::VisualId default_visual_id_{}; // The system visual is usually the same as the default visual, but // may not be in general. - VisualID system_visual_id_; - VisualID transparent_visual_id_; + x11::VisualId system_visual_id_{}; + x11::VisualId transparent_visual_id_{}; - bool using_compositing_wm_; - bool using_software_rendering_; - bool have_gpu_argb_visual_; + bool using_software_rendering_ = false; + bool have_gpu_argb_visual_ = false; DISALLOW_COPY_AND_ASSIGN(XVisualManager); }; diff --git a/chromium/ui/base/x/x11_whole_screen_move_loop.cc b/chromium/ui/base/x/x11_whole_screen_move_loop.cc index 2f7aaf4037a..39f4d0c12aa 100644 --- a/chromium/ui/base/x/x11_whole_screen_move_loop.cc +++ b/chromium/ui/base/x/x11_whole_screen_move_loop.cc @@ -26,25 +26,34 @@ #include "ui/events/platform/x11/x11_event_source.h" #include "ui/events/x/events_x_utils.h" #include "ui/events/x/x11_window_event_manager.h" +#include "ui/gfx/x/connection.h" #include "ui/gfx/x/x11.h" namespace ui { +namespace { + +constexpr x11::KeySym kEscKeysym = static_cast<x11::KeySym>(0xff1b); + // XGrabKey requires the modifier mask to explicitly be specified. -const unsigned int kModifiersMasks[] = {0, // No additional modifier. - Mod2Mask, // Num lock - LockMask, // Caps lock - Mod5Mask, // Scroll lock - Mod2Mask | LockMask, - Mod2Mask | Mod5Mask, - LockMask | Mod5Mask, - Mod2Mask | LockMask | Mod5Mask}; +constexpr x11::ModMask kModifiersMasks[] = { + {}, // No additional modifier. + x11::ModMask::c_2, // Num lock + x11::ModMask::Lock, // Caps lock + x11::ModMask::c_5, // Scroll lock + x11::ModMask::c_2 | x11::ModMask::Lock, + x11::ModMask::c_2 | x11::ModMask::c_5, + x11::ModMask::Lock | x11::ModMask::c_5, + x11::ModMask::c_2 | x11::ModMask::Lock | x11::ModMask::c_5, +}; + +} // namespace X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate) : delegate_(delegate), in_move_loop_(false), initial_cursor_(x11::None), - grab_input_window_(x11::None), + grab_input_window_(x11::Window::None), grabbed_pointer_(false), canceled_(false) {} @@ -131,7 +140,7 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(bool can_grab_pointer, // restored when the move loop finishes. initial_cursor_ = old_cursor; - CreateDragInputWindow(gfx::GetXDisplay()); + CreateDragInputWindow(x11::Connection::Get()); // Only grab mouse capture of |grab_input_window_| if |can_grab_pointer| is // true aka the source that initiated the move loop doesn't have explicit @@ -145,7 +154,7 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(bool can_grab_pointer, if (can_grab_pointer) { grabbed_pointer_ = GrabPointer(new_cursor); if (!grabbed_pointer_) { - XDestroyWindow(gfx::GetXDisplay(), grab_input_window_); + x11::Connection::Get()->DestroyWindow({grab_input_window_}); return false; } } @@ -194,59 +203,65 @@ void X11WholeScreenMoveLoop::EndMoveLoop() { else UpdateCursor(initial_cursor_); - XDisplay* display = gfx::GetXDisplay(); - unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape); + auto* connection = x11::Connection::Get(); + auto esc_keycode = KeysymToKeycode(connection, kEscKeysym); for (auto mask : kModifiersMasks) - XUngrabKey(display, esc_keycode, mask, grab_input_window_); + connection->UngrabKey({esc_keycode, grab_input_window_, mask}); // Restore the previous dispatcher. nested_dispatcher_.reset(); delegate_->OnMoveLoopEnded(); grab_input_window_events_.reset(); - XDestroyWindow(display, grab_input_window_); - grab_input_window_ = x11::None; + connection->DestroyWindow({grab_input_window_}); + grab_input_window_ = x11::Window::None; in_move_loop_ = false; std::move(quit_closure_).Run(); } bool X11WholeScreenMoveLoop::GrabPointer(::Cursor cursor) { - XDisplay* display = gfx::GetXDisplay(); + auto* connection = x11::Connection::Get(); // Pass "owner_events" as false so that X sends all mouse events to // |grab_input_window_|. int ret = ui::GrabPointer(grab_input_window_, false, cursor); if (ret != GrabSuccess) { DLOG(ERROR) << "Grabbing pointer for dragging failed: " - << ui::GetX11ErrorString(display, ret); + << ui::GetX11ErrorString(connection->display(), ret); } - XFlush(display); + connection->Flush(); return ret == GrabSuccess; } void X11WholeScreenMoveLoop::GrabEscKey() { - XDisplay* display = gfx::GetXDisplay(); - unsigned int esc_keycode = XKeysymToKeycode(display, XK_Escape); + auto* connection = x11::Connection::Get(); + auto esc_keycode = KeysymToKeycode(connection, kEscKeysym); for (auto mask : kModifiersMasks) { - XGrabKey(display, esc_keycode, mask, grab_input_window_, x11::False, - GrabModeAsync, GrabModeAsync); + connection->GrabKey({false, grab_input_window_, mask, esc_keycode, + x11::GrabMode::Async, x11::GrabMode::Async}); } } -void X11WholeScreenMoveLoop::CreateDragInputWindow(XDisplay* display) { - XSetWindowAttributes swa; - memset(&swa, 0, sizeof(swa)); - swa.override_redirect = x11::True; - grab_input_window_ = XCreateWindow(display, DefaultRootWindow(display), -100, - -100, 10, 10, 0, CopyFromParent, InputOnly, - CopyFromParent, CWOverrideRedirect, &swa); +void X11WholeScreenMoveLoop::CreateDragInputWindow( + x11::Connection* connection) { + grab_input_window_ = connection->GenerateId<x11::Window>(); + connection->CreateWindow({ + .wid = grab_input_window_, + .parent = connection->default_root(), + .x = -100, + .y = -100, + .width = 10, + .height = 10, + .c_class = x11::WindowClass::InputOnly, + .override_redirect = x11::Bool32(true), + }); uint32_t event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask; grab_input_window_events_ = std::make_unique<ui::XScopedEventSelector>( grab_input_window_, event_mask); - - XMapRaised(display, grab_input_window_); + connection->MapWindow({grab_input_window_}); + RaiseWindow(grab_input_window_); } } // namespace ui diff --git a/chromium/ui/base/x/x11_whole_screen_move_loop.h b/chromium/ui/base/x/x11_whole_screen_move_loop.h index 1132b905529..eae75d85f04 100644 --- a/chromium/ui/base/x/x11_whole_screen_move_loop.h +++ b/chromium/ui/base/x/x11_whole_screen_move_loop.h @@ -55,7 +55,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11WholeScreenMoveLoop void GrabEscKey(); // Creates an input-only window to be used during the drag. - void CreateDragInputWindow(XDisplay* display); + void CreateDragInputWindow(x11::Connection* connection); // Dispatch mouse movement event to |delegate_| in a posted task. void DispatchMouseMovement(); @@ -74,7 +74,7 @@ class COMPONENT_EXPORT(UI_BASE_X) X11WholeScreenMoveLoop // An invisible InputOnly window. Keyboard grab and sometimes mouse grab // are set on this window. - XID grab_input_window_; + x11::Window grab_input_window_; // Events selected on |grab_input_window_|. std::unique_ptr<ui::XScopedEventSelector> grab_input_window_events_; diff --git a/chromium/ui/base/x/x11_window.cc b/chromium/ui/base/x/x11_window.cc index 70f520bccd4..bc5f4fefa7a 100644 --- a/chromium/ui/base/x/x11_window.cc +++ b/chromium/ui/base/x/x11_window.cc @@ -13,6 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "net/base/network_interfaces.h" #include "third_party/skia/include/core/SkRegion.h" #include "ui/base/hit_test_x11.h" #include "ui/base/wm_role_names_linux.h" @@ -31,9 +32,13 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" #include "ui/gfx/skia_util.h" +#include "ui/gfx/x/connection.h" #include "ui/gfx/x/x11_atom_cache.h" #include "ui/gfx/x/x11_error_tracker.h" #include "ui/gfx/x/x11_path.h" +#include "ui/gfx/x/xfixes.h" +#include "ui/gfx/x/xinput.h" +#include "ui/gfx/x/xproto.h" #include "ui/platform_window/common/platform_window_defaults.h" namespace ui { @@ -46,7 +51,7 @@ const int kAllWorkspaces = 0xFFFFFFFF; constexpr char kX11WindowRolePopup[] = "popup"; constexpr char kX11WindowRoleBubble[] = "bubble"; -constexpr unsigned char kDarkGtkThemeVariant[] = "dark"; +constexpr char kDarkGtkThemeVariant[] = "dark"; constexpr long kSystemTrayRequestDock = 0; @@ -54,6 +59,11 @@ constexpr int kXembedInfoProtocolVersion = 0; constexpr int kXembedFlagMap = 1 << 0; constexpr int kXembedInfoFlags = kXembedFlagMap; +enum CrossingFlags : uint8_t { + CROSSING_FLAG_FOCUS = 1 << 0, + CROSSING_FLAG_SAME_SCREEN = 1 << 1, +}; + // In some situations, views tries to make a zero sized window, and that // makes us crash. Make sure we have valid sizes. gfx::Rect SanitizeBounds(const gfx::Rect& bounds) { @@ -64,59 +74,76 @@ gfx::Rect SanitizeBounds(const gfx::Rect& bounds) { } void SerializeImageRepresentation(const gfx::ImageSkiaRep& rep, - std::vector<unsigned long>* data) { - int width = rep.GetWidth(); + std::vector<uint32_t>* data) { + uint32_t width = rep.GetWidth(); data->push_back(width); - int height = rep.GetHeight(); + uint32_t height = rep.GetHeight(); data->push_back(height); const SkBitmap& bitmap = rep.GetBitmap(); - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; ++x) + for (uint32_t y = 0; y < height; ++y) + for (uint32_t x = 0; x < width; ++x) data->push_back(bitmap.getColor(x, y)); } -int XI2ModeToXMode(int xi2_mode) { +x11::NotifyMode XI2ModeToXMode(x11::Input::NotifyMode xi2_mode) { switch (xi2_mode) { - case XINotifyNormal: - return NotifyNormal; - case XINotifyGrab: - case XINotifyPassiveGrab: - return NotifyGrab; - case XINotifyUngrab: - case XINotifyPassiveUngrab: - return NotifyUngrab; - case XINotifyWhileGrabbed: - return NotifyWhileGrabbed; + case x11::Input::NotifyMode::Normal: + return x11::NotifyMode::Normal; + case x11::Input::NotifyMode::Grab: + case x11::Input::NotifyMode::PassiveGrab: + return x11::NotifyMode::Grab; + case x11::Input::NotifyMode::Ungrab: + case x11::Input::NotifyMode::PassiveUngrab: + return x11::NotifyMode::Ungrab; + case x11::Input::NotifyMode::WhileGrabbed: + return x11::NotifyMode::WhileGrabbed; default: NOTREACHED(); - return NotifyNormal; + return x11::NotifyMode::Normal; } } -bool SyncSetCounter(XDisplay* display, XID counter, int64_t value) { - XSyncValue sync_value; - XSyncIntsToValue(&sync_value, value & 0xFFFFFFFF, value >> 32); - return XSyncSetCounter(display, counter, sync_value) == x11::True; +x11::NotifyDetail XI2DetailToXDetail(x11::Input::NotifyDetail xi2_detail) { + switch (xi2_detail) { + case x11::Input::NotifyDetail::Ancestor: + return x11::NotifyDetail::Ancestor; + case x11::Input::NotifyDetail::Virtual: + return x11::NotifyDetail::Virtual; + case x11::Input::NotifyDetail::Inferior: + return x11::NotifyDetail::Inferior; + case x11::Input::NotifyDetail::Nonlinear: + return x11::NotifyDetail::Nonlinear; + case x11::Input::NotifyDetail::NonlinearVirtual: + return x11::NotifyDetail::NonlinearVirtual; + case x11::Input::NotifyDetail::Pointer: + return x11::NotifyDetail::Pointer; + case x11::Input::NotifyDetail::PointerRoot: + return x11::NotifyDetail::PointerRoot; + case x11::Input::NotifyDetail::None: + return x11::NotifyDetail::None; + } } -// Returns the whole path from |window| to the root. -std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) { - ::Window parent_win, root_win; - Window* child_windows; - unsigned int num_child_windows; - std::vector<::Window> result; +void SyncSetCounter(x11::Connection* connection, + x11::Sync::Counter counter, + int64_t value) { + x11::Sync::Int64 sync_value{.hi = value >> 32, .lo = value & 0xFFFFFFFF}; + connection->sync().SetCounter({counter, sync_value}); +} - while (window) { +// Returns the whole path from |window| to the root. +std::vector<x11::Window> GetParentsList(x11::Connection* connection, + x11::Window window) { + std::vector<x11::Window> result; + while (window != x11::Window::None) { result.push_back(window); - if (!XQueryTree(xdisplay, window, &root_win, &parent_win, &child_windows, - &num_child_windows)) + if (auto reply = connection->QueryTree({window}).Sync()) + window = reply->parent; + else break; - if (child_windows) - XFree(child_windows); - window = parent_win; } return result; } @@ -139,15 +166,15 @@ XWindow::Configuration::Configuration(const Configuration&) = default; XWindow::Configuration::~Configuration() = default; XWindow::XWindow() - : xdisplay_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(xdisplay_)) { - DCHECK(xdisplay_); - DCHECK_NE(x_root_window_, x11::None); + : connection_(x11::Connection::Get()), x_root_window_(GetX11RootWindow()) { + DCHECK(connection_); + DCHECK_NE(x_root_window_, x11::Window::None); } XWindow::~XWindow() { - DCHECK_EQ(xwindow_, x11::None) << "XWindow destructed without calling " - "Close() to release allocated resources."; + DCHECK_EQ(xwindow_, x11::Window::None) + << "XWindow destructed without calling " + "Close() to release allocated resources."; } void XWindow::Init(const Configuration& config) { @@ -157,31 +184,28 @@ void XWindow::Init(const Configuration& config) { activatable_ = config.activatable; - unsigned long attribute_mask = CWBackPixel | CWBitGravity; - XSetWindowAttributes swa; - memset(&swa, 0, sizeof(swa)); - swa.background_pixmap = x11::None; - swa.bit_gravity = NorthWestGravity; - swa.background_pixel = config.background_color.has_value() + x11::CreateWindowRequest req; + req.bit_gravity = x11::Gravity::NorthWest; + req.background_pixel = config.background_color.has_value() ? config.background_color.value() - : WhitePixel(xdisplay_, DefaultScreen(xdisplay_)); + : connection_->default_screen().white_pixel; - XAtom window_type; + x11::Atom window_type; switch (config.type) { case WindowType::kMenu: - swa.override_redirect = x11::True; + req.override_redirect = x11::Bool32(true); window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_MENU"); break; case WindowType::kTooltip: - swa.override_redirect = x11::True; + req.override_redirect = x11::Bool32(true); window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP"); break; case WindowType::kPopup: - swa.override_redirect = x11::True; + req.override_redirect = x11::Bool32(true); window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION"); break; case WindowType::kDrag: - swa.override_redirect = x11::True; + req.override_redirect = x11::Bool32(true); window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_DND"); break; default: @@ -190,7 +214,7 @@ void XWindow::Init(const Configuration& config) { } // An in-activatable window should not interact with the system wm. if (!activatable_ || config.override_redirect) - swa.override_redirect = x11::True; + req.override_redirect = x11::Bool32(true); #if !defined(USE_X11) // It seems like there is a difference how tests are instantiated in case of @@ -204,12 +228,10 @@ void XWindow::Init(const Configuration& config) { // here. Otherwise, tests for non-Ozone X11 fail. // TODO(msisov): figure out usage of this for non-Ozone X11. if (UseTestConfigForPlatformWindows()) - swa.override_redirect = true; + req.override_redirect = x11::Bool32(true); #endif - override_redirect_ = swa.override_redirect == x11::True; - if (override_redirect_) - attribute_mask |= CWOverrideRedirect; + override_redirect_ = req.override_redirect.has_value(); bool enable_transparent_visuals; switch (config.opacity) { @@ -223,44 +245,42 @@ void XWindow::Init(const Configuration& config) { enable_transparent_visuals = config.type == WindowType::kDrag; } - int visual_id; if (config.wm_role_name == kStatusIconWmRoleName) { std::string atom_name = - "_NET_SYSTEM_TRAY_S" + base::NumberToString(DefaultScreen(xdisplay_)); - XID manager = - XGetSelectionOwner(xdisplay_, gfx::GetAtom(atom_name.c_str())); - if (ui::GetIntProperty(manager, "_NET_SYSTEM_TRAY_VISUAL", &visual_id)) - visual_id_ = visual_id; - } - - Visual* visual = CopyFromParent; - int depth = CopyFromParent; - Colormap colormap = CopyFromParent; - ui::XVisualManager* visual_manager = ui::XVisualManager::GetInstance(); - if (!visual_id_ || - !visual_manager->GetVisualInfo(visual_id_, &visual, &depth, &colormap, - &visual_has_alpha_)) { - visual_manager->ChooseVisualForWindow(enable_transparent_visuals, &visual, - &depth, &colormap, - &visual_has_alpha_); + "_NET_SYSTEM_TRAY_S" + + base::NumberToString(connection_->DefaultScreenId()); + auto selection = connection_->GetSelectionOwner({gfx::GetAtom(atom_name)}); + if (auto reply = selection.Sync()) { + GetProperty(reply->owner, gfx::GetAtom("_NET_SYSTEM_TRAY_VISUAL"), + &visual_id_); + } } - if (colormap != CopyFromParent) { - attribute_mask |= CWColormap; - swa.colormap = colormap; + x11::VisualId visual_id = visual_id_; + uint8_t depth = 0; + XVisualManager* visual_manager = XVisualManager::GetInstance(); + if (visual_id_ == x11::VisualId{} || + !visual_manager->GetVisualInfo(visual_id_, &depth, &visual_has_alpha_)) { + visual_manager->ChooseVisualForWindow( + enable_transparent_visuals, &visual_id, &depth, &visual_has_alpha_); } // x.org will BadMatch if we don't set a border when the depth isn't the // same as the parent depth. - attribute_mask |= CWBorderPixel; - swa.border_pixel = 0; + req.border_pixel = 0; bounds_in_pixels_ = SanitizeBounds(config.bounds); - xwindow_ = XCreateWindow(xdisplay_, x_root_window_, bounds_in_pixels_.x(), - bounds_in_pixels_.y(), bounds_in_pixels_.width(), - bounds_in_pixels_.height(), - 0, // border width - depth, InputOutput, visual, attribute_mask, &swa); + req.parent = x_root_window_; + req.x = bounds_in_pixels_.x(); + req.y = bounds_in_pixels_.y(); + req.width = bounds_in_pixels_.width(); + req.height = bounds_in_pixels_.height(); + req.depth = depth; + req.c_class = x11::WindowClass::InputOutput; + req.visual = visual_id; + xwindow_ = connection_->GenerateId<x11::Window>(); + req.wid = xwindow_; + connection_->CreateWindow(req); // It can be a status icon window. If it fails to initialize, don't provide // him with a native window handle, close self and let the client destroy @@ -281,15 +301,12 @@ void XWindow::Init(const Configuration& config) { StructureNotifyMask | PropertyChangeMask | PointerMotionMask; xwindow_events_ = - std::make_unique<ui::XScopedEventSelector>(xwindow_, event_mask); - XFlush(xdisplay_); + std::make_unique<XScopedEventSelector>(xwindow_, event_mask); + connection_->Flush(); - if (ui::IsXInput2Available()) - ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); + if (IsXInput2Available()) + TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_); - // TODO(erg): We currently only request window deletion events. We also - // should listen for activation events and anything else that GTK+ listens - // for, and do something useful. // Request the _NET_WM_SYNC_REQUEST protocol which is used for synchronizing // between chrome and desktop compositor (or WM) during resizing. // The resizing behavior with _NET_WM_SYNC_REQUEST is: @@ -305,31 +322,29 @@ void XWindow::Init(const Configuration& config) { // frame with new content from chrome. // 7. Desktop compositor responses user mouse move events, and starts a new // resize process, go to step 1. - XAtom protocols[] = { + std::vector<x11::Atom> protocols = { gfx::GetAtom("WM_DELETE_WINDOW"), gfx::GetAtom("_NET_WM_PING"), gfx::GetAtom("_NET_WM_SYNC_REQUEST"), }; - XSetWMProtocols(xdisplay_, xwindow_, protocols, base::size(protocols)); + SetArrayProperty(xwindow_, gfx::GetAtom("WM_PROTOCOLS"), x11::Atom::ATOM, + protocols); - // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with - // the desktop environment. - XSetWMProperties(xdisplay_, xwindow_, nullptr, nullptr, nullptr, 0, nullptr, - nullptr, nullptr); + // We need a WM_CLIENT_MACHINE value so we integrate with the desktop + // environment. + SetStringProperty(xwindow_, gfx::GetAtom("WM_CLIENT_MACHINE"), + gfx::GetAtom("STRING"), net::GetHostName()); // Likewise, the X server needs to know this window's pid so it knows which // program to kill if the window hangs. // XChangeProperty() expects "pid" to be long. - static_assert(sizeof(long) >= sizeof(pid_t), - "pid_t should not be larger than long"); - long pid = getpid(); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_PID"), XA_CARDINAL, - 32, PropModeReplace, reinterpret_cast<unsigned char*>(&pid), - 1); + static_assert(sizeof(uint32_t) >= sizeof(pid_t), + "pid_t should not be larger than uint32_t"); + uint32_t pid = getpid(); + SetProperty(xwindow_, gfx::GetAtom("_NET_WM_PID"), x11::Atom::CARDINAL, pid); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_WINDOW_TYPE"), - XA_ATOM, 32, PropModeReplace, - reinterpret_cast<unsigned char*>(&window_type), 1); + SetProperty(xwindow_, gfx::GetAtom("_NET_WM_WINDOW_TYPE"), x11::Atom::ATOM, + window_type); // The changes to |window_properties_| here will be sent to the X server just // before the window is mapped. @@ -350,16 +365,16 @@ void XWindow::Init(const Configuration& config) { workspace_ = base::nullopt; if (config.visible_on_all_workspaces) { window_properties_.insert(gfx::GetAtom("_NET_WM_STATE_STICKY")); - ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", kAllWorkspaces); + SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", kAllWorkspaces); } else if (!config.workspace.empty()) { int workspace; if (base::StringToInt(config.workspace, &workspace)) - ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", workspace); + SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", workspace); } if (!config.wm_class_name.empty() || !config.wm_class_class.empty()) { - ui::SetWindowClassHint(xdisplay_, xwindow_, config.wm_class_name, - config.wm_class_class); + SetWindowClassHint(connection_, xwindow_, config.wm_class_name, + config.wm_class_class); } const char* wm_role_name = nullptr; @@ -380,40 +395,40 @@ void XWindow::Init(const Configuration& config) { } } if (wm_role_name) - ui::SetWindowRole(xdisplay_, xwindow_, std::string(wm_role_name)); + SetWindowRole(xwindow_, std::string(wm_role_name)); if (config.remove_standard_frame) { // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force // fullscreen on the window when it matches the desktop size. - ui::SetHideTitlebarWhenMaximizedProperty(xwindow_, - ui::HIDE_TITLEBAR_WHEN_MAXIMIZED); + SetHideTitlebarWhenMaximizedProperty(xwindow_, + HIDE_TITLEBAR_WHEN_MAXIMIZED); } if (config.prefer_dark_theme) { - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_GTK_THEME_VARIANT"), - gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace, - kDarkGtkThemeVariant, base::size(kDarkGtkThemeVariant) - 1); + SetStringProperty(xwindow_, gfx::GetAtom("_GTK_THEME_VARIANT"), + gfx::GetAtom("UTF8_STRING"), kDarkGtkThemeVariant); } - if (ui::IsSyncExtensionAvailable()) { - XSyncValue value; - XSyncIntToValue(&value, 0); - update_counter_ = XSyncCreateCounter(xdisplay_, value); - extended_update_counter_ = XSyncCreateCounter(xdisplay_, value); - XID counters[]{update_counter_, extended_update_counter_}; + if (IsSyncExtensionAvailable()) { + x11::Sync::Int64 value{}; + update_counter_ = connection_->GenerateId<x11::Sync::Counter>(); + connection_->sync().CreateCounter({update_counter_, value}); + extended_update_counter_ = connection_->GenerateId<x11::Sync::Counter>(); + connection_->sync().CreateCounter({extended_update_counter_, value}); + + std::vector<x11::Sync::Counter> counters{update_counter_, + extended_update_counter_}; // Set XSyncCounter as window property _NET_WM_SYNC_REQUEST_COUNTER. the // compositor will listen on them during resizing. - XChangeProperty( - xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_SYNC_REQUEST_COUNTER"), - XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast<const unsigned char*>(counters), base::size(counters)); + SetArrayProperty(xwindow_, gfx::GetAtom("_NET_WM_SYNC_REQUEST_COUNTER"), + x11::Atom::CARDINAL, counters); } // Always composite Chromium windows if a compositing WM is used. Sometimes, // WMs will not composite fullscreen windows as an optimization, but this can // lead to tearing of fullscreen videos. - ui::SetIntProperty(xwindow_, "_NET_WM_BYPASS_COMPOSITOR", "CARDINAL", 2); + SetIntProperty(xwindow_, "_NET_WM_BYPASS_COMPOSITOR", "CARDINAL", 2); if (config.icon) SetXWindowIcons(gfx::ImageSkia(), *config.icon); @@ -422,58 +437,55 @@ void XWindow::Init(const Configuration& config) { void XWindow::Map(bool inactive) { // Before we map the window, set size hints. Otherwise, some window managers // will ignore toplevel XMoveWindow commands. - XSizeHints size_hints; - size_hints.flags = 0; - long supplied_return; - XGetWMNormalHints(xdisplay_, xwindow_, &size_hints, &supplied_return); - size_hints.flags |= PPosition; + SizeHints size_hints; + memset(&size_hints, 0, sizeof(size_hints)); + GetWmNormalHints(xwindow_, &size_hints); + size_hints.flags |= SIZE_HINT_P_POSITION; size_hints.x = bounds_in_pixels_.x(); size_hints.y = bounds_in_pixels_.y(); - XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); + SetWmNormalHints(xwindow_, size_hints); ignore_keyboard_input_ = inactive; - unsigned long wm_user_time_ms = + uint32_t wm_user_time_ms = ignore_keyboard_input_ ? 0 : X11EventSource::GetInstance()->GetTimestamp(); if (inactive || wm_user_time_ms != 0) { - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"), - XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast<const unsigned char*>(&wm_user_time_ms), - 1); + SetProperty(xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"), + x11::Atom::CARDINAL, wm_user_time_ms); } UpdateMinAndMaxSize(); if (window_properties_.empty()) { - XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_STATE")); + DeleteProperty(xwindow_, gfx::GetAtom("_NET_WM_STATE")); } else { - ui::SetAtomArrayProperty(xwindow_, "_NET_WM_STATE", "ATOM", - std::vector<XAtom>(std::begin(window_properties_), + SetAtomArrayProperty(xwindow_, "_NET_WM_STATE", "ATOM", + std::vector<x11::Atom>(std::begin(window_properties_), std::end(window_properties_))); } - XMapWindow(xdisplay_, xwindow_); + connection_->MapWindow({xwindow_}); window_mapped_in_client_ = true; // TODO(thomasanderson): Find out why this flush is necessary. - XFlush(xdisplay_); + connection_->Flush(); } void XWindow::Close() { - if (xwindow_ == x11::None) + if (xwindow_ == x11::Window::None) return; CancelResize(); UnconfineCursor(); - XDestroyWindow(xdisplay_, xwindow_); - xwindow_ = x11::None; + connection_->DestroyWindow({xwindow_}); + xwindow_ = x11::Window::None; - if (update_counter_ != x11::None) { - XSyncDestroyCounter(xdisplay_, update_counter_); - XSyncDestroyCounter(xdisplay_, extended_update_counter_); - update_counter_ = x11::None; - extended_update_counter_ = x11::None; + if (update_counter_ != x11::Sync::Counter{}) { + connection_->sync().DestroyCounter({update_counter_}); + connection_->sync().DestroyCounter({extended_update_counter_}); + update_counter_ = {}; + extended_update_counter_ = {}; } } @@ -487,10 +499,12 @@ void XWindow::Maximize() { } void XWindow::Minimize() { - if (window_mapped_in_client_) - XIconifyWindow(xdisplay_, xwindow_, 0); - else - SetWMSpecState(true, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::None); + if (window_mapped_in_client_) { + SendClientMessage(xwindow_, x_root_window_, gfx::GetAtom("WM_CHANGE_STATE"), + {WM_STATE_ICONIC, 0, 0, 0, 0}); + } else { + SetWMSpecState(true, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); + } } void XWindow::Unmaximize() { @@ -506,18 +520,18 @@ bool XWindow::Hide() { // Make sure no resize task will run after the window is unmapped. CancelResize(); - XWithdrawWindow(xdisplay_, xwindow_, 0); + WithdrawWindow(xwindow_); window_mapped_in_client_ = false; return true; } void XWindow::Unhide() { - SetWMSpecState(false, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::None); + SetWMSpecState(false, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None); } void XWindow::SetFullscreen(bool fullscreen) { SetWMSpecState(fullscreen, gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"), - x11::None); + x11::Atom::None); } void XWindow::Activate() { @@ -531,45 +545,41 @@ void XWindow::Activate() { // wmii says that it supports _NET_ACTIVE_WINDOW but does not. // https://code.google.com/p/wmii/issues/detail?id=266 static bool wm_supports_active_window = - ui::GuessWindowManager() != ui::WM_WMII && - ui::WmSupportsHint(gfx::GetAtom("_NET_ACTIVE_WINDOW")); + GuessWindowManager() != WM_WMII && + WmSupportsHint(gfx::GetAtom("_NET_ACTIVE_WINDOW")); ::Time timestamp = X11EventSource::GetInstance()->GetTimestamp(); // override_redirect windows ignore _NET_ACTIVE_WINDOW. // https://crbug.com/940924 if (wm_supports_active_window && !override_redirect_) { - XEvent xclient; - memset(&xclient, 0, sizeof(xclient)); - xclient.type = ClientMessage; - xclient.xclient.window = xwindow_; - xclient.xclient.message_type = gfx::GetAtom("_NET_ACTIVE_WINDOW"); - xclient.xclient.format = 32; - xclient.xclient.data.l[0] = 1; // Specified we are an app. - xclient.xclient.data.l[1] = timestamp; - // TODO(thomasanderson): if another chrome window is active, specify that in - // data.l[2]. The EWMH spec claims this may make the WM more likely to - // service our _NET_ACTIVE_WINDOW request. - xclient.xclient.data.l[2] = x11::None; - xclient.xclient.data.l[3] = 0; - xclient.xclient.data.l[4] = 0; - - XSendEvent(xdisplay_, x_root_window_, x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, &xclient); + std::array<uint32_t, 5> data = { + // We're an app. + 1, + timestamp, + // TODO(thomasanderson): if another chrome window is active, specify + // that here. The EWMH spec claims this may make the WM more likely to + // service our _NET_ACTIVE_WINDOW request. + 0, + 0, + 0, + }; + SendClientMessage(xwindow_, x_root_window_, + gfx::GetAtom("_NET_ACTIVE_WINDOW"), data); } else { - XRaiseWindow(xdisplay_, xwindow_); + RaiseWindow(xwindow_); // Directly ask the X server to give focus to the window. Note that the call // would have raised an X error if the window is not mapped. - auto ignore_errors = [](XDisplay*, XErrorEvent*) -> int { return 0; }; - auto old_error_handler = XSetErrorHandler(ignore_errors); - XSetInputFocus(xdisplay_, xwindow_, RevertToParent, timestamp); + connection_ + ->SetInputFocus({x11::InputFocus::Parent, xwindow_, + static_cast<x11::Time>(timestamp)}) + .IgnoreError(); // At this point, we know we will receive focus, and some // webdriver tests depend on a window being IsActive() immediately // after an Activate(), so just set this state now. has_pointer_focus_ = false; has_window_focus_ = true; window_mapped_in_server_ = true; - XSetErrorHandler(old_error_handler); } AfterActivationStateChanged(); @@ -581,7 +591,7 @@ void XWindow::Deactivate() { // Ignore future input events. ignore_keyboard_input_ = true; - XLowerWindow(xdisplay_, xwindow_); + ui::LowerWindow(xwindow_); AfterActivationStateChanged(); } @@ -594,8 +604,9 @@ bool XWindow::IsActive() const { return (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_; } void XWindow::SetSize(const gfx::Size& size_in_pixels) { - XResizeWindow(xdisplay_, xwindow_, size_in_pixels.width(), - size_in_pixels.height()); + connection_->ConfigureWindow({.window = xwindow_, + .width = size_in_pixels.width(), + .height = size_in_pixels.height()}); bounds_in_pixels_.set_size(size_in_pixels); } @@ -603,8 +614,8 @@ void XWindow::SetBounds(const gfx::Rect& requested_bounds_in_pixels) { gfx::Rect bounds_in_pixels(requested_bounds_in_pixels); bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); - XWindowChanges changes = {0}; - unsigned value_mask = 0; + + x11::ConfigureWindowRequest req{.window = xwindow_}; if (size_changed) { // Update the minimum and maximum sizes in case they have changed. @@ -622,19 +633,17 @@ void XWindow::SetBounds(const gfx::Rect& requested_bounds_in_pixels) { bounds_in_pixels.set_size(size_in_pixels); } - changes.width = bounds_in_pixels.width(); - changes.height = bounds_in_pixels.height(); - value_mask |= CWHeight | CWWidth; + req.width = bounds_in_pixels.width(); + req.height = bounds_in_pixels.height(); } if (origin_changed) { - changes.x = bounds_in_pixels.x(); - changes.y = bounds_in_pixels.y(); - value_mask |= CWX | CWY; + req.x = bounds_in_pixels.x(); + req.y = bounds_in_pixels.y(); } - if (value_mask) - XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes); + if (origin_changed || size_changed) + connection_->ConfigureWindow(req); // Assume that the resize will go through as requested, which should be the // case if we're running without a window manager. If there's a window @@ -658,23 +667,23 @@ bool XWindow::IsXWindowVisible() const { } bool XWindow::IsMinimized() const { - return ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_HIDDEN")); + return HasWMSpecProperty(window_properties_, + gfx::GetAtom("_NET_WM_STATE_HIDDEN")); } bool XWindow::IsMaximized() const { - return (ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) && - ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))); + return (HasWMSpecProperty(window_properties_, + gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) && + HasWMSpecProperty(window_properties_, + gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"))); } bool XWindow::IsFullscreen() const { - return ui::HasWMSpecProperty(window_properties_, - gfx::GetAtom("_NET_WM_STATE_FULLSCREEN")); + return HasWMSpecProperty(window_properties_, + gfx::GetAtom("_NET_WM_STATE_FULLSCREEN")); } -gfx::Rect XWindow::GetOutterBounds() const { +gfx::Rect XWindow::GetOuterBounds() const { gfx::Rect outer_bounds(bounds_in_pixels_); outer_bounds.Inset(-native_window_frame_borders_in_pixels_); return outer_bounds; @@ -687,18 +696,18 @@ void XWindow::GrabPointer() { } void XWindow::ReleasePointerGrab() { - ui::UngrabPointer(); + UngrabPointer(); has_pointer_grab_ = false; } -void XWindow::StackXWindowAbove(::Window window) { - DCHECK(window != x11::None); +void XWindow::StackXWindowAbove(x11::Window window) { + DCHECK(window != x11::Window::None); // Find all parent windows up to the root. - std::vector<::Window> window_below_parents = - GetParentsList(xdisplay_, window); - std::vector<::Window> window_above_parents = - GetParentsList(xdisplay_, xwindow_); + std::vector<x11::Window> window_below_parents = + GetParentsList(connection_, window); + std::vector<x11::Window> window_above_parents = + GetParentsList(connection_, xwindow_); // Find their common ancestor. auto it_below_window = window_below_parents.rbegin(); @@ -711,23 +720,21 @@ void XWindow::StackXWindowAbove(::Window window) { if (it_below_window != window_below_parents.rend() && it_above_window != window_above_parents.rend()) { - // First stack |xwindow| below so Z-order of |window| stays the same. - ::Window windows[] = {*it_below_window, *it_above_window}; - if (XRestackWindows(xdisplay_, windows, 2) == 0) { - // Now stack them properly. - std::swap(windows[0], windows[1]); - XRestackWindows(xdisplay_, windows, 2); - } + connection_->ConfigureWindow({ + .window = *it_above_window, + .sibling = *it_below_window, + .stack_mode = x11::StackMode::Above, + }); } } void XWindow::StackXWindowAtTop() { - XRaiseWindow(xdisplay_, xwindow_); + RaiseWindow(xwindow_); } void XWindow::SetCursor(::Cursor cursor) { last_cursor_ = cursor; - XDefineCursor(xdisplay_, xwindow_, cursor); + DefineCursor(xwindow_, static_cast<x11::Cursor>(cursor)); } bool XWindow::SetTitle(base::string16 title) { @@ -736,17 +743,10 @@ bool XWindow::SetTitle(base::string16 title) { window_title_ = title; std::string utf8str = base::UTF16ToUTF8(title); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_NAME"), - gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace, - reinterpret_cast<const unsigned char*>(utf8str.c_str()), - utf8str.size()); - XTextProperty xtp; - char* c_utf8_str = const_cast<char*>(utf8str.c_str()); - if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle, - &xtp) == x11::Success) { - XSetWMName(xdisplay_, xwindow_, &xtp); - XFree(xtp.value); - } + SetStringProperty(xwindow_, gfx::GetAtom("_NET_WM_NAME"), + gfx::GetAtom("UTF8_STRING"), utf8str); + SetStringProperty(xwindow_, x11::Atom::WM_NAME, gfx::GetAtom("UTF8_STRING"), + utf8str); return true; } @@ -756,35 +756,35 @@ void XWindow::SetXWindowOpacity(float opacity) { // XChangeProperty() expects "cardinality" to be long. // Scale opacity to [0 .. 255] range. - unsigned long opacity_8bit = - static_cast<unsigned long>(opacity * 255.0f) & 0xFF; + uint32_t opacity_8bit = static_cast<uint32_t>(opacity * 255.0f) & 0xFF; // Use opacity value for all channels. - const unsigned long channel_multiplier = 0x1010101; - unsigned long cardinality = opacity_8bit * channel_multiplier; + uint32_t channel_multiplier = 0x1010101; + uint32_t cardinality = opacity_8bit * channel_multiplier; if (cardinality == 0xffffffff) { - XDeleteProperty(xdisplay_, xwindow_, - gfx::GetAtom("_NET_WM_WINDOW_OPACITY")); + DeleteProperty(xwindow_, gfx::GetAtom("_NET_WM_WINDOW_OPACITY")); } else { - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_WINDOW_OPACITY"), - XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast<unsigned char*>(&cardinality), 1); + SetProperty(xwindow_, gfx::GetAtom("_NET_WM_WINDOW_OPACITY"), + x11::Atom::CARDINAL, cardinality); } } void XWindow::SetXWindowAspectRatio(const gfx::SizeF& aspect_ratio) { - XSizeHints size_hints; - size_hints.flags = 0; - long supplied_return; + SizeHints size_hints; + memset(&size_hints, 0, sizeof(size_hints)); - XGetWMNormalHints(xdisplay_, xwindow_, &size_hints, &supplied_return); + GetWmNormalHints(xwindow_, &size_hints); // Unforce aspect ratio is parameter length is 0, otherwise set normally. - if (!aspect_ratio.IsEmpty()) { - size_hints.flags |= PAspect; - size_hints.min_aspect.x = size_hints.max_aspect.x = aspect_ratio.width(); - size_hints.min_aspect.y = size_hints.max_aspect.y = aspect_ratio.height(); + if (aspect_ratio.IsEmpty()) { + size_hints.flags &= ~SIZE_HINT_P_ASPECT; + } else { + size_hints.flags |= SIZE_HINT_P_ASPECT; + size_hints.min_aspect_num = size_hints.max_aspect_num = + aspect_ratio.width(); + size_hints.min_aspect_den = size_hints.max_aspect_den = + aspect_ratio.height(); } - XSetWMNormalHints(xdisplay_, xwindow_, &size_hints); + SetWmNormalHints(xwindow_, size_hints); } void XWindow::SetXWindowIcons(const gfx::ImageSkia& window_icon, @@ -797,7 +797,7 @@ void XWindow::SetXWindowIcons(const gfx::ImageSkia& window_icon, // so that we can pass to the WM. // // All of this could be made much, much better. - std::vector<unsigned long> data; + std::vector<uint32_t> data; if (!window_icon.isNull()) SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data); @@ -805,35 +805,27 @@ void XWindow::SetXWindowIcons(const gfx::ImageSkia& window_icon, if (!app_icon.isNull()) SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data); - if (!data.empty()) - ui::SetAtomArrayProperty(xwindow_, "_NET_WM_ICON", "CARDINAL", data); + if (!data.empty()) { + SetArrayProperty(xwindow_, gfx::GetAtom("_NET_WM_ICON"), + x11::Atom::CARDINAL, data); + } } void XWindow::SetXWindowVisibleOnAllWorkspaces(bool visible) { - SetWMSpecState(visible, gfx::GetAtom("_NET_WM_STATE_STICKY"), x11::None); + SetWMSpecState(visible, gfx::GetAtom("_NET_WM_STATE_STICKY"), + x11::Atom::None); int new_desktop = 0; if (visible) { new_desktop = kAllWorkspaces; } else { - if (!ui::GetCurrentDesktop(&new_desktop)) + if (!GetCurrentDesktop(&new_desktop)) return; } workspace_ = kAllWorkspaces; - XEvent xevent; - memset(&xevent, 0, sizeof(xevent)); - xevent.type = ClientMessage; - xevent.xclient.window = xwindow_; - xevent.xclient.message_type = gfx::GetAtom("_NET_WM_DESKTOP"); - xevent.xclient.format = 32; - xevent.xclient.data.l[0] = new_desktop; - xevent.xclient.data.l[1] = 0; - xevent.xclient.data.l[2] = 0; - xevent.xclient.data.l[3] = 0; - xevent.xclient.data.l[4] = 0; - XSendEvent(xdisplay_, x_root_window_, x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, &xevent); + SendClientMessage(xwindow_, x_root_window_, gfx::GetAtom("_NET_WM_DESKTOP"), + {new_desktop, 0, 0, 0, 0}); } bool XWindow::IsXWindowVisibleOnAllWorkspaces() const { @@ -845,13 +837,15 @@ bool XWindow::IsXWindowVisibleOnAllWorkspaces() const { } void XWindow::MoveCursorTo(const gfx::Point& location_in_pixels) { - XWarpPointer(xdisplay_, x11::None, x_root_window_, 0, 0, 0, 0, - bounds_in_pixels_.x() + location_in_pixels.x(), - bounds_in_pixels_.y() + location_in_pixels.y()); + connection_->WarpPointer({ + .dst_window = x_root_window_, + .dst_x = bounds_in_pixels_.x() + location_in_pixels.x(), + .dst_y = bounds_in_pixels_.y() + location_in_pixels.y(), + }); } void XWindow::ResetWindowRegion() { - XRegion* xregion = nullptr; + std::unique_ptr<std::vector<x11::Rectangle>> xregion; if (!use_custom_shape() && !IsMaximized() && !IsFullscreen()) { SkPath window_mask; GetWindowMaskForXWindow(bounds().size(), &window_mask); @@ -860,13 +854,13 @@ void XWindow::ResetWindowRegion() { if (window_mask.countPoints() > 0) xregion = gfx::CreateRegionFromSkPath(window_mask); } - UpdateWindowRegion(xregion); + UpdateWindowRegion(std::move(xregion)); } void XWindow::OnWorkspaceUpdated() { auto old_workspace = workspace_; int workspace; - if (ui::GetWindowDesktop(xwindow_, &workspace)) + if (GetWindowDesktop(xwindow_, &workspace)) workspace_ = workspace; else workspace_ = base::nullopt; @@ -877,25 +871,24 @@ void XWindow::OnWorkspaceUpdated() { void XWindow::SetAlwaysOnTop(bool always_on_top) { is_always_on_top_ = always_on_top; - SetWMSpecState(always_on_top, gfx::GetAtom("_NET_WM_STATE_ABOVE"), x11::None); + SetWMSpecState(always_on_top, gfx::GetAtom("_NET_WM_STATE_ABOVE"), + x11::Atom::None); } void XWindow::SetFlashFrameHint(bool flash_frame) { if (urgency_hint_set_ == flash_frame) return; - gfx::XScopedPtr<XWMHints> hints(XGetWMHints(xdisplay_, xwindow_)); - if (!hints) { - // The window hasn't had its hints set yet. - hints.reset(XAllocWMHints()); - } + WmHints hints; + memset(&hints, 0, sizeof(hints)); + GetWmHints(xwindow_, &hints); if (flash_frame) - hints->flags |= XUrgencyHint; + hints.flags |= WM_HINT_X_URGENCY; else - hints->flags &= ~XUrgencyHint; + hints.flags &= ~WM_HINT_X_URGENCY; - XSetWMHints(xdisplay_, xwindow_, hints.get()); + SetWmHints(xwindow_, hints); urgency_hint_set_ = flash_frame; } @@ -911,28 +904,27 @@ void XWindow::UpdateMinAndMaxSize() { min_size_in_pixels_ = minimum_in_pixels.value(); max_size_in_pixels_ = maximum_in_pixels.value(); - XSizeHints hints; - hints.flags = 0; - long supplied_return; - XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return); + SizeHints hints; + memset(&hints, 0, sizeof(hints)); + GetWmNormalHints(xwindow_, &hints); if (min_size_in_pixels_.IsEmpty()) { - hints.flags &= ~PMinSize; + hints.flags &= ~SIZE_HINT_P_MIN_SIZE; } else { - hints.flags |= PMinSize; + hints.flags |= SIZE_HINT_P_MIN_SIZE; hints.min_width = min_size_in_pixels_.width(); hints.min_height = min_size_in_pixels_.height(); } if (max_size_in_pixels_.IsEmpty()) { - hints.flags &= ~PMaxSize; + hints.flags &= ~SIZE_HINT_P_MAX_SIZE; } else { - hints.flags |= PMaxSize; + hints.flags |= SIZE_HINT_P_MAX_SIZE; hints.max_width = max_size_in_pixels_.width(); hints.max_height = max_size_in_pixels_.height(); } - XSetWMNormalHints(xdisplay_, xwindow_, &hints); + SetWmNormalHints(xwindow_, hints); } void XWindow::BeforeActivationStateChanged() { @@ -961,24 +953,24 @@ void XWindow::AfterActivationStateChanged() { void XWindow::SetUseNativeFrame(bool use_native_frame) { use_native_frame_ = use_native_frame; - ui::SetUseOSWindowFrame(xwindow_, use_native_frame); + SetUseOSWindowFrame(xwindow_, use_native_frame); ResetWindowRegion(); } void XWindow::OnCrossingEvent(bool enter, bool focus_in_window_or_ancestor, - int mode, - int detail) { + x11::NotifyMode mode, + x11::NotifyDetail detail) { // NotifyInferior on a crossing event means the pointer moved into or out of a // child window, but the pointer is still within |xwindow_|. - if (detail == NotifyInferior) + if (detail == x11::NotifyDetail::Inferior) return; BeforeActivationStateChanged(); - if (mode == NotifyGrab) + if (mode == x11::NotifyMode::Grab) has_pointer_grab_ = enter; - else if (mode == NotifyUngrab) + else if (mode == x11::NotifyMode::Ungrab) has_pointer_grab_ = false; has_pointer_ = enter; @@ -994,13 +986,16 @@ void XWindow::OnCrossingEvent(bool enter, AfterActivationStateChanged(); } -void XWindow::OnFocusEvent(bool focus_in, int mode, int detail) { +void XWindow::OnFocusEvent(bool focus_in, + x11::NotifyMode mode, + x11::NotifyDetail detail) { // NotifyInferior on a focus event means the focus moved into or out of a // child window, but the focus is still within |xwindow_|. - if (detail == NotifyInferior) + if (detail == x11::NotifyDetail::Inferior) return; - bool notify_grab = mode == NotifyGrab || mode == NotifyUngrab; + bool notify_grab = + mode == x11::NotifyMode::Grab || mode == x11::NotifyMode::Ungrab; BeforeActivationStateChanged(); @@ -1010,13 +1005,13 @@ void XWindow::OnFocusEvent(bool focus_in, int mode, int detail) { // For |has_pointer_focus_| and |has_window_focus_|, we continue tracking // state during a grab, but ignore grab/ungrab events themselves. - if (!notify_grab && detail != NotifyPointer) + if (!notify_grab && detail != x11::NotifyDetail::Pointer) has_window_focus_ = focus_in; if (!notify_grab && has_pointer_) { switch (detail) { - case NotifyAncestor: - case NotifyVirtual: + case x11::NotifyDetail::Ancestor: + case x11::NotifyDetail::Virtual: // If we reach this point, we know |has_pointer_| was true before and // after this event. Since the definition of |has_pointer_focus_| is // (An ancestor window or the PointerRoot is focused) && |has_pointer_|, @@ -1033,7 +1028,7 @@ void XWindow::OnFocusEvent(bool focus_in, int mode, int detail) { // (FocusIn with NotifyVirtual) has_pointer_focus_ = !focus_in; break; - case NotifyPointer: + case x11::NotifyDetail::Pointer: // The remaining cases for |has_pointer_focus_| becoming true are: // 3. Focus moves from |xwindow_| to the PointerRoot // 4. Focus moves from a descendant of |xwindow_| to the PointerRoot @@ -1052,8 +1047,8 @@ void XWindow::OnFocusEvent(bool focus_in, int mode, int detail) { // In each case, we will get a FocusOut with a detail of NotifyPointer. has_pointer_focus_ = focus_in; break; - case NotifyNonlinear: - case NotifyNonlinearVirtual: + case x11::NotifyDetail::Nonlinear: + case x11::NotifyDetail::NonlinearVirtual: // We get Nonlinear(Virtual) events when // 1. Focus moves from Other to |xwindow_| // (FocusIn with NotifyNonlinear) @@ -1076,11 +1071,12 @@ void XWindow::OnFocusEvent(bool focus_in, int mode, int detail) { AfterActivationStateChanged(); } -bool XWindow::IsTargetedBy(const XEvent& xev) const { - ::Window target_window = - (xev.type == GenericEvent) +bool XWindow::IsTargetedBy(const x11::Event& x11_event) const { + const XEvent& xev = x11_event.xlib_event(); + auto target_window = static_cast<x11::Window>( + xev.type == x11::GeGenericEvent::opcode ? static_cast<XIDeviceEvent*>(xev.xcookie.data)->event - : xev.xany.window; + : xev.xany.window); return target_window == xwindow_; } @@ -1089,16 +1085,16 @@ void XWindow::WmMoveResize(int hittest, const gfx::Point& location) const { if (direction == -1) return; - DoWMMoveResize(xdisplay_, x_root_window_, xwindow_, location, direction); + DoWMMoveResize(connection_, x_root_window_, xwindow_, location, direction); } -// In Ozone, there are no ui::*Event constructors receiving XEvent* as input, -// in this case ui::PlatformEvent is expected. Furthermore, +// In Ozone, there are no *Event constructors receiving XEvent* as input, +// in this case PlatformEvent is expected. Furthermore, // X11EventSourceLibevent is used in that case, which already translates -// Mouse/Key/Touch/Scroll events into ui::Events so they should not be handled +// Mouse/Key/Touch/Scroll events into Events so they should not be handled // by PlatformWindow, which is supposed to use XWindow in Ozone builds. So // handling these events is disabled for Ozone. -void XWindow::ProcessEvent(XEvent* xev) { +void XWindow::ProcessEvent(x11::Event* xev) { // We can lose track of the window's position when the window is reparented. // When the parent window is moved, we won't get an event, so the window's // position relative to the root window will get out-of-sync. We can re-sync @@ -1106,8 +1102,8 @@ void XWindow::ProcessEvent(XEvent* xev) { // ButtonRelease, MotionNotify) which include the pointer location both // relative to this window and relative to the root window, so we can // calculate this window's position from that information. - gfx::Point window_point = ui::EventLocationFromXEvent(*xev); - gfx::Point root_point = ui::EventSystemLocationFromXEvent(*xev); + gfx::Point window_point = EventLocationFromXEvent(*xev); + gfx::Point root_point = EventSystemLocationFromXEvent(*xev); if (!window_point.IsOrigin() && !root_point.IsOrigin()) { gfx::Point window_origin = gfx::Point() + (root_point - window_point); if (bounds_in_pixels_.origin() != window_origin) { @@ -1118,135 +1114,115 @@ void XWindow::ProcessEvent(XEvent* xev) { // May want to factor CheckXEventForConsistency(xev); into a common location // since it is called here. - switch (xev->type) { - case EnterNotify: - case LeaveNotify: { - OnCrossingEvent(xev->type == EnterNotify, xev->xcrossing.focus, - xev->xcrossing.mode, xev->xcrossing.detail); - break; - } - case Expose: { - gfx::Rect damage_rect_in_pixels(xev->xexpose.x, xev->xexpose.y, - xev->xexpose.width, xev->xexpose.height); - OnXWindowDamageEvent(damage_rect_in_pixels); - break; - } - case x11::FocusIn: - case x11::FocusOut: - OnFocusEvent(xev->type == x11::FocusIn, xev->xfocus.mode, - xev->xfocus.detail); - break; - case ConfigureNotify: - OnConfigureEvent(xev); - break; - case GenericEvent: { - ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); - if (!factory->ShouldProcessXI2Event(xev)) - break; - - XIEnterEvent* enter_event = static_cast<XIEnterEvent*>(xev->xcookie.data); - switch (static_cast<XIEvent*>(xev->xcookie.data)->evtype) { - case XI_Enter: - case XI_Leave: { - OnCrossingEvent(enter_event->evtype == XI_Enter, enter_event->focus, - XI2ModeToXMode(enter_event->mode), - enter_event->detail); - return; - } - case XI_FocusIn: - case XI_FocusOut: { - OnFocusEvent(enter_event->evtype == XI_FocusIn, - XI2ModeToXMode(enter_event->mode), enter_event->detail); - return; - } - default: + if (auto* crossing = xev->As<x11::CrossingEvent>()) { + bool focus = crossing->same_screen_focus & CROSSING_FLAG_FOCUS; + OnCrossingEvent(crossing->opcode == x11::CrossingEvent::EnterNotify, focus, + crossing->mode, crossing->detail); + } else if (auto* expose = xev->As<x11::ExposeEvent>()) { + gfx::Rect damage_rect_in_pixels(expose->x, expose->y, expose->width, + expose->height); + OnXWindowDamageEvent(damage_rect_in_pixels); + } else if (auto* focus = xev->As<x11::FocusEvent>()) { + OnFocusEvent(focus->opcode == x11::FocusEvent::In, focus->mode, + focus->detail); + } else if (auto* configure = xev->As<x11::ConfigureNotifyEvent>()) { + OnConfigureEvent(*configure); + } else if (auto* crossing = xev->As<x11::Input::CrossingEvent>()) { + TouchFactory* factory = TouchFactory::GetInstance(); + if (factory->ShouldProcessXI2Event(&xev->xlib_event())) { + auto mode = XI2ModeToXMode(crossing->mode); + auto detail = XI2DetailToXDetail(crossing->detail); + switch (crossing->opcode) { + case x11::Input::CrossingEvent::Enter: + OnCrossingEvent(true, crossing->focus, mode, detail); break; - } - break; - } - case MapNotify: { - OnWindowMapped(); - break; - } - case UnmapNotify: { - window_mapped_in_server_ = false; - has_pointer_ = false; - has_pointer_grab_ = false; - has_pointer_focus_ = false; - has_window_focus_ = false; - break; - } - case ClientMessage: { - Atom message_type = xev->xclient.message_type; - if (message_type == gfx::GetAtom("WM_PROTOCOLS")) { - Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]); - if (protocol == gfx::GetAtom("WM_DELETE_WINDOW")) { - // We have received a close message from the window manager. - OnXWindowCloseRequested(); - } else if (protocol == gfx::GetAtom("_NET_WM_PING")) { - XEvent reply_event = *xev; - reply_event.xclient.window = x_root_window_; - - XSendEvent(xdisplay_, reply_event.xclient.window, x11::False, - SubstructureRedirectMask | SubstructureNotifyMask, - &reply_event); - } else if (protocol == gfx::GetAtom("_NET_WM_SYNC_REQUEST")) { - pending_counter_value_ = - xev->xclient.data.l[2] + - (static_cast<int64_t>(xev->xclient.data.l[3]) << 32); - pending_counter_value_is_extended_ = xev->xclient.data.l[4] != 0; - } - } else { - OnXWindowDragDropEvent(xev); - } - break; - } - case MappingNotify: { - switch (xev->xmapping.request) { - case MappingModifier: - case MappingKeyboard: - XRefreshKeyboardMapping(&xev->xmapping); + case x11::Input::CrossingEvent::Leave: + OnCrossingEvent(false, crossing->focus, mode, detail); break; - case MappingPointer: - ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap(); + case x11::Input::CrossingEvent::FocusIn: + OnFocusEvent(true, mode, detail); break; - default: - NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request; + case x11::Input::CrossingEvent::FocusOut: + OnFocusEvent(false, mode, detail); break; } - break; } - case PropertyNotify: { - XAtom changed_atom = xev->xproperty.atom; - if (changed_atom == gfx::GetAtom("_NET_WM_STATE")) { - OnWMStateUpdated(); - } else if (changed_atom == gfx::GetAtom("_NET_FRAME_EXTENTS")) { - OnFrameExtentsUpdated(); - } else if (changed_atom == gfx::GetAtom("_NET_WM_DESKTOP")) { - OnWorkspaceUpdated(); + } else if (xev->As<x11::MapNotifyEvent>()) { + OnWindowMapped(); + } else if (xev->As<x11::UnmapNotifyEvent>()) { + window_mapped_in_server_ = false; + has_pointer_ = false; + has_pointer_grab_ = false; + has_pointer_focus_ = false; + has_window_focus_ = false; + } else if (auto* client = xev->As<x11::ClientMessageEvent>()) { + x11::Atom message_type = client->type; + if (message_type == gfx::GetAtom("WM_PROTOCOLS")) { + x11::Atom protocol = static_cast<x11::Atom>(client->data.data32[0]); + if (protocol == gfx::GetAtom("WM_DELETE_WINDOW")) { + // We have received a close message from the window manager. + OnXWindowCloseRequested(); + } else if (protocol == gfx::GetAtom("_NET_WM_PING")) { + x11::ClientMessageEvent reply_event = *client; + reply_event.window = x_root_window_; + + auto event_bytes = x11::Write(reply_event); + DCHECK_EQ(event_bytes.size(), 32ul); + + x11::SendEventRequest request{false, x_root_window_, + x11::EventMask::SubstructureNotify | + x11::EventMask::SubstructureRedirect}; + std::copy(event_bytes.begin(), event_bytes.end(), + request.event.begin()); + connection_->SendEvent(request); + } else if (protocol == gfx::GetAtom("_NET_WM_SYNC_REQUEST")) { + pending_counter_value_ = + client->data.data32[2] + + (static_cast<int64_t>(client->data.data32[3]) << 32); + pending_counter_value_is_extended_ = client->data.data32[4] != 0; } - break; + } else { + OnXWindowDragDropEvent(xev); } - case SelectionNotify: { - OnXWindowSelectionEvent(xev); - break; + } else if (auto* mapping = xev->As<x11::MappingNotifyEvent>()) { + switch (mapping->request) { + case x11::Mapping::Modifier: + case x11::Mapping::Keyboard: + XRefreshKeyboardMapping(&xev->xlib_event().xmapping); + break; + case x11::Mapping::Pointer: + DeviceDataManagerX11::GetInstance()->UpdateButtonMap(); + break; + default: + NOTIMPLEMENTED() << " Unknown request: " + << static_cast<int>(mapping->request); + break; + } + } else if (auto* property = xev->As<x11::PropertyNotifyEvent>()) { + x11::Atom changed_atom = property->atom; + if (changed_atom == gfx::GetAtom("_NET_WM_STATE")) { + OnWMStateUpdated(); + } else if (changed_atom == gfx::GetAtom("_NET_FRAME_EXTENTS")) { + OnFrameExtentsUpdated(); + } else if (changed_atom == gfx::GetAtom("_NET_WM_DESKTOP")) { + OnWorkspaceUpdated(); } + } else if (auto* selection = xev->As<x11::SelectionNotifyEvent>()) { + OnXWindowSelectionEvent(xev); } } -void XWindow::UpdateWMUserTime(ui::Event* event) { +void XWindow::UpdateWMUserTime(Event* event) { if (!IsActive()) return; DCHECK(event); - ui::EventType type = event->type(); - if (type == ui::ET_MOUSE_PRESSED || type == ui::ET_KEY_PRESSED || - type == ui::ET_TOUCH_PRESSED) { - unsigned long wm_user_time_ms = + EventType type = event->type(); + if (type == ET_MOUSE_PRESSED || type == ET_KEY_PRESSED || + type == ET_TOUCH_PRESSED) { + uint32_t wm_user_time_ms = (event->time_stamp() - base::TimeTicks()).InMilliseconds(); - XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"), - XA_CARDINAL, 32, PropModeReplace, - reinterpret_cast<const unsigned char*>(&wm_user_time_ms), - 1); + SetProperty(xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"), + x11::Atom::CARDINAL, wm_user_time_ms); } } @@ -1260,31 +1236,33 @@ void XWindow::OnWindowMapped() { } } -void XWindow::OnConfigureEvent(XEvent* xev) { - DCHECK_EQ(xwindow_, xev->xconfigure.window); - DCHECK_EQ(xwindow_, xev->xconfigure.event); +void XWindow::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure) { + DCHECK_EQ(xwindow_, configure.window); + DCHECK_EQ(xwindow_, configure.event); if (pending_counter_value_) { DCHECK(!configure_counter_value_); configure_counter_value_ = pending_counter_value_; configure_counter_value_is_extended_ = pending_counter_value_is_extended_; - pending_counter_value_is_extended_ = 0; + pending_counter_value_is_extended_ = false; pending_counter_value_ = 0; } // It's possible that the X window may be resized by some other means than // from within aura (e.g. the X window manager can change the size). Make // sure the root window size is maintained properly. - int translated_x_in_pixels = xev->xconfigure.x; - int translated_y_in_pixels = xev->xconfigure.y; - if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) { - Window unused; - XTranslateCoordinates(xdisplay_, xwindow_, x_root_window_, 0, 0, - &translated_x_in_pixels, &translated_y_in_pixels, - &unused); + int translated_x_in_pixels = configure.x; + int translated_y_in_pixels = configure.y; + if (!configure.send_event && !configure.override_redirect) { + auto future = + connection_->TranslateCoordinates({xwindow_, x_root_window_, 0, 0}); + if (auto coords = future.Sync()) { + translated_x_in_pixels = coords->dst_x; + translated_y_in_pixels = coords->dst_y; + } } gfx::Rect bounds_in_pixels(translated_x_in_pixels, translated_y_in_pixels, - xev->xconfigure.width, xev->xconfigure.height); + configure.width, configure.height); bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size(); bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin(); previous_bounds_in_pixels_ = bounds_in_pixels_; @@ -1296,13 +1274,13 @@ void XWindow::OnConfigureEvent(XEvent* xev) { NotifyBoundsChanged(bounds_in_pixels_); } -void XWindow::SetWMSpecState(bool enabled, XAtom state1, XAtom state2) { +void XWindow::SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2) { if (window_mapped_in_client_) { ui::SetWMSpecState(xwindow_, enabled, state1, state2); } else { // The updated state will be set when the window is (re)mapped. - base::flat_set<XAtom> new_window_properties = window_properties_; - for (XAtom atom : {state1, state2}) { + base::flat_set<x11::Atom> new_window_properties = window_properties_; + for (x11::Atom atom : {state1, state2}) { if (enabled) new_window_properties.insert(atom); else @@ -1318,16 +1296,16 @@ void XWindow::OnWMStateUpdated() { // persist across a Hide() and Show(). So if the window is currently // unmapped, leave the state unchanged so it will be restored when the window // is remapped. - std::vector<XAtom> atom_list; - if (ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list) || + std::vector<x11::Atom> atom_list; + if (GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list) || window_mapped_in_client_) { UpdateWindowProperties( - base::flat_set<XAtom>(std::begin(atom_list), std::end(atom_list))); + base::flat_set<x11::Atom>(std::begin(atom_list), std::end(atom_list))); } } void XWindow::UpdateWindowProperties( - const base::flat_set<XAtom>& new_window_properties) { + const base::flat_set<x11::Atom>& new_window_properties) { was_minimized_ = IsMinimized(); window_properties_ = new_window_properties; @@ -1337,15 +1315,15 @@ void XWindow::UpdateWindowProperties( // handle window manager initiated fullscreen. In particular, Chrome needs to // do preprocessing before the x window's fullscreen state is toggled. - is_always_on_top_ = ui::HasWMSpecProperty( - window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE")); + is_always_on_top_ = HasWMSpecProperty(window_properties_, + gfx::GetAtom("_NET_WM_STATE_ABOVE")); OnXWindowStateChanged(); ResetWindowRegion(); } void XWindow::OnFrameExtentsUpdated() { std::vector<int> insets; - if (ui::GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) && + if (GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) && insets.size() == 4) { // |insets| are returned in the order: [left, right, top, bottom]. native_window_frame_borders_in_pixels_ = @@ -1363,14 +1341,14 @@ void XWindow::NotifySwapAfterResize() { // Setting an even number to |extended_update_counter_| will trigger a // new resize. current_counter_value_ += 3; - SyncSetCounter(xdisplay_, extended_update_counter_, + SyncSetCounter(connection_, extended_update_counter_, current_counter_value_); } return; } if (configure_counter_value_ != 0) { - SyncSetCounter(xdisplay_, update_counter_, configure_counter_value_); + SyncSetCounter(connection_, update_counter_, configure_counter_value_); configure_counter_value_ = 0; } } @@ -1378,7 +1356,8 @@ void XWindow::NotifySwapAfterResize() { // Removes |delayed_resize_task_| from the task queue (if it's in // the queue) and adds it back at the end of the queue. void XWindow::DispatchResize() { - if (update_counter_ == x11::None || configure_counter_value_ == 0) { + if (update_counter_ == x11::Sync::Counter{} || + configure_counter_value_ == 0) { // WM doesn't support _NET_WM_SYNC_REQUEST. // Or we are too slow, so _NET_WM_SYNC_REQUEST is disabled by the // compositor. @@ -1410,7 +1389,7 @@ void XWindow::DelayedResize(const gfx::Rect& bounds_in_pixels) { // are not frozen and re-enable _NET_WM_SYNC_REQUEST, if it was disabled. // Increase the |extended_update_counter_| to an odd number will not trigger // a new resize. - SyncSetCounter(xdisplay_, extended_update_counter_, + SyncSetCounter(connection_, extended_update_counter_, ++current_counter_value_); } @@ -1434,41 +1413,51 @@ void XWindow::ConfineCursorTo(const gfx::Rect& bounds) { gfx::Rect barrier = bounds + bounds_in_pixels_.OffsetFromOrigin(); + auto make_barrier = [&](uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, + x11::XFixes::BarrierDirections directions) { + x11::XFixes::Barrier barrier = + connection_->GenerateId<x11::XFixes::Barrier>(); + connection_->xfixes().CreatePointerBarrier( + {barrier, x_root_window_, x1, y1, x2, y2, directions}); + return barrier; + }; + // Top horizontal barrier. - pointer_barriers_[0] = XFixesCreatePointerBarrier( - xdisplay_, x_root_window_, barrier.x(), barrier.y(), barrier.right(), - barrier.y(), BarrierPositiveY, 0, XIAllDevices); + pointer_barriers_[0] = + make_barrier(barrier.x(), barrier.y(), barrier.right(), barrier.y(), + x11::XFixes::BarrierDirections::PositiveY); // Bottom horizontal barrier. - pointer_barriers_[1] = XFixesCreatePointerBarrier( - xdisplay_, x_root_window_, barrier.x(), barrier.bottom(), barrier.right(), - barrier.bottom(), BarrierNegativeY, 0, XIAllDevices); + pointer_barriers_[1] = + make_barrier(barrier.x(), barrier.bottom(), barrier.right(), + barrier.bottom(), x11::XFixes::BarrierDirections::NegativeY); // Left vertical barrier. - pointer_barriers_[2] = XFixesCreatePointerBarrier( - xdisplay_, x_root_window_, barrier.x(), barrier.y(), barrier.x(), - barrier.bottom(), BarrierPositiveX, 0, XIAllDevices); + pointer_barriers_[2] = + make_barrier(barrier.x(), barrier.y(), barrier.x(), barrier.bottom(), + x11::XFixes::BarrierDirections::PositiveX); // Right vertical barrier. - pointer_barriers_[3] = XFixesCreatePointerBarrier( - xdisplay_, x_root_window_, barrier.right(), barrier.y(), barrier.right(), - barrier.bottom(), BarrierNegativeX, 0, XIAllDevices); + pointer_barriers_[3] = + make_barrier(barrier.right(), barrier.y(), barrier.right(), + barrier.bottom(), x11::XFixes::BarrierDirections::NegativeX); has_pointer_barriers_ = true; } void XWindow::LowerWindow() { - XLowerWindow(xdisplay_, xwindow_); + ui::LowerWindow(xwindow_); } void XWindow::SetOverrideRedirect(bool override_redirect) { bool remap = window_mapped_in_client_; if (remap) Hide(); - XSetWindowAttributes swa; - swa.override_redirect = override_redirect; - XChangeWindowAttributes(xdisplay_, xwindow_, CWOverrideRedirect, &swa); + connection_->ChangeWindowAttributes({ + .window = xwindow_, + .override_redirect = x11::Bool32(override_redirect), + }); if (remap) { Map(); if (has_pointer_grab_) - ui::ChangeActivePointerGrabCursor(x11::None); + ChangeActivePointerGrabCursor(x11::None); } } @@ -1476,12 +1465,16 @@ bool XWindow::ContainsPointInRegion(const gfx::Point& point) const { if (!shape()) return true; - return XPointInRegion(shape(), point.x(), point.y()) == x11::True; + for (const auto& rect : *shape()) { + if (gfx::Rect(rect.x, rect.y, rect.width, rect.height).Contains(point)) + return true; + } + return false; } void XWindow::SetXWindowShape(std::unique_ptr<NativeShapeRects> native_shape, const gfx::Transform& transform) { - XRegion* xregion = nullptr; + std::unique_ptr<std::vector<x11::Rectangle>> xregion; if (native_shape) { SkRegion native_region; for (const gfx::Rect& rect : *native_shape) @@ -1493,7 +1486,7 @@ void XWindow::SetXWindowShape(std::unique_ptr<NativeShapeRects> native_shape, path_in_dip.transform(SkMatrix(transform.matrix()), &path_in_pixels); xregion = gfx::CreateRegionFromSkPath(path_in_pixels); } else { - xregion = XCreateRegion(); + xregion = std::make_unique<std::vector<x11::Rectangle>>(); } } else { xregion = gfx::CreateRegionFromSkRegion(native_region); @@ -1501,7 +1494,7 @@ void XWindow::SetXWindowShape(std::unique_ptr<NativeShapeRects> native_shape, } custom_window_shape_ = !!xregion; - window_shape_.reset(xregion); + window_shape_ = std::move(xregion); ResetWindowRegion(); } @@ -1509,25 +1502,35 @@ void XWindow::UnconfineCursor() { if (!has_pointer_barriers_) return; - for (XID pointer_barrier : pointer_barriers_) - XFixesDestroyPointerBarrier(xdisplay_, pointer_barrier); - pointer_barriers_.fill(x11::None); + for (auto pointer_barrier : pointer_barriers_) + connection_->xfixes().DeletePointerBarrier({pointer_barrier}); + + pointer_barriers_.fill({}); has_pointer_barriers_ = false; } -void XWindow::UpdateWindowRegion(XRegion* xregion) { +void XWindow::UpdateWindowRegion( + std::unique_ptr<std::vector<x11::Rectangle>> region) { + auto set_shape = [&](const std::vector<x11::Rectangle>& rectangles) { + connection_->shape().Rectangles({ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Bounding, + .ordering = x11::ClipOrdering::YXBanded, + .destination_window = xwindow_, + .rectangles = rectangles, + }); + }; + // If a custom window shape was supplied then apply it. if (use_custom_shape()) { - XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0, - window_shape_.get(), false); + set_shape(*window_shape_); return; } - window_shape_.reset(xregion); + window_shape_ = std::move(region); if (window_shape_) { - XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0, - window_shape_.get(), false); + set_shape(*window_shape_); return; } @@ -1538,19 +1541,21 @@ void XWindow::UpdateWindowRegion(XRegion* xregion) { // If the window has system borders, the mask must be set to null (not a // rectangle), because several window managers (eg, KDE, XFCE, XMonad) will // not put borders on a window with a custom shape. - XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, x11::None, - ShapeSet); + connection_->shape().Mask({ + .operation = x11::Shape::So::Set, + .destination_kind = x11::Shape::Sk::Bounding, + .destination_window = xwindow_, + .source_bitmap = x11::Pixmap::None, + }); } else { // Conversely, if the window does not have system borders, the mask must be // manually set to a rectangle that covers the whole window (not null). This // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null // shape causes the hint to disable system borders to be ignored (resulting // in a double border). - XRectangle r = {0, 0, - static_cast<unsigned short>(bounds_in_pixels_.width()), - static_cast<unsigned short>(bounds_in_pixels_.height())}; - XShapeCombineRectangles(xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, - ShapeSet, YXBanded); + x11::Rectangle r{0, 0, bounds_in_pixels_.width(), + bounds_in_pixels_.height()}; + set_shape({r}); } } @@ -1560,42 +1565,32 @@ void XWindow::NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px) { } bool XWindow::InitializeAsStatusIcon() { - std::string atom_name = - "_NET_SYSTEM_TRAY_S" + base::NumberToString(DefaultScreen(xdisplay_)); - XID manager = XGetSelectionOwner(xdisplay_, gfx::GetAtom(atom_name.c_str())); - if (manager == x11::None) + std::string atom_name = "_NET_SYSTEM_TRAY_S" + + base::NumberToString(connection_->DefaultScreenId()); + auto reply = connection_->GetSelectionOwner({gfx::GetAtom(atom_name)}).Sync(); + if (!reply || reply->owner == x11::Window::None) return false; + auto manager = reply->owner; - ui::SetIntArrayProperty(xwindow_, "_XEMBED_INFO", "CARDINAL", - {kXembedInfoProtocolVersion, kXembedInfoFlags}); + SetIntArrayProperty(xwindow_, "_XEMBED_INFO", "CARDINAL", + {kXembedInfoProtocolVersion, kXembedInfoFlags}); - XSetWindowAttributes attrs; - unsigned long flags = 0; + x11::ChangeWindowAttributesRequest req{xwindow_}; if (has_alpha()) { - flags |= CWBackPixel; - attrs.background_pixel = 0; + req.background_pixel = 0; } else { - ui::SetIntProperty(xwindow_, "CHROMIUM_COMPOSITE_WINDOW", "CARDINAL", 1); - flags |= CWBackPixmap; - attrs.background_pixmap = ParentRelative; - } - XChangeWindowAttributes(xdisplay_, xwindow_, flags, &attrs); - XEvent ev; - memset(&ev, 0, sizeof(ev)); - ev.xclient.type = ClientMessage; - ev.xclient.window = manager; - ev.xclient.message_type = gfx::GetAtom("_NET_SYSTEM_TRAY_OPCODE"); - ev.xclient.format = 32; - ev.xclient.data.l[0] = ui::X11EventSource::GetInstance()->GetTimestamp(); - ev.xclient.data.l[1] = kSystemTrayRequestDock; - ev.xclient.data.l[2] = xwindow_; - bool error; - { - gfx::X11ErrorTracker error_tracker; - XSendEvent(xdisplay_, manager, false, NoEventMask, &ev); - error = error_tracker.FoundNewError(); + SetIntProperty(xwindow_, "CHROMIUM_COMPOSITE_WINDOW", "CARDINAL", 1); + req.background_pixmap = + static_cast<x11::Pixmap>(x11::BackPixmap::ParentRelative); } - return !error; + connection_->ChangeWindowAttributes(req); + + auto future = SendClientMessage( + manager, manager, gfx::GetAtom("_NET_SYSTEM_TRAY_OPCODE"), + {X11EventSource::GetInstance()->GetTimestamp(), kSystemTrayRequestDock, + static_cast<uint32_t>(xwindow_), 0, 0}, + x11::EventMask::NoEvent); + return !future.Sync().error; } } // namespace ui diff --git a/chromium/ui/base/x/x11_window.h b/chromium/ui/base/x/x11_window.h index feec9b62e6d..c5b0d7227a5 100644 --- a/chromium/ui/base/x/x11_window.h +++ b/chromium/ui/base/x/x11_window.h @@ -8,6 +8,7 @@ #include <array> #include <memory> #include <string> +#include <vector> #include "base/cancelable_callback.h" #include "base/component_export.h" @@ -19,8 +20,12 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/x/event.h" +#include "ui/gfx/x/sync.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/x11_types.h" +#include "ui/gfx/x/xfixes.h" +#include "ui/gfx/x/xproto.h" class SkPath; @@ -107,11 +112,11 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { bool IsActive() const; void GrabPointer(); void ReleasePointerGrab(); - void StackXWindowAbove(::Window window); + void StackXWindowAbove(x11::Window window); void StackXWindowAtTop(); - bool IsTargetedBy(const XEvent& xev) const; + bool IsTargetedBy(const x11::Event& xev) const; void WmMoveResize(int hittest, const gfx::Point& location) const; - void ProcessEvent(XEvent* xev); + void ProcessEvent(x11::Event* xev); void SetSize(const gfx::Size& size_in_pixels); void SetBounds(const gfx::Rect& requested_bounds); @@ -119,7 +124,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { bool IsMinimized() const; bool IsMaximized() const; bool IsFullscreen() const; - gfx::Rect GetOutterBounds() const; + gfx::Rect GetOuterBounds() const; void SetCursor(::Cursor cursor); bool SetTitle(base::string16 title); @@ -163,12 +168,14 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { bool has_alpha() const { return visual_has_alpha_; } base::Optional<int> workspace() const { return workspace_; } - XDisplay* display() const { return xdisplay_; } - ::Window window() const { return xwindow_; } - ::Window root_window() const { return x_root_window_; } - ::Region shape() const { return window_shape_.get(); } - XID update_counter() const { return update_counter_; } - XID extended_update_counter() const { return extended_update_counter_; } + x11::Connection* connection() const { return connection_; } + x11::Window window() const { return xwindow_; } + x11::Window root_window() const { return x_root_window_; } + std::vector<x11::Rectangle>* shape() const { return window_shape_.get(); } + x11::Sync::Counter update_counter() const { return update_counter_; } + x11::Sync::Counter extended_update_counter() const { + return extended_update_counter_; + } ::Cursor last_cursor() const { return last_cursor_; } protected: @@ -178,14 +185,16 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { private: // Called on an XFocusInEvent, XFocusOutEvent, XIFocusInEvent, or an // XIFocusOutEvent. - void OnFocusEvent(bool focus_in, int mode, int detail); + void OnFocusEvent(bool focus_in, + x11::NotifyMode mode, + x11::NotifyDetail detail); // Called on an XEnterWindowEvent, XLeaveWindowEvent, XIEnterEvent, or an // XILeaveEvent. void OnCrossingEvent(bool enter, bool focus_in_window_or_ancestor, - int mode, - int detail); + x11::NotifyMode mode, + x11::NotifyDetail detail); // Called when |xwindow_|'s _NET_WM_STATE property is updated. void OnWMStateUpdated(); @@ -193,7 +202,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated. void OnFrameExtentsUpdated(); - void OnConfigureEvent(XEvent* xev); + void OnConfigureEvent(const x11::ConfigureNotifyEvent& event); void OnWorkspaceUpdated(); @@ -215,15 +224,15 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // be invalid to unset the maximized state by making two calls like // (_NET_WM_STATE_MAXIMIZED_VERT, x11::None), (_NET_WM_STATE_MAXIMIZED_HORZ, // x11::None). - void SetWMSpecState(bool enabled, XAtom state1, XAtom state2); + void SetWMSpecState(bool enabled, x11::Atom state1, x11::Atom state2); // Updates |window_properties_| with |new_window_properties|. void UpdateWindowProperties( - const base::flat_set<XAtom>& new_window_properties); + const base::flat_set<x11::Atom>& new_window_properties); void UnconfineCursor(); - void UpdateWindowRegion(XRegion* xregion); + void UpdateWindowRegion(std::unique_ptr<std::vector<x11::Rectangle>> region); void NotifyBoundsChanged(const gfx::Rect& new_bounds_in_px); @@ -241,23 +250,23 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { virtual void OnXWindowWorkspaceChanged() = 0; virtual void OnXWindowLostPointerGrab() = 0; virtual void OnXWindowLostCapture() = 0; - virtual void OnXWindowSelectionEvent(XEvent* xev) = 0; - virtual void OnXWindowDragDropEvent(XEvent* xev) = 0; + virtual void OnXWindowSelectionEvent(x11::Event* xev) = 0; + virtual void OnXWindowDragDropEvent(x11::Event* xev) = 0; virtual base::Optional<gfx::Size> GetMinimumSizeForXWindow() = 0; virtual base::Optional<gfx::Size> GetMaximumSizeForXWindow() = 0; virtual void GetWindowMaskForXWindow(const gfx::Size& size, SkPath* window_mask) = 0; // The display and the native X window hosting the root window. - XDisplay* xdisplay_ = nullptr; - ::Window xwindow_ = x11::None; - ::Window x_root_window_ = x11::None; + x11::Connection* const connection_; + x11::Window xwindow_ = x11::Window::None; + x11::Window x_root_window_ = x11::Window::None; // Events selected on |xwindow_|. std::unique_ptr<ui::XScopedEventSelector> xwindow_events_; // The window manager state bits. - base::flat_set<XAtom> window_properties_; + base::flat_set<x11::Atom> window_properties_; // Is this window able to receive focus? bool activatable_ = true; @@ -276,7 +285,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // The bounds of |xwindow_|. gfx::Rect bounds_in_pixels_; - VisualID visual_id_ = 0; + x11::VisualId visual_id_{}; // Whether we used an ARGB visual for our window. bool visual_has_alpha_ = false; @@ -325,8 +334,8 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // Used for synchronizing between |xwindow_| and desktop compositor during // resizing. - XID update_counter_ = x11::None; - XID extended_update_counter_ = x11::None; + x11::Sync::Counter update_counter_{}; + x11::Sync::Counter extended_update_counter_{}; // Whenever the bounds are set, we keep the previous set of bounds around so // we can have a better chance of getting the real @@ -353,8 +362,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { gfx::Size max_size_in_pixels_; // The window shape if the window is non-rectangular. - gfx::XScopedPtr<XRegion, gfx::XObjectDeleter<XRegion, int, XDestroyRegion>> - window_shape_; + std::unique_ptr<std::vector<x11::Rectangle>> window_shape_; // Whether |window_shape_| was set via SetShape(). bool custom_window_shape_ = false; @@ -377,7 +385,7 @@ class COMPONENT_EXPORT(UI_BASE_X) XWindow { // Keep track of barriers to confine cursor. bool has_pointer_barriers_ = false; - std::array<XID, 4> pointer_barriers_; + std::array<x11::XFixes::Barrier, 4> pointer_barriers_; ::Cursor last_cursor_ = x11::None; }; diff --git a/chromium/ui/base/x/x11_workspace_handler.cc b/chromium/ui/base/x/x11_workspace_handler.cc index 72ea0fb82d5..cb48d38fc4a 100644 --- a/chromium/ui/base/x/x11_workspace_handler.cc +++ b/chromium/ui/base/x/x11_workspace_handler.cc @@ -15,11 +15,10 @@ namespace ui { namespace { -x11::Future<x11::XProto::GetPropertyReply> GetWorkspace() { +x11::Future<x11::GetPropertyReply> GetWorkspace() { auto* connection = x11::Connection::Get(); return connection->GetProperty({ - .window = - static_cast<x11::Window>(XDefaultRootWindow(connection->display())), + .window = connection->default_screen().root, .property = static_cast<x11::Atom>(gfx::GetAtom("_NET_CURRENT_DESKTOP")), .type = static_cast<x11::Atom>(gfx::GetAtom("CARDINAL")), .long_length = 1, @@ -30,7 +29,7 @@ x11::Future<x11::XProto::GetPropertyReply> GetWorkspace() { X11WorkspaceHandler::X11WorkspaceHandler(Delegate* delegate) : xdisplay_(gfx::GetXDisplay()), - x_root_window_(DefaultRootWindow(xdisplay_)), + x_root_window_(ui::GetX11RootWindow()), delegate_(delegate) { DCHECK(delegate_); if (ui::X11EventSource::HasInstance()) @@ -51,14 +50,16 @@ std::string X11WorkspaceHandler::GetCurrentWorkspace() { return workspace_; } -bool X11WorkspaceHandler::DispatchXEvent(XEvent* event) { +bool X11WorkspaceHandler::DispatchXEvent(x11::Event* x11_event) { + XEvent* event = &x11_event->xlib_event(); if (event->type != PropertyNotify || - event->xproperty.window != x_root_window_) { + event->xproperty.window != static_cast<uint32_t>(x_root_window_)) { return false; } switch (event->type) { - case PropertyNotify: { - if (event->xproperty.atom == gfx::GetAtom("_NET_CURRENT_DESKTOP")) { + case x11::PropertyNotifyEvent::opcode: { + if (event->xproperty.atom == + static_cast<uint32_t>(gfx::GetAtom("_NET_CURRENT_DESKTOP"))) { GetWorkspace().OnResponse( base::BindOnce(&X11WorkspaceHandler::OnWorkspaceResponse, weak_factory_.GetWeakPtr())); @@ -72,7 +73,7 @@ bool X11WorkspaceHandler::DispatchXEvent(XEvent* event) { } void X11WorkspaceHandler::OnWorkspaceResponse( - x11::XProto::GetPropertyResponse response) { + x11::GetPropertyResponse response) { if (!response || response->format != 32 || response->value.size() < 4) return; DCHECK_EQ(response->bytes_after, 0U); diff --git a/chromium/ui/base/x/x11_workspace_handler.h b/chromium/ui/base/x/x11_workspace_handler.h index b60f91a9f56..2a9c1ab4ea6 100644 --- a/chromium/ui/base/x/x11_workspace_handler.h +++ b/chromium/ui/base/x/x11_workspace_handler.h @@ -10,6 +10,7 @@ #include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "ui/events/platform/x11/x11_event_source.h" +#include "ui/gfx/x/event.h" #include "ui/gfx/x/x11.h" #include "ui/gfx/x/xproto.h" @@ -40,15 +41,15 @@ class COMPONENT_EXPORT(UI_BASE_X) X11WorkspaceHandler private: // ui::XEventDispatcher - bool DispatchXEvent(XEvent* event) override; + bool DispatchXEvent(x11::Event* event) override; - void OnWorkspaceResponse(x11::XProto::GetPropertyResponse response); + void OnWorkspaceResponse(x11::GetPropertyResponse response); // The display and the native X window hosting the root window. XDisplay* xdisplay_; // The native root window. - ::Window x_root_window_; + x11::Window x_root_window_; // Events selected on x_root_window_. std::unique_ptr<ui::XScopedEventSelector> x_root_window_events_; diff --git a/chromium/ui/base/x/xwmstartupcheck/BUILD.gn b/chromium/ui/base/x/xwmstartupcheck/BUILD.gn new file mode 100644 index 00000000000..debd8fac289 --- /dev/null +++ b/chromium/ui/base/x/xwmstartupcheck/BUILD.gn @@ -0,0 +1,13 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +executable("xwmstartupcheck") { + testonly = true + + sources = [ "xwmstartupcheck.cc" ] + + deps = [ "//base" ] + + configs += [ "//build/config/linux:x11" ] +} diff --git a/chromium/ui/base/x/xwmstartupcheck/xwmstartupcheck.cc b/chromium/ui/base/x/xwmstartupcheck/xwmstartupcheck.cc new file mode 100644 index 00000000000..09ef42f3e12 --- /dev/null +++ b/chromium/ui/base/x/xwmstartupcheck/xwmstartupcheck.cc @@ -0,0 +1,125 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Checks for the reparent notify events that is a signal that a WM has been +// started. Returns 0 on success and 1 on failure. This program must be started +// BEFORE the Wm starts. +// + +#include <cerrno> +#include <cstdio> + +#include <time.h> + +#include <X11/Xlib.h> + +void CalculateTimeout(const timespec& now, + const timespec& deadline, + timeval* timeout) { + // 1s == 1e+6 us. + // 1nsec == 1e-3 us + timeout->tv_usec = (deadline.tv_sec - now.tv_sec) * 1000000 + + (deadline.tv_nsec - now.tv_nsec) / 1000; + timeout->tv_sec = 0; +} + +class XScopedDisplay { + public: + explicit XScopedDisplay(Display* display) : display_(display) {} + ~XScopedDisplay() { + if (display_) + XCloseDisplay(display_); + } + + Display* display() const { return display_; } + + private: + Display* const display_; +}; + +int main(int argc, char* argv[]) { + // Connects to a display specified in the current process' env value DISPLAY. + XScopedDisplay scoped_display(XOpenDisplay(nullptr)); + + // No display found - fail early. + if (!scoped_display.display()) { + fprintf(stderr, "Couldn't connect to a display.\n"); + return 1; + } + + auto* xdisplay = scoped_display.display(); + + auto root_window = DefaultRootWindow(xdisplay); + if (!root_window) { + fprintf(stderr, "Couldn't find root window.\n"); + return 1; + } + + auto dummmy_window = XCreateSimpleWindow( + xdisplay, root_window, 0 /*x*/, 0 /*y*/, 1 /*width*/, 1 /*height*/, + 0 /*border width*/, 0 /*border*/, 0 /*background*/); + if (!dummmy_window) { + fprintf(stderr, "Couldn't create a dummy window."); + return 1; + } + + XMapWindow(xdisplay, dummmy_window); + // We are only interested in the ReparentNotify events that are sent whenever + // our dummy window is reparented because of a wm start. + XSelectInput(xdisplay, dummmy_window, StructureNotifyMask); + XFlush(xdisplay); + + int display_fd = ConnectionNumber(xdisplay); + + // Set deadline as 30s. + struct timespec now, deadline; + clock_gettime(CLOCK_REALTIME, &now); + deadline = now; + deadline.tv_sec += 30; + + // Calculate first timeout. + struct timeval tv; + CalculateTimeout(now, deadline, &tv); + + XEvent ev; + do { + fd_set in_fds; + FD_ZERO(&in_fds); + FD_SET(display_fd, &in_fds); + + int ret = select(display_fd + 1, &in_fds, nullptr, nullptr, &tv); + if (ret == -1) { + if (errno != EINTR) { + perror("Error occured while polling the display fd"); + break; + } + } else if (ret > 0) { + while (XPending(xdisplay)) { + XNextEvent(xdisplay, &ev); + // If we got ReparentNotify, a wm has started up and we can stop + // execution. + if (ev.type == ReparentNotify) { + return 0; + } + } + } + // Calculate next timeout. If it's less or equal to 0, give up. + clock_gettime(CLOCK_REALTIME, &now); + CalculateTimeout(now, deadline, &tv); + } while (tv.tv_usec >= 0); + + return 1; +} + +#if defined(LEAK_SANITIZER) +// XOpenDisplay leaks memory if it takes more than one try to connect. This +// causes LSan bots to fail. We don't care about memory leaks in xdisplaycheck +// anyway, so just disable LSan completely. +// This function isn't referenced from the executable itself. Make sure it isn't +// stripped by the linker. +__attribute__((used)) __attribute__((visibility("default"))) extern "C" int +__lsan_is_turned_off() { + return 1; +} +#endif |