summaryrefslogtreecommitdiff
path: root/chromium/ui/base/x
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/base/x')
-rw-r--r--chromium/ui/base/x/BUILD.gn25
-rw-r--r--chromium/ui/base/x/selection_owner.cc233
-rw-r--r--chromium/ui/base/x/selection_owner.h42
-rw-r--r--chromium/ui/base/x/selection_requestor.cc172
-rw-r--r--chromium/ui/base/x/selection_requestor.h52
-rw-r--r--chromium/ui/base/x/selection_requestor_unittest.cc86
-rw-r--r--chromium/ui/base/x/selection_utils.cc53
-rw-r--r--chromium/ui/base/x/selection_utils.h32
-rw-r--r--chromium/ui/base/x/x11_cursor.cc48
-rw-r--r--chromium/ui/base/x/x11_cursor.h55
-rw-r--r--chromium/ui/base/x/x11_cursor_factory.cc118
-rw-r--r--chromium/ui/base/x/x11_cursor_factory.h67
-rw-r--r--chromium/ui/base/x/x11_cursor_factory_unittest.cc32
-rw-r--r--chromium/ui/base/x/x11_display_manager.cc56
-rw-r--r--chromium/ui/base/x/x11_display_manager.h11
-rw-r--r--chromium/ui/base/x/x11_display_util.cc381
-rw-r--r--chromium/ui/base/x/x11_display_util.h4
-rw-r--r--chromium/ui/base/x/x11_drag_context.cc71
-rw-r--r--chromium/ui/base/x/x11_drag_context.h36
-rw-r--r--chromium/ui/base/x/x11_drag_drop_client.cc285
-rw-r--r--chromium/ui/base/x/x11_drag_drop_client.h61
-rw-r--r--chromium/ui/base/x/x11_error_handler.cc104
-rw-r--r--chromium/ui/base/x/x11_error_handler.h26
-rw-r--r--chromium/ui/base/x/x11_gl_egl_utility.cc14
-rw-r--r--chromium/ui/base/x/x11_menu_list.cc8
-rw-r--r--chromium/ui/base/x/x11_menu_list.h15
-rw-r--r--chromium/ui/base/x/x11_menu_registrar.cc15
-rw-r--r--chromium/ui/base/x/x11_menu_registrar.h7
-rw-r--r--chromium/ui/base/x/x11_os_exchange_data_provider.cc84
-rw-r--r--chromium/ui/base/x/x11_os_exchange_data_provider.h17
-rw-r--r--chromium/ui/base/x/x11_pointer_grab.cc21
-rw-r--r--chromium/ui/base/x/x11_pointer_grab.h2
-rw-r--r--chromium/ui/base/x/x11_shm_image_pool.cc20
-rw-r--r--chromium/ui/base/x/x11_shm_image_pool.h9
-rw-r--r--chromium/ui/base/x/x11_software_bitmap_presenter.cc62
-rw-r--r--chromium/ui/base/x/x11_software_bitmap_presenter.h2
-rw-r--r--chromium/ui/base/x/x11_topmost_window_finder.h2
-rw-r--r--chromium/ui/base/x/x11_util.cc1011
-rw-r--r--chromium/ui/base/x/x11_util.h311
-rw-r--r--chromium/ui/base/x/x11_util_internal.h49
-rw-r--r--chromium/ui/base/x/x11_whole_screen_move_loop.cc79
-rw-r--r--chromium/ui/base/x/x11_whole_screen_move_loop.h4
-rw-r--r--chromium/ui/base/x/x11_window.cc1043
-rw-r--r--chromium/ui/base/x/x11_window.h66
-rw-r--r--chromium/ui/base/x/x11_workspace_handler.cc19
-rw-r--r--chromium/ui/base/x/x11_workspace_handler.h7
-rw-r--r--chromium/ui/base/x/xwmstartupcheck/BUILD.gn13
-rw-r--r--chromium/ui/base/x/xwmstartupcheck/xwmstartupcheck.cc125
48 files changed, 2932 insertions, 2123 deletions
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