Home | History | Annotate | Download | only in widget
      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/views/widget/native_widget_win.h"
      6 
      7 #include <dwmapi.h>
      8 #include <shellapi.h>
      9 
     10 #include <algorithm>
     11 
     12 #include "base/bind.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/win/scoped_gdi_object.h"
     15 #include "base/win/win_util.h"
     16 #include "base/win/windows_version.h"
     17 #include "ui/base/dragdrop/drag_drop_types.h"
     18 #include "ui/base/dragdrop/drag_source_win.h"
     19 #include "ui/base/dragdrop/os_exchange_data.h"
     20 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
     21 #include "ui/base/ime/input_method_factory.h"
     22 #include "ui/base/l10n/l10n_util_win.h"
     23 #include "ui/base/theme_provider.h"
     24 #include "ui/base/view_prop.h"
     25 #include "ui/base/win/mouse_wheel_util.h"
     26 #include "ui/base/win/shell.h"
     27 #include "ui/events/event.h"
     28 #include "ui/events/keycodes/keyboard_code_conversion_win.h"
     29 #include "ui/gfx/canvas.h"
     30 #include "ui/gfx/canvas_skia_paint.h"
     31 #include "ui/gfx/path.h"
     32 #include "ui/gfx/point_conversions.h"
     33 #include "ui/gfx/screen.h"
     34 #include "ui/gfx/size_conversions.h"
     35 #include "ui/gfx/win/dpi.h"
     36 #include "ui/gfx/win/hwnd_util.h"
     37 #include "ui/native_theme/native_theme.h"
     38 #include "ui/views/controls/native_control_win.h"
     39 #include "ui/views/controls/textfield/textfield.h"
     40 #include "ui/views/drag_utils.h"
     41 #include "ui/views/focus/accelerator_handler.h"
     42 #include "ui/views/focus/view_storage.h"
     43 #include "ui/views/focus/widget_focus_manager.h"
     44 #include "ui/views/ime/input_method_bridge.h"
     45 #include "ui/views/widget/aero_tooltip_manager.h"
     46 #include "ui/views/widget/drop_target_win.h"
     47 #include "ui/views/widget/monitor_win.h"
     48 #include "ui/views/widget/native_widget_delegate.h"
     49 #include "ui/views/widget/root_view.h"
     50 #include "ui/views/widget/widget_delegate.h"
     51 #include "ui/views/widget/widget_hwnd_utils.h"
     52 #include "ui/views/win/fullscreen_handler.h"
     53 #include "ui/views/win/hwnd_message_handler.h"
     54 #include "ui/views/window/native_frame_view.h"
     55 
     56 #pragma comment(lib, "dwmapi.lib")
     57 
     58 using ui::ViewProp;
     59 
     60 namespace views {
     61 
     62 namespace {
     63 
     64 // Enumeration callback for NativeWidget::GetAllChildWidgets() and
     65 // NativeWidget::GetAllOwnedWidgets. Adds any HWNDs that correspond to
     66 // Widgets to a set.
     67 BOOL CALLBACK EnumerateNativeWidgets(HWND hwnd, LPARAM l_param) {
     68   Widget* widget = Widget::GetWidgetForNativeView(hwnd);
     69   if (widget) {
     70     Widget::Widgets* widgets = reinterpret_cast<Widget::Widgets*>(l_param);
     71     widgets->insert(widget);
     72   }
     73   return TRUE;
     74 }
     75 
     76 // Links the HWND to its NativeWidget.
     77 const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
     78 
     79 const int kDragFrameWindowAlpha = 200;
     80 
     81 }  // namespace
     82 
     83 ////////////////////////////////////////////////////////////////////////////////
     84 // NativeWidgetWin, public:
     85 
     86 NativeWidgetWin::NativeWidgetWin(internal::NativeWidgetDelegate* delegate)
     87     : delegate_(delegate),
     88       ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
     89       drag_frame_saved_window_style_(0),
     90       drag_frame_saved_window_ex_style_(0),
     91       has_non_client_view_(false),
     92       message_handler_(new HWNDMessageHandler(this)) {
     93 }
     94 
     95 NativeWidgetWin::~NativeWidgetWin() {
     96   if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
     97     delete delegate_;
     98   else
     99     CloseNow();
    100   message_handler_.reset();
    101 }
    102 
    103 // static
    104 gfx::Font NativeWidgetWin::GetWindowTitleFont() {
    105   NONCLIENTMETRICS ncm;
    106   base::win::GetNonClientMetrics(&ncm);
    107   l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
    108   base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
    109   return gfx::Font(caption_font);
    110 }
    111 
    112 void NativeWidgetWin::Show(int show_state) {
    113   message_handler_->Show(show_state);
    114 }
    115 
    116 ////////////////////////////////////////////////////////////////////////////////
    117 // NativeWidgetWin, NativeWidget implementation:
    118 
    119 void NativeWidgetWin::InitNativeWidget(const Widget::InitParams& params) {
    120   gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(params.bounds);
    121   Widget::InitParams params_in_pixel(params);
    122   params_in_pixel.bounds = pixel_bounds;
    123   SetInitParams(params_in_pixel);
    124   message_handler_->Init(params.parent, pixel_bounds);
    125 }
    126 
    127 NonClientFrameView* NativeWidgetWin::CreateNonClientFrameView() {
    128   return GetWidget()->ShouldUseNativeFrame() ?
    129       new NativeFrameView(GetWidget()) : NULL;
    130 }
    131 
    132 bool NativeWidgetWin::ShouldUseNativeFrame() const {
    133   return ui::win::IsAeroGlassEnabled();
    134 }
    135 
    136 void NativeWidgetWin::FrameTypeChanged() {
    137   message_handler_->FrameTypeChanged();
    138 }
    139 
    140 Widget* NativeWidgetWin::GetWidget() {
    141   return delegate_->AsWidget();
    142 }
    143 
    144 const Widget* NativeWidgetWin::GetWidget() const {
    145   return delegate_->AsWidget();
    146 }
    147 
    148 gfx::NativeView NativeWidgetWin::GetNativeView() const {
    149   return message_handler_->hwnd();
    150 }
    151 
    152 gfx::NativeWindow NativeWidgetWin::GetNativeWindow() const {
    153   return message_handler_->hwnd();
    154 }
    155 
    156 Widget* NativeWidgetWin::GetTopLevelWidget() {
    157   NativeWidgetPrivate* native_widget = GetTopLevelNativeWidget(GetNativeView());
    158   return native_widget ? native_widget->GetWidget() : NULL;
    159 }
    160 
    161 const ui::Compositor* NativeWidgetWin::GetCompositor() const {
    162   return NULL;
    163 }
    164 
    165 ui::Compositor* NativeWidgetWin::GetCompositor() {
    166   return NULL;
    167 }
    168 
    169 ui::Layer* NativeWidgetWin::GetLayer() {
    170   return NULL;
    171 }
    172 
    173 void NativeWidgetWin::ReorderNativeViews() {
    174 }
    175 
    176 void NativeWidgetWin::ViewRemoved(View* view) {
    177   if (drop_target_.get())
    178     drop_target_->ResetTargetViewIfEquals(view);
    179 }
    180 
    181 void NativeWidgetWin::SetNativeWindowProperty(const char* name, void* value) {
    182   // Remove the existing property (if any).
    183   for (ViewProps::iterator i = props_.begin(); i != props_.end(); ++i) {
    184     if ((*i)->Key() == name) {
    185       props_.erase(i);
    186       break;
    187     }
    188   }
    189 
    190   if (value)
    191     props_.push_back(new ViewProp(GetNativeView(), name, value));
    192 }
    193 
    194 void* NativeWidgetWin::GetNativeWindowProperty(const char* name) const {
    195   return ViewProp::GetValue(GetNativeView(), name);
    196 }
    197 
    198 TooltipManager* NativeWidgetWin::GetTooltipManager() const {
    199   return tooltip_manager_.get();
    200 }
    201 
    202 void NativeWidgetWin::SetCapture() {
    203   message_handler_->SetCapture();
    204 }
    205 
    206 void NativeWidgetWin::ReleaseCapture() {
    207   message_handler_->ReleaseCapture();
    208 }
    209 
    210 bool NativeWidgetWin::HasCapture() const {
    211   return message_handler_->HasCapture();
    212 }
    213 
    214 InputMethod* NativeWidgetWin::CreateInputMethod() {
    215   return new InputMethodBridge(GetMessageHandler(), ui::GetSharedInputMethod(),
    216                                true);
    217 }
    218 
    219 internal::InputMethodDelegate* NativeWidgetWin::GetInputMethodDelegate() {
    220   return message_handler_.get();
    221 }
    222 
    223 void NativeWidgetWin::CenterWindow(const gfx::Size& size) {
    224   gfx::Size size_in_pixels = gfx::win::DIPToScreenSize(size);
    225   message_handler_->CenterWindow(size_in_pixels);
    226 }
    227 
    228 void NativeWidgetWin::GetWindowPlacement(
    229     gfx::Rect* bounds,
    230     ui::WindowShowState* show_state) const {
    231   message_handler_->GetWindowPlacement(bounds, show_state);
    232   *bounds = gfx::win::ScreenToDIPRect(*bounds);
    233 }
    234 
    235 bool NativeWidgetWin::SetWindowTitle(const string16& title) {
    236   return message_handler_->SetTitle(title);
    237 }
    238 
    239 void NativeWidgetWin::SetWindowIcons(const gfx::ImageSkia& window_icon,
    240                                      const gfx::ImageSkia& app_icon) {
    241   message_handler_->SetWindowIcons(window_icon, app_icon);
    242 }
    243 
    244 void NativeWidgetWin::InitModalType(ui::ModalType modal_type) {
    245   message_handler_->InitModalType(modal_type);
    246 }
    247 
    248 gfx::Rect NativeWidgetWin::GetWindowBoundsInScreen() const {
    249   gfx::Rect bounds_in_pixels = message_handler_->GetWindowBoundsInScreen();
    250   return gfx::win::ScreenToDIPRect(bounds_in_pixels);
    251 }
    252 
    253 gfx::Rect NativeWidgetWin::GetClientAreaBoundsInScreen() const {
    254   gfx::Rect bounds_in_pixels = message_handler_->GetClientAreaBoundsInScreen();
    255   return gfx::win::ScreenToDIPRect(bounds_in_pixels);
    256 }
    257 
    258 gfx::Rect NativeWidgetWin::GetRestoredBounds() const {
    259   gfx::Rect bounds_in_pixels = message_handler_->GetRestoredBounds();
    260   return gfx::win::ScreenToDIPRect(bounds_in_pixels);
    261 }
    262 
    263 void NativeWidgetWin::SetBounds(const gfx::Rect& bounds) {
    264   float scale = gfx::win::GetDeviceScaleFactor();
    265   gfx::Rect bounds_in_pixels(
    266       gfx::ToCeiledPoint(gfx::ScalePoint(bounds.origin(), scale)),
    267       gfx::ToFlooredSize(gfx::ScaleSize(bounds.size(), scale)));
    268   message_handler_->SetBounds(bounds_in_pixels);
    269 }
    270 
    271 void NativeWidgetWin::SetSize(const gfx::Size& size) {
    272   message_handler_->SetSize(size);
    273 }
    274 
    275 void NativeWidgetWin::StackAbove(gfx::NativeView native_view) {
    276   message_handler_->StackAbove(native_view);
    277 }
    278 
    279 void NativeWidgetWin::StackAtTop() {
    280   message_handler_->StackAtTop();
    281 }
    282 
    283 void NativeWidgetWin::StackBelow(gfx::NativeView native_view) {
    284   NOTIMPLEMENTED();
    285 }
    286 
    287 void NativeWidgetWin::SetShape(gfx::NativeRegion region) {
    288   message_handler_->SetRegion(region);
    289 }
    290 
    291 void NativeWidgetWin::Close() {
    292   message_handler_->Close();
    293 }
    294 
    295 void NativeWidgetWin::CloseNow() {
    296   message_handler_->CloseNow();
    297 }
    298 
    299 void NativeWidgetWin::Show() {
    300   message_handler_->Show();
    301 }
    302 
    303 void NativeWidgetWin::Hide() {
    304   message_handler_->Hide();
    305 }
    306 
    307 void NativeWidgetWin::ShowMaximizedWithBounds(
    308     const gfx::Rect& restored_bounds) {
    309   gfx::Rect pixel_bounds = gfx::win::DIPToScreenRect(restored_bounds);
    310   message_handler_->ShowMaximizedWithBounds(pixel_bounds);
    311 }
    312 
    313 void NativeWidgetWin::ShowWithWindowState(ui::WindowShowState show_state) {
    314   message_handler_->ShowWindowWithState(show_state);
    315 }
    316 
    317 bool NativeWidgetWin::IsVisible() const {
    318   return message_handler_->IsVisible();
    319 }
    320 
    321 void NativeWidgetWin::Activate() {
    322   message_handler_->Activate();
    323 }
    324 
    325 void NativeWidgetWin::Deactivate() {
    326   message_handler_->Deactivate();
    327 }
    328 
    329 bool NativeWidgetWin::IsActive() const {
    330   return message_handler_->IsActive();
    331 }
    332 
    333 void NativeWidgetWin::SetAlwaysOnTop(bool on_top) {
    334   message_handler_->SetAlwaysOnTop(on_top);
    335 }
    336 
    337 bool NativeWidgetWin::IsAlwaysOnTop() const {
    338   return message_handler_->IsAlwaysOnTop();
    339 }
    340 
    341 void NativeWidgetWin::Maximize() {
    342   message_handler_->Maximize();
    343 }
    344 
    345 void NativeWidgetWin::Minimize() {
    346   message_handler_->Minimize();
    347 }
    348 
    349 bool NativeWidgetWin::IsMaximized() const {
    350   return message_handler_->IsMaximized();
    351 }
    352 
    353 bool NativeWidgetWin::IsMinimized() const {
    354   return message_handler_->IsMinimized();
    355 }
    356 
    357 void NativeWidgetWin::Restore() {
    358   message_handler_->Restore();
    359 }
    360 
    361 void NativeWidgetWin::SetFullscreen(bool fullscreen) {
    362   message_handler_->fullscreen_handler()->SetFullscreen(fullscreen);
    363 }
    364 
    365 void NativeWidgetWin::SetMetroSnapFullscreen(bool metro_snap) {
    366   message_handler_->fullscreen_handler()->SetMetroSnap(metro_snap);
    367 }
    368 
    369 bool NativeWidgetWin::IsFullscreen() const {
    370   return message_handler_->fullscreen_handler()->fullscreen();
    371 }
    372 
    373 bool NativeWidgetWin::IsInMetroSnapMode() const {
    374   return message_handler_->fullscreen_handler()->metro_snap();
    375 }
    376 
    377 void NativeWidgetWin::SetCanUpdateLayeredWindow(bool can_update) {
    378   message_handler_->set_can_update_layered_window(can_update);
    379 }
    380 
    381 void NativeWidgetWin::SetOpacity(unsigned char opacity) {
    382   message_handler_->SetOpacity(static_cast<BYTE>(opacity));
    383   GetWidget()->GetRootView()->SchedulePaint();
    384 }
    385 
    386 void NativeWidgetWin::SetUseDragFrame(bool use_drag_frame) {
    387   if (use_drag_frame) {
    388     // Make the frame slightly transparent during the drag operation.
    389     drag_frame_saved_window_style_ = GetWindowLong(GetNativeView(), GWL_STYLE);
    390     drag_frame_saved_window_ex_style_ =
    391         GetWindowLong(GetNativeView(), GWL_EXSTYLE);
    392     SetWindowLong(GetNativeView(), GWL_EXSTYLE,
    393                   drag_frame_saved_window_ex_style_ | WS_EX_LAYERED);
    394     // Remove the captions tyle so the window doesn't have window controls for a
    395     // more "transparent" look.
    396     SetWindowLong(GetNativeView(), GWL_STYLE,
    397                   drag_frame_saved_window_style_ & ~WS_CAPTION);
    398     SetLayeredWindowAttributes(GetNativeView(), RGB(0xFF, 0xFF, 0xFF),
    399                                kDragFrameWindowAlpha, LWA_ALPHA);
    400   } else {
    401     SetWindowLong(GetNativeView(), GWL_STYLE, drag_frame_saved_window_style_);
    402     SetWindowLong(GetNativeView(), GWL_EXSTYLE,
    403                   drag_frame_saved_window_ex_style_);
    404   }
    405 }
    406 
    407 void NativeWidgetWin::FlashFrame(bool flash) {
    408   message_handler_->FlashFrame(flash);
    409 }
    410 
    411 void NativeWidgetWin::RunShellDrag(View* view,
    412                                    const ui::OSExchangeData& data,
    413                                    const gfx::Point& location,
    414                                    int operation,
    415                                    ui::DragDropTypes::DragEventSource source) {
    416   views::RunShellDrag(NULL, data, location, operation, source);
    417 }
    418 
    419 void NativeWidgetWin::SchedulePaintInRect(const gfx::Rect& rect) {
    420   gfx::Rect pixel_rect = gfx::win::DIPToScreenRect(rect);
    421   message_handler_->SchedulePaintInRect(pixel_rect);
    422 }
    423 
    424 void NativeWidgetWin::SetCursor(gfx::NativeCursor cursor) {
    425   message_handler_->SetCursor(cursor);
    426 }
    427 
    428 bool NativeWidgetWin::IsMouseEventsEnabled() const {
    429   return true;
    430 }
    431 
    432 void NativeWidgetWin::ClearNativeFocus() {
    433   message_handler_->ClearNativeFocus();
    434 }
    435 
    436 gfx::Rect NativeWidgetWin::GetWorkAreaBoundsInScreen() const {
    437   return gfx::win::ScreenToDIPRect(
    438       gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(
    439       GetNativeView()).work_area());
    440 }
    441 
    442 Widget::MoveLoopResult NativeWidgetWin::RunMoveLoop(
    443     const gfx::Vector2d& drag_offset,
    444     Widget::MoveLoopSource source,
    445     Widget::MoveLoopEscapeBehavior escape_behavior) {
    446   const bool hide_on_escape =
    447       escape_behavior == Widget::MOVE_LOOP_ESCAPE_BEHAVIOR_HIDE;
    448   return message_handler_->RunMoveLoop(drag_offset, hide_on_escape) ?
    449       Widget::MOVE_LOOP_SUCCESSFUL : Widget::MOVE_LOOP_CANCELED;
    450 }
    451 
    452 void NativeWidgetWin::EndMoveLoop() {
    453   message_handler_->EndMoveLoop();
    454 }
    455 
    456 void NativeWidgetWin::SetVisibilityChangedAnimationsEnabled(bool value) {
    457   message_handler_->SetVisibilityChangedAnimationsEnabled(value);
    458 }
    459 
    460 ui::NativeTheme* NativeWidgetWin::GetNativeTheme() const {
    461   return ui::NativeTheme::instance();
    462 }
    463 
    464 void NativeWidgetWin::OnRootViewLayout() const {
    465 }
    466 
    467 ////////////////////////////////////////////////////////////////////////////////
    468 // NativeWidgetWin, NativeWidget implementation:
    469 
    470 ui::EventHandler* NativeWidgetWin::GetEventHandler() {
    471   NOTIMPLEMENTED();
    472   return NULL;
    473 }
    474 
    475 ////////////////////////////////////////////////////////////////////////////////
    476 // NativeWidgetWin, protected:
    477 
    478 void NativeWidgetWin::OnFinalMessage(HWND window) {
    479   // We don't destroy props in WM_DESTROY as we may still get messages after
    480   // WM_DESTROY that assume the properties are still valid (such as WM_CLOSE).
    481   props_.clear();
    482   delegate_->OnNativeWidgetDestroyed();
    483   if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
    484     delete this;
    485 }
    486 
    487 ////////////////////////////////////////////////////////////////////////////////
    488 // NativeWidgetWin, protected:
    489 
    490 HWNDMessageHandler* NativeWidgetWin::GetMessageHandler() {
    491   return message_handler_.get();
    492 }
    493 
    494 ////////////////////////////////////////////////////////////////////////////////
    495 // NativeWidgetWin, HWNDMessageHandlerDelegate implementation:
    496 
    497 bool NativeWidgetWin::IsWidgetWindow() const {
    498   // We don't NULL check GetWidget()->non_client_view() here because this
    499   // function can be called before the widget is fully constructed.
    500   return has_non_client_view_;
    501 }
    502 
    503 bool NativeWidgetWin::IsUsingCustomFrame() const {
    504   return !GetWidget()->ShouldUseNativeFrame();
    505 }
    506 
    507 void NativeWidgetWin::SchedulePaint() {
    508   GetWidget()->GetRootView()->SchedulePaint();
    509 }
    510 
    511 void NativeWidgetWin::EnableInactiveRendering() {
    512   delegate_->EnableInactiveRendering();
    513 }
    514 
    515 bool NativeWidgetWin::IsInactiveRenderingDisabled() {
    516   return delegate_->IsInactiveRenderingDisabled();
    517 }
    518 
    519 bool NativeWidgetWin::CanResize() const {
    520   return GetWidget()->widget_delegate()->CanResize();
    521 }
    522 
    523 bool NativeWidgetWin::CanMaximize() const {
    524   return GetWidget()->widget_delegate()->CanMaximize();
    525 }
    526 
    527 bool NativeWidgetWin::CanActivate() const {
    528   return delegate_->CanActivate();
    529 }
    530 
    531 bool NativeWidgetWin::WidgetSizeIsClientSize() const {
    532   const Widget* widget = GetWidget()->GetTopLevelWidget();
    533   return IsZoomed(GetNativeView()) ||
    534          (widget && widget->ShouldUseNativeFrame());
    535 }
    536 
    537 bool NativeWidgetWin::CanSaveFocus() const {
    538   return GetWidget()->is_top_level();
    539 }
    540 
    541 void NativeWidgetWin::SaveFocusOnDeactivate() {
    542   GetWidget()->GetFocusManager()->StoreFocusedView(true);
    543 }
    544 
    545 void NativeWidgetWin::RestoreFocusOnActivate() {
    546   // Mysteriously, this only appears to be needed support restoration of focus
    547   // to a child hwnd when restoring its top level window from the minimized
    548   // state. If we don't do this, then ::SetFocus() to that child HWND returns
    549   // ERROR_INVALID_PARAMETER, despite both HWNDs being of the same thread.
    550   // See http://crbug.com/125976 and
    551   // chrome/browser/ui/views/native_widget_win_interactive_uitest.cc .
    552   {
    553     // Since this is a synthetic reset, we don't need to tell anyone about it.
    554     AutoNativeNotificationDisabler disabler;
    555     GetWidget()->GetFocusManager()->ClearFocus();
    556   }
    557   RestoreFocusOnEnable();
    558 }
    559 
    560 void NativeWidgetWin::RestoreFocusOnEnable() {
    561   GetWidget()->GetFocusManager()->RestoreFocusedView();
    562 }
    563 
    564 bool NativeWidgetWin::IsModal() const {
    565   return delegate_->IsModal();
    566 }
    567 
    568 int NativeWidgetWin::GetInitialShowState() const {
    569   return SW_SHOWNORMAL;
    570 }
    571 
    572 bool NativeWidgetWin::WillProcessWorkAreaChange() const {
    573   return GetWidget()->widget_delegate()->WillProcessWorkAreaChange();
    574 }
    575 
    576 int NativeWidgetWin::GetNonClientComponent(const gfx::Point& point) const {
    577   gfx::Point point_in_dip = gfx::win::ScreenToDIPPoint(point);
    578   return delegate_->GetNonClientComponent(point_in_dip);
    579 }
    580 
    581 void NativeWidgetWin::GetWindowMask(const gfx::Size& size, gfx::Path* path) {
    582   if (GetWidget()->non_client_view())
    583     GetWidget()->non_client_view()->GetWindowMask(size, path);
    584 }
    585 
    586 bool NativeWidgetWin::GetClientAreaInsets(gfx::Insets* insets) const {
    587   return false;
    588 }
    589 
    590 void NativeWidgetWin::GetMinMaxSize(gfx::Size* min_size,
    591                                     gfx::Size* max_size) const {
    592   *min_size = gfx::win::ScreenToDIPSize(delegate_->GetMinimumSize());
    593   *max_size = gfx::win::ScreenToDIPSize(delegate_->GetMaximumSize());
    594 }
    595 
    596 gfx::Size NativeWidgetWin::GetRootViewSize() const {
    597   gfx::Size pixel_size = GetWidget()->GetRootView()->size();
    598   return gfx::win::ScreenToDIPSize(pixel_size);
    599 }
    600 
    601 void NativeWidgetWin::ResetWindowControls() {
    602   GetWidget()->non_client_view()->ResetWindowControls();
    603 }
    604 
    605 void NativeWidgetWin::PaintLayeredWindow(gfx::Canvas* canvas) {
    606   GetWidget()->GetRootView()->Paint(canvas);
    607 }
    608 
    609 InputMethod* NativeWidgetWin::GetInputMethod() {
    610   return GetWidget()->GetInputMethodDirect();
    611 }
    612 
    613 gfx::NativeViewAccessible NativeWidgetWin::GetNativeViewAccessible() {
    614   return GetWidget()->GetRootView()->GetNativeViewAccessible();
    615 }
    616 
    617 bool NativeWidgetWin::ShouldHandleSystemCommands() const {
    618   return GetWidget()->widget_delegate()->ShouldHandleSystemCommands();
    619 }
    620 
    621 void NativeWidgetWin::HandleAppDeactivated() {
    622   if (IsInactiveRenderingDisabled()) {
    623     delegate_->EnableInactiveRendering();
    624   } else {
    625     // TODO(pkotwicz): Remove need for SchedulePaint(). crbug.com/165841
    626     View* non_client_view = GetWidget()->non_client_view();
    627     if (non_client_view)
    628       non_client_view->SchedulePaint();
    629   }
    630 }
    631 
    632 void NativeWidgetWin::HandleActivationChanged(bool active) {
    633   delegate_->OnNativeWidgetActivationChanged(active);
    634 }
    635 
    636 bool NativeWidgetWin::HandleAppCommand(short command) {
    637   // We treat APPCOMMAND ids as an extension of our command namespace, and just
    638   // let the delegate figure out what to do...
    639   return GetWidget()->widget_delegate() &&
    640       GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
    641 }
    642 
    643 void NativeWidgetWin::HandleCancelMode() {
    644 }
    645 
    646 void NativeWidgetWin::HandleCaptureLost() {
    647   delegate_->OnMouseCaptureLost();
    648 }
    649 
    650 void NativeWidgetWin::HandleClose() {
    651   GetWidget()->Close();
    652 }
    653 
    654 bool NativeWidgetWin::HandleCommand(int command) {
    655   return GetWidget()->widget_delegate()->ExecuteWindowsCommand(command);
    656 }
    657 
    658 void NativeWidgetWin::HandleAccelerator(const ui::Accelerator& accelerator) {
    659   GetWidget()->GetFocusManager()->ProcessAccelerator(accelerator);
    660 }
    661 
    662 void NativeWidgetWin::HandleCreate() {
    663   // TODO(beng): much of this could/should maybe move to HWNDMessageHandler.
    664 
    665   SetNativeWindowProperty(kNativeWidgetKey, this);
    666   CHECK_EQ(this, GetNativeWidgetForNativeView(GetNativeView()));
    667 
    668   props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(GetNativeView()));
    669 
    670   drop_target_ = new DropTargetWin(
    671       static_cast<internal::RootView*>(GetWidget()->GetRootView()));
    672 
    673   // Windows special DWM window frame requires a special tooltip manager so
    674   // that window controls in Chrome windows don't flicker when you move your
    675   // mouse over them. See comment in aero_tooltip_manager.h.
    676   Widget* widget = GetWidget()->GetTopLevelWidget();
    677   if (widget && widget->ShouldUseNativeFrame()) {
    678     tooltip_manager_.reset(new AeroTooltipManager(GetWidget()));
    679   } else {
    680     tooltip_manager_.reset(new TooltipManagerWin(GetWidget()));
    681   }
    682   if (!tooltip_manager_->Init()) {
    683     // There was a problem creating the TooltipManager. Common error is 127.
    684     // See 82193 for details.
    685     LOG_GETLASTERROR(WARNING) << "tooltip creation failed, disabling tooltips";
    686     tooltip_manager_.reset();
    687   }
    688 
    689   delegate_->OnNativeWidgetCreated(true);
    690 }
    691 
    692 void NativeWidgetWin::HandleDestroying() {
    693   delegate_->OnNativeWidgetDestroying();
    694   if (drop_target_.get()) {
    695     RevokeDragDrop(GetNativeView());
    696     drop_target_ = NULL;
    697   }
    698 }
    699 
    700 void NativeWidgetWin::HandleDestroyed() {
    701   OnFinalMessage(GetNativeView());
    702 }
    703 
    704 bool NativeWidgetWin::HandleInitialFocus() {
    705   return GetWidget()->SetInitialFocus();
    706 }
    707 
    708 void NativeWidgetWin::HandleDisplayChange() {
    709   GetWidget()->widget_delegate()->OnDisplayChanged();
    710 }
    711 
    712 void NativeWidgetWin::HandleBeginWMSizeMove() {
    713   delegate_->OnNativeWidgetBeginUserBoundsChange();
    714 }
    715 
    716 void NativeWidgetWin::HandleEndWMSizeMove() {
    717   delegate_->OnNativeWidgetEndUserBoundsChange();
    718 }
    719 
    720 void NativeWidgetWin::HandleMove() {
    721   delegate_->OnNativeWidgetMove();
    722 }
    723 
    724 void NativeWidgetWin::HandleWorkAreaChanged() {
    725   GetWidget()->widget_delegate()->OnWorkAreaChanged();
    726 }
    727 
    728 void NativeWidgetWin::HandleVisibilityChanging(bool visible) {
    729   delegate_->OnNativeWidgetVisibilityChanging(visible);
    730 }
    731 
    732 void NativeWidgetWin::HandleVisibilityChanged(bool visible) {
    733   delegate_->OnNativeWidgetVisibilityChanged(visible);
    734 }
    735 
    736 void NativeWidgetWin::HandleClientSizeChanged(const gfx::Size& new_size) {
    737   gfx::Size size_in_dip = gfx::win::ScreenToDIPSize(new_size);
    738   delegate_->OnNativeWidgetSizeChanged(size_in_dip);
    739 }
    740 
    741 void NativeWidgetWin::HandleFrameChanged() {
    742   // Replace the frame and layout the contents.
    743   GetWidget()->non_client_view()->UpdateFrame();
    744 }
    745 
    746 void NativeWidgetWin::HandleNativeFocus(HWND last_focused_window) {
    747   delegate_->OnNativeFocus(last_focused_window);
    748   InputMethod* input_method = GetInputMethod();
    749   if (input_method)
    750     input_method->OnFocus();
    751 }
    752 
    753 void NativeWidgetWin::HandleNativeBlur(HWND focused_window) {
    754   delegate_->OnNativeBlur(focused_window);
    755   InputMethod* input_method = GetInputMethod();
    756   if (input_method)
    757     input_method->OnBlur();
    758 }
    759 
    760 bool NativeWidgetWin::HandleMouseEvent(const ui::MouseEvent& event) {
    761   static gfx::Transform scale_transform(
    762     1/gfx::win::GetDeviceScaleFactor(), 0.0,
    763     0.0, 1/gfx::win::GetDeviceScaleFactor(),
    764     0.0, 0.0);
    765   if (event.IsMouseWheelEvent()) {
    766     ui::MouseWheelEvent dpi_event(
    767         static_cast<const ui::MouseWheelEvent&>(event));
    768     dpi_event.UpdateForRootTransform(scale_transform);
    769     delegate_->OnMouseEvent(&dpi_event);
    770     return dpi_event.handled();
    771   } else if (event.IsMouseEvent()) {
    772     ui::MouseEvent dpi_event(event);
    773     if (!(dpi_event.flags() & ui::EF_IS_NON_CLIENT))
    774       dpi_event.UpdateForRootTransform(scale_transform);
    775     delegate_->OnMouseEvent(&dpi_event);
    776     return dpi_event.handled();
    777   }
    778   NOTREACHED();
    779   return false;
    780 }
    781 
    782 bool NativeWidgetWin::HandleKeyEvent(const ui::KeyEvent& event) {
    783   delegate_->OnKeyEvent(const_cast<ui::KeyEvent*>(&event));
    784   return event.handled();
    785 }
    786 
    787 bool NativeWidgetWin::HandleUntranslatedKeyEvent(const ui::KeyEvent& event) {
    788   InputMethod* input_method = GetInputMethod();
    789   if (input_method)
    790     input_method->DispatchKeyEvent(event);
    791   return !!input_method;
    792 }
    793 
    794 void NativeWidgetWin::HandleTouchEvent(const ui::TouchEvent& event) {
    795   NOTREACHED() << "Touch events are not supported";
    796 }
    797 
    798 bool NativeWidgetWin::HandleIMEMessage(UINT message,
    799                                        WPARAM w_param,
    800                                        LPARAM l_param,
    801                                        LRESULT* result) {
    802   InputMethod* input_method = GetInputMethod();
    803   if (!input_method || input_method->IsMock()) {
    804     *result = 0;
    805     return false;
    806   }
    807 
    808   MSG msg = {};
    809   msg.hwnd = message_handler_->hwnd();
    810   msg.message = message;
    811   msg.wParam = w_param;
    812   msg.lParam = l_param;
    813   return input_method->OnUntranslatedIMEMessage(msg, result);
    814 }
    815 
    816 void NativeWidgetWin::HandleInputLanguageChange(DWORD character_set,
    817                                                 HKL input_language_id) {
    818   InputMethod* input_method = GetInputMethod();
    819   if (input_method && !input_method->IsMock()) {
    820     input_method->OnInputLocaleChanged();
    821   }
    822 }
    823 
    824 bool NativeWidgetWin::HandlePaintAccelerated(const gfx::Rect& invalid_rect) {
    825   gfx::Rect dpi_rect = gfx::win::ScreenToDIPRect(invalid_rect);
    826   return delegate_->OnNativeWidgetPaintAccelerated(dpi_rect);
    827 }
    828 
    829 void NativeWidgetWin::HandlePaint(gfx::Canvas* canvas) {
    830   delegate_->OnNativeWidgetPaint(canvas);
    831 }
    832 
    833 bool NativeWidgetWin::HandleTooltipNotify(int w_param,
    834                                           NMHDR* l_param,
    835                                           LRESULT* l_result) {
    836   // We can be sent this message before the tooltip manager is created, if a
    837   // subclass overrides OnCreate and creates some kind of Windows control there
    838   // that sends WM_NOTIFY messages.
    839   if (tooltip_manager_.get()) {
    840     bool handled;
    841     *l_result = tooltip_manager_->OnNotify(w_param, l_param, &handled);
    842     return handled;
    843   }
    844   return false;
    845 }
    846 
    847 void NativeWidgetWin::HandleTooltipMouseMove(UINT message,
    848                                              WPARAM w_param,
    849                                              LPARAM l_param) {
    850   if (tooltip_manager_.get())
    851     tooltip_manager_->OnMouse(message, w_param, l_param);
    852 }
    853 
    854 bool NativeWidgetWin::PreHandleMSG(UINT message,
    855                                    WPARAM w_param,
    856                                    LPARAM l_param,
    857                                    LRESULT* result) {
    858   return false;
    859 }
    860 
    861 void NativeWidgetWin::PostHandleMSG(UINT message,
    862                                     WPARAM w_param,
    863                                     LPARAM l_param) {
    864 }
    865 
    866 bool NativeWidgetWin::HandleScrollEvent(const ui::ScrollEvent& event) {
    867   delegate_->OnScrollEvent(const_cast<ui::ScrollEvent*>(&event));
    868   return event.handled();
    869 }
    870 
    871 ////////////////////////////////////////////////////////////////////////////////
    872 // NativeWidgetWin, private:
    873 
    874 void NativeWidgetWin::SetInitParams(const Widget::InitParams& params) {
    875   // Set non-style attributes.
    876   ownership_ = params.ownership;
    877 
    878   ConfigureWindowStyles(message_handler_.get(), params,
    879                         GetWidget()->widget_delegate(), delegate_);
    880 
    881   has_non_client_view_ = Widget::RequiresNonClientView(params.type);
    882   message_handler_->set_remove_standard_frame(params.remove_standard_frame);
    883   message_handler_->set_use_system_default_icon(params.use_system_default_icon);
    884 }
    885 
    886 ////////////////////////////////////////////////////////////////////////////////
    887 // Widget, public:
    888 
    889 // static
    890 void Widget::NotifyLocaleChanged() {
    891   NOTIMPLEMENTED();
    892 }
    893 
    894 namespace {
    895 BOOL CALLBACK WindowCallbackProc(HWND hwnd, LPARAM lParam) {
    896   Widget* widget = Widget::GetWidgetForNativeView(hwnd);
    897   if (widget && widget->is_secondary_widget())
    898     widget->Close();
    899   return TRUE;
    900 }
    901 }  // namespace
    902 
    903 // static
    904 void Widget::CloseAllSecondaryWidgets() {
    905   EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0);
    906 }
    907 
    908 bool Widget::ConvertRect(const Widget* source,
    909                          const Widget* target,
    910                          gfx::Rect* rect) {
    911   DCHECK(source);
    912   DCHECK(target);
    913   DCHECK(rect);
    914 
    915   HWND source_hwnd = source->GetNativeView();
    916   HWND target_hwnd = target->GetNativeView();
    917   if (source_hwnd == target_hwnd)
    918     return true;
    919 
    920   RECT win_rect = gfx::win::DIPToScreenRect(*rect).ToRECT();
    921   if (::MapWindowPoints(source_hwnd, target_hwnd,
    922                         reinterpret_cast<LPPOINT>(&win_rect),
    923                         sizeof(RECT)/sizeof(POINT))) {
    924     *rect = gfx::win::ScreenToDIPRect(gfx::Rect(win_rect));
    925     return true;
    926   }
    927   return false;
    928 }
    929 
    930 namespace internal {
    931 
    932 ////////////////////////////////////////////////////////////////////////////////
    933 // internal::NativeWidgetPrivate, public:
    934 
    935 // static
    936 NativeWidgetPrivate* NativeWidgetPrivate::CreateNativeWidget(
    937     internal::NativeWidgetDelegate* delegate) {
    938   return new NativeWidgetWin(delegate);
    939 }
    940 
    941 // static
    942 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
    943     gfx::NativeView native_view) {
    944   return reinterpret_cast<NativeWidgetWin*>(
    945       ViewProp::GetValue(native_view, kNativeWidgetKey));
    946 }
    947 
    948 // static
    949 NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
    950     gfx::NativeWindow native_window) {
    951   return GetNativeWidgetForNativeView(native_window);
    952 }
    953 
    954 // static
    955 NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
    956     gfx::NativeView native_view) {
    957   if (!native_view)
    958     return NULL;
    959 
    960   // First, check if the top-level window is a Widget.
    961   HWND root = ::GetAncestor(native_view, GA_ROOT);
    962   if (!root)
    963     return NULL;
    964 
    965   NativeWidgetPrivate* widget = GetNativeWidgetForNativeView(root);
    966   if (widget)
    967     return widget;
    968 
    969   // Second, try to locate the last Widget window in the parent hierarchy.
    970   HWND parent_hwnd = native_view;
    971   // If we fail to find the native widget pointer for the root then it probably
    972   // means that the root belongs to a different process in which case we walk up
    973   // the native view chain looking for a parent window which corresponds to a
    974   // valid native widget. We only do this if we fail to find the native widget
    975   // for the current native view which means it is being destroyed.
    976   if (!widget && !GetNativeWidgetForNativeView(native_view)) {
    977     parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT);
    978     if (!parent_hwnd)
    979       return NULL;
    980   }
    981   NativeWidgetPrivate* parent_widget;
    982   do {
    983     parent_widget = GetNativeWidgetForNativeView(parent_hwnd);
    984     if (parent_widget) {
    985       widget = parent_widget;
    986       parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT);
    987     }
    988   } while (parent_hwnd != NULL && parent_widget != NULL);
    989 
    990   return widget;
    991 }
    992 
    993 // static
    994 void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
    995                                              Widget::Widgets* children) {
    996   if (!native_view)
    997     return;
    998 
    999   Widget* widget = Widget::GetWidgetForNativeView(native_view);
   1000   if (widget)
   1001     children->insert(widget);
   1002   EnumChildWindows(native_view, EnumerateNativeWidgets,
   1003                    reinterpret_cast<LPARAM>(children));
   1004 }
   1005 
   1006 // static
   1007 void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
   1008                                              Widget::Widgets* owned) {
   1009   if (!native_view)
   1010     return;
   1011 
   1012   Widget::Widgets all;
   1013   EnumWindows(EnumerateNativeWidgets, reinterpret_cast<LPARAM>(&all));
   1014   for (Widget::Widgets::const_iterator iter = all.begin();
   1015            iter != all.end(); ++iter) {
   1016     if (native_view == GetWindow((*iter)->GetNativeView(), GW_OWNER))
   1017       owned->insert(*iter);
   1018   }
   1019 }
   1020 
   1021 // static
   1022 void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
   1023                                              gfx::NativeView new_parent) {
   1024   if (!native_view)
   1025     return;
   1026 
   1027   HWND previous_parent = ::GetParent(native_view);
   1028   if (previous_parent == new_parent)
   1029     return;
   1030 
   1031   Widget::Widgets widgets;
   1032   GetAllChildWidgets(native_view, &widgets);
   1033 
   1034   // First notify all the widgets that they are being disassociated
   1035   // from their previous parent.
   1036   for (Widget::Widgets::iterator it = widgets.begin();
   1037        it != widgets.end(); ++it) {
   1038     (*it)->NotifyNativeViewHierarchyWillChange();
   1039   }
   1040 
   1041   ::SetParent(native_view, new_parent);
   1042 
   1043   // And now, notify them that they have a brand new parent.
   1044   for (Widget::Widgets::iterator it = widgets.begin();
   1045        it != widgets.end(); ++it) {
   1046     (*it)->NotifyNativeViewHierarchyChanged();
   1047   }
   1048 }
   1049 
   1050 // static
   1051 bool NativeWidgetPrivate::IsMouseButtonDown() {
   1052   return (GetKeyState(VK_LBUTTON) & 0x80) ||
   1053     (GetKeyState(VK_RBUTTON) & 0x80) ||
   1054     (GetKeyState(VK_MBUTTON) & 0x80) ||
   1055     (GetKeyState(VK_XBUTTON1) & 0x80) ||
   1056     (GetKeyState(VK_XBUTTON2) & 0x80);
   1057 }
   1058 
   1059 // static
   1060 bool NativeWidgetPrivate::IsTouchDown() {
   1061   // This currently isn't necessary because we're not generating touch events on
   1062   // windows.  When we do, this will need to be updated.
   1063   return false;
   1064 }
   1065 
   1066 }  // namespace internal
   1067 
   1068 }  // namespace views
   1069