Chromium Code Reviews| Index: monitor_reconfigure_main.cc |
| diff --git a/monitor_reconfigure_main.cc b/monitor_reconfigure_main.cc |
| index bfabae7731e44a35fdf073ac7cae248300a98b1f..a6974b8ff8ce30b34ee3b1d462074952bb6593bd 100644 |
| --- a/monitor_reconfigure_main.cc |
| +++ b/monitor_reconfigure_main.cc |
| @@ -20,13 +20,17 @@ using std::vector; |
| namespace monitor_reconfig { |
| static const char kLcdOutputName[] = "LVDS1"; |
| +static const float kScreenDpi = 96.0; |
| +static const float kInchInMm = 25.4; |
| MonitorReconfigureMain::MonitorReconfigureMain(Display* display, |
| + Window window, |
| XRRScreenResources* screen_info) |
| : display_(display), |
| + window_(window), |
| screen_info_(screen_info), |
| - lcd_output_(NULL), |
| - external_output_(NULL) { |
| + lcd_output_(0), |
| + external_output_(0) { |
| for (int i = 0; i < screen_info_->nmode; ++i) { |
| XRRModeInfo* current_mode = &screen_info_->modes[i]; |
| mode_map_[current_mode->id] = current_mode; |
| @@ -36,92 +40,118 @@ MonitorReconfigureMain::MonitorReconfigureMain(Display* display, |
| void MonitorReconfigureMain::Run() { |
| vector<ResolutionSelector::Mode> lcd_modes; |
| - SortModesByResolution(*lcd_output_, &lcd_modes); |
| + SortModesByResolution(lcd_output_, &lcd_modes); |
| DCHECK(!lcd_modes.empty()); |
| vector<ResolutionSelector::Mode> external_modes; |
| if (IsExternalMonitorConnected()) { |
| - SortModesByResolution(*external_output_, &external_modes); |
| + SortModesByResolution(external_output_, &external_modes); |
| DCHECK(!external_modes.empty()); |
| } |
| ResolutionSelector selector; |
| - string lcd_resolution, external_resolution, screen_resolution; |
| + ResolutionSelector::Mode lcd_resolution, |
| + external_resolution, |
|
Daniel Erat
2011/03/24 23:02:11
make each of these be declared in a separate state
|
| + screen_resolution; |
| CHECK(selector.FindBestResolutions(lcd_modes, |
| external_modes, |
| &lcd_resolution, |
| &external_resolution, |
| &screen_resolution)); |
| - CHECK(!lcd_resolution.empty() || !external_resolution.empty()); |
| + CHECK(!lcd_resolution.name.empty() || !external_resolution.name.empty()); |
| + |
| + // Grab the server during mode changes. |
| + XGrabServer (display_); |
|
Daniel Erat
2011/03/24 23:02:11
no spaces between function names and opening paren
|
| // Disable the LCD if we were told to do so (because we're using a higher |
| // resolution that'd be clipped on the LCD). |
| - if (lcd_resolution.empty()) |
| - DisableDevice(lcd_output_->name); |
| + // Otherwise enable the LCD if appropriate. |
| + if (lcd_resolution.name.empty()) |
| + DisableDevice(lcd_output_, lcd_output_info_); |
| + else |
| + SetDeviceResolution(lcd_output_, lcd_output_info_, lcd_resolution); |
| // If there's no external output connected, disable the device before we try |
| // to set the screen resolution; otherwise xrandr will complain if we're |
| // trying to set the screen to a smaller size than what the now-unplugged |
| // device was using. |
| - if (external_resolution.empty()) |
| - DisableDevice(external_output_->name); |
| - |
| - // Set the fb to try to avoid the driver's "crtc has no fb" message. |
| - // Doing this before enabling the display reduces the likelihood of a |
| - // visible "snap" when returning to the panel. |
| + // Otherwise enable the external device if appropriate. |
| + if (external_resolution.name.empty()) |
| + DisableDevice(external_output_, external_output_info_); |
| + else |
| + SetDeviceResolution(external_output_, external_output_info_, |
| + external_resolution); |
| + |
| + // Set the fb resolution. |
| SetScreenResolution(screen_resolution); |
| - // Enable the LCD if appropriate. |
| - if (!lcd_resolution.empty()) |
| - SetDeviceResolution(lcd_output_->name, lcd_resolution); |
| + if (!lcd_resolution.name.empty()) |
| + |
| + if (!external_resolution.name.empty()) |
| - // Enable the external device if appropriate. |
| - if (!external_resolution.empty()) |
| - SetDeviceResolution(external_output_->name, external_resolution); |
| + // Now let the server go and sync all changes. |
| + XUngrabServer (display_); |
| + XSync (display_, False); |
| } |
| void MonitorReconfigureMain::DetermineOutputs() { |
| CHECK(screen_info_->noutput > 1) << "Expected at least two outputs"; |
| - XRROutputInfo* first_output = |
| - XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[0]); |
| - XRROutputInfo* second_output = |
| - XRRGetOutputInfo(display_, screen_info_, screen_info_->outputs[1]); |
| - if (strcmp(first_output->name, kLcdOutputName) == 0) { |
| + RROutput first_output = screen_info_->outputs[0]; |
| + RROutput second_output = screen_info_->outputs[1]; |
| + |
| + XRROutputInfo* first_output_info = |
| + XRRGetOutputInfo(display_, screen_info_, first_output); |
| + XRROutputInfo* second_output_info = |
| + XRRGetOutputInfo(display_, screen_info_, second_output); |
| + |
| + if (strcmp(first_output_info->name, kLcdOutputName) == 0) { |
| lcd_output_ = first_output; |
| + lcd_output_info_ = first_output_info; |
| external_output_ = second_output; |
| + external_output_info_ = second_output_info; |
| } else { |
| lcd_output_ = second_output; |
| + lcd_output_info_ = second_output_info; |
| external_output_ = first_output; |
| + external_output_info_ = first_output_info; |
| } |
| - LOG(INFO) << "LCD name: " << lcd_output_->name; |
| - for (int i = 0; i < lcd_output_->nmode; ++i) { |
| - XRRModeInfo* mode = mode_map_[lcd_output_->modes[i]]; |
| - LOG(INFO) << " Mode: " << mode->width << "x" << mode->height; |
| + LOG(INFO) << "LCD name: " << lcd_output_info_->name << " (xid " |
| + << lcd_output_ << ")"; |
| + for (int i = 0; i < lcd_output_info_->nmode; ++i) { |
| + XRRModeInfo* mode = mode_map_[lcd_output_info_->modes[i]]; |
| + LOG(INFO) << " Mode: " << mode->width << "x" << mode->height |
| + << " (xid " << mode->id << ")"; |
| } |
| - LOG(INFO) << "External name: " << external_output_->name; |
| - for (int i = 0; i < external_output_->nmode; ++i) { |
| - XRRModeInfo* mode = mode_map_[external_output_->modes[i]]; |
| - LOG(INFO) << " Mode: " << mode->width << "x" << mode->height; |
| + LOG(INFO) << "External name: " << external_output_info_->name |
| + << " (xid " << external_output_ << ")"; |
| + for (int i = 0; i < external_output_info_->nmode; ++i) { |
| + XRRModeInfo* mode = mode_map_[external_output_info_->modes[i]]; |
| + LOG(INFO) << " Mode: " << mode->width << "x" << mode->height |
| + << " (xid " << mode->id << ")"; |
| } |
| } |
| bool MonitorReconfigureMain::IsExternalMonitorConnected() { |
| - return (external_output_->connection == RR_Connected); |
| + return (external_output_info_->connection == RR_Connected); |
| } |
| void MonitorReconfigureMain::SortModesByResolution( |
| - const XRROutputInfo& output_info, |
| + const RROutput output, |
| vector<ResolutionSelector::Mode>* modes_out) { |
| modes_out->clear(); |
| - for (int i = 0; i < output_info.nmode; ++i) { |
| - const XRRModeInfo* mode = mode_map_[output_info.modes[i]]; |
| + XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_info_, output); |
| + for (int i = 0; i < output_info->nmode; ++i) { |
| + const XRRModeInfo* mode = mode_map_[output_info->modes[i]]; |
| DCHECK(mode); |
| + LOG(INFO) << "Adding mode " << mode->width << " " << mode->height |
| + << " (xid " << mode->id << ")"; |
| modes_out->push_back( |
| - ResolutionSelector::Mode(mode->width, mode->height, mode->name)); |
| + ResolutionSelector::Mode(mode->width, mode->height, mode->name, |
| + mode->id)); |
| } |
| sort(modes_out->begin(), modes_out->end(), |
| @@ -129,25 +159,38 @@ void MonitorReconfigureMain::SortModesByResolution( |
| } |
| bool MonitorReconfigureMain::SetDeviceResolution( |
| - const std::string& device_name, const std::string& resolution) { |
| - string command = StringPrintf("xrandr --output %s --mode %s", |
| - device_name.c_str(), resolution.c_str()); |
| - LOG(INFO) << "Running " << command.c_str(); |
| - return system(command.c_str()) == 0; |
| + const RROutput output, const XRROutputInfo* output_info, |
| + const ResolutionSelector::Mode resolution) { |
| + RROutput o = output; |
|
Daniel Erat
2011/03/24 23:02:11
why do you need to make a copy here?
marcheu
2011/03/24 23:17:53
XRRSetCrtcConfig has a non-const RROutput* paramet
Daniel Erat
2011/03/24 23:39:46
How about const_cast?
|
| + Status s = XRRSetCrtcConfig (display_, screen_info_, output_info->crtcs[0], |
| + CurrentTime, 0, 0, resolution.id, RR_Rotate_0, |
| + &o, 1); |
| + return (s == RRSetConfigSuccess); |
| } |
| bool MonitorReconfigureMain::SetScreenResolution( |
| - const std::string& resolution) { |
| - string command = StringPrintf("xrandr --fb %s", resolution.c_str()); |
| - LOG(INFO) << "Running " << command.c_str(); |
| - return system(command.c_str()) == 0; |
| + const ResolutionSelector::Mode resolution) { |
| + int screen = DefaultScreen(display_); |
| + LOG(INFO) << "Setting resolution " << resolution.name.c_str() << " " |
| + << resolution.width << "x" << resolution.height; |
| + XRRSetScreenSize (display_, window_, |
| + resolution.width, |
| + resolution.height, |
| + resolution.width * kInchInMm / kScreenDpi, |
| + resolution.height * kInchInMm / kScreenDpi |
| + ); |
|
Daniel Erat
2011/03/24 23:02:11
move this to the end of the previous line
|
| + |
| + return true; |
| } |
| -bool MonitorReconfigureMain::DisableDevice(const std::string& device_name) { |
| - string command = StringPrintf("xrandr --output %s --off", |
| - device_name.c_str()); |
| - LOG(INFO) << "Running " << command.c_str(); |
| - return system(command.c_str()) == 0; |
| +bool MonitorReconfigureMain::DisableDevice(const RROutput output, |
| + const XRROutputInfo* output_info) { |
| + if (!output_info->crtc) |
| + return true; |
| + LOG(INFO) << "Disabling output " << output_info->name; |
| + Status s = XRRSetCrtcConfig (display_, screen_info_, output_info->crtc, |
| + CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0); |
| + return (s == RRSetConfigSuccess); |
| } |
| } // end namespace monitor_reconfig |
| @@ -163,7 +206,8 @@ int main(int argc, char** argv) { |
| Window window = RootWindow(display, DefaultScreen(display)); |
| XRRScreenResources* screen_info = XRRGetScreenResources(display, window); |
| - monitor_reconfig::MonitorReconfigureMain main_app(display, screen_info); |
| + monitor_reconfig::MonitorReconfigureMain main_app(display, window, |
| + screen_info); |
| main_app.Run(); |
| return 0; |
| } |