diff --git a/multiscreen-compositor/qml/main.qml b/multiscreen-compositor/qml/main.qml index f31c2dcd68b25423c8840ba847845843f7431250..ff8836346217f719ba34d4f951776c5d33a793d3 100644 --- a/multiscreen-compositor/qml/main.qml +++ b/multiscreen-compositor/qml/main.qml @@ -109,8 +109,7 @@ WaylandCompositor { IviApplication { onIviSurfaceCreated: handleIviSurfaceCreated(iviSurface) - //onIviSurfaceRequested: handleIviSurfaceRequested(surface, iviId, resource) - onIviSurfaceRequested: console.log("IVI surface requested: surface", surface, "iviId", iviId, "resource", resource); + //onIviSurfaceRequested: console.log("IVI surface requested: surface", surface, "iviId", iviId, "resource", resource); } // ============================================= @@ -124,7 +123,13 @@ WaylandCompositor { } onSurfaceRequested: { - console.log("Surface requested: client", client, "id", id, "version", version, "pid", client.processId); + console.log("Surface requested: client", client, "id", id, "version", version, "pid", client.processId); + /* + var surface = WaylandSurface; + surface.initialize(this, client, id, version); + console.log("created surface:", surface); + return surface; + */ } function createShellSurfaceItem(shellSurface, moveItem, output) { @@ -146,6 +151,8 @@ WaylandCompositor { } function handleShellSurfaceCreated(shellSurface) { + console.log("shell surface created:", shellSurface); + var moveItem = moveItemComponent.createObject(rootItem, { "x": screens.objectAt(0).position.x, "y": screens.objectAt(0).position.y, @@ -207,14 +214,15 @@ WaylandCompositor { // the initial screen by the iviId ranges // ============================================= function handleIviSurfaceCreated(iviSurface) { - // We select the screen by evaluating the iviId of the app, - // if more than one screen is present. - // If the unique ivi id is greater or equal 2000 we select screen 2 console.log("handleIviSurfaceCreated: surface", iviSurface, "id", iviSurface.iviId); - //cleanUpApplist(); - var item; + cleanUpApplist(); + var item = {}; var screenId = 0; + var newPid = false; if (screens.count > 1) { + // If there is at least one (frozen) surface with the same pid, + // we ignore the iviId and assign the new surface to the same + // screen as the parent surface(s). var parentScreenId = getParentScreenId(iviSurface.surface.client.processId); if (parentScreenId >= 0) { @@ -223,22 +231,132 @@ WaylandCompositor { } else { + // If there are no previous surfaces belonging to this pid, + // we evaluate the iviId and assign iviIds >= 2000 to the + // second screen. screenId = (iviSurface.iviId >= 2000) ? 1 : 0; + newPid = true; } } item = createIviSurfaceItem(iviSurface, screens.objectAt(screenId)); var pid = item.shellSurface.surface.client.processId; console.log("Created IVI surface: ", item, "id", iviSurface.iviId, "screen", screenId); - var activeSurface = ({ 'surface': item, 'screen': screenId, 'iviId': iviSurface.iviId, 'pid': pid }); - activeSurfaces.push(activeSurface); + + activeSurfaces.push({ 'surface': item, 'screen': screenId, 'iviId': iviSurface.iviId, 'pid': pid, 'master': newPid }); + //cleanOutFreezer(); } - function handleIviSurfaceRequested(surface, iviId, resource) + function pidIsAlive(pid) { - console.log("IVI surface requested: surface", surface, "iviId", iviId, "resource", resource); + var ret = false; + var i = 0; + var frozenPids = 0; + + for (i=0; i < frozenSurfaceIds.length; i++) + { + if (pid === frozenSurfaceIds[i].pid) + { + frozenPids++; + } + } + // If this pid has more than one iviId in the freezer, we assume it's alive. + if (frozenPids > 1) + { + console.log("more than one iviId found for pid:", pid); + ret = true; + } + + // If it has an active surface it is most certainly alive! + for (i=0; i < activeSurfaces.length; i++) + { + if (pid === activeSurfaces[i].surface.shellSurface.surface.client.processId) + { + console.log("active surface found for pid:", pid); + ret = true; + } + } + + // This is probably redundant. + /* + for (i=0; i < this.defaultOutput.surfaceArea.visibleChildren.length; i++) + { + if (pid === this.defaultOutput.surfaceArea.visibleChildren[i].shellSurface.surface.client.processId) + { + ret = true; + } + } + */ + return ret; } + //onActiveSurfacesChanged: cleanOutFreezer() + + function cleanOutFreezer() + { + var ids = []; + + for (var i=0; i < frozenSurfaceIds.length; i++) + { + var item = frozenSurfaceIds[i]; + var pidSeen = false; + var iviIdSeen = false; + var lowestIviId = item.iviId; + + + console.log("examining pid:", item.pid, "iviId", item.iviId); + for (var j=0; j < ids.length; j++) + { + if (ids[j].pid === item.pid) + { + pidSeen = true; + if (ids[j].iviId < lowestIviId) + lowestIviId = ids[j].iviId; + } + + if (ids[j].iviId === item.iviId) + { + iviIdSeen = true; + } + } + + /* + if ((pidSeen) && (iviIdSeen)) + { + // remove all entries that are completely identical to an already seen one + console.log("throwing out duplicate entry pid:", item.pid, "iviId", item.iviId); + frozenSurfaceIds = Array.from(frozenSurfaceIds).filter((e, idx) => idx !== i) + + } + + if ((pidSeen) && (item.iviId > lowestIviId)) + { + // remove all but the lowest iviId if the pid has any active surfaces. + console.log("throwing out active pid:", item.pid, "iviId", item.iviId); + frozenSurfaceIds = Array.from(frozenSurfaceIds).filter((e, idx) => idx !== i) + } + */ + + if (iviIdSeen) + { + for (var k=0; k < frozenSurfaceIds.length; k++) + { + // Also remove frozen Ids if there are no active surfaces for this pid. + // ^^ no more! + //if (!pidIsAlive(frozenSurfaceIds[k].pid)) + if (item.iviId === frozenSurfaceIds[k].iviId) + { + // Throw out the *first* entry with this iviId! + console.log("throwing out dead pid:", frozenSurfaceIds[k].pid, "iviId", frozenSurfaceIds[k].iviId); + frozenSurfaceIds = Array.from(frozenSurfaceIds).filter((e, idx) => idx !== k) + break; + } + } + } + + ids.push({ 'pid': item.pid, 'iviId': item.iviId}); + } + } function cleanUpApplist() { @@ -246,10 +364,22 @@ WaylandCompositor { var item = activeSurfaces[i]; if ((!item.surface.shellSurface) && (!item.surface.surface)) { - console.log("Removing lost surface from applist and saving screen assignment! iviId:", item.iviId, "pid:", item.pid, "screen:", item.screen) - var frozenId = { 'iviId': item.iviId, 'pid': item.pid, 'screen': item.screen }; - frozenSurfaceIds.push(frozenId); activeSurfaces = Array.from(activeSurfaces).filter((e, idx) => idx !== i) + + // If this is a master iviId, save everything but the surface object itself in the freezer! + if (item.master) + { + for (var k=0; k < frozenSurfaceIds.length; k++) + { + if (item.iviId === frozenSurfaceIds[k].iviId) + { + //console.log("throwing out dead pid:", frozenSurfaceIds[k].pid, "iviId", frozenSurfaceIds[k].iviId); + frozenSurfaceIds = Array.from(frozenSurfaceIds).filter((e, idx) => idx !== k) + } + } + frozenSurfaceIds.push({ 'iviId': item.iviId, 'pid': item.pid, 'screen': item.screen, 'master': item.master }); + } + console.log("Removed lost surface from applist and saving screen assignment! iviId:", item.iviId, "pid:", item.pid, "screen:", item.screen) } } } @@ -258,30 +388,30 @@ WaylandCompositor { // Remove destroyed surface from the suface list // ============================================= onSurfaceAboutToBeDestroyed: { + // + // ----------!!!! HEADS UP !!!!------------ + // + // There is some sort of race condition fuckery afoot here! + // + // Doing ANYTHING other than cleanUpApplist(), even this single + // line of logging, will lead to random segfaults when surfaces + // are destroyed. SO DON'T! + // + //console.log("surface about to be destroyed: ", surface); + // + // ----------!!!! HEADS UP !!!!------------ + // cleanUpApplist(); } - // ============================================= - // Returns the surface identified by the iviId - // ============================================= - function findSurfaceById(id) { - console.log("Lookung for surface with id", id); - for (var i=0; i < activeSurfaces.length; i++) { - var item = activeSurfaces[i]; - if ((item.surface.shellSurface) && ( id === item.surface.shellSurface.iviId)) { - console.log("found IVI Shell Surface", i, id, item.surface.shellSurface, item.surface.shellSurface.surface) - return item.surface; - } - else if ((item.surface.shellSurface) && ( id === item.surface.shellSurface.surface.client.processId)) { - //else if ((item.surface.surface) && ( id === item.surface.surface.client.processId)) { - console.log("found XDG Shell Surface", i, id, item.surface, "containing surface", item.surface.surface) - return item.surface; - } - } - console.log("Failed to find surface by id", id) - return; + onSurfaceCreated: { + console.log("surface created: ", surface); + } + // ============================================= + // Returns all active surfaces belonging to pid + // ============================================= function getActiveSurfaces(pid) { var retArray = []; @@ -296,6 +426,9 @@ WaylandCompositor { return retArray; } + // ============================================= + // Returns process id belonging to a given iviId + // ============================================= function getPidFromIviId(iviId) { var pid = -1; @@ -318,6 +451,9 @@ WaylandCompositor { return pid; } + // ==================================================== + // Updates the pid/screen assignment in internal lists. + // ==================================================== function updateScreenAssignment(pid, screen) { console.log("Updating screen for pid", pid); @@ -363,21 +499,6 @@ WaylandCompositor { surface.parent = screens.objectAt(screenid).surfaceArea; updateScreenAssignment(getPidFromIviId(windowid), screenid); } - - /* - var surface = findSurfaceById(windowid) - if( !surface ) return; - - console.log("Move", surface, "to screen", screenid) - if (surface.shellSurface.iviId) - surface.parent = screens.objectAt(screenid).surfaceArea; - else - { - surface.visible = (active_screen === screenid) ? true : false; - } - - updateScreenAssignment(surface, screenid); - */ } function windowVisibility(windowid, show){ @@ -391,23 +512,6 @@ WaylandCompositor { console.log("Set visible to", show,"for", surface) surface.visible = show } - /* - var surface = findSurfaceById(windowid) - if( !surface ) return; - - if (surface.shellSurface){ - console.log("Set visible to", show,"for", surface) - surface.visible = show - } - else if (surface.surface){ - console.log("Set visible to", show,"for", surface.toplevel) - if (show) - surface.toplevel.sendFullscreen(surface.surface.size); - else - surface.toplevel.sendFullscreen(surface.surface.size); - surface.toplevel.setMinimized(); - } - */ } function onHideWindow(windowid){ @@ -419,21 +523,28 @@ WaylandCompositor { console.log("Received a showWindow Signal", windowid) windowVisibility(windowid, true) } + function onLogWindows(){ - //cleanUpApplist(); + var item = {}; + var i = 0; console.log("Active surfaces:") - for (var i=0; i < activeSurfaces.length; i++) { - var item = activeSurfaces[i]; + for (i=0; i < activeSurfaces.length; i++) { + item = activeSurfaces[i]; if (item.surface.shellSurface.iviId) { - console.log("- Surface", i, "iviId:", item.surface.shellSurface.iviId, item.surface, "on screen", item.screen); + console.log(" - Surface", i, "pid:", item.pid, "iviId:", item.surface.shellSurface.iviId, item.surface, "on screen", item.screen); } else if (item.shellSurface) { - console.log("- Surface", i, item.shellSurface, "pid", item.surface.surface.client.processId, "on screen", item.screen); + console.log(" - Surface", i, item.shellSurface, "pid", item.surface.surface.client.processId, "on screen", item.screen); } } + console.log("Frozen surface IDs:") + for (i=0; i < frozenSurfaceIds.length; i++) { + item = frozenSurfaceIds[i]; + console.log(" - Surface", i, "pid:", item.pid, "iviId:", item.iviId, "on screen", item.screen); + } } + function onGetScreen(windowid){ - //cleanUpApplist(); console.log("Received a getScreen Signal for window ID: ", windowid) var item = {}; var i = 0; @@ -457,22 +568,6 @@ WaylandCompositor { console.log("found frozen surface with iviId", windowid, "pid", pid, "on screen", screenId); } } - /* - for (var i=0; i < activeSurfaces.length; i++) { - var item = activeSurfaces[i]; - if (item.surface) { - if ((item.surface.surface) && ( windowid === item.surface.surface.client.processId)) { - console.log("Surface", i, item.surface, "pid", item.surface.surface.client.processId, "on screen", item.screen) - screenId = item.screen; - } - else if ((item.surface.shellSurface) && ( windowid === item.surface.shellSurface.iviId)) { - console.log("- Surface", i, "iviId:", item.surface.shellSurface.iviId, item.surface, "on screen", item.screen) - screenId = item.screen; - } - } - - } - */ commands.screenInfoReceived(screenId) }