diff --git a/src/app/content.html b/src/app/content.html
index 61768e1..130c7ac 100644
--- a/src/app/content.html
+++ b/src/app/content.html
@@ -100,13 +100,13 @@
}
.window-sliding-down {
- animation: slideDownFromHeader 0.25s cubic-bezier(0.23, 1, 0.32, 1) forwards;
+ animation: slideDownFromHeader 0.12s cubic-bezier(0.23, 1, 0.32, 1) forwards;
will-change: transform, opacity;
transform-style: preserve-3d;
}
.window-sliding-up {
- animation: slideUpToHeader 0.18s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards;
+ animation: slideUpToHeader 0.10s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards;
will-change: transform, opacity;
transform-style: preserve-3d;
}
@@ -156,14 +156,14 @@
}
.settings-window-show {
- animation: settingsPopFromButton 0.22s cubic-bezier(0.23, 1, 0.32, 1) forwards;
+ animation: settingsPopFromButton 0.12s cubic-bezier(0.23, 1, 0.32, 1) forwards;
transform-origin: 85% 0%;
will-change: transform, opacity;
transform-style: preserve-3d;
}
.settings-window-hide {
- animation: settingsCollapseToButton 0.18s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards;
+ animation: settingsCollapseToButton 0.10s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards;
transform-origin: 85% 0%;
will-change: transform, opacity;
transform-style: preserve-3d;
@@ -250,7 +250,7 @@
if (animationTimeout) clearTimeout(animationTimeout);
animationTimeout = setTimeout(() => {
app.classList.remove('window-sliding-down');
- }, 250);
+ }, 120);
});
ipcRenderer.on('window-hide-animation', () => {
@@ -262,7 +262,7 @@
animationTimeout = setTimeout(() => {
app.classList.remove('window-sliding-up');
app.classList.add('window-hidden');
- }, 180);
+ }, 100);
});
ipcRenderer.on('settings-window-hide-animation', () => {
@@ -274,7 +274,7 @@
animationTimeout = setTimeout(() => {
app.classList.remove('settings-window-hide');
app.classList.add('window-hidden');
- }, 180);
+ }, 100);
});
ipcRenderer.on('listen-window-move-to-center', () => {
diff --git a/src/electron/smoothMovementManager.js b/src/electron/smoothMovementManager.js
index 2550d0a..a676c82 100644
--- a/src/electron/smoothMovementManager.js
+++ b/src/electron/smoothMovementManager.js
@@ -60,140 +60,55 @@ class SmoothMovementManager {
this.currentDisplayId = targetDisplay.id;
}
- hideToEdge(edge, callback) {
+ hideToEdge(edge, callback, { instant = false } = {}) {
const header = this.windowPool.get('header');
- if (!this._isWindowValid(header) || !header.isVisible() || this.isAnimating) return;
-
- const currentBounds = header.getBounds();
- const display = this.getCurrentDisplay(header);
-
- if (
- !currentBounds || typeof currentBounds.x !== 'number' || typeof currentBounds.y !== 'number' ||
- !display || !display.workArea || !display.workAreaSize ||
- typeof display.workArea.x !== 'number' || typeof display.workArea.y !== 'number' ||
- typeof display.workAreaSize.width !== 'number' || typeof display.workAreaSize.height !== 'number'
- ) {
- console.error('[MovementManager] Invalid bounds or display info for hideToEdge. Aborting.');
+ if (!header || header.isDestroyed()) {
+ if (typeof callback === 'function') callback();
return;
}
-
- this.lastVisiblePosition = { x: currentBounds.x, y: currentBounds.y };
- this.headerPosition = { x: currentBounds.x, y: currentBounds.y };
-
- const { width: screenWidth, height: screenHeight } = display.workAreaSize;
- const { x: workAreaX, y: workAreaY } = display.workArea;
-
- let targetX = this.headerPosition.x;
- let targetY = this.headerPosition.y;
-
- switch (edge) {
- case 'top': targetY = workAreaY - currentBounds.height - 20; break;
- case 'bottom': targetY = workAreaY + screenHeight + 20; break;
- case 'left': targetX = workAreaX - currentBounds.width - 20; break;
- case 'right': targetX = workAreaX + screenWidth + 20; break;
+
+ const { x, y } = header.getBounds();
+ this.lastVisiblePosition = { x, y };
+ this.hiddenPosition = { edge };
+
+ if (instant) {
+ header.hide();
+ if (typeof callback === 'function') callback();
+ return;
}
-
- this.hiddenPosition = { x: targetX, y: targetY, edge };
- this.isAnimating = true;
- const startX = this.headerPosition.x;
- const startY = this.headerPosition.y;
- const duration = 400;
- const startTime = Date.now();
-
- const animate = () => {
- if (!this._isWindowValid(header)) return;
- const elapsed = Date.now() - startTime;
- const progress = Math.min(elapsed / duration, 1);
- const eased = progress * progress * progress;
- const currentX = startX + (targetX - startX) * eased;
- const currentY = startY + (targetY - startY) * eased;
-
- if (!Number.isFinite(currentX) || !Number.isFinite(currentY)) {
- this.isAnimating = false;
- return;
- }
-
- if (!this._isWindowValid(header)) return;
- header.setPosition(Math.round(currentX), Math.round(currentY));
-
- if (progress < 1) {
- this.animationFrameId = setTimeout(animate, 8);
- } else {
- this.animationFrameId = null;
- this.headerPosition = { x: targetX, y: targetY };
- if (Number.isFinite(targetX) && Number.isFinite(targetY)) {
- if (!this._isWindowValid(header)) return;
- header.setPosition(Math.round(targetX), Math.round(targetY));
- }
- this.isAnimating = false;
- if (typeof callback === 'function') callback();
- }
- };
- animate();
+ header.webContents.send('window-hide-animation');
+
+ setTimeout(() => {
+ if (!header.isDestroyed()) header.hide();
+ if (typeof callback === 'function') callback();
+ }, 5);
}
-
+
showFromEdge(callback) {
const header = this.windowPool.get('header');
- if (
- !this._isWindowValid(header) || this.isAnimating ||
- !this.hiddenPosition || !this.lastVisiblePosition ||
- typeof this.hiddenPosition.x !== 'number' || typeof this.hiddenPosition.y !== 'number' ||
- typeof this.lastVisiblePosition.x !== 'number' || typeof this.lastVisiblePosition.y !== 'number'
- ) {
- console.error('[MovementManager] Invalid state for showFromEdge. Aborting.');
- this.isAnimating = false;
- this.hiddenPosition = null;
- this.lastVisiblePosition = null;
+ if (!header || header.isDestroyed()) {
+ if (typeof callback === 'function') callback();
return;
}
-
- if (!this._isWindowValid(header)) return;
- header.setPosition(this.hiddenPosition.x, this.hiddenPosition.y);
-
- this.headerPosition = { x: this.hiddenPosition.x, y: this.hiddenPosition.y };
- const targetX = this.lastVisiblePosition.x;
- const targetY = this.lastVisiblePosition.y;
- this.isAnimating = true;
- const startX = this.headerPosition.x;
- const startY = this.headerPosition.y;
- const duration = 500;
- const startTime = Date.now();
-
- const animate = () => {
- if (!this._isWindowValid(header)) return;
-
- const elapsed = Date.now() - startTime;
- const progress = Math.min(elapsed / duration, 1);
- const c1 = 1.70158;
- const c3 = c1 + 1;
- const eased = 1 + c3 * Math.pow(progress - 1, 3) + c1 * Math.pow(progress - 1, 2);
- const currentX = startX + (targetX - startX) * eased;
- const currentY = startY + (targetY - startY) * eased;
- if (!Number.isFinite(currentX) || !Number.isFinite(currentY)) {
- this.isAnimating = false;
- return;
- }
-
- if (!this._isWindowValid(header)) return;
- header.setPosition(Math.round(currentX), Math.round(currentY));
-
- if (progress < 1) {
- this.animationFrameId = setTimeout(animate, 8);
- } else {
- this.animationFrameId = null;
- this.headerPosition = { x: targetX, y: targetY };
- if (Number.isFinite(targetX) && Number.isFinite(targetY)) {
- if (!this._isWindowValid(header)) return;
- header.setPosition(Math.round(targetX), Math.round(targetY));
- }
- this.isAnimating = false;
- this.hiddenPosition = null;
- this.lastVisiblePosition = null;
- if (callback) callback();
- }
- };
- animate();
+
+ // 숨기기 전에 기억해둔 위치 복구
+ if (this.lastVisiblePosition) {
+ header.setPosition(
+ this.lastVisiblePosition.x,
+ this.lastVisiblePosition.y,
+ false // animate: false
+ );
+ }
+
+ header.show();
+ header.webContents.send('window-show-animation');
+
+ // 내부 상태 초기화
+ this.hiddenPosition = null;
+ this.lastVisiblePosition = null;
+
+ if (typeof callback === 'function') callback();
}
moveStep(direction) {
diff --git a/src/electron/windowManager.js b/src/electron/windowManager.js
index 9d74334..6c74a0f 100644
--- a/src/electron/windowManager.js
+++ b/src/electron/windowManager.js
@@ -236,12 +236,13 @@ function toggleAllWindowsVisibility(movementManager) {
if (win.isVisible()) {
lastVisibleWindows.add(name);
if (name !== 'header') {
- win.webContents.send('window-hide-animation');
- setTimeout(() => {
- if (!win.isDestroyed()) {
- win.hide();
- }
- }, 200);
+ // win.webContents.send('window-hide-animation');
+ // setTimeout(() => {
+ // if (!win.isDestroyed()) {
+ // win.hide();
+ // }
+ // }, 200);
+ win.hide();
}
}
});
@@ -251,7 +252,7 @@ function toggleAllWindowsVisibility(movementManager) {
movementManager.hideToEdge(nearestEdge, () => {
header.hide();
console.log('[Visibility] Smart hide completed');
- });
+ }, { instant: true });
} else {
console.log('[Visibility] Smart showing from hidden position');
console.log('[Visibility] Restoring windows:', Array.from(lastVisibleWindows));
@@ -372,7 +373,7 @@ function createWindows() {
// loadAndRegisterShortcuts();
// });
- ipcMain.handle('toggle-all-windows-visibility', toggleAllWindowsVisibility);
+ ipcMain.handle('toggle-all-windows-visibility', () => toggleAllWindowsVisibility(movementManager));
ipcMain.handle('toggle-feature', async (event, featureName) => {
if (!windowPool.get(featureName) && currentHeaderState === 'main') {