[Xmonad] Re: slock issue
Andrea Rossato
mailing_list at istitutocolli.org
Wed Aug 22 03:13:23 EDT 2007
On Wed, Aug 22, 2007 at 09:55:18AM +0500, Alexander Tsamutali wrote:
> Thanks a lot for your answer and for work on hslock! Hope you can fix
> it.
fixed, sort of: I adopted the same approach of alock: I grab the
keyboard. If I don't get a success back I wait for 1 second and then
retry. The second time never fails, here...
Slock instead tries many time within very small amount of time:
probably this is the reason it fails.
Andrea
ps: attached there's the fixed hslock...;-)
-------------- next part --------------
-----------------------------------------------------------------------------
-- |
-- Module : hslock
-- Copyright : (C) 2007 Andrea Rossato
-- License : BSD3
--
-- Maintainer : andrea.rossato at unibz.it
-- Stability : unstable
-- Portability : unportable
--
-- A simple screen locker in Haskell
--
-- Works only with shadow passords and if set suid root
--
-- Compile with:
--
-- hsc2hs hslock.hsc
-- ghc --make hslock.hs -fglasgow-exts -lcrypt
-----------------------------------------------------------------------------
module Main where
import Control.Monad
import Control.Concurrent
import Data.IORef
import Data.Maybe
import Foreign.C
import Foreign
import System.Environment
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
data Spwd =
Spwd { sp_namp :: CString
, sp_pwdp :: CString
}
#include "shadow.h"
#define _XOPEN_SOURCE
#include "unistd.h"
foreign import ccall unsafe "shodow.h getspnam"
getspan :: CString -> IO (Ptr Spwd)
instance Storable Spwd where
sizeOf _ = #{size struct spwd}
alignment _ = alignment (undefined :: CInt)
peek p = Spwd `fmap` #{peek struct spwd, sp_namp} p
`ap` #{peek struct spwd, sp_pwdp} p
poke p (Spwd n pw) = do
#{poke struct spwd, sp_namp} p n
#{poke struct spwd, sp_pwdp} p pw
getpass :: String -> IO Spwd
getpass name =
withCString name $ \ c_name -> do
s <- throwIfNull "No user entry" $ getspan c_name
peek s
foreign import ccall unsafe "unistd.h crypt"
hcrypt :: CString -> CString -> IO CString
encrypt_pass :: String -> String -> IO String
encrypt_pass key salt = do
withCString key $ \k ->
withCString salt $ \s -> do
e <- hcrypt k s
peekCString e
verifyPWD :: String -> String -> IO Bool
verifyPWD name pass = do
u <- getpass name
pw <- peekCString (sp_pwdp u)
e <- encrypt_pass pass pw
return (pw == e)
main :: IO ()
main = do
s <- newIORef []
d <- catch (getEnv "DISPLAY") ( const $ return [])
dpy <- openDisplay d
let dflt = defaultScreen dpy
scr = defaultScreenOfDisplay dpy
rootw <- rootWindow dpy dflt
win <- mkUnmanagedWindow dpy scr rootw 0 0 (widthOfScreen scr) (heightOfScreen scr)
selectInput dpy win keyPress
mapWindow dpy win
sync dpy False
i <- grabInput dpy win
if i == grabSuccess
then do
eventLoop dpy s
ungrabKeyboard dpy currentTime
ungrabPointer dpy currentTime
else putStrLn "Cannot grab the keyboard!"
destroyWindow dpy win
sync dpy False
grabInput :: Display -> Window -> IO GrabStatus
grabInput dpy win = do
cursor <- createFontCursor dpy 88
grabPointer dpy win False noEventMask grabModeAsync grabModeAsync win cursor currentTime
ks <- grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime
if (ks /= grabSuccess)
then do
threadDelay (1*1000000)
grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime
else return ks
eventLoop :: Display -> IORef String -> IO ()
eventLoop d i = do
(keysym,string,event) <-
allocaXEvent $ \e -> do
maskEvent d keyPressMask e
ev <- getEvent e
(ks,s) <- if ev_event_type ev == keyPress
then lookupString $ asKeyEvent e
else return (Nothing, "")
return (ks,s,ev)
handle d i (fromMaybe xK_VoidSymbol keysym,string) event
type KeyStroke = (KeySym, String)
handle :: Display -> IORef String -> KeyStroke -> Event -> IO ()
handle d i (ks,str) (KeyEvent {ev_event_type = t})
-- Return: check password
| t == keyPress && ks == xK_Return = do
u <- getEnv "USER"
p <- readIORef i
b <- verifyPWD u p
if b then return ()
else modifyIORef i (\_ -> []) >> eventLoop d i
-- Escape: restart
| t == keyPress && ks == xK_Escape = do
modifyIORef i (\_ -> [])
eventLoop d i
| t == keyPress && str == "" = eventLoop d i
| otherwise = do
modifyIORef i (\s -> s ++ str)
eventLoop d i
handle d i _ _ = eventLoop d i
mkUnmanagedWindow :: Display -> Screen -> Window -> Position
-> Position -> Dimension -> Dimension -> IO Window
mkUnmanagedWindow dpy scr rw x y w h = do
let visual = defaultVisualOfScreen scr
attrmask = cWOverrideRedirect .|. cWBackPixel
allocaSetWindowAttributes $
\attributes -> do
set_override_redirect attributes True
set_background_pixel attributes $ blackPixel dpy (defaultScreen dpy)
createWindow dpy rw x y w h 0 (defaultDepthOfScreen scr)
inputOutput visual attrmask attributes
initColor :: Display -> String -> IO Pixel
initColor dpy color = do
let colormap = defaultColormap dpy (defaultScreen dpy)
(apros,_) <- allocNamedColor dpy colormap color
return $ color_pixel apros
More information about the Xmonad
mailing list