Closed Bug 440895 Opened 15 years ago Closed 3 years ago

Session Restore does not take Spaces into account


(Firefox :: Session Restore, defect, P2)




Firefox 75
75.2 - Feb 24 - Mar 8
Tracking Status
firefox75 --- verified


(Reporter: mardmol, Assigned: mikedeboer)


(Blocks 3 open bugs, Regressed 1 open bug)



(1 file, 2 obsolete files)

User-Agent:       Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9) Gecko/2008061004 Firefox 3.0a4
Build Identifier: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9) Gecko/2008061004 Firefox 3.0a4

When restoring a session all Firefox windows are put into the currently active Space and not into the Spaces they were in.

Reproducible: Always

Steps to Reproduce:
1.Open several Firefox windows
2.Put them into different Spaces
3.Restart Firefox
Actual Results:  
All windows are in one Space

Expected Results:  
Windows are in the Spaces they were put into
See also bug 372650 for the same request on Linux.
Ever confirmed: true
Blocks: 450886
Depends on: 450953
Version: unspecified → Trunk
hmm, I didn't see at first that this bug was opened for Mac. So I made bug 372650 cross platform and opened a new bug for the Cocoa implementation. Sorry for all the noise.

What about making bug 372650 the cross platform implementation and bug 450953 depend on it?

