According to the docs onButtonActivate is depreciated so you probably shouldn't use it. Im having trouble finding the correct way though, there probably are some generics signals somewhere that you should use. You can try my solution that uses onPressed and onRelease (these are also noted as depreciated). You could do as suggested in the comment and fork a thread:
import Control.Concurrent (forkIO, killThread, threadDelay)
import Control.Monad (void, when)
whilePressed button action = do
onPressed button $ do
threadId <- forkIO go
onReleased button (killThread threadId)
where
go = do
action
threadDelay 1000000
go
Then rewrite your main to do:
whilePressed but (putStr "A")
Im not sure if this is safe though, as it seems it could be possible for the buttonReleased event to be fired before killThread is registered. It might be safer to use an IORef:
import Data.IORef
whilePressed button action = do
isPressed <- newIORef False
onPressed button $ do
writeIORef isPressed True
void $ forkIO $ go isPressed
onReleased button (writeIORef isPressed False)
where
go isPressed = do
c <- readIORef isPressed
when c $ do
action
threadDelay 1000000
void $ forkIO $ go isPressed
Unfortunately I haven't compiled or tested the code sine I cannot install GTK on this computer, but let me know if you have any issues.