2016-05-22 9 views
2

Я экспериментировал с программой образца при https://github.com/gtk2hs/gtk2hs/blob/master/gtk/demo/hello/World.hs, приводится ниже:Как обрабатывать команду Quit (Cmd-Q) в Mac OS X в Haskell gtk2hs

-- A simple program to demonstrate Gtk2Hs. 
module Main (Main.main) where 

import Graphics.UI.Gtk 

main :: IO() 
main = do 
    initGUI 
    -- Create a new window 
    window <- windowNew 
    -- Here we connect the "destroy" event to a signal handler. 
    -- This event occurs when we call widgetDestroy on the window 
    -- or if the user closes the window. 
    on window objectDestroy mainQuit 
    -- Sets the border width and tile of the window. Note that border width 
    -- attribute is in 'Container' from which 'Window' is derived. 
    set window [ containerBorderWidth := 10, windowTitle := "Hello World" ] 
    -- Creates a new button with the label "Hello World". 
    button <- buttonNew 
    set button [ buttonLabel := "Hello World" ] 
    -- When the button receives the "clicked" signal, it will call the 
    -- function given as the second argument. 
    on button buttonActivated (putStrLn "Hello World") 
    -- Gtk+ allows several callbacks for the same event. 
    -- This one will cause the window to be destroyed by calling 
    -- widgetDestroy. The callbacks are called in the sequence they were added. 
    on button buttonActivated $ do 
    putStrLn "A \"clicked\"-handler to say \"destroy\"" 
    widgetDestroy window 
    -- Insert the hello-world button into the window. 
    set window [ containerChild := button ] 
    -- The final step is to display this newly created widget. Note that this 
    -- also allocates the right amount of space to the windows and the button. 
    widgetShowAll window 
    -- All Gtk+ applications must have a main loop. Control ends here 
    -- and waits for an event to occur (like a key press or mouse event). 
    -- This function returns if the program should finish. 
    mainGUI 

Если я построить и запустить это на Mac OS X, Cmd-Q или команда Quit из меню приложения не закрывают приложение. Как заблокировать это событие и заставить его закрыть приложение?

Update

Я добавил gtk3-mac-integration зависимости к моему проекту, в import Graphics.UI.Gtk.OSX к моему исходному файлу и следующий сразу после вызова initGUI:

app <- applicationNew 
on app willTerminate (return()) 

Я определенно что-то отсутствую, как это ничего не делает (см. https://github.com/rcook/gtkapp/commit/8531509d0648ddb657633a33773c09bc5a576014).

Обновление №. 2

Благодаря @Jack Henahan и OSXDemo.hs, теперь у меня есть рабочее решение:

-- A simple program to demonstrate Gtk2Hs. 
module Main (Main.main) where 

import Control.Exception 
import Control.Monad 
import Graphics.UI.Gtk 
import Graphics.UI.Gtk.OSX 

showDialog :: Window -> String -> String -> IO() 
showDialog window title message = bracket 
    (messageDialogNew (Just window) [] MessageInfo ButtonsOk message) 
    widgetDestroy 
    (\d -> do 
     set d [ windowTitle := title ] 
     void $ dialogRun d) 

main :: IO() 
main = do 
    void initGUI 

    -- Create a new window 
    window <- windowNew 

    -- Here we connect the "destroy" event to a signal handler. 
    -- This event occurs when we call widgetDestroy on the window 
    -- or if the user closes the window. 
    void $ on window objectDestroy mainQuit 

    -- Sets the border width and tile of the window. Note that border width 
    -- attribute is in 'Container' from which 'Window' is derived. 
    set window [ containerBorderWidth := 10, windowTitle := "Hello World" ] 

    -- Creates a new button with the label "Hello World". 
    button <- buttonNew 
    set button [ buttonLabel := "Hello World" ] 

    -- When the button receives the "clicked" signal, it will call the 
    -- function given as the second argument. 
    void $ on button buttonActivated (putStrLn "Hello World") 

    void $ on button buttonActivated $ showDialog window "THE-TITLE" "THE-MESSAGE" 

    -- Gtk+ allows several callbacks for the same event. 
    -- This one will cause the window to be destroyed by calling 
    -- widgetDestroy. The callbacks are called in the sequence they were added. 
    void $ on button buttonActivated $ do 
     putStrLn "A \"clicked\"-handler to say \"destroy\"" 
     widgetDestroy window 

    -- Insert the hello-world button into the window. 
    set window [ containerChild := button ] 

    -- The final step is to display this newly created widget. Note that this 
    -- also allocates the right amount of space to the windows and the button. 
    widgetShowAll window 

    app <- applicationNew 

    -- blockTermination: return True to prevent quit, False to allow 
    on app blockTermination $ do 
     putStrLn "blockTermination" 
     return False 

    -- willTerminate: handle clean-up etc. 
    on app willTerminate $ do 
     putStrLn "willTerminate" 

    menuBar <- menuBarNew 
    applicationSetMenuBar app menuBar 
    applicationReady app 

    -- All Gtk+ applications must have a main loop. Control ends here 
    -- and waits for an event to occur (like a key press or mouse event). 
    -- This function returns if the program should finish. 
    mainGUI 

ответ

2

Вам нужно отправить NSApplicationWillTerminate сигнал.

willTerminate :: ApplicationClass self => Signal self (IO()) 
willTerminate = Signal (connect_NONE__NONE "NSApplicationWillTerminate") 

как это обрабатывается в gtk-mac-integration.

+0

Не могли бы вы указать мне конкретный пример использования 'willTerminate'? Я изменил свой первоначальный вопрос, чтобы включить, где я добавил вызов 'willTerminate', но я не знаю, что еще мне не хватает. –

+0

@RichardCook К сожалению, я больше знаком с тем, что ждут приложения OS X, чем о том, как это сделать в GTKHS. Если я запомню некоторые регулярные обсуждения GTK по этой теме, вы можете установить 'applicationSetUseQuartsAccelerators' значение' True', так как это то, что вам связывает 'Cmd + any' bindings, IIRC. Делает ли [демонстрационное приложение] (https://github.com/gtk2hs/gtk-mac-integration/blob/master/demo/OSXDemo.hs) то, что вы ожидаете? Я думаю, что меню не работает, потому что вы должны явно настроить его для отправки 'mainQuit', как это сделано в демо. –

+0

Отлично! Я понял это на основе кода в OSXDemo.hs и соответствующим образом обновил свой вопрос. Благодаря! –