Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / base / win / open_file_name_win.cc
index b63eb47..3914fa5 100644 (file)
@@ -6,10 +6,67 @@
 
 #include "base/files/file_path.h"
 #include "base/strings/string_util.h"
+#include "base/win/windows_version.h"
 
 namespace ui {
 namespace win {
 
+namespace {
+
+// Ensures that the Save As dialog is on-screen.
+UINT_PTR CALLBACK SaveAsDialogHook(HWND dialog, UINT message,
+                                   WPARAM wparam, LPARAM lparam) {
+  static const UINT kPrivateMessage = 0x2F3F;
+  switch (message) {
+    case WM_INITDIALOG: {
+      // Do nothing here. Just post a message to defer actual processing.
+      ::PostMessage(dialog, kPrivateMessage, 0, 0);
+      return TRUE;
+    }
+    case kPrivateMessage: {
+      // The dialog box is the parent of the current handle.
+      HWND real_dialog = ::GetParent(dialog);
+
+      // Retrieve the final size.
+      RECT dialog_rect;
+      ::GetWindowRect(real_dialog, &dialog_rect);
+
+      // Verify that the upper left corner is visible.
+      POINT point = { dialog_rect.left, dialog_rect.top };
+      HMONITOR monitor1 = ::MonitorFromPoint(point, MONITOR_DEFAULTTONULL);
+      point.x = dialog_rect.right;
+      point.y = dialog_rect.bottom;
+
+      // Verify that the lower right corner is visible.
+      HMONITOR monitor2 = ::MonitorFromPoint(point, MONITOR_DEFAULTTONULL);
+      if (monitor1 && monitor2)
+        return 0;
+
+      // Some part of the dialog box is not visible, fix it by moving is to the
+      // client rect position of the browser window.
+      HWND parent_window = ::GetParent(real_dialog);
+      if (!parent_window)
+        return 0;
+      WINDOWINFO parent_info;
+      parent_info.cbSize = sizeof(WINDOWINFO);
+      ::GetWindowInfo(parent_window, &parent_info);
+      ::SetWindowPos(
+          real_dialog,
+          NULL,
+          parent_info.rcClient.left,
+          parent_info.rcClient.top,
+          0,
+          0,  // Size.
+          SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER);
+
+      return 0;
+    }
+  }
+  return 0;
+}
+
+}  // namespace
+
 OpenFileName::OpenFileName(HWND parent_window, DWORD flags) {
   ::ZeroMemory(&openfilename_, sizeof(openfilename_));
   openfilename_.lStructSize = sizeof(openfilename_);
@@ -72,6 +129,15 @@ void OpenFileName::SetInitialSelection(const base::FilePath& initial_directory,
                 arraysize(filename_buffer_));
 }
 
+void OpenFileName::MaybeInstallWindowPositionHookForSaveAsOnXP() {
+  if (base::win::GetVersion() >= base::win::VERSION_VISTA)
+    return;
+
+  openfilename_.Flags |= OFN_ENABLEHOOK;
+  DCHECK(!openfilename_.lpfnHook);
+  openfilename_.lpfnHook = &SaveAsDialogHook;
+}
+
 base::FilePath OpenFileName::GetSingleResult() {
   base::FilePath directory;
   std::vector<base::FilePath> filenames;
@@ -85,10 +151,19 @@ void OpenFileName::GetResult(base::FilePath* directory,
                              std::vector<base::FilePath>* filenames) {
   DCHECK(filenames->empty());
   const wchar_t* selection = openfilename_.lpstrFile;
-  while (*selection) {  // Empty string indicates end of list.
+  // The return value of |openfilename_.lpstrFile| is dependent on the
+  // value of the Multi-Select flag within |openfilename_|. If the flag is
+  // not set the return value will be a single null-terminated wide string.
+  // If it is set it will be more than one null-terminated wide string, itself
+  // terminated by an empty null-terminated wide string.
+  if (openfilename_.Flags & OFN_ALLOWMULTISELECT) {
+    while (*selection) {  // Empty string indicates end of list.
+      filenames->push_back(base::FilePath(selection));
+      // Skip over filename and null-terminator.
+      selection += filenames->back().value().length() + 1;
+    }
+  } else {
     filenames->push_back(base::FilePath(selection));
-    // Skip over filename and null-terminator.
-    selection += filenames->back().value().length() + 1;
   }
   if (filenames->size() == 1) {
     // When there is one file, it contains the path and filename.