From 4d6b0fc01b471adf7529f6e3bb60cb2a3e96759e Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 27 Mar 2017 11:22:52 +1100 Subject: [PATCH 01/14] Add a method to set the escape identifier on the touch bar --- atom/browser/api/atom_api_window.cc | 5 +++++ atom/browser/api/atom_api_window.h | 1 + atom/browser/native_window.cc | 3 +++ atom/browser/native_window.h | 1 + atom/browser/native_window_mac.h | 1 + atom/browser/native_window_mac.mm | 9 +++++++++ atom/browser/ui/cocoa/atom_touch_bar.h | 2 ++ atom/browser/ui/cocoa/atom_touch_bar.mm | 18 ++++++++++++++++++ docs/api/touch-bar.md | 13 ++++++++++++- lib/browser/api/touch-bar.js | 14 ++++++++++++++ 10 files changed, 66 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 6748c9c0dd1..f64b0408274 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -853,6 +853,10 @@ void Window::RefreshTouchBarItem(const std::string& item_id) { window_->RefreshTouchBarItem(item_id); } +void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { + window_->SetEscapeTouchBarItem(item); +} + int32_t Window::ID() const { return weak_map_id(); } @@ -975,6 +979,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("setVibrancy", &Window::SetVibrancy) .SetMethod("_setTouchBarItems", &Window::SetTouchBar) .SetMethod("_refreshTouchBarItem", &Window::RefreshTouchBarItem) + .SetMethod("_setEscapeTouchBarItem", &Window::SetEscapeTouchBarItem) #if defined(OS_WIN) .SetMethod("hookWindowMessage", &Window::HookWindowMessage) .SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index f30baf79d4d..c7b6a37265b 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -208,6 +208,7 @@ class Window : public mate::TrackableObject, void SetVibrancy(mate::Arguments* args); void SetTouchBar(const std::vector& items); void RefreshTouchBarItem(const std::string& item_id); + void SetEscapeTouchBarItem(const mate::PersistentDictionary item); v8::Local WebContents(v8::Isolate* isolate); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 90a823f80b6..4866e4294ca 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -347,6 +347,9 @@ void NativeWindow::SetTouchBar( void NativeWindow::RefreshTouchBarItem(const std::string& item_id) { } +void NativeWindow::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { +} + void NativeWindow::FocusOnWebView() { web_contents()->GetRenderViewHost()->GetWidget()->Focus(); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 941f5849a65..3de57895e52 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -174,6 +174,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetTouchBar( const std::vector& items); virtual void RefreshTouchBarItem(const std::string& item_id); + virtual void SetEscapeTouchBarItem(const mate::PersistentDictionary item); // Webview APIs. virtual void FocusOnWebView(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index bd34993fb11..80ae8895aa1 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -103,6 +103,7 @@ class NativeWindowMac : public NativeWindow, void SetTouchBar( const std::vector& items) override; void RefreshTouchBarItem(const std::string& item_id) override; + void SetEscapeTouchBarItem(const mate::PersistentDictionary item) override; // content::RenderWidgetHost::InputEventObserver: void OnInputEvent(const blink::WebInputEvent& event) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 621e786ddc0..7cbb8e2dffd 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -410,6 +410,11 @@ enum { return nil; } +-(void)setEscapeTouchBarItem:(mate::PersistentDictionary)item { + if (self.touchBar && atom_touch_bar_) + [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:self.touchBar]; +} + // NSWindow overrides. - (void)swipeWithEvent:(NSEvent *)event { @@ -1417,6 +1422,10 @@ void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { [window_ refreshTouchBarItem:item_id]; } +void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { + [window_ setEscapeTouchBarItem:item]; +} + void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) { switch (event.type) { case blink::WebInputEvent::GestureScrollBegin: diff --git a/atom/browser/ui/cocoa/atom_touch_bar.h b/atom/browser/ui/cocoa/atom_touch_bar.h index 29cdf79b255..8232e56f0a1 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.h +++ b/atom/browser/ui/cocoa/atom_touch_bar.h @@ -31,6 +31,8 @@ - (NSTouchBar*)touchBarFromItemIdentifiers:(NSMutableArray*)items; - (NSMutableArray*)identifiersFromSettings:(const std::vector&)settings; - (void)refreshTouchBarItem:(NSTouchBar*)touchBar id:(const std::string&)item_id; +- (void)addNonDefaultTouchBarItems:(std::vector)items; +- (void)setEscapeTouchBarItem:(mate::PersistentDictionary)item forTouchBar:(NSTouchBar*)touchBar; - (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix; diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index 69926684b67..c12434467ee 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -145,7 +145,25 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; } else if (item_type == "scrubber") { [self updateScrubber:(NSCustomTouchBarItem*)item withSettings:settings]; } +} +- (void)addNonDefaultTouchBarItems:(std::vector)items { + [self identifiersFromSettings:items]; +} + +- (void)setEscapeTouchBarItem:(mate::PersistentDictionary)item forTouchBar:(NSTouchBar*)touchBar { + std::string type; + std::string item_id; + NSTouchBarItemIdentifier identifier = nil; + if (item.Get("type", &type) && item.Get("id", &item_id)) { + identifier = [self identifierFromID:item_id type:type]; + } + if (identifier) { + [self addNonDefaultTouchBarItems:{ item }]; + touchBar.escapeKeyReplacementItemIdentifier = identifier; + } else { + touchBar.escapeKeyReplacementItemIdentifier = nil; + } } - (void)buttonAction:(id)sender { diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index 7eb2eb0209b..d5496b8b3f7 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -6,7 +6,7 @@ Process: [Main](../tutorial/quick-start.md#main-process) ### `new TouchBar(items)` _Experimental_ -* `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] +* `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] Creates a new touch bar with the specified items. Use `BrowserWindow.setTouchBar` to add the `TouchBar` to a window. @@ -14,6 +14,17 @@ Creates a new touch bar with the specified items. Use **Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases. +### Instance Methods + +The following methods are available on instances of `TouchBar`: + +#### `touchBar.replaceEscapeItem([touchBarItem])` + +* `touchBarItem` (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer) - (Optional) The touch bar item to replace the escape button with + +Replaces the "esc" button on the touchbar with the given TouchBarItem, if `touchBarItem` is not provided or is falsey the button is reset +to the "esc" button automatically. + ## Examples Below is an example of a simple slot machine touch bar game with a button diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 74951edbac6..68cd6238616 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -28,6 +28,7 @@ class TouchBar extends EventEmitter { } this.windowListeners = {} + this.windows = {} this.items = {} this.ordereredItems = [] @@ -49,6 +50,15 @@ class TouchBar extends EventEmitter { }) } + replaceEscapeItem(item) { + if (!item) item = {} + Object.keys(this.windows).forEach((windowID) => { + const window = this.windows[windowID] + window._setEscapeTouchBarItem(item) + }) + this._escape = item; + } + _addToWindow (window) { const {id} = window @@ -76,11 +86,15 @@ class TouchBar extends EventEmitter { window.removeListener('closed', removeListeners) window._touchBar = null delete this.windowListeners[id] + delete this.windows[id] } window.once('closed', removeListeners) this.windowListeners[id] = removeListeners + this.windows[id] = window; window._setTouchBarItems(this.ordereredItems) + + if (this._escape) window._setEscapeTouchBarItem(this._escape) } _removeFromWindow (window) { From 2ba937289c71b4c7f1da8d31a3d0edf4eabf0d4e Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 27 Mar 2017 11:23:48 +1100 Subject: [PATCH 02/14] Add smoke test for escape replacement --- spec/api-touch-bar-spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index a8e90502f55..0c2f917821c 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -56,6 +56,9 @@ describe('TouchBar module', function () { }) ]) window.setTouchBar(touchBar) + touchBar.replaceEscapeItem(new TouchBarButton({ + label: 'foo' + })) label.label = 'baz' window.setTouchBar() window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) From 60cc8620317e604401cc2c06b13530a9e9e705fa Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 29 Mar 2017 15:11:39 +1100 Subject: [PATCH 03/14] Make everything pointer like --- atom/browser/api/atom_api_window.cc | 2 +- atom/browser/api/atom_api_window.h | 2 +- atom/browser/native_window.cc | 2 +- atom/browser/native_window.h | 2 +- atom/browser/native_window_mac.h | 2 +- atom/browser/native_window_mac.mm | 4 ++-- atom/browser/ui/cocoa/atom_touch_bar.h | 4 ++-- atom/browser/ui/cocoa/atom_touch_bar.mm | 4 ++-- docs/api/touch-bar.md | 2 +- lib/browser/api/touch-bar.js | 6 +++--- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index f64b0408274..9a4ae5850dc 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -853,7 +853,7 @@ void Window::RefreshTouchBarItem(const std::string& item_id) { window_->RefreshTouchBarItem(item_id); } -void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { +void Window::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { window_->SetEscapeTouchBarItem(item); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index c7b6a37265b..24afec354df 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -208,7 +208,7 @@ class Window : public mate::TrackableObject, void SetVibrancy(mate::Arguments* args); void SetTouchBar(const std::vector& items); void RefreshTouchBarItem(const std::string& item_id); - void SetEscapeTouchBarItem(const mate::PersistentDictionary item); + void SetEscapeTouchBarItem(const mate::PersistentDictionary& item); v8::Local WebContents(v8::Isolate* isolate); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 4866e4294ca..413c756cdc3 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -347,7 +347,7 @@ void NativeWindow::SetTouchBar( void NativeWindow::RefreshTouchBarItem(const std::string& item_id) { } -void NativeWindow::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { +void NativeWindow::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { } void NativeWindow::FocusOnWebView() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 3de57895e52..227e28c1e46 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -174,7 +174,7 @@ class NativeWindow : public base::SupportsUserData, virtual void SetTouchBar( const std::vector& items); virtual void RefreshTouchBarItem(const std::string& item_id); - virtual void SetEscapeTouchBarItem(const mate::PersistentDictionary item); + virtual void SetEscapeTouchBarItem(const mate::PersistentDictionary& item); // Webview APIs. virtual void FocusOnWebView(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 80ae8895aa1..a535cdb4bef 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -103,7 +103,7 @@ class NativeWindowMac : public NativeWindow, void SetTouchBar( const std::vector& items) override; void RefreshTouchBarItem(const std::string& item_id) override; - void SetEscapeTouchBarItem(const mate::PersistentDictionary item) override; + void SetEscapeTouchBarItem(const mate::PersistentDictionary& item) override; // content::RenderWidgetHost::InputEventObserver: void OnInputEvent(const blink::WebInputEvent& event) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 7cbb8e2dffd..438bab6e5af 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -411,7 +411,7 @@ enum { } -(void)setEscapeTouchBarItem:(mate::PersistentDictionary)item { - if (self.touchBar && atom_touch_bar_) + if (atom_touch_bar_ && self.touchBar) [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:self.touchBar]; } @@ -1422,7 +1422,7 @@ void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) { [window_ refreshTouchBarItem:item_id]; } -void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary item) { +void NativeWindowMac::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { [window_ setEscapeTouchBarItem:item]; } diff --git a/atom/browser/ui/cocoa/atom_touch_bar.h b/atom/browser/ui/cocoa/atom_touch_bar.h index 8232e56f0a1..26662cf4850 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.h +++ b/atom/browser/ui/cocoa/atom_touch_bar.h @@ -31,8 +31,8 @@ - (NSTouchBar*)touchBarFromItemIdentifiers:(NSMutableArray*)items; - (NSMutableArray*)identifiersFromSettings:(const std::vector&)settings; - (void)refreshTouchBarItem:(NSTouchBar*)touchBar id:(const std::string&)item_id; -- (void)addNonDefaultTouchBarItems:(std::vector)items; -- (void)setEscapeTouchBarItem:(mate::PersistentDictionary)item forTouchBar:(NSTouchBar*)touchBar; +- (void)addNonDefaultTouchBarItems:(const std::vector&)items; +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar; - (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix; diff --git a/atom/browser/ui/cocoa/atom_touch_bar.mm b/atom/browser/ui/cocoa/atom_touch_bar.mm index c12434467ee..3a8037b1c5f 100644 --- a/atom/browser/ui/cocoa/atom_touch_bar.mm +++ b/atom/browser/ui/cocoa/atom_touch_bar.mm @@ -147,11 +147,11 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item"; } } -- (void)addNonDefaultTouchBarItems:(std::vector)items { +- (void)addNonDefaultTouchBarItems:(const std::vector&)items { [self identifiersFromSettings:items]; } -- (void)setEscapeTouchBarItem:(mate::PersistentDictionary)item forTouchBar:(NSTouchBar*)touchBar { +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar { std::string type; std::string item_id; NSTouchBarItemIdentifier identifier = nil; diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index d5496b8b3f7..54315d79773 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -18,7 +18,7 @@ removed in future Electron releases. The following methods are available on instances of `TouchBar`: -#### `touchBar.replaceEscapeItem([touchBarItem])` +#### `touchBar.setEscapeItem([touchBarItem])` * `touchBarItem` (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer) - (Optional) The touch bar item to replace the escape button with diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 68cd6238616..1af18dfbe76 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -50,13 +50,13 @@ class TouchBar extends EventEmitter { }) } - replaceEscapeItem(item) { + setEscapeItem(item) { if (!item) item = {} Object.keys(this.windows).forEach((windowID) => { const window = this.windows[windowID] window._setEscapeTouchBarItem(item) }) - this._escape = item; + this._escape = item } _addToWindow (window) { @@ -90,7 +90,7 @@ class TouchBar extends EventEmitter { } window.once('closed', removeListeners) this.windowListeners[id] = removeListeners - this.windows[id] = window; + this.windows[id] = window window._setTouchBarItems(this.ordereredItems) From df0f468dea069e6a511235e4ffb02e3fe6e7f463 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 12:41:36 -0700 Subject: [PATCH 04/14] Add escapeKeyReplacementItemIdentifier forward declaration --- atom/browser/ui/cocoa/touch_bar_forward_declarations.h | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/ui/cocoa/touch_bar_forward_declarations.h b/atom/browser/ui/cocoa/touch_bar_forward_declarations.h index 57d5bd7453b..6fe7c820a1c 100644 --- a/atom/browser/ui/cocoa/touch_bar_forward_declarations.h +++ b/atom/browser/ui/cocoa/touch_bar_forward_declarations.h @@ -55,6 +55,7 @@ static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierOtherItemsProxy = @property(copy) NSArray* defaultItemIdentifiers; @property(copy, readonly) NSArray* itemIdentifiers; @property(copy, nullable) NSTouchBarItemIdentifier principalItemIdentifier; +@property(copy, nullable) NSTouchBarItemIdentifier escapeKeyReplacementItemIdentifier; @property(copy) NSSet* templateItems; @property(nullable, weak) id delegate; From d596d85288ddca1c5c9e50a26097e3ff76129762 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 12:41:49 -0700 Subject: [PATCH 05/14] :art: --- atom/browser/native_window.cc | 3 ++- lib/browser/api/touch-bar.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 413c756cdc3..af32a2e8a85 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -347,7 +347,8 @@ void NativeWindow::SetTouchBar( void NativeWindow::RefreshTouchBarItem(const std::string& item_id) { } -void NativeWindow::SetEscapeTouchBarItem(const mate::PersistentDictionary& item) { +void NativeWindow::SetEscapeTouchBarItem( + const mate::PersistentDictionary& item) { } void NativeWindow::FocusOnWebView() { diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 1af18dfbe76..2c6b72b8933 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -50,7 +50,7 @@ class TouchBar extends EventEmitter { }) } - setEscapeItem(item) { + setEscapeItem (item) { if (!item) item = {} Object.keys(this.windows).forEach((windowID) => { const window = this.windows[windowID] From 7f8e490839560c63bbf3372ef9699c1d19d3611f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 12:45:01 -0700 Subject: [PATCH 06/14] Take const reference --- atom/browser/native_window_mac.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 438bab6e5af..c3ca24a3d41 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -368,6 +368,7 @@ enum { - (void)enableWindowButtonsOffset; - (void)resetTouchBar:(const std::vector&)settings; - (void)refreshTouchBarItem:(const std::string&)item_id; +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item; @end @@ -410,7 +411,7 @@ enum { return nil; } --(void)setEscapeTouchBarItem:(mate::PersistentDictionary)item { +- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item { if (atom_touch_bar_ && self.touchBar) [atom_touch_bar_ setEscapeTouchBarItem:item forTouchBar:self.touchBar]; } From 6eacec7dc3ddddac37c5f14f41a8b9c6ec16034b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 12:46:33 -0700 Subject: [PATCH 07/14] replaceEscapeItem -> setEscapeItem --- spec/api-touch-bar-spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 0c2f917821c..5564556585f 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -56,7 +56,7 @@ describe('TouchBar module', function () { }) ]) window.setTouchBar(touchBar) - touchBar.replaceEscapeItem(new TouchBarButton({ + touchBar.setEscapeItem(new TouchBarButton({ label: 'foo' })) label.label = 'baz' From 0501a20fe67f6ef3ba348d27bb68bc9ca3f2eb2c Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 12:48:58 -0700 Subject: [PATCH 08/14] Clear escape item --- spec/api-touch-bar-spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 5564556585f..465be6287fc 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -62,6 +62,7 @@ describe('TouchBar module', function () { label.label = 'baz' window.setTouchBar() window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) + touchBar.setEscapeItem() }) }) }) From 591cd8d07338c69dd177e90dd222cf1112ec35ce Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 13:11:25 -0700 Subject: [PATCH 09/14] Update window via listener when escape item changes --- lib/browser/api/touch-bar.js | 25 ++++++++++++++----------- spec/api-touch-bar-spec.js | 7 +++++++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 2c6b72b8933..02e719ada71 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -28,9 +28,9 @@ class TouchBar extends EventEmitter { } this.windowListeners = {} - this.windows = {} this.items = {} this.ordereredItems = [] + this.escapeItem = {} const registerItem = (item) => { this.items[item.id] = item @@ -51,12 +51,12 @@ class TouchBar extends EventEmitter { } setEscapeItem (item) { - if (!item) item = {} - Object.keys(this.windows).forEach((windowID) => { - const window = this.windows[windowID] - window._setEscapeTouchBarItem(item) - }) - this._escape = item + if (item != null && !(item instanceof TouchBarItem)) { + throw new Error('Escape item must be an instance of TouchBarItem') + } + if (item == null) item = {} + this.escapeItem = item + this.emit('escape-item-change', item) } _addToWindow (window) { @@ -72,6 +72,11 @@ class TouchBar extends EventEmitter { } this.on('change', changeListener) + const escapeItemListener = (item) => { + window._setEscapeTouchBarItem(item) + } + this.on('escape-item-change', escapeItemListener) + const interactionListener = (event, itemID, details) => { const item = this.items[itemID] if (item != null && item.onInteraction != null) { @@ -82,19 +87,17 @@ class TouchBar extends EventEmitter { const removeListeners = () => { this.removeListener('change', changeListener) + this.removeListener('escape-item-change', escapeItemListener) window.removeListener('-touch-bar-interaction', interactionListener) window.removeListener('closed', removeListeners) window._touchBar = null delete this.windowListeners[id] - delete this.windows[id] } window.once('closed', removeListeners) this.windowListeners[id] = removeListeners - this.windows[id] = window window._setTouchBarItems(this.ordereredItems) - - if (this._escape) window._setEscapeTouchBarItem(this._escape) + window._setEscapeTouchBarItem(this.escapeItem) } _removeFromWindow (window) { diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 465be6287fc..81bf47eba39 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -20,6 +20,13 @@ describe('TouchBar module', function () { }, /Each item must be an instance of TouchBarItem/) }) + it('throws an error when an invalid escape item is set', function () { + assert.throws(() => { + const touchBar = new TouchBar([]) + touchBar.setEscapeItem('esc') + }, /Escape item must be an instance of TouchBarItem/) + }) + describe('BrowserWindow behavior', function () { let window From 21c1ddffb38cd6eededb057d6af5997727f20067 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 29 Mar 2017 13:26:52 -0700 Subject: [PATCH 10/14] Handle change and interaction events on escape items --- lib/browser/api/touch-bar.js | 24 +++++++++++++++++------- spec/api-touch-bar-spec.js | 8 +++++--- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 02e719ada71..2b95616f221 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -2,6 +2,8 @@ const {EventEmitter} = require('events') let nextItemID = 1 +const DEFAULT_ESCAPE_ITEM = new EventEmitter() + class TouchBar extends EventEmitter { // Bind a touch bar to a window static _setOnWindow (touchBar, window) { @@ -30,13 +32,14 @@ class TouchBar extends EventEmitter { this.windowListeners = {} this.items = {} this.ordereredItems = [] - this.escapeItem = {} + this.escapeItem = DEFAULT_ESCAPE_ITEM + this.changeListener = (item) => { + this.emit('change', item.id, item.type) + } const registerItem = (item) => { this.items[item.id] = item - item.on('change', () => { - this.emit('change', item.id, item.type) - }) + item.on('change', this.changeListener) if (item.child instanceof TouchBar) { item.child.ordereredItems.forEach(registerItem) } @@ -54,8 +57,12 @@ class TouchBar extends EventEmitter { if (item != null && !(item instanceof TouchBarItem)) { throw new Error('Escape item must be an instance of TouchBarItem') } - if (item == null) item = {} + if (item == null) { + item = DEFAULT_ESCAPE_ITEM + } + this.escapeItem.removeListener('change', this.changeListener) this.escapeItem = item + this.escapeItem.on('change', this.changeListener) this.emit('escape-item-change', item) } @@ -78,7 +85,10 @@ class TouchBar extends EventEmitter { this.on('escape-item-change', escapeItemListener) const interactionListener = (event, itemID, details) => { - const item = this.items[itemID] + let item = this.items[itemID] + if (item == null && this.escapeItem.id === itemID) { + item = this.escapeItem + } if (item != null && item.onInteraction != null) { item.onInteraction(details) } @@ -121,7 +131,7 @@ class TouchBarItem extends EventEmitter { }, set: function (value) { this[privateName] = value - this.emit('change') + this.emit('change', this) }, enumerable: true }) diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 81bf47eba39..aafb8c68217 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -62,11 +62,13 @@ describe('TouchBar module', function () { showArrowButtons: true }) ]) - window.setTouchBar(touchBar) - touchBar.setEscapeItem(new TouchBarButton({ + const escapeButton = new TouchBarButton({ label: 'foo' - })) + }) + window.setTouchBar(touchBar) + touchBar.setEscapeItem(escapeButton) label.label = 'baz' + escapeButton.label = 'hello' window.setTouchBar() window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) touchBar.setEscapeItem() From b24b4212c517557db34c02a378394acb12b49062 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 3 Apr 2017 09:34:55 -0700 Subject: [PATCH 11/14] Make escape item a property instead of setter --- docs/api/touch-bar.md | 13 ++++++------- lib/browser/api/touch-bar.js | 25 ++++++++++++++----------- spec/api-touch-bar-spec.js | 6 +++--- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index 54315d79773..a1d86794dd7 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -14,16 +14,15 @@ Creates a new touch bar with the specified items. Use **Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases. -### Instance Methods +### Instance Properties -The following methods are available on instances of `TouchBar`: +The following properties are available on instances of `TouchBar`: -#### `touchBar.setEscapeItem([touchBarItem])` +#### `touchBar.escapeItem` -* `touchBarItem` (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopover | TouchBarScrubber | TouchBarSegmentedControl | TouchBarSlider | TouchBarSpacer) - (Optional) The touch bar item to replace the escape button with - -Replaces the "esc" button on the touchbar with the given TouchBarItem, if `touchBarItem` is not provided or is falsey the button is reset -to the "esc" button automatically. +The `TouchBarItem` that will replace the "esc" button on the touch bar when set. +Setting to `null` restores the default "esc" button. Changing this value +immediately updates the escape item in the touch bar. ## Examples diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 2b95616f221..cd806a5562b 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -2,8 +2,6 @@ const {EventEmitter} = require('events') let nextItemID = 1 -const DEFAULT_ESCAPE_ITEM = new EventEmitter() - class TouchBar extends EventEmitter { // Bind a touch bar to a window static _setOnWindow (touchBar, window) { @@ -32,7 +30,7 @@ class TouchBar extends EventEmitter { this.windowListeners = {} this.items = {} this.ordereredItems = [] - this.escapeItem = DEFAULT_ESCAPE_ITEM + this.escapeItem = null this.changeListener = (item) => { this.emit('change', item.id, item.type) } @@ -53,19 +51,24 @@ class TouchBar extends EventEmitter { }) } - setEscapeItem (item) { + set escapeItem (item) { if (item != null && !(item instanceof TouchBarItem)) { throw new Error('Escape item must be an instance of TouchBarItem') } - if (item == null) { - item = DEFAULT_ESCAPE_ITEM + if (this.escapeItem != null) { + this.escapeItem.removeListener('change', this.changeListener) + } + this._escapeItem = item + if (this.escapeItem != null) { + this.escapeItem.on('change', this.changeListener) } - this.escapeItem.removeListener('change', this.changeListener) - this.escapeItem = item - this.escapeItem.on('change', this.changeListener) this.emit('escape-item-change', item) } + get escapeItem () { + return this._escapeItem + } + _addToWindow (window) { const {id} = window @@ -80,7 +83,7 @@ class TouchBar extends EventEmitter { this.on('change', changeListener) const escapeItemListener = (item) => { - window._setEscapeTouchBarItem(item) + window._setEscapeTouchBarItem(item != null ? item : {}) } this.on('escape-item-change', escapeItemListener) @@ -107,7 +110,7 @@ class TouchBar extends EventEmitter { this.windowListeners[id] = removeListeners window._setTouchBarItems(this.ordereredItems) - window._setEscapeTouchBarItem(this.escapeItem) + escapeItemListener(this.escapeItem) } _removeFromWindow (window) { diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index aafb8c68217..3b986ba032e 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -23,7 +23,7 @@ describe('TouchBar module', function () { it('throws an error when an invalid escape item is set', function () { assert.throws(() => { const touchBar = new TouchBar([]) - touchBar.setEscapeItem('esc') + touchBar.escapeItem = 'esc' }, /Escape item must be an instance of TouchBarItem/) }) @@ -66,12 +66,12 @@ describe('TouchBar module', function () { label: 'foo' }) window.setTouchBar(touchBar) - touchBar.setEscapeItem(escapeButton) + touchBar.escapeItem = escapeButton label.label = 'baz' escapeButton.label = 'hello' window.setTouchBar() window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) - touchBar.setEscapeItem() + touchBar.escapeItem = null }) }) }) From 414540bfcb28cf6c79b35616a48485f265db7378 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 3 Apr 2017 15:12:57 -0700 Subject: [PATCH 12/14] Support passing escape item to TouchBar constructor --- docs/api/touch-bar.md | 6 ++++-- lib/browser/api/touch-bar.js | 18 +++++++++++++++--- spec/api-touch-bar-spec.js | 13 +++++++++---- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/api/touch-bar.md b/docs/api/touch-bar.md index a1d86794dd7..7ac578da46d 100644 --- a/docs/api/touch-bar.md +++ b/docs/api/touch-bar.md @@ -4,9 +4,11 @@ Process: [Main](../tutorial/quick-start.md#main-process) -### `new TouchBar(items)` _Experimental_ +### `new TouchBar(options)` _Experimental_ -* `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] +* `options` - Object + * `items` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md))[] + * `escapeItem` ([TouchBarButton](touch-bar-button.md) | [TouchBarColorPicker](touch-bar-color-picker.md) | [TouchBarGroup](touch-bar-group.md) | [TouchBarLabel](touch-bar-label.md) | [TouchBarPopover](touch-bar-popover.md) | [TouchBarScrubber](touch-bar-scrubber.md) | [TouchBarSegmentedControl](touch-bar-segmented-control.md) | [TouchBarSlider](touch-bar-slider.md) | [TouchBarSpacer](touch-bar-spacer.md)) (optional) Creates a new touch bar with the specified items. Use `BrowserWindow.setTouchBar` to add the `TouchBar` to a window. diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index cd806a5562b..f9629a66ce2 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -20,17 +20,29 @@ class TouchBar extends EventEmitter { touchBar._addToWindow(window) } - constructor (items) { + constructor (options) { super() + if (options == null) { + throw new Error('Must specify options object as first argument') + } + + let {items, escapeItem} = options + + // FIXME Support array as first argument, remove in 2.0 + if (Array.isArray(options)) { + items = options + escapeItem = null + } + if (!Array.isArray(items)) { - throw new Error('Must specify items array as first argument') + items = [] } this.windowListeners = {} this.items = {} this.ordereredItems = [] - this.escapeItem = null + this.escapeItem = escapeItem this.changeListener = (item) => { this.emit('change', item.id, item.type) } diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 3b986ba032e..c2d5d26c3e4 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -6,23 +6,28 @@ const {TouchBarButton, TouchBarColorPicker, TouchBarGroup} = TouchBar const {TouchBarLabel, TouchBarPopover, TouchBarScrubber, TouchBarSegmentedControl, TouchBarSlider, TouchBarSpacer} = TouchBar describe('TouchBar module', function () { - it('throws an error when created without an items array', function () { + it('throws an error when created without an options object', function () { assert.throws(() => { const touchBar = new TouchBar() touchBar.toString() - }, /Must specify items array as first argument/) + }, /Must specify options object as first argument/) }) it('throws an error when created with invalid items', function () { assert.throws(() => { - const touchBar = new TouchBar([1, true, {}, []]) + const touchBar = new TouchBar({items: [1, true, {}, []]}) touchBar.toString() }, /Each item must be an instance of TouchBarItem/) }) it('throws an error when an invalid escape item is set', function () { assert.throws(() => { - const touchBar = new TouchBar([]) + const touchBar = new TouchBar({items: [], escapeItem: 'esc'}) + touchBar.toString() + }, /Escape item must be an instance of TouchBarItem/) + + assert.throws(() => { + const touchBar = new TouchBar({items: []}) touchBar.escapeItem = 'esc' }, /Escape item must be an instance of TouchBarItem/) }) From bbadeb62ac2a2c4745a4481cc3dc334abf7685d1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 4 Apr 2017 13:12:29 -0700 Subject: [PATCH 13/14] Check that escape item is non-null before checking id --- lib/browser/api/touch-bar.js | 2 +- spec/api-touch-bar-spec.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index f9629a66ce2..327b6392fe8 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -101,7 +101,7 @@ class TouchBar extends EventEmitter { const interactionListener = (event, itemID, details) => { let item = this.items[itemID] - if (item == null && this.escapeItem.id === itemID) { + if (item == null && this.escapeItem != null && this.escapeItem.id === itemID) { item = this.escapeItem } if (item != null && item.onInteraction != null) { diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index c2d5d26c3e4..70803045911 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -78,5 +78,17 @@ describe('TouchBar module', function () { window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})])) touchBar.escapeItem = null }) + + it('calls the callback on the items when a window interaction event fires', function (done) { + const button = new TouchBarButton({ + label: 'bar', + click: () => { + done() + } + }) + const touchBar = new TouchBar({items: [button]}) + window.setTouchBar(touchBar) + window.emit('-touch-bar-interaction', {}, button.id) + }) }) }) From 74a3a34caa301cbe5390d00d2cc35fdcf2b97fa7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 4 Apr 2017 13:14:56 -0700 Subject: [PATCH 14/14] Add spec for interaction event with escape item --- lib/browser/api/touch-bar.js | 7 ++++--- spec/api-touch-bar-spec.js | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/browser/api/touch-bar.js b/lib/browser/api/touch-bar.js index 327b6392fe8..1070398c75c 100644 --- a/lib/browser/api/touch-bar.js +++ b/lib/browser/api/touch-bar.js @@ -39,13 +39,14 @@ class TouchBar extends EventEmitter { items = [] } + this.changeListener = (item) => { + this.emit('change', item.id, item.type) + } + this.windowListeners = {} this.items = {} this.ordereredItems = [] this.escapeItem = escapeItem - this.changeListener = (item) => { - this.emit('change', item.id, item.type) - } const registerItem = (item) => { this.items[item.id] = item diff --git a/spec/api-touch-bar-spec.js b/spec/api-touch-bar-spec.js index 70803045911..420ef3fc7b3 100644 --- a/spec/api-touch-bar-spec.js +++ b/spec/api-touch-bar-spec.js @@ -90,5 +90,17 @@ describe('TouchBar module', function () { window.setTouchBar(touchBar) window.emit('-touch-bar-interaction', {}, button.id) }) + + it('calls the callback on the escape item when a window interaction event fires', function (done) { + const button = new TouchBarButton({ + label: 'bar', + click: () => { + done() + } + }) + const touchBar = new TouchBar({escapeItem: button}) + window.setTouchBar(touchBar) + window.emit('-touch-bar-interaction', {}, button.id) + }) }) })