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
CalculateWindowStylesFromInitParams(const Widget::InitParams & params,WidgetDelegate * widget_delegate,internal::NativeWidgetDelegate * native_widget_delegate,DWORD * style,DWORD * ex_style,DWORD * class_style)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
DidClientAreaSizeChange(const WINDOWPOS * window_pos)140 bool DidClientAreaSizeChange(const WINDOWPOS* window_pos) {
141 return !(window_pos->flags & SWP_NOSIZE) ||
142 window_pos->flags & SWP_FRAMECHANGED;
143 }
144
ConfigureWindowStyles(HWNDMessageHandler * handler,const Widget::InitParams & params,WidgetDelegate * widget_delegate,internal::NativeWidgetDelegate * native_widget_delegate)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