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 )
, ("next-layout" , sendMessage NextLayout )
, ("default-layout" , asks (layoutHook . config) >>= setLayout )
, ("restart-wm" , sr >> restart Nothing True )
, ("restart-wm-no-resume", sr >> restart Nothing False )
, ("restart-wm" , sr >> restart "xmonad" True )
, ("restart-wm-no-resume", sr >> restart "xmonad" False )
, ("xterm" , spawn =<< asks (terminal . config) )
, ("run" , spawn "exe=`dmenu_path | dmenu -b` && exec $exe" )
, ("kill" , kill )

View File

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

View File

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

View File

@@ -10,7 +10,7 @@
-- Portability : unportable
--
-- 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,
shiftToPrev,
toggleWS,
nextScreen,
prevScreen,
shiftNextScreen,
shiftPrevScreen
) where
import Data.List ( sortBy, findIndex )
import Data.List ( findIndex )
import Data.Maybe ( fromMaybe )
import Data.Ord ( comparing )
import XMonad hiding (workspaces)
import qualified XMonad (workspaces)
import XMonad.StackSet hiding (filter)
import XMonad.Util.WorkspaceCompare
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
--
-- > import XMonad.Actions.CycleWS
--
-- > , ((modMask x, xK_Right), nextWS)
-- > , ((modMask x, xK_Left), prevWS)
-- > , ((modMask x .|. shiftMask, xK_Right), shiftToNext)
-- > , ((modMask x .|. shiftMask, xK_Left), shiftToPrev)
-- > , ((modMask x, xK_Down), nextWS)
-- > , ((modMask x, xK_Up), prevWS)
-- > , ((modMask x .|. shiftMask, xK_Down), shiftToNext)
-- > , ((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)
--
-- If you want to follow the moved window, you can use both actions:
--
-- > , ((modMask x .|. shiftMask, xK_Right), shiftToNext >> nextWS)
-- > , ((modMask x .|. shiftMask, xK_Left), shiftToPrev >> prevWS)
-- > , ((modMask x .|. shiftMask, xK_Down), shiftToNext >> nextWS)
-- > , ((modMask x .|. shiftMask, xK_Up), shiftToPrev >> prevWS)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
@@ -81,14 +88,47 @@ shiftBy d = wsBy d >>= windows . shift
wsBy :: Int -> X (WorkspaceId)
wsBy d = do
ws <- gets windowset
spaces <- asks (XMonad.workspaces . config)
let orderedWs = sortBy (comparing (wsIndex spaces)) (workspaces ws)
sort' <- getSortByTag
let orderedWs = sort' (workspaces ws)
let now = fromMaybe 0 $ findWsIndex (workspace (current ws)) orderedWs
let next = orderedWs !! ((now + d) `mod` length orderedWs)
return $ tag next
wsIndex :: [WorkspaceId] -> WindowSpace -> Maybe Int
wsIndex spaces ws = findIndex (== tag ws) spaces
findWsIndex :: WindowSpace -> [WindowSpace] -> Maybe Int
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).
module XMonad.Actions.FlexibleManipulate (
-- * Usage
-- $usage
mouseWindow, discrete, linear, resize, position
-- * Usage
-- $usage
mouseWindow, discrete, linear, resize, position
) where
import XMonad

View File

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

View File

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

View File

@@ -15,7 +15,7 @@
module XMonad.Actions.MouseGestures (
-- * Usage
-- $usage
Direction(..),
Direction(..),
mouseGesture
) 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.
-----------------------------------------------------------------------------
module XMonad.Actions.RotSlaves (
-- $usage
rotSlaves', rotSlavesUp, rotSlavesDown,
rotAll', rotAllUp, rotAllDown
) where
-- $usage
rotSlaves', rotSlavesUp, rotSlavesDown,
rotAll', rotAllUp, rotAllDown
) where
import XMonad.StackSet
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)
-- Stability : unstable
-- 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..]]
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

View File

