|
|
@@ -11,7 +11,9 @@ Singleton {
|
|
|
|
property int floatingWindowPosition: Number.MAX_SAFE_INTEGER
|
|
|
|
property int floatingWindowPosition: Number.MAX_SAFE_INTEGER
|
|
|
|
property ListModel workspaces
|
|
|
|
property ListModel workspaces
|
|
|
|
property var windows: []
|
|
|
|
property var windows: []
|
|
|
|
property bool hasFocusedWindow: focusedWindowIndex >= 0 && focusedWindowIndex < windows.length
|
|
|
|
property var windowIndexCache: ({
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
property bool hasFocusedWindow: focusedWindowIndex >= 0
|
|
|
|
property int focusedWindowIndex: -1
|
|
|
|
property int focusedWindowIndex: -1
|
|
|
|
property string focusedWindowAppId: hasFocusedWindow ? windows[focusedWindowIndex].appId : ""
|
|
|
|
property string focusedWindowAppId: hasFocusedWindow ? windows[focusedWindowIndex].appId : ""
|
|
|
|
property string focusedWindowTitle: hasFocusedWindow ? windows[focusedWindowIndex].title : ""
|
|
|
|
property string focusedWindowTitle: hasFocusedWindow ? windows[focusedWindowIndex].title : ""
|
|
|
@@ -215,30 +217,56 @@ Singleton {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _rebuildWindowIndexCache() {
|
|
|
|
|
|
|
|
const cache = {
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
for (var i = 0; i < windows.length; i++) {
|
|
|
|
|
|
|
|
cache[windows[i].id] = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
windowIndexCache = cache;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _syncFocusedWindowIndex(preferredWindowId) {
|
|
|
|
|
|
|
|
var nextIndex = -1;
|
|
|
|
|
|
|
|
if (preferredWindowId !== undefined && preferredWindowId !== null) {
|
|
|
|
|
|
|
|
const cachedIndex = windowIndexCache[preferredWindowId];
|
|
|
|
|
|
|
|
if (cachedIndex !== undefined)
|
|
|
|
|
|
|
|
nextIndex = cachedIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nextIndex < 0 && focusedWindowIndex >= 0 && focusedWindowIndex < windows.length && windows[focusedWindowIndex].isFocused)
|
|
|
|
|
|
|
|
nextIndex = focusedWindowIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nextIndex < 0)
|
|
|
|
|
|
|
|
nextIndex = windows.findIndex((w) => {
|
|
|
|
|
|
|
|
return w.isFocused;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const hasChanged = nextIndex !== focusedWindowIndex;
|
|
|
|
|
|
|
|
focusedWindowIndex = nextIndex;
|
|
|
|
|
|
|
|
return hasChanged;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function recollectWindows(windowsData) {
|
|
|
|
function recollectWindows(windowsData) {
|
|
|
|
const windowsList = [];
|
|
|
|
const windowsList = [];
|
|
|
|
for (const win of windowsData) {
|
|
|
|
for (const win of windowsData) {
|
|
|
|
windowsList.push(getWindowData(win));
|
|
|
|
windowsList.push(getWindowData(win));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
windows = toSortedWindowList(windowsList);
|
|
|
|
windows = toSortedWindowList(windowsList);
|
|
|
|
|
|
|
|
_rebuildWindowIndexCache();
|
|
|
|
|
|
|
|
const focusedChanged = _syncFocusedWindowIndex();
|
|
|
|
windowListChanged();
|
|
|
|
windowListChanged();
|
|
|
|
// Find focused window index in the SORTED windows array
|
|
|
|
if (focusedChanged)
|
|
|
|
focusedWindowIndex = -1;
|
|
|
|
activeWindowChanged();
|
|
|
|
for (var i = 0; i < windows.length; i++) {
|
|
|
|
|
|
|
|
if (windows[i].isFocused) {
|
|
|
|
|
|
|
|
focusedWindowIndex = i;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function _handleWindowOpenedOrChanged(eventData) {
|
|
|
|
function _handleWindowOpenedOrChanged(eventData) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const windowData = eventData.window;
|
|
|
|
const windowData = eventData.window;
|
|
|
|
const existingIndex = windows.findIndex((w) => {
|
|
|
|
const cachedIndex = windowIndexCache[windowData.id];
|
|
|
|
return w.id === windowData.id;
|
|
|
|
const existingIndex = cachedIndex !== undefined ? cachedIndex : -1;
|
|
|
|
});
|
|
|
|
|
|
|
|
const newWindow = getWindowData(windowData);
|
|
|
|
const newWindow = getWindowData(windowData);
|
|
|
|
// Find the previously focused window ID before any modifications
|
|
|
|
// Find the previously focused window ID before any modifications
|
|
|
|
const previouslyFocusedId = focusedWindowIndex >= 0 && focusedWindowIndex < windows.length ? windows[focusedWindowIndex].id : null;
|
|
|
|
const previouslyFocusedId = focusedWindowIndex >= 0 && focusedWindowIndex < windows.length ? windows[focusedWindowIndex].id : null;
|
|
|
@@ -247,20 +275,20 @@ Singleton {
|
|
|
|
else
|
|
|
|
else
|
|
|
|
windows.push(newWindow);
|
|
|
|
windows.push(newWindow);
|
|
|
|
windows = toSortedWindowList(windows);
|
|
|
|
windows = toSortedWindowList(windows);
|
|
|
|
|
|
|
|
_rebuildWindowIndexCache();
|
|
|
|
|
|
|
|
const focusedChanged = _syncFocusedWindowIndex(newWindow.isFocused ? windowData.id : null);
|
|
|
|
if (newWindow.isFocused) {
|
|
|
|
if (newWindow.isFocused) {
|
|
|
|
focusedWindowIndex = windows.findIndex((w) => {
|
|
|
|
|
|
|
|
return w.id === windowData.id;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
// Clear focus on the previously focused window by ID (not index, since list was re-sorted)
|
|
|
|
// Clear focus on the previously focused window by ID (not index, since list was re-sorted)
|
|
|
|
if (previouslyFocusedId !== null && previouslyFocusedId !== windowData.id) {
|
|
|
|
if (previouslyFocusedId !== null && previouslyFocusedId !== windowData.id) {
|
|
|
|
const oldFocusedWindow = windows.find((w) => {
|
|
|
|
const oldFocusedIndex = windowIndexCache[previouslyFocusedId];
|
|
|
|
return w.id === previouslyFocusedId;
|
|
|
|
const oldFocusedWindow = oldFocusedIndex !== undefined ? windows[oldFocusedIndex] : null;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (oldFocusedWindow)
|
|
|
|
if (oldFocusedWindow)
|
|
|
|
oldFocusedWindow.isFocused = false;
|
|
|
|
oldFocusedWindow.isFocused = false;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
activeWindowChanged();
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
} else if (focusedChanged) {
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
windowListChanged();
|
|
|
|
windowListChanged();
|
|
|
|
workspaceUpdateTimer.restart();
|
|
|
|
workspaceUpdateTimer.restart();
|
|
|
@@ -272,17 +300,15 @@ Singleton {
|
|
|
|
function _handleWindowClosed(eventData) {
|
|
|
|
function _handleWindowClosed(eventData) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const windowId = eventData.id;
|
|
|
|
const windowId = eventData.id;
|
|
|
|
const windowIndex = windows.findIndex((w) => {
|
|
|
|
const cachedIndex = windowIndexCache[windowId];
|
|
|
|
return w.id === windowId;
|
|
|
|
const windowIndex = cachedIndex !== undefined ? cachedIndex : -1;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (windowIndex >= 0) {
|
|
|
|
if (windowIndex >= 0) {
|
|
|
|
if (windowIndex === focusedWindowIndex) {
|
|
|
|
const wasFocused = windows[windowIndex].isFocused;
|
|
|
|
focusedWindowIndex = -1;
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
} else if (focusedWindowIndex > windowIndex) {
|
|
|
|
|
|
|
|
focusedWindowIndex--;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
windows.splice(windowIndex, 1);
|
|
|
|
windows.splice(windowIndex, 1);
|
|
|
|
|
|
|
|
_rebuildWindowIndexCache();
|
|
|
|
|
|
|
|
if (_syncFocusedWindowIndex() || wasFocused)
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
|
|
|
|
windowListChanged();
|
|
|
|
windowListChanged();
|
|
|
|
workspaceUpdateTimer.restart();
|
|
|
|
workspaceUpdateTimer.restart();
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -303,21 +329,20 @@ Singleton {
|
|
|
|
function _handleWindowFocusChanged(eventData) {
|
|
|
|
function _handleWindowFocusChanged(eventData) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const focusedId = eventData.id;
|
|
|
|
const focusedId = eventData.id;
|
|
|
|
if (windows[focusedWindowIndex])
|
|
|
|
const previousFocusedId = focusedWindowIndex >= 0 && focusedWindowIndex < windows.length ? windows[focusedWindowIndex].id : null;
|
|
|
|
|
|
|
|
if (focusedWindowIndex >= 0 && focusedWindowIndex < windows.length)
|
|
|
|
windows[focusedWindowIndex].isFocused = false;
|
|
|
|
windows[focusedWindowIndex].isFocused = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (focusedId) {
|
|
|
|
if (focusedId) {
|
|
|
|
const newIndex = windows.findIndex((w) => {
|
|
|
|
const cachedIndex = windowIndexCache[focusedId];
|
|
|
|
return w.id === focusedId;
|
|
|
|
const newIndex = cachedIndex !== undefined ? cachedIndex : -1;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (newIndex >= 0 && newIndex < windows.length)
|
|
|
|
if (newIndex >= 0 && newIndex < windows.length)
|
|
|
|
windows[newIndex].isFocused = true;
|
|
|
|
windows[newIndex].isFocused = true;
|
|
|
|
|
|
|
|
|
|
|
|
focusedWindowIndex = newIndex >= 0 ? newIndex : -1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
focusedWindowIndex = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
activeWindowChanged();
|
|
|
|
if (_syncFocusedWindowIndex(focusedId) || previousFocusedId !== focusedId)
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
Logger.e("NiriService", "Error handling WindowFocusChanged:", e);
|
|
|
|
Logger.e("NiriService", "Error handling WindowFocusChanged:", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -325,17 +350,27 @@ Singleton {
|
|
|
|
|
|
|
|
|
|
|
|
function _handleWindowLayoutsChanged(eventData) {
|
|
|
|
function _handleWindowLayoutsChanged(eventData) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
|
|
|
|
const previousFocusedId = focusedWindowIndex >= 0 && focusedWindowIndex < windows.length ? windows[focusedWindowIndex].id : null;
|
|
|
|
|
|
|
|
var hasMatchedWindow = false;
|
|
|
|
for (const change of eventData.changes) {
|
|
|
|
for (const change of eventData.changes) {
|
|
|
|
const windowId = change[0];
|
|
|
|
const windowId = change[0];
|
|
|
|
const layout = change[1];
|
|
|
|
const layout = change[1];
|
|
|
|
const window = windows.find((w) => {
|
|
|
|
const windowIndex = windowIndexCache[windowId];
|
|
|
|
return w.id === windowId;
|
|
|
|
const window = windowIndex !== undefined ? windows[windowIndex] : null;
|
|
|
|
});
|
|
|
|
|
|
|
|
if (window)
|
|
|
|
if (window)
|
|
|
|
window.position = getWindowPosition(layout);
|
|
|
|
window.position = getWindowPosition(layout);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hasMatchedWindow = hasMatchedWindow || window !== null;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasMatchedWindow)
|
|
|
|
|
|
|
|
return ;
|
|
|
|
|
|
|
|
|
|
|
|
windows = toSortedWindowList(windows);
|
|
|
|
windows = toSortedWindowList(windows);
|
|
|
|
|
|
|
|
_rebuildWindowIndexCache();
|
|
|
|
|
|
|
|
if (_syncFocusedWindowIndex(previousFocusedId))
|
|
|
|
|
|
|
|
activeWindowChanged();
|
|
|
|
|
|
|
|
|
|
|
|
windowListChanged();
|
|
|
|
windowListChanged();
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
Logger.e("NiriService", "Error handling WindowLayoutChanged:", e);
|
|
|
|
Logger.e("NiriService", "Error handling WindowLayoutChanged:", e);
|
|
|
|