Skip to content

Instantly share code, notes, and snippets.

@bellbind
Last active November 22, 2018 16:02
Show Gist options
  • Save bellbind/b69f6ef133f0ad5266ff40be2001aecc to your computer and use it in GitHub Desktop.
Save bellbind/b69f6ef133f0ad5266ff40be2001aecc to your computer and use it in GitHub Desktop.
[macos][swift4] DisplayMode switcher on StatusBar
#!/usr/bin/env swift
// DisplayMode switcher on StatrusBar (for swift4)
// $ swiftc DisplayModeSwitcher.swift
import Cocoa
let monoText = NSFont.monospacedDigitSystemFont(ofSize: NSFont.systemFontSize, weight: .regular)
let attrsT: [NSAttributedString.Key: Any] = [.font: monoText]
let attrsS: [NSAttributedString.Key: Any] = [.font: monoText, .expansion: 0.8]
func resolution(_ id: String, _ w: String, _ h: String, _ mark: String) -> NSAttributedString {
let parts = [(String(repeating: " ", count: 3 - id.count), attrsS), ("\(id): ", attrsT),
(String(repeating: " ", count: 5 - w.count), attrsS), ("\(w) x \(h)", attrsT),
(String(repeating: " ", count: 5 - h.count), attrsS), (mark, attrsT)]
let title = NSMutableAttributedString()
for (text, attrs) in parts {title.append(NSAttributedString(string: text, attributes: attrs))}
return title
}
class Main: NSObject, NSMenuDelegate {
func menuWillOpen(_ menu: NSMenu) {
menu.removeAllItems()
let display = CGMainDisplayID()
let modes = CGDisplayCopyAllDisplayModes(display, nil)
guard let dmodes = modes as? [CGDisplayMode] else {return}
if let current = CGDisplayCopyDisplayMode(display) {
let now = NSMenuItem()
now.attributedTitle = resolution("Now", "\(current.width)", "\(current.height)", "")
menu.addItem(now)
menu.addItem(NSMenuItem.separator())
let items = dmodes.enumerated().map {(i, dmode) -> NSMenuItem in
let mi = NSMenuItem()
let mark = dmode.ioDisplayModeID == current.ioDisplayModeID ? "\u{2713}" : ""
mi.attributedTitle = resolution("\(i)", "\(dmode.width)", "\(dmode.height)", mark)
mi.action = #selector(self.switchMode)
mi.target = self
mi.tag = i
return mi
}
for item in items {menu.addItem(item)}
}
menu.addItem(NSMenuItem.separator())
let terminate = #selector(NSApplication.shared.terminate)
menu.addItem(withTitle: "Quit", action: terminate, keyEquivalent: "")
}
@objc func switchMode(_ sender: NSMenuItem) {
let display = CGMainDisplayID()
let modes = CGDisplayCopyAllDisplayModes(display, nil)
guard let dmodes = modes as? [CGDisplayMode] else {return}
let config = UnsafeMutablePointer<CGDisplayConfigRef?>.allocate(capacity: 1)
defer {config.deallocate()}
CGBeginDisplayConfiguration(config)
CGConfigureDisplayWithDisplayMode(config.pointee, display, dmodes[sender.tag], nil)
CGCompleteDisplayConfiguration(config.pointee, CGConfigureOption.permanently)
}
}
let main = Main()
NSApplication.loadApplication()
let menu = NSMenu()
menu.delegate = main
let statusItem = NSStatusBar.system.statusItem(withLength: -1)
//statusItem.button?.title = "\u{1F5A5}"
statusItem.button?.title = "\u{1F4BB}"
statusItem.menu = menu
NSApplication.shared.run()
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>%name%</string>
<key>CFBundleIdentifier</key>
<string>%id%</string>
<key>CFBundleIconFile</key>
<string>%name%.icns</string>
<key>CFBundleName</key>
<string>%name%</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSUIElement</key>
<true/>
</dict>
</plist>
#!/bin/bash
if [ "$(which convert)" == "" ] ; then
echo "[Abort] Please install imagemagick"
exit 1
fi
namespace=bellbind
name=DisplayModeSwitcher
svg=icon.svg
id="$namespace.$name"
#NOTE: Prepare your certificate in "Keychain Access"
#cert=bellbind
# build bin
cd $(dirname $0)
swiftopts=""
swiftc $swiftopts "$name.swift"
# build icns from svg
iconset="$name.iconset"
png="$svg.png"
opts="-fuzz 15% -transparent white"
mkdir -p "$iconset"
qlmanage -t -s 1024 -o . "$svg"
convert "$png" $opts -resize 16x16 "$iconset/icon_16x16.png"
convert "$png" $opts -resize 32x32 "$iconset/icon_16x16@2x.png"
convert "$png" $opts -resize 32x32 "$iconset/icon_32x32.png"
convert "$png" $opts -resize 64x64 "$iconset/icon_32x32@2x.png"
convert "$png" $opts -resize 128x128 "$iconset/icon_128x128.png"
convert "$png" $opts -resize 256x256 "$iconset/icon_128x128@2x.png"
convert "$png" $opts -resize 256x256 "$iconset/icon_256x256.png"
convert "$png" $opts -resize 512x512 "$iconset/icon_256x256@2x.png"
convert "$png" $opts -resize 512x512 "$iconset/icon_512x512.png"
convert "$png" $opts -resize 1024x1024 "$iconset/icon_512x512@2x.png"
iconutil -c icns "$iconset"
# build app bundle
app="$name.app"
mkdir -p "$app/Contents/MacOS"
mkdir -p "$app/Contents/Resources"
sed -e "s/%name%/$name/g;s/%id%/$id/g" Info.plist.xml > "$app/Contents/Info.plist"
cp "$name" "$app/Contents/MacOS"
cp "$name.icns" "$app/Contents/Resources"
# cleanup
rm -r "$name.iconset"
rm "$name" "$name.icns" "$png"
# codesign
if [ "$cert" ] ; then
codesign -s "$cert" "$app"
fi
# make dmg
mkdir -p dmg/
cp -a "$app" dmg/
( cd dmg ; ln -s /Applications/ )
hdiutil create -srcfolder dmg -volname "$name" "$name.dmg"
rm -rf dmg/
@bellbind
Copy link
Author

bellbind commented Nov 11, 2018

@bellbind
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment