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