@@ -41,8 +41,8 @@ import XMonad.Actions.CopyWindow
import XMonad.Actions.DynamicWorkspaces
import XMonad.Actions.RotView
--import XMonad.Hooks.ManageDocks
--import XMonad.Hooks.UrgencyHook
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.UrgencyHook
myXPConfig :: XPConfig
myXPConfig = defaultXPConfig {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*"
@@ -77,7 +77,7 @@ keys x = M.fromList $
-- quit, or restart
, ((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 ),
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..])
config = -- withUrgencyHook FocusUrgencyHook $
withUrgencyHook NoUrgencyHook $
defaultConfig
{ borderWidth = 1 -- Width of the window border in pixels.
, XMonad.workspaces = ["1:mutt","2:iceweasel"]
, layoutHook = workspaceDir "~" $ windowNavigation $
toggleLayouts (noBorders Full) $ -- avoidStruts $
toggleLayouts (noBorders Full) $ avoidStruts $
Named "tabbed" (noBorders mytab) |||
Named "xclock" (mytab ****//* combineTwo Square mytab mytab) |||
Named "three" (mytab **//* mytab *//* combineTwo Square mytab mytab) |||
Named "widescreen" ((mytab *||* mytab)
****//* combineTwo Square mytab mytab) -- |||
--mosaic 0.25 0.5

View File

@@ -20,7 +20,7 @@ import System.IO (hPutStrLn)
sjanssenConfig = do
xmobar <- spawnPipe "xmobar"
return $ defaultConfig
{ terminal = "urxvt"
{ terminal = "urxvtc"
, workspaces = ["irc", "web"] ++ map show [3 .. 7 :: Int] ++ ["mail", "im"]
, logHook = dynamicLogWithPP $ sjanssenPP { ppOutput = hPutStrLn xmobar }
, 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
avoid name clashes with Prelude functions such as 'Prelude.delete' and
'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
function to manipulate the 'XMonad.Core.WindowSet' and does all the
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
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.
@@ -260,6 +260,31 @@ xmonad contributed extensions.
* Any pure function added to the core should have QuickCheck properties
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

View File

@@ -152,6 +152,9 @@ edit your key bindings.
* "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.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.ManageHelpers": provide helper functions to be used
in @manageHook@.
* "XMonad.Hooks.SetWMName": set the WM name. Useful when e.g. running
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
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.Square": split the screen into a square area plus the rest.

View File

@@ -10,17 +10,18 @@
--
-- DynamicLog
--
-- Log events in:
-- By default, log events in:
--
-- > 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.
--
-----------------------------------------------------------------------------
module XMonad.Hooks.DynamicLog (
-- * Usage
-- $usage
-- $usage
dynamicLog,
dynamicLogDzen,
dynamicLogXmobar,
@@ -37,7 +38,7 @@ module XMonad.Hooks.DynamicLog (
makeSimpleDzenConfig
) where
--
--
-- Useful imports
--
import XMonad
@@ -45,12 +46,13 @@ import Data.Maybe ( isJust )
import Data.List
import Data.Ord ( comparing )
import qualified XMonad.StackSet as S
import Data.Monoid
import System.IO
import XMonad.Util.WorkspaceCompare
import XMonad.Util.NamedWindows
import XMonad.Util.Run
import XMonad.Hooks.UrgencyHook
-- $usage
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad
@@ -67,9 +69,9 @@ makeSimpleDzenConfig = do
, logHook = dynamicLogWithPP dzenPP
{ ppOutput = hPutStrLn h } }
-- |
-- |
--
-- Run xmonad with a dzen status bar set to some nice defaults. Output
-- Run xmonad with a dzen status bar set to some nice defaults. Output
-- is taken from the dynamicLogWithPP hook.
--
-- > main = dzen xmonad
@@ -104,13 +106,15 @@ dynamicLog = dynamicLogWithPP defaultPP
-- A log function that uses the 'PP' hooks to customize output.
dynamicLogWithPP :: PP -> X ()
dynamicLogWithPP pp = do
spaces <- asks (workspaces . config)
winset <- gets windowset
urgents <- readUrgents
sort' <- getSortByTag
-- layout description
ld <- withWindowSet $ return . description . S.layout . S.workspace . S.current
let ld = description . S.layout . S.workspace . S.current $ winset
-- workspace list
ws <- withWindowSet $ return . pprWindowSet spaces pp
let ws = pprWindowSet sort' urgents pp winset
-- 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 $
[ ws
@@ -124,27 +128,18 @@ dynamicLogWithPP pp = do
dynamicLogDzen :: X ()
dynamicLogDzen = dynamicLogWithPP dzenPP
pprWindowSet :: [String] -> PP -> WindowSet -> String
pprWindowSet spaces pp s = sepBy (ppWsSep pp) $ map fmt $ sortBy cmp
(map S.workspace (S.current s : S.visible s) ++ S.hidden 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))
pprWindowSet :: ([WindowSpace] -> [WindowSpace]) -> [Window] -> PP -> WindowSet -> String
pprWindowSet sort' urgents pp s = sepBy (ppWsSep pp) . map fmt . sort' $
map S.workspace (S.current s : S.visible s) ++ S.hidden s
where this = S.tag (S.workspace (S.current s))
visibles = map (S.tag . S.workspace) (S.visible s)
fmt w = printer pp (S.tag w)
where printer | S.tag w == this = ppCurrent
| S.tag w `elem` visibles = ppVisible
| isJust (S.stack w) = ppHidden
| otherwise = ppHiddenNoWindows
where printer | S.tag w == this = ppCurrent
| S.tag w `elem` visibles = ppVisible
| any (\x -> maybe False (== S.tag w) (S.findTag x s)) urgents = \ppC -> ppUrgent ppC . ppHidden ppC
| isJust (S.stack w) = ppHidden
| otherwise = ppHiddenNoWindows
-- |
-- 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
-- dynamicLogPP
data PP = PP { ppCurrent, ppVisible
, ppHidden, ppHiddenNoWindows :: WorkspaceId -> String
, ppHidden, ppHiddenNoWindows
, ppUrgent :: WorkspaceId -> String
, ppSep, ppWsSep :: String
, ppTitle :: String -> String
, ppLayout :: String -> String
@@ -212,6 +208,7 @@ defaultPP = PP { ppCurrent = wrap "[" "]"
, ppVisible = wrap "<" ">"
, ppHidden = id
, ppHiddenNoWindows = const ""
, ppUrgent = id
, ppSep = " : "
, ppWsSep = " "
, ppTitle = shorten 80
@@ -226,6 +223,7 @@ dzenPP = defaultPP { ppCurrent = dzenColor "white" "#2b4f98" . pad
, ppVisible = dzenColor "black" "#999999" . pad
, ppHidden = dzenColor "black" "#cccccc" . pad
, ppHiddenNoWindows = const ""
, ppUrgent = dzenColor "red" "yellow"
, ppWsSep = ""
, ppSep = ""
, ppLayout = dzenColor "black" "#cccccc" .
@@ -247,7 +245,7 @@ sjanssenPP = defaultPP { ppCurrent = xmobarColor "white" "#ff000000"
-- | These are good defaults to be used with the xmobar status bar
dynamicLogXmobar :: X ()
dynamicLogXmobar =
dynamicLogXmobar =
dynamicLogWithPP defaultPP { ppCurrent = xmobarColor "yellow" "" . wrap "[" "]"
, ppTitle = xmobarColor "green" "" . shorten 40
, ppVisible = wrap "(" ")"

View File

@@ -17,15 +17,15 @@ module XMonad.Hooks.EwmhDesktops (
ewmhDesktopsLogHook
) where
import Data.List (elemIndex, sortBy)
import Data.Ord (comparing)
import Data.Maybe (fromMaybe)
import Data.List
import Data.Maybe
import XMonad
import Control.Monad
import qualified XMonad.StackSet as W
import XMonad.Hooks.SetWMName
import XMonad.Util.WorkspaceCompare
-- $usage
-- 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.
ewmhDesktopsLogHook :: X ()
ewmhDesktopsLogHook = withWindowSet $ \s -> do
-- Bad hack because xmonad forgets the original order of things, it seems
-- see http://code.google.com/p/xmonad/issues/detail?id=53
let ws = sortBy (comparing W.tag) $ W.workspaces s
sort' <- getSortByTag
let ws = sort' $ W.workspaces s
let wins = W.allWindows s
setSupported
@@ -62,18 +61,26 @@ ewmhDesktopsLogHook = withWindowSet $ \s -> do
setDesktopNames (map W.tag ws)
-- Current desktop
fromMaybe (return ()) $ do
n <- W.lookupWorkspace 0 s
i <- elemIndex n $ map W.tag ws
return $ setCurrentDesktop i
let curr = fromJust $ elemIndex (W.tag (W.workspace (W.current s))) $ map W.tag ws
setCurrentDesktop curr
setClientList wins
-- Per window Desktop
forM (zip ws [(0::Int)..]) $ \(w, wn) ->
forM (W.integrate' (W.stack w)) $ \win -> do
-- To make gnome-panel accept our xinerama stuff, we display
-- 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
setActiveWindow
return ()
@@ -98,7 +105,7 @@ setDesktopNames names = withDisplay $ \dpy -> do
a <- getAtom "_NET_DESKTOP_NAMES"
c <- getAtom "UTF8_STRING"
let names' = map (fromIntegral.fromEnum) $
concatMap (("Workspace "++) . (++['\0'])) names
concatMap (++['\0']) names
io $ changeProperty8 dpy r a c propModeReplace names'
setClientList :: [Window] -> X ()
@@ -122,9 +129,23 @@ setSupported = withDisplay $ \dpy -> do
r <- asks theRoot
a <- getAtom "_NET_SUPPORTED"
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)
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 Foreign.C.Types (CLong)
import Data.Maybe (catMaybes)
-- import Data.Maybe (catMaybes, fromMaybe)
import Control.Monad
-- $usage
-- 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:
--
-- > layoutHook = avoidStruts (tall ||| mirror tall ||| ...)
-- > where tall = Tall 1 (3/100) (1/2)
--
-- 'AvoidStruts' also supports toggling the dock gap, add a keybinding similar
-- 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
@@ -54,29 +59,35 @@ manageDocks :: ManageHook
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 = ask >>= \w -> liftX $ do
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
case mbr of
Just [r] -> return (fromIntegral r == d)
Just [r] -> return $ elem (fromIntegral r) [dock, desk]
_ -> return False
-- |
-- 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
a <- getAtom "_NET_WM_STRUT"
mbr <- getProp a w
case mbr of
Just [l,r,t,b] -> return (Just (
fromIntegral t,
fromIntegral b,
fromIntegral l,
fromIntegral r))
_ -> return Nothing
spa <- getAtom "_NET_WM_STRUT_PARTIAL"
sa <- getAtom "_NET_WM_STRUT"
msp <- getProp spa w
case msp of
Just sp -> return $ parseStrutPartial sp
Nothing -> fmap (maybe [] parseStrut) $ getProp sa w
where
parseStrut xs@[_, _, _, _] = parseStrutPartial . take 12 $ xs ++ cycle [minBound, maxBound]
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
@@ -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
-- settings are satisfied.
calcGap :: X Rectangle
calcGap :: X (Rectangle -> Rectangle)
calcGap = withDisplay $ \dpy -> do
rootw <- asks theRoot
-- We don't keep track of dock like windows, so we find all of them here
(_,_,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
-- the width of the screen because xlib caches this info and it tends to
-- be incorrect after RAndR
wa <- io $ getWindowAttributes dpy rootw
return $ reduceScreen (foldl max4 (0,0,0,0) struts)
$ Rectangle (fi $ wa_x wa) (fi $ wa_y wa) (fi $ wa_width wa) (fi $ wa_height wa)
-- |
-- 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)
let screen = r2c $ 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
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral
-- | Given strut values and the screen rectangle, compute a reduced screen
-- rectangle.
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 -> RectC
r2c (Rectangle x y w h) = (fi x, fi y, fi x + fi w, fi y + fi h)
r2c :: Rectangle -> (Position, Position, Position, Position)
r2c (Rectangle x y w h) = (x, y, x + fi w, y + fi h)
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
c2r :: RectC -> Rectangle
c2r (x1, y1, x2, y2) = Rectangle (fi x1) (fi y1) (fi $ x2 - x1) (fi $ y2 - y1)
-- | Adjust layout automagically.
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
doLayout (AvoidStruts True lo) r s =
do rect <- fmap (flip fitRect r) calcGap
do rect <- fmap ($ r) calcGap
(wrs,mlo') <- doLayout lo rect s
return (wrs, AvoidStruts True `fmap` mlo')
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
return (AvoidStruts b `fmap` ml')
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
right = case right' of
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
Rectangle x y w 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 r = do
let mask = Just $ exposureMask .|. buttonPressMask
w <- createNewWindow r mask handleColor
w <- createNewWindow r mask handleColor False
showWindow w
return w

View File

@@ -17,7 +17,7 @@
module XMonad.Layout.Grid (
-- * Usage
-- $usage
Grid(..)
Grid(..)
) where
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
-- 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.TwoPane
--
-- Then add some keybindings; for example:
--
-- > , ((modMask .|. shiftMask, xK_space), layoutScreens 2 (TwoPane 0.5 0.5))
-- > , ((controlMask .|. modMask .|. shiftMask, xK_space), rescreen)
-- > , ((modMask x .|. shiftMask, xK_space), layoutScreens 2 (TwoPane 0.5 0.5))
-- > , ((modMask x .|. controlMask .|. shiftMask, xK_space), rescreen)
--
-- 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
@@ -45,9 +47,9 @@ import qualified XMonad.StackSet as W
--
-- > import XMonad.Layout.LayoutScreens
--
-- > , ((modMask .|. shiftMask, xK_space),
-- > , ((modMask x .|. shiftMask, xK_space),
-- > 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
-- "XMonad.Doc.Extending#Editing_key_bindings".

View File

@@ -22,6 +22,8 @@ module XMonad.Layout.Magnifier
-- $usage
magnifier,
magnifier',
magnifiercz,
magnifiercz',
MagnifyMsg (..)
) where
@@ -34,12 +36,24 @@ import XMonad.Layout.LayoutModifier
--
-- > 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:
--
-- > myLayouts = magnifier (Tall 1 (3/100) (1/2)) ||| Full ||| etc..
-- > 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:
--
-- "XMonad.Doc.Extending#Editing_the_layout_hook"
@@ -59,11 +73,20 @@ import XMonad.Layout.LayoutModifier
magnifier :: l a -> ModifiedLayout Magnifier l a
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
-- master window.
magnifier' :: l a -> ModifiedLayout Magnifier l a
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 )
instance Message MagnifyMsg

View File

@@ -23,6 +23,7 @@ module XMonad.Layout.MultiToggle (
Toggle(..),
(??),
EOT(..),
single,
mkToggle
) where
@@ -39,7 +40,7 @@ import Data.Maybe
-- group of radio buttons.
--
-- 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
-- layout, then reapply the transformer.
--
@@ -63,7 +64,7 @@ import Data.Maybe
--
-- 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:
--
@@ -81,7 +82,7 @@ import Data.Maybe
-- > data NOBORDERS = NOBORDERS deriving (Read, Show, Eq, Typeable)
-- > instance Transformer NOBORDERS Window where
-- > transform _ x k = k (noBorders x)
-- >
-- >
-- > data FULL = FULL deriving (Read, Show, Eq, Typeable)
-- > instance Transformer FULL Window where
-- > transform _ x k = k Full
@@ -90,7 +91,7 @@ import Data.Maybe
-- layout = id
-- . 'XMonad.Layout.NoBorders.smartBorders'
-- . mkToggle (NOBORDERS ?? FULL ?? EOT)
-- . mkToggle (MIRROR ?? EOT)
-- . mkToggle (single MIRROR)
-- $ tiled ||| 'XMonad.Layout.Grid.Grid' ||| 'XMonad.Layout.Circle.Circle'
-- @
--
@@ -164,6 +165,10 @@ infixr 0 ??
(??) :: (HList b w) => a -> b -> HCons a b
(??) = HCons
-- | Construct a singleton transformer table.
single :: a -> HCons a EOT
single = (?? EOT)
class HList c a where
find :: (Transformer t a) => c -> t -> Maybe Int
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 }))
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

View File

@@ -12,6 +12,13 @@
--
-- Configure layouts on a per-workspace basis. NOTE that this module
-- 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 (

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 qualified XMonad.StackSet as W
import Control.Monad
import qualified Data.Map as M
import Data.List ((\\))
-- $usage
-- 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
handleMessage (ResizableTall nmaster delta frac mfrac) m =
do ms <- (W.stack . W.workspace . W.current) `fmap` gets windowset
case ms of
Nothing -> return Nothing
Just s -> return $ msum [fmap resize (fromMessage m)
,fmap (\x -> mresize x s) (fromMessage m)
,fmap incmastern (fromMessage m)]
where resize Shrink = ResizableTall nmaster delta (max 0 $ frac-delta) mfrac
fs <- (M.keys . W.floating) `fmap` gets windowset
return $ ms >>= unfloat fs >>= handleMesg
where handleMesg s = msum [fmap resize (fromMessage m)
,fmap (\x -> mresize x s) (fromMessage m)
,fmap incmastern (fromMessage m)]
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
mresize MirrorShrink s = mresize' s 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.Font
import XMonad.Hooks.UrgencyHook
-- $usage
-- 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 =
TConf { activeColor :: String
, inactiveColor :: String
, urgentColor :: String
, activeBorderColor :: String
, inactiveTextColor :: String
, inactiveBorderColor :: String
, urgentBorderColor :: String
, activeTextColor :: String
, inactiveTextColor :: String
, urgentTextColor :: String
, fontName :: String
, tabSize :: Int
} deriving (Show, Read)
@@ -74,10 +79,13 @@ defaultTConf :: TConf
defaultTConf =
TConf { activeColor = "#999999"
, inactiveColor = "#666666"
, urgentColor = "#FFFF00"
, activeBorderColor = "#FFFFFF"
, inactiveBorderColor = "#BBBBBB"
, urgentBorderColor = "##00FF00"
, activeTextColor = "#FFFFFF"
, inactiveTextColor = "#BFBFBF"
, urgentTextColor = "#FF0000"
, fontName = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
, tabSize = 20
}
@@ -86,7 +94,7 @@ data TabState =
TabState { tabsWindows :: [(Window,Window)]
, scr :: Rectangle
, font :: XMonadFont
}
}
data Tabbed s a =
Tabbed (Invisible Maybe TabState) s TConf
@@ -128,8 +136,8 @@ handleMess _ _ = return Nothing
handleEvent :: Shrinker s => s -> TConf -> TabState -> Event -> X ()
-- button press
handleEvent ishr conf (TabState {tabsWindows = tws, scr = screen, font = fs})
(ButtonEvent {ev_window = thisw, ev_subwindow = thisbw, ev_event_type = t})
handleEvent ishr conf (TabState {tabsWindows = tws, scr = screen, font = fs})
(ButtonEvent {ev_window = thisw, ev_subwindow = thisbw, ev_event_type = t })
| t == buttonPress, tl <- map fst tws, thisw `elem` tl || thisbw `elem` tl = do
case lookup thisw tws of
Just x -> do focus x
@@ -174,7 +182,7 @@ createTabs c (Rectangle x y wh ht) owl@(ow:ows) = do
height = fromIntegral $ tabSize c
mask = Just (exposureMask .|. buttonPressMask)
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]
ws <- createTabs c (Rectangle (x + fromIntegral wid) y (wh - wid) ht) ows
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 ishr c fs wh (tabw,ow) = do
nw <- getName ow
ur <- readUrgents
let ht = fromIntegral $ tabSize c :: Dimension
focusColor win ic ac = (maybe ic (\focusw -> if focusw == win
then ac else ic) . W.peek)
`fmap` gets windowset
focusColor win ic ac uc = (maybe ic (\focusw -> case () of
_ | focusw == win -> ac
| win `elem` ur -> uc
| otherwise -> ic) . W.peek)
`fmap` gets windowset
(bc',borderc',tc') <- focusColor ow
(inactiveColor c, inactiveBorderColor c, inactiveTextColor c)
(activeColor c, activeBorderColor c, activeTextColor c)
(urgentColor c, urgentBorderColor c, urgentTextColor c)
dpy <- asks display
let s = shrinkIt ishr
name <- shrinkWhile s (\n -> do
size <- io $ textWidthXMF dpy fs n
return $ size > fromIntegral wh - fromIntegral (ht `div` 2)) (show nw)
size <- io $ textWidthXMF dpy fs n
return $ size > fromIntegral wh - fromIntegral (ht `div` 2)) (show nw)
paintAndWrite tabw fs wh ht 1 bc' borderc' tc' bc' AlignCenter name
shrink :: TConf -> Rectangle -> Rectangle
@@ -205,10 +217,10 @@ shrinkWhile sh p x = sw $ sh x
where sw [n] = return n
sw [] = return ""
sw (n:ns) = do
cond <- p n
if cond
then sw ns
else return n
cond <- p n
if cond
then sw ns
else return n
data CustomShrink = CustomShrink
instance Show CustomShrink where show _ = ""

View File

@@ -96,6 +96,7 @@ data XPConfig =
, position :: XPPosition -- ^ Position: 'Top' or 'Bottom'
, height :: Dimension -- ^ Window height
, historySize :: Int -- ^ The number of history entries to be saved
, defaultText :: String -- ^ The text by default in the prompt line
} deriving (Show, Read)
data XPType = forall p . XPrompt p => XPT p
@@ -135,6 +136,7 @@ defaultXPConfig =
, position = Bottom
, height = 18
, historySize = 256
, defaultText = []
}
type ComplFunction = String -> IO [String]
@@ -142,7 +144,21 @@ type ComplFunction = String -> IO [String]
initState :: XPrompt p => Display -> Window -> Window -> Rectangle -> ComplFunction
-> GC -> XMonadFont -> p -> [History] -> XPConfig -> XPState
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
-- 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_e -> endOfLine >> 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_BackSpace -> killWord Prev >> go
| ks == xK_g || ks == xK_c -> quit
@@ -380,6 +398,21 @@ moveCursor d =
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)
-- | 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 d = do
h <- getHistory
@@ -454,7 +487,7 @@ printPrompt drw = do
ht = height c
fsl <- io $ textWidthXMF (dpy st) fs f
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
x = (asc + desc) `div` 2
@@ -521,7 +554,7 @@ getComplWinDim compl = do
(x,y) = case position c of
Top -> (0,ht)
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
xp = (asc + desc) `div` 2
yy = map fi . take (fi actual_rows) $ [yp,(yp + ht)..]
@@ -613,7 +646,7 @@ getHistory = do
readHistory :: IO ([History],Handle)
readHistory = do
home <- getEnv "HOME"
let path = home ++ "/.xmonad_history"
let path = home ++ "/.xmonad/history"
f <- fileExist path
if f then do h <- openFile path ReadMode
str <- hGetContents h
@@ -627,7 +660,7 @@ readHistory = do
writeHistory :: [History] -> IO ()
writeHistory hist = do
home <- getEnv "HOME"
let path = home ++ "/.xmonad_history"
let path = home ++ "/.xmonad/history"
catch (writeFile path (show hist)) (\_ -> do putStrLn "error in writing"; return ())
-- $xutils

View File

@@ -13,8 +13,6 @@
--
-- * narrow completions by section number, if the one is specified
-- (like @\/etc\/bash_completion@ does)
--
-- * write QuickCheck properties
-----------------------------------------------------------------------------
module XMonad.Prompt.Man (
@@ -58,33 +56,36 @@ instance XPrompt Man where
-- | Query for manual page to be displayed.
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]
manCompl str | '/' `elem` str = do
-- XXX It may be better to use readline instead of bash's compgen...
lines `fmap` getCommandOutput ("bash -c 'compgen -A file " ++ str ++ "'")
| otherwise = do
mp <- getCommandOutput "manpath -g 2>/dev/null" `E.catch` \_ -> return []
getMans :: IO [String]
getMans = do
paths <- getCommandOutput "manpath -g 2>/dev/null" `E.catch` \_ -> return []
let sects = ["man" ++ show n | n <- [1..9 :: Int]]
dirs = [d ++ "/" ++ s | d <- split ':' mp, s <- sects]
stripExt = reverse . drop 1 . dropWhile (/= '.') . reverse
dirs = [d ++ "/" ++ s | d <- split ':' paths, s <- sects]
mans <- forM dirs $ \d -> do
exists <- doesDirectoryExist d
if exists
then map (stripExt . stripSuffixes [".gz", ".bz2"]) `fmap`
getDirectoryContents d
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.
--
-- 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 s = do
(pin, pout, perr, ph) <- runInteractiveCommand s
@@ -95,6 +96,9 @@ getCommandOutput s = do
waitForProcess ph
return output
stripExt :: String -> String
stripExt = reverse . drop 1 . dropWhile (/= '.') . reverse
stripSuffixes :: Eq a => [[a]] -> [a] -> [a]
stripSuffixes sufs fn =
head . catMaybes $ map (flip rstrip fn) sufs ++ [Just fn]

View File

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

View File

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

View File

@@ -102,10 +102,10 @@ textWidthXMF dpy (Xft xftdraw) s = liftIO $ do
return $ xglyphinfo_width gi
#endif
textExtentsXMF :: MonadIO m => Display -> XMonadFont -> String -> m (FontDirection,Int32,Int32,CharStruct)
textExtentsXMF _ (Core fs) s = return $ textExtents fs s
textExtentsXMF :: MonadIO m => XMonadFont -> String -> m (FontDirection,Int32,Int32,CharStruct)
textExtentsXMF (Core fs) s = return $ textExtents fs s
#ifdef XFT
textExtentsXMF _ (Xft xftfont) _ = liftIO $ do
textExtentsXMF (Xft xftfont) _ = liftIO $ do
ascent <- xftfont_ascent xftfont
descent <- xftfont_descent xftfont
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
dpy <- asks display
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;
x = case al of
AlignCenter -> fi (w `div` 2) - fi (width `div` 2)

View File

@@ -29,11 +29,9 @@ module XMonad.Util.Run (
) where
import System.Posix.IO
import System.Posix.Process (createSession, forkProcess, executeFile,
getProcessStatus)
import System.Posix.Process (executeFile)
import Control.Concurrent (threadDelay)
import Control.Exception (try)
import System.Exit (ExitCode(ExitSuccess), exitWith)
import System.IO
import System.Process (runInteractiveProcess, waitForProcess)
import XMonad
@@ -50,7 +48,7 @@ import Control.Monad
-- For an example usage of 'runProcessWithInputAndWait' see
-- "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.
runProcessWithInput :: FilePath -> [String] -> String -> IO String
runProcessWithInput cmd args input = do
@@ -67,22 +65,16 @@ runProcessWithInput cmd args input = do
-- | Wait is in us
runProcessWithInputAndWait :: FilePath -> [String] -> String -> Int -> IO ()
runProcessWithInputAndWait cmd args input timeout = do
pid <- forkProcess $ do
forkProcess $ do -- double fork it over to init
createSession
(pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing
hPutStr pin input
hFlush pin
threadDelay timeout
hClose pin
hClose pout
hClose perr
waitForProcess ph
return ()
exitWith ExitSuccess
return ()
getProcessStatus True False pid
return ()
doubleFork $ do
(pin, pout, perr, ph) <- runInteractiveProcess cmd args Nothing Nothing
hPutStr pin input
hFlush pin
threadDelay timeout
hClose pin
hClose pout
hClose perr
waitForProcess ph
return ()
-- | Multiplies by ONE MILLION, for use with
-- 'runProcessWithInputAndWait'.
@@ -104,16 +96,16 @@ seconds = fromEnum . (* 1000000)
-- unsafeSpawn is an alias for XMonad's 'spawn', to remind one that use
-- of it can be, well, unsafe.
-- Examples:
--
--
-- > , ((modMask, xK_Print), unsafeSpawn "import -window root png:$HOME/xwd-$(date +%s)$$.png")
-- > , ((modMask, xK_d ), safeSpawn "firefox" "")
--
--
-- Note that the unsafeSpawn example must be unsafe and not safe because
-- it makes use of shell interpretation by relying on @$HOME@ and
-- interpolation, whereas the safeSpawn example can be safe because
-- Firefox doesn't need any arguments if it is just being started.
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 = spawn
@@ -134,11 +126,7 @@ spawnPipe x = do
setFdOption wr CloseOnExec True
h <- fdToHandle wr
hSetBuffering h LineBuffering
pid <- forkProcess $ do
forkProcess $ do
dupTo rd stdInput
createSession
executeFile "/bin/sh" False ["-c", x] Nothing
exitWith ExitSuccess
getProcessStatus True False pid
doubleFork $ do
dupTo rd stdInput
executeFile "/bin/sh" False ["-c", x] Nothing
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
-- really only reliable for ASCII text and currently escapes or otherwise mangles more complex UTF-8 characters.
getSelection :: IO String
getSelection = do
getSelection :: MonadIO m => m String
getSelection = io $ do
dpy <- openDisplay ""
let dflt = defaultScreen dpy
rootw <- rootWindow dpy dflt
@@ -80,8 +80,8 @@ getSelection = do
else destroyWindow dpy win >> return ""
-- | Set the current X Selection to a given String.
putSelection :: String -> IO ()
putSelection text = do
putSelection :: MonadIO m => String -> m ()
putSelection text = io $ do
dpy <- openDisplay ""
let dflt = defaultScreen dpy
rootw <- rootWindow dpy dflt

View File

@@ -3,7 +3,7 @@
-- Module : XMonad.Util.XUtils
-- Copyright : (c) 2007 Andrea Rossato
-- License : BSD-style (see xmonad/LICENSE)
--
--
-- Maintainer : andrea.rossato@unibz.it
-- Stability : unstable
-- Portability : unportable
@@ -12,7 +12,7 @@
--
-----------------------------------------------------------------------------
module XMonad.Util.XUtils (
module XMonad.Util.XUtils (
-- * Usage:
-- $usage
averagePixels
@@ -22,7 +22,7 @@ module XMonad.Util.XUtils (
, deleteWindow
, paintWindow
, paintAndWrite
, stringToPixel
, stringToPixel
) where
@@ -44,15 +44,16 @@ averagePixels p1 p2 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)
return p
-- | Create a simple window given a rectangle. If Nothing is given
-- only the exposureMask will be set, otherwise the Just value.
-- Use 'showWindow' to map and hideWindow to unmap.
createNewWindow :: Rectangle -> Maybe EventMask -> String -> X Window
createNewWindow (Rectangle x y w h) m col = do
createNewWindow :: Rectangle -> Maybe EventMask -> String -> Bool -> X Window
createNewWindow (Rectangle x y w h) m col o = do
d <- asks display
rw <- asks theRoot
c <- stringToPixel d col
win <- io $ createSimpleWindow d rw x y w h 0 c c
c <- stringToPixel d col
win <- io $ mkWindow d (defaultScreenOfDisplay d) rw x y w h c o
case m of
Just em -> io $ selectInput d win em
Nothing -> io $ selectInput d win exposureMask
@@ -77,9 +78,9 @@ deleteWindow w = do
io $ destroyWindow d w
-- | Fill a window with a rectangle and a border
paintWindow :: Window -- ^ The window where to draw
paintWindow :: Window -- ^ The window where to draw
-> Dimension -- ^ Window width
-> Dimension -- ^ Window height
-> Dimension -- ^ Window height
-> Dimension -- ^ Border width
-> String -- ^ Window background color
-> String -- ^ Border color
@@ -88,10 +89,10 @@ paintWindow w wh ht bw c bc =
paintWindow' w (Rectangle 0 0 wh ht) bw c bc Nothing
-- | Fill a window with a rectangle and a border, and write a string at given position
paintAndWrite :: Window -- ^ The window where to draw
paintAndWrite :: Window -- ^ The window where to draw
-> XMonadFont -- ^ XMonad Font for drawing
-> Dimension -- ^ Window width
-> Dimension -- ^ Window height
-> Dimension -- ^ Window height
-> Dimension -- ^ Border width
-> String -- ^ Window background color
-> String -- ^ Border color
@@ -130,6 +131,21 @@ paintWindow' win (Rectangle x y wh ht) bw color b_color str = do
io $ freePixmap d p
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'
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral

View File

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