91 Commits
v0.5 ... v0.6

Author SHA1 Message Date
Spencer Janssen
2659a12049 depend on xmonad-0.6 2008-01-27 22:11:01 +00:00
Spencer Janssen
3533a5d3f3 Bump version to 0.6 2008-01-27 21:15:04 +00:00
Spencer Janssen
d8baf188db I use urxvtc now 2008-01-27 21:14:52 +00:00
Spencer Janssen
8dcb699db3 Update the test hook 2008-01-27 20:51:48 +00:00
Lukas Mai
4440974718 add 'single' helper function 2008-01-17 23:45:50 +00:00
Lukas Mai
7629022c72 documentation fix 2008-01-17 23:44:01 +00:00
Lukas Mai
9a209f6d55 style assimilation 2008-01-17 23:40:59 +00:00
xmonad-contrib
9a6494fae2 cleared up transience to better highlight how to use ManageHooks properly
The initial patch that extended the EDSL for writing ManageHook rules did not come with a good example on how to use it.  This patch ammends that. 'move' is an example of how to write a rule to resolve a Query (Maybe a) into something tangible.  'move'' is an example of how to write a rule isolating window managing code from the rest ofthe mess the EDSL creates.
2008-01-02 07:48:10 +00:00
xmonad-contrib
f7c34eef31 expands the EDSL for performing actions on windows
This patch adds a few types of relationships and operators for managing windows with rules.  It provides grouping operators so the X action can access the quantifier that was matched or not matched.  It provides a formalism for predicates that work in both grouping and non grouping rules.  It could do with some classes, so that there are fewer operators that always do the Right Thing (TM), but the Haskell Type system currently has some problems resolving types.  Since I don't know enough about these high level things, it would be hard to create a GHC patch just to make it all work.
2008-01-01 17:44:46 +00:00
Spencer Janssen
dec7167bc8 -Werror when flag(testing) only 2008-01-18 01:52:07 +00:00
Andrea Rossato
80f70d284d Timer: some code cleanup 2008-01-14 21:11:14 +00:00
nicolas.pouillard
c7a64a99ce Use doubleFork instead of manual double fork, or buggy single fork.
This fixes showWName because Timer was leaking zombie processes.
You should update xmonad, since doubleFork was not exported.
2008-01-14 20:28:33 +00:00
Brent Yorgey
73502fbbdf Reflect.hs: minor haddock fix 2008-01-16 20:35:46 +00:00
Brent Yorgey
10fbf85a2a Reflect.hs: use -fglasgow-exts for now instead of LANGUAGE pragmas, for compatibility with ghc 6.6 2008-01-15 19:48:11 +00:00
Brent Yorgey
e0024ec9c8 Reflect.hs: add MultiToggle support 2008-01-15 19:35:19 +00:00
Brent Yorgey
670d3160c4 MultiToggle.hs: improve 'description' implementation in LayoutClass instance to display the current transformed layout rather than just 'MultiToggle' 2008-01-15 19:33:11 +00:00
Brent Yorgey
4026d40730 Layout.Reflect: new contrib module for reflecting layouts horizontally/vertically 2008-01-15 03:09:47 +00:00
Brent Yorgey
e76c654211 ShowWName.hs: switch color/bgcolor in call to paintAndWrite 2008-01-14 15:38:21 +00:00
Andrea Rossato
1e7cd73544 Prompt: clean up and optimize moveWord a bit 2008-01-13 16:47:45 +00:00
Andrea Rossato
06b3767cae Prompt: added moveWord to move the cursor to the word boundaries
The actions have been bound to ctrl+Left and Right
2008-01-13 12:35:29 +00:00
Andrea Rossato
1125e9102e Doc.Extending: added links and description of recent module addition 2008-01-13 09:32:11 +00:00
Andrea Rossato
396ae4e77c Action.Search: small haddock fixes 2008-01-13 09:26:46 +00:00
Andrea Rossato
7124346ebe ShowWName now uses Timer and XUtils to display the workspace name 2008-01-13 09:11:07 +00:00
Andrea Rossato
6283298a85 Add XMonad.Util.Timer, a module to set up timers and to handle them 2008-01-13 09:01:40 +00:00
Andrea Rossato
c1a711dba0 de-obfuscate the initState and set the init offset to the length of the default text 2008-01-10 14:09:51 +00:00
nicolas.pouillard
9a4559d2fa prompt: Allow to provide a default text in the prompt config. 2008-01-09 21:39:16 +00:00
Joachim Fasting
9b0a2649b6 Correct caps in module header. 2007-12-30 06:19:20 +00:00
Joachim Fasting
8454e5d6b3 Use LANGUAGE pragma. 2007-12-30 06:18:17 +00:00
mail
35c5c1eaf0 shiftPrevScreen and shiftNextScreen, to make CycleWS consistent 2007-12-31 17:16:09 +00:00
Don Stewart
a0dde418ad formatting 2007-12-04 17:49:20 +00:00
Brent Yorgey
4fbd0c5b3f PerWorkspace.hs: add an explanatory note 2007-12-31 13:58:06 +00:00
Andrea Rossato
926c5ec9d2 Add ShowWName a layout modifier to show the workspace name
This module requires dzen
2007-12-31 13:04:41 +00:00
Andrea Rossato
69453d212a ManageDocks: some documentation fixes 2007-12-31 10:18:20 +00:00
Spencer Janssen
0917d4f5d4 -Wall police (again) 2007-12-28 06:18:41 +00:00
Spencer Janssen
0bf616d2fb -Wall police 2007-12-28 06:18:22 +00:00
mail
4f2feafd04 Fulfill the EWMH specification by listing the supported ATOMs, doesnt really make a differene AFAIK 2007-12-27 21:56:07 +00:00
mail
e153c6d406 display all visible windows on the current desktop in the pager
This is my best shot at modeling xmonad’s WM behaviour in a way that
the Extended Window Manager Hints specification allows.

