• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "win8/metro_driver/stdafx.h"
6 
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"
10 
11 typedef winfoundtn::Collections::
12     IVector<ABI::Windows::UI::Popups::IUICommand*> WindowsUICommands;
13 
14 typedef winfoundtn::IAsyncOperation<ABI::Windows::UI::Popups::IUICommand*>
15     AsyncCommandStatus;
16 
MetroDialogBox()17 MetroDialogBox::MetroDialogBox() {
18   DVLOG(1) << __FUNCTION__;
19   dialog_box_info_.button1_handler = NULL;
20   dialog_box_info_.button2_handler = NULL;
21 }
22 
~MetroDialogBox()23 MetroDialogBox::~MetroDialogBox() {
24   DVLOG(1) << __FUNCTION__;
25 }
26 
Show(const DialogBoxInfo & dialog_box_info)27 void MetroDialogBox::Show(
28     const DialogBoxInfo& dialog_box_info) {
29   DVLOG(1) << __FUNCTION__;
30 
31   // Only one dialog can be displayed at a given time.
32   DCHECK(dialog_box_.Get() == NULL);
33 
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");
40 
41   mswrw::HString message_title;
42   message_title.Attach(MakeHString(dialog_box_info.title));
43 
44   mswrw::HString message_content;
45   message_content.Attach(MakeHString(dialog_box_info.content));
46 
47   hr = message_dialog_factory->CreateWithTitle(
48       message_content.Get(),
49       message_title.Get(),
50       dialog_box_.GetAddressOf());
51   CheckHR(hr, "Failed to create message dialog");
52 
53   mswr::ComPtr<WindowsUICommands> commands;
54   hr = dialog_box_->get_Commands(commands.GetAddressOf());
55   CheckHR(hr, "Failed to create ui command collection");
56 
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");
62 
63   mswrw::HString label1;
64   label1.Attach(MakeHString(dialog_box_info.button1_label));
65 
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");
70 
71   mswrw::HString label2;
72   label2.Attach(MakeHString(dialog_box_info.button2_label));
73 
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");
78 
79   commands->Append(label1_command.Get());
80   commands->Append(label2_command.Get());
81 
82   mswr::ComPtr<AsyncCommandStatus> ret;
83   hr = dialog_box_->ShowAsync(ret.GetAddressOf());
84   CheckHR(hr, "Failed to show dialog");
85 
86   dialog_box_info_ = dialog_box_info;
87 }
88 
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.
DialogBoxFinder(HWND hwnd,LPARAM lparam)93 BOOL CALLBACK DialogBoxFinder(HWND hwnd, LPARAM lparam) {
94   char classname[MAX_PATH] = {0};
95 
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;
105 
106         if (window_pid == ::GetCurrentProcessId()) {
107           HWND* dialog_window = reinterpret_cast<HWND*>(lparam);
108           *dialog_window = hwnd;
109           return FALSE;
110         }
111       }
112     }
113   }
114   return TRUE;
115 }
116 
Dismiss()117 void MetroDialogBox::Dismiss() {
118   DVLOG(1) << __FUNCTION__;
119   if (!dialog_box_)
120     return;
121 
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();
126   dialog_box_.Reset();
127 
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
130   // message.
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);
135 }
136 
Invoke(winui::Popups::IUICommand * command)137 HRESULT STDMETHODCALLTYPE MetroDialogBox::Invoke(
138     winui::Popups::IUICommand* command) {
139   DVLOG(1) << __FUNCTION__;
140 
141   mswrw::HString label;
142   command->get_Label(label.GetAddressOf());
143 
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();
154   }
155   // The dialog box is destroyed once we return from invoke. Go ahead and
156   // dismiss it.
157   Dismiss();
158   return S_OK;
159 }
160 
161