Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Unified Diff: ui/views/win/hwnd_message_handler.cc

Issue 10870110: Move more code from NWW to HWNDMessageHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | ui/views/win/hwnd_message_handler_delegate.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/win/hwnd_message_handler.cc
===================================================================
--- ui/views/win/hwnd_message_handler.cc (revision 153503)
+++ ui/views/win/hwnd_message_handler.cc (working copy)
@@ -19,11 +19,14 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/canvas_paint.h"
#include "ui/gfx/canvas_skia_paint.h"
+#include "ui/gfx/icon_util.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/path.h"
#include "ui/gfx/screen.h"
#include "ui/views/accessibility/native_view_accessibility_win.h"
#include "ui/views/ime/input_method_win.h"
+#include "ui/views/views_delegate.h"
+#include "ui/views/widget/child_window_message_processor.h"
#include "ui/views/widget/monitor_win.h"
#include "ui/views/widget/native_widget_win.h"
#include "ui/views/widget/widget_hwnd_utils.h"
@@ -236,6 +239,50 @@
return TRUE;
}
+// Get the source HWND of the specified message. Depending on the message, the
+// source HWND is encoded in either the WPARAM or the LPARAM value.
+HWND GetControlHWNDForMessage(UINT message, WPARAM w_param, LPARAM l_param) {
+ // Each of the following messages can be sent by a child HWND and must be
+ // forwarded to its associated NativeControlWin for handling.
+ switch (message) {
+ case WM_NOTIFY:
+ return reinterpret_cast<NMHDR*>(l_param)->hwndFrom;
+ case WM_COMMAND:
+ return reinterpret_cast<HWND>(l_param);
+ case WM_CONTEXTMENU:
+ return reinterpret_cast<HWND>(w_param);
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORSTATIC:
+ return reinterpret_cast<HWND>(l_param);
+ }
+ return NULL;
+}
+
+// Some messages may be sent to us by a child HWND. If this is the case, this
+// function will forward those messages on to the object associated with the
+// source HWND and return true, in which case the window procedure must not do
+// any further processing of the message. If there is no associated
+// ChildWindowMessageProcessor, the return value will be false and the WndProc
+// can continue processing the message normally. |l_result| contains the result
+// of the message processing by the control and must be returned by the WndProc
+// if the return value is true.
+bool ProcessChildWindowMessage(UINT message,
+ WPARAM w_param,
+ LPARAM l_param,
+ LRESULT* l_result) {
+ *l_result = 0;
+
+ HWND control_hwnd = GetControlHWNDForMessage(message, w_param, l_param);
+ if (IsWindow(control_hwnd)) {
+ ChildWindowMessageProcessor* processor =
+ ChildWindowMessageProcessor::Get(control_hwnd);
+ if (processor)
+ return processor->ProcessMessage(message, w_param, l_param, l_result);
+ }
+
+ return false;
+}
+
// A custom MSAA object id used to determine if a screen reader is actively
// listening for MSAA events.
const int kCustomObjectID = 1;
@@ -316,7 +363,10 @@
: delegate_(delegate),
ALLOW_THIS_IN_INITIALIZER_LIST(fullscreen_handler_(new FullscreenHandler(
delegate->AsNativeWidgetWin()->GetWidget()))),
+ ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
remove_standard_frame_(false),
+ restore_focus_when_enabled_(false),
+ restored_enabled_(false),
previous_cursor_(NULL),
active_mouse_tracking_flags_(0),
is_right_mouse_pressed_on_caption_(false),
@@ -354,6 +404,29 @@
}
}
+void HWNDMessageHandler::Close() {
+ if (!IsWindow(hwnd()))
+ return; // No need to do anything.
+
+ // Let's hide ourselves right away.
+ Hide();
+
+ // Modal dialog windows disable their owner windows; re-enable them now so
+ // they can activate as foreground windows upon this window's destruction.
+ RestoreEnabledIfNecessary();
+
+ if (!close_widget_factory_.HasWeakPtrs()) {
+ // And we delay the close so that if we are called from an ATL callback,
+ // we don't destroy the window before the callback returned (as the caller
+ // may delete ourselves on destroy and the ATL callback would still
+ // dereference us when the callback returns).
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&HWNDMessageHandler::CloseNow,
+ close_widget_factory_.GetWeakPtr()));
+ }
+}
+
void HWNDMessageHandler::CloseNow() {
// We may already have been destroyed if the selection resulted in a tab
// switch which will have reactivated the browser window and closed us, so
@@ -457,6 +530,59 @@
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
+void HWNDMessageHandler::Show() {
+ // TODO(beng): Seems like this could just be rewritten as
+ // ShowWindowWithState(SW_SHOWNOACTIVATE).
+ if (!IsWindow(hwnd()))
+ return;
+
+ ShowWindow(hwnd(), SW_SHOWNOACTIVATE);
+ SetInitialFocus();
+}
+
+void HWNDMessageHandler::ShowWindowWithState(ui::WindowShowState show_state) {
+ DWORD native_show_state;
+ switch (show_state) {
+ case ui::SHOW_STATE_INACTIVE:
+ native_show_state = SW_SHOWNOACTIVATE;
+ break;
+ case ui::SHOW_STATE_MAXIMIZED:
+ native_show_state = SW_SHOWMAXIMIZED;
+ break;
+ case ui::SHOW_STATE_MINIMIZED:
+ native_show_state = SW_SHOWMINIMIZED;
+ break;
+ default:
+ native_show_state = delegate_->GetInitialShowState();
+ break;
+ }
+ Show(native_show_state);
+}
+
+void HWNDMessageHandler::Show(int show_state) {
+ ShowWindow(hwnd(), show_state);
+ // When launched from certain programs like bash and Windows Live Messenger,
+ // show_state is set to SW_HIDE, so we need to correct that condition. We
+ // don't just change show_state to SW_SHOWNORMAL because MSDN says we must
+ // always first call ShowWindow with the specified value from STARTUPINFO,
+ // otherwise all future ShowWindow calls will be ignored (!!#@@#!). Instead,
+ // we call ShowWindow again in this case.
+ if (show_state == SW_HIDE) {
+ show_state = SW_SHOWNORMAL;
+ ShowWindow(hwnd(), show_state);
+ }
+
+ // We need to explicitly activate the window if we've been shown with a state
+ // that should activate, because if we're opened from a desktop shortcut while
+ // an existing window is already running it doesn't seem to be enough to use
+ // one of these flags to activate the window.
+ if (show_state == SW_SHOWNORMAL || show_state == SW_SHOWMAXIMIZED)
+ Activate();
+
+ if (!delegate_->HandleInitialFocus())
+ SetInitialFocus();
+}
+
void HWNDMessageHandler::ShowMaximizedWithBounds(const gfx::Rect& bounds) {
WINDOWPLACEMENT placement = { 0 };
placement.length = sizeof(WINDOWPLACEMENT);
@@ -537,6 +663,10 @@
return watcher.got_mouse_up();
}
+void HWNDMessageHandler::EndMoveLoop() {
+ SendMessage(hwnd(), WM_CANCELMODE, 0, 0);
+}
+
void HWNDMessageHandler::SendFrameChanged() {
SetWindowPos(hwnd(), NULL, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOCOPYBITS |
@@ -598,6 +728,51 @@
return new InputMethodWin(this);
}
+void HWNDMessageHandler::SetTitle(const string16& title) {
+ SetWindowText(hwnd(), title.c_str());
+ SetAccessibleName(title);
+}
+
+void HWNDMessageHandler::SetAccessibleName(const string16& name) {
+ base::win::ScopedComPtr<IAccPropServices> pAccPropServices;
+ HRESULT hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER,
+ IID_IAccPropServices, reinterpret_cast<void**>(&pAccPropServices));
+ if (SUCCEEDED(hr))
+ hr = pAccPropServices->SetHwndPropStr(hwnd(), OBJID_CLIENT, CHILDID_SELF,
+ PROPID_ACC_NAME, name.c_str());
+}
+
+void HWNDMessageHandler::SetAccessibleRole(ui::AccessibilityTypes::Role role) {
+ base::win::ScopedComPtr<IAccPropServices> pAccPropServices;
+ HRESULT hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER,
+ IID_IAccPropServices, reinterpret_cast<void**>(&pAccPropServices));
+ if (SUCCEEDED(hr)) {
+ VARIANT var;
+ if (role) {
+ var.vt = VT_I4;
+ var.lVal = NativeViewAccessibilityWin::MSAARole(role);
+ hr = pAccPropServices->SetHwndProp(hwnd(), OBJID_CLIENT, CHILDID_SELF,
+ PROPID_ACC_ROLE, var);
+ }
+ }
+}
+
+void HWNDMessageHandler::SetAccessibleState(
+ ui::AccessibilityTypes::State state) {
+ base::win::ScopedComPtr<IAccPropServices> pAccPropServices;
+ HRESULT hr = CoCreateInstance(CLSID_AccPropServices, NULL, CLSCTX_SERVER,
+ IID_IAccPropServices, reinterpret_cast<void**>(&pAccPropServices));
+ if (SUCCEEDED(hr)) {
+ VARIANT var;
+ if (state) {
+ var.vt = VT_I4;
+ var.lVal = NativeViewAccessibilityWin::MSAAState(state);
+ hr = pAccPropServices->SetHwndProp(hwnd(), OBJID_CLIENT, CHILDID_SELF,
+ PROPID_ACC_STATE, var);
+ }
+ }
+}
+
void HWNDMessageHandler::SendNativeAccessibilityEvent(
int id,
ui::AccessibilityTypes::Event event_type) {
@@ -676,6 +851,28 @@
layered_alpha_ = opacity;
}
+void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon,
+ const gfx::ImageSkia& app_icon) {
+ if (!window_icon.isNull()) {
+ HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(window_icon);
+ // We need to make sure to destroy the previous icon, otherwise we'll leak
+ // these GDI objects until we crash!
+ HICON old_icon = reinterpret_cast<HICON>(
+ SendMessage(hwnd(), WM_SETICON, ICON_SMALL,
+ reinterpret_cast<LPARAM>(windows_icon)));
+ if (old_icon)
+ DestroyIcon(old_icon);
+ }
+ if (!app_icon.isNull()) {
+ HICON windows_icon = IconUtil::CreateHICONFromSkBitmap(app_icon);
+ HICON old_icon = reinterpret_cast<HICON>(
+ SendMessage(hwnd(), WM_SETICON, ICON_BIG,
+ reinterpret_cast<LPARAM>(windows_icon)));
+ if (old_icon)
+ DestroyIcon(old_icon);
+ }
+}
+
void HWNDMessageHandler::OnActivate(UINT action, BOOL minimized, HWND window) {
SetMsgHandled(FALSE);
}
@@ -765,7 +962,7 @@
}
void HWNDMessageHandler::OnDestroy() {
- delegate_->HandleDestroy();
+ delegate_->HandleDestroying();
}
void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
@@ -1642,8 +1839,96 @@
}
////////////////////////////////////////////////////////////////////////////////
+// HWNDMessageHandler, ui::WindowImpl overrides:
+
+HICON HWNDMessageHandler::GetDefaultWindowIcon() const {
+ return ViewsDelegate::views_delegate ?
+ ViewsDelegate::views_delegate->GetDefaultWindowIcon() : NULL;
+}
+
+LRESULT HWNDMessageHandler::OnWndProc(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ HWND window = hwnd();
+ LRESULT result = 0;
+
+ // First allow messages sent by child controls to be processed directly by
+ // their associated views. If such a view is present, it will handle the
+ // message *instead of* this NativeWidgetWin.
+ if (ProcessChildWindowMessage(message, w_param, l_param, &result))
+ return result;
+
+ // Otherwise we handle everything else.
+ if (!delegate_->AsNativeWidgetWin()->ProcessWindowMessage(
+ window, message, w_param, l_param, result)) {
+ result = DefWindowProc(window, message, w_param, l_param);
+ }
+ if (message == WM_NCDESTROY)
+ delegate_->HandleDestroyed();
+
+ // Only top level widget should store/restore focus.
+ if (message == WM_ACTIVATE && delegate_->CanSaveFocus())
+ PostProcessActivateMessage(LOWORD(w_param));
+ if (message == WM_ENABLE && restore_focus_when_enabled_) {
+ // This path should be executed only for top level as
+ // restore_focus_when_enabled_ is set in PostProcessActivateMessage.
+ DCHECK(delegate_->CanSaveFocus());
+ restore_focus_when_enabled_ = false;
+ delegate_->RestoreFocusOnEnable();
+ }
+ return result;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, private:
+void HWNDMessageHandler::SetInitialFocus() {
+ if (!(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_TRANSPARENT) &&
+ !(GetWindowLong(hwnd(), GWL_EXSTYLE) & WS_EX_NOACTIVATE)) {
+ // The window does not get keyboard messages unless we focus it.
+ SetFocus(hwnd());
+ }
+}
+
+void HWNDMessageHandler::PostProcessActivateMessage(int activation_state) {
+ DCHECK(delegate_->CanSaveFocus());
+ if (WA_INACTIVE == activation_state) {
+ // We might get activated/inactivated without being enabled, so we need to
+ // clear restore_focus_when_enabled_.
+ restore_focus_when_enabled_ = false;
+ delegate_->SaveFocusOnDeactivate();
+ } else {
+ // We must restore the focus after the message has been DefProc'ed as it
+ // does set the focus to the last focused HWND.
+ // Note that if the window is not enabled, we cannot restore the focus as
+ // calling ::SetFocus on a child of the non-enabled top-window would fail.
+ // This is the case when showing a modal dialog (such as 'open file',
+ // 'print'...) from a different thread.
+ // In that case we delay the focus restoration to when the window is enabled
+ // again.
+ if (!IsWindowEnabled(hwnd())) {
+ DCHECK(!restore_focus_when_enabled_);
+ restore_focus_when_enabled_ = true;
+ return;
+ }
+ delegate_->RestoreFocusOnActivate();
+ }
+}
+
+void HWNDMessageHandler::RestoreEnabledIfNecessary() {
+ if (delegate_->IsModal() && !restored_enabled_) {
+ restored_enabled_ = true;
+ // If we were run modally, we need to undo the disabled-ness we inflicted on
+ // the owner's parent hierarchy.
+ HWND start = ::GetWindow(hwnd(), GW_OWNER);
+ while (start) {
+ ::EnableWindow(start, TRUE);
+ start = ::GetParent(start);
+ }
+ }
+}
+
void HWNDMessageHandler::ExecuteSystemMenuCommand(int command) {
if (command)
SendMessage(hwnd(), WM_SYSCOMMAND, command, 0);
« no previous file with comments | « ui/views/win/hwnd_message_handler.h ('k') | ui/views/win/hwnd_message_handler_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698