15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/platform_window/win/win_window.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/event.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/events/event_utils.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/win/msg_util.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/platform_window/platform_window_delegate.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace ui {
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool use_popup_as_root_window_for_test = false;
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)gfx::Rect GetWindowBoundsForClientBounds(DWORD style, DWORD ex_style,
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         const gfx::Rect& bounds) {
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RECT wr;
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  wr.left = bounds.x();
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  wr.top = bounds.y();
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  wr.right = bounds.x() + bounds.width();
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  wr.bottom = bounds.y() + bounds.height();
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  AdjustWindowRectEx(&wr, style, FALSE, ex_style);
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Make sure to keep the window onscreen, as AdjustWindowRectEx() may have
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // moved part of it offscreen.
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect window_bounds(wr.left, wr.top,
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          wr.right - wr.left, wr.bottom - wr.top);
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  window_bounds.set_x(std::max(0, window_bounds.x()));
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  window_bounds.set_y(std::max(0, window_bounds.y()));
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return window_bounds;
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WinWindow::WinWindow(PlatformWindowDelegate* delegate,
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     const gfx::Rect& bounds)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : delegate_(delegate) {
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CHECK(delegate_);
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (use_popup_as_root_window_for_test)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    set_window_style(WS_POPUP);
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect window_bounds = GetWindowBoundsForClientBounds(
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      WS_OVERLAPPEDWINDOW, window_ex_style(), bounds);
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::WindowImpl::Init(NULL, window_bounds);
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetWindowText(hwnd(), L"WinWindow");
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)WinWindow::~WinWindow() {
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Destroy();
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Destroy() {
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsWindow(hwnd()))
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DestroyWindow(hwnd());
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Show() {
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ShowWindow(hwnd(), SW_SHOWNORMAL);
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Hide() {
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ShowWindow(hwnd(), SW_HIDE);
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Close() {
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Destroy();
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::SetBounds(const gfx::Rect& bounds) {
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect window_bounds = GetWindowBoundsForClientBounds(
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetWindowLong(hwnd(), GWL_STYLE),
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetWindowLong(hwnd(), GWL_EXSTYLE),
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bounds);
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetWindowPos(hwnd(), NULL, window_bounds.x(), window_bounds.y(),
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               window_bounds.width(), window_bounds.height(),
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               SWP_NOREPOSITION);
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)gfx::Rect WinWindow::GetBounds() {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RECT cr;
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetClientRect(hwnd(), &cr);
845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return gfx::Rect(cr);
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::SetCapture() {
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(::GetCapture() != hwnd());
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ::SetCapture(hwnd());
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::ReleaseCapture() {
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (::GetCapture() == hwnd())
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ::ReleaseCapture();
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::ToggleFullscreen() {}
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Maximize() {}
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Minimize() {}
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::Restore() {}
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::SetCursor(PlatformCursor cursor) {}
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::MoveCursorTo(const gfx::Point& location) {}
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LRESULT WinWindow::OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) {
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MSG msg = { hwnd(), message, w_param, l_param, 0,
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MouseEvent event(msg);
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (IsMouseEventFromTouch(message))
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    event.set_flags(event.flags() | EF_FROM_TOUCH);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!(event.flags() & ui::EF_IS_NON_CLIENT))
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->DispatchEvent(&event);
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetMsgHandled(event.handled());
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LRESULT WinWindow::OnCaptureChanged(UINT message,
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    WPARAM w_param,
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                    LPARAM l_param) {
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnLostCapture();
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LRESULT WinWindow::OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param) {
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MSG msg = { hwnd(), message, w_param, l_param };
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  KeyEvent event(msg);
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->DispatchEvent(&event);
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetMsgHandled(event.handled());
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LRESULT WinWindow::OnNCActivate(UINT message, WPARAM w_param, LPARAM l_param) {
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnActivationChanged(!!w_param);
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return DefWindowProc(hwnd(), message, w_param, l_param);
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::OnClose() {
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnCloseRequest();
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LRESULT WinWindow::OnCreate(CREATESTRUCT* create_struct) {
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnAcceleratedWidgetAvailable(hwnd());
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return 0;
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::OnDestroy() {
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnClosed();
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::OnPaint(HDC) {
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Rect damage_rect;
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RECT update_rect = {0};
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (GetUpdateRect(hwnd(), &update_rect, FALSE))
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    damage_rect = gfx::Rect(update_rect);
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  delegate_->OnDamageRect(damage_rect);
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ValidateRect(hwnd(), NULL);
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WinWindow::OnWindowPosChanged(WINDOWPOS* window_pos) {
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!(window_pos->flags & SWP_NOSIZE) ||
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      !(window_pos->flags & SWP_NOMOVE)) {
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RECT cr;
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GetClientRect(hwnd(), &cr);
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    delegate_->OnBoundsChanged(
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        gfx::Rect(window_pos->x, window_pos->y,
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  cr.right - cr.left, cr.bottom - cr.top));
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace test {
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SetUsePopupAsRootWindowForTest(bool use) {
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  use_popup_as_root_window_for_test = use;
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace test
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace ui
183