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/widget_hwnd_utils.h"
      6 
      7 #include <dwmapi.h>
      8 
      9 #include "base/command_line.h"
     10 #include "base/win/windows_version.h"
     11 #include "ui/base/l10n/l10n_util_win.h"
     12 #include "ui/base/ui_base_switches.h"
     13 #include "ui/views/widget/widget_delegate.h"
     14 #include "ui/views/win/hwnd_message_handler.h"
     15 
     16 #if defined(OS_WIN)
     17 #include "ui/base/win/shell.h"
     18 #endif
     19 
     20 namespace views {
     21 
     22 namespace {
     23 
     24 void CalculateWindowStylesFromInitParams(
     25     const Widget::InitParams& params,
     26     WidgetDelegate* widget_delegate,
     27     internal::NativeWidgetDelegate* native_widget_delegate,
     28     DWORD* style,
     29     DWORD* ex_style,
     30     DWORD* class_style) {
     31   *style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
     32   *ex_style = 0;
     33   *class_style = CS_DBLCLKS;
     34 
     35   // Set type-independent style attributes.
     36   if (params.child)
     37     *style |= WS_CHILD;
     38   if (params.show_state == ui::SHOW_STATE_MAXIMIZED)
     39     *style |= WS_MAXIMIZE;
     40   if (params.show_state == ui::SHOW_STATE_MINIMIZED)
     41     *style |= WS_MINIMIZE;
     42   if (!params.accept_events)
     43     *ex_style |= WS_EX_TRANSPARENT;
     44   if (!params.can_activate)
     45     *ex_style |= WS_EX_NOACTIVATE;
     46   if (params.keep_on_top)
     47     *ex_style |= WS_EX_TOPMOST;
     48   if (params.mirror_origin_in_rtl)
     49     *ex_style |= l10n_util::GetExtendedTooltipStyles();
     50   // Layered windows do not work with Aura. They are basically incompatible
     51   // with Direct3D surfaces. Officially, it should be impossible to achieve
     52   // per-pixel alpha compositing with the desktop and 3D acceleration but it
     53   // has been discovered that since Vista There is a secret handshake between
     54   // user32 and the DMW. If things are set up just right DMW gets out of the
     55   // way; it does not create a backbuffer and simply blends our D3D surface
     56   // and the desktop background. The handshake is as follows:
     57   // 1- Use D3D9Ex to create device/swapchain, etc. You need D3DFMT_A8R8G8B8.
     58   // 2- The window must have WS_EX_COMPOSITED in the extended style.
     59   // 3- The window must have WS_POPUP in its style.
     60   // 4- The windows must not have WM_SIZEBOX, WS_THICKFRAME or WS_CAPTION in its
     61   //    style.
     62   // 5- When the window is created but before it is presented, call
     63   //    DwmExtendFrameIntoClientArea passing -1 as the margins.
     64   if (params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW) {
     65 #if defined(USE_AURA)
     66     if (ui::win::IsAeroGlassEnabled())
     67       *ex_style |= WS_EX_COMPOSITED;
     68 #else
     69     *ex_style |= WS_EX_LAYERED;
     70 #endif
     71   }
     72   if (params.has_dropshadow) {
     73     *class_style |= (base::win::GetVersion() < base::win::VERSION_XP) ?
     74         0 : CS_DROPSHADOW;
     75   }
     76 
     77   // Set type-dependent style attributes.
     78   switch (params.type) {
     79     case Widget::InitParams::TYPE_PANEL:
     80       *ex_style |= WS_EX_TOPMOST;
     81       if (params.remove_standard_frame) {
     82         *style |= WS_POPUP;
     83         break;
     84       }
     85       // Else, no break. Fall through to TYPE_WINDOW.
     86     case Widget::InitParams::TYPE_WINDOW: {
     87       *style |= WS_SYSMENU | WS_CAPTION;
     88       bool can_resize = widget_delegate->CanResize();
     89       bool can_maximize = widget_delegate->CanMaximize();
     90       if (can_maximize) {
     91         *style |= WS_OVERLAPPEDWINDOW;
     92       } else if (can_resize || params.remove_standard_frame) {
     93         *style |= WS_OVERLAPPED | WS_THICKFRAME;
     94       }
     95       if (native_widget_delegate->IsDialogBox()) {
     96         *style |= DS_MODALFRAME;
     97         // NOTE: Turning this off means we lose the close button, which is bad.
     98         // Turning it on though means the user can maximize or size the window
     99         // from the system menu, which is worse. We may need to provide our own
    100         // menu to get the close button to appear properly.
    101         // style &= ~WS_SYSMENU;
    102 
    103         // Set the WS_POPUP style for modal dialogs. This ensures that the owner
    104         // window is activated on destruction. This style should not be set for
    105         // non-modal non-top-level dialogs like constrained windows.
    106         *style |= native_widget_delegate->IsModal() ? WS_POPUP : 0;
    107       }
    108       *ex_style |=
    109           native_widget_delegate->IsDialogBox() ? WS_EX_DLGMODALFRAME : 0;
    110 
    111       // See layered window comment above.
    112       if (*ex_style & WS_EX_COMPOSITED)
    113         *style &= ~(WS_THICKFRAME | WS_CAPTION);
    114       break;
    115     }
    116     case Widget::InitParams::TYPE_CONTROL:
    117       *style |= WS_VISIBLE;
    118       break;
    119     case Widget::InitParams::TYPE_WINDOW_FRAMELESS:
    120       *style |= WS_POPUP;
    121       break;
    122     case Widget::InitParams::TYPE_BUBBLE:
    123       *style |= WS_POPUP;
    124       *style |= WS_CLIPCHILDREN;
    125       break;
    126     case Widget::InitParams::TYPE_POPUP:
    127       *style |= WS_POPUP;
    128       *ex_style |= WS_EX_TOOLWINDOW;
    129       break;
    130     case Widget::InitParams::TYPE_MENU:
    131       *style |= WS_POPUP;
    132       break;
    133     default:
    134       NOTREACHED();
    135   }
    136 }
    137 
    138 }  // namespace
    139 
    140 bool DidClientAreaSizeChange(const WINDOWPOS* window_pos) {
    141   return !(window_pos->flags & SWP_NOSIZE) ||
    142          window_pos->flags & SWP_FRAMECHANGED;
    143 }
    144 
    145 void ConfigureWindowStyles(
    146     HWNDMessageHandler* handler,
    147     const Widget::InitParams& params,
    148     WidgetDelegate* widget_delegate,
    149     internal::NativeWidgetDelegate* native_widget_delegate) {
    150   // Configure the HWNDMessageHandler with the appropriate
    151   DWORD style = 0;
    152   DWORD ex_style = 0;
    153   DWORD class_style = 0;
    154   CalculateWindowStylesFromInitParams(params, widget_delegate,
    155                                       native_widget_delegate, &style, &ex_style,
    156                                       &class_style);
    157   handler->set_initial_class_style(class_style);
    158   handler->set_window_style(handler->window_style() | style);
    159   handler->set_window_ex_style(handler->window_ex_style() | ex_style);
    160 }
    161 
    162 }  // namespace views
    163