winemac.drv: add fullscreen mode support for Mac OS X 10.7+

Ken Thomases ken at codeweavers.com
Thu May 9 23:56:58 CDT 2013


Hi,

On May 9, 2013, at 5:48 PM, Kevin Eaves wrote:

> Attached patch is a proof-of-concept for the fullscreen APIs provided in OS X 10.7+, which allows applications to enter fullscreen in a separate desktop space.

Thanks for this.  It's quite interesting.

> The fullscreen button appears if a main window is resizable.

We may want to narrow this down a bit.  For example, the common file dialogs are resizable, but probably shouldn't be full-screen-enabled.  Perhaps no owned window should be.

> Basically this feature is the zoom button on crack.  It doesn't actually go fullscreen 'natively' but simply resizes the window fullscreen, and automatically moves it to its own space.  As far as Wine is concerned the window resized — just like clicking the zoom button and manually assigning the window to its own space.

Understood.

> I doubled the MaxTrackSize in user32/winpos.c, but it only  needs +15 for the height.

This is a gross hack that's going to have to be reworked if this is ever going to get accepted. :)

If I'm understanding correctly, user32 is restricting the window to a size that keeps its caption (title bar) within the desktop.  Without this hack, the window resizes to be slightly smaller than would actually fill the screen.  Is that right?

Maybe we could add a new driver entry point to have user32 offer the driver the opportunity to override the default MINMAXINFO values.


From cocoa_window.m.diff:

> +#import <Cocoa/Cocoa.h>


Was that actually needed?  cocoa_window.h already imports <AppKit/AppKit.h>.

On a related note, to enable this to compile against the 10.6 SDK, we should have something like:

#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
enum {
    NSFullScreenWindowMask = 0,
    NSWindowCollectionBehaviorFullScreenPrimary = 0,
    NSWindowFullScreenButton = 7,
};
#endif

>          if (self.disabled)
>              style &= ~NSResizableWindowMask;
> -        if (style != [self styleMask])
> +        if (style != [self styleMask] && !([self styleMask] & NSFullScreenWindowMask))
>              [self setStyleMask:style];

This is to avoid accidentally removing NSFullScreenWindowMask just because it's never in normalStyleMask, right?  I think a simpler solution is to just do:

        style |= [self styleMask] & NSFullScreenWindowMask;

In fact, we should probably make a mask of the style mask bits that are ever valid in normalStyleMask and only tweak those.  That would be more future proof.  So, something like:

enum {
    MACDRV_KNOWN_STYLES = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask | NSUtilityWindowMask | NSBorderlessWindowMask
};
…
        NSUInteger style = normalStyleMask | ([self styleMask] & ~MACDRV_KNOWN_STYLES);


This:

> +        if (style & NSResizableWindowMask)
> +            [[self standardWindowButton:NSWindowZoomButton] setEnabled:!self.disabled];


is to compensate for the fact that you might not call -setStyleMask:, above, right?  So it wouldn't be necessary after the change I suggested.  Furthermore, it isn't adequate.  You've disabled the zoom button but not the resize cursors all around the window border.

However, it does make me realize that we need to disable NSWindowFullScreenButton if the window is disabled.  Or is that what you meant to do here?  (We'd need to a protect against calling -standardWindowButton: with NSWindowFullScreenButton on OSes that don't support it.  It should suffice to test if [self respondsToSelector:@selector(toggleFullScreen:)].)


> -        if (captured || fullscreen)
> +        if (captured || (fullscreen && !(normalStyleMask & NSResizableWindowMask)))

You're trying to distinguish between a window that was full-screened at the instigation of the Windows program versus one which has been full-screened by Cocoa, right?  Hmm.  I think we need a better technique to determine that.  I agree that it's not likely the Windows program would make its window full-screen while still allowing it to be resized but it feels wrong to assume that.

Also, I think we can entirely avoid setting the window level for windows that have been Cocoa full-screened.  Setting the window level is mostly about relationship to other windows, but a Cocoa full-screen window should be on a space by itself, shouldn't it?

> +            else if ([self styleMask] & NSFullScreenWindowMask)
> +                level = NSMainMenuWindowLevel + 2;

I'm not following why Cocoa full-screened windows should be at +2 vs. +1.

Also, fair warning: I've got some in-progress changes that will overhaul the management of window levels.  I don't think it will be too hard to adapt your patch, but methods will be moving or going away.


> +            if (normalStyleMask & NSResizableWindowMask)
> +                behavior |= NSWindowCollectionBehaviorFullScreenPrimary;

This is in -setMacDrvState: but, since normalStyleMask is changed in -setWindowFeatures:, the collection behavior has to be updated there, too.


> +    - (NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
> +    {
> +        return NSMakeSize(proposedSize.width, proposedSize.height);
> +    }

Is this actually needed?  I assume that's the default behavior when the delegate method is absent.  (Also, if it is necessary, it can just return proposedSize without making a new size struct.)

In addition to this work, it would probably good to add an "Enter Full Screen" item in the Window menu.  We'd do so only if [NSWindow instancesRespondToSelector:@(toggleFullScreen:)] and the item would use that action and a target of nil (first responder).

Sorry to have nitpicked just about every hunk of the patch.  I realize you were just hacking and I appreciate your sharing this with us.

Thanks again,
Ken




More information about the wine-devel mailing list