commit
0098822fcf
26 changed files with 1288 additions and 2 deletions
|
@ -282,6 +282,11 @@ void Window::OnExecuteWindowsCommand(const std::string& command_name) {
|
|||
Emit("app-command", command_name);
|
||||
}
|
||||
|
||||
void Window::OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) {
|
||||
Emit("-touch-bar-interaction", item_id, details);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void Window::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
if (IsWindowMessageHooked(message)) {
|
||||
|
@ -840,6 +845,14 @@ void Window::SetVibrancy(mate::Arguments* args) {
|
|||
window_->SetVibrancy(type);
|
||||
}
|
||||
|
||||
void Window::SetTouchBar(const std::vector<mate::PersistentDictionary>& items) {
|
||||
window_->SetTouchBar(items);
|
||||
}
|
||||
|
||||
void Window::RefreshTouchBarItem(const std::string& item_id) {
|
||||
window_->RefreshTouchBarItem(item_id);
|
||||
}
|
||||
|
||||
int32_t Window::ID() const {
|
||||
return weak_map_id();
|
||||
}
|
||||
|
@ -960,6 +973,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("setAutoHideCursor", &Window::SetAutoHideCursor)
|
||||
#endif
|
||||
.SetMethod("setVibrancy", &Window::SetVibrancy)
|
||||
.SetMethod("_setTouchBarItems", &Window::SetTouchBar)
|
||||
.SetMethod("_refreshTouchBarItem", &Window::RefreshTouchBarItem)
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("hookWindowMessage", &Window::HookWindowMessage)
|
||||
.SetMethod("isWindowMessageHooked", &Window::IsWindowMessageHooked)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "atom/common/api/atom_api_native_image.h"
|
||||
#include "atom/common/key_weak_map.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "native_mate/persistent_dictionary.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
class GURL;
|
||||
|
@ -85,6 +86,8 @@ class Window : public mate::TrackableObject<Window>,
|
|||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
void OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) override;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||
|
@ -203,6 +206,8 @@ class Window : public mate::TrackableObject<Window>,
|
|||
void SetAutoHideCursor(bool auto_hide);
|
||||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
void SetTouchBar(const std::vector<mate::PersistentDictionary>& items);
|
||||
void RefreshTouchBarItem(const std::string& item_id);
|
||||
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
|
||||
|
|
|
@ -340,6 +340,13 @@ void NativeWindow::SetAutoHideCursor(bool auto_hide) {
|
|||
void NativeWindow::SetVibrancy(const std::string& filename) {
|
||||
}
|
||||
|
||||
void NativeWindow::SetTouchBar(
|
||||
const std::vector<mate::PersistentDictionary>& items) {
|
||||
}
|
||||
|
||||
void NativeWindow::RefreshTouchBarItem(const std::string& item_id) {
|
||||
}
|
||||
|
||||
void NativeWindow::FocusOnWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
|
||||
}
|
||||
|
@ -565,6 +572,13 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand(
|
|||
observer.OnExecuteWindowsCommand(command);
|
||||
}
|
||||
|
||||
void NativeWindow::NotifyTouchBarItemInteraction(
|
||||
const std::string& item_id,
|
||||
const base::DictionaryValue& details) {
|
||||
for (NativeWindowObserver& observer : observers_)
|
||||
observer.OnTouchBarItemResult(item_id, details);
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void NativeWindow::NotifyWindowMessage(
|
||||
UINT message, WPARAM w_param, LPARAM l_param) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
#include "extensions/browser/app_window/size_constraints.h"
|
||||
#include "native_mate/persistent_dictionary.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
|
@ -169,6 +170,11 @@ class NativeWindow : public base::SupportsUserData,
|
|||
// Vibrancy API
|
||||
virtual void SetVibrancy(const std::string& type);
|
||||
|
||||
// Touchbar API
|
||||
virtual void SetTouchBar(
|
||||
const std::vector<mate::PersistentDictionary>& items);
|
||||
virtual void RefreshTouchBarItem(const std::string& item_id);
|
||||
|
||||
// Webview APIs.
|
||||
virtual void FocusOnWebView();
|
||||
virtual void BlurWebView();
|
||||
|
@ -228,6 +234,8 @@ class NativeWindow : public base::SupportsUserData,
|
|||
void NotifyWindowEnterHtmlFullScreen();
|
||||
void NotifyWindowLeaveHtmlFullScreen();
|
||||
void NotifyWindowExecuteWindowsCommand(const std::string& command);
|
||||
void NotifyTouchBarItemInteraction(const std::string& item_id,
|
||||
const base::DictionaryValue& details);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void NotifyWindowMessage(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
|
|
@ -100,6 +100,9 @@ class NativeWindowMac : public NativeWindow,
|
|||
void SetAutoHideCursor(bool auto_hide) override;
|
||||
|
||||
void SetVibrancy(const std::string& type) override;
|
||||
void SetTouchBar(
|
||||
const std::vector<mate::PersistentDictionary>& items) override;
|
||||
void RefreshTouchBarItem(const std::string& item_id) override;
|
||||
|
||||
// content::RenderWidgetHost::InputEventObserver:
|
||||
void OnInputEvent(const blink::WebInputEvent& event) override;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <Quartz/Quartz.h>
|
||||
#include <string>
|
||||
|
||||
#include "atom/browser/ui/cocoa/atom_touch_bar.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/draggable_region.h"
|
||||
|
@ -335,10 +336,11 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
|
||||
@end
|
||||
|
||||
@interface AtomNSWindow : EventDispatchingWindow<QLPreviewPanelDataSource, QLPreviewPanelDelegate> {
|
||||
@interface AtomNSWindow : EventDispatchingWindow<QLPreviewPanelDataSource, QLPreviewPanelDelegate, NSTouchBarDelegate> {
|
||||
@private
|
||||
atom::NativeWindowMac* shell_;
|
||||
bool enable_larger_than_screen_;
|
||||
base::scoped_nsobject<AtomTouchBar> atom_touch_bar_;
|
||||
CGFloat windowButtonsInterButtonSpacing_;
|
||||
}
|
||||
@property BOOL acceptsFirstMouse;
|
||||
|
@ -351,6 +353,9 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
- (void)setShell:(atom::NativeWindowMac*)shell;
|
||||
- (void)setEnableLargerThanScreen:(bool)enable;
|
||||
- (void)enableWindowButtonsOffset;
|
||||
- (void)resetTouchBar:(const std::vector<mate::PersistentDictionary>&)settings;
|
||||
- (void)refreshTouchBarItem:(const std::string&)item_id;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AtomNSWindow
|
||||
|
@ -363,6 +368,35 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
enable_larger_than_screen_ = enable;
|
||||
}
|
||||
|
||||
- (void)resetTouchBar:(const std::vector<mate::PersistentDictionary>&)settings {
|
||||
if (![self respondsToSelector:@selector(touchBar)]) return;
|
||||
|
||||
atom_touch_bar_.reset([[AtomTouchBar alloc] initWithDelegate:self
|
||||
window:shell_
|
||||
settings:settings]);
|
||||
self.touchBar = nil;
|
||||
}
|
||||
|
||||
- (void)refreshTouchBarItem:(const std::string&)item_id {
|
||||
if (atom_touch_bar_ && self.touchBar)
|
||||
[atom_touch_bar_ refreshTouchBarItem:self.touchBar id:item_id];
|
||||
}
|
||||
|
||||
- (NSTouchBar*)makeTouchBar {
|
||||
if (atom_touch_bar_)
|
||||
return [atom_touch_bar_ makeTouchBar];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
|
||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
|
||||
if (touchBar && atom_touch_bar_)
|
||||
return [atom_touch_bar_ makeItemForIdentifier:identifier];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
// NSWindow overrides.
|
||||
|
||||
- (void)swipeWithEvent:(NSEvent *)event {
|
||||
|
@ -1346,6 +1380,15 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
|
|||
[effect_view setMaterial:vibrancyType];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetTouchBar(
|
||||
const std::vector<mate::PersistentDictionary>& items) {
|
||||
[window_ resetTouchBar:items];
|
||||
}
|
||||
|
||||
void NativeWindowMac::RefreshTouchBarItem(const std::string& item_id) {
|
||||
[window_ refreshTouchBarItem:item_id];
|
||||
}
|
||||
|
||||
void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) {
|
||||
switch (event.type) {
|
||||
case blink::WebInputEvent::GestureScrollBegin:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
#include "base/values.h"
|
||||
#include "ui/base/window_open_disposition.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
|
@ -70,6 +71,8 @@ class NativeWindowObserver {
|
|||
virtual void OnWindowLeaveFullScreen() {}
|
||||
virtual void OnWindowEnterHtmlFullScreen() {}
|
||||
virtual void OnWindowLeaveHtmlFullScreen() {}
|
||||
virtual void OnTouchBarItemResult(const std::string& item_id,
|
||||
const base::DictionaryValue& details) {}
|
||||
|
||||
// Called when window message received
|
||||
#if defined(OS_WIN)
|
||||
|
|
64
atom/browser/ui/cocoa/atom_touch_bar.h
Normal file
64
atom/browser/ui/cocoa/atom_touch_bar.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_UI_COCOA_ATOM_TOUCH_BAR_H_
|
||||
#define ATOM_BROWSER_UI_COCOA_ATOM_TOUCH_BAR_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/ui/cocoa/touch_bar_forward_declarations.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/persistent_dictionary.h"
|
||||
|
||||
@interface AtomTouchBar : NSObject {
|
||||
@protected
|
||||
std::vector<mate::PersistentDictionary> ordered_settings_;
|
||||
std::map<std::string, mate::PersistentDictionary> settings_;
|
||||
id<NSTouchBarDelegate> delegate_;
|
||||
atom::NativeWindow* window_;
|
||||
}
|
||||
|
||||
- (id)initWithDelegate:(id<NSTouchBarDelegate>)delegate window:(atom::NativeWindow*)window settings:(const std::vector<mate::PersistentDictionary>&)settings;
|
||||
|
||||
- (NSTouchBar*)makeTouchBar;
|
||||
- (NSTouchBar*)touchBarFromItemIdentifiers:(NSMutableArray*)items;
|
||||
- (NSMutableArray*)identifiersFromSettings:(const std::vector<mate::PersistentDictionary>&)settings;
|
||||
- (void)refreshTouchBarItem:(NSTouchBar*)touchBar id:(const std::string&)item_id;
|
||||
|
||||
|
||||
- (NSString*)idFromIdentifier:(NSString*)identifier withPrefix:(NSString*)prefix;
|
||||
- (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id type:(const std::string&)typere;
|
||||
- (bool)hasItemWithID:(const std::string&)item_id;
|
||||
- (NSColor*)colorFromHexColorString:(const std::string&)colorString;
|
||||
|
||||
// Selector actions
|
||||
- (void)buttonAction:(id)sender;
|
||||
- (void)colorPickerAction:(id)sender;
|
||||
- (void)sliderAction:(id)sender;
|
||||
|
||||
// Helpers to create touch bar items
|
||||
- (NSTouchBarItem*)makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier;
|
||||
- (NSTouchBarItem*)makeButtonForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
- (NSTouchBarItem*)makeLabelForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
- (NSTouchBarItem*)makeColorPickerForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
- (NSTouchBarItem*)makeSliderForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
- (NSTouchBarItem*)makePopoverForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
- (NSTouchBarItem*)makeGroupForID:(NSString*)id withIdentifier:(NSString*)identifier;
|
||||
|
||||
// Helpers to update touch bar items
|
||||
- (void)updateButton:(NSCustomTouchBarItem*)item withSettings:(const mate::PersistentDictionary&)settings;
|
||||
- (void)updateLabel:(NSCustomTouchBarItem*)item withSettings:(const mate::PersistentDictionary&)settings;
|
||||
- (void)updateColorPicker:(NSColorPickerTouchBarItem*)item withSettings:(const mate::PersistentDictionary&)settings;
|
||||
- (void)updateSlider:(NSSliderTouchBarItem*)item withSettings:(const mate::PersistentDictionary&)settings;
|
||||
- (void)updatePopover:(NSPopoverTouchBarItem*)item withSettings:(const mate::PersistentDictionary&)settings;
|
||||
|
||||
@end
|
||||
|
||||
#endif // ATOM_BROWSER_UI_COCOA_ATOM_TOUCH_BAR_H_
|
381
atom/browser/ui/cocoa/atom_touch_bar.mm
Normal file
381
atom/browser/ui/cocoa/atom_touch_bar.mm
Normal file
|
@ -0,0 +1,381 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_touch_bar.h"
|
||||
|
||||
#include "atom/common/color_util.h"
|
||||
#include "atom/common/native_mate_converters/image_converter.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "skia/ext/skia_utils_mac.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
@implementation AtomTouchBar
|
||||
|
||||
static NSTouchBarItemIdentifier ButtonIdentifier = @"com.electron.touchbar.button.";
|
||||
static NSTouchBarItemIdentifier ColorPickerIdentifier = @"com.electron.touchbar.colorpicker.";
|
||||
static NSTouchBarItemIdentifier GroupIdentifier = @"com.electron.touchbar.group.";
|
||||
static NSTouchBarItemIdentifier LabelIdentifier = @"com.electron.touchbar.label.";
|
||||
static NSTouchBarItemIdentifier PopoverIdentifier = @"com.electron.touchbar.popover.";
|
||||
static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slider.";
|
||||
|
||||
- (id)initWithDelegate:(id<NSTouchBarDelegate>)delegate
|
||||
window:(atom::NativeWindow*)window
|
||||
settings:(const std::vector<mate::PersistentDictionary>&)settings {
|
||||
if ((self = [super init])) {
|
||||
delegate_ = delegate;
|
||||
window_ = window;
|
||||
ordered_settings_ = settings;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSTouchBar*)makeTouchBar {
|
||||
NSMutableArray* identifiers = [self identifiersFromSettings:ordered_settings_];
|
||||
return [self touchBarFromItemIdentifiers:identifiers];
|
||||
}
|
||||
|
||||
- (NSTouchBar*)touchBarFromItemIdentifiers:(NSMutableArray*)items {
|
||||
base::scoped_nsobject<NSTouchBar> bar(
|
||||
[[NSClassFromString(@"NSTouchBar") alloc] init]);
|
||||
[bar setDelegate:delegate_];
|
||||
[bar setDefaultItemIdentifiers:items];
|
||||
return bar.autorelease();
|
||||
}
|
||||
|
||||
- (NSMutableArray*)identifiersFromSettings:(const std::vector<mate::PersistentDictionary>&)dicts {
|
||||
NSMutableArray* identifiers = [NSMutableArray array];
|
||||
|
||||
for (const auto& item : dicts) {
|
||||
std::string type;
|
||||
std::string item_id;
|
||||
if (item.Get("type", &type) && item.Get("id", &item_id)) {
|
||||
NSTouchBarItemIdentifier identifier = nil;
|
||||
if (type == "spacer") {
|
||||
std::string size;
|
||||
item.Get("size", &size);
|
||||
if (size == "large") {
|
||||
identifier = NSTouchBarItemIdentifierFixedSpaceLarge;
|
||||
} else if (size == "flexible") {
|
||||
identifier = NSTouchBarItemIdentifierFlexibleSpace;
|
||||
} else {
|
||||
identifier = NSTouchBarItemIdentifierFixedSpaceSmall;
|
||||
}
|
||||
} else {
|
||||
identifier = [self identifierFromID:item_id type:type];
|
||||
}
|
||||
|
||||
if (identifier) {
|
||||
settings_[item_id] = item;
|
||||
[identifiers addObject:identifier];
|
||||
}
|
||||
}
|
||||
}
|
||||
[identifiers addObject:NSTouchBarItemIdentifierOtherItemsProxy];
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier {
|
||||
NSString* item_id = nil;
|
||||
|
||||
if ([identifier hasPrefix:ButtonIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:ButtonIdentifier];
|
||||
return [self makeButtonForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:LabelIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:LabelIdentifier];
|
||||
return [self makeLabelForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:ColorPickerIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier];
|
||||
return [self makeColorPickerForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:SliderIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:SliderIdentifier];
|
||||
return [self makeSliderForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:PopoverIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:PopoverIdentifier];
|
||||
return [self makePopoverForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:GroupIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:GroupIdentifier];
|
||||
return [self makeGroupForID:item_id withIdentifier:identifier];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (void)refreshTouchBarItem:(NSTouchBar*)touchBar
|
||||
id:(const std::string&)item_id {
|
||||
if (![self hasItemWithID:item_id]) return;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[item_id];
|
||||
std::string item_type;
|
||||
settings.Get("type", &item_type);
|
||||
|
||||
NSTouchBarItemIdentifier identifier = [self identifierFromID:item_id
|
||||
type:item_type];
|
||||
if (!identifier) return;
|
||||
|
||||
NSTouchBarItem* item = [touchBar itemForIdentifier:identifier];
|
||||
if (!item) return;
|
||||
|
||||
if (item_type == "button") {
|
||||
[self updateButton:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "label") {
|
||||
[self updateLabel:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "colorpicker") {
|
||||
[self updateColorPicker:(NSColorPickerTouchBarItem*)item
|
||||
withSettings:settings];
|
||||
} else if (item_type == "slider") {
|
||||
[self updateSlider:(NSSliderTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "popover") {
|
||||
[self updatePopover:(NSPopoverTouchBarItem*)item withSettings:settings];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)buttonAction:(id)sender {
|
||||
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSButton*)sender).tag];
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||
base::DictionaryValue());
|
||||
}
|
||||
|
||||
- (void)colorPickerAction:(id)sender {
|
||||
NSString* identifier = ((NSColorPickerTouchBarItem*)sender).identifier;
|
||||
NSString* item_id = [self idFromIdentifier:identifier
|
||||
withPrefix:ColorPickerIdentifier];
|
||||
NSColor* color = ((NSColorPickerTouchBarItem*)sender).color;
|
||||
std::string hex_color = atom::ToRGBHex(skia::NSDeviceColorToSkColor(color));
|
||||
base::DictionaryValue details;
|
||||
details.SetString("color", hex_color);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
|
||||
}
|
||||
|
||||
- (void)sliderAction:(id)sender {
|
||||
NSString* identifier = ((NSSliderTouchBarItem*)sender).identifier;
|
||||
NSString* item_id = [self idFromIdentifier:identifier
|
||||
withPrefix:SliderIdentifier];
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("value",
|
||||
[((NSSliderTouchBarItem*)sender).slider intValue]);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
|
||||
}
|
||||
|
||||
- (NSString*)idFromIdentifier:(NSString*)identifier
|
||||
withPrefix:(NSString*)prefix {
|
||||
return [identifier substringFromIndex:[prefix length]];
|
||||
}
|
||||
|
||||
- (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id
|
||||
type:(const std::string&)type {
|
||||
NSTouchBarItemIdentifier base_identifier = nil;
|
||||
if (type == "button")
|
||||
base_identifier = ButtonIdentifier;
|
||||
else if (type == "label")
|
||||
base_identifier = LabelIdentifier;
|
||||
else if (type == "colorpicker")
|
||||
base_identifier = ColorPickerIdentifier;
|
||||
else if (type == "slider")
|
||||
base_identifier = SliderIdentifier;
|
||||
else if (type == "popover")
|
||||
base_identifier = PopoverIdentifier;
|
||||
else if (type == "group")
|
||||
base_identifier = GroupIdentifier;
|
||||
|
||||
if (base_identifier)
|
||||
return [NSString stringWithFormat:@"%@%s", base_identifier, item_id.data()];
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (bool)hasItemWithID:(const std::string&)item_id {
|
||||
return settings_.find(item_id) != settings_.end();
|
||||
}
|
||||
|
||||
- (NSColor*)colorFromHexColorString:(const std::string&)colorString {
|
||||
SkColor color = atom::ParseHexColor(colorString);
|
||||
return skia::SkColorToDeviceNSColor(color);
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeButtonForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
NSButton* button = [NSButton buttonWithTitle:@""
|
||||
target:self
|
||||
action:@selector(buttonAction:)];
|
||||
button.tag = [id floatValue];
|
||||
[item setView:button];
|
||||
[self updateButton:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updateButton:(NSCustomTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
NSButton* button = (NSButton*)item.view;
|
||||
|
||||
std::string backgroundColor;
|
||||
if (settings.Get("backgroundColor", &backgroundColor)) {
|
||||
button.bezelColor = [self colorFromHexColorString:backgroundColor];
|
||||
}
|
||||
|
||||
std::string label;
|
||||
if (settings.Get("label", &label)) {
|
||||
button.title = base::SysUTF8ToNSString(label);
|
||||
}
|
||||
|
||||
gfx::Image image;
|
||||
if (settings.Get("icon", &image)) {
|
||||
button.image = image.AsNSImage();
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeLabelForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
[item setView:[NSTextField labelWithString:@""]];
|
||||
[self updateLabel:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updateLabel:(NSCustomTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
std::string label;
|
||||
settings.Get("label", &label);
|
||||
NSTextField* text_field = (NSTextField*)item.view;
|
||||
text_field.stringValue = base::SysUTF8ToNSString(label);
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeColorPickerForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSColorPickerTouchBarItem> item([[NSClassFromString(
|
||||
@"NSColorPickerTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(colorPickerAction:)];
|
||||
[self updateColorPicker:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updateColorPicker:(NSColorPickerTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
std::vector<std::string> colors;
|
||||
if (settings.Get("availableColors", &colors) && colors.size() > 0) {
|
||||
NSColorList* color_list = [[[NSColorList alloc] initWithName:@""] autorelease];
|
||||
for (size_t i = 0; i < colors.size(); ++i) {
|
||||
[color_list insertColor:[self colorFromHexColorString:colors[i]]
|
||||
key:base::SysUTF8ToNSString(colors[i])
|
||||
atIndex:i];
|
||||
}
|
||||
item.colorList = color_list;
|
||||
}
|
||||
|
||||
std::string selectedColor;
|
||||
if (settings.Get("selectedColor", &selectedColor)) {
|
||||
item.color = [self colorFromHexColorString:selectedColor];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeSliderForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSSliderTouchBarItem> item([[NSClassFromString(
|
||||
@"NSSliderTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(sliderAction:)];
|
||||
[self updateSlider:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updateSlider:(NSSliderTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
std::string label;
|
||||
settings.Get("label", &label);
|
||||
item.label = base::SysUTF8ToNSString(label);
|
||||
|
||||
int maxValue = 100;
|
||||
int minValue = 0;
|
||||
int value = 50;
|
||||
settings.Get("minValue", &minValue);
|
||||
settings.Get("maxValue", &maxValue);
|
||||
settings.Get("value", &value);
|
||||
|
||||
item.slider.minValue = minValue;
|
||||
item.slider.maxValue = maxValue;
|
||||
item.slider.doubleValue = value;
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makePopoverForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSPopoverTouchBarItem> item([[NSClassFromString(
|
||||
@"NSPopoverTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
[self updatePopover:item withSettings:settings];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
- (void)updatePopover:(NSPopoverTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
std::string label;
|
||||
if (settings.Get("label", &label)) {
|
||||
item.collapsedRepresentationLabel = base::SysUTF8ToNSString(label);
|
||||
}
|
||||
gfx::Image image;
|
||||
if (settings.Get("icon", &image)) {
|
||||
item.collapsedRepresentationImage = image.AsNSImage();
|
||||
}
|
||||
|
||||
bool showCloseButton = true;
|
||||
if (settings.Get("showCloseButton", &showCloseButton)) {
|
||||
item.showsCloseButton = showCloseButton;
|
||||
}
|
||||
|
||||
mate::PersistentDictionary child;
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (settings.Get("child", &child) && child.Get("ordereredItems", &items)) {
|
||||
item.popoverTouchBar = [self touchBarFromItemIdentifiers:[self identifiersFromSettings:items]];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeGroupForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
|
||||
mate::PersistentDictionary child;
|
||||
if (!settings.Get("child", &child)) return nil;
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (!child.Get("ordereredItems", &items)) return nil;
|
||||
|
||||
NSMutableArray* generatedItems = [NSMutableArray array];
|
||||
NSMutableArray* identList = [self identifiersFromSettings:items];
|
||||
for (NSUInteger i = 0; i < [identList count]; i++) {
|
||||
if ([identList objectAtIndex:i] != NSTouchBarItemIdentifierOtherItemsProxy) {
|
||||
NSTouchBarItem* generatedItem = [self makeItemForIdentifier:[identList objectAtIndex:i]];
|
||||
if (generatedItem) {
|
||||
[generatedItems addObject:generatedItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSClassFromString(@"NSGroupTouchBarItem") groupItemWithIdentifier:identifier
|
||||
items:generatedItems];
|
||||
}
|
||||
|
||||
@end
|
173
atom/browser/ui/cocoa/touch_bar_forward_declarations.h
Normal file
173
atom/browser/ui/cocoa/touch_bar_forward_declarations.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
// Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_UI_COCOA_TOUCH_BAR_FORWARD_DECLARATIONS_H_
|
||||
#define ATOM_BROWSER_UI_COCOA_TOUCH_BAR_FORWARD_DECLARATIONS_H_
|
||||
|
||||
// Once Chrome no longer supports OSX 10.12.0, this file can be deleted.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_12_1)
|
||||
|
||||
#pragma clang assume_nonnull begin
|
||||
|
||||
@class NSTouchBar, NSTouchBarItem;
|
||||
@protocol NSTouchBarDelegate;
|
||||
|
||||
typedef float NSTouchBarItemPriority;
|
||||
static const NSTouchBarItemPriority NSTouchBarItemPriorityHigh = 1000;
|
||||
static const NSTouchBarItemPriority NSTouchBarItemPriorityNormal = 0;
|
||||
static const NSTouchBarItemPriority NSTouchBarItemPriorityLow = -1000;
|
||||
|
||||
typedef NSString* NSTouchBarItemIdentifier;
|
||||
typedef NSString* NSTouchBarCustomizationIdentifier;
|
||||
|
||||
static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierFixedSpaceSmall =
|
||||
@"NSTouchBarItemIdentifierFixedSpaceSmall";
|
||||
|
||||
static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierFixedSpaceLarge =
|
||||
@"NSTouchBarItemIdentifierFixedSpaceLarge";
|
||||
|
||||
static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierFlexibleSpace =
|
||||
@"NSTouchBarItemIdentifierFlexibleSpace";
|
||||
|
||||
static const NSTouchBarItemIdentifier NSTouchBarItemIdentifierOtherItemsProxy =
|
||||
@"NSTouchBarItemIdentifierOtherItemsProxy";
|
||||
|
||||
@interface NSTouchBar : NSObject<NSCoding>
|
||||
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder*)aDecoder
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property(copy, nullable)
|
||||
NSTouchBarCustomizationIdentifier customizationIdentifier;
|
||||
@property(copy) NSArray* customizationAllowedItemIdentifiers;
|
||||
@property(copy) NSArray* customizationRequiredItemIdentifiers;
|
||||
@property(copy) NSArray* defaultItemIdentifiers;
|
||||
@property(copy, readonly) NSArray* itemIdentifiers;
|
||||
@property(copy, nullable) NSTouchBarItemIdentifier principalItemIdentifier;
|
||||
@property(copy) NSSet* templateItems;
|
||||
@property(nullable, weak) id<NSTouchBarDelegate> delegate;
|
||||
|
||||
- (nullable __kindof NSTouchBarItem*)itemForIdentifier:
|
||||
(NSTouchBarItemIdentifier)identifier;
|
||||
|
||||
@property(readonly, getter=isVisible) BOOL visible;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSTouchBarItem : NSObject<NSCoding>
|
||||
|
||||
- (instancetype)initWithIdentifier:(NSTouchBarItemIdentifier)identifier
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
- (nullable instancetype)initWithCoder:(NSCoder*)coder
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@property(readonly, copy) NSTouchBarItemIdentifier identifier;
|
||||
@property NSTouchBarItemPriority visibilityPriority;
|
||||
@property(readonly, nullable) NSView* view;
|
||||
@property(readonly, nullable) NSViewController* viewController;
|
||||
@property(readwrite, copy) NSString* customizationLabel;
|
||||
@property(readonly, getter=isVisible) BOOL visible;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSGroupTouchBarItem : NSTouchBarItem
|
||||
|
||||
+ (NSGroupTouchBarItem*)groupItemWithIdentifier:
|
||||
(NSTouchBarItemIdentifier)identifier
|
||||
items:(NSArray*)items;
|
||||
|
||||
@property(strong) NSTouchBar* groupTouchBar;
|
||||
@property(readwrite, copy, null_resettable) NSString* customizationLabel;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSCustomTouchBarItem : NSTouchBarItem
|
||||
|
||||
@property(readwrite, strong) __kindof NSView* view;
|
||||
@property(readwrite, strong, nullable)
|
||||
__kindof NSViewController* viewController;
|
||||
@property(readwrite, copy, null_resettable) NSString* customizationLabel;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSColorPickerTouchBarItem : NSTouchBarItem
|
||||
|
||||
@property SEL action;
|
||||
@property(weak) id target;
|
||||
@property(copy) NSColor *color;
|
||||
@property(strong) NSColorList *colorList;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSPopoverTouchBarItem : NSTouchBarItem
|
||||
|
||||
@property BOOL showsCloseButton;
|
||||
@property(strong) NSImage *collapsedRepresentationImage;
|
||||
@property(strong) NSString *collapsedRepresentationLabel;
|
||||
@property(strong) NSTouchBar *popoverTouchBar;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSSliderTouchBarItem : NSTouchBarItem
|
||||
|
||||
@property SEL action;
|
||||
@property(weak) id target;
|
||||
@property(copy) NSString *label;
|
||||
@property(strong) NSSlider *slider;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSWindow (TouchBarSDK)
|
||||
|
||||
@property(strong, readwrite, nullable) NSTouchBar* touchBar;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSButton (TouchBarSDK)
|
||||
|
||||
@property(copy) NSColor *bezelColor;
|
||||
+ (instancetype)buttonWithTitle:(NSString *)title
|
||||
target:(id)target
|
||||
action:(SEL)action;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSTextField (TouchBarSDK)
|
||||
|
||||
+ (instancetype)labelWithString:(NSString *)stringValue;
|
||||
|
||||
@end
|
||||
|
||||
@protocol NSTouchBarDelegate<NSObject>
|
||||
|
||||
@optional
|
||||
- (nullable NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
|
||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier;
|
||||
@end
|
||||
|
||||
#pragma clang assume_nonnull end
|
||||
|
||||
#elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12_1
|
||||
|
||||
// When compiling against the 10.12.1 SDK or later, just provide forward
|
||||
// declarations to suppress the partial availability warnings.
|
||||
|
||||
@class NSCustomTouchBarItem;
|
||||
@class NSGroupTouchBarItem;
|
||||
@class NSTouchBar;
|
||||
@protocol NSTouchBarDelegate;
|
||||
@class NSTouchBarItem;
|
||||
|
||||
@interface NSWindow (TouchBarSDK)
|
||||
@property(strong, readonly) NSTouchBar* touchBar;
|
||||
@end
|
||||
|
||||
#endif // MAC_OS_X_VERSION_10_12_1
|
||||
|
||||
#endif // ATOM_BROWSER_UI_COCOA_TOUCH_BAR_FORWARD_DECLARATIONS_H_
|
|
@ -1266,6 +1266,14 @@ Controls whether to hide cursor when typing.
|
|||
Adds a vibrancy effect to the browser window. Passing `null` or an empty string
|
||||
will remove the vibrancy effect on the window.
|
||||
|
||||
#### `win.setTouchBar(touchBar)` _macOS_
|
||||
|
||||
* `touchBar` TouchBar
|
||||
|
||||
Sets the touchBar layout for the current window. Specifying `null` or
|
||||
`undefined` clears the touch bar. This method only has an effect if the
|
||||
machine has a touch bar and is running on macOS 10.12.1+.
|
||||
|
||||
[blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5?l=62
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
[vibrancy-docs]: https://developer.apple.com/reference/appkit/nsvisualeffectview?language=objc
|
||||
|
|
33
docs/api/touch-bar-button.md
Normal file
33
docs/api/touch-bar-button.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
## Class: TouchBarButton
|
||||
|
||||
> Create a button in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarButton(options)`
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Button text.
|
||||
* `backgroundColor` String (optional) - Button background color in hex format,
|
||||
i.e `#ABCDEF`.
|
||||
* `icon` NativeImage (optional) - Button icon.
|
||||
* `click` Function (optional) - Function to call when the button is clicked.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarButton`:
|
||||
|
||||
#### `touchBarButton.label`
|
||||
|
||||
The button's current text. Changing this value immediately updates the button
|
||||
in the touch bar.
|
||||
|
||||
#### `touchBarButton.backgroundColor`
|
||||
|
||||
The button's current background color. Changing this value immediately updates
|
||||
the button in the touch bar.
|
||||
|
||||
#### `touchBarButton.icon`
|
||||
|
||||
The button's current icon. Changing this value immediately updates the button
|
||||
in the touch bar.
|
28
docs/api/touch-bar-color-picker.md
Normal file
28
docs/api/touch-bar-color-picker.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
## Class: TouchBarColorPicker
|
||||
|
||||
> Create a color picker in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarColorPicker(options)`
|
||||
|
||||
* `options` Object
|
||||
* `availableColors` String[] (optional) - Array of hex color strings to
|
||||
appear as possible colors to select.
|
||||
* `selectedColor` String (optional) - The selected hex color in the picker,
|
||||
i.e `#ABCDEF`.
|
||||
* `change` Function (optional) - Function to call when a color is selected.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarColorPicker`:
|
||||
|
||||
#### `touchBarColorPicker.availableColors`
|
||||
|
||||
The color picker's available colors to select. Changing this value immediately
|
||||
updates the color picker in the touch bar.
|
||||
|
||||
#### `touchBarColorPicker.selectedColor`
|
||||
|
||||
The color picker's currently selected color. Changing this value immediately
|
||||
updates the color picker in the touch bar.
|
10
docs/api/touch-bar-group.md
Normal file
10
docs/api/touch-bar-group.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
## Class: TouchBarGroup
|
||||
|
||||
> Create a group in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarGroup(options)`
|
||||
|
||||
* `options` Object
|
||||
* `items` TouchBar - Items to display as a group.
|
19
docs/api/touch-bar-label.md
Normal file
19
docs/api/touch-bar-label.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
## Class: TouchBarLabel
|
||||
|
||||
> Create a label in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarLabel(options)`
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Text to display.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarLabel`:
|
||||
|
||||
#### `touchBarLabel.label`
|
||||
|
||||
The label's current text. Changing this value immediately updates the label in
|
||||
the touch bar.
|
28
docs/api/touch-bar-popover.md
Normal file
28
docs/api/touch-bar-popover.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
## Class: TouchBarPopover
|
||||
|
||||
> Create a popover in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarPopover(options)`
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Popover button text.
|
||||
* `icon` NativeImage (optional) - Popover button icon.
|
||||
* `items` TouchBar (optional) - Items to display in the popover.
|
||||
* `showCloseButton` Boolean (optional) - `true` to display a close button
|
||||
on the left of the popover, `false` to not show it. Default is `true`.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarPopover`:
|
||||
|
||||
#### `touchBarPopover.label`
|
||||
|
||||
The popover's current button text. Changing this value immediately updates the
|
||||
popover in the touch bar.
|
||||
|
||||
#### `touchBarPopover.icon`
|
||||
|
||||
The popover's current button icon. Changing this value immediately updates the
|
||||
popover in the touch bar.
|
38
docs/api/touch-bar-slider.md
Normal file
38
docs/api/touch-bar-slider.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
## Class: TouchBarSlider
|
||||
|
||||
> Create a slider in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarSlider(options)`
|
||||
|
||||
* `options` Object
|
||||
* `label` String (optional) - Label text.
|
||||
* `value` Integer (optional) - Selected value.
|
||||
* `minValue` Integer (optional) - Minimum value.
|
||||
* `maxValue` Integer (optional) - Maximum value.
|
||||
* `change` Function (optional) - Function to call when the slider is changed.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `TouchBarSlider`:
|
||||
|
||||
#### `touchBarSlider.label`
|
||||
|
||||
The slider's current text. Changing this value immediately updates the slider
|
||||
in the touch bar.
|
||||
|
||||
#### `touchBarSlider.value`
|
||||
|
||||
The slider's current value. Changing this value immediately updates the slider
|
||||
in the touch bar.
|
||||
|
||||
#### `touchBarSlider.minValue`
|
||||
|
||||
The slider's current minimum value. Changing this value immediately updates the
|
||||
slider in the touch bar.
|
||||
|
||||
#### `touchBarSlider.maxValue`
|
||||
|
||||
The slider's current maximum value. Changing this value immediately updates the
|
||||
slider in the touch bar.
|
13
docs/api/touch-bar-spacer.md
Normal file
13
docs/api/touch-bar-spacer.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
## Class: TouchBarSpacer
|
||||
|
||||
> Create a spacer between two items in the touch bar for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBarSlider(options)`
|
||||
|
||||
* `options` Object
|
||||
* `size` String (optional) - Size of spacer, possible values are:
|
||||
* `small` - Small space between items.
|
||||
* `large` - Large space between items.
|
||||
* `flexible` - Take up all available space.
|
116
docs/api/touch-bar.md
Normal file
116
docs/api/touch-bar.md
Normal file
|
@ -0,0 +1,116 @@
|
|||
## Class: TouchBar
|
||||
|
||||
> Create TouchBar layouts for native macOS applications
|
||||
|
||||
Process: [Main](../tutorial/quick-start.md#main-process)
|
||||
|
||||
### `new TouchBar(items)`
|
||||
|
||||
* `items` (TouchBarButton | TouchBarColorPicker | TouchBarGroup | TouchBarLabel | TouchBarPopOver | TouchBarSlider | TouchBarSpacer)[]
|
||||
|
||||
Creates a new touch bar with the specified items. Use
|
||||
`BrowserWindow.setTouchBar` to add the `TouchBar` to a window.
|
||||
|
||||
## Examples
|
||||
|
||||
Below is an example of a simple slot machine touch bar game with a button
|
||||
and some labels.
|
||||
|
||||
```javascript
|
||||
const {app, BrowserWindow, TouchBar} = require('electron')
|
||||
|
||||
const {TouchBarLabel, TouchBarButton, TouchBarSpacer} = TouchBar
|
||||
|
||||
let spinning = false
|
||||
|
||||
// Reel labels
|
||||
const reel1 = new TouchBarLabel()
|
||||
const reel2 = new TouchBarLabel()
|
||||
const reel3 = new TouchBarLabel()
|
||||
|
||||
// Spin result label
|
||||
const result = new TouchBarLabel()
|
||||
|
||||
// Spin button
|
||||
const spin = new TouchBarButton({
|
||||
label: '🎰 Spin',
|
||||
backgroundColor: '#7851A9',
|
||||
click: () => {
|
||||
// Ignore clicks if already spinning
|
||||
if (spinning) {
|
||||
return
|
||||
}
|
||||
|
||||
spinning = true
|
||||
result.label = ''
|
||||
|
||||
let timeout = 10
|
||||
const spinLength = 4 * 1000 // 4 seconds
|
||||
const startTime = Date.now()
|
||||
|
||||
const spinReels = () => {
|
||||
updateReels()
|
||||
|
||||
if ((Date.now() - startTime) >= spinLength) {
|
||||
finishSpin()
|
||||
} else {
|
||||
// Slow down a bit on each spin
|
||||
timeout *= 1.1
|
||||
setTimeout(spinReels, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
spinReels()
|
||||
}
|
||||
})
|
||||
|
||||
const getRandomValue = () => {
|
||||
const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀']
|
||||
return values[Math.floor(Math.random() * values.length)]
|
||||
}
|
||||
|
||||
const updateReels = () => {
|
||||
reel1.label = getRandomValue()
|
||||
reel2.label = getRandomValue()
|
||||
reel3.label = getRandomValue()
|
||||
}
|
||||
|
||||
const finishSpin = () => {
|
||||
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size
|
||||
if (uniqueValues === 1) {
|
||||
// All 3 values are the same
|
||||
result.label = '💰 Jackpot!'
|
||||
} else if (uniqueValues === 2) {
|
||||
// 2 values are the same
|
||||
result.label = '😍 Winner!'
|
||||
} else {
|
||||
// No values are the same
|
||||
result.label = '🙁 Spin Again'
|
||||
}
|
||||
spinning = false
|
||||
}
|
||||
|
||||
const touchBar = new TouchBar([
|
||||
spin,
|
||||
new TouchBarSpacer({size: 'large'}),
|
||||
reel1,
|
||||
reel2,
|
||||
reel3,
|
||||
new TouchBarSpacer({size: 'large'}),
|
||||
result
|
||||
])
|
||||
|
||||
let window
|
||||
|
||||
app.once('ready', () => {
|
||||
window = new BrowserWindow({
|
||||
frame: false,
|
||||
titleBarStyle: 'hidden-inset',
|
||||
width: 200,
|
||||
height: 200,
|
||||
backgroundColor: '#000'
|
||||
})
|
||||
window.loadURL('about:blank')
|
||||
window.setTouchBar(touchBar)
|
||||
})
|
||||
```
|
|
@ -30,6 +30,7 @@
|
|||
'lib/browser/api/session.js',
|
||||
'lib/browser/api/screen.js',
|
||||
'lib/browser/api/system-preferences.js',
|
||||
'lib/browser/api/touch-bar.js',
|
||||
'lib/browser/api/tray.js',
|
||||
'lib/browser/api/web-contents.js',
|
||||
'lib/browser/chrome-extension.js',
|
||||
|
@ -280,6 +281,9 @@
|
|||
'atom/browser/ui/atom_menu_model.h',
|
||||
'atom/browser/ui/cocoa/atom_menu_controller.h',
|
||||
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
||||
'atom/browser/ui/cocoa/atom_touch_bar.h',
|
||||
'atom/browser/ui/cocoa/atom_touch_bar.mm',
|
||||
'atom/browser/ui/cocoa/touch_bar_forward_declarations.h',
|
||||
'atom/browser/ui/drag_util_mac.mm',
|
||||
'atom/browser/ui/drag_util_views.cc',
|
||||
'atom/browser/ui/drag_util.h',
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
const {ipcMain} = require('electron')
|
||||
const electron = require('electron')
|
||||
const {ipcMain} = electron
|
||||
const {EventEmitter} = require('events')
|
||||
const {BrowserWindow} = process.atomBinding('window')
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
|
@ -195,6 +196,9 @@ Object.assign(BrowserWindow.prototype, {
|
|||
},
|
||||
capturePage (...args) {
|
||||
return this.webContents.capturePage(...args)
|
||||
},
|
||||
setTouchBar (touchBar) {
|
||||
electron.TouchBar._setOnWindow(touchBar, this)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -103,6 +103,12 @@ Object.defineProperties(exports, {
|
|||
return require('../system-preferences')
|
||||
}
|
||||
},
|
||||
TouchBar: {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return require('../touch-bar')
|
||||
}
|
||||
},
|
||||
Tray: {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
|
|
214
lib/browser/api/touch-bar.js
Normal file
214
lib/browser/api/touch-bar.js
Normal file
|
@ -0,0 +1,214 @@
|
|||
const {EventEmitter} = require('events')
|
||||
|
||||
let nextItemID = 1
|
||||
|
||||
class TouchBar extends EventEmitter {
|
||||
// Bind a touch bar to a window
|
||||
static _setOnWindow (touchBar, window) {
|
||||
if (window._touchBar != null) {
|
||||
window._touchBar._removeFromWindow(window)
|
||||
}
|
||||
|
||||
if (touchBar == null) {
|
||||
window._setTouchBarItems([])
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(touchBar)) {
|
||||
touchBar = new TouchBar(touchBar)
|
||||
}
|
||||
touchBar._addToWindow(window)
|
||||
}
|
||||
|
||||
constructor (items) {
|
||||
super()
|
||||
|
||||
if (!Array.isArray(items)) {
|
||||
throw new Error('Must specify items array as first argument')
|
||||
}
|
||||
|
||||
this.windowListeners = {}
|
||||
this.items = {}
|
||||
this.ordereredItems = []
|
||||
|
||||
const registerItem = (item) => {
|
||||
this.items[item.id] = item
|
||||
item.on('change', () => {
|
||||
this.emit('change', item.id, item.type)
|
||||
})
|
||||
if (item.child instanceof TouchBar) {
|
||||
item.child.ordereredItems.forEach(registerItem)
|
||||
}
|
||||
}
|
||||
items.forEach((item) => {
|
||||
if (!(item instanceof TouchBarItem)) {
|
||||
throw new Error('Each item must be an instance of TouchBarItem')
|
||||
}
|
||||
this.ordereredItems.push(item)
|
||||
registerItem(item)
|
||||
})
|
||||
}
|
||||
|
||||
_addToWindow (window) {
|
||||
const {id} = window
|
||||
|
||||
// Already added to window
|
||||
if (this.windowListeners.hasOwnProperty(id)) return
|
||||
|
||||
window._touchBar = this
|
||||
|
||||
const changeListener = (itemID) => {
|
||||
window._refreshTouchBarItem(itemID)
|
||||
}
|
||||
this.on('change', changeListener)
|
||||
|
||||
const interactionListener = (event, itemID, details) => {
|
||||
const item = this.items[itemID]
|
||||
if (item != null && item.onInteraction != null) {
|
||||
item.onInteraction(details)
|
||||
}
|
||||
}
|
||||
window.on('-touch-bar-interaction', interactionListener)
|
||||
|
||||
const removeListeners = () => {
|
||||
this.removeListener('change', changeListener)
|
||||
window.removeListener('-touch-bar-interaction', interactionListener)
|
||||
window.removeListener('closed', removeListeners)
|
||||
window._touchBar = null
|
||||
delete this.windowListeners[id]
|
||||
}
|
||||
window.once('closed', removeListeners)
|
||||
this.windowListeners[id] = removeListeners
|
||||
|
||||
window._setTouchBarItems(this.ordereredItems)
|
||||
}
|
||||
|
||||
_removeFromWindow (window) {
|
||||
const removeListeners = this.windowListeners[window.id]
|
||||
if (removeListeners != null) removeListeners()
|
||||
}
|
||||
}
|
||||
|
||||
class TouchBarItem extends EventEmitter {
|
||||
constructor () {
|
||||
super()
|
||||
this.id = `${nextItemID++}`
|
||||
}
|
||||
|
||||
_addLiveProperty (name, initialValue) {
|
||||
const privateName = `_${name}`
|
||||
this[privateName] = initialValue
|
||||
Object.defineProperty(this, name, {
|
||||
get: function () {
|
||||
return this[privateName]
|
||||
},
|
||||
set: function (value) {
|
||||
this[privateName] = value
|
||||
this.emit('change')
|
||||
},
|
||||
enumerable: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarButton = class TouchBarButton extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'button'
|
||||
const {click, icon, label, backgroundColor} = config
|
||||
this._addLiveProperty('label', label)
|
||||
this._addLiveProperty('backgroundColor', backgroundColor)
|
||||
this._addLiveProperty('icon', icon)
|
||||
if (typeof click === 'function') {
|
||||
this.onInteraction = () => {
|
||||
config.click()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarColorPicker = class TouchBarColorPicker extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'colorpicker'
|
||||
const {availableColors, change, selectedColor} = config
|
||||
this._addLiveProperty('availableColors', availableColors)
|
||||
this._addLiveProperty('selectedColor', selectedColor)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
this.onInteraction = (details) => {
|
||||
this._selectedColor = details.color
|
||||
change(details.color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarGroup = class TouchBarGroup extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'group'
|
||||
this.child = config.items
|
||||
if (!(this.child instanceof TouchBar)) {
|
||||
this.child = new TouchBar(this.child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarLabel = class TouchBarLabel extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'label'
|
||||
this._addLiveProperty('label', config.label)
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarPopover = class TouchBarPopover extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'popover'
|
||||
this._addLiveProperty('label', config.label)
|
||||
this._addLiveProperty('icon', config.icon)
|
||||
this.showCloseButton = config.showCloseButton
|
||||
this.child = config.items
|
||||
if (!(this.child instanceof TouchBar)) {
|
||||
this.child = new TouchBar(this.child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarSlider = class TouchBarSlider extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'slider'
|
||||
const {change, label, minValue, maxValue, value} = config
|
||||
this._addLiveProperty('label', label)
|
||||
this._addLiveProperty('minValue', minValue)
|
||||
this._addLiveProperty('maxValue', maxValue)
|
||||
this._addLiveProperty('value', value)
|
||||
|
||||
if (typeof change === 'function') {
|
||||
this.onInteraction = (details) => {
|
||||
this._value = details.value
|
||||
change(details.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TouchBar.TouchBarSpacer = class TouchBarSpacer extends TouchBarItem {
|
||||
constructor (config) {
|
||||
super()
|
||||
if (config == null) config = {}
|
||||
this.type = 'spacer'
|
||||
this.size = config.size
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TouchBar
|
|
@ -360,6 +360,7 @@ const browserModules = [
|
|||
'screen',
|
||||
'session',
|
||||
'systemPreferences',
|
||||
'TouchBar',
|
||||
'Tray',
|
||||
'webContents'
|
||||
]
|
||||
|
|
3
script/cpplint.py
vendored
3
script/cpplint.py
vendored
|
@ -11,6 +11,9 @@ IGNORE_FILES = [
|
|||
os.path.join('atom', 'browser', 'mac', 'atom_application_delegate.h'),
|
||||
os.path.join('atom', 'browser', 'resources', 'win', 'resource.h'),
|
||||
os.path.join('atom', 'browser', 'ui', 'cocoa', 'atom_menu_controller.h'),
|
||||
os.path.join('atom', 'browser', 'ui', 'cocoa', 'atom_touch_bar.h'),
|
||||
os.path.join('atom', 'browser', 'ui', 'cocoa',
|
||||
'touch_bar_forward_declarations.h'),
|
||||
os.path.join('atom', 'common', 'api', 'api_messages.h'),
|
||||
os.path.join('atom', 'common', 'common_message_generator.cc'),
|
||||
os.path.join('atom', 'common', 'common_message_generator.h'),
|
||||
|
|
52
spec/api-touch-bar-spec.js
Normal file
52
spec/api-touch-bar-spec.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
const assert = require('assert')
|
||||
const {BrowserWindow, TouchBar} = require('electron').remote
|
||||
const {closeWindow} = require('./window-helpers')
|
||||
|
||||
const {TouchBarButton, TouchBarColorPicker, TouchBarGroup} = TouchBar
|
||||
const {TouchBarLabel, TouchBarPopover, TouchBarSlider, TouchBarSpacer} = TouchBar
|
||||
|
||||
describe('TouchBar module', function () {
|
||||
it('throws an error when created without an items array', function () {
|
||||
assert.throws(() => {
|
||||
const touchBar = new TouchBar()
|
||||
touchBar.toString()
|
||||
}, /Must specify items array as first argument/)
|
||||
})
|
||||
|
||||
it('throws an error when created with invalid items', function () {
|
||||
assert.throws(() => {
|
||||
const touchBar = new TouchBar([1, true, {}, []])
|
||||
touchBar.toString()
|
||||
}, /Each item must be an instance of TouchBarItem/)
|
||||
})
|
||||
|
||||
describe('BrowserWindow behavior', function () {
|
||||
let window
|
||||
|
||||
beforeEach(function () {
|
||||
window = new BrowserWindow()
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.setTouchBar(null)
|
||||
return closeWindow(window).then(function () { window = null })
|
||||
})
|
||||
|
||||
it('can be added to and removed from a window', function () {
|
||||
const label = new TouchBarLabel({label: 'bar'})
|
||||
const touchBar = new TouchBar([
|
||||
new TouchBarButton({label: 'foo', backgroundColor: '#F00', click: () => {}}),
|
||||
new TouchBarColorPicker({selectedColor: '#F00', change: () => {}}),
|
||||
new TouchBarGroup({items: new TouchBar([new TouchBarLabel({label: 'hello'})])}),
|
||||
label,
|
||||
new TouchBarPopover({items: new TouchBar([new TouchBarButton({label: 'pop'})])}),
|
||||
new TouchBarSlider({label: 'slide', value: 5, minValue: 2, maxValue: 75, change: () => {}}),
|
||||
new TouchBarSpacer({size: 'large'})
|
||||
])
|
||||
window.setTouchBar(touchBar)
|
||||
label.label = 'baz'
|
||||
window.setTouchBar()
|
||||
window.setTouchBar(new TouchBar([new TouchBarLabel({label: 'two'})]))
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue