| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/aura/monitor_change_observer_x11.h" | 5 #include "ui/aura/monitor_change_observer_x11.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include <X11/extensions/Xrandr.h> | 12 #include <X11/extensions/Xrandr.h> |
| 13 | 13 |
| 14 #include "base/message_pump_aurax11.h" | 14 #include "base/message_pump_aurax11.h" |
| 15 #include "ui/aura/dispatcher_linux.h" |
| 15 #include "ui/aura/env.h" | 16 #include "ui/aura/env.h" |
| 16 #include "ui/aura/dispatcher_linux.h" | |
| 17 #include "ui/aura/monitor_manager.h" | 17 #include "ui/aura/monitor_manager.h" |
| 18 #include "ui/compositor/dip_util.h" | 18 #include "ui/compositor/dip_util.h" |
| 19 #include "ui/gfx/monitor.h" | 19 #include "ui/gfx/display.h" |
| 20 | 20 |
| 21 namespace aura { | 21 namespace aura { |
| 22 namespace internal { | 22 namespace internal { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // The DPI threshold to detect high density screen. | 26 // The DPI threshold to detect high density screen. |
| 27 // Higher DPI than this will use device_scale_factor=2. | 27 // Higher DPI than this will use device_scale_factor=2. |
| 28 // Note: This value has to be kept in sync with the mouse/touchpad driver | 28 // Note: This value has to be kept in sync with the mouse/touchpad driver |
| 29 // which controls mouse pointer acceleration. If you need to update this value, | 29 // which controls mouse pointer acceleration. If you need to update this value, |
| 30 // please update the bug (crosbug.com/31628) first and make sure that the | 30 // please update the bug (crosbug.com/31628) first and make sure that the |
| 31 // driver will use the same value. | 31 // driver will use the same value. |
| 32 const unsigned int kHighDensityDIPThreshold = 160; | 32 const unsigned int kHighDensityDIPThreshold = 160; |
| 33 | 33 |
| 34 // 1 inch in mm. | 34 // 1 inch in mm. |
| 35 const float kInchInMm = 25.4f; | 35 const float kInchInMm = 25.4f; |
| 36 | 36 |
| 37 XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) { | 37 XRRModeInfo* FindMode(XRRScreenResources* screen_resources, XID current_mode) { |
| 38 for (int m = 0; m < screen_resources->nmode; m++) { | 38 for (int m = 0; m < screen_resources->nmode; m++) { |
| 39 XRRModeInfo *mode = &screen_resources->modes[m]; | 39 XRRModeInfo *mode = &screen_resources->modes[m]; |
| 40 if (mode->id == current_mode) | 40 if (mode->id == current_mode) |
| 41 return mode; | 41 return mode; |
| 42 } | 42 } |
| 43 return NULL; | 43 return NULL; |
| 44 } | 44 } |
| 45 | 45 |
| 46 bool CompareMonitorY(const gfx::Monitor& lhs, const gfx::Monitor& rhs) { | 46 bool CompareDisplayY(const gfx::Display& lhs, const gfx::Display& rhs) { |
| 47 return lhs.bounds_in_pixel().y() > rhs.bounds_in_pixel().y(); | 47 return lhs.bounds_in_pixel().y() > rhs.bounds_in_pixel().y(); |
| 48 } | 48 } |
| 49 | 49 |
| 50 } // namespace | 50 } // namespace |
| 51 | 51 |
| 52 MonitorChangeObserverX11::MonitorChangeObserverX11() | 52 MonitorChangeObserverX11::MonitorChangeObserverX11() |
| 53 : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), | 53 : xdisplay_(base::MessagePumpAuraX11::GetDefaultXDisplay()), |
| 54 x_root_window_(DefaultRootWindow(xdisplay_)), | 54 x_root_window_(DefaultRootWindow(xdisplay_)), |
| 55 xrandr_event_base_(0) { | 55 xrandr_event_base_(0) { |
| 56 int error_base_ignored; | 56 int error_base_ignored; |
| 57 XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); | 57 XRRQueryExtension(xdisplay_, &xrandr_event_base_, &error_base_ignored); |
| 58 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> | 58 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
| 59 AddDispatcherForRootWindow(this); | 59 AddDispatcherForRootWindow(this); |
| 60 } | 60 } |
| 61 | 61 |
| 62 MonitorChangeObserverX11::~MonitorChangeObserverX11() { | 62 MonitorChangeObserverX11::~MonitorChangeObserverX11() { |
| 63 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> | 63 static_cast<DispatcherLinux*>(Env::GetInstance()->GetDispatcher())-> |
| 64 RemoveDispatcherForRootWindow(this); | 64 RemoveDispatcherForRootWindow(this); |
| 65 } | 65 } |
| 66 | 66 |
| 67 bool MonitorChangeObserverX11::Dispatch(const base::NativeEvent& event) { | 67 bool MonitorChangeObserverX11::Dispatch(const base::NativeEvent& event) { |
| 68 if (event->type - xrandr_event_base_ == RRScreenChangeNotify) { | 68 if (event->type - xrandr_event_base_ == RRScreenChangeNotify) { |
| 69 NotifyMonitorChange(); | 69 NotifyDisplayChange(); |
| 70 } | 70 } |
| 71 return true; | 71 return true; |
| 72 } | 72 } |
| 73 | 73 |
| 74 void MonitorChangeObserverX11::NotifyMonitorChange() { | 74 void MonitorChangeObserverX11::NotifyDisplayChange() { |
| 75 if (!MonitorManager::use_fullscreen_host_window()) | 75 if (!MonitorManager::use_fullscreen_host_window()) |
| 76 return; // Use the default monitor that monitor manager determined. | 76 return; // Use the default monitor that monitor manager determined. |
| 77 | 77 |
| 78 XRRScreenResources* screen_resources = | 78 XRRScreenResources* screen_resources = |
| 79 XRRGetScreenResources(xdisplay_, x_root_window_); | 79 XRRGetScreenResources(xdisplay_, x_root_window_); |
| 80 std::map<XID, XRRCrtcInfo*> crtc_info_map; | 80 std::map<XID, XRRCrtcInfo*> crtc_info_map; |
| 81 | 81 |
| 82 for (int c = 0; c < screen_resources->ncrtc; c++) { | 82 for (int c = 0; c < screen_resources->ncrtc; c++) { |
| 83 XID crtc_id = screen_resources->crtcs[c]; | 83 XID crtc_id = screen_resources->crtcs[c]; |
| 84 XRRCrtcInfo *crtc_info = | 84 XRRCrtcInfo *crtc_info = |
| 85 XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id); | 85 XRRGetCrtcInfo(xdisplay_, screen_resources, crtc_id); |
| 86 crtc_info_map[crtc_id] = crtc_info; | 86 crtc_info_map[crtc_id] = crtc_info; |
| 87 } | 87 } |
| 88 | 88 |
| 89 std::vector<gfx::Monitor> monitors; | 89 std::vector<gfx::Display> displays; |
| 90 std::set<int> y_coords; | 90 std::set<int> y_coords; |
| 91 for (int o = 0; o < screen_resources->noutput; o++) { | 91 for (int o = 0; o < screen_resources->noutput; o++) { |
| 92 XRROutputInfo *output_info = | 92 XRROutputInfo *output_info = |
| 93 XRRGetOutputInfo(xdisplay_, | 93 XRRGetOutputInfo(xdisplay_, |
| 94 screen_resources, | 94 screen_resources, |
| 95 screen_resources->outputs[o]); | 95 screen_resources->outputs[o]); |
| 96 if (output_info->connection != RR_Connected) { | 96 if (output_info->connection != RR_Connected) { |
| 97 XRRFreeOutputInfo(output_info); | 97 XRRFreeOutputInfo(output_info); |
| 98 continue; | 98 continue; |
| 99 } | 99 } |
| 100 XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc]; | 100 XRRCrtcInfo* crtc_info = crtc_info_map[output_info->crtc]; |
| 101 if (!crtc_info) { | 101 if (!crtc_info) { |
| 102 LOG(WARNING) << "Crtc not found for output"; | 102 LOG(WARNING) << "Crtc not found for output"; |
| 103 continue; | 103 continue; |
| 104 } | 104 } |
| 105 XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode); | 105 XRRModeInfo* mode = FindMode(screen_resources, crtc_info->mode); |
| 106 CHECK(mode); | 106 CHECK(mode); |
| 107 // Mirrored monitors have the same y coordinates. | 107 // Mirrored monitors have the same y coordinates. |
| 108 if (y_coords.find(crtc_info->y) != y_coords.end()) | 108 if (y_coords.find(crtc_info->y) != y_coords.end()) |
| 109 continue; | 109 continue; |
| 110 // TODO(oshima): Create unique ID for the monitor. | 110 // TODO(oshima): Create unique ID for the monitor. |
| 111 monitors.push_back(gfx::Monitor( | 111 displays.push_back(gfx::Display( |
| 112 0, | 112 0, |
| 113 gfx::Rect(crtc_info->x, crtc_info->y, mode->width, mode->height))); | 113 gfx::Rect(crtc_info->x, crtc_info->y, mode->width, mode->height))); |
| 114 | 114 |
| 115 float device_scale_factor = 1.0f; | 115 float device_scale_factor = 1.0f; |
| 116 if (output_info->mm_width > 0 && | 116 if (output_info->mm_width > 0 && |
| 117 (kInchInMm * mode->width / output_info->mm_width) > | 117 (kInchInMm * mode->width / output_info->mm_width) > |
| 118 kHighDensityDIPThreshold) { | 118 kHighDensityDIPThreshold) { |
| 119 device_scale_factor = 2.0f; | 119 device_scale_factor = 2.0f; |
| 120 } | 120 } |
| 121 monitors.back().set_device_scale_factor(device_scale_factor); | 121 displays.back().set_device_scale_factor(device_scale_factor); |
| 122 y_coords.insert(crtc_info->y); | 122 y_coords.insert(crtc_info->y); |
| 123 XRRFreeOutputInfo(output_info); | 123 XRRFreeOutputInfo(output_info); |
| 124 } | 124 } |
| 125 | 125 |
| 126 // Free all allocated resources. | 126 // Free all allocated resources. |
| 127 for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin(); | 127 for (std::map<XID, XRRCrtcInfo*>::const_iterator iter = crtc_info_map.begin(); |
| 128 iter != crtc_info_map.end(); ++iter) { | 128 iter != crtc_info_map.end(); ++iter) { |
| 129 XRRFreeCrtcInfo(iter->second); | 129 XRRFreeCrtcInfo(iter->second); |
| 130 } | 130 } |
| 131 XRRFreeScreenResources(screen_resources); | 131 XRRFreeScreenResources(screen_resources); |
| 132 | 132 |
| 133 // PowerManager lays out the outputs vertically. Sort them by Y | 133 // PowerManager lays out the outputs vertically. Sort them by Y |
| 134 // coordinates. | 134 // coordinates. |
| 135 std::sort(monitors.begin(), monitors.end(), CompareMonitorY); | 135 std::sort(displays.begin(), displays.end(), CompareDisplayY); |
| 136 // TODO(oshima): Assisgn index as ID for now. Use unique ID. | 136 // TODO(oshima): Assisgn index as ID for now. Use unique ID. |
| 137 int id = 0; | 137 int id = 0; |
| 138 for (std::vector<gfx::Monitor>::iterator iter = monitors.begin(); | 138 for (std::vector<gfx::Display>::iterator iter = displays.begin(); |
| 139 iter != monitors.end(); ++iter, ++id) | 139 iter != displays.end(); ++iter, ++id) |
| 140 (*iter).set_id(id); | 140 (*iter).set_id(id); |
| 141 | 141 |
| 142 Env::GetInstance()->monitor_manager() | 142 Env::GetInstance()->monitor_manager()->OnNativeMonitorsChanged(displays); |
| 143 ->OnNativeMonitorsChanged(monitors); | |
| 144 } | 143 } |
| 145 | 144 |
| 146 } // namespace internal | 145 } // namespace internal |
| 147 } // namespace aura | 146 } // namespace aura |
| OLD | NEW |