1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2012 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "examples/peerconnection/client/main_wnd.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <math.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include "api/video/i420_buffer.h"
16*d9f75844SAndroid Build Coastguard Worker #include "examples/peerconnection/client/defaults.h"
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/arraysize.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
20*d9f75844SAndroid Build Coastguard Worker #include "third_party/libyuv/include/libyuv/convert_argb.h"
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker ATOM MainWnd::wnd_class_ = 0;
23*d9f75844SAndroid Build Coastguard Worker const wchar_t MainWnd::kClassName[] = L"WebRTC_MainWnd";
24*d9f75844SAndroid Build Coastguard Worker
25*d9f75844SAndroid Build Coastguard Worker namespace {
26*d9f75844SAndroid Build Coastguard Worker
27*d9f75844SAndroid Build Coastguard Worker const char kConnecting[] = "Connecting... ";
28*d9f75844SAndroid Build Coastguard Worker const char kNoVideoStreams[] = "(no video streams either way)";
29*d9f75844SAndroid Build Coastguard Worker const char kNoIncomingStream[] = "(no incoming video)";
30*d9f75844SAndroid Build Coastguard Worker
CalculateWindowSizeForText(HWND wnd,const wchar_t * text,size_t * width,size_t * height)31*d9f75844SAndroid Build Coastguard Worker void CalculateWindowSizeForText(HWND wnd,
32*d9f75844SAndroid Build Coastguard Worker const wchar_t* text,
33*d9f75844SAndroid Build Coastguard Worker size_t* width,
34*d9f75844SAndroid Build Coastguard Worker size_t* height) {
35*d9f75844SAndroid Build Coastguard Worker HDC dc = ::GetDC(wnd);
36*d9f75844SAndroid Build Coastguard Worker RECT text_rc = {0};
37*d9f75844SAndroid Build Coastguard Worker ::DrawTextW(dc, text, -1, &text_rc, DT_CALCRECT | DT_SINGLELINE);
38*d9f75844SAndroid Build Coastguard Worker ::ReleaseDC(wnd, dc);
39*d9f75844SAndroid Build Coastguard Worker RECT client, window;
40*d9f75844SAndroid Build Coastguard Worker ::GetClientRect(wnd, &client);
41*d9f75844SAndroid Build Coastguard Worker ::GetWindowRect(wnd, &window);
42*d9f75844SAndroid Build Coastguard Worker
43*d9f75844SAndroid Build Coastguard Worker *width = text_rc.right - text_rc.left;
44*d9f75844SAndroid Build Coastguard Worker *width += (window.right - window.left) - (client.right - client.left);
45*d9f75844SAndroid Build Coastguard Worker *height = text_rc.bottom - text_rc.top;
46*d9f75844SAndroid Build Coastguard Worker *height += (window.bottom - window.top) - (client.bottom - client.top);
47*d9f75844SAndroid Build Coastguard Worker }
48*d9f75844SAndroid Build Coastguard Worker
GetDefaultFont()49*d9f75844SAndroid Build Coastguard Worker HFONT GetDefaultFont() {
50*d9f75844SAndroid Build Coastguard Worker static HFONT font = reinterpret_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT));
51*d9f75844SAndroid Build Coastguard Worker return font;
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker
GetWindowText(HWND wnd)54*d9f75844SAndroid Build Coastguard Worker std::string GetWindowText(HWND wnd) {
55*d9f75844SAndroid Build Coastguard Worker char text[MAX_PATH] = {0};
56*d9f75844SAndroid Build Coastguard Worker ::GetWindowTextA(wnd, &text[0], ARRAYSIZE(text));
57*d9f75844SAndroid Build Coastguard Worker return text;
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker
AddListBoxItem(HWND listbox,const std::string & str,LPARAM item_data)60*d9f75844SAndroid Build Coastguard Worker void AddListBoxItem(HWND listbox, const std::string& str, LPARAM item_data) {
61*d9f75844SAndroid Build Coastguard Worker LRESULT index = ::SendMessageA(listbox, LB_ADDSTRING, 0,
62*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<LPARAM>(str.c_str()));
63*d9f75844SAndroid Build Coastguard Worker ::SendMessageA(listbox, LB_SETITEMDATA, index, item_data);
64*d9f75844SAndroid Build Coastguard Worker }
65*d9f75844SAndroid Build Coastguard Worker
66*d9f75844SAndroid Build Coastguard Worker } // namespace
67*d9f75844SAndroid Build Coastguard Worker
MainWnd(const char * server,int port,bool auto_connect,bool auto_call)68*d9f75844SAndroid Build Coastguard Worker MainWnd::MainWnd(const char* server,
69*d9f75844SAndroid Build Coastguard Worker int port,
70*d9f75844SAndroid Build Coastguard Worker bool auto_connect,
71*d9f75844SAndroid Build Coastguard Worker bool auto_call)
72*d9f75844SAndroid Build Coastguard Worker : ui_(CONNECT_TO_SERVER),
73*d9f75844SAndroid Build Coastguard Worker wnd_(NULL),
74*d9f75844SAndroid Build Coastguard Worker edit1_(NULL),
75*d9f75844SAndroid Build Coastguard Worker edit2_(NULL),
76*d9f75844SAndroid Build Coastguard Worker label1_(NULL),
77*d9f75844SAndroid Build Coastguard Worker label2_(NULL),
78*d9f75844SAndroid Build Coastguard Worker button_(NULL),
79*d9f75844SAndroid Build Coastguard Worker listbox_(NULL),
80*d9f75844SAndroid Build Coastguard Worker destroyed_(false),
81*d9f75844SAndroid Build Coastguard Worker nested_msg_(NULL),
82*d9f75844SAndroid Build Coastguard Worker callback_(NULL),
83*d9f75844SAndroid Build Coastguard Worker server_(server),
84*d9f75844SAndroid Build Coastguard Worker auto_connect_(auto_connect),
85*d9f75844SAndroid Build Coastguard Worker auto_call_(auto_call) {
86*d9f75844SAndroid Build Coastguard Worker char buffer[10];
87*d9f75844SAndroid Build Coastguard Worker snprintf(buffer, sizeof(buffer), "%i", port);
88*d9f75844SAndroid Build Coastguard Worker port_ = buffer;
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker
~MainWnd()91*d9f75844SAndroid Build Coastguard Worker MainWnd::~MainWnd() {
92*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!IsWindow());
93*d9f75844SAndroid Build Coastguard Worker }
94*d9f75844SAndroid Build Coastguard Worker
Create()95*d9f75844SAndroid Build Coastguard Worker bool MainWnd::Create() {
96*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(wnd_ == NULL);
97*d9f75844SAndroid Build Coastguard Worker if (!RegisterWindowClass())
98*d9f75844SAndroid Build Coastguard Worker return false;
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker ui_thread_id_ = ::GetCurrentThreadId();
101*d9f75844SAndroid Build Coastguard Worker wnd_ =
102*d9f75844SAndroid Build Coastguard Worker ::CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, kClassName, L"WebRTC",
103*d9f75844SAndroid Build Coastguard Worker WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
104*d9f75844SAndroid Build Coastguard Worker CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
105*d9f75844SAndroid Build Coastguard Worker CW_USEDEFAULT, NULL, NULL, GetModuleHandle(NULL), this);
106*d9f75844SAndroid Build Coastguard Worker
107*d9f75844SAndroid Build Coastguard Worker ::SendMessage(wnd_, WM_SETFONT, reinterpret_cast<WPARAM>(GetDefaultFont()),
108*d9f75844SAndroid Build Coastguard Worker TRUE);
109*d9f75844SAndroid Build Coastguard Worker
110*d9f75844SAndroid Build Coastguard Worker CreateChildWindows();
111*d9f75844SAndroid Build Coastguard Worker SwitchToConnectUI();
112*d9f75844SAndroid Build Coastguard Worker
113*d9f75844SAndroid Build Coastguard Worker return wnd_ != NULL;
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker
Destroy()116*d9f75844SAndroid Build Coastguard Worker bool MainWnd::Destroy() {
117*d9f75844SAndroid Build Coastguard Worker BOOL ret = FALSE;
118*d9f75844SAndroid Build Coastguard Worker if (IsWindow()) {
119*d9f75844SAndroid Build Coastguard Worker ret = ::DestroyWindow(wnd_);
120*d9f75844SAndroid Build Coastguard Worker }
121*d9f75844SAndroid Build Coastguard Worker
122*d9f75844SAndroid Build Coastguard Worker return ret != FALSE;
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker
RegisterObserver(MainWndCallback * callback)125*d9f75844SAndroid Build Coastguard Worker void MainWnd::RegisterObserver(MainWndCallback* callback) {
126*d9f75844SAndroid Build Coastguard Worker callback_ = callback;
127*d9f75844SAndroid Build Coastguard Worker }
128*d9f75844SAndroid Build Coastguard Worker
IsWindow()129*d9f75844SAndroid Build Coastguard Worker bool MainWnd::IsWindow() {
130*d9f75844SAndroid Build Coastguard Worker return wnd_ && ::IsWindow(wnd_) != FALSE;
131*d9f75844SAndroid Build Coastguard Worker }
132*d9f75844SAndroid Build Coastguard Worker
PreTranslateMessage(MSG * msg)133*d9f75844SAndroid Build Coastguard Worker bool MainWnd::PreTranslateMessage(MSG* msg) {
134*d9f75844SAndroid Build Coastguard Worker bool ret = false;
135*d9f75844SAndroid Build Coastguard Worker if (msg->message == WM_CHAR) {
136*d9f75844SAndroid Build Coastguard Worker if (msg->wParam == VK_TAB) {
137*d9f75844SAndroid Build Coastguard Worker HandleTabbing();
138*d9f75844SAndroid Build Coastguard Worker ret = true;
139*d9f75844SAndroid Build Coastguard Worker } else if (msg->wParam == VK_RETURN) {
140*d9f75844SAndroid Build Coastguard Worker OnDefaultAction();
141*d9f75844SAndroid Build Coastguard Worker ret = true;
142*d9f75844SAndroid Build Coastguard Worker } else if (msg->wParam == VK_ESCAPE) {
143*d9f75844SAndroid Build Coastguard Worker if (callback_) {
144*d9f75844SAndroid Build Coastguard Worker if (ui_ == STREAMING) {
145*d9f75844SAndroid Build Coastguard Worker callback_->DisconnectFromCurrentPeer();
146*d9f75844SAndroid Build Coastguard Worker } else {
147*d9f75844SAndroid Build Coastguard Worker callback_->DisconnectFromServer();
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker } else if (msg->hwnd == NULL && msg->message == UI_THREAD_CALLBACK) {
152*d9f75844SAndroid Build Coastguard Worker callback_->UIThreadCallback(static_cast<int>(msg->wParam),
153*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<void*>(msg->lParam));
154*d9f75844SAndroid Build Coastguard Worker ret = true;
155*d9f75844SAndroid Build Coastguard Worker }
156*d9f75844SAndroid Build Coastguard Worker return ret;
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker
SwitchToConnectUI()159*d9f75844SAndroid Build Coastguard Worker void MainWnd::SwitchToConnectUI() {
160*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(IsWindow());
161*d9f75844SAndroid Build Coastguard Worker LayoutPeerListUI(false);
162*d9f75844SAndroid Build Coastguard Worker ui_ = CONNECT_TO_SERVER;
163*d9f75844SAndroid Build Coastguard Worker LayoutConnectUI(true);
164*d9f75844SAndroid Build Coastguard Worker ::SetFocus(edit1_);
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker if (auto_connect_)
167*d9f75844SAndroid Build Coastguard Worker ::PostMessage(button_, BM_CLICK, 0, 0);
168*d9f75844SAndroid Build Coastguard Worker }
169*d9f75844SAndroid Build Coastguard Worker
SwitchToPeerList(const Peers & peers)170*d9f75844SAndroid Build Coastguard Worker void MainWnd::SwitchToPeerList(const Peers& peers) {
171*d9f75844SAndroid Build Coastguard Worker LayoutConnectUI(false);
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker ::SendMessage(listbox_, LB_RESETCONTENT, 0, 0);
174*d9f75844SAndroid Build Coastguard Worker
175*d9f75844SAndroid Build Coastguard Worker AddListBoxItem(listbox_, "List of currently connected peers:", -1);
176*d9f75844SAndroid Build Coastguard Worker Peers::const_iterator i = peers.begin();
177*d9f75844SAndroid Build Coastguard Worker for (; i != peers.end(); ++i)
178*d9f75844SAndroid Build Coastguard Worker AddListBoxItem(listbox_, i->second.c_str(), i->first);
179*d9f75844SAndroid Build Coastguard Worker
180*d9f75844SAndroid Build Coastguard Worker ui_ = LIST_PEERS;
181*d9f75844SAndroid Build Coastguard Worker LayoutPeerListUI(true);
182*d9f75844SAndroid Build Coastguard Worker ::SetFocus(listbox_);
183*d9f75844SAndroid Build Coastguard Worker
184*d9f75844SAndroid Build Coastguard Worker if (auto_call_ && peers.begin() != peers.end()) {
185*d9f75844SAndroid Build Coastguard Worker // Get the number of items in the list
186*d9f75844SAndroid Build Coastguard Worker LRESULT count = ::SendMessage(listbox_, LB_GETCOUNT, 0, 0);
187*d9f75844SAndroid Build Coastguard Worker if (count != LB_ERR) {
188*d9f75844SAndroid Build Coastguard Worker // Select the last item in the list
189*d9f75844SAndroid Build Coastguard Worker LRESULT selection = ::SendMessage(listbox_, LB_SETCURSEL, count - 1, 0);
190*d9f75844SAndroid Build Coastguard Worker if (selection != LB_ERR)
191*d9f75844SAndroid Build Coastguard Worker ::PostMessage(wnd_, WM_COMMAND,
192*d9f75844SAndroid Build Coastguard Worker MAKEWPARAM(GetDlgCtrlID(listbox_), LBN_DBLCLK),
193*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<LPARAM>(listbox_));
194*d9f75844SAndroid Build Coastguard Worker }
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker
SwitchToStreamingUI()198*d9f75844SAndroid Build Coastguard Worker void MainWnd::SwitchToStreamingUI() {
199*d9f75844SAndroid Build Coastguard Worker LayoutConnectUI(false);
200*d9f75844SAndroid Build Coastguard Worker LayoutPeerListUI(false);
201*d9f75844SAndroid Build Coastguard Worker ui_ = STREAMING;
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker
MessageBox(const char * caption,const char * text,bool is_error)204*d9f75844SAndroid Build Coastguard Worker void MainWnd::MessageBox(const char* caption, const char* text, bool is_error) {
205*d9f75844SAndroid Build Coastguard Worker DWORD flags = MB_OK;
206*d9f75844SAndroid Build Coastguard Worker if (is_error)
207*d9f75844SAndroid Build Coastguard Worker flags |= MB_ICONERROR;
208*d9f75844SAndroid Build Coastguard Worker
209*d9f75844SAndroid Build Coastguard Worker ::MessageBoxA(handle(), text, caption, flags);
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker
StartLocalRenderer(webrtc::VideoTrackInterface * local_video)212*d9f75844SAndroid Build Coastguard Worker void MainWnd::StartLocalRenderer(webrtc::VideoTrackInterface* local_video) {
213*d9f75844SAndroid Build Coastguard Worker local_renderer_.reset(new VideoRenderer(handle(), 1, 1, local_video));
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker
StopLocalRenderer()216*d9f75844SAndroid Build Coastguard Worker void MainWnd::StopLocalRenderer() {
217*d9f75844SAndroid Build Coastguard Worker local_renderer_.reset();
218*d9f75844SAndroid Build Coastguard Worker }
219*d9f75844SAndroid Build Coastguard Worker
StartRemoteRenderer(webrtc::VideoTrackInterface * remote_video)220*d9f75844SAndroid Build Coastguard Worker void MainWnd::StartRemoteRenderer(webrtc::VideoTrackInterface* remote_video) {
221*d9f75844SAndroid Build Coastguard Worker remote_renderer_.reset(new VideoRenderer(handle(), 1, 1, remote_video));
222*d9f75844SAndroid Build Coastguard Worker }
223*d9f75844SAndroid Build Coastguard Worker
StopRemoteRenderer()224*d9f75844SAndroid Build Coastguard Worker void MainWnd::StopRemoteRenderer() {
225*d9f75844SAndroid Build Coastguard Worker remote_renderer_.reset();
226*d9f75844SAndroid Build Coastguard Worker }
227*d9f75844SAndroid Build Coastguard Worker
QueueUIThreadCallback(int msg_id,void * data)228*d9f75844SAndroid Build Coastguard Worker void MainWnd::QueueUIThreadCallback(int msg_id, void* data) {
229*d9f75844SAndroid Build Coastguard Worker ::PostThreadMessage(ui_thread_id_, UI_THREAD_CALLBACK,
230*d9f75844SAndroid Build Coastguard Worker static_cast<WPARAM>(msg_id),
231*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<LPARAM>(data));
232*d9f75844SAndroid Build Coastguard Worker }
233*d9f75844SAndroid Build Coastguard Worker
OnPaint()234*d9f75844SAndroid Build Coastguard Worker void MainWnd::OnPaint() {
235*d9f75844SAndroid Build Coastguard Worker PAINTSTRUCT ps;
236*d9f75844SAndroid Build Coastguard Worker ::BeginPaint(handle(), &ps);
237*d9f75844SAndroid Build Coastguard Worker
238*d9f75844SAndroid Build Coastguard Worker RECT rc;
239*d9f75844SAndroid Build Coastguard Worker ::GetClientRect(handle(), &rc);
240*d9f75844SAndroid Build Coastguard Worker
241*d9f75844SAndroid Build Coastguard Worker VideoRenderer* local_renderer = local_renderer_.get();
242*d9f75844SAndroid Build Coastguard Worker VideoRenderer* remote_renderer = remote_renderer_.get();
243*d9f75844SAndroid Build Coastguard Worker if (ui_ == STREAMING && remote_renderer && local_renderer) {
244*d9f75844SAndroid Build Coastguard Worker AutoLock<VideoRenderer> local_lock(local_renderer);
245*d9f75844SAndroid Build Coastguard Worker AutoLock<VideoRenderer> remote_lock(remote_renderer);
246*d9f75844SAndroid Build Coastguard Worker
247*d9f75844SAndroid Build Coastguard Worker const BITMAPINFO& bmi = remote_renderer->bmi();
248*d9f75844SAndroid Build Coastguard Worker int height = abs(bmi.bmiHeader.biHeight);
249*d9f75844SAndroid Build Coastguard Worker int width = bmi.bmiHeader.biWidth;
250*d9f75844SAndroid Build Coastguard Worker
251*d9f75844SAndroid Build Coastguard Worker const uint8_t* image = remote_renderer->image();
252*d9f75844SAndroid Build Coastguard Worker if (image != NULL) {
253*d9f75844SAndroid Build Coastguard Worker HDC dc_mem = ::CreateCompatibleDC(ps.hdc);
254*d9f75844SAndroid Build Coastguard Worker ::SetStretchBltMode(dc_mem, HALFTONE);
255*d9f75844SAndroid Build Coastguard Worker
256*d9f75844SAndroid Build Coastguard Worker // Set the map mode so that the ratio will be maintained for us.
257*d9f75844SAndroid Build Coastguard Worker HDC all_dc[] = {ps.hdc, dc_mem};
258*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(all_dc); ++i) {
259*d9f75844SAndroid Build Coastguard Worker SetMapMode(all_dc[i], MM_ISOTROPIC);
260*d9f75844SAndroid Build Coastguard Worker SetWindowExtEx(all_dc[i], width, height, NULL);
261*d9f75844SAndroid Build Coastguard Worker SetViewportExtEx(all_dc[i], rc.right, rc.bottom, NULL);
262*d9f75844SAndroid Build Coastguard Worker }
263*d9f75844SAndroid Build Coastguard Worker
264*d9f75844SAndroid Build Coastguard Worker HBITMAP bmp_mem = ::CreateCompatibleBitmap(ps.hdc, rc.right, rc.bottom);
265*d9f75844SAndroid Build Coastguard Worker HGDIOBJ bmp_old = ::SelectObject(dc_mem, bmp_mem);
266*d9f75844SAndroid Build Coastguard Worker
267*d9f75844SAndroid Build Coastguard Worker POINT logical_area = {rc.right, rc.bottom};
268*d9f75844SAndroid Build Coastguard Worker DPtoLP(ps.hdc, &logical_area, 1);
269*d9f75844SAndroid Build Coastguard Worker
270*d9f75844SAndroid Build Coastguard Worker HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
271*d9f75844SAndroid Build Coastguard Worker RECT logical_rect = {0, 0, logical_area.x, logical_area.y};
272*d9f75844SAndroid Build Coastguard Worker ::FillRect(dc_mem, &logical_rect, brush);
273*d9f75844SAndroid Build Coastguard Worker ::DeleteObject(brush);
274*d9f75844SAndroid Build Coastguard Worker
275*d9f75844SAndroid Build Coastguard Worker int x = (logical_area.x / 2) - (width / 2);
276*d9f75844SAndroid Build Coastguard Worker int y = (logical_area.y / 2) - (height / 2);
277*d9f75844SAndroid Build Coastguard Worker
278*d9f75844SAndroid Build Coastguard Worker StretchDIBits(dc_mem, x, y, width, height, 0, 0, width, height, image,
279*d9f75844SAndroid Build Coastguard Worker &bmi, DIB_RGB_COLORS, SRCCOPY);
280*d9f75844SAndroid Build Coastguard Worker
281*d9f75844SAndroid Build Coastguard Worker if ((rc.right - rc.left) > 200 && (rc.bottom - rc.top) > 200) {
282*d9f75844SAndroid Build Coastguard Worker const BITMAPINFO& bmi = local_renderer->bmi();
283*d9f75844SAndroid Build Coastguard Worker image = local_renderer->image();
284*d9f75844SAndroid Build Coastguard Worker int thumb_width = bmi.bmiHeader.biWidth / 4;
285*d9f75844SAndroid Build Coastguard Worker int thumb_height = abs(bmi.bmiHeader.biHeight) / 4;
286*d9f75844SAndroid Build Coastguard Worker StretchDIBits(dc_mem, logical_area.x - thumb_width - 10,
287*d9f75844SAndroid Build Coastguard Worker logical_area.y - thumb_height - 10, thumb_width,
288*d9f75844SAndroid Build Coastguard Worker thumb_height, 0, 0, bmi.bmiHeader.biWidth,
289*d9f75844SAndroid Build Coastguard Worker -bmi.bmiHeader.biHeight, image, &bmi, DIB_RGB_COLORS,
290*d9f75844SAndroid Build Coastguard Worker SRCCOPY);
291*d9f75844SAndroid Build Coastguard Worker }
292*d9f75844SAndroid Build Coastguard Worker
293*d9f75844SAndroid Build Coastguard Worker BitBlt(ps.hdc, 0, 0, logical_area.x, logical_area.y, dc_mem, 0, 0,
294*d9f75844SAndroid Build Coastguard Worker SRCCOPY);
295*d9f75844SAndroid Build Coastguard Worker
296*d9f75844SAndroid Build Coastguard Worker // Cleanup.
297*d9f75844SAndroid Build Coastguard Worker ::SelectObject(dc_mem, bmp_old);
298*d9f75844SAndroid Build Coastguard Worker ::DeleteObject(bmp_mem);
299*d9f75844SAndroid Build Coastguard Worker ::DeleteDC(dc_mem);
300*d9f75844SAndroid Build Coastguard Worker } else {
301*d9f75844SAndroid Build Coastguard Worker // We're still waiting for the video stream to be initialized.
302*d9f75844SAndroid Build Coastguard Worker HBRUSH brush = ::CreateSolidBrush(RGB(0, 0, 0));
303*d9f75844SAndroid Build Coastguard Worker ::FillRect(ps.hdc, &rc, brush);
304*d9f75844SAndroid Build Coastguard Worker ::DeleteObject(brush);
305*d9f75844SAndroid Build Coastguard Worker
306*d9f75844SAndroid Build Coastguard Worker HGDIOBJ old_font = ::SelectObject(ps.hdc, GetDefaultFont());
307*d9f75844SAndroid Build Coastguard Worker ::SetTextColor(ps.hdc, RGB(0xff, 0xff, 0xff));
308*d9f75844SAndroid Build Coastguard Worker ::SetBkMode(ps.hdc, TRANSPARENT);
309*d9f75844SAndroid Build Coastguard Worker
310*d9f75844SAndroid Build Coastguard Worker std::string text(kConnecting);
311*d9f75844SAndroid Build Coastguard Worker if (!local_renderer->image()) {
312*d9f75844SAndroid Build Coastguard Worker text += kNoVideoStreams;
313*d9f75844SAndroid Build Coastguard Worker } else {
314*d9f75844SAndroid Build Coastguard Worker text += kNoIncomingStream;
315*d9f75844SAndroid Build Coastguard Worker }
316*d9f75844SAndroid Build Coastguard Worker ::DrawTextA(ps.hdc, text.c_str(), -1, &rc,
317*d9f75844SAndroid Build Coastguard Worker DT_SINGLELINE | DT_CENTER | DT_VCENTER);
318*d9f75844SAndroid Build Coastguard Worker ::SelectObject(ps.hdc, old_font);
319*d9f75844SAndroid Build Coastguard Worker }
320*d9f75844SAndroid Build Coastguard Worker } else {
321*d9f75844SAndroid Build Coastguard Worker HBRUSH brush = ::CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
322*d9f75844SAndroid Build Coastguard Worker ::FillRect(ps.hdc, &rc, brush);
323*d9f75844SAndroid Build Coastguard Worker ::DeleteObject(brush);
324*d9f75844SAndroid Build Coastguard Worker }
325*d9f75844SAndroid Build Coastguard Worker
326*d9f75844SAndroid Build Coastguard Worker ::EndPaint(handle(), &ps);
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker
OnDestroyed()329*d9f75844SAndroid Build Coastguard Worker void MainWnd::OnDestroyed() {
330*d9f75844SAndroid Build Coastguard Worker PostQuitMessage(0);
331*d9f75844SAndroid Build Coastguard Worker }
332*d9f75844SAndroid Build Coastguard Worker
OnDefaultAction()333*d9f75844SAndroid Build Coastguard Worker void MainWnd::OnDefaultAction() {
334*d9f75844SAndroid Build Coastguard Worker if (!callback_)
335*d9f75844SAndroid Build Coastguard Worker return;
336*d9f75844SAndroid Build Coastguard Worker if (ui_ == CONNECT_TO_SERVER) {
337*d9f75844SAndroid Build Coastguard Worker std::string server(GetWindowText(edit1_));
338*d9f75844SAndroid Build Coastguard Worker std::string port_str(GetWindowText(edit2_));
339*d9f75844SAndroid Build Coastguard Worker int port = port_str.length() ? atoi(port_str.c_str()) : 0;
340*d9f75844SAndroid Build Coastguard Worker callback_->StartLogin(server, port);
341*d9f75844SAndroid Build Coastguard Worker } else if (ui_ == LIST_PEERS) {
342*d9f75844SAndroid Build Coastguard Worker LRESULT sel = ::SendMessage(listbox_, LB_GETCURSEL, 0, 0);
343*d9f75844SAndroid Build Coastguard Worker if (sel != LB_ERR) {
344*d9f75844SAndroid Build Coastguard Worker LRESULT peer_id = ::SendMessage(listbox_, LB_GETITEMDATA, sel, 0);
345*d9f75844SAndroid Build Coastguard Worker if (peer_id != -1 && callback_) {
346*d9f75844SAndroid Build Coastguard Worker callback_->ConnectToPeer(peer_id);
347*d9f75844SAndroid Build Coastguard Worker }
348*d9f75844SAndroid Build Coastguard Worker }
349*d9f75844SAndroid Build Coastguard Worker } else {
350*d9f75844SAndroid Build Coastguard Worker ::MessageBoxA(wnd_, "OK!", "Yeah", MB_OK);
351*d9f75844SAndroid Build Coastguard Worker }
352*d9f75844SAndroid Build Coastguard Worker }
353*d9f75844SAndroid Build Coastguard Worker
OnMessage(UINT msg,WPARAM wp,LPARAM lp,LRESULT * result)354*d9f75844SAndroid Build Coastguard Worker bool MainWnd::OnMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT* result) {
355*d9f75844SAndroid Build Coastguard Worker switch (msg) {
356*d9f75844SAndroid Build Coastguard Worker case WM_ERASEBKGND:
357*d9f75844SAndroid Build Coastguard Worker *result = TRUE;
358*d9f75844SAndroid Build Coastguard Worker return true;
359*d9f75844SAndroid Build Coastguard Worker
360*d9f75844SAndroid Build Coastguard Worker case WM_PAINT:
361*d9f75844SAndroid Build Coastguard Worker OnPaint();
362*d9f75844SAndroid Build Coastguard Worker return true;
363*d9f75844SAndroid Build Coastguard Worker
364*d9f75844SAndroid Build Coastguard Worker case WM_SETFOCUS:
365*d9f75844SAndroid Build Coastguard Worker if (ui_ == CONNECT_TO_SERVER) {
366*d9f75844SAndroid Build Coastguard Worker SetFocus(edit1_);
367*d9f75844SAndroid Build Coastguard Worker } else if (ui_ == LIST_PEERS) {
368*d9f75844SAndroid Build Coastguard Worker SetFocus(listbox_);
369*d9f75844SAndroid Build Coastguard Worker }
370*d9f75844SAndroid Build Coastguard Worker return true;
371*d9f75844SAndroid Build Coastguard Worker
372*d9f75844SAndroid Build Coastguard Worker case WM_SIZE:
373*d9f75844SAndroid Build Coastguard Worker if (ui_ == CONNECT_TO_SERVER) {
374*d9f75844SAndroid Build Coastguard Worker LayoutConnectUI(true);
375*d9f75844SAndroid Build Coastguard Worker } else if (ui_ == LIST_PEERS) {
376*d9f75844SAndroid Build Coastguard Worker LayoutPeerListUI(true);
377*d9f75844SAndroid Build Coastguard Worker }
378*d9f75844SAndroid Build Coastguard Worker break;
379*d9f75844SAndroid Build Coastguard Worker
380*d9f75844SAndroid Build Coastguard Worker case WM_CTLCOLORSTATIC:
381*d9f75844SAndroid Build Coastguard Worker *result = reinterpret_cast<LRESULT>(GetSysColorBrush(COLOR_WINDOW));
382*d9f75844SAndroid Build Coastguard Worker return true;
383*d9f75844SAndroid Build Coastguard Worker
384*d9f75844SAndroid Build Coastguard Worker case WM_COMMAND:
385*d9f75844SAndroid Build Coastguard Worker if (button_ == reinterpret_cast<HWND>(lp)) {
386*d9f75844SAndroid Build Coastguard Worker if (BN_CLICKED == HIWORD(wp))
387*d9f75844SAndroid Build Coastguard Worker OnDefaultAction();
388*d9f75844SAndroid Build Coastguard Worker } else if (listbox_ == reinterpret_cast<HWND>(lp)) {
389*d9f75844SAndroid Build Coastguard Worker if (LBN_DBLCLK == HIWORD(wp)) {
390*d9f75844SAndroid Build Coastguard Worker OnDefaultAction();
391*d9f75844SAndroid Build Coastguard Worker }
392*d9f75844SAndroid Build Coastguard Worker }
393*d9f75844SAndroid Build Coastguard Worker return true;
394*d9f75844SAndroid Build Coastguard Worker
395*d9f75844SAndroid Build Coastguard Worker case WM_CLOSE:
396*d9f75844SAndroid Build Coastguard Worker if (callback_)
397*d9f75844SAndroid Build Coastguard Worker callback_->Close();
398*d9f75844SAndroid Build Coastguard Worker break;
399*d9f75844SAndroid Build Coastguard Worker }
400*d9f75844SAndroid Build Coastguard Worker return false;
401*d9f75844SAndroid Build Coastguard Worker }
402*d9f75844SAndroid Build Coastguard Worker
403*d9f75844SAndroid Build Coastguard Worker // static
WndProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)404*d9f75844SAndroid Build Coastguard Worker LRESULT CALLBACK MainWnd::WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
405*d9f75844SAndroid Build Coastguard Worker MainWnd* me =
406*d9f75844SAndroid Build Coastguard Worker reinterpret_cast<MainWnd*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
407*d9f75844SAndroid Build Coastguard Worker if (!me && WM_CREATE == msg) {
408*d9f75844SAndroid Build Coastguard Worker CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lp);
409*d9f75844SAndroid Build Coastguard Worker me = reinterpret_cast<MainWnd*>(cs->lpCreateParams);
410*d9f75844SAndroid Build Coastguard Worker me->wnd_ = hwnd;
411*d9f75844SAndroid Build Coastguard Worker ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(me));
412*d9f75844SAndroid Build Coastguard Worker }
413*d9f75844SAndroid Build Coastguard Worker
414*d9f75844SAndroid Build Coastguard Worker LRESULT result = 0;
415*d9f75844SAndroid Build Coastguard Worker if (me) {
416*d9f75844SAndroid Build Coastguard Worker void* prev_nested_msg = me->nested_msg_;
417*d9f75844SAndroid Build Coastguard Worker me->nested_msg_ = &msg;
418*d9f75844SAndroid Build Coastguard Worker
419*d9f75844SAndroid Build Coastguard Worker bool handled = me->OnMessage(msg, wp, lp, &result);
420*d9f75844SAndroid Build Coastguard Worker if (WM_NCDESTROY == msg) {
421*d9f75844SAndroid Build Coastguard Worker me->destroyed_ = true;
422*d9f75844SAndroid Build Coastguard Worker } else if (!handled) {
423*d9f75844SAndroid Build Coastguard Worker result = ::DefWindowProc(hwnd, msg, wp, lp);
424*d9f75844SAndroid Build Coastguard Worker }
425*d9f75844SAndroid Build Coastguard Worker
426*d9f75844SAndroid Build Coastguard Worker if (me->destroyed_ && prev_nested_msg == NULL) {
427*d9f75844SAndroid Build Coastguard Worker me->OnDestroyed();
428*d9f75844SAndroid Build Coastguard Worker me->wnd_ = NULL;
429*d9f75844SAndroid Build Coastguard Worker me->destroyed_ = false;
430*d9f75844SAndroid Build Coastguard Worker }
431*d9f75844SAndroid Build Coastguard Worker
432*d9f75844SAndroid Build Coastguard Worker me->nested_msg_ = prev_nested_msg;
433*d9f75844SAndroid Build Coastguard Worker } else {
434*d9f75844SAndroid Build Coastguard Worker result = ::DefWindowProc(hwnd, msg, wp, lp);
435*d9f75844SAndroid Build Coastguard Worker }
436*d9f75844SAndroid Build Coastguard Worker
437*d9f75844SAndroid Build Coastguard Worker return result;
438*d9f75844SAndroid Build Coastguard Worker }
439*d9f75844SAndroid Build Coastguard Worker
440*d9f75844SAndroid Build Coastguard Worker // static
RegisterWindowClass()441*d9f75844SAndroid Build Coastguard Worker bool MainWnd::RegisterWindowClass() {
442*d9f75844SAndroid Build Coastguard Worker if (wnd_class_)
443*d9f75844SAndroid Build Coastguard Worker return true;
444*d9f75844SAndroid Build Coastguard Worker
445*d9f75844SAndroid Build Coastguard Worker WNDCLASSEXW wcex = {sizeof(WNDCLASSEX)};
446*d9f75844SAndroid Build Coastguard Worker wcex.style = CS_DBLCLKS;
447*d9f75844SAndroid Build Coastguard Worker wcex.hInstance = GetModuleHandle(NULL);
448*d9f75844SAndroid Build Coastguard Worker wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
449*d9f75844SAndroid Build Coastguard Worker wcex.hCursor = ::LoadCursor(NULL, IDC_ARROW);
450*d9f75844SAndroid Build Coastguard Worker wcex.lpfnWndProc = &WndProc;
451*d9f75844SAndroid Build Coastguard Worker wcex.lpszClassName = kClassName;
452*d9f75844SAndroid Build Coastguard Worker wnd_class_ = ::RegisterClassExW(&wcex);
453*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(wnd_class_ != 0);
454*d9f75844SAndroid Build Coastguard Worker return wnd_class_ != 0;
455*d9f75844SAndroid Build Coastguard Worker }
456*d9f75844SAndroid Build Coastguard Worker
CreateChildWindow(HWND * wnd,MainWnd::ChildWindowID id,const wchar_t * class_name,DWORD control_style,DWORD ex_style)457*d9f75844SAndroid Build Coastguard Worker void MainWnd::CreateChildWindow(HWND* wnd,
458*d9f75844SAndroid Build Coastguard Worker MainWnd::ChildWindowID id,
459*d9f75844SAndroid Build Coastguard Worker const wchar_t* class_name,
460*d9f75844SAndroid Build Coastguard Worker DWORD control_style,
461*d9f75844SAndroid Build Coastguard Worker DWORD ex_style) {
462*d9f75844SAndroid Build Coastguard Worker if (::IsWindow(*wnd))
463*d9f75844SAndroid Build Coastguard Worker return;
464*d9f75844SAndroid Build Coastguard Worker
465*d9f75844SAndroid Build Coastguard Worker // Child windows are invisible at first, and shown after being resized.
466*d9f75844SAndroid Build Coastguard Worker DWORD style = WS_CHILD | control_style;
467*d9f75844SAndroid Build Coastguard Worker *wnd = ::CreateWindowExW(ex_style, class_name, L"", style, 100, 100, 100, 100,
468*d9f75844SAndroid Build Coastguard Worker wnd_, reinterpret_cast<HMENU>(id),
469*d9f75844SAndroid Build Coastguard Worker GetModuleHandle(NULL), NULL);
470*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(::IsWindow(*wnd) != FALSE);
471*d9f75844SAndroid Build Coastguard Worker ::SendMessage(*wnd, WM_SETFONT, reinterpret_cast<WPARAM>(GetDefaultFont()),
472*d9f75844SAndroid Build Coastguard Worker TRUE);
473*d9f75844SAndroid Build Coastguard Worker }
474*d9f75844SAndroid Build Coastguard Worker
CreateChildWindows()475*d9f75844SAndroid Build Coastguard Worker void MainWnd::CreateChildWindows() {
476*d9f75844SAndroid Build Coastguard Worker // Create the child windows in tab order.
477*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&label1_, LABEL1_ID, L"Static", ES_CENTER | ES_READONLY, 0);
478*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&edit1_, EDIT_ID, L"Edit",
479*d9f75844SAndroid Build Coastguard Worker ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, WS_EX_CLIENTEDGE);
480*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&label2_, LABEL2_ID, L"Static", ES_CENTER | ES_READONLY, 0);
481*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&edit2_, EDIT_ID, L"Edit",
482*d9f75844SAndroid Build Coastguard Worker ES_LEFT | ES_NOHIDESEL | WS_TABSTOP, WS_EX_CLIENTEDGE);
483*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&button_, BUTTON_ID, L"Button", BS_CENTER | WS_TABSTOP, 0);
484*d9f75844SAndroid Build Coastguard Worker
485*d9f75844SAndroid Build Coastguard Worker CreateChildWindow(&listbox_, LISTBOX_ID, L"ListBox",
486*d9f75844SAndroid Build Coastguard Worker LBS_HASSTRINGS | LBS_NOTIFY, WS_EX_CLIENTEDGE);
487*d9f75844SAndroid Build Coastguard Worker
488*d9f75844SAndroid Build Coastguard Worker ::SetWindowTextA(edit1_, server_.c_str());
489*d9f75844SAndroid Build Coastguard Worker ::SetWindowTextA(edit2_, port_.c_str());
490*d9f75844SAndroid Build Coastguard Worker }
491*d9f75844SAndroid Build Coastguard Worker
LayoutConnectUI(bool show)492*d9f75844SAndroid Build Coastguard Worker void MainWnd::LayoutConnectUI(bool show) {
493*d9f75844SAndroid Build Coastguard Worker struct Windows {
494*d9f75844SAndroid Build Coastguard Worker HWND wnd;
495*d9f75844SAndroid Build Coastguard Worker const wchar_t* text;
496*d9f75844SAndroid Build Coastguard Worker size_t width;
497*d9f75844SAndroid Build Coastguard Worker size_t height;
498*d9f75844SAndroid Build Coastguard Worker } windows[] = {
499*d9f75844SAndroid Build Coastguard Worker {label1_, L"Server"}, {edit1_, L"XXXyyyYYYgggXXXyyyYYYggg"},
500*d9f75844SAndroid Build Coastguard Worker {label2_, L":"}, {edit2_, L"XyXyX"},
501*d9f75844SAndroid Build Coastguard Worker {button_, L"Connect"},
502*d9f75844SAndroid Build Coastguard Worker };
503*d9f75844SAndroid Build Coastguard Worker
504*d9f75844SAndroid Build Coastguard Worker if (show) {
505*d9f75844SAndroid Build Coastguard Worker const size_t kSeparator = 5;
506*d9f75844SAndroid Build Coastguard Worker size_t total_width = (ARRAYSIZE(windows) - 1) * kSeparator;
507*d9f75844SAndroid Build Coastguard Worker
508*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAYSIZE(windows); ++i) {
509*d9f75844SAndroid Build Coastguard Worker CalculateWindowSizeForText(windows[i].wnd, windows[i].text,
510*d9f75844SAndroid Build Coastguard Worker &windows[i].width, &windows[i].height);
511*d9f75844SAndroid Build Coastguard Worker total_width += windows[i].width;
512*d9f75844SAndroid Build Coastguard Worker }
513*d9f75844SAndroid Build Coastguard Worker
514*d9f75844SAndroid Build Coastguard Worker RECT rc;
515*d9f75844SAndroid Build Coastguard Worker ::GetClientRect(wnd_, &rc);
516*d9f75844SAndroid Build Coastguard Worker size_t x = (rc.right / 2) - (total_width / 2);
517*d9f75844SAndroid Build Coastguard Worker size_t y = rc.bottom / 2;
518*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAYSIZE(windows); ++i) {
519*d9f75844SAndroid Build Coastguard Worker size_t top = y - (windows[i].height / 2);
520*d9f75844SAndroid Build Coastguard Worker ::MoveWindow(windows[i].wnd, static_cast<int>(x), static_cast<int>(top),
521*d9f75844SAndroid Build Coastguard Worker static_cast<int>(windows[i].width),
522*d9f75844SAndroid Build Coastguard Worker static_cast<int>(windows[i].height), TRUE);
523*d9f75844SAndroid Build Coastguard Worker x += kSeparator + windows[i].width;
524*d9f75844SAndroid Build Coastguard Worker if (windows[i].text[0] != 'X')
525*d9f75844SAndroid Build Coastguard Worker ::SetWindowTextW(windows[i].wnd, windows[i].text);
526*d9f75844SAndroid Build Coastguard Worker ::ShowWindow(windows[i].wnd, SW_SHOWNA);
527*d9f75844SAndroid Build Coastguard Worker }
528*d9f75844SAndroid Build Coastguard Worker } else {
529*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAYSIZE(windows); ++i) {
530*d9f75844SAndroid Build Coastguard Worker ::ShowWindow(windows[i].wnd, SW_HIDE);
531*d9f75844SAndroid Build Coastguard Worker }
532*d9f75844SAndroid Build Coastguard Worker }
533*d9f75844SAndroid Build Coastguard Worker }
534*d9f75844SAndroid Build Coastguard Worker
LayoutPeerListUI(bool show)535*d9f75844SAndroid Build Coastguard Worker void MainWnd::LayoutPeerListUI(bool show) {
536*d9f75844SAndroid Build Coastguard Worker if (show) {
537*d9f75844SAndroid Build Coastguard Worker RECT rc;
538*d9f75844SAndroid Build Coastguard Worker ::GetClientRect(wnd_, &rc);
539*d9f75844SAndroid Build Coastguard Worker ::MoveWindow(listbox_, 0, 0, rc.right, rc.bottom, TRUE);
540*d9f75844SAndroid Build Coastguard Worker ::ShowWindow(listbox_, SW_SHOWNA);
541*d9f75844SAndroid Build Coastguard Worker } else {
542*d9f75844SAndroid Build Coastguard Worker ::ShowWindow(listbox_, SW_HIDE);
543*d9f75844SAndroid Build Coastguard Worker InvalidateRect(wnd_, NULL, TRUE);
544*d9f75844SAndroid Build Coastguard Worker }
545*d9f75844SAndroid Build Coastguard Worker }
546*d9f75844SAndroid Build Coastguard Worker
HandleTabbing()547*d9f75844SAndroid Build Coastguard Worker void MainWnd::HandleTabbing() {
548*d9f75844SAndroid Build Coastguard Worker bool shift = ((::GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
549*d9f75844SAndroid Build Coastguard Worker UINT next_cmd = shift ? GW_HWNDPREV : GW_HWNDNEXT;
550*d9f75844SAndroid Build Coastguard Worker UINT loop_around_cmd = shift ? GW_HWNDLAST : GW_HWNDFIRST;
551*d9f75844SAndroid Build Coastguard Worker HWND focus = GetFocus(), next;
552*d9f75844SAndroid Build Coastguard Worker do {
553*d9f75844SAndroid Build Coastguard Worker next = ::GetWindow(focus, next_cmd);
554*d9f75844SAndroid Build Coastguard Worker if (IsWindowVisible(next) &&
555*d9f75844SAndroid Build Coastguard Worker (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP)) {
556*d9f75844SAndroid Build Coastguard Worker break;
557*d9f75844SAndroid Build Coastguard Worker }
558*d9f75844SAndroid Build Coastguard Worker
559*d9f75844SAndroid Build Coastguard Worker if (!next) {
560*d9f75844SAndroid Build Coastguard Worker next = ::GetWindow(focus, loop_around_cmd);
561*d9f75844SAndroid Build Coastguard Worker if (IsWindowVisible(next) &&
562*d9f75844SAndroid Build Coastguard Worker (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP)) {
563*d9f75844SAndroid Build Coastguard Worker break;
564*d9f75844SAndroid Build Coastguard Worker }
565*d9f75844SAndroid Build Coastguard Worker }
566*d9f75844SAndroid Build Coastguard Worker focus = next;
567*d9f75844SAndroid Build Coastguard Worker } while (true);
568*d9f75844SAndroid Build Coastguard Worker ::SetFocus(next);
569*d9f75844SAndroid Build Coastguard Worker }
570*d9f75844SAndroid Build Coastguard Worker
571*d9f75844SAndroid Build Coastguard Worker //
572*d9f75844SAndroid Build Coastguard Worker // MainWnd::VideoRenderer
573*d9f75844SAndroid Build Coastguard Worker //
574*d9f75844SAndroid Build Coastguard Worker
VideoRenderer(HWND wnd,int width,int height,webrtc::VideoTrackInterface * track_to_render)575*d9f75844SAndroid Build Coastguard Worker MainWnd::VideoRenderer::VideoRenderer(
576*d9f75844SAndroid Build Coastguard Worker HWND wnd,
577*d9f75844SAndroid Build Coastguard Worker int width,
578*d9f75844SAndroid Build Coastguard Worker int height,
579*d9f75844SAndroid Build Coastguard Worker webrtc::VideoTrackInterface* track_to_render)
580*d9f75844SAndroid Build Coastguard Worker : wnd_(wnd), rendered_track_(track_to_render) {
581*d9f75844SAndroid Build Coastguard Worker ::InitializeCriticalSection(&buffer_lock_);
582*d9f75844SAndroid Build Coastguard Worker ZeroMemory(&bmi_, sizeof(bmi_));
583*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
584*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biPlanes = 1;
585*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biBitCount = 32;
586*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biCompression = BI_RGB;
587*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biWidth = width;
588*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biHeight = -height;
589*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biSizeImage =
590*d9f75844SAndroid Build Coastguard Worker width * height * (bmi_.bmiHeader.biBitCount >> 3);
591*d9f75844SAndroid Build Coastguard Worker rendered_track_->AddOrUpdateSink(this, rtc::VideoSinkWants());
592*d9f75844SAndroid Build Coastguard Worker }
593*d9f75844SAndroid Build Coastguard Worker
~VideoRenderer()594*d9f75844SAndroid Build Coastguard Worker MainWnd::VideoRenderer::~VideoRenderer() {
595*d9f75844SAndroid Build Coastguard Worker rendered_track_->RemoveSink(this);
596*d9f75844SAndroid Build Coastguard Worker ::DeleteCriticalSection(&buffer_lock_);
597*d9f75844SAndroid Build Coastguard Worker }
598*d9f75844SAndroid Build Coastguard Worker
SetSize(int width,int height)599*d9f75844SAndroid Build Coastguard Worker void MainWnd::VideoRenderer::SetSize(int width, int height) {
600*d9f75844SAndroid Build Coastguard Worker AutoLock<VideoRenderer> lock(this);
601*d9f75844SAndroid Build Coastguard Worker
602*d9f75844SAndroid Build Coastguard Worker if (width == bmi_.bmiHeader.biWidth && height == bmi_.bmiHeader.biHeight) {
603*d9f75844SAndroid Build Coastguard Worker return;
604*d9f75844SAndroid Build Coastguard Worker }
605*d9f75844SAndroid Build Coastguard Worker
606*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biWidth = width;
607*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biHeight = -height;
608*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biSizeImage =
609*d9f75844SAndroid Build Coastguard Worker width * height * (bmi_.bmiHeader.biBitCount >> 3);
610*d9f75844SAndroid Build Coastguard Worker image_.reset(new uint8_t[bmi_.bmiHeader.biSizeImage]);
611*d9f75844SAndroid Build Coastguard Worker }
612*d9f75844SAndroid Build Coastguard Worker
OnFrame(const webrtc::VideoFrame & video_frame)613*d9f75844SAndroid Build Coastguard Worker void MainWnd::VideoRenderer::OnFrame(const webrtc::VideoFrame& video_frame) {
614*d9f75844SAndroid Build Coastguard Worker {
615*d9f75844SAndroid Build Coastguard Worker AutoLock<VideoRenderer> lock(this);
616*d9f75844SAndroid Build Coastguard Worker
617*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<webrtc::I420BufferInterface> buffer(
618*d9f75844SAndroid Build Coastguard Worker video_frame.video_frame_buffer()->ToI420());
619*d9f75844SAndroid Build Coastguard Worker if (video_frame.rotation() != webrtc::kVideoRotation_0) {
620*d9f75844SAndroid Build Coastguard Worker buffer = webrtc::I420Buffer::Rotate(*buffer, video_frame.rotation());
621*d9f75844SAndroid Build Coastguard Worker }
622*d9f75844SAndroid Build Coastguard Worker
623*d9f75844SAndroid Build Coastguard Worker SetSize(buffer->width(), buffer->height());
624*d9f75844SAndroid Build Coastguard Worker
625*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(image_.get() != NULL);
626*d9f75844SAndroid Build Coastguard Worker libyuv::I420ToARGB(buffer->DataY(), buffer->StrideY(), buffer->DataU(),
627*d9f75844SAndroid Build Coastguard Worker buffer->StrideU(), buffer->DataV(), buffer->StrideV(),
628*d9f75844SAndroid Build Coastguard Worker image_.get(),
629*d9f75844SAndroid Build Coastguard Worker bmi_.bmiHeader.biWidth * bmi_.bmiHeader.biBitCount / 8,
630*d9f75844SAndroid Build Coastguard Worker buffer->width(), buffer->height());
631*d9f75844SAndroid Build Coastguard Worker }
632*d9f75844SAndroid Build Coastguard Worker InvalidateRect(wnd_, NULL, TRUE);
633*d9f75844SAndroid Build Coastguard Worker }
634