This source file includes following definitions.
- GetControlText
- GetControlTextWidth
- border_pen_
- Start
- DialogProc
- OnDialogMessage
- BeginDialog
- EndDialog
- GetControlRect
- SetDialogPosition
- SetStrings
- CreateDisconnectWindow
#include <windows.h>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/process/memory.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "remoting/host/client_session_control.h"
#include "remoting/host/host_window.h"
#include "remoting/host/win/core_resource.h"
namespace remoting {
namespace {
const int DISCONNECT_HOTKEY_ID = 1000;
const size_t kMaxSharingWithTextLength = 100;
const wchar_t kShellTrayWindowName[] = L"Shell_TrayWnd";
const int kWindowBorderRadius = 14;
const int kWindowTextMargin = 8;
class DisconnectWindowWin : public HostWindow {
public:
DisconnectWindowWin();
virtual ~DisconnectWindowWin();
virtual void Start(
const base::WeakPtr<ClientSessionControl>& client_session_control)
OVERRIDE;
protected:
static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wparam,
LPARAM lparam);
BOOL OnDialogMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
bool BeginDialog();
void EndDialog();
bool GetControlRect(HWND control, RECT* rect);
void SetDialogPosition();
bool SetStrings();
base::WeakPtr<ClientSessionControl> client_session_control_;
std::string username_;
HWND hwnd_;
bool has_hotkey_;
base::win::ScopedGDIObject<HPEN> border_pen_;
DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin);
};
bool GetControlText(HWND control, base::string16* text) {
WCHAR buffer[256];
int result = GetWindowText(control, buffer, arraysize(buffer));
if (!result)
return false;
text->assign(buffer);
return true;
}
bool GetControlTextWidth(HWND control,
const base::string16& text,
LONG* width) {
RECT rect = {0, 0, 0, 0};
base::win::ScopedGetDC dc(control);
base::win::ScopedSelectObject font(
dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
if (!DrawText(dc, text.c_str(), -1, &rect, DT_CALCRECT | DT_SINGLELINE))
return false;
*width = rect.right;
return true;
}
DisconnectWindowWin::DisconnectWindowWin()
: hwnd_(NULL),
has_hotkey_(false),
border_pen_(CreatePen(PS_SOLID, 5,
RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) {
}
DisconnectWindowWin::~DisconnectWindowWin() {
EndDialog();
}
void DisconnectWindowWin::Start(
const base::WeakPtr<ClientSessionControl>& client_session_control) {
DCHECK(CalledOnValidThread());
DCHECK(!client_session_control_);
DCHECK(client_session_control);
client_session_control_ = client_session_control;
std::string client_jid = client_session_control_->client_jid();
username_ = client_jid.substr(0, client_jid.find('/'));
if (!BeginDialog())
EndDialog();
}
INT_PTR CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
LONG_PTR self = NULL;
if (message == WM_INITDIALOG) {
self = lparam;
SetLastError(ERROR_SUCCESS);
LONG_PTR result = SetWindowLongPtr(hwnd, DWLP_USER, self);
if (result == 0 && GetLastError() != ERROR_SUCCESS)
reinterpret_cast<DisconnectWindowWin*>(self)->EndDialog();
} else {
self = GetWindowLongPtr(hwnd, DWLP_USER);
}
if (self) {
return reinterpret_cast<DisconnectWindowWin*>(self)->OnDialogMessage(
hwnd, message, wparam, lparam);
}
return FALSE;
}
BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
DCHECK(CalledOnValidThread());
switch (message) {
case WM_CLOSE:
return TRUE;
case WM_COMMAND:
switch (LOWORD(wparam)) {
case IDC_DISCONNECT:
EndDialog();
return TRUE;
}
return FALSE;
case WM_DESTROY:
hwnd_ = NULL;
EndDialog();
return TRUE;
case WM_SETTINGCHANGE:
if (wparam == SPI_SETWORKAREA)
SetDialogPosition();
return TRUE;
case WM_DISPLAYCHANGE:
SetDialogPosition();
return TRUE;
case WM_HOTKEY:
EndDialog();
return TRUE;
case WM_NCHITTEST:
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, HTCAPTION);
return TRUE;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd_, &ps);
RECT rect;
GetClientRect(hwnd_, &rect);
{
base::win::ScopedSelectObject border(hdc, border_pen_);
base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
kWindowBorderRadius, kWindowBorderRadius);
}
EndPaint(hwnd_, &ps);
return TRUE;
}
}
return FALSE;
}
bool DisconnectWindowWin::BeginDialog() {
DCHECK(CalledOnValidThread());
DCHECK(!hwnd_);
HMODULE module = base::GetModuleFromAddress(&DialogProc);
hwnd_ = CreateDialogParam(module, MAKEINTRESOURCE(IDD_DISCONNECT), NULL,
DialogProc, reinterpret_cast<LPARAM>(this));
if (!hwnd_)
return false;
if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID,
MOD_ALT | MOD_CONTROL, VK_ESCAPE)) {
has_hotkey_ = true;
}
if (!SetStrings())
return false;
SetDialogPosition();
ShowWindow(hwnd_, SW_SHOW);
return IsWindowVisible(hwnd_) != FALSE;
}
void DisconnectWindowWin::EndDialog() {
DCHECK(CalledOnValidThread());
if (has_hotkey_) {
UnregisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID);
has_hotkey_ = false;
}
if (hwnd_) {
DestroyWindow(hwnd_);
hwnd_ = NULL;
}
if (client_session_control_)
client_session_control_->DisconnectSession();
}
bool DisconnectWindowWin::GetControlRect(HWND control, RECT* rect) {
if (!GetWindowRect(control, rect))
return false;
SetLastError(ERROR_SUCCESS);
int result = MapWindowPoints(HWND_DESKTOP, hwnd_,
reinterpret_cast<LPPOINT>(rect), 2);
if (!result && GetLastError() != ERROR_SUCCESS)
return false;
return true;
}
void DisconnectWindowWin::SetDialogPosition() {
DCHECK(CalledOnValidThread());
HWND taskbar = FindWindow(kShellTrayWindowName, NULL);
HMONITOR monitor = MonitorFromWindow(taskbar, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO monitor_info = {sizeof(monitor_info)};
RECT window_rect;
if (GetMonitorInfo(monitor, &monitor_info) &&
GetWindowRect(hwnd_, &window_rect)) {
int window_width = window_rect.right - window_rect.left;
int window_height = window_rect.bottom - window_rect.top;
int top = monitor_info.rcWork.bottom - window_height;
int left = (monitor_info.rcWork.right + monitor_info.rcWork.left -
window_width) / 2;
SetWindowPos(hwnd_, NULL, left, top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
bool DisconnectWindowWin::SetStrings() {
DCHECK(CalledOnValidThread());
HWND hwnd_button = GetDlgItem(hwnd_, IDC_DISCONNECT);
HWND hwnd_message = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH);
if (!hwnd_button || !hwnd_message)
return false;
base::string16 button_text;
base::string16 message_text;
if (!GetControlText(hwnd_button, &button_text) ||
!GetControlText(hwnd_message, &message_text)) {
return false;
}
message_text = ReplaceStringPlaceholders(message_text,
base::UTF8ToUTF16(username_),
NULL);
if (message_text.length() > kMaxSharingWithTextLength)
message_text.erase(kMaxSharingWithTextLength);
if (!SetWindowText(hwnd_message, message_text.c_str()))
return false;
RECT rect = {0};
rect.right = kWindowTextMargin;
if (!MapDialogRect(hwnd_, &rect))
return false;
int margin = rect.right;
RECT message_rect;
if (!GetControlRect(hwnd_message, &message_rect))
return false;
LONG control_width;
if (!GetControlTextWidth(hwnd_message, message_text, &control_width))
return false;
message_rect.right = message_rect.left + control_width + margin;
if (!SetWindowPos(hwnd_message, NULL,
message_rect.left, message_rect.top,
message_rect.right - message_rect.left,
message_rect.bottom - message_rect.top,
SWP_NOZORDER)) {
return false;
}
RECT button_rect;
if (!GetControlRect(hwnd_button, &button_rect))
return false;
if (!GetControlTextWidth(hwnd_button, button_text, &control_width))
return false;
button_rect.left = message_rect.right;
button_rect.right = button_rect.left + control_width + margin * 2;
if (!SetWindowPos(hwnd_button, NULL,
button_rect.left, button_rect.top,
button_rect.right - button_rect.left,
button_rect.bottom - button_rect.top,
SWP_NOZORDER)) {
return false;
}
RECT window_rect;
if (!GetWindowRect(hwnd_, &window_rect))
return false;
int width = button_rect.right + margin;
int height = window_rect.bottom - window_rect.top;
if (!SetWindowPos(hwnd_, NULL, 0, 0, width, height,
SWP_NOMOVE | SWP_NOZORDER)) {
return false;
}
HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
kWindowBorderRadius);
if (!rgn)
return false;
if (!SetWindowRgn(hwnd_, rgn, TRUE))
return false;
return true;
}
}
scoped_ptr<HostWindow> HostWindow::CreateDisconnectWindow() {
return scoped_ptr<HostWindow>(new DisconnectWindowWin());
}
}