diff options
Diffstat (limited to 'chromeos/monitor/output_configurator.h')
-rw-r--r-- | chromeos/monitor/output_configurator.h | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/chromeos/monitor/output_configurator.h b/chromeos/monitor/output_configurator.h new file mode 100644 index 0000000..b59474f2 --- /dev/null +++ b/chromeos/monitor/output_configurator.h @@ -0,0 +1,145 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_MONITOR_OUTPUT_CONFIGURATOR_H_ +#define CHROMEOS_MONITOR_OUTPUT_CONFIGURATOR_H_ +#pragma once + +#include <X11/Xlib.h> +#include <X11/extensions/dpms.h> +#include <X11/extensions/Xrandr.h> + +// Xlib defines Status as int which causes our include of dbus/bus.h to fail +// when it tries to name an enum Status. Thus, we need to undefine it (note +// that this will cause a problem if code needs to use the Status type). +// RootWindow causes similar problems in that there is a Chromium type with that +// name. +#undef Status +#undef RootWindow + +#include "base/basictypes.h" +#include "base/event_types.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "chromeos/chromeos_export.h" + +namespace chromeos { + +// The information we need to cache from an output to implement operations such +// as power state but also to eliminate duplicate operations within a given +// action (determining which CRTC to use for a given output, for example). +struct CachedOutputDescription { + RROutput output; + RRCrtc crtc; + RRMode mirror_mode; + RRMode ideal_mode; + int x; + int y; + bool is_connected; + bool is_powered_on; + bool is_internal; +}; + +// Used to describe the state of a multi-monitor configuration. +enum State { + STATE_INVALID, + STATE_HEADLESS, + STATE_SINGLE, + STATE_DUAL_MIRROR, + STATE_DUAL_PRIMARY_ONLY, + STATE_DUAL_SECONDARY_ONLY, +}; + +// This class interacts directly with the underlying Xrandr API to manipulate +// CTRCs and Outputs. It will likely grow more state, over time, or expose +// Output info in other ways as more of the Chrome display code grows up around +// it. +class CHROMEOS_EXPORT OutputConfigurator : public MessageLoop::Dispatcher { + public: + OutputConfigurator(); + virtual ~OutputConfigurator(); + + // Called when the user hits ctrl-F4 to request a display mode change. + // This method should only return false if it was called in a single-head or + // headless mode. + bool CycleDisplayMode(); + + // Called when powerd notifies us that some set of displays should be turned + // on or off. This requires enabling or disabling the CRTC associated with + // the display(s) in question so that the low power state is engaged. + bool ScreenPowerSet(bool power_on, bool all_displays); + + // Called when an RRNotify event is received. The implementation is + // interested in the cases of RRNotify events which correspond to output + // add/remove events. Note that Output add/remove events are sent in response + // to our own reconfiguration operations so spurious events are common. + // Spurious events will have no effect. + virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; + + private: + // Updates |output_count_|, |output_cache_|, |mirror_supported_|, + // |primary_output_index_|, and |secondary_output_index_| with new data. + // Returns true if the update succeeded or false if it was skipped since no + // actual change was observed. + // Note that |output_state_| is not updated by this call. + bool TryRecacheOutputs(Display* display, XRRScreenResources* screen); + + // Uses the data stored in |output_cache_| and the given |new_state| to + // configure the Xrandr interface and then updates |output_state_| to reflect + // the new state. + void UpdateCacheAndXrandrToState(Display* display, + XRRScreenResources* screen, + Window window, + State new_state); + + // A helper to re-cache instance variable state and transition into the + // appropriate default state for the observed displays. + bool RecacheAndUseDefaultState(); + + // Checks the |primary_output_index_|, |secondary_output_index_|, and + // |mirror_supported_| to see how many displays are currently connected and + // returns the state which is most appropriate as a default state for those + // displays. + State GetDefaultState() const; + + // This is detected by the constructor to determine whether or not we should + // be enabled. If we aren't running on ChromeOS, we can't assume that the + // Xrandr X11 extension is supported. + // If this flag is set to false, any attempts to change the output + // configuration to immediately fail without changing the state. + bool is_running_on_chrome_os_; + + // The number of outputs in the output_cache_ array. + int output_count_; + + // The list of cached output descriptions (|output_count_| elements long). + scoped_array<CachedOutputDescription> output_cache_; + + // True if |output_cache_| describes a permutation of outputs which support a + // mirrored device mode. + bool mirror_supported_; + + // The index of the primary connected output in |output_cache_|. -1 if there + // is no primary output. This implies the machine currently has no outputs. + int primary_output_index_; + + // The index of the secondary connected output in |output_cache_|. -1 if + // there is no secondary output. This implies the machine currently has one + // output. + int secondary_output_index_; + + // The base of the event numbers used to represent XRandr events used in + // decoding events regarding output add/remove. + int xrandr_event_base_; + + // The display state as derived from the outputs observed in |output_cache_|. + // This is used for rotating display modes. + State output_state_; + + DISALLOW_COPY_AND_ASSIGN(OutputConfigurator); +}; + +} // namespace chromeos + +#endif // CHROMEOS_MONITOR_OUTPUT_CONFIGURATOR_H_ |