CFRelease the duration preference value if we get one. Found by the clang static analyzer.
2 // GrowlBubblesWindowController.m
5 // Created by Nelson Elhage on Wed Jun 09 2004.
6 // Name changed from KABubbleWindowController.m by Justin Burns on Fri Nov 05 2004.
7 // Copyright (c) 2004-2006 The Growl Project. All rights reserved.
10 #import "GrowlBubblesWindowController.h"
11 #import "GrowlBubblesWindowView.h"
12 #import "GrowlBubblesPrefsController.h"
13 #import "GrowlBubblesDefines.h"
14 #import "GrowlApplicationNotification.h"
15 #import "NSWindow+Transforms.h"
16 #include "CFDictionaryAdditions.h"
17 #import "GrowlWindowTransition.h"
18 #import "GrowlFadingWindowTransition.h"
19 #import "GrowlPositionController.h"
21 @implementation GrowlBubblesWindowController
23 #define GrowlBubblesPadding 5.0f
29 READ_GROWL_PREF_INT(GrowlBubblesScreen, GrowlBubblesPrefDomain, &screenNumber);
30 NSArray *screens = [NSScreen screens];
31 unsigned screensCount = [screens count];
33 [self setScreen:((screensCount >= (screenNumber + 1)) ? [screens objectAtIndex:screenNumber] : [screens objectAtIndex:0])];
36 CFNumberRef prefsDuration = NULL;
37 READ_GROWL_PREF_VALUE(GrowlBubblesDuration, GrowlBubblesPrefDomain, CFNumberRef, &prefsDuration);
38 [self setDisplayDuration:(prefsDuration ?
39 [(NSNumber *)prefsDuration doubleValue] :
40 GrowlBubblesDurationPrefDefault)];
41 if (prefsDuration) CFRelease(prefsDuration);
43 // I tried setting the width/height to zero, since the view resizes itself later.
44 // This made it ignore the alpha at the edges (using 1.0 instead). Why?
45 // A window with a frame of NSZeroRect is off-screen and doesn't respect opacity even
46 // if moved on screen later. -Evan
47 NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0.0f, 0.0f, 270.0f, 65.0f)
48 styleMask:NSBorderlessWindowMask | NSNonactivatingPanelMask
49 backing:NSBackingStoreBuffered
51 NSRect panelFrame = [panel frame];
52 [panel setBecomesKeyOnlyIfNeeded:YES];
53 [panel setHidesOnDeactivate:NO];
54 [panel setBackgroundColor:[NSColor clearColor]];
55 [panel setLevel:NSStatusWindowLevel];
56 [panel setSticky:YES];
57 [panel setAlphaValue:0.0f];
59 [panel setHasShadow:YES];
60 [panel setCanHide:NO];
61 [panel setOneShot:YES];
62 [panel useOptimizedDrawing:YES];
63 [panel setMovableByWindowBackground:NO];
65 // Create the content view...
66 GrowlBubblesWindowView *view = [[GrowlBubblesWindowView alloc] initWithFrame:panelFrame];
67 [view setTarget:self];
68 [view setAction:@selector(notificationClicked:)];
69 [panel setContentView:view];
72 // call super so everything else is set up...
73 if ((self = [super initWithWindow:panel])) {
74 // set up the transitions...
75 GrowlFadingWindowTransition *fader = [[GrowlFadingWindowTransition alloc] initWithWindow:panel];
76 [self addTransition:fader];
77 [self setStartPercentage:0 endPercentage:100 forTransition:fader];
78 [fader setAutoReverses:YES];
88 - (void) setNotification: (GrowlApplicationNotification *) theNotification {
89 [super setNotification:theNotification];
93 NSDictionary *noteDict = [notification dictionaryRepresentation];
94 NSString *title = [notification title];
95 NSString *text = [notification notificationDescription];
96 NSImage *icon = getObjectForKey(noteDict, GROWL_NOTIFICATION_ICON);
97 int priority = getIntegerForKey(noteDict, GROWL_NOTIFICATION_PRIORITY);
99 GrowlBubblesWindowView *view = [[self window] contentView];
100 [view setPriority:priority];
101 [view setTitle:title];
108 #pragma mark positioning methods
110 - (NSPoint) idealOriginInRect:(NSRect)rect {
111 NSRect viewFrame = [[[self window] contentView] frame];
112 enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
115 switch(originatingPosition){
116 case GrowlTopRightPosition:
117 idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
118 NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
120 case GrowlTopLeftPosition:
121 idealOrigin = NSMakePoint(NSMinX(rect) + GrowlBubblesPadding,
122 NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
124 case GrowlBottomLeftPosition:
125 idealOrigin = NSMakePoint(NSMinX(rect) + GrowlBubblesPadding,
126 NSMinY(rect) + GrowlBubblesPadding);
128 case GrowlBottomRightPosition:
129 idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
130 NSMinY(rect) + GrowlBubblesPadding);
133 idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
134 NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
141 - (enum GrowlExpansionDirection) primaryExpansionDirection {
142 enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
143 enum GrowlExpansionDirection directionToExpand;
145 switch(originatingPosition){
146 case GrowlTopLeftPosition:
147 directionToExpand = GrowlDownExpansionDirection;
149 case GrowlTopRightPosition:
150 directionToExpand = GrowlDownExpansionDirection;
152 case GrowlBottomLeftPosition:
153 directionToExpand = GrowlUpExpansionDirection;
155 case GrowlBottomRightPosition:
156 directionToExpand = GrowlUpExpansionDirection;
159 directionToExpand = GrowlDownExpansionDirection;
163 return directionToExpand;
166 - (enum GrowlExpansionDirection) secondaryExpansionDirection {
167 enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
168 enum GrowlExpansionDirection directionToExpand;
170 switch(originatingPosition){
171 case GrowlTopLeftPosition:
172 directionToExpand = GrowlRightExpansionDirection;
174 case GrowlTopRightPosition:
175 directionToExpand = GrowlLeftExpansionDirection;
177 case GrowlBottomLeftPosition:
178 directionToExpand = GrowlRightExpansionDirection;
180 case GrowlBottomRightPosition:
181 directionToExpand = GrowlLeftExpansionDirection;
184 directionToExpand = GrowlRightExpansionDirection;
188 return directionToExpand;
191 - (float) requiredDistanceFromExistingDisplays {
192 return GrowlBubblesPadding;