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

Side by Side Diff: src/platform/monitor_reconfig/monitor_reconfigure_main.cc

Issue 1646010: monitor_reconfigure: Try to improve resolution selection. (Closed)
Patch Set: apply review feedback Created 10 years, 8 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
« no previous file with comments | « src/platform/monitor_reconfig/monitor_reconfigure_main.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2009 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 <cstdio> 8 #include <cstdio>
8 #include <cstdlib> 9 #include <cstdlib>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/string_util.h"
11 13
12 using std::map; 14 using std::map;
15 using std::sort;
16 using std::string;
17 using std::vector;
13 18
14 namespace monitor_reconfig { 19 namespace monitor_reconfig {
15 20
16 MonitorReconfigureMain::MonitorReconfigureMain(Display* display, 21 MonitorReconfigureMain::MonitorReconfigureMain(Display* display,
17 XRRScreenResources* screen_info) 22 XRRScreenResources* screen_info)
18 : display_(display), 23 : display_(display),
19 screen_info_(screen_info) { 24 screen_info_(screen_info),
25 lcd_output_(NULL),
26 external_output_(NULL) {
20 for (int i = 0; i < screen_info_->nmode; ++i) { 27 for (int i = 0; i < screen_info_->nmode; ++i) {
21 XRRModeInfo* current_mode = &screen_info_->modes[i]; 28 XRRModeInfo* current_mode = &screen_info_->modes[i];
22 mode_map_[current_mode->id] = current_mode; 29 mode_map_[current_mode->id] = current_mode;
23 } 30 }
24 DetermineOutputs(); 31 DetermineOutputs();
25 } 32 }
26 33
27 void MonitorReconfigureMain::DetermineOutputs() { 34 void MonitorReconfigureMain::DetermineOutputs() {
28 XRROutputInfo* first_output = 35 XRROutputInfo* first_output =
29 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[0]); 36 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[0]);
30 XRROutputInfo* second_output = 37 XRROutputInfo* second_output =
31 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[1]); 38 XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[1]);
32 39
33 static const char* kNotebookOutputName = "LVDS1"; 40 static const char* kLcdOutputName = "LVDS1";
34 if (strcmp(first_output->name, kNotebookOutputName) == 0) { 41 if (strcmp(first_output->name, kLcdOutputName) == 0) {
35 notebook_output_ = first_output; 42 lcd_output_ = first_output;
36 external_output_ = second_output; 43 external_output_ = second_output;
37 } else { 44 } else {
38 notebook_output_ = second_output; 45 lcd_output_ = second_output;
39 external_output_ = first_output; 46 external_output_ = first_output;
40 } 47 }
41 48
42 for (int i = 0; i < notebook_output_->nmode; ++i) { 49 LOG(INFO) << "LCD name: " << lcd_output_->name;
43 XRRModeInfo* mode = mode_map_[notebook_output_->modes[i]]; 50 for (int i = 0; i < lcd_output_->nmode; ++i) {
44 LOG(INFO) << "notebook mode: " << mode->width << "x" << mode->height; 51 XRRModeInfo* mode = mode_map_[lcd_output_->modes[i]];
52 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height;
45 } 53 }
54
55 LOG(INFO) << "External name: " << external_output_->name;
46 for (int i = 0; i < external_output_->nmode; ++i) { 56 for (int i = 0; i < external_output_->nmode; ++i) {
47 XRRModeInfo* mode = mode_map_[external_output_->modes[i]]; 57 XRRModeInfo* mode = mode_map_[external_output_->modes[i]];
48 LOG(INFO) << "external mode: " << mode->width << "x" << mode->height; 58 LOG(INFO) << " Mode: " << mode->width << "x" << mode->height;
49 } 59 }
50 } 60 }
51 61
52
53 XRRModeInfo* MonitorReconfigureMain::FindMaxResolution(XRROutputInfo* output) {
54 XRRModeInfo* mode_return = NULL;
55 for (int i = 0; i < output->nmode; ++i) {
56 XRRModeInfo* current_mode = mode_map_[output->modes[i]];
57 if (mode_return == NULL) {
58 mode_return = current_mode;
59 } else {
60 int n_size = mode_return->height * mode_return->width;
61 int c_size = current_mode->height * current_mode->width;
62 if (c_size > n_size) {
63 mode_return = current_mode;
64 }
65 }
66 }
67 return mode_return;
68 }
69
70 bool MonitorReconfigureMain::IsEqual(XRRModeInfo* one, XRRModeInfo* two) {
71 return (one->height * one->width) == (two->height * two->width);
72 }
73
74 bool MonitorReconfigureMain::IsBiggerOrEqual(XRRModeInfo* target,
75 XRRModeInfo* screen) {
76 return ((target->width >= screen->width) &&
77 (target->height >= screen->height));
78 }
79
80 bool MonitorReconfigureMain::IsBetterMatching(XRRModeInfo* target,
81 XRRModeInfo* to_match,
82 XRRModeInfo* previous_best) {
83 if (IsEqual(previous_best, to_match))
84 return false;
85 // If the current will have some of the display cut off
86 // and the new choice doesn't, choose the new one
87 if ((!IsBiggerOrEqual(previous_best, to_match)) &&
88 (IsBiggerOrEqual(target, to_match))) {
89 return true;
90 // If the current one isn't cropped and the new one would
91 // get cropped
92 } else if (IsBiggerOrEqual(previous_best, to_match) &&
93 !IsBiggerOrEqual(target, to_match)) {
94 return false;
95 // Case if the current is bigger than the matching but the new target falls
96 // between the current and the matching (so it's closer to the matching)
97 } else if (IsBiggerOrEqual(previous_best, to_match)) {
98 return !IsBiggerOrEqual(target, previous_best);
99 } else {
100 // Final case, we know the current is smaller than the matching
101 // We just need to check if the new will bring us closer to the matching
102 return IsBiggerOrEqual(target, previous_best);
103 }
104 }
105
106 XRRModeInfo* MonitorReconfigureMain::FindBestMatchingResolution(
107 XRRModeInfo* matching_mode) {
108 // Need a min mode to increase from
109 XRRModeInfo min_mode;
110 min_mode.height = 0;
111 min_mode.width = 0;
112 XRRModeInfo* best_mode = &min_mode;
113 // Match horizontal if notebook is wider, o/w match vertical
114 for (int i = 0; i < external_output_->nmode; ++i) {
115 XRRModeInfo* current_mode = mode_map_[external_output_->modes[i]];
116 if (IsBetterMatching(current_mode, matching_mode, best_mode))
117 best_mode = current_mode;
118 }
119 if (best_mode == &min_mode)
120 best_mode = NULL;
121 return best_mode;
122 }
123
124 void MonitorReconfigureMain::SetResolutions(XRRModeInfo* notebook_mode,
125 XRRModeInfo* external_mode,
126 XRRModeInfo* overall_screen_size) {
127 // We use xrandr script to set modes
128 char buffer[512];
129 snprintf(buffer, sizeof(buffer), "xrandr --output %s --mode %s",
130 external_output_->name, external_mode->name);
131 system(buffer);
132 snprintf(buffer, sizeof(buffer), "xrandr --output %s --mode %s",
133 notebook_output_->name, notebook_mode->name);
134 system(buffer);
135 snprintf(buffer, sizeof(buffer), "xrandr --fb %s", overall_screen_size->name);
136 system(buffer);
137 }
138
139 void MonitorReconfigureMain::Run() {
140 if (!IsExternalMonitorConnected())
141 return;
142
143 // Find the max resolution for the notebook
144 XRRModeInfo* notebook_mode = FindMaxResolution(notebook_output_);
145 // Find the best mode for external output relative to above mode
146 XRRModeInfo* external_mode = FindBestMatchingResolution(notebook_mode);
147 // Set the resolutions accordingly
148 SetResolutions(notebook_mode, external_mode, notebook_mode);
149 }
150
151 bool MonitorReconfigureMain::IsExternalMonitorConnected() { 62 bool MonitorReconfigureMain::IsExternalMonitorConnected() {
152 return (external_output_->connection == RR_Connected); 63 return (external_output_->connection == RR_Connected);
153 } 64 }
154 65
66 void MonitorReconfigureMain::SortModesByResolution(
67 const XRROutputInfo& output_info, vector<XRRModeInfo*>* modes_out) {
68 modes_out->clear();
69 for (int i = 0; i < output_info.nmode; ++i)
70 modes_out->push_back(mode_map_[output_info.modes[i]]);
71 sort(modes_out->begin(), modes_out->end(), ModeResolutionComparator());
72 }
73
74 bool MonitorReconfigureMain::FindBestResolutions(
75 string* lcd_resolution,
76 string* external_resolution,
77 string* screen_resolution) {
78 DCHECK(lcd_resolution);
79 DCHECK(external_resolution);
80 DCHECK(screen_resolution);
81
82 vector<XRRModeInfo*> lcd_modes, external_modes;
83 SortModesByResolution(*lcd_output_, &lcd_modes);
84 SortModesByResolution(*external_output_, &external_modes);
85 DCHECK(!lcd_modes.empty());
86 DCHECK(!external_modes.empty());
87
88 if ((lcd_modes[0]->width * lcd_modes[0]->height) >=
89 (external_modes[0]->width * external_modes[0]->height)) {
90 return FindNearestResolutions(
91 lcd_modes, external_modes,
92 lcd_resolution, external_resolution, screen_resolution);
93 } else {
94 return FindNearestResolutions(
95 external_modes, lcd_modes,
96 external_resolution, lcd_resolution, screen_resolution);
97 }
98 }
99
100 bool MonitorReconfigureMain::FindNearestResolutions(
101 const vector<XRRModeInfo*>& larger_device_modes,
102 const vector<XRRModeInfo*>& smaller_device_modes,
103 string* larger_resolution,
104 string* smaller_resolution,
105 string* screen_resolution) {
106 DCHECK(larger_resolution);
107 DCHECK(smaller_resolution);
108
109 // Start with the best that the smaller device has to offer.
110 smaller_resolution->assign(smaller_device_modes[0]->name);
111 *screen_resolution = *smaller_resolution;
112 int smaller_width = smaller_device_modes[0]->width;
113 int smaller_height = smaller_device_modes[0]->height;
114
115 for (vector<XRRModeInfo*>::const_reverse_iterator it =
116 larger_device_modes.rbegin();
117 it != larger_device_modes.rend(); ++it) {
118 if ((*it)->width >= smaller_width && (*it)->height >= smaller_height) {
119 larger_resolution->assign((*it)->name);
120 return true;
121 }
122 }
123
124 LOG(WARNING) << "Failed to find a resolution from larger device "
125 << "exceeding chosen resolution from smaller device ("
126 << *smaller_resolution << ")";
127 return false;
128 }
129
130 bool MonitorReconfigureMain::SetDeviceResolution(
131 const std::string& device_name, const std::string& resolution) {
132 string command = StringPrintf("xrandr --output %s --mode %s",
133 device_name.c_str(), resolution.c_str());
134 LOG(INFO) << "Running " << command.c_str();
135 return system(command.c_str()) == 0;
136 }
137
138 bool MonitorReconfigureMain::SetScreenResolution(
139 const std::string& resolution) {
140 string command = StringPrintf("xrandr --fb %s", resolution.c_str());
141 LOG(INFO) << "Running " << command.c_str();
142 return system(command.c_str()) == 0;
143 }
144
145 void MonitorReconfigureMain::Run() {
146 // If there's no external monitor connected, just use the highest resolution
147 // supported by the LCD.
148 if (!IsExternalMonitorConnected()) {
149 LOG(INFO) << "No external monitor connected; using max LCD resolution";
150 vector<XRRModeInfo*> lcd_modes;
151 SortModesByResolution(*lcd_output_, &lcd_modes);
152 CHECK(!lcd_modes.empty());
153 SetDeviceResolution(lcd_output_->name, lcd_modes[0]->name);
154 SetScreenResolution(lcd_modes[0]->name);
155 return;
156 }
157
158 string lcd_resolution, external_resolution, screen_resolution;
159 CHECK(FindBestResolutions(&lcd_resolution,
160 &external_resolution,
161 &screen_resolution));
162 SetDeviceResolution(lcd_output_->name, lcd_resolution);
163 SetDeviceResolution(external_output_->name, external_resolution);
164 SetScreenResolution(screen_resolution);
165 }
166
155 } // end namespace monitor_reconfig 167 } // end namespace monitor_reconfig
156 168
157 int main(int argc, char** argv) { 169 int main(int argc, char** argv) {
158 Display* display = XOpenDisplay(NULL); 170 Display* display = XOpenDisplay(NULL);
159 CHECK(display) << "Could not open display"; 171 CHECK(display) << "Could not open display";
160 172
161 Window window = RootWindow(display, DefaultScreen(display)); 173 Window window = RootWindow(display, DefaultScreen(display));
162 XRRScreenResources* screen_info = XRRGetScreenResources(display, window); 174 XRRScreenResources* screen_info = XRRGetScreenResources(display, window);
163 monitor_reconfig::MonitorReconfigureMain main_app(display, screen_info); 175 monitor_reconfig::MonitorReconfigureMain main_app(display, screen_info);
164 176
165 main_app.Run(); 177 main_app.Run();
166 return 0; 178 return 0;
167 } 179 }
OLDNEW
« no previous file with comments | « src/platform/monitor_reconfig/monitor_reconfigure_main.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698