1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #import <CoreServices/CoreServices.h>
9 #import <Cocoa/Cocoa.h>
12 #include "nsCocoaFeatures.h"
13 #include "nsNativeAppSupportBase.h"
14 #include "nsServiceManagerUtils.h"
16 #include "nsIBaseWindow.h"
17 #include "nsCommandLine.h"
18 #include "mozIDOMWindow.h"
19 #include "nsIWebNavigation.h"
20 #include "nsIWidget.h"
21 #include "nsIWindowMediator.h"
22 #include "nsPIDOMWindow.h"
23 #include "WidgetUtils.h"
25 // This must be included last:
26 #include "nsObjCExceptions.h"
28 using mozilla::widget::WidgetUtils;
30 nsresult GetNativeWindowPointerFromDOMWindow(mozIDOMWindowProxy* a_window,
31 NSWindow** a_nativeWindow) {
32 *a_nativeWindow = nil;
33 if (!a_window) return NS_ERROR_INVALID_ARG;
35 nsPIDOMWindowOuter* win = nsPIDOMWindowOuter::From(a_window);
36 nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(win);
38 return NS_ERROR_FAILURE;
41 *a_nativeWindow = (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
46 class nsNativeAppSupportCocoa : public nsNativeAppSupportBase {
48 nsNativeAppSupportCocoa() : mCanShowUI(false) {}
50 NS_IMETHOD Start(bool* aRetVal) override;
51 NS_IMETHOD ReOpen() override;
52 NS_IMETHOD Enable() override;
59 nsNativeAppSupportCocoa::Enable() {
64 NS_IMETHODIMP nsNativeAppSupportCocoa::Start(bool* _retval) {
65 int major, minor, bugfix;
66 nsCocoaFeatures::GetSystemVersion(major, minor, bugfix);
68 NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
70 // Check that the OS version is supported, if not return false,
71 // which will make the browser quit. In principle we could display an
72 // alert here. But the alert's message and buttons would require custom
73 // localization. So (for now at least) we just log an English message
74 // to the console before quitting.
75 if (major < 10 || (major == 10 && minor < 12)) {
76 NSLog(@"Minimum OS version requirement not met!");
84 NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
88 nsNativeAppSupportCocoa::ReOpen() {
89 NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
91 if (!mCanShowUI) return NS_ERROR_FAILURE;
93 bool haveNonMiniaturized = false;
94 bool haveOpenWindows = false;
97 nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
99 return NS_ERROR_FAILURE;
101 nsCOMPtr<nsISimpleEnumerator> windowList;
102 wm->GetAppWindowEnumerator(nullptr, getter_AddRefs(windowList));
104 windowList->HasMoreElements(&more);
106 nsCOMPtr<nsISupports> nextWindow = nullptr;
107 windowList->GetNext(getter_AddRefs(nextWindow));
108 nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(nextWindow));
110 windowList->HasMoreElements(&more);
113 haveOpenWindows = true;
116 nsCOMPtr<nsIWidget> widget = nullptr;
117 baseWindow->GetMainWidget(getter_AddRefs(widget));
118 if (!widget || !widget->IsVisible()) {
119 windowList->HasMoreElements(&more);
122 NSWindow* cocoaWindow =
123 (NSWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
124 if (![cocoaWindow isMiniaturized]) {
125 haveNonMiniaturized = true;
126 break; // have un-minimized windows, nothing to do
128 windowList->HasMoreElements(&more);
131 if (!haveNonMiniaturized) {
132 // Prioritize browser windows for deminiaturization
133 nsCOMPtr<mozIDOMWindowProxy> mru;
134 wm->GetMostRecentBrowserWindow(getter_AddRefs(mru));
136 // Failing that, deminiaturize the most recently used window
138 wm->GetMostRecentWindow(nullptr, getter_AddRefs(mru));
142 NSWindow* cocoaMru = nil;
143 GetNativeWindowPointerFromDOMWindow(mru, &cocoaMru);
145 [cocoaMru deminiaturize:nil];
149 } // end if have non miniaturized
151 if (!haveOpenWindows && !done) {
152 char* argv[] = {nullptr};
154 // use an empty command line to make the right kind(s) of window open
155 nsCOMPtr<nsICommandLineRunner> cmdLine(new nsCommandLine());
158 rv = cmdLine->Init(0, argv, nullptr,
159 nsICommandLine::STATE_REMOTE_EXPLICIT);
160 NS_ENSURE_SUCCESS(rv, rv);
162 return cmdLine->Run();
165 } // got window mediator
168 NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
173 // Create and return an instance of class nsNativeAppSupportCocoa.
174 nsresult NS_CreateNativeAppSupport(nsINativeAppSupport** aResult) {
175 *aResult = new nsNativeAppSupportCocoa;
176 if (!*aResult) return NS_ERROR_OUT_OF_MEMORY;