desktop_screen_x11.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_screen_x11.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <X11/extensions/Xrandr.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xlib.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It clashes with out RootWindow. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef RootWindow 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/debug/trace_event.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/aura/window_tree_host.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/layout.h" 190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/display/util/display_util.h" 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/display/util/x11/edid_parser_x11.h" 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/platform_event_source.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h" 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/display_observer.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/native_widget_types.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/gfx/x/x11_types.h" 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_screen.h" 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/widget/desktop_aura/x11_topmost_window_finder.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// The delay to perform configuration after RRNotify. See the comment 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// in |Dispatch()|. 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kConfigureDelayMs = 500; 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// TODO(oshima): Consider using gtk-xft-dpi instead. 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)float GetDeviceScaleFactor(int screen_pixels, int screen_mm) { 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const int kCSSDefaultDPI = 96; 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const float kInchInMm = 25.4f; 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) float screen_inches = screen_mm / kInchInMm; 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) float screen_dpi = screen_pixels / screen_inches; 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) float scale = screen_dpi / kCSSDefaultDPI; 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale)); 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<gfx::Display> GetFallbackDisplayList() { 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ::XDisplay* display = gfx::GetXDisplay(); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Screen* screen = DefaultScreenOfDisplay(display); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = WidthOfScreen(screen); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int height = HeightOfScreen(screen); 54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch gfx::Size physical_size(WidthMMOfScreen(screen), HeightMMOfScreen(screen)); 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect bounds_in_pixels(0, 0, width, height); 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Display gfx_display(0, bounds_in_pixels); 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!gfx::Display::HasForceDeviceScaleFactor() && 59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !ui::IsDisplaySizeBlackListed(physical_size)) { 60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch float device_scale_factor = GetDeviceScaleFactor( 61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch width, physical_size.width()); 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_LE(1.0f, device_scale_factor); 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx_display.SetScaleAndBounds(device_scale_factor, bounds_in_pixels); 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return std::vector<gfx::Display>(1, gfx_display); 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace views { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopScreenX11, public: 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DesktopScreenX11::DesktopScreenX11() 77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : xdisplay_(gfx::GetXDisplay()), 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) x_root_window_(DefaultRootWindow(xdisplay_)), 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) has_xrandr_(false), 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) xrandr_event_base_(0) { 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // We only support 1.3+. There were library changes before this and we should 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // use the new interface instead of the 1.2 one. 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int randr_version_major = 0; 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int randr_version_minor = 0; 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) has_xrandr_ = XRRQueryVersion( 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) xdisplay_, &randr_version_major, &randr_version_minor) && 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) randr_version_major == 1 && 8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) randr_version_minor >= 3; 8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_xrandr_) { 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int error_base_ignored = 0; 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (ui::PlatformEventSource::GetInstance()) 95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRSelectInput(xdisplay_, 9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) x_root_window_, 980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RRScreenChangeNotifyMask | 990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RROutputChangeNotifyMask | 1000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch RRCrtcChangeNotifyMask); 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) displays_ = BuildDisplaysFromXRandRInfo(); 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) displays_ = GetFallbackDisplayList(); 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DesktopScreenX11::~DesktopScreenX11() { 109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (has_xrandr_ && ui::PlatformEventSource::GetInstance()) 110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); 11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DesktopScreenX11::ProcessDisplayChange( 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::vector<gfx::Display>& incoming) { 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<gfx::Display> old_displays = displays_; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) displays_ = incoming; 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef std::vector<gfx::Display>::const_iterator DisplayIt; 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<gfx::Display>::const_iterator old_it = old_displays.begin(); 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (; old_it != old_displays.end(); ++old_it) { 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool found = false; 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (std::vector<gfx::Display>::const_iterator new_it = 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) displays_.begin(); new_it != displays_.end(); ++new_it) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (old_it->id() == new_it->id()) { 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) found = true; 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) break; 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!found) { 13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_, 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDisplayRemoved(*old_it)); 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<gfx::Display>::const_iterator new_it = displays_.begin(); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (; new_it != displays_.end(); ++new_it) { 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool found = false; 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (std::vector<gfx::Display>::const_iterator old_it = 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) old_displays.begin(); old_it != old_displays.end(); ++old_it) { 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_it->id() != old_it->id()) 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint32_t metrics = gfx::DisplayObserver::DISPLAY_METRIC_NONE; 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_it->bounds() != old_it->bounds()) 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics |= gfx::DisplayObserver::DISPLAY_METRIC_BOUNDS; 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_it->rotation() != old_it->rotation()) 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics |= gfx::DisplayObserver::DISPLAY_METRIC_ROTATION; 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_it->work_area() != old_it->work_area()) 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics |= gfx::DisplayObserver::DISPLAY_METRIC_WORK_AREA; 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_it->device_scale_factor() != old_it->device_scale_factor()) 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) metrics |= gfx::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR; 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (metrics != gfx::DisplayObserver::DISPLAY_METRIC_NONE) { 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FOR_EACH_OBSERVER(gfx::DisplayObserver, 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) observer_list_, 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) OnDisplayMetricsChanged(*new_it, metrics)); 16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) found = true; 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!found) { 16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FOR_EACH_OBSERVER(gfx::DisplayObserver, observer_list_, 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDisplayAdded(*new_it)); 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DesktopScreenX11, gfx::Screen implementation: 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool DesktopScreenX11::IsDIPEnabled() { 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Point DesktopScreenX11::GetCursorScreenPoint() { 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("views", "DesktopScreenX11::GetCursorScreenPoint()"); 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XDisplay* display = gfx::GetXDisplay(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::Window root, child; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int root_x, root_y, win_x, win_y; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int mask; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XQueryPointer(display, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultRootWindow(display), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &root, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &child, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &root_x, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &root_y, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &win_x, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &win_y, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &mask); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Point(root_x, root_y); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow DesktopScreenX11::GetWindowUnderCursor() { 20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return GetWindowAtScreenPoint(GetCursorScreenPoint()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint( 208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const gfx::Point& point) { 209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) X11TopmostWindowFinder finder; 210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return finder.FindLocalProcessWindowAt(point, std::set<aura::Window*>()); 211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int DesktopScreenX11::GetNumDisplays() const { 21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return displays_.size(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::vector<gfx::Display> DesktopScreenX11::GetAllDisplays() const { 21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return displays_; 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayNearestWindow( 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeView window) const { 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Getting screen bounds here safely is hard. 22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // You'd think we'd be able to just call window->GetBoundsInScreen(), but we 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // can't because |window| (and the associated WindowEventDispatcher*) can be 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // partially initialized at this point; WindowEventDispatcher initializations 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // call through into GetDisplayNearestWindow(). But the X11 resources are 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // created before we create the aura::WindowEventDispatcher. So we ask what 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the DRWHX11 believes the window bounds are instead of going through the 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // aura::Window's screen bounds. 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) aura::WindowTreeHost* host = window->GetHost(); 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (host) { 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID( 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) host->GetAcceleratedWidget()); 2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (rwh) 2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return GetDisplayMatching(rwh->GetX11RootWindowBounds()); 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return GetPrimaryDisplay(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayNearestPoint( 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) const { 24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<gfx::Display>::const_iterator it = displays_.begin(); 24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it != displays_.end(); ++it) { 24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (it->bounds().Contains(point)) 24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return *it; 24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return GetPrimaryDisplay(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetDisplayMatching( 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect& match_rect) const { 25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int max_area = 0; 25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const gfx::Display* matching = NULL; 25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<gfx::Display>::const_iterator it = displays_.begin(); 25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it != displays_.end(); ++it) { 26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect); 26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int area = intersect.width() * intersect.height(); 26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (area > max_area) { 26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) max_area = area; 26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) matching = &*it; 26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Fallback to the primary display if there is no matching display. 26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return matching ? *matching : GetPrimaryDisplay(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Display DesktopScreenX11::GetPrimaryDisplay() const { 27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return displays_.front(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopScreenX11::AddObserver(gfx::DisplayObserver* observer) { 27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) observer_list_.AddObserver(observer); 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DesktopScreenX11::RemoveObserver(gfx::DisplayObserver* observer) { 28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) observer_list_.RemoveObserver(observer); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool DesktopScreenX11::CanDispatchEvent(const ui::PlatformEvent& event) { 284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return event->type - xrandr_event_base_ == RRScreenChangeNotify || 285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch event->type - xrandr_event_base_ == RRNotify; 286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochuint32_t DesktopScreenX11::DispatchEvent(const ui::PlatformEvent& event) { 28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (event->type - xrandr_event_base_ == RRScreenChangeNotify) { 29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Pass the event through to xlib. 29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRUpdateConfiguration(event); 29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else if (event->type - xrandr_event_base_ == RRNotify) { 29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // There's some sort of observer dispatch going on here, but I don't think 29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // it's the screen's? 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (configure_timer_.get() && configure_timer_->IsRunning()) { 29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) configure_timer_->Reset(); 29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) configure_timer_.reset(new base::OneShotTimer<DesktopScreenX11>()); 29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) configure_timer_->Start( 30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kConfigureDelayMs), 30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) this, 30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) &DesktopScreenX11::ConfigureTimerFired); 30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 305c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } else { 306c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch NOTREACHED(); 30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return ui::POST_DISPATCH_NONE; 31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// DesktopScreenX11, private: 31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DesktopScreenX11::DesktopScreenX11( 31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::vector<gfx::Display>& test_displays) 317a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : xdisplay_(gfx::GetXDisplay()), 31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) x_root_window_(DefaultRootWindow(xdisplay_)), 31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) has_xrandr_(false), 32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) xrandr_event_base_(0), 32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) displays_(test_displays) { 32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::vector<gfx::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() { 32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<gfx::Display> displays; 32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRScreenResources* resources = 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRGetScreenResourcesCurrent(xdisplay_, x_root_window_); 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!resources) { 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) LOG(ERROR) << "XRandR returned no displays. Falling back to Root Window."; 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return GetFallbackDisplayList(); 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool has_work_area = false; 33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Rect work_area; 33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<int> value; 33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ui::GetIntArrayProperty(x_root_window_, "_NET_WORKAREA", &value) && 33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) value.size() >= 4) { 33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) work_area = gfx::Rect(value[0], value[1], value[2], value[3]); 33968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) has_work_area = true; 34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) float device_scale_factor = 1.0f; 34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (int i = 0; i < resources->noutput; ++i) { 34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RROutput output_id = resources->outputs[i]; 34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRROutputInfo* output_info = 34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRGetOutputInfo(xdisplay_, resources, output_id); 34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool is_connected = (output_info->connection == RR_Connected); 34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (!is_connected) { 35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRFreeOutputInfo(output_info); 35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) continue; 35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (output_info->crtc) { 35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRCrtcInfo *crtc = XRRGetCrtcInfo(xdisplay_, 35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) resources, 35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) output_info->crtc); 35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int64 display_id = -1; 360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!ui::GetDisplayId(output_id, static_cast<uint8>(i), &display_id)) { 36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // It isn't ideal, but if we can't parse the EDID data, fallback on the 36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // display number. 36368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) display_id = i; 36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Rect crtc_bounds(crtc->x, crtc->y, crtc->width, crtc->height); 36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Display display(display_id, crtc_bounds); 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!gfx::Display::HasForceDeviceScaleFactor()) { 370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (i == 0 && !ui::IsDisplaySizeBlackListed( 371c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch gfx::Size(output_info->mm_width, output_info->mm_height))) { 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // As per display scale factor is not supported right now, 373f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the primary display's scale factor is always used. 374f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) device_scale_factor = GetDeviceScaleFactor(crtc->width, 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) output_info->mm_width); 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_LE(1.0f, device_scale_factor); 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) display.SetScaleAndBounds(device_scale_factor, crtc_bounds); 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (has_work_area) { 38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::Rect intersection = crtc_bounds; 38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) intersection.Intersect(work_area); 38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) display.set_work_area(intersection); 38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) switch (crtc->rotation) { 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case RR_Rotate_0: 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) display.set_rotation(gfx::Display::ROTATE_0); 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case RR_Rotate_90: 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) display.set_rotation(gfx::Display::ROTATE_90); 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case RR_Rotate_180: 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) display.set_rotation(gfx::Display::ROTATE_180); 396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case RR_Rotate_270: 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) display.set_rotation(gfx::Display::ROTATE_270); 399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) displays.push_back(display); 40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRFreeCrtcInfo(crtc); 40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRFreeOutputInfo(output_info); 40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) XRRFreeScreenResources(resources); 41168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (displays.empty()) 41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return GetFallbackDisplayList(); 41468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return displays; 41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DesktopScreenX11::ConfigureTimerFired() { 41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::vector<gfx::Display> new_displays = BuildDisplaysFromXRandRInfo(); 42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ProcessDisplayChange(new_displays); 42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Screen* CreateDesktopScreen() { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new DesktopScreenX11; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace views 430