Home | History | Annotate | Download | only in metro_driver
      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 
     17 MetroDialogBox::MetroDialogBox() {
     18   DVLOG(1) << __FUNCTION__;
     19   dialog_box_info_.button1_handler = NULL;
     20   dialog_box_info_.button2_handler = NULL;
     21 }
     22 
     23 MetroDialogBox::~MetroDialogBox() {
     24   DVLOG(1) << __FUNCTION__;
     25 }
     26 
     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.
     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 
    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 
    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