Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: programmatically modify traffic light positioning #22533

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/api/browser-window.md
Expand Up @@ -1750,6 +1750,17 @@ will remove the vibrancy effect on the window.
Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been
deprecated and will be removed in an upcoming version of macOS.

#### `win.setTrafficLightPosition(position)` _macOS_

* `position` [Point](structures/point.md)

Set a custom position for the traffic light buttons. Can only be used with `titleBarStyle` set to `hidden`.

#### `win.getTrafficLightPosition()` _macOS_

Returns `Point` - The current position for the traffic light buttons. Can only be used with `titleBarStyle`
set to `hidden`.

#### `win.setTouchBar(touchBar)` _macOS_ _Experimental_

* `touchBar` TouchBar | null
Expand Down
16 changes: 16 additions & 0 deletions shell/browser/api/electron_api_top_level_window.cc
Expand Up @@ -814,6 +814,16 @@ void TopLevelWindow::SetVibrancy(v8::Isolate* isolate,
window_->SetVibrancy(type);
}

#if defined(OS_MACOSX)
void TopLevelWindow::SetTrafficLightPosition(const gfx::Point& position) {
window_->SetTrafficLightPosition(position);
}

gfx::Point TopLevelWindow::GetTrafficLightPosition() const {
return window_->GetTrafficLightPosition();
}
#endif

