Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: remoting/host/desktop_shape_tracker_win.cc

Issue 83183007: Add DesktopShapeTracker with implementation for Windows (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "remoting/host/desktop_shape_tracker.h"
6
7 #include <vector>
8
9 #include "base/memory/scoped_ptr.h"
10 #include "base/win/scoped_gdi_object.h"
11 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
12 #include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
13
14 namespace remoting {
15
16 namespace {
17
18 struct EnumDesktopShapeData {
19 EnumDesktopShapeData()
20 : window_region(CreateRectRgn(0, 0, 0, 0)),
21 desktop_region(CreateRectRgn(0, 0, 0, 0)) {
22 }
23 base::win::ScopedRegion window_region;
24 base::win::ScopedRegion desktop_region;
25 };
26
27 class DesktopShapeTrackerWin : public DesktopShapeTracker {
28 public:
29 DesktopShapeTrackerWin();
30 virtual ~DesktopShapeTrackerWin();
31
32 virtual void RefreshDesktopShape();
33 virtual const webrtc::DesktopRegion& desktop_shape();
34
35 private:
36 // Callback passed to EnumWindows() to enumerate windows.
37 static BOOL CALLBACK EnumWindowsCallback(HWND window, LPARAM lparam);
38
39 // The most recently calculated desktop region.
40 webrtc::DesktopRegion desktop_shape_;
41
42 // Stored to compare with newly calculated desktop shapes, to avoid converting
43 // to an DesktopRegion unless the shape has actually changed.
44 base::win::ScopedRegion old_desktop_region_;
45
46 DISALLOW_COPY_AND_ASSIGN(DesktopShapeTrackerWin);
47 };
48
49 DesktopShapeTrackerWin::DesktopShapeTrackerWin()
50 : old_desktop_region_(CreateRectRgn(0, 0, 0, 0)) {
51 }
52
53 DesktopShapeTrackerWin::~DesktopShapeTrackerWin() {
54 }
55
56 void DesktopShapeTrackerWin::RefreshDesktopShape() {
57 // Accumulate a new desktop shape from current window positions.
58 scoped_ptr<EnumDesktopShapeData> shape_data(new EnumDesktopShapeData);
59 if (!EnumWindows(EnumWindowsCallback, (LPARAM)shape_data.get())) {
60 LOG_GETLASTERROR(ERROR) << "Failed to enumerate windows";
61 desktop_shape_.Clear();
62 return;
63 }
64
65 // If the shape has changed, refresh |desktop_shape_|.
66 if (!EqualRgn(shape_data->desktop_region, old_desktop_region_)) {
67 old_desktop_region_.Set(shape_data->desktop_region.release());
68
69 // Determine the size of output buffer required to receive the region.
70 DWORD bytes_size = GetRegionData(old_desktop_region_, 0, NULL);
71 CHECK(bytes_size != 0);
72
73 // Fetch the Windows RECTs that comprise the region.
74 std::vector<char> buffer(bytes_size);;
75 LPRGNDATA region_data = reinterpret_cast<LPRGNDATA>(buffer.data());
76 DWORD result = GetRegionData(old_desktop_region_, bytes_size, region_data);
77 CHECK(result == bytes_size);
78 const LPRECT rects = reinterpret_cast<LPRECT>(&region_data->Buffer[0]);
79
80 // Reset |desktop_shape_| and add new rectangles into it.
81 desktop_shape_.Clear();
82 for (size_t i = 0; i < region_data->rdh.nCount; ++i) {
83 desktop_shape_.AddRect(webrtc::DesktopRect::MakeLTRB(
84 rects[i].left, rects[i].top, rects[i].right, rects[i].bottom));
85 }
86 }
87 }
88
89 const webrtc::DesktopRegion& DesktopShapeTrackerWin::desktop_shape() {
90 return desktop_shape_;
91 }
92
93 // static
94 BOOL DesktopShapeTrackerWin::EnumWindowsCallback(HWND window, LPARAM lparam) {
95 EnumDesktopShapeData* data = reinterpret_cast<EnumDesktopShapeData*>(lparam);
96 HRGN desktop_region = data->desktop_region.Get();
97 HRGN window_region = data->window_region.Get();
98
99 // Is the window visible?
100 if (!IsWindow(window) || !IsWindowVisible(window) || IsIconic(window))
101 return TRUE;
102
103 // Find the desktop position of the window (including non-client-area).
104 RECT window_rect;
105 if (!GetWindowRect(window, &window_rect))
106 return TRUE;
107
108 // Find the shape of the window, in window coords.
109 // GetWindowRgn will overwrite the current contents of |window_region|.
110 if (GetWindowRgn(window, window_region) != ERROR) {
111 // Translate the window region into desktop coordinates.
112 OffsetRgn(window_region, window_rect.left, window_rect.top);
113 } else {
114 // Window has no shape, or an error occurred, so assume it's rectangular.
115 SetRectRgn(window_region, window_rect.left, window_rect.top,
116 window_rect.right, window_rect.bottom);
117 }
118
119 // TODO(wez): If the window is maximized then we should clip it to the
120 // display on which it is maximized.
121 // if (IsZoomed(window))
122 // CombineRgn(window_region, window_region, screen_region, RGN_AND);
123
124 // Merge the window region into the accumulated desktop region. Window
125 // regions are combined together before converting the result to
126 // DesktopRegion. It assumed that this approach is more efficient than
127 // converting each window region individually.
128 CombineRgn(desktop_region, desktop_region, window_region, RGN_OR);
129
130 return TRUE;
131 }
132
133 } // namespace
134
135 // static
136 scoped_ptr<DesktopShapeTracker> DesktopShapeTracker::Create(
137 webrtc::DesktopCaptureOptions options) {
138 return scoped_ptr<DesktopShapeTracker>(new DesktopShapeTrackerWin());
139 }
140
141 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/desktop_shape_tracker_unittest.cc ('k') | remoting/host/desktop_shape_tracker_x11.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698