Home | History | Annotate | Download | only in aura
      1 // Copyright (c) 2012 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 "ui/aura/window_tree_host_win.h"
      6 
      7 #include <windows.h>
      8 
      9 #include <algorithm>
     10 
     11 #include "base/message_loop/message_loop.h"
     12 #include "ui/aura/client/cursor_client.h"
     13 #include "ui/aura/window_event_dispatcher.h"
     14 #include "ui/base/cursor/cursor_loader_win.h"
     15 #include "ui/base/view_prop.h"
     16 #include "ui/compositor/compositor.h"
     17 #include "ui/events/event.h"
     18 #include "ui/gfx/display.h"
     19 #include "ui/gfx/insets.h"
     20 #include "ui/gfx/screen.h"
     21 
     22 using std::max;
     23 using std::min;
     24 
     25 namespace aura {
     26 namespace {
     27 
     28 bool use_popup_as_root_window_for_test = false;
     29 
     30 }  // namespace
     31 
     32 // static
     33 WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
     34   return new WindowTreeHostWin(bounds);
     35 }
     36 
     37 // static
     38 gfx::Size WindowTreeHost::GetNativeScreenSize() {
     39   return gfx::Size(GetSystemMetrics(SM_CXSCREEN),
     40                    GetSystemMetrics(SM_CYSCREEN));
     41 }
     42 
     43 WindowTreeHostWin::WindowTreeHostWin(const gfx::Rect& bounds)
     44     : has_capture_(false) {
     45   if (use_popup_as_root_window_for_test)
     46     set_window_style(WS_POPUP);
     47   Init(NULL, bounds);
     48   SetWindowText(hwnd(), L"aura::RootWindow!");
     49   CreateCompositor(GetAcceleratedWidget());
     50 }
     51 
     52 WindowTreeHostWin::~WindowTreeHostWin() {
     53   DestroyCompositor();
     54   DestroyDispatcher();
     55   DestroyWindow(hwnd());
     56 }
     57 
     58 ui::EventSource* WindowTreeHostWin::GetEventSource() {
     59   return this;
     60 }
     61 
     62 gfx::AcceleratedWidget WindowTreeHostWin::GetAcceleratedWidget() {
     63   return hwnd();
     64 }
     65 
     66 void WindowTreeHostWin::Show() {
     67   ShowWindow(hwnd(), SW_SHOWNORMAL);
     68 }
     69 
     70 void WindowTreeHostWin::Hide() {
     71   NOTIMPLEMENTED();
     72 }
     73 
     74 gfx::Rect WindowTreeHostWin::GetBounds() const {
     75   RECT r;
     76   GetClientRect(hwnd(), &r);
     77   return gfx::Rect(r);
     78 }
     79 
     80 void WindowTreeHostWin::SetBounds(const gfx::Rect& bounds) {
     81   RECT window_rect;
     82   window_rect.left = bounds.x();
     83   window_rect.top = bounds.y();
     84   window_rect.right = bounds.right() ;
     85   window_rect.bottom = bounds.bottom();
     86   AdjustWindowRectEx(&window_rect,
     87                      GetWindowLong(hwnd(), GWL_STYLE),
     88                      FALSE,
     89                      GetWindowLong(hwnd(), GWL_EXSTYLE));
     90   SetWindowPos(
     91       hwnd(),
     92       NULL,
     93       window_rect.left,
     94       window_rect.top,
     95       window_rect.right - window_rect.left,
     96       window_rect.bottom - window_rect.top,
     97       SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOREPOSITION);
     98 
     99   // Explicity call OnHostResized when the scale has changed because
    100   // the window size may not have changed.
    101   float current_scale = compositor()->device_scale_factor();
    102   float new_scale = gfx::Screen::GetScreenFor(window())->
    103       GetDisplayNearestWindow(window()).device_scale_factor();
    104   if (current_scale != new_scale)
    105     OnHostResized(bounds.size());
    106 }
    107 
    108 gfx::Point WindowTreeHostWin::GetLocationOnNativeScreen() const {
    109   RECT r;
    110   GetClientRect(hwnd(), &r);
    111   return gfx::Point(r.left, r.top);
    112 }
    113 
    114 
    115 void WindowTreeHostWin::SetCapture() {
    116   if (!has_capture_) {
    117     has_capture_ = true;
    118     ::SetCapture(hwnd());
    119   }
    120 }
    121 
    122 void WindowTreeHostWin::ReleaseCapture() {
    123   if (has_capture_) {
    124     has_capture_ = false;
    125     ::ReleaseCapture();
    126   }
    127 }
    128 
    129 void WindowTreeHostWin::SetCursorNative(gfx::NativeCursor native_cursor) {
    130   // Custom web cursors are handled directly.
    131   if (native_cursor == ui::kCursorCustom)
    132     return;
    133 
    134   ui::CursorLoaderWin cursor_loader;
    135   cursor_loader.SetPlatformCursor(&native_cursor);
    136   ::SetCursor(native_cursor.platform());
    137 }
    138 
    139 void WindowTreeHostWin::MoveCursorToNative(const gfx::Point& location) {
    140   // Deliberately not implemented.
    141 }
    142 
    143 void WindowTreeHostWin::OnCursorVisibilityChangedNative(bool show) {
    144   NOTIMPLEMENTED();
    145 }
    146 
    147 void WindowTreeHostWin::PostNativeEvent(const base::NativeEvent& native_event) {
    148   ::PostMessage(
    149       hwnd(), native_event.message, native_event.wParam, native_event.lParam);
    150 }
    151 
    152 void WindowTreeHostWin::OnDeviceScaleFactorChanged(
    153     float device_scale_factor) {
    154   NOTIMPLEMENTED();
    155 }
    156 
    157 ui::EventProcessor* WindowTreeHostWin::GetEventProcessor() {
    158   return dispatcher();
    159 }
    160 
    161 void WindowTreeHostWin::OnClose() {
    162   // TODO: this obviously shouldn't be here.
    163   base::MessageLoopForUI::current()->Quit();
    164 }
    165 
    166 LRESULT WindowTreeHostWin::OnKeyEvent(UINT message,
    167                                       WPARAM w_param,
    168                                       LPARAM l_param) {
    169   MSG msg = { hwnd(), message, w_param, l_param };
    170   ui::KeyEvent keyev(msg, message == WM_CHAR);
    171   ui::EventDispatchDetails details = SendEventToProcessor(&keyev);
    172   SetMsgHandled(keyev.handled() || details.dispatcher_destroyed);
    173   return 0;
    174 }
    175 
    176 LRESULT WindowTreeHostWin::OnMouseRange(UINT message,
    177                                         WPARAM w_param,
    178                                         LPARAM l_param) {
    179   MSG msg = { hwnd(), message, w_param, l_param, 0,
    180               { CR_GET_X_LPARAM(l_param), CR_GET_Y_LPARAM(l_param) } };
    181   ui::MouseEvent event(msg);
    182   bool handled = false;
    183   if (!(event.flags() & ui::EF_IS_NON_CLIENT)) {
    184     ui::EventDispatchDetails details = SendEventToProcessor(&event);
    185     handled = event.handled() || details.dispatcher_destroyed;
    186   }
    187   SetMsgHandled(handled);
    188   return 0;
    189 }
    190 
    191 LRESULT WindowTreeHostWin::OnCaptureChanged(UINT message,
    192                                             WPARAM w_param,
    193                                             LPARAM l_param) {
    194   if (has_capture_) {
    195     has_capture_ = false;
    196     OnHostLostWindowCapture();
    197   }
    198   return 0;
    199 }
    200 
    201 LRESULT WindowTreeHostWin::OnNCActivate(UINT message,
    202                                         WPARAM w_param,
    203                                         LPARAM l_param) {
    204   if (!!w_param)
    205     OnHostActivated();
    206   return DefWindowProc(hwnd(), message, w_param, l_param);
    207 }
    208 
    209 void WindowTreeHostWin::OnMove(const gfx::Point& point) {
    210   OnHostMoved(point);
    211 }
    212 
    213 void WindowTreeHostWin::OnPaint(HDC dc) {
    214   gfx::Rect damage_rect;
    215   RECT update_rect = {0};
    216   if (GetUpdateRect(hwnd(), &update_rect, FALSE))
    217     damage_rect = gfx::Rect(update_rect);
    218   compositor()->ScheduleRedrawRect(damage_rect);
    219   ValidateRect(hwnd(), NULL);
    220 }
    221 
    222 void WindowTreeHostWin::OnSize(UINT param, const gfx::Size& size) {
    223   // Minimizing resizes the window to 0x0 which causes our layout to go all
    224   // screwy, so we just ignore it.
    225   if (dispatcher() && param != SIZE_MINIMIZED)
    226     OnHostResized(size);
    227 }
    228 
    229 namespace test {
    230 
    231 // static
    232 void SetUsePopupAsRootWindowForTest(bool use) {
    233   use_popup_as_root_window_for_test = use;
    234 }
    235 
    236 }  // namespace test
    237 
    238 }  // namespace aura
    239