diff --git a/XMonad/Prelude.hs b/XMonad/Prelude.hs index ba10f772..18805fa2 100644 --- a/XMonad/Prelude.hs +++ b/XMonad/Prelude.hs @@ -22,9 +22,16 @@ module XMonad.Prelude ( NonEmpty((:|)), notEmpty, safeGetWindowAttributes, + + -- * Keys keyToString, keymaskToString, cleanKeyMask, + regularKeys, + allSpecialKeys, + specialKeys, + multimediaKeys, + functionKeys, ) where import Foreign (alloca, peek) @@ -42,9 +49,13 @@ import Data.Maybe as Exports import Data.Monoid as Exports import Data.Traversable as Exports +import qualified Data.Map.Strict as Map + +import Control.Arrow ((&&&), first) import Data.Bifunctor (bimap) import Data.Bits import Data.List.NonEmpty (NonEmpty ((:|))) +import Data.Tuple (swap) import GHC.Stack -- | Short for 'fromIntegral'. @@ -86,6 +97,9 @@ safeGetWindowAttributes w = withDisplay $ \dpy -> io . alloca $ \p -> 0 -> pure Nothing _ -> Just <$> peek p +----------------------------------------------------------------------- +-- Keys + -- | Convert a modifier mask into a useful string. keymaskToString :: KeyMask -- ^ Num lock mask -> KeyMask -- ^ Modifier mask @@ -115,8 +129,18 @@ keymaskToString numLockMask msk = -- | Convert a full key combination; i.e., a 'KeyMask' and 'KeySym' -- pair, into a string. -keyToString :: (KeyMask, KeySym) -> [Char] -keyToString = uncurry (++) . bimap (keymaskToString 0) keysymToString +keyToString :: (KeyMask, KeySym) -> String +keyToString = uncurry (++) . bimap (keymaskToString 0) ppKeysym + where + ppKeysym :: KeySym -> String + ppKeysym x = case specialMap Map.!? x of + Just s -> "<" <> s <> ">" + Nothing -> case regularMap Map.!? x of + Nothing -> keysymToString x + Just s -> s + + regularMap = Map.fromList (map swap regularKeys) + specialMap = Map.fromList (map swap allSpecialKeys) -- | Strip numlock, capslock, mouse buttons and XKB group from a 'KeyMask', -- leaving only modifier keys like Shift, Control, Super, Hyper in the mask @@ -132,3 +156,262 @@ cleanKeyMask = cleanKeyMask' <$> gets numberlockMask cleanKeyMask' :: KeyMask -> KeyMask -> KeyMask cleanKeyMask' numLockMask mask = mask .&. complement (numLockMask .|. lockMask) .&. (button1Mask - 1) + +-- | A list of "regular" (extended ASCII) keys. +regularKeys :: [(String, KeySym)] +regularKeys = map (first (:[])) + $ zip ['!' .. '~' ] -- ASCII + [xK_exclam .. xK_asciitilde] + <> zip ['\xa0' .. '\xff' ] -- Latin1 + [xK_nobreakspace .. xK_ydiaeresis] + +-- | A list of all special key names and their associated KeySyms. +allSpecialKeys :: [(String, KeySym)] +allSpecialKeys = functionKeys <> specialKeys <> multimediaKeys + +-- | A list pairing function key descriptor strings (e.g. @\"\"@) +-- with the associated KeySyms. +functionKeys :: [(String, KeySym)] +functionKeys = [ ('F' : show n, k) + | (n,k) <- zip ([1..24] :: [Int]) [xK_F1..] + ] + +-- | A list of special key names and their corresponding KeySyms. +specialKeys :: [(String, KeySym)] +specialKeys = + [ ("Backspace" , xK_BackSpace) + , ("Tab" , xK_Tab) + , ("Return" , xK_Return) + , ("Pause" , xK_Pause) + , ("Num_Lock" , xK_Num_Lock) + , ("Caps_Lock" , xK_Caps_Lock) + , ("Scroll_lock", xK_Scroll_Lock) + , ("Sys_Req" , xK_Sys_Req) + , ("Print" , xK_Print) + , ("Escape" , xK_Escape) + , ("Esc" , xK_Escape) + , ("Delete" , xK_Delete) + , ("Home" , xK_Home) + , ("Left" , xK_Left) + , ("Up" , xK_Up) + , ("Right" , xK_Right) + , ("Down" , xK_Down) + , ("L" , xK_Left) + , ("U" , xK_Up) + , ("R" , xK_Right) + , ("D" , xK_Down) + , ("Page_Up" , xK_Page_Up) + , ("Page_Down" , xK_Page_Down) + , ("End" , xK_End) + , ("Insert" , xK_Insert) + , ("Break" , xK_Break) + , ("Space" , xK_space) + , ("Control_L" , xK_Control_L) + , ("Control_R" , xK_Control_R) + , ("Shift_L" , xK_Shift_L) + , ("Shift_R" , xK_Shift_R) + , ("Alt_L" , xK_Alt_L) + , ("Alt_R" , xK_Alt_R) + , ("Meta_L" , xK_Meta_L) + , ("Meta_R" , xK_Meta_R) + , ("Super_L" , xK_Super_L) + , ("Super_R" , xK_Super_R) + , ("Hyper_L" , xK_Hyper_L) + , ("Hyper_R" , xK_Hyper_R) + , ("KP_Space" , xK_KP_Space) + , ("KP_Tab" , xK_KP_Tab) + , ("KP_Enter" , xK_KP_Enter) + , ("KP_F1" , xK_KP_F1) + , ("KP_F2" , xK_KP_F2) + , ("KP_F3" , xK_KP_F3) + , ("KP_F4" , xK_KP_F4) + , ("KP_Home" , xK_KP_Home) + , ("KP_Left" , xK_KP_Left) + , ("KP_Up" , xK_KP_Up) + , ("KP_Right" , xK_KP_Right) + , ("KP_Down" , xK_KP_Down) + , ("KP_Prior" , xK_KP_Prior) + , ("KP_Page_Up" , xK_KP_Page_Up) + , ("KP_Next" , xK_KP_Next) + , ("KP_Page_Down", xK_KP_Page_Down) + , ("KP_End" , xK_KP_End) + , ("KP_Begin" , xK_KP_Begin) + , ("KP_Insert" , xK_KP_Insert) + , ("KP_Delete" , xK_KP_Delete) + , ("KP_Equal" , xK_KP_Equal) + , ("KP_Multiply", xK_KP_Multiply) + , ("KP_Add" , xK_KP_Add) + , ("KP_Separator", xK_KP_Separator) + , ("KP_Subtract", xK_KP_Subtract) + , ("KP_Decimal" , xK_KP_Decimal) + , ("KP_Divide" , xK_KP_Divide) + , ("KP_0" , xK_KP_0) + , ("KP_1" , xK_KP_1) + , ("KP_2" , xK_KP_2) + , ("KP_3" , xK_KP_3) + , ("KP_4" , xK_KP_4) + , ("KP_5" , xK_KP_5) + , ("KP_6" , xK_KP_6) + , ("KP_7" , xK_KP_7) + , ("KP_8" , xK_KP_8) + , ("KP_9" , xK_KP_9) + ] + +-- | List of multimedia keys. If Xlib does not know about some keysym +-- it's omitted from the list ('stringToKeysym' returns 'noSymbol' in +-- this case). +multimediaKeys :: [(String, KeySym)] +multimediaKeys = filter ((/= noSymbol) . snd) . map (id &&& stringToKeysym) $ + [ "XF86ModeLock" + , "XF86MonBrightnessUp" + , "XF86MonBrightnessDown" + , "XF86KbdLightOnOff" + , "XF86KbdBrightnessUp" + , "XF86KbdBrightnessDown" + , "XF86Standby" + , "XF86AudioLowerVolume" + , "XF86AudioMute" + , "XF86AudioRaiseVolume" + , "XF86AudioPlay" + , "XF86AudioStop" + , "XF86AudioPrev" + , "XF86AudioNext" + , "XF86HomePage" + , "XF86Mail" + , "XF86Start" + , "XF86Search" + , "XF86AudioRecord" + , "XF86Calculator" + , "XF86Memo" + , "XF86ToDoList" + , "XF86Calendar" + , "XF86PowerDown" + , "XF86ContrastAdjust" + , "XF86RockerUp" + , "XF86RockerDown" + , "XF86RockerEnter" + , "XF86Back" + , "XF86Forward" + , "XF86Stop" + , "XF86Refresh" + , "XF86PowerOff" + , "XF86WakeUp" + , "XF86Eject" + , "XF86ScreenSaver" + , "XF86WWW" + , "XF86Sleep" + , "XF86Favorites" + , "XF86AudioPause" + , "XF86AudioMedia" + , "XF86MyComputer" + , "XF86VendorHome" + , "XF86LightBulb" + , "XF86Shop" + , "XF86History" + , "XF86OpenURL" + , "XF86AddFavorite" + , "XF86HotLinks" + , "XF86BrightnessAdjust" + , "XF86Finance" + , "XF86Community" + , "XF86AudioRewind" + , "XF86BackForward" + , "XF86Launch0" + , "XF86Launch1" + , "XF86Launch2" + , "XF86Launch3" + , "XF86Launch4" + , "XF86Launch5" + , "XF86Launch6" + , "XF86Launch7" + , "XF86Launch8" + , "XF86Launch9" + , "XF86LaunchA" + , "XF86LaunchB" + , "XF86LaunchC" + , "XF86LaunchD" + , "XF86LaunchE" + , "XF86LaunchF" + , "XF86ApplicationLeft" + , "XF86ApplicationRight" + , "XF86Book" + , "XF86CD" + , "XF86Calculater" + , "XF86Clear" + , "XF86Close" + , "XF86Copy" + , "XF86Cut" + , "XF86Display" + , "XF86DOS" + , "XF86Documents" + , "XF86Excel" + , "XF86Explorer" + , "XF86Game" + , "XF86Go" + , "XF86iTouch" + , "XF86LogOff" + , "XF86Market" + , "XF86Meeting" + , "XF86MenuKB" + , "XF86MenuPB" + , "XF86MySites" + , "XF86New" + , "XF86News" + , "XF86OfficeHome" + , "XF86Open" + , "XF86Option" + , "XF86Paste" + , "XF86Phone" + , "XF86Q" + , "XF86Reply" + , "XF86Reload" + , "XF86RotateWindows" + , "XF86RotationPB" + , "XF86RotationKB" + , "XF86Save" + , "XF86ScrollUp" + , "XF86ScrollDown" + , "XF86ScrollClick" + , "XF86Send" + , "XF86Spell" + , "XF86SplitScreen" + , "XF86Support" + , "XF86TaskPane" + , "XF86Terminal" + , "XF86Tools" + , "XF86Travel" + , "XF86UserPB" + , "XF86User1KB" + , "XF86User2KB" + , "XF86Video" + , "XF86WheelButton" + , "XF86Word" + , "XF86Xfer" + , "XF86ZoomIn" + , "XF86ZoomOut" + , "XF86Away" + , "XF86Messenger" + , "XF86WebCam" + , "XF86MailForward" + , "XF86Pictures" + , "XF86Music" + , "XF86TouchpadToggle" + , "XF86AudioMicMute" + , "XF86_Switch_VT_1" + , "XF86_Switch_VT_2" + , "XF86_Switch_VT_3" + , "XF86_Switch_VT_4" + , "XF86_Switch_VT_5" + , "XF86_Switch_VT_6" + , "XF86_Switch_VT_7" + , "XF86_Switch_VT_8" + , "XF86_Switch_VT_9" + , "XF86_Switch_VT_10" + , "XF86_Switch_VT_11" + , "XF86_Switch_VT_12" + , "XF86_Ungrab" + , "XF86_ClearGrab" + , "XF86_Next_VMode" + , "XF86_Prev_VMode" + , "XF86Bluetooth" + ] diff --git a/XMonad/Util/EZConfig.hs b/XMonad/Util/EZConfig.hs index 71e54f09..3fd76be7 100644 --- a/XMonad/Util/EZConfig.hs +++ b/XMonad/Util/EZConfig.hs @@ -37,7 +37,6 @@ module XMonad.Util.EZConfig ( parseKeyCombo, parseKeySequence, readKeySequence, #ifdef TESTING - functionKeys, specialKeys, multimediaKeys, parseModifier, #endif ) where @@ -444,268 +443,15 @@ parseKey = parseSpecial <> parseRegular -- | Parse a regular key name (represented by itself). parseRegular :: Parser KeySym -parseRegular = choice [ char s $> k - | (s,k) <- zip ['!' .. '~' ] -- ASCII - [xK_exclam .. xK_asciitilde] - - ++ zip ['\xa0' .. '\xff' ] -- Latin1 - [xK_nobreakspace .. xK_ydiaeresis] - ] +parseRegular = choice [ string s $> k | (s, k) <- regularKeys ] -- | Parse a special key name (one enclosed in angle brackets). parseSpecial :: Parser KeySym parseSpecial = do _ <- char '<' choice [ k <$ string name <* char '>' - | (name, k) <- keyNames + | (name, k) <- allSpecialKeys ] --- | A list of all special key names and their associated KeySyms. -keyNames :: [(String, KeySym)] -keyNames = functionKeys ++ specialKeys ++ multimediaKeys - --- | A list pairing function key descriptor strings (e.g. @\"\"@) with --- the associated KeySyms. -functionKeys :: [(String, KeySym)] -functionKeys = [ ('F' : show n, k) - | (n,k) <- zip ([1..24] :: [Int]) [xK_F1..] ] - --- | A list of special key names and their corresponding KeySyms. -specialKeys :: [(String, KeySym)] -specialKeys = [ ("Backspace" , xK_BackSpace) - , ("Tab" , xK_Tab) - , ("Return" , xK_Return) - , ("Pause" , xK_Pause) - , ("Num_Lock" , xK_Num_Lock) - , ("Caps_Lock" , xK_Caps_Lock) - , ("Scroll_lock", xK_Scroll_Lock) - , ("Sys_Req" , xK_Sys_Req) - , ("Print" , xK_Print) - , ("Escape" , xK_Escape) - , ("Esc" , xK_Escape) - , ("Delete" , xK_Delete) - , ("Home" , xK_Home) - , ("Left" , xK_Left) - , ("Up" , xK_Up) - , ("Right" , xK_Right) - , ("Down" , xK_Down) - , ("L" , xK_Left) - , ("U" , xK_Up) - , ("R" , xK_Right) - , ("D" , xK_Down) - , ("Page_Up" , xK_Page_Up) - , ("Page_Down" , xK_Page_Down) - , ("End" , xK_End) - , ("Insert" , xK_Insert) - , ("Break" , xK_Break) - , ("Space" , xK_space) - , ("Control_L" , xK_Control_L) - , ("Control_R" , xK_Control_R) - , ("Shift_L" , xK_Shift_L) - , ("Shift_R" , xK_Shift_R) - , ("Alt_L" , xK_Alt_L) - , ("Alt_R" , xK_Alt_R) - , ("Meta_L" , xK_Meta_L) - , ("Meta_R" , xK_Meta_R) - , ("Super_L" , xK_Super_L) - , ("Super_R" , xK_Super_R) - , ("Hyper_L" , xK_Hyper_L) - , ("Hyper_R" , xK_Hyper_R) - , ("KP_Space" , xK_KP_Space) - , ("KP_Tab" , xK_KP_Tab) - , ("KP_Enter" , xK_KP_Enter) - , ("KP_F1" , xK_KP_F1) - , ("KP_F2" , xK_KP_F2) - , ("KP_F3" , xK_KP_F3) - , ("KP_F4" , xK_KP_F4) - , ("KP_Home" , xK_KP_Home) - , ("KP_Left" , xK_KP_Left) - , ("KP_Up" , xK_KP_Up) - , ("KP_Right" , xK_KP_Right) - , ("KP_Down" , xK_KP_Down) - , ("KP_Prior" , xK_KP_Prior) - , ("KP_Page_Up" , xK_KP_Page_Up) - , ("KP_Next" , xK_KP_Next) - , ("KP_Page_Down", xK_KP_Page_Down) - , ("KP_End" , xK_KP_End) - , ("KP_Begin" , xK_KP_Begin) - , ("KP_Insert" , xK_KP_Insert) - , ("KP_Delete" , xK_KP_Delete) - , ("KP_Equal" , xK_KP_Equal) - , ("KP_Multiply", xK_KP_Multiply) - , ("KP_Add" , xK_KP_Add) - , ("KP_Separator", xK_KP_Separator) - , ("KP_Subtract", xK_KP_Subtract) - , ("KP_Decimal" , xK_KP_Decimal) - , ("KP_Divide" , xK_KP_Divide) - , ("KP_0" , xK_KP_0) - , ("KP_1" , xK_KP_1) - , ("KP_2" , xK_KP_2) - , ("KP_3" , xK_KP_3) - , ("KP_4" , xK_KP_4) - , ("KP_5" , xK_KP_5) - , ("KP_6" , xK_KP_6) - , ("KP_7" , xK_KP_7) - , ("KP_8" , xK_KP_8) - , ("KP_9" , xK_KP_9) - ] - --- | List of multimedia keys. If X server does not know about some --- | keysym it's omitted from list. (stringToKeysym returns noSymbol in this case) -multimediaKeys :: [(String, KeySym)] -multimediaKeys = filter ((/= noSymbol) . snd) . map (id &&& stringToKeysym) $ - [ "XF86ModeLock" - , "XF86MonBrightnessUp" - , "XF86MonBrightnessDown" - , "XF86KbdLightOnOff" - , "XF86KbdBrightnessUp" - , "XF86KbdBrightnessDown" - , "XF86Standby" - , "XF86AudioLowerVolume" - , "XF86AudioMute" - , "XF86AudioRaiseVolume" - , "XF86AudioPlay" - , "XF86AudioStop" - , "XF86AudioPrev" - , "XF86AudioNext" - , "XF86HomePage" - , "XF86Mail" - , "XF86Start" - , "XF86Search" - , "XF86AudioRecord" - , "XF86Calculator" - , "XF86Memo" - , "XF86ToDoList" - , "XF86Calendar" - , "XF86PowerDown" - , "XF86ContrastAdjust" - , "XF86RockerUp" - , "XF86RockerDown" - , "XF86RockerEnter" - , "XF86Back" - , "XF86Forward" - , "XF86Stop" - , "XF86Refresh" - , "XF86PowerOff" - , "XF86WakeUp" - , "XF86Eject" - , "XF86ScreenSaver" - , "XF86WWW" - , "XF86Sleep" - , "XF86Favorites" - , "XF86AudioPause" - , "XF86AudioMedia" - , "XF86MyComputer" - , "XF86VendorHome" - , "XF86LightBulb" - , "XF86Shop" - , "XF86History" - , "XF86OpenURL" - , "XF86AddFavorite" - , "XF86HotLinks" - , "XF86BrightnessAdjust" - , "XF86Finance" - , "XF86Community" - , "XF86AudioRewind" - , "XF86BackForward" - , "XF86Launch0" - , "XF86Launch1" - , "XF86Launch2" - , "XF86Launch3" - , "XF86Launch4" - , "XF86Launch5" - , "XF86Launch6" - , "XF86Launch7" - , "XF86Launch8" - , "XF86Launch9" - , "XF86LaunchA" - , "XF86LaunchB" - , "XF86LaunchC" - , "XF86LaunchD" - , "XF86LaunchE" - , "XF86LaunchF" - , "XF86ApplicationLeft" - , "XF86ApplicationRight" - , "XF86Book" - , "XF86CD" - , "XF86Calculater" - , "XF86Clear" - , "XF86Close" - , "XF86Copy" - , "XF86Cut" - , "XF86Display" - , "XF86DOS" - , "XF86Documents" - , "XF86Excel" - , "XF86Explorer" - , "XF86Game" - , "XF86Go" - , "XF86iTouch" - , "XF86LogOff" - , "XF86Market" - , "XF86Meeting" - , "XF86MenuKB" - , "XF86MenuPB" - , "XF86MySites" - , "XF86New" - , "XF86News" - , "XF86OfficeHome" - , "XF86Open" - , "XF86Option" - , "XF86Paste" - , "XF86Phone" - , "XF86Q" - , "XF86Reply" - , "XF86Reload" - , "XF86RotateWindows" - , "XF86RotationPB" - , "XF86RotationKB" - , "XF86Save" - , "XF86ScrollUp" - , "XF86ScrollDown" - , "XF86ScrollClick" - , "XF86Send" - , "XF86Spell" - , "XF86SplitScreen" - , "XF86Support" - , "XF86TaskPane" - , "XF86Terminal" - , "XF86Tools" - , "XF86Travel" - , "XF86UserPB" - , "XF86User1KB" - , "XF86User2KB" - , "XF86Video" - , "XF86WheelButton" - , "XF86Word" - , "XF86Xfer" - , "XF86ZoomIn" - , "XF86ZoomOut" - , "XF86Away" - , "XF86Messenger" - , "XF86WebCam" - , "XF86MailForward" - , "XF86Pictures" - , "XF86Music" - , "XF86TouchpadToggle" - , "XF86AudioMicMute" - , "XF86_Switch_VT_1" - , "XF86_Switch_VT_2" - , "XF86_Switch_VT_3" - , "XF86_Switch_VT_4" - , "XF86_Switch_VT_5" - , "XF86_Switch_VT_6" - , "XF86_Switch_VT_7" - , "XF86_Switch_VT_8" - , "XF86_Switch_VT_9" - , "XF86_Switch_VT_10" - , "XF86_Switch_VT_11" - , "XF86_Switch_VT_12" - , "XF86_Ungrab" - , "XF86_ClearGrab" - , "XF86_Next_VMode" - , "XF86_Prev_VMode" - , "XF86Bluetooth" ] - -- | Given a configuration record and a list of (key sequence -- description, action) pairs, check the key sequence descriptions -- for validity, and warn the user (via a popup xmessage window) of