summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-20 19:31:09 +0000
committerjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-20 19:31:09 +0000
commit274f00dcade3160d4edc874dee612a57a801e2ef (patch)
treeeb28d56120e083ae8a0f368709f991eedab9444f
parent3975f111b396e195babfeb76b6f3d7dc0eb8d27c (diff)
downloadchromium_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.cc145
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);