Skip to content

Commit

Permalink
v1.5.0 (#17)
Browse files Browse the repository at this point in the history
* たまにウィンドウが重複して消えなくなるのを修正

* たまにウィンドウが重複して消えなくなるのを修正

* 機能追加:ウィンドウごとの座標順ソート

* 機能追加:すべてのウィンドウで表示

* パフォーマンスの改善
-----
- フィルタ操作の大部分をNodeプロセスで行うように
- 起動中のプロセスチェックをディスプレイの枚数分繰り返していたのを1回に変更
- 差分がなければRendererプロセスに送らないように変更
  • Loading branch information
fruitriin committed Jul 22, 2023
1 parent c241ff9 commit 4212668
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 3,884 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@vitejs/plugin-vue": "^4.1.0",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.2",
"add": "^2.0.6",
"bulma": "^0.9.4",
"dotenv": "^16.1.4",
"electron": "^22.3.4",
Expand All @@ -50,6 +49,8 @@
"eslint": "^8.36.0",
"eslint-plugin-vue": "^9.10.0",
"html-escaper": "^3.0.3",
"just-diff": "^6.0.2",
"just-diff-apply": "^5.5.0",
"less": "^4.1.3",
"prettier": "^2.8.7",
"sass": "^1.62.1",
Expand Down
35 changes: 24 additions & 11 deletions src/main/funcs/events.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// レンダラープロセスからのメッセージを受信する
import { createOptionWindow, mainWindow, windowPosition } from './windows'
import { activateWindow, grantPermission } from './helper'
import { createOptionWindow, taskbars, windowPosition } from './windows'
import { activateWindow, grantPermission, macWindowProcesses } from './helper'
import { ipcMain, screen } from 'electron'
import { store } from './store'

type LayoutType = 'right' | 'left' | 'bottom'
import { Options, store } from './store'

export function setEventHandlers() {
ipcMain.on('activeWindow', (_event, windowId) => {
Expand All @@ -13,13 +11,28 @@ export function setEventHandlers() {
ipcMain.on('openOption', () => {
createOptionWindow()
})
// ウィンドウの準備ができたらプロセスリストを破棄
// ホットリロードフロントのdataが破棄されても
// nodeプロセスがそのままなので差分なしになるのを防ぐ
ipcMain.on('windowReady', () => {
macWindowProcesses.splice(0, macWindowProcesses.length)
})

ipcMain.on('setOptions', (_event, value: Options) => {
const layout = store.get('options.layout')
const displays = screen.getAllDisplays()

store.set('options', value)
for (const displayId in taskbars) {
taskbars[displayId].webContents.send('updateOptions', value)

ipcMain.on('setLayout', (_event, layout: LayoutType) => {
store.set('layout', layout)
const primaryDisplay = screen.getPrimaryDisplay()
const position = windowPosition(primaryDisplay, layout)
mainWindow.setBounds(position)
mainWindow.webContents.send('setLayout', layout)
// メインプロセスに作用するものを別途処理
if (layout != value.layout) {
const targetDisplay = displays.find((display) => display.id.toString() === displayId)
if (targetDisplay)
taskbars[displayId].setBounds(windowPosition(targetDisplay, value.layout))
}
}
})

ipcMain.on('grantPermission', () => {
Expand Down
46 changes: 40 additions & 6 deletions src/main/funcs/helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, BrowserWindow } from 'electron'
import { app } from 'electron'
import path from 'path'
const { spawn, exec } = require('child_process')
import { MacWindow } from '@/type'
Expand All @@ -12,22 +12,22 @@ if (app.isPackaged) {
binaryPath = path.join(__dirname, '../../resources', 'TaskbarHelper')
}

export function getAndSubmitProcesses(win: BrowserWindow): void {
export const macWindowProcesses: MacWindow[] = []

export function getAndSubmitProcesses(): void {
let rawData = ''
try {
const taskbarHelper = spawn(binaryPath, ['list'])
// console.log("tick")
taskbarHelper.stdout.on('data', (raw) => {
rawData += raw
// console.log(raw)
})
// taskbarHelper.on("data", console.info)
taskbarHelper.stderr.on('data', (raw) => {
console.error(raw)
})
taskbarHelper.on('close', async (code) => {
if ((await code) === 0) {
win.webContents.send('process', new Buffer(rawData).toString('utf-8'))
const jsoned = JSON.parse(new Buffer(rawData).toString('utf-8'))
applyProcessChange(jsoned)
rawData = ''
}
})
Expand All @@ -40,7 +40,23 @@ export function grantPermission(): void {
spawn(binaryPath, ['grant'])
}

import { diff } from 'just-diff'
import { diffApply } from 'just-diff-apply'

function applyProcessChange(newProcesses: typeof macWindowProcesses) {
const result = diff(macWindowProcesses, filterProcesses(newProcesses))

if (result.length > 0) {
diffApply(macWindowProcesses, result)
for (const taskbarKey in taskbars) {
taskbars[taskbarKey].webContents.send('process', macWindowProcesses)
}
}
}

import { escape } from 'html-escaper'
import { store } from './store'
import { taskbars } from './windows'

// ウィンドウをアクティブにする関数
export function activateWindow(window: MacWindow): void {
Expand All @@ -66,3 +82,21 @@ end tell
// console.log(_stdout);
})
}

/**
* 高さ・幅が低すぎるものと、store.filters から条件に一致するものを除外する
*/
function filterProcesses(windows: MacWindow[]) {
return windows.filter((win) => {
if (win.kCGWindowBounds?.Height < 40) return false
if (win.kCGWindowBounds?.Width < 40) return false

for (const filter of store.store.filters) {
for (const filterElement of filter) {
if (win[filterElement.property] === undefined) return false
if (win[filterElement.property] == filterElement.is) return false
}
}
return true
})
}
11 changes: 8 additions & 3 deletions src/main/funcs/store.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import Store from 'electron-store'
import ElectronStore from 'electron-store'

export const store = new Store({
type LayoutType = 'right' | 'left' | 'bottom'
export const store = new ElectronStore({
defaults: {
layout: 'bottom',
options: {
layout: 'bottom' as LayoutType,
windowSortByPositionInApp: false
},
filters: [
[{ property: 'kCGWindowIsOnscreen', is: false }],
[{ property: 'kCGWindowOwnerName', is: 'Dock' }],
Expand All @@ -24,3 +28,4 @@ export const store = new Store({
]
}
})
export type Options = typeof store.store.options
91 changes: 50 additions & 41 deletions src/main/funcs/windows.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,59 @@
import { join } from 'path'
import { is } from '@electron-toolkit/utils'
import { BrowserWindow, screen } from 'electron'
import { getAndSubmitProcesses } from './helper'
import { BrowserWindow, ipcMain, screen, Display } from 'electron'
import { store } from './store'

type LayoutType = 'right' | 'left' | 'bottom'

export let mainWindow: BrowserWindow
type Taskbar = BrowserWindow
type displayId = Display['id']
export const taskbars: Record<displayId, Taskbar> = {}
export type Taskbars = typeof taskbars

export function createWindow() {
// Create the browser window.
const allDisplays = screen.getAllDisplays()
allDisplays.forEach((display) => {
const taskbarWindow = new BrowserWindow({
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
},
titleBarStyle: 'hiddenInset',
autoHideMenuBar: true,
// resizable: false,
movable: false,
maximizable: false,
minimizable: false,
alwaysOnTop: true,
skipTaskbar: true,
show: false,
...windowPosition(display, store.get('layout') as LayoutType)
})

const primaryDisplay = screen.getPrimaryDisplay()
// 準備ができたら表示
taskbarWindow.on('ready-to-show', () => {
taskbarWindow.show()
})
// 閉じるボタンなどを消す
taskbarWindow.setWindowButtonVisibility(false)

mainWindow = new BrowserWindow({
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
sandbox: false
},
titleBarStyle: 'hiddenInset',
autoHideMenuBar: true,
// resizable: false,
movable: false,
maximizable: false,
minimizable: false,
alwaysOnTop: true,
skipTaskbar: true,
show: false,
...windowPosition(primaryDisplay, store.get('layout') as LayoutType)
})
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
taskbarWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
taskbarWindow.loadFile(join(__dirname, '../renderer/index.html'))
}

// 準備ができたら表示
mainWindow.on('ready-to-show', () => {
mainWindow.show()
taskbars[display.id] = taskbarWindow
ipcMain.on('windowReady', () => {
taskbarWindow.webContents.send('displayInfo', {
label: display.label,
id: display.id,
workArea: display.workArea
})
})
})
// 閉じるボタンなどを消す
mainWindow.setWindowButtonVisibility(false)

// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}

// 1秒ごとにプロセスのリストを取得
setInterval(() => {
getAndSubmitProcesses(mainWindow)
}, 1000)
}

export let optionWindow: BrowserWindow
Expand Down Expand Up @@ -80,7 +86,10 @@ export function windowPosition(
return {
width: type === 'bottom' ? display.workArea.width : 210,
height: type !== 'bottom' ? display.workArea.height : 60,
x: type === 'right' ? display.workArea.width - 210 : 0,
y: type === 'bottom' ? display.workArea.height - 30 : 0
x: type === 'right' ? display.workArea.x - 210 : display.workArea.x,
y:
type === 'bottom'
? display.workArea.height + display.workArea.y - 30
: display.workArea.height + display.workArea.y
}
}
8 changes: 8 additions & 0 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { electronApp, optimizer } from '@electron-toolkit/utils'

import { createWindow } from './funcs/windows'
import { setEventHandlers } from './funcs/events'
import { getAndSubmitProcesses } from './funcs/helper'

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
Expand All @@ -27,8 +28,15 @@ app.whenReady().then(() => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})

// イベントハンドラーを設定する
setEventHandlers()

// 1秒ごとにプロセスを取得する
setInterval(() => {
getAndSubmitProcesses()
}, 1000)

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
Expand Down
1 change: 0 additions & 1 deletion src/renderer/renderer-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ const router = createRouter({
history: createWebHistory('#'),
routes
})
console.log(routes)

createApp(App).use(router).mount('#app')
Loading

0 comments on commit 4212668

Please sign in to comment.