void TopLevelWindow::SetTouchBar(
std::vector<gin_helper::PersistentDictionary> items) {
window_->SetTouchBar(std::move(items));
Expand Down Expand Up @@ -1184,6 +1194,12 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setAutoHideCursor", &TopLevelWindow::SetAutoHideCursor)
#endif
.SetMethod("setVibrancy", &TopLevelWindow::SetVibrancy)
#if defined(OS_MACOSX)
.SetMethod("setTrafficLightPosition",
&TopLevelWindow::SetTrafficLightPosition)
.SetMethod("getTrafficLightPosition",
&TopLevelWindow::GetTrafficLightPosition)
#endif
.SetMethod("_setTouchBarItems", &TopLevelWindow::SetTouchBar)
.SetMethod("_refreshTouchBarItem", &TopLevelWindow::RefreshTouchBarItem)
.SetMethod("_setEscapeTouchBarItem",
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/api/electron_api_top_level_window.h
Expand Up @@ -185,6 +185,12 @@ class TopLevelWindow : public gin_helper::TrackableObject<TopLevelWindow>,
bool IsVisibleOnAllWorkspaces();
void SetAutoHideCursor(bool auto_hide);
virtual void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value);

#if defined(OS_MACOSX)
void SetTrafficLightPosition(const gfx::Point& position);
gfx::Point GetTrafficLightPosition() const;
#endif

void SetTouchBar(std::vector<gin_helper::PersistentDictionary> items);
void RefreshTouchBarItem(const std::string& item_id);
void SetEscapeTouchBarItem(gin_helper::PersistentDictionary item);
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/native_window.h
Expand Up @@ -194,6 +194,12 @@ class NativeWindow : public base::SupportsUserData,
// Vibrancy API
virtual void SetVibrancy(const std::string& type);

// Traffic Light API
#if defined(OS_MACOSX)
virtual void SetTrafficLightPosition(const gfx::Point& position) = 0;
virtual gfx::Point GetTrafficLightPosition() const = 0;
#endif

// Touchbar API
virtual void SetTouchBar(std::vector<gin_helper::PersistentDictionary> items);
virtual void RefreshTouchBarItem(const std::string& item_id);
Expand Down
2 changes: 2 additions & 0 deletions shell/browser/native_window_mac.h
Expand Up @@ -153,6 +153,8 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
// Custom traffic light positioning
void RepositionTrafficLights();
void SetExitingFullScreen(bool flag);
void SetTrafficLightPosition(const gfx::Point& position) override;
gfx::Point GetTrafficLightPosition() const override;
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;

enum class TitleBarStyle {
Expand Down
9 changes: 9 additions & 0 deletions shell/browser/native_window_mac.mm
Expand Up @@ -1552,6 +1552,15 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) {
[effect_view setMaterial:vibrancyType];
}

void NativeWindowMac::SetTrafficLightPosition(const gfx::Point& position) {
traffic_light_position_ = position;
RepositionTrafficLights();
}

gfx::Point NativeWindowMac::GetTrafficLightPosition() const {
return traffic_light_position_;
}

void NativeWindowMac::SetTouchBar(
std::vector<gin_helper::PersistentDictionary> items) {
if (@available(macOS 10.12.2, *)) {
Expand Down
35 changes: 30 additions & 5 deletions spec-main/api-browser-window-spec.ts
Expand Up @@ -210,7 +210,7 @@ describe('BrowserWindow module', () => {
}).to.throw('Object has been destroyed')
})
it('should not crash when destroying windows with pending events', () => {
const focusListener = () => {}
const focusListener = () => { }
app.on('browser-window-focus', focusListener)
const windowCount = 3
const windowOptions = {
Expand Down Expand Up @@ -281,7 +281,7 @@ describe('BrowserWindow module', () => {
fs.readFile(filePath, (err, data) => {
if (err) return
if (parsedData.username === 'test' &&
parsedData.file === data.toString()) {
parsedData.file === data.toString()) {
res.end()
}
})
Expand Down Expand Up @@ -1347,6 +1347,31 @@ describe('BrowserWindow module', () => {
})
})

ifdescribe(process.platform === 'darwin')('BrowserWindow.getTrafficLightPosition(pos)', () => {
afterEach(closeAllWindows)

it('gets the set traffic light position property', () => {
const pos = { x: 10, y: 10 }
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos })
const currentPosition = w.getTrafficLightPosition()

expect(currentPosition).to.deep.equal(pos)
})
})

ifdescribe(process.platform === 'darwin')('BrowserWindow.setTrafficLightPosition(pos)', () => {
afterEach(closeAllWindows)

it('can set the traffic light position property', () => {
const pos = { x: 10, y: 10 }
const w = new BrowserWindow({ show: false, titleBarStyle: 'hidden', trafficLightPosition: pos })
w.setTrafficLightPosition(pos)
const currentPosition = w.getTrafficLightPosition()

expect(currentPosition).to.deep.equal(pos)
})
})

ifdescribe(process.platform === 'win32')('BrowserWindow.setAppDetails(options)', () => {
afterEach(closeAllWindows)

Expand Down Expand Up @@ -1613,7 +1638,7 @@ describe('BrowserWindow module', () => {
afterEach(closeAllWindows)

describe('"preload" option', () => {
const doesNotLeakSpec = (name: string, webPrefs: {nodeIntegration: boolean, sandbox: boolean, contextIsolation: boolean}) => {
const doesNotLeakSpec = (name: string, webPrefs: { nodeIntegration: boolean, sandbox: boolean, contextIsolation: boolean }) => {
it(name, async () => {
const w = new BrowserWindow({
webPreferences: {
Expand Down Expand Up @@ -1875,7 +1900,7 @@ describe('BrowserWindow module', () => {
})

describe('"sandbox" option', () => {
function waitForEvents<T> (emitter: {once: Function}, events: string[], callback: () => void) {
function waitForEvents<T> (emitter: { once: Function }, events: string[], callback: () => void) {
let count = events.length
for (const event of events) {
emitter.once(event, () => {
Expand Down Expand Up @@ -2863,7 +2888,7 @@ describe('BrowserWindow module', () => {
return
}
if (rect.height === contentHeight && rect.width === contentWidth &&
!gotInitialFullSizeFrame) {
!gotInitialFullSizeFrame) {
// The initial frame is full-size, but we're looking for a call
// with just the dirty-rect. The next frame should be a smaller
// rect.
Expand Down