From b724fbc0ed816828ece7bdcfb10583123c56e78c Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 11 Mar 2020 16:07:01 +0000 Subject: [PATCH] feat: add force option to app.focus() (#22612) --- docs/api/app.md | 8 +++++++- shell/browser/browser.h | 2 +- shell/browser/browser_linux.cc | 2 +- shell/browser/browser_mac.mm | 18 ++++++++++++++++-- shell/browser/browser_win.cc | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/api/app.md b/docs/api/app.md index 2974cb8a03b4..72a6a6e024a3 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -554,11 +554,17 @@ Returns `Promise` - fulfilled when Electron is initialized. May be used as a convenient alternative to checking `app.isReady()` and subscribing to the `ready` event if the app is not ready yet. -### `app.focus()` +### `app.focus([options])` + +* `options` Object (optional) + * `steal` Boolean _macOS_ - Make the receiver the active app even if another app is + currently active. On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses on the application's first window. +You should seek to use the `steal` option as sparingly as possible. + ### `app.hide()` _macOS_ Hides all application windows without minimizing them. diff --git a/shell/browser/browser.h b/shell/browser/browser.h index 1ea9c10ef6a1..3135936cd584 100644 --- a/shell/browser/browser.h +++ b/shell/browser/browser.h @@ -57,7 +57,7 @@ class Browser : public WindowListObserver { void Shutdown(); // Focus the application. - void Focus(); + void Focus(gin_helper::Arguments* args); // Returns the version of the executable (or bundle). std::string GetVersion() const; diff --git a/shell/browser/browser_linux.cc b/shell/browser/browser_linux.cc index 48161a4f9e8d..fb605e8e88a7 100644 --- a/shell/browser/browser_linux.cc +++ b/shell/browser/browser_linux.cc @@ -84,7 +84,7 @@ bool SetDefaultWebClient(const std::string& protocol) { return ran_ok && exit_code == EXIT_SUCCESS; } -void Browser::Focus() { +void Browser::Focus(gin_helper::Arguments* args) { // Focus on the first visible window. for (auto* const window : WindowList::GetWindows()) { if (window->IsVisible()) { diff --git a/shell/browser/browser_mac.mm b/shell/browser/browser_mac.mm index fce1493dc184..b51860340e48 100644 --- a/shell/browser/browser_mac.mm +++ b/shell/browser/browser_mac.mm @@ -21,6 +21,8 @@ #include "shell/browser/window_list.h" #include "shell/common/application_info.h" #include "shell/common/gin_helper/arguments.h" +#include "shell/common/gin_helper/dictionary.h" +#include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/promise.h" #include "shell/common/platform_util.h" #include "ui/gfx/image/image.h" @@ -32,8 +34,20 @@ void Browser::SetShutdownHandler(base::Callback handler) { [[AtomApplication sharedApplication] setShutdownHandler:std::move(handler)]; } -void Browser::Focus() { - [[AtomApplication sharedApplication] activateIgnoringOtherApps:NO]; +void Browser::Focus(gin_helper::Arguments* args) { + gin_helper::Dictionary opts; + bool steal_focus = false; + + if (args->GetNext(&opts)) { + gin_helper::ErrorThrower thrower(args->isolate()); + if (!opts.Get("steal", &steal_focus)) { + thrower.ThrowError( + "Expected options object to contain a 'steal' boolean property"); + return; + } + } + + [[AtomApplication sharedApplication] activateIgnoringOtherApps:steal_focus]; } void Browser::Hide() { diff --git a/shell/browser/browser_win.cc b/shell/browser/browser_win.cc index 7e5953050d3d..47e476c4110c 100644 --- a/shell/browser/browser_win.cc +++ b/shell/browser/browser_win.cc @@ -163,7 +163,7 @@ Browser::UserTask::UserTask() = default; Browser::UserTask::UserTask(const UserTask&) = default; Browser::UserTask::~UserTask() = default; -void Browser::Focus() { +void Browser::Focus(gin_helper::Arguments* args) { // On Windows we just focus on the first window found for this process. DWORD pid = GetCurrentProcessId(); EnumWindows(&WindowsEnumerationHandler, reinterpret_cast(&pid));