175 Commits

Author SHA1 Message Date
Peter Jones
1833003404 Update X11 version for xmonad/xmonad#9 2016-11-22 18:49:01 -07:00
Peter Jones
be036f9bb9 Export `removeEmptyWorkspaceByTag'
It looks like this function should have been exported all along but
was overlooked.
2016-11-21 17:15:53 -07:00
Peter Jones
217abc39a2 Compose startupHook/logHook in the same order as other modules
I believe this was causing issues where a dynamically created
workspace would not properly trigger manageDocks logic.
2016-11-16 15:13:58 -07:00
Peter Jones
5790913eae Teach X.A.DynamicProjects to use removeWorkspaceByTag when deleting a project
When deleting a dynamic project, also delete its workspace.
2016-11-15 17:00:50 -07:00
Brent Yorgey
d21ed81801 Merge pull request #106 from IvanMalison/custom_focus_raise_next_maybe
X.A.WindowGo: Add arg for custom focus fn to raiseNextMaybe
2016-11-08 22:59:21 -05:00
Brent Yorgey
cc44be649d Merge pull request #113 from pjones/xmonad/features/layoutb
Refactor all X.L.LayoutBuilderP functionality into X.L.LayoutBuilder
2016-11-08 22:57:08 -05:00
Brent Yorgey
a7059e1a32 Merge pull request #114 from liskin/workspacenames2
X.A.WorkspaceNames: add getWorkspaceNames'
2016-11-08 22:53:31 -05:00
Tomas Janousek
7ada94df42 X.A.WorkspaceNames: add getWorkspaceNames' 2016-11-07 20:59:20 +01:00
Peter Jones
c0a0a44fbc Update CHANGES.md for PR #113 2016-11-05 10:00:17 -07:00
Peter Jones
ca5fbc155b Refactor all X.L.LayoutBuilderP functionality into X.L.LayoutBuilder
X.L.LayoutBuilderP is nearly identical to X.L.LayoutBuilder.  Originally
I wanted to add the ability to dynamically resize the layout boxes so it
make a lot of sense to join these two modules together so I wouldn't
have to do it in both.  Even though I never got around to that I still
think it's a good idea to merge these two modules into one.

I believe I was able to merge these without creating any
backward-compatibility issues.  I've been sitting on these changes since
2015 and they work for me without having to change older parts of my
config (relating to X.L.LayoutBuilder).

If anyone wants to work on dynamically resizing layout boxes the issue I
created for it is #36.
2016-11-05 09:51:28 -07:00
Ivan Malison
856b125186 X.A.WindowGo: Make comment style more consistent 2016-11-03 19:22:49 -07:00
Ivan Malison
c51bd739d7 X.A.WindowGo: Add a haddock comment to raiseNextMaybeCustomFocus 2016-11-03 19:21:52 -07:00
Ivan Malison
0e1cecd135 Merge remote-tracking branch 'origin/master' into custom_focus_raise_next_maybe 2016-11-03 19:15:28 -07:00
Brent Yorgey
ec5f9a9e59 Merge pull request #80 from f1u77y/managedocks-global-cache
Make strut cache global
2016-11-03 17:40:04 -04:00
Brent Yorgey
65bbe1a995 Merge pull request #108 from liskin/workspacenames
X.A.WorkspaceNames: add get(Current)WorkspaceName
2016-11-02 21:25:06 -04:00
Brent Yorgey
7b8798cb30 Merge pull request #104 from IvanMalison/windowBringerDefaults
X.A.WindowBringer: Add a config object with a X.C.Default implementation
2016-11-02 21:23:20 -04:00
Tomas Janousek
0a74e3479e X.A.WorkspaceNames: add get(Current)WorkspaceName 2016-10-29 23:36:19 +02:00
Ivan Malison
8e061c0c6d X.A.WindowGo: Remove uncurry from raiseNextMaybeCustomFocus 2016-10-26 17:24:45 -07:00
Ivan Malison
49fecdf4eb X.A.WindowGo: Add arg for custom focus fn to raiseNextMaybe 2016-10-26 17:09:42 -07:00
Ivan Malison
993dedf6d3 X.A.WindowBringer: Use <$> instead of fmap 2016-10-24 22:38:45 -07:00
Bogdan Sinitsyn
fcb57bd657 Move modifyXS to X.U.ExtensibleState 2016-10-25 08:22:02 +03:00
Ivan Malison
05d7493888 X.A.WindowBringer: Misc. cleanup and whitespace fixes 2016-10-24 22:10:56 -07:00
Ivan Malison
4983ecfd23 X.A.WindowBringer: Add haddocks for WindowBringerConfig 2016-10-24 22:10:09 -07:00
Brent Yorgey
ae7fd21e29 Merge pull request #97 from samdoshi/prompt-haddock
fix broken XPConfig docs
2016-10-24 17:57:53 -04:00
Ivan Malison
6cb10c9300 X.A.WindowBringer: Add a X.C.Default impl
This provides a less complicated interface to the specification of
custom behavior. In particular it allows the specification of a custom
window titling function.
2016-10-21 20:14:52 -07:00
Brent Yorgey
e98fedfaa5 Merge pull request #92 from jschwab/use-searchPredicate-in-prompt-pass
XMonad.Prompt.Pass: Use searchPredicate from XPConfig
2016-10-21 22:35:09 -04:00
Sam Doshi
dcc2759c4d fix broken XPConfig docs 2016-10-19 11:41:06 +01:00
Brent Yorgey
b871a0c7ee Merge pull request #91 from nomeata/prompt-unicode
Add XMonad.Prompt.Unicode
2016-10-19 19:13:47 +09:00
Brent Yorgey
c71f72ff66 Merge pull request #95 from Fuco1/feature/add-submapdefaultwithkey
Feature/add submapdefaultwithkey
2016-10-18 10:58:27 +09:00
Matus Goljer
e5ca066057 Add submapDefaultWithKey.
This is useful for when we want to decide what to do in the default
action based on the key that failed to match in the submap.
2016-10-16 16:40:13 +02:00
Matus Goljer
444986d993 Remove unneeded argument 2016-10-16 16:36:18 +02:00
Matus Goljer
1553d81ce7 Use fromMaybe over "maybe .. id" 2016-10-16 16:33:49 +02:00
Josiah Schwab
082c64ec37 XMonad.Prompt.Pass: Use searchPredicate from XPConfig
XMonad.Prompt allows the user to specify a search predicate in XPConfig.
However, previously XMonad.Prompt.Pass did not apply this predicate.
This now applies the predicate in similar manner as XMonad.Prompt.Shell.
2016-10-12 10:28:01 -07:00
Joachim Breitner
01ddbb7b82 Do not use sortOn
as it is not available in old versions of base.
2016-10-07 15:40:04 -04:00
Joachim Breitner
feec53c78c Avoid attoparsec dependency for this simple parsing task 2016-10-07 15:29:03 -04:00
Joachim Breitner
e4e120bb8e Add XMonad.Prompt.Unicode
I have been using this code locally for years now, and it turned out to
be quite useful in many cases, so I thought it is about time to submit
it to the repository.
2016-10-07 11:50:21 -04:00
Brent Yorgey
858a906240 Merge pull request #87 from nlewo/master
X.A.DynamicWorkspaces: associate indexes to workspaces
2016-10-05 20:32:34 +09:00
Brent Yorgey
1b81ac7314 Merge pull request #86 from aiya000/master
Export XMonad.Actions.Workscreen (WorkscreenId)
2016-10-05 20:29:18 +09:00
Brent Yorgey
262e78770f Merge pull request #82 from 41px/dev-41px
Switch/Move to physical/Xinerama screens 1, 2 or 3
2016-09-23 07:14:17 +09:00
Brent Yorgey
1c8e17e127 Merge pull request #84 from TomSmeets/treeselect
Fix incorrect documentation in TreeSelect
2016-09-23 07:11:56 +09:00
Antoine Eiche
f3de3e2719 X.A.DynamicWorkspace: update index map on workspace renaming 2016-09-20 20:42:03 +02:00
Antoine Eiche
464a99b842 X.A.DynamicWorkspaces: associate indexes to workspaces
You can add indexes to workspaces and use them to do actions on
workspaces. This allows you to dynamicaly associate a workspace to a
keybinding without depending of the workspace name or the workspace
position.
2016-09-19 14:33:18 +02:00
aiya000
f6ded1a4d7 Export XMonad.Actions.Workscreen (WorkscreenId)
This is fixing for problem that
WorkscreenId was shown in XMonad.Actions.Workscreen document
(ex: viewWorkscreen),
but never shown WorkscreenId definition.
2016-09-19 16:31:43 +09:00
Tom Smeets
3b4a3d2bd2 Fix incorrect documentation for WorkspaceHistory 2016-09-14 20:02:07 +02:00
Brent Yorgey
753e9ce4b0 Merge pull request #72 from TomSmeets/treeselect
Add TreeSelect action for selecting from many workspaces and X actions
2016-09-14 07:22:05 -04:00
Daniel Wagner
bf1f4fcc76 Merge pull request #81 from asjo/add_note_to_stoppable
Add note about when Stoppable does not work.
2016-09-11 16:04:39 -07:00
Tom Smeets
305c8eff0d Add optional workspace-history navigation
To enable this feature add `workspaceHisotryHook` from
`XMonad.Hooks.WorkspaceHistory` to your logHook.

Your previously-visited workspaces can be navigated with
the 'moveHistBack' and 'moveHistForward' actions (which are bound to the 'o' and 'i' keys)
2016-09-08 17:00:21 +02:00
Tom Smeets
52b180e6b2 Fixed getSubForest and rootNode 2016-09-08 17:00:21 +02:00
Tom Smeets
c2331f9657 Fixed a small error in the documentation 2016-09-08 17:00:21 +02:00
Tom Hinton
953f1576f4 Determine which groups to Hide correctly
This is a fix I have applied locally to make sure that when I use decorated layouts like tabbed in groups, XMonad does not leave bogus decoration windows lying around.

I think that the issue fixed is that the set of groups to send `Hide` to is determined by subtracting the extant groups from `l`, but `l` has already been put through `readapt` and so some groups may have been removed (if they are empty), so they don't get the Hide message.

The comparison should therefore be between `_l` and the new groups.
2016-09-08 17:00:21 +02:00
Alexandre Px
7629f774c6 fix Couldn't match expected type `KeyMask' 2016-09-07 21:54:09 +02:00
Alexandre Px
a1adb0b801 Replace M.union to <+> in documentation 2016-09-07 21:48:49 +02:00
Alexandre Px
c3081bd783 Switch/Move to physical/Xinerama screens 1, 2 or 3 2016-09-07 21:44:15 +02:00
Tomas Janousek
e38fb3bdb8 Make usage of ManageDocks simpler and more robust
As it now consists of a startup hook, a manage hook, an event hook and
a layout modifier, and behaves erratically when any one component is not
included in a user's config (which happens to be the case for all
configs from xmonad-contrib 0.12 since the startup hook is a new
inclusion), it's probably wise to have a single function that adds
all the hooks to the config instead.

NB: This will need a release notes entry anyway!
2016-09-07 13:26:58 +03:00
Bogdan Sinitsyn
c48d81e378 Fix caching issues in ManageDocks
Commits d638dc8b and a5e87e38 introduced a per-AvoidStruts-instance
strut cache that

a) didn't get initialized at startup,
b) didn't get reinitialized after layout reset and
c) didn't get updates if it wasn't the active layout, for example when
   layoutHook = avoidStruts tall ||| avoidStruts (mirror tall)

a) + b) could be fixed by using the docksStartupHook introduced in
28e9f8bc, although this wasn't documented and having to call
docksStartupHook after setLayout is far from obvious.

By moving the strut cache from AvoidStruts instances to a global state,
b) and c) are fixed. One still has to invoke the docksStartupHook for
a), and this will be addressed in the next commit.
2016-09-07 13:26:50 +03:00
Brent Yorgey
94c7cb513c Merge pull request #77 from LSLeary/master
A very simple extension to Navigation2D so it plays better with gaps
2016-09-06 13:19:17 -04:00
Adam Sjøgren
61038f95fb Add note about when Stoppable does not work. 2016-09-03 23:41:10 +02:00
L.S. Leary
4358f58de8 Swapped pickSomething for <|> in doHybridNavigation. 2016-08-30 13:11:54 +12:00
Brent Yorgey
899ff52316 Merge pull request #78 from larkery/patch-1
Determine which groups to Hide correctly
2016-08-29 19:04:13 -04:00
L.S. Leary
ea6e1a5d6d Removed extraneous blank line from Nav2D. 2016-08-29 16:53:46 +12:00
LSLeary
4aaf053273 Rewrote doHybridNavigation. 2016-08-29 14:30:03 +12:00
Tom Hinton
2e53a6cdd6 Determine which groups to Hide correctly
This is a fix I have applied locally to make sure that when I use decorated layouts like tabbed in groups, XMonad does not leave bogus decoration windows lying around.

I think that the issue fixed is that the set of groups to send `Hide` to is determined by subtracting the extant groups from `l`, but `l` has already been put through `readapt` and so some groups may have been removed (if they are empty), so they don't get the Hide message.

The comparison should therefore be between `_l` and the new groups.
2016-08-27 17:12:34 +01:00
L.S. Leary
76565e42c4 Removed an extraneous comment that had been accidentally left in place. 2016-08-27 03:49:52 +12:00
L.S. Leary
a7d5696e5a Punctuation tweak in docs. 2016-08-27 03:27:08 +12:00
L.S. Leary
b9215181bb Rather than writing over the vanilla Line navigation function, Hybrid navigation has been implemented separately. 2016-08-27 03:17:05 +12:00
L.S. Leary
806a501d51 Modified Line to default to Center if it can't move. This provides the best way to get around if you use gaps and float no windows. 2016-08-27 02:37:35 +12:00
Tom Smeets
529683660c Show error when using incorrect XConfig.workspaces 2016-08-22 21:18:04 +02:00
Tom Smeets
15a2a86d46 Removed a useless comment 2016-08-22 20:15:25 +02:00
Tom Smeets
25df357a4a Fixed a small bug 2016-08-10 10:30:39 +02:00
Tom Smeets
c2e0fc517c Fixed incompatibility with older GHC versions 2016-08-08 18:53:27 +02:00
Tom Smeets
1087844a7f Add screenshots and a little more info 2016-08-08 17:26:26 +02:00
Tom Smeets
8bfbafeae9 Add entry to XMonad.Doc.Extending 2016-08-08 11:47:08 +02:00
Tom Smeets
7e777bebfd Select your workspaces and actions in a Tree format.
TreeSelect displays your workspaces or actions in a Tree-like format.
You can select the desired workspace/action with the cursor or hjkl keys.

This module is fully configurable and very useful if you like to have a
lot of workspaces.

Please see the Documentation provided by 'XMonad.Actions.TreeSelect'.
2016-08-07 20:40:40 +02:00
Brent Yorgey
8d2582f032 Merge pull request #66 from mathstuf/fix-warnings
Fix warnings
2016-08-01 14:12:35 -04:00
Brent Yorgey
81f1eab1ee X.A.Search: fix amazon search URL
Closes #71.
2016-08-01 13:01:30 -05:00
Ben Boeckel
4e880b37a2 IfMax: add the PatternGuards extension 2016-07-16 13:23:11 -04:00
Ben Boeckel
637c5c67b1 BinarySpacePartition: add type signature for noRef 2016-07-16 13:22:45 -04:00
Ben Boeckel
8fd8c5d02d warnings: remove unused variables 2016-07-16 13:22:34 -04:00
Ben Boeckel
d414c76da8 warnings: rename shadowing variables 2016-07-16 13:22:12 -04:00
geekosaur
ddcc9e0209 Merge pull request #63 from oldmanmike/XMonad-Config-Desktop-update
Update XMonad.Config.Desktop for 0.12 ManageDocks
2016-07-13 15:46:08 -04:00
Brent Yorgey
e280f62a57 Merge pull request #61 from oldmanmike/update-extending-docs
Add missing Extending documentation for new modules
2016-07-05 15:19:56 -04:00
oldmanmike
a8ca8bcd6f Update XMonad.Config.Desktop for 0.12 ManageDocks 2016-07-02 02:14:36 -04:00
oldmanmike
f3dc89f821 Add missing Extending documentation for new modules 2016-07-01 12:36:15 -04:00
Adam Vogt
6a9e9e5a78 Merge pull request #59 from chongli/master
New SortedLayout module.
2016-07-01 11:52:22 -04:00
Kurt Dietrich
1d5cdc108a New SortedLayout module. 2016-06-30 15:33:15 -04:00
Daniel Wagner
d6243c9564 improve documentation on fonts in Prompt 2016-06-22 13:17:28 -07:00
Daniel Wagner
c2c6a94834 Merge branch 'master' of github:xmonad/xmonad-contrib 2016-06-22 12:57:14 -07:00
Brent Yorgey
6aa289c713 Merge pull request #4 from mathstuf/dynamic-bars-partial-cleanup
X.H.DynamicBars: support per-monitor cleanup
2016-06-16 17:31:05 -04:00
Ben Boeckel
cc77b5019d DynamicBars: improve documentation 2016-06-12 20:03:22 -04:00
geekosaur
a421da29e6 Merge pull request #57 from CaptainPatate/master
Fix minor things
2016-06-12 19:00:45 -04:00
Amaury Gauthier
2831378f8f Fix type of additionalKeys and removeKeys functions 2016-06-08 00:35:25 +02:00
Amaury Gauthier
34f9dda006 Fix documentation 2016-06-08 00:35:25 +02:00
Ben Boeckel
e698e5fe53 X.H.DynamicBars: support per-monitor cleanup
Add functions to allow cleaning up only screens which disappear. This
works better where killing the statusbar for a specific screen is
possible. The old way is still relevant for setups which do not have
such a method (e.g., safeSpawn xmobar/spawnPipe xmonadpropwrite).
2016-05-22 17:28:46 -04:00
Brent Yorgey
fce36bda16 Merge pull request #24 from nlewo/master
X.P.Window: add window selector for the prompt and BringToMaster action
2016-05-12 12:11:25 -04:00
Antoine Eiche
73134369ea X.P.Window: add window selector for the prompt and BringToMaster action
- The set of windows proposed by the prompt can be parametrized. Two
  helper functions are currently defined. One for selecting all
  available windows and another one for selecting all windows of the
  current workspace.

- Add BringToMaster action which brings the selected window to the
  current workspace and set it as master.

- windowPromptGoto, windowPromptBring, windowPromptBringCopy are
  marked as deprecated since they can be realized by the more generic
  windowPrompt function.  For instance, "windowPromptGoto prompt" can
  be easily replaced by "windowPrompt prompt Goto allWindows".
