Skip to content

Commit

Permalink
[desktop] Fix drag-n-drop on mac, fix #2850
Browse files Browse the repository at this point in the history
  • Loading branch information
bedhub committed Apr 1, 2021
1 parent 52decbd commit 87a2d2c
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 149 deletions.
2 changes: 1 addition & 1 deletion flow/electron.js
Expand Up @@ -42,7 +42,7 @@ declare module 'electron' {
openPath(fullPath: string): Promise<string>;
};

declare export type NativeImage = {};
declare export class NativeImage {}

declare export type Rectangle = {|
x: number,
Expand Down
8 changes: 4 additions & 4 deletions src/desktop/DesktopNotifier.js
Expand Up @@ -43,12 +43,12 @@ export class DesktopNotifier {
* @param props.clickHandler Called when the user clicks the notification
* @param props.closeHandler Called when the notification was closed (by timeout or user action).
*/
showOneShot(props: {|
async showOneShot(props: {|
title: string,
body?: string,
icon?: NativeImage
|}): Promise<NotificationResultEnum> {
const withIcon = {title: props.title, body: props.body, icon: props.icon || this._tray.getIcon()}
const withIcon = {title: props.title, body: props.body, icon: props.icon || await this._tray.getAppIcon()}
if (!this.isAvailable()) {
return Promise.reject()
}
Expand All @@ -64,14 +64,14 @@ export class DesktopNotifier {
this._notificationCloseFunctions[id]()
}

const showIt = () => {
const showIt = async () => {
if (!this.isAvailable()) {
return
}
this._notificationCloseFunctions[id] = this._notificationFactory.makeNotification({
title: title,
body: message,
icon: this._tray.getIcon(),
icon: await this._tray.getAppIcon(),
}, onClick)
this._tray.setBadge()
this._tray.update(this)
Expand Down
43 changes: 23 additions & 20 deletions src/desktop/tray/DesktopTray.js
Expand Up @@ -5,23 +5,23 @@ import type {DesktopConfig} from '../config/DesktopConfig.js'
import type {WindowManager} from "../DesktopWindowManager.js"
import type {DesktopNotifier} from "../DesktopNotifier.js"
import {lang} from "../../misc/LanguageViewModel"
import macTray from "./PlatformDock"
import nonMacTray from "./PlatformTray"
import {MacTray} from "./MacTray"
import {NonMacTray} from "./NonMacTray"
import {getResourcePath} from "../resources"

const platformTray: PlatformTray = process.platform === 'darwin'
? macTray
: nonMacTray

export type PlatformTray = {
setBadge: ()=>void,
clearBadge: ()=>void,
getTray: (WindowManager, NativeImage) => ?Tray,
getPlatformMenuItems: ()=>Array<MenuItem>,
attachMenuToTray: (Menu, ?Tray) => void,
iconPath: string => string,
needsWindowListInMenu: ()=>boolean
export interface PlatformTray {
setBadge(): void,
clearBadge(): void,
getTray(WindowManager, NativeImage): ?Tray,
getPlatformMenuItems(): Array<MenuItem>,
attachMenuToTray(Menu, ?Tray): void,
getAppIconPathFromName(string): string,
needsWindowListInMenu(): boolean,
}

const platformTray: PlatformTray = (process.platform === 'darwin')
? new MacTray()
: new NonMacTray()

export class DesktopTray {
+_conf: DesktopConfig;
Expand All @@ -31,15 +31,15 @@ export class DesktopTray {

constructor(config: DesktopConfig) {
this._conf = config
this.getIcon()
this.getAppIcon()
app.on('will-quit', (e: Event) => {
if (this._tray) {
this._tray.destroy()
this._tray = null
}
}).on('ready', () => {
}).on('ready', async () => {
if (!this._wm) console.warn("Tray: No WM set before 'ready'!")
this._tray = platformTray.getTray(this._wm, this.getIcon())
this._tray = platformTray.getTray(this._wm, await this.getAppIcon())
})
}

Expand Down Expand Up @@ -79,15 +79,18 @@ export class DesktopTray {
platformTray.clearBadge()
}

async getIcon(): Promise<NativeImage> {
async getAppIcon(): Promise<NativeImage> {
if (!this._icon) {
this._icon = this.getIconByName(await this._conf.getConst('iconName'))
const iconName = await this._conf.getConst('iconName')
const iconPath = platformTray.getAppIconPathFromName(iconName)
this._icon = nativeImage.createFromPath(iconPath)
}
return this._icon
}

getIconByName(iconName: string): NativeImage {
return nativeImage.createFromPath(platformTray.iconPath(iconName))
const iconPath = getResourcePath(`icons/${iconName}`)
return nativeImage.createFromPath(iconPath)
}

setWindowManager(wm: WindowManager) {
Expand Down
47 changes: 47 additions & 0 deletions src/desktop/tray/MacTray.js
@@ -0,0 +1,47 @@
// @flow

/**
* This file provides the functionality used by DesktopTray on mac
*/

import type {NativeImage} from "electron"
import {app, Menu, MenuItem, Tray} from "electron"
import type {WindowManager} from "../DesktopWindowManager"
import os from 'os'
import {getResourcePath} from "../resources"
import type {PlatformTray} from "./DesktopTray"

export class MacTray implements PlatformTray {
needsWindowListInMenu(): boolean {
//MacOs Catalina started showing the window list on its own
return Number(os.release().slice(0, 2)) < 19
}

attachMenuToTray(m: Menu, tray: ?Tray): void {
app.dock.setMenu(m)
}

getPlatformMenuItems(): Array<MenuItem> {
return []
}

getTray(wm: WindowManager, icon: NativeImage): ?Tray {
if (!app.dock.isVisible()) {
app.dock.show()
}
return null
}

setBadge() {
app.dock.bounce()
app.dock.setBadge("●")
}

clearBadge() {
app.dock.setBadge("")
}

getAppIconPathFromName(iconName: string): string {
return getResourcePath(`icons/${iconName}.icns`)
}
}
57 changes: 57 additions & 0 deletions src/desktop/tray/NonMacTray.js
@@ -0,0 +1,57 @@
// @flow
import type {NativeImage} from 'electron'
import {app, Menu, MenuItem, Tray} from "electron"
import type {WindowManager} from "../DesktopWindowManager"
import {lang} from "../../misc/LanguageViewModel"
import type {PlatformTray} from './DesktopTray'
import path from "path"
import {getResourcePath} from "../resources"

/**
* This file provides the functionality used by DesktopTray on windows & linux.
*/

export class NonMacTray implements PlatformTray {
attachMenuToTray(m: Menu, tray: ?Tray): void {
if (tray) tray.setContextMenu(m)
}

needsWindowListInMenu(): boolean {
return true
}

getPlatformMenuItems(): Array<MenuItem> {
return [
new MenuItem({type: 'separator'}),
new MenuItem({
label: lang.get("quit_action"),
accelerator: "CmdOrCtrl+Q",
click: app.quit
})
]
}

getTray(wm: WindowManager, icon: NativeImage): Tray {
const tray = new Tray(icon)
/*
setting the context menu is necessary to prevent electron from segfaulting shortly after creating the tray.
workaround from: https://github.com/electron/electron/issues/22137#issuecomment-586105622
issue: https://github.com/electron/electron/issues/22215
*/
tray.setContextMenu(null)
tray.on('click', ev => {
wm.getLastFocused(true)
})
return tray
}



setBadge() {}

clearBadge() {}

getAppIconPathFromName(iconName: string): string {
return getResourcePath(`icons/${iconName}`)
}
}
57 changes: 0 additions & 57 deletions src/desktop/tray/PlatformDock.js

This file was deleted.

67 changes: 0 additions & 67 deletions src/desktop/tray/PlatformTray.js

This file was deleted.

0 comments on commit 87a2d2c

Please sign in to comment.