Skip to content

Fix #3857: Enter Full Screen exists under 2 different menu items #3891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 24, 2022

Conversation

svobs
Copy link
Contributor

@svobs svobs commented Jul 28, 2022


Description:
Since the "Enter Fullscreen" option already exists under the Video menu, this patch hides the instance under the Window menu, to conform with Apple HIG. Note:

  • This change has no effect on the built-in fn-F shortcut, which still works.
  • This is set as a preference value which MacOS recognizes, which means:
    • Although it's set when IINA starts, it will not take effect until the app is closed & reopened.
    • After being set, even old versions of IINA will hide the full-screen option in the Window menu (unless IINA's prefs are manually deleted or edited to remove this key)

@@ -201,6 +201,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

// Hide Window > "Enter Full Screen" menu item, becuase this is already present in the Video menu
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because

@@ -201,6 +201,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

// Hide Window > "Enter Full Screen" menu item, becuase this is already present in the Video menu
UserDefaults.standard.set(false, forKey: "NSFullScreenMenuItemEverywhere")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong place to set this. That is what is causing this:

Although it's set when IINA starts, it will not take effect until the app is closed & reopened.

The only Apple documentation on this seems to be AppKit Release Notes (macOS 10.12 and Earlier) which says:

AppKit automatically creates an "Enter Full Screen" menu item after the application finishes launching if an equivalent menu item isn't found. If this menu item should not be created for your app, before NSApplicationDidFinishLaunchingNotification is sent you may set the NSFullScreenMenuItemEverywhere default to NO.

This statement has been added to the method applicationDidFinishLaunching which is after the NSApplicationDidFinishLaunchingNotification notification. I tested moving this statement into the applicationWillFinishLaunching method right after the "App will launch" log is emitted. I used defaults to make sure that key was not set. The menu item was hidden on the first run. I did not have to restart IINA for it to take effect.

@saagarjha
Copy link
Member

I think the correct solution here should be to get AppKit to recognize our fullscreen menu item as the legitimate one, rather than using the user default to suppress the addition of the second one in the Window menu.

@svobs svobs force-pushed the pr-hide-redundant-fullscreen-menu-item branch from a31df3c to fd261eb Compare August 9, 2022 04:53
@svobs
Copy link
Contributor Author

svobs commented Aug 9, 2022

I've force-re-submitted an improved commit based on the above feedback, though honestly @low-batt should get full credit, since he did do more than 50% of the work for this one-liner.

I think the correct solution here should be to get AppKit to recognize our fullscreen menu item as the legitimate one, rather than using the user default to suppress the addition of the second one in the Window menu.

@saagarjha I did a deep-dive into this...

Of the affected open source projects I found, the majority seem to have settled on the above preference setting (Electron being the biggest name I found) but I did discover that the Chromium was able to trigger Apple's matching logic by changing the name of the menu item action to toggleFullScreen and is using that.

I was able to do the same in this branch, but there are still some problems. I was only able to trigger the override by hard-coding the action selector in the XIB file. But I still can't figure out how to create a selector for MainWindowController inside the XIB -- IINA is currently doing that in code after the app has started. Best I could do was to make the XIB call an action in MenuController, which in turn calls the action in MainWindowController. And everything works this way - except the "Enter Full Screen" menu item is never grayed out because it's using a MenuController selector instead of a MainWindowController selector, and I'm not ready to commit a lot more time to figure out how to make that work.

IMHO it seems like using a special selector name is not the most robust solution, especially because I haven't found any documentation from Apple to support it. At least the preference key is documented.

@low-batt
Copy link
Contributor

low-batt commented Aug 9, 2022

@svobs Full credit goes to you for providing the implementation. With Apple specifying a clear requirement on how the menus must be structured, but apparently no documentation on how to implement it, I thought this needed a detailed review.

Due to the feedback from @saagarjha I looked again for guidence from Apple on how to implement the HIG requirement of suppressing the menu item in the Window menu. Nothing useful.

One reason why developers fail to document things is because "it is obvious". So I tried a quick experiment. I first made sure to delete the preference:

defaults delete com.colliderli.iina NSFullScreenMenuItemEverywhere

The documentation for NSWindow.toggleFullScreen says:

If an application supports fullscreen, it should add a menu item to the View menu with toggleFullScreen: as the action, and nil as the target.

IINA's main menu does not contain a "Enter Full Screen" menu item. In a quick test I added that menu item to the Window menu and tied the action to toggleFullScreen in First Responder and checked Hidden. That quick test seemed to work. Busy today, so I only tested Monterey.

Given the only documentation for NSFullScreenMenuItemEverywhere is from that archived old AppKit release notes from 10.12, maybe adding a menu item as a solution should be further explored?

I followed this post in order to properly attach the action:
How to connect IBAction and menu item to First Responder?

If the menu item action is not attached to toggleFullScreen then AppKit does not recognize it as the standard Enter Full Screen menu item.

@saagarjha
Copy link
Member

My understanding is that using the toggleFullScreen: action is the correct way to do this, yes. Is it not being propagated correctly through the responder chain?

@low-batt
Copy link
Contributor

The responder chain is not being used. The full screen menu item under the Video menu is tied to MenuController which sets the action to MainWindowController.menuToggleFullScreen. That calls the method toggleWindowFullScreen which will either call NSWindow.toggleFullScreen or legacy full screen methods in MainWindowController.

The task at hand is to eliminate the full screen menu item under the Window menu. Right now IINA does not have such a menu item. AppKit is adding a disabled one. By adding a full screen menu item under the Window menu, using NSWindow.toggleFullScreen and marking that menu item as hidden we can eliminate the disabled Enter Full Screen as required by the HIG.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The Full-screen Option Exists As 2 Instances Under Different Menu Items.
5 participants