Basically, bug 372650 would have the widget/public/* and widget/src/xpwidgets/* part. bug 450952 the widget/src/gtk2/* part and finally bug 450953 the widget/src/cocoa/* part.
It looks like there's no public API that makes this possible:

"No, there is no API to put a window on a particular space."

There seem to be undocumented ways to do it, though it's probably not the best idea to use them:
(In reply to Jez Ng [:int3] from comment #5)
> "No, there is no API to put a window on a particular space."

This may have changed by now (and broken again?), see and following.
Blocks: 372650
Hardware: PowerPC → All
See Also: → 461285
This is so very annoying, and frankly, makes me delay updating.

As an update, I trolled through the whole Chrome bug report history.  Some notables:

- In Aug 2015, they got a reply from Apple. Applications are not supposed to be able to re-open themselves on (correct/different) spaces. It's by design. However, windows should restore themselves to the correct location after a reboot. IF they don't, it's a bug in the application because it doesn't properly us NSDocument, encodeRestorableStateWithCoder, and restoreStateWithCoder

- In Apr 2017, people noticed that iTerm somehow figured out how to preserve the space configuration across reboots. (That's interesting, but it's not the bug; this bug is about session restore and browser restart absent a reboot, I think.)

- There's some mac documentation about that too:

- There is apparently an undocumented API for moving a window to a space: CGSSpaceAddWindowsAndRemoveFromSpaces ; which would help for Session Restore. 

- There is also the (older, slightly more documented) private method CGSMoveWorkspaceWindowList

- A former Apple graphics engineer said:

> There is a high probability that future macOS releases will rename WindowServer's SPI calls for managing a window's space (the CGS* methods). (This is armchair advice from a former CoreGraphics engineer: I was on the team while we were building Mission Control.)

So, long story short, we have two options:

1: Do nothing, wait for Apple to give us the APIs.

2: Do runtime version detection of the OS, and if it's a version we know this works with, enable the feature.  Maybe also require a non-default flag to be flipped.

I don't really know who to ask if we would accept a patch to do #2. I guess I'll start with Tim, and hopefully he can redirect?
Flags: needinfo?(ttaubert)
Redirecting to Mike, he's taken over the Session Restore feature.
Flags: needinfo?(ttaubert) → needinfo?(mdeboer)
I'm thinking that might something we can use here, if runtime detection is an option.

I'd prefer getting a `workspaceID` getter and a `moveToWorkspace(workspaceID)` on nsPIDOMWindow as a more generic interface for *Nix support in the future and implement it by proxying calls to for starters.

Relevant code snippet from the post I linked to:

// Grab workspace identifier:
NSObject* workspace_identifier = [self.window performSelector:@selector(_copyWorkspaceIdentifier)]

// Move a window to a workspace
NSObject* contextID = [NSApp performSelector:@selector(contextID)];
int realwindownumber = [self.window performSelector:@selector(_realWindowNumber)];
NSObject* windowID = @[@(realwindownumber)];
int spacename = CGSSpaceWithName(contextID, workspace_identifier);
CGSSpaceAddWindowsAndRemoveFromSpaces(contextID, spacename, windowID, 0x80007);

Is `respondsToSelector` applicable here to check if `CGSSpaceAddWindowsAndRemoveFromSpaces` is available?
Flags: needinfo?(mdeboer) → needinfo?(mstange)
No it's not, but you can use dlsym to look up the function dynamically, similar to what we do for CGContextSetFontSmoothingBackgroundColor:
Flags: needinfo?(mstange)
Attached patch Patch using Cocoa private APIs (obsolete) — Splinter Review
This is what I managed to get to within a reasonable timeframe:

 * Add a `getWorkspaceID()` and `moveToWorkspace(workspaceID)` to the [[Window]] object, so that privileged, chrome-only scripts can do something useful.
 * Implemented the OSX Space ID retrieval is it is supposed to work, using undocumented, private APIs.
 * Set up Sessionstore to be able to work with this architecture once each widget implementation (cocoa, win, gtk, etc) gains support for it.

These private APIs were also used by iTerm2 and Chrome some time ago, but were removed because they _apparently_ stopped working. It's not documented anywhere _why_ and _how_ they stopped working, so for posterity I'll note it here.

Today, running OSX 10.13.x:
 * invoking `CGSGetWindowWorkspace()` for a window on the default Space (Desktop 1 once you added another Space), will return '1'. As expected.
 * invoking `CGSGetWindowWorkspace()` for a window on any other Space than the default one (Desktop X, where x is not '1'), will return '0'. In other words: totally useless, garbage.
 * invoking `CGSMoveWorkspaceWindowList()` and passing in '2' (interpolated ID) as the Space number, does not move a window to that Space (i.e. 'Desktop 2'). Also utterly useless.
 * invoking `CGSMoveWorkspaceWindowList()` and passing in '1' as the Space number, does not move a window to that Space (i.e. 'Desktop 1'). The window to move resides in another space, like 'Desktop 3'.

The - private, granted - APIs are there and can be invoked but do not work as expected. And I doubt they will in the near future.

This will make it very _very_ unlikely that Firefox will have support for multiple Spaces some day, because Apple will need to create and ship an API that is
a) public,
b) future-proof (i.e. won't break between releases).

To be clear: I could live with using a private APIs like I tried to do in this patch, but they need to work. If Apple can distribute a fixed-up CoreGraphics bundle update, I'd be over the moon.
Not only Firefox would benefit here; Chrome, iTerm2 and many other productivity apps - that coincidentally will never fit in the App Store model - will too, accounting for a reach of millions of users worldwide.

I'd love to get in touch with an Apple spokesperson to explain more and/ or request a feature in more detail!
Attached patch Patch using Cocoa private APIs (obsolete) — Splinter Review
Attachment #8945226 - Attachment is obsolete: true
Blocks: ss-feature
See Also: → 372650

Chrome appears to have recently merged an attempt at this as of 2019-10. It appears to function via the encodeRestorableStateWithCoder / restoreStateWithCoder APIs that Apple recommended to the Chrome team in 2015.

Thanks for spotting that, Ryan! Perhaps Harry may have a cycle or two available to take a look at this as a short intermezzo between other things?

Flags: needinfo?(htwyford)

Unfortunately I didn't get to this over the holidays. I'll stay subscribed to this bug and might return to it in the future when I have free cycles.

I did take a bit of time to investigate Chrome's implementation. While it may have been my testing methodology, I found it didn't work well. It could remember the positions of windows across up to two Spaces on any number of monitors, but adding a third Space to any of the monitors complicated things. The windows from the 3rd+ Spaces usually ended up on the first Space, although (iirc) they also sometimes ended up on the second Space. At least once all the windows (including those from the second Space) ended up on the first Space. I didn't get time to tell if this is an issue with the Cocoa API or Chrome's implementation of it, but I suspect this wouldn't be a straight port of Chrome's implementation if we want to get this working correctly.

Flags: needinfo?(htwyford)
Assignee: nobody → mdeboer
Iteration: --- → 74.2 - Jan 20 - Feb 09
Points: --- → 5
Priority: -- → P2
Attachment #8945228 - Attachment is obsolete: true
Attachment #9124050 - Attachment description: Bug 440895 - Add support for Mac OSX spaces in session restore, which allows any window to be restored to their respective (work)space. r?mconley!,spohl! → Bug 440895 - Add support for Mac OSX spaces in session restore, which allows any window to be restored to their respective (work)space. r?mconley!,mstange!,nika!
See Also: → 1608743

Setting n-i for my question in Phab :)

Flags: needinfo?(mstange)
Pushed by
Add support for Mac OSX spaces in session restore, which allows any window to be restored to their respective (work)space. r=mconley,mstange,nika
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 75
Iteration: 74.2 - Jan 20 - Feb 09 → 75.2 - Feb 24 - Mar 8
Blocks: 1619515
Flags: needinfo?(mstange)
Flags: qe-verify+

I was able to reproduce this issue using an affected Nightly build e.g. 75.0a1 (2020-03-01).

The issue is verified as fixed on Beta 75 running macOS 10.14.

Flags: qe-verify+

I hate to complain after all the hard work done to fix this bug, but it'd be really nice to have a preference to go back to the previous behavior. I've grown quite used to it over the years, and I find the current behavior very annoying.

Alternatively, why not change the current behavior so that, if only a single window is being restored, it's restored to the current workspace (not to the one it was previously open on). This is how Apple's own apps behave (like Safari), and also how Chrome behaves.

This was working for me, and I love that this was fixed after so long! But it seems to have regressed for me when I upgraded from 76 to 77.0.1.

I've been following this issue for at least some 5 years and about a few months ago, I noticed it started working. Perfect! I was thrilled :)
But now, some weeks ago it stopped working again. Unlike @JT I didn't notice the version it was working on, nor the version in which it stopped working, but I always keep my FF updated. I work with 8! spaces on a daily basis and each has at least one FF window with a few tabs. Part of my daily routine is restoring my FF, which opens all windows on one space, and then dragging each window to its space. I've been doing this for years, but it was pretty cool when I didn't need to, for a short period of time.

So, is there a way to return to that working version? Even more important, why it stopped working? Was it apple or the FF team?

I'm currently on Catalina (10.15.5), but about 2 weeks ago I was on Mojave (10.14.4) and on both the error is the same.

Hope you guys can figure it out!

To clarify, I noticed that preservation of spaces works for me when I restart Firefox normally. However, it did not work when I updated again, this time from Firefox 77.0.1 to 78.0.1. I'm running on macOS 10.14.6 Mojave.

This bug is closed as resolved in Firefox 75. It was regressed by the fix in bug 1630732 in Firefox 77, if the Mission Control pref 'Displays have separate spaces' is enabled. I suggest bug 1642310 is used to fix that case.

Regressions: 1675724
See Also: → 1642310
You need to log in before you can comment on or make changes to this bug.