2016-05-10 09:54:41 +02:00
Brent Yorgey
26b50c043c Merge pull request #52 from geekosaur/nsp-loggers
XMonad.Util.Loggers for NamedScratchPad-s
2016-05-09 20:55:25 -04:00
brandon s allbery kf8nh
ed4909aa65 pre-Typeable-unsafeCoerce-fix ghc needs a deriving pragma 2016-05-02 23:06:08 -04:00
Brent Yorgey
f12167b298 Merge pull request #53 from jablko/master
Make WindowBringer case insensitive
2016-05-02 23:00:55 -04:00
Brent Yorgey
00c6a44bdc Merge pull request #51 from seanstrom/feature/dynamicbars-multiPPFormat
DynamicBars: Add new multiPPFormat function
2016-05-02 22:47:27 -04:00
geekosaur
b41544b6cc Merge pull request #55 from Delapouite/docs
docs: fix typo Repace → Replace in XMonad.Layout.Renamed
2016-04-29 10:02:47 -04:00
Delapouite
da44e76f75 docs: fix typo Repace → Replace in XMonad.Layout.Renamed 2016-04-29 13:31:59 +02:00
Jack Bates
75b3cae49f Make WindowBringer case insensitive 2016-04-27 09:48:36 -07:00
brandon s allbery kf8nh
72956159b6 Add XMonad.Util.NoTaskbar, XMonad.Util.Loggers.NamedScratchpad 2016-04-21 14:49:13 -04:00
geekosaur
9a187f243c Merge pull request #50 from damianfral/patch-1
Fix updatePointer equivalence table.
2016-04-12 11:15:56 -04:00
Damián Franco Álvarez
e0211ad7d6 Fix updatePointer equivalence table.
In order to get the behavior I had with `updatePointer (Relative 0.5 0.5)`, I have to use `updatePointer (0.5,0.5) (0,0)`.
2016-04-12 16:36:56 +02:00
geekosaur
c08d48f6aa Merge pull request #31 from geekosaur/master
add X.U.Ungrab
2016-04-07 14:22:47 -04:00
geekosaur
81dd1cba1d Merge pull request #48 from f1u77y/fix-ifmax-3
Final(I hope) attempt to fix X.L.IfMax
2016-04-06 23:04:25 -04:00
brandon s allbery kf8nh
abe911a8d6 Merge remote-tracking branch 'upstream/master' 2016-04-06 21:24:21 -04:00
seanstrom
1452c9e273 add new multiPPFormat function 2016-04-03 16:04:49 -07:00
Bogdan Sinitsyn
44abb6c8d4 handle ReleaseResources correctly 2016-03-26 16:28:23 +03:00
Bogdan Sinitsyn
43fccf1a6c use workspace name for running layouts 2016-03-26 16:28:23 +03:00
Bogdan Sinitsyn
f429843b66 remove reundant ReleaseResources handling 2016-03-26 16:28:23 +03:00
Bogdan Sinitsyn
dd5a36cc08 hide layout when changing to another 2016-03-26 16:28:23 +03:00
Brent Yorgey
01ea659a06 Merge pull request #21 from f1u77y/#16
fix #16
2016-03-15 22:02:39 -05:00
geekosaur
f1d3118417 Merge pull request #45 from f1u77y/fix-ifmax-2
watch only for tiled windows in X.L.IfMax
2016-03-10 19:53:25 -05:00
Bogdan Sinitsyn
ceb2df8931 watch only for tiled windows in X.L.IfMax 2016-02-29 14:12:36 +03:00
Adam Vogt
99cc0b6c85 Merge pull request #42 from f1u77y/fix-ifmax
handle messages in X.L.IfMax
2016-02-28 19:23:16 -05:00
Adam Vogt
9c95c81a90 Merge pull request #22 from f1u77y/#14
close #14
2016-02-28 19:20:20 -05:00
Adam Vogt
15c645d9f2 use traverse_ instead of traverse in DynamicBars 2016-02-26 19:08:57 -05:00
Bogdan Sinitsyn
94a7e97ac8 handle messages in X.L.IfMax 2016-02-23 16:06:21 +03:00
Brent Yorgey
c736d52268 Merge pull request #41 from jmickelin/wmii-togglegroupfull-fix
Fixed bottom-yielding definition of toggleGroupFull
2016-02-23 06:30:09 -06:00
Jonne Mickelin Sätherblom
c27ef4d418 Fixed bottom-yielding definition of toggleGroupFull 2016-02-19 19:51:31 +01:00
Brent Yorgey
571193a219 Merge pull request #34 from bb-h8/master
Added missing boundary check in Layout.Spacing.shrinkRect
2016-02-14 16:42:03 -06:00
f1u77y
bbbdad8faa prevent losing focus in gridSelect(fix #16) 2016-02-14 20:15:26 +03:00
geekosaur
311d3a0582 Merge pull request #38 from kurnevsky/docmentation_fix
Documentation fix.
2016-02-14 11:10:53 -05:00
geekosaur
b14db06f65 Merge pull request #39 from f1u77y/fix-prompt-numlock
strip numlock from mask in X.Prompt(fixes #37)
2016-02-14 11:10:04 -05:00
Bogdan Sinitsyn
30f657a437 strip numlock from mask in X.Prompt(fixes #37) 2016-02-14 14:54:26 +03:00
Kurnevsky Evgeny
a6f286dbdc Documentation fix. 2016-02-14 12:59:29 +03:00
brandon s allbery kf8nh
3796569268 whoops, CHANGES.md 2016-02-13 21:29:06 -05:00
geekosaur
d5eb7316d1 Merge pull request #30 from f1u77y/fix-docks
fix xmonad/xmonad#21
2016-02-13 21:23:50 -05:00
bb-h8
baf1dd9251 Added missing boundary check in Layout.Spacing.shrinkRect 2016-01-26 21:27:49 +01:00
Bogdan Sinitsyn
5e96324d80 send all docks messages only from event hook 2016-01-18 12:02:40 +03:00
Bogdan Sinitsyn
5df7ba160e some minor fixes in X.H.ManageDocks 2016-01-18 10:37:04 +03:00
Bogdan Sinitsyn
431fd66527 fix slowdown when removing docks 2016-01-17 18:15:41 +03:00
Bogdan Sinitsyn
f79e3fadea handle docks remove correctly 2016-01-17 16:32:56 +03:00
Bogdan Sinitsyn
28e9f8bce7 add docksStartupHook for handling docks when restarted 2016-01-17 11:55:59 +03:00
Bogdan Sinitsyn
f73eb1c938 handle PropertyNotify events on docks 2016-01-17 11:46:53 +03:00
Bogdan Sinitsyn
83ee18ad94 add new dock if it hasn't strut properties 2016-01-17 10:53:55 +03:00
Bogdan Sinitsyn
f4d4bde026 typo 2016-01-17 10:38:51 +03:00
Bogdan Sinitsyn
f1b9a0c193 add calcGapForAll for other modules 2016-01-17 10:35:26 +03:00
Bogdan Sinitsyn
34beb76562 fix X.H.PositionStoreHooks for new signature of calcGaps 2016-01-17 10:14:51 +03:00
Bogdan Sinitsyn
028ad6d6ec minor fixes in X.H.ManageDocks 2016-01-17 10:08:20 +03:00
Bogdan Sinitsyn
a5e87e3894 never query all the tree in X.H.ManageHook 2016-01-17 10:03:07 +03:00
brandon s allbery kf8nh
2855ed3d70 add X.U.Ungrab 2016-01-16 00:37:19 -05:00
Bogdan Sinitsyn
68cfa84b91 fix build with older ghc 2016-01-15 21:21:47 +03:00
Peter J. Jones
b20e7fa1e4 Merge pull request #29 from f1u77y/prompt-position
Prompt position
2016-01-10 16:06:29 -07:00
Bogdan Sinitsyn
58c3062910 typo 2016-01-10 23:52:13 +03:00
Bogdan Sinitsyn
889cd97d08 add myself to .mailmap and edit changelog 2016-01-10 23:51:00 +03:00
Bogdan Sinitsyn
4a9e28ca8b Merge branch 'master' of https://github.com/xmonad/xmonad-contrib into prompt-position 2016-01-10 23:43:11 +03:00
Peter J. Jones
604a262f38 Merge pull request #23 from psibi/prompt-multiple-key
Add multiple key support for completion key
2016-01-10 12:01:06 -07:00
Sibi Prabakaran
0510da7659 Add changelog for the patch. 2016-01-10 23:17:00 +05:30
Sibi Prabakaran
93b2620ad3 Add myself in mailmap 2016-01-10 23:17:00 +05:30
Sibi Prabakaran
727e214195 Add multiple key support for completion key
This patch enables support for key binding like Ctrl + i which was not
previously possible. Technically, this changes the type of completionKey
from KeySym to (KeyMask, KeySym).
2016-01-10 23:17:00 +05:30
Bogdan Sinitsyn
9a7a63bfb4 improve documentation for X.Prompt 2016-01-08 20:58:56 +03:00
Bogdan Sinitsyn
a61ce8dd74 improve documentation for X.Prompt 2016-01-08 20:29:45 +03:00
Bogdan Sinitsyn
d638dc8b0a fix xmonad/xmonad#21 2016-01-03 12:41:15 +03:00
Bogdan Sinitsyn
bce9c551ef fix CenteredAt in X.Prompt 2016-01-01 00:22:45 +03:00
Bogdan Sinitsyn
26309d1622 improve CenteredAt in X.Prompt 2015-12-31 23:51:03 +03:00
Bogdan Sinitsyn
d81b4e5bcb add documentation for XPPosition in X.Prompt 2015-12-31 23:36:07 +03:00
Bogdan Sinitsyn
6043914841 fix border between prompt and completions in X.Prompt 2015-12-31 16:03:00 +03:00
Bogdan Sinitsyn
ed7be9a791 fix border between prompt and completion window in X.Prompt 2015-12-31 15:57:36 +03:00
Bogdan Sinitsyn
becb724f95 fix prompt width 2015-12-28 19:37:52 +03:00
Bogdan Sinitsyn
0447c76d48 change documentation 2015-12-28 15:19:02 +03:00
Bogdan Sinitsyn
e47794148c fix border drawing 2015-12-28 15:14:35 +03:00
Bogdan Sinitsyn
edd6b8be55 add customization for prompt position 2015-12-28 14:49:36 +03:00
Bogdan Sinitsyn
ddcf5abcbf fix swapNth' 2015-12-23 09:28:18 +03:00
Bogdan Sinitsyn
e19460677a fix swapNth' 2015-12-23 09:16:01 +03:00
Adam Vogt
b23f56d65d clean up `git shortlog' output 2015-12-22 16:42:06 -05:00
Brent Yorgey
c3b05ceb7f travis: comment out cabal check for now
It complains about the -Werror enabled by the 'testing' flag,
even though the testing flag is set to manual: True, default: False
2015-12-22 07:51:37 -06:00
Brent Yorgey
9f68077c6c .cabal: remove outdated flag
xmonad no longer supports GHC 6.10, and the -O0 was causing
cabal to generate a warning.
2015-12-22 07:39:06 -06:00
Brent Yorgey
723494f01e travis: build xmonad from HEAD 2015-12-22 07:35:05 -06:00
Brent Yorgey
ae6b8db29b Update lower bounds for containers and base
Closes #28.
2015-12-22 07:31:36 -06:00
Brent Yorgey
1ce26e8cd2 .cabal: make testing flag manual 2015-12-21 13:15:00 -06:00
Daniel Wagner
800ae670e2 use a record pattern to be robust against additions to the X11 library 2015-12-15 07:44:36 -08:00
f1u77y
d81c48d022 fix #14 2015-12-11 16:42:14 +03:00
56 changed files with 2617 additions and 477 deletions

View File

@@ -1,80 +0,0 @@
Alejandro Serrano Mena <trupill@gmail.com>, trupill@gmail.com
Alexandre Buisse <buisse@cs.chalmers.se>, buisse@cs.chalmers.se
Audun Skaugen <audun@skaugen.name>, Audun Skaugen <audunskaugen@gmail.com>, audunskaugen@gmail.com
Bas van Dijk <v.dijk.bas@gmail.com>, v.dijk.bas@gmail.com
Ben Boeckel <mathstuf@gmail.com>, mathstuf@gmail.com
Brandon S Allbery KF8NH <allbery.b@gmail.com>, allbery@ece.cmu.edu
Brent Yorgey <byorgey@cis.upenn.edu>, Brent Yorgey <byorgey@gmail.com>
Carlos Lopez-Camey <c.lopez@kmels.net>, c.lopez@kmels.net
Carsten Otto <xmonad@c-otto.de>, xmonad@c-otto.de
Christian Dietrich <stettberger@dokucode.de>, stettberger@dokucode.de
Daniel Neri <daniel.neri@sigicom.com>, Daniel Neri <daniel.neri@sigicom.se>
Daniel Schoepe <daniel.schoepe@googlemail.com>, Daniel Schoepe <daniel.schoepe@gmail.com>, Daniel Schoepe <asgaroth_@gmx.de>
Daniel Wagner <daniel@wagner-home.com>, daniel@wagner-home.com
Dave Harrison <dave@nullcube.com>, dave@nullcube.com
David Glasser <glasser@mit.edu>, glasser@mit.edu
David McLean <gopsychonauts@gmail.com>, gopsychonauts@gmail.com
Dominik Bruhn <dominik@dbruhn.de>, dominik@dbruhn.de
Don Stewart <dons00@gmail.com>, Don Stewart <dons@cse.unsw.edu.au>, Don Stewart <dons@galois.com>
Gwern Branwen <gwern0@gmail.com>, gwern0@gmail.com
Henrique Abreu <hgabreu@gmail.com>, `Henrique Abreu <hgabreu@gmail.com>'
Ilya Portnov <portnov84@rambler.ru>, portnov84@rambler.ru
intrigeri <intrigeri@boum.org>, intrigeri@boum.org
Ivan Miljenovic <Ivan.Miljenovic@gmail.com>, Ivan.Miljenovic@gmail.com
Jan-David Quesel <quesel@informatik.uni-oldenburg.de>, quesel@informatik.uni-oldenburg.de
Jeremy Apthorp <nornagon@gmail.com>, nornagon@gmail.com
Joachim Breitner <mail@joachim-breitner.de>, mail@joachim-breitner.de
Joachim Fasting <joachim.fasting@gmail.com>, joachim.fasting@gmail.com
Joel Suovaniemi <joel.suovaniemi@iki.fi>, joel.suovaniemi@iki.fi
Joe Thornber <joe.thornber@gmail.com>, joe.thornber@gmail.com
Johann Giwer <johanngiwer@web.de>, johanngiwer@web.de
Jussi Maki <joamaki@gmail.com>, joamaki@gmail.com
kedals0 <kedals0@gmail.com>, kedals0@gmail.com
Konstantin Sobolev <konstantin.sobolev@gmail.com>, konstantin.sobolev@gmail.com
Lanny Ripple <lan3ny@gmail.com>, lan3ny@gmail.com
Leonardo Serra <leoserra@minaslivre.org>, leoserra@minaslivre.org
lithis <xmonad@selg.hethrael.org>, xmonad@selg.hethrael.org, xmonad@s001.hethrael.com
Luis Cabellos <zhen.sydow@gmail.com>, zhen.sydow@gmail.com
Lukas Mai <l.mai@web.de>, l.mai@web.de
Mario Pastorelli <pastorelli.mario@gmail.com>, pastorelli.mario@gmail.com
Mathias Stearn <redbeard0531@gmail.com>, redbeard0531@gmail.com
Matt Brown <deadguysfrom@gmail.com>, deadguysfrom@gmail.com
Nelson Elhage <nelhage@mit.edu>, nelhage@mit.edu
Nicolas Dudebout <nicolas.dudebout@gatech.edu>, nicolas.dudebout@gatech.edu
Nicolas Pouillard <nicolas.pouillard@gmail.com>, nicolas.pouillard@gmail.com
Nils Schweinsberg <mail@n-sch.de>, mail@n-sch.de
Norbert Zeh <nzeh@cs.dal.ca>, nzeh@cs.dal.ca
Quentin Moser <moserq@gmail.com>, moserq@gmail.com
Quentin Moser <quentin.moser@unifr.ch>, quentin.moser@unifr.ch
Rickard Gustafsson <acura@allyourbase.se>, acura@allyourbase.se
Robert Marlow <bobstopper@bobturf.org>, bobstopper@bobturf.org, robreim@bobturf.org
Rohan Jain <crodjer@gmail.com>, crodjer@gmail.com
Sean Escriva <sean.escriva@gmail.com>, sean.escriva@gmail.com
Spencer Janssen <spencerjanssen@gmail.com>, sjanssen@cse.unl.edu
Tomohiro Matsuyama <matsuyama3@ariel-networks.com>, matsuyama3@ariel-networks.com
Tom Rauchenwald <its.sec@gmx.net>, <its.sec@gmx.net>
Tony Morris <haskell@tmorris.net>, haskell@tmorris.net
Valery V. Vorotyntsev <valery.vv@gmail.com>, valery.vv@gmail.com
Will Farrington <wcfarrington@gmail.com>, wcfarrington@gmail.com
Wirt Wolff <wirtwolff@gmail.com>, wirtwolff@gmail.com
Yaakov Nemoy <loupgaroublond@gmail.com>, loupgaroublond@gmail.com
timthelion <tim.thelion@gmail.com>, tim.thelion@gmail.com
seanmce33 <seanmce33@gmail.com>, seanmce33@gmail.com
rupa <rupa@lrrr.us>, rupa@lrrr.us
perlkat <perlkat@katspace.org>, perlkat@katspace.org
longpoke <longpoke@gmail.com>, longpoke@gmail.com
cardboard42 <cardboard42@gmail.com>, cardboard42@gmail.com
daedalusinfinity <daedalusinfinity@gmail.com>, daedalusinfinity@gmail.com
Jens Petersen <juhp@community.haskell.org>, Jens Petersen <petersen@haskell.org>
Neil Mitchell <http://www.cs.york.ac.uk/~ndm/>, Neil Mitchell
Nick Burlett <nickburlett@mac.com>, nickburlett@mac.com
Sam Hughes <hughes@rpi.edu>, hughes@rpi.edu
Shae Erisson <shae@ScannedInAvian.com>, shae@ScannedInAvian.com
Conrad Irwin <conrad.irwin@gmail.com>, conrad.irwin@gmail.com
-- unknown:
-- xmonad-contrib@hexago.nl
-- brian@lorf.org
-- jakob@pipefour.org

102
.mailmap Normal file
View File

@@ -0,0 +1,102 @@
Alejandro Serrano Mena <trupill@gmail.com>
Alexandre Buisse <buisse@cs.chalmers.se>
Anders Engstrom <ankaan@gmail.com>
Antoine R. Dumont <eniotna.t@gmail.com>
Anton Pirogov <anton.pirogov@gmail.com>
Anton Pirogov <anton.pirogov@gmail.com> anton.pirogov at gmail . com <unknown>
Arjun Comar <nrujac@gmail.com>
Audun Skaugen <audun@skaugen.name> <audunskaugen@gmail.com>
Bas van Dijk <v.dijk.bas@gmail.com>
Ben Boeckel <mathstuf@gmail.com>
Ben Weitzman <benweitzman@gmail.com>
Bogdan Sinitsyn <bogdan.sinitsyn@gmail.com>
Brandon S Allbery KF8NH <allbery.b@gmail.com>
Brandon S Allbery KF8NH <allbery.b@gmail.com> <allbery@ece.cmu.edu>
Brent Yorgey <byorgey@gmail.com> <byorgey@cis.upenn.edu>
Carlos Lopez-Camey <c.lopez@kmels.net>
Carsten Otto <xmonad@c-otto.de>
Christian Dietrich <stettberger@dokucode.de>
Christian Wills <cwills.dev@gmail.com>
Daniel Neri <daniel.neri@sigicom.com> <daniel.neri@sigicom.se>
Daniel Schoepe <daniel.schoepe@googlemail.com> <asgaroth_@gmx.de>
Daniel Schoepe <daniel.schoepe@googlemail.com> <daniel.schoepe@gmail.com>
Daniel Wagner <me@dmwit.com> <daniel@wagner-home.com>
Dave Harrison <dave@nullcube.com>
David Glasser <glasser@mit.edu>
David McLean <gopsychonauts@gmail.com>
Devin Mullins <devin.mullins@gmail.com> <me@twifkak.com>
Dominik Bruhn <dominik@dbruhn.de>
Don Stewart <dons00@gmail.com> <dons@cse.unsw.edu.au>
Don Stewart <dons00@gmail.com> <dons@galois.com>
Edward Z. Yang <ezyang@cs.stanford.edu>
Gwern Branwen <gwern@gwern.net>
Gwern Branwen <gwern@gwern.net> <gwern0@gmail.com>
Henrique Abreu <hgabreu@gmail.com>
Ilya Portnov <portnov84@rambler.ru>
intrigeri <intrigeri@boum.org>
Ivan Miljenovic <Ivan.Miljenovic@gmail.com>
Jan-David Quesel <quesel@informatik.uni-oldenburg.de>
Jens Petersen <juhp@community.haskell.org> <petersen@haskell.org>
Jeremy Apthorp <nornagon@gmail.com>
Joachim Breitner <mail@joachim-breitner.de>
Joachim Fasting <joachim.fasting@gmail.com>
Joel Suovaniemi <joel.suovaniemi@iki.fi>
Joe Thornber <joe.thornber@gmail.com>
Johann Giwer <johanngiwer@web.de>
Jussi Maki <joamaki@gmail.com>
Konstantin Sobolev <konstantin.sobolev@gmail.com>
Lanny Ripple <lan3ny@gmail.com>
Lei Chen <linxray@gmail.com>
Leonardo Serra <leoserra@minaslivre.org>
Luis Cabellos <zhen.sydow@gmail.com>
Lukas Mai <l.mai@web.de>
Mario Pastorelli <pastorelli.mario@gmail.com>
Mathias Stearn <redbeard0531@gmail.com>
Matt Brown <deadguysfrom@gmail.com>
Matthew Hague <matthewhague@zoho.com>
Nathaniel Filardo <nwfilardo@gmail.com>
Nelson Elhage <nelhage@mit.edu>
Nicolas Dudebout <nicolas.dudebout@gatech.edu>
Nicolas Pouillard <nicolas.pouillard@gmail.com>
Nils Schweinsberg <mail@n-sch.de>
Norbert Zeh <nzeh@cs.dal.ca>
Peter Olson <polson2@hawk.iit.edu>
Quentin Moser <moserq@gmail.com>
Quentin Moser <quentin.moser@unifr.ch>
Rickard Gustafsson <acura@allyourbase.se>
Robert Marlow <bobstopper@bobturf.org>
Robert Marlow <bobstopper@bobturf.org> <robreim@bobturf.org>
Rohan Jain <crodjer@gmail.com>
Sibi Prabakaran <sibi@psibi.in> <psibi2000@gmail.com>
Sean Escriva <sean.escriva@gmail.com>
Sean McEligot <seanmce33@gmail.com>
Spencer Janssen <spencerjanssen@gmail.com> <sjanssen@cse.unl.edu>
Tomohiro Matsuyama <matsuyama3@ariel-networks.com>
Tom Rauchenwald <its.sec@gmx.net>
Tony Morris <haskell@tmorris.net>
Valery V. Vorotyntsev <valery.vv@gmail.com>
Will Farrington <wcfarrington@gmail.com>
Wirt Wolff <wirtwolff@gmail.com>
Yaakov Nemoy <loupgaroublond@gmail.com>
brian <brian@lorf.org>
cardboard42 <cardboard42@gmail.com>
daedalusinfinity <daedalusinfinity@gmail.com>
hexago.nl <xmonad-contrib@hexago.nl>
intrigeri <intrigeri@boum.org>
jakob <jakob@pipefour.org>
kedals0 <kedals0@gmail.com>
lithis <xmonad@selg.hethrael.org>
lithis <xmonad@selg.hethrael.org> <xmonad@s001.hethrael.com>
longpoke <longpoke@gmail.com>
md143rbh7f <md143rbh7f@gmail.com>
perlkat <perlkat@katspace.org>
rupa <rupa@lrrr.us> <rupa@lrrr.us>
timthelion <tim.thelion@gmail.com>
# for core only
Neil Mitchell <http://www.cs.york.ac.uk/~ndm/>, Neil Mitchell
Nick Burlett <nickburlett@mac.com>
Sam Hughes <hughes@rpi.edu>
Shae Erisson <shae@ScannedInAvian.com>
Conrad Irwin <conrad.irwin@gmail.com>

View File

@@ -31,6 +31,9 @@ before_install:
- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
install:
# build xmonad from HEAD
- git clone https://github.com/xmonad/xmonad.git
- cabal --version
- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
@@ -66,6 +69,8 @@ install:
cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
fi
- cabal install xmonad/
# Here starts the actual work to be performed for the package under test;
# any command which exits with a non-zero exit code causes the build to fail.
script:
@@ -73,7 +78,8 @@ script:
- cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
- cabal build # this builds all libraries and executables (including tests/benchmarks)
- cabal test
- cabal check
# - cabal check # complains about -Werror even though it is
# hidden behind a manual flag with default false
- cabal sdist # tests that a source-distribution can be generated
# Check that the resulting source distribution can be built & installed.

View File

@@ -1,5 +1,62 @@
# Change Log / Release Notes
## 0.13
### Breaking Changes
* The type of `completionKey` (of `XPConfig` record) has been
changed from `KeySym` to `(KeyMask, KeySym)`. The default value
for this is still binded to `Tab` key.
* New constructor `CenteredAt Rational Rational` added for
`XMonad.Prompt.XPPosition`.
### New Modules
* `XMonad.Layout.SortedLayout`
A new LayoutModifier that sorts a given layout by a list of
properties. The order of properties in the list determines
the order of windows in the final layout. Any unmatched windows
go to the end of the order.
* `XMonad.Prompt.Unicode`
A prompt to search a unicode character by its name, and put it into the
clipboard.
* `XMonad.Util.Ungrab`
Release xmonad's keyboard and pointer grabs immediately, so
screen grabbers and lock utilities, etc. will work. Replaces
the short sleep hackaround.
* `XMonad.Util.Loggers.NamedScratchpad`
A collection of Loggers (see `XMonad.Util.Loggers`) for NamedScratchpads
(see `XMonad.Util.NamedScratchpad`).
* `XMonad.Util.NoTaskbar`
Utility function and `ManageHook` to mark a window to be ignored by
EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since
you will usually be taken to the `NSP` workspace by them.
### Minor Changes
* `XMonad.Layout.LayoutBuilder`
Merge all functionality from `XMonad.Layout.LayoutBuilderP` into
`XMonad.Layout.LayoutBuilder`.
* `XMonad.Actions.DynamicProjects`
- Switching away from a dynamic project that contains no windows
automatically deletes that project's workspace.
The project itself was already being deleted, this just deletes
the workspace created for it as well.
## 0.12 (December 14, 2015)
### Breaking Changes
@@ -12,7 +69,7 @@
| < 0.12 | >= 0.12 |
|-------------------------------------|----------------------------------|
| `updatePointer Nearest` | `updatePointer (0.5, 0.5) (1,1)` |
| `updatePointer (Relative x y)` | `updatePointer (x,y) (1,1)` |
| `updatePointer (Relative x y)` | `updatePointer (x,y) (0,0)` |
| `updatePointer (TowardsCentre x y)` | `updatePointer (0.5,0.5) (x,y)` |
### New Modules

View File

@@ -146,21 +146,21 @@ instance ExtensionClass ProjectState where
-- | Add dynamic projects support to the given config.
dynamicProjects :: [Project] -> XConfig a -> XConfig a
dynamicProjects ps c =
c { startupHook = startupHook c <> dynamicProjectsStartupHook ps
, logHook = logHook c <> dynamicProjectsLogHook
c { startupHook = dynamicProjectsStartupHook ps <> startupHook c
, logHook = dynamicProjectsLogHook <> logHook c
}
--------------------------------------------------------------------------------
-- | Log hook for tracking workspace changes.
dynamicProjectsLogHook :: X ()
dynamicProjectsLogHook = do
name <- gets (W.tag . W.workspace . W.current . windowset)
state <- XS.get
name <- gets (W.tag . W.workspace . W.current . windowset)
xstate <- XS.get
unless (Just name == previousProject state) $ do
XS.put (state {previousProject = Just name})
unless (Just name == previousProject xstate) $ do
XS.put (xstate {previousProject = Just name})
activateProject . fromMaybe (defProject name) $
Map.lookup name (projects state)
Map.lookup name (projects xstate)
--------------------------------------------------------------------------------
-- | Start-up hook for recording configured projects.
@@ -210,7 +210,8 @@ switchProject p = do
-- If the project we are switching away from has no windows, and
-- it's a dynamic project, remove it from the configuration.
when (null ws && isNothing (projectStartHook oldp)) $
when (null ws && isNothing (projectStartHook oldp)) $ do
removeWorkspaceByTag name -- also remove the old workspace
XS.modify (\s -> s {projects = Map.delete name $ projects s})
appendWorkspace (projectName p)

View File

@@ -1,3 +1,5 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicWorkspaces
@@ -21,13 +23,16 @@ module XMonad.Actions.DynamicWorkspaces (
removeWorkspace,
removeWorkspaceByTag,
removeEmptyWorkspace,
removeEmptyWorkspaceByTag,
removeEmptyWorkspaceAfter,
removeEmptyWorkspaceAfterExcept,
addHiddenWorkspace, addHiddenWorkspaceAt,
withWorkspace,
selectWorkspace, renameWorkspace,
renameWorkspaceByName,
toNthWorkspace, withNthWorkspace
toNthWorkspace, withNthWorkspace,
setWorkspaceIndex, withWorkspaceIndex,
WorkspaceIndex
) where
import XMonad hiding (workspaces)
@@ -38,6 +43,8 @@ import XMonad.Util.WorkspaceCompare ( getSortByIndex )
import Data.List (find)
import Data.Maybe (isNothing)
import Control.Monad (when)
import qualified Data.Map.Strict as Map
import qualified XMonad.Util.ExtensibleState as XS
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
@@ -53,17 +60,55 @@ import Control.Monad (when)
-- > , ((modm .|. shiftMask, xK_m ), withWorkspace def (windows . copy))
-- > , ((modm .|. shiftMask, xK_r ), renameWorkspace def)
--
-- > -- mod-[1..9] %! Switch to workspace N
-- > -- mod-shift-[1..9] %! Move client to workspace N
-- > -- mod-[1..9] %! Switch to workspace N in the list of workspaces
-- > -- mod-shift-[1..9] %! Move client to workspace N in the list of workspaces
-- > ++
-- > zip (zip (repeat (modm)) [xK_1..xK_9]) (map (withNthWorkspace W.greedyView) [0..])
-- > ++
-- > zip (zip (repeat (modm .|. shiftMask)) [xK_1..xK_9]) (map (withNthWorkspace W.shift) [0..])
--
-- Alternatively, you can associate indexes (which don't depend of the
-- workspace list order) to workspaces by using following keybindings:
--
-- > -- mod-[1..9] %! Switch to workspace of index N
-- > -- mod-control-[1..9] %! Set index N to the current workspace
-- > ++
-- > zip (zip (repeat (modm)) [xK_1..xK_9]) (map (withWorkspaceIndex W.greedyView) [1..])
-- > ++
-- > zip (zip (repeat (modm .|. controlMask)) [xK_1..xK_9]) (map (setWorkspaceIndex) [1..])
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings". See also the documentation for
-- "XMonad.Actions.CopyWindow", 'windows', 'shift', and 'XPConfig'.
type WorkspaceTag = String
-- | The workspace index is mapped to a workspace tag by the user and
-- can be updated.
type WorkspaceIndex = Int
-- | Internal dynamic project state that stores a mapping between
-- workspace indexes and workspace tags.
data DynamicWorkspaceState = DynamicWorkspaceState {workspaceIndexMap :: Map.Map WorkspaceIndex WorkspaceTag}
deriving (Typeable, Read, Show)
instance ExtensionClass DynamicWorkspaceState where
initialValue = DynamicWorkspaceState Map.empty
extensionType = PersistentExtension
-- | Set the index of the current workspace.
setWorkspaceIndex :: WorkspaceIndex -> X ()
setWorkspaceIndex widx = do
wtag <- gets (currentTag . windowset)
wmap <- XS.gets workspaceIndexMap
XS.modify $ \s -> s {workspaceIndexMap = Map.insert widx wtag wmap}
withWorkspaceIndex :: (String -> WindowSet -> WindowSet) -> WorkspaceIndex -> X ()
withWorkspaceIndex job widx = do
wtag <- ilookup widx
maybe (return ()) (windows . job) wtag
where
ilookup :: WorkspaceIndex -> X (Maybe WorkspaceTag)
ilookup idx = Map.lookup idx `fmap` XS.gets workspaceIndexMap
mkCompl :: [String] -> String -> IO [String]
@@ -81,10 +126,15 @@ renameWorkspace :: XPConfig -> X ()
renameWorkspace conf = workspacePrompt conf renameWorkspaceByName
renameWorkspaceByName :: String -> X ()
renameWorkspaceByName w = windows $ \s -> let sett wk = wk { tag = w }
setscr scr = scr { workspace = sett $ workspace scr }
sets q = q { current = setscr $ current q }
in sets $ removeWorkspace' w s
renameWorkspaceByName w = do old <- gets (currentTag . windowset)
windows $ \s -> let sett wk = wk { tag = w }
setscr scr = scr { workspace = sett $ workspace scr }
sets q = q { current = setscr $ current q }
in sets $ removeWorkspace' w s
updateIndexMap old w
where updateIndexMap old new = do
wmap <- XS.gets workspaceIndexMap
XS.modify $ \s -> s {workspaceIndexMap = Map.map (\t -> if t == old then new else t) wmap}
toNthWorkspace :: (String -> X ()) -> Int -> X ()
toNthWorkspace job wnum = do sort <- getSortByIndex
@@ -128,7 +178,7 @@ addWorkspaceAt add newtag = addHiddenWorkspaceAt add newtag >> windows (greedyVi
addWorkspacePrompt :: XPConfig -> X ()
addWorkspacePrompt conf = mkXPrompt (Wor "New workspace name: ") conf (const (return [])) addWorkspace
-- | Prompt for the name of a new workspace, appending it to the end of the list of workspaces
-- | Prompt for the name of a new workspace, appending it to the end of the list of workspaces
-- if it does not already exist, and switch to it.
appendWorkspacePrompt :: XPConfig -> X ()
appendWorkspacePrompt conf = mkXPrompt (Wor "New workspace name: ") conf (const (return [])) appendWorkspace

View File

@@ -14,7 +14,8 @@
module XMonad.Actions.FocusNth (
-- * Usage
-- $usage
focusNth,focusNth') where
focusNth,focusNth',
swapNth,swapNth') where
import XMonad.StackSet
import XMonad
@@ -41,6 +42,17 @@ 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)
-- | Swap current window with nth. Focus stays in the same position
swapNth :: Int -> X ()
swapNth = windows . modify' . swapNth'
swapNth' :: Int -> Stack a -> Stack a
swapNth' n s@(Stack c l r)
| (n < 0) || (n > length l + length r) || (n == length l) = s
| n < length l = let (nl, nc:nr) = splitAt (length l - n - 1) l in Stack nc (nl ++ c : nr) r
| otherwise = let (nl, nc:nr) = splitAt (n - length l - 1) r in Stack nc l (nl ++ c : nr)
listToStack :: Int -> [a] -> Stack a
listToStack n l = Stack t ls rs
where

View File

@@ -653,7 +653,7 @@ gridselect gsconfig elements =
liftIO $ mapWindow dpy win
liftIO $ selectInput dpy win (exposureMask .|. keyPressMask .|. buttonReleaseMask)
status <- io $ grabKeyboard dpy win True grabModeAsync grabModeAsync currentTime
io $ grabButton dpy button1 anyModifier win True buttonReleaseMask grabModeAsync grabModeAsync none none
io $ grabPointer dpy win True buttonReleaseMask grabModeAsync grabModeAsync none none currentTime
font <- initXMF (gs_font gsconfig)
let screenWidth = toInteger $ rect_width scr
screenHeight = toInteger $ rect_height scr
@@ -682,6 +682,7 @@ gridselect gsconfig elements =
liftIO $ do
unmapWindow dpy win
destroyWindow dpy win
ungrabPointer dpy currentTime
sync dpy False
releaseXMF font
return selectedElement

View File

@@ -43,6 +43,7 @@ module XMonad.Actions.Navigation2D ( -- * Usage
, Navigation2D
, lineNavigation
, centerNavigation
, hybridNavigation
, fullScreenRect
, singleWindowRect
, switchLayer
@@ -74,10 +75,11 @@ import XMonad.Util.Types
-- natural but may make it impossible to navigate to a given window from the
-- current window, particularly in the floating layer. /Center navigation/
-- feels less natural in certain situations but ensures that all windows can be
-- reached without the need to involve the mouse. Navigation2D allows different
-- navigation strategies to be used in the two layers and allows customization
-- of the navigation strategy for the tiled layer based on the layout currently
-- in effect.
-- reached without the need to involve the mouse. A third option is to use
-- /Hybrid navigation/, which automatically chooses between the two whenever
-- navigation is attempted. Navigation2D allows different navigation strategies
-- to be used in the two layers and allows customization of the navigation strategy
-- for the tiled layer based on the layout currently in effect.
--
-- You can use this module with (a subset of) the following in your @~\/.xmonad\/xmonad.hs@:
--
@@ -316,6 +318,13 @@ lineNavigation = N 1 doLineNavigation
centerNavigation :: Navigation2D
centerNavigation = N 2 doCenterNavigation
-- | Hybrid navigation. This attempts Line navigation, then falls back on Center
-- navigation if it does not find any suitable target windows. This is useful since
-- Line navigation tends to fail on gaps, but provides more intuitive motions
-- when it succeeds—provided there are no floating windows.
hybridNavigation :: Navigation2D
hybridNavigation = N 2 doHybridNavigation
-- | Stores the configuration of directional navigation. The 'Default' instance
-- uses line navigation for the tiled layer and for navigation between screens,
-- and center navigation for the float layer. No custom navigation strategies
@@ -758,6 +767,13 @@ doCenterNavigation dir (cur, rect) winrects
-- or it has the same distance but comes later
-- in the window stack
-- | Implements Hybrid navigation. This attempts Line navigation first,
-- then falls back on Center navigation if it finds no suitable target window.
doHybridNavigation :: Eq a => Direction2D -> Rect a -> [Rect a] -> Maybe a
doHybridNavigation = applyToBoth (<|>) doLineNavigation doCenterNavigation
where
applyToBoth f g h a b c = f (g a b c) (h a b c)
-- | Swaps the current window with the window given as argument
swap :: Window -> WindowSet -> WindowSet
swap win winset = W.focusWindow cur

View File

@@ -284,7 +284,7 @@ searchEngineF = SearchEngine
amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle,
images, imdb, isohunt, lucky, maps, mathworld, openstreetmap, scholar, stackage, thesaurus, vocabulary, wayback, wikipedia, wiktionary,
youtube, duckduckgo :: SearchEngine
amazon = searchEngine "amazon" "http://www.amazon.com/exec/obidos/external-search?index=all&keyword="
amazon = searchEngine "amazon" "http://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords="
alpha = searchEngine "alpha" "http://www.wolframalpha.com/input/?i="
codesearch = searchEngine "codesearch" "http://www.google.com/codesearch?q="
deb = searchEngine "deb" "http://packages.debian.org/"

View File

@@ -16,9 +16,11 @@ module XMonad.Actions.Submap (
-- * Usage
-- $usage
submap,
submapDefault
submapDefault,
submapDefaultWithKey
) where
import Data.Bits
import Data.Maybe (fromMaybe)
import XMonad hiding (keys)
import qualified Data.Map as M
import Control.Monad.Fix (fix)
@@ -58,11 +60,18 @@ For detailed instructions on editing your key bindings, see
-- corresponding action, or does nothing if the key is not found in
-- the map.
submap :: M.Map (KeyMask, KeySym) (X ()) -> X ()
submap keys = submapDefault (return ()) keys
submap = submapDefault (return ())
-- | Like 'submap', but executes a default action if the key did not match.
submapDefault :: X () -> M.Map (KeyMask, KeySym) (X ()) -> X ()
submapDefault defAction keys = do
submapDefault = submapDefaultWithKey . const
-- | Like 'submapDefault', but sends the unmatched key to the default
-- action as argument.
submapDefaultWithKey :: ((KeyMask, KeySym) -> X ())
-> M.Map (KeyMask, KeySym) (X ())
-> X ()
submapDefaultWithKey defAction keys = do
XConf { theRoot = root, display = d } <- ask
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
@@ -79,4 +88,4 @@ submapDefault defAction keys = do
io $ ungrabKeyboard d currentTime
maybe defAction id (M.lookup (m', s) keys)
fromMaybe (defAction (m', s)) (M.lookup (m', s) keys)

View File

@@ -0,0 +1,657 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TreeSelect
-- Copyright : (c) Tom Smeets <tom.tsmeets@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Tom Smeets <tom.tsmeets@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
--
-- TreeSelect displays your workspaces or actions in a Tree-like format.
-- You can select the desired workspace/action with the cursor or hjkl keys.
--
-- This module is fully configurable and very useful if you like to have a
-- lot of workspaces.
--
-- Only the nodes up to the currently selected are displayed.
-- This will be configurable in the near future by changing 'ts_hidechildren' to @False@, this is not yet implemented.
--
-- <<https://wiki.haskell.org/wikiupload/thumb/0/0b/Treeselect-Workspace.png/800px-Treeselect-Workspace.png>>
--
-----------------------------------------------------------------------------
module XMonad.Actions.TreeSelect
(
-- * Usage
-- $usage
treeselectWorkspace
, toWorkspaces
, treeselectAction
-- * Configuring
-- $config
, Pixel
-- $pixel
, TSConfig(..)
, tsDefaultConfig
-- * Navigation
-- $navigation
, defaultNavigation
, select
, cancel
, moveParent
, moveChild
, moveNext
, movePrev
, moveHistBack
, moveHistForward
, moveTo
-- * Advanced usage
-- $advusage
, TSNode(..)
, treeselect
, treeselectAt
) where
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.State
import Data.List (find)
import Data.Maybe
import Data.Tree
import Foreign
import System.IO
import System.Posix.Process (forkProcess, executeFile)
import XMonad hiding (liftX)
import XMonad.StackSet as W
import XMonad.Util.Font
import XMonad.Util.NamedWindows
import XMonad.Util.TreeZipper
import XMonad.Hooks.WorkspaceHistory
import qualified Data.Map as M
#ifdef XFT
import Graphics.X11.Xft
import Graphics.X11.Xrender
#endif
-- $usage
--
-- These imports are used in the following example
--
-- > import Data.Tree
-- > import XMonad.Actions.TreeSelect
-- > import XMonad.Hooks.WorkspaceHistory
-- > import qualified XMonad.StackSet as W
--
-- For selecting Workspaces, you need to define them in a tree structure using 'Data.Tree.Node' instead of just a standard list
--
-- Here is an example workspace-tree
--
-- > myWorkspaces :: Forest String
-- > myWorkspaces = [ Node "Browser" [] -- a workspace for your browser
-- > , Node "Home" -- for everyday activity's
-- > [ Node "1" [] -- with 4 extra sub-workspaces, for even more activity's
-- > , Node "2" []
-- > , Node "3" []
-- > , Node "4" []
-- > ]
-- > , Node "Programming" -- for all your programming needs
-- > [ Node "Haskell" []
-- > , Node "Docs" [] -- documentation
-- > ]
-- > ]
--
-- Then add it to your 'XMonad.Core.workspaces' using the 'toWorkspaces' function.
--
-- Optionally, if you add 'workspaceHistoryHook' to your 'logHook' you can use the \'o\' and \'i\' keys to select from previously-visited workspaces
--
-- > xmonad $ defaultConfig { ...
-- > , workspaces = toWorkspaces myWorkspaces
-- > , logHook = workspaceHistoryHook
-- > }
--
-- After that you still need to bind buttons to 'treeselectWorkspace' to start selecting a workspaces and moving windows
--
-- you could bind @Mod-f@ to switch workspace
--
-- > , ((modMask, xK_f), treeselectWorkspace myTreeConf myWorkspaces W.greedyView)
--
-- and bind @Mod-Shift-f@ to moving the focused windows to a workspace
--
-- > , ((modMask .|. shiftMask, xK_f), treeselectWorkspace myTreeConf myWorkspaces W.shift)
-- $config
-- The selection menu is very configurable, you can change the font, all colors and the sizes of the boxes.
--
-- The default config defined as 'tsDefaultConfig'
--
-- > tsDefaultConfig = TSConfig { ts_hidechildren = True
-- > , ts_background = 0xc0c0c0c0
-- > , ts_font = "xft:Sans-16"
-- > , ts_node = (0xff000000, 0xff50d0db)
-- > , ts_nodealt = (0xff000000, 0xff10b8d6)
-- > , ts_highlight = (0xffffffff, 0xffff0000)
-- > , ts_extra = 0xff000000
-- > , ts_node_width = 200
-- > , ts_node_height = 30
-- > , ts_originX = 0
-- > , ts_originY = 0
-- > , ts_indent = 80
-- > , ts_navigate = defaultNavigation
-- > }
-- $pixel
--
-- The 'Pixel' Color format is in the form of @0xaarrggbb@
--
-- Note that transparency is only supported if you have a window compositor running like <https://github.com/chjj/compton compton>
--
-- Some Examples:
--
-- @
-- white = 0xffffffff
-- black = 0xff000000
-- red = 0xffff0000
-- blue = 0xff00ff00
-- green = 0xff0000ff
-- transparent = 0x00000000
-- @
-- $navigation
--
-- Keybindings for navigations can also be modified
--
-- This is the definition of 'defaultNavigation'
--
-- > defaultNavigation :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a))
-- > defaultNavigation = M.fromList
-- > [ ((0, xK_Escape), cancel)
-- > , ((0, xK_Return), select)
-- > , ((0, xK_space), select)
-- > , ((0, xK_Up), movePrev)
-- > , ((0, xK_Down), moveNext)
-- > , ((0, xK_Left), moveParent)
-- > , ((0, xK_Right), moveChild)
-- > , ((0, xK_k), movePrev)
-- > , ((0, xK_j), moveNext)
-- > , ((0, xK_h), moveParent)
-- > , ((0, xK_l), moveChild)
-- > , ((0, xK_o), moveHistBack)
-- > , ((0, xK_i), moveHistForward)
-- > ]
-- $advusage
-- This module can also be used to select any other action
-- | Extensive configuration for displaying the tree.
--
-- This class also has a 'Default' instance
data TSConfig a = TSConfig { ts_hidechildren :: Bool -- ^ when enabled, only the parents (and their first children) of the current node will be shown (This feature is not yet implemented!)
, ts_background :: Pixel -- ^ background color filling the entire screen.
, ts_font :: String -- ^ XMF font for drawing the node name extra text
, ts_node :: (Pixel, Pixel) -- ^ node foreground (text) and background color when not selected
, ts_nodealt :: (Pixel, Pixel) -- ^ every other node will use this color instead of 'ts_node'
, ts_highlight :: (Pixel, Pixel) -- ^ node foreground (text) and background color when selected
, ts_extra :: Pixel -- ^ extra text color
, ts_node_width :: Int -- ^ node width in pixels
, ts_node_height :: Int -- ^ node height in pixels
, ts_originX :: Int -- ^ tree X position on the screen in pixels
, ts_originY :: Int -- ^ tree Y position on the screen in pixels
, ts_indent :: Int -- ^ indentation amount for each level in pixels
, ts_navigate :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a)) -- ^ key bindings for navigating the tree
}
instance Default (TSConfig a) where
def = TSConfig { ts_hidechildren = True
, ts_background = 0xc0c0c0c0
, ts_font = "xft:Sans-16"
, ts_node = (0xff000000, 0xff50d0db)
, ts_nodealt = (0xff000000, 0xff10b8d6)
, ts_highlight = (0xffffffff, 0xffff0000)
, ts_extra = 0xff000000
, ts_node_width = 200
, ts_node_height = 30
, ts_originX = 0
, ts_originY = 0
, ts_indent = 80
, ts_navigate = defaultNavigation
}
-- | Default navigation
--
-- * navigation using either arrow key or vi style hjkl
-- * Return or Space to confirm
-- * Escape or Backspace to cancel to
defaultNavigation :: M.Map (KeyMask, KeySym) (TreeSelect a (Maybe a))
defaultNavigation = M.fromList
[ ((0, xK_Escape), cancel)
, ((0, xK_Return), select)
, ((0, xK_space), select)
, ((0, xK_Up), movePrev)
, ((0, xK_Down), moveNext)
, ((0, xK_Left), moveParent)
, ((0, xK_Right), moveChild)
, ((0, xK_k), movePrev)
, ((0, xK_j), moveNext)
, ((0, xK_h), moveParent)
, ((0, xK_l), moveChild)
, ((0, xK_o), moveHistBack)
, ((0, xK_i), moveHistForward)
]
-- | Default configuration.
--
-- Using nice alternating blue nodes
tsDefaultConfig :: TSConfig a
tsDefaultConfig = def
-- | Tree Node With a name and extra text
data TSNode a = TSNode { tsn_name :: String
, tsn_extra :: String -- ^ extra text, displayed next to the node name
, tsn_value :: a -- ^ value to return when this node is selected
}
-- | State used by TreeSelect.
--
-- Contains all needed information such as the window, font and a zipper over the tree.
data TSState a = TSState { tss_tree :: TreeZipper (TSNode a)
, tss_window :: Window
, tss_display :: Display
, tss_size :: (Int, Int) -- ^ size of 'tz_window'
, tss_xfont :: XMonadFont
, tss_gc :: GC
, tss_visual :: Visual
, tss_colormap :: Colormap
, tss_history :: ([[String]], [[String]]) -- ^ history zipper, navigated with 'moveHistBack' and 'moveHistForward'
}
-- | State monad transformer using 'TSState'
newtype TreeSelect a b = TreeSelect { runTreeSelect :: ReaderT (TSConfig a) (StateT (TSState a) X) b }
deriving (Monad, Applicative, Functor, MonadState (TSState a), MonadReader (TSConfig a), MonadIO)
-- | Lift the 'X' action into the 'XMonad.Actions.TreeSelect.TreeSelect' monad
liftX :: X a -> TreeSelect b a
liftX = TreeSelect . lift . lift
-- | Run Treeselect with a given config and tree.
-- This can be used for selectiong anything
--
-- * for switching workspaces and moving windows use 'treeselectWorkspace'
-- * for selecting actions use 'treeselectAction'
treeselect :: TSConfig a -- ^ config file
-> Forest (TSNode a) -- ^ a list of 'Data.Tree.Tree's to select from.
-> X (Maybe a)
treeselect c t = treeselectAt c (fromForest t) []
-- | Same as 'treeselect' but ad a specific starting position
treeselectAt :: TSConfig a -- ^ config file
-> TreeZipper (TSNode a) -- ^ tree structure with a cursor position (starting node)
-> [[String]] -- ^ list of paths that can be navigated with 'moveHistBack' and 'moveHistForward' (bound to the 'o' and 'i' keys)
-> X (Maybe a)
treeselectAt conf@TSConfig{..} zipper hist = withDisplay $ \display -> do
-- create a window on the currently focused screen
rootw <- asks theRoot
Rectangle{..} <- gets $ screenRect . W.screenDetail . W.current . windowset
Just vinfo <- liftIO $ matchVisualInfo display (defaultScreen display) 32 4
colormap <- liftIO $ createColormap display rootw (visualInfo_visual vinfo) allocNone
win <- liftIO $ allocaSetWindowAttributes $ \attributes -> do
set_override_redirect attributes True
set_colormap attributes colormap
set_background_pixel attributes ts_background
set_border_pixel attributes 0
createWindow display rootw rect_x rect_y rect_width rect_height 0 (visualInfo_depth vinfo) inputOutput (visualInfo_visual vinfo) (cWColormap .|. cWBorderPixel .|. cWBackPixel) attributes
liftIO $ do
-- TODO: move below?
-- make the window visible
mapWindow display win
-- listen to key and mouse button events
selectInput display win (exposureMask .|. keyPressMask .|. buttonReleaseMask)
-- TODO: enable mouse select?
-- and mouse button 1
grabButton display button1 anyModifier win True buttonReleaseMask grabModeAsync grabModeAsync none none
-- grab the keyboard
status <- liftIO $ grabKeyboard display win True grabModeAsync grabModeAsync currentTime
r <- if status == grabSuccess
then do
-- load the XMF font
gc <- liftIO $ createGC display win
xfont <- initXMF ts_font
-- run the treeselect Monad
ret <- evalStateT (runReaderT (runTreeSelect (redraw >> navigate)) conf)
TSState{ tss_tree = zipper
, tss_window = win
, tss_display = display
, tss_xfont = xfont
, tss_size = (fromIntegral rect_width, fromIntegral rect_height)
, tss_gc = gc
, tss_visual = visualInfo_visual vinfo
, tss_colormap = colormap
, tss_history = ([], hist)
}
-- release the XMF font
releaseXMF xfont
liftIO $ freeGC display gc
return ret
else return Nothing
-- destroy the window
liftIO $ do
unmapWindow display win
destroyWindow display win
freeColormap display colormap
-- Flush the output buffer and wait for all the events to be processed
-- TODO: is this needed?
sync display False
return r
-- | Select a workspace and execute a \"view\" function from "XMonad.StackSet" on it.
treeselectWorkspace :: TSConfig WorkspaceId
-> Forest String -- ^ your tree of workspace-names
-> (WorkspaceId -> WindowSet -> WindowSet) -- ^ the \"view\" function.
-- Instances can be 'W.greedyView' for switching to a workspace
-- and/or 'W.shift' for moving the focused window to a selected workspace.
--
-- These actions can also be combined by doing
--
-- > \i -> W.greedyView i . W.shift i
-> X ()
treeselectWorkspace c xs f = do
-- get all defined workspaces
-- They have to be set with 'toWorkspaces'!
ws <- gets (W.workspaces . windowset)
-- check the 'XConfig.workspaces'
if all (`elem` map tag ws) (toWorkspaces xs)
then do
-- convert the 'Forest WorkspaceId' to 'Forest (TSNode WorkspaceId)'
wsf <- forMForest (mkPaths xs) $ \(n, i) -> maybe (return (TSNode n "Does not exist!" "")) (mkNode n) (find (\w -> i == tag w) ws)
-- get the current workspace path
me <- gets (W.tag . W.workspace . W.current . windowset)
hist <- workspaceHistory
treeselectAt c (fromJust $ followPath tsn_name (splitPath me) $ fromForest wsf) (map splitPath hist) >>= maybe (return ()) (windows . f)
else liftIO $ do
-- error!
let msg = unlines $ [ "Please add:"
, " workspaces = toWorkspaces myWorkspaces"
, "to your XMonad config!"
, ""
, "XConfig.workspaces: "
] ++ map tag ws
hPutStrLn stderr msg
_ <- forkProcess $ executeFile "xmessage" True [msg] Nothing
return ()
where
mkNode n w = do
-- find the focused window's name on this workspace
name <- maybe (return "") (fmap show . getName . W.focus) $ stack w
return $ TSNode n name (tag w)
-- | Convert the workspace-tree to a flat list of paths such that XMonad can use them
--
-- The Nodes will be separated by a dot (\'.\') character
toWorkspaces :: Forest String -> [WorkspaceId]
toWorkspaces = map snd . concatMap flatten . mkPaths
mkPaths :: Forest String -> Forest (String, WorkspaceId)
mkPaths = map (\(Node n ns) -> Node (n, n) (map (f n) ns))
where
f pth (Node x xs) = let pth' = pth ++ '.' : x
in Node (x, pth') (map (f pth') xs)
splitPath :: WorkspaceId -> [String]
splitPath i = case break (== '.') i of
(x, []) -> [x]
(x, _:xs) -> x : splitPath xs
-- | Select from a Tree of 'X' actions
--
-- <<https://wiki.haskell.org/wikiupload/thumb/9/9b/Treeselect-Action.png/800px-Treeselect-Action.png>>
--
-- Each of these actions have to be specified inside a 'TSNode'
--
-- Example
--
-- > treeselectAction myTreeConf
-- > [ Node (TSNode "Hello" "displays hello" (spawn "xmessage hello!")) []
-- > , Node (TSNode "Shutdown" "Poweroff the system" (spawn "shutdown")) []
-- > , Node (TSNode "Brightness" "Sets screen brightness using xbacklight" (return ()))
-- > [ Node (TSNode "Bright" "FULL POWER!!" (spawn "xbacklight -set 100")) []
-- > , Node (TSNode "Normal" "Normal Brightness (50%)" (spawn "xbacklight -set 50")) []
-- > , Node (TSNode "Dim" "Quite dark" (spawn "xbacklight -set 10")) []
-- > ]
-- > ]
treeselectAction :: TSConfig (X a) -> Forest (TSNode (X a)) -> X ()
treeselectAction c xs = treeselect c xs >>= \x -> case x of
Just a -> a >> return ()
Nothing -> return ()
forMForest :: (Functor m, Applicative m, Monad m) => [Tree a] -> (a -> m b) -> m [Tree b]
forMForest x g = mapM (mapMTree g) x
mapMTree :: (Functor m, Applicative m, Monad m) => (a -> m b) -> Tree a -> m (Tree b)
mapMTree f (Node x xs) = Node <$> f x <*> mapM (mapMTree f) xs
-- | Quit returning the currently selected node
select :: TreeSelect a (Maybe a)
select = Just <$> gets (tsn_value . cursor . tss_tree)
-- | Quit without returning anything
cancel :: TreeSelect a (Maybe a)
cancel = return Nothing
-- TODO: redraw only what is necessary.
-- Examples: redrawAboveCursor, redrawBelowCursor and redrawCursor
-- | Move the cursor to its parent node
moveParent :: TreeSelect a (Maybe a)
moveParent = moveWith parent >> redraw >> navigate
-- | Move the cursor one level down, highlighting its first child-node
moveChild :: TreeSelect a (Maybe a)
moveChild = moveWith children >> redraw >> navigate
-- | Move the cursor to the next child-node
moveNext :: TreeSelect a (Maybe a)
moveNext = moveWith nextChild >> redraw >> navigate
-- | Move the cursor to the previous child-node
movePrev :: TreeSelect a (Maybe a)
movePrev = moveWith previousChild >> redraw >> navigate
-- | Move backwards in history
moveHistBack :: TreeSelect a (Maybe a)
moveHistBack = do
s <- get
case tss_history s of
(xs, a:y:ys) -> do
put s{tss_history = (a:xs, y:ys)}
moveTo y
_ -> navigate
-- | Move forward in history
moveHistForward :: TreeSelect a (Maybe a)
moveHistForward = do
s <- get
case tss_history s of
(x:xs, ys) -> do
put s{tss_history = (xs, x:ys)}
moveTo x
_ -> navigate
-- | Move to a specific node
moveTo :: [String] -- ^ path, always starting from the top
-> TreeSelect a (Maybe a)
moveTo i = moveWith (followPath tsn_name i . rootNode) >> redraw >> navigate
-- | Apply a transformation on the internal 'XMonad.Util.TreeZipper.TreeZipper'.
moveWith :: (TreeZipper (TSNode a) -> Maybe (TreeZipper (TSNode a))) -> TreeSelect a ()
moveWith f = do
s <- get
case f (tss_tree s) of
-- TODO: redraw cursor only?
Just t -> put s{ tss_tree = t }
Nothing -> return ()
-- | wait for keys and run navigation
navigate :: TreeSelect a (Maybe a)
navigate = gets tss_display >>= \d -> join . liftIO . allocaXEvent $ \e -> do
maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask) e
ev <- getEvent e
if ev_event_type ev == keyPress
then do
(ks, _) <- lookupString $ asKeyEvent e
return $ do
mask <- liftX $ cleanMask (ev_state ev)
f <- asks ts_navigate
fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f
else return navigate
-- | Request a full redraw
redraw :: TreeSelect a ()
redraw = do
win <- gets tss_window
dpy <- gets tss_display
-- clear window
-- TODO: not always needed!
liftIO $ clearWindow dpy win
t <- gets tss_tree
_ <- drawLayers 0 0 (reverse $ (tz_before t, cursor t, tz_after t) : tz_parents t)
return ()
drawLayers :: Int -- ^ indentation level
-> Int -- ^ height
-> [(Forest (TSNode a), TSNode a, Forest (TSNode a))] -- ^ node layers (from top to bottom!)
-> TreeSelect a Int
drawLayers _ yl [] = return yl
drawLayers xl yl ((bs, c, as):xs) = do
TSConfig{..} <- ask
let nodeColor y = if odd y then ts_node else ts_nodealt
-- draw nodes above
forM_ (zip [yl ..] (reverse bs)) $ \(y, Node n _) ->
drawNode xl y n (nodeColor y)
-- drawLayers (xl + 1) (y + 1) ns
-- TODO: draw rest? if not ts_hidechildren
-- drawLayers (xl + 1) (y + 1) ns
-- draw the current / parent node
-- if this is the last (currently focused) we use the 'ts_highlight' color
let current_level = yl + length bs
drawNode xl current_level c $
if null xs then ts_highlight
else nodeColor current_level
l2 <- drawLayers (xl + 1) (current_level + 1) xs
-- draw nodes below
forM_ (zip [l2 ..] as) $ \(y, Node n _) ->
drawNode xl y n (nodeColor y)
-- TODO: draw rest? if not ts_hidechildren
-- drawLayers (xl + 1) (y + 1) ns
return (l2 + length as)
-- | Draw a node at a given indentation and height level
drawNode :: Int -- ^ indentation level (not in pixels)
-> Int -- ^ height level (not in pixels)
-> TSNode a -- ^ node to draw
-> (Pixel, Pixel) -- ^ node foreground (font) and background color
-> TreeSelect a ()
drawNode ix iy TSNode{..} col = do
TSConfig{..} <- ask
window <- gets tss_window
display <- gets tss_display
font <- gets tss_xfont
gc <- gets tss_gc
colormap <- gets tss_colormap
visual <- gets tss_visual
liftIO $ drawWinBox window display visual colormap gc font col tsn_name ts_extra tsn_extra
(ix * ts_indent) (iy * ts_node_height)
ts_node_width ts_node_height
-- TODO: draw extra text (transparent background? or ts_background)
-- drawWinBox window fnt col2 nodeH (scW-x) (mes) (x+nodeW) y 8
-- | Draw a simple box with text
drawWinBox :: Window -> Display -> Visual -> Colormap -> GC -> XMonadFont -> (Pixel, Pixel) -> String -> Pixel -> String -> Int -> Int -> Int -> Int -> IO ()
drawWinBox win display visual colormap gc font (fg, bg) text fg2 text2 x y w h = do
-- draw box
setForeground display gc bg
fillRectangle display win gc (fromIntegral x) (fromIntegral y) (fromIntegral w) (fromIntegral h)
-- dreaw text
drawStringXMF display win visual colormap gc font fg
(fromIntegral $ x + 8)
(fromIntegral $ y + h - 8)
text
-- dreaw extra text
drawStringXMF display win visual colormap gc font fg2
(fromIntegral $ x + w + 8)
(fromIntegral $ y + h - 8)
text2
-- | Modified version of 'XMonad.Util.Font.printStringXMF' that uses 'Pixel' as color format
drawStringXMF :: Display -> Drawable -> Visual -> Colormap -> GC
-> XMonadFont -- ^ XMF Font
-> Pixel -- ^ font color
-> Position -- ^ x-position
-> Position -- ^ y-position
-> String -- ^ string text
-> IO ()
drawStringXMF display window visual colormap gc font col x y text = case font of
Core fnt -> do
setForeground display gc col
setFont display gc $ fontFromFontStruct fnt
drawImageString display window gc x y text
Utf8 fnt -> do
setForeground display gc col
wcDrawImageString display window fnt gc x y text
#ifdef XFT
Xft fnt -> do
withXftDraw display window visual colormap $
\ft_draw -> withXftColorValue display visual colormap (fromARGB col) $
\ft_color -> xftDrawString ft_draw ft_color fnt x y text
-- | Convert 'Pixel' to 'XRenderColor'
--
-- Note that it uses short to represent its components
fromARGB :: Pixel -> XRenderColor
fromARGB x = XRenderColor (fromIntegral $ 0xff00 .&. shiftR x 8) -- red
(fromIntegral $ 0xff00 .&. x) -- green
(fromIntegral $ 0xff00 .&. shiftL x 8) -- blue
(fromIntegral $ 0xff00 .&. shiftR x 16) -- alpha
#endif

View File

@@ -1,3 +1,4 @@
{-# LANGUAGE TupleSections #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WindowBringer
@@ -17,13 +18,13 @@
module XMonad.Actions.WindowBringer (
-- * Usage
-- $usage
gotoMenu, gotoMenu', gotoMenuArgs, gotoMenuArgs',
bringMenu, bringMenu', bringMenuArgs, bringMenuArgs',
windowMap,
bringWindow
WindowBringerConfig(..),
gotoMenu, gotoMenuConfig, gotoMenu', gotoMenuArgs, gotoMenuArgs',
bringMenu, bringMenuConfig, bringMenu', bringMenuArgs, bringMenuArgs',
windowMap, windowMap', bringWindow, actionMenu
) where
import Data.Char (toLower)
import Control.Applicative((<$>))
import qualified Data.Map as M
import qualified XMonad.StackSet as W
@@ -46,54 +47,74 @@ import XMonad.Util.NamedWindows (getName)
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- | Default menu command
defaultCmd :: String
defaultCmd = "dmenu"
data WindowBringerConfig = WindowBringerConfig
{ menuCommand :: String -- ^ The shell command that will handle window selection
, menuArgs :: [String] -- ^ Arguments to be passed to menuCommand
, windowTitler :: X.WindowSpace -> Window -> X String -- ^ A function that produces window titles given a workspace and a window
}
instance Default WindowBringerConfig where
def = WindowBringerConfig{ menuCommand = "dmenu"
, menuArgs = ["-i"]
, windowTitler = decorateName
}
-- | Pops open a dmenu with window titles. Choose one, and you will be
-- taken to the corresponding workspace.
gotoMenu :: X ()
gotoMenu = gotoMenuArgs []
gotoMenu = gotoMenuConfig def
-- | Pops open a dmenu with window titles. Choose one, and you will be
-- taken to the corresponding workspace. This version accepts a configuration
-- object.
gotoMenuConfig :: WindowBringerConfig -> X ()
gotoMenuConfig wbConfig = actionMenu wbConfig W.focusWindow
-- | Pops open a dmenu with window titles. Choose one, and you will be
-- taken to the corresponding workspace. This version takes a list of
-- arguments to pass to dmenu.
gotoMenuArgs :: [String] -> X ()
gotoMenuArgs menuArgs = gotoMenuArgs' defaultCmd menuArgs
gotoMenuArgs args = gotoMenuConfig def { menuArgs = args }
-- | Pops open an application with window titles given over stdin. Choose one,
-- and you will be taken to the corresponding workspace.
gotoMenu' :: String -> X ()
gotoMenu' menuCmd = gotoMenuArgs' menuCmd []
gotoMenu' cmd = gotoMenuConfig def { menuArgs = [], menuCommand = cmd }
-- | Pops open an application with window titles given over stdin. Choose one,
-- and you will be taken to the corresponding workspace. This version takes a
-- list of arguments to pass to dmenu.
gotoMenuArgs' :: String -> [String] -> X ()
gotoMenuArgs' menuCmd menuArgs = actionMenu menuCmd menuArgs W.focusWindow
gotoMenuArgs' cmd args = gotoMenuConfig def { menuCommand = cmd, menuArgs = args }
-- | Pops open a dmenu with window titles. Choose one, and it will be
-- dragged, kicking and screaming, into your current workspace.
bringMenu :: X ()
bringMenu = bringMenuArgs []
bringMenu = bringMenuArgs def
-- | Pops open a dmenu with window titles. Choose one, and it will be
-- dragged, kicking and screaming, into your current workspace. This version
-- accepts a configuration object.
bringMenuConfig :: WindowBringerConfig -> X ()
bringMenuConfig wbConfig = actionMenu wbConfig bringWindow
-- | Pops open a dmenu with window titles. Choose one, and it will be
-- dragged, kicking and screaming, into your current workspace. This version
-- takes a list of arguments to pass to dmenu.
bringMenuArgs :: [String] -> X ()
bringMenuArgs menuArgs = bringMenuArgs' defaultCmd menuArgs
bringMenuArgs args = bringMenuConfig def { menuArgs = args }
-- | Pops open an application with window titles given over stdin. Choose one,
-- and it will be dragged, kicking and screaming, into your current
-- workspace.
bringMenu' :: String -> X ()
bringMenu' menuCmd = bringMenuArgs' menuCmd []
bringMenu' cmd = bringMenuConfig def { menuArgs = [], menuCommand = cmd }
-- | Pops open an application with window titles given over stdin. Choose one,
-- and it will be dragged, kicking and screaming, into your current
-- workspace. This version allows arguments to the chooser to be specified.
bringMenuArgs' :: String -> [String] -> X ()
bringMenuArgs' menuCmd menuArgs = actionMenu menuCmd menuArgs bringWindow
bringMenuArgs' cmd args = bringMenuConfig def { menuArgs = args, menuCommand = cmd }
-- | Brings the specified window into the current workspace.
bringWindow :: Window -> X.WindowSet -> X.WindowSet
@@ -101,25 +122,33 @@ bringWindow w ws = W.shiftWin (W.currentTag ws) w ws
-- | Calls dmenuMap to grab the appropriate Window, and hands it off to action
-- if found.
actionMenu :: String -> [String] -> (Window -> X.WindowSet -> X.WindowSet) -> X ()
actionMenu menuCmd menuArgs action = windowMap >>= menuMapFunction >>= flip X.whenJust (windows . action)
actionMenu :: WindowBringerConfig -> (Window -> X.WindowSet -> X.WindowSet) -> X ()
actionMenu WindowBringerConfig{ menuCommand = cmd
, menuArgs = args
, windowTitler = titler
} action
= windowMap' titler >>= menuMapFunction >>= flip X.whenJust (windows . action)
where
menuMapFunction :: M.Map String a -> X (Maybe a)
menuMapFunction selectionMap = menuMapArgs menuCmd menuArgs selectionMap
menuMapFunction = menuMapArgs cmd args
-- | A map from window names to Windows.
windowMap :: X (M.Map String Window)
windowMap = do
windowMap = windowMap' decorateName
-- | A map from window names to Windows, given a windowTitler function.
windowMap' :: (X.WindowSpace -> Window -> X String) -> X (M.Map String Window)
windowMap' titler = do
ws <- gets X.windowset
M.fromList `fmap` concat `fmap` mapM keyValuePairs (W.workspaces ws)
M.fromList . concat <$> mapM keyValuePairs (W.workspaces ws)
where keyValuePairs ws = mapM (keyValuePair ws) $ W.integrate' (W.stack ws)
keyValuePair ws w = flip (,) w `fmap` decorateName ws w
keyValuePair ws w = flip (,) w <$> titler ws w
-- | Returns the window name as will be listed in dmenu.
-- Lowercased, for your convenience (since dmenu is case-sensitive).
-- Tagged with the workspace ID, to guarantee uniqueness, and to let the user
-- know where he's going.
decorateName :: X.WindowSpace -> Window -> X String
decorateName ws w = do
name <- fmap (map toLower . show) $ getName w
name <- show <$> getName w
return $ name ++ " [" ++ W.tag ws ++ "]"

View File

@@ -21,6 +21,7 @@ module XMonad.Actions.WindowGo (
runOrRaiseNext,
raiseMaybe,
raiseNextMaybe,
raiseNextMaybeCustomFocus,
raiseBrowser,
raiseEditor,
@@ -38,7 +39,7 @@ module XMonad.Actions.WindowGo (
import Control.Monad
import Data.Char (toLower)
import Data.Monoid
import XMonad (Query(), X(), ManageHook, withWindowSet, runQuery, liftIO, ask)
import XMonad (Query(), X(), ManageHook, WindowSet, withWindowSet, runQuery, liftIO, ask)
import Graphics.X11 (Window)
import XMonad.ManageHook
import XMonad.Operations (windows)
@@ -137,16 +138,21 @@ raiseNext = raiseNextMaybe $ return ()
'raiseNextMaybe' is an alternative version that allows cycling
through the matching windows. If the focused window matches the
query the next matching window is raised. If no matches are found
the function f is executed.
-}
the function f is executed. -}
raiseNextMaybe :: X () -> Query Bool -> X ()
raiseNextMaybe f qry = flip (ifWindows qry) f $ \ws -> do
raiseNextMaybe = raiseNextMaybeCustomFocus W.focusWindow
{- | See 'raiseMaybe' and 'raiseNextMaybe'.
In addition to all of the options offered by 'raiseNextMaybe'
'raiseNextMaybeCustomFocus' allows the user to supply the function that
should be used to shift the focus to any window that is found. -}
raiseNextMaybeCustomFocus :: (Window -> WindowSet -> WindowSet) -> X() -> Query Bool -> X()
raiseNextMaybeCustomFocus focusFn f qry = flip (ifWindows qry) f $ \ws -> do
foc <- withWindowSet $ return . W.peek
case foc of
Just w | w `elem` ws -> let (_:y:_) = dropWhile (/=w) $ cycle ws -- cannot fail to match
in windows $ W.focusWindow y
_ -> windows . W.focusWindow . head $ ws
in windows $ focusFn y
_ -> windows . focusFn . head $ ws
-- | Given a function which gets us a String, we try to raise a window with that classname,
-- or we then interpret that String as a executable name.
@@ -167,7 +173,8 @@ raiseAndDo :: X () -> Query Bool -> (Window -> X ()) -> X ()
raiseAndDo f qry after = ifWindow qry (afterRaise `mappend` raiseHook) f
where afterRaise = ask >>= (>> idHook) . liftX . after
{- | If a window matching the second argument is found, the window is focused and the third argument is called;
{- | If a window matching the second argument is found, the window is focused and
the third argument is called;
otherwise, the first argument is called. -}
runOrRaiseAndDo :: String -> Query Bool -> (Window -> X ()) -> X ()
runOrRaiseAndDo = raiseAndDo . safeSpawnProg
@@ -182,7 +189,6 @@ raiseMaster raisef thatUserQuery = raiseAndDo raisef thatUserQuery (\_ -> window
{- | If the window is found the window is focused and set to master
otherwise, action is run.
> runOrRaiseMaster "firefox" (className =? "Firefox"))
-}
> runOrRaiseMaster "firefox" (className =? "Firefox")) -}
runOrRaiseMaster :: String -> Query Bool -> X ()
runOrRaiseMaster run query = runOrRaiseAndDo run query (\_ -> windows W.swapMaster)

View File

@@ -31,6 +31,7 @@ module XMonad.Actions.Workscreen (
,shiftToWorkscreen
,fromWorkspace
,expandWorkspace
,WorkscreenId
) where
import XMonad hiding (workspaces)

View File

@@ -24,7 +24,10 @@ module XMonad.Actions.WorkspaceNames (
-- * Workspace naming
renameWorkspace,
workspaceNamesPP,
getWorkspaceNames',
getWorkspaceNames,
getWorkspaceName,
getCurrentWorkspaceName,
setWorkspaceName,
setCurrentWorkspaceName,
@@ -88,14 +91,27 @@ instance ExtensionClass WorkspaceNames where
initialValue = WorkspaceNames M.empty
extensionType = PersistentExtension
-- | Returns a lookup function that maps workspace tags to workspace names.
getWorkspaceNames' :: X (WorkspaceId -> Maybe String)
getWorkspaceNames' = do
WorkspaceNames m <- XS.get
return (`M.lookup` m)
-- | Returns a function that maps workspace tag @\"t\"@ to @\"t:name\"@ for
-- workspaces with a name, and to @\"t\"@ otherwise.
getWorkspaceNames :: X (WorkspaceId -> String)
getWorkspaceNames = do
WorkspaceNames m <- XS.get
return $ \wks -> case M.lookup wks m of
Nothing -> wks
Just s -> wks ++ ":" ++ s
lookup <- getWorkspaceNames'
return $ \wks -> wks ++ maybe "" (':' :) (lookup wks)
-- | Gets the name of a workspace, if set, otherwise returns nothing.
getWorkspaceName :: WorkspaceId -> X (Maybe String)
getWorkspaceName w = ($ w) `fmap` getWorkspaceNames'
-- | Gets the name of the current workspace. See 'getWorkspaceName'
getCurrentWorkspaceName :: X (Maybe String)
getCurrentWorkspaceName = do
getWorkspaceName =<< gets (W.currentTag . windowset)
-- | Sets the name of a workspace. Empty string makes the workspace unnamed
-- again.

View File

@@ -36,7 +36,7 @@ import qualified Data.Map as M
-- If you prefer, an azertyKeys function is provided which you can use as so:
--
-- > import qualified Data.Map as M
-- > main = xmonad someConfig { keys = \c -> azertyKeys c `M.union` keys someConfig c }
-- > main = xmonad someConfig { keys = \c -> azertyKeys c <+> keys someConfig c }
azertyConfig = def { keys = azertyKeys <+> keys def }
@@ -46,3 +46,9 @@ azertyKeys conf@(XConfig {modMask = modm}) = M.fromList $
[((m .|. modm, k), windows $ f i)
| (i, k) <- zip (workspaces conf) [0x26,0xe9,0x22,0x27,0x28,0x2d,0xe8,0x5f,0xe7,0xe0],
(f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
++
-- mod-{z,e,r} %! Switch to physical/Xinerama screens 1, 2, or 3
-- mod-shift-{z,e,r} %! Move client to screen 1, 2, or 3
[((m .|. modm, key), screenWorkspace sc >>= flip whenJust (windows . f))
| (key, sc) <- zip [xK_z, xK_e, xK_r] [0..],
(f, m) <- [(W.view, 0), (W.shift, shiftMask)]]

View File

@@ -180,8 +180,7 @@ bluetileManageHook :: ManageHook
bluetileManageHook = composeAll
[ workspaceByPos, positionStoreManageHook (Just defaultThemeWithButtons)
, className =? "MPlayer" --> doFloat
, isFullscreen --> doFullFloat
, manageDocks]
, isFullscreen --> doFullFloat]
bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $ (
named "Floating" floating |||
@@ -199,6 +198,7 @@ bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $ (
floatingDeco l = buttonDeco shrinkText defaultThemeWithButtons l
bluetileConfig =
docks $
def
{ modMask = mod4Mask, -- logo key
manageHook = bluetileManageHook,

View File

@@ -164,10 +164,9 @@ import qualified Data.Map as M
-- > adjustEventInput
--
desktopConfig = ewmh def
{ startupHook = setDefaultCursor xC_left_ptr
desktopConfig = docks $ ewmh def
{ startupHook = setDefaultCursor xC_left_ptr <+> startupHook def
, layoutHook = desktopLayoutModifiers $ layoutHook def
, manageHook = manageHook def <+> manageDocks
, keys = desktopKeys <+> keys def }
desktopKeys (XConfig {modMask = modm}) = M.fromList $

View File

@@ -205,7 +205,7 @@ instance PPrint ScreenId
instance (Show a, Show b) => PPrint (Map a b)
-- }}}
-- main {{{
dmwitConfig nScreens = def {
dmwitConfig nScreens = docks $ def {
borderWidth = 2,
workspaces = withScreens nScreens (map show [1..5]),
terminal = "urxvt",
@@ -221,7 +221,6 @@ dmwitConfig nScreens = def {
<+> (appName =? "huludesktop" --> doRectFloat fullscreen43on169)
<+> fullscreenMPlayer
<+> floatAll ["Gimp", "Wine"]
<+> manageDocks
<+> manageSpawn,
logHook = allPPs nScreens,
startupHook = refresh

View File

@@ -42,7 +42,7 @@ import XMonad.Actions.DynamicWorkspaces ( withNthWorkspace, withWorkspace,
import XMonad.Actions.CycleWS ( moveTo, WSType( HiddenNonEmptyWS ),
Direction1D( Prev, Next) )
import XMonad.Hooks.ManageDocks ( avoidStruts, manageDocks )
import XMonad.Hooks.ManageDocks ( avoidStruts, docks )
import XMonad.Hooks.EwmhDesktops ( ewmh )
myXPConfig :: XPConfig
@@ -117,7 +117,7 @@ keys x = M.fromList $
++
zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..])
config = ewmh def
config = docks $ ewmh def
{ borderWidth = 1 -- Width of the window border in pixels.
, XMonad.workspaces = ["mutt","iceweasel"]
, layoutHook = showWName $ workspaceDir "~" $
@@ -129,7 +129,6 @@ config = ewmh def
named "widescreen" ((mytab *||* mytab)
****//* combineTwo Square mytab mytab) -- |||
--mosaic 0.25 0.5
, manageHook = manageHook def <+> manageDocks -- add panel-handling
, terminal = "xterm" -- The preferred terminal program.
, normalBorderColor = "#222222" -- Border color for unfocused windows.
, focusedBorderColor = "#00ff00" -- Border color for focused windows.

View File

@@ -18,7 +18,8 @@ module XMonad.Config.Gnome (
-- $usage
gnomeConfig,
gnomeRun,
gnomeRegister
gnomeRegister,
desktopLayoutModifiers
) where
import XMonad

View File

@@ -17,7 +17,8 @@ module XMonad.Config.Kde (
-- * Usage
-- $usage
kdeConfig,
kde4Config
kde4Config,
desktopLayoutModifiers
) where
import XMonad

View File

@@ -20,7 +20,8 @@ module XMonad.Config.Mate (
-- $usage
mateConfig,
mateRun,
mateRegister
mateRegister,
desktopLayoutModifiers
) where
import XMonad

View File

@@ -21,7 +21,7 @@ import XMonad.Layout.TwoPane
import qualified Data.Map as M
sjanssenConfig =
ewmh $ def
docks $ ewmh $ def
{ terminal = "exec urxvt"
, workspaces = ["irc", "web"] ++ map show [3 .. 9 :: Int]
, mouseBindings = \(XConfig {modMask = modm}) -> M.fromList $
@@ -35,7 +35,7 @@ sjanssenConfig =
| (x, w) <- [ ("Firefox", "web")
, ("Ktorrent", "7")
, ("Amarokapp", "7")]]
<+> manageHook def <+> manageDocks <+> manageSpawn
<+> manageHook def <+> manageSpawn
<+> (isFullscreen --> doFullFloat)
, startupHook = mapM_ spawnOnce spawns
}

View File

@@ -16,7 +16,8 @@
module XMonad.Config.Xfce (
-- * Usage
-- $usage
xfceConfig
xfceConfig,
desktopLayoutModifiers
) where
import XMonad

View File

@@ -116,6 +116,13 @@ beyond the standard keybindings provided by xmonad.
See "XMonad.Doc.Extending#Editing_key_bindings" for instructions on how to
edit your key bindings.
* "XMonad.Actions.AfterDrag":
Allows you to add actions dependent on the current mouse drag.
* "XMonad.Actions.BluetileCommands":
External commands for interfacing the [Bluetile](https://hackage.haskell.org/package/bluetile)
tiling window manager with Xmonad.
* "XMonad.Actions.Commands":
Allows you to run internal xmonad commands (X () actions) using
a dmenu menu in addition to key bindings. Requires dmenu and
@@ -159,6 +166,20 @@ edit your key bindings.
master, swap it with the next window in the stack. Focus stays in the
master.
* "XMonad.Actions.DynamicProjects":
Imbues workspaces with additional features so they can be treated as
individual project areas.
* "XMonad.Actions.DynamicWorkspaceGroups":
Dynamically manage "workspace groups", sets of workspaces being used
together for some common task or purpose, to allow switching between
workspace groups in a single action. Note that this only makes sense for
multi-head setups.
* "XMonad.Actions.DynamicWorkspaceOrder":
Remember a dynamically updateable ordering on workspaces, together with
tools for using this ordering with "XMonad.Actions.CycleWS" and "XMonad.Hooks.DynamicLog".
* "XMonad.Actions.DynamicWorkspaces":
Provides bindings to add and delete workspaces. Note that you may only
delete a workspace that is already empty.
@@ -186,6 +207,24 @@ edit your key bindings.
GridSelect displays items(e.g. the opened windows) in a 2D grid and lets
the user select from it with the cursor/hjkl keys or the mouse.
* "XMonad.Actions.GroupNavigation":
Provides methods for cycling through groups of windows across workspaces,
ignoring windows that do not belong to this group. A group consists of all
windows matching a user-provided boolean query. Also provides a method for
jumping back to the most recently used window in any given group.
* "XMonad.Actions.KeyRemap":
Remap Keybinding on the fly, e.g having Dvorak char,
but everything with Control/Shift is left US Layout.
* "XMonad.Actions.Launcher":
A set of prompts for XMonad.
* "XMonad.Actions.LinkWorkspaces":
Provides bindings to add and delete links between workspaces. It is aimed at
providing useful links between workspaces in a multihead setup.
Linked workspaces are view at the same time.
* "XMonad.Actions.MessageFeedback":
Alternative to 'XMonad.Operations.sendMessage' that provides knowledge
of whether the message was handled, and utility functions based on
@@ -198,6 +237,10 @@ edit your key bindings.
A layout modifier to resize windows with the mouse by grabbing the
window's lower right corner.
* "XMonad.Actions.Navigation2D":
Navigation2D is an xmonad extension that allows easy directional navigation
of windows and screens (in a multi-monitor setup).
* "XMonad.Actions.NoBorders":
This module provides helper functions for dealing with window borders.
@@ -228,6 +271,10 @@ edit your key bindings.
A module for easily running Internet searches on web sites through xmonad.
Modeled after the handy Surfraw CLI search tools at <https://secure.wikimedia.org/wikipedia/en/wiki/Surfraw>.
* "XMonad.Actions.ShowText":
ShowText displays text for sometime on the screen similar to
"XMonad.Util.Dzen" which offers more features (currently).
* "XMonad.Actions.SimpleDate":
An example external contrib module for XMonad.
Provides a simple binding to dzen2 to print the date as a popup menu.
@@ -254,6 +301,12 @@ edit your key bindings.
* "XMonad.Actions.TopicSpace":
Turns your workspaces into a more topic oriented system.
* "XMonad.Actions.TreeSelect":
TreeSelect displays your workspaces or actions in a Tree-like format.
You can select the desired workspace/action with the cursor or hjkl keys.
This module is fully configurable and very useful if you like to have a
lot of workspaces.
* "XMonad.Actions.UpdateFocus":
Updates the focus on mouse move in unfocused windows.
@@ -283,9 +336,23 @@ edit your key bindings.
Provides functions for performing a given action on all windows of
the current workspace.
* "XMonad.Actions.Workscreen":
A workscreen permits to display a set of workspaces on several screens. In
xinerama mode, when a workscreen is viewed, workspaces associated to all
screens are visible. The first workspace of a workscreen is displayed on
first screen, second on second screen, etc. Workspace position can be easily
changed. If the current workscreen is called again, workspaces are shifted.
This also permits to see all workspaces of a workscreen even if just one screen
is present, and to move windows from workspace to workscreen.
* "XMonad.Actions.WorkspaceCursors":
Like "XMonad.Actions.Plane" for an arbitrary number of dimensions.
* "XMonad.Actions.WorkspaceNames":
Provides bindings to rename workspaces, show these names in DynamicLog and
swap workspaces along with their names. These names survive restart. Together
with "XMonad.Layout.WorkspaceDir" this provides for a fully dynamic topic
space workflow.
-}
{- $configs
@@ -297,25 +364,56 @@ configuration; you can also simply import them and use them as your
own configuration, possibly with some modifications.
* "XMonad.Config.Arossato"
* "XMonad.Config.Arossato":
This module specifies my xmonad defaults.
* "XMonad.Config.Azerty"
* "XMonad.Config.Azerty":
Fixes some keybindings for users of French keyboard layouts.
* "XMonad.Config.Desktop"
* "XMonad.Config.Bepo":
This module fixes some of the keybindings for the francophone among you who
use a BEPO keyboard layout. Based on "XMonad.Config.Azerty".
* "XMonad.Config.Bluetile":
This is the default configuration of [Bluetile](http://projects.haskell.org/bluetile/).
If you are migrating from Bluetile to xmonad or want to create a similar setup,
then this will give you pretty much the same thing, except for Bluetile's
helper applications such as the dock.
* "XMonad.Config.Desktop":
This module provides core desktop environment settings used
in the Gnome, Kde, and Xfce config configs. It is also useful
for people using other environments such as lxde, or using
tray or panel applications without full desktop environments.
* "XMonad.Config.Gnome"
* "XMonad.Config.Dmwit":
[dmwit](https://github.com/dmwit)'s xmonad configs and helpers.
* "XMonad.Config.Kde"
* "XMonad.Config.Droundy":
Droundy's xmonad config.
* "XMonad.Config.Sjanssen"
* "XMonad.Config.Gnome":
This module provides a config suitable for use with the GNOME desktop environment.
* "XMonad.Config.Xfce"
* "XMonad.Config.Kde":
This module provides a config suitable for use with the KDE desktop environment.
* "XMonad.Config.Mate":
This module provides a config suitable for use with the MATE desktop environment.
* "XMonad.Config.Prime":
This is a draft of a brand new config syntax for xmonad. It aims to be
1) easier to copy/paste snippets from the docs 2) easier to get the gist
for what's going on, for you imperative programmers. It's brand new, so it's
pretty much guaranteed to break or change syntax. But what's the worst that
could happen? Xmonad crashes and logs you out? It probably won't do that.
Give it a try.
* "XMonad.Config.Sjanssen":
[spencerjanssen](https://github.com/spencerjanssen)'s xmonad configs.
* "XMonad.Config.Xfce":
This module provides a config suitable for use with the Xfce desktop environment.
-}
@@ -349,6 +447,29 @@ occur. The two most important hooks are:
Here is a list of the modules found in @XMonad.Hooks@:
* "XMonad.Hooks.CurrentWorkspaceOnTop":
Ensures that the windows of the current workspace are always in front of
windows that are located on other visible screens. This becomes important if
you use decoration and drag windows from one screen to another.
Using this module, the dragged window will always be in front of other windows.
* "XMonad.Hooks.DebugEvents":
Module to dump diagnostic information about X11 events received by xmonad.
This is incomplete due to "Event" being incomplete and not providing
information about a number of events, and enforcing artificial constraints
on others (for example ClientMessage); the X11 package will require a number
of changes to fix these problems.
* "XMonad.Hooks.DebugKeyEvents":
A debugging module to track key events, useful when you can't tell whether
xmonad is processing some or all key events.
* "XMonad.Hooks.DebugStack":
Dump the state of the StackSet. A logHook and handleEventHook are also provided.
* "Xmonad.Hooks.DynamicBars":
Manage per-screen status bars.
* "XMonad.Hooks.DynamicHooks":
One-shot and permanent ManageHooks that can be updated at runtime.
@@ -367,14 +488,28 @@ Here is a list of the modules found in @XMonad.Hooks@:
which causes those windows to become slightly translucent if something
like xcompmgr is running
* "XMonad.Hooks.FadeWindows":
A more flexible and general compositing interface than FadeInactive. Windows
can be selected and opacity specified by means of FadeHooks, which are very
similar to ManageHooks and use the same machinery.
* "XMonad.Hooks.FloatNext":
Hook and keybindings for automatically sending the next
spawned window(s) to the floating layer.
* "XMonad.Hooks.ICCCMFocus":
Deprecated.
* "XMonad.Hooks.InsertPosition":
Configure where new windows should be added and which window should be
focused.
* "XMonad.Hooks.ManageDebug":
A manageHook and associated logHook for debugging "ManageHooks". Simplest
usage: wrap your xmonad config in the debugManageHook combinator. Or use
debugManageHookOn for a triggerable version, specifying the triggering key
sequence in "EZConfig" syntax. Or use the individual hooks in whatever way you see fit.
* "XMonad.Hooks.ManageDocks":
This module provides tools to automatically manage 'dock' type programs,
such as gnome-panel, kicker, dzen, and xmobar.
@@ -389,35 +524,54 @@ Here is a list of the modules found in @XMonad.Hooks@:
* "XMonad.Hooks.Place":
Automatic placement of floating windows.
* "XMonad.Hooks.PositionStoreHooks":
This module contains two hooks for the PositionStore (see XMonad.Util.PositionStore) -
a ManageHook and an EventHook. The ManageHook can be used to fill the
PositionStore with position and size information about new windows. The advantage
of using this hook is, that the information is recorded independent of the
currently active layout. So the floating shape of the window can later be restored
even if it was opened in a tiled layout initially. The EventHook makes sure
that windows are deleted from the PositionStore when they are closed.
* "XMonad.Hooks.RestoreMinimized":
(Deprecated: Use XMonad.Hooks.Minimize) Lets you restore minimized
windows (see "XMonad.Layout.Minimize") by selecting them on a
taskbar (listens for _NET_ACTIVE_WINDOW and WM_CHANGE_STATE).
* "XMonad.Hooks.ScreenCorners":
Run X () actions by touching the edge of your screen with your mouse.
* "XMonad.Hooks.Script":
Provides a simple interface for running a ~\/.xmonad\/hooks script with the
name of a hook.
* "XMonad.Hooks.ServerMode": Allows sending commands to a running xmonad process.
* "XMonad.Hooks.SetCursor":
Set a default mouse cursor on startup.
* "XMonad.Hooks.ServerMode":
Allows sending commands to a running xmonad process.
* "XMonad.Hooks.SetWMName":
Sets the WM name to a given string, so that it could be detected using
_NET_SUPPORTING_WM_CHECK protocol. May be useful for making Java GUI
programs work.
* "XMonad.Hooks.ToggleHook":
Hook and keybindings for toggling hook behavior.
* "XMonad.Hooks.UrgencyHook":
UrgencyHook lets you configure an action to occur when a window demands
your attention. (In traditional WMs, this takes the form of \"flashing\"
on your \"taskbar.\" Blech.)
* "XMonad.Hooks.WallpaperSetter":
Log hook which changes the wallpapers depending on visible workspaces.
* "XMonad.Hooks.WorkspaceByPos":
Useful in a dual-head setup: Looks at the requested geometry of
new windows and moves them to the workspace of the non-focused
screen if necessary.
* "XMonad.Hooks.WorkspaceHistory":
Keeps track of workspace viewing order.
* "XMonad.Hooks.XPropManage":
A ManageHook matching on XProperties.
@@ -450,6 +604,13 @@ For more information on using those modules for customizing your
master and slave. Size of slave area automatically changes depending on
number of slave windows.
* "XMonad.Layout.AvoidFloats":
Find a maximum empty rectangle around floating windows and use that area to
display non-floating windows.
* "XMonad.Layout.BinarySpacePartition":
Layout where new windows will split the focused window in half, based off of BSPWM.
* "XMonad.Layout.BorderResize":
This layout modifier will allow to resize windows by dragging their
borders with the mouse. However, it only works in layouts or modified
@@ -460,6 +621,11 @@ For more information on using those modules for customizing your
* "XMonad.Layout.BoringWindows":
BoringWindows is an extension to allow windows to be marked boring
* "XMonad.Layout.ButtonDecoration":
A decoration that includes small buttons on both ends which invoke various
actions when clicked on: Show a window menu (see "XMonad.Actions.WindowMenu"),
minimize, maximize or close the window.
* "XMonad.Layout.CenteredMaster":
Two layout modifiers. centerMaster places master window at center,
on top of all other windows, which are managed by base layout.
@@ -488,6 +654,11 @@ For more information on using those modules for customizing your
A layout modifier and a class for easily creating decorated
layouts.
* "XMonad.Layout.DecorationAddons":
Various stuff that can be added to the decoration. Most of it is intended to
be used by other modules. See "XMonad.Layout.ButtonDecoration" for a module
that makes use of this.
* "XMonad.Layout.DecorationMadness":
A collection of decorated layouts: some of them may be nice, some
usable, others just funny.
@@ -502,6 +673,24 @@ For more information on using those modules for customizing your
the other is either the currently focused window or the second window in
layout order. See also "XMonad.Layout.MouseResizableTall"
* "XMonad.Layout.DraggingVisualizer":
A helper module to visualize the process of dragging a window by making it
follow the mouse cursor. See "XMonad.Layout.WindowSwitcherDecoration" for a
module that makes use of this.
* "XMonad.Layout.Drawer":
A layout modifier that puts some windows in a "drawer" which retracts and
expands depending on whether any window in it has focus. Useful for music
players, tool palettes, etc.
* "XMonad.Layout.Dwindle":
Three layouts: The first, Spiral, is a reimplementation of spiral with, at
least to me, more intuitive semantics. The second, Dwindle, is inspired by
a similar layout in awesome and produces the same sequence of decreasing
window sizes as Spiral but pushes the smallest windows into a screen corner
rather than the centre. The third, Squeeze arranges all windows in one row
or in one column, with geometrically decreasing sizes.
* "XMonad.Layout.DwmStyle":
A layout modifier for decorating windows in a dwm like style.
@@ -511,6 +700,10 @@ For more information on using those modules for customizing your
split. This is useful when you usually leave a text editor or
terminal in the master pane and like it to be 80 columns wide.
* "XMonad.Layout.Fullscreen":
Hooks for sending messages about fullscreen windows to layouts, and a few
example layout modifier that implement fullscreen windows.
* "XMonad.Layout.Gaps":
Create manually-sized gaps along edges of the screen which will not
be used for tiling, along with support for toggling gaps on and
@@ -526,6 +719,25 @@ For more information on using those modules for customizing your
master area and uses an aspect-ratio-specified layout for the
slaves.
* "XMonad.Layout.Groups":
Two-level layout with windows split in individual layout groups, themselves
managed by a user-provided layout.
* * "XMonad.Layout.Groups.Examples":
Example layouts for "XMonad.Layout.Groups".
* * "XMonad.Layout.Groups.Helpers":
Utility functions for "XMonad.Layout.Groups".
* * "XMonad.Layout.Groups.Wmii":
A wmii-like layout algorithm.
* "XMonad.Layout.Hidden":
Similar to XMonad.Layout.Minimize but completely removes windows from the
window set so XMonad.Layout.BoringWindows isn't necessary. Perfect companion
to XMonad.Layout.BinarySpacePartition since it can be used to move windows
to another part of the BSP tree.
* "XMonad.Layout.HintedGrid":
A not so simple layout that attempts to put all windows in a square grid
while obeying their size hints.
@@ -538,6 +750,16 @@ For more information on using those modules for customizing your
Layout modfier suitable for workspace with multi-windowed instant messenger
(like Psi or Tkabber).
* "XMonad.Layout.IfMax":
Provides IfMax layout, which will run one layout if there are maximum N
windows on workspace, and another layout, when number of windows is greater
than N.
* "XMonad.Layout.ImageButtonDecoration":
A decoration that includes small image buttons on both ends which invoke
various actions when clicked on: Show a window menu (see "XMonad.Actions.WindowMenu"),
minimize, maximize or close the window.
* "XMonad.Layout.IndependentScreens":
Utility functions for simulating independent sets of workspaces on
each screen (like dwm's workspace model), using internal tags to
@@ -613,12 +835,19 @@ For more information on using those modules for customizing your
A layout in the spirit of "XMonad.Layout.ResizableTile", but with the option
to use the mouse to adjust the layout.
* "XMonad.Layout.MultiColumns":
This layout tiles windows in a growing number of columns. The number of
windows in each column can be controlled by messages.
* "XMonad.Layout.MultiToggle":
Dynamically apply and unapply transformers to your window layout. This can
be used to rotate your window layout by 90 degrees, or to make the
currently focused window occupy the whole screen (\"zoom in\") then undo
the transformation (\"zoom out\").
* * "XMonad.Layout.MultiToggle.Instances":
Some convenient common instances of the Transformer class, for use with "XMonad.Layout.MultiToggle".
* "XMonad.Layout.Named":
A module for assigning a name to a given layout.
@@ -634,17 +863,38 @@ For more information on using those modules for customizing your
result in title bars that span the entire window instead of being only the
length of the window title.
* "XMonad.Layout.OnHost":
Configure layouts on a per-host basis: use layouts and apply layout modifiers
selectively, depending on the host. Heavily based on "XMonad.Layout.PerWorkspace"
by Brent Yorgey.
* "XMonad.Layout.OneBig":
Places one (master) window at top left corner of screen, and other (slave)
windows at the top.
* "XMonad.Layout.PerScreen":
Configure layouts based on the width of your screen; use your favorite
multi-column layout for wide screens and a full-screen layout for small ones.
* "XMonad.Layout.PerWorkspace":
Configure layouts on a per-workspace basis: use layouts and apply
layout modifiers selectively, depending on the workspace.
* "XMonad.Layout.PositionStoreFloat":
A floating layout which has been designed with a dual-head setup in mind.
It makes use of "XMonad.Util.PositionStore" as well as "XMonad.Hooks.PositionStoreHooks".
Since there is currently no way to move or resize windows with the keyboard
alone in this layout, it is adviced to use it in combination with a decoration
such as "XMonad.Layout.NoFrillsDecoration" (to move windows) and the layout
modifier "XMonad.Layout.BorderResize" (to resize windows).
* "XMonad.Layout.Reflect":
Reflect a layout horizontally or vertically.
* "XMonad.Layout.Renamed":
Layout modifier that can modify the description of its underlying layout on
a (hopefully) flexible way.
* "XMonad.Layout.ResizableTile":
More useful tiled layout that allows you to change a width\/height of window.
See also "XMonad.Layout.MouseResizableTile".
@@ -676,6 +926,12 @@ For more information on using those modules for customizing your
* "XMonad.Layout.SimplestFloat":
A basic floating layout like SimpleFloat but without the decoration.
* "XMonad.Layout.SortedLayout":
A new LayoutModifier that sorts a given layout by a list of
properties. The order of properties in the list determines
the order of windows in the final layout. Any unmatched windows
go to the end of the order.
* "XMonad.Layout.Spacing":
Add a configurable amount of space around windows.
@@ -694,6 +950,13 @@ For more information on using those modules for customizing your
A stacking layout, like dishes but with the ability to resize master pane.
Mostly useful on small screens.
* "XMonad.Layout.Stoppable":
This module implements a special kind of layout modifier, which when applied
to a layout, causes xmonad to stop all non-visible processes. In a way,
this is a sledge-hammer for applications that drain power. For example, given
a web browser on a stoppable workspace, once the workspace is hidden the web
browser will be stopped.
* "XMonad.Layout.SubLayouts":
A layout combinator that allows layouts to be nested.
@@ -724,6 +987,10 @@ For more information on using those modules for customizing your
WindowNavigation is an extension to allow easy navigation of a workspace.
See also "XMonad.Actions.WindowNavigation".
* "XMonad.Layout.WindowSwitcherDecoration":
A decoration that allows to switch the position of windows by dragging them
onto each other.
* "XMonad.Layout.WorkspaceDir":
WorkspaceDir is an extension to set the current directory in a workspace.
Actually, it sets the current directory in a layout, since there's no way I
@@ -757,6 +1024,9 @@ These are the available prompts:
you're doing.
Who knows, it might be useful for other purposes as well!
* "XMonad.Prompt.ConfirmPrompt":
A module for setting up simple confirmation prompts for keybindings.
* "XMonad.Prompt.DirExec":
A directory file executables prompt for XMonad. This might be useful if you
don't want to have scripts in your PATH environment variable (same
@@ -786,6 +1056,13 @@ These are the available prompts:
* narrow completions by section number, if the one is specified
(like @\/etc\/bash_completion@ does)
* "XMonad.Prompt.Pass":
This module provides 3 combinators for ease passwords manipulation (generate, read, remove):
1) one to lookup passwords in the password-storage.
2) one to generate a password for a given password label that the user inputs.
3) one to delete a stored password for a given password label that the user inputs.
* "XMonad.Prompt.RunOrRaise":
A prompt for XMonad which will run a program, open a file,
or raise an already running program, depending on context.
@@ -830,6 +1107,10 @@ A non complete list with a brief description:
* "XMonad.Util.CustomKeys": configure key bindings (see
"XMonad.Doc.Extending#Editing_key_bindings").
* "XMonad.Util.DebugWindow":
Module to dump window information for diagnostic/debugging purposes. See
"XMonad.Hooks.DebugEvents" and "XMonad.Hooks.DebugStack" for practical uses.
* "XMonad.Util.Dmenu":
A convenient binding to dmenu.
Requires the process-1.0 package
@@ -837,11 +1118,19 @@ A non complete list with a brief description:
* "XMonad.Util.Dzen":
Handy wrapper for dzen. Requires dzen >= 0.2.4.
* "XMonad.Util.EZConfig": configure key bindings easily, including a
parser for writing key bindings in "M-C-x" style.
* "XMonad.Util.EZConfig":
Configure key bindings easily, including a
parser for writing key bindings in "M-C-x" style.
* "XMonad.Util.Font": A module for abstracting a font facility over
Core fonts and Xft
* "XMonad.Util.ExtensibleState":
Module for storing custom mutable state in xmonad.
* "XMonad.Util.Font":
A module for abstracting a font facility over
Core fonts and Xft.
* "XMonad.Util.Image":
Utilities for manipulating [[Bool]] as images.
* "XMonad.Util.Invisible":
A data type to store the layout state
@@ -852,6 +1141,10 @@ A non complete list with a brief description:
a pretty-printing status logger format. See "XMonad.Hooks.DynamicLog"
for more information.
* * "XMonad.Util.Loggers.NamedScratchpad":
A collection of Loggers (see "XMonad.Util.Loggers") for NamedScratchpads
(see "XMonad.Util.NamedScratchpad").
* "XMonad.Util.NamedActions":
A wrapper for keybinding configuration that can list the available
keybindings.
@@ -864,10 +1157,22 @@ A non complete list with a brief description:
This module allows you to associate the X titles of windows with
them.
* "XMonad.Util.NoTaskbar":
Utility function and 'ManageHook` to mark a window to be ignored by
EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since
you will usually be taken to the `NSP` workspace by them.
* "XMonad.Util.Paste":
A module for sending key presses to windows. This modules provides generalized
and specialized functions for this task.
* "XMonad.Util.PositionStore":
A utility module to store information about position and size of a window.
See "XMonad.Layout.PositionStoreFloat" for a layout that makes use of this.
* "XMonad.Util.RemoteWindows":
This module implements a proper way of finding out whether the window is remote or local.
* "XMonad.Util.Replace":
Implements a @--replace@ flag outside of core.
@@ -880,6 +1185,16 @@ A non complete list with a brief description:
* "XMonad.Util.Scratchpad":
Very handy hotkey-launched toggleable floating terminal window.
* "XMonad.Util.SpawnNamedPipe":
A module for spawning a pipe whose Handle lives in the Xmonad state.
* "XMonad.Util.SpawnOnce":
A module for spawning a command once, and only once. Useful to start status
bars and make session settings inside startupHook.
* "XMonad.Util.Stack":
Utility functions for manipulating Maybe Stacks.
* "XMonad.Util.StringProp":
Internal utility functions for storing Strings with the root window.
Used for global state like IORefs with string keys, but more latency,
@@ -894,10 +1209,21 @@ A non complete list with a brief description:
* "XMonad.Util.Types":
Miscellaneous commonly used types.
* "XMonad.Util.Ungrab":
Release xmonad's keyboard and pointer grabs immediately, so
screen grabbers and lock utilities, etc. will work. Replaces
the short sleep hackaround.
* "XMonad.Util.WindowProperties":
EDSL for specifying window properties; various utilities related to window
properties.
* "XMonad.Util.WindowState":
Functions for saving per-window data.
* "XMonad.Util.WorkspaceCompare":
Functions for examining, comparing, and sorting workspaces.
* "XMonad.Util.XSelection":
A module for accessing and manipulating X Window's mouse selection (the buffer used in copy and pasting).
'getSelection' and 'putSelection' are adaptations of Hxsel.hs and Hxput.hs from the XMonad-utils

View File

@@ -18,9 +18,13 @@ module XMonad.Hooks.DynamicBars (
-- $usage
DynamicStatusBar
, DynamicStatusBarCleanup
, DynamicStatusBarPartialCleanup
, dynStatusBarStartup
, dynStatusBarStartup'
, dynStatusBarEventHook
, dynStatusBarEventHook'
, multiPP
, multiPPFormat
) where
import Prelude
@@ -29,9 +33,10 @@ import Control.Monad
import Control.Monad.Trans (lift)
import Control.Monad.Writer (WriterT, execWriterT, tell)
import Data.List
import Data.Maybe
import Data.Monoid
import Data.Traversable (traverse)
import Data.Foldable (traverse_)
import Graphics.X11.Xinerama
import Graphics.X11.Xlib
@@ -50,13 +55,28 @@ import qualified XMonad.Util.ExtensibleState as XS
-- dynamically responding to screen changes. A startup action, event hook, and
-- a way to separate PP styles based on the screen's focus are provided:
--
-- * The 'dynStatusBarStartup' hook which initializes the status bars.
-- * The 'dynStatusBarStartup' hook which initializes the status bars. The
-- first argument is an `ScreenId -> IO Handle` which spawns a status bar on the
-- given screen and returns the pipe which the string should be written to.
-- The second argument is a `IO ()` to shut down all status bars. This should
-- be placed in your `startupHook`.
--
-- * The 'dynStatusBarEventHook' hook which respawns status bars when the
-- number of screens changes.
-- number of screens changes. The arguments are the same as for the
-- `dynStatusBarStartup` function. This should be placed in your
-- `handleEventHook`.
--
-- * Each of the above functions have an alternate form
-- (`dynStatusBarStartup'` and `dynStatusBarEventHook'`) which use a cleanup
-- function which takes an additional `ScreenId` argument which allows for
-- more fine-grained control for shutting down a specific screen's status bar.
--
-- * The 'multiPP' function which allows for different output based on whether
-- the screen for the status bar has focus.
-- the screen for the status bar has focus (the first argument) or not (the
-- second argument). This is for use in your `logHook`.
--
-- * The 'multiPPFormat' function is the same as the 'multiPP' function, but it
-- also takes in a function that can customize the output to status bars.
--
-- The hooks take a 'DynamicStatusBar' function which is given the id of the
-- screen to start up and returns the 'Handle' to the pipe to write to. The
@@ -65,37 +85,67 @@ import qualified XMonad.Util.ExtensibleState as XS
--
data DynStatusBarInfo = DynStatusBarInfo
{ dsbInfoScreens :: [ScreenId]
, dsbInfoHandles :: [Handle]
{ dsbInfo :: [(ScreenId, Handle)]
} deriving (Typeable)
instance ExtensionClass DynStatusBarInfo where
initialValue = DynStatusBarInfo [] []
initialValue = DynStatusBarInfo []
type DynamicStatusBar = ScreenId -> IO Handle
type DynamicStatusBarCleanup = IO ()
type DynamicStatusBarPartialCleanup = ScreenId -> IO ()
dynStatusBarStartup :: DynamicStatusBar -> DynamicStatusBarCleanup -> X ()
dynStatusBarStartup sb cleanup = do
dynStatusBarSetup :: X ()
dynStatusBarSetup = do
dpy <- asks display
root <- asks theRoot
io $ xrrSelectInput dpy root rrScreenChangeNotifyMask
dynStatusBarStartup :: DynamicStatusBar -> DynamicStatusBarCleanup -> X ()
dynStatusBarStartup sb cleanup = do
dynStatusBarSetup
updateStatusBars sb cleanup
dynStatusBarStartup' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> X ()
dynStatusBarStartup' sb cleanup = do
dynStatusBarSetup
updateStatusBars' sb cleanup
dynStatusBarEventHook :: DynamicStatusBar -> DynamicStatusBarCleanup -> Event -> X All
dynStatusBarEventHook sb cleanup (RRScreenChangeNotifyEvent {}) = updateStatusBars sb cleanup >> return (All True)
dynStatusBarEventHook _ _ _ = return (All True)
dynStatusBarEventHook sb cleanup = dynStatusBarRun (updateStatusBars sb cleanup)
dynStatusBarEventHook' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> Event -> X All
dynStatusBarEventHook' sb cleanup = dynStatusBarRun (updateStatusBars' sb cleanup)
dynStatusBarRun :: X () -> Event -> X All
dynStatusBarRun action (RRScreenChangeNotifyEvent {}) = action >> return (All True)
dynStatusBarRun _ _ = return (All True)
updateStatusBars :: DynamicStatusBar -> DynamicStatusBarCleanup -> X ()
updateStatusBars sb cleanup = do
dsbInfo <- XS.get
(dsbInfoScreens, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo
screens <- getScreens
when (screens /= dsbInfoScreens dsbInfo) $ do
when (screens /= dsbInfoScreens) $ do
newHandles <- liftIO $ do
hClose `mapM_` dsbInfoHandles dsbInfo
hClose `mapM_` dsbInfoHandles
cleanup
mapM sb screens
XS.put $ DynStatusBarInfo screens newHandles
XS.put $ DynStatusBarInfo (zip screens newHandles)
updateStatusBars' :: DynamicStatusBar -> DynamicStatusBarPartialCleanup -> X ()
updateStatusBars' sb cleanup = do
(dsbInfoScreens, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo
screens <- getScreens
when (screens /= dsbInfoScreens) $ do
let oldInfo = zip dsbInfoScreens dsbInfoHandles
let (infoToKeep, infoToClose) = partition (flip elem screens . fst) oldInfo
newInfo <- liftIO $ do
mapM_ hClose $ map snd infoToClose
mapM_ cleanup $ map fst infoToClose
let newScreens = screens \\ dsbInfoScreens
newHandles <- mapM sb newScreens
return $ zip newScreens newHandles
XS.put . DynStatusBarInfo $ infoToKeep ++ newInfo
-----------------------------------------------------------------------------
-- The following code is from adamvo's xmonad.hs file.
@@ -104,9 +154,12 @@ updateStatusBars sb cleanup = do
multiPP :: PP -- ^ The PP to use if the screen is focused
-> PP -- ^ The PP to use otherwise
-> X ()
multiPP focusPP unfocusPP = do
dsbInfo <- XS.get
multiPP' dynamicLogString focusPP unfocusPP (dsbInfoHandles dsbInfo)
multiPP = multiPPFormat dynamicLogString
multiPPFormat :: (PP -> X String) -> PP -> PP -> X ()
multiPPFormat dynlStr focusPP unfocusPP = do
(_, dsbInfoHandles) <- XS.get >>= return . unzip . dsbInfo
multiPP' dynlStr focusPP unfocusPP dsbInfoHandles
multiPP' :: (PP -> X String) -> PP -> PP -> [Handle] -> X ()
multiPP' dynlStr focusPP unfocusPP handles = do
@@ -118,10 +171,9 @@ multiPP' dynlStr focusPP unfocusPP handles = do
out <- lift $ dynlStr $ if isFoc then focusPP else unfocusPP
when isFoc $ get >>= tell . Last . Just
return out
traverse put . getLast
traverse_ put . getLast
=<< execWriterT . (io . zipWithM_ hPutStrLn handles <=< mapM pickPP) . catMaybes
=<< mapM screenWorkspace (zipWith const [0 .. ] handles)
return ()
getScreens :: MonadIO m => m [ScreenId]
getScreens = liftIO $ do

View File

@@ -199,12 +199,11 @@ statusBar :: LayoutClass l Window
-> IO (XConfig (ModifiedLayout AvoidStruts l))
statusBar cmd pp k conf = do
h <- spawnPipe cmd
return $ conf
return $ docks $ conf
{ layoutHook = avoidStruts (layoutHook conf)
, logHook = do
logHook conf
dynamicLogWithPP pp { ppOutput = hPutStrLn h }
, manageHook = manageHook conf <+> manageDocks
, keys = liftM2 M.union keys' (keys conf)
}
where

View File

@@ -47,7 +47,7 @@ import XMonad.Util.WindowProperties (getProp32)
-- > main = xmonad $ ewmh def{ handleEventHook =
-- > handleEventHook def <+> fullscreenEventHook }
--
-- You may also be interested in 'avoidStruts' from "XMonad.Hooks.ManageDocks".
-- You may also be interested in 'docks' from "XMonad.Hooks.ManageDocks".
-- | Add EWMH functionality to the given config. See above for an example.

View File

@@ -15,8 +15,8 @@
module XMonad.Hooks.ManageDocks (
-- * Usage
-- $usage
manageDocks, checkDock, AvoidStruts, avoidStruts, avoidStrutsOn,
docksEventHook,
docks, manageDocks, checkDock, AvoidStruts, avoidStruts, avoidStrutsOn,
docksEventHook, docksStartupHook,
ToggleStruts(..),
SetStruts(..),
module XMonad.Util.Types,
@@ -39,34 +39,29 @@ import XMonad.Layout.LayoutModifier
import XMonad.Util.Types
import XMonad.Util.WindowProperties (getProp32s)
import XMonad.Util.XUtils (fi)
import qualified XMonad.Util.ExtensibleState as XS
import Data.Monoid (All(..), mempty)
import Data.Functor((<$>))
import qualified Data.Set as S
import qualified Data.Map as M
import Control.Monad (when, forM_, filterM)
-- $usage
-- To use this module, add the following import to @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Hooks.ManageDocks
--
-- The first component is a 'ManageHook' which recognizes these
-- windows and de-manages them, so that xmonad does not try to tile
-- them. To enable it:
-- Wrap your xmonad config with a call to 'docks', like so:
--
-- > manageHook = ... <+> manageDocks
-- > main = xmonad $ docks def
--
-- The second component is a layout modifier that prevents windows
-- from overlapping these dock windows. It is intended to replace
-- xmonad's so-called \"gap\" support. First, you must add it to your
-- list of layouts:
-- Then add 'avoidStruts' or 'avoidStrutsOn' layout modifier to your layout
-- to prevent windows from overlapping these windows.
--
-- > layoutHook = avoidStruts (tall ||| mirror tall ||| ...)
-- > where tall = Tall 1 (3/100) (1/2)
--
-- The third component is an event hook that causes new docks to appear
-- immediately, instead of waiting for the next focus change.
--
-- > handleEventHook = ... <+> docksEventHook
--
-- 'AvoidStruts' also supports toggling the dock gaps; add a keybinding
-- similar to:
--
@@ -86,23 +81,43 @@ import qualified Data.Set as S
--
-- > layoutHook = avoidStrutsOn [U,L] (tall ||| mirror tall ||| ...)
--
-- /Important note/: if you are switching from manual gaps
-- (defaultGaps in your config) to avoidStruts (recommended, since
-- manual gaps will probably be phased out soon), be sure to switch
-- off all your gaps (with mod-b) /before/ reloading your config with
-- avoidStruts! Toggling struts with a 'ToggleStruts' message will
-- not work unless your gaps are set to zero.
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
--
-- | Add docks functionality to the given config. See above for an example.
docks :: XConfig a -> XConfig a
docks c = c { startupHook = docksStartupHook <+> startupHook c
, handleEventHook = docksEventHook <+> handleEventHook c
, manageHook = manageDocks <+> manageHook c }
newtype StrutCache = StrutCache { fromStrutCache :: M.Map Window [Strut] }
deriving (Eq, Typeable)
data UpdateDocks = UpdateDocks deriving Typeable
instance Message UpdateDocks
refreshDocks :: X ()
refreshDocks = sendMessage UpdateDocks
instance ExtensionClass StrutCache where
initialValue = StrutCache M.empty
updateStrutCache :: Window -> [Strut] -> X Bool
updateStrutCache w strut = do
XS.modified $ StrutCache . M.insert w strut . fromStrutCache
deleteFromStructCache :: Window -> X Bool
deleteFromStructCache w = do
XS.modified $ StrutCache . M.delete w . fromStrutCache
-- | Detects if the given window is of type DOCK and if so, reveals
-- it, but does not manage it.
manageDocks :: ManageHook
manageDocks = checkDock --> (doIgnore <+> clearGapCache)
where clearGapCache = do
liftX (broadcastMessage ClearGapCache)
manageDocks = checkDock --> (doIgnore <+> setDocksMask)
where setDocksMask = do
ask >>= \win -> liftX $ withDisplay $ \dpy -> do
io $ selectInput dpy win (propertyChangeMask .|. structureNotifyMask)
mempty
-- | Checks if a window is a DOCK or DESKTOP window
@@ -118,13 +133,35 @@ checkDock = ask >>= \w -> liftX $ do
-- | Whenever a new dock appears, refresh the layout immediately to avoid the
-- new dock.
docksEventHook :: Event -> X All
docksEventHook (MapNotifyEvent {ev_window = w}) = do
whenX ((not `fmap` (isClient w)) <&&> runQuery checkDock w) $ do
broadcastMessage ClearGapCache
refresh
docksEventHook (MapNotifyEvent { ev_window = w }) = do
whenX (runQuery checkDock w <&&> (not <$> isClient w)) $ do
strut <- getStrut w
whenX (updateStrutCache w strut) refreshDocks
return (All True)
docksEventHook (PropertyEvent { ev_window = w
, ev_atom = a }) = do
whenX (runQuery checkDock w) $ do
nws <- getAtom "_NET_WM_STRUT"
nwsp <- getAtom "_NET_WM_STRUT_PARTIAL"
when (a == nws || a == nwsp) $ do
strut <- getStrut w
whenX (updateStrutCache w strut) refreshDocks
return (All True)
docksEventHook (DestroyWindowEvent {ev_window = w}) = do
whenX (deleteFromStructCache w) refreshDocks
return (All True)
docksEventHook _ = return (All True)
docksStartupHook :: X ()
docksStartupHook = withDisplay $ \dpy -> do
rootw <- asks theRoot
(_,_,wins) <- io $ queryTree dpy rootw
docks <- filterM (runQuery checkDock) wins
forM_ docks $ \win -> do
strut <- getStrut win
updateStrutCache win strut
refreshDocks
-- | Gets the STRUT config, if present, in xmonad gap order
getStrut :: Window -> X [Strut]
getStrut w = do
@@ -146,9 +183,7 @@ getStrut w = do
calcGap :: S.Set Direction2D -> X (Rectangle -> Rectangle)
calcGap ss = 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 <- (filter careAbout . concat) `fmap` mapM getStrut wins
struts <- (filter careAbout . concat) `fmap` XS.gets (M.elems . fromStrutCache)
-- 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
@@ -170,12 +205,9 @@ avoidStrutsOn :: LayoutClass l a =>
[Direction2D]
-> l a
-> ModifiedLayout AvoidStruts l a
avoidStrutsOn ss = ModifiedLayout $ AvoidStruts (S.fromList ss) Nothing
avoidStrutsOn ss = ModifiedLayout $ AvoidStruts (S.fromList ss)
data AvoidStruts a = AvoidStruts {
avoidStrutsDirection :: S.Set Direction2D,
avoidStrutsRectCache :: Maybe (S.Set Direction2D, Rectangle, Rectangle )
} deriving ( Read, Show )
data AvoidStruts a = AvoidStruts (S.Set Direction2D) deriving ( Read, Show )
-- | Message type which can be sent to an 'AvoidStruts' layout
-- modifier to alter its behavior.
@@ -185,13 +217,6 @@ data ToggleStruts = ToggleStruts
instance Message ToggleStruts
-- | message sent to ensure that caching the gaps won't give a wrong result
-- because a new dock has been added
data ClearGapCache = ClearGapCache
deriving (Read,Show,Typeable)
instance Message ClearGapCache
-- | SetStruts is a message constructor used to set or unset specific struts,
-- regardless of whether or not the struts were originally set. Here are some
-- example bindings:
@@ -219,26 +244,18 @@ data SetStruts = SetStruts { addedStruts :: [Direction2D]
instance Message SetStruts
instance LayoutModifier AvoidStruts a where
modifyLayoutWithUpdate as@(AvoidStruts ss cache) w r = do
nr <- case cache of
Just (ss', r', nr) | ss' == ss, r' == r -> return nr
_ -> do
nr <- fmap ($ r) (calcGap ss)
setWorkarea nr
return nr
arranged <- runLayout w nr
let newCache = Just (ss, r, nr)
return (arranged, if newCache == cache
then Nothing
else Just as{ avoidStrutsRectCache = newCache } )
modifyLayout (AvoidStruts ss) w r = do
srect <- fmap ($ r) (calcGap ss)
setWorkarea srect
runLayout w srect
pureMess as@(AvoidStruts { avoidStrutsDirection = ss }) m
| Just ToggleStruts <- fromMessage m = Just $ as { avoidStrutsDirection = toggleAll ss }
| Just (ToggleStrut s) <- fromMessage m = Just $ as { avoidStrutsDirection = toggleOne s ss }
pureMess as@(AvoidStruts ss) m
| Just ToggleStruts <- fromMessage m = Just $ AvoidStruts (toggleAll ss)
| Just (ToggleStrut s) <- fromMessage m = Just $ AvoidStruts (toggleOne s ss)
| Just (SetStruts n k) <- fromMessage m
, let newSS = S.fromList n `S.union` (ss S.\\ S.fromList k)
, newSS /= ss = Just $ as { avoidStrutsDirection = newSS }
| Just ClearGapCache <- fromMessage m = Just $ as { avoidStrutsRectCache = Nothing }
, newSS /= ss = Just $ AvoidStruts newSS
| Just UpdateDocks <- fromMessage m = Just as
| otherwise = Nothing
where toggleAll x | S.null x = S.fromList [minBound .. maxBound]
| otherwise = S.empty

View File

@@ -88,9 +88,9 @@ positionStoreInit mDecoTheme w = withDisplay $ \d -> do
else do
sc <- fromMaybe (W.current ws) <$> pointScreen (fi $ wa_x wa) (fi $ wa_y wa)
let sr = screenRect . W.screenDetail $ sc
sr' <- fmap ($ sr) (calcGap $ S.fromList [minBound .. maxBound]) -- take docks into account, accepting
-- a somewhat unfortunate inter-dependency
-- with 'XMonad.Hooks.ManageDocks'
sr' <- fmap ($ sr) (calcGap $ S.fromList [minBound .. maxBound]) -- take docks into account, accepting
-- a somewhat unfortunate inter-dependency
-- with 'XMonad.Hooks.ManageDocks'
modifyPosStore (\ps -> posStoreInsert ps w
(Rectangle (fi $ wa_x wa) (fi (wa_y wa) - fi decoH)
(fi $ wa_width wa) (decoH + fi (wa_height wa))) sr' )

View File

@@ -185,6 +185,7 @@ screenCornerLayoutHook = ModifiedLayout ScreenCornerLayout
-- > ]
--
-- Then add layout hook:
--
-- > myLayout = screenCornerLayoutHook $ tiled ||| Mirror tiled ||| Full where
-- > tiled = Tall nmaster delta ratio
-- > nmaster = 1

View File

@@ -425,6 +425,7 @@ optimizeOrientation rct (t, cs) = Just (opt t rct, cs)
-- initially focused leaf, path from root to selected node, window ids of borders highlighting the selection
data NodeRef = NodeRef { refLeaf :: Int, refPath :: [Direction2D], refWins :: [Window] } deriving (Show,Read,Eq)
noRef :: NodeRef
noRef = NodeRef (-1) [] []
goToNode :: NodeRef -> Zipper a -> Maybe (Zipper a)

View File

@@ -274,7 +274,7 @@ instance (LayoutClass l Window, LayoutClass l2 (Group l Window))
results <- forM areas $ \(g, r') -> runLayout ws { W.layout = gLayout g
, W.stack = gZipper g } r'
let hidden = map gLayout (W.integrate $ groups l) \\ map (gLayout . fst) areas
let hidden = map gLayout (W.integrate $ groups _l) \\ map (gLayout . fst) areas
hidden' <- mapM (flip handleMessage $ SomeMessage Hide) hidden
let placements = concatMap fst results

View File

@@ -114,7 +114,7 @@ zoomGroupReset = zoomColumnReset
-- | Toggle whether the currently focused group should be maximized
-- whenever it has focus.
toggleGroupFull :: X ()
toggleGroupFull = toggleGroupFull
toggleGroupFull = toggleColumnFull
-- | Rotate the layouts in the focused group.
groupToNextLayout :: X ()

View File

@@ -14,7 +14,7 @@
--
-----------------------------------------------------------------------------
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, PatternGuards #-}
module XMonad.Layout.IfMax
( -- * Usage
@@ -23,6 +23,10 @@ module XMonad.Layout.IfMax
, ifMax
) where
import Control.Applicative((<$>))
import Control.Arrow
import qualified Data.List as L
import qualified Data.Map as M
import Data.Maybe
import XMonad
@@ -47,21 +51,36 @@ import qualified XMonad.StackSet as W
data IfMax l1 l2 w = IfMax Int (l1 w) (l2 w)
deriving (Read, Show)
instance (LayoutClass l1 a, LayoutClass l2 a) => LayoutClass (IfMax l1 l2) a where
instance (LayoutClass l1 Window, LayoutClass l2 Window) => LayoutClass (IfMax l1 l2) Window where
runLayout (W.Workspace _ (IfMax n l1 l2) s) rect = arrange (W.integrate' s)
runLayout (W.Workspace wname (IfMax n l1 l2) s) rect = withWindowSet $ \ws -> arrange (W.integrate' s) (M.keys . W.floating $ ws)
where
arrange [] = do l1' <- maybe l1 id `fmap` handleMessage l1 (SomeMessage ReleaseResources)
l2' <- maybe l2 id `fmap` handleMessage l2 (SomeMessage ReleaseResources)
return ([], Just $ IfMax n l1' l2')
arrange ws | length ws <= n = do
(wrs, ml1') <- runLayout (W.Workspace "" l1 s) rect
arrange ws fw | length (ws L.\\ fw) <= n = do
(wrs, ml1') <- runLayout (W.Workspace wname l1 s) rect
let l1' = fromMaybe l1 ml1'
return (wrs, Just $ IfMax n l1' l2)
| otherwise = do
(wrs, ml2') <- runLayout (W.Workspace "" l2 s) rect
l2' <- fromMaybe l2 <$> handleMessage l2 (SomeMessage Hide)
return (wrs, Just $ IfMax n l1' l2')
| otherwise = do
(wrs, ml2') <- runLayout (W.Workspace wname l2 s) rect
l1' <- fromMaybe l1 <$> handleMessage l1 (SomeMessage Hide)
let l2' = fromMaybe l2 ml2'
return (wrs, Just $ IfMax n l1 l2')
return (wrs, Just $ IfMax n l1' l2')
handleMessage (IfMax n l1 l2) m | Just ReleaseResources <- fromMessage m = do
l1' <- handleMessage l1 (SomeMessage ReleaseResources)
l2' <- handleMessage l2 (SomeMessage ReleaseResources)
if isNothing l1' && isNothing l2'
then return Nothing
else return $ Just $ IfMax n (fromMaybe l1 l1') (fromMaybe l2 l2')
handleMessage (IfMax n l1 l2) m = do
(allWindows, floatingWindows) <- gets ((W.integrate' . W.stack . W.workspace . W.current &&& M.keys . W.floating) . windowset)
if length (allWindows L.\\ floatingWindows) <= n
then do
l1' <- handleMessage l1 m
return $ flip (IfMax n) l2 <$> l1'
else do
l2' <- handleMessage l2 m
return $ IfMax n l1 <$> l2'
description (IfMax n l1 l2) = "If number of windows is <= " ++ show n ++ ", then " ++
description l1 ++ ", else " ++ description l2

View File

@@ -1,11 +1,26 @@
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, PatternGuards, DeriveDataTypeable #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.LayoutBuilder
-- Copyright : (c) 2009 Anders Engstrom <ankaan@gmail.com>
--
-- Copyright : (c) 2009 Anders Engstrom <ankaan@gmail.com>,
-- 2011 Ilya Portnov <portnov84@rambler.ru>,
-- 2015 Peter Jones <pjones@devalot.com>
--
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Anders Engstrom <ankaan@gmail.com>
-- Maintainer : Anders Engstrom <ankaan@gmail.com>,
-- Ilya Portnov <portnov84@rambler.ru>,
-- Peter Jones <pjones@devalot.com>
--
-- Stability : unstable
-- Portability : unportable
--
@@ -17,25 +32,40 @@
-- ("XMonad.Layout.LayoutHints", "XMonad.Layout.HintedGrid" etc.)
--
-----------------------------------------------------------------------------
module XMonad.Layout.LayoutBuilder (
-- * Usage
-- $usage
layoutN,
layoutR,
layoutP,
layoutAll,
-- * Selecting Windows
-- $selectWin
Predicate (..),
Proxy(..),
-- * Messages
IncLayoutN (..),
-- * Utilities
SubMeasure (..),
SubBox (..),
absBox,
relBox,
LayoutB,
LayoutN,
) where
--------------------------------------------------------------------------------
import Control.Applicative ((<|>))
import Control.Monad (foldM)
import Data.Maybe
import XMonad
import qualified XMonad.StackSet as W
import Data.Maybe (isJust,isNothing,listToMaybe)
import XMonad.Util.WindowProperties
--------------------------------------------------------------------------------
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
--
@@ -89,56 +119,126 @@ import Data.Maybe (isJust,isNothing,listToMaybe)
--
-- "XMonad.Doc.Extending#Editing_key_bindings".
type WindowNum = Either Int (Rational,Rational)
--------------------------------------------------------------------------------
-- $selectWin
--
-- 'Predicate' exists because layouts are required to be serializable, and
-- "XMonad.Util.WindowProperties" is not sufficient (for example it does not
-- allow using regular expressions).
--
-- compare "XMonad.Util.Invisible"
-- | Use one layout in the specified area for a number of windows and possibly let another layout handle the rest.
data LayoutN l1 l2 a =
LayoutN (Maybe a) (Maybe a) WindowNum SubBox (Maybe SubBox) (l1 a) (Maybe (l2 a))
deriving (Show,Read)
-- | Type class for predicates. This enables us to manage not only Windows,
-- but any objects, for which instance Predicate is defined.
--
-- Another instance exists in XMonad.Util.WindowPropertiesRE in xmonad-extras
class Predicate p w where
alwaysTrue :: Proxy w -> p -- ^ A predicate that is always True.
checkPredicate :: p -> w -> X Bool -- ^ Check if given object (window or smth else) matches that predicate
-- | Use the specified layout in the described area for N windows and send the rest of the windows to the next layout in the chain.
-- It is possible to supply an alternative area that will then be used instead, if there are no windows to send to the next layout.
instance Predicate () a where
alwaysTrue _ = ()
checkPredicate _ _ = return True
instance Predicate Property Window where
alwaysTrue _ = Const True
checkPredicate = hasProperty
--------------------------------------------------------------------------------
-- | Contains no actual data, but is needed to help select the correct instance
-- of 'Predicate'
data Proxy a = Proxy
--------------------------------------------------------------------------------
-- | Information about how to split windows between layouts.
data Limit p = LimitN Int -- ^ See: 'layoutN'.
| LimitR (Rational, Rational) -- ^ See: 'layoutR'.
| LimitP p -- ^ See: 'layoutP'.
deriving (Show, Read)
--------------------------------------------------------------------------------
-- | Use one layout in the specified area for a number of windows and
-- possibly let another layout handle the rest.
data LayoutB l1 l2 p a = LayoutB
{ subFocus :: Maybe a -- ^ The focused window in this layout.
, nextFocus :: Maybe a -- ^ The focused window in the next layout.
, limit :: Limit p -- ^ How to split windows between layouts.
, box :: SubBox -- ^ Normal size of layout.
, mbox :: Maybe SubBox -- ^ Size of layout when handling all windows.
, sub :: l1 a -- ^ The layout to use in this box.
, next :: Maybe (l2 a) -- ^ The next layout in the chain.
} deriving (Show, Read)
--------------------------------------------------------------------------------
-- | A variant of 'LayoutB' that can't use 'layoutP'. For backwards
-- compatibility with previous versions of LayoutBuilder.
type LayoutN l1 l2 a = LayoutB l1 l2 () a
--------------------------------------------------------------------------------
-- | Use the specified layout in the described area for N windows and
-- send the rest of the windows to the next layout in the chain. It
-- is possible to supply an alternative area that will then be used
-- instead, if there are no windows to send to the next layout.
layoutN :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>
Int -- ^ The number of windows to handle
-> SubBox -- ^ The box to place the windows in
-> Maybe SubBox -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
-> l1 a -- ^ The layout to use in the specified area
-> LayoutN l2 l3 a -- ^ Where to send the remaining windows
-> LayoutN l1 (LayoutN l2 l3) a -- ^ The resulting layout
layoutN num box mbox sub next = LayoutN Nothing Nothing (Left num) box mbox sub (Just next)
Int -- ^ The number of windows to handle
-> SubBox -- ^ The box to place the windows in
-> Maybe SubBox -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
-> l1 a -- ^ The layout to use in the specified area
-> LayoutB l2 l3 p a -- ^ Where to send the remaining windows
-> LayoutB l1 (LayoutB l2 l3 p) () a -- ^ The resulting layout
layoutN num box mbox sub next = LayoutB Nothing Nothing (LimitN num) box mbox sub (Just next)
-- | As layoutN, but the number of windows is given relative to the total number of windows remaining to be handled. The first
-- argument is how much to change the ratio when using IncLayoutN, and the second is the initial ratio.
layoutR :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a) =>
Rational -- ^ How much to change the ratio with each IncLayoutN
-> Rational -- ^ The ratio of the remaining windows to handle
-> SubBox -- ^ The box to place the windows in
-> Maybe SubBox -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
-> l1 a -- ^ The layout to use in the specified area
-> LayoutN l2 l3 a -- ^ Where to send the remaining windows
-> LayoutN l1 (LayoutN l2 l3) a -- ^ The resulting layout
layoutR numdiff num box mbox sub next = LayoutN Nothing Nothing (Right (numdiff,num)) box mbox sub (Just next)
Rational -- ^ How much to change the ratio with each IncLayoutN
-> Rational -- ^ The ratio of the remaining windows to handle
-> SubBox -- ^ The box to place the windows in
-> Maybe SubBox -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
-> l1 a -- ^ The layout to use in the specified area
-> LayoutB l2 l3 p a -- ^ Where to send the remaining windows
-> LayoutB l1 (LayoutB l2 l3 p) p a -- ^ The resulting layout
layoutR numdiff num box mbox sub next = LayoutB Nothing Nothing (LimitR (numdiff,num)) box mbox sub (Just next)
--------------------------------------------------------------------------------
-- | Use the specified layout in the described area windows that match
-- given predicate and send the rest of the windows to the next layout
-- in the chain. It is possible to supply an alternative area that
-- will then be used instead, if there are no windows to send to the
-- next layout.
layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a, Predicate p' a) =>
p -- ^ The predicate to use
-> SubBox -- ^ The box to place the windows in
-> Maybe SubBox -- ^ Possibly an alternative box that is used when this layout handles all windows that are left
-> l1 a -- ^ The layout to use in the specified area
-> LayoutB l2 l3 p' a -- ^ Where to send the remaining windows
-> LayoutB l1 (LayoutB l2 l3 p') p a -- ^ The resulting layout
layoutP prop box mbox sub next = LayoutB Nothing Nothing (LimitP prop) box mbox sub (Just next)
--------------------------------------------------------------------------------
-- | Use the specified layout in the described area for all remaining windows.
layoutAll :: (Read a, Eq a, LayoutClass l1 a) =>
SubBox -- ^ The box to place the windows in
-> l1 a -- ^ The layout to use in the specified area
-> LayoutN l1 Full a -- ^ The resulting layout
layoutAll box sub = LayoutN Nothing Nothing (Right (0,1)) box Nothing sub Nothing
SubBox -- ^ The box to place the windows in
-> l1 a -- ^ The layout to use in the specified area
-> LayoutB l1 Full () a -- ^ The resulting layout
layoutAll box sub = LayoutB Nothing Nothing (LimitR (0,1)) box Nothing sub Nothing
--------------------------------------------------------------------------------
-- | Change the number of windows handled by the focused layout.
data IncLayoutN = IncLayoutN Int deriving Typeable
instance Message IncLayoutN
--------------------------------------------------------------------------------
-- | The absolute or relative measures used to describe the area a layout should be placed in. For negative absolute values
-- the total remaining space will be added. For sizes, the remaining space will also be added for zeroes. Relative values
-- are applied on the remaining space after the top-left corner of the box have been removed.
data SubMeasure = Abs Int | Rel Rational deriving (Show,Read)
--------------------------------------------------------------------------------
-- | A box to place a layout in. The stored values are xpos, ypos, width and height.
data SubBox = SubBox SubMeasure SubMeasure SubMeasure SubMeasure deriving (Show,Read)
--------------------------------------------------------------------------------
-- | Create a box with only absolute measurements. If the values are negative, the total remaining space will be added. For
-- sizes it will also be added for zeroes.
absBox :: Int -- ^ Absolute X-Position
@@ -148,7 +248,7 @@ absBox :: Int -- ^ Absolute X-Position
-> SubBox -- ^ The resulting 'SubBox' describing the area
absBox x y w h = SubBox (Abs x) (Abs y) (Abs w) (Abs h)
--------------------------------------------------------------------------------
-- | Create a box with only relative measurements.
relBox :: Rational -- ^ Relative X-Position with respect to the surrounding area
-> Rational -- ^ Relative Y-Position with respect to the surrounding area
@@ -157,138 +257,209 @@ relBox :: Rational -- ^ Relative X-Position with respect to the surrounding are
-> SubBox -- ^ The resulting 'SubBox' describing the area
relBox x y w h = SubBox (Rel x) (Rel y) (Rel w) (Rel h)
--------------------------------------------------------------------------------
instance ( LayoutClass l1 a, LayoutClass l2 a
, Read a, Show a, Show p, Eq a, Typeable a, Predicate p a
) => LayoutClass (LayoutB l1 l2 p) a where
instance (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) =>
LayoutClass (LayoutN l1 l2) a where
-- | Update window locations.
runLayout (W.Workspace _ LayoutB {..} s) rect = do
(subs, nexts, subFocus', nextFocus') <- splitStack s limit subFocus nextFocus
-- | Update window locations.
runLayout (W.Workspace _ (LayoutN subf nextf num box mbox sub next) s) rect
= do let (subs,nexts,subf',nextf') = splitStack s num subf nextf
selBox = if isJust nextf'
then box
else maybe box id mbox
let selBox = if isJust nextFocus' then box else fromMaybe box mbox
(sublist,sub',schange) <- handle sub subs $ calcArea selBox rect
(sublist, sub', schange) <- handle sub subs (calcArea selBox rect)
(nextlist,next',nchange) <- case next of Nothing -> return ([], Nothing, False)
Just n -> do (res, l, ch) <- handle n nexts rect
return (res, Just l, ch)
(nextlist, next', nchange) <- case next of
Nothing -> return ([], Nothing, False)
Just n -> do (res, l, ch) <- handle n nexts rect
return (res, Just l, ch)
let newlist = if (length $ maybe [] W.up s) < (length $ W.integrate' subs)
then sublist++nextlist
else nextlist++sublist
newstate = if subf' /= subf || nextf' /= nextf || schange || nchange
then Just $ LayoutN subf' nextf' num box mbox sub' next'
else Nothing
let newlist = if length (maybe [] W.up s) < length (W.integrate' subs)
then sublist++nextlist
else nextlist++sublist
return (newlist, newstate)
where
handle l s' r = do (res,ml) <- runLayout (W.Workspace "" l s') r
l' <- return $ maybe l id ml
return (res, l', isNothing ml)
newstate = if subFocus' /= subFocus || nextFocus' /= nextFocus || schange || nchange
then Just $ LayoutB subFocus' nextFocus' limit box mbox sub' next'
else Nothing
-- | Propagate messages.
handleMessage l m
| Just (IncLayoutN _) <- fromMessage m = windowNum l m
| Just (IncMasterN _) <- fromMessage m = sendFocus l m
| Just (Shrink) <- fromMessage m = sendFocus l m
| Just (Expand) <- fromMessage m = sendFocus l m
| otherwise = sendBoth l m
return (newlist, newstate)
where
handle l s' r = do (res,ml) <- runLayout (W.Workspace "" l s') r
return (res, fromMaybe l ml, isNothing ml)
-- | Descriptive name for layout.
description (LayoutN _ _ _ _ _ sub Nothing) = "layoutAll "++ description sub
description (LayoutN _ _ (Left _) _ _ sub (Just next)) = "layoutN "++ description sub ++" "++ description next
description (LayoutN _ _ (Right _) _ _ sub (Just next)) = "layoutR "++ description sub ++" "++ description next
-- | Propagate messages.
handleMessage l m
| Just (IncLayoutN n) <- fromMessage m = incLayoutN l m n
| Just (IncMasterN _) <- fromMessage m = sendFocus l m
| Just Shrink <- fromMessage m = sendFocus l m
| Just Expand <- fromMessage m = sendFocus l m
| otherwise = sendBoth l m
-- | Descriptive name for layout.
description layout = case layout of
(LayoutB _ _ _ _ _ sub Nothing) ->
"layoutAll " ++ description sub
windowNum :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))
windowNum l@(LayoutN subf nextf num box mbox subl nextl) m | (Just (IncLayoutN n)) <- fromMessage m =
do foc <- isFocus subf
if foc then do let newnum = case num of
(Left oldnum) -> Left $ max 1 $ oldnum + n
(Right (diff,oldnum)) -> Right (diff, min 1 $ max 0 $ oldnum + (fromIntegral n)*diff)
return $ Just $ LayoutN subf nextf newnum box mbox subl nextl
else sendNext l m
windowNum l m = sendNext l m
(LayoutB _ _ (LimitN _) _ _ sub (Just next)) ->
"layoutN " ++ description sub ++ " " ++ description next
sendSub :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))
sendSub (LayoutN subf nextf num box mbox sub next) m =
(LayoutB _ _ (LimitR _) _ _ sub (Just next)) ->
"layoutR " ++ description sub ++ " " ++ description next
(LayoutB _ _ (LimitP _) _ _ sub (Just next)) ->
"layoutP " ++ description sub ++ " " ++ description next
--------------------------------------------------------------------------------
-- | Increase the number of windows allowed in the focused layout.
incLayoutN :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a)
=> LayoutB l1 l2 p a
-> SomeMessage
-> Int
-> X (Maybe (LayoutB l1 l2 p a))
incLayoutN layout@LayoutB {..} message n = do
incThis <- isFocus subFocus
if incThis
then return $ Just layout { limit = newLimit }
else sendNext layout message
where
newLimit = case limit of
LimitN oldnum -> LimitN (max 1 $ oldnum + n)
LimitR (diff, oldnum) -> LimitR (diff, min 1 $ max 0 $ oldnum + fromIntegral n * diff)
LimitP _ -> limit
--------------------------------------------------------------------------------
sendSub :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
sendSub (LayoutB subFocus nextFocus num box mbox sub next) m =
do sub' <- handleMessage sub m
return $ if isJust sub'
then Just $ LayoutN subf nextf num box mbox (maybe sub id sub') next
then Just $ LayoutB subFocus nextFocus num box mbox (fromMaybe sub sub') next
else Nothing
sendBoth :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))
sendBoth l@(LayoutN _ _ _ _ _ _ Nothing) m = sendSub l m
sendBoth (LayoutN subf nextf num box mbox sub (Just next)) m =
--------------------------------------------------------------------------------
sendBoth :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
sendBoth l@(LayoutB _ _ _ _ _ _ Nothing) m = sendSub l m
sendBoth (LayoutB subFocus nextFocus num box mbox sub (Just next)) m =
do sub' <- handleMessage sub m
next' <- handleMessage next m
return $ if isJust sub' || isJust next'
then Just $ LayoutN subf nextf num box mbox (maybe sub id sub') (Just $ maybe next id next')
then Just $ LayoutB subFocus nextFocus num box mbox (fromMaybe sub sub') (next' <|> Just next)
else Nothing
sendNext :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))
sendNext (LayoutN _ _ _ _ _ _ Nothing) _ = return Nothing
sendNext (LayoutN subf nextf num box mbox sub (Just next)) m =
--------------------------------------------------------------------------------
sendNext :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
sendNext (LayoutB _ _ _ _ _ _ Nothing) _ = return Nothing
sendNext (LayoutB subFocus nextFocus num box mbox sub (Just next)) m =
do next' <- handleMessage next m
return $ if isJust next'
then Just $ LayoutN subf nextf num box mbox sub next'
then Just $ LayoutB subFocus nextFocus num box mbox sub next'
else Nothing
sendFocus :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutN l1 l2 a -> SomeMessage -> X (Maybe (LayoutN l1 l2 a))
sendFocus l@(LayoutN subf _ _ _ _ _ _) m = do foc <- isFocus subf
if foc then sendSub l m
else sendNext l m
--------------------------------------------------------------------------------
sendFocus :: (LayoutClass l1 a, LayoutClass l2 a, Read a, Show a, Eq a, Typeable a) => LayoutB l1 l2 p a -> SomeMessage -> X (Maybe (LayoutB l1 l2 p a))
sendFocus l@(LayoutB subFocus _ _ _ _ _ _) m = do
foc <- isFocus subFocus
if foc
then sendSub l m
else sendNext l m
--------------------------------------------------------------------------------
-- | Check to see if the given window is currently focused.
isFocus :: (Show a) => Maybe a -> X Bool
isFocus Nothing = return False
isFocus (Just w) = do ms <- (W.stack . W.workspace . W.current) `fmap` gets windowset
return $ maybe False (\s -> show w == (show $ W.focus s)) ms
return $ maybe False (\s -> show w == show (W.focus s)) ms
--------------------------------------------------------------------------------
calcNum :: Int -> Limit p -> Int
calcNum tot num = max 1 $ case num of LimitN i -> i
LimitR (_,r) -> ceiling $ r * fromIntegral tot
LimitP _ -> 1
calcNum :: Int -> WindowNum -> Int
calcNum tot num = max 1 $ case num of Left i -> i
Right (_,r) -> ceiling $ r * fromIntegral tot
--------------------------------------------------------------------------------
-- | Split given list of objects (i.e. windows) using predicate.
splitBy :: (Predicate p a) => p -> [a] -> X ([a], [a])
splitBy prop = foldM step ([], [])
where
step (good, bad) w = do
ok <- checkPredicate prop w
return $ if ok
then (w:good, bad)
else (good, w:bad)
splitStack :: Eq a => Maybe (W.Stack a) -> WindowNum -> Maybe a -> Maybe a -> (Maybe (W.Stack a),Maybe (W.Stack a),Maybe a,Maybe a)
splitStack Nothing _ _ _ = (Nothing,Nothing,Nothing,Nothing)
splitStack (Just s) num subf nextf = ( differentiate' subf' subl
, differentiate' nextf' nextl
, subf'
, nextf'
)
where
ws = W.integrate s
n = calcNum (length ws) num
subl = take n ws
nextl = drop n ws
subf' = foc subl subf
nextf' = foc nextl nextf
foc [] _ = Nothing
foc l f | W.focus s `elem` l = Just $ W.focus s
| maybe False (`elem` l) f = f
| otherwise = listToMaybe l
--------------------------------------------------------------------------------
splitStack :: forall a p. (Eq a, Predicate p a)
=> Maybe (W.Stack a) -- ^ Window set.
-> Limit p -- ^ How to split the stack.
-> Maybe a -- ^ The window that was focused in this layout.
-> Maybe a -- ^ The window that was focused in the next layout.
-> X (Maybe (W.Stack a), Maybe (W.Stack a), Maybe a, Maybe a)
splitStack Nothing _ _ _ = return (Nothing, Nothing, Nothing, Nothing)
splitStack (Just s) limit subFocus nextFocus =
case limit of
LimitN _ -> splitN
LimitR _ -> splitN
LimitP prop -> splitP prop
where
ws = W.integrate s
n = calcNum (length ws) limit
subl = take n ws
nextl = drop n ws
subFocus' xs = foc xs subFocus
nextFocus' xs = foc xs nextFocus
-- Pick a new focused window if necessary.
foc :: [a] -> Maybe a -> Maybe a
foc [] _ = Nothing
foc l f | W.focus s `elem` l = Just (W.focus s)
| maybe False (`elem` l) f = f
| otherwise = listToMaybe l
-- Split based on max number of windows.
splitN = return ( differentiate' (subFocus' subl) subl
, differentiate' (nextFocus' nextl) nextl
, subFocus' subl
, nextFocus' nextl
)
-- Split based on a predicate.
splitP prop = do
(this, other) <- splitBy prop ws
return ( differentiate' (subFocus' this) this
, differentiate' (nextFocus' other) other
, subFocus' this
, nextFocus' other
)
--------------------------------------------------------------------------------
calcArea :: SubBox -> Rectangle -> Rectangle
calcArea (SubBox xpos ypos width height) rect = Rectangle (rect_x rect + fromIntegral xpos') (rect_y rect + fromIntegral ypos') width' height'
where
xpos' = calc False xpos $ rect_width rect
ypos' = calc False ypos $ rect_height rect
width' = calc True width $ rect_width rect - xpos'
height' = calc True height $ rect_height rect - ypos'
calcArea (SubBox xpos ypos width height) rect =
Rectangle (rect_x rect + fromIntegral xpos')
(rect_y rect + fromIntegral ypos')
width' height'
where
xpos' = calc False xpos $ rect_width rect
ypos' = calc False ypos $ rect_height rect
width' = calc True width $ rect_width rect - xpos'
height' = calc True height $ rect_height rect - ypos'
calc zneg val tot = fromIntegral $ min (fromIntegral tot) $ max 0 $
case val of Rel v -> floor $ v * fromIntegral tot
Abs v -> if v<0 || (zneg && v==0)
then (fromIntegral tot)+v
else v
calc zneg val tot = fromIntegral $ min (fromIntegral tot) $ max 0 $
case val of Rel v -> floor $ v * fromIntegral tot
Abs v -> if v<0 || (zneg && v==0)
then fromIntegral tot + v
else v
--------------------------------------------------------------------------------
differentiate' :: Eq q => Maybe q -> [q] -> Maybe (W.Stack q)
differentiate' _ [] = Nothing
differentiate' Nothing w = W.differentiate w
differentiate' (Just f) w
| f `elem` w = Just $ W.Stack { W.focus = f
, W.up = reverse $ takeWhile (/=f) w
, W.down = tail $ dropWhile (/=f) w
}
| f `elem` w = Just W.Stack { W.focus = f
, W.up = reverse $ takeWhile (/=f) w
, W.down = tail $ dropWhile (/=f) w
}
| otherwise = W.differentiate w

View File

@@ -9,12 +9,11 @@
-- Stability : unstable
-- Portability : unportable
--
-- A layout combinator that sends windows matching given predicate to one rectangle
-- and the rest to another.
-- DEPRECATED. Use 'XMonad.Layout.LayoutBuilder' instead.
--
-----------------------------------------------------------------------------
module XMonad.Layout.LayoutBuilderP (
module XMonad.Layout.LayoutBuilderP {-# DEPRECATED "Use XMonad.Layout.LayoutBuilder instead" #-} (
LayoutP (..),
layoutP, layoutAll,
B.relBox, B.absBox,
@@ -59,6 +58,7 @@ data LayoutP p l1 l2 a =
-- | Use the specified layout in the described area windows that match given predicate and send the rest of the windows to the next layout in the chain.
-- It is possible to supply an alternative area that will then be used instead, if there are no windows to send to the next layout.
{-# DEPRECATED layoutP "Use XMonad.Layout.LayoutBuilder.layoutP instead." #-}
layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a, Predicate p a) =>
p
-> B.SubBox -- ^ The box to place the windows in
@@ -69,6 +69,7 @@ layoutP :: (Read a, Eq a, LayoutClass l1 a, LayoutClass l2 a, LayoutClass l3 a,
layoutP prop box mbox sub next = LayoutP Nothing Nothing prop box mbox sub (Just next)
-- | Use the specified layout in the described area for all remaining windows.
{-# DEPRECATED layoutAll "Use XMonad.Layout.LayoutBuilder.layoutAll instead." #-}
layoutAll :: forall l1 p a. (Read a, Eq a, LayoutClass l1 a, Predicate p a) =>
B.SubBox -- ^ The box to place the windows in
-> l1 a -- ^ The layout to use in the specified area
@@ -207,4 +208,3 @@ differentiate' (Just f) w
instance Predicate Property Window where
alwaysTrue _ = Const True
checkPredicate = hasProperty

View File

@@ -50,7 +50,7 @@ data Rename a = CutLeft Int -- ^ Remove a number of characters from the left
-- if necessary
| PrependWords String -- ^ Add a string to the left, appending a space to it if
-- necessary
| Replace String -- ^ Repace with another wtring
| Replace String -- ^ Replace with another string
| Chain [Rename a] -- ^ Apply a list of modifications in left-to-right order
deriving (Show, Read, Eq)
@@ -68,4 +68,4 @@ apply (PrependWords s') s = unwords $ s' : words s
apply (Chain rs) s = ($s) $ foldr (flip (.)) id $ map apply rs
instance LayoutModifier Rename a where
modifyDescription r l = apply r (description l)
modifyDescription r l = apply r (description l)

View File

@@ -0,0 +1,88 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.SortedLayout
-- Copyright : (c) 2016 Kurt Dietrich
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : kurto@mac.com
-- Stability : unstable
-- Portability : unportable
--
-- A 'LayoutModifier' that sorts the windows in another layout, given a
-- list of properties. The order of properties in the list determines
-- the order of windows in the final layout. Any unmatched windows
-- go to the end of the order.
-----------------------------------------------------------------------------
module XMonad.Layout.SortedLayout
( -- *Usage:
-- $usage
sorted
, Property(..)
) where
import Control.Monad
import Data.Functor ((<$>))
import Data.List
import XMonad
import XMonad.Layout.LayoutModifier
import XMonad.StackSet as W
import XMonad.Util.WindowProperties
-- $usage
-- You can use this module with the following in your
-- @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad.Layout.SortedLayout
--
-- Then edit your @layoutHook@ to sort another layout (in this case, 'XMonad.Layout.Grid.Grid'):
--
-- > myLayout = sorted [ClassName "Firefox", ClassName "URxvt"] Grid
-- > main = xmonad def { layoutHook = myLayout }
--
-- For more detailed instructions on editing the layoutHook see:
--
-- "XMonad.Doc.Extending#Editing_the_layout_hook"
-- | Modify a layout using a list of properties to sort its windows.
sorted :: [Property]
-> l a
-> ModifiedLayout SortedLayout l a
sorted props = ModifiedLayout . SortedLayout $ props ++ [Const True]
data WindowDescriptor = WindowDescriptor { wdSeqn :: !Integer
, wdProp :: !Property
, wdId :: !Window
} deriving (Show, Read)
instance Eq WindowDescriptor where
(==) a b = wdId a == wdId b
instance Ord WindowDescriptor where
compare a b = compare (wdSeqn a) (wdSeqn b)
data SortedLayout a = SortedLayout [Property] deriving (Show, Read)
instance LayoutModifier SortedLayout Window where
modifyLayout (SortedLayout props) = sortLayout props
modifierDescription _ = "Sorted"
findMatchingWindows :: Integer -> Property -> [Window] -> X [WindowDescriptor]
findMatchingWindows seqn prop wids = fmap (fmap (WindowDescriptor seqn prop)) matching where
matching = filterM (hasProperty prop) wids
sortLayout :: (LayoutClass l Window)
=> [Property]
-> W.Workspace WorkspaceId (l Window) Window
-> Rectangle
-> X ([(Window, Rectangle)], Maybe (l Window))
sortLayout props (W.Workspace w l r) rect = do
let wids = W.integrate' r
sortedWids <- map wdId . nub . sort . concat <$> zipWithM (\s p -> findMatchingWindows s p wids) [0..] props
let sr = W.differentiate sortedWids
runLayout (W.Workspace w l sr) rect

View File

@@ -93,7 +93,7 @@ instance LayoutModifier SpacingWithEdge a where
modifierDescription (SpacingWithEdge p) = "SpacingWithEdge " ++ show p
shrinkRect :: Int -> Rectangle -> Rectangle
shrinkRect p (Rectangle x y w h) = Rectangle (x+fi p) (y+fi p) (w-2*fi p) (h-2*fi p)
shrinkRect p (Rectangle x y w h) = Rectangle (x+fi p) (y+fi p) (fi $ max 1 $ fi w-2*p) (fi $ max 1 $ fi h-2*p)
-- | Surrounds all windows with blank space, except when the window is the only
-- visible window on the current workspace.

View File

@@ -35,6 +35,9 @@
-- (Linux-centric) approach may be used. See
-- <https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt>
--
-- * Note
-- This module doesn't work on programs that do fancy things with processes
-- (such as Chromium) and programs that do not set _NET_WM_PID.
-----------------------------------------------------------------------------
module XMonad.Layout.Stoppable

View File

@@ -4,6 +4,7 @@
-- |
-- Module : XMonad.Prompt
-- Copyright : (C) 2007 Andrea Rossato, 2015 Evgeny Kurnevsky
-- 2015 Sibi Prabakaran
-- License : BSD3
--
-- Maintainer : Spencer Janssen <spencerjanssen@gmail.com>
@@ -126,14 +127,14 @@ data XPState =
}
data XPConfig =
XPC { font :: String -- ^ Font
XPC { font :: String -- ^ Font; use the prefix @"xft:"@ for TrueType fonts
, bgColor :: String -- ^ Background color
, fgColor :: String -- ^ Font color
, fgHLight :: String -- ^ Font color of a highlighted completion entry
, bgHLight :: String -- ^ Background color of a highlighted completion entry
, borderColor :: String -- ^ Border color
, promptBorderWidth :: !Dimension -- ^ Border width
, position :: XPPosition -- ^ Position: 'Top' or 'Bottom'
, position :: XPPosition -- ^ Position: 'Top', 'Bottom', or 'CenteredAt'
, alwaysHighlight :: !Bool -- ^ Always highlight an item, overriden to True with multiple modes. This implies having *one* column of autocompletions only.
, height :: !Dimension -- ^ Window height
, maxComplRows :: Maybe Dimension
@@ -144,12 +145,12 @@ data XPConfig =
-- history entries to remember
, promptKeymap :: M.Map (KeyMask,KeySym) (XP ())
-- ^ Mapping from key combinations to actions
, completionKey :: KeySym -- ^ Key that should trigger completion
, completionKey :: (KeyMask, KeySym) -- ^ Key that should trigger completion
, changeModeKey :: KeySym -- ^ Key to change mode (when the prompt has multiple modes)
, defaultText :: String -- ^ The text by default in the prompt line
, autoComplete :: Maybe Int -- ^ Just x: if only one completion remains, auto-select it,
, showCompletionOnTab :: Bool -- ^ Only show list of completions when Tab was pressed
-- and delay by x microseconds
, showCompletionOnTab :: Bool -- ^ Only show list of completions when Tab was pressed
, searchPredicate :: String -> String -> Bool
-- ^ Given the typed string and a possible
-- completion, is the completion valid?
@@ -228,6 +229,17 @@ class XPrompt t where
data XPPosition = Top
| Bottom
-- | Prompt will be placed in the center horizontally and
-- in the certain place of screen vertically. If it's in the upper
-- part of the screen, completion window will be placed below(like
-- in 'Top') and otherwise above(like in 'Bottom')
| CenteredAt { xpCenterY :: Rational
-- ^ Rational between 0 and 1, giving
-- y coordinate of center of the prompt relative to the screen height.
, xpWidth :: Rational
-- ^ Rational between 0 and 1, giving
-- width of the prompt relatave to the screen width.
}
deriving (Show,Read)
amberXPConfig, defaultXPConfig, greenXPConfig :: XPConfig
@@ -242,7 +254,7 @@ instance Default XPConfig where
, borderColor = "white"
, promptBorderWidth = 1
, promptKeymap = defaultXPKeymap
, completionKey = xK_Tab
, completionKey = (0,xK_Tab)
, changeModeKey = xK_grave
, position = Bottom
, height = 18
@@ -488,14 +500,15 @@ handle ks@(sym,_) e@(KeyEvent {ev_event_type = t, ev_state = m}) = do
complKey <- gets $ completionKey . config
chgModeKey <- gets $ changeModeKey . config
c <- getCompletions
mCleaned <- cleanMask m
when (length c > 1) $ modify (\s -> s { showComplWin = True })
if complKey == sym
if complKey == (mCleaned,sym)
then completionHandle c ks e
else if (sym == chgModeKey) then
do
modify setNextMode
updateWindows
else when (t == keyPress) $ keyPressHandle m ks
else when (t == keyPress) $ keyPressHandle mCleaned ks
handle _ (ExposeEvent {ev_window = w}) = do
st <- get
when (win st == w) updateWindows
@@ -506,8 +519,9 @@ completionHandle :: [String] -> KeyStroke -> Event -> XP ()
completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = do
complKey <- gets $ completionKey . config
alwaysHlight <- gets $ alwaysHighlight . config
mCleaned <- cleanMask m
case () of
() | t == keyPress && sym == complKey ->
() | t == keyPress && (mCleaned,sym) == complKey ->
do
st <- get
let updateState l = case alwaysHlight of
@@ -523,8 +537,8 @@ completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = d
[] -> updateWindows >> eventLoop handle
[x] -> updateState [x] >> getCompletions >>= updateWins
l -> updateState l >> updateWins l
| t == keyRelease && sym == complKey -> eventLoop (completionHandle c)
| otherwise -> keyPressHandle m ks -- some other key, handle it normally
| t == keyRelease && (mCleaned,sym) == complKey -> eventLoop (completionHandle c)
| otherwise -> keyPressHandle mCleaned ks -- some other key, handle it normally
-- some other event: go back to main loop
completionHandle _ k e = handle k e
@@ -662,12 +676,11 @@ emacsLikeXPKeymap' p = M.fromList $
keyPressHandle :: KeyMask -> KeyStroke -> XP ()
keyPressHandle m (ks,str) = do
km <- gets (promptKeymap . config)
kmask <- cleanMask m -- mask is defined in ghc7
case M.lookup (kmask,ks) km of
case M.lookup (m,ks) km of
Just action -> action >> updateWindows
Nothing -> case str of
"" -> eventLoop handle
_ -> when (kmask .&. controlMask == 0) $ do
_ -> when (m .&. controlMask == 0) $ do
let str' = if isUTF8Encoded str
then decodeString str
else str
@@ -842,8 +855,12 @@ createWin d rw c s = do
let (x,y) = case position c of
Top -> (0,0)
Bottom -> (0, rect_height s - height c)
CenteredAt py w -> (floor $ (fi $ rect_width s) * ((1 - w) / 2), floor $ py * fi (rect_height s) - (fi (height c) / 2))
width = case position c of
CenteredAt _ w -> floor $ fi (rect_width s) * w
_ -> rect_width s
w <- mkUnmanagedWindow d (defaultScreenOfDisplay d) rw
(rect_x s + x) (rect_y s + fi y) (rect_width s) (height c)
(rect_x s + x) (rect_y s + fi y) width (height c)
mapWindow d w
return w
@@ -852,7 +869,9 @@ drawWin = do
st <- get
let (c,(d,(w,gc))) = (config &&& dpy &&& win &&& gcon) st
scr = defaultScreenOfDisplay d
wh = widthOfScreen scr
wh = case position c of
CenteredAt _ wd -> floor $ wd * fi (widthOfScreen scr)
_ -> widthOfScreen scr
ht = height c
bw = promptBorderWidth c
Just bgcolor <- io $ initColor d (bgColor c)
@@ -935,8 +954,11 @@ getComplWinDim :: [String] -> XP ComplWindowDim
getComplWinDim compl = do
st <- get
let (c,(scr,fs)) = (config &&& screen &&& fontS) st
wh = rect_width scr
wh = case position c of
CenteredAt _ w -> floor $ fi (rect_width scr) * w
_ -> rect_width scr
ht = height c
bw = promptBorderWidth c
tws <- mapM (textWidthXMF (dpy st) fs) compl
let max_compl_len = fromIntegral ((fi ht `div` 2) + maximum tws)
@@ -951,8 +973,11 @@ getComplWinDim compl = do
actual_rows = min actual_max_number_of_rows (fi needed_rows)
actual_height = actual_rows * ht
(x,y) = case position c of
Top -> (0,ht)
Bottom -> (0, (0 + rem_height - actual_height))
Top -> (0,ht - bw)
Bottom -> (0, (0 + rem_height - actual_height + bw))
CenteredAt py w
| py <= 1/2 -> (floor $ fi (rect_width scr) * ((1 - w) / 2), floor (py * fi (rect_height scr) + (fi ht)/2) - bw)
| otherwise -> (floor $ fi (rect_width scr) * ((1 - w) / 2), floor (py * fi (rect_height scr) - (fi ht)/2) - actual_height + bw)
(asc,desc) <- io $ textExtentsXMF fs $ head compl
let yp = fi $ (ht + fi (asc - desc)) `div` 2
xp = (asc + desc) `div` 2

View File

@@ -48,7 +48,7 @@ import XMonad.Prompt ( XPrompt
, getNextCompletion
, XPConfig
, mkXPrompt
, mkComplFunFromList)
, searchPredicate)
import System.Directory (getHomeDirectory)
import System.FilePath (takeExtension, dropExtension, combine)
import System.Posix.Env (getEnv)
@@ -72,6 +72,11 @@ import XMonad.Util.Run (runProcessWithInput)
-- - how to setup the password storage, see <http://git.zx2c4.com/password-store/about/>
--
type Predicate = String -> String -> Bool
getPassCompl :: [String] -> Predicate -> String -> IO [String]
getPassCompl compls p s = do return $ filter (p s) compls
type PromptLabel = String
data Pass = Pass PromptLabel
@@ -101,7 +106,7 @@ passwordStoreFolder =
mkPassPrompt :: PromptLabel -> (String -> X ()) -> XPConfig -> X ()
mkPassPrompt promptLabel passwordFunction xpconfig = do
passwords <- io (passwordStoreFolder >>= getPasswords)
mkXPrompt (Pass promptLabel) xpconfig (mkComplFunFromList passwords) passwordFunction
mkXPrompt (Pass promptLabel) xpconfig (getPassCompl passwords $ searchPredicate xpconfig) passwordFunction
-- | A prompt to retrieve a password from a given entry.
--

99
XMonad/Prompt/Unicode.hs Normal file
View File

@@ -0,0 +1,99 @@
{- |
Module : XMonad.Prompt.Unicode
Copyright : (c) 2016 Joachim Breitner
License : BSD-style (see LICENSE)
Maintainer : <mail@joachim-breitner.de>
Stability : stable
A prompt for searching unicode characters by name and inserting them into
the clipboard.
Requires the file @\/usr\/share\/unicode\/UnicodeData.txt@ (shipped in the package
@unicode-data@ on Debian) and the @xsel@ tool.
-}
module XMonad.Prompt.Unicode (
-- * Usage
-- $usage
unicodePrompt
) where
import qualified Data.ByteString.Char8 as BS
import Data.Char
import Data.Maybe
import Data.Ord
import Numeric
import System.Environment
import System.IO
import System.IO.Unsafe
import System.IO.Error
import Control.Arrow
import Data.List
import Text.Printf
import XMonad
import XMonad.Util.Run
import XMonad.Prompt
{- $usage
You can use this module by importing it, along with
"XMonad.Prompt", into your ~\/.xmonad\/xmonad.hs file:
> import XMonad.Prompt
> import XMonad.Prompt.Unicode
and adding an appropriate keybinding, for example:
> , ((modm .|. controlMask, xK_u), unicodePrompt def)
-}
unicodeDataFilename :: String
unicodeDataFilename = "/usr/share/unicode/UnicodeData.txt"
entries :: [(Char, BS.ByteString)]
entries = unsafePerformIO $ do
datE <- tryIOError $ BS.readFile unicodeDataFilename
case datE of
Left e -> do
hPutStrLn stderr $ "Could not read file \"" ++ unicodeDataFilename ++ "\""
hPutStrLn stderr $ show e
hPutStrLn stderr $ "Do you have unicode-data installed?"
return []
Right dat -> return $ sortBy (comparing (BS.length . snd)) $ parseUnicodeData dat
{-# NOINLINE entries #-}
parseUnicodeData :: BS.ByteString -> [(Char, BS.ByteString)]
parseUnicodeData = mapMaybe parseLine . BS.lines
where
parseLine l = do
field1 : field2 : _ <- return $ BS.split ';' l
[(c,"")] <- return $ readHex (BS.unpack field1)
return (chr c, field2)
searchUnicode :: String -> [(Char, String)]
searchUnicode s = map (second BS.unpack) $ filter go entries
where w = map BS.pack $ filter (all isAscii) $ filter ((> 1) . length) $ words $ map toUpper s
go (c,d) = all (`BS.isInfixOf` d) w
-- | Prompt the user for a unicode character to be inserted into the paste buffer of the X server.
unicodePrompt :: XPConfig -> X ()
unicodePrompt config = mkXPrompt Unicode config unicodeCompl paste
where
unicodeCompl [] = return []
unicodeCompl s = do
return $ map (\(c,d) -> printf "%s %s" [c] d) $ take 20 $ searchUnicode s
paste [] = return ()
paste (c:_) = do
runProcessWithInput "xsel" ["-i"] [c]
return ()
data Unicode = Unicode
instance XPrompt Unicode where
showXPrompt Unicode = "Unicode: "
commandToComplete Unicode s = s
nextCompletion Unicode = getNextCompletion

View File

@@ -18,10 +18,16 @@ module XMonad.Prompt.Window
(
-- * Usage
-- $usage
WindowPrompt(..),
windowPrompt,
allWindows,
wsWindows,
XWindowMap,
-- * Deprecated
windowPromptGoto,
windowPromptBring,
windowPromptBringCopy,
WindowPrompt,
) where
import qualified Data.Map as M
@@ -31,11 +37,13 @@ import XMonad
import XMonad.Prompt
import XMonad.Actions.CopyWindow
import XMonad.Actions.WindowBringer
import XMonad.Util.NamedWindows
-- $usage
-- WindowPrompt brings windows to you and you to windows.
-- That is to say, it pops up a prompt with window names, in case you forgot
-- where you left your XChat.
-- WindowPrompt brings windows to you and you to windows. That is to
-- say, it pops up a prompt with window names, in case you forgot
-- where you left your XChat. It also offers helpers to build the
-- subset of windows which is used for the prompt completion.
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
--
@@ -44,13 +52,14 @@ import XMonad.Actions.WindowBringer
--
-- and in the keys definition:
--
-- > , ((modm .|. shiftMask, xK_g ), windowPromptGoto def)
-- > , ((modm .|. shiftMask, xK_b ), windowPromptBring def)
-- > , ((modm .|. shiftMask, xK_g ), windowPrompt def Goto wsWindows)
-- > , ((modm .|. shiftMask, xK_b ), windowPrompt def Bring allWindows)
--
-- The autoComplete option is a handy complement here:
--
-- > , ((modm .|. shiftMask, xK_g ), windowPromptGoto
-- > def { autoComplete = Just 500000 } )
-- > , ((modm .|. shiftMask, xK_g ), windowPrompt
-- > def { autoComplete = Just 500000 }
-- > Goto allWindows)
--
-- The \'500000\' is the number of microseconds to pause before sending you to
-- your new window. This is useful so that you don't accidentally send some
@@ -59,28 +68,50 @@ import XMonad.Actions.WindowBringer
-- For detailed instruction on editing the key binding see
-- "XMonad.Doc.Extending#Editing_key_bindings".
data WindowPrompt = Goto | Bring | BringCopy
-- Describe actions that can applied on the selected window
data WindowPrompt = Goto | Bring | BringCopy | BringToMaster
instance XPrompt WindowPrompt where
showXPrompt Goto = "Go to window: "
showXPrompt Bring = "Bring window: "
showXPrompt BringToMaster
= "Bring window to master: "
showXPrompt BringCopy = "Bring a copy: "
commandToComplete _ c = c
nextCompletion _ = getNextCompletion
-- | Deprecated. Use windowPrompt instead.
windowPromptGoto, windowPromptBring, windowPromptBringCopy :: XPConfig -> X ()
windowPromptGoto = doPrompt Goto
windowPromptBring = doPrompt Bring
windowPromptBringCopy = doPrompt BringCopy
windowPromptGoto c = windowPrompt c Goto windowMap
windowPromptBring c = windowPrompt c Bring windowMap
windowPromptBringCopy c = windowPrompt c BringCopy windowMap
-- | Pops open a prompt with window titles. Choose one, and you will be
-- taken to the corresponding workspace.
doPrompt :: WindowPrompt -> XPConfig -> X ()
doPrompt t c = do
-- | A helper to get the map of all windows.
allWindows :: XWindowMap
allWindows = windowMap
-- | A helper to get the map of windows of the current workspace.
wsWindows :: XWindowMap
wsWindows = withWindowSet (return . W.index) >>= winmap
where
winmap = fmap M.fromList . mapM pair
pair w = do name <- fmap show $ getName w
return (name, w)
-- | A Map where keys are pretty printable window names and values are
-- Xmonad windows identifier.
type XWindowMap = X (M.Map String Window)
-- | Pops open a prompt with window titles belonging to
-- winmap. Choose one, and an action is applied on the
-- selected window, according to WindowPrompt.
windowPrompt :: XPConfig -> WindowPrompt -> XWindowMap -> X ()
windowPrompt c t winmap = do
a <- case t of
Goto -> fmap gotoAction windowMap
Bring -> fmap bringAction windowMap
BringCopy -> fmap bringCopyAction windowMap
wm <- windowMap
Goto -> fmap gotoAction winmap
Bring -> fmap bringAction winmap
BringCopy -> fmap bringCopyAction winmap
BringToMaster -> fmap bringToMaster winmap
wm <- winmap
mkXPrompt t c (compList wm) a
where
@@ -88,10 +119,10 @@ doPrompt t c = do
gotoAction = winAction W.focusWindow
bringAction = winAction bringWindow
bringCopyAction = winAction bringCopyWindow
bringToMaster = winAction (\w s -> W.shiftMaster . W.focusWindow w $ bringWindow w s)
compList m s = return . filter (searchPredicate c s) . map fst . M.toList $ m
-- | Brings a copy of the specified window into the current workspace.
bringCopyWindow :: Window -> WindowSet -> WindowSet
bringCopyWindow w ws = copyWindow w (W.currentTag ws) ws

View File

@@ -41,7 +41,15 @@ debugWindow w = do
case w' of
Nothing ->
return $ "(deleted window " ++ wx ++ ")"
Just (WindowAttributes x y wid ht bw m o) -> do
Just (WindowAttributes
{ wa_x = x
, wa_y = y
, wa_width = wid
, wa_height = ht
, wa_border_width = bw
, wa_map_state = m
, wa_override_redirect = o
}) -> do
c' <- withDisplay $ \d ->
io (getWindowProperty8 d wM_CLASS w)
let c = case c' of

View File

@@ -80,7 +80,7 @@ import Text.ParserCombinators.ReadP
-- Note that, unlike in xmonad 0.4 and previous, you can't use modMask to refer
-- to the modMask you configured earlier. You must specify mod1Mask (or
-- whichever), or add your own @myModMask = mod1Mask@ line.
additionalKeys :: XConfig a -> [((ButtonMask, KeySym), X ())] -> XConfig a
additionalKeys :: XConfig a -> [((KeyMask, KeySym), X ())] -> XConfig a
additionalKeys conf keyList =
conf { keys = \cnf -> M.union (M.fromList keyList) (keys conf cnf) }
@@ -103,7 +103,7 @@ additionalKeysP conf keyList =
--
-- > main = xmonad $ def { terminal = "urxvt" }
-- > `removeKeys` [(mod1Mask .|. shiftMask, n) | n <- [xK_1 .. xK_9]]
removeKeys :: XConfig a -> [(ButtonMask, KeySym)] -> XConfig a
removeKeys :: XConfig a -> [(KeyMask, KeySym)] -> XConfig a
removeKeys conf keyList =
conf { keys = \cnf -> keys conf cnf `M.difference` M.fromList (zip keyList $ repeat ()) }

View File

@@ -21,6 +21,7 @@ module XMonad.Util.ExtensibleState (
, remove
, get
, gets
, modified
) where
import Data.Typeable (typeOf,cast)
@@ -115,3 +116,10 @@ gets = flip fmap get
-- | Remove the value from the extensible state field that has the same type as the supplied argument
remove :: ExtensionClass a => a -> X ()
remove wit = modifyStateExts $ M.delete (show . typeOf $ wit)
modified :: (ExtensionClass a, Eq a) => (a -> a) -> X Bool
modified f = do
v <- get
case f v of
v' | v' == v -> return False
| otherwise -> put v' >> return True

View File

@@ -0,0 +1,138 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Util.Loggers.NamedScratchpad
-- Copyright : (c) Brandon S Allbery <allbery.b@gmail.com>
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Brandon S Allbery <allbery.b@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- 'XMonad.Util.Loggers' for 'XMonad.Util.NamedScratchpad'
--
-----------------------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
module XMonad.Util.Loggers.NamedScratchpad (-- * Usage
-- $usage
nspTrackStartup
,nspTrackHook
,nspActiveIcon
,nspActive
,nspActive') where
import XMonad.Core
import Graphics.X11.Xlib (Window)
import Graphics.X11.Xlib.Extras (Event(..))
import XMonad.Util.Loggers (Logger)
import XMonad.Util.NamedScratchpad (NamedScratchpad(..))
import qualified XMonad.Util.ExtensibleState as XS
import Data.Monoid (All(..))
import Data.Char (chr)
import Control.Monad (forM, foldM)
import qualified Data.IntMap as M
import qualified XMonad.StackSet as W (allWindows)
-- $usage
-- This is a set of 'Logger's for 'NamedScratchpad's.
-- It provides a 'startupHook' and 'handleEventHook' to keep track of
-- 'NamedScratchpad's, and several possible 'Logger's for use in
-- 'XMonad.Hooks.DynamicLog' 'ppExtras'.
--
-- You must add 'nspTrackStartup' to your 'startupHook' to initialize
-- 'NamedScratchpad' tracking and to detect any currently running
-- 'NamedScratchpad's on restart, and 'nspTrackHook' to your 'handleEventHook'
-- to track the coming and going of 'NamedScratchpad's.
--
-- Why would you want to do this? If you aren't using 'EwmhDesktops', this
-- gives you a way to see what 'NamedScratchpad's are running. If you are
-- using 'EwmhDesktops' then you can get that from a taskbar... but you may
-- have noticed that selecting the window from the taskbar moves you to
-- the 'NSP' workspace instead of moving the window to the current workspace.
-- (This is difficult to change; "minimizing" by moving it back to 'NSP'
-- is even harder.)
-- I hide the 'NamedScratchpad's from the taskbar and use this to track
-- them instead (see 'XMonad.Util.NoTaskbar').
-- The extension data for tracking NSP windows
data NSPTrack = NSPTrack [Maybe Window] deriving Typeable
instance ExtensionClass NSPTrack where
initialValue = NSPTrack []
-- | 'startupHook' to initialize scratchpad activation tracking
--
-- > , startupHook = ... <+> nspTrackStartup scratchpads
--
-- If you kickstart the 'logHook', do it /after/ 'nspTrackStartup'!
nspTrackStartup :: [NamedScratchpad] -> X ()
nspTrackStartup ns = do
let ns'i = M.fromList $ zip [0..] $ map (const Nothing) ns
ns' <- withWindowSet $ foldM (isSp ns) ns'i . W.allWindows
XS.put (NSPTrack (map snd $ M.toAscList ns'))
isSp :: [NamedScratchpad] -> M.IntMap (Maybe Window) -> Window -> X (M.IntMap (Maybe Window))
isSp ns ws w = do
n <- runQuery (scratchpadWindow ns) w
return $ case n of
Nothing -> ws
Just n' -> M.insert n' (Just w) ws
scratchpadWindow :: [NamedScratchpad] -> Query (Maybe Int)
scratchpadWindow ns = foldM sp' Nothing (zip [0..] ns)
where sp' :: Maybe Int -> (Int,NamedScratchpad) -> Query (Maybe Int)
sp' r@(Just _) _ = return r
sp' Nothing (n,NS _ _ q _) = q >>= \p -> return $ if p then Just n else Nothing
-- | 'handleEventHook' to track scratchpad activation/deactivation
--
-- > , handleEventHook = ... <+> nspTrackHook scratchpads
nspTrackHook :: [NamedScratchpad] -> Event -> X All
nspTrackHook _ (DestroyWindowEvent {ev_window = w}) = do
XS.modify $ \(NSPTrack ws) -> NSPTrack $ map (\sw -> if sw == Just w then Nothing else sw) ws
return (All True)
nspTrackHook ns (ConfigureRequestEvent {ev_window = w}) = do
NSPTrack ws <- XS.get
ws' <- forM (zip3 [0..] ws ns) $ \(_,w',NS _ _ q _) -> do
p <- runQuery q w
return $ if p then Just w else w'
XS.put $ NSPTrack ws'
return (All True)
nspTrackHook _ _ = return (All True)
-- | 'Logger' for scratchpads' state, using Unicode characters as "icons".
--
-- > , ppExtras = [..., nspActive' iconChars showActive showInactive, ...]
nspActiveIcon :: [Char] -> (String -> String) -> (String -> String) -> Logger
nspActiveIcon icns act inact = do
NSPTrack ws <- XS.get
return $ if null ws
then Nothing
else let icon' n = if n < length icns then icns !! n else '\NUL'
icon n = let c = icon' n
in [if c == '\NUL' then chr (0x2460 + n) else c]
ckact n w = let icn = icon n
in case w of
Nothing -> inact icn
Just _ -> act icn
s = unwords $ zipWith ckact [0..] ws
in Just s
-- | 'Logger' with String-s (and no defaults)
--
-- > , ppExtras = [..., nspActive iconStrs showActive showInactive, ...]
nspActive :: [String] -> (String -> String) -> (String -> String) -> Logger
nspActive icns act inact = do
NSPTrack ws <- XS.get
return $ if null ws
then Nothing
else let ckact n w = let icn = icns !! n
in case w of
Nothing -> inact icn
Just _ -> act icn
s = unwords $ zipWith ckact [0..] ws
in Just s
-- | Variant of the above getting the String-s from the 'NamedScratchpad's
nspActive' :: [NamedScratchpad] -> (String -> String) -> (String -> String) -> Logger
nspActive' ns = nspActive (map name ns)

33
XMonad/Util/NoTaskbar.hs Normal file
View File

@@ -0,0 +1,33 @@
module XMonad.Util.NoTaskbar (-- * Usage
-- $usage
noTaskbar
,markNoTaskbar) where
import XMonad.Core
import XMonad.ManageHook
import Graphics.X11.Xlib (Window)
import Graphics.X11.Xlib.Atom (aTOM)
import Graphics.X11.Xlib.Extras (changeProperty32
,propModePrepend)
import Control.Monad.Reader (ask)
-- $usage
-- Utility functions to hide windows from pagers and taskbars. Mostly useful
-- when EWMH doesn't do what you intend (e.g. for 'NamedScratchpad' windows you
-- probably don't want to be dumped into the 'NSP' workspace).
-- | A 'ManageHook' to mark a window to not be shown in pagers or taskbars.
noTaskbar :: ManageHook
noTaskbar = ask >>= (>> idHook) . liftX . markNoTaskbar
-- | An 'X' action to mark a window to not be shown in pagers or taskbars.
markNoTaskbar :: Window -> X ()
markNoTaskbar w = withDisplay $ \d -> do
ws <- getAtom "_NET_WM_STATE"
ntb <- getAtom "_NET_WM_STATE_SKIP_TASKBAR"
npg <- getAtom "_NET_WM_STATE_SKIP_PAGER"
io $ changeProperty32 d w ws aTOM propModePrepend [fi ntb,fi npg]
-- sigh
fi :: (Integral i, Num n) => i -> n
fi = fromIntegral

View File

@@ -94,7 +94,7 @@ runProcessWithInputAndWait cmd args input timeout = io $ do
--
-- to the top of your file) or use seconds in prefix form:
--
-- > 5.5 seconds
-- > seconds 5.5
seconds :: Rational -> Int
seconds = fromEnum . (* 1000000)

177
XMonad/Util/TreeZipper.hs Normal file
View File

@@ -0,0 +1,177 @@
{-# LANGUAGE RecordWildCards #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TreeSelect
-- Copyright : (c) Tom Smeets <tom.tsmeets@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Tom Smeets <tom.tsmeets@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- <https://wiki.haskell.org/Zipper Zipper> over the "Data.Tree" data structure.
-- This module is based on <http://hackage.haskell.org/package/rosezipper rosezipper>.
--
-----------------------------------------------------------------------------
module XMonad.Util.TreeZipper(
-- * Data structure
TreeZipper(..)
, cursor
-- * Conversion
, fromForest
, toForest
, getSubForest
-- * Navigation
, rootNode
, parent
, children
, nextChild
, previousChild
-- * Utils
, nodeDepth
, nodeIndex
, followPath
, findChild
, isLeaf
, isRoot
, isLast
, isFirst
) where
import Data.Tree
-- | A <https://wiki.haskell.org/Zipper Zipper> over the "Data.Tree" data structure.
data TreeZipper a = TreeZipper { tz_current :: Tree a -- ^ the currently focused sub-tree under the cursor
, tz_before :: Forest a -- ^ all sub-tree's to the /left/ of the cursor that have the same parent
, tz_after :: Forest a -- ^ all sub-tree's to the /right/ of the cursor that have the same parent
, tz_parents :: [(Forest a, a, Forest a)] -- ^ list zippers for each parent level, the first element is the current parent
}
-- ^ Very crappy visualization of the 'TreeZipper' data structure
--
-- @
-- (tz_parents)
-- ([*], *, [*])
-- ([*, *], *, [])
-- ([], * [*, *])
-- | | |
-- +-------+--------+-------+------+ +-*-+ *
-- | | | | | | |
-- (tz_before) (tz_current) (tz_after) * *
-- | | | |
-- +-*-+ * * *
-- | |
-- * *
-- @
-- | Get the highlighted value
cursor :: TreeZipper a -> a
cursor = rootLabel . tz_current
-- | Create a 'TreeZipper' from a list of 'Data.Tree.Tree's focused on the first element
fromForest :: Forest a -> TreeZipper a
fromForest [] = error "XMonad.Util.TreeZipper.fromForest: can't create a TreeZipper from an empty list!"
fromForest (x:xs) = TreeZipper { tz_current = x
, tz_before = []
, tz_after = xs
, tz_parents = []
}
-- | Convert the entire zipper back to a 'Data.Tree.Forest'
toForest :: TreeZipper a -> Forest a
toForest = getSubForest . rootNode
-- | Create a 'Data.Tree.Forest' from all the children of the current parent
getSubForest :: TreeZipper a -> Forest a
getSubForest TreeZipper{..} = reverse tz_before ++ tz_current : tz_after
-- | Go to the upper most node such that
-- nothing is before nor above the cursor
rootNode :: TreeZipper a -> TreeZipper a
rootNode = f
where
f z = maybe (g z) f $ parent z
g z = maybe z g $ previousChild z
-- | Move to the parent node
parent :: TreeZipper a -> Maybe (TreeZipper a)
parent t = case tz_parents t of
(xs,a,ys) : ps -> Just
TreeZipper { tz_current = Node a (reverse (tz_before t) ++ tz_current t : tz_after t)
, tz_before = xs
, tz_after = ys
, tz_parents = ps
}
[] -> Nothing
-- | Move the cursor one level down to the first node
children :: TreeZipper a -> Maybe (TreeZipper a)
children z = case subForest $ tz_current z of
(n:xs) -> Just
TreeZipper { tz_current = n
, tz_before = []
, tz_after = xs
, tz_parents = (tz_before z, cursor z, tz_after z) : tz_parents z
}
[] -> Nothing
-- | Go to the next child node
nextChild :: TreeZipper a -> Maybe (TreeZipper a)
nextChild z = case tz_after z of
(n:xs) -> Just
TreeZipper { tz_current = n
, tz_before = tz_current z : tz_before z
, tz_after = xs
, tz_parents = tz_parents z
}
[] -> Nothing
-- | Go to the previous child node
previousChild :: TreeZipper a -> Maybe (TreeZipper a)
previousChild z = case tz_before z of
(n:xs) -> Just
TreeZipper { tz_current = n
, tz_before = xs
, tz_after = tz_current z : tz_after z
, tz_parents = tz_parents z
}
[] -> Nothing
-- | How many nodes are above this one?
nodeDepth :: TreeZipper a -> Int
nodeDepth = length . tz_parents
-- | How many nodes are before the cursor? (on the current level)
nodeIndex :: TreeZipper a -> Int
nodeIndex = length . tz_before
-- | follow a Path specified by the list of nodes
followPath :: Eq b => (a -> b) -> [b] -> TreeZipper a -> Maybe (TreeZipper a)
followPath _ [] z = Just z
followPath f [x] z = findChild (\y -> f y == x) z
followPath f (x:xs) z = findChild (\y -> f y == x) z >>= children >>= followPath f xs
-- | go to the first node next to the cursor that matches
findChild :: (a -> Bool) -> TreeZipper a -> Maybe (TreeZipper a)
findChild f z | f (cursor z) = Just z
| otherwise = nextChild z >>= findChild f
-- | Check whenther this is a leaf node
isLeaf :: TreeZipper a -> Bool
isLeaf = null . subForest . tz_current
-- | Check whenther this is a leaf node
isRoot :: TreeZipper a -> Bool
isRoot = null . tz_parents
-- | Check whenther this the last child
isLast :: TreeZipper a -> Bool
isLast = null . tz_after
-- | Check whenther this the first child
isFirst :: TreeZipper a -> Bool
isFirst = null . tz_before

43
XMonad/Util/Ungrab.hs Normal file
View File

@@ -0,0 +1,43 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Util.Ungrab
-- Copyright : (c) 2016 Brandon S Allbery
-- License : BSD-style (see xmonad/LICENSE)
--
-- Maintainer : allbery.b@gmail.com
-- Stability : unstable
-- Portability : unportable
--
-- Allow releasing xmonad's keyboard grab
--
-----------------------------------------------------------------------------
module XMonad.Util.Ungrab
( -- * Usage:
-- $usage
unGrab
) where
import Graphics.X11.Xlib.Extras (currentTime)
import Graphics.X11.Xlib.Misc (ungrabKeyboard, ungrabPointer)
import XMonad.Core
-- $usage
-- Start a keyboard action with this if it is going to run something
-- that needs to do a keyboard, pointer, or server grab. For example,
--
-- > , ((modm .|. controlMask, xK_p), unGrab >> spawn "scrot")
--
-- (Other examples are screen lockers and "gksu".)
-- This avoids needing to insert a pause/sleep before running the
-- command.
--
-- xmonad retains the keyboard grab during key actions because if they
-- use a Submap, they need the keyboard to be grabbed, and if they had
-- to assert their own grab then the asynchronous nature of X11 allows
-- race conditions between xmonad, other clients, and the X server that
-- would cause keys to sometimes be "leaked" to the focused window.
-- | Release xmonad's keyboard grab, so other grabbers can do their thing.
unGrab :: X ()
unGrab = withDisplay $ \d -> io (ungrabKeyboard d currentTime >> ungrabPointer d currentTime)

View File

@@ -50,23 +50,25 @@ flag use_xft
flag testing
description: Testing mode
manual: True
default: False
library
build-depends: base >= 3 && < 5,
containers,
directory,
extensible-exceptions,
filepath,
old-locale,
old-time,
process,
random,
mtl >= 1 && < 3,
unix,
X11>=1.6.1 && < 1.7,
xmonad>=0.12 && < 0.13,
utf8-string
build-depends: base >= 4.5 && < 5,
bytestring >= 0.10 && < 0.11,
containers >= 0.5 && < 0.6,
directory,
extensible-exceptions,
filepath,
old-locale,
old-time,
process,
random,
mtl >= 1 && < 3,
unix,
X11>=1.7 && < 1.8,
xmonad>=0.12 && < 0.13,
utf8-string
if flag(use_xft)
build-depends: X11-xft >= 0.2
@@ -81,9 +83,6 @@ library
if impl(ghc >= 6.12.1)
ghc-options: -fno-warn-unused-do-bind
if impl (ghc == 6.10.1) && arch (x86_64)
ghc-options: -O0
exposed-modules: XMonad.Doc
XMonad.Doc.Configuring
XMonad.Doc.Extending
@@ -135,6 +134,7 @@ library
XMonad.Actions.SwapWorkspaces
XMonad.Actions.TagWindows
XMonad.Actions.TopicSpace
XMonad.Actions.TreeSelect
XMonad.Actions.UpdateFocus
XMonad.Actions.UpdatePointer
XMonad.Actions.Warp
@@ -266,6 +266,7 @@ library
XMonad.Layout.SimpleFloat
XMonad.Layout.Simplest
XMonad.Layout.SimplestFloat
XMonad.Layout.SortedLayout
XMonad.Layout.Spacing
XMonad.Layout.Spiral
XMonad.Layout.Square
@@ -298,6 +299,7 @@ library
XMonad.Prompt.Shell
XMonad.Prompt.Ssh
XMonad.Prompt.Theme
XMonad.Prompt.Unicode
XMonad.Prompt.Window
XMonad.Prompt.Workspace
XMonad.Prompt.XMonad
@@ -312,9 +314,11 @@ library
XMonad.Util.Image
XMonad.Util.Invisible
XMonad.Util.Loggers
XMonad.Util.Loggers.NamedScratchpad
XMonad.Util.NamedActions
XMonad.Util.NamedScratchpad
XMonad.Util.NamedWindows
XMonad.Util.NoTaskbar
XMonad.Util.Paste
XMonad.Util.PositionStore
XMonad.Util.RemoteWindows
@@ -327,7 +331,9 @@ library
XMonad.Util.StringProp
XMonad.Util.Themes
XMonad.Util.Timer
XMonad.Util.TreeZipper
XMonad.Util.Types
XMonad.Util.Ungrab
XMonad.Util.WindowProperties
XMonad.Util.WindowState
XMonad.Util.WorkspaceCompare