Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: monitor_reconfigure_main.cc

Issue 6732013: Refactor monitor_reconfigure to stop using system("xrandr"). (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/monitor_reconfig.git@master
Patch Set: Update the patch: address comments, make tests pass, free X structures. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS 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 "monitor_reconfig/monitor_reconfigure_main.h" 5 #include "monitor_reconfig/monitor_reconfigure_main.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstdio> 8 #include <cstdio>
9 #include <cstdlib> 9 #include <cstdlib>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 14
15 using std::map; 15 using std::map;
16 using std::sort; 16 using std::sort;
17 using std::string; 17 using std::string;
18 using std::vector; 18 using std::vector;
19 19
20 namespace monitor_reconfig { 20 namespace monitor_reconfig {
21 21
22 static const char kLcdOutputName[] = "LVDS1"; 22 static const char kLcdOutputName[] = "LVDS1";
23 static const float kScreenDpi = 96.0;
24 static const float kInchInMm = 25.4;
23 25
24 MonitorReconfigureMain::MonitorReconfigureMain(Display* display, 26 MonitorReconfigureMain::MonitorReconfigureMain(Display* display,
27 Window window,
25 XRRScreenResources* screen_info) 28 XRRScreenResources* screen_info)
26 : display_(display), 29 : display_(display),
30 window_(window),
27 screen_info_(screen_info), 31 screen_info_(screen_info),
28 lcd_output_(NULL), 32 lcd_output_(0),
29 external_output_(NULL) { 33 lcd_output_info_(NULL),
34 external_output_(0),
35 external_output_info_(NULL) {
30 for (int i = 0; i < screen_info_->nmode; ++i) { 36 for (int i = 0; i < screen_info_->nmode; ++i) {
31 XRRModeInfo* current_mode = &screen_info_->modes[i]; 37 XRRModeInfo* current_mode = &screen_info_->modes[i];
32 mode_map_[current_mode->id] = current_mode; 38 mode_map_[current_mode->id] = current_mode;
33 } 39 }
34 DetermineOutputs(); 40 DetermineOutputs();
35 } 41 }
36 42
37 void MonitorReconfigureMain::Run() { 43 void MonitorReconfigureMain::Run() {
38 vector<ResolutionSelector::Mode> lcd_modes; 44 vector<ResolutionSelector::Mode> lcd_modes;
39 SortModesByResolution(*lcd_output_, &lcd_modes); 45 SortModesByResolution(lcd_output_, &lcd_modes);
40 DCHECK(!lcd_modes.empty()); 46 DCHECK(!lcd_modes.empty());
41 47
42 vector<ResolutionSelector::Mode> external_modes; 48 vector<ResolutionSelector::Mode> external_modes;
43 if (IsExternalMonitorConnected()) { 49 if (IsExternalMonitorConnected()) {
44 SortModesByResolution(*external_output_, &external_modes); 50 SortModesByResolution(external_output_, &external_modes);
45 DCHECK(!external_modes.empty()); 51 DCHECK(!external_modes.empty());
46 } 52 }
47 53
48 ResolutionSelector selector; 54 ResolutionSelector selector;
49 string lcd_resolution, external_resolution, screen_resolution; 55 ResolutionSelector::Mode lcd_resolution(0, 0, "", 0);
Daniel Erat 2011/03/25 03:39:02 i think that it's okay to make an additional c'tor
marcheu 2011/03/25 17:39:42 Done.
56 ResolutionSelector::Mode external_resolution(0, 0, "", 0);
57 ResolutionSelector::Mode screen_resolution(0, 0, "", 0);
58
50 CHECK(selector.FindBestResolutions(lcd_modes, 59 CHECK(selector.FindBestResolutions(lcd_modes,
51 external_modes, 60 external_modes,
52 &lcd_resolution, 61 &lcd_resolution,
53 &external_resolution, 62 &external_resolution,
54 &screen_resolution)); 63 &screen_resolution));
55 CHECK(!lcd_resolution.empty() || !external_resolution.empty()); 64 CHECK(!lcd_resolution.name.empty() || !external_resolution.name.empty());
65
66 // Grab the server during mode changes.
67 XGrabServer(display_);
56 68
57 // Disable the LCD if we were told to do so (because we're using a higher 69 // Disable the LCD if we were told to do so (because we're using a higher
58 // resolution that'd be clipped on the LCD). 70 // resolution that'd be clipped on the LCD).
59 if (lcd_resolution.empty()) 71 // Otherwise enable the LCD if appropriate.
60 DisableDevice(lcd_output_->name); 72 if (lcd_resolution.name.empty())
73 DisableDevice(lcd_output_, lcd_output_info_);
74 else
75 SetDeviceResolution(lcd_output_, lcd_output_info_, lcd_resolution);
61 76
62 // If there's no external output connected, disable the device before we try 77 // If there's no external output connected, disable the device before we try
63 // to set the screen resolution; otherwise xrandr will complain if we're 78 // to set the screen resolution; otherwise xrandr will complain if we're
64 // trying to set the screen to a smaller size than what the now-unplugged 79 // trying to set the screen to a smaller size than what the now-unplugged
65 // device was using. 80 // device was using.
66 if (external_resolution.empty()) 81 // Otherwise enable the external device if appropriate.
67 DisableDevice(external_output_->name); 82 if (external_resolution.name.empty())
83 DisableDevice(external_output_, external_output_info_);
84 else
85 SetDeviceResolution(external_output_, external_output_info_,
86 external_resolution);
68 87
69 // Set the fb to try to avoid the driver's "crtc has no fb" message. 88 // Set the fb resolution.
70 // Doing this before enabling the display reduces the likelihood of a
71 // visible "snap" when returning to the panel.
72 SetScreenResolution(screen_resolution); 89 SetScreenResolution(screen_resolution);
73 90
74 // Enable the LCD if appropriate. 91 if (!lcd_resolution.name.empty())
Daniel Erat 2011/03/25 03:39:02 i think that something went horribly wrong here an
marcheu 2011/03/25 17:39:42 Indeed. Oops.
75 if (!lcd_resolution.empty())
76 SetDeviceResolution(lcd_output_->name, lcd_resolution);
77 92
78 // Enable the external device if appropriate. 93 if (!external_resolution.name.empty())
79 if (!external_resolution.empty()) 94
80 SetDeviceResolution(external_output_->name, external_resolution); 95 // Now let the server go and sync all changes.
96 XUngrabServer(display_);
97 XSync(display_, False);
81 } 98 }
82 99
83 void MonitorReconfigureMain::DetermineOutputs() { 100 void MonitorReconfigureMain::DetermineOutputs() {
84 CHECK(screen_info_->noutput > 1) << "Expected at least two outputs"; 101 CHECK(screen_info_->noutput > 1) << "Expected at least two outputs";
85 XRROutputInfo* first_output =
86 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[0]);
87 XRROutputInfo* second_output =
88 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[1]);
89 102
90 if (strcmp(first_output->name, kLcdOutputName) == 0) { 103 RROutput first_output = screen_info_->outputs[0];
104 RROutput second_output = screen_info_->outputs[1];
105
106 XRROutputInfo* first_output_info =
107 XRRGetOutputInfo(display_, screen_info_, first_output);
108 XRROutputInfo* second_output_info =
109 XRRGetOutputInfo(display_, screen_info_, second_output);
110
111 if (strcmp(first_output_info->name, kLcdOutputName) == 0) {
91 lcd_output_ = first_output; 112 lcd_output_ = first_output;
113 lcd_output_info_ = first_output_info;
92 external_output_ = second_output; 114 external_output_ = second_output;
115 external_output_info_ = second_output_info;
Daniel Erat 2011/03/25 03:39:02 can you add a check earlier in this method to make
marcheu 2011/03/25 17:39:42 Done.
93 } else { 116 } else {
94 lcd_output_ = second_output; 117 lcd_output_ = second_output;
118 lcd_output_info_ = second_output_info;
95 external_output_ = first_output; 119 external_output_ = first_output;
120 external_output_info_ = first_output_info;
96 } 121 }
97 122
98 LOG(INFO) << "LCD name: " << lcd_output_->name; 123 LOG(INFO) << "LCD name: " << lcd_output_info_->name << " (xid "
99 for (int i = 0; i < lcd_output_->nmode; ++i) { 124 << lcd_output_ << ")";
100 XRRModeInfo* mode = mode_map_[lcd_output_->modes[i]]; 125 for (int i = 0; i < lcd_output_info_->nmode; ++i) {
101 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height; 126 XRRModeInfo* mode = mode_map_[lcd_output_info_->modes[i]];
127 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
128 << " (xid " << mode->id << ")";
102 } 129 }
103 130
104 LOG(INFO) << "External name: " << external_output_->name; 131 LOG(INFO) << "External name: " << external_output_info_->name
105 for (int i = 0; i < external_output_->nmode; ++i) { 132 << " (xid " << external_output_ << ")";
106 XRRModeInfo* mode = mode_map_[external_output_->modes[i]]; 133 for (int i = 0; i < external_output_info_->nmode; ++i) {
107 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height; 134 XRRModeInfo* mode = mode_map_[external_output_info_->modes[i]];
135 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height
136 << " (xid " << mode->id << ")";
108 } 137 }
109 } 138 }
110 139
111 bool MonitorReconfigureMain::IsExternalMonitorConnected() { 140 bool MonitorReconfigureMain::IsExternalMonitorConnected() {
112 return (external_output_->connection == RR_Connected); 141 return (external_output_info_->connection == RR_Connected);
113 } 142 }
114 143
115 void MonitorReconfigureMain::SortModesByResolution( 144 void MonitorReconfigureMain::SortModesByResolution(
116 const XRROutputInfo& output_info, 145 RROutput output,
117 vector<ResolutionSelector::Mode>* modes_out) { 146 vector<ResolutionSelector::Mode>* modes_out) {
118 modes_out->clear(); 147 modes_out->clear();
119 148
120 for (int i = 0; i < output_info.nmode; ++i) { 149 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_info_, output);
121 const XRRModeInfo* mode = mode_map_[output_info.modes[i]]; 150 for (int i = 0; i < output_info->nmode; ++i) {
151 const XRRModeInfo* mode = mode_map_[output_info->modes[i]];
122 DCHECK(mode); 152 DCHECK(mode);
153 LOG(INFO) << "Adding mode " << mode->width << " " << mode->height
154 << " (xid " << mode->id << ")";
123 modes_out->push_back( 155 modes_out->push_back(
124 ResolutionSelector::Mode(mode->width, mode->height, mode->name)); 156 ResolutionSelector::Mode(mode->width, mode->height, mode->name,
157 mode->id));
125 } 158 }
126 159
127 sort(modes_out->begin(), modes_out->end(), 160 sort(modes_out->begin(), modes_out->end(),
128 ResolutionSelector::ModeResolutionComparator()); 161 ResolutionSelector::ModeResolutionComparator());
162
163 XRRFreeOutputInfo(output_info);
129 } 164 }
130 165
131 bool MonitorReconfigureMain::SetDeviceResolution( 166 bool MonitorReconfigureMain::SetDeviceResolution(
132 const std::string& device_name, const std::string& resolution) { 167 RROutput output, const XRROutputInfo* output_info,
133 string command = StringPrintf("xrandr --output %s --mode %s", 168 const ResolutionSelector::Mode& resolution) {
134 device_name.c_str(), resolution.c_str()); 169 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtcs[0],
135 LOG(INFO) << "Running " << command.c_str(); 170 CurrentTime, 0, 0, resolution.id, RR_Rotate_0,
136 return system(command.c_str()) == 0; 171 &output, 1);
172 return (s == RRSetConfigSuccess);
137 } 173 }
138 174
139 bool MonitorReconfigureMain::SetScreenResolution( 175 bool MonitorReconfigureMain::SetScreenResolution(
140 const std::string& resolution) { 176 const ResolutionSelector::Mode& resolution) {
141 string command = StringPrintf("xrandr --fb %s", resolution.c_str()); 177 int screen = DefaultScreen(display_);
Daniel Erat 2011/03/25 03:39:02 this variable looks like it isn't being used
marcheu 2011/03/25 17:39:42 Done.
142 LOG(INFO) << "Running " << command.c_str(); 178 LOG(INFO) << "Setting resolution " << resolution.name.c_str() << " "
143 return system(command.c_str()) == 0; 179 << resolution.width << "x" << resolution.height;
180 XRRSetScreenSize(display_, window_,
181 resolution.width,
182 resolution.height,
183 resolution.width * kInchInMm / kScreenDpi,
184 resolution.height * kInchInMm / kScreenDpi);
185
186 return true;
144 } 187 }
145 188
146 bool MonitorReconfigureMain::DisableDevice(const std::string& device_name) { 189 bool MonitorReconfigureMain::DisableDevice(RROutput output,
147 string command = StringPrintf("xrandr --output %s --off", 190 const XRROutputInfo* output_info) {
148 device_name.c_str()); 191 if (!output_info->crtc)
149 LOG(INFO) << "Running " << command.c_str(); 192 return true;
150 return system(command.c_str()) == 0; 193 LOG(INFO) << "Disabling output " << output_info->name;
194 Status s = XRRSetCrtcConfig(display_, screen_info_, output_info->crtc,
195 CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0);
196 return (s == RRSetConfigSuccess);
151 } 197 }
152 198
153 } // end namespace monitor_reconfig 199 } // end namespace monitor_reconfig
154 200
155 int main(int argc, char** argv) { 201 int main(int argc, char** argv) {
156 CommandLine::Init(argc, argv); 202 CommandLine::Init(argc, argv);
157 logging::InitLogging(NULL, 203 logging::InitLogging(NULL,
158 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, 204 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
159 logging::DONT_LOCK_LOG_FILE, 205 logging::DONT_LOCK_LOG_FILE,
160 logging::APPEND_TO_OLD_LOG_FILE); 206 logging::APPEND_TO_OLD_LOG_FILE);
161 Display* display = XOpenDisplay(NULL); 207 Display* display = XOpenDisplay(NULL);
162 CHECK(display) << "Could not open display"; 208 CHECK(display) << "Could not open display";
163 209
164 Window window = RootWindow(display, DefaultScreen(display)); 210 Window window = RootWindow(display, DefaultScreen(display));
165 XRRScreenResources* screen_info = XRRGetScreenResources(display, window); 211 XRRScreenResources* screen_info = XRRGetScreenResources(display, window);
166 monitor_reconfig::MonitorReconfigureMain main_app(display, screen_info); 212 monitor_reconfig::MonitorReconfigureMain main_app(display, window,
213 screen_info);
167 main_app.Run(); 214 main_app.Run();
215 XRRFreeScreenResources(screen_info);
168 return 0; 216 return 0;
169 } 217 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698