0

I have a macOS menu bar app. I like to know can we prioritize the order that the app shows in the status bar.

//
//  AppDelegate.swift
//  elmc_midi_deck-macOS
//
//  Created by Jerry Seigle on 6/23/22.
//

import Foundation
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
  var popover: NSPopover!
  var window: NSWindow!
  var statusBarItem: NSStatusItem!

  func applicationDidFinishLaunching(_ aNotification: Notification) {
    let jsCodeLocation: URL

    #if DEBUG
      jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackResource:nil)
    #else
      jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
    #endif
    let rootView = RCTRootView(bundleURL: jsCodeLocation, moduleName: "elmc_midi_deck", initialProperties: nil, launchOptions: nil)
    let rootViewController = NSViewController()
    rootViewController.view = rootView

    popover = NSPopover()

    popover.contentSize = NSSize(width: 400, height: 600)
    popover.animates = true
    popover.behavior = .transient
    popover.contentViewController = rootViewController

    statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(60))

    if let button = self.statusBarItem.button {
      button.action = #selector(togglePopover(_:))
      button.title = "elmc_midi_deck"
    }

    #if DEBUG
    window = NSWindow(
      contentRect: NSRect(x: 0, y: 0, width: 1, height: 1),
      styleMask: [.titled, .closable, .miniaturizable, .resizable],
      backing: .buffered,
      defer: false)

    window.contentViewController = rootViewController
    window.center()
    window.setFrameAutosaveName("ELMC Midi Deck")
    window.isReleasedWhenClosed = false
    window.makeKeyAndOrderFront(self)
    let screen: NSScreen = NSScreen.main!
    let midScreenX = screen.frame.midX
    let posScreenY = 200
    let origin = CGPoint(x: Int(midScreenX), y: posScreenY)
    let size = CGSize(width: 400, height: 600)
    let frame = NSRect(origin: origin, size: size)
    window.setFrame(frame, display: true)
    #endif
  }

  @objc func togglePopover(_ sender: AnyObject?) {
    if let button = self.statusBarItem.button {
      if self.popover.isShown {
        self.popover.performClose(sender)
      } else {
        self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)

        self.popover.contentViewController?.view.window?.becomeKey()
      }
    }
  }
}


Currently the app will show at the far left once started. Of course you can command click and drag left to right but I like to make the app show after Apple's default apps like show in the photo

enter image description here

1 Answers1

0

As mentioned in this post, you can use this library to do this. The library allows defining the position for an NSStatusBarItem inside the NSStatusBar. It is written in Objective-C and available via CocoaPods, you probably have to create a bridging header or manually convert it in order to use it in Swift. Refer to this post for details on how to do this.

AgentBilly
  • 756
  • 5
  • 20