summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-23 20:58:14 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-23 20:58:14 +0000
commit41c19234e2f62eba64776f3d4f46f484c2a5c440 (patch)
tree7f28e753a25ff8217665141af16165b427f79cb5
parent7dcf0f549ed34d19057612eb55fb6b59c3582229 (diff)
downloadchromium_src-41c19234e2f62eba64776f3d4f46f484c2a5c440.zip
chromium_src-41c19234e2f62eba64776f3d4f46f484c2a5c440.tar.gz
chromium_src-41c19234e2f62eba64776f3d4f46f484c2a5c440.tar.bz2
Add DesktopShapeTracker with implementation for Windows
The new class will be used in Me2App mode to capture window shape. BUG=134209 Review URL: https://codereview.chromium.org/83183007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236972 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/host/desktop_shape_tracker.h38
-rw-r--r--remoting/host/desktop_shape_tracker_mac.cc17
-rw-r--r--remoting/host/desktop_shape_tracker_unittest.cc32
-rw-r--r--remoting/host/desktop_shape_tracker_win.cc141
-rw-r--r--remoting/host/desktop_shape_tracker_x11.cc17
-rw-r--r--remoting/remoting.gyp5
6 files changed, 250 insertions, 0 deletions
diff --git a/remoting/host/desktop_shape_tracker.h b/remoting/host/desktop_shape_tracker.h
new file mode 100644
index 0000000..9530b22
--- /dev/null
+++ b/remoting/host/desktop_shape_tracker.h
@@ -0,0 +1,38 @@
+// Copyright 2013 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 REMOTING_HOST_DESKTOP_SHAPE_TRACKER_H_
+#define REMOTING_HOST_DESKTOP_SHAPE_TRACKER_H_
+
+#include "base/memory/scoped_ptr.h"
+
+namespace webrtc {
+class DesktopCaptureOptions;
+class DesktopRegion;
+} // namespace webrtc
+
+namespace remoting {
+
+// Tracks changes in the area of the desktop that is occupied by windows.
+class DesktopShapeTracker {
+ public:
+ static scoped_ptr<DesktopShapeTracker> Create(
+ webrtc::DesktopCaptureOptions options);
+
+ DesktopShapeTracker() {}
+ virtual ~DesktopShapeTracker() {}
+
+ // Recalculates the desktop shape, as returned by desktop_shape();
+ virtual void RefreshDesktopShape() = 0;
+
+ // Returns a reference to the most recently capture desktop shape.
+ virtual const webrtc::DesktopRegion& desktop_shape() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DesktopShapeTracker);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_DESKTOP_SHAPE_TRACKER_H_
diff --git a/remoting/host/desktop_shape_tracker_mac.cc b/remoting/host/desktop_shape_tracker_mac.cc
new file mode 100644
index 0000000..8ee02b3
--- /dev/null
+++ b/remoting/host/desktop_shape_tracker_mac.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+#include "remoting/host/desktop_shape_tracker.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+
+namespace remoting {
+
+scoped_ptr<DesktopShapeTracker> DesktopShapeTracker::Create(
+ webrtc::DesktopCaptureOptions options) {
+ return scoped_ptr<DesktopShapeTracker>();
+}
+
+} // namespace remoting
diff --git a/remoting/host/desktop_shape_tracker_unittest.cc b/remoting/host/desktop_shape_tracker_unittest.cc
new file mode 100644
index 0000000..36a1333
--- /dev/null
+++ b/remoting/host/desktop_shape_tracker_unittest.cc
@@ -0,0 +1,32 @@
+// Copyright 2013 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.
+
+// DesktopShapeTracker tests assume that there is at least one top-level
+// window on-screen. Currently we assume the presence of the Explorer
+// task bar window.
+
+#include "remoting/host/desktop_shape_tracker.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
+
+namespace remoting {
+
+// Verify that the desktop shape tracker returns a non-empty region.
+TEST(DesktopShapeTrackerTest, Basic) {
+ scoped_ptr<DesktopShapeTracker> shape_tracker = DesktopShapeTracker::Create(
+ webrtc::DesktopCaptureOptions::CreateDefault());
+
+ // Shape tracker is not supported on all platforms yet.
+#if defined(OS_WIN)
+ shape_tracker->RefreshDesktopShape();
+ EXPECT_FALSE(shape_tracker->desktop_shape().is_empty());
+#else
+ EXPECT_FALSE(shape_tracker);
+#endif
+}
+
+} // namespace remoting
diff --git a/remoting/host/desktop_shape_tracker_win.cc b/remoting/host/desktop_shape_tracker_win.cc
new file mode 100644
index 0000000..afae3e0
--- /dev/null
+++ b/remoting/host/desktop_shape_tracker_win.cc
@@ -0,0 +1,141 @@
+// Copyright 2013 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.
+
+#include "remoting/host/desktop_shape_tracker.h"
+
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_gdi_object.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
+
+namespace remoting {
+
+namespace {
+
+struct EnumDesktopShapeData {
+ EnumDesktopShapeData()
+ : window_region(CreateRectRgn(0, 0, 0, 0)),
+ desktop_region(CreateRectRgn(0, 0, 0, 0)) {
+ }
+ base::win::ScopedRegion window_region;
+ base::win::ScopedRegion desktop_region;
+};
+
+class DesktopShapeTrackerWin : public DesktopShapeTracker {
+ public:
+ DesktopShapeTrackerWin();
+ virtual ~DesktopShapeTrackerWin();
+
+ virtual void RefreshDesktopShape();
+ virtual const webrtc::DesktopRegion& desktop_shape();
+
+ private:
+ // Callback passed to EnumWindows() to enumerate windows.
+ static BOOL CALLBACK EnumWindowsCallback(HWND window, LPARAM lparam);
+
+ // The most recently calculated desktop region.
+ webrtc::DesktopRegion desktop_shape_;
+
+ // Stored to compare with newly calculated desktop shapes, to avoid converting
+ // to an DesktopRegion unless the shape has actually changed.
+ base::win::ScopedRegion old_desktop_region_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesktopShapeTrackerWin);
+};
+
+DesktopShapeTrackerWin::DesktopShapeTrackerWin()
+ : old_desktop_region_(CreateRectRgn(0, 0, 0, 0)) {
+}
+
+DesktopShapeTrackerWin::~DesktopShapeTrackerWin() {
+}
+
+void DesktopShapeTrackerWin::RefreshDesktopShape() {
+ // Accumulate a new desktop shape from current window positions.
+ scoped_ptr<EnumDesktopShapeData> shape_data(new EnumDesktopShapeData);
+ if (!EnumWindows(EnumWindowsCallback, (LPARAM)shape_data.get())) {
+ LOG_GETLASTERROR(ERROR) << "Failed to enumerate windows";
+ desktop_shape_.Clear();
+ return;
+ }
+
+ // If the shape has changed, refresh |desktop_shape_|.
+ if (!EqualRgn(shape_data->desktop_region, old_desktop_region_)) {
+ old_desktop_region_.Set(shape_data->desktop_region.release());
+
+ // Determine the size of output buffer required to receive the region.
+ DWORD bytes_size = GetRegionData(old_desktop_region_, 0, NULL);
+ CHECK(bytes_size != 0);
+
+ // Fetch the Windows RECTs that comprise the region.
+ std::vector<char> buffer(bytes_size);;
+ LPRGNDATA region_data = reinterpret_cast<LPRGNDATA>(buffer.data());
+ DWORD result = GetRegionData(old_desktop_region_, bytes_size, region_data);
+ CHECK(result == bytes_size);
+ const LPRECT rects = reinterpret_cast<LPRECT>(&region_data->Buffer[0]);
+
+ // Reset |desktop_shape_| and add new rectangles into it.
+ desktop_shape_.Clear();
+ for (size_t i = 0; i < region_data->rdh.nCount; ++i) {
+ desktop_shape_.AddRect(webrtc::DesktopRect::MakeLTRB(
+ rects[i].left, rects[i].top, rects[i].right, rects[i].bottom));
+ }
+ }
+}
+
+const webrtc::DesktopRegion& DesktopShapeTrackerWin::desktop_shape() {
+ return desktop_shape_;
+}
+
+// static
+BOOL DesktopShapeTrackerWin::EnumWindowsCallback(HWND window, LPARAM lparam) {
+ EnumDesktopShapeData* data = reinterpret_cast<EnumDesktopShapeData*>(lparam);
+ HRGN desktop_region = data->desktop_region.Get();
+ HRGN window_region = data->window_region.Get();
+
+ // Is the window visible?
+ if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
+ return TRUE;
+
+ // Find the desktop position of the window (including non-client-area).
+ RECT window_rect;
+ if (!GetWindowRect(window, &window_rect))
+ return TRUE;
+
+ // Find the shape of the window, in window coords.
+ // GetWindowRgn will overwrite the current contents of |window_region|.
+ if (GetWindowRgn(window, window_region) != ERROR) {
+ // Translate the window region into desktop coordinates.
+ OffsetRgn(window_region, window_rect.left, window_rect.top);
+ } else {
+ // Window has no shape, or an error occurred, so assume it's rectangular.
+ SetRectRgn(window_region, window_rect.left, window_rect.top,
+ window_rect.right, window_rect.bottom);
+ }
+
+ // TODO(wez): If the window is maximized then we should clip it to the
+ // display on which it is maximized.
+ // if (IsZoomed(window))
+ // CombineRgn(window_region, window_region, screen_region, RGN_AND);
+
+ // Merge the window region into the accumulated desktop region. Window
+ // regions are combined together before converting the result to
+ // DesktopRegion. It assumed that this approach is more efficient than
+ // converting each window region individually.
+ CombineRgn(desktop_region, desktop_region, window_region, RGN_OR);
+
+ return TRUE;
+}
+
+} // namespace
+
+// static
+scoped_ptr<DesktopShapeTracker> DesktopShapeTracker::Create(
+ webrtc::DesktopCaptureOptions options) {
+ return scoped_ptr<DesktopShapeTracker>(new DesktopShapeTrackerWin());
+}
+
+} // namespace remoting
diff --git a/remoting/host/desktop_shape_tracker_x11.cc b/remoting/host/desktop_shape_tracker_x11.cc
new file mode 100644
index 0000000..8ee02b3
--- /dev/null
+++ b/remoting/host/desktop_shape_tracker_x11.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 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.
+
+#include "remoting/host/desktop_shape_tracker.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
+
+namespace remoting {
+
+scoped_ptr<DesktopShapeTracker> DesktopShapeTracker::Create(
+ webrtc::DesktopCaptureOptions options) {
+ return scoped_ptr<DesktopShapeTracker>();
+}
+
+} // namespace remoting
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 9359095..6fb5c25 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -329,6 +329,10 @@
'host/desktop_session_connector.h',
'host/desktop_session_proxy.cc',
'host/desktop_session_proxy.h',
+ 'host/desktop_shape_tracker.h',
+ 'host/desktop_shape_tracker_mac.cc',
+ 'host/desktop_shape_tracker_win.cc',
+ 'host/desktop_shape_tracker_x11.cc',
'host/disconnect_window_aura.cc',
'host/disconnect_window_gtk.cc',
'host/disconnect_window_mac.h',
@@ -2850,6 +2854,7 @@
'host/desktop_process_unittest.cc',
'host/desktop_session.cc',
'host/desktop_session.h',
+ 'host/desktop_shape_tracker_unittest.cc',
'host/desktop_session_agent.cc',
'host/desktop_session_agent.h',
'host/heartbeat_sender_unittest.cc',