diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-23 20:58:14 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-23 20:58:14 +0000 |
commit | 41c19234e2f62eba64776f3d4f46f484c2a5c440 (patch) | |
tree | 7f28e753a25ff8217665141af16165b427f79cb5 | |
parent | 7dcf0f549ed34d19057612eb55fb6b59c3582229 (diff) | |
download | chromium_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.h | 38 | ||||
-rw-r--r-- | remoting/host/desktop_shape_tracker_mac.cc | 17 | ||||
-rw-r--r-- | remoting/host/desktop_shape_tracker_unittest.cc | 32 | ||||
-rw-r--r-- | remoting/host/desktop_shape_tracker_win.cc | 141 | ||||
-rw-r--r-- | remoting/host/desktop_shape_tracker_x11.cc | 17 | ||||
-rw-r--r-- | remoting/remoting.gyp | 5 |
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>(®ion_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', |