2 * MACDRV Cocoa status item class
4 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #import <Cocoa/Cocoa.h>
22 #include "macdrv_cocoa.h"
24 #import "cocoa_event.h"
27 @interface WineStatusItem : NSView
30 WineEventQueue* queue;
31 NSTrackingArea* trackingArea;
35 @property (retain, nonatomic) NSStatusItem* item;
36 @property (assign, nonatomic) WineEventQueue* queue;
37 @property (retain, nonatomic) NSImage* image;
42 @implementation WineStatusItem
44 @synthesize item, queue, image;
46 - (id) initWithEventQueue:(WineEventQueue*)inQueue
48 NSStatusBar* statusBar = [NSStatusBar systemStatusBar];
49 CGFloat thickness = [statusBar thickness];
51 self = [super initWithFrame:NSMakeRect(0, 0, thickness, thickness)];
54 item = [[statusBar statusItemWithLength:NSSquareStatusItemLength] retain];
55 // This is a retain cycle which is broken in -removeFromStatusBar.
60 trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
61 options:NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect
64 [self addTrackingArea:trackingArea];
73 NSStatusBar* statusBar = [NSStatusBar systemStatusBar];
74 [statusBar removeStatusItem:item];
78 [trackingArea release];
82 - (void) setImage:(NSImage*)inImage
87 image = [inImage retain];
88 [self setNeedsDisplay:YES];
92 - (void) removeFromStatusBar
96 NSStatusBar* statusBar = [NSStatusBar systemStatusBar];
97 [statusBar removeStatusItem:item];
103 - (void) postMouseButtonEvent:(NSEvent*)nsevent;
106 NSUInteger typeMask = NSEventMaskFromType([nsevent type]);
108 event = macdrv_create_event(STATUS_ITEM_MOUSE_BUTTON, nil);
109 event->status_item_mouse_button.item = (macdrv_status_item)self;
110 event->status_item_mouse_button.button = [nsevent buttonNumber];
111 event->status_item_mouse_button.down = (typeMask & (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask)) != 0;
112 event->status_item_mouse_button.count = [nsevent clickCount];
113 [queue postEvent:event];
114 macdrv_release_event(event);
119 * ---------- NSView methods ----------
121 - (void) drawRect:(NSRect)rect
123 [item drawStatusBarBackgroundInRect:[self bounds] withHighlight:NO];
127 NSSize imageSize = [image size];
128 NSRect bounds = [self bounds];
129 NSPoint imageOrigin = NSMakePoint(NSMidX(bounds) - imageSize.width / 2,
130 NSMidY(bounds) - imageSize.height / 2);
132 imageOrigin = [self convertPointToBase:imageOrigin];
133 imageOrigin.x = floor(imageOrigin.x);
134 imageOrigin.y = floor(imageOrigin.y);
135 imageOrigin = [self convertPointFromBase:imageOrigin];
137 [image drawAtPoint:imageOrigin
139 operation:NSCompositeSourceOver
146 * ---------- NSResponder methods ----------
148 - (void) mouseDown:(NSEvent*)event
150 [self postMouseButtonEvent:event];
153 - (void) mouseDragged:(NSEvent*)event
155 [self mouseMoved:event];
158 - (void) mouseMoved:(NSEvent*)nsevent
161 event = macdrv_create_event(STATUS_ITEM_MOUSE_MOVE, nil);
162 event->status_item_mouse_move.item = (macdrv_status_item)self;
163 [queue postEvent:event];
164 macdrv_release_event(event);
167 - (void) mouseUp:(NSEvent*)event
169 [self postMouseButtonEvent:event];
172 - (void) otherMouseDown:(NSEvent*)event
174 [self postMouseButtonEvent:event];
177 - (void) otherMouseDragged:(NSEvent*)event
179 [self mouseMoved:event];
182 - (void) otherMouseUp:(NSEvent*)event
184 [self postMouseButtonEvent:event];
187 - (void) rightMouseDown:(NSEvent*)event
189 [self postMouseButtonEvent:event];
192 - (void) rightMouseDragged:(NSEvent*)event
194 [self mouseMoved:event];
197 - (void) rightMouseUp:(NSEvent*)event
199 [self postMouseButtonEvent:event];
205 /***********************************************************************
206 * macdrv_create_status_item
208 * Creates a new status item in the status bar.
210 macdrv_status_item macdrv_create_status_item(macdrv_event_queue q)
212 WineEventQueue* queue = (WineEventQueue*)q;
213 __block WineStatusItem* statusItem;
216 statusItem = [[WineStatusItem alloc] initWithEventQueue:queue];
219 return (macdrv_status_item)statusItem;
222 /***********************************************************************
223 * macdrv_destroy_status_item
225 * Removes a status item previously returned by
226 * macdrv_create_status_item() from the status bar and destroys it.
228 void macdrv_destroy_status_item(macdrv_status_item s)
230 WineStatusItem* statusItem = (WineStatusItem*)s;
233 [statusItem removeFromStatusBar];
234 [statusItem release];
238 /***********************************************************************
239 * macdrv_set_status_item_image
241 * Sets the image for a status item. If cgimage is NULL, clears the
242 * image of the status item (leaving it a blank spot on the menu bar).
244 void macdrv_set_status_item_image(macdrv_status_item s, CGImageRef cgimage)
246 WineStatusItem* statusItem = (WineStatusItem*)s;
248 CGImageRetain(cgimage);
251 NSImage* image = nil;
255 CGFloat maxSize = [[NSStatusBar systemStatusBar] thickness];
256 BOOL changed = FALSE;
258 image = [[NSImage alloc] initWithCGImage:cgimage size:NSZeroSize];
259 CGImageRelease(cgimage);
261 while (size.width > maxSize || size.height > maxSize)
268 [image setSize:size];
270 statusItem.image = image;
275 /***********************************************************************
276 * macdrv_set_status_item_tooltip
278 * Sets the tooltip string for a status item. If cftip is NULL, clears
279 * the tooltip string for the status item.
281 void macdrv_set_status_item_tooltip(macdrv_status_item s, CFStringRef cftip)
283 WineStatusItem* statusItem = (WineStatusItem*)s;
284 NSString* tip = (NSString*)cftip;
286 if (![tip length]) tip = nil;
288 [statusItem setToolTip:tip];