diff options
author | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-20 19:31:09 +0000 |
---|---|---|
committer | jamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-20 19:31:09 +0000 |
commit | 274f00dcade3160d4edc874dee612a57a801e2ef (patch) | |
tree | eb28d56120e083ae8a0f368709f991eedab9444f | |
parent | 3975f111b396e195babfeb76b6f3d7dc0eb8d27c (diff) | |
download | chromium_src-274f00dcade3160d4edc874dee612a57a801e2ef.zip chromium_src-274f00dcade3160d4edc874dee612a57a801e2ef.tar.gz chromium_src-274f00dcade3160d4edc874dee612a57a801e2ef.tar.bz2 |
Mac resize-to-client implementation.
BUG=154891
Review URL: https://chromiumcodereview.appspot.com/11086089
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163180 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | remoting/host/desktop_resizer_mac.cc | 145 |
1 files changed, 127 insertions, 18 deletions
diff --git a/remoting/host/desktop_resizer_mac.cc b/remoting/host/desktop_resizer_mac.cc index 5d23ec6..d1d6c2c 100644 --- a/remoting/host/desktop_resizer_mac.cc +++ b/remoting/host/desktop_resizer_mac.cc @@ -4,39 +4,148 @@ #include "remoting/host/desktop_resizer.h" +#include <Carbon/Carbon.h> + +#include "base/basictypes.h" #include "base/logging.h" +#include "base/mac/foundation_util.h" +#include "base/mac/mac_util.h" +#include "base/mac/scoped_cftyperef.h" namespace remoting { -namespace { class DesktopResizerMac : public DesktopResizer { public: - DesktopResizerMac() { - } + DesktopResizerMac(); + + // DesktopResizer interface + virtual SkISize GetCurrentSize() OVERRIDE; + virtual std::list<SkISize> GetSupportedSizes( + const SkISize& preferred) OVERRIDE; + virtual void SetSize(const SkISize& size) OVERRIDE; + virtual void RestoreSize(const SkISize& original) OVERRIDE; + + private: + // If there is a single display, get its id and return true, otherwise return + // false. We don't currently support resize-to-client on multi-monitor Macs. + bool GetSoleDisplayId(CGDirectDisplayID* display); + + void GetSupportedModesAndSizes( + base::mac::ScopedCFTypeRef<CFMutableArrayRef>* modes, + std::list<SkISize>* sizes); - virtual SkISize GetCurrentSize() OVERRIDE { - NOTIMPLEMENTED(); - return SkISize::Make(0, 0); + DISALLOW_COPY_AND_ASSIGN(DesktopResizerMac); +}; + +DesktopResizerMac::DesktopResizerMac() {} + +SkISize DesktopResizerMac::GetCurrentSize() { + CGDirectDisplayID display; + if (!base::mac::IsOSSnowLeopard() && GetSoleDisplayId(&display)) { + CGRect rect = CGDisplayBounds(display); + return SkISize::Make(rect.size.width, rect.size.height); } + return SkISize::Make(0, 0); +} - virtual std::list<SkISize> GetSupportedSizes( - const SkISize& preferred) OVERRIDE { - NOTIMPLEMENTED(); - return std::list<SkISize>(); +std::list<SkISize> DesktopResizerMac::GetSupportedSizes( + const SkISize& preferred) { + base::mac::ScopedCFTypeRef<CFMutableArrayRef> modes; + std::list<SkISize> sizes; + GetSupportedModesAndSizes(&modes, &sizes); + return sizes; +} + +void DesktopResizerMac::SetSize(const SkISize& size) { + CGDirectDisplayID display; + if (base::mac::IsOSSnowLeopard() || !GetSoleDisplayId(&display)) { + return; } - virtual void SetSize(const SkISize& size) OVERRIDE { - NOTIMPLEMENTED(); + base::mac::ScopedCFTypeRef<CFMutableArrayRef> modes; + std::list<SkISize> sizes; + GetSupportedModesAndSizes(&modes, &sizes); + // There may be many modes with the requested size. Pick the one with the + // highest color depth. + int index = 0, best_depth = 0; + CGDisplayModeRef best_mode = NULL; + for (std::list<SkISize>::const_iterator i = sizes.begin(); i != sizes.end(); + ++i, ++index) { + if (*i == size) { + CGDisplayModeRef mode = const_cast<CGDisplayModeRef>( + static_cast<const CGDisplayMode*>( + CFArrayGetValueAtIndex(modes, index))); + int depth = 0; + base::mac::ScopedCFTypeRef<CFStringRef> encoding( + CGDisplayModeCopyPixelEncoding(mode)); + if (CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 32; + } else if (CFStringCompare( + encoding, CFSTR(IO16BitDirectPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 16; + } else if(CFStringCompare( + encoding, CFSTR(IO8BitIndexedPixels), + kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + depth = 8; + } + if (depth > best_depth) { + best_depth = depth; + best_mode = mode; + } + } + } + if (best_mode) { + LOG(INFO) << "Changing mode to " << best_mode << " (" << size.width() + << "x" << size.height() << "x" << best_depth << ")"; + CGDisplaySetDisplayMode(display, best_mode, NULL); } +} + +void DesktopResizerMac::RestoreSize(const SkISize& original) { + SetSize(original); +} - virtual void RestoreSize(const SkISize& original) OVERRIDE { - NOTIMPLEMENTED(); +void DesktopResizerMac::GetSupportedModesAndSizes( + base::mac::ScopedCFTypeRef<CFMutableArrayRef>* modes, + std::list<SkISize>* sizes) { + CGDirectDisplayID display; + if (GetSoleDisplayId(&display)) { + base::mac::ScopedCFTypeRef<CFArrayRef> + all_modes(CGDisplayCopyAllDisplayModes(display, NULL)); + modes->reset(CFArrayCreateMutableCopy(NULL, 0, all_modes)); + CFIndex count = CFArrayGetCount(*modes); + for (CFIndex i = 0; i < count; ++i) { + CGDisplayModeRef mode = const_cast<CGDisplayModeRef>( + static_cast<const CGDisplayMode*>( + CFArrayGetValueAtIndex(*modes, i))); + if (CGDisplayModeIsUsableForDesktopGUI(mode)) { + SkISize size = SkISize::Make(CGDisplayModeGetWidth(mode), + CGDisplayModeGetHeight(mode)); + sizes->push_back(size); + } else { + CFArrayRemoveValueAtIndex(*modes, i); + --count; + --i; + } + } } +} - private: - DISALLOW_COPY_AND_ASSIGN(DesktopResizerMac); -}; -} // namespace +bool DesktopResizerMac::GetSoleDisplayId(CGDirectDisplayID* display) { + // This code only supports a single display, but allocates space for two + // to allow the multi-monitor case to be detected. + CGDirectDisplayID displays[2]; + uint32_t num_displays; + CGError err = CGGetActiveDisplayList(arraysize(displays), + displays, &num_displays); + if (err != kCGErrorSuccess || num_displays != 1) { + return false; + } + *display = displays[0]; + return true; +} scoped_ptr<DesktopResizer> DesktopResizer::Create() { return scoped_ptr<DesktopResizer>(new DesktopResizerMac); |