feat: allow registering multiple shortcuts (#15542)
This PR allows for multiple global shortcuts to be registered such that triggering any of them calls the same callback.
This commit is contained in:
parent
20a540e680
commit
e9ba26f50e
4 changed files with 61 additions and 2 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include "atom/browser/api/atom_api_global_shortcut.h"
|
#include "atom/browser/api/atom_api_global_shortcut.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/common/native_mate_converters/accelerator_converter.h"
|
#include "atom/common/native_mate_converters/accelerator_converter.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
@ -38,6 +39,24 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||||
accelerator_callback_map_[accelerator].Run();
|
accelerator_callback_map_[accelerator].Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GlobalShortcut::RegisterAll(
|
||||||
|
const std::vector<ui::Accelerator>& accelerators,
|
||||||
|
const base::Closure& callback) {
|
||||||
|
std::vector<ui::Accelerator> registered;
|
||||||
|
for (auto& accelerator : accelerators) {
|
||||||
|
GlobalShortcutListener* listener = GlobalShortcutListener::GetInstance();
|
||||||
|
if (!listener->RegisterAccelerator(accelerator, this)) {
|
||||||
|
// unregister all shortcuts if any failed
|
||||||
|
UnregisterSome(registered);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
registered.push_back(accelerator);
|
||||||
|
accelerator_callback_map_[accelerator] = callback;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||||
const base::Closure& callback) {
|
const base::Closure& callback) {
|
||||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
||||||
|
@ -58,6 +77,13 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlobalShortcut::UnregisterSome(
|
||||||
|
const std::vector<ui::Accelerator>& accelerators) {
|
||||||
|
for (auto& accelerator : accelerators) {
|
||||||
|
Unregister(accelerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
||||||
return ContainsKey(accelerator_callback_map_, accelerator);
|
return ContainsKey(accelerator_callback_map_, accelerator);
|
||||||
}
|
}
|
||||||
|
@ -77,6 +103,7 @@ void GlobalShortcut::BuildPrototype(v8::Isolate* isolate,
|
||||||
v8::Local<v8::FunctionTemplate> prototype) {
|
v8::Local<v8::FunctionTemplate> prototype) {
|
||||||
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
prototype->SetClassName(mate::StringToV8(isolate, "GlobalShortcut"));
|
||||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||||
|
.SetMethod("registerAll", &GlobalShortcut::RegisterAll)
|
||||||
.SetMethod("register", &GlobalShortcut::Register)
|
.SetMethod("register", &GlobalShortcut::Register)
|
||||||
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
.SetMethod("isRegistered", &GlobalShortcut::IsRegistered)
|
||||||
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
.SetMethod("unregister", &GlobalShortcut::Unregister)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/browser/api/trackable_object.h"
|
#include "atom/browser/api/trackable_object.h"
|
||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
|
@ -33,10 +34,13 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
|
||||||
private:
|
private:
|
||||||
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
|
typedef std::map<ui::Accelerator, base::Closure> AcceleratorCallbackMap;
|
||||||
|
|
||||||
|
bool RegisterAll(const std::vector<ui::Accelerator>& accelerators,
|
||||||
|
const base::Closure& callback);
|
||||||
bool Register(const ui::Accelerator& accelerator,
|
bool Register(const ui::Accelerator& accelerator,
|
||||||
const base::Closure& callback);
|
const base::Closure& callback);
|
||||||
bool IsRegistered(const ui::Accelerator& accelerator);
|
bool IsRegistered(const ui::Accelerator& accelerator);
|
||||||
void Unregister(const ui::Accelerator& accelerator);
|
void Unregister(const ui::Accelerator& accelerator);
|
||||||
|
void UnregisterSome(const std::vector<ui::Accelerator>& accelerators);
|
||||||
void UnregisterAll();
|
void UnregisterAll();
|
||||||
|
|
||||||
// GlobalShortcutListener::Observer implementation.
|
// GlobalShortcutListener::Observer implementation.
|
||||||
|
|
|
@ -54,6 +54,17 @@ When the accelerator is already taken by other applications, this call will
|
||||||
silently fail. This behavior is intended by operating systems, since they don't
|
silently fail. This behavior is intended by operating systems, since they don't
|
||||||
want applications to fight for global shortcuts.
|
want applications to fight for global shortcuts.
|
||||||
|
|
||||||
|
### `globalShortcut.registerAll(accelerators, callback)`
|
||||||
|
|
||||||
|
* `accelerators` String[] - an array of [Accelerator](accelerator.md)s.
|
||||||
|
* `callback` Function
|
||||||
|
|
||||||
|
Registers a global shortcut of all `accelerator` items in `accelerators`. The `callback` is called when any of the registered shortcuts are pressed by the user.
|
||||||
|
|
||||||
|
When a given accelerator is already taken by other applications, this call will
|
||||||
|
silently fail. This behavior is intended by operating systems, since they don't
|
||||||
|
want applications to fight for global shortcuts.
|
||||||
|
|
||||||
### `globalShortcut.isRegistered(accelerator)`
|
### `globalShortcut.isRegistered(accelerator)`
|
||||||
|
|
||||||
* `accelerator` [Accelerator](accelerator.md)
|
* `accelerator` [Accelerator](accelerator.md)
|
||||||
|
|
|
@ -18,8 +18,8 @@ describe('globalShortcut module', () => {
|
||||||
globalShortcut.unregisterAll()
|
globalShortcut.unregisterAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can register and unregister accelerators', () => {
|
it('can register and unregister single accelerators', () => {
|
||||||
const accelerator = 'CommandOrControl+A+B+C'
|
const accelerator = 'CmdOrCtrl+A+B+C'
|
||||||
|
|
||||||
expect(globalShortcut.isRegistered(accelerator)).to.be.false()
|
expect(globalShortcut.isRegistered(accelerator)).to.be.false()
|
||||||
globalShortcut.register(accelerator, () => {})
|
globalShortcut.register(accelerator, () => {})
|
||||||
|
@ -33,4 +33,21 @@ describe('globalShortcut module', () => {
|
||||||
globalShortcut.unregisterAll()
|
globalShortcut.unregisterAll()
|
||||||
expect(globalShortcut.isRegistered(accelerator)).to.be.false()
|
expect(globalShortcut.isRegistered(accelerator)).to.be.false()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('can register and unregister multiple accelerators', () => {
|
||||||
|
const accelerators = ['CmdOrCtrl+X', 'CmdOrCtrl+Y']
|
||||||
|
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[0])).to.be.false()
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[1])).to.be.false()
|
||||||
|
|
||||||
|
globalShortcut.registerAll(accelerators, () => {})
|
||||||
|
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[0])).to.be.true()
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[1])).to.be.true()
|
||||||
|
|
||||||
|
globalShortcut.unregisterAll()
|
||||||
|
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[0])).to.be.false()
|
||||||
|
expect(globalShortcut.isRegistered(accelerators[1])).to.be.false()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue