I have made a script that mimics the dialog you would normally get when you hold down the control key and eject key.
I needed this function for when I use a keyboard that doesn’t have an eject key, or for cases where I want this dialog inside another script.
use AppleScript version "2.4" -- Yosemite 10.10 or later required
--use scripting additions
use framework "Foundation"
use framework "AppKit"
property ca : current application
property NSButton : class "NSButton"
property NSTextField : class "NSTextField"
property NSImage : class "NSImage"
property NSImageView : class "NSImageView"
property nulls : missing value
property winClose : false
property dialogWindow : missing value
property returnCode : missing value
property buttonCode : missing value
property buttonReturned : missing value
property checkBoxBool : false
global mainThread, screenSize
on run
set mainThread to my NSThread's isMainThread() as boolean
set screenSize to my screenSize()
activate
ca's NSFont's systemFontSizeForControlSize:(ca's NSRegularControlSize)
try
if mainThread then
my makeShutdownDialog:nulls
else
my performSelectorOnMainThread:"makeShutdownDialog:" withObject:nulls waitUntilDone:true
end if
on error the errorMessage number the errorNumber
set the ErrorText to "Error: " & the errorNumber & ". " & the errorMessage
return the ErrorText
end try
--say "Return code is " & returnCode
if returnCode ≠ -1000 then
--say "Closing"
try
if mainThread then
my closeDialog:nulls
else
my performSelectorOnMainThread:"closeDialog:" withObject:nulls waitUntilDone:false
end if
on error the errorMessage number the errorNumber
set the ErrorText to "Error: " & the errorNumber & ". " & the errorMessage
return the ErrorText
end try
end if
--say "Button " & buttonReturned & " clicked"
--say "Checkbox is " & checkBoxBool
if buttonReturned = "Restart" then
tell application "loginwindow" to «event aevtrest»
else if buttonReturned = "Shut Down" then
tell application "loginwindow" to «event aevtshut»
else if buttonReturned = "Sleep" then
tell application "loginwindow" to «event aevtslep»
end if
end run
on closeDialog:arguments
dialogWindow's |close|()
set dialogWindow to missing value
set winClose to false
--ca's NSApp's stopModalWithCode:(returnCode)
ca's NSApp's stopModal
end closeDialog:
on makeShutdownDialog:arguments
local winStyle, wPos, hPos, width, height, rect, theFont, theFont2, fontSize
set {width, height} to {466, 145}
set wPos to ((item 1 of screenSize) - width) div 2
set hPos to ((item 2 of screenSize) - 250)
set rect to ca's NSMakeRect(wPos, hPos, width, height)
set winStyle to (ca's NSWindowStyleMaskTitled as integer) + (ca's NSWindowStyleMaskFullSizeContentView as integer) + (ca's NSWindowStyleMaskBorderless as integer) --+ (ca's NSWindowStyleMaskResizable as integer)
set dialogWindow to ca's NSWindow's alloc()'s initWithContentRect:rect styleMask:winStyle backing:2 defer:true
set titlebarAppearsTransparent of dialogWindow to 1
dialogWindow's setShowsToolbarButton:0
--make text field
set fontSize to ca's NSFont's systemFontSizeForControlSize:(ca's NSRegularControlSize)
set theFont to ca's NSFont's boldSystemFontOfSize:fontSize
set label_field to NSTextField's labelWithString:("Are you sure you want to shut down your" & return & "computer now?")
tell label_field
its setFrame:{{90, 90}, {358, 32}}
its setFont:theFont
set its translatesAutoresizingMaskIntoConstraints to false
end tell
-- make check box
set theCheckbox to NSButton's alloc()'s initWithFrame:{{90, 61}, {260, 18}}
set theFont2 to ca's NSFont's systemFontOfSize:fontSize
tell theCheckbox
its setButtonType:(ca's NSSwitchButton)
its setTitle:"Reopen windows when logging back in"
its setState:false
its setFont:theFont2
its setTag:5
its setAction:"btnAction:"
end tell
theCheckbox's setFrameSize:(theCheckbox's fittingSize())
-- make container view, and add subviews
set powerIcon to NSImage's alloc()'s initWithContentsOfFile:"/System/Library/CoreServices/loginwindow.app/Contents/Resources/ShutDown.tiff"
set content_view to dialogWindow's contentView
content_view's addSubview:label_field
content_view's addSubview:theCheckbox
-- make buttons
set btnList to {{"Shut Down", return}, {"Cancel", character id 27}, {"Sleep", "s"}, {"Restart", "r"}}
set {cancelIndex, okIndex} to {2, 1}
repeat with i from 1 to count btnList
--set aBtn to item i of btnList
set aBtn to item i of btnList
--(451 - i * 98)
set thisButton to (NSButton's alloc()'s initWithFrame:{{(451 - i * 98), 15}, {100, 32}})
(thisButton's setButtonType:(ca's NSMomentaryPushInButton))
(thisButton's setBezelStyle:(ca's NSRoundedBezelStyle))
(thisButton's setImagePosition:(ca's NSNoImage))
(thisButton's setTag:i)
(thisButton's setTitle:(item 1 of aBtn))
if (length of item 2 of aBtn) = 1 then (thisButton's setKeyEquivalent:(item 2 of aBtn))
(thisButton's setTarget:me)
(thisButton's setAction:"btnAction:")
if i = cancelIndex then -- make esc the shortcut
(thisButton's setTag:(ca's NSModalResponseCancel))
end if
(content_view's addSubview:thisButton)
end repeat
--content_view's addSubview:thisButton
set aNSV to NSImageView's alloc()'s initWithFrame:(current application's NSMakeRect(20, 60, 64, 64))
aNSV's setImage:powerIcon
content_view's addSubview:aNSV
set delegate of dialogWindow to me
--ca's NSApp's performSelector:"abortModal" withObject:(missing value) afterDelay:10 inModes:{ca's NSModalPanelRunLoopMode}
set my returnCode to (ca's NSApp)'s runModalForWindow:dialogWindow
--tell me to say "OOps"
--progress_indicator's sizeToFit()
--set dialogWindow's contentView to content_view
end makeShutdownDialog:
on screenSize()
local theScreen, theFrame
set theScreen to ca's NSScreen's mainScreen()
set theFrame to item 2 of (theScreen's visibleFrame() as list)
return {item 1 of theFrame as integer, item 2 of theFrame as integer}
end screenSize
-- NSButton Delegate Functions
on btnAction:sender
set my buttonReturned to sender's title as text
set my buttonCode to sender's tag as integer
if my buttonCode = 5 then -- checkbox
set my checkBoxBool to sender's state as boolean
else
try
my closeDialog:nulls
on error the errorMessage number the errorNumber
set the ErrorText to "Error: " & the errorNumber & ". " & the errorMessage
return the ErrorText
end try
end if
end btnAction:
-- Start NSWindowDelegate Functions
on windowWillClose:arguments
set winClose to true
end windowWillClose:
on windowDidMove:arguments
--tell me to beep
end windowDidMove:
-- End NSWindowDelegate Functions