views:

73

answers:

1

I'm trying to make a server monitor in Objective-C, that behaves kind of like the dock on Mac OS X. I'm hoping to have it slide from the side of the screen when the mouse is moved to a side of the screen, kind of like a dock with auto hide on. I'm not sure where to start though.

I'm guessing I need to have a window with a NSBorderlessWindowMask mask, but after that I'm at a loss. Do I just have 1 pixel of that window showing, and wait for a mouseOver event, or is that just a hacky way for some thing that can be done reasonably? How would I check for a mouse over event if that's the best way to do it?

Sorry if this is a stupid question, but I don't know that much about Objective-C and I'm hoping this project will be a good learning experience.

Thanks,
Ryan Pendleton

+2  A: 

You have the right idea, I think. Keep in mind though that, depending on what you want to do, borderless windows are not the easiest thing to work with (they can be tricky, especially with the complexities that things like Spaces and Exposé may add).

If this is just a personal project, you could probably get away with a one pixel edge of the window showing. If this is a professional project, I would recommend looking into using Event Taps (more on that later).

If you go the "personal project" way, you could leave 1 px edge of the window showing, use a custom NSView subclass that would draw itself as transparent and set up an NSTrackingArea to inform you of mouseEntered: events.

To draw a transparent area, you could do something like this in drawRect:

- (void)drawRect:(NSRect)frame {
   [[NSColor clearColor] set];
   NSRectFill(frame);
}

To set up a tracking area, do this in the awakeFromNib in your view subclass:

- (void)awakeFromNib {
 NSTrackingArea *tracker = [[[NSTrackingArea alloc] initWithRect:[self frame]
   options:(NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways)
   owner:self
   userInfo:nil] autorelease];

 [self addTrackingArea:tracker];
}

- (void)mouseEntered:(NSEvent *)theEvent {
 [[[self window] windowController] showWindow:self];
}

- (void)mouseExited:(NSEvent *)theEvent {
 [[[self window] windowController] myHideMethodName:self];
}

This assumes you're overriding the window controller's showWindow: method to do an animation or whatever). By the way, whatever you do, DO NOT look for mouse moved events. (Not a big deal in your case, since your area will likely be very small, but in general, looking for mouse moved events is the wrong way to do it, as they can quickly flood the event queue. Use the tracking area feature in Quartz Debug to see how most software does it). Keep in mind that even though the view may draw itself transparent, it will still prevent your mouse events from going through to whatever is underneath it (could be another window or the Desktop, etc.).

If you want to go the "pro" route, you should be able to set up Event Taps to basically accomplish the same thing the tracking area code does. With this route, you can have the window completely hidden so it doesn't interfere with anything. To understand how Event Taps work, you might want to download the following 2 apps:

http://brockerhoff.net/quay/

http://pfiddlesoft.com/eventtapstestbench/

The first is a cool example of how you can use event taps to accomplish some cool stuff (read the Help to see some more advanced features). Rainer uses event taps to tap the Dock to figure out when you move your mouse overtop of the items in the left side of the Dock. He can then show his custom menus instead of the Dock's built-in menus.

The second app will be indispensable in examining how and what Quay (or QuayMenu, really) is doing to its event taps.

BTW, the event taps API is in Quartz (the following is an example of what you would use to set up an event tap):

CFMachPortRef CGEventTapCreate (
   CGEventTapLocation tap,
   CGEventTapPlacement place,
   CGEventTapOptions options,
   CGEventMask eventsOfInterest,
   CGEventTapCallBack callback,
   void *refcon
);

I don't know enough about event taps myself to give an example of how to set it up, but that should at least point you in the right direction.

Hope this helps....

NSGod