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