Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a window pop in and out of the edge of the screen

I'm trying to re-write an application I have for Windows in Objective-C for my Mac, and I want to be able to do something like Mac's hot corners. If I move my mouse to the left side of the screen it will make a window visible, if I move it outside of the window location the window will hide again. (window would be pushed up to the left side of screen).

Does anyone know where I can find some demo code (or reference) on how to do this, or at least how to tell where the mouse is at, even if the current application is not on top. (not sure how to word this, too used to Windows world).

Thank you

-Brad

like image 667
Brad Avatar asked Jan 03 '10 08:01

Brad


People also ask

How do I move a window that is partially off screen?

Hold down the Shift key, then right-click on the appropriate application icon in the Windows taskbar. On the resulting pop-up, select the Move option. Begin pressing the arrow keys on your keyboard to move the invisible window from off-screen to on-screen.

How do I show a window that is off the screen?

Right-click the program on the taskbar, and then click Move. Move the mouse pointer to the middle of the screen. Use the ARROW keys on the keyboard to move the program window to a viewable area on the screen. Press ENTER.

Why do windows appear off screen?

This usually happens after you change screen resolution, or if you closed the application with the window in that position. In some cases, the window will open up completely off the screen; the only evidence that the application has launched will be its entry on the Taskbar.

How do I move a popup window?

You must place the cursor anywhere on the active window frame and press Enter. ISPF acknowledges the window move request by displaying WINDOW MOVE pending message. Then place the cursor where you want the upper left corner of the pop-up placed. press Enter a second time, and the pop-up is moved to the new location.


2 Answers

You're going to want to implement an invisible window on the edge of the screen with the window order set so it's always on top. Then, you can listen for mouse-moved events in this window.

To set the window to be invisible and on top, make a window subclass use calls like:

[self setBackgroundColor:[NSColor clearColor]];
[self setExcludedFromWindowsMenu:YES];
[self setCanHide:NO];
[self setLevel:NSScreenSaverWindowLevel];
[self setAlphaValue:0.0f];
[self setOpaque:NO];
[self orderFrontRegardless];

then, to turn on mouse moved events,

[self setAcceptsMouseMovedEvents:YES];

will cause the window to get calls to:

- (void)mouseMoved:(NSEvent *)theEvent
{
   NSLog(@"mouse moved into invisible window.");
}

So hopefully that's enough to give you a start.

-Ken

like image 96
Ken Aspeslagh Avatar answered Sep 21 '22 16:09

Ken Aspeslagh


Here's AutoHidingWindow - a subclass of SlidingWindow which pops up when the mouse hits the edge of the screen. Feedback welcome.

@interface ActivationWindow : NSWindow
{
    AutoHidingWindow *_activationDelegate;
    NSTrackingArea *_trackingArea;
}

- (ActivationWindow*)initWithDelegate:(AutoHidingWindow*)activationDelegate;

@property (assign) AutoHidingWindow *activationDelegate;
@property (retain) NSTrackingArea *trackingArea;

- (void)adjustWindowFrame;
- (void)adjustTrackingArea;

@end

@interface AutoHidingWindow ()

- (void)autoShow;
- (void)autoHide;

@end 


@implementation AutoHidingWindow

- (id)initWithContentRect:(NSRect) contentRect 
                styleMask:(unsigned int) styleMask 
                  backing:(NSBackingStoreType) backingType 
                    defer:(BOOL) flag
{

    if ((self = [super initWithContentRect:contentRect
                                 styleMask:NSBorderlessWindowMask 
                                   backing:backingType
                                     defer:flag])) {
        _activationWindow = [[ActivationWindow alloc] initWithDelegate:self];
    }

    return self;
}

@synthesize activationWindow = _activationWindow;

- (void)dealloc
{
    [_activationWindow release], _activationWindow = nil;

    [super dealloc];
}

- (void)makeKeyAndOrderFront:(id)sender
{
    [super makeKeyAndOrderFront:sender];

}

- (void)autoShow
{
    [self makeKeyAndOrderFront:self];

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(autoHide) object:nil];
    [self performSelector:@selector(autoHide) withObject:nil afterDelay:2];
}

- (void)autoHide
{
    NSPoint mouseLocation = [NSEvent mouseLocation];
    NSRect windowFrame = [self frame];

    if (NSPointInRect(mouseLocation, windowFrame)) {
        [self performSelector:@selector(autoHide) withObject:nil afterDelay:2];
    }
    else {
        [self orderOut:self];
    }
}

@end


@implementation ActivationWindow 

- (ActivationWindow*)initWithDelegate:(AutoHidingWindow*)activationDelegate
{   
    if ((self = [super initWithContentRect:[[NSScreen mainScreen] frame]
                                 styleMask:NSBorderlessWindowMask
                                   backing:NSBackingStoreBuffered
                                     defer:NO]) != nil) {
        _activationDelegate = activationDelegate;

        [self setBackgroundColor:[NSColor clearColor]];
        [self setExcludedFromWindowsMenu:YES];
        [self setCanHide:NO];
        [self setHasShadow:NO];
        [self setLevel:NSScreenSaverWindowLevel];
        [self setAlphaValue:0.0];
        [self setIgnoresMouseEvents:YES];
        [self setOpaque:NO];
        [self orderFrontRegardless];

        [self adjustWindowFrame];
        [self.activationDelegate addObserver:self
                                 forKeyPath:@"slidingEdge"
                                    options:0
                                    context:@"slidingEdge"];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(screenParametersChanged:) 
                                                     name:NSApplicationDidChangeScreenParametersNotification 
                                                   object:nil];     
    }

    return self;
}

@synthesize activationDelegate = _activationDelegate;
@synthesize trackingArea = _trackingArea;

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([@"slidingEdge" isEqual:context]) {
        [self adjustTrackingArea];
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}


- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

    [self.activationDelegate removeObserver:self forKeyPath:@"slidingEdge"];
    _activationDelegate = nil;

    [_trackingArea release], _trackingArea = nil;

    [super dealloc];
}

- (void)screenParametersChanged:(NSNotification *)notification
{
    [self adjustWindowFrame];
}

- (void)adjustWindowFrame
{
    NSScreen *mainScreen = [NSScreen mainScreen];
    CGFloat menuBarHeight = [NSMenuView menuBarHeight];
    NSRect windowFrame = [mainScreen frame];

    windowFrame.size.height -= menuBarHeight;

    [self setFrame:windowFrame display:NO];
    [self adjustTrackingArea];
}

- (void)adjustTrackingArea
{
    NSView *contentView = [self contentView];
    NSRect trackingRect = contentView.bounds;   
    CGRectEdge slidingEdge = self.activationDelegate.slidingEdge;
    CGFloat trackingRectSize = 2.0;

    switch (slidingEdge) {
        case CGRectMaxXEdge:
            trackingRect.origin.x = trackingRect.origin.x + trackingRect.size.width - trackingRectSize;
            trackingRect.size.width = trackingRectSize;
            break;

        case CGRectMaxYEdge:
            trackingRect.origin.y = trackingRect.origin.y + trackingRect.size.height - trackingRectSize;
            trackingRect.size.height = trackingRectSize;
            break;

        case CGRectMinXEdge:
            trackingRect.origin.x = 0;
            trackingRect.size.width = trackingRectSize;
            break;

        case CGRectMinYEdge:
        default:
            trackingRect.origin.y = 0;
            trackingRect.size.height = trackingRectSize;
    }


    NSTrackingAreaOptions options =
    NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
    NSTrackingActiveAlways |
    NSTrackingEnabledDuringMouseDrag;

    NSTrackingArea *trackingArea = self.trackingArea;

    if (trackingArea != nil) {
        [contentView removeTrackingArea:trackingArea];
    }

    trackingArea = [[NSTrackingArea alloc] initWithRect:trackingRect
                                                options:options
                                                  owner:self
                                               userInfo:nil];

    [contentView addTrackingArea:trackingArea];

    self.trackingArea = [trackingArea autorelease];
}

- (void)mouseEntered:(NSEvent *)theEvent
{
    [self.activationDelegate autoShow];
}


- (void)mouseMoved:(NSEvent *)theEvent
{
    [self.activationDelegate autoShow];
}

- (void)mouseExited:(NSEvent *)theEvent
{
}

@end
like image 35
Pierre Bernard Avatar answered Sep 19 '22 16:09

Pierre Bernard