Commit fce1db03 authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

[XProto] Use serializer/deserializers for special-case structs

This CL uses the special reader/writer added by [1] to check
that it's working.

[1] https://chromium-review.googlesource.com/c/chromium/src/+/2209961

BUG=1066670
R=msisov
CC=sky

Change-Id: I09c83827145916366f283e2bac93ed03d5db113a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2212976
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarMaksim Sisov <msisov@igalia.com>
Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772383}
parent b1d9122c
...@@ -102,18 +102,13 @@ float GetRefreshRateFromXRRModeInfo( ...@@ -102,18 +102,13 @@ float GetRefreshRateFromXRRModeInfo(
return 0; return 0;
} }
int DefaultScreenDepth(XDisplay* xdisplay) { int DefaultBitsPerComponent() {
return DefaultDepth(xdisplay, DefaultScreen(xdisplay)); auto* connection = x11::Connection::Get();
} const x11::XProto::VisualType* visual = connection->default_root_visual();
int DefaultBitsPerComponent(XDisplay* xdisplay) {
Visual* visual = DefaultVisual(xdisplay, DefaultScreen(xdisplay));
// The mask fields are only valid for DirectColor and TrueColor classes. // The mask fields are only valid for DirectColor and TrueColor classes.
if (visual->c_class == if (visual->c_class == x11::XProto::VisualClass::DirectColor ||
static_cast<int>(x11::XProto::VisualClass::DirectColor) || visual->c_class == x11::XProto::VisualClass::TrueColor) {
visual->c_class ==
static_cast<int>(x11::XProto::VisualClass::TrueColor)) {
// RGB components are packed into fixed size integers for each visual. The // RGB components are packed into fixed size integers for each visual. The
// layout of bits in the packing is given by // 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
...@@ -130,12 +125,12 @@ int DefaultBitsPerComponent(XDisplay* xdisplay) { ...@@ -130,12 +125,12 @@ int DefaultBitsPerComponent(XDisplay* xdisplay) {
// Next, try getting the number of colormap entries per subfield. If it's a // 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. // power of 2, log2 is a possible guess for the number of bits per component.
if (base::bits::IsPowerOfTwo(visual->map_entries)) if (base::bits::IsPowerOfTwo(visual->colormap_entries))
return base::bits::Log2Ceiling(visual->map_entries); return base::bits::Log2Ceiling(visual->colormap_entries);
// |bits_per_rgb| can sometimes be unreliable (may be 11 for 30bpp visuals), // |bits_per_rgb| can sometimes be unreliable (may be 11 for 30bpp visuals),
// so only use it as a last resort. // so only use it as a last resort.
return visual->bits_per_rgb; return visual->bits_per_rgb_value;
} }
// Get the EDID data from the |output| and stores to |edid|. // Get the EDID data from the |output| and stores to |edid|.
...@@ -168,12 +163,12 @@ int GetXrandrVersion(XDisplay* xdisplay) { ...@@ -168,12 +163,12 @@ int GetXrandrVersion(XDisplay* xdisplay) {
} }
std::vector<display::Display> GetFallbackDisplayList(float scale) { std::vector<display::Display> GetFallbackDisplayList(float scale) {
XDisplay* display = gfx::GetXDisplay(); const auto* screen = x11::Connection::Get()->default_screen();
::Screen* screen = DefaultScreenOfDisplay(display); gfx::Size physical_size(screen->width_in_millimeters,
gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen)); screen->height_in_millimeters);
int width = WidthOfScreen(screen); int width = screen->width_in_pixels;
int height = HeightOfScreen(screen); int height = screen->height_in_pixels;
gfx::Rect bounds_in_pixels(0, 0, width, height); gfx::Rect bounds_in_pixels(0, 0, width, height);
display::Display gfx_display(0, bounds_in_pixels); display::Display gfx_display(0, bounds_in_pixels);
...@@ -187,8 +182,8 @@ std::vector<display::Display> GetFallbackDisplayList(float scale) { ...@@ -187,8 +182,8 @@ std::vector<display::Display> GetFallbackDisplayList(float scale) {
scale = 1; scale = 1;
} }
gfx_display.set_color_depth(DefaultScreenDepth(display)); gfx_display.set_color_depth(screen->root_depth);
gfx_display.set_depth_per_component(DefaultBitsPerComponent(display)); gfx_display.set_depth_per_component(DefaultBitsPerComponent());
std::vector<display::Display> displays{gfx_display}; std::vector<display::Display> displays{gfx_display};
ClipWorkArea(&displays, 0, scale); ClipWorkArea(&displays, 0, scale);
...@@ -201,7 +196,8 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo( ...@@ -201,7 +196,8 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo(
int64_t* primary_display_index_out) { int64_t* primary_display_index_out) {
DCHECK(primary_display_index_out); DCHECK(primary_display_index_out);
DCHECK_GE(version, kMinVersionXrandr); DCHECK_GE(version, kMinVersionXrandr);
auto* randr = x11::Connection::Get()->randr(); auto* connection = x11::Connection::Get();
auto* randr = connection->randr();
if (!randr) if (!randr)
return GetFallbackDisplayList(scale); return GetFallbackDisplayList(scale);
auto x_root_window = static_cast<x11::Window>(ui::GetX11RootWindow()); auto x_root_window = static_cast<x11::Window>(ui::GetX11RootWindow());
...@@ -212,8 +208,8 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo( ...@@ -212,8 +208,8 @@ std::vector<display::Display> BuildDisplaysFromXRandRInfo(
return GetFallbackDisplayList(scale); return GetFallbackDisplayList(scale);
} }
const int depth = DefaultScreenDepth(gfx::GetXDisplay()); const int depth = connection->default_screen()->root_depth;
const int bits_per_component = DefaultBitsPerComponent(gfx::GetXDisplay()); const int bits_per_component = DefaultBitsPerComponent();
std::map<x11::RandR::Output, int> output_to_monitor = std::map<x11::RandR::Output, int> output_to_monitor =
GetMonitors(version, randr, x_root_window); GetMonitors(version, randr, x_root_window);
......
...@@ -773,23 +773,10 @@ void SetWMSpecState(XID window, ...@@ -773,23 +773,10 @@ void SetWMSpecState(XID window,
bool enabled, bool enabled,
x11::Atom state1, x11::Atom state1,
x11::Atom state2) { x11::Atom state2) {
XEvent xclient; SendClientMessage(
memset(&xclient, 0, sizeof(xclient)); window, GetX11RootWindow(), gfx::GetAtom("_NET_WM_STATE"),
xclient.type = ClientMessage; {enabled ? kNetWMStateAdd : kNetWMStateRemove,
xclient.xclient.window = window; static_cast<uint32_t>(state1), static_cast<uint32_t>(state2), 1, 0});
xclient.xclient.message_type =
static_cast<uint32_t>(gfx::GetAtom("_NET_WM_STATE"));
// The data should be viewed as a list of longs, because x11::Atom is a
// typedef of long.
xclient.xclient.format = 32;
xclient.xclient.data.l[0] = enabled ? kNetWMStateAdd : kNetWMStateRemove;
xclient.xclient.data.l[1] = static_cast<uint32_t>(state1);
xclient.xclient.data.l[2] = static_cast<uint32_t>(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, void DoWMMoveResize(XDisplay* display,
...@@ -803,20 +790,8 @@ void DoWMMoveResize(XDisplay* display, ...@@ -803,20 +790,8 @@ void DoWMMoveResize(XDisplay* display,
// grabs when it receives the event below. // grabs when it receives the event below.
XUngrabPointer(display, x11::CurrentTime); XUngrabPointer(display, x11::CurrentTime);
XEvent event; SendClientMessage(window, root_window, gfx::GetAtom("_NET_WM_MOVERESIZE"),
memset(&event, 0, sizeof(event)); {location_px.x(), location_px.y(), direction, 0, 0});
event.xclient.type = ClientMessage;
event.xclient.display = display;
event.xclient.window = window;
event.xclient.message_type =
static_cast<uint32_t>(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);
} }
bool HasWMSpecProperty(const base::flat_set<x11::Atom>& properties, bool HasWMSpecProperty(const base::flat_set<x11::Atom>& properties,
...@@ -1177,6 +1152,24 @@ SkColorType ColorTypeForVisual(void* visual) { ...@@ -1177,6 +1152,24 @@ SkColorType ColorTypeForVisual(void* visual) {
return kUnknown_SkColorType; return kUnknown_SkColorType;
} }
x11::Future<void> SendClientMessage(XID window,
XID target,
x11::Atom type,
const std::array<uint32_t, 5> data,
x11::XProto::EventMask event_mask) {
x11::XProto::ClientMessageEvent event{
.format = 32, .window = static_cast<x11::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::XProto::SendEventRequest request{false, static_cast<x11::Window>(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) XRefcountedMemory::XRefcountedMemory(unsigned char* x11_data, size_t length)
: x11_data_(length ? x11_data : nullptr), length_(length) {} : x11_data_(length ? x11_data : nullptr), length_(length) {}
......
...@@ -404,6 +404,16 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsSyncExtensionAvailable(); ...@@ -404,6 +404,16 @@ COMPONENT_EXPORT(UI_BASE_X) bool IsSyncExtensionAvailable();
COMPONENT_EXPORT(UI_BASE_X) COMPONENT_EXPORT(UI_BASE_X)
SkColorType ColorTypeForVisual(void* visual); SkColorType ColorTypeForVisual(void* visual);
COMPONENT_EXPORT(UI_BASE_X)
x11::Future<void> SendClientMessage(
XID window,
XID target,
x11::Atom type,
const std::array<uint32_t, 5> data,
x11::XProto::EventMask event_mask =
x11::XProto::EventMask::SubstructureNotify |
x11::XProto::EventMask::SubstructureRedirect);
// Manages a piece of X11 allocated memory as a RefCountedMemory segment. This // 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 // object takes ownership over the passed in memory and will free it with the
// X11 allocator when done. // X11 allocator when done.
......
...@@ -1577,23 +1577,13 @@ bool XWindow::InitializeAsStatusIcon() { ...@@ -1577,23 +1577,13 @@ bool XWindow::InitializeAsStatusIcon() {
static_cast<int>(x11::XProto::BackPixmap::ParentRelative); static_cast<int>(x11::XProto::BackPixmap::ParentRelative);
} }
XChangeWindowAttributes(xdisplay_, xwindow_, flags, &attrs); XChangeWindowAttributes(xdisplay_, xwindow_, flags, &attrs);
XEvent ev;
memset(&ev, 0, sizeof(ev)); auto future = ui::SendClientMessage(
ev.xclient.type = ClientMessage; manager, manager, gfx::GetAtom("_NET_SYSTEM_TRAY_OPCODE"),
ev.xclient.window = manager; {ui::X11EventSource::GetInstance()->GetTimestamp(),
ev.xclient.message_type = kSystemTrayRequestDock, xwindow_, 0, 0},
static_cast<uint32_t>(gfx::GetAtom("_NET_SYSTEM_TRAY_OPCODE")); x11::XProto::EventMask::NoEvent);
ev.xclient.format = 32; return !future.Sync().error;
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();
}
return !error;
} }
} // namespace ui } // namespace ui
...@@ -4,8 +4,14 @@ ...@@ -4,8 +4,14 @@
#include "ui/gfx/x/connection.h" #include "ui/gfx/x/connection.h"
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <algorithm>
#include "base/command_line.h" #include "base/command_line.h"
#include "ui/gfx/x/x11_switches.h" #include "ui/gfx/x/x11_switches.h"
#include "ui/gfx/x/xproto_types.h"
namespace x11 { namespace x11 {
...@@ -28,6 +34,32 @@ Connection* Connection::Get() { ...@@ -28,6 +34,32 @@ Connection* Connection::Get() {
} }
Connection::Connection(XDisplay* display) Connection::Connection(XDisplay* display)
: XProto(display), ExtensionManager(this) {} : XProto(display), ExtensionManager(this) {
if (!display)
return;
setup_ = std::make_unique<x11::XProto::Setup>(x11::Read<x11::XProto::Setup>(
reinterpret_cast<const uint8_t*>(xcb_get_setup(XcbConnection()))));
default_screen_ = &setup_->roots[DefaultScreen(display)];
default_root_depth_ =
&*std::find_if(default_screen_->allowed_depths.begin(),
default_screen_->allowed_depths.end(),
[&](const x11::XProto::Depth& depth) {
return depth.depth == default_screen_->root_depth;
});
defualt_root_visual_ = &*std::find_if(
default_root_depth_->visuals.begin(), default_root_depth_->visuals.end(),
[&](const x11::XProto::VisualType visual) {
return visual.visual_id == default_screen_->root_visual;
});
}
Connection::~Connection() = default;
xcb_connection_t* Connection::XcbConnection() {
if (!display())
return nullptr;
return XGetXCBConnection(display());
}
} // namespace x11 } // namespace x11
...@@ -24,8 +24,25 @@ class COMPONENT_EXPORT(X11) Connection : public XProto, ...@@ -24,8 +24,25 @@ class COMPONENT_EXPORT(X11) Connection : public XProto,
Connection(const Connection&) = delete; Connection(const Connection&) = delete;
Connection(Connection&&) = delete; Connection(Connection&&) = delete;
xcb_connection_t* XcbConnection();
const x11::XProto::Setup* setup() const { return setup_.get(); }
const x11::XProto::Screen* default_screen() const { return default_screen_; }
const x11::XProto::Depth* default_root_depth() const {
return default_root_depth_;
}
const x11::XProto::VisualType* default_root_visual() const {
return defualt_root_visual_;
}
private: private:
explicit Connection(XDisplay* display); explicit Connection(XDisplay* display);
~Connection();
std::unique_ptr<x11::XProto::Setup> setup_;
const x11::XProto::Screen* default_screen_ = nullptr;
const x11::XProto::Depth* default_root_depth_ = nullptr;
const x11::XProto::VisualType* defualt_root_visual_ = nullptr;
}; };
} // namespace x11 } // namespace x11
......
...@@ -358,6 +358,9 @@ class GenXproto(FileWriter): ...@@ -358,6 +358,9 @@ class GenXproto(FileWriter):
# Map from (XML tag, XML name) to XML element # Map from (XML tag, XML name) to XML element
self.module_names = {} self.module_names = {}
# Enums that represent bit masks.
self.bitenums = []
# Geenerate an ID suitable for use in temporary variable names. # Geenerate an ID suitable for use in temporary variable names.
def new_uid(self, ): def new_uid(self, ):
self.prev_id += 1 self.prev_id += 1
...@@ -953,6 +956,9 @@ class GenXproto(FileWriter): ...@@ -953,6 +956,9 @@ class GenXproto(FileWriter):
return return
self.types[renamed].add(t) self.types[renamed].add(t)
if isinstance(t, self.xcbgen.xtypes.Enum):
self.bitenums.append((t, name))
if not t.is_container: if not t.is_container:
return return
...@@ -1103,6 +1109,16 @@ class GenXproto(FileWriter): ...@@ -1103,6 +1109,16 @@ class GenXproto(FileWriter):
self.write() self.write()
self.write('} // namespace x11') self.write('} // namespace x11')
self.write() self.write()
self.namespace = []
for enum, name in self.bitenums:
name = self.qualtype(enum, name)
self.write('inline %s operator|(' % name)
with Indent(self, ' {0} l, {0} r)'.format(name) + ' {', '}'):
self.write('using T = std::underlying_type_t<%s>;' % name)
self.write('return static_cast<%s>(' % name)
self.write(' static_cast<T>(l) | static_cast<T>(r));')
self.write()
self.write()
self.write('#endif // ' + include_guard) self.write('#endif // ' + include_guard)
def gen_source(self): def gen_source(self):
......
...@@ -49,11 +49,17 @@ struct ReadBuffer { ...@@ -49,11 +49,17 @@ struct ReadBuffer {
}; };
template <typename T> template <typename T>
void Write(const T* t, WriteBuffer* buf) { void VerifyAlignment(T* t, size_t offset) {
static_assert(std::is_trivially_copyable<T>::value, "");
// On the wire, X11 types are always aligned to their size. This is a sanity // On the wire, X11 types are always aligned to their size. This is a sanity
// check to ensure padding etc are working properly. // check to ensure padding etc are working properly.
DCHECK_EQ(buf->size() % sizeof(*t), 0UL); if (sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8)
DCHECK_EQ(offset % sizeof(*t), 0UL);
}
template <typename T>
void Write(const T* t, WriteBuffer* buf) {
static_assert(std::is_trivially_copyable<T>::value, "");
VerifyAlignment(t, buf->size());
const uint8_t* start = reinterpret_cast<const uint8_t*>(t); const uint8_t* start = reinterpret_cast<const uint8_t*>(t);
std::copy(start, start + sizeof(*t), std::back_inserter(*buf)); std::copy(start, start + sizeof(*t), std::back_inserter(*buf));
} }
...@@ -61,9 +67,7 @@ void Write(const T* t, WriteBuffer* buf) { ...@@ -61,9 +67,7 @@ void Write(const T* t, WriteBuffer* buf) {
template <typename T> template <typename T>
void Read(T* t, ReadBuffer* buf) { void Read(T* t, ReadBuffer* buf) {
static_assert(std::is_trivially_copyable<T>::value, ""); static_assert(std::is_trivially_copyable<T>::value, "");
// On the wire, X11 types are always aligned to their size. This is a sanity VerifyAlignment(t, buf->offset);
// check to ensure padding etc are working properly.
DCHECK_EQ(buf->offset % sizeof(*t), 0UL);
memcpy(t, buf->data + buf->offset, sizeof(*t)); memcpy(t, buf->data + buf->offset, sizeof(*t));
buf->offset += sizeof(*t); buf->offset += sizeof(*t);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment