title: Cocoa: programmatically show/hide custom NSWindow with custom NSView
body: <p>First of all I have to inform you that I am new to Objective-C and Cocoa.</p>
  
  <p>I have read some books about that and I am able to build quite simple programmes now.</p>
  
  <p>it's been 15 days that I'm stuck with a program that I'm trying to build and I really don't know more where to look..</p>
  
  <p>I want to build a program that can change the brightness of my monitor using DDC/CI and I want to show/hide a window (where it is written the level of brightness) exactly like the Apple brightness bezel of Leopard or Snow Leopard with the exact same style.</p>
  
  <p>Using <code>RegisterEventHotKey</code> and various IOservices functions I have been able to increase brightness when I press F2 and to decrease it wheh I press F1.</p>
  
  <p>Using custom NSWindow (TransparentWindow) and custom NSView (RoundedView) I have been able to obtain a window which appears exactly as the Apple brightness bezel. I have put it on awakeFromNib and it appears correctly and stays there.</p>
  
  <p>What I am not able to achieve (and I'm really becoming crazy on that) is to show the window only when I press F1 or F2. (to hide it I have alredy implemented an <code>NSTimer</code> but this is offtopic now) </p>
  
  <p>I tried different ways:</p>
  
  <p>1) From the NSobject class where I implement <code>RegisterEventHotKey</code> I have created an instance of TransparentWindow and then I have sent <code>orderOut</code> to that instance.</p>
  
  <p>2) I have used NSNotificationCenter to send a notification directly to TransparentWindow class and call <code>orderOut</code> from there.</p>
  
  <p>3) and many other that I don't remember now.</p>
  
  <p>What I'm trying to do now is to make the window appearing by creating it inside <code>awakeFromNib</code> (and this works) and then to hide it with <code>orderOut</code> (and this never works).</p>
  
  <p>These are the involved classes:</p>
  
  <p>TransparentWindow.h:</p>
  
  <pre><code>#import &lt;Cocoa/Cocoa.h&gt;
  
  @interface TransparentWindow : NSWindow
  {
  IBOutlet NSWindow *window;
  }
  
  @property (retain) IBOutlet NSWindow *window;
  
  @end
  </code></pre>
  
  <p>TransparentWindow.m:</p>
  
  <pre><code>#import "TransparentWindow.h"
  
  
  @implementation TransparentWindow
  
  @synthesize window;
  
  
  - (id)initWithContentRect:(NSRect)contentRect 
                  styleMask:(unsigned int)aStyle 
                    backing:(NSBackingStoreType)bufferingType 
                      defer:(BOOL)flag {
  
      window = [super initWithContentRect:contentRect 
                                          styleMask:NSBorderlessWindowMask 
                                            backing:NSBackingStoreBuffered 
                                  defer:NO];
      if (window != nil) {
  
          [window setLevel: NSStatusWindowLevel];
          [window setBackgroundColor: [NSColor clearColor]];
          [window setAlphaValue:1.0];
          [window setOpaque:NO];
          [window setHasShadow:NO];
          [window setIgnoresMouseEvents: YES];
          NSLog(@"%p", window);
  
      }
      return window;
  
  }
  
  
  - (BOOL) canBecomeKeyWindow
  {
      return YES;
  }
  
  - (void)notify {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:self];
  }
  
  
  
  
  - (void)handleNotification:(NSNotification*)note {
  
          [window orderOut:self];
  
      }
  
  
  @end
  </code></pre>
  
  <p>RoundedView.h:</p>
  
  <pre><code>#import &lt;Cocoa/Cocoa.h&gt;
  
  @interface RoundedView : NSView
  {
  }
  
  
  @end
  </code></pre>
  
  <p>RoundedView.m:</p>
  
  <pre><code>#import "RoundedView.h"
  
  @implementation RoundedView
  
  
  - (void)drawRect:(NSRect)rect
  {
          NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.25];
      NSRect bgRect = rect;
      int minX = NSMinX(bgRect);
      int midX = NSMidX(bgRect);
      int maxX = NSMaxX(bgRect);
      int minY = NSMinY(bgRect);
      int midY = NSMidY(bgRect);
      int maxY = NSMaxY(bgRect);
      float radius = 20.0; // correct value to duplicate Panther's App Switcher
      NSBezierPath *bgPath = [NSBezierPath bezierPath];
  
      // Bottom edge and bottom-right curve
      [bgPath moveToPoint:NSMakePoint(midX, minY)];
      [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, minY) 
                                       toPoint:NSMakePoint(maxX, midY) 
                                        radius:radius];
  
      // Right edge and top-right curve
      [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(maxX, maxY) 
                                       toPoint:NSMakePoint(midX, maxY) 
                                        radius:radius];
  
      // Top edge and top-left curve
      [bgPath appendBezierPathWithArcFromPoint:NSMakePoint(minX, maxY) 
                                       toPoint:NSMakePoint(minX, midY) 
                                        radius:radius];
  
      // Left edge and bottom-left curve
      [bgPath appendBezierPathWithArcFromPoint:bgRect.origin 
                                       toPoint:NSMakePoint(midX, minY) 
                                        radius:radius];
      [bgPath closePath];
  
      [bgColor set];
      [bgPath fill];
  
  }
  </code></pre>
  
  <p>MainProgram.h:</p>
  
  <pre><code>#import &lt;Cocoa/Cocoa.h&gt;
  #import &lt;carbon/carbon.h&gt;
  #include &lt;assert.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;IOKit/IOKitLib.h&gt; 
  #include &lt;ApplicationServices/ApplicationServices.h&gt;
  #include &lt;IOKit/i2c/IOI2CInterface.h&gt;
  
  @interface MainProgram : NSObject {
  
  }
  
  @end
  </code></pre>
  
  <p>MainProgram.m:</p>
  
  <pre><code>#import "MainProgram.h"
  #import &lt;Carbon/Carbon.h&gt;
  #import "TransparentWindow.h"
  #include &lt;assert.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;IOKit/IOKitLib.h&gt; 
  #include &lt;ApplicationServices/ApplicationServices.h&gt;
  #include &lt;IOKit/i2c/IOI2CInterface.h&gt;
  
  
  static OSStatus OnHotKeyEvent(EventHandlerCallRef nextHandler,EventRef theEvent,void *userData);
  
  extern int level;
  
  @implementation MainProgram
  
  
  - (void)awakeFromNib
  {
  
      EventHotKeyRef gMyHotKeyRef;
      EventHotKeyID gMyHotKeyID;
      EventTypeSpec eventType;
      eventType.eventClass=kEventClassKeyboard;
      eventType.eventKind=kEventHotKeyPressed;
  
      InstallApplicationEventHandler(&amp;OnHotKeyEvent, 1, &amp;eventType, NULL, NULL);
  
      gMyHotKeyID.signature='htk1';
      gMyHotKeyID.id=1;
      //RegisterEventHotKey(122, controlKey, gMyHotKeyID, GetApplicationEventTarget(), 0, &amp;gMyHotKeyRef);
      RegisterEventHotKey(122, NULL, gMyHotKeyID, GetApplicationEventTarget(), 0, &amp;gMyHotKeyRef);
  
      gMyHotKeyID.signature='htk2';
      gMyHotKeyID.id=2;
      RegisterEventHotKey(120, NULL, gMyHotKeyID, GetApplicationEventTarget(), 0, &amp;gMyHotKeyRef);
  }
  
  
  
  
  OSStatus OnHotKeyEvent(EventHandlerCallRef nextHandler,EventRef theEvent,
                           void *userData)
  {
  
      EventHotKeyID hkCom;
      GetEventParameter(theEvent,kEventParamDirectObject,typeEventHotKeyID,NULL,
                        sizeof(hkCom),NULL,&amp;hkCom);
      int l = hkCom.id;
  
      switch (l) {
          case 1: 
              //NSLog(@"Hotkey 1");
              level = level - 5;
  
              if (level&lt;0) {
                  level = 0;
              }
              else {
                  BrightnessMain(level);
              }
              break;
          case 2: 
              //NSLog(@"Hotkey 2");
              level = level + 5;
  
              if (level&gt;100) {
                  level = 100;
              }
              else {
                  BrightnessMain(level);
  
                  TransparentWindow *object3 = [[TransparentWindow alloc] init];
  
                  //[object3 orderOut:nil];
                  [[NSNotificationCenter defaultCenter] addObserver:object3 selector:@selector(handleNotification:) name:@"MyNotification" object:nil];
                  [object3 notify];
  
              }
              break;
      }
  
      return noErr;
  }
  
  
  @end
  </code></pre>
  
  <p>Where is the mistake?
  I'm not an expert programmer but I think it could be a stupid simple mistake but I'm not able to figure it out..</p>
  
  <p><strong>Update of MainProgram.m:</strong></p>
  
  <p>I have replaced this</p>
  
  <p><code>TransparentWindow *object3 = [[TransparentWindow alloc] init]</code>;</p>
  
  <p>with this:</p>
  
  <pre><code>NSRect contentRect;
  NSSize contentSize;
  
  contentSize.width  = 210;
  contentSize.height = 205;
  
  contentRect.origin = NSMakePoint(855, 140);
  contentRect.size  = contentSize;
  
  TransparentWindow *object3 = [[TransparentWindow alloc] initWithContentRect:contentRect 
                                                                                    styleMask:NSBorderlessWindowMask 
                                                                                      backing:NSBackingStoreBuffered 
                                                                                        defer:NO];
  </code></pre>
  
  <p>I'm not sure if this is what you meant..</p>
  
  <p><strong>Corrected TransparentWindow.h:</strong></p>
  
  <pre><code>#import &lt;Cocoa/Cocoa.h&gt;
  
  @interface TransparentWindow : NSWindow
  {
  
  }
  
  
  @end
  </code></pre>
  
  <p><strong>Corrected TransparentWindow.m:</strong></p>
  
  <pre><code>#import "TransparentWindow.h"
  
  
  @implementation TransparentWindow
  
  
  - (id)initWithContentRect:(NSRect)contentRect 
                  styleMask:(unsigned int)aStyle 
                    backing:(NSBackingStoreType)bufferingType 
                      defer:(BOOL)flag {
  
      self = [super initWithContentRect:contentRect 
                                          styleMask:NSBorderlessWindowMask 
                                            backing:NSBackingStoreBuffered 
                                  defer:NO];
      if (self != nil) {
  
          [self setLevel: NSStatusWindowLevel];
          [self setBackgroundColor: [NSColor clearColor]];
          [self setAlphaValue:1.0];
          [self setOpaque:NO];
          [self setHasShadow:NO];
          [self setIgnoresMouseEvents: YES];
          NSLog(@"%p", self);
  
      }
      return self;
  
  }
  
  
  
  - (BOOL) canBecomeKeyWindow
  {
      return YES;
  }
  
  - (void)notify {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:self];
  }
  
  
  
  
  - (void)handleNotification:(NSNotification*)note {
  
      [self orderOut:self];
  
      }
  
  @end
  </code></pre>
  
  <p><strong>Update 2:</strong></p>
  
  <p>If I use makeKeyAndOrderFront instead of orderFront it happens a really strange fact.</p>
  
  <p>After the first 3 or 4 pressing of the F1 or F2 button, nothing happens but when I press F1 or F2 another time, still no window appears but I get these strange errors in console:</p>
  
  <pre><code>RoundedFloatingPanel[2346] &lt;Warning&gt;: CGSResolveShmemReference : window.RO.dirtyRegion : Reference offset (38464) exceeds bounds (32768) on shmem obj 0x229
  RoundedFloatingPanel[2346] &lt;Warning&gt;: CGSResolveShmemReference : window.RO : Reference offset (38144) exceeds bounds (32768) on shmem obj 0x229
  RoundedFloatingPanel[2346] &lt;Error&gt;: kCGErrorFailure: CGSNewWindowWithOpaqueShape: Cannot map window information shmem
  RoundedFloatingPanel[2346] &lt;Error&gt;: kCGErrorFailure: Set a breakpoint @ CGErrorBreakpoint() to catch errors as they are logged.
  2011-02-17 16:01:42.895 RoundedFloatingPanel[2346:a0f] HIToolbox: ignoring exception 'Error (1000) creating CGSWindow' that raised inside Carbon event dispatch
  (
      0   CoreFoundation                      0x91f186ba __raiseError + 410
      1   libobjc.A.dylib                     0x999e3509 objc_exception_throw + 56
      2   CoreFoundation                      0x91f183e8 +[NSException raise:format:arguments:] + 136
      3   CoreFoundation                      0x91f1835a +[NSException raise:format:] + 58
      4   AppKit                              0x93408915 _NXCreateWindow + 316
      5   AppKit                              0x93408720 _NSCreateWindow + 59
      6   AppKit                              0x93407946 -[NSWindow _commonAwake] + 1784
      7   AppKit                              0x9340456e -[NSWindow _commonInitFrame:styleMask:backing:defer:] + 1524
      8   AppKit                              0x934031c1 -[NSWindow _initContent:styleMask:backing:defer:contentView:] + 1568
      9   AppKit                              0x93402b9b -[NSWindow initWithContentRect:styleMask:backing:defer:] + 71
      10  RoundedFloatingPanel                0x000029a6 -[TransparentWindow initWithContentRect:styleMask:backing:defer:] + 119
      11  RoundedFloatingPanel                0x000031ec OnHotKeyEvent + 447
      12  HIToolbox                           0x95ff0ecf _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 1567
      13  HIToolbox                           0x95ff0196 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 411
      14  HIToolbox                           0x95fefff5 SendEventToEventTargetWithOptions + 58
      15  HIToolbox                           0x96024c18 _ZL29ToolboxEventDispatcherHandlerP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv + 3006
      16  HIToolbox                           0x95ff1320 _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec + 2672
      17  HIToolbox                           0x95ff0196 _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec + 411
      18  HIToolbox                           0x96012a07 SendEventToEventTarget + 52
      19  AppKit                              0x93460c3e -[NSApplication sendEvent:] + 7494
      20  AppKit                              0x933f42a7 -[NSApplication run] + 917
      21  AppKit                              0x933ec2d9 NSApplicationMain + 574
      22  RoundedFloatingPanel                0x00002368 main + 30
      23  RoundedFloatingPanel                0x0000231e start + 54
      24  ???                                 0x00000001 0x0 + 1
  </code></pre>