3

Trying to recognize a right click on a NSStatusItem I got a suggestion ( Thanks to Zoff Dino ) to use a NSClickGestureRecognizer for that. But for some bizarre reason it isn't working as it should be. I am able to recognize a left click (buttonMask = 0x1) but not a right-click (buttonMask = 0x2). This is how I would like it to work but it isn't:

func applicationDidFinishLaunching(aNotification: NSNotification) {
    // Insert code here to initialize your application


    if let button = statusItem.button {

        // Add right click functionality
        let gesture = NSClickGestureRecognizer()
        gesture.buttonMask = 0x2 // right mouse
        gesture.target = self
        gesture.action = "rightClickAction:"
        button.addGestureRecognizer(gesture)


    }}

func rightClickAction(sender: NSGestureRecognizer) {
    if let button = sender.view as? NSButton {
        NSLog("rightClick")
    }
}

UPDATE:

I still did not manage to gets to work. Somehow it doesn't react on a right click (but changing the code on a left click) does. I guess some really simple issues are occurring that seem to block it from working. Even stranger is the fact that gesture.buttonMask = 0x1 works on the left click.

Devapploper
  • 6,062
  • 3
  • 20
  • 41

1 Answers1

2

An alternative solution rather than NSClickGestureRecognizer is to attach a custom view to the status bar and handle the event from there.

The small disadvantage is you have to take care of the drawing and menu delegate methods.

Here a simple example:

Create a file StatusItemView a subclass of NSView

import Cocoa

class StatusItemView: NSView, NSMenuDelegate {

  //MARK: - Variables

  weak var statusItem : NSStatusItem!
  var menuVisible = false

  var image : NSImage! {
    didSet {
      if image != nil {
        statusItem.length = image.size.width
        needsDisplay = true
      }
    }
  }

  //MARK: - Override functions

  override func mouseDown(theEvent: NSEvent) {
    if let hasMenu = menu {
      hasMenu.delegate = self
      statusItem.popUpStatusItemMenu(hasMenu)
      needsDisplay = true
    }
  }

  override func rightMouseDown(theEvent: NSEvent) {
    Swift.print(theEvent)
  }

  //MARK: - NSMenuDelegate

  func menuWillOpen(menu: NSMenu) {
    menuVisible = true
    needsDisplay = true
  }

  func menuDidClose(menu: NSMenu) {
    menuVisible = false
    menu.delegate = nil
    needsDisplay = true
  }

  //MARK: - DrawRect

  override func drawRect(dirtyRect: NSRect) {
    statusItem.drawStatusBarBackgroundInRect(bounds, withHighlight:menuVisible)
    let origin = NSMakePoint(2.0, 3.0) // adjust origin if necessary
    image?.drawAtPoint(origin, fromRect: dirtyRect, operation: .CompositeSourceOver, fraction: 1.0)
  }
}

In AppDelegate you need a reference to the custom menu and an instance variable for the NSStatusItem instance

 @IBOutlet weak var menu : NSMenu!
 var statusItem : NSStatusItem!

In applicationDidFinishLaunching create the view and attach it to the status item. Be aware to set the image of the view after attaching it to make sure the width is considered.

  func applicationDidFinishLaunching(aNotification: NSNotification) {
    statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1) // NSVariableStatusItemLength)
    let statusItemView = StatusItemView(frame: NSRect(x: 0.0, y: 0.0, width: statusItem.length, height: 22.0))
    statusItemView.statusItem = statusItem;
    statusItemView.menu = menu
    statusItem.view = statusItemView
    statusItemView.image = NSImage(named: NSImageNameStatusAvailable)
  }

The special case control-click to trigger the right-click function is not implemented.

vadian
  • 274,689
  • 30
  • 353
  • 361
  • Everything seems to be working(thanks for that). But I would like to use an image instead of the title. How can I achieve this? – Devapploper Sep 06 '15 at 15:20
  • Do you want no title at all? I could update the post to use an image instead of a title – vadian Sep 06 '15 at 15:27
  • 1
    Done. You might scale the image. The `origin` variable in `drawRect` is for fine adjustment of the origin point. – vadian Sep 06 '15 at 15:39
  • Ok thanks! You really helped me out!! I will mark your answer as solved :) And of course you will receive the bounty! – Devapploper Sep 06 '15 at 15:49
  • Now setting custom view for NSStatusItem is marked as deprecated, however right click gesture recognizer still doesn't work. Any ideas how to implement that without the deprecated methods? – Nickolay Olshevsky Jan 17 '21 at 15:21
  • 1
    @NickolayOlshevsky Attach the view to the NSStatusBarButton – vadian Jan 17 '21 at 15:54