12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shlobj.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/base_shell_dialog.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/shell_dialogs_export.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A base class for all shell dialog implementations that handles showing a
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shell dialog modally on its own thread.
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SHELL_DIALOGS_EXPORT BaseShellDialogImpl {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BaseShellDialogImpl();
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BaseShellDialogImpl();
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Represents a run of a dialog.
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct RunState {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Owning HWND, may be null.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HWND owner;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Thread dialog is run on.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Thread* dialog_thread;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called at the beginning of a modal dialog run. Disables the owner window
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and tracks it. Returns the message loop of the thread that the dialog will
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be run on.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunState BeginRun(HWND owner);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cleans up after a dialog run. If the run_state has a valid HWND this makes
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sure that the window is enabled. This is essential because BeginRun
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // aggressively guards against multiple modal dialogs per HWND. Must be called
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the UI thread after the result of the dialog has been determined.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In addition this deletes the Thread in RunState.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EndRun(RunState run_state);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if a modal shell dialog is currently active for the specified
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // owner. Must be called on the UI thread.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsRunningDialogForOwner(HWND owner) const;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disables the window |owner|. Can be run from either the ui or the dialog
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread. Can be called on either the UI or the dialog thread. This function
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is called on the dialog thread after the modal Windows Common dialog
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // functions return because Windows automatically re-enables the owning
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window when those functions return, but we don't actually want them to be
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // re-enabled until the response of the dialog propagates back to the UI
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread, so we disable the owner manually after the Common dialog function
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DisableOwner(HWND owner);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<HWND> Owners;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a thread to run a shell dialog on. Each dialog requires its own
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread otherwise in some situations where a singleton owns a single
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance of this object we can have a situation where a modal dialog in
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one window blocks the appearance of a modal dialog in another.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static base::Thread* CreateDialogThread();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enables the window |owner_|. Can only be run from the ui thread.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnableOwner(HWND owner);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A list of windows that currently own active shell dialogs for this
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance. For example, if the DownloadManager owns an instance of this
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object and there are two browser windows open both with Save As dialog
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // boxes active, this list will consist of the two browser windows' HWNDs.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The derived class must call EndRun once the dialog is done showing to
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // remove the owning HWND from this list.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This object is static since it is maintained for all instances of this
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object - i.e. you can't have two file pickers open for the
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same owner, even though they might be represented by different instances
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of this object.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This set only contains non-null HWNDs. NULL hwnds are not added to this
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // list.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Owners owners_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int instance_count_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BaseShellDialogImpl);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // UI_SHELL_DIALOGS_BASE_SHELL_DIALOG_WIN_H_
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
99