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.
5 #include "win8/metro_driver/stdafx.h"
7 #include "win8/metro_driver/chrome_app_view.h"
8 #include "win8/metro_driver/metro_dialog_box.h"
9 #include "win8/metro_driver/winrt_utils.h"
11 typedef winfoundtn::Collections::
12 IVector
<ABI::Windows::UI::Popups::IUICommand
*> WindowsUICommands
;
14 typedef winfoundtn::IAsyncOperation
<ABI::Windows::UI::Popups::IUICommand
*>
17 MetroDialogBox::MetroDialogBox() {
18 DVLOG(1) << __FUNCTION__
;
19 dialog_box_info_
.button1_handler
= NULL
;
20 dialog_box_info_
.button2_handler
= NULL
;
23 MetroDialogBox::~MetroDialogBox() {
24 DVLOG(1) << __FUNCTION__
;
27 void MetroDialogBox::Show(
28 const DialogBoxInfo
& dialog_box_info
) {
29 DVLOG(1) << __FUNCTION__
;
31 // Only one dialog can be displayed at a given time.
32 DCHECK(dialog_box_
.Get() == NULL
);
34 // The message dialog display does not work correctly in snapped mode.
35 mswr::ComPtr
<winui::Popups::IMessageDialogFactory
> message_dialog_factory
;
36 HRESULT hr
= winrt_utils::CreateActivationFactory(
37 RuntimeClass_Windows_UI_Popups_MessageDialog
,
38 message_dialog_factory
.GetAddressOf());
39 CheckHR(hr
, "Failed to activate IMessageDialogFactory");
41 mswrw::HString message_title
;
42 message_title
.Attach(MakeHString(dialog_box_info
.title
));
44 mswrw::HString message_content
;
45 message_content
.Attach(MakeHString(dialog_box_info
.content
));
47 hr
= message_dialog_factory
->CreateWithTitle(
48 message_content
.Get(),
50 dialog_box_
.GetAddressOf());
51 CheckHR(hr
, "Failed to create message dialog");
53 mswr::ComPtr
<WindowsUICommands
> commands
;
54 hr
= dialog_box_
->get_Commands(commands
.GetAddressOf());
55 CheckHR(hr
, "Failed to create ui command collection");
57 mswr::ComPtr
<winui::Popups::IUICommandFactory
> ui_command_factory
;
58 hr
= winrt_utils::CreateActivationFactory(
59 RuntimeClass_Windows_UI_Popups_UICommand
,
60 ui_command_factory
.GetAddressOf());
61 CheckHR(hr
, "Failed to activate IUICommandFactory");
63 mswrw::HString label1
;
64 label1
.Attach(MakeHString(dialog_box_info
.button1_label
));
66 mswr::ComPtr
<winui::Popups::IUICommand
> label1_command
;
67 hr
= ui_command_factory
->CreateWithHandler(
68 label1
.Get(), this, label1_command
.GetAddressOf());
69 CheckHR(hr
, "Failed to add button1");
71 mswrw::HString label2
;
72 label2
.Attach(MakeHString(dialog_box_info
.button2_label
));
74 mswr::ComPtr
<winui::Popups::IUICommand
> label2_command
;
75 hr
= ui_command_factory
->CreateWithHandler(label2
.Get(), this,
76 label2_command
.GetAddressOf());
77 CheckHR(hr
, "Failed to add button2");
79 commands
->Append(label1_command
.Get());
80 commands
->Append(label2_command
.Get());
82 mswr::ComPtr
<AsyncCommandStatus
> ret
;
83 hr
= dialog_box_
->ShowAsync(ret
.GetAddressOf());
84 CheckHR(hr
, "Failed to show dialog");
86 dialog_box_info_
= dialog_box_info
;
89 // The dialog box displayed via the MessageDialog interface has the class name
90 // 'Shell_Dialog'. The dialog box is top level window. To find it we enumerate
91 // all top level windows and compare the class names. If we find a matching
92 // window class we compare its process id with ours and return the same.
93 BOOL CALLBACK
DialogBoxFinder(HWND hwnd
, LPARAM lparam
) {
94 char classname
[MAX_PATH
] = {0};
96 if (::GetClassNameA(hwnd
, classname
, ARRAYSIZE(classname
))) {
97 if (lstrcmpiA("Shell_Dialog", classname
) == 0) {
98 if (GetWindowLong(hwnd
, GWL_EXSTYLE
) & WS_EX_TOPMOST
) {
99 DVLOG(1) << "Found top most dialog box: " << classname
;
100 DVLOG(1) << "HWND: " << hwnd
;
101 DWORD window_pid
= 0;
102 DWORD window_tid
= GetWindowThreadProcessId(hwnd
, &window_pid
);
103 DVLOG(1) << "Window tid: " << window_tid
;
104 DVLOG(1) << "Window pid: " << window_pid
;
106 if (window_pid
== ::GetCurrentProcessId()) {
107 HWND
* dialog_window
= reinterpret_cast<HWND
*>(lparam
);
108 *dialog_window
= hwnd
;
117 void MetroDialogBox::Dismiss() {
118 DVLOG(1) << __FUNCTION__
;
122 dialog_box_info_
.button1_handler
= NULL
;
123 dialog_box_info_
.button2_handler
= NULL
;
124 dialog_box_info_
.button1_label
.clear();
125 dialog_box_info_
.button2_label
.clear();
128 // We don't have a good way to dismiss the dialog box. Hack for now is to
129 // find the dialog box class in our process and close it via the WM_CLOSE
131 HWND dialog_box
= NULL
;
132 ::EnumWindows(&DialogBoxFinder
, reinterpret_cast<LPARAM
>(&dialog_box
));
133 if (::IsWindow(dialog_box
))
134 PostMessage(dialog_box
, WM_CLOSE
, 0, 0);
137 HRESULT STDMETHODCALLTYPE
MetroDialogBox::Invoke(
138 winui::Popups::IUICommand
* command
) {
139 DVLOG(1) << __FUNCTION__
;
141 mswrw::HString label
;
142 command
->get_Label(label
.GetAddressOf());
144 string16 button_label
= MakeStdWString(label
.Get());
145 DVLOG(1) << "Clicked button label is : " << button_label
;
146 if (button_label
== dialog_box_info_
.button1_label
) {
147 DVLOG(1) << "Button1 clicked";
148 DCHECK(dialog_box_info_
.button1_handler
);
149 dialog_box_info_
.button1_handler();
150 } else if (button_label
== dialog_box_info_
.button2_label
) {
151 DVLOG(1) << "Button2 clicked";
152 DCHECK(dialog_box_info_
.button2_handler
);
153 dialog_box_info_
.button2_handler();
155 // The dialog box is destroyed once we return from invoke. Go ahead and