Commit 6b2841f3 authored by Fredrik Hubinette's avatar Fredrik Hubinette Committed by Commit Bot

Read per-display ICC profiles on linux.

For future reference, the correct "order" of monitors in X11
is the one given by xrandr --listmonitors

Bug: 822068
Change-Id: I6ceedc8db1d381ab3955af584fd365a764910ea7
Reviewed-on: https://chromium-review.googlesource.com/972547
Commit-Queue: Fredrik Hubinette <hubbe@chromium.org>
Reviewed-by: default avatarccameron <ccameron@chromium.org>
Reviewed-by: default avatarStéphane Marchesin <marcheu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547839}
parent 314637c0
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
...@@ -33,14 +34,22 @@ ...@@ -33,14 +34,22 @@
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" #include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h"
#include <dlfcn.h>
namespace { namespace {
// static // static
gfx::ICCProfile GetICCProfileFromBestMonitor() { gfx::ICCProfile GetICCProfileForMonitor(int monitor) {
gfx::ICCProfile icc_profile; gfx::ICCProfile icc_profile;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
return icc_profile; return icc_profile;
Atom property = gfx::GetAtom("_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) { if (property != x11::None) {
Atom prop_type = x11::None; Atom prop_type = x11::None;
int prop_format = 0; int prop_format = 0;
...@@ -108,7 +117,7 @@ namespace views { ...@@ -108,7 +117,7 @@ namespace views {
DesktopScreenX11::DesktopScreenX11() DesktopScreenX11::DesktopScreenX11()
: xdisplay_(gfx::GetXDisplay()), : xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)), x_root_window_(DefaultRootWindow(xdisplay_)),
has_xrandr_(false), xrandr_version_(0),
xrandr_event_base_(0), xrandr_event_base_(0),
primary_display_index_(0), primary_display_index_(0),
weak_factory_(this) { weak_factory_(this) {
...@@ -118,12 +127,11 @@ DesktopScreenX11::DesktopScreenX11() ...@@ -118,12 +127,11 @@ DesktopScreenX11::DesktopScreenX11()
// use the new interface instead of the 1.2 one. // use the new interface instead of the 1.2 one.
int randr_version_major = 0; int randr_version_major = 0;
int randr_version_minor = 0; int randr_version_minor = 0;
has_xrandr_ = XRRQueryVersion( if (XRRQueryVersion(xdisplay_, &randr_version_major, &randr_version_minor)) {
xdisplay_, &randr_version_major, &randr_version_minor) && xrandr_version_ = randr_version_major * 100 + randr_version_minor;
randr_version_major == 1 && }
randr_version_minor >= 3; // Need at least xrandr version 1.3.
if (xrandr_version_ >= 103) {
if (has_xrandr_) {
int error_base_ignored = 0; int error_base_ignored = 0;
XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored);
...@@ -144,7 +152,7 @@ DesktopScreenX11::DesktopScreenX11() ...@@ -144,7 +152,7 @@ DesktopScreenX11::DesktopScreenX11()
DesktopScreenX11::~DesktopScreenX11() { DesktopScreenX11::~DesktopScreenX11() {
if (views::LinuxUI::instance()) if (views::LinuxUI::instance())
views::LinuxUI::instance()->AddDeviceScaleFactorObserver(this); views::LinuxUI::instance()->AddDeviceScaleFactorObserver(this);
if (has_xrandr_ && ui::PlatformEventSource::GetInstance()) if (xrandr_version_ >= 103 && ui::PlatformEventSource::GetInstance())
ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
} }
...@@ -297,7 +305,7 @@ DesktopScreenX11::DesktopScreenX11( ...@@ -297,7 +305,7 @@ DesktopScreenX11::DesktopScreenX11(
const std::vector<display::Display>& test_displays) const std::vector<display::Display>& test_displays)
: xdisplay_(gfx::GetXDisplay()), : xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)), x_root_window_(DefaultRootWindow(xdisplay_)),
has_xrandr_(false), xrandr_version_(0),
xrandr_event_base_(0), xrandr_event_base_(0),
displays_(test_displays), displays_(test_displays),
primary_display_index_(0), primary_display_index_(0),
...@@ -307,7 +315,7 @@ DesktopScreenX11::DesktopScreenX11( ...@@ -307,7 +315,7 @@ DesktopScreenX11::DesktopScreenX11(
} }
std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
DCHECK(has_xrandr_); DCHECK(xrandr_version_ >= 103);
std::vector<display::Display> displays; std::vector<display::Display> displays;
gfx::XScopedPtr< gfx::XScopedPtr<
XRRScreenResources, XRRScreenResources,
...@@ -318,6 +326,31 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { ...@@ -318,6 +326,31 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
return GetFallbackDisplayList(); return GetFallbackDisplayList();
} }
std::map<RROutput, int> output_to_monitor;
if (xrandr_version_ >= 105) {
void* xrandr_lib = dlopen(NULL, RTLD_NOW);
if (xrandr_lib) {
typedef XRRMonitorInfo* (*XRRGetMonitors_type)(Display*, Window, bool,
int*);
typedef void (*XRRFreeMonitors_type)(XRRMonitorInfo*);
XRRGetMonitors_type XRRGetMonitors_ptr =
(XRRGetMonitors_type)dlsym(xrandr_lib, "XRRGetMonitors");
XRRFreeMonitors_type XRRFreeMonitors_ptr =
(XRRFreeMonitors_type)dlsym(xrandr_lib, "XRRFreeMonitors");
if (XRRGetMonitors_ptr && XRRFreeMonitors_ptr) {
int nmonitors = 0;
XRRMonitorInfo* monitors =
XRRGetMonitors_ptr(xdisplay_, x_root_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);
}
}
}
primary_display_index_ = 0; primary_display_index_ = 0;
RROutput primary_display_id = XRRGetOutputPrimary(xdisplay_, x_root_window_); RROutput primary_display_id = XRRGetOutputPrimary(xdisplay_, x_root_window_);
...@@ -397,10 +430,10 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { ...@@ -397,10 +430,10 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
if (is_primary_display) if (is_primary_display)
primary_display_index_ = displays.size(); primary_display_index_ = displays.size();
// TODO(ccameron): Populate this based on this specific display.
// http://crbug.com/735613
if (!display::Display::HasForceColorProfile()) { if (!display::Display::HasForceColorProfile()) {
gfx::ICCProfile icc_profile = GetICCProfileFromBestMonitor(); auto monitor_iter = output_to_monitor.find(output_id);
gfx::ICCProfile icc_profile = GetICCProfileForMonitor(
monitor_iter == output_to_monitor.end() ? 0 : monitor_iter->second);
icc_profile.HistogramDisplay(display.id()); icc_profile.HistogramDisplay(display.id());
display.set_color_space(icc_profile.GetColorSpace()); display.set_color_space(icc_profile.GetColorSpace());
} }
...@@ -424,7 +457,7 @@ void DesktopScreenX11::RestartDelayedConfigurationTask() { ...@@ -424,7 +457,7 @@ void DesktopScreenX11::RestartDelayedConfigurationTask() {
void DesktopScreenX11::UpdateDisplays() { void DesktopScreenX11::UpdateDisplays() {
std::vector<display::Display> old_displays = displays_; std::vector<display::Display> old_displays = displays_;
if (has_xrandr_) if (xrandr_version_ > 103)
SetDisplaysInternal(BuildDisplaysFromXRandRInfo()); SetDisplaysInternal(BuildDisplaysFromXRandRInfo());
else else
SetDisplaysInternal(GetFallbackDisplayList()); SetDisplaysInternal(GetFallbackDisplayList());
......
...@@ -87,8 +87,8 @@ class VIEWS_EXPORT DesktopScreenX11 : public display::Screen, ...@@ -87,8 +87,8 @@ class VIEWS_EXPORT DesktopScreenX11 : public display::Screen,
::Display* xdisplay_; ::Display* xdisplay_;
::Window x_root_window_; ::Window x_root_window_;
// Whether the x server supports the XRandR extension. // XRandR version. MAJOR * 100 + MINOR. Zero if no xrandr is present.
bool has_xrandr_; int xrandr_version_;
// The base of the event numbers used to represent XRandr events used in // The base of the event numbers used to represent XRandr events used in
// decoding events regarding output add/remove. // decoding events regarding output add/remove.
......
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