Unfortunately, we can not tell the panel what size and position it should
think the apps are.
2007-12-27 20:43:49 +00:00
mail
0b1beb1d2b Although I do not need the curr variable after all, this is nicer 2007-12-27 19:01:13 +00:00
mail
54c138c4f0 Add support for cycling through screens to CycleWS 2007-12-27 18:26:35 +00:00
mail
35ea95dc88 Clear _NET_ACTIVE_WINDOW when nothing is focused 2007-12-28 15:42:22 +00:00
Andrea Rossato
6bcefb308b textExtentsXMF doesn't require the display 2007-12-28 12:59:13 +00:00
Spencer Janssen
c6e80350e2 Don't bother checking executable bits of items in $PATH, yields a significant speed-up 2007-12-26 03:24:12 +00:00
Brent Yorgey
24b112c452 ResizableTile.hs: fix resizing to work in the presence of floating windows (resolves issue #100) 2007-12-25 13:58:39 +00:00
Andrea Rossato
c698a58fe6 LayoutScreens: haddock fixes 2007-12-25 10:53:16 +00:00
Andrea Rossato
f6723df7d8 XMonad.Actions.Search: haddock fix 2007-12-24 17:11:15 +00:00
Andrea Rossato
0c835744c2 Fix isssue 105
issue 105 was due to the fact that tab windows created when
bootstrapping the windowset after a restart where managed. Setting the
override_redirect attributes to True fixes the issue.

Added the possibility to set the override_redirect attribute with
XMonad.Util.XUtils.creationNewWindow
2007-12-24 17:10:20 +00:00
gwern0
7e0186ef4e Prompt.hs: mv .xmonad_history into .xmonad/
See my email to mailing list. This will slightly break anyone who upgrades while running and expects to see their prompt history, and leave a stray file, I think, but nothing else, and it'll permanently improve tab-completion, and is tidier.
2007-12-24 05:46:10 +00:00
gwern0
9e28c1ce37 Search.hs: +docs, and export simpleEngine so users can define their own 2007-12-24 04:38:28 +00:00
gwern0
7b3466d9a9 Search.hs: mv into Actions/ per IRC suggestion 2007-12-24 04:37:35 +00:00
Lukas Mai
bf55da2bad add XMonad.Actions.NoBorders 2007-12-20 20:39:53 +00:00
Spencer Janssen
53571aad1e AvoidStruts: add support for partial struts 2007-12-22 13:34:25 +00:00
Brent Yorgey
838c878fa2 Search.hs: add hoogle 2007-12-22 18:49:12 +00:00
Spencer Janssen
feae6b11e5 ManageDocks: ignore desktop windows also 2007-12-22 11:38:08 +00:00
Spencer Janssen
0cca07363d Wibble 2007-12-22 11:06:41 +00:00
Spencer Janssen
4c6f940a1d EwmhDesktops: add _NET_ACTIVE_WINDOW support 2007-12-22 11:05:52 +00:00
Spencer Janssen
44cf0f02c3 A few short comments for WorkspaceCompare 2007-12-22 10:50:45 +00:00
Spencer Janssen
64c9db6bab EwmhDesktops: drop 'Workspace' from displayed workspace names 2007-12-22 10:45:59 +00:00
Spencer Janssen
e11534fa56 Factor workspace sorting into a separate module 2007-12-22 10:41:14 +00:00
Spencer Janssen
662eeb7e5f No more tabs 2007-12-22 05:04:39 +00:00
Spencer Janssen
da6155ebac Refactor Search.hs 2007-12-22 04:47:14 +00:00
Spencer Janssen
edb48ee66c Generalize XSelection functions to MonadIO 2007-12-22 04:45:14 +00:00
gwern0
a5431b3f85 Search.hs: +imdb & amazon engines for unk_red 2007-12-22 03:58:37 +00:00
gwern0
cdf37639e4 Search.hs: cleanup and refactor 2007-12-20 17:40:01 +00:00
Spencer Janssen
9997b18970 Update various restart bindings 2007-12-19 22:06:34 +00:00
Roman Cheplyaka
ef14aa07ba Fix typo. 2007-12-19 07:38:57 +00:00
Brent Yorgey
f20b54067c Doc/Developing.hs: add some information about Haddock documentation. 2007-12-19 21:53:00 +00:00
Brent Yorgey
1a4c17e35e require haddock documentation to build successfully in order to record a patch. 2007-12-19 21:52:17 +00:00
Spencer Janssen
71f87d5804 Remove inaccurate comment about 'banish' 2007-12-17 23:15:40 +00:00
Brent Yorgey
0d5de727c3 Warp.hs: haddock fixes 2007-12-17 22:47:12 +00:00
gwern0
697d9e21b7 Warp.hs: +doc
Describe how to emulate Ratpoison's 'banish' functionality on one's config
2007-12-16 03:00:15 +00:00
Brent Yorgey
2949cbeef4 Util/Search.hs: a few updates/fixes
* fix shadowing warning (ghc 6.8.2 complains)
  * export a few more of the functions
  * re-de-obfuscate generated URLs by not escaping alphanumerics or punct.
2007-12-17 22:29:30 +00:00
gwern0
8925732d5f Util.Search: import escapeURIString, and fall back on the ugly const false hack to avoid copy-pasting even more 2007-12-15 21:16:38 +00:00
David Roundy
ecc2f0d5ec update Config.Droundy to use a few nice hooks. 2007-12-16 18:56:53 +00:00
Shachaf Ben-Kiki
0853c1ce21 Add UrgencyHook support to Tabbed 2007-12-15 17:16:17 +00:00
Brent Yorgey
b95f4daab7 DynamicLog.hs: some documentation updates. 2007-12-15 14:37:27 +00:00
Brent Yorgey
e75a72d63f DynamicLog.hs: fix shadowing warning 2007-12-15 14:32:27 +00:00
Shachaf Ben-Kiki
7064ac5ec9 Add UrgencyHook support to DynamicLog
Someone with Xinerama should look at this -- I don't know exactly how that
should behave.
2007-12-14 04:35:28 +00:00
Spencer Janssen
d4798cf7ae Depend on X11-1.4.1, it has crucial bugfixes 2007-12-15 02:21:51 +00:00
Spencer Janssen
5954f61988 Remove network dependency, potentially breaking XMonad.Util.Search 2007-12-14 23:18:59 +00:00
Brent Yorgey
67ab9fb6ad Search.hs: fix shadowing warning and haddock errors 2007-12-14 16:31:19 +00:00
gwern0
38306b1deb +cabal support for XMonad.Util.Search 2007-12-13 20:56:54 +00:00
gwern0
aba20ccf60 +XMonad.Util.Search: new module
This module is intended to provide helpful functions for easily running web searchs; just hit a bound key, enter your query, and up opens a new tab/browser/window with the search results. In theory anyway; the Wikipedia and Google ones work fine for me, but the Internet Archive's docs on how to do don't necessarily seem to be correct. If you were, like me, previously running shell commands to call Surfraw or similar shell scripts to do the same thing, you can now scrap them and replace them.

There aren't too many search engines defined here; new ones would be good, and they're easy to add!
2007-12-13 20:51:59 +00:00
Spencer Janssen
647c7e9b61 Add support for _NET_WM_STRUT_PARTIAL 2007-12-13 02:17:04 +00:00
Spencer Janssen
2033064db1 ManageDocks: when there are struts on opposing edges, the right/bottom strut
was ignored.  TODO: quickchecks
2007-12-10 02:10:30 +00:00
"Valery V. Vorotyntsev"
dd80c23f56 Run.hs: fix documentation, cleanup whitespace 2007-12-12 09:15:16 +00:00
"Valery V. Vorotyntsev"
fb9a8cfef8 Man.hs: input speedup
Descend manpage directories once -- when `manPrompt' is called.
(Previous version used to search directories upon each character
arrival.)
2007-12-12 09:02:56 +00:00
Lukas Mai
02012aeedd new XMonad.Hooks.ManageHelpers module 2007-12-11 18:30:40 +00:00
intrigeri
ef79fa7c10 Magnifier: custom zoom ratio for magnifier' too 2007-12-11 01:55:54 +00:00
Brent Yorgey
2a73b577c2 Magnifier.hs: minor haddock fixes 2007-12-11 01:11:54 +00:00
tim.thelion
0155164015 fix haddock on Magnifier 2007-12-10 23:19:42 +00:00
tim.thelion
5375240f08 Custom zoom levels for magnifier 2007-12-08 23:08:44 +00:00
42 changed files with 1099 additions and 255 deletions

View File

@@ -88,8 +88,8 @@ defaultCommands = do
, ("expand" , sendMessage Expand ) , ("expand" , sendMessage Expand )
, ("next-layout" , sendMessage NextLayout ) , ("next-layout" , sendMessage NextLayout )
, ("default-layout" , asks (layoutHook . config) >>= setLayout ) , ("default-layout" , asks (layoutHook . config) >>= setLayout )
, ("restart-wm" , sr >> restart Nothing True ) , ("restart-wm" , sr >> restart "xmonad" True )
, ("restart-wm-no-resume", sr >> restart Nothing False ) , ("restart-wm-no-resume", sr >> restart "xmonad" False )
, ("xterm" , spawn =<< asks (terminal . config) ) , ("xterm" , spawn =<< asks (terminal . config) )
, ("run" , spawn "exe=`dmenu_path | dmenu -b` && exec $exe" ) , ("run" , spawn "exe=`dmenu_path | dmenu -b` && exec $exe" )
, ("kill" , kill ) , ("kill" , kill )

View File

@@ -16,9 +16,9 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Actions.ConstrainedResize ( module XMonad.Actions.ConstrainedResize (
-- * Usage -- * Usage
-- $usage -- $usage
XMonad.Actions.ConstrainedResize.mouseResizeWindow XMonad.Actions.ConstrainedResize.mouseResizeWindow
) where ) where
import XMonad import XMonad

View File

@@ -1,4 +1,4 @@
{-# OPTIONS_GHC -fglasgow-exts #-} {-# LANGUAGE PatternGuards #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : XMonad.Actions.CopyWindow -- Module : XMonad.Actions.CopyWindow

View File

@@ -10,7 +10,7 @@
-- Portability : unportable -- Portability : unportable
-- --
-- Provides bindings to cycle forward or backward through the list -- Provides bindings to cycle forward or backward through the list
-- of workspaces, and to move windows there. -- of workspaces, and to move windows there, and to cycle between the screens.
-- --
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
@@ -22,31 +22,38 @@ module XMonad.Actions.CycleWS (
shiftToNext, shiftToNext,
shiftToPrev, shiftToPrev,
toggleWS, toggleWS,
nextScreen,
prevScreen,
shiftNextScreen,
shiftPrevScreen
) where ) where
import Data.List ( sortBy, findIndex ) import Data.List ( findIndex )
import Data.Maybe ( fromMaybe ) import Data.Maybe ( fromMaybe )
import Data.Ord ( comparing )
import XMonad hiding (workspaces) import XMonad hiding (workspaces)
import qualified XMonad (workspaces)
import XMonad.StackSet hiding (filter) import XMonad.StackSet hiding (filter)
import XMonad.Util.WorkspaceCompare
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- --
-- > import XMonad.Actions.CycleWS -- > import XMonad.Actions.CycleWS
-- --
-- > , ((modMask x, xK_Right), nextWS) -- > , ((modMask x, xK_Down), nextWS)
-- > , ((modMask x, xK_Left), prevWS) -- > , ((modMask x, xK_Up), prevWS)
-- > , ((modMask x .|. shiftMask, xK_Right), shiftToNext) -- > , ((modMask x .|. shiftMask, xK_Down), shiftToNext)
-- > , ((modMask x .|. shiftMask, xK_Left), shiftToPrev) -- > , ((modMask x .|. shiftMask, xK_Up), shiftToPrev)
-- > , ((modMask x, xK_Right), nextScreen)
-- > , ((modMask x, xK_Left), prevScreen)
-- > , ((modMask x .|. shiftMask, xK_Right), shiftNextScreen)
-- > , ((modMask x .|. shiftMask, xK_Left), shiftPrevScreen)
-- > , ((modMask x, xK_t), toggleWS) -- > , ((modMask x, xK_t), toggleWS)
-- --
-- If you want to follow the moved window, you can use both actions: -- If you want to follow the moved window, you can use both actions:
-- --
-- > , ((modMask x .|. shiftMask, xK_Right), shiftToNext >> nextWS) -- > , ((modMask x .|. shiftMask, xK_Down), shiftToNext >> nextWS)
-- > , ((modMask x .|. shiftMask, xK_Left), shiftToPrev >> prevWS) -- > , ((modMask x .|. shiftMask, xK_Up), shiftToPrev >> prevWS)
-- --
-- For detailed instructions on editing your key bindings, see -- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings". -- "XMonad.Doc.Extending#Editing_key_bindings".
@@ -81,14 +88,47 @@ shiftBy d = wsBy d >>= windows . shift
wsBy :: Int -> X (WorkspaceId) wsBy :: Int -> X (WorkspaceId)
wsBy d = do wsBy d = do
ws <- gets windowset ws <- gets windowset
spaces <- asks (XMonad.workspaces . config) sort' <- getSortByTag
let orderedWs = sortBy (comparing (wsIndex spaces)) (workspaces ws) let orderedWs = sort' (workspaces ws)
let now = fromMaybe 0 $ findWsIndex (workspace (current ws)) orderedWs let now = fromMaybe 0 $ findWsIndex (workspace (current ws)) orderedWs
let next = orderedWs !! ((now + d) `mod` length orderedWs) let next = orderedWs !! ((now + d) `mod` length orderedWs)
return $ tag next return $ tag next
wsIndex :: [WorkspaceId] -> WindowSpace -> Maybe Int
wsIndex spaces ws = findIndex (== tag ws) spaces
findWsIndex :: WindowSpace -> [WindowSpace] -> Maybe Int findWsIndex :: WindowSpace -> [WindowSpace] -> Maybe Int
findWsIndex ws wss = findIndex ((== tag ws) . tag) wss findWsIndex ws wss = findIndex ((== tag ws) . tag) wss
-- | View next screen
nextScreen :: X ()
nextScreen = switchScreen 1
-- | View prev screen
prevScreen :: X ()
prevScreen = switchScreen (-1)
switchScreen :: Int -> X ()
switchScreen d = do s <- screenBy d
mws <- screenWorkspace s
case mws of
Nothing -> return ()
Just ws -> windows (view ws)
screenBy :: Int -> X (ScreenId)
screenBy d = do ws <- gets windowset
--let ss = sortBy screen (screens ws)
let now = screen (current ws)
return $ (now + fromIntegral d) `mod` fromIntegral (length (screens ws))
-- | Move focused window to workspace on next screen
shiftNextScreen :: X ()
shiftNextScreen = shiftScreenBy 1
-- | Move focused window to workspace on prev screen
shiftPrevScreen :: X ()
shiftPrevScreen = shiftScreenBy (-1)
shiftScreenBy :: Int -> X ()
shiftScreenBy d = do s <- screenBy d
mws <- screenWorkspace s
case mws of
Nothing -> return ()
Just ws -> windows (shift ws)

View File

@@ -17,9 +17,9 @@
-- Based on the FlexibleResize code by Lukas Mai (mauke). -- Based on the FlexibleResize code by Lukas Mai (mauke).
module XMonad.Actions.FlexibleManipulate ( module XMonad.Actions.FlexibleManipulate (
-- * Usage -- * Usage
-- $usage -- $usage
mouseWindow, discrete, linear, resize, position mouseWindow, discrete, linear, resize, position
) where ) where
import XMonad import XMonad

View File

@@ -13,9 +13,9 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Actions.FlexibleResize ( module XMonad.Actions.FlexibleResize (
-- * Usage -- * Usage
-- $usage -- $usage
XMonad.Actions.FlexibleResize.mouseResizeWindow XMonad.Actions.FlexibleResize.mouseResizeWindow
) where ) where
import XMonad import XMonad

View File

@@ -38,12 +38,13 @@ focusNth :: Int -> X ()
focusNth = windows . modify' . focusNth' focusNth = windows . modify' . focusNth'
focusNth' :: Int -> Stack a -> Stack a focusNth' :: Int -> Stack a -> Stack a
focusNth' n s@(Stack _ ls rs) | (n < 0) || (n > length(ls) + length(rs)) = s focusNth' n s@(Stack _ ls rs) | (n < 0) || (n > length(ls) + length(rs)) = s
| otherwise = listToStack n (integrate s) | otherwise = listToStack n (integrate s)
listToStack :: Int -> [a] -> Stack a listToStack :: Int -> [a] -> Stack a
listToStack n l = Stack t ls rs listToStack n l = Stack t ls rs
where (t:rs) = drop n l where
ls = reverse (take n l) (t:rs) = drop n l
ls = reverse (take n l)

View File

@@ -15,7 +15,7 @@
module XMonad.Actions.MouseGestures ( module XMonad.Actions.MouseGestures (
-- * Usage -- * Usage
-- $usage -- $usage
Direction(..), Direction(..),
mouseGesture mouseGesture
) where ) where

View File

@@ -0,0 +1,33 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.NoBorders
-- Copyright : (c) Lukas Mai
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Lukas Mai <l.mai@web.de>
-- Stability : unstable
-- Portability : unportable
--
-- This module provides helper functions for dealing with window borders.
--
-----------------------------------------------------------------------------
module XMonad.Actions.NoBorders (
toggleBorder
) where
import XMonad
-- | Toggle the border of the currently focused window. To use it, add a
-- keybinding like so:
--
-- > , ((modMask x, xK_g ), withFocused toggleBorder)
--
toggleBorder :: Window -> X ()
toggleBorder w = do
bw <- asks (borderWidth . config)
withDisplay $ \d -> io $ do
cw <- wa_border_width `fmap` getWindowAttributes d w
if cw == 0
then setWindowBorderWidth d w bw
else setWindowBorderWidth d w 0

View File

@@ -12,10 +12,10 @@
-- place. -- place.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Actions.RotSlaves ( module XMonad.Actions.RotSlaves (
-- $usage -- $usage
rotSlaves', rotSlavesUp, rotSlavesDown, rotSlaves', rotSlavesUp, rotSlavesDown,
rotAll', rotAllUp, rotAllDown rotAll', rotAllUp, rotAllDown
) where ) where
import XMonad.StackSet import XMonad.StackSet
import XMonad import XMonad

138
XMonad/Actions/Search.hs Normal file
View File

@@ -0,0 +1,138 @@
{- |
Module : XMonad.Actions.Search
Copyright : (C) 2007 Gwern Branwen
License : None; public domain
Maintainer : <gwern0@gmail.com>
Stability : unstable
Portability : unportable
A module for easily running Internet searches on web sites through XMonad.
Modeled after the handy Surfraw CLI search tools
<https://secure.wikimedia.org/wikipedia/en/wiki/Surfraw>.
Additional sites welcomed.
-}
module XMonad.Actions.Search ( -- * Usage
-- $usage
search,
simpleEngine,
promptSearch,
selectSearch,
amazon,
google,
imdb,
wayback,
wikipedia,
hoogle
) where
import Data.Char (chr, ord, isAlpha, isMark, isDigit)
import Numeric (showIntAtBase)
import XMonad (X(), MonadIO)
import XMonad.Prompt (XPrompt(showXPrompt), mkXPrompt, XPConfig())
import XMonad.Prompt.Shell (getShellCompl)
import XMonad.Util.Run (safeSpawn)
import XMonad.Util.XSelection (getSelection)
{- $usage
This module is intended to allow easy access to databases on the Internet
through XMonad's interface. The idea is that one wants to run a search but the
query string and the browser to use must come from somewhere. There are two
places the query string can come from - the user can type it into a prompt
which pops up, or the query could be available already in the X Windows
copy\/paste buffer (perhaps you just highlighted the string of interest).
Thus, there are two main functions: 'promptSearch', and 'selectSearch'
(implemented using the more primitive 'search'). To each of these is passed an
engine function; this is a function that knows how to search a particular
site.
For example, the 'google' function knows how to search Google, and so on. You pass
promptSearch and selectSearch the engine you want, the browser you want, and
anything special they might need; this whole line is then bound to a key of
you choosing in your xmonad.hs. For specific examples, see each function.
This module is easily extended to new sites by using 'simpleEngine'.
-}
-- A customized prompt.
data Search = Search
instance XPrompt Search where
showXPrompt Search = "Search: "
-- | Escape the search string so search engines understand it.
-- Note that everything is escaped; we could be smarter and use 'isAllowedInURI'
-- but then that'd be hard enough to copy-and-paste we'd need to depend on 'network'.
escape :: String -> String
escape = escapeURIString (\c -> isAlpha c || isDigit c || isMark c)
where -- Copied from Network.URI.
escapeURIString ::
(Char -> Bool) -- a predicate which returns 'False' if should escape
-> String -- the string to process
-> String -- the resulting URI string
escapeURIString p s = concatMap (escapeURIChar p) s
escapeURIChar :: (Char->Bool) -> Char -> String
escapeURIChar p c
| p c = [c]
| otherwise = '%' : myShowHex (ord c) ""
where
myShowHex :: Int -> ShowS
myShowHex n r = case showIntAtBase 16 (toChrHex) n r of
[] -> "00"
[ch] -> ['0',ch]
cs -> cs
toChrHex d
| d < 10 = chr (ord '0' + fromIntegral d)
| otherwise = chr (ord 'A' + fromIntegral (d - 10))
type Browser = FilePath
type SearchEngine = String -> String
search :: MonadIO m => Browser -> SearchEngine -> String -> m ()
search browser site query = safeSpawn browser $ site query
{- | Given a base URL, create the SearchEngine that escapes the query and
appends it to the base. You can easily define a new engine locally using simpleEngine
without needing to modify Search.hs:
> newEngine = simpleEngine "http://site.com/search="
The important thing is that the site has a interface which accepts the query
string as part of the URL. Alas, the exact URL to feed simpleEngine varies
from site to site, often considerably. Generally, examining the resultant URL
of a search will allow you to reverse-engineer it if you can't find the
necessary URL already described in other projects such as Surfraw. -}
simpleEngine :: String -> SearchEngine
simpleEngine site query = site ++ escape query
-- The engines
amazon, google, hoogle, imdb, wayback, wikipedia :: SearchEngine
amazon = simpleEngine "http://www.amazon.com/exec/obidos/external-search?index=all&keyword="
google = simpleEngine "http://www.google.com/search?num=100&q="
hoogle = simpleEngine "http://www.haskell.org/hoogle/?q="
imdb = simpleEngine "http://www.imdb.com/Find?select=all&for="
wikipedia = simpleEngine "https://secure.wikimedia.org/wikipedia/en/wiki/Special:Search?go=Go&search="
wayback = simpleEngine "http://web.archive.org/"
{- This doesn't seem to work, but nevertheless, it seems to be the official
method at <http://web.archive.org/collections/web/advanced.html> to get the
latest backup. -}
{- | Like 'search', but in this case, the string is not specified but grabbed
from the user's response to a prompt. Example:
> , ((modm, xK_g ), promptSearch greenXPConfig "firefox" google)
-}
promptSearch :: XPConfig -> Browser -> SearchEngine -> X ()
promptSearch config browser site = mkXPrompt Search config (getShellCompl []) $ search browser site
{- | Like search, but for use with the X selection; it grabs the selection,
passes it to a given searchEngine and opens it in the given browser. Example:
> , ((modm .|. shiftMask, xK_g ), selectSearch "firefox" google)
-}
selectSearch :: MonadIO m => Browser -> SearchEngine -> m ()
selectSearch browser searchEngine = search browser searchEngine =<< getSelection

View File

@@ -1,6 +1,6 @@
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : Xmonad.Actions.SinkAll -- Module : XMonad.Actions.SinkAll
-- License : BSD3-style (see LICENSE) -- License : BSD3-style (see LICENSE)
-- Stability : unstable -- Stability : unstable
-- Portability : unportable -- Portability : unportable

View File

@@ -39,6 +39,14 @@ then add appropriate keybindings to warp the pointer; for example:
> | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]] > | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]]
Note that warping to a particular screen may change the focus. Note that warping to a particular screen may change the focus.
'warpToScreen' and 'warpToWindow' can be used in a variety of
ways. Suppose you wanted to emulate Ratpoison's \'banish\' command,
which moves the mouse pointer to a corner; you could define:
> banish :: X ()
> banish = warpToWindow 1 1 -- lower left
-} -}
-- For detailed instructions on editing your key bindings, see -- For detailed instructions on editing your key bindings, see

View File

@@ -41,8 +41,8 @@ import XMonad.Actions.CopyWindow
import XMonad.Actions.DynamicWorkspaces import XMonad.Actions.DynamicWorkspaces
import XMonad.Actions.RotView import XMonad.Actions.RotView
--import XMonad.Hooks.ManageDocks import XMonad.Hooks.ManageDocks
--import XMonad.Hooks.UrgencyHook import XMonad.Hooks.UrgencyHook
myXPConfig :: XPConfig myXPConfig :: XPConfig
myXPConfig = defaultXPConfig {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*" myXPConfig = defaultXPConfig {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*"
@@ -77,7 +77,7 @@ keys x = M.fromList $
-- quit, or restart -- quit, or restart
, ((modMask x .|. shiftMask, xK_Escape), io (exitWith ExitSuccess)) -- %! Quit xmonad , ((modMask x .|. shiftMask, xK_Escape), io (exitWith ExitSuccess)) -- %! Quit xmonad
, ((modMask x , xK_Escape), broadcastMessage ReleaseResources >> restart (Just "xmonad") True) -- %! Restart xmonad , ((modMask x , xK_Escape), restart "xmonad" True) -- %! Restart xmonad
, ((modMask x .|. shiftMask, xK_z ), , ((modMask x .|. shiftMask, xK_z ),
layoutScreens 1 (fixedLayout [Rectangle 0 0 1024 768])) layoutScreens 1 (fixedLayout [Rectangle 0 0 1024 768]))
@@ -127,13 +127,15 @@ keys x = M.fromList $
zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..]) zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..])
config = -- withUrgencyHook FocusUrgencyHook $ config = -- withUrgencyHook FocusUrgencyHook $
withUrgencyHook NoUrgencyHook $
defaultConfig defaultConfig
{ borderWidth = 1 -- Width of the window border in pixels. { borderWidth = 1 -- Width of the window border in pixels.
, XMonad.workspaces = ["1:mutt","2:iceweasel"] , XMonad.workspaces = ["1:mutt","2:iceweasel"]
, layoutHook = workspaceDir "~" $ windowNavigation $ , layoutHook = workspaceDir "~" $ windowNavigation $
toggleLayouts (noBorders Full) $ -- avoidStruts $ toggleLayouts (noBorders Full) $ avoidStruts $
Named "tabbed" (noBorders mytab) ||| Named "tabbed" (noBorders mytab) |||
Named "xclock" (mytab ****//* combineTwo Square mytab mytab) ||| Named "xclock" (mytab ****//* combineTwo Square mytab mytab) |||
Named "three" (mytab **//* mytab *//* combineTwo Square mytab mytab) |||
Named "widescreen" ((mytab *||* mytab) Named "widescreen" ((mytab *||* mytab)
****//* combineTwo Square mytab mytab) -- ||| ****//* combineTwo Square mytab mytab) -- |||
--mosaic 0.25 0.5 --mosaic 0.25 0.5

View File

@@ -20,7 +20,7 @@ import System.IO (hPutStrLn)
sjanssenConfig = do sjanssenConfig = do
xmobar <- spawnPipe "xmobar" xmobar <- spawnPipe "xmobar"
return $ defaultConfig return $ defaultConfig
{ terminal = "urxvt" { terminal = "urxvtc"
, workspaces = ["irc", "web"] ++ map show [3 .. 7 :: Int] ++ ["mail", "im"] , workspaces = ["irc", "web"] ++ map show [3 .. 7 :: Int] ++ ["mail", "im"]
, logHook = dynamicLogWithPP $ sjanssenPP { ppOutput = hPutStrLn xmobar } , logHook = dynamicLogWithPP $ sjanssenPP { ppOutput = hPutStrLn xmobar }
, modMask = mod4Mask , modMask = mod4Mask

View File

@@ -178,7 +178,7 @@ a (possibly empty) 'XMonad.StackSet.stack' of windows.
"XMonad.StackSet" (which should usually be imported qualified, to "XMonad.StackSet" (which should usually be imported qualified, to
avoid name clashes with Prelude functions such as 'Prelude.delete' and avoid name clashes with Prelude functions such as 'Prelude.delete' and
'Prelude.filter') provides many pure functions to manipulate the 'Prelude.filter') provides many pure functions to manipulate the
'XMonad.StackSet.StackSet'. These functions are most commonlyq used as 'XMonad.StackSet.StackSet'. These functions are most commonly used as
an argument to 'XMonad.Operations.windows', which takes a pure an argument to 'XMonad.Operations.windows', which takes a pure
function to manipulate the 'XMonad.Core.WindowSet' and does all the function to manipulate the 'XMonad.Core.WindowSet' and does all the
needed operations to refresh the screen and save the modified needed operations to refresh the screen and save the modified
@@ -246,7 +246,7 @@ xmonad contributed extensions.
* Comment every top level function (particularly exported funtions), and * Comment every top level function (particularly exported funtions), and
provide a type signature. provide a type signature.
* Use Haddock syntax in the comments. * Use Haddock syntax in the comments (see below).
* Follow the coding style of the other modules. * Follow the coding style of the other modules.
@@ -260,6 +260,31 @@ xmonad contributed extensions.
* Any pure function added to the core should have QuickCheck properties * Any pure function added to the core should have QuickCheck properties
precisely defining its behaviour. precisely defining its behaviour.
For examples of Haddock documentation syntax, have a look at other
extensions. Important points are:
* Every exported function (or even better, every function) should have
a Haddock comment explaining what it does.
* Literal chunks of code can be written in comments using
\"birdtrack\" notation (a greater-than symbol at the beginning of
each line). Be sure to leave a blank line before and after each
birdtrack-quoted section.
* Link to functions by surrounding the names in single quotes, modules
in double quotes.
* Literal quote marks and slashes should be escaped with a backslash.
To generate and view the Haddock documentation for your extension, run
> runhaskell Setup haddock
and then point your browser to @\/path\/to\/XMonadContrib\/dist\/doc\/html\/xmonad-contrib\/index.html@.
For more information, see the Haddock documentation:
<http://www.haskell.org/haddock/haddock-html-0.8/index.html>.
-} -}
{- $license {- $license

View File

@@ -152,6 +152,9 @@ edit your key bindings.
* "XMonad.Actions.RotView": cycle through non-empty workspaces. * "XMonad.Actions.RotView": cycle through non-empty workspaces.
* "XMonad.Actions.Search": provide helpful functions for easily
running web searchs.
* "XMonad.Actions.SimpleDate": display the date in a popup menu. * "XMonad.Actions.SimpleDate": display the date in a popup menu.
* "XMonad.Actions.SinkAll": sink all floating windows. * "XMonad.Actions.SinkAll": sink all floating windows.
@@ -226,6 +229,9 @@ Here is a list of the modules found in @XMonad.Hooks@:
* "XMonad.Hooks.ManageDocks": handle DOCK and STRUT windows appropriately. * "XMonad.Hooks.ManageDocks": handle DOCK and STRUT windows appropriately.
* "XMonad.Hooks.ManageHelpers": provide helper functions to be used
in @manageHook@.
* "XMonad.Hooks.SetWMName": set the WM name. Useful when e.g. running * "XMonad.Hooks.SetWMName": set the WM name. Useful when e.g. running
Java GUI programs. Java GUI programs.
@@ -307,6 +313,8 @@ For more information on using those modules for customizing your
* "XMonad.Layout.Roledex": a \"completely pointless layout which acts * "XMonad.Layout.Roledex": a \"completely pointless layout which acts
like Microsoft's Flip 3D\". like Microsoft's Flip 3D\".
* "XMonad.Layout.ShowWName": Show the name of the current workspace when switching.
* "XMonad.Layout.Spiral": Fibonacci spiral layout. * "XMonad.Layout.Spiral": Fibonacci spiral layout.
* "XMonad.Layout.Square": split the screen into a square area plus the rest. * "XMonad.Layout.Square": split the screen into a square area plus the rest.

View File

@@ -10,11 +10,12 @@
-- --
-- DynamicLog -- DynamicLog
-- --
-- Log events in: -- By default, log events in:
-- --
-- > 1 2 [3] 4 8 -- > 1 2 [3] 4 8
-- --
-- format. Suitable to pipe into dzen. -- format, although the format is highly customizable.
-- Suitable to pipe into dzen or xmobar.
-- --
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
@@ -45,10 +46,11 @@ import Data.Maybe ( isJust )
import Data.List import Data.List
import Data.Ord ( comparing ) import Data.Ord ( comparing )
import qualified XMonad.StackSet as S import qualified XMonad.StackSet as S
import Data.Monoid
import System.IO import System.IO
import XMonad.Util.WorkspaceCompare
import XMonad.Util.NamedWindows import XMonad.Util.NamedWindows
import XMonad.Util.Run import XMonad.Util.Run
import XMonad.Hooks.UrgencyHook
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -104,13 +106,15 @@ dynamicLog = dynamicLogWithPP defaultPP
-- A log function that uses the 'PP' hooks to customize output. -- A log function that uses the 'PP' hooks to customize output.
dynamicLogWithPP :: PP -> X () dynamicLogWithPP :: PP -> X ()
dynamicLogWithPP pp = do dynamicLogWithPP pp = do
spaces <- asks (workspaces . config) winset <- gets windowset
urgents <- readUrgents
sort' <- getSortByTag
-- layout description -- layout description
ld <- withWindowSet $ return . description . S.layout . S.workspace . S.current let ld = description . S.layout . S.workspace . S.current $ winset
-- workspace list -- workspace list
ws <- withWindowSet $ return . pprWindowSet spaces pp let ws = pprWindowSet sort' urgents pp winset
-- window title -- window title
wt <- withWindowSet $ maybe (return "") (fmap show . getName) . S.peek wt <- maybe (return "") (fmap show . getName) . S.peek $ winset
io . ppOutput pp . sepBy (ppSep pp) . ppOrder pp $ io . ppOutput pp . sepBy (ppSep pp) . ppOrder pp $
[ ws [ ws
@@ -124,27 +128,18 @@ dynamicLogWithPP pp = do
dynamicLogDzen :: X () dynamicLogDzen :: X ()
dynamicLogDzen = dynamicLogWithPP dzenPP dynamicLogDzen = dynamicLogWithPP dzenPP
pprWindowSet :: ([WindowSpace] -> [WindowSpace]) -> [Window] -> PP -> WindowSet -> String
pprWindowSet :: [String] -> PP -> WindowSet -> String pprWindowSet sort' urgents pp s = sepBy (ppWsSep pp) . map fmt . sort' $
pprWindowSet spaces pp s = sepBy (ppWsSep pp) $ map fmt $ sortBy cmp map S.workspace (S.current s : S.visible s) ++ S.hidden s
(map S.workspace (S.current s : S.visible s) ++ S.hidden s) where this = S.tag (S.workspace (S.current s))
where f Nothing Nothing = EQ
f (Just _) Nothing = LT
f Nothing (Just _) = GT
f (Just x) (Just y) = compare x y
wsIndex = flip elemIndex spaces . S.tag
cmp a b = f (wsIndex a) (wsIndex b) `mappend` compare (S.tag a) (S.tag b)
this = S.tag (S.workspace (S.current s))
visibles = map (S.tag . S.workspace) (S.visible s) visibles = map (S.tag . S.workspace) (S.visible s)
fmt w = printer pp (S.tag w) fmt w = printer pp (S.tag w)
where printer | S.tag w == this = ppCurrent where printer | S.tag w == this = ppCurrent
| S.tag w `elem` visibles = ppVisible | S.tag w `elem` visibles = ppVisible
| isJust (S.stack w) = ppHidden | any (\x -> maybe False (== S.tag w) (S.findTag x s)) urgents = \ppC -> ppUrgent ppC . ppHidden ppC
| otherwise = ppHiddenNoWindows | isJust (S.stack w) = ppHidden
| otherwise = ppHiddenNoWindows
-- | -- |
-- Workspace logger with a format designed for Xinerama: -- Workspace logger with a format designed for Xinerama:
@@ -198,7 +193,8 @@ xmobarColor fg bg = wrap t "</fc>"
-- | The 'PP' type allows the user to customize various behaviors of -- | The 'PP' type allows the user to customize various behaviors of
-- dynamicLogPP -- dynamicLogPP
data PP = PP { ppCurrent, ppVisible data PP = PP { ppCurrent, ppVisible
, ppHidden, ppHiddenNoWindows :: WorkspaceId -> String , ppHidden, ppHiddenNoWindows
, ppUrgent :: WorkspaceId -> String
, ppSep, ppWsSep :: String , ppSep, ppWsSep :: String
, ppTitle :: String -> String , ppTitle :: String -> String
, ppLayout :: String -> String , ppLayout :: String -> String
@@ -212,6 +208,7 @@ defaultPP = PP { ppCurrent = wrap "[" "]"
, ppVisible = wrap "<" ">" , ppVisible = wrap "<" ">"
, ppHidden = id , ppHidden = id
, ppHiddenNoWindows = const "" , ppHiddenNoWindows = const ""
, ppUrgent = id
, ppSep = " : " , ppSep = " : "
, ppWsSep = " " , ppWsSep = " "
, ppTitle = shorten 80 , ppTitle = shorten 80
@@ -226,6 +223,7 @@ dzenPP = defaultPP { ppCurrent = dzenColor "white" "#2b4f98" . pad
, ppVisible = dzenColor "black" "#999999" . pad , ppVisible = dzenColor "black" "#999999" . pad
, ppHidden = dzenColor "black" "#cccccc" . pad , ppHidden = dzenColor "black" "#cccccc" . pad
, ppHiddenNoWindows = const "" , ppHiddenNoWindows = const ""
, ppUrgent = dzenColor "red" "yellow"
, ppWsSep = "" , ppWsSep = ""
, ppSep = "" , ppSep = ""
, ppLayout = dzenColor "black" "#cccccc" . , ppLayout = dzenColor "black" "#cccccc" .

View File

@@ -17,15 +17,15 @@ module XMonad.Hooks.EwmhDesktops (
ewmhDesktopsLogHook ewmhDesktopsLogHook
) where ) where
import Data.List (elemIndex, sortBy) import Data.List
import Data.Ord (comparing) import Data.Maybe
import Data.Maybe (fromMaybe)
import XMonad import XMonad
import Control.Monad import Control.Monad
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import XMonad.Hooks.SetWMName import XMonad.Hooks.SetWMName
import XMonad.Util.WorkspaceCompare
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -48,9 +48,8 @@ import XMonad.Hooks.SetWMName
-- of the current state of workspaces and windows. -- of the current state of workspaces and windows.
ewmhDesktopsLogHook :: X () ewmhDesktopsLogHook :: X ()
ewmhDesktopsLogHook = withWindowSet $ \s -> do ewmhDesktopsLogHook = withWindowSet $ \s -> do
-- Bad hack because xmonad forgets the original order of things, it seems sort' <- getSortByTag
-- see http://code.google.com/p/xmonad/issues/detail?id=53 let ws = sort' $ W.workspaces s
let ws = sortBy (comparing W.tag) $ W.workspaces s
let wins = W.allWindows s let wins = W.allWindows s
setSupported setSupported
@@ -62,18 +61,26 @@ ewmhDesktopsLogHook = withWindowSet $ \s -> do
setDesktopNames (map W.tag ws) setDesktopNames (map W.tag ws)
-- Current desktop -- Current desktop
fromMaybe (return ()) $ do let curr = fromJust $ elemIndex (W.tag (W.workspace (W.current s))) $ map W.tag ws
n <- W.lookupWorkspace 0 s
i <- elemIndex n $ map W.tag ws setCurrentDesktop curr
return $ setCurrentDesktop i
setClientList wins setClientList wins
-- Per window Desktop -- Per window Desktop
forM (zip ws [(0::Int)..]) $ \(w, wn) -> -- To make gnome-panel accept our xinerama stuff, we display
forM (W.integrate' (W.stack w)) $ \win -> do -- all visible windows on the current desktop.
forM_ (W.current s : W.visible s) $ \x ->
forM_ (W.integrate' (W.stack (W.workspace x))) $ \win -> do
setWindowDesktop win curr
forM_ (W.hidden s) $ \w ->
let wn = fromJust $ elemIndex (W.tag w) (map W.tag ws) in
forM_ (W.integrate' (W.stack w)) $ \win -> do
setWindowDesktop win wn setWindowDesktop win wn
setActiveWindow
return () return ()
@@ -98,7 +105,7 @@ setDesktopNames names = withDisplay $ \dpy -> do
a <- getAtom "_NET_DESKTOP_NAMES" a <- getAtom "_NET_DESKTOP_NAMES"
c <- getAtom "UTF8_STRING" c <- getAtom "UTF8_STRING"
let names' = map (fromIntegral.fromEnum) $ let names' = map (fromIntegral.fromEnum) $
concatMap (("Workspace "++) . (++['\0'])) names concatMap (++['\0']) names
io $ changeProperty8 dpy r a c propModeReplace names' io $ changeProperty8 dpy r a c propModeReplace names'
setClientList :: [Window] -> X () setClientList :: [Window] -> X ()
@@ -122,9 +129,23 @@ setSupported = withDisplay $ \dpy -> do
r <- asks theRoot r <- asks theRoot
a <- getAtom "_NET_SUPPORTED" a <- getAtom "_NET_SUPPORTED"
c <- getAtom "ATOM" c <- getAtom "ATOM"
supp <- mapM getAtom ["_NET_WM_STATE_HIDDEN"] supp <- mapM getAtom ["_NET_WM_STATE_HIDDEN"
,"_NET_NUMBER_OF_DESKTOPS"
,"_NET_CLIENT_LIST"
,"_NET_CURRENT_DESKTOP"
,"_NET_DESKTOP_NAMES"
,"_NET_ACTIVE_WINDOW"
,"_NET_WM_DESKTOP"
,"_NET_WM_STRUT"
]
io $ changeProperty32 dpy r a c propModeReplace (fmap fromIntegral supp) io $ changeProperty32 dpy r a c propModeReplace (fmap fromIntegral supp)
setWMName "xmonad" setWMName "xmonad"
setActiveWindow :: X ()
setActiveWindow = withWindowSet $ \s -> withDisplay $ \dpy -> do
let w = fromMaybe 0 (W.peek s)
r <- asks theRoot
a <- getAtom "_NET_ACTIVE_WINDOW"
c <- getAtom "WINDOW"
io $ changeProperty32 dpy r a c propModeReplace [fromIntegral w]

View File

@@ -24,7 +24,9 @@ module XMonad.Hooks.ManageDocks (
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
import XMonad import XMonad
import Foreign.C.Types (CLong) import Foreign.C.Types (CLong)
import Data.Maybe (catMaybes) -- import Data.Maybe (catMaybes, fromMaybe)
import Control.Monad
-- $usage -- $usage
-- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@: -- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@:
-- --
@@ -40,12 +42,15 @@ import Data.Maybe (catMaybes)
-- so-called "gap" support. First, you must add it to your list of layouts: -- so-called "gap" support. First, you must add it to your list of layouts:
-- --
-- > layoutHook = avoidStruts (tall ||| mirror tall ||| ...) -- > layoutHook = avoidStruts (tall ||| mirror tall ||| ...)
-- > where tall = Tall 1 (3/100) (1/2)
-- --
-- 'AvoidStruts' also supports toggling the dock gap, add a keybinding similar -- 'AvoidStruts' also supports toggling the dock gap, add a keybinding similar
-- to: -- to:
-- --
-- > ,((modMask, xK_b ), sendMessage ToggleStruts) -- > ,((modMask x, xK_b ), sendMessage ToggleStruts)
-- --
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- | -- |
-- Detects if the given window is of type DOCK and if so, reveals it, but does -- Detects if the given window is of type DOCK and if so, reveals it, but does
@@ -54,29 +59,35 @@ manageDocks :: ManageHook
manageDocks = checkDock --> doIgnore manageDocks = checkDock --> doIgnore
-- | -- |
-- Checks if a window is a DOCK window -- Checks if a window is a DOCK or DESKTOP window
checkDock :: Query Bool checkDock :: Query Bool
checkDock = ask >>= \w -> liftX $ do checkDock = ask >>= \w -> liftX $ do
a <- getAtom "_NET_WM_WINDOW_TYPE" a <- getAtom "_NET_WM_WINDOW_TYPE"
d <- getAtom "_NET_WM_WINDOW_TYPE_DOCK" dock <- getAtom "_NET_WM_WINDOW_TYPE_DOCK"
desk <- getAtom "_NET_WM_WINDOW_TYPE_DESKTOP"
mbr <- getProp a w mbr <- getProp a w
case mbr of case mbr of
Just [r] -> return (fromIntegral r == d) Just [r] -> return $ elem (fromIntegral r) [dock, desk]
_ -> return False _ -> return False
-- | -- |
-- Gets the STRUT config, if present, in xmonad gap order -- Gets the STRUT config, if present, in xmonad gap order
getStrut :: Window -> X (Maybe (Int, Int, Int, Int)) getStrut :: Window -> X [Strut]
getStrut w = do getStrut w = do
a <- getAtom "_NET_WM_STRUT" spa <- getAtom "_NET_WM_STRUT_PARTIAL"
mbr <- getProp a w sa <- getAtom "_NET_WM_STRUT"
case mbr of msp <- getProp spa w
Just [l,r,t,b] -> return (Just ( case msp of
fromIntegral t, Just sp -> return $ parseStrutPartial sp
fromIntegral b, Nothing -> fmap (maybe [] parseStrut) $ getProp sa w
fromIntegral l, where
fromIntegral r)) parseStrut xs@[_, _, _, _] = parseStrutPartial . take 12 $ xs ++ cycle [minBound, maxBound]
_ -> return Nothing parseStrut _ = []
parseStrutPartial [l, r, t, b, ly1, ly2, ry1, ry2, tx1, tx2, bx1, bx2]
= filter (\(_, n, _, _) -> n /= 0)
[(L, l, ly1, ly2), (R, r, ry1, ry2), (T, t, tx1, tx2), (B, b, bx1, bx2)]
parseStrutPartial _ = []
-- | -- |
-- Helper to read a property -- Helper to read a property
@@ -86,48 +97,28 @@ getProp a w = withDisplay $ \dpy -> io $ getWindowProperty32 dpy a w
-- | -- |
-- Goes through the list of windows and find the gap so that all STRUT -- Goes through the list of windows and find the gap so that all STRUT
-- settings are satisfied. -- settings are satisfied.
calcGap :: X Rectangle calcGap :: X (Rectangle -> Rectangle)
calcGap = withDisplay $ \dpy -> do calcGap = withDisplay $ \dpy -> do
rootw <- asks theRoot rootw <- asks theRoot
-- We don't keep track of dock like windows, so we find all of them here -- We don't keep track of dock like windows, so we find all of them here
(_,_,wins) <- io $ queryTree dpy rootw (_,_,wins) <- io $ queryTree dpy rootw
struts <- catMaybes `fmap` mapM getStrut wins struts <- concat `fmap` mapM getStrut wins
-- we grab the window attributes of the root window rather than checking -- we grab the window attributes of the root window rather than checking
-- the width of the screen because xlib caches this info and it tends to -- the width of the screen because xlib caches this info and it tends to
-- be incorrect after RAndR -- be incorrect after RAndR
wa <- io $ getWindowAttributes dpy rootw wa <- io $ getWindowAttributes dpy rootw
return $ reduceScreen (foldl max4 (0,0,0,0) struts) let screen = r2c $ Rectangle (fi $ wa_x wa) (fi $ wa_y wa) (fi $ wa_width wa) (fi $ wa_height wa)
$ Rectangle (fi $ wa_x wa) (fi $ wa_y wa) (fi $ wa_width wa) (fi $ wa_height wa) return $ \r -> c2r $ foldr (reduce screen) (r2c r) struts
-- |
-- Piecewise maximum of a 4-tuple of Ints
max4 :: (Int, Int, Int, Int) -> (Int, Int, Int, Int) -> (Int, Int, Int, Int)
max4 (a1,a2,a3,a4) (b1,b2,b3,b4) = (max a1 b1, max a2 b2, max a3 b3, max a4 b4)
fi :: (Integral a, Num b) => a -> b fi :: (Integral a, Num b) => a -> b
fi = fromIntegral fi = fromIntegral
-- | Given strut values and the screen rectangle, compute a reduced screen r2c :: Rectangle -> RectC
-- rectangle. r2c (Rectangle x y w h) = (fi x, fi y, fi x + fi w, fi y + fi h)
reduceScreen :: (Int, Int, Int, Int) -> Rectangle -> Rectangle
reduceScreen (t, b, l, r) (Rectangle rx ry rw rh)
= Rectangle (rx + fi l) (ry + fi t) (rw - fi r) (rh - fi b)
r2c :: Rectangle -> (Position, Position, Position, Position) c2r :: RectC -> Rectangle
r2c (Rectangle x y w h) = (x, y, x + fi w, y + fi h) c2r (x1, y1, x2, y2) = Rectangle (fi x1) (fi y1) (fi $ x2 - x1) (fi $ y2 - y1)
c2r :: (Position, Position, Position, Position) -> Rectangle
c2r (x1, y1, x2, y2) = Rectangle x1 y1 (fi $ x2 - x1) (fi $ y2 - y1)
-- | Given a bounding rectangle 's' and another rectangle 'r', compute a
-- rectangle 'r' that fits inside 's'.
fitRect :: Rectangle -> Rectangle -> Rectangle
fitRect s r
= c2r (max sx1 rx1, max sy1 ry1, min sx2 rx2, min sy2 ry2)
where
(sx1, sy1, sx2, sy2) = r2c s
(rx1, ry1, rx2, ry2) = r2c r
-- | Adjust layout automagically. -- | Adjust layout automagically.
avoidStruts :: LayoutClass l a => l a -> AvoidStruts l a avoidStruts :: LayoutClass l a => l a -> AvoidStruts l a
@@ -140,7 +131,7 @@ instance Message ToggleStruts
instance LayoutClass l a => LayoutClass (AvoidStruts l) a where instance LayoutClass l a => LayoutClass (AvoidStruts l) a where
doLayout (AvoidStruts True lo) r s = doLayout (AvoidStruts True lo) r s =
do rect <- fmap (flip fitRect r) calcGap do rect <- fmap ($ r) calcGap
(wrs,mlo') <- doLayout lo rect s (wrs,mlo') <- doLayout lo rect s
return (wrs, AvoidStruts True `fmap` mlo') return (wrs, AvoidStruts True `fmap` mlo')
doLayout (AvoidStruts False lo) r s = do (wrs,mlo') <- doLayout lo r s doLayout (AvoidStruts False lo) r s = do (wrs,mlo') <- doLayout lo r s
@@ -150,3 +141,22 @@ instance LayoutClass l a => LayoutClass (AvoidStruts l) a where
| otherwise = do ml' <- handleMessage l m | otherwise = do ml' <- handleMessage l m
return (AvoidStruts b `fmap` ml') return (AvoidStruts b `fmap` ml')
description (AvoidStruts _ l) = description l description (AvoidStruts _ l) = description l
data Side = L | R | T | B
type Strut = (Side, CLong, CLong, CLong)
type RectC = (CLong, CLong, CLong, CLong)
reduce :: RectC -> Strut -> RectC -> RectC
reduce (sx0, sy0, sx1, sy1) (s, n, l, h) (x0, y0, x1, y1) = case s of
L | p (y0, y1) -> (mx x0 sx0 , y0 , x1 , y1 )
R | p (y0, y1) -> (x0 , y0 , mn x1 sx1, y1 )
T | p (x0, x1) -> (x0 , mx y0 sy0, x1 , y1 )
B | p (x0, x1) -> (x0 , y0 , x1 , mn y1 sy1)
_ -> (x0 , y0 , x1 , y1 )
where
mx a b = max a (b + n)
mn a b = min a (b - n)
inRange (a, b) c = c > a && c < b
p (a, b) = inRange (a, b) l || inRange (a, b) h || inRange (a, b) l || inRange (l, h) b

View File

@@ -0,0 +1,130 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Hooks.ManageHelpers
-- Copyright : (c) Lukas Mai
-- License : BSD
--
-- Maintainer : Lukas Mai <l.mai@web.de>
-- Stability : unstable
-- Portability : unportable
--
-- This module provides helper functions to be used in @manageHook@. Here's how you
-- might use this:
--
-- > import XMonad.Hooks.ManageHelpers
-- > main =
-- > xmonad defaultConfig{
-- > ...
-- > manageHook = composeOne [
-- > isKDETrayWindow -?> doIgnore,
-- > transience,
-- > resource =? "stalonetray" -?> doIgnore
-- > ],
-- > ...
-- > }
module XMonad.Hooks.ManageHelpers (
composeOne,
(-?>), (/=?), (<==?), (</=?), (-->>), (-?>>),
isKDETrayWindow,
transientTo,
maybeToDefinite,
MaybeManageHook,
transience,
transience'
) where
import XMonad
import qualified XMonad.StackSet as W
import Data.Maybe
import Data.Monoid
-- | A ManageHook that may or may not have been executed; the outcome is embedded in the Maybe
type MaybeManageHook = Query (Maybe (Endo WindowSet))
-- | A grouping type, which can hold the outcome of a predicate Query
-- This is analogous to group types in regular expressions
-- TODO create a better API for aggregating multiple Matches logically
data Match a = Match Bool a
-- | An alternative 'ManageHook' composer. Unlike 'composeAll' it stops as soon as
-- a candidate returns a 'Just' value, effectively running only the first match
-- (whereas 'composeAll' continues and executes all matching rules).
composeOne :: [MaybeManageHook] -> ManageHook
composeOne = foldr try idHook
where
try q z = do
x <- q
case x of
Just h -> return h
Nothing -> z
infixr 0 -?>, -->>, -?>>
-- | q \/=? x. if the result of q equals x, return False
(/=?) :: Eq a => Query a -> a -> Query Bool
q /=? x = fmap (/= x) q
-- | q <==? x. if the result of q equals x, return True grouped with q
(<==?) :: Eq a => Query a -> a -> Query (Match a)
q <==? x = fmap (`eq` x) q
where eq q' x' = Match (q' == x') q'
-- | q <\/=? x. if the result of q notequals x, return True grouped with q
(</=?) :: Eq a => Query a -> a -> Query (Match a)
q </=? x = fmap (`neq` x) q
where neq q' x' = Match (q' /= x') q'
-- | A helper operator for use in 'composeOne'. It takes a condition and an action;
-- if the condition fails, it returns 'Nothing' from the 'Query' so 'composeOne' will
-- go on and try the next rule.
(-?>) :: Query Bool -> ManageHook -> MaybeManageHook
p -?> f = do
x <- p
if x then fmap Just f else return Nothing
-- | A helper operator for use in 'composeAll'. It takes a condition and a function taking a grouped datum to action. If 'p' is true, it executes the resulting action.
(-->>) :: Query (Match a) -> (a -> ManageHook) -> ManageHook
p -->> f = do Match b m <- p
if b then (f m) else mempty
-- | A helper operator for use in 'composeOne'. It takes a condition and a function taking a groupdatum to action. If 'p' is true, it executes the resulting action. If it fails, it returns 'Nothing' from the 'Query' so 'composeOne' will go on and try the next rule.
(-?>>) :: Query (Match a) -> (a -> ManageHook) -> MaybeManageHook
p -?>> f = do Match b m <- p
if b then fmap Just (f m) else return Nothing
-- | A predicate to check whether a window is a KDE system tray icon.
isKDETrayWindow :: Query Bool
isKDETrayWindow = ask >>= \w -> liftX $ do
dpy <- asks display
kde_tray <- getAtom "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR"
r <- io $ getWindowProperty32 dpy kde_tray w
return $ case r of
Just [_] -> True
_ -> False
-- | A predicate to check whether a window is Transient.
-- It holds the result which might be the window it is transient to
-- or it might be 'Nothing'.
transientTo :: Query (Maybe Window)
transientTo = do w <- ask
d <- (liftX . asks) display
liftIO $ getTransientForHint d w
-- | A convenience 'MaybeManageHook' that will check to see if a window
-- is transient, and then move it to it's parent.
transience :: MaybeManageHook
transience = transientTo </=? Nothing
-?>> move
where move :: Maybe Window -> ManageHook
move mw = maybe idHook (doF . move') mw
where move' :: Window -> (WindowSet -> WindowSet)
move' w = \s -> maybe s (`W.shift` s) (W.findTag w s)
-- | 'transience' set to a 'ManageHook'
transience' :: ManageHook
transience' = maybeToDefinite transience
-- | converts 'MaybeManageHook's to 'ManageHook's
maybeToDefinite :: MaybeManageHook -> ManageHook
maybeToDefinite = fmap (fromMaybe mempty)

View File

@@ -107,7 +107,7 @@ doLay mirror (DragPane mw ty delta split) r s = do
mirror $ Rectangle x y (w-halfHandleWidth) h mirror $ Rectangle x y (w-halfHandleWidth) h
right = case right' of right = case right' of
Rectangle x y w h -> Rectangle x y w h ->
mirror $ Rectangle (x+halfHandleWidth) y (w-halfHandleWidth) h mirror $ Rectangle (x+halfHandleWidth) y (w-halfHandleWidth) h
handr = case left' of handr = case left' of
Rectangle x y w h -> Rectangle x y w h ->
mirror $ Rectangle (x + fromIntegral w - halfHandleWidth) y (2*halfHandleWidth) h mirror $ Rectangle (x + fromIntegral w - halfHandleWidth) y (2*halfHandleWidth) h
@@ -131,6 +131,6 @@ doLay mirror (DragPane mw ty delta split) r s = do
newDragWin :: Rectangle -> X Window newDragWin :: Rectangle -> X Window
newDragWin r = do newDragWin r = do
let mask = Just $ exposureMask .|. buttonPressMask let mask = Just $ exposureMask .|. buttonPressMask
w <- createNewWindow r mask handleColor w <- createNewWindow r mask handleColor False
showWindow w showWindow w
return w return w

View File

@@ -17,7 +17,7 @@
module XMonad.Layout.Grid ( module XMonad.Layout.Grid (
-- * Usage -- * Usage
-- $usage -- $usage
Grid(..) Grid(..)
) where ) where
import XMonad import XMonad

View File

@@ -30,14 +30,16 @@ import qualified XMonad.StackSet as W
-- screen and long for greater flexibility (e.g. being able to see your -- screen and long for greater flexibility (e.g. being able to see your
-- email window at all times, a crude mimic of sticky windows). -- email window at all times, a crude mimic of sticky windows).
-- --
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file: -- You can use this module with the following in your
-- @~\/.xmonad\/xmonad.hs@ file:
-- --
-- > import XMonad.Layout.LayoutScreens -- > import XMonad.Layout.LayoutScreens
-- > import XMonad.Layout.TwoPane
-- --
-- Then add some keybindings; for example: -- Then add some keybindings; for example:
-- --
-- > , ((modMask .|. shiftMask, xK_space), layoutScreens 2 (TwoPane 0.5 0.5)) -- > , ((modMask x .|. shiftMask, xK_space), layoutScreens 2 (TwoPane 0.5 0.5))
-- > , ((controlMask .|. modMask .|. shiftMask, xK_space), rescreen) -- > , ((modMask x .|. controlMask .|. shiftMask, xK_space), rescreen)
-- --
-- Another example use would be to handle a scenario where xrandr didn't -- Another example use would be to handle a scenario where xrandr didn't
-- work properly (e.g. a VNC X server in my case) and you want to be able -- work properly (e.g. a VNC X server in my case) and you want to be able
@@ -45,9 +47,9 @@ import qualified XMonad.StackSet as W
-- --
-- > import XMonad.Layout.LayoutScreens -- > import XMonad.Layout.LayoutScreens
-- --
-- > , ((modMask .|. shiftMask, xK_space), -- > , ((modMask x .|. shiftMask, xK_space),
-- > layoutScreens 1 (fixedLayout [Rectangle 0 0 1024 768])) -- > layoutScreens 1 (fixedLayout [Rectangle 0 0 1024 768]))
-- > , ((controlMask .|. modMask .|. shiftMask, xK_space), rescreen) -- > , ((modMask x .|. controlMask .|. shiftMask, xK_space), rescreen)
-- --
-- For detailed instructions on editing your key bindings, see -- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings". -- "XMonad.Doc.Extending#Editing_key_bindings".

View File

@@ -22,6 +22,8 @@ module XMonad.Layout.Magnifier
-- $usage -- $usage
magnifier, magnifier,
magnifier', magnifier',
magnifiercz,
magnifiercz',
MagnifyMsg (..) MagnifyMsg (..)
) where ) where
@@ -34,12 +36,24 @@ import XMonad.Layout.LayoutModifier
-- --
-- > import XMonad.Layout.Magnifier -- > import XMonad.Layout.Magnifier
-- --
-- Then edit your @layoutHook@ by adding the Magnifier layout modifier -- Then edit your @layoutHook@ by adding the 'magnifier' layout modifier
-- to some layout: -- to some layout:
-- --
-- > myLayouts = magnifier (Tall 1 (3/100) (1/2)) ||| Full ||| etc.. -- > myLayouts = magnifier (Tall 1 (3/100) (1/2)) ||| Full ||| etc..
-- > main = xmonad defaultConfig { layoutHook = myLayouts } -- > main = xmonad defaultConfig { layoutHook = myLayouts }
-- --
-- By default magnifier increases the focused window's size by 1.5.
-- You can also use:
--
-- > magnifiercz (12%10)
--
-- to use a custom level of magnification. You can even make the focused
-- window smaller for a pop in effect. Keep in mind, you must
--
-- > import Data.Ratio
--
-- in order to use rationals (such as @12%10@) in your config.
--
-- For more detailed instructions on editing the layoutHook see: -- For more detailed instructions on editing the layoutHook see:
-- --
-- "XMonad.Doc.Extending#Editing_the_layout_hook" -- "XMonad.Doc.Extending#Editing_the_layout_hook"
@@ -59,11 +73,20 @@ import XMonad.Layout.LayoutModifier
magnifier :: l a -> ModifiedLayout Magnifier l a magnifier :: l a -> ModifiedLayout Magnifier l a
magnifier = ModifiedLayout (Mag 1.5 On All) magnifier = ModifiedLayout (Mag 1.5 On All)
-- | Change the size of the window that has focus by a custom zoom
magnifiercz :: Rational -> l a -> ModifiedLayout Magnifier l a
magnifiercz cz = ModifiedLayout (Mag ((fromRational cz)*1.0::Double) On All)
-- | Increase the size of the window that has focus, unless if it is the -- | Increase the size of the window that has focus, unless if it is the
-- master window. -- master window.
magnifier' :: l a -> ModifiedLayout Magnifier l a magnifier' :: l a -> ModifiedLayout Magnifier l a
magnifier' = ModifiedLayout (Mag 1.5 On NoMaster) magnifier' = ModifiedLayout (Mag 1.5 On NoMaster)
-- | Increase the size of the window that has focus by a custom zoom,
-- unless if it is the master window.
magnifiercz' :: Rational -> l a -> ModifiedLayout Magnifier l a
magnifiercz' cz = ModifiedLayout (Mag ((fromRational cz)*1.0::Double) On NoMaster)
data MagnifyMsg = MagnifyMore | MagnifyLess | ToggleOn | ToggleOff deriving ( Typeable ) data MagnifyMsg = MagnifyMore | MagnifyLess | ToggleOn | ToggleOff deriving ( Typeable )
instance Message MagnifyMsg instance Message MagnifyMsg

View File

@@ -23,6 +23,7 @@ module XMonad.Layout.MultiToggle (
Toggle(..), Toggle(..),
(??), (??),
EOT(..), EOT(..),
single,
mkToggle mkToggle
) where ) where
@@ -39,7 +40,7 @@ import Data.Maybe
-- group of radio buttons. -- group of radio buttons.
-- --
-- A side effect of this meta-layout is that layout transformers no longer -- A side effect of this meta-layout is that layout transformers no longer
-- receive any messages; any message not handled by SwitchTrans itself will -- receive any messages; any message not handled by MultiToggle itself will
-- undo the current layout transformer, pass the message on to the base -- undo the current layout transformer, pass the message on to the base
-- layout, then reapply the transformer. -- layout, then reapply the transformer.
-- --
@@ -63,7 +64,7 @@ import Data.Maybe
-- --
-- After changing this to -- After changing this to
-- --
-- > layout = mkToggle (MIRROR ?? EOT) (tiled ||| Full) -- > layout = mkToggle (single MIRROR) (tiled ||| Full)
-- --
-- you can now dynamically apply the 'XMonad.Layout.Mirror' transformation: -- you can now dynamically apply the 'XMonad.Layout.Mirror' transformation:
-- --
@@ -90,7 +91,7 @@ import Data.Maybe
-- layout = id -- layout = id
-- . 'XMonad.Layout.NoBorders.smartBorders' -- . 'XMonad.Layout.NoBorders.smartBorders'
-- . mkToggle (NOBORDERS ?? FULL ?? EOT) -- . mkToggle (NOBORDERS ?? FULL ?? EOT)
-- . mkToggle (MIRROR ?? EOT) -- . mkToggle (single MIRROR)
-- $ tiled ||| 'XMonad.Layout.Grid.Grid' ||| 'XMonad.Layout.Circle.Circle' -- $ tiled ||| 'XMonad.Layout.Grid.Grid' ||| 'XMonad.Layout.Circle.Circle'
-- @ -- @
-- --
@@ -164,6 +165,10 @@ infixr 0 ??
(??) :: (HList b w) => a -> b -> HCons a b (??) :: (HList b w) => a -> b -> HCons a b
(??) = HCons (??) = HCons
-- | Construct a singleton transformer table.
single :: a -> HCons a EOT
single = (?? EOT)
class HList c a where class HList c a where
find :: (Transformer t a) => c -> t -> Maybe Int find :: (Transformer t a) => c -> t -> Maybe Int
resolve :: c -> Int -> b -> (forall t. (Transformer t a) => t -> b) -> b resolve :: c -> Int -> b -> (forall t. (Transformer t a) => t -> b) -> b
@@ -189,7 +194,7 @@ acceptChange :: (LayoutClass l' a) => MultiToggle ts l a -> ((l' a -> MultiToggl
acceptChange mt f = fmap (f (\x -> mt{ currLayout = EL x })) acceptChange mt f = fmap (f (\x -> mt{ currLayout = EL x }))
instance (Typeable a, Show ts, HList ts a, LayoutClass l a) => LayoutClass (MultiToggle ts l) a where instance (Typeable a, Show ts, HList ts a, LayoutClass l a) => LayoutClass (MultiToggle ts l) a where
description _ = "MultiToggle" description mt = currLayout mt `unEL` \l -> description l
pureLayout mt r s = currLayout mt `unEL` \l -> pureLayout l r s pureLayout mt r s = currLayout mt `unEL` \l -> pureLayout l r s

View File

@@ -12,6 +12,13 @@
-- --
-- Configure layouts on a per-workspace basis. NOTE that this module -- Configure layouts on a per-workspace basis. NOTE that this module
-- does not (yet) work in conjunction with multiple screens! =( -- does not (yet) work in conjunction with multiple screens! =(
--
-- Note also that when using PerWorkspace, on initial startup workspaces
-- may not respond to messages properly until a window has been opened.
-- This is due to a limitation inherent in the way PerWorkspace is
-- implemented: it cannot decide which layout to use until actually
-- required to lay out some windows (which does not happen until a window
-- is opened).
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Layout.PerWorkspace ( module XMonad.Layout.PerWorkspace (

119
XMonad/Layout/Reflect.hs Normal file
View File

@@ -0,0 +1,119 @@
{-# OPTIONS_GHC -fglasgow-exts #-}
-- for now, use -fglasgow-exts for compatibility with ghc 6.6, which chokes
-- on some of the LANGUAGE pragmas below
{- LANGUAGE FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable, TypeSynonymInstances -}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.Reflect
-- Copyright : (c) Brent Yorgey
-- License : BSD-style (see LICENSE)
--
-- Maintainer : <byorgey@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Reflect a layout horizontally or vertically.
-----------------------------------------------------------------------------
module XMonad.Layout.Reflect (
-- * Usage
-- $usage
reflectHoriz, reflectVert,
REFLECTX(..), REFLECTY(..)
) where
import XMonad.Core
import Graphics.X11 (Rectangle(..), Window)
import Control.Arrow ((***), second)
import Control.Applicative ((<$>))
import XMonad.Layout.MultiToggle
-- $usage
-- You can use this module by importing it into your @~\/.xmonad\/xmonad.hs@ file:
--
-- > import XMonad.Layout.Reflect
--
-- and modifying your layoutHook as follows (for example):
--
-- > layoutHook = reflectHoriz $ Tall 1 (3/100) (1/2) -- put master pane on the right
--
-- 'reflectHoriz' and 'reflectVert' can be applied to any sort of
-- layout (including Mirrored layouts) and will simply flip the
-- physical layout of the windows vertically or horizontally.
--
-- "XMonad.Layout.MultiToggle" transformers are also provided for
-- toggling layouts between reflected\/non-reflected with a keybinding.
-- To use this feature, you will also need to import the MultiToggle
-- module:
--
-- > import XMonad.Layout.MultiToggle
--
-- Next, add one or more toggles to your layout. For example, to allow
-- separate toggling of both vertical and horizontal reflection:
--
-- > layoutHook = mkToggle (REFLECTX ?? EOT) $
-- > mkToggle (REFLECTY ?? EOT) $
-- > (tiled ||| Mirror tiled ||| ...) -- whatever layouts you use
--
-- Finally, add some keybindings to do the toggling, for example:
--
-- > , ((modMask x .|. controlMask, xK_x), sendMessage $ Toggle REFLECTX)
-- > , ((modMask x .|. controlMask, xK_y), sendMessage $ Toggle REFLECTY)
--
-- | Apply a horizontal reflection (left \<--\> right) to a
-- layout.
reflectHoriz :: (LayoutClass l a) => (l a) -> Reflect l a
reflectHoriz = Reflect Horiz
-- | Apply a vertical reflection (top \<--\> bottom) to a
-- layout.
reflectVert :: (LayoutClass l a) => (l a) -> Reflect l a
reflectVert = Reflect Vert
data ReflectDir = Horiz | Vert
deriving (Read, Show)
-- | Given an axis of reflection and the enclosing rectangle which
-- contains all the laid out windows, transform a rectangle
-- representing a window into its flipped counterpart.
reflectRect :: ReflectDir -> Rectangle -> Rectangle -> Rectangle
reflectRect Horiz (Rectangle sx _ sw _) (Rectangle rx ry rw rh) =
Rectangle (2*sx + fi sw - rx - fi rw) ry rw rh
reflectRect Vert (Rectangle _ sy _ sh) (Rectangle rx ry rw rh) =
Rectangle rx (2*sy + fi sh - ry - fi rh) rw rh
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral
data Reflect l a = Reflect ReflectDir (l a) deriving (Show, Read)
instance LayoutClass l a => LayoutClass (Reflect l) a where
-- do layout l, then reflect all the generated Rectangles.
doLayout (Reflect d l) r s = (map (second (reflectRect d r)) *** fmap (Reflect d))
<$> doLayout l r s
-- pass messages on to the underlying layout
handleMessage (Reflect d l) = fmap (fmap (Reflect d)) . handleMessage l
description (Reflect d l) = "Reflect" ++ xy ++ " " ++ description l
where xy = case d of { Horiz -> "X" ; Vert -> "Y" }
-------- instances for MultiToggle ------------------
data REFLECTX = REFLECTX deriving (Read, Show, Eq, Typeable)
data REFLECTY = REFLECTY deriving (Read, Show, Eq, Typeable)
instance Transformer REFLECTX Window where
transform REFLECTX x k = k (reflectHoriz x)
instance Transformer REFLECTY Window where
transform REFLECTY x k = k (reflectVert x)

View File

@@ -24,6 +24,8 @@ module XMonad.Layout.ResizableTile (
import XMonad hiding (splitVertically, splitHorizontallyBy) import XMonad hiding (splitVertically, splitHorizontallyBy)
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import Control.Monad import Control.Monad
import qualified Data.Map as M
import Data.List ((\\))
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -58,12 +60,16 @@ instance LayoutClass ResizableTall a where
ap zip (tile frac (mfrac ++ repeat 1) r nmaster . length) . W.integrate ap zip (tile frac (mfrac ++ repeat 1) r nmaster . length) . W.integrate
handleMessage (ResizableTall nmaster delta frac mfrac) m = handleMessage (ResizableTall nmaster delta frac mfrac) m =
do ms <- (W.stack . W.workspace . W.current) `fmap` gets windowset do ms <- (W.stack . W.workspace . W.current) `fmap` gets windowset
case ms of fs <- (M.keys . W.floating) `fmap` gets windowset
Nothing -> return Nothing return $ ms >>= unfloat fs >>= handleMesg
Just s -> return $ msum [fmap resize (fromMessage m) where handleMesg s = msum [fmap resize (fromMessage m)
,fmap (\x -> mresize x s) (fromMessage m) ,fmap (\x -> mresize x s) (fromMessage m)
,fmap incmastern (fromMessage m)] ,fmap incmastern (fromMessage m)]
where resize Shrink = ResizableTall nmaster delta (max 0 $ frac-delta) mfrac unfloat fs s = if W.focus s `elem` fs
then Nothing
else Just (s { W.up = (W.up s) \\ fs
, W.down = (W.down s) \\ fs })
resize Shrink = ResizableTall nmaster delta (max 0 $ frac-delta) mfrac
resize Expand = ResizableTall nmaster delta (min 1 $ frac+delta) mfrac resize Expand = ResizableTall nmaster delta (min 1 $ frac+delta) mfrac
mresize MirrorShrink s = mresize' s delta mresize MirrorShrink s = mresize' s delta
mresize MirrorExpand s = mresize' s (0-delta) mresize MirrorExpand s = mresize' s (0-delta)

104
XMonad/Layout/ShowWName.hs Normal file
View File

@@ -0,0 +1,104 @@
{-# LANGUAGE PatternGuards, TypeSynonymInstances, MultiParamTypeClasses #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.ShowWName
-- Copyright : (c) Andrea Rossato 2007
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : andrea.rossato@unibz.it
-- Stability : unstable
-- Portability : unportable
--
-- This is a layout modifier that will show the workspace name
-----------------------------------------------------------------------------
module XMonad.Layout.ShowWName
( -- * Usage
-- $usage
showWName
, showWName'
, defaultSWNConfig
, SWNConfig(..)
) where
import XMonad
import qualified XMonad.StackSet as S
import XMonad.Layout.LayoutModifier
import XMonad.Util.Font
import XMonad.Util.Timer
import XMonad.Util.XUtils
-- $usage
-- You can use this module with the following in your
-- @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Layout.ShowWName
-- > myLayout = layoutHook defaultConfig
-- > main = xmonad defaultConfig { layoutHook = showWName myLayout }
--
-- For more detailed instructions on editing the layoutHook see:
--
-- "XMonad.Doc.Extending#Editing_the_layout_hook"
-- | A layout modifier to show the workspace name when switching
showWName :: l a -> ModifiedLayout ShowWName l a
showWName = ModifiedLayout (SWN True defaultSWNConfig Nothing)
-- | A layout modifier to show the workspace name when switching. It
-- is possible to provide a costum configuration.
showWName' :: SWNConfig -> l a -> ModifiedLayout ShowWName l a
showWName' c = ModifiedLayout (SWN True c Nothing)
type ShowWNState = Maybe (TimerId, Window)
data ShowWName a = SWN Bool SWNConfig ShowWNState deriving (Read, Show)
data SWNConfig =
SWNC { swn_font :: String -- ^ Font name
, swn_bgcolor :: String -- ^ Backgorund color
, swn_color :: String -- ^ String color
, swn_fade :: Rational -- ^ Time in seconds of the name visibility
} deriving (Read, Show)
defaultSWNConfig :: SWNConfig
defaultSWNConfig =
SWNC { swn_font = "-misc-fixed-*-*-*-*-20-*-*-*-*-*-*-*"
, swn_bgcolor = "black"
, swn_color = "white"
, swn_fade = 1
}
instance LayoutModifier ShowWName Window where
redoLayout (SWN True c (Just (_,w))) r _ wrs = deleteWindow w >> flashName c r wrs
redoLayout (SWN True c Nothing ) r _ wrs = flashName c r wrs
redoLayout (SWN False _ _ ) _ _ wrs = return (wrs, Nothing)
handleMess (SWN _ c (Just (i,w))) m
| Just e <- fromMessage m = handleTimer i e (deleteWindow w >> return Nothing)
| Just Hide <- fromMessage m = do deleteWindow w
return . Just $ SWN True c Nothing
handleMess (SWN _ c s) m
| Just Hide <- fromMessage m = return . Just $ SWN True c s
| otherwise = return Nothing
flashName :: SWNConfig -> Rectangle -> [(a, Rectangle)] -> X ([(a, Rectangle)], Maybe (ShowWName a))
flashName c (Rectangle _ _ wh ht) wrs = do
d <- asks display
n <- withWindowSet (return . S.tag . S.workspace . S.current)
f <- initXMF (swn_font c)
width <- textWidthXMF d f n
(_,as,ds,_) <- textExtentsXMF f n
let hight = as + ds
y = (fi ht - hight + 2) `div` 2
x = (fi wh - width + 2) `div` 2
w <- createNewWindow (Rectangle (fi x) (fi y) (fi width) (fi hight)) Nothing "" True
showWindow w
paintAndWrite w f (fi width) (fi hight) 0 "" "" (swn_color c) (swn_bgcolor c) AlignCenter n
releaseXMF f
io $ sync d False
i <- startTimer (swn_fade c)
return (wrs, Just $ SWN False c $ Just (i,w))
-- | Short-hand for 'fromIntegral'
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral

View File

@@ -33,6 +33,8 @@ import XMonad.Util.Invisible
import XMonad.Util.XUtils import XMonad.Util.XUtils
import XMonad.Util.Font import XMonad.Util.Font
import XMonad.Hooks.UrgencyHook
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- --
@@ -62,10 +64,13 @@ tabbed s t = Tabbed (I Nothing) s t
data TConf = data TConf =
TConf { activeColor :: String TConf { activeColor :: String
, inactiveColor :: String , inactiveColor :: String
, urgentColor :: String
, activeBorderColor :: String , activeBorderColor :: String
, inactiveTextColor :: String
, inactiveBorderColor :: String , inactiveBorderColor :: String
, urgentBorderColor :: String
, activeTextColor :: String , activeTextColor :: String
, inactiveTextColor :: String
, urgentTextColor :: String
, fontName :: String , fontName :: String
, tabSize :: Int , tabSize :: Int
} deriving (Show, Read) } deriving (Show, Read)
@@ -74,10 +79,13 @@ defaultTConf :: TConf
defaultTConf = defaultTConf =
TConf { activeColor = "#999999" TConf { activeColor = "#999999"
, inactiveColor = "#666666" , inactiveColor = "#666666"
, urgentColor = "#FFFF00"
, activeBorderColor = "#FFFFFF" , activeBorderColor = "#FFFFFF"
, inactiveBorderColor = "#BBBBBB" , inactiveBorderColor = "#BBBBBB"
, urgentBorderColor = "##00FF00"
, activeTextColor = "#FFFFFF" , activeTextColor = "#FFFFFF"
, inactiveTextColor = "#BFBFBF" , inactiveTextColor = "#BFBFBF"
, urgentTextColor = "#FF0000"
, fontName = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*" , fontName = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
, tabSize = 20 , tabSize = 20
} }
@@ -86,7 +94,7 @@ data TabState =
TabState { tabsWindows :: [(Window,Window)] TabState { tabsWindows :: [(Window,Window)]
, scr :: Rectangle , scr :: Rectangle
, font :: XMonadFont , font :: XMonadFont
} }
data Tabbed s a = data Tabbed s a =
Tabbed (Invisible Maybe TabState) s TConf Tabbed (Invisible Maybe TabState) s TConf
@@ -128,8 +136,8 @@ handleMess _ _ = return Nothing
handleEvent :: Shrinker s => s -> TConf -> TabState -> Event -> X () handleEvent :: Shrinker s => s -> TConf -> TabState -> Event -> X ()
-- button press -- button press
handleEvent ishr conf (TabState {tabsWindows = tws, scr = screen, font = fs}) handleEvent ishr conf (TabState {tabsWindows = tws, scr = screen, font = fs})
(ButtonEvent {ev_window = thisw, ev_subwindow = thisbw, ev_event_type = t}) (ButtonEvent {ev_window = thisw, ev_subwindow = thisbw, ev_event_type = t })
| t == buttonPress, tl <- map fst tws, thisw `elem` tl || thisbw `elem` tl = do | t == buttonPress, tl <- map fst tws, thisw `elem` tl || thisbw `elem` tl = do
case lookup thisw tws of case lookup thisw tws of
Just x -> do focus x Just x -> do focus x
@@ -174,7 +182,7 @@ createTabs c (Rectangle x y wh ht) owl@(ow:ows) = do
height = fromIntegral $ tabSize c height = fromIntegral $ tabSize c
mask = Just (exposureMask .|. buttonPressMask) mask = Just (exposureMask .|. buttonPressMask)
d <- asks display d <- asks display
w <- createNewWindow (Rectangle x y wid height) mask (inactiveColor c) w <- createNewWindow (Rectangle x y wid height) mask (inactiveColor c) True
io $ restackWindows d $ w : [ow] io $ restackWindows d $ w : [ow]
ws <- createTabs c (Rectangle (x + fromIntegral wid) y (wh - wid) ht) ows ws <- createTabs c (Rectangle (x + fromIntegral wid) y (wh - wid) ht) ows
return (w:ws) return (w:ws)
@@ -182,18 +190,22 @@ createTabs c (Rectangle x y wh ht) owl@(ow:ows) = do
updateTab :: Shrinker s => s -> TConf -> XMonadFont -> Dimension -> (Window,Window) -> X () updateTab :: Shrinker s => s -> TConf -> XMonadFont -> Dimension -> (Window,Window) -> X ()
updateTab ishr c fs wh (tabw,ow) = do updateTab ishr c fs wh (tabw,ow) = do
nw <- getName ow nw <- getName ow
ur <- readUrgents
let ht = fromIntegral $ tabSize c :: Dimension let ht = fromIntegral $ tabSize c :: Dimension
focusColor win ic ac = (maybe ic (\focusw -> if focusw == win focusColor win ic ac uc = (maybe ic (\focusw -> case () of
then ac else ic) . W.peek) _ | focusw == win -> ac
`fmap` gets windowset | win `elem` ur -> uc
| otherwise -> ic) . W.peek)
`fmap` gets windowset
(bc',borderc',tc') <- focusColor ow (bc',borderc',tc') <- focusColor ow
(inactiveColor c, inactiveBorderColor c, inactiveTextColor c) (inactiveColor c, inactiveBorderColor c, inactiveTextColor c)
(activeColor c, activeBorderColor c, activeTextColor c) (activeColor c, activeBorderColor c, activeTextColor c)
(urgentColor c, urgentBorderColor c, urgentTextColor c)
dpy <- asks display dpy <- asks display
let s = shrinkIt ishr let s = shrinkIt ishr
name <- shrinkWhile s (\n -> do name <- shrinkWhile s (\n -> do
size <- io $ textWidthXMF dpy fs n size <- io $ textWidthXMF dpy fs n
return $ size > fromIntegral wh - fromIntegral (ht `div` 2)) (show nw) return $ size > fromIntegral wh - fromIntegral (ht `div` 2)) (show nw)
paintAndWrite tabw fs wh ht 1 bc' borderc' tc' bc' AlignCenter name paintAndWrite tabw fs wh ht 1 bc' borderc' tc' bc' AlignCenter name
shrink :: TConf -> Rectangle -> Rectangle shrink :: TConf -> Rectangle -> Rectangle
@@ -205,10 +217,10 @@ shrinkWhile sh p x = sw $ sh x
where sw [n] = return n where sw [n] = return n
sw [] = return "" sw [] = return ""
sw (n:ns) = do sw (n:ns) = do
cond <- p n cond <- p n
if cond if cond
then sw ns then sw ns
else return n else return n
data CustomShrink = CustomShrink data CustomShrink = CustomShrink
instance Show CustomShrink where show _ = "" instance Show CustomShrink where show _ = ""

View File

@@ -96,6 +96,7 @@ data XPConfig =
, position :: XPPosition -- ^ Position: 'Top' or 'Bottom' , position :: XPPosition -- ^ Position: 'Top' or 'Bottom'
, height :: Dimension -- ^ Window height , height :: Dimension -- ^ Window height
, historySize :: Int -- ^ The number of history entries to be saved , historySize :: Int -- ^ The number of history entries to be saved
, defaultText :: String -- ^ The text by default in the prompt line
} deriving (Show, Read) } deriving (Show, Read)
data XPType = forall p . XPrompt p => XPT p data XPType = forall p . XPrompt p => XPT p
@@ -135,6 +136,7 @@ defaultXPConfig =
, position = Bottom , position = Bottom
, height = 18 , height = 18
, historySize = 256 , historySize = 256
, defaultText = []
} }
type ComplFunction = String -> IO [String] type ComplFunction = String -> IO [String]
@@ -142,7 +144,21 @@ type ComplFunction = String -> IO [String]
initState :: XPrompt p => Display -> Window -> Window -> Rectangle -> ComplFunction initState :: XPrompt p => Display -> Window -> Window -> Rectangle -> ComplFunction
-> GC -> XMonadFont -> p -> [History] -> XPConfig -> XPState -> GC -> XMonadFont -> p -> [History] -> XPConfig -> XPState
initState d rw w s compl gc fonts pt h c = initState d rw w s compl gc fonts pt h c =
XPS d rw w s Nothing Nothing compl gc fonts (XPT pt) "" 0 h c XPS { dpy = d
, rootw = rw
, win = w
, screen = s
, complWin = Nothing
, complWinDim = Nothing
, completionFunction = compl
, gcon = gc
, fontS = fonts
, xptype = XPT pt
, command = defaultText c
, offset = length (defaultText c)
, history = h
, config = c
}
-- | Same as 'mkXPrompt', except that the action function can have -- | Same as 'mkXPrompt', except that the action function can have
-- type @String -> X a@, for any @a@, and the final action returned -- type @String -> X a@, for any @a@, and the final action returned
@@ -281,6 +297,8 @@ keyPressHandle mask (ks,_)
| ks == xK_a -> startOfLine >> go | ks == xK_a -> startOfLine >> go
| ks == xK_e -> endOfLine >> go | ks == xK_e -> endOfLine >> go
| ks == xK_y -> pasteString >> go | ks == xK_y -> pasteString >> go
| ks == xK_Right -> moveWord Next >> go
| ks == xK_Left -> moveWord Prev >> go
| ks == xK_Delete -> killWord Next >> go | ks == xK_Delete -> killWord Next >> go
| ks == xK_BackSpace -> killWord Prev >> go | ks == xK_BackSpace -> killWord Prev >> go
| ks == xK_g || ks == xK_c -> quit | ks == xK_g || ks == xK_c -> quit
@@ -380,6 +398,21 @@ moveCursor d =
modify $ \s -> s { offset = o (offset s) (command s)} modify $ \s -> s { offset = o (offset s) (command s)}
where o oo c = if d == Prev then max 0 (oo - 1) else min (length c) (oo + 1) where o oo c = if d == Prev then max 0 (oo - 1) else min (length c) (oo + 1)
-- | move the cursor one word
moveWord :: Direction -> XP ()
moveWord d = do
c <- gets command
o <- gets offset
let (f,ss) = splitAt o c
lenToS = length . fst . break isSpace
ln p s = case p s of
' ':x -> 1 + lenToS x
x -> lenToS x
newoff = case d of
Prev -> o - (ln reverse f )
_ -> o + (ln id ss)
modify $ \s -> s { offset = newoff }
moveHistory :: Direction -> XP () moveHistory :: Direction -> XP ()
moveHistory d = do moveHistory d = do
h <- getHistory h <- getHistory
@@ -454,7 +487,7 @@ printPrompt drw = do
ht = height c ht = height c
fsl <- io $ textWidthXMF (dpy st) fs f fsl <- io $ textWidthXMF (dpy st) fs f
psl <- io $ textWidthXMF (dpy st) fs p psl <- io $ textWidthXMF (dpy st) fs p
(_,asc,desc,_) <- io $ textExtentsXMF (dpy st) fs str (_,asc,desc,_) <- io $ textExtentsXMF fs str
let y = fi $ ((ht - fi (asc + desc)) `div` 2) + fi asc let y = fi $ ((ht - fi (asc + desc)) `div` 2) + fi asc
x = (asc + desc) `div` 2 x = (asc + desc) `div` 2
@@ -521,7 +554,7 @@ getComplWinDim compl = do
(x,y) = case position c of (x,y) = case position c of
Top -> (0,ht) Top -> (0,ht)
Bottom -> (0, (0 + rem_height - actual_height)) Bottom -> (0, (0 + rem_height - actual_height))
(_,asc,desc,_) <- io $ textExtentsXMF (dpy st) fs $ head compl (_,asc,desc,_) <- io $ textExtentsXMF fs $ head compl
let yp = fi $ (ht + fi (asc - desc)) `div` 2 let yp = fi $ (ht + fi (asc - desc)) `div` 2
xp = (asc + desc) `div` 2 xp = (asc + desc) `div` 2
yy = map fi . take (fi actual_rows) $ [yp,(yp + ht)..] yy = map fi . take (fi actual_rows) $ [yp,(yp + ht)..]
@@ -613,7 +646,7 @@ getHistory = do
readHistory :: IO ([History],Handle) readHistory :: IO ([History],Handle)
readHistory = do readHistory = do
home <- getEnv "HOME" home <- getEnv "HOME"
let path = home ++ "/.xmonad_history" let path = home ++ "/.xmonad/history"
f <- fileExist path f <- fileExist path
if f then do h <- openFile path ReadMode if f then do h <- openFile path ReadMode
str <- hGetContents h str <- hGetContents h
@@ -627,7 +660,7 @@ readHistory = do
writeHistory :: [History] -> IO () writeHistory :: [History] -> IO ()
writeHistory hist = do writeHistory hist = do
home <- getEnv "HOME" home <- getEnv "HOME"
let path = home ++ "/.xmonad_history" let path = home ++ "/.xmonad/history"
catch (writeFile path (show hist)) (\_ -> do putStrLn "error in writing"; return ()) catch (writeFile path (show hist)) (\_ -> do putStrLn "error in writing"; return ())
-- $xutils -- $xutils

View File

@@ -13,8 +13,6 @@
-- --
-- * narrow completions by section number, if the one is specified -- * narrow completions by section number, if the one is specified
-- (like @\/etc\/bash_completion@ does) -- (like @\/etc\/bash_completion@ does)
--
-- * write QuickCheck properties
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Prompt.Man ( module XMonad.Prompt.Man (
@@ -58,33 +56,36 @@ instance XPrompt Man where
-- | Query for manual page to be displayed. -- | Query for manual page to be displayed.
manPrompt :: XPConfig -> X () manPrompt :: XPConfig -> X ()
manPrompt c = mkXPrompt Man c manCompl $ runInTerm . (++) "man " manPrompt c = do
mans <- io getMans
mkXPrompt Man c (manCompl mans) $ runInTerm . (++) "man "
manCompl :: String -> IO [String] getMans :: IO [String]
manCompl str | '/' `elem` str = do getMans = do
-- XXX It may be better to use readline instead of bash's compgen... paths <- getCommandOutput "manpath -g 2>/dev/null" `E.catch` \_ -> return []
lines `fmap` getCommandOutput ("bash -c 'compgen -A file " ++ str ++ "'")
| otherwise = do
mp <- getCommandOutput "manpath -g 2>/dev/null" `E.catch` \_ -> return []
let sects = ["man" ++ show n | n <- [1..9 :: Int]] let sects = ["man" ++ show n | n <- [1..9 :: Int]]
dirs = [d ++ "/" ++ s | d <- split ':' mp, s <- sects] dirs = [d ++ "/" ++ s | d <- split ':' paths, s <- sects]
stripExt = reverse . drop 1 . dropWhile (/= '.') . reverse
mans <- forM dirs $ \d -> do mans <- forM dirs $ \d -> do
exists <- doesDirectoryExist d exists <- doesDirectoryExist d
if exists if exists
then map (stripExt . stripSuffixes [".gz", ".bz2"]) `fmap` then map (stripExt . stripSuffixes [".gz", ".bz2"]) `fmap`
getDirectoryContents d getDirectoryContents d
else return [] else return []
mkComplFunFromList (uniqSort $ concat mans) str return $ uniqSort $ concat mans
manCompl :: [String] -> String -> IO [String]
manCompl mans s | s == "" || last s == ' ' = return []
| otherwise = do
-- XXX readline instead of bash's compgen?
f <- lines `fmap` getCommandOutput ("bash -c 'compgen -A file " ++ s ++ "'")
mkComplFunFromList (f ++ mans) s
-- | Run a command using shell and return its output. -- | Run a command using shell and return its output.
-- --
-- XXX merge with 'XMonad.Util.Run.runProcessWithInput'? -- XXX Merge into 'XMonad.Util.Run'?
-- --
-- * update documentation of the latter (there is no 'Maybe' in result) -- (Ask \"gurus\" whether @evaluate (length ...)@ approach is
-- -- better\/more idiomatic.)
-- * ask \"gurus\" whether @evaluate (length ...)@ approach is
-- better\/more idiomatic
getCommandOutput :: String -> IO String getCommandOutput :: String -> IO String
getCommandOutput s = do getCommandOutput s = do
(pin, pout, perr, ph) <- runInteractiveCommand s (pin, pout, perr, ph) <- runInteractiveCommand s
@@ -95,6 +96,9 @@ getCommandOutput s = do
waitForProcess ph waitForProcess ph
return output return output
stripExt :: String -> String
stripExt = reverse . drop 1 . dropWhile (/= '.') . reverse
stripSuffixes :: Eq a => [[a]] -> [a] -> [a] stripSuffixes :: Eq a => [[a]] -> [a] -> [a]
stripSuffixes sufs fn = stripSuffixes sufs fn =
head . catMaybes $ map (flip rstrip fn) sufs ++ [Just fn] head . catMaybes $ map (flip rstrip fn) sufs ++ [Just fn]

View File

@@ -89,20 +89,12 @@ getCommands :: IO [String]
getCommands = do getCommands = do
p <- getEnv "PATH" `catch` const (return []) p <- getEnv "PATH" `catch` const (return [])
let ds = split ':' p let ds = split ':' p
fp d f = d ++ "/" ++ f
es <- forM ds $ \d -> do es <- forM ds $ \d -> do
exists <- doesDirectoryExist d exists <- doesDirectoryExist d
if exists if exists
then getDirectoryContents d >>= filterM (isExecutable . fp d) then getDirectoryContents d
else return [] else return []
return . uniqSort . concat $ es return . uniqSort . filter ((/= '.') . head) . concat $ es
isExecutable :: FilePath ->IO Bool
isExecutable f = do
fe <- doesFileExist f
if fe
then fmap executable $ getPermissions f
else return False
split :: Eq a => a -> [a] -> [[a]] split :: Eq a => a -> [a] -> [[a]]
split _ [] = [] split _ [] = []

View File

@@ -12,8 +12,12 @@
-- --
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
module XMonad.Util.Dzen (dzen, dzenWithArgs, dzenScreen, module XMonad.Util.Dzen (
seconds) where dzen,
dzenWithArgs,
dzenScreen,
seconds
) where
import XMonad import XMonad
import XMonad.Util.Run (runProcessWithInputAndWait, seconds) import XMonad.Util.Run (runProcessWithInputAndWait, seconds)

View File

@@ -102,10 +102,10 @@ textWidthXMF dpy (Xft xftdraw) s = liftIO $ do
return $ xglyphinfo_width gi return $ xglyphinfo_width gi
#endif #endif
textExtentsXMF :: MonadIO m => Display -> XMonadFont -> String -> m (FontDirection,Int32,Int32,CharStruct) textExtentsXMF :: MonadIO m => XMonadFont -> String -> m (FontDirection,Int32,Int32,CharStruct)
textExtentsXMF _ (Core fs) s = return $ textExtents fs s textExtentsXMF (Core fs) s = return $ textExtents fs s
#ifdef XFT #ifdef XFT
textExtentsXMF _ (Xft xftfont) _ = liftIO $ do textExtentsXMF (Xft xftfont) _ = liftIO $ do
ascent <- xftfont_ascent xftfont ascent <- xftfont_ascent xftfont
descent <- xftfont_descent xftfont descent <- xftfont_descent xftfont
return (error "Font direction touched", fi ascent, fi descent, error "Font overall size touched") return (error "Font direction touched", fi ascent, fi descent, error "Font overall size touched")
@@ -120,7 +120,7 @@ stringPosition :: XMonadFont -> Rectangle -> Align -> String -> X (Position,Posi
stringPosition fs (Rectangle _ _ w h) al s = do stringPosition fs (Rectangle _ _ w h) al s = do
dpy <- asks display dpy <- asks display
width <- io $ textWidthXMF dpy fs s width <- io $ textWidthXMF dpy fs s
(_,a,d,_) <- io $ textExtentsXMF dpy fs s (_,a,d,_) <- io $ textExtentsXMF fs s
let y = fi $ ((h - fi (a + d)) `div` 2) + fi a; let y = fi $ ((h - fi (a + d)) `div` 2) + fi a;
x = case al of x = case al of
AlignCenter -> fi (w `div` 2) - fi (width `div` 2) AlignCenter -> fi (w `div` 2) - fi (width `div` 2)

View File

@@ -29,11 +29,9 @@ module XMonad.Util.Run (
) where ) where
import System.Posix.IO import System.Posix.IO
import System.Posix.Process (createSession, forkProcess, executeFile, import System.Posix.Process (executeFile)
getProcessStatus)
import Control.Concurrent (threadDelay) import Control.Concurrent (threadDelay)
import Control.Exception (try) import Control.Exception (try)
import System.Exit (ExitCode(ExitSuccess), exitWith)
import System.IO import System.IO
import System.Process (runInteractiveProcess, waitForProcess) import System.Process (runInteractiveProcess, waitForProcess)
import XMonad import XMonad
@@ -50,7 +48,7 @@ import Control.Monad
-- For an example usage of 'runProcessWithInputAndWait' see -- For an example usage of 'runProcessWithInputAndWait' see
-- "XMonad.Util.Dzen" -- "XMonad.Util.Dzen"
-- | Returns Just output if the command succeeded, and Nothing if it didn't. -- | Return output if the command succeeded, otherwise return @()@.
-- This corresponds to dmenu's notion of exit code 1 for a cancelled invocation. -- This corresponds to dmenu's notion of exit code 1 for a cancelled invocation.
runProcessWithInput :: FilePath -> [String] -> String -> IO String runProcessWithInput :: FilePath -> [String] -> String -> IO String
runProcessWithInput cmd args input = do runProcessWithInput cmd args input = do
@@ -67,22 +65,16 @@ runProcessWithInput cmd args input = do
-- | Wait is in us -- | Wait is in us
runProcessWithInputAndWait :: FilePath -> [String] -> String -> Int -> IO () runProcessWithInputAndWait :: FilePath -> [String] -> String -> Int -> IO ()
runProcessWithInputAndWait cmd args input timeout = do runProcessWithInputAndWait cmd args input timeout = do
pid <- forkProcess $ do doubleFork $ do
forkProcess $ do -- double fork it over to init (pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing
createSession hPutStr pin input
(pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing hFlush pin
hPutStr pin input threadDelay timeout
hFlush pin hClose pin
threadDelay timeout hClose pout
hClose pin hClose perr
hClose pout waitForProcess ph
hClose perr return ()
waitForProcess ph
return ()
exitWith ExitSuccess
return ()
getProcessStatus True False pid
return ()
-- | Multiplies by ONE MILLION, for use with -- | Multiplies by ONE MILLION, for use with
-- 'runProcessWithInputAndWait'. -- 'runProcessWithInputAndWait'.
@@ -113,7 +105,7 @@ seconds = fromEnum . (* 1000000)
-- interpolation, whereas the safeSpawn example can be safe because -- interpolation, whereas the safeSpawn example can be safe because
-- Firefox doesn't need any arguments if it is just being started. -- Firefox doesn't need any arguments if it is just being started.
safeSpawn :: MonadIO m => FilePath -> String -> m () safeSpawn :: MonadIO m => FilePath -> String -> m ()
safeSpawn prog arg = liftIO (try (forkProcess $ executeFile prog True [arg] Nothing) >> return ()) safeSpawn prog arg = liftIO (try (doubleFork $ executeFile prog True [arg] Nothing) >> return ())
unsafeSpawn :: MonadIO m => String -> m () unsafeSpawn :: MonadIO m => String -> m ()
unsafeSpawn = spawn unsafeSpawn = spawn
@@ -134,11 +126,7 @@ spawnPipe x = do
setFdOption wr CloseOnExec True setFdOption wr CloseOnExec True
h <- fdToHandle wr h <- fdToHandle wr
hSetBuffering h LineBuffering hSetBuffering h LineBuffering
pid <- forkProcess $ do doubleFork $ do
forkProcess $ do dupTo rd stdInput
dupTo rd stdInput executeFile "/bin/sh" False ["-c", x] Nothing
createSession
executeFile "/bin/sh" False ["-c", x] Nothing
exitWith ExitSuccess
getProcessStatus True False pid
return h return h

59
XMonad/Util/Timer.hs Normal file
View File

@@ -0,0 +1,59 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Util.Timer
-- Copyright : (c) Andrea Rossato and David Roundy 2007
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : andrea.rossato@unibz.it
-- Stability : unstable
-- Portability : unportable
--
-- A module for setting up timers
-----------------------------------------------------------------------------
module XMonad.Util.Timer
( -- * Usage
-- $usage
startTimer
, handleTimer
, TimerId
) where
import XMonad
import Control.Applicative
import Control.Concurrent
import Data.Unique
-- $usage
-- This module can be used to setup a timer to handle deferred events.
-- See 'XMonad.Layout.ShowWName' for an usage example.
type TimerId = Int
-- | Start a timer, which will send a ClientMessageEvent after some
-- time (in seconds).
startTimer :: Rational -> X TimerId
startTimer s = io $ do
u <- hashUnique <$> newUnique
doubleFork $ do
d <- openDisplay ""
rw <- rootWindow d $ defaultScreen d
threadDelay (fromEnum $ s * 1000000)
a <- internAtom d "XMONAD_TIMER" False
allocaXEvent $ \e -> do
setEventType e clientMessage
setClientMessageEvent e rw a 32 (fromIntegral u) currentTime
sendEvent d rw False structureNotifyMask e
sync d False
return u
-- | Given a 'TimerId' and an 'Event', run an action when the 'Event'
-- has been sent by the timer specified by the 'TimerId'
handleTimer :: TimerId -> Event -> X (Maybe a) -> X (Maybe a)
handleTimer ti (ClientMessageEvent {ev_message_type = mt, ev_data = dt}) action = do
d <- asks display
a <- io $ internAtom d "XMONAD_TIMER" False
if mt == a && dt /= [] && fromIntegral (head dt) == ti
then action
else return Nothing
handleTimer _ _ _ = return Nothing

View File

@@ -0,0 +1,41 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Util.WorkspaceCompare
-- Copyright : (c) Spencer Janssen <sjanssen@cse.unl.edu>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Spencer Janssen <sjanssen@cse.unl.edu>
-- Stability : unstable
-- Portability : unportable
--
module XMonad.Util.WorkspaceCompare ( getWsIndex, getWsCompare, getSortByTag ) where
import XMonad
import qualified XMonad.StackSet as S
import Data.List
import Data.Monoid
-- | Lookup the index of a workspace id in the user's config, return Nothing
-- if that workspace does not exist in the config.
getWsIndex :: X (WorkspaceId -> Maybe Int)
getWsIndex = do
spaces <- asks (workspaces . config)
return $ flip elemIndex spaces
-- | A comparison function for WorkspaceId
getWsCompare :: X (WorkspaceId -> WorkspaceId -> Ordering)
getWsCompare = do
wsIndex <- getWsIndex
return $ \a b -> f (wsIndex a) (wsIndex b) `mappend` compare a b
where
f Nothing Nothing = EQ
f (Just _) Nothing = LT
f Nothing (Just _) = GT
f (Just x) (Just y) = compare x y
-- | Sort several workspaces according to the order in getWsCompare
getSortByTag :: X ([WindowSpace] -> [WindowSpace])
getSortByTag = do
cmp <- getWsCompare
return $ sortBy (\a b -> cmp (S.tag a) (S.tag b))

View File

@@ -57,8 +57,8 @@ import XMonad.Util.Run (safeSpawn, unsafeSpawn)
-- | Returns a String corresponding to the current mouse selection in X; if there is none, an empty string is returned. Note that this is -- | Returns a String corresponding to the current mouse selection in X; if there is none, an empty string is returned. Note that this is
-- really only reliable for ASCII text and currently escapes or otherwise mangles more complex UTF-8 characters. -- really only reliable for ASCII text and currently escapes or otherwise mangles more complex UTF-8 characters.
getSelection :: IO String getSelection :: MonadIO m => m String
getSelection = do getSelection = io $ do
dpy <- openDisplay "" dpy <- openDisplay ""
let dflt = defaultScreen dpy let dflt = defaultScreen dpy
rootw <- rootWindow dpy dflt rootw <- rootWindow dpy dflt
@@ -80,8 +80,8 @@ getSelection = do
else destroyWindow dpy win >> return "" else destroyWindow dpy win >> return ""
-- | Set the current X Selection to a given String. -- | Set the current X Selection to a given String.
putSelection :: String -> IO () putSelection :: MonadIO m => String -> m ()
putSelection text = do putSelection text = io $ do
dpy <- openDisplay "" dpy <- openDisplay ""
let dflt = defaultScreen dpy let dflt = defaultScreen dpy
rootw <- rootWindow dpy dflt rootw <- rootWindow dpy dflt

View File

@@ -22,7 +22,7 @@ module XMonad.Util.XUtils (
, deleteWindow , deleteWindow
, paintWindow , paintWindow
, paintAndWrite , paintAndWrite
, stringToPixel , stringToPixel
) where ) where
@@ -44,15 +44,16 @@ averagePixels p1 p2 f =
let mn x1 x2 = round (fromIntegral x1 * f + fromIntegral x2 * (1-f)) let mn x1 x2 = round (fromIntegral x1 * f + fromIntegral x2 * (1-f))
Color p _ _ _ _ <- io $ allocColor d cm (Color 0 (mn r1 r2) (mn g1 g2) (mn b1 b2) 0) Color p _ _ _ _ <- io $ allocColor d cm (Color 0 (mn r1 r2) (mn g1 g2) (mn b1 b2) 0)
return p return p
-- | Create a simple window given a rectangle. If Nothing is given -- | Create a simple window given a rectangle. If Nothing is given
-- only the exposureMask will be set, otherwise the Just value. -- only the exposureMask will be set, otherwise the Just value.
-- Use 'showWindow' to map and hideWindow to unmap. -- Use 'showWindow' to map and hideWindow to unmap.
createNewWindow :: Rectangle -> Maybe EventMask -> String -> X Window createNewWindow :: Rectangle -> Maybe EventMask -> String -> Bool -> X Window
createNewWindow (Rectangle x y w h) m col = do createNewWindow (Rectangle x y w h) m col o = do
d <- asks display d <- asks display
rw <- asks theRoot rw <- asks theRoot
c <- stringToPixel d col c <- stringToPixel d col
win <- io $ createSimpleWindow d rw x y w h 0 c c win <- io $ mkWindow d (defaultScreenOfDisplay d) rw x y w h c o
case m of case m of
Just em -> io $ selectInput d win em Just em -> io $ selectInput d win em
Nothing -> io $ selectInput d win exposureMask Nothing -> io $ selectInput d win exposureMask
@@ -130,6 +131,21 @@ paintWindow' win (Rectangle x y wh ht) bw color b_color str = do
io $ freePixmap d p io $ freePixmap d p
io $ freeGC d gc io $ freeGC d gc
-- | Creates a window with the possibility of setting some attributes.
-- Not exported.
mkWindow :: Display -> Screen -> Window -> Position
-> Position -> Dimension -> Dimension -> Pixel -> Bool -> IO Window
mkWindow d s rw x y w h p o = do
let visual = defaultVisualOfScreen s
attrmask = cWOverrideRedirect .|. cWBackPixel .|. cWBorderPixel
allocaSetWindowAttributes $
\attributes -> do
set_override_redirect attributes o
set_border_pixel attributes p
set_background_pixel attributes p
createWindow d rw x y w h 0 (defaultDepthOfScreen s)
inputOutput visual attrmask attributes
-- | Short-hand for 'fromIntegral' -- | Short-hand for 'fromIntegral'
fi :: (Integral a, Num b) => a -> b fi :: (Integral a, Num b) => a -> b
fi = fromIntegral fi = fromIntegral

View File

@@ -1,5 +1,5 @@
name: xmonad-contrib name: xmonad-contrib
version: 0.5 version: 0.6
homepage: http://xmonad.org/ homepage: http://xmonad.org/
synopsis: Third party extensions for xmonad synopsis: Third party extensions for xmonad
description: description:
@@ -33,6 +33,10 @@ flag small_base
flag use_xft flag use_xft
description: Use Xft to render text description: Use Xft to render text
flag testing
description: Testing mode
default: False
library library
if flag(small_base) if flag(small_base)
build-depends: base >= 3, containers, directory, process, random build-depends: base >= 3, containers, directory, process, random
@@ -43,8 +47,12 @@ library
build-depends: X11-xft >= 0.2 build-depends: X11-xft >= 0.2
cpp-options: -DXFT cpp-options: -DXFT
build-depends: mtl, unix, X11>=1.4.0, xmonad==0.5 build-depends: mtl, unix, X11>=1.4.1, xmonad==0.6
ghc-options: -Wall -Werror ghc-options: -Wall
if flag(testing)
ghc-options: -Werror
exposed-modules: XMonad.Doc exposed-modules: XMonad.Doc
XMonad.Doc.Configuring XMonad.Doc.Configuring
XMonad.Doc.Extending XMonad.Doc.Extending
@@ -62,8 +70,10 @@ library
XMonad.Actions.FloatKeys XMonad.Actions.FloatKeys
XMonad.Actions.FocusNth XMonad.Actions.FocusNth
XMonad.Actions.MouseGestures XMonad.Actions.MouseGestures
XMonad.Actions.NoBorders
XMonad.Actions.RotSlaves XMonad.Actions.RotSlaves
XMonad.Actions.RotView XMonad.Actions.RotView
XMonad.Actions.Search
XMonad.Actions.SimpleDate XMonad.Actions.SimpleDate
XMonad.Actions.SinkAll XMonad.Actions.SinkAll
XMonad.Actions.Submap XMonad.Actions.Submap
@@ -79,6 +89,7 @@ library
XMonad.Hooks.DynamicLog XMonad.Hooks.DynamicLog
XMonad.Hooks.EwmhDesktops XMonad.Hooks.EwmhDesktops
XMonad.Hooks.ManageDocks XMonad.Hooks.ManageDocks
XMonad.Hooks.ManageHelpers
XMonad.Hooks.SetWMName XMonad.Hooks.SetWMName
XMonad.Hooks.UrgencyHook XMonad.Hooks.UrgencyHook
XMonad.Hooks.XPropManage XMonad.Hooks.XPropManage
@@ -102,10 +113,12 @@ library
XMonad.Layout.Named XMonad.Layout.Named
XMonad.Layout.NoBorders XMonad.Layout.NoBorders
XMonad.Layout.PerWorkspace XMonad.Layout.PerWorkspace
XMonad.Layout.Reflect
XMonad.Layout.ResizableTile XMonad.Layout.ResizableTile
XMonad.Layout.Roledex XMonad.Layout.Roledex
XMonad.Layout.Spiral XMonad.Layout.Spiral
XMonad.Layout.Square XMonad.Layout.Square
XMonad.Layout.ShowWName
XMonad.Layout.Tabbed XMonad.Layout.Tabbed
XMonad.Layout.ThreeColumns XMonad.Layout.ThreeColumns
XMonad.Layout.ToggleLayouts XMonad.Layout.ToggleLayouts
@@ -133,5 +146,7 @@ library
XMonad.Util.Invisible XMonad.Util.Invisible
XMonad.Util.NamedWindows XMonad.Util.NamedWindows
XMonad.Util.Run XMonad.Util.Run
XMonad.Util.Timer
XMonad.Util.WorkspaceCompare
XMonad.Util.XSelection XMonad.Util.XSelection
XMonad.Util.XUtils XMonad.Util.XUtils