8

I'm writing an app that has a custom, transparent NSWindow created using a NSWindow subclass with the following:

- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag 
{
   self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];

   if (self)
   {
     [self setOpaque:NO];
     [self setBackgroundColor:[NSColor clearColor]];
   }

   return self;
}

- (BOOL)canBecomeKeyWindow
{
  return YES;
}

- (BOOL)canBecomeMainWindow
{
  return YES;
}

I have everything working perfectly, including dragging and resizing, except the window doesn't work with Spaces. I cannot move the window to another space by either holding the window while switching spaces via keyboard shortcut, or by dragging to the bottom/top/left/right of the window. Is there anyway to have a custom window behave exactly like a normal window with regards to Spaces?

Zach Waugh
  • 736
  • 1
  • 6
  • 9
  • I am facing the same problem... did you find an solution? maybe a private API? http://stackoverflow.com/questions/6250864/change-to-other-space-macosx-programmatically – nacho4d Jun 06 '11 at 14:18

3 Answers3

8

After a long time I found a solution to this annoying problem. Indeed [window setMovableByWindowBackground:YES]; conflicts with my own resizing methods, the window trembles, it looks awful!

But overriding mouse event methods like below solved the problem in my case :)

- (void)mouseMoved:(NSEvent *)event
{
    //set movableByWindowBackground to YES **ONLY** when the mouse is on the title bar
    NSPoint mouseLocation = [event locationInWindow];
    if (NSPointInRect(mouseLocation, [titleBar frame])){
        [self setMovableByWindowBackground:YES];
    }else{
        [self setMovableByWindowBackground:NO];
    }

    //This is a good place to set the appropriate cursor too
}

- (void)mouseDown:(NSEvent *)event
{
    //Just in case there was no mouse movement before the click AND
    //is inside the title bar frame then setMovableByWindowBackground:YES
    NSPoint mouseLocation = [event locationInWindow];
    if (NSPointInRect(mouseLocation, [titleBar frame])){
        [self setMovableByWindowBackground:YES];
    }else if (NSPointInRect(mouseLocation, bottomRightResizingCornerRect)){
        [self doBottomRightResize:event];
    }//... do all other resizings here. There are 6 more in OSX 10.7!
}

- (void)mouseUp:(NSEvent *)event
{
    //movableByBackground must be set to YES **ONLY**
    //when the mouse is inside the titlebar.
    //Disable it here :)
    [self setMovableByWindowBackground:NO];
}

All my resizing methods start in mouseDown:

- (void)doBottomRightResize:(NSEvent *)event {
    //This is a good place to push the appropriate cursor

    NSRect r = [self frame];
    while ([event type] != NSLeftMouseUp) {
        event = [self nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
        //do a little bit of maths and adjust rect r
        [self setFrame:r display:YES];
    }

    //This is a good place to pop the cursor :)

    //Dispatch unused NSLeftMouseUp event object
    if ([event type] == NSLeftMouseUp) {
        [self mouseUp:event];
    }
}

Now I have my Custom window and plays nice with Spaces :)

nacho4d
  • 43,720
  • 45
  • 157
  • 240
1

Two things here.

You need to set the window to allow dragging by background, [window setMovableByWindowBackground:YES];

And If your custom window areas you expect to be draggable are custom NSView subclasses, you must override the method - (BOOL)mouseDownCanMoveWindow to return YES in any NSView subclass that needs to be able to move the window by dragging.

uchuugaka
  • 12,679
  • 6
  • 37
  • 55
0

Did you override isMovable?
The Apple documentation says, that it changes Spaces behavior:

If a window returns NO, that means it can only be dragged between spaces in F8 mode, ...

Another method that might be related: NSWindow setCollectionBehavior

Thomas Zoechling
  • 34,177
  • 3
  • 81
  • 112
  • Unfortunately, isMovable has no effect, and setCollectionBehavior only allows me to force the app to appear on all spaces. I did find that by using setMovableByWindowBackground, everything works with regards to Spaces, but that interferes with my custom dragging and resizing code, which I don't want. So setMovableByWindowBackground must be doing something that enables the window to be moved between spaces. – Zach Waugh Nov 08 '09 at 05:07