1962 Commits

Author SHA1 Message Date
Tony Zorman
9217ac18e9 cabal: Bump xmonad dependency 2024-02-03 16:06:47 +01:00
Tony Zorman
c65ea8d3ab Bump version to 0.18.0 2024-02-03 16:02:47 +01:00
Tony Zorman
d54d37e344 Merge pull request #869 from dcousens/patch-1
X.P: Fix some typos in comments
2024-01-24 14:40:44 +01:00
Daniel Cousens
903e50a65c X.P: Fix some typos in comments 2024-01-25 00:17:18 +11:00
dependabot[bot]
f3ee6289ec build(deps): bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)
2024-01-22 11:55:52 +00:00
brandon s allbery kf8nh
318ee92e61 only sink window if actually fullscreened
`EwmhFullscreen` unconditionally sinks windows in response to a
`_NET_WM_STATE` root window message removing `_NET_WM_STATE_FULLSCREEN`.
Unfortunately, at least some versions of either the Gtk or GNOME
libraries send this on startup while restoring a window's last
known state, which means a `manageHook` `doFloat` will be undone.

This change ignores the remove if the window is not fullscreen.

A followup issue, #865, has been added for the follow-on problem
that the floating state of a window is not restored on removal of
the fullscreen state.

Fixes: #820
2024-01-21 12:07:09 -05:00
Ilya V. Portnov
a5fb7e021a X.L.DecorationEx: extensible mechanism for window decorations (#857)
* First version of DecorationEx.

* Fixed most warnings.

* Fix build error with ghc-9.8.1.

* Fix title shrinking with text decoration.

* Add convinience re-exports.

* Get rid of orphan instances.

* Fix a couple of warnings.

* Rename X.L.DecorationEx.Types -> X.L.DecorationEx.Common

* Add instance Default StandardCommand.

* Fix some typos and formatting

thanks to @geekosaur

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>

* Fix reference to xmonad.hs

See also #859

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>

* Fix reference to xmonad.hs

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>

* Fix formatting

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>

* Fix some typos and formatting

thanks to @geekosaur

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>

* Remove commented code.

* Update CHANGES.md.

* calcWidgetPlace is now allowed to return rectangle with any X,

but that will be ignored.

* More generic instance for DecorationWidget GenericWidget.

* Replace explicit definition of `fi` with import from X.Prelude.

thanks to @slotThe.

* Move fetch-all pattern to the end of definition.

thanks to @slotThe.

* X.L.DecorationEx: Add screenshot

---------

Co-authored-by: brandon s allbery kf8nh <allbery.b@gmail.com>
Co-authored-by: Tony Zorman <soliditsallgood@mailbox.org>
2024-01-21 12:02:08 -05:00
Tomáš Janoušek
09e37131ca Merge pull request #863 from xmonad/haskell-ci-update
ci: Regenerate haskell-ci
2024-01-17 11:54:01 +00:00
github-actions[bot]
39310a6695 ci: Regenerate haskell-ci 2024-01-17 11:28:14 +00:00
github-actions[bot]
14e80f2f74 ci: Bump GHC patch versions in tested-with 2024-01-17 11:28:13 +00:00
dependabot[bot]
2272691ada build(deps): bump cachix/install-nix-action from 24 to 25
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 24 to 25.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v24...v25)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 16:37:58 +00:00
Tomas Janousek
4bb6a2eedb X.H.EwmhDesktops: Fix haddock markup
Fixes: 2dcc3a92e7 ("X.H.EwmhDesktops: Add (un)fullscreen hooks")
2024-01-14 10:20:27 +00:00
Tony Zorman
7cb6b0f87b Merge pull request #861 from dcousens/patch-1
XMonad.Prompt: export getCurrentCompletions (and setCurrentCompletions)
2024-01-10 08:06:04 +01:00
Daniel Cousens
385d7e9579 X.P: Export {selected,setCurrent,getCurrent}Completion[s] 2024-01-10 08:04:59 +01:00
Tony Zorman
99b24f314b Merge pull request #860 from dcousens/patch-1
Fix Xmonad.Prompt.Input usage example
2023-12-28 16:02:38 +01:00
Daniel Cousens
9f51b2a1d6 Fix example Xmonad.Prompt.Input usage example 2023-12-28 00:54:36 +11:00
Tony Zorman
82e4260084 Merge pull request #859 from slotThe/kill-dots
`~/.xmonad/xmonad.hs` -> `xmonad.hs`
2023-12-23 08:08:43 +01:00
Tony Zorman
5ceaed8126 Merge pull request #858 from dcousens/fix-min-width
Fix minimum widths for Shrink and Expand
2023-12-23 08:07:57 +01:00
Daniel Cousens
cd32cac54b X.L.TwoPane[Persistent]: Add minimum widths for Shrink and Expand 2023-12-23 08:07:00 +01:00
Tony Zorman
b1b3c4c469 ~/.xmonad/xmonad.hs -> xmonad.hs
With XDG support so firmly ingrained now, it's about time we stop
hard-coding the configuration path in the docs.
2023-12-22 18:17:17 +01:00
Tony Zorman
c01cd3a33b Merge pull request #848 from portnov/master
Add new module: X.L.CircleEx: advanced version of Circle layout
2023-12-21 19:58:00 +01:00
Ilya V. Portnov
4f2a5c7f43 X.L.Circle: Deprecate in favour of X.L.CircleEx 2023-12-21 19:52:20 +01:00
Ilya V. Portnov
19edf5a7a8 X.L.CircleEx: Init 2023-12-21 19:52:20 +01:00
Tony Zorman
75d67cfb1d Merge pull request #856 from l29ah/prompt-return-normal-vim
X.Prompt: handle Return key in vim normal mode
2023-12-20 05:58:38 +01:00
Sergey Alirzaev
9609e0ef2e X.Prompt: handle Return key in vim normal mode 2023-12-20 05:57:58 +01:00
Tomas Janousek
3613d4d543 X.U.Ungrab: Avoid "Ambiguous occurrence" error in user configs 2023-12-18 10:32:03 +00:00
Tony Zorman
d54a7e21dd Merge pull request #853 from liskin/ewmh-desktop-managehook
X.H.{EwmhDesktops,ManageHelpers}: Add _NET_WM_DESKTOP-handling ManageHook
2023-12-18 10:53:26 +01:00
Tony Zorman
0fe948feb3 Merge pull request #852 from liskin/renamed-named
X.L.Renamed: Provide "named" convenience alias
2023-12-18 10:48:19 +01:00
Tomas Janousek
3c329e0aad X.H.{EwmhDesktops,ManageHelpers}: Add _NET_WM_DESKTOP-handling ManageHook
Useful for restoring browser windows to where they were before restart
(which is something one should do several times a week as security
updates get released).
2023-12-17 21:58:57 +00:00
Tomas Janousek
92a7c030b2 X.L.Renamed: Provide "named" convenience alias
I believe this common use-case for the deprecated X.L.Named should still
be provided somewhere, rather than telling everybody to let-define this
themselves.

The other one – `nameTail` – only has about 6 uses in publicly available
configs (https://github.com/search?q=nameTail+path%3Axmonad&type=code),
so I'm not adding that one but I'm happy to be convinced to add it too.

Related: 3bf9d80c40 ("XMonad.Layout.Named: Deprecate")
2023-12-17 21:49:49 +00:00
Tony Zorman
e75eb16a93 Merge pull request #850 from slotThe/fix/prompt-ignores-left
X.Prompt: Execute keypress when it has an action associated to it
2023-12-17 13:39:27 +01:00
Tony Zorman
00993d46fa X.Prompt: Execute keypress when it has an action associated to it
It might be that the keypress does not have a valid stroke associated to
it, but is still bound to an action (e.g., xK_Left an friends). In this
case, we still want to execute it.

Closes: https://github.com/xmonad/xmonad-contrib/issues/845
2023-12-16 15:42:53 +01:00
Tony Zorman
5c30cadaf6 Merge pull request #843 from iogrt/ungrab
deprecate `XMonad.Util.Ungrab`
2023-12-09 08:18:51 +01:00
iogrt
22372abaab X.U.Ungrab: Deprecate 2023-12-09 07:49:49 +01:00
Tony Zorman
a34287dda6 Merge pull request #847 from xmonad/haskell-ci-update
ci: Regenerate haskell-ci
2023-12-09 07:34:19 +01:00
github-actions[bot]
34d55ede85 ci: Regenerate haskell-ci 2023-12-09 03:13:33 +00:00
dependabot[bot]
7ce7ddf9e6 build(deps): bump cachix/install-nix-action from 23 to 24
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 23 to 24.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v23...v24)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 16:51:51 +00:00
Tony Zorman
7464b36afa NIX.md: Add flakes semi-walkthrough 2023-12-02 16:04:49 +01:00
Tony Zorman
45dd67433c Merge pull request #844 from xmonad/haskell-ci-update
ci: Regenerate haskell-ci
2023-11-18 08:06:46 +01:00
github-actions[bot]
ff8d4ebb94 ci: Regenerate haskell-ci 2023-11-18 03:15:29 +00:00
github-actions[bot]
f9d98e0936 ci: Bump GHC patch versions in tested-with 2023-11-18 03:15:29 +00:00
Tomáš Janoušek
ad28ae1daa Merge pull request #842 from xmonad/haskell-ci-update
ci: Regenerate haskell-ci
2023-11-13 00:28:50 +00:00
Tomas Janousek
192c0da831 ci: Only build haddock for hackage with the latest GHC
Cabal 3.10.2.0 exposes a bug in Haddock shipped with GHC 9.0 and 9.2, so
we need to work around it by bumping the version of GHC/Haddock we use
for building/uploading docs to Hackage, and to prevent build failures we
don't ever try to build haddocks for Hackage with older versions of
GHC/Haddock.

Related: https://github.com/haskell/haddock/issues/1582#issuecomment-1611412223
Related: https://github.com/haskell/cabal/issues/8326
Related: https://github.com/haskell/cabal/issues/9060
Related: https://github.com/haskell/cabal/pull/9073
Related: https://github.com/haskell/cabal/pull/9049
2023-11-12 23:58:14 +00:00
github-actions[bot]
e38e19edc1 ci: Regenerate haskell-ci 2023-11-11 03:20:02 +00:00
Tony Zorman
8035db1bd0 Merge pull request #841 from jpolchlo/docs/unicode-prompt
Add documentation for unicode prompt
2023-11-08 10:34:40 +01:00
jpolchlo
da566d63e6 X.P.Unicode: Add docs about UnicodeData.txt
Having this file is required for the prompt to work, and how to obtain
it may not be immediately obvious.
2023-11-08 10:33:46 +01:00
Tony Zorman
c176a752de Merge pull request #838 from xmonad/haskell-ci-update
ci: Regenerate haskell-ci
2023-10-28 12:55:13 +02:00
Tomas Janousek
532d64a0f9 ci: Disable x-partial warnings in the testsuite
Related: https://github.com/xmonad/xmonad/pull/477
2023-10-28 11:29:36 +01:00
github-actions[bot]
487b6d1677 ci: Regenerate haskell-ci 2023-10-28 11:44:37 +02:00
github-actions[bot]
a9ba19fb24 ci: Bump GHC patch versions in tested-with 2023-10-28 11:44:37 +02:00
Tony Zorman
105e529826 Fix partial uses of head
Fixes: https://github.com/xmonad/xmonad-contrib/issues/830
Related: https://github.com/xmonad/xmonad-contrib/pull/836
2023-10-28 11:41:24 +02:00
Tony Zorman
42179b8625 X.U.EZConfig: Make readKeySequence return non-empty list 2023-10-26 14:18:31 +02:00
Tony Zorman
d668e4cb10 X.Prelude: Add takeS 2023-10-26 11:52:40 +02:00
Tony Zorman
f654082c5b Merge pull request #837 from philib/master
introduce single active scratchpad hook
2023-10-24 21:10:00 +02:00
Tony Zorman
e1dc2a3750 X.U.NamedScratchpad: Extract common parts of ns{HideOnFocusLoss,SingleScratchpadPerWorkspace} 2023-10-24 21:01:22 +02:00
philib
105cbe0362 X.U.NamedScratchpad: Add nsSingleScratchpadPerWorkspace
A logHook to allow only one active scratchpad per workspace.
2023-10-24 21:00:46 +02:00
Tony Zorman
9c4325f3ef Merge pull request #836 from slotThe/wx-partial
Address some `-Wx-Partial` warnings
2023-10-20 08:21:59 +02:00
Tony Zorman
46a26487ba Reduce head usage 2023-10-20 08:13:24 +02:00
Tony Zorman
7680ebb93b Import X.Prelude unqualified if necessary
This gets rid of, for example,

    The import of ‘liftA2’ from module ‘XMonad.Prelude’ is redundant

-type warnings.
2023-10-20 08:13:23 +02:00
Tony Zorman
c3d16bfa99 X.L.Groups: Rewrite gen using infinite streams 2023-10-20 08:13:23 +02:00
Tony Zorman
7599c898ef X.Prelude: Add infinite stream type
Stolen from X.A.MostRecentlyUsed. This can be used in favour of lists
when we know the generated lists are definitely infinite.
2023-10-20 08:13:23 +02:00
Tony Zorman
8ee129483a X.U.Stack: Add zipperFocusedAtFirstOf 2023-10-20 08:13:02 +02:00
Tony Zorman
52a40f376c Replace tail with drop 1
Where appropriate.
2023-10-15 18:46:28 +02:00
Tony Zorman
c8c81474a2 X.A.CycleWindows: Move rot{Up,Down} to X.A.RotSlaves
Reexport them instead.
2023-10-15 11:00:35 +02:00
Tony Zorman
8c0ca8b9fe X.Prompt: Add isModifier
It seems sensible to abstract this away, if only to make the code a tad
more readable.
2023-10-11 09:43:26 +02:00
Tony Zorman
3cd1b066a2 Merge pull request #835 from slotThe/deprecate-cross
X.L.Cross: Deprecate
2023-10-10 07:35:28 +02:00
Tony Zorman
ba5011b874 Merge pull request #834 from slotThe/feat/prompt/cycle-backwards
X.Prompt: Allow for backwards cycling of completions
2023-10-09 16:36:42 +02:00
Tony Zorman
60867bdd2d X.L.Cross: Deprecate
The module has badly bitrotted, and is in such a state that it's
unlikely anyone is using it currently. Better alternatives exist, so
just deprecating seems appropriate here.

Closes: https://github.com/xmonad/xmonad-contrib/issues/793
2023-10-09 14:32:32 +02:00
Tony Zorman
8f8730b222 Merge pull request #833 from slotThe/pass-otp-type
X.P.Pass: Add passOTPTypePrompt
2023-10-06 10:03:17 +02:00
Tony Zorman
7854f7766e X.P.Pass: Properly escape backslashes 2023-10-06 09:07:11 +02:00
Tony Zorman
fde30fc073 X.P.Pass: Add passOTPTypePrompt 2023-10-06 09:07:11 +02:00
Tony Zorman
431ba22e3c X.P.Pass: Clean up code 2023-10-06 09:07:11 +02:00
Tony Zorman
570bd17a51 cabal: Bump containers dependency
Version 0.7 was confirmed to build via

    cabal build --flags=pedantic --constraint='containers >= 0.7'
2023-10-04 13:09:58 +02:00
Tony Zorman
4c0d3cac8d X.Prompt: Allow for backwards cycling of completions
+ Add a new prevCompletionKey to XPConfig, in order to cycle backwards.
  Bound to S-<Tab> by default.

+ Already handle null keystrings (times when only a modifier was
  pressed) in handleMain, such that completions aren't cleared
  prematurely.

+ Augment nextComplIndex (now computeComplIndex) with the ability to go
  in an arbitrary 1-dimensional direction. As a result, that function,
  as well as handleCompletion and handleCompletionMain now take an
  additional Direction1D argument.

Based on: https://github.com/solomon-b/xmonad-contrib/tree/feature/scrolling-prompt-completions
Fixes: https://github.com/xmonad/xmonad-contrib/issues/831

Co-authored-by: Solomon Bothwell <ssbothwell@gmail.com>
2023-10-04 09:27:53 +02:00
Christina Sørensen
a379850f50 XMonad.actions.search: Add NixOS and home-manager searchEngines (#832)
* feat(search): add nixos as searchEngine
* feat(search): add homeManager as searchEngine
* docs(CHANGES): add nixos, homeManager to searchEngine section

Signed-off-by: Christina Sørensen <christina@cafkafk.com>
2023-09-27 11:05:09 -04:00
Tony Zorman
7bb1f0b887 stack: Bump resolver to lts-21.12
This also bumps the default GHC version from 9.4.6 to 9.4.7.
2023-09-23 14:14:30 +02:00
Tony Zorman
4f6a9deaf8 Merge pull request #829 from slotThe/ghc/head
X.Prelude: Compatibility with base-4.18.0.0
2023-09-20 17:53:23 +02:00
Tony Zorman
32ff4db11c cabal: Bump bytestring dependency
Related: https://mail.haskell.org/pipermail/xmonad/2023-September/015647.html
2023-09-18 17:39:27 +02:00
Tomas Janousek
ac9265e774 ci: Replace deprecated haskell/actions/hlint-*
See https://github.com/haskell/actions/pull/301#issuecomment-1722353522
2023-09-18 15:42:25 +01:00
Tomas Janousek
c9a096ac1f ci: Replace deprecated haskell/actions/setup
See https://github.com/haskell/actions/pull/301 and
https://github.com/haskell/actions/pull/301/files
2023-09-17 23:17:05 +01:00
dependabot[bot]
51ba23b776 build(deps): bump actions/checkout from 3 to 4 (except haskell-ci workflow)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)
2023-09-17 21:22:45 +01:00
Tomas Janousek
b358c90a73 ci: Drop unnecessary cmd from "Install packdeps"
Not needed since https://github.com/haskell/actions/pull/165 (Jan 2023).
2023-09-17 21:21:18 +01:00
Tony Zorman
000cd14799 X.Prelude: Compatibility with base-4.18.0.0
Will ship with GHC 9.8.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/826
2023-09-17 12:23:22 +02:00
Tony Zorman
0e2d3c159d Merge pull request #827 from xmonad/dependabot/github_actions/cachix/install-nix-action-23
build(deps): bump cachix/install-nix-action from 22 to 23
2023-09-04 21:48:52 +02:00
dependabot[bot]
63a758243a build(deps): bump cachix/install-nix-action from 22 to 23
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 22 to 23.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v22...v23)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-04 16:50:28 +00:00
Tony Zorman
2df26cf9f8 stack: Bump resolver to 21.6
This is the newest lts resolver for 9.4.5.
2023-08-12 14:22:26 +02:00
Tomas Janousek
6912eca829 X.A.WorkspaceNames: Use history for completion in renameWorkspace 2023-08-11 00:12:43 +01:00
Tony Zorman
348df92b89 X.U.Run: Fix definitions of >&&> and >||>
Whoops.

Fixes: 1b7fd6d8c9
2023-08-09 06:07:10 +02:00
Tony Zorman
1b7fd6d8c9 X.U.Run: Add >&&> and >||> 2023-08-08 20:08:11 +02:00
Tony Zorman
0ca3ce7a18 X.U.Run: Add toInput 2023-08-08 20:01:23 +02:00
Tony Zorman
bf41a85d9c Merge pull request #822 from Zawaken/magnifiercxy
Add magnifiyxy combinator to XMonad.Layout.Magnifier
2023-08-06 09:35:48 +02:00
Zawaken
a0bfa8a447 X.L.Magnifier: Add magnifyxy
The combinator allows for different magnification to be used in the
horizontal and vertical direction.
2023-08-06 09:28:23 +02:00
Tony Zorman
7062b75ea9 Merge pull request #819 from slotThe/ci/bump
Bump cabal/stack CI
2023-07-18 09:35:44 +02:00
Tony Zorman
34b544b7a1 ci/cabal: Bump GHC versions 2023-07-16 17:27:16 +02:00
Tony Zorman
5b5a51787c ci/stack: Add lts-21 resolver 2023-07-16 17:26:49 +02:00
Tomáš Janoušek
4d0f3ee944 Merge pull request #818 from geekosaur/debugwindow-fix-decode
fix double decode in `debugWindow`
2023-06-26 14:56:14 +02:00
Tony Zorman
e02400b1c7 X.A.Prefix: Add orIfPrefixed
- Generalise signature of withPrefixArgument, in order to accommodate
  this.
2023-06-23 08:14:38 +02:00
brandon s allbery kf8nh
4a60866ea4 fix double decode in debugWindow
At some point `peekCString` became locale aware. This is a double
bug, since (a) `decodeString` was being applied to the result and
(b) the locale might not be UTF-8, but the string being decoded
always is.

The fix is to use `peekCAString` which bypasses the locale decode,
then continuing to do UTF-8 decode.
2023-06-22 06:25:56 -04:00
Tomáš Janoušek
4bdcab8bf6 Merge pull request #817 from xmonad/dependabot/github_actions/cachix/install-nix-action-22
build(deps): bump cachix/install-nix-action from 21 to 22
2023-06-19 22:52:20 +02:00
dependabot[bot]
f2ac181616 build(deps): bump cachix/install-nix-action from 21 to 22
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 21 to 22.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v21...v22)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 17:00:04 +00:00
Tomáš Janoušek
b6c0dd9cfc Merge pull request #816 from xmonad/dependabot/github_actions/cachix/install-nix-action-21
build(deps): bump cachix/install-nix-action from 20 to 21
2023-05-29 20:15:44 +02:00
dependabot[bot]
611317f398 build(deps): bump cachix/install-nix-action from 20 to 21
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 20 to 21.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v20...v21)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-29 16:59:34 +00:00
Tony Zorman
ad48cdc2cb Merge pull request #814 from geekosaur/808-supported-partial-struts
add `_NET_WM_STRUT_PARTIAL` to `_NET_SUPPORTED`
2023-05-14 12:28:06 +02:00
brandon s allbery kf8nh
1486d076dc add _NET_WM_STRUT_PARTIAL to _NET_SUPPORTED
For docks that don't support `_NET_WM_STRUT` any more,
notably `xfce4-panel`.
2023-05-12 12:29:37 -04:00
brandon s allbery kf8nh
1243bbbded Fix many bugs and shortcomings in debugEventsHook
Added support for several more properties, and fixed parsing of many
others. Still doesn't handle COMPOUND_TEXT and the code in DebugWindow
is wrong. I have correct code in C++ but it will require some work to
translate to Haskell so it can be used in both places.
2023-04-26 13:24:01 -04:00
Mahdi Seyedan
cf00d2d237 Add CenterMainFluid layout 2023-04-21 10:23:13 -04:00
brandon s allbery kf8nh
87ae269b82 Put a cap on window names
It turns out qutebrowser will place an entire `data:` URL in
`_NET_WM_NAME`, up to at least 389K characters including
newlines and possibly binary characters.

Clamping window titles to the first line, and to 2K chars
because `defaultShrinker` is quadratic in the title length.
2023-04-19 12:53:33 -04:00
Tomáš Janoušek
673de11ca8 Merge pull request #768 from liskin/fullscreen-hooks
Add (un)fullscreen hooks and float-restoring toggleFullFloat action
2023-04-01 12:32:01 +02:00
Tomas Janousek
02bd9eb0c0 CHANGES: Document X.A.ToggleFullFloat and setEwmhFullscreenHooks 2023-04-01 12:06:58 +02:00
Tomas Janousek
d86f9ade22 Add X.A.ToggleFullFloat - state-remembering fullscreen hooks
Fixes: https://github.com/xmonad/xmonad-contrib/issues/456
Related: https://github.com/xmonad/xmonad-contrib/issues/394
Related: https://github.com/xmonad/xmonad-contrib/pull/626
2023-04-01 12:06:58 +02:00
Tomas Janousek
2dcc3a92e7 X.H.EwmhDesktops: Add (un)fullscreen hooks
Fairly straightforward, just add two hooks for (un)fullscreening. There
are multiple motivations for this:

* Users are calling for unfullscreened windows to revert back to their
  original location if they were floating.

* XMonad.Layout.Fullscreen uses some deprecated exports from
  XMonad.Hooks.EwmhDesktops and reimplements fullscreenEventHook.

This commit only adds the hooks. Neither of the motivations are dealt
with yet, so the docs are a bit terse still.

Related: https://github.com/xmonad/xmonad-contrib/issues/456
Related: https://github.com/xmonad/xmonad-contrib/issues/394
Related: https://github.com/xmonad/xmonad-contrib/pull/626
2023-04-01 12:06:58 +02:00
Tony Zorman
815a595b46 stack: Bump resolver to lts-20.16
We test against 9.2.7 now, so we should make our stack config reflect
that—plus, it's more convenient for users, since one is more likely to
already have the latest minor version of GHC installed.

Related: 67064ddd9264bbe39d6fa88fd8336086817dd0db
2023-03-31 07:50:09 +02:00
Tony Zorman
1d84db959c ci: Bump 9.2 and 9.4 minor versions
The stack CI already tests against 9.2.7 instead of 9.2.5 (as the cabal
file said), since we just specify the major version of the LTS resolver,
and lts-20 is up to 9.2.7 by now. Not much has changed since 9.2.5, but
update the haskell-ci workflow regardless. Likewise, 9.4 can be bumped
one minor version, so do that as well.
2023-03-31 07:48:02 +02:00
Tony Zorman
f127f71c91 X.Prompt: Alias C-m to RET in Emacs/Vim bindings
Both programs interpret C-m as RET, so the prompt should reflect this as
well.
2023-03-29 08:26:20 +02:00
Tony Zorman
fb63987ac8 X.Prompt: Factor out how to accept the current selection 2023-03-29 08:22:26 +02:00
Tony Zorman
635711e994 ci: Test against GHC 9.6.1
+ Regenerate haskell-ci and adjust relevant patches.
  - Remove haskell-ci-dependabot.patch, as it is no longer necessary.

Related: https://github.com/xmonad/xmonad-contrib/issues/805
2023-03-28 07:53:09 +02:00
Tony Zorman
4929da0eac CI: Fix build with mtl-2.3.1
Technically, contrib still does not build with stack, as it forces
xmonad-0.17.0, while only HEAD builds with newer mtl versions.  However,
until our dependencies are at least revbumped, this may be the best we
can do.

Related: https://github.com/xmonad/xmonad-contrib/issues/805
2023-03-27 08:17:36 +02:00
Tony Zorman
e60805bd45 Merge pull request #804 from xmonad/dependabot/github_actions/cachix/install-nix-action-20
build(deps): bump cachix/install-nix-action from 19 to 20
2023-03-06 18:39:48 +01:00
dependabot[bot]
49edaf37fd build(deps): bump cachix/install-nix-action from 19 to 20
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 19 to 20.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v19...v20)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 17:08:28 +00:00
Tomáš Janoušek
5324f53501 Merge pull request #802 from geekosaur/801-dynamicLogString
`dynamicLogString` forces its result and recovers
2023-02-20 21:45:42 +00:00
brandon s allbery kf8nh
4a97716d59 dynamicLogString forces its result and recovers
Originally, `dynamicLogString` could have a bottom hidden in it and
thereby crash the `logHook`. Under some circumstances (see #801)
this could cause xmonad to get stuck. We now force the result, and
`dynamicLogString` catches the exception and substitutes a
message (currently "_|_"). Use `dynamicLogString'` for the old behavior.
2023-02-20 16:39:49 -05:00
Tony Zorman
6063855a3e X.P.OrgMode: Simplify refile 2023-02-18 13:23:15 +01:00
Yecine Megdiche
1bcdbc9072 Merge pull request #800 from 1in1/master
Add loggers for window classname
2023-02-13 10:49:07 +01:00
l
2dd3c614e2 add loggers for window classname 2023-02-12 11:17:32 +00:00
Leary
6b19388139 Merge pull request #784 from LSLeary/focus-tracking
Extract redundant layouts into new module: X.L.FocusTracking
2023-02-12 20:36:32 +13:00
L. S. Leary
a52e646cc1 Extract redundant layouts into new module: X.L.FocusTracking
X.L.StateFull's `FocusTracking` and the eponymous `TrackFloating` were
redundant, hence the former was slated for deprecation. However,
the latter and its host module are somewhat poorly named; the layout
modifier has little relation to floats. As such, it's renamed and
rehosted, becoming the eponymous `FocusTracking`.

The redundant offerings in the original modules are redefined in terms
of the new module where possible, and deprecated.

See: #418; comments on #253, #783.
2023-02-12 20:20:52 +13:00
brandon s allbery kf8nh
29f0e03256 Config modifiers infixl 4 so you can use (++) 2023-02-09 03:52:58 -05:00
dependabot[bot]
726e887239 build(deps): bump cachix/install-nix-action from 18 to 19
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 18 to 19.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v18...v19)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 20:48:12 +00:00
Tony Zorman
6fba80168d Merge pull request #796 from slotThe/fix/named-actions/key-overwriting
X.U.NamedActions: Do not discard all keybindings in addDescrKeys
2023-01-29 08:24:47 +01:00
Tony Zorman
90f4a96f93 X.U.NamedActions: Do not discard all keybindings in addDescrKeys
Discarding keybindings may yield unintended behaviour when keybindings
are added via combinators, instead of the `keys` field.  This makes the
combinators noncommutative, which is very counterintuitive.

Related: https://old.reddit.com/r/xmonad/comments/10g1v1r/deftogglestrutskey_not_working/
2023-01-27 20:34:43 +01:00
Tony Zorman
33c1e24288 Merge pull request #794 from slotThe/ezconfig/remapkeysp
X.U.EZConfig: Add remapKeysP
2023-01-25 21:02:51 +01:00
Tony Zorman
49904ec4d3 X.U.NamedScratchpad: Fix typo in exclusive docs
Fixes: f059829f03
2023-01-25 07:49:05 +01:00
Tony Zorman
339dbbf2fd Merge pull request #795 from TheMC47/feat/start-sbs
X.H.StatusBar: Added startAllStatusBars
2023-01-24 20:35:34 +01:00
Yecine Megdiche
6caba97b34 X.H.StatusBar: Added startAllStatusBars 2023-01-24 20:34:58 +01:00
Tony Zorman
0afbbf9129 X.U.EZConfig: Add remapKeysP 2023-01-21 07:05:08 +01:00
Tony Zorman
df1fc2d334 X.A.Search: Export noogle
Fixes: 7665b67ff4
2023-01-18 20:42:45 +01:00
Tony Zorman
7665b67ff4 X.A.Search: Add noogle 2023-01-18 17:56:57 +01:00
Tony Zorman
a790c816d2 Merge pull request #766 from LSLeary/repeatable
Factor X.A.Cycle* modules; Write Alt+Tab style window switching
2023-01-14 15:29:50 +01:00
L. S. Leary
b9263ad17e Write new module: X.A.MostRecentlyUsed 2023-01-12 17:53:26 +01:00
L. S. Leary
8f0912a674 Write new module: X.U.History 2023-01-12 17:52:58 +01:00
L. S. Leary
dd7855da3d Factor shared logic out of X.A.Cycle* modules
These modules were duplicating a substantial amount of low-level code.

`X.A.CycleWorkspaceByScreen` had already separated most of the
implementation details from the logic with `repeatableAction`; all that
was left was to generalise it a little further, put it in a suitable
place and express the other modules through it.
2023-01-12 17:52:18 +01:00
Tony Zorman
e85f0151b2 X.A.VisualSubmap: Fix example 2023-01-11 16:50:42 +01:00
Tony Zorman
840d740366 Merge pull request #792 from TheMC47/master
README: update badge URLs
2023-01-06 19:03:42 +01:00
Yecine Megdiche
a5bd5d96ca README: update badge URLs
See https://github.com/badges/shields/issues/8671
2023-01-06 13:44:16 +01:00
Tony Zorman
4e8857ecee Merge pull request #791 from pbrisbin/pb/desktop-viewport
Add EWMH configuration to not set _NET_DESKTOP_VIEWPORT
2023-01-05 07:51:37 +01:00
patrick brisbin
cf13f8f9a7 X.H.EwmhDesktops: Add disableEwmhManageDesktopViewport
This combinator forces XMonad to *not* set _NET_DESKTOP_VIEWPORT.

This information is picked up by polybar's xworkspaces module and used
to re-group the workspaces by monitor. I (and others) find this super
confusing, but polybar doesn't not seem open to addressing it.

https://github.com/polybar/polybar/issues/2603

Opting in to the old behavior of not managing this property is one way
to work around it instead.
2023-01-05 07:47:16 +01:00
Tomas Janousek
e2ffa533da ci: Unpin runner in hlint workflow; bump hlint to 3.5
hlint 3.5 is built against libtinfo6 and works on Ubuntu 22.04 without
needing to install libtinfo5.

Fixes: b7afb0c0bc ("ci: Pin runner in hlint, nix workflows to ubuntu-20.04")
2023-01-02 20:45:19 +01:00
Tomas Janousek
6b20dbca42 Apply hlint 3.5 hints 2023-01-02 20:45:19 +01:00
Tony Zorman
6117a867d9 Update CHANGES.md
Mention f7e9c0cf0d
2022-12-31 13:52:32 +01:00
Tony Zorman
f7e9c0cf0d X.L.ResizableThreeColumns: Fix bottom right window not resizing
...by introducing yet another special case.  Unsurprisingly, this is
just a bandaid—the logic in this module is just wrong.  It
purposefully (not introduced with this change) computes the wrong
positions for certain extreme points such that splitVertically (which
simply goes down the list of stack windows _in order_) still works.

What we should do instead is to either

  - keep track of windows that want to change their size and compute a
    rectangle for them first, or

  - immediately when handling the resize message, compute *all* of the
    new sizes immediately (instead of only for the window getting
    resized).

The latter would force us to keep track of the size of the current stack
we operate in, but since 'handleMessage' lives in X this should not pose
a big problem.  I reckon this is the better approach.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/788
2022-12-31 13:33:36 +01:00
Tony Zorman
e0be851074 X.L.ResizableThreeColumns: Change terminology
For everything, except the exported fields.  Perhaps we should change
these as well, but that's for another commit.
2022-12-31 13:33:36 +01:00
Tony Zorman
55855ccb5f Merge pull request #785 from geekosaur/debugwindow-fix-netwm
fix EWMH titles
2022-12-28 16:43:41 +01:00
brandon s allbery kf8nh
4df2036187 remove references to baseConfig
that's from my private config and has no referent here
2022-12-12 16:16:45 -05:00
brandon s allbery kf8nh
4998e946cc fix EWMH titles
I have no idea what I was thinking when I wrote that code.
While at it, just reused the code for ICCCM title which already
assumes the client may have broken the rules (I think we have
seen a case of `WM_NAME` being `UTF8_STRING`).
2022-12-12 13:30:42 -05:00
Tomas Janousek
04c0ddd3e0 ci: Cabal install packdeps outside of project dir
Invoking cabal in the project directory with a cabal.project file might
fail on unrelated dependencies missing, see
4f539734be

Doesn't fail in this repo, but let's keep the workflows in sync.
2022-12-03 13:15:48 +00:00
Tomas Janousek
b7afb0c0bc ci: Pin runner in hlint, nix workflows to ubuntu-20.04
Both are now broken with ubuntu-22.04. Nix:

    error: could not set permissions on '/nix/var/nix/profiles/per-user' to 755: Operation not permitted

hlint:

    /opt/hostedtoolcache/hlint/3.4.1/x64/hlint: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory
2022-12-01 12:09:25 +00:00
Tomas Janousek
18eca4e8d6 ci: Drop ppa:hvr/ghc
Breaks `apt update` on the ubuntu-22.04 runner, which is what
ubuntu-latest resolves to these days.

Fixes: 7312d6f3f3 ("ci: Drop GHC installation via apt")
2022-12-01 12:06:17 +00:00
dependabot[bot]
797fd24112 build(deps): bump haskell/actions from 1 to 2
Bumps [haskell/actions](https://github.com/haskell/actions) from 1 to 2.
- [Release notes](https://github.com/haskell/actions/releases)
- [Commits](https://github.com/haskell/actions/compare/v1...v2)
2022-11-27 17:42:25 +00:00
Tomáš Janoušek
cf0e3531f9 ci: Configure dependabot to keep GH Actions up to date 2022-11-27 17:42:25 +00:00
Tomas Janousek
8cd09601b1 ci: Bump actions/* to v3 in haskell-ci workflow
This gets rid of the deprecation warnings about
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-11-27 17:42:25 +00:00
Tomas Janousek
0bd43c072f ci: Update to GHC 9.4.3 2022-11-27 17:42:25 +00:00
Tony Zorman
10c1a93963 X.U.NamedScratchpads: Check for "new" workspace in nsHideOnFocusLoss
When XMonad was recently restarted, it can happen that the workspace
history is empty, hence the last focused window could actually be the
currently focused one.  In that case, we don't want to go through the
machinery of looking to hide any NSPs, as there is only one window in
the current workspace (the focused one).  This may or may not be a
scratchpad, we don't care.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/779
2022-11-20 17:06:35 +01:00
Tony Zorman
58e7f6d3c3 Merge pull request #778 from slotThe/drop-8.4
Drop GHC 8.4
2022-11-20 17:01:48 +01:00
Tony Zorman
502f6a0e75 X.P.OrgMode: Fix deprecation warning
Starting with time-1.10, the iso8601DateFormat function was deprecated
in favour of more sophisticated methods for showing ISO 8601 date
formats—as such, follow the libraries lead.

Sadly, the new functionality was only introduced in time-1.9, meaning
GHC 8.8 and up.  Since we still support 8.6, the introduction of some
CPP is necessary.
2022-11-20 16:53:36 +01:00
Tony Zorman
35e434ed85 stack: Bump resolver to lts-20.0 2022-11-20 16:53:36 +01:00
Tony Zorman
b96bb908db Simplify instance declarations
Many instance declarations can now be derived either by DerivingVia or
GeneralizedNewtypeDeriving.
2022-11-20 16:53:36 +01:00
Tony Zorman
5d0013ef53 ci: Drop support for GHC 8.4
Debian stable and Ubuntu 20.04 are now 8.8 and 8.6, respectively, which
was always our guide as to which GHC versions we want to support.
2022-11-20 16:53:06 +01:00
Tony Zorman
0f69215fc8 ci: Update to GHC 9.2.5
+ A new stackage LTS is out with GHC 9.2.5, so test for this.
+ Update the haskell-ci jobs accordingly from 9.2.4.
2022-11-19 09:18:35 +01:00
Tony Zorman
57b5055858 X.A.Search: Add arXiv, clojureDocs, cratesIo, rustStd, zbmath
Related: 233a05908d
         (https://github.com/xmonad/xmonad-contrib/pull/777)
2022-11-15 09:29:08 +01:00
Tony Zorman
af5fced79a X.A.Search: voidpackages -> voidpgks_x86_64{_musl}
Musl on Void is popular enough that it makes sense to provide an extra
search engine for it.

Related: https://github.com/xmonad/xmonad-contrib/pull/777/files
2022-11-13 10:16:23 +01:00
Tony Zorman
d7499d1db0 CHANGES: Reindent
Fixes: https://github.com/xmonad/xmonad-contrib/pull/777
2022-11-13 10:04:19 +01:00
Luc-Saccoccio
233a05908d Added AUR, Flora, nCatLab, ProtonDB, RosettaCode, Sourcehut, Steam, Void
Linux packages. Reorganized the list, and added wiktionary which was
forgotten in the list although it was implemented.
2022-11-12 12:43:12 -05:00
Tony Zorman
e406e27139 Merge pull request #774 from slotThe/nsp/exclusive
X.U.NamedScratchpad: Add exclusive scratchpad capabilities
2022-11-11 21:06:10 +01:00
Tony Zorman
1c6ae39fc9 X.P.OrgMode: Also parse time in HHMM format 2022-11-10 11:50:28 +01:00
Tony Zorman
b627306772 X.P.OrgMode: Include 00:xx and xx:00 in the date range 2022-11-10 11:49:46 +01:00
Tony Zorman
8b4560dc1e X.P.OrgMode: Parse dates case-insensitively 2022-11-10 11:49:46 +01:00
L. S. Leary
608a8e4b88 Fix documentation bug in X.A.GridSelect 2022-11-08 23:02:51 +13:00
Tony Zorman
6373dc41fa Merge pull request #772 from ilya-bobyr/master
EwmhDesktops: _NET_CLIENT_LIST_STACKING: In focus order
2022-11-07 08:01:52 +01:00
Tony Zorman
8cb789af39 CI: Compatibility with mtl 2.3.1
Libraries like Control.Monad are no longer exported from
Control.Monad.Reader et.al.

Related: https://github.com/xmonad/xmonad/pull/427
         xmonad/xmonad#d170e99bc5e97db96be9a02b72149103e8d419af
2022-11-03 08:25:00 +01:00
Illia Bobyr
cf975d082e EwmhDesktops: _NET_CLIENT_LIST_STACKING: In focus order
Order workspaces based on the visibility, before collecting windows.
`_NET_CLIENT_LIST_STACKING` is supposed to be in the focus order.
2022-11-02 11:03:08 -07:00
Tony Zorman
e0d1f177ea Merge pull request #773 from aplaice/broken_links_doc
Fix some more broken inter-module docs links
2022-11-02 15:50:32 +01:00
Tony Zorman
bb9d6edad6 CHANGES: Re-indent newest changes
To conform with the style that all of the other changes (and the
breaking changes of the same release) have.
2022-11-02 11:17:51 +01:00
Tony Zorman
ab6299a488 X.U.ExclusiveScratchpads: Deprecate
Obsoleted by the exclusive scratchpad functionality of X.U.NSP.
2022-11-02 11:17:51 +01:00
Tony Zorman
226629977b X.U.NamedScratchpad: Add documentation about other types
With [1] and now [2], NSP has a lot more functionality that used to be
confined to other modules.  This is indicated in the TOC when viewing
the documentation, but it should perhaps be more prominently mentioned
in the introduction/usage docs.

[1]: https://github.com/xmonad/xmonad-contrib/pull/690
     533e17135e
[2]: https://github.com/xmonad/xmonad-contrib/pull/774
2022-11-02 11:17:51 +01:00
Tony Zorman
f059829f03 X.U.NamedScratchpad: Add exclusive scratchpad capabilities 2022-11-02 11:17:51 +01:00
Tony Zorman
49e9570f12 X.U.NamedScratchpad: Factor out isNSP
This function can be pretty useful in a general context, so let's factor
it out.
2022-11-02 11:17:49 +01:00
Tony Zorman
48a6d34f55 X.Prelude: Add findM
Several definitions of this were scattered over a few modules, so just
re-export it from our prelude.
2022-11-02 11:17:26 +01:00
Adam Plaice
ca866229f6 Fix most remaining broken inter-module docs links
The links were broken due to:

1. Incorrect quotes (' instead of " for module links and occasionally
vice-versa).

2. Changes in the name of the "target" module not reflected in the
"source" docs.

3. Typos to begin with.

4. Use of `<foo>` in the docs is rendered as just `foo` with a link to
`/foo`.

5. Similarly for `"Foo"` if it starts with a capital letter (and hence
could be a module).

6. Markup inside `@` code blocks still being applied.

e.g. `@M-<arrow-keys>@` is rendered as `M-arrow-keys` with a spurious
hyperlink from arrow-keys to `/arrow-keys`, which is confusing.

Three links from XMonad.Util.Run have been removed outright, since
they're no longer examples of the usage of 'runProcessWithInput'.
WmiiActions has been gone since 2008, while XMonad.Prompt.Directory
and XMonad.Layout.WorkspaceDir haven't been using
'runProcessWithInput' since 2020 and 2012, respectively.

In some cases the `<foo>` were surrounded with @, especially in the
case of key definitions, for consistency.  (This wasn't done
everywhere, because it looks ugly in the source.)

MoreManageHelpers has never been in xmonad-contrib.  ManageHelpers
seems to fill the expected role.

In the case of the module description for X.H.ManageDebug the quotes
were simply removed because none of the likely options to make the
link work were successful.
2022-11-01 19:35:55 +01:00
Tony Zorman
d301affabb Merge pull request #760 from slotThe/orgmode/refile
X.P.OrgMode: Add orgPromptRefile[To]
2022-10-31 14:38:25 +01:00
Tony Zorman
a97a1acf87 X.P.OrgMode: Remove the need for todoKeywords argument
This is (i) much simpler to use and (ii) helps us with refiling.  Emacs
will ignore todo keywords _that it knows_ when refiling, but when
started in batch-mode it doesn't know a whole lot.  One would need to
thread the `todoKeywords' through to `refile' and then set
`org-todo-keywords' or a similar variable, which does not sound like a
good experience.  Hence, falling back to showing the todo keyword to the
user when deciding upon a headline sounds acceptable.
2022-10-31 14:29:43 +01:00
Tony Zorman
bdb13e2551 X.P.OrgMode: Add orgPromptRefile[To]
Add orgPromptRefile and orgPromptRefileTo in order to refile entries
after insertion.
2022-10-31 14:29:43 +01:00
Tomáš Janoušek
3d0502f7b6 Merge pull request #775 from liskin/ci
CI maintenance (GHA deprecations, GHC 9.4)
2022-10-31 11:45:12 +00:00
Tomas Janousek
6880417911 ci: Fix docs tarball
haskell-ci by default passes --haddock-all to cabal v2-haddock, which
builds docs for all components and the …-docs.tar.gz tarball ends up
containing the docs for the last component, which happens to be tests.
We need the tarball to contain the library docs, for upload to Hackage.

Fixes: 7cee191516 ("CI: Remove hlint from haskell-ci")
2022-10-30 23:01:41 +00:00
Tomas Janousek
c4dca3592e Appease -Werror=type-equality-requires-operators
GHC 9.4 complains:

    The use of ‘~’ without TypeOperators
    will become an error in a future GHC release.
2022-10-30 21:52:10 +00:00
Tomas Janousek
4242fa02a0 ci: Add GHC 9.4 to tested-with matrix (haskell-ci workflow)
(Also bump 9.2 to 9.2.4)
2022-10-30 21:37:23 +00:00
Tomas Janousek
f81b9fb725 ci: Bump cachix/install-nix-action to v18
This gets rid of the deprecation warnings about
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-10-30 21:24:46 +00:00
Tomas Janousek
b0b8e4fb2c ci: Bump actions/{checkout,cache} to v3
This gets rid of the deprecation warnings about
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-10-30 21:20:21 +00:00
Tomas Janousek
7312d6f3f3 ci: Drop GHC installation via apt
The apt repo hosting these packages has been unmaintained for quite a
while, and we've excluded ~/.stack/programs from the cache long time
ago, so we can just let stack handle the installation. It's not much
slower than installing via apt, and even if it was, some matrix jobs
need to use the slow path anyway.

Related: 9fce3805fcf2 ("ci: Use system GHC in Stack to not waste GH Actions cache space")
Related: 7d10e470d71d ("ci: Avoid caching GHC")
2022-10-30 21:19:16 +00:00
Tomas Janousek
b75ed7295c ci: Replace deprecated GHA set-output command
See https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
2022-10-30 21:11:20 +00:00
Tony Zorman
c27a1f0791 Merge pull request #770 from slotThe/bikeshed/dynamicproperty
New module: XMonad.Hooks.OnPropertyChange
2022-10-29 14:48:43 +02:00
Tony Zorman
eaab5bfbba New module: XMonad.Hooks.OnPropertyChange
This is the same module as X.H.DynamicProperty, just with (hopefully)
more discoverable names.

Closes: https://github.com/xmonad/xmonad-contrib/issues/588

Co-authored-by: Tomas Janousek <tomi@nomi.cz>
2022-10-29 14:42:48 +02:00
Tony Zorman
fce5558b62 Merge pull request #769 from aplaice/spawnonce_doc_link
Fix broken link in doc for XMonad.Util.SpawnOnce
2022-10-27 07:45:48 +02:00
Adam Plaice
2ab520eeda Fix inter-module link (use " instead of ')
Otherwise, haddock tries to link to a (non-existent) function in
"XMonad.Util", which gives a "page not found".

See:

https://haskell-haddock.readthedocs.io/en/latest/markup.html#
linking-to-modules
2022-10-26 21:19:29 +02:00
Tony Zorman
cd95bf9c28 X.P.OrgMode: Return "exitCode" mkOrgPrompt
More formally, return whether the user cancelled the prompt or not.
This is useful in case we want to do things only after a "successful"
input.
2022-10-26 20:25:53 +02:00
Tony Zorman
b9c8294045 X.P.OrgMode: Add mkOrgCfg
This ensures that we always immediately expand the file path upon
constructing an `OrgMode' record.  We thus do not have to do this in
`mkOrgPrompt' anymore.
2022-10-26 20:25:53 +02:00
Tony Zorman
2ffc5de6cf X.U.Run: Don't use elispFun in progn
This is already taken care of by execute and eval, so forcing it in
progn only hampers composability.
2022-10-26 20:25:53 +02:00
Tony Zorman
08071706ba X.U.Run: Add list, saveExcursion 2022-10-26 20:25:53 +02:00
Tony Zorman
f55502f723 Merge pull request #765 from slotThe/hlint-workflow
Create HLint workflow
2022-10-25 08:55:14 +02:00
Tony Zorman
7cee191516 CI: Remove hlint from haskell-ci
As we have a proper hlint action now, this is no longer needed.
2022-10-25 08:49:23 +02:00
Tony Zorman
dd26fcc3f1 CI: Add hlint workflow
Closes: https://github.com/xmonad/xmonad-contrib/issues/669
2022-10-25 08:49:23 +02:00
Tony Zorman
571d017b82 Merge pull request #763 from slotThe/extending->tutorial
A Potpourri of Small Changes
2022-10-21 09:24:46 +02:00
Tony Zorman
570eb8ccb8 X.A.Navigation2D: Add sideNavigation as to default tiled navigation
Add sideNavigation as a fallback if needed.  This should not have any
user-facing behaviour change when not using gaps or spacing, as line
navigation is preferred.  However, users who do use spacing or gaps
should now potentially not have to change the default strategy in order
to have a usable module.
2022-10-21 09:18:06 +02:00
Tony Zorman
cca2ccfc71 X.A.Navigation2D: More prominently document strategies
Also, add a note that users who use gaps or spacing may need to look
into these strategies a bit more deeply.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/627
2022-10-21 09:18:06 +02:00
Tony Zorman
41d6ac96d5 X.H.InsertPosition: Add combinator
Users may not see the warning that insertPosition definitely needs to be
inserted at the leftmost position, which can cause undesired behaviour.
Having a combinator that handles this automatically seems like a sane
idea.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/709

       (Note that `docs` wasn't changed since it already inserts itself
       rightmost.)
2022-10-21 09:18:06 +02:00
Tony Zorman
4c8edd3bfb X.A.FloatKeys: Add direction{Move,Resize}Window
These are simpler, more easily understood, alternatives to the existing
functions.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/712
2022-10-21 09:18:04 +02:00
Tony Zorman
3d65a6bf72 Refer to the tutorial instead of X.D.Extending more often
Essentially, whenever the tutorial actually has decent material on the
subject matter.  The replacement is roughly done as follows:

  - logHook → tutorial
  - keybindings → tutorial, as this is thoroughly covered
  - manageHook → tutorial + X.D.Extending, as the manageHook stuff the
    tutorial talks about is a little bit of an afterthought.
  - X.D.Extending (on its own) → tutorial + X.D.Extending
  - layoutHook → tutorial + X.D.Extending, as the tutorial, while
    talking about layouts, doesn't necessarily have a huge focus there.
  - mouse bindings → leave this alone, as the tutorial does not at all
    talk about them.
2022-10-21 09:17:43 +02:00
Tony Zorman
05c4c776af Merge pull request #759 from slotThe/parser/feature-parity
X.U.Parser: Achieve feature parity with ReadP
2022-10-17 17:23:44 +02:00
Tony Zorman
2b1a15c9e5 X.P.OrgMode: Remove pLast
Use the more aptly named `option` instead.
2022-10-17 14:04:43 +02:00
Tony Zorman
0bef428f8f X.U.Parser: Inline definitions
Most of these definitions are probably small enough to be inlined on
their own, but tell GHC to try really hard regardless.  This is commonly
done by other parser libraries as well; e.g., [1], so it shouldn't cause
any issues either way.

[1]: https://hackage.haskell.org/package/parsers-0.12.11
2022-10-17 14:04:43 +02:00
Tony Zorman
4d7ae81f7a X.U.Parser: Feature parity with ReadP
While not many of these more exotic combinators are used right now, it's
still nice to have feature parity (i.e., everything that one could want
from a basic parser) such that people don't have to add their own
combinators, in case they want to use one that's not already
implemented.
2022-10-17 14:04:43 +02:00
Tony Zorman
7d4f0aaece Merge pull request #761 from exorcist365/master
X.H.Modal: Remove `Keys` type alias
2022-10-14 07:24:02 +02:00
exorcist365
4734551c76 X.H.Modal: Remove Keys type alias
This was only used in three places throughout the module and is sort of
non-standard terminology, hence it might confuse users.  Talking about
functions of type

    XConfig Layout -> M.Map (ButtonMask, KeySym) (X ())

is relatively standard in other modules as well, so it's probably best
to remove the type alias for it.
2022-10-14 07:20:42 +02:00
Tony Zorman
865c63a361 X.U.Run: Add executeNoQuote 2022-10-11 19:22:40 +02:00
Tomas Janousek
c3ea62c972 CHANGES: Fix thinko in module name 2022-10-05 22:21:23 +01:00
Tomas Janousek
005951535b CHANGES: Fix whitespace and misplaced underscores 2022-10-05 22:17:57 +01:00
Tony Zorman
ecd052b7fd Merge pull request #410 from slotThe/remove-deprecations
Remove (more) Deprecations, Properly Deprecate Modules
2022-10-04 07:10:18 +02:00
Tony Zorman
e15f2d17e5 Merge pull request #758 from alexandersokolow/master
expose more messages in MouseResizableTile layout
2022-09-30 11:38:38 +02:00
alexandersokolow
9e55ae9184 expose more messages in MouseResizableTile layout 2022-09-29 19:43:28 +02:00
L. S. Leary
b9794e6a13 Fix documentation bug in X.U.NSP
The Usage section made reference to a non-existent
`namedScratchpadSpawnAction` function. It has been replaced with
`namedScratchpadAction` in accordance with the documented bindings
below.
2022-09-23 19:21:48 +12:00
slotThe
1e3b49f064 CHANGES: Mention deprecations and removals
This reflects the changes made in the following previous commits:

  - f02b3a9869
  - 3bf9d80c40
  - 4a8bd762af
  - d28c0a2425
  - 6f49a9394f
  - 287b8bf95f
  - d8a23d47bf
  - 16701c2df2
  - 6ab4d9c0bc
2022-09-22 07:59:14 +02:00
slotThe
f02b3a9869 XMonad.Actions.SinkAll: Deprecate 2022-09-22 07:51:52 +02:00
slotThe
3bf9d80c40 XMonad.Layout.Named: Deprecate 2022-09-22 07:51:52 +02:00
slotThe
4a8bd762af XMonad.Hooks.RestoreMinimized: Remove 2022-09-22 07:39:54 +02:00
slotThe
d28c0a2425 XMonad.Layout.LayoutBuilderP: Remove 2022-09-22 07:39:54 +02:00
slotThe
6f49a9394f XMonad.Hooks.ICCCMFocus: Remove 2022-09-22 07:39:54 +02:00
slotThe
287b8bf95f XMonad.Layout.Navigation2D: Remove deprecations 2022-09-22 07:39:54 +02:00
slotThe
d8a23d47bf XMonad.Layout.Spacing: Remove deprecations 2022-09-22 07:39:54 +02:00
slotThe
16701c2df2 XMonad.Actions.MessageFeedback: Remove deprecations 2022-09-22 07:39:54 +02:00
slotThe
6ab4d9c0bc XMonad.Prompt.Window: Remove deprecations 2022-09-22 07:39:54 +02:00
Tony Zorman
24f11362c7 docs: Add additional external blog posts
This may seem a bit self-indulgent, but both of these features are
either quite new or so old that no one remembers them anymore, so not a
lot of up-to-date content exists for them.
2022-09-22 07:37:28 +02:00
Tony Zorman
a267fed24f Merge pull request #757 from slotThe/deprecate-sp
X.U.Scratchpad: Deprecate
2022-09-20 11:54:32 +02:00
Tony Zorman
a44df170f4 X.U.Run: Add findFile 2022-09-19 09:43:42 +02:00
Tony Zorman
2ebbe57bc2 X.U.Run: Quote string in execute and eval
Ordinarily, this should already be the case.  If for some reason it is
not, definitely make sure to quote the input string that we want to
execute.
2022-09-19 09:43:42 +02:00
Tony Zorman
ea16598a78 X.U.Scratchpad: Deprecate
This is i) broken and ii) just the functionality of X.U.NamedScratchpad
rewrapped (and not necessarily improved upon) at this point.

With recent changes to the way named scratchpads work[1], we would have
to export internals of X.U.NamedScratchpad in order to restore
X.U.Scratchpad to its full functionality.  This does not seem worth it,
as the latter does not bring anything substantially new to the table.

Closes: https://github.com/xmonad/xmonad-contrib/issues/756
Related: https://github.com/xmonad/xmonad-contrib/issues/591
[1]: 3fc830aa09
2022-09-18 17:29:26 +02:00
Tony Zorman
4a3f8eb032 X.U.Font: Add a fallback font to initXMF
In case a font could not be opened, simply fall back to "xft:monospace"
and open that.  The initCoreFont and initUtf8Font functions already have
mechanisms like this, is was just missing from initXMF.

Closes: https://github.com/xmonad/xmonad-contrib/issues/723
2022-09-15 19:02:26 +02:00
Tony Zorman
b0fc55499d Merge pull request #754 from Quoteme/master
made borderresize take a parameter
2022-09-10 16:30:15 +02:00
Luca Leon Happel
ae652b40f4 X.L.BorderResize: Add borderResizeNear
TODO
The parameter is how many pixels near the border of a window resizing
will be possible
2022-09-10 16:20:35 +02:00
Tony Zorman
8a6542f6b3 Merge pull request #751 from slotThe/x.d.extending/round-two
X.D.Extending: Round Two
2022-09-08 13:10:31 +02:00
Tony Zorman
5378e93e15 X.D.Extending: Remove keyAddDel and logHook
+ $keyAddDel can just be a side note in $keyDel, it does not need its
  own section.

+ $logHook is covered in more detail in the tutorial and does not serve
  a real purpose anymore.  One could rewrite it to be more in-depth
  about the inner workings of X.H.StatusBar, but for the time removing
  it seems like the best option.

Closes: https://github.com/xmonad/xmonad-contrib/issues/645
2022-09-08 13:09:55 +02:00
Tony Zorman
cedb8d7c78 X.D.Extending: Rewrite keyDel
Nowadays, removing keys is mostly done via removeKeys and removeKeysP,
so the documentation should reflect that fact.  This part is less
step-by-step instructive than the section about adding keys, but read in
succession it presents a way to deepen the newly acquired knowledge.
2022-09-08 13:09:55 +02:00
Tony Zorman
9809b2013f X.D.Extending: Update hooks
+ Refer to X.H.StatusBar whenever possible at the start.
+ Fix some small typos throughout the module.

Related: https://github.com/xmonad/xmonad-contrib/issues/645
2022-09-08 13:09:55 +02:00
Tony Zorman
9b6bef7e9d X.D.Extending: Add links to headings
This is more ergonomic to use than the old-style headings; plus, the
generated Haddock is easier to read than just stating
"XMonad.Doc.Extending".
2022-09-06 20:16:21 +02:00
Tony Zorman
fd5970fb34 NIX.md: Suggest a recent revision of GHC 9.2
Lest anyone run into https://github.com/xmonad/xmonad/issues/389.
2022-09-05 19:05:27 +02:00
Tony Zorman
b0ca330d08 Merge pull request #750 from LSLeary/nixflake
Fixes and Workarounds in flake.nix, Documentation in NIX.md
2022-09-05 17:50:56 +02:00
L. S. Leary
edf8e2526d flake.nix:
* Support comp.nix.
  * Re-order overlays and modules dependency-last for sanity.
  * Re-export `xmonad.modernise`.
NIX.md:
  * Document comp.nix.
  * Simplify example system flake, removing direct dependency on the
    xmonad flake.
  * Advise sane module ordering.
  * Include and document `modernise` workaround.
  * Clarify user-substituted `<foo>` values.
.gitignore:
  * Include nix 'result' symlink.
2022-09-05 20:57:17 +12:00
Tomas Janousek
d0d222e974 Bump version to 0.17.1.9 and prepare CHANGES.md sections 2022-09-03 16:25:12 +01:00
Tony Zorman
c688975625 CHANGES: Fix date for 0.17.1 release
Derp.
2022-09-03 16:50:41 +02:00
Tony Zorman
afd6824ce0 Bump version to 0.17.1 2022-09-03 14:54:32 +02:00
brandon s allbery kf8nh
f5de0fc764 Document WNConfig
And rearrange the documentation slightly so it makes more sense.
Also document the defaults, and clean up the existing markup a bit.
2022-08-28 01:56:32 -04:00
Tony Zorman
c701a75002 X.P.OrgMode: Require whitespace before priority
By being a bit less greedy with consuming whitespace in the date/time
parsers, we can make the `prop_{encode,decode}Preservation` properties
well-defined again.
2022-08-28 07:41:08 +02:00
Tony Zorman
f77fb802eb X.P.OrgMode: Mention more resources
Specifically, a blog post by yours truly featuring some animated GIFs,
which might be more digestible than a wall of text.
2022-08-27 12:43:28 +02:00
Tony Zorman
063d97f8d3 Merge pull request #735 from PRESFIL/x-p-unicode-unidescriptions
`X.P.Unicode`: `BS` -> `String` to support Unicode descriptions
2022-08-24 15:09:49 +02:00
PRESFIL
c187dfde4c X.P.Unicode: BS -> String to support Unicode descriptions
Switch the underlying UnicodeData data type from the current ByteString
implementation to String.  This is in order to facilitate descriptions
Unicode descriptions of the Unicode characters themselves.  We chose
String instead of Text because it does not incur an extra dependency.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/733
2022-08-24 15:08:07 +02:00
Tony Zorman
766667d8fa X.U.Loggers: Make logTitlesOnScreen default to correct value
To keep the behaviour of the old code, we want to fall back to the
unfocused format here, not the identity.

Fixes: cfc6a52935
2022-08-24 14:55:11 +02:00
Tony Zorman
113dda4389 Merge pull request #747 from slotThe/org-mode/priorities
X.P.OrgMode: Add ability to specify priorities
2022-08-24 14:36:35 +02:00
Tony Zorman
888a1e4f12 X.P.Pass: Add note about enabling fuzzy matching
Instead of providing these as default values, as originally planned,
just add a note for users who wish to customise that part of the prompt.
We simply get the user config in mkPassPrompt and so overriding that
with a custom searchPredicate and sorter seems unwise.

Closes: https://github.com/xmonad/xmonad-contrib/issues/746
2022-08-23 21:32:34 +02:00
Tony Zorman
4d11a372c9 tests/OrgMode: Generate arbitrary priorities
Add the trivial Arbitrary instance for Priority, extend the Arbitrary
instance of OrgMsg, as well as some plumbing.  Also work in some unit
tests for regression testing.
2022-08-23 18:49:38 +02:00
Tony Zorman
68b5a12f96 X.P.OrgMode: Add ability to specify priorities
Add the ability to specify alphabetic (`#A`, `#B`, and `#C`) org-mode
priorities[1] at the end of the input note.

[1]: https://orgmode.org/manual/Priorities.html
2022-08-23 18:47:03 +02:00
Tony Zorman
ae7f615b60 Merge pull request #743 from alternateved/add-log-titles-variant
X.U.Loggers: Add variants of logTitle with urgent windows support
2022-08-21 17:23:48 +02:00
Tomasz Hołubowicz
cfc6a52935 X.U.Loggers: Add variants of logTitle with urgent windows support 2022-08-21 16:53:39 +02:00
brandon s allbery kf8nh
699d7d5002 Merge pull request #745 from geekosaur/prompt-pass-specify
Allow users to specify custom prompts
2022-08-21 10:44:33 -04:00
brandon s allbery kf8nh
996921528d Merge branch 'master' into prompt-pass-specify 2022-08-21 10:26:36 -04:00
Tony Zorman
2ae1c86ceb Merge pull request #744 from geekosaur/absolute-path
Use `mkAbsolutePath` in `doAppend` (XMonad.Prompt.AppendFile)
2022-08-21 06:53:53 +02:00
brandon s allbery kf8nh
2c5ea5f94a change XMonad.Prompt.AppendFile to use mkAbsolutePath 2022-08-20 17:18:52 -04:00
brandon s allbery kf8nh
64eb4e46ec modify mkAbsolutePath to support environment vars
If you want more general support, comment on PR #744.
2022-08-20 17:18:51 -04:00
brandon s allbery kf8nh
a7ed269a01 update CHANGES.md 2022-08-20 17:18:00 -04:00
brandon s allbery kf8nh
84f928068f versions of pass functions with user-specified prompt
By request of a user on IRC
2022-08-20 17:18:00 -04:00
Tony Zorman
40171824cd Merge pull request #742 from slotThe/sideborderdec
New module: XMonad.Layout.SideBorderDecoration
2022-08-19 09:54:03 +02:00
Tony Zorman
7185b28e09 New module: XMonad.Layout.SideBorderDecoration
New module that allows for having a configurable border position around
windows.  Originally found in a comment by L. S. Leary in [1].  Enough
people have requested this on IRC in recent memory to warrant a proper
module.

[1]: https://github.com/xmonad/xmonad/issues/152#issuecomment-362716434

Co-authored-by: L. S. Leary <LSLeary@users.noreply.github.com>
2022-08-19 09:43:02 +02:00
Tony Zorman
284463a172 X.U.Parser: Give (Parser a) an IsString instance when a ~ String
When the -XOverloadedStrings language extension is on, treat a string s
as the parser 'string' s, when appropriate.  This allows one to write
things like "a" *> otherParser instead of 'string' "a" *> otherParser.
2022-08-19 09:37:07 +02:00
Tony Zorman
df3d0aa057 X.U.Run: Use isPrefixOf in withEmacsLibs
The `lisp` and `elpa` lists will simply be the (unqualified) file names.
Thus, if we use isInfixOf and try to require a library with a very short
name (like s.el), other things may be chosen over it.  isPrefixOf,
together with the additional `-`, prevents this from happening.
2022-08-16 07:38:18 +02:00
Tony Zorman
ee97eec17d Remove all remaining occurences of defaultTConf
Data.Default deprecations were removed in
5140f5b5d0, yet some comments still refer
to defaultTConf—fix that.

Related: 6b4675e3fa
2022-08-03 10:06:23 +02:00
brandon s allbery kf8nh
6b4675e3fa fix some deprecated and removed defaultTConfs 2022-08-02 19:37:18 -04:00
Tony Zorman
0934fe5cd7 X.U.Grab: Hide mkGrabs from XMonad
With [1] merged, the XMonad module from core now exports mkGrabs and
setNumlockMask (now cacheNumlockMask).  However, since we want
xmonad-contrib 0.17.1 to compile against xmonad 0.17.0 still, hide the
function for now and continue to use the vendored copies we have in
X.U.Grab currently.  We have to ignore the dodgy-imports warning when
-fpedantic is on, but that seems like a small price to pay.

A breaking change for this is planned for 0.18.0.

[1]: https://github.com/xmonad/xmonad/pull/405
2022-08-02 09:57:32 +02:00
Tony Zorman
8268cdde26 Merge pull request #736 from geekosaur/EWMH-windowDebug
print EWMH type and state in debugWindow
2022-07-29 09:10:02 +02:00
brandon s allbery kf8nh
607fdc2a12 print EWMH type and state in debugWindow 2022-07-28 10:18:11 -04:00
Yecine Megdiche
0a3fa0c3ed Merge pull request #737 from geekosaur/bits-warning
silence warning about extraneous Data.Bits import
2022-07-26 12:39:20 +02:00
brandon s allbery kf8nh
1aad21e866 silence Data.Bits warning
I had missed that `(.&.)` was already being imported from
`XMonad.Prelude`.
2022-07-25 20:25:48 -04:00
Tomas Janousek
8da08b8848 scripts: Include xmonad{ctl,propread}.hs in the release tarball
Last year I thought a bit about making this an actual `executable` in
xmonad-contrib.cabal, but decided against it. Unfortunately I can't
remember why. So let's do the bare minimum to at least ship it now, and
if I remember or if anyone has any ideas, we can do the next step or
document why not.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/734
2022-07-12 22:17:36 +01:00
Tomas Janousek
a45ecd3779 scripts: Drop obsolete grabDescriptions.hs
We haven't used this for a while, and since we dropped descriptions in
X.D.Extending in favor of the haddock-generated index in
839302533b, it's useless.
2022-07-12 22:13:31 +01:00
Tomas Janousek
820a2f75de scripts: Drop obsolete generate-configs
The last time this could work was 2007
(1e35714e1e).
2022-07-12 22:10:44 +01:00
brandon s allbery kf8nh
2a6ac58c71 change a defaultGSConfig doc to a def 2022-07-12 14:25:13 -04:00
Tomáš Janoušek
ea97c3562f Merge pull request #732 from liskin/getppidof
X.A.SpawnOn, X.H.WindowSwallowing: Fix parsing of process PPIDs
2022-07-06 09:03:20 +01:00
Tomas Janousek
fc482b8771 X.A.SpawnOn, X.H.WindowSwallowing: Fix parsing of process PPIDs
This fixes several issues related to parsing of parent PIDs:

* A process with lines or spaces or parentheses in its process name
  would confuse the code in X.A.SpawnOn and possibly lead to a
  `Prelude.read: no parse` exception.

* `X.H.WindowSwallowing.isChildOf` looked for the parent PID anywhere in
  the output of pstree, so single-digit parent PIDs would be considered
  as parents of any process with that digit anywhere in its chain of
  parent PIDs. (Note that apps in PID namespaces like in Flatpak often
  have single-digit PIDs.)

* `pstree` is no longer required in `$PATH`.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/726
2022-07-06 09:00:35 +01:00
brandon s allbery kf8nh
5557944fb6 Proper fix for alpha channel mishandling
X11 only handles alpha channels in a restricted set of APIs (such as
setting `border_color`); most others throw undocumented errors and/or
produce black pixels. Document this, and mask out alpha where it
matters.

Fixes xmonad/xmonad#395, xmonad/xmonad#398.
2022-07-05 17:34:49 -04:00
Tony Zorman
ebdb079a94 Merge pull request #727 from ilya-bobyr/master
X.H.UrgencyHook: Default for DzenUrgencyHook and UrgencyConfig
2022-07-05 08:32:35 +02:00
Illia Bobyr
3e7b22fe9b X.H.UrgencyHook: Default for DzenUrgencyHook and UrgencyConfig
As the XMonad config is commonly customized by saying

    def { startupHook = ...
        , manageHook = ...
        , ...
        }

It seems consistent to allow the same for an individual hook config:

    let urgencyHook = def { suppressWhen = ...
                          , remindWhen = ...
                          }
2022-07-05 08:28:59 +02:00
Tony Zorman
839bc907ba Merge pull request #730 from slotThe/nsp-fix
X.U.NamedScratchpad: Initialise if necessary
2022-07-03 13:32:20 +02:00
Tony Zorman
7a33639aaa X.U.NamedScratchpads: Fill NSPState when necessary
Since 3fc830aa09, scratchpads are now
added in namedScratchpadManageHook.  This, however, means that we need
some kind of MapRequestEvent to happen before processing scratchpads,
otherwise the manageHook didn't run yet and our extensible state is
being left empty.  When trying to open a scratchpad right after starting
xmonad—i.e., before having opened a window—this may not be the case.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/728
2022-07-03 12:24:44 +02:00
Tony Zorman
a4c73ad090 Merge pull request #729 from slotThe/modal-fixups
X.H.Modal: Add EZConfig support
2022-07-02 17:28:00 +02:00
Tony Zorman
8ddc1f48e2 X.H.Modal: Update documentation
Now that we use a slightly different setup, as well as EZConfig support,
rewrite the introduction to the module a little.
2022-07-02 17:27:33 +02:00
Tony Zorman
fe337dc6b0 X.H.Modal: Add support for EZConfig-style bindings
Add support for EZConfig-style bindings while also maintaining some
guarantees as to which type of representation we will store in the
extensible state.  This means that parsing of the keys will happen no
later than the call to `modal`.

Users can choose to use `mkKeysEz` or `mkKeysFun` to create a new
collection of keys to bind for a mode.  This is deemed more ergonomic
than exporting the respective constructors directly.
2022-07-02 17:27:33 +02:00
Tony Zorman
87a36d7d31 X.H.Modal: Cleanup
Mostly small things, like making imports line up with the provided
comments.  Also:

+ Rename mode' -> modeWithExit.  This seems like a better name for
  discoverability reasons.

+ Make the fields of Mode strict, because they have no reason not to,
  really.
2022-06-29 15:00:40 +02:00
Yecine Megdiche
0891575518 New module: XMonad.Hooks.Modal
Based on the draft by L. S.
Leary.  (https://gist.github.com/LSLeary/6741b0572d62db3f0cea8e6618141b2f).
2022-06-28 22:27:29 +02:00
Yecine Megdiche
8b2594a526 New Module: XMonad.Util.Grab
Based on the draft by L. S.
Leary.  (https://gist.github.com/LSLeary/6741b0572d62db3f0cea8e6618141b2f).
2022-06-28 22:27:29 +02:00
brandon s allbery kf8nh
6e1a1fe0df Stray def in additionalNav2DKeysP documentation 2022-06-24 19:47:14 -04:00
Tony Zorman
4287bab252 XMonad.Util.Run: Add quote
This is quite convenient in arguments; e.g.,

    progn [ "fun1" <> asString "string"
          , "fun2" <> quote "symbol"
          ]
2022-06-22 17:23:45 +02:00
Tony Zorman
2643528945 Merge pull request #725 from emptyflask/emptyflask/centered-if-single
CenteredIfSingle allow resizing in both dimensions
2022-06-21 13:22:29 +02:00
Jon Roberts
accea5b1d8 X.L.CenteredIfSingle: Allow specifying ratio in both dimensions
While monitors are, more often than not, wider than they are high,
specifying a ratio in the vertical direction can also make sense; e.g.,
when flipping a monitor by 90 degrees.  Thus, we should definitely
support both.
2022-06-21 13:16:50 +02:00
Tomas Janousek
0d5a952035 ci: Prevent scheduled workflows from being auto-disabled by GitHub 2022-06-19 17:14:24 +01:00
brandon s allbery kf8nh
f998cc2d2e Complete #708 by updating _NET_SUPPORTED. 2022-05-29 20:24:47 -04:00
Tony Zorman
a88d6328fe Merge pull request #718 from slotThe/spawn-external
Extend X.U.Run with an EDSL for spawning processes
2022-05-24 08:18:57 +02:00
Tony Zorman
b6be0dca40 X.U.Run: Add examples to Haddocks 2022-05-23 20:12:57 +02:00
Tony Zorman
e466d9b1dc X.Prelude: Add mkAbsolutePath 2022-05-23 20:12:57 +02:00
Tony Zorman
473dc41afb X.U.Run: Improve and add documentation
This adds documentation for the new EDSL, as well as small fixes to
existing docs.

Importantly, I've added myself as a maintainer of the file (even though
we don't really care about this at this point) and updated the
copyright; the changes seem large enough to warrant this.
2022-05-23 20:12:57 +02:00
Tony Zorman
2b48f3ff09 X.U.Run: Add an EDSL to spawn external programs
Extend X.U.Run with an EDSL for spawning (external) processes.  For
example:

    do url <- getSelection  -- from XMonad.Util.XSelection
       proc $ inEmacs
          >-> withEmacsLibs [ElpaLib "dash", ElpaLib "s", OwnFile "arXiv-citation"]
          >-> asBatch
          >-> execute (elispFun $ "arXiv-citation" <> asString url)

is essentially equivalent to (line breaks mine)

    /usr/bin/sh -c "emacs -L /home/slot/.config/emacs/elpa/dash-20220417.2250
                          -L /home/slot/.config/emacs/elpa/s-20210616.619
                          -l /home/slot/.config/emacs/lisp/arXiv-citation.el
                          --batch
                          -e '(arXiv-citation \"<url-in-the-primary-selection>\")'"
2022-05-23 20:11:29 +02:00
brandon s allbery kf8nh
67243cbf7c the rest of the fix for #719
It's just two more exports.
2022-05-08 09:27:56 -04:00
brandon s allbery kf8nh
41674386a6 Export shrinkText
Closes #719.
(This being a trivial one-line change and the description being already bigger than the change, I'm committing it directly.)
2022-05-08 09:06:18 -04:00
Tony Zorman
616222c9f0 stack: Bump default resolver to 19.6
No impact on CI, just makes it easier for contributors to use the latest
9.0 GHC.
2022-05-07 09:39:19 +02:00
Tony Zorman
21e613e242 Merge pull request #717 from Pachin0/desktop-viewport
X.H.EwmhDesktops: Add `_NET_DESKTOP_VIEWPORT` support
2022-05-06 08:51:33 +02:00
Jose Antonio Martinez Vidaurre
2291d3a009 X.H.EwmhDesktops: Add _NET_DESKTOP_VIEWPORT support
Some panels—such as polybar—require _NET_DESKTOP_VIEWPORT support in
order to know which workspace is on which monitor.  They are then able
to only show workspaces defined on the same output as the bar with just
X11 properties.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/708
2022-05-06 08:12:13 +02:00
Tony Zorman
6c787204aa Update my name 2022-05-05 21:07:27 +02:00
Tony Zorman
4a982e54c9 Merge pull request #711 from LSLeary/flake-module
Apply Patch in Nix Flake; Enable Configuration (Contrib Edition)
2022-05-04 20:53:31 +02:00
L. S. Leary
6ab69e97d3 NIX.md: Document the NixOS modules provided by the core and contrib flakes.
flake.nix: Assume maintainership.
2022-05-04 19:20:13 +12:00
Tony Zorman
0e14e13845 Merge pull request #716 from johnli360/master
Replace <+> with <>
2022-05-02 17:52:01 +02:00
John Lind
a7fd31d233 Replace <+> with <> 2022-05-02 08:28:36 +02:00
Tomas Janousek
3adb47235f Apply hlint 3.4 hints 2022-05-02 00:06:59 +01:00
Tomas Janousek
154388aa20 ci: Drop hlint -XCPP workaround
https://github.com/ndmitchell/hlint/issues/1360 is fixed and the fix
released.
2022-05-01 23:25:08 +01:00
Tony Zorman
716c634dc9 Merge pull request #715 from Ahanaf-Ether/master
X.A.PerLayoutKeys: Fix typo
2022-05-01 08:51:03 +02:00
Ether
51907ad59e X.A.PerLayoutKeys: Fix typo 2022-05-01 08:49:54 +02:00
L. S. Leary
fa498ca728 flake.nix: Provide a NixOS module corresponding to that of the
xmonad (core) flake.
2022-04-25 02:02:11 +12:00
L. S. Leary
b4b4d9b7c8 flake.nix: Expose hoverlay for use with fromHOL. 2022-04-25 01:51:24 +12:00
L. S. Leary
12cd1b9c6e flake.nix: Erase the noise with xmonad.lib.fromHOL. 2022-04-25 01:38:39 +12:00
Tomas Janousek
0e106ccfbe ci: Discard old caches to fix build failures
We're getting "undefined reference" errors during linking, suggesting
some build artifacts in the cache are stale and need to be rebuilt.
2022-04-18 23:39:01 +02:00
brandon s allbery kf8nh
b6d62fe9d3 migrate build scripts from xmonad-testing
The testing repo was not a good location for them, and is now
deprecated. They are now in `scripts/build`, and will be documented
in the main repo's `INSTALL.md`.
2022-04-18 17:30:51 -04:00
Tony Zorman
965c4052fb Merge pull request #705 from kozlov721/repeat-action
added Actions.RepeatAction
2022-04-17 10:37:29 +02:00
Martin Kozlovsky
3f590b86c6 New module: XMonad.Actions.RepeatAction
Closes: https://github.com/xmonad/xmonad-contrib/issues/489
2022-04-17 10:25:47 +02:00
brandon s allbery kf8nh
80776d8969 buggy boolean blindness
`ManageDebug` was continuing to report in the `logHook` even after
the `manageHook` was done. In diagnosing this, I discovered that
the original code was using a tuple of `Bool`s and not even a
comment about which meant what.

The code now uses a proper pair type, and dedicated `data`s for
the two flags that make it clear what each means. This also fixed
the bug, so apparently I had the `Bool`s confused somewhere.

I also took the chance to clarify the documentation a little (a
misleading "persistent", since it doesn't use persistent XS) and
a few more cleanups. Also, it now logs all `manageHook` runs
before the `logHook` in case multiple windows are opened.
2022-04-15 14:17:50 -04:00
Tony Zorman
923c5a2548 Merge pull request #704 from amenonsen/master
Fix missing prompt configuration in DynamicProjects example
2022-04-12 09:06:27 +02:00
Abhijit Menon-Sen
cf3a2be6d9 Fix missing prompt configuration in DynamicProjects example 2022-04-12 12:25:44 +05:30
Yecine Megdiche
b7799c1e5b Merge pull request #701 from PRESFIL/fix-synopsis-typo
Fix synopsis typo
2022-04-09 10:18:14 +02:00
PRESFIL
f43bd08728 Fix synopsis typo
Removes a repeating word in a package synopsis
2022-04-09 10:05:38 +03:00
brandon s allbery kf8nh
0833c347e7 Missed a reference to bindOn
The perils of making 1-line changes to another module….

Co-authored-by: Tomáš Janoušek <tomi@nomi.cz>
2022-04-06 13:13:55 -04:00
brandon s allbery kf8nh
84caf89894 new module XMonad.Actions.PerLayoutKeys 2022-04-06 13:13:55 -04:00
slotThe
78dce3d85b X.U.NamedScratchpad: Fix docs regarding dynamic NSPs
The documentation and usage example still had the old names.

Related: https://github.com/xmonad/xmonad-contrib/issues/699
2022-04-05 16:13:08 +02:00
Tomáš Janoušek
737f8040cb Merge pull request #694 from slotThe/ci/update-ghcs
ci: Update supported GHC versions
2022-04-05 12:31:27 +01:00
slotThe
e3ffbf63f6 ci: Update supported GHC versions
+ Prefer GHC 8.10.7 to 8.10.4, as versions seem to have stabilised now.
+ Add support for Stackage LTS 19, which ships with GHC 9.0.2.
+ Since a new version of 9.2 has been released, prefer 9.2.2 over 9.2.1.

Also, explicitly pass -XCPP to hlint; see [1].

[1]: https://github.com/ndmitchell/hlint/issues/1360
2022-04-05 12:18:12 +01:00
Tony Zorman
533e17135e Merge pull request #690 from slotThe/scratchpads
X.U.NamedScratchpads: Add dynamic scratchpad capabilities
2022-04-01 08:40:37 +02:00
slotThe
4c350b9a65 X.U.NamedScratchpad: Use a map for internal state 2022-04-01 08:28:55 +02:00
slotThe
bc2aaf41af X.U.DynamicScratchpads: Deprecate 2022-04-01 08:28:55 +02:00
slotThe
f6334b6af6 X.U.NamedScratchpad: Create a `Deprecations' section
Since users should not use these functions, anyways, separating them out
seems like a good idea.  Plus, one now does not need to scroll over them
to get to the dynamic scratchpad functionality (people may stop when
seeing "DEPRECATED" signs everywhere).
2022-04-01 08:28:55 +02:00
slotThe
bf064710d0 X.U.NamedScratchpad: Add support for dynamic scratchpads
With the extensible state machinery in place[1], we are now able to
seamlessly integrate dynamic scratchpad functionality into
X.U.NamedScratchpad.  This is one step into the direction of having a
single scratchpad implementation that can "do anything".

Related: https://github.com/xmonad/xmonad-contrib/issues/591
Related: https://github.com/xmonad/xmonad-contrib/pull/662

[1]: 70d08b82f43057447e8e2479aa515b6db0d199e4
     (X.U.NamedScratchpad: Use ExtensibleState to store scratchpads)
2022-04-01 08:28:55 +02:00
slotThe
3fc830aa09 X.U.NamedScratchpad: Use ExtensibleState to store scratchpads
Instead of using the scratchpads that the user specifies (as this will
realistically just be "all of them"), create some extensible state for
the scratchpads to reside in.

To ensure that this is done in a backwards compatible way, function
signatures did not change and they instead just ignore the list of
scratchpads given to them and the initialisation is done in the
manageHook, which users already have to use anyways.
2022-04-01 08:28:55 +02:00
Tony Zorman
0f788a9d92 Merge pull request #697 from xmonad/696-add-SessionStart-ref
Have `X.U.SpawnOnce` point to `X.U.SessionStart`
2022-03-25 08:07:00 +01:00
brandon s allbery kf8nh
fad1411995 Have X.U.SpawnOnce point to X.U.SessionStart
Just a simple doc change, but should make `X.U.SessionStart` more discoverable.

Closes #696.
2022-03-24 20:18:49 -04:00
Tony Zorman
8693654bdd Merge pull request #695 from a5ob7r/fix_typo_in_doc
Fix typo on the 'XMonad.Hooks.Rescreen' doc
2022-03-23 20:18:27 +01:00
a5ob7r
9128342f25 Fix typo on the 'XMonad.Hooks.Rescreen' doc 2022-03-22 11:21:53 +09:00
slotThe
8a28fbb29e cabal: Remove NIX.md from extra-source-files
We do not ship the nix flake in the release tarball, so it does not make
sense to include NIX.md in there either; at least for now.

Fixes: 4ca46c2414 (Add NIX.md)
2022-03-14 20:22:12 +01:00
slotThe
dcd5918d3a X.L.ThreeColumns: Resize screenshot
Fixes: https://github.com/xmonad/xmonad-contrib/issues/530
2022-03-06 20:23:15 +01:00
Tony Zorman
974c10dca7 Merge pull request #589 from IvanMalison/customizableNixDevelop
Provide a mechanism by which users can customize the nix devShell
2022-03-06 18:21:12 +01:00
slotThe
4ca46c2414 Add NIX.md
There are multiple ways one could use XMonad with nix, so a separate
file for documenting all of this seems appropriate.  E.g., when it
contains the respective installation instructions (e.g, "normally" as
instructed in the NixOS wiki, via stack, via flake, ...) we could link
to it from INSTALL.md.

For now it's a good place to document the new `develop.nix`
functionality.

Co-authored-by: Ivan Malison <IvanMalison@gmail.com>
2022-03-05 09:50:58 +01:00
Ivan Malison
f1ea1e533d Provide a mechanism by which users can customize the nix devShell 2022-03-05 09:50:58 +01:00
Tony Zorman
ca25b36aa0 Merge pull request #689 from slotThe/X.H.ShowWName
Add XMonad.Hooks.ShowWName
2022-02-28 08:55:59 +01:00
slotThe
fba22a7366 Add XMonad.Hooks.ShowWName
This is a reimplementation of X.L.ShowWName as a logHook, using the new
simpleWindow interface from 86b816ec50.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/612
2022-02-28 08:53:22 +01:00
Yecine Megdiche
6a46ff449f Merge pull request #684 from TheMC47/feature/workspace-screen
Export `WindowScreen` type and add a new module: `X.H.WorkspaceScreen`
2022-02-24 20:08:00 +01:00
Yecine Megdiche
eb8da2dcb2 New Module: XMonad.Hooks.WorkspaceScreen
In a multi-head setup, it might be useful to have screen information of the
visible workspaces combined with the workspace name, for example in a status
bar. This module provides utility functions to do just that.
2022-02-24 20:00:46 +01:00
Yecine Megdiche
2d33f18dec XMonad.Prelude: add the WindowScreen type
`WindowScreen` is a type synonym for the specialized `Screen` type, that
results from the `WindowSet` definition in XMonad.Core. Having this type
defined and exported in a central module saves extension developers from
trying to reconstruct it, whenever the general `Screen i l a sid sd` is
not suitable.

Note: this should be moved to `XMonad.Core` in the next core release.
2022-02-24 20:00:46 +01:00
Tomáš Janoušek
d2b174f269 Merge pull request #688 from liskin/dynamic-workspaces-nub-refresh-loop
X.H.ManageDocks: Avoid unnecessary refresh (loop) for decorations

This started as an investigation of the root cause of
<https://github.com/xmonad/xmonad-contrib/issues/565>, which was
addressed by <https://github.com/xmonad/xmonad-contrib/pull/621> without
having a full understanding of why xmonad ends up in a busy loop.

What was going on:

* X.L.SubLayouts group update algorithm assumes no duplicities in the
  Stack, and results in multiplying those duplicities otherwise. Note
  that this is a reasonable assumption—duplicities in a Stack have no
  defined behaviour in xmonad (X11 can't place a window on a screen
  twice), so "fixing" this algorithm is a waste of time.

* X.L.Decoration creates windows which X.H.ManageDocks treats as
  possible docks, resulting in extra refresh whenever they appear.

* The extra refresh causes X.L.SubLayouts to multiply the duplicities,
  X.L.Decoration to create new decoration windows, and these invalidate
  the X.H.ManageDocks strut cache, leading to yet another refresh, and
  an endless loop of these.

Having concluded that the no-duplicities assumption is a reasonable one,
there's nothing really to fix here after
<https://github.com/xmonad/xmonad-contrib/pull/621>. Still, the extra
refresh might be causing extra flicker in decorated layouts, and we can
easily avoid it, so I do that here. Plus a bit of documentation for
X.L.SubLayouts.
2022-02-20 18:24:59 +00:00
Tomas Janousek
253b952814 X.L.SubLayouts: Document assumptions/pre-conditions of toGroupStack
This started as an investigation/fix of xmonad freezing when a bug in
X.A.DynamicWorkspaces caused duplicate Windows in a single Workspace
Stack, but I soon(-ish) realized that trying to make SubLayouts robust
enough to handle duplicities in a Stack is futile. Any code that creates
duplicities in a Stack is buggy, and must be fixed; the rest can assume
there aren't any.

Instead, let's just document that this is a pre-condition, and that (and
how) stuff will misbehave.

Related: https://github.com/xmonad/xmonad-contrib/issues/565
2022-02-20 18:22:19 +00:00
Tomas Janousek
a6c048899c X.L.SubLayouts: Use ScopedTypeVariables as intended years ago
We don't need to support GHC 6.8.2 any more. :-)
2022-02-20 18:22:19 +00:00
Tomas Janousek
6a6e4bcce8 X.H.ManageDocks: Avoid unnecessary refresh (loop) for decorations
Windows created by X.U.XUtils.createNewWindow have _NET_WM_WINDOW_TYPE =
_NET_WM_WINDOW_TYPE_DESKTOP, which caused checkDock to match them and an
UpdateDocks event to be sent, causing an additional layout refresh
whenever a decoration window appeared.

This could in theory lead to a refresh loop with a layout (modifier)
that dropped and recreated its decoration windows on every
runLayout—which isn't entirely unreasonable, X.L.MouseResizableTile does
it, just luckily happens to not mark its windows as
_NET_WM_WINDOW_TYPE_DESKTOP.

In practice, such a refresh loop could be triggered when buggy
X.A.DynamicWorkspaces (before 929a6a3f6f) duplicated a Window in a
single workspace's Stack, and buggy X.L.SubLayouts then kept duplicating
the duplication (2 → 4 → 8 → …), triggering the creation of new
decoration window in each iteration.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/565
2022-02-20 18:22:19 +00:00
slotThe
e98d666447 X.U.XUtils: Fix alignment in showSimpleWindow 2022-02-19 11:52:44 +01:00
Tony Zorman
ee3ea2402d Merge pull request #685 from slotThe/ezconfig-property-tests
X.U.EZConfig: Add property tests
2022-02-13 16:16:54 +01:00
slotThe
153d46fd90 tests: Add property tests for X.U.EZConfig
Adds property tests in both directions for the parser in X.U.EZConfig.
As with the tests for X.P.OrgMode, these (modulo `Maybe` noise) take the
shape of the operation of an inverse semigroup:

    pp ∘ p ∘ pp ≡ pp        and        p ∘ pp ∘ p = p,

where pp is pretty-printing and p is parsing.
2022-02-13 15:00:21 +01:00
slotThe
7d91a1bf85 X.Prelude: Improve keyToString output
The keysymToString function prints the key names in pure ASCII; e.g.,
`keysymToString 250` returns "uacute" instead of "ú".  This is
undesirable when printing these keysyms in places like visualSubmap.

Thus, move all of the key infrastructure (heh) from X.U.EZConfig to
X.Prelude and look up the name of the key if possible.  For better
composability, slightly change the signature for `regularKeys` and the
associated parser.
2022-02-13 14:49:02 +01:00
slotThe
e6b50c5dd6 X.Prelude: Concat modifier keys instead of unwording
Instead of printing "M- S- C-", print "M-S-C".
2022-02-13 14:46:23 +01:00
Tomáš Janoušek
493b6adbc4 Merge pull request #686 from liskin/keypress-fixes
X.{A.{{Grid,Tree}Select,Submap},Prompt}: KeyPress handling fixes
2022-02-13 10:22:54 +00:00
Tomas Janousek
1b728ff96a CHANGES: Document the key bindings changes 2022-02-10 15:01:10 +00:00
Nikolay Yakimov
68c967ec0c X.A.{Grid,Tree}Select, X.Prompt: Fix keybindings like Shift-Tab and similar
This changes KeyPress handling in these modules to behave much closer to
how xmonad core itself handles keypresses. The primary difference lies
in that xmonad reads raw KeyCode and then converts it to unmodified
KeySym, while these modules used `lookupString` to find the actual
keysyms. As a consequence, key definitions like `(shiftMap, xK_Tab)`
didn't work on many layouts because an actual KeySym for `Shift-Tab` is
commonly `ISO_LEFT_TAB`, and not `Tab`.

Closes: https://github.com/xmonad/xmonad-contrib/pull/590
Co-authored-by: Tomas Janousek <tomi@nomi.cz>
2022-02-10 14:42:23 +00:00
Tomas Janousek
12c5518852 X.A.Submap, X.Prompt: Use cleanKeyMask
This replaces the custom `cleanMask` extension in these modules—which
only filtered out XKB group bits and Button5Mask¹—with the new
`cleanKeyMask` which additionally filters out all mouse buttons, as
these aren't relevant for key bindings.

¹) Filtering out Button5Mask was probably an off-by-one mistake.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/290
Related: https://github.com/xmonad/xmonad-contrib/pull/590
2022-02-10 14:23:01 +00:00
Tomas Janousek
adced0a8c8 X.A.{Grid,Tree}Select: Fix keybindings in secondary kbd layouts
We didn't clean XKB group bits out of the KeyPress events' state so key
bindings only worked in the primary keyboard layout (first XKB group).
To fix this, this adds a `cleanKeyMask` function to X.Prelude which is
analogous to `cleanMask` but aimed at cleaning regular KeyPress states
(as opposed to just KeyPresses from passive key grabs), and this is then
used instead of `cleanMask`.

Related: https://github.com/xmonad/xmonad-contrib/issues/290
Related: https://github.com/xmonad/xmonad-contrib/pull/590
2022-02-09 23:53:16 +00:00
Tomas Janousek
2e3254a908 X.H.Rescreen: Catch exceptions in user-provided hooks in add*Hook
This way a single failing hook won't disturb other hooks (not just
rescreen hooks, also other event hooks).
2022-02-03 11:53:54 +00:00
Tomas Janousek
7445390432 X.H.Rescreen: Improve usage doc (recommend add*Hook)
There's no reason (other than me forgetting to update the docs when
these add-Hooks were added) to steer users towards the ugly record-based
low-level API.
2022-02-03 11:49:34 +00:00
Tony Zorman
a49b664276 Merge pull request #680 from slotThe/visual-submap
X.A.Submap: Add `visualSubmap`
2022-02-03 09:38:13 +01:00
slotThe
cf1d966ee6 X.A.Submap: Add visualSubmap
Add a `visualSubmap` function, which works much like the regular
`submap` one, except that it visualises the available choices in a
pop-up window.

Related: https://github.com/xmonad/xmonad-contrib/issues/472
2022-02-03 08:53:33 +01:00
slotThe
86b816ec50 X.U.XUtils: Add framework for manipulating simple windows
Adds several new functions and type for manipulating "simple windows".

There are several ways to draw windows in X.U.XUtils and other places
already, but they are all quite manual.  Most of the time one does not
want to think about dimensions much and assumes that the code is smart
enough to "figure it out"; this is an attempt to do exactly that.

There is a less-managed version `showSimpleWindow`, which just creates
and shows the windows, as well as a wrapper-like `withSimpleWindow` that
also destroys the window once some action finishes executing.

With these functions it should be possible to refactor some contrib
modules that currently draw windows manually, like X.U.EasyMotion.
2022-02-03 08:53:22 +01:00
slotThe
505577b755 X.Prelude: Add keymaskToString, keyToString
This technically introduces a regression with regards to the way that
modifier masks are printed in X.U.NamedActions and X.H.DebugEvents.
However, since this way of printing masks is move in line with
X.U.EZConfig, I personally don't think that this is noteworthy.
2022-02-03 08:53:22 +01:00
Tomas Janousek
54095f5420 X.U.Hacks: Clean up tray padding hooks a bit
Un-export trivial/useless definitions and adapt the generic versions of
trayerPaddingXmobarEventHook to be more generally useful.

Related: https://github.com/xmonad/xmonad-contrib/pull/643#issuecomment-962661655
2022-02-01 19:17:30 +00:00
Tomas Janousek
d71856431a CHANGES: Fix formatting of the VoidBorders entry 2022-02-01 19:16:13 +00:00
Tomáš Janoušek
ae9b9c43a4 Merge pull request #682 from rayes0/master
X.L.VoidBorders: Add ability to reset borders for certain layouts
2022-02-01 18:39:57 +00:00
Tomas Janousek
c4d718be9a X.L.VoidBorders: Improve doc a bit 2022-02-01 18:39:33 +00:00
rayes
a3012eaa27 X.L.VoidBorders: Add ability to reset borders for certain layouts 2022-01-30 21:07:46 -07:00
slotThe
741d90eb9b X.P.Man: Use System.FilePath
Instead of hand-written functions, just use what's already provided by
filepath.
2022-01-30 10:20:04 +01:00
slotThe
c36a888a59 X.P.FuzzyMatch: Use isSubsequenceOf
The implementation is exactly the same, just that this function is now
in base, so there should be no change in behaviour.
2022-01-30 10:20:04 +01:00
Tony Zorman
56cc296754 Merge pull request #643 from tulth/trayerResizeHook
add to hacks: rough draft trayer resize event hook
2022-01-21 09:30:46 +01:00
tulthix
4d24193baa X.U.Hacks: Add tray(er) event hooks
Adds event hooks to communicate with trayer or, more generally, with
other tray programs.  For convenience, a standard query for trayer is
also provided.
2022-01-21 09:16:28 +01:00
slotThe
de886d6182 CHANGES: Remove Bluetile from deprecated modules
Was undeprecated in 981166a2ab.
2022-01-17 18:33:22 +01:00
Tomas Janousek
201a14718e X.A.GroupNavigation, X.H.WorkspaceHistory: Leak fix cleanups
Simplify stuff a bit. Prevent memory leaks additionally in:
`workspaceHistoryTransaction` and `workspaceHistoryModify`.

Related: https://github.com/xmonad/xmonad-contrib/pull/653
2022-01-15 19:12:32 +00:00
Tomas Janousek
981166a2ab Un-deprecate X.C.Bluetile
This one isn't actually a personal configuration, it's more like
X.C.Desktop and the other desktop-specific configs. As I happen to
sometimes use it for testing whether everything still works with
decorated layouts, it shouldn't be considered abandoned.

Related: https://github.com/xmonad/xmonad-contrib/pull/679
2022-01-15 18:23:59 +00:00
Tomas Janousek
2b5d2c5ab8 X.U.ActionQueue: Separate ExtState and ExtConf data types
Using the same type for both is confusing and requires a bogus Semigroup
instance.
2022-01-15 13:43:16 +00:00
Tomas Janousek
50527a4613 X.H.BorderPerWindow: Improve module synopsis 2022-01-15 13:43:16 +00:00
Tomas Janousek
20753c1bdb flake.nix: Use upstream gitignore.nix instead of Ivan's fork 2022-01-15 12:24:03 +00:00
Tomas Janousek
756d73c78c Merge branch 'mikenrafter/master' 2022-01-15 12:23:22 +00:00
Tony Zorman
f90e76248f Merge pull request #679 from slotThe/deprecate-modules
Deprecate user and abandoned modules
2022-01-14 07:55:52 +01:00
slotThe
478393fb7d Deprecate user and abandoned modules
Now that the user configs are on the website, it is time to deprecate
them.  At the same time deprecated X.C.Monad, which hasn't been updated
since 2008 and X.C.Prime, which has confused users quite recently,
thinking it to be a better starting place.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/677
Fixes: https://github.com/xmonad/xmonad-contrib/issues/595
Related: https://github.com/xmonad/xmonad-web/pull/49
2022-01-14 07:58:18 +01:00
Mike Nrafter
77ba202548 Fixed flake.nix's use of GitIgnore. 2022-01-12 20:02:33 -07:00
Tony Zorman
41ca79986b Merge pull request #676 from exorcist365/master
X.A.FloatKeys: Export ChangeDim
2022-01-08 09:05:51 +01:00
exorcist365
be1201cdeb X.A.FloatKeys: Export ChangeDim
Haddock displays exported types in a much nicer way.
2022-01-08 09:06:00 +01:00
brandon s allbery kf8nh
aad8a3a865 Missed a reference to the old SP workspace 2022-01-06 08:10:02 -05:00
slotThe
0a6048c66d X.U.EZConfig: Force readKeySequence to consume the whole input
When users specify non-existent keys, it seems most intuitive to just
abort the parse and not try to take the "longest" input that still
works.  For example, given the "key" `M-10` we should signal a parse
error (by returning `Nothing`) instead of parsing `M-1` and ignoring
the rest of the input.  The old EZConfig parser accounted for this but
when the module was rewritten to use X.U.Parser in [1], this was
forgotten about.

Fixes: https://github.com/xmonad/xmonad/issues/361

[1]: 8abeb81fd0
2022-01-05 15:06:17 +01:00
Yecine Megdiche
28d86f3a28 Merge pull request #675 from afreakk/patch-1
keysMoveWindow: change signature type D to ChangeDim in XMonad.Actions.FloatKeys
2022-01-03 11:08:42 +01:00
slotThe
324fdd802a tests: Fix typos in prop names 2022-01-03 08:59:41 +01:00
afreakk
7bcd81a7e9 keysMoveWindow signature D -> ChangeDim 2022-01-02 20:41:43 +01:00
Yecine Megdiche
5cc2db4a9a Merge pull request #674 from TheMC47/minimize-haddock-formatting
X.A.Minimize: fix formatting
2022-01-01 23:12:16 +01:00
Yecine Megdiche
be6530808f X.A.Minimize: fix formatting 2022-01-01 17:55:51 +01:00
Tony Zorman
a17e2904dd Merge pull request #671 from SimSaladin/simsaladin/minimize-improvements-rebased
X.L.BinarySpacePartition: Ignore minimized windows
2021-12-31 10:51:22 +01:00
Tony Zorman
3389241adb Merge pull request #673 from slotThe/org-mode-parser
X.P.OrgMode: Update parser tests
2021-12-31 10:02:29 +01:00
slotThe
2e74c62be7 tests: Check for inverse semigroup property in OrgMode parser
Ever since [1] we allow a second representation for the month (namely,
the numerical one).  Since we lose this information during parsing,
pretty printing is now not a proper postinverse of parsing (it still is
a proper preinverse, however).

Thus, we can't simply check for an inverse anymore.  However, the
operations still form an inverse semigroup [2], which is something
that's easily checkable.  For simplicity, do this in both directions and
completely forget about linearity for now.

[1]: 91f1a0de1e (Fix date parsing issue
                                               for org mode plugin)
[2]: https://en.wikipedia.org/wiki/Inverse_semigroup
2021-12-31 09:55:49 +01:00
slotThe
4f048fb563 X.P.OrgMode: Check num validity while parsing
There are a lot of times when we could already check for "valid" input
during parsing instead of relaying possibly incorrect dates and times to
`org-mode`.  This seems like a sensible thing to do—I don't think anyone
would ever want to schedule anything for 35:90 :)
2021-12-31 09:55:49 +01:00
Sibi Prabakaran
0f8b3616b2 Merge pull request #672 from xmonad/org-mode-date-parsing-fix
Fix date parsing issue for org mode plugin
2021-12-29 23:30:48 +05:30
Sibi Prabakaran
66fb59e934 Update pfail to empty 2021-12-29 23:20:30 +05:30
Sibi Prabakaran
f47ed83462 Update changes.md 2021-12-29 15:02:47 +05:30
Sibi Prabakaran
91f1a0de1e Fix date parsing issue for org mode plugin
This patch fixes the date parsing issue currently when an entry like
`todo +d 22 01 2022` is used. I have added tests too which demonstrate
the current issue so that we can prevent future regression.
2021-12-29 14:58:46 +05:30
Samuli Thomasson
508586bf44 X.L.BinarySpacePartition: Ignore minimized windows
Hidden windows are now ignored by the layout so that hidden windows in
the stack don't offset position calculations in the layout.

Also in X.H.ManageHelpers: added `isMinimized`
2021-12-28 22:33:52 +01:00
Tony Zorman
769e5f9c94 Merge pull request #670 from rdiaz02/withWorkspace-fuzzyMatch
X.A.DynamicWorkspaces.withWorkspace: honor custom search predicate
2021-12-28 14:04:07 +01:00
ramon diaz-uriarte (at Phelsuma)
540635fe1c X.A.DynamicWorkspaces: Honor searchPredicate in withWorkspace
If the user's prompt configuration has a custom `searchPredicate` (e.g.,
`X.P.FuzzyMatch.fuzzyMatch`) the `withWorkspace` prompt should make use
of it (instead of defaulting to an `isPrefixOf`-style matching).  For
details see

    https://mail.haskell.org/pipermail/xmonad/2021-December/015491.html
2021-12-28 14:00:52 +01:00
Tony Zorman
4d387bbfc9 Merge pull request #667 from geekosaur/664-spawnonce-documentation
document need for `manageSpawn` in `SpawnOnce`
2021-12-27 17:30:46 +01:00
brandon s allbery kf8nh
125c945cc9 X.U.SpawnOnce: Document need for manageSpawn
Also, reexport `manageSpawn` for convenience.
2021-12-27 17:31:54 +01:00
Tony Zorman
adeb27dc69 Merge pull request #666 from geekosaur/665-spacing-avoidstruts-documentation
Document interaction of `avoidStruts` with the screen rectangle
2021-12-23 09:52:41 +01:00
brandon s allbery kf8nh
d65cf05369 warn about using avoidStruts with gap modifiers 2021-12-22 16:41:30 -05:00
brandon s allbery kf8nh
2cf0a10f5b warn about use of avoidStruts with spacing modifiers 2021-12-22 16:38:11 -05:00
brandon s allbery kf8nh
a67be39673 document that avoidStruts must be applied before any modifier that
changes the screen rectangle
2021-12-22 16:27:21 -05:00
Tony Zorman
0010735aca Merge pull request #659 from slotThe/x.u.parser
New Module: XMonad.Util.Parser
2021-12-17 12:13:02 +01:00
slotThe
520c51817a X.U.EZConfig: Add simple unit tests
Add very basic unit tests for EZConfig to see if it can parse all of the
keys (and key combinations) that it promises to parse.

The long-term goal here should be to write a pretty-printer for EZConfig
and to check whether that's a proper inverse (either in the normal sense
or in the inverse semigroup sense), as the tests for X.P.OrgMode do.
2021-12-13 16:11:57 +01:00
slotThe
8abeb81fd0 X.U.EZConfig: Use X.U.Parser
Using X.U.Parser works almost as a drop-in replacement for ReadP here.
In some places (like `parseSpecial`) we need to be a little bit more
careful when constructing the parser, but this is offset a much simpler
`readKeySequence`.
2021-12-13 16:11:57 +01:00
slotThe
b1532e666f X.P.OrgMode: Use X.U.Parser
Since we now have an "internal" parser library in xmonad, use it.  This
allows us to get rid of some hacks in this module that were needed
because of ReadP's parsing behaviour.
2021-12-13 16:11:57 +01:00
slotThe
8b3df5b268 New module: XMonad.Util.Parser
This module provides a parser combinator library based on base's ReadP,
which aims to function more like other popular combinator libraries like
attoparsec and megaparsec.

In particular, the Alternative and Monoid instances are left-biased now,
so combinators like `many` and `optional` from Control.Applicative work
in a more intuitive manner.  Further, some functions (like `endBy1`)
only return the "most successful" parse, instead of returning all of
them.  We can now get away with providing a single parsing result
instead of ReadP's list of results (as such, parsers need to be
disambiguated earlier instead of trimming the list down after parsing).
2021-12-13 16:11:57 +01:00
Tony Zorman
061faf1748 Merge pull request #646 from iliayar/feature/fallback-fonts
Add xft-based font fallback support
2021-12-11 19:12:14 +01:00
Ilya
42b392e06a X.U.Font: Add font-fallback support
This adds basic font-fallback support for X.U.Font, as well as modules
using it, like X.Prompt and X.A.TreeSelect.

In the new system, multiple fonts may be specified with the syntax

    "xft:iosevka-11,FontAwesome-9"

Fixes: https://github.com/xmonad/xmonad-contrib/issues/208
2021-12-11 15:08:42 +01:00
Tony Zorman
905a4fec9c Merge pull request #660 from exorcist365/master
X.H.BorderPerWindow: Remove unused import
2021-12-07 09:10:20 +01:00
exorcist365
3569e7168b X.H.BorderPerWindow: Remove unused import
Dimension is already exported by XMonad.

Fixes: 95b37a9ab2
2021-12-07 09:08:22 +01:00
slotThe
853264b113 X.H.BorderPerWindow: Fix typo in documentation
Fixes: 95b37a9ab2
2021-12-06 12:38:04 +01:00
Tony Zorman
afdd466bc6 Merge pull request #640 from subbyte/master
Add X.U.ActionQueue and X.H.BorderPerWindow
2021-12-05 14:24:17 +01:00
slotThe
ba43dc6c7e X.U.ExtensibleConf: Fix typo in docs 2021-12-04 17:21:10 +01:00
Xiaokui Shu
95b37a9ab2 New module: XMonad.Hooks.BorderPerWindow 2021-12-04 17:21:10 +01:00
Xiaokui Shu
a981832aaf New module: XMonad.Util.ActionQueue 2021-12-04 17:21:10 +01:00
Tony Zorman
28aa164abd Merge pull request #647 from slotThe/safe-window-attrs
Prefer safe alternatives to getWindowAttributes
2021-11-28 20:43:02 +01:00
Tony Zorman
243deb943f Merge pull request #658 from d3adb5/master
X.L.MagicFocus: always use focused as master
2021-11-28 17:08:45 +01:00
d3adb5
97beb3efc7 X.L.MagicFocus: always use focused as master
Instead of searching for the currently focused window across workspaces,
make it so there is never any window above focus on the Stack that is
given to the modified layout.

Closes #657.
2021-11-28 02:04:22 -03:00
Tony Zorman
3d71669b0a Merge pull request #653 from RubenAstudillo/feature/no-leak-history-hook
Fix memory leaks in `historyHook` and `workspaceHistoryHook`
2021-11-24 21:03:17 +01:00
Ruben Astudillo
b75d0d265e Use deepseq instead of parallel 2021-11-24 15:24:08 -03:00
Ruben Astudillo
44fb597350 Fix workspaceHistoryHook memory leak
The XS.modify was leaving thunk on the history that the demand analyser
could not prove to be neccesary as they depended on the future user
interaction. This was bad as the time advance there was less and less
neccesity to force such value, so the thunk would be increasing. Since the
datatypes that the `WorkspaceHistory` are really simple, we can just
evaluate and save a good chunk of memory.
2021-11-23 17:50:18 -03:00
Ruben Astudillo
ed5d6f0d78 Fix historyHook memory leak
updateHistory leaks unfiltered windows from previous states as it is never
forced. The consumer of such data structure is not visible to ghc, so the
demand analysis has to fallback on pure laziness.

We fix this inserting evaluation points on the `historyHook` function. We do
this for two reasons, this is the only function calling `updateHistory`.
Plus we cannot do it clearly at the `updateHistory` function as we operate
inside a continuation on withWindowSet. In respect to the `put`, everything
would be a big thunk.
2021-11-23 17:50:18 -03:00
Ruben Astudillo
282afefddf Add a modify' function on extensible state 2021-11-22 17:29:08 -03:00
Tony Zorman
2a02fb3753 Merge pull request #652 from Rogach/pr/fix-window-navigation
X.A.WindowNavigation: Fix navigation being "stuck" in certain situations
2021-11-22 21:10:39 +01:00
Platon Pronko
ca5841f7fa X.A.WindowNavigation: Fix navigation getting stuck
Update left and right navigation to behave correctly even if the
currently saved position is directly on the edge of the focused window.
This makes the L/R behavior consistent with U/D navigation.

How to reproduce the issue on a 16:9 resolution like 1920x1080:

  - configure Grid layout;
  - open 4 terminals;
  - navigate to the top-right terminal;
  - open another terminal;
  - immediately close it;
  - try navigating left from the currently focused top-right terminal;
  - observe navigation being "stuck".
2021-11-22 21:12:17 +01:00
Tomas Janousek
5f3d660fde README: Add badges for IRC and Matrix 2021-11-22 11:30:59 +00:00
Tomas Janousek
65408dc07a README: Make spaces _not_ part of hyperlinks 2021-11-22 11:30:35 +00:00
slotThe
61c3aff33c X.A.CycleWorkspaceByScreen: Document
The documentation for this module was lacking, making it significantly
harder to use than the functionality wise very similar
X.A.CycleRecentWS—change that.
2021-11-21 16:42:55 +01:00
slotThe
90a96dee49 X.H.ManageHelpers: Flip logic for (^?), (~?), and ($?)
This changes how the "is*Of" infix operators are hoisted into the
ManageHook context.  Instead of `q ~? x` being a lifted version of
`isPrefixOf q x` we instead let it be a lift of `isPrefixOf x q`.

While this obviously does not matter for symmetric operators like `(==)`
and `(/=)`, for `isInfixOf` it is rather essential.  The reason for that
is that the given `q` on the left side is an atom that can't (shouldn't)
be changed (by the user) and we only have control over the right hand
side.  Otherwise, things like

    title ~? "foo"

would read "only match if `title` is an infix of `foo`" instead of the
much more useful "only match if `foo` is an infix of `title`".

Fixes: 8b6f17ba66
2021-11-17 20:14:26 +01:00
Artem Smaznov
e82a8b8849 X.U.EZConfig: Add modifier keys' KeySyms 2021-11-15 14:16:01 -05:00
slotThe
b6a8069e44 Prefer safe alternatives to getWindowAttributes
Whenever possible, prefer the safe wrappers withWindowAttributes or
safeGetWindowAttributes to getWindowAttributes.

Places where these are not applicable are limited to layouts, where
there is not good "default value" to give back in case these calls fail.
In these cases, we let the exception handling of the layout mechanism
handle it and fall back to the Full layout.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/146
2021-11-13 21:26:02 +01:00
slotThe
528b9d9fde X.Prelude: Add safeGetWindowAttributes
Move the function from X.U.DebugWindow, where it was defined already.
This is a safe version of getWindowAttributes, returning a Maybe instead
of throwing an exception, in case the window attributes could not be
retrieved.
2021-11-13 20:44:15 +01:00
brandon s allbery kf8nh
6cb2796fc0 Fix thinko in documentation
This file was obviously copied from `DwmStyle`, and the author missed changing that
out to `simpleDeco` in one place. Just patching in place since it's a one-word change.
2021-11-12 13:47:21 -05:00
slotThe
67a92edd2a Merge pull request #637 from slotThe/modernise-extending
Start modernising X.D.Extending
2021-11-10 11:47:31 +01:00
slotThe
3109e3966c X.D.Extending: Explain how to write additionalKeys
Instead of telling the user how to add custom keybindings to
xmonad—something which is already done in the tutorial—instead explain
instead how one would go about writing a version of
X.U.EZConfig.additionalKeys.  This mostly involves looking at the type
signatures and sticking some standard functions together, so it's quite
a decent way to learn about some of xmonad's internals.
2021-11-09 20:33:32 +01:00
Tomas Janousek
7807eb1be0 ci: Show error body from Hackage when it fails
Prevents having to upload the candidate manually to see what's wrong.
2021-11-08 18:18:09 +00:00
Tomas Janousek
b40b672288 ci: Swap candidate/final release logic
During the release of xmonad 0.17.0, I realized that we need to be able
to upload candidates before tagging the release on GitHub, because there
might be issues with the tarball and Hackage may reject it. When that
happened, I had to remove the release, delete the tag, upload the
candidate manually to see what's wrong with it, try to fix it, upload it
manually again, and so on.

This commit swaps the logic: when the workflow is invoked manually, it
uploads the candidate. This can be done multiple times, and once
everything is fine, the release can finally be tagged and it's released
to Hackage proper. The only disadvantage is that we need to remember to
try uploading the candidate. Not sure if there's a perfect solution…
2021-11-08 18:17:36 +00:00
slotThe
99e1b30e86 X.A.Search: Remove num=100 from google search engine
It no longer does what it was intended to do, and in fact, now does the
opposite.

When X.A.Search came to be in ~2007, Google's default of showing 10 or
so search hits was radically inadequate for poweruser needs. The 'num'
argument was used to force display of more hits (i.e., n meant 'display
at least n hits per page').

However, at some point, 'num' was inverted to mean something
catastrophically different: now it apparently means 'display no more
than n hits, total'. If you use that parameter, you will get 1 or 2
pages of hits at most reading 'About 98 results' or 'About 99
results' (no matter how many millions are available), and a blurb at the
bottom of the final page saying 'In order to show you the most relevant
results, we have omitted some entries very similar to the 99 already
displayed.' Removing the 'num' parameter then shows you all the hits
that were suppressed.

This is bad, and should be removed.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/642

Co-authored-by: Gwern Branwen <gwern@gwern.net>
2021-11-08 16:46:24 +01:00
slotThe
42dec50c17 Merge pull request #644 from slotThe/window-swallowing-noborder
X.H.WindowSwallowing: Fix single window getting lost
2021-11-08 11:46:05 +01:00
slotThe
5c50387db0 X.H.WindowSwallowing: Fix single window getting lost
ConfigureEvents may occur after a window has been deleted, an UnmapEvent
has already been sent (and thus xmonad already unmanaged the window),
but before a DestroyWindowEvent is caught by the eventHook.  For
example, this is the case when one uses smartBorders with a single
window (such that smartBorders is "active").  The ConfigureEvents
sensibly already have an empty stack (because the UnmapEvent has already
been received), which we then copy to the history.

Whenever a parent window has been found, the sensible thing to do is to
always restore it.  The fact that oldStack is Nothing simply encodes an
empty workspace and is thus something we definitely need to handle as
well.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/638
2021-11-07 16:06:30 +01:00
slotThe
feee11a0ba X.H.DynamicLog: Fix xmobarProp example
In [1] we changed the return type to not be an IO action and hence this
example can't work, even with an otherwise correct configuration.

[1]: 168cb6a6c3 (Removed unnecessary IO)
2021-11-06 11:40:13 +01:00
slotThe
3bc06447d2 X.H.TaffybarPagerHints: Rename defaultConfig to def
The former was removed in [1], so only the latter is valid code right
now.

[1]: 5140f5b5d0
     (Remove things deprecated by Data.Default)
2021-11-06 11:40:13 +01:00
Tomáš Janoušek
52998657ef Merge pull request #639 from liskin/ghc92
Test against GHC 9.2.1; fix new warnings
2021-11-05 10:30:22 +00:00
Tomas Janousek
d67df574cf ci: Run hlint with 9.0.1, not 9.2.1
cabal-3.6.2.0: Could not resolve dependencies:
    [__0] trying: hlint-3.3.4 (user goal)
    [__1] next goal: ghc-lib-parser (dependency of hlint +/-ghc-lib)
    [__1] rejecting: ghc-lib-parser-9.2.1.20211030 (conflict: hlint +/-ghc-lib =>
    ghc-lib-parser>=9.0 && <9.1)
    [__1] trying: ghc-lib-parser-9.0.1.20210324
    [__2] next goal: base (dependency of hlint)
    [__2] rejecting: base-4.16.0.0/installed-4.16.0.0 (conflict: ghc-lib-parser =>
    base>=4.13 && <4.16)
    [__2] skipping: base-4.16.0.0 (has the same characteristics that caused the
    previous version to fail: excluded by constraint '>=4.13 && <4.16' from
    'ghc-lib-parser')
    [__2] rejecting: base-4.15.0.0, base-4.14.3.0, base-4.14.2.0, base-4.14.1.0,
    base-4.14.0.0, base-4.13.0.0, base-4.12.0.0, base-4.11.1.0, base-4.11.0.0,
    base-4.10.1.0, base-4.10.0.0, base-4.9.1.0, base-4.9.0.0, base-4.8.2.0,
    base-4.8.1.0, base-4.8.0.0, base-4.7.0.2, base-4.7.0.1, base-4.7.0.0,
    base-4.6.0.1, base-4.6.0.0, base-4.5.1.0, base-4.5.0.0, base-4.4.1.0,
    base-4.4.0.0, base-4.3.1.0, base-4.3.0.0, base-4.2.0.2, base-4.2.0.1,
    base-4.2.0.0, base-4.1.0.0, base-4.0.0.0, base-3.0.3.2, base-3.0.3.1
    (constraint from non-upgradeable package requires installed instance)
    [__2] fail (backjumping, conflict set: base, ghc-lib-parser, hlint)
    After searching the rest of the dependency tree exhaustively, these were the
    goals I've had most trouble fulfilling: hlint (536), ghc-lib-parser (335),
    base (219)
2021-11-05 10:14:20 +00:00
Tomas Janousek
4b4f7f2dd6 ci: Test against GHC 9.2 2021-11-05 10:14:20 +00:00
Tomas Janousek
8623c29dd5 ci: Update haskell-ci 2021-11-05 10:14:20 +00:00
Tomas Janousek
5aff766a4c Apply hlint 3.3 hints 2021-11-05 10:14:20 +00:00
Tomas Janousek
e7f102bc9a Revert "Fix -Wdeprecations warnings (time 1.11)"
This doesn't work with the version of time shipped with GHC 8.4 and 8.6.

This reverts commit f2db7bcaa6367bc7db6b49c30e029f10534a99a2.
2021-11-05 10:14:20 +00:00
Tomas Janousek
8197cd9105 Fix -Wincomplete-uni-patterns warnings
I am not proud of this.
2021-11-05 10:14:20 +00:00
Tomas Janousek
5f3a6210a2 Fix -Wincomplete-record-updates warnings
(undefined has `HasCallStack =>` so this will give a useful error
message if anyone ever makes the code fail)
2021-11-05 10:14:20 +00:00
Tomas Janousek
b83f49d90b Fix -Wdeprecations warnings (time 1.11) 2021-11-05 10:14:20 +00:00
Tomas Janousek
850a3c245e Fix -Woperator-whitespace-ext-conflict warnings 2021-11-05 10:14:20 +00:00
Tomas Janousek
e252cc75b1 Fix -Wnoncanonical-monad-instances warnings 2021-11-05 10:14:20 +00:00
Tomas Janousek
d8faed6ad2 Fix -Wnoncanonical-monoid-instances warnings 2021-11-05 10:14:20 +00:00
slotThe
d2f0a0586c Merge pull request #641 from slotThe/prompt-C-t
X.Prompt: Add transposeChars
2021-11-05 08:36:50 +01:00
slotThe
c30e406cfd X.Prompt: Add transposeChars
This is an analogue to Emacs's `transpose-chars` function (expect that
it does not take a universal argument), bound to its default keybinding.
2021-11-03 21:11:05 +01:00
Yecine Megdiche
0973107b29 X.L.CenteredIfSignle: Update CHANGES.md 2021-10-31 10:01:58 +01:00
Yecine Megdiche
f6bcf094e1 Merge pull request #634 from elkowar/centered-if-single
Add XMonad.Layout.CenteredIfSingle
2021-10-30 22:27:09 +02:00
elkowar
eeb36e0d08 Add XMonad.Layout.CenteredIfSingle 2021-10-30 22:11:45 +02:00
slotThe
ab2ba347e5 X.D.Extending: Rephrase introduction, update
Since the tutorial is really the better place to start learning how to
use xmonad, X.D.Extending can be the place for more "advanced" usage
examples.  These would be things like writing small functions to scratch
an itch (rather than entire modules).  Rewrite the introduction
accordingly.

On the way, remove some small inconsistencies/dead links/remarks about
how things are different from version 0.5 onwards—these times are long
gone now.
2021-10-30 14:25:27 +02:00
slotThe
edbff0dca1 X.D.Extending: Link to tutorial instead of the wiki
The configurations on the wiki are quite old and mostly non-functional
at this point.  Instead, we have a shiny new tutorial we can refer to.
It contains links to actual maintainers configurations (complex they may
be, at least they compile).
2021-10-30 14:25:22 +02:00
Tomas Janousek
2b98286ba3 Bump version to 0.17.0.9 and prepare CHANGES.md sections
We need to bump the version early to avoid overwriting
https://xmonad.github.io/xmonad-docs/xmonad-contrib-0.17.0/
2021-10-28 17:58:18 +01:00
Tomas Janousek
f5f6ef41cb stack: Bump default resolver to 18.14
No impact on CI, just makes it easier for contributors to use the latest
8.10 GHC.
2021-10-28 17:22:54 +01:00
Tomas Janousek
4a356cfc7c ci: Reenable testing against released X11, xmonad
This was temporarily disabled in 229d52ff07 and 086db3123b because we
couldn't keep xmonad-contrib backwards compatible with xmonad 0.15 any
more, but xmonad 0.17.0 is out now and we can try to stay compatible for
a while.
2021-10-28 17:19:32 +01:00
Tomas Janousek
0fde4c8848 Fix Haskell2010 incompatibilities 2021-10-27 18:06:41 +01:00
Tomas Janousek
991dc6dfac xmonad-contrib.cabal: Specify default-language
Required for cabal-version >= 1.10
2021-10-27 17:57:10 +01:00
Tomas Janousek
805de214d8 Bump cabal-version in xmonad-contrib.cabal
Hackage won't accept the release otherwise.
2021-10-27 17:49:44 +01:00
Tomas Janousek
585558bfb0 Bump version number (0.17.0), update date in changelog 2021-10-27 17:00:33 +01:00
Tomáš Janoušek
a7ccfe61f3 Merge pull request #605 from TheMC47/pp-predicates
`ppPrinters` for custom workspace types, `copiesPP` fix
2021-10-27 10:16:46 +01:00
Yecine Megdiche
16b9f0f96d X.A.CopyWindow: fix copiesPP
Related: https://github.com/xmonad/xmonad-contrib/issues/557

Co-authored-by: Tomáš Janoušek <tomi@nomi.cz>
2021-10-27 10:15:29 +01:00
Yecine Megdiche
2d849cc0b7 X.H.SB.PP: ppPrinters and custom workspace types
Using `ppPrinters` with `WorkspacePredicate` and `WorkspaceFormatter`
allows users to define custom workspace types, beyond the ones
integrated in PP (i.e. urgent, current, visible, visible with no
windows, hidden, and hidden with no windows). `WorkspacePredicate`s are
added for these predicates (`isType`) with unsafe versions that assume
that predicates with a higher precedence already faield `isType'`.
`WorkspacePredicate`s can also be combined and modified with `notWP`,
`andWP`, and `orWP`.

Related: https://github.com/xmonad/xmonad-contrib/issues/557

Co-authored-by: Tomáš Janoušek <tomi@nomi.cz>
2021-10-27 10:15:29 +01:00
Aleksei Pirogov
8b6f17ba66 X.H.ManageHelpers: Add new operators (#633)
Closes: #628
2021-10-26 21:53:52 +02:00
Tomáš Janoušek
e1f4f77346 Merge pull request #632 from Targuinia/patch-1
Minor documentation fixes to `XMonad.Hooks.FadeWindows`
2021-10-26 18:43:34 +01:00
Targuinia
9824b57d12 Corrected a comment in XMonad.Hooks.FadeWindows 2021-10-26 17:03:12 +02:00
Targuinia
a335809767 Fix Haddock comments in XMonad.Hooks.FadeWindows
Some Haddocks comments were for the wrong declaration (-- ^ instead of -- |)
2021-10-26 16:52:29 +02:00
slotThe
719c8ecfe9 X.D.Developing: Refer to cabal instead of runhaskell 2021-10-25 18:40:05 +02:00
slotThe
bc5d4f18e2 X.D.Developing: Refer to CONTRIBUTING for style
The CONTRIBUTING.md file for xmonad now has style guidelines [1].  Since
X.D.Developing does not add anything new here and we direct new
contributors to CONTRIBUTING.md anyways, simply refer to the relevant
section.

[1]: bc8f7ff133
2021-10-25 14:40:26 +02:00
slotThe
5d9a599c9f X.D.Developing: Update Haddock introduction
* The Haddock documentation is a very good resource for the general
  markup syntax.
* Since we are very biased in favour of stack, document how to build
  Haddock docks with it.
2021-10-25 14:40:26 +02:00
Tomas Janousek
7a4dc29418 X.L.Fullscreen: Silence deprecation warning temporarily
Deprecation warnings are now shown to users via xmessage when xmonad
recompiles, and this may include warnings in xmonad(-contrib) itself if
people have a build script that invokes stack/cabal without --silent,
and they then may get confused. The deprecation warning in that case
won't be shown every recompile but only once whenever xmonad(-contrib)
needs to be rebuilt, but it's still annoying.

This silences the warning. We intend to refactor this part of the code
so this is a temporary measure.

Fixes: f666cf4e4e ("X.H.EwmhDesktops: Deprecate standalone hooks")
2021-10-25 10:45:51 +01:00
Tomas Janousek
c51353c6c6 Merge branch 'packdeps' 2021-10-24 13:56:53 +01:00
Tomas Janousek
046f3c3871 Bump lower bound for base
We only test with GHC 8.4+ so it's unlikely this builds with older base
(Semigroup stuff …).
2021-10-24 13:55:19 +01:00
Tomas Janousek
8edc8ab789 Bump upper bounds for bytestring, time
I've tested these manually by adding them to extra-deps. Hopefully
they'll soon be available in a release of GHC or Stackage, so I'm not
adding an extra stack.yaml to test this.
2021-10-24 13:55:19 +01:00
Tomas Janousek
5cc26aaa21 ci: Check package bounds using packdeps once a week
This was a part of the release procedure but we should do it proactively
instead.

Related: https://github.com/xmonad/xmonad-contrib/issues/393
2021-10-24 13:55:02 +01:00
Tomas Janousek
d6b4f174d6 ci: Add Stackage LTS 18 to Stack test matrix 2021-10-24 11:17:41 +01:00
Tomas Janousek
0be6780559 ci: Avoid caching GHC
We install GHC using apt, so stack shouldn't install it, but should it
ever end up installing it anyway (version mismatch, version unavailable
in hvr/ghc ppa, …), we don't want it wasting valuable cache space.
2021-10-24 11:11:48 +01:00
slotThe
f39218ddb5 X.D.Developing: Drop confusing "or freer" part
Currently, all contrib modules are licensed under a 3-clause BSD license
anyways.  The term "freer" is quite confusing and may even refer to
several (non-BSD) licenses, depending on the authors sensibilities.
2021-10-24 08:04:38 +02:00
slotThe
9b840a1189 Merge pull request #631 from liskin/readme
README: Improve badges, Installation/Contributing sections; CHANGES prep
2021-10-23 09:38:39 +02:00
Tomas Janousek
c71756095e CHANGES: Almost final prep 2021-10-23 00:41:27 +01:00
Tomas Janousek
32028915a3 README: Improve Installation/Contributing sections further
(Copy&paste from https://github.com/xmonad/xmonad/pull/340 mostly.)
2021-10-23 00:34:39 +01:00
Tomas Janousek
4560abd1e6 README: Tweak badges a bit 2021-10-22 23:24:15 +01:00
Tomáš Janoušek
2c01279d1c Merge pull request #630 from liskin/readme
README: Long overdue update
2021-10-22 22:12:20 +01:00
Tomas Janousek
33ccf910a6 Add CONTRIBUTING.md
This makes GitHub show a link to it when opening issues/PRs.
2021-10-22 22:11:56 +01:00
Tomas Janousek
268fc70d0e README: Long overdue update
* "community-maintained" is more accurate and sounds better than "third-party"
* refresh description
* add logo and badges to make it prettier
* update doc links
2021-10-22 22:11:56 +01:00
Tomas Janousek
c0cea57604 LICENSE: Fix wording to make it detectable by GitHub 2021-10-22 22:11:56 +01:00
Tomáš Janoušek
0f6403c2e9 Merge pull request #629 from liskin/managedocks-hooks-deprecation
X.H.ManageDocks: Deprecate individual hooks
2021-10-22 20:48:16 +01:00
Tomas Janousek
c2e36da92c X.H.ManageDocks: Deprecate individual hooks
This will make it easier to transition to an implementation of EWMH that
doesn't expose the individual hooks: X.H.ManageDocks would become a
deprecated compatibility reexport of X.H.EWMH.Struts for a release or
two, but the individual hooks need to be removed before that.

Note that individual hooks in X.H.EwmhDesktops were deprecated earlier
and individual hooks in XMonad.Hooks.UrgencyHook aren't exported any
more (or perhaps never been), so this only leaves X.H.SetWMName, which
unfortunately does not have a combinator interface at this point.

Related: https://github.com/xmonad/xmonad-contrib/pull/625
2021-10-22 16:07:31 +01:00
slotThe
0aeaf93a6e Merge pull request #438 from elkowar/cleanup-independent-screens
X.L.IndependentScreens: Add utility functions, refactor
2021-10-22 08:30:21 +02:00
elkowar
b552b453d5 X.L.IndependentScreens: Add utility functions, refactor
* Add a few utility functions which make working with IndependentScreens
  more ergonomic; namely workspaceOnScreen, focusWindow', focusScreen,
  nthWorkspace, and withWspOnScreen.
* Clean up whenCurrentOn and make it more readable.
* Fix the type-signature of onCurrentScreen.
2021-10-22 08:21:24 +02:00
Tomas Janousek
956d51c225 Update .mailmap
Drop lines that aren't needed.
Add lines to deduplicate people.
Add lines to add/fix some names.
2021-10-21 16:22:07 +01:00
slotThe
08b8b285a8 Merge pull request #620 from TheMC47/extending-module-list
`X.D.Extending`: Remove module list
2021-10-21 14:49:37 +02:00
Yecine Megdiche
b2d4aa7dad Pull Request Template: Drop X.D.Extending 2021-10-21 08:28:35 +02:00
Yecine Megdiche
839302533b X.D.Extending: Remove module list
As of 38c11c1e3c, all modules now include
a `Description` string that can be rendered using Haddock. This makes
the list in `XMonad.Doc.Extending` redundant.

Related: https://github.com/xmonad/xmonad-contrib/issues/619
2021-10-21 08:28:35 +02:00
Tomáš Janoušek
e5b5ce74b2 Merge pull request #626 from liskin/ewmh-refactor-quick
EWMH: Improve interface for custom sorting, filtering, renaming and window activation
2021-10-20 16:58:40 +02:00
Tomas Janousek
6ab136eb56 scripts/xmonadctl: Fix build
Fixes: bd5b969d9b ("Apply hlint hints")
2021-10-20 15:24:55 +01:00
Tomas Janousek
f666cf4e4e X.H.EwmhDesktops: Deprecate standalone hooks
We should get rid of this error-prone interface ASAP, so mark it as
deprecated to give people some time to adapt their configs.
2021-10-20 14:51:39 +01:00
Tomas Janousek
860f80a6d3 X.H.Focus: Adapt docs to the new activation interface
Fixes: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/192
Related: https://github.com/xmonad/xmonad-contrib/pull/128
2021-10-20 14:51:23 +01:00
Tomas Janousek
79b130b9d6 Add some docs references for workspace filtering 2021-10-20 14:51:23 +01:00
Tomas Janousek
08ec79eec1 X.H.EwmhDesktops: Improve interface for hooking window activation
https://github.com/xmonad/xmonad-contrib/pull/192 introduced a breaking change:

  * `XMonad.Hooks.EwmhDesktops`

    `ewmh` function will use `logHook` for handling activated window. And now
    by default window activation will do nothing.

This breaking change can be avoided if we designed that a bit
differently. #192 changed `ewmhDesktopsEventHook` to invoke `logHook`
instead of focusing the window that requested activation and now
`logHook` is supposed to invoke a `ManageHook` through `activateLogHook`
which consults a global `NetActivated` extensible state to tell if it's
being invoked from `ewmhDesktopsEventHook`. This seems convoluted to me.

A better design, in my opinion, is to invoke the `ManageHook` directly
from `ewmhDesktopsEventHook`, and we just need a way to configure the
hook. Luckily, we now have `X.U.ExtensibleConf` which makes this
straightforward. So we now have a `setEwmhActivateHook`, and the
activation hook defaults to focusing the window, undoing the breaking
change.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/110
Related: https://github.com/xmonad/xmonad-contrib/pull/192
Related: https://github.com/xmonad/xmonad-contrib/pull/128
2021-10-20 14:51:23 +01:00
Tomas Janousek
3175f276be X.A.WorkspaceNames: Adapt EwmhDesktops integration to the new interface
Related: https://github.com/xmonad/xmonad-contrib/pull/105
Related: https://github.com/xmonad/xmonad-contrib/pull/122
Related: f271d59c34 ("X.A.WorkspaceNames: Provide workspaceListTransform for EwmhDesktops")
2021-10-20 14:50:17 +01:00
Tomas Janousek
fe933c3707 X.H.EwmhDesktops: Improve interface for custom workspace sorting, filtering and renaming
Now that we have `XMonad.Util.ExtensibleConf`, users can comfortably use
the `ewmh` combinator and still customize workspace ordering, filter out
scratchpads and expose altered workspace names.

To make this all work nicely, we introduce not one, but two
configuration options: a sort/filter function and a rename function.
This is because renaming and sorting in one go makes it hard (perhaps
even impossible) to decide which workspace to switch to upon receipt of
a _NET_CURRENT_DESKTOP request from a pager or wmctrl/xdotool. (The only
reason this wasn't a problem before is because one could pass the
renaming function to `ewmhDesktopsLogHookCustom` only, not
`ewmhDesktopsEventHookCustom`, which is a confusing hack as can be seen
in the related closed pull requests.)

Related: https://github.com/xmonad/xmonad-contrib/pull/238
Related: https://github.com/xmonad/xmonad-contrib/pull/105
Related: https://github.com/xmonad/xmonad-contrib/pull/122
2021-10-20 14:50:17 +01:00
Tomas Janousek
6b9520b03b X.H.EwmhDesktops: Mostly cosmetic, mostly docs cleanups 2021-10-20 14:48:41 +01:00
Tomas Janousek
6358683058 X.H.UrgencyHook: Add askUrgent and doAskUrgent
These are useful when one blocks some _NET_ACTIVE_WINDOW requests but
still wants to somehow show that a window requested focus.

Related: https://github.com/xmonad/xmonad-contrib/pull/110
Related: https://github.com/xmonad/xmonad-contrib/pull/128
Related: https://github.com/xmonad/xmonad-contrib/pull/192
2021-10-20 14:46:52 +01:00
Tomas Janousek
3a72dd5355 X.U.ExtensibleConf: Add high-level idioms for non-Semigroup, but Default types
For configuration values that don't compose well using a Semigroup
instance, provide a high-level API allowing arbitrary modification of
the value, taking its Default if absent. This API is only usable for
separate configuration data and cannot be used to guard addition of hook
using `once`.
2021-10-20 14:46:52 +01:00
Tomas Janousek
3dbdc51158 X.U.ExtensibleConf: Perform 'add' before modifying in once(M)
This better matches the documentation.

It is still, however, considered bad practice to rely on the order of
these operations. `f` isn't meant to touch any extensible configuration.
If it happens to do so anyway, it no longer loops. :-)
2021-10-19 22:57:50 +01:00
Yecine Megdiche
e0c7e35b3d Merge pull request #613 from TheMC47/update-dynamiclog-docs
Update `X.H.DynamicLog` references
2021-10-19 21:54:01 +02:00
slotThe
8e0e8a605d X.A.Search: Make (!>) right associative
Unless specified otherwise, operators in Haskell associative to the
left.  However, the ergonomics of (!>) heavily lean towards the left
operand being a "single" search engine, not a combined one.

This causes trouble when not using `multi` or defining search engines
with a right fold, but (following the documentation) writing something
like

    multiEngine = intelligent (wikipedia !> mathworld !> (prefixAware google))

instead.  This particular definition would force the user to write
`wikipedia/mathworld:wikipedia:search-term` instead of just
`wikipedia:search-term` to access the first search engine.

Simply giving (!>) an explicit associativity fixes these problems.
2021-10-19 18:48:47 +02:00
Yecine Megdiche
53adf02b38 X.A.Prefix: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
a5b335469a Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
8defd7f4c8 xmonadpropread.hs: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
c2f45b49ff X.A.WorkspaceNames: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
45a07b0e1b X.U.L.NamedScratchpad: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
8b3ed5224a X.U.WorkspaceCompare: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
2cbb342adc X.A.DynamicWorkspaceOrder: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
74f3b6206f X.H.DynamicBars: Deprecate in favor of X.H.StatusBar 2021-10-19 07:56:11 +02:00
Yecine Megdiche
76bab07eb9 X.A.WindowNavigation: Added bind example 2021-10-19 07:56:11 +02:00
Yecine Megdiche
6ca1e334eb X.U.Loggers: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
0e3001681d X.U.NamedScratchpad: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
3f2210206f X.L.IndependentScreens: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
9151492c6e X.U.Loggers: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
5e7085661e X.H.FloatNext: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
cfe7533c42 X.H.UrgencyHook: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
ac6705a144 X.A.WorkspaceCursors: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
6ddde878ec X.L.LayoutModifier: Update X.H.DynamicLog reference 2021-10-19 07:56:11 +02:00
Yecine Megdiche
2932a8e2f8 X.H.ToggleHook: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Yecine Megdiche
7ec3a4e034 X.A.TopicSpace: Update X.H.DynamicLog references 2021-10-19 07:56:11 +02:00
Tomas Janousek
586416b0f9 X.H.Rescreen: XConfig (a ⇒ l)
It's a layout, `a` is misleading.
2021-10-18 10:30:41 +01:00
Tomas Janousek
087526dee3 X.H.Rescreen: Fix typo in haddocks 2021-10-18 10:30:41 +01:00
Tomas Janousek
0de958e09c X.H.Rescreen: import X.Prelude
A race condition between merging the Prelude PR and the Rescreen PR. :-)
2021-10-18 10:30:41 +01:00
brandon s allbery kf8nh
fa3536b40b Merge pull request #624 from alternateved/add-usage-section
X.H.DynamicProperty: Add usage section
2021-10-14 13:50:09 -04:00
alternateved
ab98b40034 Add X.H.DynamicProperty usage section 2021-10-14 19:28:33 +02:00
Yecine Megdiche
50996809aa Merge pull request #623 from alternateved/fix-missing-information
X.A.CycleWS: Fix missing type names in documentation
2021-10-14 18:02:59 +02:00
alternateved
2a9ccf3002 X.A.CycleWS: Fix names in example 2021-10-14 17:57:00 +02:00
Tomáš Janoušek
5085e72217 Merge pull request #622 from alternateved/fix-missing-export
X.A.Search: Fix missing export
2021-10-13 20:38:39 +02:00
alternateved
374293c179 Fix missing export 2021-10-13 19:23:40 +02:00
Tomáš Janoušek
3b4a262658 Merge pull request #621 from slotThe/dynamic-workspaces-nub
X.A.DynamicWorkspaces: Remove duplicates when melding
2021-10-13 16:51:05 +02:00
slotThe
bb5b64a198 Update CHANGES.md: Fix X.A.DynamicWorkspaces freeze 2021-10-13 14:29:56 +02:00
slotThe
929a6a3f6f X.A.DynamicWorkspaces: Remove duplicates when melding
When removing a workspace and distributing its windows, it's important
to remove any duplicates that may be there due to, for example, usage of
X.A.CopyWindow.  X will only draw one of these window, leading to some
artifacts.

Related: https://github.com/xmonad/xmonad-contrib/issues/565

Co-authored-by: Tomas Janousek <tomi@nomi.cz>
2021-10-13 12:05:52 +02:00
slotThe
f821a2ec0c Merge pull request #617 from slotThe/runorraise-dir-exe
X.P.RunOrRaise: Disambiguate directories and executables
2021-10-11 20:42:59 +02:00
slotThe
5bdc5993f9 X.P.RunOrRaise: Disambiguate directories and executables
When there is a directory and a file in $PATH of the same name `foo`, we
display `foo`, as well as `foo/` in the prompt, but selecting either one
of them will invariably run or raise the directory, as this test is done
beforehand.

Since directories already carry a trailing forward slash from the shell
prompt's `getShellCompl`, this is easily disambiguated by incorporating
an additional check.

It is duly noted that the same problem also exists for files in the
current directory.  This could be fixed in a similar way (adding a
unique suffix to files and checking for that), but since this would
involve changing `getShellCompl` and no-one has complained about this so
far, it was deemed "not worth it" for now.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/616
2021-10-11 20:41:57 +02:00
Tomáš Janoušek
b331821275 Merge pull request #618 from aartamonau/master
EwmhDesktops: Advertise _NET_WM_STATE_DEMANDS_ATTENTION.
2021-10-10 11:09:37 +02:00
Aliaksey Artamonau
2b1febb40b EwmhDesktops: Advertise _NET_WM_STATE_DEMANDS_ATTENTION.
XMonad.Hooks.UrgencyHook knows how to understand this hint, but it's
not advertised as supported via _NET_SUPPORTED. This prevents certain
applications (e.g. kitty terminal emulator) from using it.
2021-10-09 16:12:04 -07:00
Yecine Megdiche
8ef05975c7 X.H.DynamicIcons: Add X.H.StatusBar support 2021-10-05 21:45:42 +02:00
Yecine Megdiche
f470f18cf0 X.H.DynamicIcons: tweak docs example 2021-10-04 18:03:58 +02:00
slotThe
9ff7f89664 Merge pull request #608 from slotThe/ez-prefix
X.A.Prefix: Use EZConfig parser for usePrefixKey
2021-10-04 16:33:40 +02:00
slotThe
82f0a7ad57 X.A.FloatKeys: Use Int for offset deltas
So far, we have used the `D` tuple, as defined in X.Operations, for
these.  However, `D` uses `Word32` for its components, which are not
supposed to carry negative values.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/578
2021-10-03 17:35:07 +02:00
slotThe
967cc9a869 X.A.FloatKeys: Use fi
Instead of fromIntegral, use the somewhat more concise and often used fi
alias.
2021-10-03 17:24:54 +02:00
slotThe
30c139e298 X.A.Prefix: Use EZConfig parser for usePrefixKey
Utilise EZConfig's Emacs style syntax for entering the prefix key.

The syntax has been well-established for use in configuration files;
especially in this case it can be a bit awkward having to specify a
function that takes a config just for a single keybinding.
2021-10-03 08:55:31 +02:00
slotThe
3058d1ca22 Merge pull request #609 from slotThe/fun-with-descriptions
Add Description string to modules
2021-09-30 15:10:07 +02:00
slotThe
38c11c1e3c Add "Description" field to module headers
Fixes: https://github.com/xmonad/xmonad-contrib/issues/592
2021-09-26 14:15:54 +02:00
slotThe
4d1f76f7d8 X.D.Extending: Add missing modules
X.D.Extending claims to index all of the contrib library, but this was
not really the case.  While most modules where indeed indexed, some
notable ones were missing from this list.  Since we're pointing users to
this quite prominently, this is something that needs to be fixed.
2021-09-26 14:14:44 +02:00
slotThe
20fdcbad01 Merge pull request #606 from alternateved/remove-outdated-search-engines
* X.A.Search: Update/Remove outdated URLs, add GitHub

  - The `codesearch`, `openstreetmap`, and `thesaurus` searches were
    using old URLs; update those.
  - Remove the now defunct isoHunt serach.
  - Add a search for GitHub.

* X.A.Search: Change http to https
2021-09-23 12:30:00 +02:00
slotThe
7f49fe3b4d X.A.Search: Change http to https
It really is time.
2021-09-23 12:16:29 +02:00
alternateved
732a3b6e75 X.A.Search: Update/Remove outdated URLs, add GitHub
- The `codesearch`, `openstreetmap`, and `thesaurus` searches were
    using old URLs; update those.
  - Remove the now defunct isoHunt serach.
  - Add a search for GitHub.
2021-09-23 12:16:29 +02:00
slotThe
948c048832 Merge pull request #602 from ssbothwell/master
X.A.WithAll: Add killOthers
2021-09-22 16:51:51 +02:00
Solomon Bothwell
7a2001cfa2 X.A.WithAll: Add killOthers
This adds the function `killOthers`, which kills all unfocused windows
on the current workspace.

As discussed in the PR itself [1], the module suffix `WithAll` is not
quite optimal at this point, as we are acting on window _groups_ and not
necessarily just all window on a workspace.  However, in order to keep
this commit atomic, this consideration is postponed until another day.

[1]: https://github.com/xmonad/xmonad-contrib/pull/602
2021-09-22 16:45:37 +02:00
slotThe
0c6fdf4e75 Merge pull request #601 from ssbothwell/feature/custom-xmonad-prompt-title
Add custom title to xmonad prompts
2021-09-09 21:49:37 +02:00
Solomon Bothwell
b79fbf6975 X.P.XMonad: Add xmonadPromptCT
Currently when creating an XMonad Prompt one is stuck with "XMonad:" as
the title for the prompt.  However, sometimes it is nice to be able to
create a prompt with custom commands that has a particular title.

This changes the internals of X.P.XMonad to facilitate this and adds
xmonadPromptCT as a user facing function.
2021-09-09 21:43:43 +02:00
slotThe
81339f2044 Merge pull request #598 from slotThe/spacing-docs
Update X.L.Spacing documentation
2021-08-30 10:48:02 +02:00
slotThe
34af6ebed1 X.L.Spacing: Extend documentation
Users are having trouble with this module all the time.  Now that
certain helper functions are undeprecated, we should tell users how they
may use them.  It is also worth explaining the scary-looking
`spacingRaw` command a bit further.

Related: https://github.com/xmonad/xmonad-contrib/pull/597
2021-08-29 10:10:49 +02:00
slotThe
4a63999df6 X.L.Spacing: Reorder export list 2021-08-29 10:03:01 +02:00
slotThe
64e67d5749 CHANGES.md: Mention X.L.Spacing undeprecations
Related: https://github.com/xmonad/xmonad-contrib/pull/597
2021-08-29 10:03:01 +02:00
slotThe
d8f4f841a0 X.L.Spacing: Remove link to backwards compatibility section
This has been removed already, so remove the link and move the
undeprecated functions out of there.

Related: https://github.com/xmonad/xmonad-contrib/pull/597 (cadb178819)
2021-08-29 09:37:28 +02:00
slotThe
04eadeb5ed Merge pull request #597 from IvanMalison/unDeprecateSpacingFunctions
Undeprecate spacing convenience functions
2021-08-28 10:49:21 +02:00
Ivan Malison
cadb178819 Undeprecate spacing convenience functions
These should be undeprecated for several reasons:

  - The suggestion to use spacingRaw is pretty ridiculous; the interface
    to spacingRaw is very general and flexible, which is great, but I
    think that most people probably do not need all of that flexibility,
    and one of these convenience functions may suit their needs better.

  - There is precendent for having convenience functions like
    these (like X.L.Magnifier)

These were deprecated in a rewrite to make X.L.Spacing support a
non-uniform border length, but from a usability perspective wrappers
should always be preferred to such a general interface with rather shaky
documentation.

Related: https://github.com/xmonad/xmonad-contrib/pull/243 (2c53d507ee)
2021-08-28 10:45:00 +02:00
slotThe
04713d2e9c Merge pull request #596 from slotThe/logTitlesOnScreen
X.U.Loggers: Add `logTitlesOnScreen`
2021-08-19 08:40:01 +02:00
slotThe
0935fd26e0 Update CHANGES.md: Add logTitlesOnScreen 2021-08-18 08:05:14 +02:00
slotThe
1cab211bf0 X.U.Loggers: Add logTitlesOnScreen
This works like logTitles, but gets an explicit screen to log the window
titles on.  This may be useful when having status bars for each screen
that show all windows on their respective visible workspaces.
2021-08-17 12:26:34 +02:00
Tomáš Janoušek
a9ad56be11 Merge pull request #585 from liskin/xmessage
Use xmessage from core
2021-08-17 11:01:29 +01:00
Tomas Janousek
07040cbd58 Use xmessage from core
Related: https://github.com/xmonad/xmonad/pull/318
2021-08-17 10:56:14 +01:00
Tomas Janousek
8d557c6954 github: Drop FUNDING.yml
Replaced with https://github.com/xmonad/.github/blob/main/FUNDING.yml,
which points to xmonad's funding platforms instead of mine.

Related: https://github.com/xmonad/xmonad/pull/295
Related: https://github.com/xmonad/xmonad-contrib/pull/544
2021-08-15 22:29:27 +01:00
Tomas Janousek
89ecfe72a1 ci: Hackage release automation
Tested on https://github.com/xmonad/X11/releases/tag/1.10.1 so we can
deploy this here as well now.

Related: https://github.com/xmonad/xmonad/pull/308
Related: https://github.com/xmonad/xmonad-contrib/issues/393
2021-08-15 17:37:22 +01:00
slotThe
fa00fad1d9 Merge pull request #594 from IvanMalison/windowBringerFilter
X.A.WindowBringer: Add a filter function to config
2021-08-15 17:32:34 +02:00
slotThe
ee40542cb8 X.P.OrgMode: Allow specifying home dir starting with ~
It is already possible to "start" from $HOME by specifying a relative
directory (one starting without a starting slash).  However, it is often
nice to be explicit about this by writing `~/' directly—support this.
2021-08-15 17:04:21 +02:00
Ivan Malison
09b1dc1a6e X.A.WindowBringer: Add a filter function to config 2021-08-15 17:01:26 +02:00
slotThe
5417969522 X.P.OrgMode: Update documentation
Fix spelling mistakes, as well as make the existing documentation a
little bit more accurate in places.
2021-08-15 16:34:41 +02:00
Tomáš Janoušek
b4a13e6b1b Merge pull request #119 from IvanMalison/query_toggle_state
X.L.MultiToggle: Add function to query toggle state
2021-08-13 01:26:04 +01:00
Ivan Malison
3e83068e0a X.L.MultiToggle: Add function to query toggle state 2021-08-13 01:25:03 +01:00
Yecine Megdiche
a03d58cf6a Merge pull request #474 from TheMC47/fixed-aspect-ratio
New layout modifier: XMonad.Layout.FixedAspectRatio
2021-08-11 12:21:03 +01:00
Yecine Megdiche
b6b6616400 Added XMonad.Layout.FixedAspectRatio
Layout modifier for user provided per-window aspect ratios.
2021-08-11 13:15:21 +02:00
slotThe
efcc424c98 Merge pull request #587 from slotThe/fix-orgmode-parser
X.P.OrgMode: Fix behaviour of getLast
2021-08-11 07:16:52 +02:00
slotThe
e4b8b1f6f2 Tests: Add tests for OrgMode regressions
Add regression tests to make sure we keep the behaviour fixed by
97aeaf11c10a0f38b4cd1df4726a10bb9188f4ca.

Related: https://github.com/xmonad/xmonad-contrib/issues/584
2021-08-11 07:11:54 +02:00
slotThe
b42303aa6f X.P.OrgMode: Fix behaviour of getLast
So far, while parsing strings like "<ptn><more-letters>", the `getLast`
function immediately stopped on strings of the form "<ptn><whitespace>".
This may be a bit confusing given the functions name.  Strings of
the—perhaps artificial—form

    "a +d f 1 +d f 2"

would be cut short and parsed as

    Deadline "a" (Time { date = Next Friday, tod = Just 01:00 })

instead of the more intuitive

    Deadline "a +d f 1" (Time { date = Next Friday, tod = Just 02:00 }).

This is readily fixed by applying the `go` parser as often as possible,
only returning the longest list, and then pruning eventual leftovers at
the end of the string.  Since we were already invoking `dropWhileEnd` to
trim whitespace before, the added `reverse`s should not impact
performance at all.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/584
2021-08-11 07:11:54 +02:00
Yecine Megdiche
e1a2bad168 Export placeRectangle 2021-08-09 12:06:19 +02:00
Tomáš Janoušek
8fab380724 Merge pull request #580 from IvanMalison/add-nix-flake
Add a flake.nix file
2021-08-09 10:57:21 +01:00
Ivan Malison
7402a7c250 Use "nix develop -c cabal v2-build -O0" to speed up the workflow
With "nix build", just the build of xmonad-contrib itself takes 3
minutes (it builds twice, the second build with profiling enabled), so
it ends up being almost 6 minutes in total, making this workflow the
slowest one.
2021-08-09 10:50:10 +01:00
Ivan Malison
7c7ff1fabd Add workflow for testing nix flake 2021-08-09 10:46:15 +01:00
Ivan Malison
3e43315def Add a flake.nix file 2021-08-09 10:46:15 +01:00
Tomáš Janoušek
6f0b9e3142 Merge pull request #577 from liskin/focus-under-pointer
X.A.UpdateFocus: Add focusUnderPointer
2021-08-09 10:20:41 +01:00
Tomas Janousek
fefebd56b2 X.A.UpdateFocus: Add focusUnderPointer
Some people like their mouse pointer to move when changing focus with
the keyboard, other people like their pointer to stay and focus to
follow. xmonad(-contrib) supports both preferences, but imperfectly:
The former requires using the XMonad.Actions.UpdatePointer contrib
module, the latter (focusFollowsMouse) only reacts to CrossingEvent; the
focus isn't updated after changing workspaces or layouts.

This adds an inverse of XMonad.Actions.UpdatePointer.updatePointer that
immediately updates the focus instead.

Fixes: https://github.com/xmonad/xmonad/issues/108
2021-08-09 10:20:00 +01:00
Tomáš Janoušek
78373349c2 Merge pull request #586 from liskin/submap-sync
X.A.Submap, X.U.Ungrab: Sync after ungrab (fixes issues with runProcessWithInput)
2021-08-09 10:12:44 +01:00
Tomas Janousek
91995df559 X.A.Submap, X.U.Ungrab: Sync after ungrab (fixes issues with runProcessWithInput)
When `runProcessWithInput` is invoked immediately after
`ungrabPointer`/`ungrabKeyboard`, we don't actually ungrab at all
because `runProcessWithInput` blocks and the ungrab requests wait in
Xlib's queue for a requests that needs a queue flush.

Common uses of `unGrab` (before `spawn`) aren't followed by a blocking
action, so the ungrab requests are flushed by xmonad's main loop, and
this is merely a timing issue—fork/exec takes a while and xmonad
probably manages to get back to its main loop in time. Uses of
`runProcessWithInput` in ordinary non-submap key bindings happen to work
because key bindings are passive grabs—the grab is released by the
user's fingers releasing the key itself, even if xmonad's ungrab
requests are stuck in a blocked queue. Submap key bindings, however,
take an active grab and therefore need to ungrab explicitly.

Easy fix—explicit `sync`.

Fixes: https://github.com/xmonad/xmonad/issues/313
2021-08-08 16:05:49 +01:00
Tomas Janousek
73e4691ba7 ci: Test with GHC 8.10.4 2021-08-08 11:41:16 +01:00
Tomas Janousek
8de415743d ci: Disable optimization in the haskell-ci workflow
Cuts a minute from the build. This was already disabled in the Stack
workflow and we just forgot to put it here as well.

Related: https://github.com/xmonad/xmonad-contrib/pull/580
2021-08-08 11:37:29 +01:00
Tomas Janousek
c5654c47ba tests: Show counterexamples for test failures in OrgMode 2021-08-07 15:25:35 +01:00
Tomas Janousek
97508ac109 X.H.TaffybarPagerHints: Correct module name in haddock header
Fixes: f754b9f926 ("X.U.TaffybarPagerHints: init")
2021-08-01 09:22:58 +01:00
Tomas Janousek
ad23988a99 Merge branch 'addTaffybarPagerHints' 2021-07-31 23:07:10 +01:00
Ivan Malison
f754b9f926 X.U.TaffybarPagerHints: init 2021-07-31 23:06:19 +01:00
Tomas Janousek
4c759ff70c CHANGES: Fix whitespace 2021-07-26 18:52:22 +01:00
slotThe
97289ff6ca Merge pull request #574 from slotThe/only-float
X.L.NoBorders: Add OnlyFloat
2021-07-24 10:22:46 +02:00
slotThe
815d0e397b Merge pull request #562 from 4caraml/window-sublayouting
Add sublayouting to X.H.WindowSwallowing
2021-07-23 19:18:48 +02:00
4caraml
bbd972012e X.H.WindowSwallowing: Implement SubLayout window "swallowing"
This implements window swallowing on top of SubLayouts; the matched
windows are simply tabbed together instead of one actually being
swallowed.  This provides an improved experience for people using
SubLayouts, as the parent window is still accessible.

Done as part of ZuriHac 2021.

Related: https://github.com/xmonad/xmonad-contrib/issues/416#issuecomment-777400194
2021-07-23 18:48:37 +02:00
slotThe
a3aff3b946 Merge pull request #576 from liskin/fix-def-k
X.H.StatusBar: Simplify the fix for `def` as `k`
2021-07-23 08:20:00 +02:00
Tomas Janousek
af2183b316 X.H.StatusBar: Simplify the fix for def as k
Fixes: 58e2b803a4 ("fix: handle `const (0,0)` from passing `def` as keybinding action")
2021-07-22 18:47:10 +01:00
Yecine Megdiche
6b16e45166 Merge pull request #575 from geekosaur/def-keybinding-function
trap `(0,0)` keybinding function and use default binding
2021-07-22 10:48:34 +01:00
brandon s allbery kf8nh
58e2b803a4 fix: handle const (0,0) from passing def as keybinding action
Before https://github.com/xmonad/xmonad/commit/383ffb7 this would
bind all unbound keys to toggle struts; after it, it would bind no
keys at all. With this commit, it will check for this case and use
the default keybinding instead.

Users who intend no key to be bound should probably use `withSB`
instead, especially in light of aforementioned commit.
2021-07-21 15:30:29 -04:00
slotThe
03f055fe0d Updates CHANGES.md: Add OnlyFloat 2021-07-21 07:59:22 +02:00
slotThe
ad58f0a388 X.L.NoBorders: Add property test for OnlyFloat
OnlyFloat should remove all floating borders at all times; this is a
property that's readily tested with the multihead setup that's already
defined.
2021-07-21 07:59:22 +02:00
slotThe
220656aab0 Add Arbitrary instance for RationalRect 2021-07-21 07:59:22 +02:00
slotThe
8a0a84f1d5 Merge pull request #573 from Rogach/pr--fix-color-range-from-class-name
Rewrite GridSelect.stringToRatio to use randomR (fixes #572)
2021-07-20 10:38:16 +02:00
Platon Pronko
71e57caa8e rewrite GridSelect.stringToRatio to use randomR (fixes #572)
Due to differences between random-1.1 and random-1.2, on newer systems
stringToRatio returns numbers outside [0, 1] range, which breaks
colorRangeFromClassName colorizers.

This commit fixes the issue by using randomR to directly generate the random number.

Also this fixes the compilation warning (genRange and next are deprecated in random-1.2).
2021-07-19 21:20:40 +03:00
slotThe
28fff7c1a2 X.L.NoBorders: Add OnlyFloat
This adds a new constructor to Ambiguity to unconditionally remove
borders for all floating windows.
2021-07-16 13:52:20 +02:00
slotThe
da2fb360b8 Merge pull request #568 from kurnevsky/ewmh-windows-ordering
Change EWMH windows ordering to be closer to the spec

Fixes: #567
2021-07-14 19:36:34 +02:00
Tomas Janousek
5d0a3de24d Merge branch 'AusCyberman/master'
Closes: https://github.com/xmonad/xmonad-contrib/pull/569
2021-07-13 10:43:10 +01:00
Tomas Janousek
747862c1eb X.H.DynamicIcons: Import X.H.StatusBar.PP instead of the obsolete X.H.DynamicLog 2021-07-13 10:42:55 +01:00
Tomas Janousek
23e3decbb2 CHANGES: Clarify X.H.DynamicIcons entry
This should've been part of a0caca5edc but
got lost.

Fixes: a0caca5edc ("X.H.DynamicIcons: Update docs")
2021-07-13 10:42:55 +01:00
AusCyber
bbb093d466 X.H.DynamicIcons: Add icon filtering to configuration 2021-07-13 10:42:55 +01:00
slotThe
27ae4bd2a4 Merge pull request #570 from skewerr/master
X.A.DynamicWorkspaceOrder: Export swapOrder and swapWithCurrent
2021-07-13 10:10:08 +02:00
spoonm
31b12ebb8a X.A.DynamicWorkspaceOrder: Export swapOrder and swapWithCurrent
These actions are very convenient for managing the workspace order, and
should be made available for use through the module.
2021-07-13 04:02:02 -03:00
Evgeny Kurnevsky
fa82db1130 Change EWMH windows ordering to be closer to the spec. 2021-07-02 23:13:54 +03:00
slotThe
1351f9a931 Merge pull request #564 from slotThe/nspHide
X.U.NamedScratchpad: Add logHook to auto-hide named scratchpads on focus loss
2021-06-29 14:15:29 +02:00
slotThe
159adddb3b Update CHANGES.md: Add nsHideOnFocusLoss 2021-06-29 14:07:05 +02:00
slotThe
361a34d797 X.U.NamedScratchpad: Add nsHideOnFocusLoss
This adds a new logHook, nsHideOnFocusLoss, that hides the given
scratchpads when they lose focus.  This is akin to the functionality
provided by a lot of dropdown terminals.
2021-06-29 14:07:05 +02:00
slotThe
5fffe03e06 Merge pull request #563 from ss7m/master
Add shiftWin to X.U.PureX
2021-06-28 09:06:03 +02:00
ss7m
7d4c3e36c9 Update CHANGES.md: Add shiftWin 2021-06-28 08:59:42 +02:00
sam-barr
640388942b X.U.PureX Add shiftWin 2021-06-28 08:59:36 +02:00
slotThe
e30269fe96 Update CHANGES.md: Move X.A.EasyMotion to 0.17 section
Moving this from the new modules in 0.14 to the current release was
missed when the pr was resurrected.

Related: https://github.com/xmonad/xmonad-contrib/pull/222
Related: https://github.com/xmonad/xmonad-contrib/pull/515
2021-06-25 18:54:52 +02:00
slotThe
67c9d7fe90 X.H.RefocusLast: Export withRecentsIn
This exports the `withRecentsIn` function, as it's quite useful when
using X.H.RefocusLast in other modules as a library.

It is already possible (RecentsMap is fully exported) to completely
define this function outside of the module, so we are not exposing any
more internals than we were before.
2021-06-23 09:51:33 +02:00
slotThe
722967cb12 Merge pull request #561 from exorcist365/master
Remove all derivations of Typeable
2021-06-18 14:12:51 +02:00
Joan Milev
f732082fdc Remove all derivations of Typeable
Typeable has been automatically derived for every type since GHC 7.10,
so remove these obsolete derivations.  This also allows us to get rid of
the `DeriveDataTypeable` pragma quite naturally.

Related: https://github.com/xmonad/xmonad/pull/299 (xmonad/xmonad@9e5b16ed8a)
Related: bd5b969d9b
Fixes: https://github.com/xmonad/xmonad-contrib/issues/548
2021-06-18 14:10:23 +02:00
slotThe
4ddb3e4915 Merge pull request #559 from slotThe/OrgMode-tests
X.P.OrgMode: Add property tests
2021-06-17 09:47:35 +02:00
Yecine Megdiche
35197c8907 Merge pull request #558 from TheMC47/X.A.CycleWS-refactor-wstype
`X.A.CycleWS`: deprecate `WSType` constructors, add `ignoringWSs` predicate
2021-06-15 11:40:43 +01:00
Yecine Megdiche
ea990921e2 X.A.CycleWS: Added ignoringWSs
`ignoringWSs` is useful in combination with `X.U.NamedScratchpad` to
skip a list of tags
2021-06-15 08:51:02 +02:00
Yecine Megdiche
51394c6e3e X.A.CycleWS: Deprecated WSType Data Constructors
By deprecating everything except `WSIs` and adding constructors to
logically combine `WSType` values, we can have a more flexible interface.
Adding anything to the old interface would mean going through `WSIs`, and
all old constructors can be implemented of terms of `WSIs`.
2021-06-15 08:48:53 +02:00
slotThe
5995d6c117 X.C.Desktop: Add type signatures
When we applied hlint hints in bd5b969d9b,
the definition of desktopLayoutModifiers got (via the hint to eta
reduce) changed from

    desktopLayoutModifiers layout = avoidStruts layout

to

    desktopLayoutModifiers = avoidStruts

While the former is general enough to infer the type signature

    LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a

the latter just sees the usage site of

    , layoutHook = desktopLayoutModifiers $ layoutHook def

in the desktopConfig function and thus—through the magic of
MonomorphismRestriction—infers the specialized type

    Choose Tall (Choose (Mirror Tall) Full) Window
      -> ModifiedLayout AvoidStruts
           (Choose Tall (Choose (Mirror Tall) Full)) Window

This obviously completely falls apart once someone wants to change the
layout and still uses desktopLayoutModifiers (unaware that it is just
avoidStruts at the moment).  The easy fix is to give things type
signatures, so nothing needs to be inferred.

The _actual_ solution would be, in my opinion, to completely deprecate
X.C.Desktop and remove it in a future release, as well as to completely
rewrite the provided Example.hs.  This needs more deliberation though.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/560
Related: bd5b969d9b
2021-06-14 18:36:04 +02:00
slotThe
cfc793e94f tests: Add OrgMode
Adds a pretty-printer, as well as property tests that this is in fact
an proper inverse for the parser.
2021-06-13 19:52:48 +02:00
slotThe
dea8d9dced X.P.OrgMode: Appropriately pad output time
The standard formatting for org is to left-pad single digits with a
zero; do that.
2021-06-13 19:33:08 +02:00
slotThe
1c6e6c808d X.P.OrgMode: Start counting years at 25
This is for disambiguation purposes.  Otherwise, there is no way to
decide whether

    message +s 17 jul 12

wants to schedule the note for the 17th of july at 12:00, or for
the 17th of july in the year 12.  The easiest way around this is to
stipulate that people want to make these notes for the future more
often than not and to simply prohibit note before the year 25 (as that
is where the valid times end).
2021-06-13 19:08:09 +02:00
slotThe
4b15ea2ecc X.P.OrgMode: Parse empty message
Empty messages seem quite useless, but it's an easy fix for the parser
to be able to deal with them, so do it.
2021-06-13 19:02:01 +02:00
slotThe
c1cb3aaa24 X.P.OrgMode: Only parse actual words
Instead of trying to find a prefix and then killing the rest of the
word, actually see whether it at least fits the pattern.  This means
that

    message +s saturated

will no longer parse as a scheduled item for saturday, while

    message +s satur

still will.
2021-06-13 19:01:59 +02:00
slotThe
5067164d19 Merge pull request #556 from slotThe/org-mode-link
X.P.OrgMode: Linkify URLs with `orgPromptPrimary`
2021-06-11 16:49:04 +02:00
slotThe
c9ca4ce026 X.P.OrgMode: Linkify URLs in orgPromptPrimary
If we have a URL in the clipboard and we use `orgPromptPrimary`, it
would be nice if

    message +s 11 jan 2013

would result in

    * TODO [[_URL_][message]]
      SCHEDULED: <2013-01-11 Fri>

instead of the current

    * TODO message
      SCHEDULED: <2013-01-11 Fri>
      _URL_

This has the advantage that if one shows scheduled or deadlines items in
the org-agenda, it is possible to immediately follow this link with
`C-c C-o` or similar functionality.

The URL detection is very rudimentary right now.  One use `parseURI`
from `network-uri`, but that would be an additional dependency that I
didn't think was worth it.
2021-06-10 15:46:48 +02:00
slotThe
5da9b26142 X.P.OrgMode: Prune extra whitespace
This implements whitespace pruning at the end of a sheduled item or
deadline.  If we have a message like

    This is a message                +s today

it is expected that we created a heading of just "This is a message",
without the extra whitespace.
2021-06-10 15:43:27 +02:00
slotThe
6d184e859c Merge pull request #534 from oogeek/X.A.CopyWindow-doc-improve
X.A.CopyWindow: Add copiesPP
2021-06-10 14:08:27 +02:00
oogeek
d521d18dde X.A.CopyWindow: Add copiesPP
This is a function that takes a pretty-printer and makes it aware of
copies of the currently focused window.  This is particularly nice when
using it with a StatusBarConfig.

Related: https://github.com/xmonad/xmonad-contrib/pull/463
2021-06-10 14:03:52 +02:00
slotThe
c89730fc32 Merge pull request #501 from oogeek/for-layout-independentscreens
X.L.IndependentScreens: Add workspacesOn, withScreen, fix marshallPP always sorting lexically
2021-06-10 11:09:14 +02:00
oogeek
8899078b00 X.L.IndependentScreens: Add workspacesOn, withScreen, fix marshallPP always sorting lexically
- Added `workspacesOn` for filtering workspaces on the current screen.

- Added `withScreen` to specify names for a given single screen.

- Added new aliases `PhysicalWindowSpace` and `VirtualWindowSpace`
  for a `WindowSpace` for easier to read function signatures.

- Fixed a bug where `marshallPP` always sorted workspace names
  lexically.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/420
2021-06-10 11:07:49 +02:00
Tomas Janousek
b6cd47db29 X.H.StatusBar.PP: Clarify ppOutput doc + minor cleanups 2021-06-08 00:14:17 +01:00
Tomas Janousek
c3b67ab0df X.U.ClickableWorkspaces: Fix Haddock formatting 2021-06-08 00:14:17 +01:00
slotThe
4bc0470e62 Merge pull request #525 from slotThe/compl-docs
X.Prompt: Document, simplify completion window implementation
2021-06-07 09:39:04 +02:00
slotThe
f76318ce5f X.Prompt: Calculate prompt width once at the start
At the moment, we re-calculate the prompt width every time we want
to (re)draw the prompt window.  This is unnecessary, as the screen
dimensions or the preferred position changing _while the prompt is
active_ is extremely unlikely.

This now calculates the desired width at the start of the prompts event
loop and threads it through to the places that need it.
2021-06-07 09:33:35 +02:00
slotThe
5bc0d9d777 X.Prompt: Remove non-IORef complWin
While it is true that we need an IORef complWin in case of an exception,
so the window can be destroyed correctly, we do not need its non-IORef
counterpart at all.

When we need to access the complWin it's undoubtably when we want to do
_something_ with regards to window management; these things naturally
live in `XP ()` and so there's not loss of purity with this change.
2021-06-07 09:33:35 +02:00
slotThe
84dcc9b716 X.Prompt: Document createPromptWin 2021-06-07 09:33:35 +02:00
slotThe
a49c4066b9 X.Prompt: Simplify nextComplIndex 2021-06-07 09:33:35 +02:00
slotThe
6036151ca7 X.Prompt: Document destroyComplWin 2021-06-07 09:33:35 +02:00
slotThe
aa35d6a2f2 X.Prompt: Document getCompletions 2021-06-07 09:33:35 +02:00
slotThe
26c4fb0f2d X.Prompt: Document printComplList, rename 2021-06-07 09:33:35 +02:00
slotThe
5f58fb5cd1 X.Prompt: Document drawComplWin 2021-06-07 09:33:35 +02:00
slotThe
2f6546a8d6 X.Prompt: Document getComplWinDim 2021-06-07 09:33:34 +02:00
slotThe
96640f7aae X.Prompt: Document printPrompt 2021-06-07 09:32:56 +02:00
slotThe
548595ed34 X.Prompt: Document redrawComplWin 2021-06-07 09:32:56 +02:00
slotThe
b7dbc277a7 X.Prompt: write updateWindows in terms of redrawWindows
Also document the functions because they dearly need it.
2021-06-07 09:32:56 +02:00
slotThe
0af9435d58 X.Prompt: Make ComplWindowDim a proper type 2021-06-07 09:32:56 +02:00
Tomas Janousek
402d29b306 ci: Enable hlint in haskell-ci 2021-06-06 18:47:13 +01:00
slotThe
9f52af27b9 Add .hlint.yaml
We do want to ignore some hints.

Currently this is:

  - Evaluate: Some type level magic sometimes requires us to write
    expressions that could be evaluated further, but should not.

Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-06-06 18:59:05 +02:00
slotThe
bd5b969d9b Apply hlint hints
All hints are applied in one single commit, as a commit per hint would
result in 80+ separate commits—tihs is really just too much noise.

Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-06-06 18:59:05 +02:00
Tomas Janousek
b96899afb6 X.H.StatusBar: Fix misleading doc comment about encodeString
This isn't true since 63e31ccd8d, `xmonadPropLog'` does the encoding
now and accepts a normal Haskell String now.

Fixes: 63e31ccd8d ("X.H.DynamicLog: Move UTF8 encoding from dynamicLogString to xmonadPropLog'")
2021-06-06 13:56:40 +01:00
Tomas Janousek
e9334b5268 Bump xmonad dependency
Merging NewSelect into Choose is a breaking change, bump the dependency
to let users know they absolutely have to fetch today's xmonad git as
well.
2021-06-04 19:04:17 +01:00
Tomáš Janoušek
8c72f77c8e Merge pull request #493 from slotThe/NewSel
Move X.L.LayoutCombinators.(|||) to XMonad.Layout
2021-06-04 18:30:03 +01:00
slotThe
4489ab2147 Update CHANGES.md 2021-06-04 18:24:42 +01:00
slotThe
9af232489d Remove unnecessary imports of X.L.LayoutCombinators 2021-06-04 18:23:37 +01:00
slotThe
921ee69064 X.L.LayoutCombinators: Update for new X.L.(|||)
With xmonad/xmonad@45b2275b88 going live
the functionality of X.L.LayoutCombinators.(|||) was moved into xmonad
core, more specifically into X.L.(|||).  We just need to clean up the
contrib side of things, which involves making JumpToLayout and NewSelect
type aliases and cutting out the custom layout combinator.

Related:
  - https://github.com/xmonad/xmonad/pull/281
  - xmonad/xmonad@45b2275b88
  - https://github.com/xmonad/xmonad-contrib/issues/116
2021-06-04 18:23:37 +01:00
Tomas Janousek
bb71111b75 X.L.LayoutModifier: Drop outdated comment about haddock bug
This doesn't seem to be true any more with haddock 2.23.0.
2021-06-04 16:38:20 +01:00
Tomas Janousek
5230f038b3 Merge branch 'pr/rescreen' 2021-06-03 11:10:58 +01:00
Tomas Janousek
30995c41ff X.H.StatusBar: Use addAfterRescreenHook instead of listening for RRScreenChangeNotifyEvent
The new X.H.Rescreen provides a simpler composable API for hooking into
rescreen. Unfortunately it also breaks other code that listens for
RRScreenChangeNotifyEvent, so this conversion isn't really optional.

Not that there's any dispute this is nicer, is there? :-)
2021-06-03 11:10:33 +01:00
Tomas Janousek
eab9a3a58e X.U.ExtensibleConf: Flip arguments of once(M)
This appears to be more natural. The function will most often be fixed
by the module using `XC.once` and the configuration will often be
supplied by users of those modules, so it's better to partially apply
the function first.
2021-06-03 11:10:33 +01:00
Tomas Janousek
13b1de27a9 X.H.StatusBar: Add statusBarGeneric for taffybar/trayer/stalonetray
`statusBarGeneric`: A generic `StatusBarConfig` that launches a status
bar but takes a generic `X ()` logging function instead of a `PP`. This
has several uses:

 * With `xmonadPropLog` or `xmonadPropLog'` in the logging function, a
   custom non-`PP`-based logger can be used for logging into an `xmobar`.

 * With `mempty` as the logging function, it's possible to manage a status
   bar that reads information from EWMH properties like `taffybar`.

 * With `mempty` as the logging function, any other dock like `trayer` or
   `stalonetray` can be managed by this module.

Related: https://github.com/xmonad/xmonad-contrib/pull/463
2021-06-03 02:31:47 +01:00
Tomas Janousek
4a6f21604f X.H.Rescreen: Port to ExtensibleConf 2021-06-03 01:02:57 +01:00
Tomas Janousek
280964b9f5 Update CHANGES, X.D.Extending: add X.H.Rescreen 2021-06-03 01:02:57 +01:00
Tomas Janousek
90c7621e1f X.H.Rescreen: Merge the two hooks together and improve their behaviour
Now that randrChangeHook is only invoked for changes that don't result
in rescreen, it can actually be used for autorandr.
2021-06-03 01:02:57 +01:00
Tomas Janousek
1ff954b4b6 X.H.Rescreen: Add randrHook 2021-06-03 01:02:57 +01:00
Tomas Janousek
5b28f5ee54 Add X.H.Rescreen module (custom rescreen hooks) 2021-06-03 01:02:57 +01:00
Tomas Janousek
f71095885f Fix more GHC warnings: -Wdeprecations
With the bumped xmonad dependency, we can drop these, leaving just 4
warnings visible in ghcid. \o/

Related: https://github.com/xmonad/xmonad/pull/258
2021-06-03 00:01:27 +01:00
Yecine Megdiche
dac3acc5dd Merge pull request #553 from TheMC47/postpone-pipe
X.H.StatusBar.statusBarPipe: spawn in the startupHook
2021-06-02 16:02:57 +02:00
Yecine Megdiche
465044d5ce X.H.StatusBar.statusBarPipe: spawn in the startupHook
statusBarPipe abuses the interface of StatusBarConfig by starting the
status bar before the startupHook. This worked correctly before, but it
does not play will with `dynamicSBs`
2021-06-02 15:52:05 +02:00
Tomáš Janoušek
e1db71c42c Merge pull request #546 from slotThe/set-class
Set `WM_CLASS` for some windows
2021-06-02 11:48:19 +01:00
slotThe
f19b3f6de3 Update CHANGES.md 2021-06-02 12:37:53 +02:00
Tomas Janousek
086db3123b Temporarily symlink stack.yaml to stack-master.yaml
This shall be reverted together with the .github/workflows/stack.yml
part of 229d52ff07 once xmonad 0.17 is
out.
2021-06-02 11:06:30 +01:00
Tomas Janousek
7d122b2edf Fix typo in stack.yaml and bump resolver
Fixes: 229d52ff07 ("Bump X11, xmonad dependencies")
2021-06-02 11:05:44 +01:00
slotThe
ff42434be3 Merge pull request #543 from slotThe/view-ws-instead-of-entering-parallel-universe-where-the-focus-is-somewhere-else
X.A.CycleRecentWS: Cycle workspaces, not windowsets
2021-06-02 09:42:09 +02:00
slotThe
055c4877a1 Update CHANGES.md 2021-06-02 09:18:43 +02:00
Tomas Janousek
86522a27b0 X.A.CycleRecentWS: Make unView work with greedyView as well
Entirely unnecessary for the current version of `cycleWindowSets`, but
if anyone ever wants to use `greedyView`, this shows that it's not at
all complicated to adapt `unView` to that.
2021-06-02 09:18:43 +02:00
Tomas Janousek
1e2e1273b8 X.A.CycleRecentWS: Revert setOption changes
These are remnants of the first fix attempt, but are no longer
necessary. This reduces the diff to `view . unview` instead of `const`.
2021-06-02 09:18:43 +02:00
Tomas Janousek
b65b83661b X.A.CycleRecentWS: Simplify unView even more
Instead of implementing `view` in reverse, we can use it directly and
then just fix the order of visible/hidden workspaces.
2021-06-02 09:18:43 +02:00
Tomas Janousek
12b30c393c X.A.CycleRecentWS: Simplify/fix unView
To make this more "obviously correct", make it resemble the `view`
implementation, just do the exact reverse. Now the only complex bit is
the "undelete" operation.

This also fixes another issue: state was only preserved in the focused
workspace, but it may have changed in another visible workspace as well.
The property test is updated to test this.
2021-06-02 08:32:41 +02:00
Tomas Janousek
24786c6d04 X.A.CycleRecentWS: Add property test for unView
Scary looking code better be tested. :-)

(For the record, the test did find an issue that is already fixed in the
previous commit.)
2021-06-02 08:32:34 +02:00
Tomas Janousek
3db9167da4 X.A.CycleRecentWS: Rename restoreOrder to unView
Makes it more obvious what it really does.

Also, don't expose origWSet as a variable, lest someone uses it. :-)
2021-06-02 08:31:53 +02:00
slotThe
f0809e5d1d X.A.CycleRecentWS: Cycle workspaces, not windowsets
The way that workspace cycling is implemented right now—by generating
new windowsets where the things we want happen to be true and then
replacing the old windowsets—is not safe, as workspaces and layouts may
carry state with them.  That state will get lost in translation when
windowsets are simply replaced.

As an example, a conflict occurs when using `X.L.ShowWName.showWName` in
one's layoutHook.  When cycling through workspaces via, e.g.,
`cycleRecentWS` the flashed workspace tag will not disappear, as the
necessary state to control this isn't present in the new windowset.

Instead, what we want to do is to keep the "current" windowset alive and
actually switch to the requested workspaces.  This mostly works without
much trouble, the only hard part is maintaining the invariant that
previewed workspaces don't count towards the history of recently-viewed
workspaces.  This is done by remembering the tag-order of the original
windowset and then restoring that at the end.

This is a breaking change, insofar as it changes the type signatures of
the exported functions `recentWS`, `cycleWindowSets`, and
`toggleWindowSets` to return a list of `WorkspaceId`s instead of a list
of `WindowSet`s.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/504
2021-06-02 08:31:53 +02:00
slotThe
fd5d8267d2 Set WM_CLASS for created windows
Set the WM_CLASS property for long-living windows that need it.  This
helps users to properly match on these windows for certain tasks.

Fixes:
  - https://github.com/xmonad/xmonad-contrib/issues/526
  - https://github.com/xmonad/xmonad-contrib/issues/369
2021-06-02 08:18:11 +02:00
Joan Milev
f4673d611b X.L.BinarySpacePartition: Customizable ratio in messages that resize windows
Co-authored-by: Yecine Megdiche <yecine.megdiche@gmail.com>
2021-06-01 19:56:58 +01:00
Tomas Janousek
f6b1e5dd88 X.U.ExtensibleConf: New helper module for extensible config
It's often difficult to make contrib modules work together. When one
depends on a functionality of another, it is often necessary to expose
lots of low-level functions and hooks and have the user combine these
into a complex configuration that works. This is error-prone, and
arguably a bad UX in general.

This commit presents a simple solution to that problem inspired by
"extensible state": extensible config. It allows contrib modules to
store custom configuration values inside XConfig. This lets them create
custom hooks, ensure they hook into xmonad core only once, and possibly
other use cases I haven't thought of yet.

This requires changes to xmonad core: https://github.com/xmonad/xmonad/pull/294

A couple examples of what this gives us:

* [X.H.RescreenHook](https://github.com/xmonad/xmonad-contrib/pull/460)
  can be made safe to apply multiple times, making it composable and
  usable in other contrib modules like X.H.StatusBar

* `withSB` from X.H.StatusBar can also be made safe to apply multiple
  times, and we can even provide an API [similar to what we had
  before](https://hackage.haskell.org/package/xmonad-contrib-0.16/docs/XMonad-Hooks-DynamicLog.html#v:statusBar)
  if we want (probably not, consistency with the new dynamic status bars
  of https://github.com/xmonad/xmonad-contrib/pull/463 is more important)

* The [X.H.EwmhDesktops refactor](https://github.com/xmonad/xmonad-contrib/pull/399)
  can possibly be made without breaking the `ewmh`/`ewmhFullscreen` API.
  And we will finally be able to have composable EWMH hooks.

Related: https://github.com/xmonad/xmonad/pull/294
2021-06-01 19:07:13 +01:00
Tomas Janousek
56cf96cfa9 X.H.ManageDocks: Fix button events on decoration windows
Decoration windows are created using XMonad.Util.XUtils.createNewWindow
which happens to set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_DESKTOP,
and ManageDocks considers such windows candidates for struts and
therefore requests property events, thus overriding the original event
mask requested by decorations.

The fix is to first obtain the current event mask, set the required bits
in it only then reset the mask.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/517
Fixes: ec14617123 ("X.H.ManageDocks: React to strut updates of override_redirect docks")
Related: https://github.com/xmonad/X11/pull/77
2021-06-01 18:56:44 +01:00
Tomas Janousek
1427c9484a Bump version number (pre-release 0.16.999) 2021-06-01 18:35:03 +01:00
Tomas Janousek
229d52ff07 Bump X11, xmonad dependencies 2021-06-01 18:34:40 +01:00
Yecine Megdiche
5c73845c68 Merge pull request #463 from TheMC47/dynamic-status-bar-configs
Dynamic Status Bars support for XMonad.Hooks.StatusBar
2021-05-28 22:50:35 +02:00
Yecine Megdiche
d2f3a8de74 Added support for dynamic status bars.
This is heavily inspired by "XMonad.Hooks.DynamicBars", but it can be
used with any status-bar.
2021-05-28 18:47:50 +02:00
Yecine Megdiche
b6e364ce42 Rename 'spawnStatusBarAndRemember' and 'cleanupStatusBars', made them
command specific

- The names were awfully long. spawnStatusBar and killStatusBar are
perfectly fine alternatives.
- It's more flexible to have killStatusBar command specific. Also added
killAllStatusBars to provide the old functionality
2021-05-28 18:47:50 +02:00
Tomas Janousek
fde7f4f8b0 X.H.EwmhDesktops: Ignore _NET_WM_STATE_FULLSCREEN from unmanaged windows
This prevents an unnecessary refresh.

That refresh would normally be harmless but it does reset the input
focus, which happens to upset some non-conforming clients such as
https://github.com/flameshot-org/flameshot. Flameshot is an interactive
screenshot tool that creates an override-redirect fullscreen window to
let the user select a rectangle to capture and then allows drawing and
adding text and so on, but it unfortunately doesn't follow ICCCM
recommendations:

> If it is necessary for a client to receive keystrokes on an
> override-redirect window, either the client must grab the keyboard, or
> the client must have another top-level window that is not
> override-redirect and that has selected the Locally Active or Globally
> Active focus model.

Instead, it just takes input focus and hopes for the best. And it also
sends an entirely useless _NET_WM_STATE_FULLSCREEN request, which would
trigger a refresh and take that focus away.

This commit works around that by not handling that useless
_NET_WM_STATE_FULLSCREEN for unmanaged windows and thus preventing that
refresh. It's just a workaround, however: if a legitimate refresh is
necessary at any point, the focus _will_ be taken away.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/550
Fixes: https://github.com/flameshot-org/flameshot/issues/773
2021-05-28 15:13:09 +01:00
Tomas Janousek
37fc86c5c4 CHANGES: Join xmobarBorder, xmobarFont entries into one
Related: https://github.com/xmonad/xmonad-contrib/pull/549
2021-05-24 20:32:24 +01:00
Yecine Megdiche
ff391de17d Merge pull request #549 from rolsdorph/add-xmobarfont
Add xmobarFont
2021-05-24 21:26:44 +02:00
Mads Rolsdorph
1fabce659f Add xmobarFont
xmobar allows you to define a list of additional fonts (additionalFonts) and to use the fn tag to choose between them. xmobarFont is essentially the same as the xmobarColor function, but for fonts.
2021-05-24 19:45:31 +02:00
Tomas Janousek
9b933b1f69 ci: Speed up builds using ghc-options: -j
Building xmonad-contrib benefits greatly from compiling modules in
parallel. Vanessa McHale suggested setting ghc-options in
xmonad-contrib.cabal in #431, but that's bad practice—these options
should be set by the user/environment where it's being built, not
selfishly hardcoded for specific package. In stack.yaml and
cabal.haskell-ci, we know for sure that xmonad-contrib is the terminal
(leaf) library, so we can set it there and speed up builds in our CI and
also for anyone who uses our stack.yaml (not that anyone should).

Closes: https://github.com/xmonad/xmonad-contrib/pull/431
2021-05-24 18:12:10 +01:00
Tomas Janousek
17ef2b95db ci: Workaround for stack/pantry caching of github archives
Turns out `commit: master` doesn't really mean latest master, because
it's cached. It sometimes works, because when the GHA cache comes from
a job that depended on xmonad-0.15, then the master archive isn't cached
and is fetched. When the cache comes from a job that previously fetched
master, it's not fetched again.

The least ugly way to fix it I found is to use the `[<refname>]@{<date>}`
git revision format, and substitute current date/time before invoking
stack. To make stack-master.yaml valid without the substitution, we use
`master@{today}` which is a valid git revision that GitHub understands.
2021-05-24 17:49:03 +01:00
Tomas Janousek
cef324795e ci: Enable -Werror
Related: 14d9fa247a
Related: 5cdf428f55
2021-05-24 17:49:03 +01:00
Tomas Janousek
43e35952c8 Fix a few warnings reported by GHC 9.0 2021-05-24 00:21:07 +01:00
Tomas Janousek
147e83cbd0 Fix ambiguous occurrence ‘singleton’ with GHC 9.0 2021-05-24 00:19:37 +01:00
Tomas Janousek
52751f47d0 ci: Refresh caches once a month
GitHub Actions writes caches on the first miss and then never updates
them again. If the CI is used frequently, the caches never expire and
as they get old, become less useful.

To avoid this, force refreshing the caches once a month.
2021-05-24 00:19:37 +01:00
Tomas Janousek
d1a4820b55 ci: Prevent ~/.stack/pantry cache from being empty
When building with an LTS version that has exactly the dependencies we
need (xmonad-0.15), stack doesn't need to download the Hackage index. If
GitHub Actions cache locking chooses this job as the one that writes the
cache, then the "stack-pantry-Linux" cache entry stays empty, possibly
forever.

Force Hackage index update to prevent this from happening.
2021-05-24 00:19:37 +01:00
Tomas Janousek
96aae28641 ci: Cache pantry (hackage metadata) separately
This further reduces our usage of cache storage by caching the metadata
only once per repo. Now the metadata cache is ~250MB and the individual
caches with built dependencies are ~10M each.

Related: cfe99998fc
Related: https://github.com/xmonad/X11/pull/75
2021-05-24 00:19:33 +01:00
Tomas Janousek
bf0e2c18ea ci: Use system GHC in Stack to not waste GH Actions cache space
Stack installation of GHC takes more than a gigabyte, so caching it
wastes space (GitHub docs say it will be aggressively evicted after
reaching the 5G limit) and also time (compression, decompression).

Related: 9fce3805fc
Related: a5cee9bac2
Related: https://github.com/xmonad/X11/pull/75
2021-05-24 00:18:41 +01:00
Tomas Janousek
10574d9b61 ci: Reduce stack test matrix
Drop nightly and lts-15: they don't add GHC versions to the matrix and
new deps are better tested in the haskell-ci (cabal) workflow.

There's also little point in testing against both xmonad 0.15 and xmonad
master with all LTS versions. Drop most of those, reduces GitHub cache
and CPU time usage.

Related: fd243ca1c1
Related: https://github.com/xmonad/X11/pull/75
2021-05-24 00:18:34 +01:00
Tomas Janousek
6384cd04a4 ci: Refresh tested-with
Related: fd243ca1c1
Related: https://github.com/xmonad/X11/pull/75
2021-05-23 22:20:17 +01:00
Tomas Janousek
0c11288ea0 ci: Use xmonad master for haskell-ci workflow
Last released xmonad doesn't build with GHC 9.0 and haskell-ci doesn't
let us tweak the test matrix easily. Let's hope the stack.yml workflow
is sufficient to test backward compat.

Related: 2a1a18023a
2021-05-23 22:19:59 +01:00
Tomas Janousek
8d2d34ed6b ci: Move apt deps to cabal.haskell-ci and regenerate haskell-ci
Related: e4659c2475
Related: https://github.com/xmonad/X11/pull/75
2021-05-23 18:35:34 +01:00
Tomas Janousek
5c40a928a1 ci: Minor cleanup
* rename workflow to Stack

* tweak C deps

* use `*.cabal` to minimize diff between our repos

Related: caae51c399
Related: https://github.com/xmonad/X11/pull/75
2021-05-23 18:26:46 +01:00
slotThe
cbd44dd9f9 Fix GHC warning: -Wmissing-home-modules
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-21 17:37:09 +02:00
slotThe
410469e124 Fix GHC warnings in tests/
Related:
  - https://github.com/xmonad/xmonad-contrib/issues/537
  - 673f727206
2021-05-21 17:37:09 +02:00
slotThe
ea09fc2bf4 Fix GHC warning: -Wdeprecations
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-21 17:37:09 +02:00
slotThe
bf55122a82 Fix GHC warning: -Wincomplete-patterns
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-21 17:37:09 +02:00
Tomas Janousek
5b171640fb Merge branch 'pr/funding' 2021-05-21 12:20:29 +01:00
Tomas Janousek
ebe2a6284a X.H.EwmhDesktops: Avoid some unnecessary refreshes (border flicker)
Current version of Steam sends _NET_ACTIVE_WINDOW ClientMessage for
every mouse click which results in a lot of border blinking.

Ignore requests that would result in no change to get rid of the
annoying border flicker that is inevitable with the current
implementation of XMonad.Operations.windows.

(Note that Steam also sends ConfigureRequest events, and these cause
an additional refresh due to the call to `float` when handling the event
in xmonad core. Not sure if worth fixing.)

Related: https://github.com/xmonad/xmonad-contrib/pull/371
Related: https://github.com/xmonad/xmonad-contrib/pull/399
2021-05-21 12:19:45 +01:00
slotThe
2fb435724f Merge pull request #539 from slotThe/topic-item
X.A.TopicSpace: Add `TopicItem`
2021-05-21 13:07:48 +02:00
slotThe
7ad38d4063 Fix GHC warning: -Wtabs
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:18 +02:00
slotThe
518e96b384 Fix GHC warning: -Wmissing-signatures
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:17 +02:00
slotThe
7894bcec5c Fix GHC warning: -Woverlapping-patterns
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:16 +02:00
slotThe
25ad725e0c Fix GHC warning: -Wtype-defaults
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:13 +02:00
slotThe
6b014e6025 Fix GHC warning: -Wunused-local-binds
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:08 +02:00
slotThe
538089db83 X.H.EwmhDesktops, X.L.Spacing: Use PatternGuards
Fixes a GHC warning about non-standard pattern guards.

Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:04 +02:00
slotThe
673f727206 Fix GHC warning: -Wname-shadowing
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:03 +02:00
slotThe
b51ccc87b8 Fix GHC warning: -Wunused-matches
Related: https://github.com/xmonad/xmonad-contrib/issues/537
2021-05-20 17:32:02 +02:00
slotThe
f81cb24f0a Update CHANGES.md: Add TopicItem 2021-05-20 11:24:58 +02:00
slotThe
c5781f225e X.A.TopicSpace: Update documentation
- Only suggest the usage of TopicItem; this is much easier to work
    with and essentially a straight upgrade to the old method.

  - Use a more stripped-down example so we don't confuse beginners more
    than necessary (though this is still not optimal).
2021-05-20 11:24:58 +02:00
slotThe
35a32b22d0 X.A.TopicSpace: Add TopicItem and helper functions
Add the convenience type `TopicItem`, for easier (and safer!)
specification of topics, as well as several small helper functions to
help users work with it.
2021-05-20 11:24:58 +02:00
Yecine Megdiche
3f8c570347 X.A.DynamicWorkspaceGroups: TopicSpace support (#538)
* `X.A.DynamicWorkspaceGroups`: TopicSpace support

This adds `viewTopicGroup` and a corresponding prompt. This is similar
to `viewWSGroup`, but it calls `switchTopic` instead of `W.greedyView`,
inorder to run the topic action on the workspace.
2021-05-18 09:31:05 +02:00
Tomas Janousek
12b17c4935 X.D.Extending: Fix nested lists; fix StatusBar.PP placement
Fixes: 5eb3dbd61b ("Split XMonad.Hooks.DynamicLog")
2021-05-17 22:21:57 +01:00
Tomas Janousek
41ba7fd0d3 X.H.EwmhDesktops: Fix _NET_ACTIVE_WINDOW requests from pagers being ignored
This makes window switching apps like rofi and alttab able to activate
windows even if the logHook doesn't activate them (which it doesn't by
default, and that's a regression).

Fixes: 45052b984d ("X.H.EwmhDesktops. run 'logHook' for activated window.")
Related: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/110
Related: https://github.com/xmonad/xmonad-contrib/pull/192
2021-05-16 15:02:37 +01:00
Tomas Janousek
82ecde86fe X.H.EwmhDesktops: Clean up "handle"
Related: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/399
Related: https://github.com/xmonad/xmonad-contrib/pull/192
2021-05-16 15:02:37 +01:00
Tomas Janousek
6946bbc48b X.{H.EwmhDesktops,L.Fullscreen}: Kill a few warnings
Related: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/399
2021-05-16 14:58:44 +01:00
Tomas Janousek
2c1c96c3e5 X.H.{EwmhDesktops,ManageDocks}: Improve the usage doc a bit
Don't assume ewmh/docks are the only xmonad config combinator out there.

Related: https://github.com/xmonad/xmonad-contrib/issues/396
Related: https://github.com/xmonad/xmonad-contrib/pull/399
2021-05-16 14:58:38 +01:00
Tomas Janousek
19b2665246 Add Sponsor button to GitHub
These past months I've spent a lot of time working on xmonad and I feel
like I've done a lot. This is, however, not sustainable long term. :-(

I'd like to try making my GitHub Sponsors profile a bit more visible,
hoping that would allow me to continue dedicating time to xmonad.

I know that the correct approach probably is for the xmonad project to
find a fiscal sponsor like the Software Freedom Conservancy or Open
Collective or something and accept donations as a project, and then
redistribute that to people, but I don't think the project has enough
momentum to do something as complicated as that. :-/
2021-05-14 17:06:22 +01:00
slotThe
bf5dce592f Merge pull request #499 from slotThe/contrib-prelude
New module: XMonad.Prelude
2021-05-14 16:09:50 +02:00
slotThe
00e7a5c197 X.D.Developing: Add X.Prelude
Add a small note in order to aid discoverability amongst developers.
2021-05-13 17:44:50 +02:00
slotThe
2469269119 New module: XMonad.Prelude
This is a convenience module in order to have less import noise.  It
re-exports the following:

  a) Commonly used modules in full (Data.Foldable, Data.Applicative, and
     so on); though only those that play nicely with each other, so that
     XMonad.Prelude can be imported unqualified without any problems.
     This prevents things like `Prelude.(.)` and `Control.Category.(.)`
     fighting with each other.

  b) Helper functions that don't necessarily fit in any other module;
     e.g., the often used abbreviation `fi = fromIntegral`.
2021-05-13 17:44:47 +02:00
slotThe
6ece010c01 Use reverseS instead of self-defined functions 2021-05-13 17:43:32 +02:00
Yecine Megdiche
02d0b79289 Merge pull request #536 from TheMC47/add-loggers-reference
Documentation tweaks for `X.H.StatusBar(.PP)`
2021-05-12 11:36:59 +02:00
Tomas Janousek
a622c0808f Merge branches 'sublayouts-floating-order', 'sublayouts-stack-of-stacks' 2021-05-11 15:25:18 +01:00
Tomas Janousek
8cdbb5d422 X.L.SubLayouts: Fix focusWindow' being quadratic 2021-05-11 15:10:56 +01:00
Tomas Janousek
36d06c1c5d X.L.SubLayouts: Rewrite updateGroup, updateWs' using stack of stacks
A stack of stacks is a more natural representation of what SubLayouts
does: it packs information about the global focus as well as focus in
individual groups (sublayouts).

It doesn't carry information about the sublayouts themselves (but a
similar structure in X.L.Groups does), so we still use Groups and
fromGroups in some places, but future refactor can simplify that as
well, I'm sure.

My main motivation for this is that I need to expose the window groups
to the user config, and a stack of stacks seems to be a nice data
structure for that. The motivation for exposing the groups is that I
want to manipulate focus in a way that takes groups into account. As an
example, I want the following:

 * mod-1, mod-2 to mod-0 switches to n-th group if not already focused,
   and if focused, focus next in the group

 * show these numbers and window titles in xmobar (like tmux/screen/vim
   status line), like so:

     1a weechat  1b browser  2 vim  3 mutt

Achieving this just using BoringWindows is quite tricky, but with the
ability to somehow (InspectLayout, which is work-in-progress, or message
with IORef) get the stack of stacks out of SubLayouts, this becomes
easy.
2021-05-11 15:10:52 +01:00
Tomas Janousek
975a99d9dd X.L.SubLayouts: Simplify updateWs' using updateGroup
Turns out similar logic is already in updateGroup, and we don't even
need to worry about extra/missing windows and we can just differentiate
the result of reordering.
2021-05-11 15:09:40 +01:00
Tomas Janousek
9c93d90970 X.L.SubLayouts: Avoid moving floats to end of window stack
This makes the following sequence of operations idempotent, as it should be:

    windows $ W.float w $ W.RationalRect 0 0 1 1
    windows $ W.sink w

Previously, any window not visible to the SubLayout modifier (xmonad
invokes runLayout with tiled windows only) would be reordered to the end
of stack. This commit changes the reordering logic to only reorder
windows in Groups and keep all other windows where they were.
2021-05-11 15:09:40 +01:00
Yecine Megdiche
644f993fef Added reference to "XMonad.Util.Loggers" 2021-05-11 12:32:12 +02:00
slotThe
da59f9f360 Merge pull request #540 from liskin/treeselect-xft-color
X.A.TreeSelect: Only swap green/blue for X11-xft < 0.3.3
2021-05-11 08:01:52 +02:00
Tomas Janousek
57674eb545 X.A.TreeSelect: Only swap green/blue for X11-xft < 0.3.3
The issue was fixed upstream in 0.3.3:
24f6275791
24f6275791^
(it is yet to be uploaded to Hackage, Clemens lost his Hackage
credentials :-))

Related: https://github.com/xmonad/xmonad-contrib/pull/486
Related: 46f24bb27e ("X.A.TreeSelect: Fix swapped green/blue in foreground when using Xft")
2021-05-10 22:53:25 +01:00
Yecine Megdiche
0f617114c8 Updated the example usage of statusBarProp 2021-05-09 13:07:50 +02:00
slotThe
8cbe3ecd48 Merge pull request #535 from slotThe/ppWindowTitle
Move `ppTitleUnfocused` to X.U.Loggers
2021-05-08 08:10:44 +02:00
slotThe
017f79fd7a Update CHANGES.md 2021-05-08 08:07:33 +02:00
slotThe
322e06eed9 X.H.SB.PP: Move ppTitleUnfocused to X.U.Loggers
This way, people not using this functionality don't get the burden of a
bunch of `getName`s that they haven't asked about.
2021-05-08 08:07:33 +02:00
Tomáš Janoušek
aa6d1eb60b Merge pull request #533 from slotThe/update-templates
Update issue and pull-request templates
2021-05-07 00:24:54 +01:00
slotThe
4815c42482 Change xmonad-testing box to question about tests
I don't think I've ever seen anyone check that mark, so let's transform
it into something more useful.
2021-05-06 13:13:13 +02:00
slotThe
4badaa45ed Update issue template
- We would really like a full template and not just a snippet where
  we'll have to guess the context.

- It's generally nice to know which versions of xmonad and contrib a
  users was using when encountering an issue.
2021-05-04 07:57:38 +02:00
slotThe
a99c76cce4 Merge pull request #532 from oogeek/StatusBar-doc-improve
X.H.StatusBar: update example for multiple monitors
2021-04-30 16:54:33 +02:00
oogeek
79e06cf76a update doc example for multiple monitors 2021-04-30 21:13:25 +08:00
slotThe
130e675837 Merge pull request #515 from slotThe/ezmotion
X.A.EasyMotion: Cleanup, doc improvement
2021-04-26 08:16:05 +02:00
slotThe
6a23836539 Merge pull request #529 from slotThe/ezconfig-removeKeys
X.U.EZConfig: Simplify removeKeys, removeMouseBindings
2021-04-25 16:36:07 +02:00
slotThe
226b385729 X.U.EZConfig: Simplify removeKeys, removeMouseBindings
We're not parsing anything (as opposed to the respective `P` functions)
and so there's no need to create a dummy map with units as values and
then take the difference; we can simply remove the relevant keys from
the map.
2021-04-24 09:23:02 +02:00
slotThe
1b8c3993e2 Merge pull request #506 from slotThe/safeDirPrompt
X.P.Shell: Add `safeDirPrompt`
2021-04-23 07:45:33 +02:00
slotThe
c17fc2ed65 Merge pull request #521 from oogeek/add-format-wallpapersetter
X.H.WallpaperSetter: Add defWPNamesPng, defWPNamesJpg
2021-04-22 07:25:10 +02:00
slotThe
5d148b53a3 Update CHANGES.md 2021-04-21 20:22:48 +02:00
oogeek
e214c94f0d X.H.WallpaperSetter: Add defWPNamesPng, defWPNamesJpg
This also deprecates defWPNames in favour of the (equivalent)
defWPNamesJpg.
2021-04-21 20:22:48 +02:00
slotThe
41df4b4079 Merge pull request #522 from oogeek/resize-git-X.U.Hacks
X.U.Hacks: Resize GIF
2021-04-20 18:28:22 +02:00
oogeek
1009284a03 add link to resized gifs 2021-04-20 15:27:14 +08:00
slotThe
1324baa193 Update CHANGES.md: add safeDirPrompt 2021-04-20 07:57:40 +02:00
slotThe
07439cc169 X.P.Shell: add safeDirPrompt
A new prompt that works like 'safePrompt', but is optimized for the
use-case of a program that needs a file as an argument.

This is necessarily a new function and can't just be achieved by using
the old `safePrompt`, as `getShellCompl'` does not at all filter the
files (compgen already does that based on the input), but only the
available commands.  If we start the prompt with a single command then
the chosen `searchPredicate` becomes quite useless and we can't take
advantage of fuzzy matching for file finding.  This, however, is quite
useful when having a program that explicitly expects a file as one of
its arguments, e.g. dragon [1].

What we have to do instead of to generate all available files with
compgen and _then_ filter this down to what we want via a given
function.  In order to make this change backwards compatible we have to
introduce the rather ugly `shellComplImpl`, which takes a laundry list
of all of the different parameters that we need.  Since the function is
not exported, this ugliness does perhaps not matter too much.

[1]: https://github.com/mwh/dragon
2021-04-20 07:57:40 +02:00
slotThe
6687a5bc40 CHANGES.md: Fix typo 2021-04-17 09:27:28 +02:00
slotThe
b1782da37c Merge pull request #520 from nikshalark/master
Redefine `ComplCaseSensitivity` as a proper sum type. (#509)
2021-04-17 09:23:09 +02:00
nikshalark
f49e7d653a Redefined ComplCaseSensitivity as a proper sum type. (#509) 2021-04-17 02:19:16 -04:00
Tomas Janousek
336afc82ca X.U.ClickableWorkspaces: Fix typo 2021-04-15 10:51:32 +01:00
Tomas Janousek
52bb28824d X.U.ClickableWorkspaces: Improve getWsIndex doc 2021-04-15 08:48:40 +01:00
slotThe
1d7abb102f Merge pull request #512 from oogeek/ClickableWorkspace-Improve
X.U.ClickableWorkspaces: Fix integration with X.A.DynamicWorkspaces
2021-04-15 08:44:10 +02:00
slotThe
ad1e858bac Merge pull request #508 from slotThe/prompt-ah-immediate
X.Prompt: fix selection not entering history
2021-04-14 08:12:23 +02:00
slotThe
83aaf0414b X.A.EasyMotion: Update documentation 2021-04-13 19:16:31 +02:00
slotThe
c649d314fa X.A.EasyMotion: Small nits
Superficial simplifications for certain functions
2021-04-13 19:16:16 +02:00
slotThe
78f3ad26ed X.A.EasyMotion: Strictify records
There is no reason for these not to be strict.
2021-04-13 19:16:08 +02:00
slotThe
827ea89b6b X.A.EasyMotion: Add Haddock headings
These are generally very useful for users in order to get a quick
overview of what the module offers them.
2021-04-13 19:16:03 +02:00
oogeek
a33de7f73a ClickableWorkspace Improvement for X.A.DynamicWorkspaces 2021-04-13 20:38:54 +08:00
Joan MIlev
f5464224e2 X.A.EasyMotion: export proportional (#514) 2021-04-12 19:14:19 +02:00
slotThe
563aa08fae X.A.EasyMotion: font -> emFont
the `font` field is already exported by X.Prompt and so there is a
conflict when importing both modules unqualified (as many people do).
2021-04-12 09:16:46 +02:00
slotThe
a05128359a X.A.EasyMotion: consistent indentation, hlint nits 2021-04-12 08:28:19 +02:00
Matt Kingston
99ea4c23e8 New module: Actions.EasyMotion (#222) 2021-04-12 08:12:42 +02:00
Tomáš Janoušek
0ebd3a0534 Merge pull request #507 from slotThe/minimal-pragmas
Add `MINIMAL` pragmas to `HasName` and `XPrompt`
2021-04-10 09:29:09 +01:00
slotThe
8aefbf8883 Add MINIMAL for HasName 2021-04-10 08:32:32 +02:00
slotThe
7702fa052b Add MINIMAL for XPrompt 2021-04-10 08:32:32 +02:00
slotThe
828983060d X.Prompt: fix selection not entering history
When `alwaysHighlight` is enabled and one immediately presses (by
default) Return after opening the prompt (because the highlighted
completion is what one wants) then the selection will not enter the
prompt history.  Instead, an empty string will be entered because there
hasn't been any input yet and hence the `highlightedCompl` field has not
yet been filled in.

The fix is simply checking whether `alwaysHighlight` is set during
startup and, if yes, already setting the highlighted completion to the
first suggestion.
2021-04-09 15:29:51 +02:00
slotThe
d7ad486a6e X.Prompt: get rid of MultiWayIf
Not needed anymore
2021-04-08 14:47:59 +02:00
slotThe
344ace492b X.Prompt: Properly handle one completion in hlComplete
This builds upon the idea of 780360abf0
but it fixes the issue in a bit of a nicer way; instead of throwing an
exception and closing the prompt, we simply check if there is only a
single completion available inside `hlComplete` directly.

While what 780360abf0 said is true insofar
that we have incomplete information when inside `hlComplete`, this does
not actually matter in this case.  We have access to the complete user
input (possibly consisting of things not from this round of completion),
which is enough here.
2021-04-08 14:47:39 +02:00
Tomáš Janoušek
72548b9206 Merge pull request #491 from liskin/pr/dynamicicons-changes
X.H.DynamicIcons: Cleanups, docs improvements, composability with other *PPs
2021-04-08 09:26:48 +01:00
slotThe
c5ccb1a7ef Merge pull request #505 from slotThe/hl-item
X.Prompt: Special handling of one highlighted item
2021-04-07 15:26:56 +02:00
slotThe
780360abf0 X.Prompt: Special handling of one highlighted item
Fixes a bug introduced in f2cfaa3398.

The changes there allowed the prompt to cycle through its input; it now
becomes necessary to single out the case of only having a single
suggestion that's also highlighted.  Otherwise, `hlComplete` (condition:
`alwaysHighlight` is enabled) will loop forever.  This case can't be
handled from within hlComplete, as we are giving it incomplete
information to start with (by only calling it with the last word of the
current completion in `handleCompletion`), which is necessary for things
like completing arguments.
2021-04-06 19:46:21 +02:00
Tomas Janousek
78b6df0e69 Drop some recently added trailing whitespace 2021-04-05 21:24:43 +01:00
Yecine Megdiche
a668b0f13a Merge pull request #503 from oogeek/X.L.Rename-KeepWordsLR
add KeepWordsLeft and KeepWordsRight for X.L.Renamed
2021-04-05 18:46:02 +01:00
oogeek
c3c033bb91 add KeepWordsLeft and KeepWordsRight for X.L.Renamed and updated CHANGES.md 2021-04-06 01:32:19 +08:00
Tomáš Janoušek
0efc99ae13 Merge pull request #502 from TheMC47/rework-status-bar
X.H.StatusBar: Removed unnecessary IO
2021-04-04 10:56:45 +01:00
Yecine Megdiche
168cb6a6c3 Removed unnecessary IO
This applies for withSB and withEasySB, as well as statusBarProp and
statusBarPropTo, making composability better. statusBarPipe is more
awkward to use now, but that's fine
2021-04-04 00:53:42 +02:00
Tomas Janousek
654fa5045c Merge branch 'TheMC47/split-dynamic-log' 2021-04-02 21:36:38 +01:00
Tomas Janousek
a1c2d144b3 Final touch of DynamicLog/StatusBar/PP docs 2021-04-02 21:28:41 +01:00
Yecine Megdiche
06fd90a5f8 Rename makeStatusBar to withSB, makeStatusBar' to withEasySB 2021-04-02 21:19:34 +01:00
slotThe
3e11bae4b1 X.H.StatusBar: Doc suggestions 2021-04-02 21:19:34 +01:00
Yecine Megdiche
b9913bd4df Cleanup CHANGES.md
Adapted mentions of `XMonad.Hooks.DynamicLog`, and moved the changes in
`XMonad.Hooks.DynamicLog` to the appropriate entries
2021-04-02 21:19:34 +01:00
Tomas Janousek
8e39d22cec X.H.StatusBar.PP: Move dynamicLog to DynamicLog
This function isn't useful in the new interface, ditch it.
2021-04-02 21:19:34 +01:00
Tomas Janousek
4e1b277784 X.H.StatusBar: Clean up usage documentation 2021-04-02 21:19:34 +01:00
Tomas Janousek
e32e17aa2d X.U.ClickableWorkspaces: Update docs for X.H.StatusBar 2021-04-02 21:19:34 +01:00
Tomas Janousek
2865268a7a Improve descriptions of X.H.{DynamicLog,StatusBar,StatusBar.PP} 2021-04-02 21:19:34 +01:00
Tomas Janousek
f316d52c1c X.H.StatusBar: Reword the $multiple section
Do not assume knowledge of what this used to be like in the past. Start
by describing how to configure multiple status bars now.
2021-04-02 21:19:34 +01:00
Tomas Janousek
eea41cbf76 Sort exposed-modules in xmonad-contrib.cabal 2021-04-02 21:19:34 +01:00
Yecine Megdiche
5eb3dbd61b Split XMonad.Hooks.DynamicLog
- XMonad.Hooks.DynamicLog.PP: the pretty-printing abstracion, with the
corresponding utilities
- XMonad.Hooks.StatusBar: A new module to provide a better interface to
manage external status bars.
2021-04-02 21:19:34 +01:00
slotThe
42307c2855 Merge pull request #500 from slotThe/xmonad.prompt.orgmode
New Module: XMonad.Prompt.OrgMode
2021-04-02 16:58:02 +02:00
slotThe
fd20202c23 X.P.OrgMode: Add ability to schedule hours/minutes 2021-04-02 08:15:28 +02:00
slotThe
db8e47e0b4 Update CHANGES.md, X.D.Extending.hs: add X.P.OrgMode 2021-04-01 18:36:31 +02:00
slotThe
e2eee301e0 New module: XMonad.Prompt.OrgMode 2021-04-01 18:36:31 +02:00
slotThe
902c2bb17d Merge pull request #497 from l29ah/ghc-9.0.1
Fix ghc-9.0.1 compatibility
2021-03-26 07:37:05 +01:00
Sergey Alirzaev
1033818631 ghc-9.0.1 compatibility fixes 2021-03-26 05:20:49 +03:00
slotThe
7d5426a183 X.L.Magnifier: All -> AllWins
This was exposed in afb6ef8412, but
clashes with Data.Monoid.All
2021-03-25 21:16:04 +01:00
slotThe
08059e8fb7 Merge pull request #496 from slotThe/magnifier-n
X.L.Magnifier: Add `magnify` combinator and magnification at N windows
2021-03-25 17:49:49 +01:00
slotThe
9618a0b616 Update CHANGES.md 2021-03-25 15:24:43 +01:00
slotThe
315d1acaea X.L.Magnifier: Update documentation 2021-03-25 15:24:43 +01:00
slotThe
afb6ef8412 X.L.Magnifier: Add magnify
This more general function subsumes (almost) all previously known
combinators in this library (it is still symmetric with regards to
magnification, as this is what most users want).  Also export some
previously internal (but not crucial to the implementation) types to
make this possible.
2021-03-25 15:24:43 +01:00
slotThe
2b6075666c X.L.Magnifier: Add way to magnify only starting at N windows
Also fix the rather embarrassing mistake of
bb205e9205 to not just make everything a
proper record.
2021-03-25 13:59:29 +01:00
slotThe
b56804d5f2 X.L.Magnifier: re-indent handleMess
More conventional style
2021-03-25 13:24:59 +01:00
Tomas Janousek
a0caca5edc X.H.DynamicIcons: Update docs 2021-03-25 10:08:37 +00:00
Tomas Janousek
835aeaaffb X.H.DynamicIcons: Move stuff around a bit (similar order to export list)
Makes the other commits easier to review.
2021-03-25 10:08:37 +00:00
Tomas Janousek
52f6aa2c4b X.H.DynamicIcons: Use ppRename - simpler, better interop with other modules
This ports DynamicIcons to the recently introduced ppRename mechanism,
which means DynamicIcons can now safely be combined with clickablePP,
workspaceNamesPP and marshallPP.

This also fixes DynamicIcons not working properly with urgent workspaces
due to forgotten ppUrgent counterpart in data Icon. Also,
ppVisibleNoWindows wouldn't work properly.

The code is now considerably simpler, but we lost the ability to use
different icons depending on whether the workspace is
visible/hidden/urgent/etc. If anyone needs that, it can be worked around
by using some markup that is later interpreted in
ppVisible/ppHidden/ppUrgent/etc.

Related: https://github.com/xmonad/xmonad-contrib/pull/481
2021-03-25 10:08:37 +00:00
Tomas Janousek
a18a155a8b X.H.DynamicIcons: Refactor dynamicIconsPP, getIcons a bit
Move all the workspaces and icon generation logic into getWorkspaceIcons
and drop the Maybe which is no longer necessary since we made the
formatting logic configurable.

Related: https://github.com/xmonad/xmonad-contrib/pull/450
2021-03-25 10:08:37 +00:00
Tomas Janousek
a000438526 X.H.DynamicIcons: Refactor dynamicLogIconsConvert a bit
Rename to dynamicIconsPP and change the type to something similar to
workspaceNamesPP and marshallPP.

Related: https://github.com/xmonad/xmonad-contrib/pull/450
2021-03-25 10:08:37 +00:00
Tomas Janousek
f127cf55f4 X.H.DynamicIcons: Improve configuration of output formatting
Make it possible to keep workspace id in the output (iconsFmtAppend) and
to wrap icons even if there's just one, or zero.

Also, change the default to use curly brackets to avoid confict with
brackets/parentheses used by default PPs in DynamicLog.

Related: https://github.com/xmonad/xmonad-contrib/pull/450
2021-03-25 10:08:37 +00:00
slotThe
c9a9cabcce Merge pull request #495 from slotThe/magnifier-cleanup
X.L.Magnifier: Add `magnifierczOff` and `magnifierczOff'`
2021-03-24 18:48:07 +01:00
slotThe
3aadb487ed Update CHANGES.md 2021-03-24 18:33:47 +01:00
slotThe
bb205e9205 X.L.Magnifier: Strictify and document Magnifier type 2021-03-24 18:33:47 +01:00
slotThe
1726bdb67b Merge pull request #349 from sergeykish/master
Use XFT fonts if available
2021-03-24 12:44:09 +01:00
Sergey Kish
619d0819af Use XFT fonts if available
The silent error `user error (createFontSet)` would break certain
modules (like the prompt) by simply not showing anything.

Pango 1.44 dropped support for FreeType in favor of HarfBuzz, losing
support for traditional BDF/PCF bitmap fonts.  Hence, some distributions
don't ship `xorg-fonts-misc` anymore.

Fixes https://github.com/xmonad/xmonad-contrib/issues/348
2021-03-24 12:29:18 +01:00
slotThe
b49ebdf2e0 X.L.Magnifier: Add magnifierczOff and magnifierczOff'
Instead of exporting the internal constructor, define a few more
functions for people who like their magnifier to start of in the Off
position.

Closes: https://github.com/xmonad/xmonad-contrib/issues/168
2021-03-24 10:08:10 +01:00
slotThe
5fbfcaada0 X.L.Magnifier: Implement magnifier['] in term of magnifiercz['] 2021-03-24 10:08:10 +01:00
Tomáš Janoušek
cd24f84774 Merge pull request #490 from liskin/pr/hacks-trayer
X.U.Hacks: Add "Stacking trays (trayer) above panels (xmobar)"
2021-03-23 21:55:19 +00:00
Tomáš Janoušek
06dafe3772 Merge pull request #492 from liskin/pr/managedocks-override-redirect
X.H.ManageDocks: React to strut updates of override_redirect docks
2021-03-23 21:55:07 +00:00
Tomas Janousek
ec14617123 X.H.ManageDocks: React to strut updates of override_redirect docks
We only requested PropertyChange events from docks in the `manageDocks`
manageHook, but that only gets called for normal windows, not
override_redirect ones. Therefore, xmobar in its default configuration
wouldn't get its struts refreshed on changes. This resulted in gaps not
updating after xmobar repositions itself on xrandr changes.

If one wanted to handle that repositioning in xmonad, it was possible to
configure xmobar with `overrideRedirect = False`, which is meant for
window managers with proper EWMH stacking order support [1], so in
xmonad it resulted in xmobar covering fullscreen windows. That can be
worked around by adding `checkDock --> doLower` to manageHook, but it
starts to smell of too many workarounds.

[1]: https://specifications.freedesktop.org/wm-spec/wm-spec-1.5.html#STACKINGORDER

The fix is to request PropertyChange events for all windows that we
treat as docks.

Related: https://github.com/xmonad/xmonad-contrib/pull/490
2021-03-23 14:24:30 +00:00
Tomas Janousek
88b9c80618 X.H.ManageDocks: Refactor strut cache
This is primarily a cleanup to make it easier to use `setDocksMask` from
the on-demand cache init (see further commits), but it makes the code
nicer:

- the logic to refresh and cache a strut is now concentrated in
  `updateStrut` instead of being spread over `updateStrutCache` and
  `docksEventHook`

- the logic to initialize the cache if not yet initialized is now
  concentrated in `maybeInitStrutCache` instead of being spread over
  `initStrutCache` and `getStrutCache`, so the dual-purpose return type
  of `getStrutCache` is no more

- the logic to detect changes and refresh is now always handled by
  `XS.modifiedM` instead of an additional `||`

Related: https://github.com/xmonad/xmonad-contrib/pull/406
2021-03-23 14:24:10 +00:00
Tomas Janousek
37fbf24ba7 X.U.ExtensibleState: Add modifiedM for effectful modifications 2021-03-23 14:23:55 +00:00
Tomas Janousek
04be5fc22e X.H.ManageDocks: Fix typo in deleteFromStructCache
Fixes: c48d81e378 ("Fix caching issues in ManageDocks")
2021-03-23 14:22:36 +00:00
Tomas Janousek
74e55421d3 Update CHANGES 2021-03-23 14:15:34 +00:00
Tomas Janousek
6d42c540a5 X.U.Hacks: Add "Stacking trays (trayer) above panels (xmobar)" 2021-03-23 14:15:34 +00:00
slotThe
c3fa5138f9 Merge pull request #479 from slotThe/topic-history
X.A.TopicSpace: Deprecate internal history
2021-03-23 07:51:16 +01:00
Tomas Janousek
46f24bb27e X.A.TreeSelect: Fix swapped green/blue in foreground when using Xft
Closes: https://github.com/xmonad/xmonad-contrib/pull/486
Co-authored-by: Joan Milev <joantmilev@gmail.com>
2021-03-22 15:30:03 +00:00
Tomas Janousek
b6bd6f6d9d X.U.Hacks: Minor cleanup
Improve diffability of module exports; fix haddock.
2021-03-22 10:29:27 +00:00
slotThe
bebcb605a8 Merge pull request #185 from aplaice/master
Improve conversion of Char to KeySym in XMonad.Util.Paste
2021-03-22 07:35:33 +01:00
Tomáš Janoušek
0d93820160 Merge pull request #470 from liskin/pr/notifications-obscured-by-floats
Apply two xmonad core fixes to float moving/resizing in various contrib modules
2021-03-21 21:31:01 +00:00
slotThe
43d68bd451 Update CHANGES.md 2021-03-21 08:01:19 +01:00
slotThe
3c4f42d2da X.A.TopicSpace: More aggressively use X.H.WorkspaceHistory
Ever since ce5aae5403 TopicSpace uses the
history implementation of X.H.WorkspaceHistory instead of something
hand-rolled.  This, however, did not go far enough; at this point, we
can deprecate essentially all of TopicSpace's redundant history handling
and explicitly tell users to use the more modular X.H.WorkspaceHistory
instead.
2021-03-21 08:00:44 +01:00
slotThe
280c1a8ed5 X.H.WorkspaceHistory: Fix hlint nits, strictness
There is no reason why the used maps should not be strict, as we are
definitely traversing.
2021-03-21 08:00:44 +01:00
slotThe
62e9941d3d X.H.WorkspaceHistory: Add ability to exclude workspaces 2021-03-21 08:00:44 +01:00
Tomáš Janoušek
ab60361c5b Merge pull request #487 from slotThe/old-time->time
Use time instead of old-time and old-locale
2021-03-21 00:02:12 +00:00
slotThe
e3a13a57e8 Merge pull request #471 from liskin/pr/spawnpipe-dynamiclog-encoding
Fix encoding issues in spawnPipe/dynamicLogString/xmonadPropLog
2021-03-20 18:18:35 +01:00
Tomas Janousek
63e31ccd8d X.H.DynamicLog: Move UTF8 encoding from dynamicLogString to xmonadPropLog'
For many (10+) years, we had a cascade of ugly workarounds:

 * X.U.Run.spawnPipe returned a binary handle, so the String passed to
   it must have been encoded by C.B.UTF8.String.encodeString

 * X.H.DynamicLog.dynamicLogString therefore returned such an encoded
   String, so one could use it directly in a hPutStrLn, but literal
   Strings wouldn't work

 * xmonadPropLog' also expected an encoded String to make it easier to
   use together with dynamicLogString, again breaking usage with String
   literals and other normal unicode Strings

Then in 1d0eaddc25 Sibi fixed spawnPipe to return a handle usable with
normal Strings, which then obviously broke the entire cascade. But,
instead of using the opportunity to remove all the ugly workarounds, he
decided to add some more on top, so now spawnPipe with dynamicLogString
outputs doubly encoded UTF-8 and xmobar has a hack to strip this double
encoding (https://github.com/jaor/xmobar/pull/482), which only works
when XFT is in use and breaks on some long unicode codepoints. :-(

There is a better way: make everything just use normal Strings and only
encode when it goes out the wire. This means dynamicLogString can be
freely mixed with String literals, manual uses of xmonadPropLog' don't
need encodeString, and everything just works nicely.

This obviously breaks configs that used some of these pieces in
isolation (like mine), but that's a small price to pay. After all, right
now all users of spawnPipe/dynamicLogString are getting doubly encoded
UTF-8 which might or might not work in xmobar and probably breaks
horribly everywhere else, so this fix should be a clear improvement. :-)

Fixes: 1d0eaddc25 ("Make spawnPipe to use system's locale encoding")
Fixes: https://github.com/xmonad/xmonad-contrib/issues/377
Fixes: https://github.com/jaor/xmobar/issues/476
Related: https://github.com/xmonad/xmonad-contrib/pull/334
Related: https://github.com/jaor/xmobar/pull/482
2021-03-20 18:11:33 +01:00
Tomas Janousek
21fb9dfc43 X.U.Run: Clean up spawnPipes a bit
This makes it easier to see the differences between these functions,
makes it less likely someone will change one and not the others, etc.
More importantly, the documentation doesn't contain circular references
any more. :-)

Also, let's just use hSetEncoding. The concern of this being stateful
and theoretically having something written in the wrong encoding is
pointless: nobody has the handle until we return it from `spawnPipe'`.

(This also means that spawnPipeWithNoEncoding is now a text handle that
possibly does newline translation, just with char8 encoding. There
should be no difference in practice.)

Fixes: 8b2bd3ae5c ("Add new variants of spawnPipe functions with encoding support")
2021-03-20 18:11:33 +01:00
slotThe
d32febd60d Merge pull request #392 from wygulmage/nix
Add nix packages to stack.yaml.
2021-03-20 16:53:01 +01:00
Keith
d05b934cbf Add nix packages to stack.yaml. 2021-03-20 16:46:17 +01:00
slotThe
cf9388a918 Merge pull request #481 from liskin/pr/pp-composable-rename
Extend PP with ppRename: nicer compose of WorkspaceNames, ClickableWorkspaces, …
2021-03-20 16:32:57 +01:00
slotThe
94f1e943d4 Use time instead of old-time and old-locale
Get rid of these deprecated libraries, as the new `time' library
provides a strict superset of the functionality of `old-time' and
`old-locale'.
2021-03-20 16:14:26 +01:00
slotThe
f1bd315448 Merge pull request #484 from ulrikdem/max-compl-columns
X.Prompt: Add maxComplColumns field to XPConfig
2021-03-20 08:03:22 +01:00
Tomas Janousek
dbaf0e60ce Merge branch 'AusCyberman/master' 2021-03-19 17:05:30 +00:00
Tomas Janousek
b0f5c69baf X.U.ClickableWorkspaces: Drop escaping from clickableWrap
This breaks putting <fn> tags and icons into workspace names, which some
people might like. Those few who generate workspace names dynamically
from window titles may (and should) escape it themselves.
2021-03-18 22:17:19 +00:00
Ulrik de Muelenaere
577fd81450 X.Prompt: Add maxComplColumns field to XPConfig
This allows limiting the number of columns in the completion window. The
window width is divided equally between the columns.
2021-03-18 23:09:00 +02:00
Tomáš Janoušek
fcbccc1df2 Merge pull request #480 from slotThe/prompt.pass
X.P.Pass: Update Documentation
2021-03-17 16:47:30 +00:00
Tomas Janousek
7dbedb17d6 Merge branch 'antoniotrkdz/mate-main-menu' 2021-03-17 12:04:09 +00:00
Tomas Janousek
47a0f17230 Update CHANGES 2021-03-17 12:02:45 +00:00
antoniotrkdz
670124e309 X.C.Mate: Add Main Menu keybinding
Now it is possible to use mod+d to open the Mate Main Menu.
2021-03-17 12:01:08 +00:00
Tomas Janousek
e91b0fef82 X.A.WorkspaceNames, X.L.IndependentScreens, X.U.ClickableWorkspaces: Use ppRename
Also, drop now useless integrations from X.U.ClickableWorkspaces:
workspaceNamesPP, marshallPP and clickablePP can now be composed
directly using >>= and it just works.

Related: https://github.com/xmonad/xmonad-contrib/pull/390
Related: https://github.com/xmonad/xmonad-contrib/pull/462
2021-03-17 11:53:44 +00:00
slotThe
cb86dd3c61 Fix inconsistency in CHANGES.md 2021-03-17 09:54:15 +01:00
Joan MIlev
d9a7f4388a Add fullscreenSupportBorder (#476)
Add fullscreenSupportBorder for autohiding window borders
2021-03-17 09:50:16 +01:00
Tomas Janousek
be963c0e93 X.H.ManageHelpers: Fix trailing whitespace 2021-03-16 20:24:33 +00:00
Tomas Janousek
91010f6eb9 X.H.DynamicLog: Add ppRename (composable tag augmentation)
This one is a Reader in WindowSpace, and therefore significantly
simplifies the composition of WorkspaceNames, IndependentScreens,
ClickableWorkspaces and possibly other similar modules.

Related: https://github.com/xmonad/xmonad-contrib/pull/390
Related: https://github.com/xmonad/xmonad-contrib/pull/462
2021-03-16 18:45:19 +00:00
Tomas Janousek
fc7ea97582 X.H.DynamicLog: Reindent pprWindowSet 2021-03-16 18:23:28 +00:00
slotThe
c8de3b92af X.P.Pass: Update documentation 2021-03-16 14:13:24 +01:00
slotThe
90974fd820 X.L.Magnifier: Update screenshot 2021-03-16 10:36:25 +01:00
Tomáš Janoušek
62d65d3cdd Merge pull request #459 from slotThe/prompt-spaces
X.Prompt: Correct tab completion handling
2021-03-15 18:33:04 +01:00
AusCyber
feb9306222 Added Dynamic Icon Support
Created a separate module DynamicIcons
2021-03-12 11:46:54 +00:00
Tomas Janousek
8a0151fe77 X.U.ClickableWorkspaces: Drop obsolete doc reference 2021-03-12 11:46:23 +00:00
Tomas Janousek
690e928a1c Merge branch 'pr/trackfloating' 2021-03-12 11:17:57 +00:00
Tomas Janousek
3df6d2af01 CHANGES: Fix whitespace
Fixes: 2e2d344d92 ("X.C.Mate: logout, shutdown options (#475)")
2021-03-12 11:16:14 +00:00
Tomas Janousek
652dd03319 Merge branch 'pr/servermode' 2021-03-12 11:15:32 +00:00
Tomas Janousek
60bf7a4d42 Merge branch 'pr/urgencyhook' 2021-03-12 11:04:33 +00:00
Tomáš Janoušek
c826d068bc Merge pull request #473 from mflav/master
X.H.ManageHelpers: Add shiftToSame, clientLeader
2021-03-12 11:18:19 +01:00
Matthew Flavin
e38274e05c X.H.ManageHelpers: Revised documentation for new sameBy and shiftToSame functions 2021-03-11 22:51:09 -05:00
brandon s allbery kf8nh
2e2d344d92 X.C.Mate: logout, shutdown options (#475)
* New logout options

Factor out Mate logout action and add a shutdown action which the user can bind additionally or in its place.

* Add documentation

* Update CHANGES.md
2021-03-11 22:29:50 +01:00
Tomas Janousek
9f6c829c94 Update CHANGES (X.H.ManageHelpers) 2021-03-10 00:24:34 +00:00
Tomas Janousek
2bec3175cc X.H.ManageHelpers: Generalize shiftByLeader to shiftToSame (supports pid as well) 2021-03-10 00:15:02 +00:00
Tomas Janousek
c7e9d914e1 X.H.ManageHelpers: Simplify shiftToLeader implementation
Short-circuiting the search isn't worth the code complexity, so just
search for all windows with the same leader and then pick the first one
using `listToMaybe` and pass that to `doShiftTo`.

Also, rename to `shiftByLeader` because we aren't really shifting to the
leader itself. We just shift to another window that has the same leader.
2021-03-09 23:40:20 +00:00
Tomas Janousek
289c7e433a X.H.ManageHelpers: Factor doShiftTo out of transience and switch to W.shiftWin
Will be useful for shiftToLeader.

Use W.shiftWin instead of W.shift as it isn't guaranteed that the window
being managed by the ManageHook is still in focus.
2021-03-09 23:27:14 +00:00
Matthew Flavin
8202594b1d Added leader functions 2021-03-08 14:52:01 -05:00
Tomas Janousek
9451d81427 Apply two xmonad core fixes to float moving/resizing in various contrib modules
This applies fixes from
4565e2c90e
and
b9ce5b034b.

tl;dr:
When dragging, refloat and refresh to fix https://github.com/xmonad/xmonad/issues/63.
When starting dragging, raising the window is then unnecessary, and
removing it fixes https://github.com/xmonad/xmonad/issues/208.
Also remove unnecessary raises for keyboard moving/resizing which always
refloated the window.

Fixes: https://github.com/xmonad/xmonad/issues/63
Fixes: https://github.com/xmonad/xmonad/issues/208
2021-02-16 12:23:28 +00:00
Tomas Janousek
3d6844c65f Update CHANGES 2021-02-15 17:58:26 +00:00
Tomas Janousek
1b327a059a X.H.UrgencyHook: Generalize filterUrgencyHook to Query Bool 2021-02-15 17:58:21 +00:00
Tomas Janousek
d49f7a49a2 X.H.ManageHelpers: Add windowTag
Not useful in a manageHook, but useful when a Query is used to select an
existing managed window.
2021-02-15 17:58:15 +00:00
Tomas Janousek
43592c84d4 X.L.TrackFloating: Fix changing focus on inactive workspaces
When focus changes¹ on an inactive workspace (not `current`, but
`visible`), TrackFloating and UseTransientFor would think they should
use the remembered focus point as they look at the wrong (`current`)
workspace instead of the workspace they're supposed to layout, and so
focus seems to be out of their set of windows, when actually it is not.

Fix this by looking at the correct workspace.

¹) This isn't entirely straightforward, as there are normally no
   keybindings or StackSet operations for this, but it's perfectly legal
   to `W.view` the inactive workspace, change focus, and `W.view` back
   in a single `windows` action.
2021-02-15 17:25:48 +00:00
Tomas Janousek
9e6e521fbb X.H.UrgencyHook: Cleanup stale urgents in startupHook (small memleak workaround)
If a manually crafted ClientMessageEvent with invalid (nonexistent)
ev_window is sent to xmonad (by sending it to the root window), the
nonexistent window is added to Urgents and stays there forever.

This can also happen when a window in Urgents disappears while xmonad is
restarting, in which case xmonad never sees the DestroyWindowEvent and
never gets to remove the window from Urgents.

As both of these are fairly unlikely, only do the cleanup in
startupHook to not waste cycles.
2021-02-15 12:17:57 +00:00
Tomas Janousek
13f21f4704 X.H.UrgencyHook: Export clearUrgents'
This makes it possible to clear urgency of selected windows only, which
may be useful to some users (like me).
2021-02-15 12:17:57 +00:00
Tomas Janousek
101d6e89bd X.H.UrgencyHook: Clear EWMH urgency in clearUrgents and filterUrgencyHook
The EWMH support added in 7e9c986217 only added handling of
_NET_WM_STATE_DEMANDS_ATTENTION to handleEvent and cleanupUrgents, but
manual urgency clearing via clearUrgents or automatic urgency clearing
via filterUrgencyHook was left without EWMH support. This commit adds
the missing pieces.

Fixes: 7e9c986217 ("Add EWMH DEMANDS_ATTENTION support to UrgencyHook.")
2021-02-15 12:17:57 +00:00
Tomas Janousek
90737d6d03 X.H.UrgencyHook: Drop $note (obsolete for 12 years)
The note doesn't apply since 9a7dcbbabb ("Adjustments to use the new
event hook feature instead of Hooks.EventHook").
2021-02-15 12:17:57 +00:00
Tomas Janousek
b24a88a3a3 Update CHANGES 2021-02-15 11:49:00 +00:00
Tomas Janousek
fc60ccb1fb scripts: Make scripts executable and add #!runhaskell to xmonad{ctl,propread} 2021-02-15 11:42:23 +00:00
Tomas Janousek
52717dd5fb X.H.ServerMode: Only read the first ClientMessage data item
Atoms are at most 32-bit even on 64-bit platforms, per the X protocol,
despite them being stored in a CLong. Even if they weren't (and they
are, see /usr/include/X11/Xproto.h and
https://stackoverflow.com/a/23265984/3407728), xmonadctl isn't unpacking
the CLong into multiple data items.
2021-02-15 11:42:23 +00:00
Tomas Janousek
d70128418b xmonadctl: Tidy help a bit 2021-02-15 11:42:23 +00:00
Tomas Janousek
eb752b15d8 Pass 0 to setClientMessageEvent where appropriate
Stop pretending it has anything to do with time, it's zero, and it's not
being read anywhere, we're passing the parameter only because
setClientMessageEvent needs one. We should switch to
setClientMessageEvent' and pass no data, but that would move the X11
dependency lower bound.
2021-02-15 11:42:23 +00:00
Tomas Janousek
a7bb1a776a X.H.ServerMode: Move xmonadctl source code to scripts/
Makes it easier to build and maintain.
2021-02-15 11:42:23 +00:00
Tomas Janousek
ebf9561d76 scripts/xmonadpropread: Print current property value at start
It was only printed after the first change.
2021-02-11 21:24:08 +00:00
Tomas Janousek
f2993f5a25 X.D.Extending: Fix typo 2021-02-11 15:53:19 +00:00
Tomas Janousek
ccebeb675d scripts/xmonadpropread: Document and support custom props 2021-02-11 15:53:17 +00:00
Tomáš Janoušek
cdc6c6d39c Merge pull request #443 from TheMC47/refactor-dynamic-log
Refactor X.H.DynamicLog and multiple loggers support
2021-02-10 22:16:14 +01:00
Yecine Megdiche
44c575930a Added StatusBarConfig and multiple loggers support
- StatusBarConfig serves as an abstraction over status bars. This
enables users to customize their status bars without having to do
the plumbing themselves.
- Multiple status bars can be used directly thanks to the
StatusBarConfig, which provides a way to compose status bars
2021-02-10 21:05:23 +00:00
Tomáš Janoušek
b63eb1c283 Merge pull request #464 from TheMC47/java-hack
X.U.Hacks: Add javaHack
2021-02-10 13:05:37 +01:00
Yecine Megdiche
c3e5c1a9aa Added javaHack
Fixes Java applications that don't work well with xmonad, by setting @_JAVA_AWT_WM_NONREPARENTING=1@
2021-02-08 17:30:13 +01:00
Tomáš Janoušek
747202a214 Merge pull request #462 from liskin/pr/clickable
X.U.ClickableWorkspaces: Integrations with X.L.IndependentScreens and X.A.WorkspaceNames
2021-02-04 20:56:06 +01:00
Tomáš Janoušek
39a9c041c5 Merge pull request #458 from liskin/pr/dolower-doraise
X.H.ManageHelpers: Add doLower, doRaise
2021-02-04 17:18:40 +01:00
Tomas Janousek
3876f2fc86 X.H.ManageHelpers: Add doLower, doRaise
I need this in my config and I've seen it being useful for others on
Reddit and IRC.
2021-02-04 16:03:05 +00:00
Tomas Janousek
18c5498aeb X.U.ClickableWorkspaces: Improve docs a bit 2021-02-04 16:01:19 +00:00
Tomas Janousek
30d6d7ed4c X.L.IndependentScreens: Use the unmarshallW abstraction where appropriate 2021-02-04 16:01:19 +00:00
Tomas Janousek
c37737bf73 Add missing ppVisibleNoWindows to workspaceNamesPP, marshallPP, clickableRenamedPP
The ppVisibleNoWindows was added in #241 but none of the modules that
rename/mangle workspace names were updated (or didn't exist at the
time). This fixes this.

Related: https://github.com/xmonad/xmonad-contrib/pull/241
Related: 670eb3bc60 ("Added pretty printer for empty visible workspaces")
2021-02-04 16:01:19 +00:00
Tomas Janousek
c6b4e69f39 X.U.ClickableWorkspaces: Add integrations with X.L.IndependentScreens and X.A.WorkspaceNames
Having these work together isn't entirely trivial so let's provide the
integrations.

Related: https://github.com/xmonad/xmonad-contrib/pull/390
2021-02-04 16:01:19 +00:00
Tomas Janousek
5990456cc9 X.U.ClickableWorkspaces: Use xdotool instead of the unmaintained wmctrl
The last release of wmctrl was in 2005 and it doesn't correctly set
source indication in _NET_ACTIVE_WINDOW client messages
(https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html#sourceindication),
which is obviously completely irrelevant here, but if one decides to
implement clickableWrap for switching windows as well (like I did), it's
nice to use the same tool for it.

It's also nice to use a tool that compiles and runs on 64-bit
architectures without having to patch it (taken care of by distros,
though). :-)
2021-02-04 16:01:19 +00:00
slotThe
00a6e4839a Update CHANGES.md 2021-02-04 15:29:18 +01:00
slotThe
ee4a3a932d XMonad.Prompt: Fix alwaysHighlight tab-completion
526336ecec introduced a bug where
tab-completion has an issue when a completion contains spaces; it only
deletes the last word of that completion, causing the next TAB to again
select the current selection and add it to the command.  In this way,
the prompt can get "stuck" on an item, endlessly adding all but the
first word to the command every time TAB is pressed.

C.f. xmonad/xmonad-contrib/issues/455
2021-02-04 10:16:09 +01:00
slotThe
0a2e1f7254 XMonad.Prompt: hlint nits 2021-02-04 10:16:09 +01:00
slotThe
f2cfaa3398 Safe indexing in 'highlightedItem'
Just because there are some completions doesn't mean that the given
index may not still be too big.

Incidentally, this now allows every prompt to cycle through its items in
a nice way.
2021-02-04 10:16:09 +01:00
slotThe
4eec511eb8 Merge pull request #461 from slotThe/changes-cleanup
Clean up and unify CHANGES.md
2021-02-04 09:04:11 +00:00
slotThe
db972afbc6 Clean up and unify CHANGES.md 2021-02-03 08:04:22 +01:00
slotThe
b13447b361 Merge pull request #448 from TheMC47/more-loggers
More loggers: A `maybe`-like combinator, and screen-specific loggers
2021-01-30 20:22:51 +00:00
Tomáš Janoušek
f42989112c Merge pull request #457 from slotThe/issue-template
Add "Steps to Reproduce" to ISSUE_TEMPLATE.md
2021-01-30 17:42:20 +01:00
slotThe
3c7ec6343a Add "Steps to Reproduce" to ISSUE_TEMPLATE.md 2021-01-30 16:40:46 +01:00
Yecine Megdiche
32ffca599e Added more loggers
- `logWhenActive` to have loggers active only when a certain screen is
active.
- `logTitleOnScreen`, `logCurrentOnScreen` and `logLayoutOnScreen` as
screen-specific variants of `logTitle`, `logCurrent`, `logLayout`
- `logConst` to log a constant `String`
- `logMaybe` and `.|` to combine loggers.
2021-01-30 15:29:51 +01:00
Tomáš Janoušek
2eb67ed341 Merge pull request #418 from liskin/trackfloating-focustracking
X.L.TrackFloating: Clean up and simplify
2021-01-30 12:53:09 +01:00
Tomáš Janoušek
c3c0d38b26 Merge pull request #397 from liskin/purex-focusnth
X.U.PureX: Add focusWindow and focusNth
2021-01-30 12:46:29 +01:00
Tomáš Janoušek
000590fa62 Merge pull request #453 from slotThe/default->def
Remove last occurences of non Data.Default defaults
2021-01-28 21:48:25 +01:00
slotThe
227a3e0aa5 X.A.TreeSelect: Deprecate tsDefaultConfig
Replace with Data.Default.def, as already happened a while ago (in
0f1b6fb772) in all other modules.
2021-01-28 21:39:45 +01:00
slotThe
e83081b6ef Remove mentions of defaultConfig
These were superseded, but forgotten to be updated, by Data.Default.def
in 5140f5b5d0.
2021-01-28 21:36:48 +01:00
Tomáš Janoušek
444bdc09f0 Merge pull request #440 from liskin/pr/borders
X.L.NoBorders: Fix float handling on multihead setups
2021-01-27 22:29:28 +01:00
Tomas Janousek
48156cafb8 X.L.NoBorders: Add unit test for multihead floats 2021-01-27 20:14:17 +00:00
Tomas Janousek
9cff824a24 X.L.NoBorders: Fix float handling on multihead setups
Before c6cdb77e3b, handling of floats was
trivial (too trivial, and thus inefficient and flickery): any float
whose rectangle covered (RationalRect 0 0 1 1), regardless of what
screen or workspace it belonged to, got its borders hidden.

Then c6cdb77e3b added some nuance
(OnlyLayoutFloatBelow, OnlyLayoutFloat, OnlyScreenFloat) which requires
looking at floats in the context of individual screens. Unfortunately
the implementation only worked in singlehead setups, as it always used
only the active screen/workspace regardless of which screen/workspace
was currently being layouted. This resulted in the new functionality not
working correctly on inactive screens and also regressed the handling of
fullscreen floats on inactive screens.

The fix is conceptually easy: use the screen that is being layouted.

There is a catch, unfortunately: this code runs in redoLayout, but the
information we need is only available in modifyLayout and
modifyLayoutWithUpdate. I could store a screen id in the
ConfigurableBorder record in modifyLayoutWithUpdate and use it later in
redoLayout, but that'd be a massive hack, so what I do instead is to
find the relevant screen by searching for one that covers the `lr`
(layout/screen rectangle). In most setups, this should be reliable. If
it turns out it is not, we can fix this later.

Fixes: c6cdb77e3b ("'XMonad.Layout.NoBorders': various improvements:")
Fixes: https://github.com/xmonad/xmonad-contrib/issues/280
2021-01-27 20:14:08 +00:00
Tomas Janousek
a98cc194ad X.L.NoBorders: Fix docs of data Ambiguity
In c6cdb77e3b, several new constructors
were added but not "In order of increasing ambiguity (less borders more
frequently)" as the docs for data Ambiguity say. Correct the order and
clarify that Never only considers ambiguity of tiled windows (as in the
doc for smartBorders).

Fixes: c6cdb77e3b ("'XMonad.Layout.NoBorders': various improvements:")
Related: https://github.com/xmonad/xmonad-contrib/issues/280
2021-01-27 20:13:49 +00:00
Tomáš Janoušek
081629d39f Merge pull request #451 from liskin/pr/ci
ci: Maintenance
2021-01-27 21:12:03 +01:00
Tomáš Janoušek
627e203bcf Merge pull request #452 from liskin/pr/hspec
tests: Use hspec as test driver (prep for #407 #430 #440 unit tests); speed up
2021-01-27 21:05:49 +01:00
Tomáš Janoušek
94670a72be Merge pull request #447 from slotThe/grab-pointer
Grab the Pointer in X.Prompt and X.A.TreeSelect
2021-01-27 17:43:42 +01:00
slotThe
6d1f34cf18 Update CHANGES.md 2021-01-27 16:37:59 +01:00
slotThe
c59805636d XMonad.Action.TreeSelect: Allow Pointer Events
If this is not done, trying to select another window with the mouse when
the treeselect window is up, the X server executes a pointer/keyboard
grab until `allowEvents' is called; which it never is and so both remain
frozen indefinitely.

C.f.:
  - xmonad/xmonad/issues/116
  - xmonad/xmonad-contrib/issues/445
2021-01-27 16:37:59 +01:00
slotThe
08a165df40 XMonad.Prompt: Allow Pointer Events
If this is not done, trying to select another window with the mouse when
the prompt is up, the X server executes a pointer/keyboard grab until
`allowEvents' is called; which it never is and so both remain frozen
indefinitely.

C.f.:
  - xmonad/xmonad/issues/116
  - xmonad/xmonad-contrib/issues/445
2021-01-27 08:30:41 +01:00
Tomas Janousek
6179ed9dbe X.L.LimitWindows: Silence duplicate export warnings in tests 2021-01-26 22:21:20 +00:00
Tomas Janousek
2691e3a490 X.A.GridSelect: Use OVERLAPPABLE, seems to help with unnecessary recompiles
Without this, any change to tests triggers a recompile of GridSelect
when invoking "stack test", adding a couple seconds. This seems to help.
2021-01-26 13:43:35 +00:00
Tomas Janousek
5c7e1194d0 ci: Drop some unnecessary build deps from tests (stack) workflow
Consistency with the other workflow…
2021-01-25 22:34:28 +00:00
Tomas Janousek
42771e4658 ci: Run tests (stack) workflow in all branches
Consistency with haskell-ci (cabal) workflow. It's nice to see the
results before opening a PR so that one doesn't need to embarrass
themselves.
2021-01-25 22:34:28 +00:00
Tomas Janousek
d4d78abc4a ci: Minor cleanup
* split into buildenv deps and stack build
* make the deps list more git-friendly
* use stack from github environment (I've seen the curl fail intermittently)
* indent consistency
2021-01-25 22:34:28 +00:00
Tomas Janousek
55747ecced ci: Add lts-17 and nightly 2021-01-25 22:34:28 +00:00
Tomas Janousek
245dac496b tests: Speed up by producing less discarded tests in SwapWorkspaces 2021-01-25 22:14:47 +00:00
Tomas Janousek
cd5b1a1015 tests: Use hspec as test driver
My main motivation here is that I'd like to add some unit tests (as
opposed to testing everything using QuickCheck properties), but there
are other benefits: it's now easier to run a subset of tests -- the
command-line interface is more powerful.

Also, rename the test-suite to "tests" as it's no longer limited to
properties.
2021-01-25 22:14:47 +00:00
Tomas Janousek
320fe8c537 tests: Clean up test-suite in cabal
* silence warnings about unlisted modules
* remove xmonad-contrib dependency to make it unambiguous that modules
  are recompiled with -DTESTING, not taken from the library
* sort build-depends
2021-01-25 22:14:47 +00:00
Tomáš Janoušek
b8ac9804fc Merge pull request #449 from TheMC47/cleanup-dynamic-log
Cleanup: XMonad.Hooks.DynamicLog
2021-01-24 17:32:21 +01:00
Yecine Megdiche
67341e30a2 Cleanup: hlint hints 2021-01-24 17:20:50 +01:00
Tomáš Janoušek
3e6f0f9f51 Merge pull request #406 from liskin/managedocks-cache-on-demand
X.H.ManageDocks: Init strut cache on demand if necessary
2021-01-24 16:43:56 +01:00
Peter Simons
8b50ee5c9b Merge pull request #446 from xmonad/t/haskell-ci
Generate CI with the haskell-ci utility.
2021-01-19 21:05:31 +01:00
Peter Simons
14393a2cf9 Add haskell-ci generated Github actions. 2021-01-19 20:55:56 +01:00
Peter Simons
96e3f00a1f xmonad-contrib.cabal: update the list of supported compilers 2021-01-19 20:55:29 +01:00
Tomáš Janoušek
03650d5d3f Merge pull request #444 from slotThe/exception-extensible
Control.Exception.Extensible -> Control.Exception
2021-01-17 20:35:38 +01:00
slotThe
77b047316c Control.Exception.Extensible -> Control.Exception
According to its documentation[1], this module simply re-exports
Control.Exception on recent GHC versions.  As we only support recent
versions, this import is unnecessary.

[1] http://hackage.haskell.org/package/extensible-exceptions-0.1.1.4/docs/Control-Exception-Extensible.html
2021-01-12 11:13:29 +01:00
slotThe
0a44981d0f Merge pull request #442 from slotThe/prompt-ah-history
X.Prompt: Correctly Update History with alwaysHighlight
2021-01-11 15:10:26 +00:00
slotThe
b3316c2e34 Update CHANGES.md 2021-01-08 17:15:31 +01:00
slotThe
404b3f59b4 X.Prompt: correctly update history
So far, when `alwaysHighlight' was enabled and the user selected an item
while not having completely written it out in the prompt, the input
string and not the eventual completion string would be entered into the
prompt history, which is obviously not the desired behaviour.  This can
cause the history to clutter up with all these abbreviations, making
subsequent invocations of the prompt tedious to work with.

For example, an input of "xm" would narrow to both "xmonad" and
"xmobar", but thanks to `alwaysHighlight' "xmobar" was selected.  If the
user now pressed enter, the prompt would correctly return "xmobar" as
the string to act upon, but "xm" would be entered into the prompt
history!
2021-01-08 17:08:53 +01:00
Tomáš Janoušek
d0813f0b3a Merge pull request #441 from slotThe/xdg-mess
Revise XDG handling
2021-01-07 19:52:23 +01:00
slotThe
c39a5cf618 Update CHANGES.md 2021-01-07 15:23:54 +01:00
slotThe
9d520dc880 X.Prompt: X constraint for historyCompletion[P]
This is needed because the cache directory is now a part of XConf, which
is calculated once on startup and hence any recalculation would be
fragile.

Some internal functions that are not exposed (like writeHistory) were
also changed to accept that directory as an argument.
2021-01-07 10:33:47 +01:00
slotThe
3213925b6b X.H.Script: Add X constraint 2021-01-07 10:33:47 +01:00
slotThe
9fe3444374 Merge pull request #437 from slotThe/ppTitleUnfocused
X.H.DynamicLog: Add ppTitleUnfocused
2021-01-07 09:31:57 +00:00
slotThe
e06eafbadd Update CHANGES.md 2021-01-07 10:23:53 +01:00
slotThe
a3e06685ef X.H.DynamicLog: Add ppTitleUnfocused 2021-01-07 10:23:53 +01:00
slotThe
0313b26cd8 Merge pull request #403 from elkowar/fullscreen-fix
Add new module XMonad.Util.Hacks (formerly XMonad.Hooks.WindowedFullscreenFix)
2021-01-07 09:22:49 +00:00
slotThe
ba94d48464 Merge pull request #170 from mavant/issue/164
Only modify the last word during tab completion
2021-01-04 13:01:26 +00:00
slotThe
526336ecec Only modify the last word during tab completion
Fixes #164.

It's not clear to me why these functions take in XPState as a param only
to then produce some XP () values. It seems like they could just as well
call `get`.
2021-01-04 10:17:28 +01:00
slotThe
f9a226e75a Merge pull request #439 from TheMC47/cleanupStatusBars-startup
Add cleanupStatusBars to statusBarPropTo
2021-01-02 10:07:26 +00:00
Yecine Megdiche
6c83af1c69 Added cleanupStatusBars to the startup-hook 2021-01-01 21:08:51 +01:00
elkowar
71863c735a Fix documentation issues and add gifs 2021-01-01 16:37:49 +01:00
elkowar
d293a053e1 Fix typo and remove +1 from resizeWindow 2021-01-01 14:40:33 +01:00
elkowar
b41a5a50e9 Move module to new module XMonad.Util.Hacks 2021-01-01 13:15:18 +01:00
elkowar
3d553ad5e0 Add new module XMonad.Hooks.WindowedFullscreenFix 2021-01-01 13:14:05 +01:00
Tomáš Janoušek
b963c3cf9d Merge pull request #434 from TheMC47/restart-docks
Restarting status bars on restart
2020-12-30 09:57:01 +01:00
Yecine Megdiche
78df487e4c Added spawnStatusBarAndRemember and cleanupStatusBars
In order to effectively restart status bars without relying
on pipes, spawnStatusBarAndRemember saves the PID of status
bars to kill them with cleanupStatusBars.

Removed checking for docks

Cleaned imports

Use signalProcesGroup instead of inverting the PID

Updated the documentation

Updated the documentation
2020-12-29 21:45:33 +01:00
slotThe
63a3282133 Merge pull request #428 from pshevtsov/lxqt-config
Add XMonad.Config.LXQt
2020-12-29 20:13:05 +00:00
Petr Shevtsov
2809ed105e Add new module XMonad.Config.LXQt 2020-12-29 21:39:02 +03:00
slotThe
ef3697c09c Merge pull request #427 from slotThe/fix-fadewindows
Fix Documentation in X.H.FadeWindows
2020-12-29 17:37:27 +00:00
Tomas Janousek
555cd7c596 X.H.DynamicLog: Minor doc tweaks 2020-12-19 18:27:19 +00:00
Sibi Prabakaran
cff344811f Merge pull request #408 from slotThe/dynamic-log
X.H.DynamicLog: Start recommending poperty-based logging
2020-12-19 18:46:46 +05:30
Tomáš Janoušek
88ddd54084 Merge pull request #435 from wz1000/master
Export modifyProject in XMonad.Actions.DynamicProjects
2020-12-19 11:32:08 +00:00
Zubin Duggal
c66345467e Export modifyProject 2020-12-19 16:42:20 +05:30
slotThe
06af11a463 Update CHANGES.md 2020-12-18 21:10:44 +01:00
slotThe
6977d0cdfb X.H.DynamicLog: Update documentation
Stop recommending pipes as the best/first thing to do and instead
recommend property based logging for all bars that support it.  Also
strongly recommend users to use the already pre-made functions that do
all of the plumbing.

Add comments for the arguments of the most important user-facing
functions.
2020-12-18 21:10:44 +01:00
slotThe
9b6c098c9c Add xmobarProp, statusBarProp, and statusBarPropTo
In an effort to modernize XMonad.Hooks.DynamicLog (and thus to stop
recommending pipes as the best way to interface with xmobar), implement
property log based solutions for the most important functions.  Sadly
dzen does not seem to support this kind of interfacing with xmonad.

The descriptions of xmobar, statusBar, and statusBar' have been updated
to reflect that they should be seen as secondary choices.
2020-12-18 13:54:22 +01:00
Tomas Janousek
35e794b1b2 Minor cleanup of CI 2020-12-16 11:22:41 +00:00
Sibi Prabakaran
8648ea790a Merge pull request #432 from slotThe/unused-imports
Get rid of unused imports
2020-12-16 10:32:43 +05:30
slotThe
0490e77970 Fix Documentation in X.H.FadeWindows 2020-12-15 17:23:35 +01:00
slotThe
d6cc525500 X.H.FadeWindows: Default to opacity 1 2020-12-15 17:22:18 +01:00
slotThe
53903b086f Conditionally error on unused imports
This turns off the warnings about unused imports _unless_ one is using
the oldest supported version of GHC (right now that's 8.4.4 or older);
then it turns them into errors!  This prevents xmonad from emitting
warnings about imports that have to be there due to backwards
compatibility, but are obsolete in newer versions (think MFP), while at
the same time preventing bitrot.
2020-12-14 14:04:57 +01:00
slotThe
6715c75c50 Drop old versions of GHC
Removes references to all versions of GHC that are not part of the CI,
as these can't be guaranteed to be built against master every time
2020-12-14 14:04:19 +01:00
slotThe
78d526d1dd Get rid of unused imports
Starting with 5240116f3c we only support
GHC versions 8.4.4 and up (more precisely, the GHC version associated
with stackage lts-12 and up).  The imports in question are now in
Prelude and need not be imported explicitly.
2020-12-14 13:41:28 +01:00
Sibi Prabakaran
5240116f3c Add CI workflow against xmonad latest commit (#429) 2020-12-14 17:22:01 +05:30
Tomas Janousek
89646d75fd X.H.DynamicLog: Add shorten' and shortenLeft' (customizable end) 2020-12-13 21:38:35 +00:00
Petr Shevtsov
5e0ef3777a Update CHANGES.md 2020-12-12 21:39:53 +03:00
Petr Shevtsov
69c1821818 Initial commit 2020-12-12 21:35:36 +03:00
Tomáš Janoušek
27f03ad9c5 Merge pull request #426 from pshevtsov/patch-1
Use the default XFCE terminal with `XMonad.Config.Xfce`
2020-12-12 00:33:22 +00:00
Tomáš Janoušek
bd9a79cb80 Merge pull request #421 from slotThe/filterOutWsPP
Add filterOutWs[PP]
2020-12-11 17:58:16 +00:00
slotThe
e956fbf3ce Update CHANGES 2020-12-11 18:54:11 +01:00
slotThe
6087bdd40d Deprecate namedScratchpadFilterOutWorkspace[PP]
These were superseded by more generic function in
XMonad.Hooks.DynamicLog.
2020-12-11 18:54:11 +01:00
slotThe
d3f11d041a Export scratchpadWorkspaceTag
Users are now able to use this, instead of hard-coding the "NSP" name in
their configurations
2020-12-11 18:54:11 +01:00
slotThe
0cbee237c7 Add filterOutWs and filterOutWsPP
These are more generic versions of the respective functions in
XMonad.Util.NamedScratchpad.
2020-12-11 18:54:11 +01:00
Sibi Prabakaran
83b005ee79 Merge pull request #417 from TheMC47/refactor-test-suite
Refactor the test-suite
2020-12-11 22:47:32 +05:30
Yecine Megdiche
048b12995a removed tests/* from extra-source-files 2020-12-11 18:03:22 +01:00
Yecine Megdiche
7ef0faa986 added new test-suite 2020-12-11 18:03:22 +01:00
Sibi Prabakaran
69a2886a8b Merge pull request #425 from xmonad/ci-github
Add github actions for test
2020-12-11 22:22:10 +05:30
Petr Shevtsov
f24788260d Update CHANGES.md 2020-12-11 18:35:19 +03:00
Petr Shevtsov
6e44ddb57a Use xfce4-terminal for terminal 2020-12-11 18:29:29 +03:00
Sibi Prabakaran
2e900cc10b Update README 2020-12-11 17:46:03 +05:30
Sibi Prabakaran
f73ebf1da1 Update 2020-12-11 17:29:14 +05:30
Sibi Prabakaran
84caa46dab Add github actions for test 2020-12-11 17:20:59 +05:30
Tomáš Janoušek
5db2589abf Merge pull request #423 from dminuoso/fix-toenum-crash
Check for text encoding correctly and avoid bottom (#422)
2020-12-11 01:53:41 +00:00
Victor Nawothnig
b594d97604 Check for text encoding correctly and avoid crash (#422) 2020-12-11 02:46:40 +01:00
Tomas Janousek
89dbdd4767 X.L.TrackFloating: Simplify focus logic
It seems the logic used in X.L.StateFull's FocusTracking should cover
all use cases here. Let's try it for a while. :-)
2020-12-09 00:20:41 +00:00
Tomas Janousek
0e9c865e72 X.L.TrackFloating: Drop redundant _wasFloating
It was added in 81d338952d in an attempt to fix focus handling after
closing a floating window, but shortly after made redundant in
a551d1367c when we noticed it causes more harm than good. Unfortunately
it wasn't fully reverted, making the code more complex than necessary.

Drop the remaining bits.

Now it's almost obvious that the only difference between this and
X.L.StateFull.FocusTracking is the isF condition.

BTW the original issue 81d338952d was trying to fix can be fixed by
using X.H.RefocusLast, from the author of X.L.StateFull.FocusTracking.
:-)
2020-12-09 00:20:41 +00:00
Tomas Janousek
8afd51517c X.L.TrackFloating: Simplify by using X.U.Stack.findZ
X.L.TrackFloating is more or less the same as X.L.StateFull's
FocusTracking, so it's no surprise the same helpers can be used...
2020-12-09 00:20:41 +00:00
Tomas Janousek
72b5e662de X.U.Stack: Fix/simplify find{S,Z} types
Drop Eq constraint that isn't needed.

Drop the redundant Maybe from findZ return type. Breaks symmetry but
makes it easier to use (join no longer needed).
2020-12-09 00:20:41 +00:00
Brent Yorgey
6381a4687f Merge pull request #411 from PRESFIL/fix-Example.hs
Fix transients managing in X.C.Example
2020-12-02 13:17:28 -06:00
Brent Yorgey
a74ed5f724 Merge pull request #203 from Ongy/dzen-dock
Add -dock to dzen command
2020-12-02 13:15:28 -06:00
Brent Yorgey
317eb23654 Merge branch 'master' into dzen-dock 2020-12-02 13:15:01 -06:00
Brent Yorgey
e3558bce93 Merge pull request #401 from elkowar/cycle-action
Add new module XMonad.Util.ActionCycle
2020-12-01 14:32:54 -06:00
Matus Goljer
d9ad93a888 Add Emacs-style Prefix handling (#159)
* Add Emacs-style Prefix handling

* Update CHANGES.md

* Add helper tests for prefix type

* Add docstrings.

* Fix handling of repeated prefix when we fall-back with no binding.

* Add a caveat about nested prefix binding
2020-11-29 22:35:52 +05:30
Tomáš Janoušek
8f7f5f0a56 Merge pull request #414 from srid/patch-1
Loggers: don't hardcode /usr/bin
2020-11-29 11:55:45 +00:00
Brent Yorgey
8694656840 Merge pull request #405 from slotThe/toggleTopic
Update XMonad.Actions.TopicSpace
2020-11-28 14:00:41 -06:00
Tomáš Janoušek
a29b1565d4 Merge pull request #413 from amenonsen/dev/issue-111
Fix typo in X.L.IndependentScreens example code
2020-11-28 00:15:27 +00:00
Sridhar Ratnakumar
e52c20f70c Update CHANGES.md 2020-11-27 21:56:13 +00:00
Sridhar Ratnakumar
95f68e2ca3 Loggers: don't hardcode /usr/bin
Some Linux distros, like NixOS, don't put these binaries under /usr/bin.
2020-11-27 21:54:07 +00:00
Abhijit Menon-Sen
d8cfdaf020 Fix typo in X.L.IndependentScreens example code
Closes #111
2020-11-27 21:51:09 +05:30
PRESFIL
2cfa5ef23a Fix: reorder statements 2020-11-26 13:24:43 +00:00
PRESFIL
d18bcdc165 Replace composeOne with composeAll 2020-11-26 13:23:33 +00:00
slotThe
78796a24f9 Update changelog 2020-11-26 12:54:55 +01:00
slotThe
8822d2ff51 Add getLastFocusedTopicsByScreen, switchNthLastFocusedByScreen 2020-11-26 12:54:55 +01:00
slotThe
ce5aae5403 Use WorkspaceHistory
Instead of defining our own (internal) history, use an already established
module.
2020-11-24 08:35:08 +01:00
slotThe
3e7df4911a Add workspaceHistoryModify 2020-11-24 08:27:39 +01:00
slotThe
ae6c658bc4 Add switchTopicWith 2020-11-24 08:27:39 +01:00
slotThe
1400d167ad Cons on new topic before filtering the last used topics
Because the there is a hard limit on the number of items in the topic
history now, it makes sense to first cons on the topic and then filter
the result (so setLastFocusedTopic can be used to exclude certain topics
from ever entering the history).
2020-11-24 08:27:39 +01:00
slotThe
6079c61063 Use sortOn instead of sortBy comparing 2020-11-24 08:27:39 +01:00
slotThe
aa67fa5352 Respect maxTopicHistory when entering topics into the history
So far, maxTopicHistory was only used when pretty-printing the history
via pprWindowSet, which does not line up with the documentation that it
has.
2020-11-24 08:27:39 +01:00
slotThe
4c0b5330e7 Consistent indentation throughout the module
Two spaces seem to be a bit more common here, hence it was chosen over four
spaces.
2020-11-24 08:27:39 +01:00
slotThe
3c1866979d Update documentation 2020-11-24 08:27:39 +01:00
slotThe
6b22ce17c7 Add switchNthLastFocusedExclude
This may be used to exclude certain topics that one never wants to
"switch back" to, even if it was visited (for example, the named
scratchpad topic).
2020-11-24 08:27:39 +01:00
slotThe
d13a26b11e Update last focused topics when switching to a new one 2020-11-24 08:27:39 +01:00
Sibi Prabakaran
9976aa3b3c Merge pull request #404 from slotThe/remove-default-deprecations
Remove Data.Default Deprecations
2020-11-24 12:29:13 +05:30
PRESFIL
02c6e0b0d4 Handle floating windows after making windows floating
Inspired with hgabreu's config. Now it makes more sense.
2020-11-24 00:33:54 +03:00
PRESFIL
e504f40f88 Fix transient windows handling
Since *transient windows* are a subset of *dialog windows*, they need to be caught early.
Otherwise, they are never managed by `transience`.
2020-11-24 00:33:34 +03:00
Tomas Janousek
6db6854752 X.U.PureX: Add focusWindow and focusNth
This can be used to reduce flicker in noop focus actions.
2020-11-17 14:10:20 +00:00
Tomas Janousek
14dc3a7f79 X.H.ManageDocks: Init strut cache on demand if necessary
This makes docksStartupHook unnecessary. That is desirable because we
didn't add a changelog entry about it being necessary, and 4 years after
its introduction we still have users grabbing old configs and reporting
(https://github.com/xmonad/xmonad/issues/21#issuecomment-596161669) that
ManageDocks doesn't work properly.

I would love to finally settle this.

Full story follows:

xmonad-contrib 0.12 introduced (00be056a1b, merged in April 2013)
caching to ManageDocks to avoid queryTree calls on every runLayout,
which brought in several bugs. Attempts to fix these bugs in
xmonad-contrib 0.13 introduced (28e9f8bce7, merged in February 2016) a
breaking change in ManageDocks that required users to add
docksStartupHook (or docks, after e38fb3bdb8 got merged in November
2016) to their configs for avoidStruts to still work after xmonad
restart. Unfortunately this was never mentioned in the changelog nor in
any compilation warning (which get discarded by xmonad --recompile
anyway !!!), so as of March 2020 we still have users being bitten by
this.

Back in September 2016 in a discussion about other bugs introduced in
28e9f8bce7 I suggested that we use Maybe to indicate whether the cache
had been initialized and initialize it on demand when it had not.
Unfortunately I wasn't sufficiently clear about what I meant and Brandon
was going through some health issues, so we just got into a heated
argument and ended up merging a suboptimal solution. :-(

And since we're _still_ getting complaints from users every now and
then, I believe it's worth dealing with even after all these years.
If nothing else, let this serve as a reminder that breaking users'
configs without any warning is wrong.

(Oh and we should probably stop hiding xmonad.hs compilation warnings,
otherwise we can't ever hope to provide smooth deprecation and upgrade
paths.)

Fixes: 00be056a1b ("Cache results from calcGap in ManageDocks")
Fixes: 28e9f8bce7 ("add docksStartupHook for handling docks when restarted")
Fixes: e38fb3bdb8 ("Make usage of ManageDocks simpler and more robust")
Related: https://github.com/xmonad/xmonad-contrib/issues/118
Related: https://github.com/xmonad/xmonad-contrib/pull/30
Related: https://github.com/xmonad/xmonad-contrib/pull/80
Related: https://github.com/xmonad/xmonad/issues/21
2020-11-17 00:46:12 +00:00
Tomas Janousek
f271d59c34 X.A.WorkspaceNames: Provide workspaceListTransform for EwmhDesktops
Together with ewmhDesktopsLogHookCustom this exposes workspace names to
external pagers.

Fixes: https://github.com/xmonad/xmonad-contrib/pull/105
Fixes: https://github.com/xmonad/xmonad-contrib/pull/122
Co-authored-by: Ivan Malison <IvanMalison@gmail.com>
2020-11-16 11:16:59 +00:00
Tomas Janousek
3dc6b44f86 X.A.WorkspaceNames: Kill a warning 2020-11-16 10:55:22 +00:00
Tomas Janousek
bda1d3356d CHANGES: Trailing whitespace fixes 2020-11-16 10:55:22 +00:00
slotThe
683344ed25 Update CHANGES.md 2020-11-16 10:31:02 +01:00
slotThe
5140f5b5d0 Remove things deprecated by Data.Default 2020-11-16 10:31:02 +01:00
Sibi Prabakaran
cd1c1d1d69 Merge pull request #402 from elkowar/fix-usage-missing
Fix missing usage-section in XMonad.Hooks.WindowSwallowing
2020-11-15 22:01:50 +05:30
elkowar
9e3d17c1c0 Fix missing usage-section in XMonad.Hooks.WindowSwallowing 2020-11-15 13:28:13 +01:00
elkowar
ffae2dcd2f Add new module XMonad.Util.ActionCycle 2020-11-15 13:22:11 +01:00
Tomas Janousek
5d2a6d75a8 X.H.EwmhDesktops: Fix _NET_* properties not being set at startup
None of these properties are currently being set when xmonad starts:

    _NET_ACTIVE_WINDOW(WINDOW): window id # 0x0
    _NET_CURRENT_DESKTOP(CARDINAL) = 0
    _NET_CLIENT_LIST_STACKING(WINDOW): window id #
    _NET_CLIENT_LIST(WINDOW): window id #

because the caching introduced in 92fe5f34ff initializes the
cache with the same values that they should have in an empty session, so
we don't detect a change and don't set them.

Fix it by initializing the cache with impossible (or at least extremely
improbable) values.

Fixes: https://github.com/xmonad/xmonad-contrib/issues/363
2020-11-09 22:15:25 +00:00
Brent Yorgey
e042bcce97 Merge pull request #398 from liskin/layoutclass-typeable
Add Typeable constraint to a few LayoutClass instances
2020-11-09 14:13:09 -06:00
Tomas Janousek
b989655cea Add Typeable constraint to a few LayoutClass instances
This enables adding the Typeable constraint to LayoutClass itself
(https://github.com/xmonad/xmonad/pull/242) which in turn enables
querying the current layout state. That might be useful to e.g. show the
current X.L.WorkspaceDir in xmobar.

This is a preparation commit that fixes the compile failures that would
result in merging that change to xmonad. For this to be generally useful
we first need to merge (and ideally also release) that xmonad change,
and then we'll need some documentation and perhaps a type class to help
find the right LayoutModifier in the tree of ModifiedLayouts and
Choices. That will come later.
2020-11-09 16:37:30 +00:00
Tomas Janousek
087076f136 CHANGES: Document last 3 commits 2020-11-04 16:23:37 +00:00
Tomas Janousek
0996e71c7e X.H.DynamicLog: Add shortenLeft
This can be sometimes useful, e.g. when showing a directory.
2020-11-04 16:17:32 +00:00
Tomas Janousek
d5b64c1e5d X.L.WorkspaceDir: Export Chdir
This makes it possible to change the workspace directory by sending a
message, which enables automation/scripting not possible with
`changeDir` which displays a prompt.

Example of such usage:
6ea6c52aac/.xmonad/xmonad.hs (L183-L189)
2020-11-04 16:16:51 +00:00
Tomas Janousek
73eb28f669 XMonad.Prompt.Directory: Sort completion suggestions 2020-11-04 11:31:50 +00:00
Brent Yorgey
aa67439bfe Merge pull request #192 from sgf-dma/x.h.focus
Resubmit #128 (X.H.Focus)
2020-10-29 19:55:41 -05:00
sgf
2cc20b4116 Add new module XMonad.Hooks.Focus .
Extend ManageHook EDSL to work on focused windows and current workspace.
2020-10-28 17:51:40 +03:00
sgf
45052b984d X.H.EwmhDesktops. run 'logHook' for activated window.
- By default window activation does nothing.
- `activateLogHook` may be used for running some 'ManageHook' for
activated window.
- `activated` predicate may be used for checking was window activated or
not.
2020-10-28 17:51:40 +03:00
sgf
b2e16d3bf1 X.H.ManageHelpers: Make type of ManageHook combinators more general. 2020-10-19 15:18:00 +03:00
sgf
3a7399b56a X.H.SetWMName: Add getWMName function. 2020-10-19 15:18:00 +03:00
Brent Yorgey
4670ec002f Merge pull request #389 from skewerr/master
add XMonad.Layout.VoidBorders
2020-10-17 06:39:18 -05:00
Wilson Sales
5fd8ff86e9 add XMonad.Layout.VoidBorders
This module contains a modifier that simply sets X11 window border width
to 0 for every window in the layout it modifies. No efforts are made to
bring the border back, which can be annoying if windows are moved to a
different workspace, but it prevents the "border flash" you get with
XMonad.Layout.NoBorders.
2020-10-17 00:08:40 -03:00
Brent Yorgey
d4e15cddd1 Merge pull request #390 from ivanbrennan/export-clickableWrap
Export clickableWrap
2020-10-16 17:36:34 -05:00
Brent Yorgey
4f9dec9760 Merge pull request #391 from NickHu/unicode
Fixes for XMonad.Prompt.Unicode
2020-10-16 17:35:18 -05:00
Nick Hu
598a40da9c add missing documentation of XMonad.Prompt.FuzzyMatch and
XMonad.Prompt.Unicode to XMonad.Doc.Extending
2020-10-14 17:20:28 +01:00
Nick Hu
1a085bec43 XMonad.Prompt.FuzzyMatch: handle case when input is not a subsequence of every completion 2020-10-14 17:16:06 +01:00
Nick Hu
a69794892b XMonad.Prompt.Unicode: respect searchPredicate and sorter from XPConfig 2020-10-14 17:13:30 +01:00
ivanbrennan
8e12681925 export clickableWrap
Configs that apply WorkspaceId transformations, such as
IndependentScreens (adding/removing a screen-number prefix) and
NamedWorkspaces (adding/removing a name suffix), cannot use clickablePP
as is, since they need to apply clickableWrap to an appropriately
transformed WorkspaceId. Rather than force them to reimpliment
clickableWrap, export it.

An example use-case, where IndependentScreens has added a screen number
prefix to the workspace ids (0_1, 0_2, ...), and we want a status-bar
that shows the ids without screen number (1, 2, ...), but also makes
them clickable:

    getClickable :: (WorkspaceId -> WorkspaceId) -> X (WorkspaceId -> String)
    getClickable f = do
      wsIndex <- getWsIndex
      pure $ \ws -> case wsIndex (f ws) of
                      Just idx -> clickableWrap idx ws
                      Nothing -> ws

    composePP :: PP -> ScreenId -> X PP
    composePP pp s = do
      clickable <- getClickable (marshall s)
      return
        . marshallPP s
        $ pp
          { ppCurrent         = ppCurrent         pp . clickable,
            ppVisible         = ppVisible         pp . clickable,
            ppHidden          = ppHidden          pp . clickable,
            ppHiddenNoWindows = ppHiddenNoWindows pp . clickable,
            ppUrgent          = ppUrgent          pp . clickable
          }
2020-10-14 07:31:44 -04:00
Nick Hu
9c09072843 XMonad.Prompt.Unicode: use spawnPipe instead of runProcessWithInput 2020-10-13 20:39:21 +01:00
Tomáš Janoušek
02baee5f7e Merge pull request #388 from ivanbrennan/export-clickable-workspaces
Add ClickableWorkspaces to exposed modules
2020-10-12 01:28:08 +02:00
ivanbrennan
00d829803d expose XMonad.Util.ClickableWorkspaces
This module was not exposed, so any attempt to use it resulted in a
compilation error.
2020-10-11 18:49:41 -04:00
Brent Yorgey
9c4c417936 Merge pull request #386 from ivanbrennan/compl-case-sensitivity
Allow case-insensitive shell prompt completion
2020-09-30 17:56:23 -05:00
ivanbrennan
52c5bd61cb use complCaseSensitivity field
Use the newly-added complCaseSensitivity field of XPConfig where
possible, rather than declaring primed function variants.
2020-09-28 22:36:05 -04:00
ivanbrennan
b63159fd00 add complCaseSensitivity field to XPConfig 2020-09-28 21:51:45 -04:00
ivanbrennan
bbcc7e576f CHANGES: directory completion case sensitivity 2020-09-24 08:14:50 -04:00
ivanbrennan
86ef180162 usage: changeDir' 2020-09-24 07:57:34 -04:00
ivanbrennan
4de529a923 DynamicProjects: allow case-insensitive prompts
Provide a way to use case-insensitive directory completion.
2020-09-24 07:57:33 -04:00
ivanbrennan
0c9c330295 Dir: ComplCaseSensitivity field (breaking change)
Parameterizing completion case-sensitivity for single-mode prompts was
possible without making any breaking changes. For multi-mode prompts,
however, the completion function is expressed through the XPrompt
'completionFunction' method. The only argument that method receives is a
Dir value, so parameterizing completion case-sensitivity means adding a
new field to the Dir constructor.
2020-09-24 07:57:33 -04:00
ivanbrennan
795be75a58 prompt completion: case-sensitivity
Provide a way to perform case-insensitive file / directory completion.
We're using compgen to generate completion candidates, and this is
case-sensitive by default. We can control this by setting the
completion-ignore-case Readline variable prior to invoking compgen. If
we're running a Bash with Readline support, this works as expected.
Otherwise, it has no effect -- completion candidates are still returned,
but compgen generates them in a case-sensitive manner.

To avoid breaking changes, the signatures and behavior of existing
exported functions are unchanged:
  - XMonad.Layout.WorkspaceDir.changeDir
  - XMonad.Prompt.Directory.directoryPrompt
  - XMonad.Prompt.Shell.getShellCompl

New variations of these functions are provided, allowing the caller
to specify the desired case-sensitivity via a ComplCaseSensitivity
argument:
  - XMonad.Layout.WorkspaceDir.changeDir'
  - XMonad.Prompt.Directory.directoryPrompt'
  - XMonad.Prompt.Shell.getShellCompl'

The XMonad.Prompt.Shell exports a couple new functions:
  - compgenDirectories
  - compgenFiles

We make use of this in XMonad.Prompt.Directory to avoid duplicating the
compgen code.
2020-09-24 07:57:33 -04:00
Brent Yorgey
b5105381bf Merge pull request #384 from ivanbrennan/rotate-some
RotateSome
2020-09-24 05:09:06 -05:00
ivanbrennan
c5ff88b87b improve RotateSome documentation and readability
Add an example and more comments to the documentation, and make some
small code tweaks (more type signatures and a couple variable renames)
to aid readability.
2020-09-23 16:55:14 -04:00
Ivan
1e73a97500 Merge pull request #383 from ivanbrennan/pretty-printing-modifier
Add statusBar' to support dynamic pretty printing modifiers
2020-09-19 15:27:41 -04:00
ivanbrennan
551ff2b8ac CHANGES: add XMonad.Hooks.DynamicLog.statusBar' 2020-09-19 15:12:54 -04:00
ivanbrennan
ebfc068b99 DynamicLog: statusBar'
Add a statusBar' function that accepts pretty printing options embedded
in the X monad, so users can leverage dynamic printing modifiers, such
as workspaceNamesPP.
2020-09-19 15:12:40 -04:00
Brent Yorgey
dea887d487 Merge pull request #385 from TomSmeets/tree-select-fix-origin
TreeSelect: Resolve issue #362 with origin offset being ignored
2020-09-19 13:23:35 -05:00
ivanbrennan
8fe0eabaf8 add tests/RotateSome.hs to extra-source-files 2020-09-19 14:05:49 -04:00
Brent Yorgey
010cd4ff5f Merge pull request #382 from ivanbrennan/boring-sift
BoringWindows: siftUp, siftDown
2020-09-19 11:12:25 -05:00
ivanbrennan
957f4518b9 surfaceNext, surfacePrev exclude floating windows
I was naively passing the workspace to runLayout without filtering out
floating windows from its stack, like XMonad.Operations.windows does.
The fact that 'windows' does this filtering explains how layouts like
those in LimitWindows continue to behave correctly in the presence of
floating windows.

This fixes some incorrect behavior where the presence of a floating
windows caused visible windows (other than the focused one) to be
included in the surfaceRing.
2020-09-19 11:29:30 -04:00
Tom Smeets
4b65f9eef0 TreeSelect: Resolve issue #362 with origin offset being ignored
The config values `ts_originX` and `ts_originY` were not behaving like documented. They weren't doing anything at all.
This should fix that.
2020-09-18 21:31:10 +02:00
ivanbrennan
e88e7ee1f0 CHANGES: add XMonad.Actions.RotateSome 2020-09-18 12:03:45 -04:00
ivanbrennan
c5745b6299 add RotateSome property tests
Verify that rotateSome behaves as expected and never fails to pattern
match.

In order to run these tests, I ran a custom script:

  scripts/run-tests.sh tests/RotateSome.hs

where the script contained the following:

  set -eu

  toplevel=$(git rev-parse --show-toplevel)
  XMONAD="${XMONAD:-$toplevel/../xmonad}"
  main=$(realpath -e "$1")

  instances_target="$XMONAD/tests/Instances.hs"
  instances_symlink="$toplevel/tests/Instances.hs"

  properties_target="$XMONAD/tests/Properties"
  properties_symlink="$toplevel/tests/Properties"

  utils_target="$XMONAD/tests/Utils.hs"
  utils_symlink="$toplevel/tests/Utils.hs"

  trap "
      rm '$instances_symlink' '$utils_symlink' '$properties_symlink' || true
  " EXIT INT QUIT TERM

  ln -s "$instances_target" "$instances_symlink"
  ln -s "$properties_target" "$properties_symlink"
  ln -s "$utils_target" "$utils_symlink"

  runghc -DTESTING \
      -i"$toplevel" \
      -i"$toplevel/tests" \
      "$main"
2020-09-18 11:31:50 -04:00
ivanbrennan
f06ee5e1ff add XMonad.Actions.RotateSome
This module provides a pure function, 'rotateSome', as well as a pair of
X actions that use it to rotate unshown windows through the focused
stack position while leaving other windows in place. I find this useful
in combination with layouts such as LimitWindows, which determine window
visibility based on stack position.
2020-09-17 22:51:16 -04:00
ivanbrennan
db3e5d85b5 CHANGES: additions to XMonad.Layout.BoringWindows 2020-09-14 17:56:41 -04:00
ivanbrennan
aa3939e66b XMonad.Layout.BoringWindows: siftUp, siftDown
Provide boring-aware versions of the 'siftUp' and 'siftDown' functions.
Since these actions never affect the position of boring windows, they
work well with layouts that decide which windows are visible/hidden
based on stack position, such as LimitWindows.
2020-09-14 17:37:38 -04:00
Brent Yorgey
fe027ce358 Merge pull request #380 from ivanbrennan/sift
XMonad.Actions.Sift
2020-09-14 14:00:50 -05:00
Brent Yorgey
3661471377 Merge pull request #378 from ivanbrennan/boring-swaps
BoringWindows: swapUp, swapDown
2020-09-14 13:50:33 -05:00
ivanbrennan
33ad9e526d CHANGES: add XMonad.Actions.Sift 2020-09-12 13:49:35 -04:00
ivanbrennan
e2fa1ce8a1 add XMonad.Actions.Sift (siftUp, siftDown)
Provide swap-like functions that handle the wrapping case by exchanging
the windows at either end of the stack rather than rotating the stack.

https://github.com/xmonad/xmonad/issues/234
2020-09-12 09:35:35 -04:00
ivanbrennan
f94984c141 CHANGES: additions to XMonad.Layout.BoringWindows 2020-09-10 07:38:11 -04:00
ivanbrennan
c2dd9b0b7a skip boring: extract common iterate/filter logic 2020-09-10 06:40:14 -04:00
ivanbrennan
610fb0e200 skipBoring: drop zeroth iteration before filtering
The effect is the same, but this seems to express the intent more
clearly, and it will make it easier to factor out the shared behavior
with skipBoringSwapUp.
2020-09-10 06:39:50 -04:00
ivanbrennan
53b0edae28 BoringWindows: swapUp, swapDown
Provide boring-aware versions of 'swapUp' and 'swapDown'.

Note that 'iterate f x' produces a list whose zeroth element is
'x' prior to any application of 'f'. The 'focusUp' and 'focusDown'
operations reject this iteration by checking in the filter predicate
that the focus actually changed:

  filter ((`notElem` W.focus st:bs) . W.focus)

We can't do that for swaps, since our focus never changes, so we drop
the zeroth iteration prior to any predicate-based filtering.

The filter predicate checks whether the window immediately below the
our focus is boring. If so, we've performed an uninteresting upwards
swap and should continue swapping until we either swap past a window
that is not boring or wrap around the top of the stack.

It's particularly important that we accept the wrapping case regardless
of any boring neighbor, otherwise we risk missing a legitimate
non-boring swap. Consider, for example, the following stack:

  focus: A
  up: []
  down: [B, boringC]

A swapUp yields:

  focus: A
  up: [boringC, B]
  down: []

This should be considered non-boring, since the non-boring windows
swapped order: A B -> B A. If we were to reject it, we'd swap A up past
boringC and up again past B, putting us back where we started.

Put another way, if our focus was at the top of the stack, then all
other windows were necessarily below it. We want a swapUp to place our
focus below the lowest non-boring window. A wrap around to the bottom of
the stack guarantees that is the case.
2020-09-10 06:39:47 -04:00
Brent Yorgey
58feba91d9 Merge pull request #375 from ivanbrennan/minimize-export
Minimize: export type constructor
2020-08-30 14:04:47 -05:00
ivanbrennan
6e162280b9 CHANGES: XMonad.Layout.Minimize export Minimize 2020-08-30 14:58:34 -04:00
ivanbrennan
1c97ca63c3 export Minimize type constructor
Some users like to include type signatures in their configuration. The
Minimize type constructor was not exported, making it impossible to
write a type signature when using minimize.

With this change, a user can write an xmonad.hs like:

  import XMonad
  import XMonad.Layout.Minimize (Minimize, minimize)
  import XMonad.Layout.LayoutModifier

  myLayout :: ModifiedLayout
              Minimize
              (Choose Tall (Choose (Mirror Tall) Full))
              Window
  myLayout = minimize $ layoutHook def

  main :: IO ()
  main = xmonad def { layoutHook = myLayout }
2020-08-30 14:54:39 -04:00
Brent Yorgey
2ad0c04447 Merge pull request #373 from TheMC47/xmobarBorder
Added xmobarBorder utility function to add borders to strings
2020-08-29 15:31:51 -05:00
Yecine Megdiche
40b939f7a6 typo 2020-08-29 20:26:49 +02:00
Yecine Megdiche
ab04e29e42 added xmobarBorder 2020-08-29 19:44:01 +02:00
Brent Yorgey
51bc4f8c2f Merge pull request #370 from felixonmars/patch-1
Depend on semigroups only on GHC < 8.0
2020-08-15 11:28:12 -05:00
Brent Yorgey
07717e5dea Merge pull request #368 from sam-barr/master
Export AvoidStruts constructor and doSink
2020-08-13 17:41:52 -05:00
Felix Yan
e61a408e9d Depend on semigroups only on GHC < 8.0
They are not needed on newer GHC.
2020-08-11 17:40:27 +08:00
sam-barr
c60d8fc29d Merge branch 'master' into master 2020-08-06 07:48:49 -05:00
Brent Yorgey
15dbfeff32 Merge pull request #365 from frozencemetery/xf86bluetooth
EZConfig: Learn about XF86Bluetooth
2020-08-06 07:00:59 -05:00
sam-barr
dcf5fad5f9 Expose internal state of AvoidStruts layout modifier
Updated Changes.md

Export doSink
2020-08-05 19:31:52 -05:00
Brent Yorgey
4a6bbb63b4 Merge pull request #367 from elkowar/fix/window-swallowing-bug
Fix rare issues with windows wrongly dissapearing after windowswallowing
2020-07-27 05:19:34 -05:00
elkowar
8059d4c38c Fix rare issues with windows wrongly dissapearing after windowswallowing 2020-07-27 11:50:16 +02:00
Geoff deRosenroll
c7afc2904b Add XMonad.Util.ClickableWorkspaces module (#364)
This module enables clickable workspace tags in XMobar in a relatively unobtrusive fashion.
Inspired by https://arch-ed.dk/xmobar-clickable-workspaces
2020-07-24 01:11:48 +02:00
Robbie Harwood
04ccc4d972 EZConfig: Learn about XF86Bluetooth 2020-07-22 16:14:38 -04:00
Brent Yorgey
3dc49721b6 Merge pull request #357 from elkowar/window_swallowing
Add XMonad.Hooks.WindowSwallowing
2020-06-23 09:05:23 -05:00
Brent Yorgey
4d6209e17a Merge pull request #360 from Xandaros/iss359
Export EZConfig parsers
2020-06-22 06:19:03 -05:00
Martin Zeller
abfeff5db7 Export EZConfig parsers 2020-06-22 13:01:48 +02:00
Leon Kowarschick
5869af1c56 Fix floating state not correctly being cleaned after swallowing and make handleEventHook take Query Bool rather than [Query Bool] 2020-06-21 11:54:40 +02:00
Leon Kowarschick
ba247afd0a Add XMonad.Hooks.WindowSwallowing 2020-06-20 14:00:54 +02:00
Brent Yorgey
e3632cb0b4 Merge pull request #355 from wz1000/zsh-prompt
Add XMonad.Prompt.Zsh
2020-06-19 18:02:19 -05:00
Brent Yorgey
9fa69a5603 Merge pull request #356 from elkowar/hidden_layout_pop_specific
Add restoreHiddenWindow function to XMonad.Layout.Hidden
2020-06-19 17:59:39 -05:00
Brent Yorgey
5c8ff36bcb Merge pull request #351 from elkowar/master
Make XMonad.Util.NamedScratchpad more flexible
2020-06-18 07:06:21 -05:00
Leon Kowarschick
65036457cc Add restoreHiddenWindow function to XMonad.Layout.Hidden, restoring a specific window 2020-06-13 15:01:25 +02:00
Zubin Duggal
8c39850dc0 Add XMonad.Prompt.Zsh 2020-06-13 04:07:09 +05:30
Leon Kowarschick
5f3edb110e Refactor someNamedScratchpadOption to use Data.NonEmpty and to improve readability 2020-06-06 14:55:31 +02:00
Brent Yorgey
8ba646aec6 Merge pull request #340 from igor04/max-magnifier-off
Add maxMagnifierOff to Magnifier layout
2020-06-05 15:38:59 -05:00
ElKowar
22fcf69e83 Add PR-template checkbox about updating XMonad.Doc.Extending (#353) 2020-06-03 20:33:57 +05:30
Leon Kowarschick
a861a8f954 Add more customizability to how scratchpads are initially started in XMonad.Util.NamedScratchpad 2020-06-03 10:35:28 +02:00
Brent Yorgey
24d2f26302 Merge pull request #344 from elkowar/master
add new XMonad.Actions.TiledWindowDragging module
2020-06-01 15:36:41 -05:00
Brent Yorgey
aa3f93afea Merge pull request #350 from davama/master
Add Ebay Function to X.A.Search
2020-06-01 14:25:50 -05:00
Dave
faf89612aa Update Search.hs
Add ebay function
2020-06-01 12:00:04 -04:00
Brent Yorgey
6c60740f7e Merge pull request #345 from mephory/master
X.U.DynamicScratchpads: Make any window a scratchpad
2020-05-30 07:17:48 -05:00
Brent Yorgey
4aa6f22899 Merge pull request #346 from psibi/338-no-encoding
Make spawnPipe to use system's locale encoding
2020-05-30 07:15:56 -05:00
Brent Yorgey
290d58dd9a Merge pull request #347 from psibi/update-stack-resolver
Update stack resolver
2020-05-30 07:14:31 -05:00
Sibi Prabakaran
89603c4a36 Update stack resolver 2020-05-29 22:28:33 +05:30
Sibi Prabakaran
b200d0c735 Update changelog 2020-05-29 22:25:34 +05:30
Sibi Prabakaran
1d0eaddc25 Make spawnPipe to use system's locale encoding
Add a function named spawnPipeWithNoEncoding for people who might want
to use binary handles.

Fixes https://github.com/xmonad/xmonad-contrib/issues/338
2020-05-29 22:21:38 +05:30
mephory
1fdfb4b8d0 X.U.DynamicScratchpads: added missing functions 2020-05-29 16:15:51 +02:00
mephory
ff0ab6f977 X.U.DynamicScratchpads: Make any window a scratchpad 2020-05-29 15:51:24 +02:00
Leon Kowarschick
b2446cd633 Adjust code style to match guidelines 2020-05-27 18:01:01 +02:00
Leon Kowarschick
365988774f include changes in CHANGES.md 2020-05-27 18:00:44 +02:00
Leon Kowarschick
08b54edbf9 add new XMonad.Layout.TiledWindowDragging module 2020-05-27 17:52:58 +02:00
Brent Yorgey
28e29fa238 Merge pull request #339 from samtay/three-column-resizable
Add ResizableThreeColumns layout
2020-05-23 13:45:46 -05:00
Sam Tay
0c642c3e9a Add ResizableThreeColumns layout
Based on ThreeColumns and ResizableTile
2020-05-18 14:18:36 -07:00
igor04
2149f0a07b Add maxMagnifierOff to Magnifier layout 2020-05-17 19:37:07 +03:00
Brent Yorgey
14faa12f69 Merge pull request #336 from ivanbrennan/hidden-windows-export
HiddenWindows: export type constructor
2020-05-14 14:46:43 -05:00
Brent Yorgey
d95dc14970 Merge pull request #335 from sam-barr/master
Add a doSink manage hook
2020-05-11 06:41:01 -05:00
Sibi Prabakaran
f8105131e1 Merge pull request #334 from psibi/spawn-functions
Add new variants of spawnPipe functions with encoding support
2020-05-09 19:44:55 +05:30
ivanbrennan
57936bf6d9 CHANGES: XMonad.Layout.Hidden export HiddenWindows 2020-05-03 13:33:42 -04:00
ivanbrennan
c201a9e33e export HiddenWindows type constructor
Some users like to include type signatures in their configuration. The
HiddenWindows type constructor was not exported, making it impossible to
write a type signature when using hiddenWindows.

With this change, a user can write an xmonad.hs like:

  import XMonad
  import XMonad.Layout.Hidden (HiddenWindows, hiddenWindows)
  import XMonad.Layout.LayoutModifier

  myLayout :: ModifiedLayout
              HiddenWindows
              (Choose Tall (Choose (Mirror Tall) Full))
              Window
  myLayout = hiddenWindows $ layoutHook def

  main :: IO ()
  main = xmonad def { layoutHook = myLayout }
2020-05-03 13:32:28 -04:00
sam-barr
dea927d887 Fix failing build 2020-04-29 20:29:07 -05:00
sam-barr
0eed434b0e Noted doSink in CHANGES.md 2020-04-29 20:18:18 -05:00
sam-barr
04625d0d04 added doSink ManageHook 2020-04-29 20:12:57 -05:00
Sibi Prabakaran
8b2bd3ae5c Add new variants of spawnPipe functions with encoding support
The current handle returned by `spawnPipe` doesn't have any encoding
and it uses the function fdToHandle which returns a Binary
Handle. When spawnPipe is used with a program like xmobar, this can
easily lead to errors:

λ> h <- spawnPipe "xmobar"
λ> hPutStrLn h
"\35753Haskell\25110\32773Ghci\33021\27491\30830\26174\31034\27721\23383\24182\19988\35835\21462\27721\23383\21629\21517\30340\25991\26723"
<stdin>: hGetLine: invalid argument (invalid byte sequence)

One workaround, to avoid this is to use `hSetEncoding`. But from
reading GHC's source code - the entire Handle and write operations
seems stateful. So doing something like hPutStr and hSetEncoding can
theoretically lead to an undefined state as the first write will use
latin encoding and the second write will use the new encoding. More
details about it are present here:

* http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.IO.Handle.Internals.html#writeCharBuffer
* http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.IO.Buffer.html#CharBuffer

So having these new functions will ensure that we get the handles in
the proper encoding in the first place.
2020-04-24 14:12:21 +05:30
Brent Yorgey
252e6e4d00 Merge pull request #333 from wz1000/master
Allow WindowPrompt to execute arbitrary actions with the window
2020-04-16 22:05:28 -05:00
Zubin Duggal
f7ed56fc6b Update changelog 2020-04-09 01:11:04 +05:30
Zubin Duggal
5880e01ad2 Add message to window prompt to execute arbitrary actions with the window 2020-04-09 01:06:20 +05:30
Brent Yorgey
5521b432dd Merge pull request #331 from ivanbrennan/toggle-recent-workspace
CycleRecentWS: add non-empty and toggle functionality
2020-03-08 17:52:58 -05:00
ivanbrennan
c48ddb08af CHANGES: additions to XMonad.Actions.CycleRecentWS 2020-03-06 08:31:55 -05:00
ivanbrennan
5aca3fb542 export recentWS
Allow consumers of this module to filter the recency list with a custom
predicate when cycling/toggling workspaces.
2020-03-06 08:31:55 -05:00
ivanbrennan
423d70593d refactor recentWS
Instead of constructing workspaces and rearranging it with tail and
head, construct it in the desired formation directly.
2020-03-05 09:13:14 -05:00
ivanbrennan
53a59d6592 cycleRecentNonEmptyWS, toggleRecentNonEmptyWS
Add non-empty variants to these workspace cycling/toggling functions.
2020-03-05 09:13:13 -05:00
ivanbrennan
dcf1f3e694 add toggleRecentWS
Add toggleRecentWS to switch to the most recent workspace, with repeated
use toggling between a pair of workspaces.
2020-03-05 09:13:13 -05:00
Brent Yorgey
1e3448fc53 Merge pull request #330 from slotThe/master
X.A.Search: Add promptSearchBrowser'
2020-02-14 17:59:10 -06:00
slotThe
eacd20ad00 Update CHANGES.md 2020-01-19 22:22:50 +01:00
slotThe
5493ff190d Add promptSearchBrowser' to further filter suggestions
Users may suggesting previous searches if and only if they came from the same
search engine more natural.
2020-01-19 22:08:48 +01:00
Brent Yorgey
a3afd6219d Merge pull request #328 from atondwal/master
X.L.MouseResizableTile borderWidth via focused win
2020-01-18 09:34:53 -06:00
Brent Yorgey
c4f64bc7d6 Merge pull request #326 from mrVanDalo/boring/broadcast
XMonad.Layout.BoringWindows: add markBoringEverywhere
2020-01-03 14:18:32 -06:00
Brent Yorgey
eb38b064a7 Merge pull request #324 from tidues/master
New Feature for TallMastersCombo: Switch between Focused Windows across All Sub-layouts
2020-01-03 14:15:46 -06:00
Brent Yorgey
fca0929876 Merge pull request #325 from jcpetruzza/prompt-searchPredicate-in-more-cases
Prompt: Use searchPredicate in more cases
2019-12-17 13:25:17 -06:00
Brent Yorgey
f1fc219732 Merge pull request #329 from josephcsible/patch-1
Use `drop 1` instead of reimplementing it in terms of `tail`
2019-12-15 20:59:50 -06:00
Joseph C. Sible
5860864e45 Use drop 1 instead of reimplementing it in terms of tail 2019-12-14 23:43:31 -05:00
Anish Tondwalkar
d6244a1069 X.L.MouseResizableTile borderWidth via focused win
When we calculate draggerGeometry, we should use the current width of
the border (if available), rather than the initial borderWidth.
2019-12-01 17:09:54 -08:00
Ingolf Wagner
1a3d58143e XMonad.Layout.BoringWindows: add markBoringEverywhere
to mark the currently focused window boring on all layouts,
when using XMonad.Actions.CopyWindow.
2019-11-21 17:42:01 +13:00
Daniel Gorin
28b3e34fd7 Prompt: Use searchPredicate in more cases
Prompts based on `mkComplFunList` and `mkComplFunList'` were not
taking into account the `searchPredicate` funtion from `XPConfig`.
This was rather confusing.

We fix it by passing `XPConfig` to these functions; although
this is strictly more than they need, it makes the breaking change very
easy to fix and is also more future-proof.
2019-11-18 20:13:40 +00:00
Brent Yorgey
52f8c82504 Merge pull request #109 from liskin/ewmh-fullscreen
X.H.EwmhDesktops: optionally advertise fullscreen support in _NET_SUPPORTED
2019-11-04 05:14:39 -06:00
tidues
3825c56e1d TallMastersCombo New Feature 2019-10-29 01:20:11 -04:00
brandon s allbery kf8nh
37a3d08d73 Merge pull request #323 from liskin/changes
CHANGES: Move stuff merged post-0.16 upwards
2019-10-16 10:32:21 -04:00
Tomas Janousek
d07f0a9ee4 X.L.Fullscreen: fullscreenSupport advertises fs support in _NET_SUPPORTED
Makes X.L.Fullscreen behave similarly to ewmhFullscreen. See the
X.H.EwmhDesktops commit for details.
2019-10-16 16:25:37 +02:00
Tomas Janousek
7bf8544f1c X.H.EwmhDesktops: optionally advertise fullscreen support in _NET_SUPPORTED
Provide a way to advertise _NET_WM_STATE_FULLSCREEN in _NET_SUPPORTED.
I had this hardcoded for a while but read the mpv manpage recently:

    Specifically, yes will force use of NetWM fullscreen support, even
    if not advertised by the WM. This can be useful for WMs that are
    broken on purpose, like XMonad. (XMonad supposedly doesn't advertise
    fullscreen support, because Flash uses it. Apparently, applications
    which want to use fullscreen anyway are supposed to either ignore
    the NetWM support hints, or provide a workaround. Shame on XMonad
    for deliberately breaking X protocols (as if X isn't bad enough
    already).

I'm not sure Flash is still a good reason these days to not advertise
fullscreen support yet still handle it and look like idiots while doing
so. (And if anyone thinks it is a good reason, their unchanged xmonad
config will continue behaving that way.)
2019-10-16 16:25:36 +02:00
Tomas Janousek
dc2b96d575 Use Graphics.X11.Xlib.Atom constants in invocations of changeProperty 2019-10-16 16:24:29 +02:00
Tomas Janousek
d8e496d3f0 CHANGES: Move stuff merged post-0.16 upwards 2019-10-16 16:21:29 +02:00
Brent Yorgey
a58c1a6071 Merge pull request #321 from slotThe/master
Remove redundant do's
2019-10-12 05:59:06 -05:00
slotThe
bcd4dde298 Remove redundant do's 2019-10-11 16:35:54 +02:00
Brent Yorgey
c3bb1cb2e7 Merge pull request #320 from slotThe/master
Remove legacy code regarding fmap
2019-10-09 05:07:15 -05:00
slotThe
30d45f8993 Clean up Control.Monad imports 2019-10-08 11:27:30 +02:00
slotThe
273ae32438 Replace 'join . fmap' with =<< 2019-10-08 11:19:09 +02:00
slotThe
22aebcb26d Replace 'fmap f $ fa' with 'f <$> fa', apply functor laws 2019-10-08 11:13:02 +02:00
slotThe
e8da66e575 Replace liftM with fmap 2019-10-08 10:45:44 +02:00
slotThe
0b26ddf489 Replace liftM2 with liftA2 2019-10-08 10:41:14 +02:00
slotThe
53b57eba14 Replace liftM and fmap with <$> 2019-10-08 10:33:56 +02:00
slotThe
f3024e6779 Remove unnecessary imports of Control.Applicative 2019-10-08 10:21:15 +02:00
Brent Yorgey
f98095d33e Merge pull request #311 from skewerr/master
Added module X.A.PerWindowKeys
2019-10-07 10:45:29 -05:00
Brent Yorgey
809ba2a8c0 Merge pull request #310 from psibi/named-window
Added 'allApplications' to XMonad.Prompt.Window
2019-10-06 20:35:09 -05:00
Sibi Prabakaran
a8d41df92b Added allApplications to XMonad.Prompt.Window 2019-10-06 10:06:02 +05:30
Brent Yorgey
7100e7db4f Merge pull request #315 from tidues/master
A New Layout Combinator: TallMastersCombo
2019-10-05 17:52:18 -05:00
Brent Yorgey
6040fe6c8f Merge pull request #318 from slotThe/master
X.A.Search: Update hoogle URL
2019-10-05 08:05:44 -05:00
Brent Yorgey
b87e801872 Merge pull request #317 from budevg/fix-spelling-mistake
XMonad/Actions/Search: fix spelling mistake
2019-10-05 08:05:10 -05:00
slotThe
48e6bb5529 X.A.Search: Update hoogle URL 2019-10-05 10:30:50 +02:00
Evgeny Budilovsky
3c7d58b836 XMonad/Actions/Search: fix spelling mistake 2019-10-05 09:11:38 +03:00
Wilson Sales
6eae27390d Added module X.A.PerWindowKeys
Allows one to shortcut actions that are performed based on queries.

Signed-off-by: Wilson Sales <spoonm@spoonm.org>
2019-09-30 21:21:46 -03:00
tidues
b43fdcb57f edit CHANGES.md 2019-09-27 16:57:50 -04:00
tidues
599c0f8613 XMonad.Layout.TallMastersCombo v1.0 2019-09-27 16:43:04 -04:00
tidues
6da250003f XMonad.Layout.TallMastersCombo v1.0 2019-09-27 16:36:30 -04:00
Peter Simons
60101b9a70 Bump version number to 0.16 for the upcoming release. 2019-09-22 10:33:26 +02:00
Peter Simons
5f1fc602ab CHANGES.md: document changes from 303f0c24bc 2019-09-22 10:11:10 +02:00
Peter Simons
303f0c24bc cabal.project: the new setlocale version works fine 2019-09-22 10:02:29 +02:00
Peter Simons
8df80e7805 travis.yml: re-generate with the latest version of haskell-ci 2019-09-21 21:10:12 +02:00
Peter Simons
36dba39c44 cabal.project: don't hard-code paths to ../xmonad and ../x11
Not everyone has those repositories checked out at those paths. IMHO, it would
be much better to configure these as "optional-packages". In any case, users
should probably configure those in their cabal.project.local.
2019-09-21 21:07:56 +02:00
Peter Simons
8847b3b2f6 cabal.project: configure allower-newer for setlocale
This allows us to compile with GHC 8.8.1.
2019-09-21 21:03:13 +02:00
Peter Simons
1b061245af xmonad-contrib.cabal: update our tested-with declaration 2019-09-21 21:03:13 +02:00
Peter Simons
94662bffc6 XMonad.Util.Invisible: fix build with GHC 8.8.1
This change needs base-4.9.0.0 or later so that we can
include Control.Monad.Fail. We could jump through hoops to
support older compilers still, but it feels like it's not
worthwhile.
2019-09-21 21:03:13 +02:00
Brent Yorgey
23102a6d5c Merge pull request #289 from berkeleyinc/improved-left-right-tabbed
Improved tabbedRight and tabbedLeft in XMonad.Layout.Tabbed
2019-09-16 16:47:28 -05:00
Brent Yorgey
728f9bc270 Merge pull request #299 from pkinsky/master
Add configurable border width fields to XMonad.Layout.Decoration.Theme
2019-08-12 08:32:22 -05:00
Brent Yorgey
d9856b955a Merge pull request #303 from obszczymucha/master
Add SplitShiftDirectional message into BinarySpacePartition layout.
2019-08-12 07:22:52 -05:00
Brent Yorgey
603fc4ccb7 Merge branch 'master' into master 2019-08-12 07:22:39 -05:00
Brent Yorgey
65e7153874 Merge pull request #309 from ryantrinkle/pass-generate-and-copy
Add XMonad.Prompt.Pass.passGenerateAndCopy
2019-08-10 16:45:14 -05:00
Ryan Trinkle
6a0dc1685c Add XMonad.Prompt.Pass.passGenerateAndCopy 2019-08-10 10:25:34 -04:00
Brent Yorgey
41e8708eb5 Merge pull request #308 from kurnevsky/fuzzy-sort
Make fuzzy sort show shorter strings first
2019-08-08 21:45:23 -05:00
Evgeny Kurnevsky
18979de5f6 Make fuzzy sort show shorter strings first. 2019-08-08 09:12:48 +03:00
Brent Yorgey
5ffb4e7f52 Merge pull request #307 from ryantrinkle/pass-traverse-symlinks
Make XMonad.Prompt.Pass traverse symlinks for its tab completion
2019-08-07 22:22:27 -05:00
Ryan Trinkle
52a3800b96 Make XMonad.Prompt.Pass traverse symlinks for its tab completion 2019-08-07 13:09:40 -04:00
Brent Yorgey
dd89eae446 Merge pull request #300 from roosemberth/refocuslast
RefocusLast Module
2019-05-26 20:32:30 -05:00
Obszczymucha
6b68ec5c00 Add SplitShiftDirectional message into BinarySpacePartition layout. 2019-05-26 16:01:06 +10:00
Sibi
db80842e65 Merge pull request #301 from h-jones-uk/master
Fix broken internal Haddock links
2019-05-08 21:04:13 +05:30
Henri Jones
4e4856c722 Fix broken internal Haddock links 2019-05-07 22:32:05 +01:00
Roosembert Palacios
b5eb418fa4 cabal: Export module XMonad.Hooks.RefocusLast
Signed-off-by: Roosembert Palacios <roosembert.palacios@epfl.ch>
2019-05-01 23:53:38 +02:00
L. S. Leary
04b32ae021 X.H.RefocusLast: added action to swap current window with last + minor refactoring. 2019-05-01 23:53:07 +02:00
L. S. Leary
9c6d1e696f X.H.RefocusLast: added runtime toggle and refactored predicate system. 2019-05-01 16:56:44 +02:00
L. S. Leary
dad911913c RefocusLast bug fix, extension to support float-only refocusing and
improved support for refocusing on non-current workspaces.
2019-05-01 16:56:39 +02:00
Paul Kinsky
b3f5a09673 record changes 2019-04-17 16:40:48 -07:00
Brent Yorgey
4ad6ecf892 Merge pull request #297 from ajgrf/bg-ratio
Hooks.WallpaperSetter: Preserve aspect ratio while scaling images
2019-04-10 22:07:22 -05:00
Brent Yorgey
fcd296e87a Merge branch 'master' into bg-ratio 2019-04-10 22:07:06 -05:00
Brent Yorgey
fddd5ea1fe Merge pull request #298 from orhan89/pass-otp
Support OTP in XMonad.Prompt.Pass
2019-04-05 04:44:09 -05:00
Ricky Hariady
c3cee11ad6 Support OTP in XMonad.Prompt.Pass
update CHANGES.md
2019-04-05 09:31:49 +07:00
Brent Yorgey
22e6d4b017 Merge pull request #296 from ajgrf/adwaita-theme
XMonad.Util.Themes: Add adwaitaTheme and adwaitaDarkTheme
2019-04-02 05:50:26 -05:00
Alex Griffin
fcced8991a Hooks.WallpaperSetter: Preserve aspect ratio while scaling images 2019-03-18 16:32:35 -05:00
Alex Griffin
bfb52a5025 XMonad.Util.Themes: Add adwaitaTheme and adwaitaDarkTheme 2019-03-13 14:48:10 -05:00
Brent Yorgey
c53436f3a6 Merge pull request #178 from bforte/module-MutexScratchpads
add new module X.U.ExclusiveScratchpads
2019-03-06 15:14:51 -06:00
Brent Yorgey
66c1977c29 Merge branch 'master' into module-MutexScratchpads 2019-03-06 15:14:27 -06:00
Brent Yorgey
a18395a13c Merge pull request #295 from alhirzel/add-isOnAnyVisibleWS
Actions.GroupNavigation: fix bad import
2019-03-03 21:15:56 -06:00
Alex Hirzel
ca69574cfe Actions.GroupNavigation: add CMS import 2019-03-03 10:59:58 -05:00
Alex Hirzel
faa252e309 Actions.GroupNavigation: another import issue 2019-03-03 10:20:22 -05:00
Alex Hirzel
71fec4f61a Actions.GroupNavigation: fix bad import 2019-03-03 10:08:25 -05:00
Brent Yorgey
0301d6e21b Merge pull request #294 from alhirzel/add-isOnAnyVisibleWS
Add isOnAnyVisibleWS function to Actions.GroupNavigation
2019-03-03 08:57:04 -06:00
Alex Hirzel
0cfe3a288e whitespace reformat in changelog 2019-03-02 09:36:47 -05:00
Alex Hirzel
84c63abda6 Add changelog entry for isOnAnyVisibleWS 2019-03-02 09:36:36 -05:00
Alex Hirzel
e12511c658 Actions.GroupNavigation: move "Utilities" header for documentation 2019-03-02 09:32:16 -05:00
Alex Hirzel
52890f6007 Actions.GroupNavigation: document isOnAnyVisibleWS 2019-02-27 23:08:07 -05:00
Alex Hirzel
51bc32ea75 Actions.GroupNavigation: add isOnAnyVisibleWS 2019-02-27 23:08:07 -05:00
Alex Hirzel
cce7f50372 Actions.GroupNavigation: hlint fixes 2019-02-27 23:08:04 -05:00
Brent Yorgey
ba9b108a68 Merge pull request #263 from bgamari/ewmh-wakeup-reduction
Wakeup reduction in EwmhDesktops
2019-02-27 21:21:37 -06:00
Brent Yorgey
e12c047870 move change from #284 to the right place 2019-02-13 05:54:03 -06:00
Brent Yorgey
2ce876c330 Merge pull request #284 from skewerr/master
X.A.DynamicWorkspaceOrder: add transformation-aware withNthWorkspace
2019-02-13 05:49:42 -06:00
Brent Yorgey
3faa9b2c38 Merge pull request #292 from wz1000/master
Use absolute paths in DynamicProjects
2019-02-13 05:40:18 -06:00
Zubin Duggal
6720eefce7 update CHANGES.md 2019-02-13 16:19:01 +05:30
Zubin Duggal
cf789504e8 Use absolute paths in DynamicProjects 2019-02-13 16:06:10 +05:30
Brent Yorgey
deaaf6b177 Merge pull request #287 from mgsloan/bracket-prompt-resources
Use bracket pattern in XMonad.Prompt
2019-02-12 09:14:02 -06:00
Brent Yorgey
60b35ff431 Merge branch 'master' into bracket-prompt-resources 2019-02-12 09:13:51 -06:00
Brent Yorgey
cd404eb644 Merge pull request #291 from mgsloan/fix-prompt-max-rows-wrap-around-217
Fix XMonad.Prompt wraparound when maxComplRows not Nothing #217
2019-02-12 09:08:23 -06:00
Michael Sloan
d9f43c78d6 Fix XMonad.Prompt wraparound when maxComplRows not Nothing #217 2019-02-10 04:47:16 -08:00
Michael Sloan
b9603a0e10 Also destroy completion window on exceptions #180 2019-02-10 04:18:56 -08:00
Michael Sloan
09a5fa111c Use bracket pattern in XMonad.Prompt 2019-02-10 04:18:30 -08:00
Michael Sloan
41a2db5563 Refactoring: helper for mkXPromptWithReturn and mkXPromptWithModes 2019-02-10 03:51:40 -08:00
Yclept Nemo
1706160b14 Merge pull request #245 from orbisvicis/vimishPrompt
Vimish Prompt
2019-01-26 16:23:49 -05:00
Yclept Nemo
207d5962e2 Vim for 'XMonad.Prompt': backwards compatibility
Colors in 'XPState' continue to use 'XPColor' since it provides a
cleaner interface. For backwards compatibility color changes to
'XPConfig' were reverted. To avoid accessor clashes you'll have to deal
with slightly different names:

| 'XPState'/'XPColor' | 'XPConfig'  |
| ------------------- | ----------- |
| bgNormal            | bgColor     |
| fgNormal            | fgColor     |
| bgHighlight         | bgHLight    |
| fgHighlight         | fgHLight    |
| border              | borderColor |
2019-01-26 15:18:27 -05:00
Yclept Nemo
c7e02726bf Vim for 'XMonad.Prompt': advertise changes 2019-01-26 15:03:18 -05:00
Yclept Nemo
b0d6e0f942 Vim for 'XMonad.Prompt':
A vim-like keymap, yay! And dynamic colors and a reworked event loop.
Also fixes 'showCompletionOnTab' which was broken, and many new or
improved prompt interface functions.

Changes moveWord/moveWord' but updates the old keymaps to retain the
original behavior. See the documentation to do the same to your XMonad
configuration.

P.S. That bug I mention was there before my changes.
2019-01-26 14:49:52 -05:00
Brent Yorgey
a774168415 Merge pull request #264 from namo626/module/TwoPanePersistent
Added module X.L.TwoPanePersistent
2019-01-22 11:15:36 -06:00
Brent Yorgey
17da8bc8ee Merge pull request #259 from u11gh/passEditPrompt
Add passEditPrompt to Xmonad.Prompt.Pass
2019-01-21 16:49:38 -06:00
Brent Yorgey
c2c0585d7e Merge branch 'master' into module/TwoPanePersistent 2019-01-21 11:03:26 -06:00
yuri
7a6d24712f Merge branch 'improved-left-right-tabbed' of github.com:berkeleyinc/xmonad-contrib into improved-left-right-tabbed 2019-01-09 07:42:58 +01:00
yuri
13260cae58 Merge branch 'improved-left-right-tabbed' of github.com:berkeleyinc/xmonad-contrib into improved-left-right-tabbed 2019-01-09 07:42:46 +01:00
yuri
07f4ce8029 Merge branch 'improved-left-right-tabbed' of github.com:berkeleyinc/xmonad-contrib into improved-left-right-tabbed 2019-01-09 07:41:49 +01:00
yuri
298cdd6114 improving tabbedRight/tabbedLeft by having their tabs' height set by decoHeight 2019-01-09 07:41:10 +01:00
yuri
36356dd8f5 improving tabbedRight/tabbedLeft by having their tabs' height set by decoHeight 2019-01-09 07:37:03 +01:00
Wilson Sales
dd905d2603 X.A.DynamicWorkspaceOrder: add transformation-aware withNthWorkspace
The user may modify the list of workspace tags that results form
applying the dynamic order. This way one may filter workspaces they
don't want in the order (e.g. "NSP") or apply any transformation he
wishes to the list of tags.
2018-11-08 19:02:59 -02:00
L. S. Leary
dda242a459 Relocate change in CHANGES.md. 2018-10-18 05:49:30 +13:00
Leary
204524328d Merge pull request #282 from anthraxx/fixup/prompt-fuzzymatch
XMonad.Prompt sorter for FuzzyMatch
2018-10-18 05:36:51 +13:00
Peter Simons
81a980823e Bump version number and update the changelog. 2018-09-30 13:38:33 +02:00
Peter Simons
677e64dcf6 travis.yml: enable builds with ghc 8.6.1 2018-09-28 11:50:27 +02:00
Peter Simons
c5c3fec26c inhale: avoid monadic pattern matching in pure code
These changes avoid the need for having a MonadFail instance for Decoder.
2018-09-28 11:47:11 +02:00
Peter Simons
59fbcdfba9 dumpExcept: avoid monadic pattern matching in pure code
These changes avoid the need for having a MonadFail instance for Decoder.
2018-09-28 11:46:33 +02:00
Peter Simons
778e32305f dumpString: avoid monadic pattern matching in pure code
These changes avoid the need for having a MonadFail instance for Decoder.
2018-09-28 11:45:39 +02:00
Peter Simons
5334130bf7 historyCompletion: prefer Data.Map.foldr over deprecated fold function 2018-09-28 11:44:49 +02:00
Peter Simons
aca76956ba xmonad-contrib.cabal: support containers-0.6 from ghc-8.6.x
The build works fine with the new version.
2018-09-27 16:01:43 +02:00
anthraxx
6dcc36c904 XMonad.Prompt.FuzzyMatch: favor modern windowPrompt in docs
Use modern windowPrompt in docs instead of the deprecated
windowPromptGoto.
2018-09-25 22:16:06 +02:00
anthraxx
705494eb4c XMonad.Prompt.FuzzyMatch: fix missing docs code block 2018-09-25 22:16:06 +02:00
Sergey Alirzaev
6b9fb096d6 employ the prompt sorter for the window selector
as in https://markmail.org/thread/kgrybzqarqzqiige
2018-09-25 22:15:45 +02:00
L. S. Leary
02278e5bbb Merge pull request #281 from LSLeary/purex. 2018-09-26 01:57:04 +12:00
L. S. Leary
4dcc78b59e Added the X.U.PureX module and generalised type signatures in
`X.U.ExtensibleState`.
2018-09-19 02:35:55 +12:00
L. S. Leary
e7c92bc628 Merge pull request #276 from LSLeary/groups. 2018-09-16 16:22:49 +12:00
L. S. Leary
dba402aba4 X.L.G.Helpers: replace (deprecated) send with sendMessageB as we
may now need the refresh it can perform.
2018-09-16 13:52:43 +12:00
L. S. Leary
8ea584cdb9 X.L.Groups:
* Rewrite the `refocus` function such that it modifies the windowset
   without performing a refresh, instead returning the given layout
   object when one is required.
 * Message handling which uses `refocus` has been rewritten to less
   frequently request unnecessary refreshes.
2018-09-16 13:52:43 +12:00
L. S. Leary
6ea4ee8fbd X.A.MessageFeedback: update manual Message handlers following
changes to `X.O.sendMessage`.
2018-09-16 13:52:43 +12:00
L. S. Leary
f1c7b09656 Core xmonad currently does not build against sub-8 GHC; exclude from travis. 2018-09-16 13:50:38 +12:00
Brent Yorgey
13e5429dc2 Merge pull request #279 from orbisvicis/fullscreenFix
X.L.Fullscreen: 'FullscreenFull' hides all windows
2018-09-11 05:56:11 -05:00
Yclept Nemo
8ec1efd472 X.L.Fullscreen: 'FullscreenFull' hides all windows
The 'FullscreenFull' layout modifier hides all windows fully covered by
the fullscreen area, even when no fullscreen windows are present. Fix
this, closing #278. Also switch to 'X.U.Rectangle'.
2018-09-05 07:47:25 -04:00
Peter Simons
337ca60f76 Merge pull request #277 from NickHu/patch-1
Typo in PhysicalScreens.hs
2018-08-08 15:09:27 +02:00
Nick Hu
62d161ca4e Typo in PhysicalScreens.hs
The documentation has a typo so copying and pasting the example does not work.
2018-08-08 16:53:44 +09:00
Peter Simons
16836b6f91 Merge pull request #275 from LSLeary/point14
0.14
2018-07-31 09:54:42 +02:00
L. S. Leary
065c305fed version bump to 0.14 2018-07-30 23:44:56 +12:00
L. S. Leary
9a80f2d891 Clean up CHANGES.md:
* 0.14 (Not Yet) -> 0.14
 * Removed reverted changes left over from #128 & #161
 * Fixed some typos
 * Made markup more consistent.
2018-07-30 23:44:56 +12:00
LSLeary
a1111a3418 Merge pull request #274 from LSLeary/travis 2018-07-30 23:43:49 +12:00
L. S. Leary
fdc3f78588 Drop GHC 7.6 compatibility. 2018-07-30 22:50:03 +12:00
L. S. Leary
259c170ac9 Travis-CI:
* don't constrain to precise
 * add libxrandr dependency
 * test against new GHC versions
 * install xmonad from git before cabal can install it from hackage
2018-07-30 22:50:03 +12:00
L. S. Leary
4f23016e54 GHC 7.8 compatibility:
* Explicitly import pure, (<$>), (<*>) and (<$) from Control.Applicative.
 * Use DeriveDataTypeable pragma.
 * Remove type signature from pattern synonym.
2018-07-30 22:50:03 +12:00
LSLeary
4ec78aa3f2 Merge pull request #273 from orbisvicis/reSpaced
reSpaced: Compatibility v2
2018-07-30 22:12:55 +12:00
L. S. Leary
ea39960bd4 Merge pull request #261 from orbisvicis/messaging 2018-07-30 22:05:48 +12:00
L. S. Leary
d015416573 Revert "Merge pull request #256 from LSLeary/refocuslast"
This reverts commit b0f9197e04, reversing
changes made to 6b8a8f9c8d.

Not for 0.14.
2018-07-30 16:53:44 +12:00
Brent Yorgey
c90241807a Merge pull request #269 from MichielDerhaeg/belgianKeys
add support for belgian keyboards in XMonad.Config.Azerty
2018-07-27 11:40:50 -05:00
Brent Yorgey
0731407537 Merge pull request #270 from lucianposton/doc
X.L.MultiToggle: Doc improvement
2018-07-27 11:39:01 -05:00
Brent Yorgey
a6a69394be Merge pull request #271 from lucianposton/tbf
Add the X.L.MultiToggle.TabBarDecoration module
2018-07-27 11:38:35 -05:00
Brent Yorgey
0fb36d418b Merge pull request #272 from lucianposton/darktheme
X.U.Themes: Add darkTheme
2018-07-27 11:37:19 -05:00
Yclept Nemo
3e68036360 XMonad.Layout.Spacing: extreme compatibility
* Reintroduce the original 'ModifySpacing' type and constructor as
  deprecated; the new 'ModifySpacing' type was renamed to
  'SpacingModifier'. Suggested by @LSLeary.
* Types 'SpacingWithEdge', 'SmartSpacing', and 'SmartSpacingWithEdge'
  have been reintroduced as deprecated type synonyms of 'Spacing'. Work
  by @LSLeary.

Also 'borderMap' is now exported; it might be useful.
2018-07-19 15:06:35 -04:00
Lucian Poston
8109a605fd X.U.Themes: Add darkTheme 2018-07-17 19:17:45 -07:00
Lucian Poston
048bb42e7a Add the X.L.MultiToggle.TabBarDecoration module 2018-07-16 19:51:14 -07:00
Lucian Poston
b9ef1649b0 X.L.MultiToggle: Doc improvement 2018-07-15 17:18:12 -07:00
LSLeary
a4b430bfa7 Merge pull request #266 from LSLeary/master
Fix to X.L.Grid as per issue #223
2018-07-09 05:34:45 +12:00
Michiel Derhaeg
d0e283d175 add support for belgian keyboards in XMonad.Config.Azerty 2018-07-05 22:22:28 +02:00
L.S. Leary
90e54a9abb Fix to X.L.Grid as per issue #223; it will no longer calculate more columns than there are windows. 2018-07-02 18:20:13 +12:00
namo626
913183463a added module X.L.TwoPanePersistent
updated CHANGES.md
2018-06-22 18:40:14 -04:00
Ben Gamari
92fe5f34ff EwmhDesktops: Cache properties independently 2018-06-19 12:39:24 -04:00
Ben Gamari
8c309f87b8 EwmhDesktops: Cache active window as well 2018-06-19 11:54:20 -04:00
Ben Gamari
f6f925c823 Use extensible state instead of IORef 2018-06-19 11:54:18 -04:00
Ben Gamari
203e63b055 EwmhDesktops: Only update properties when something changed 2018-06-19 10:03:20 -04:00
Ben Gamari
e814f748b5 EwmhDesktops: Cache property values to avoid needless property changes 2018-06-19 01:47:08 -04:00
Yclept Nemo
9fcea6cb55 Merge pull request #252 from orbisvicis/swapPromote
Swap Promote
2018-06-15 12:29:14 -04:00
Yclept Nemo
7e54a9d90b 'XMonad.Actions.SwapPromote': advertise changes...
... and expose the new module.
2018-06-15 12:26:28 -04:00
Yclept Nemo
66281f07f1 'XMonad.Actions.SwapPromote': 'stackMerge' fixes
Make 'stackMerge' safer by implicitly appending any leftover elements
rather than discarding them. Otherwise on refresh the missing windows
will be deleted. This is only necessary if the stack has been shortened
- i.e. not required by this module.

Minor miscellaneous documentation fixes.
2018-06-15 12:26:28 -04:00
Yclept Nemo
56a76df88f 'XMonad.Actions.SwapPromote': new module
Module for tracking master window history per workspace, and associated
functions for manipulating the stack using such history.
2018-06-15 12:26:28 -04:00
Yclept Nemo
b6a09f5d80 Merge pull request #242 from orbisvicis/borderControl
Border Control
2018-06-15 12:19:07 -04:00
Yclept Nemo
2fde742e7a 'XMonad.Layout.Spacing': compatibility tweaks
* All the backwards-compatibility functions now accept `Int` rather than
  `Integer`: `spacing`, `spacingWithEdge`, `smartSpacing`,
  `smartSpacingWithEdge`, `setSpacing`, and `incSpacing`. Work done by
  @LSLeary.
* Introduce the new functions `setScreenWindowSpacing`,
  `incScreenWindowSpacing`, `decScreenWindowSpacing`. Unlike their
  original `setSpacing`, `incSpacing` counterparts, these refresh no
  more than once. Requires `sendMessages` from my PR of
  `XMonad.Actions.MessageFeedback`. Suggestion by @LSLeary and
  implemented so any combination of messages can be sent without
  triggering unnecessary refreshes.
2018-06-14 13:10:19 -04:00
Yclept Nemo
8ee2e39fb2 'XMonad.Actions.MessageFeedback': standardize
- Follow the naming conventions of `XMonad.Operations`. Functions returning
  `X ()` are named regularly (previously these ended in underscore) while
  those returning `X Bool` are suffixed with an uppercase 'B'.

- Provide all `X Bool` and `SomeMessage` variations for `sendMessage` and
  `sendMessageWithNoRefresh`, not just `sendMessageWithNoRefreshToCurrent`
  (renamed from `send`).

- The new `tryInOrderB` and `tryMessageB` functions accept a parameter of
  type `SomeMessage -> X Bool`, which means you are no longer constrained
  to the behavior of the `sendMessageWithNoRefreshToCurrent` dispatcher.

- The `send*Messages*` family of funtions allows for sequencing arbitrary
  sets of messages with minimal refresh. It makes little sense for these
  functions to support custom message dispatchers.

- Remain backwards compatible. Maintain deprecated aliases of all renamed
  functions:
  - `send`          -> `sendMessageWithNoRefreshToCurrentB`
  - `sendSM`        -> `sendSomeMessageWithNoRefreshToCurrentB`
  - `sendSM_`       -> `sendSomeMessageWithNoRefreshToCurrent`
  - `tryInOrder`    -> `tryInOrderWithNoRefreshToCurrentB`
  - `tryInOrder_`   -> `tryInOrderWithNoRefreshToCurrent`
  - `tryMessage`    -> `tryMessageWithNoRefreshToCurrentB`
  - `tryMessage_`   -> `tryMessageWithNoRefreshToCurrent`
2018-06-13 15:26:18 -04:00
Yclept Nemo
9d342cddb7 'XMonad.Layout.NoBorders': document upgrade path
Document upgrade path for 'hiddens', which added a 'Rectangle'
parameter.
2018-06-10 19:45:17 -04:00
Yclept Nemo
0c1a6c25f6 'XMonad.Layout.NoBorders': advertise changes 2018-06-10 18:12:21 -04:00
Yclept Nemo
c6cdb77e3b 'XMonad.Layout.NoBorders': various improvements:
The layout now maintains a list of windows that never have borders, and
a list of windows that always have borders. Use 'BorderMessage' to
manage these lists and the accompanying event hook ('borderEventHook')
to remove destroyed windows from them. Also provides the 'hasBorder'
manage hook.

Two new conditions have been added to 'Ambiguity': 'OnlyLayoutFloat' and
'OnlyLayoutFloatBelow'; 'OnlyFloat' was renamed to 'OnlyScreenFloat'.
See the documentation for more information.
2018-06-10 18:06:00 -04:00
Brent Yorgey
e0b1954e62 Merge pull request #254 from mimi1vx/patch-1
Allow build with X11-1.9
2018-06-09 07:43:49 -05:00
Brent Yorgey
178ec86cc6 Merge pull request #257 from skewerr/master
Added two actions to X.A.DynamicWorkspaceOrder
2018-06-09 07:37:38 -05:00
Brent Yorgey
b0f9197e04 Merge pull request #256 from LSLeary/refocuslast
RefocusLast
2018-06-09 07:34:22 -05:00
L. S. Leary
d7461c037e Added the X.H.RefocusLast module. 2018-06-06 18:43:28 +12:00
Ulf Jasper
ed32ccd080 Add passEditPrompt to Xmonad.Prompt.Pass 2018-06-05 19:34:06 +02:00
Brent Yorgey
6b8a8f9c8d add X.U.Rectangle to exposed-modules 2018-06-04 14:28:33 -05:00
Brent Yorgey
cfe7a90d4a Merge pull request #244 from orbisvicis/rectangle
Rectangle
2018-06-04 14:27:59 -05:00
Brent Yorgey
44306eb0ab Merge branch 'master' into rectangle 2018-06-04 14:27:11 -05:00
Brent Yorgey
18eb79ce73 add X.L.BinaryColumn to exposed-modules
Also fix typo in CHANGES.md. See #233.
2018-06-04 14:24:18 -05:00
Brent Yorgey
3f54045af2 Merge pull request #253 from LSLeary/statefull
StateFull: Fixing Full (and other layouts we lie to)
2018-06-04 14:18:31 -05:00
Brent Yorgey
22345dce9f Merge pull request #248 from jktomer/master
Fullscreen.hs: don't lay out windows obscured by fullscreen
2018-06-04 14:12:28 -05:00
Brent Yorgey
bc63ff3f0d Merge pull request #243 from orbisvicis/reSpaced
reSpaced
2018-06-04 13:59:33 -05:00
Brent Yorgey
83e421c495 Merge branch 'master' into reSpaced 2018-06-04 13:59:21 -05:00
L. S. Leary
c4c007806c Added the X.L.StateFull module providing the StateFull layout and the FocusTracking layout transformer. 2018-05-29 22:58:51 +12:00
spoonm
635a9dee4c Added updateName and removeName to X.A.DynamicWorkspaceOrder
This adds the possibility to maintain the ordering of workspaces after
they are renamed and to remove them from sorting when they are deleted.
2018-05-21 16:22:52 -03:00
L. S. Leary
0cd4690f9b Added findS/Z and reverseS/Z to X.U.Stack. 2018-05-18 11:04:09 +12:00
Brent Yorgey
d3d0818e9b Merge pull request #246 from orbisvicis/xmobar
Xmobar
2018-05-17 16:47:19 -05:00
Ondřej Súkup
d3ae0eeac2 Allow build with X11-1.9 2018-05-15 13:02:38 +02:00
Brent Yorgey
295adf056e Merge pull request #250 from LSLeary/master
X.P.FuzzyMatch: Relocate imports so that haddock generation succeeds.
2018-05-08 21:33:09 -05:00
L. S. Leary
56f7b3acb3 X.P.FuzzyMatch: Relocate imports so that haddock generation succeeds. 2018-05-08 03:29:46 +12:00
Brent Yorgey
9a68684ec1 Merge pull request #233 from ideasman42/layout-binary-column
Add BinaryColumn layout
2018-05-07 06:02:28 -05:00
Brent Yorgey
54ee8933ee Merge pull request #241 from miguelclean/master
Added pretty printer for empty visible workspaces (wrapped in Maybe)
2018-04-24 15:58:13 -05:00
jktomer
d338e11110 Fullscreen.hs: don't lay out windows obscured by fullscreen
There's no reason to return a rectangle for any window that is totally
obscured by a full-screen window, and not doing so has the nice property that
when hidden windows' borders overlap with a full-screen window's, the user
will not be confused by overlapping partially-drawn borders. It also makes the
Fullscreen modifiers combine much better with smartBorders.
2018-04-24 07:06:23 -07:00
Brent Yorgey
09426e9d71 Merge pull request #239 from marcsaegesser/SpawnOnceEnhancements
Add spawnOnOnce and related functions.
2018-04-21 11:47:21 -05:00
Yclept Nemo
2c53d507ee 'XMonad.Layout.Spacing': backwards compatibility 2018-04-21 11:43:53 -04:00
Yclept Nemo
19a020837d 'XMonad.Layout.Spacing': advertise changes 2018-04-20 12:55:08 -04:00
Yclept Nemo
fdccc873de 'XMonad.Layout.Spacing': the finished product.
Both screen and window borders can now be disabled. Implement missing
messages. The layout now handles windows that are displayed but not part
of the stack, such as those created by 'XMonad.Layout.Decoration'.
Several additional fixes.
2018-04-20 12:55:08 -04:00
Yclept Nemo
f1ed0a5edb 'Layout.Spacing': Improve the smart screen border:
The 'smartBorder' now depends on the window/rectangle list resulting
from 'runLayout' rather than the stack, which means that the child
layout will always be called with the screen border. If only a single
window is displayed, it will be expanded into the original layout
rectangle.
2018-04-20 12:55:08 -04:00
Yclept Nemo
6ae7c2c8b4 Rewrite of 'XMonad.Layout.Spacing':
* Independent screen/window borders
* Configurable top/bottom/right/left borders
2018-04-20 12:55:08 -04:00
Yclept Nemo
108431d03d 'XMonad.Util.Rectangle': advertise changes 2018-04-20 12:54:09 -04:00
Yclept Nemo
31bfcc217f 'XMonad.Util.Rectangle': 'withBorder' fixes
Fix handling of negative borders in 'withBorder'.
2018-04-20 12:54:09 -04:00
Yclept Nemo
cc00a93f1a 'XMonad.Util.Rectangle': new module
A new module for handling pixel rectangles.
2018-04-20 12:54:09 -04:00
Yclept Nemo
26d6bde9c3 'XMonad.Hooks.DynamicLog': advertise changes 2018-04-20 12:52:22 -04:00
Yclept Nemo
348861da00 'XMonad.Hooks.DynamicLog': xmobar tags
Support xmobar's <action> and <raw> tags.
2018-04-20 12:52:22 -04:00
Miguel
670eb3bc60 Added pretty printer for empty visible workspaces
Simple extensions of the pretty printer to differentiate between empty
and non-empty visible workspaces. Analogical to the existing
functionality for hidden workspaces. Particularly useful if some
displays managed by xmonad are turned off temporarily.

The new 'ppVisibleNoWindows' function was wrapped in a Maybe data type.
Its value dafaults to 'Nothing' and 'ppVisible' is used as fallback.
2018-04-18 11:36:46 +02:00
Campbell Barton
869311090c Correct docs 2018-04-11 07:58:11 +02:00
Brent Yorgey
5f2afb08e9 Merge pull request #240 from ae-g-i-s/more-dzen-options
Implement additional options for Dzen
2018-04-10 23:08:34 -05:00
Brent Yorgey
1ce035ee7d Merge pull request #232 from l29ah/fuzzymatch
+ FuzzyMatch by @nzeh
2018-04-10 20:56:08 -05:00
Brent Yorgey
41e6343a7e Merge pull request #237 from ccrusius/master
Add a `ModifyX` message to `Groups`
2018-04-10 20:43:28 -05:00
ae-g-i-s
b20cf7c1e6 Implement additional options for Dzen 2018-04-04 14:25:42 +02:00
Brent Yorgey
5cdf4e408c Merge pull request #234 from vmandela/dzen
DynamicLog: add dzenWithFlags function
2018-04-02 10:14:50 -05:00
Marc A. Saegesser
9c4dad9946 Add spawnOnOnce and related functions. 2018-03-30 13:43:05 -05:00
geekosaur
13e37b964e Merge pull request #238 from IvanMalison/remove_gnome_panel_ewmh_code
Remove gnome-panel hack from ewmh desktop code
2018-03-28 22:01:02 -04:00
Ivan Malison
a512351d3a Remove gnome-panel hack from ewmh desktop code
Fixes #216
2018-03-28 15:06:33 -07:00
Venkateswara Rao Mandela
82aba52541 DynamicLog: add dzenWithFlags function
This commit adds `dzenWithFlags` function for users who wish to change the
command line arguments passed to `dzen`. The behaviour of `dzen` function is
kept the same.
2018-03-27 20:09:34 +05:30
Cesar Crusius
62e04de68e Add a ModifyX message to Groups
The `group3` addition I made in a previous commit enabled one to go so
far, but then quickly hit some walls due to non-exported symbols from
`XMonad.Layout.Groups`.

This commit removes `group3`, as it would hardly be useful to anybody,
and introduces a new `ModifyX` message that allows the modifying
function to return a `Groups` layout inside the `X` monad. Here's an
example on why this is useful:

Say you have a master layout with tabbed sub-layouts, and you have
terminal windows sprinkled around these sub-layouts. You now want to
gather all of them into a single tabbed sub-layout, effectively
implementing a "tabbed terminal" (or browser, or editor, etc). With
functionality like this, `XMonad` can become a unified multi-window
application manager: one does not need tabbed browsers, terminals,
etc.

In order for this to be possible, however, the modifier function needs
to be able to query for things like the window class name with
`runQuery`, and that in turn means it has to operate inside the `X`
monad. This is only possible if `Groups` accepts the modifier
introduced in this commit.

I bet many other uses for a `ModifierX` message can be found. I have
the functionality of the example I gave implemented and working with
this change, since it was my motivation to get it done (and I must say
it is quite sweet to have tabbed window unification).
2018-03-21 21:16:06 -07:00
Brent Yorgey
2448a2a6a6 Merge pull request #236 from MichielDerhaeg/ghc84-compat
update to work with GHC 8.4.1
2018-03-21 15:26:15 -05:00
Michiel Derhaeg
86595e193e update to work with GHC 8.4.1 2018-03-20 22:06:18 +01:00
Campbell Barton
236ca9959d Add BinaryColumn layout
This is similar to 'Column' layout with some differences.

- Add/remove windows keeps window bounds.
- Enforce minimum window size.
- Negative scale can be used to increase the size of the last window
  instead of the master window.
2018-03-11 20:45:20 +11:00
Sergey Alirzaev
d5d82267c5 + FuzzyMatch by @nzeh
Provides a predicate 'fuzzyMatch' that is much more lenient in matching
completions in XMonad.Prompt than the default prefix match.  Also provides
a function 'fuzzySort' that allows sorting the fuzzy matches by "how well"
they match.

Not sure why wasn't it accepted.
Discussion: https://markmail.org/thread/kgrybzqarqzqiige
2018-03-10 09:07:00 +03:00
Brent Yorgey
3d3e898166 Merge pull request #229 from ccrusius/master
Add three-dimensional group layout
2018-03-06 20:52:56 -06:00
Brent Yorgey
e03844dd20 Merge pull request #230 from IamfromSpace/add-layout-multi-dishes-squashed
Add a new layout MultiDishes
2018-03-06 20:50:15 -06:00
Nathan Fairhurst
b42a1392da Add a new layout MultiDishes, which behaves like Dishes, but allows a configurable number windows within each stack. 2018-03-04 21:03:45 -08:00
Brent Yorgey
0bde284129 Merge pull request #219 from LSLeary/master
New sideNavigation strategy for X.A.Navigation2D
2018-03-02 05:55:33 -06:00
ccrusius
1c52484753 Add three-dimensional group layout
This is as per the work done in
http://lynnard.me/blog/2013/12/30/more-xmonad-goodies/, where the
functionality is explained in detail.

This also fixes #214. The original suggestion in that bug report is
not enough. Even if we export `gen` and `Uniq`, we would still have to
export the `Groups` type constructor. I thought it better to simply
allow the user to create a three-dimensional group instead.
2018-02-28 18:37:24 -08:00
Brent Yorgey
d7c6ee940b Merge pull request #228 from codetriage-readme-bot/codetriage-badge
Add CodeTriage badge to xmonad/xmonad-contrib
2018-02-14 22:13:46 -06:00
Brent Yorgey
a96d1d0bb7 Merge pull request #225 from maciasello/master
Add appendFilePrompt' to allow transforming text before appending
2018-02-12 09:59:40 -06:00
codetriage-readme-bot
a590034a23 Add CodeTriage badge to xmonad/xmonad-contrib
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/xmonad/xmonad-contrib/badges/users.svg)](https://www.codetriage.com/xmonad/xmonad-contrib)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 7 months ago, [wisn](https://github.com/wisn) added this project to CodeTriage in order to start contributing. Since then, 2 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-11 13:51:19 -06:00
Maciej Ligenza
ff3e415b9d Add appendFilePrompt' to allow transforming text before appending to file 2018-01-21 02:12:24 +01:00
Brent Yorgey
3044577a4c Merge pull request #182 from strokyl/157_allow_custom_physical_screen_order
157 allow user to customize screen ordering
2018-01-18 23:43:25 -06:00
Luc DUZAN
756507e2b6 157 allow user to customize screen ordering
Now when using getSortByXineramaPhysicalRule and all helper given by
Actions.PhysicalScreens the user have to provide a screen comparator that can
compare screen using their id or/and their coordinate.
2018-01-14 22:13:31 +01:00
L.S. Leary
4a98a27950 Added navigation strategy sideNavigation and parameterised variant sideNavigationWithBias to X.A.Navigation2D. 2017-12-16 17:37:52 +13:00
Brent Yorgey
51857a1a20 Merge pull request #218 from LSLeary/master
Extended the sendMessage interface of X.L.Gaps to allow arbitrary modifications
2017-11-28 23:58:33 -05:00
L.S. Leary
cc9622ab28 Extended the sendMessage interface of X.L.Gaps to allow arbitrary modifications to the GapSpec. 2017-11-22 07:58:41 +13:00
Brent Yorgey
89a0fdf7fe Merge pull request #181 from NickHu/master
Make UnicodeData.txt path configurable, remove unsafePerformIO
2017-10-16 00:18:43 -04:00
Nick Hu
50b2abce5b Merge branch 'master' into master 2017-10-09 12:52:41 +01:00
Brent Yorgey
dc30cbd2f9 Merge pull request #197 from NickHu/pass
Add facility for automatically typing passwords via XMonad.Prompt.Pass, and handle special characters in pass labels
2017-10-07 16:43:21 -04:00
Peter J. Jones
6b5d08c46b Merge pull request #212 from LSLeary/master
Generalised hybridNavigation to hybridOf
2017-09-26 11:49:26 -07:00
L.S. Leary
c778b9c2af Generalised (and hence deprecated) hybridNavigation to hybridOf so that users can choose order of preference of navigation strategies. 2017-09-27 07:25:35 +13:00
Peter J. Jones
823362ce79 Update .travis.yml 2017-09-26 10:53:02 -07:00
Nick Hu
ecd0048d83 Make UnicodeData.txt path configurable, remove unsafePerformIO in favour
of ExtensibleState

Add facility to type Unicode character via xdotool
2017-08-19 00:27:52 +01:00
Nick Hu
8daa84375b Pipe password to xdotool via undocumented --file to prevent snatch
from `ps`, and also some backwards compatibility.
2017-08-17 21:46:41 +01:00
Nick Hu
cee5aa2a58 Adds a new function to spawn a pass prompt which will use xdotool to
type in a password, bypassing the clipboard. Also incorporate some shell
escapes to properly handle pass labels with spaces and special
characters in them.
2017-08-17 21:46:41 +01:00
Brent Yorgey
676d83ce83 Merge pull request #196 from Ongy/sessionstartup
Add XMonad.Util.SessionStart
2017-07-25 11:44:33 -04:00
Brent Yorgey
6b1f755e20 Merge pull request #206 from foreverbell/master
Export XMonad.Prompt.insertString.
2017-07-24 17:41:51 -04:00
Brent Yorgey
df88bc62d7 Merge pull request #189 from skewerr/master
Added functions to perform actions with the first minimized window.
2017-07-24 11:37:42 -04:00
Brent Yorgey
dcc2a69fbc Merge branch 'master' into master 2017-07-24 11:37:32 -04:00
foreverbell
ff3ecd2032 Update CHANGES.md 2017-07-23 00:59:02 +08:00
foreverbell
96e9cab753 Export XMonad.Prompt.insertString. 2017-07-23 00:52:43 +08:00
Brent Yorgey
97daafa723 Merge pull request #205 from Gekkio/fix-gnome-config-mod-shift-q
Fix Gnome config modm+shift+Q logout command
2017-07-17 17:40:29 -04:00
Joonas Javanainen
26690e2d0b Fix Gnome config modm+shift+Q logout command
The --kill option was deprecated in 2.23.x (year 2008):
c91d138b33/NEWS (L1843)

gnome-session-save was renamed to gnome-session-quit in 2.91.x (year 2011):
c91d138b33/NEWS (L988)
2017-07-16 15:04:00 +03:00
Brent Yorgey
dc04c3821c Merge pull request #200 from xrvdg/readme
README.md: Update links and add contributing info.
2017-07-10 11:44:34 -04:00
Brent Yorgey
430942e981 Merge pull request #201 from xrvdg/commands-dmenulike
X.A.Commands: Parameterize runCommand to accept dmenu-like launchers.
2017-07-10 11:41:17 -04:00
Brent Yorgey
62028bbff7 Merge pull request #202 from xrvdg/spacing-gaps-documentation
X.L.Spacing + X.L.Gaps: add mutual hyperlink
2017-07-10 11:37:17 -04:00
Brent Yorgey
4719dfe260 Merge pull request #190 from crocket/master
Replace X with MonadIO in XMonad.Util.Dmenu
2017-07-10 11:35:49 -04:00
Markus Ongyerth
b1f28e64d7 Add -dock to dzen command 2017-07-08 08:37:35 +02:00
crocket
7930151604 Make XMonad.Util.Dmenu.menuArgs compatible with GHC < 7.10
menuArgs breaks compilation on GHC < 7.10 because it uses fmap but
only has a MonadIO constraint.
Functor was not a superclass of Monad until GHC 7.10.
2017-07-08 08:16:14 +09:00
Xander Rémon van der Goot
cad6bb7769 X.L.Spacing + X.L.Gaps: add mutual hyperlink
These layout have different applications but their names could cause some
confusion since the module names could just as well be swapped. To support this claim,
what we call "spacing" is named "gaps" in i3wm (i3-gaps). Therefore hyperlinks have
been added to inform the reader of the existence of the other module.
2017-07-03 21:27:58 +02:00
Xander Rémon van der Goot
d5dd9329b5 X.A.Commands: Parameterize runCommand to accept dmenu-like launchers.
The X.U.Dmenu library has support to run dmenu-like launchers, but X.A.Commands
has the use of dmenu hardcoded. This commit makes it possible to use other
launchers without duplicating existing code.
2017-07-03 19:41:11 +02:00
xrvdg
1b1a0eeada README.md: Update links and add contributing info.
Firstly, the links are updated to point to Hackage rather than xmonad.org since not all redirect work correctly. For example the link to developing documentation went to the main XMonad's Hackage page rather then XMonad.Docs.Extending on Hackage.

Secondly, the links are changed such that their [id]-tag isn't showing.

Lastly, a link to XMonad's contributing.md has been added.
2017-07-03 17:53:50 +02:00
Markus Ongyerth
c8ce8dcd41 Add XMonad.Util.SessionStart
This module provides a way to query the session startup.
Currently the flag has to be set by calling setSessionStarted in
the startupHook. The goal would be to merge this into xmonad at some
point and set the flag when the state file is read in, and remove the
need to manually set it.
2017-06-25 12:15:17 +02:00
spoonm
8266feba95 Added withFirstMinimized and withFirstMinimized'.
Also changed the order of the `L.intersect` line to prevent the map key ordering from changing the minimizedStack.
2017-06-17 10:20:49 -03:00
crocket
3282fb420d Replace X with MonadIO in XMonad.Util.Dmenu
MonadIO is compatible with xfork which prevents dmenu prompts from
freezing XMonad.
Without xfork, if I try to give focus to another window while dmenu is
waiting, XMonad freezes until I kill dmenu in virtual terminal or ssh
session.
2017-06-06 10:17:00 +09:00
Peter J. Jones
12227d37ca Merge pull request #186 from ankaan/multicolumns-layouthints-windoworderfix
Fix render order of LayoutHints and MultiColumns
2017-05-24 16:52:41 -07:00
Anders Engström
cff3343a8c Fix render order of LayoutHints and MultiColumns
Before this fix, when using layoutHintsToCenter together with
MultiColumns, in certain situations XMonad would render the border of
the focused window below a border of unfocused windows. This looks odd
and is here fixed by changing MultiColumns to always place the focused
window in front (even though they should not really overlap) and making
LayoutHints preserve the order returned from the underlying layout,
except for the focused window that is placed on top.

This is a good idea since layoutHintsToCenter requires the focused
window to be on top for good rendering, even if that is not really
required when the underlying layout is used on its own. This way
layoutHintsToCenter requires less of the layout that is modified and
MultiColumns is more compatible with future layout modifiers that are
not so considerate.
2017-05-24 22:18:34 +02:00
Adam Plaice
a5c5c52745 Improve conversion of Char to KeySym in XMonad.Util.Paste 2017-05-23 03:05:16 +01:00
bforte
2314dd628a reimplemented with X.A.Minimize 2017-05-10 00:57:49 +02:00
Bruce Forte
95cd118c9a forgot importing <$> 2017-05-07 14:15:49 +02:00
Bruce Forte
53481b2269 Update xmonad-contrib.cabal 2017-05-07 14:01:38 +02:00
Bruce Forte
c1c7c30532 renamed the module to X.U.ExclusiveScratchpads 2017-05-07 14:00:40 +02:00
Bruce Forte
617099badd Update CHANGES.md 2017-05-07 13:38:34 +02:00
Bruce Forte
b05f5f12cf import (<$>) because travis failed 2017-05-06 04:12:44 +02:00
bforte
270ca2da23 add new module X.U.MutexScratchpads 2017-05-06 00:37:28 +02:00
Daniel Wagner
ade890ac63 Merge pull request #172 from bforte/fixed-haddock-comments
trivial changes to fix haddock documentation
2017-04-29 15:23:01 -07:00
Bruce Forte
295d416e9d Update CycleWorkspaceByScreen.hs 2017-04-29 22:53:42 +02:00
bforte
38b7a2e7f4 trivial changes to fix haddock documentation 2017-04-29 21:08:12 +02:00
Peter J. Jones
abb5f3d45c Merge pull request #171 from pjones/pjones/combop-parition
Add message to "re-partition" a ComboP layout
2017-04-28 21:14:33 -07:00
Peter Jones
e3c46b36db Add message to "re-partition" a ComboP layout
This is especially useful with the `Tagged' window property.
2017-04-27 21:28:00 -07:00
Peter J. Jones
e5534d16cd Merge pull request #167 from IvanMalison/CycleWorkspaceByScreen
Cycle workspace by screen
2017-04-21 14:37:10 -07:00
Ivan Malison
0e35b6e504 Add X.A.CycleWorkspaceByScreen, Per screen WorkspaceHistory 2017-04-20 15:46:23 -07:00
Peter J. Jones
7e47ecc124 Merge pull request #102 from f1u77y/rewrite-minimize
Rewrite minimization-related modules
2017-04-20 10:46:26 -07:00
Bogdan Sinitsyn
c99606bbdd Rewrite minimization-related modules
* Use global state instead of per-layout - so now window is minimized on
  all workspaces (EWMH requires that windows with _NET_WM_STATE_HIDDEN
  set should be minimized on any workspace but previously they were not)
* Use `windows` instead of `modify`. That should fix bugs related to
  actions that should be done by `windows` and not done by
  `modify` (fixes #46)
* Mark module X.H.RestoreMinimized as deprecated
2017-04-20 20:09:16 +03:00
Brent Yorgey
a226ca62c7 Merge pull request #156 from strokyl/add_modifySpacing_message_handling_to_smartpacing
Add ModifySpacing message handling to SmartPacing and SmartSpacingWit…
2017-04-19 12:25:38 -04:00
Peter J. Jones
87683afd72 Merge pull request #165 from davama/master
X.P.Pass doc typo
2017-04-13 11:30:59 -07:00
Dave
20e8a33e0c Typo fix 2017-04-13 13:37:30 -04:00
Peter J. Jones
21062dd392 Merge pull request #44 from deepfire/spawnon-child-pid-tracking
Spawnon child pid tracking
2017-04-12 08:26:18 -07:00
Peter J. Jones
cfc99693fe Merge pull request #161 from xmonad/revert-128-master
Requesting focus causes layout order to change

Reverts xmonad/xmonad-contrib#128
2017-04-10 16:52:12 -07:00
Peter J. Jones
1b738c2bed Revert "Add new module XMonad.Hooks.Focus ." 2017-04-10 16:19:06 -07:00
Kosyrev Serge
33237f47f7 Actions.SpawnOn: make spawnOn more reliable on Linux, by tracking children across fork 2017-04-11 01:00:47 +03:00
Peter Jones
65ac029636 Move example configuration file into xmonad-contrib for better visibility 2017-04-10 10:38:23 -07:00
Brent Yorgey
7136394282 Merge pull request #147 from pjones/pjones/windowMultiPrompt
New function: `X.P.Window.windowMultiPrompt'
2017-03-30 16:15:50 -05:00
Brent Yorgey
0ecbc68b98 Merge branch 'master' into pjones/windowMultiPrompt 2017-03-30 16:15:06 -05:00
Brent Yorgey
3ab4a94d6f clean up Hooks.Focus-related CHANGES and move to 0.14 2017-03-30 16:10:21 -05:00
Brent Yorgey
3b9924b181 Merge pull request #128 from sgf-dma/master
Add new module XMonad.Hooks.Focus .
2017-03-30 16:03:18 -05:00
Brent Yorgey
08abaccdce Merge branch 'master' into master 2017-03-30 16:02:47 -05:00
geekosaur
acdea28dfd Merge pull request #158 from xmonad/ezconfig-latin1
X.U.EZConfig: include Latin1 keys
2017-03-28 20:20:04 -04:00
Brent Yorgey
4ba56ee388 update CHANGES for EZConfig Latin1 changes 2017-03-26 22:06:05 -05:00
Brent Yorgey
057af44998 X.U.EZConfig: include Latin1 keys 2017-03-26 22:02:48 -05:00
Luc DUZAN
b4e7ab3d37 Add ModifySpacing message handling to SmartPacing and SmartSpacingWithEdge 2017-03-15 17:53:02 +01:00
Daniel Wagner
8984ce64bb Merge pull request #153 from mitchellwrosen/master
Respect number of master windows in Magnify layout
2017-02-25 10:07:01 -08:00
Mitchell Rosen
1b96c646c1 Respect number of master windows in Magnify layout 2017-02-25 10:02:29 -05:00
Brent Yorgey
78a15b9d49 Merge pull request #151 from samdoshi/gridselect
GridSelect: border colour and vertically centring text
2017-02-21 20:20:20 -06:00
Brent Yorgey
4c00eb5848 fix ThreeColMid window shuffling
Fixes #137.
2017-02-19 20:45:43 -06:00
geekosaur
a372b455dc typo in navigation2DP example
The example code in the documentation uses `navigation2D` instead of `navigation2DP`, evidently a simple copy/paste error. No actual code change.
2017-02-18 17:19:59 -05:00
Sam Doshi
a79a116934 improve the vertical centring in X.A.GridSelect 2017-02-18 13:46:30 +00:00
Sam Doshi
b1dee9b0b4 allow border colour to be specified in GSConfig 2017-02-17 08:29:12 +00:00
Brent Yorgey
54ef9f6f8d Merge pull request #149 from pjones/pjones/tagged
X.U.WindowProperties: Added the ability to test if a window has a tag…
2017-02-16 21:59:09 -06:00
Brent Yorgey
cffc36e21a Merge pull request #148 from samdoshi/bsp
export BinarySpacePartition type
2017-02-16 21:52:46 -06:00
Peter Jones
025433c658 X.U.WindowProperties: Added the ability to test if a window has a tag from X.A.TagWindows
New data constructor `Tagged` that uses `hasTag` from
`X.A.TagWindows`.  This is great for building layouts based off of
window tags.
2017-02-15 09:36:35 -07:00
Sam Doshi
0f9a6015e4 export BinarySpacePartition type 2017-02-15 14:45:11 +00:00
Peter Jones
00eb2abd87 New function: `X.P.Window.windowMultiPrompt'
Like 'windowPrompt', but uses the multiple modes feature of
@Prompt@ (via 'mkXPromptWithModes').

Given a list of actions along with the windows they should work
with, display the appropriate prompt with the ability to switch
between them using the @changeModeKey@.

For example, to have a prompt that first shows you all windows, but
allows you to narrow the list down to just the windows on the
current workspace:

> windowMultiPrompt config [(Goto, allWindows), (Goto, wsWindows)]
2017-02-14 10:32:50 -07:00
sgf
6f8145a2dc X.H.Focus: Add predefined configurations and more examples. 2017-02-14 20:13:49 +03:00
Peter Jones
298e51f939 Correctly mark functions in X.P.Window as deprecated 2017-02-13 16:16:04 -07:00
Peter J. Jones
9d2ffeb8e1 Merge pull request #139 from mekeor/better-xpc-font-description
Better description of 'font' field of 'XPC' record
2017-02-13 12:15:59 -07:00
Mekeor Melire
878987071b Better description of 'font' field of 'XPC' record
Describe how to use the 'font' field of 'XPC' record by adding two different examples.
2017-02-13 13:25:25 +01:00
Peter Jones
ca9b7d9dfc Add a stack.yaml file for testing and easy Hackage upload 2017-02-10 16:20:42 -07:00
Peter Jones
615f007fe4 Add a cabal.project file 2017-02-10 16:04:33 -07:00
Peter Jones
e4e20da8f0 Clean up the change log just a bit 2017-02-10 16:02:41 -07:00
Peter Jones
b064d22c2d Add a release date 2017-02-09 16:25:24 -07:00
Peter Jones
d2ffb75031 Merge remote-tracking branch 'origin/pjones/rmworkarea' into release-0.13 2017-02-09 16:13:36 -07:00
Peter Jones
cb344d14b9 Bump version to 0.13 2017-02-09 16:12:55 -07:00
Peter J. Jones
d1a5f9cf91 Merge pull request #141 from pjones/pjones/prompt-complete
Better completion when using `alwaysHighlight'
2017-02-09 15:10:27 -07:00
Peter J. Jones
3b1c43cced Merge pull request #142 from pjones/pjones/border
Use `setWindowBorderWithFallback' to support windows with RGBA color maps
2017-02-09 15:10:13 -07:00
Peter J. Jones
76b1771a31 Merge pull request #144 from pjones/pjones/dzen
Manage struts even when _NET_WM_WINDOW_TYPE isn't a dock
2017-02-09 15:07:40 -07:00
Peter Jones
cd96de5378 Manage struts even when _NET_WM_WINDOW_TYPE isn't a dock
Relates to #21
2017-02-07 15:58:55 -07:00
Peter Jones
0a8e68b458 Delete _NET_WORKAREA instead of setting it
References:

  * 9c020877dd

  * https://github.com/qtile/qtile/issues/847

  * eec80838ab

  * https://github.com/xmonad/xmonad-contrib/pull/79
2017-02-07 15:42:35 -07:00
Peter Jones
de4a3bd0ed Use `setWindowBorderWithFallback' to support windows with RGBA color maps
This brings xmonad-contrib inline with xmonad in this regard.  Should
also be fix for #138
2017-02-07 14:49:01 -07:00
Peter Jones
4f3020313d Don't use `windows' in X.L.Hidden, it might cause an infinite loop
Fixes #132
2017-02-07 13:39:01 -07:00
Peter Jones
57c00b1086 Better completion when using `alwaysHighlight'
This change improves the UX of X.Prompt when `alwaysHighlight` is
enabled.  This is especially useful for use with `mkXPromptWithModes`
which forces `alwaysHighlight` to be `True`.

When the user presses the `complKey` and `alwaysHighlight` is `True`,
one of two things will happen:

  1. If this is the first time `complKey` is pressed in this round of
     completion then the prompt buffer will be updated so it contains
     the currently highlighted item.

  2. Every other time that the `complKey` is pressed the next
     completion item will be selected and the prompt buffer updated.

This gives immediate feedback to the user and allows using some
prompts with `alwaysHighlight` that weren't possible before (e.g.,
shellPrompt, directoryPrompt, etc.)
2017-02-05 19:38:00 -07:00
Peter Jones
bdec8df4c6 Improve prompts for X.A.DynamicProjects 2017-02-05 19:36:30 -07:00
Peter Jones
52087953fd Add `directoryMultipleModes'
Allow X.P.Directory to be used with `mkXPromptWithModes`
2017-02-05 19:31:41 -07:00
Peter Jones
33c805fadc Add GitHub templates 2017-01-12 12:27:11 -07:00
Peter J. Jones
32b9f00ce7 Merge pull request #134 from pjones/bugfix/prompt-history
Use the new getXMonadCacheDir function from #62
2017-01-08 21:26:13 -07:00
sgf
a3593e5607 Remove no longer relevant changes from CHANGES.md. Fix merge conflicts. 2017-01-06 18:01:41 +03:00
Peter Jones
4dd60756ea Update the change log 2017-01-04 14:47:20 -07:00
Peter Jones
74b281b5d3 Use the new getXMonadCacheDir function from #62
Prompt should have been using getXMonadDir this entire time but since
we now have getXMonadCacheDir use that instead.  This brings
xmonad-contrib inline with the changes in #62.

This also fixes xmonad/xmonad-contrib#68
2017-01-04 14:39:00 -07:00
Peter J. Jones
77e5e5190d Merge pull request #131 from sgf-dma/fix-changes.md
Fix CHANGES.md after b9d8f6c .
2017-01-03 15:49:09 -07:00
sgf
5bf4b27054 Fix CHANGES.md after b9d8f6c . 2016-12-25 14:59:30 +03:00
Brent Yorgey
8956684ff5 Merge pull request #130 from strokyl/add_HiddenEmptyWS_to_CycleWS
Add HiddenEmptyWS to CycleWS
2016-12-23 23:50:52 -05:00
Luc DUZAN
9da78669e7 Add HiddenEmptyWS to CycleWS
When I have multiscreen I think it's usefull to get the next empty workspace
that is not already displayed.
2016-12-22 22:48:23 +01:00
sgf
c07be09e17 X.H.EwmhDesktops: use manageHook for handling activated window.
Move EWMH code from `X.H.Focus` to `X.H.EwmhDesktops`. Thus:

- I'll use `manageHook` for handling activated window.
- By default window activation do nothing (assuming default `ManageHook`).
- I can use `activated` predicate for changing window activation behavior.
- I may use additional combinators from `X.H.Focus` for more complex
  focus/workspace switch strategies.
2016-12-16 23:59:04 +03:00
sgf
8e5931272c X.H.ManageHelpers: Make type of ManageHook combinators more general. 2016-12-16 14:22:39 +03:00
sgf
2807935900 X.H.SetWMName: Add getWMName function.
And do not overwrite wm name in `handleFocusQuery`, if user has already set
it.
2016-12-15 22:13:48 +03:00
sgf
195cfbe77e Add new module XMonad.Hooks.Focus .
Extend ManageHook EDSL to work on focused windows and current workspace.
2016-12-15 22:13:42 +03:00
Peter J. Jones
c0cf18def2 Merge pull request #17 from kurnevsky/update_pointer_bugfix
UpdatePointer bugfix.
2016-12-14 14:48:52 -07:00
Peter Jones
d5aa562282 Add build status badge from Travis 2016-12-14 14:44:15 -07:00
Peter Jones
f1de0413da Update GHC versions to a more reasonable list 2016-12-14 14:29:52 -07:00
Peter Jones
6eac81cf51 Bump X11 version upper-bounds to 1.8 2016-12-14 14:11:30 -07:00
Kurnevsky Evgeny
a8d290b830 Update CHANGES.md 2016-12-14 11:49:28 +03:00
Kurnevsky Evgeny
86280c5063 Rewrite XMonad.Actions.UpdatePointer bugfix with Control.Exception.try. 2016-12-14 09:03:26 +03:00
Kurnevsky Evgeny
11e0d683af UpdatePointer bugfix. 2016-12-14 09:03:26 +03:00
geekosaur
061edbd954 Merge pull request #127 from bennofs/patch-1
DynamicProperty: execute other hooks
2016-12-09 23:10:06 -05:00
Benno Fünfstück
0949b9ec91 DynamicProperty: execute other hooks
All False short-cuts the default behavior for the event, which leads to a non-functioning window manager. Returning mempty ensures that the default action is still executed,
2016-12-09 22:35:11 +01:00
Peter J. Jones
f837a4fb36 Merge pull request #6 from sgf-dma/master
X.A.Submap: establish pointer grab to avoid freezing X.
2016-12-09 08:34:47 -07:00
sgf
b9d8f6ce34 X.A.Submap: establish pointer grab to avoid freezing X.
Establish active asynchronous pointer grab before entering infinity cycle.
Because xmonad already has passive synchronous pointer grab, this overwrites
it temporary and avoids freezing X, when button press occurs after submap key
press.

Also, terminate submap at button press in the same way, as we do for wrong key
press.
2016-12-09 12:38:33 +03:00
Peter J. Jones
c69b2933a3 Merge pull request #126 from pauleve/master
Fix #120 - Make Actions.WindowGo.raiseNextMaybe span over all workspaces
2016-12-08 14:39:30 -07:00
Loïc Paulevé
0573451789 Update CHANGES.md for #126 2016-12-08 22:24:24 +01:00
Loïc Paulevé
43673b3907 workspacesSorted: fix indentation + add comment 2016-12-05 13:37:26 +01:00
Loïc Paulevé
9f9b5d3748 Make Actions.WindowGo.raiseNextMaybe span over all workspaces. Fixes #120 2016-12-02 08:54:01 +01:00
Daniel Wagner
0a1d8505a0 Merge pull request #125 from vvv/fix-custom-keys-doc
CustomKeys.hs: Fix documentation
2016-11-30 18:41:54 +01:00
Valery V. Vorotyntsev
c392a407bb CustomKeys.hs: Fix documentation
Fix code example in documentation. (Wrong implementation of `delkeys`.)
Thanks to Lasse R.H. Nielsen for reporting the problem!
2016-11-30 17:55:20 +02:00
Brent Yorgey
16b80a4331 Merge pull request #124 from trofi/master
XMonad/Layout/Groups/Helpers.hs: drop broken ImpredicativeTypes extension (fixes #123)
2016-11-28 17:54:29 -05:00
Sergei Trofimovich
a681e68602 XMonad/Layout/Groups/Helpers.hs: drop broken ImpredicativeTypes extension (fixes #123)
ImpredicativeTypes is practically unsupported extension
on it's way to be removed from GHC:
    https://mail.haskell.org/pipermail/ghc-devs/2016-September/012826.html

GHC-8.0.2-rc1 already fails to build xmonad-contrib as:

  XMonad/Layout/Groups/Helpers.hs:181:22: error:
    • Couldn't match type ‘G.WithID l0 Window
                           -> XMonad.Util.Stack.Zipper (G.Group l0 Window)
                           -> XMonad.Util.Stack.Zipper (G.Group l0 Window)’
                     with ‘G.ModifySpec’
      Expected type: (G.WithID l0 Window
                      -> XMonad.Util.Stack.Zipper (G.Group l0 Window)
                      -> XMonad.Util.Stack.Zipper (G.Group l0 Window))
                     -> G.GroupsMessage
        Actual type: G.ModifySpec -> G.GroupsMessage
    • In the second argument of ‘(.)’, namely ‘G.Modify’
      In the expression: sendMessage . G.Modify
      In an equation for ‘wrap’: wrap = sendMessage . G.Modify

The workaround is simple: add explicit types to applications
or open-code direct application (this change).

Bug: https://github.com/xmonad/xmonad-contrib/issues/123
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
2016-11-27 10:03:17 +00: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
Brent Yorgey
cc7ddcfa60 Merge pull request #25 from iblech/patch-1
Fix tiny markup typo
2015-12-18 14:11:11 -06:00
Brent Yorgey
02ddfebf05 Merge pull request #26 from pjones/release-0.12
Release 0.12
2015-12-18 11:22:32 -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
Peter Jones
093352f6c5 Finial tweaks before release 2015-12-14 13:30:55 -07:00
Ingo Blechschmidt
fa3e774a65 Fix tiny markup typo 2015-12-14 16:24:16 +01:00
Peter Jones
126ce6f3c9 Update development references (darcs, code.google.com, etc.)
* All references to darcs have been updated to git

  * Most Google Code references have been changed to GitHub

  * References to specific issues at code.google.com have been left
    alone

  * Updated the GenerateManpage.hs to work with the latest version of
    pandoc
2015-12-11 11:17:26 -07:00
Peter Jones
c98f2b16db Add change log entries for recent merges 2015-12-11 10:31:58 -07:00
Peter Jones
0d6c2b1668 Use a table format that works with Pandoc and GitHub 2015-12-11 09:49:52 -07:00
Peter Jones
5739da65b3 Added more detail to the change log
* Brought in changes from https://wiki.haskell.org/Xmonad/Notable_changes_since_0.11

  * List all new modules along with their description
2015-12-11 09:49:52 -07:00
Peter Jones
4d3f633c73 Reformat README.md, add CHANGES.md, update xmonad-contrib.cabal 2015-12-11 09:49:52 -07:00
Peter Jones
6177841488 Rename the REAME file for GitHub/Hackage 2015-12-11 09:49:52 -07:00
f1u77y
d81c48d022 fix #14 2015-12-11 16:42:14 +03:00
Brent Yorgey
b9b4f4af07 Merge pull request #19 from kurnevsky/move_history_bugfix
Bugfix for moveHistory when alwaysHighlight is enabled.
2015-12-10 21:35:15 -06:00
Brent Yorgey
8e532562e7 X.P.Shell: fix shadowing warning 2015-12-10 21:08:38 -06:00
Brent Yorgey
e521d6546f X.A.Search: fix missing type sig warning 2015-12-10 21:07:24 -06:00
Brent Yorgey
dfeed762d4 Merge pull request #11 from pjones/projects
New module: XMonad.Actions.DynamicProjects
2015-12-10 20:55:42 -06:00
David Unric
0d4439b7a7 stop ignoring Prompt.Shell searchPredicate
Closes #9.

See also https://code.google.com/p/xmonad/issues/detail?id=393 .
2015-12-10 20:50:38 -06:00
Kurnevsky Evgeny
09f3c3fbea Bugfix for moveHistory when alwaysHighlight is enabled. 2015-12-09 17:50:15 +03:00
Brent Yorgey
6ae90737de Merge pull request #10 from pjones/dirfix
NixOS does not have /bin/bash
2015-12-08 21:25:41 -06:00
Brent Yorgey
1c61f3cf05 Merge pull request #5 from kurnevsky/master
Add layout hook for ScreenCorners.
2015-12-08 21:24:02 -06:00
Kurnevsky Evgeny
dfb1c52c66 Add layout hook for ScreenCorners. 2015-12-08 08:39:55 +03:00
Peter Jones
f35083da9f Don't auto-delete workspaces
* Previously I was removing empty workspaces after switching away from
    them, but this seemed to cause a bug when workspaces were defined
    statically in your XMonad configuration.

  * Next up: a function to delete an existing project.
2015-12-02 20:07:57 -07:00
Brent Yorgey
dc5fbfecc4 Merge pull request #12 from psibi/add-search-engine
Add Stackage and Vocabulary as new search engines.
2015-12-02 16:56:24 -06:00
Brent Yorgey
8cc31b5c76 Merge pull request #15 from nikolas/patch-1
Fix typo in Monitor layout description
2015-12-02 15:49:18 -06:00
Peter Jones
ea8e0ea7b6 Add renameProjectPrompt, fix directory prompting completion 2015-12-01 12:08:52 -07:00
Nik Nyby
62dac9ccd2 Fix typo in Monitor layout description 2015-11-30 20:10:17 -05:00
Peter Jones
60922e0cae Remove unnecessary call to XS.modify 2015-11-30 12:54:06 -07:00
Sibi Prabakaran
9eb55c76ea Add Stackage and Vocabulary as new search engines. 2015-11-22 15:10:14 +05:30
Peter Jones
08c88abfb2 Fix a small space leak in DynamicProjects
Add a couple of strictness annotations to keep ExtensibleState from
building up thunks.
2015-11-18 13:53:31 -07:00
Peter Jones
b1360f08d0 Fix warnings from hlint 2015-11-16 13:12:49 -07:00
Peter Jones
3b9c6d6ff2 New module: XMonad.Actions.DynamicProjects 2015-11-16 11:51:31 -07:00
Peter Jones
6f0a9785d6 NixOS does not have /bin/bash 2015-11-16 10:10:34 -07:00
Brent Yorgey
dbfd81b3f9 add generated .travis.yml 2015-11-06 14:51:52 -06:00
Brent Yorgey
e6350c91b8 .cabal: update tested-with field 2015-11-06 14:51:15 -06:00
geekosaur
32f3fbdb2f Merge pull request #2 from vrs/master
X.H.DynamicLog: make xmobarStrip actually strip xmobar tags
2015-09-11 17:03:05 -04:00
geekosaur
62e40287a6 Merge pull request #1 from 0/dynamic-bars
Use existing connection in X.H.DynamicBars
2015-09-11 17:01:22 -04:00
vrs
0a7ae19f90 X.H.DynamicLog: make xmobarStrip actually strip xmobar tags
consider the old implementation:
> xmobarStrip "<<fc=#f00>fc=#f00>foo</</fc>fc>"
"<fc=#f00>foo</fc>"
2015-09-07 22:59:38 +02:00
Dmitri Iouchtchenko
42a69bfa98 Use existing connection in X.H.DynamicBars
Adapted from patch attributed to geekosaur
(https://code.google.com/p/xmonad/issues/detail?id=538).
2015-08-24 01:56:46 -04:00
brandon s allbery kf8nh
05f3eb17f5 Add .gitignore
Shamelessly ganked from cabal.
2015-08-22 14:01:56 -04:00
Tuncer Ayaz
d26da8e63a Fix 7.10.2 compile 2015-06-17 19:09:33 +00:00
Brent Yorgey
c1db249147 X.A.WorkspaceNames: convert tabs to spaces, cleanup 2015-06-03 14:20:27 +00:00
Antoine Eiche
bbf36809e9 XMonad.Actions.WorkspaceName.workspaceNamePrompt is XMonad.Prompt.Workspace.workspacePrompt acting on the workspace name. 2015-06-01 09:32:53 +00:00
anton.pirogov at gmail . com
c4b3895af6 BinarySpacePartition: make all actions work on nodes, add MoveNode feature 2015-05-07 09:08:42 +00:00
allbery.b
e41d7135a9 ewmh-hook-order
Reorder the application of hooks so that users' config is honored.
Notably, this means setWMName works in startupHook instead of
needing to do it repeatedly in logHook.
2015-04-23 15:44:36 +00:00
ezyang
f7f87c03cb Add XMonad.Layout.PerScreen 2015-05-02 04:53:53 +00:00
Adam Vogt
0d061462c7 make X.A.Plane example config actually compile 2015-04-24 01:22:09 +00:00
Adam Vogt
08beff45b9 address warnings 2015-04-14 19:48:38 +00:00
allbery.b
d3ffb1661a dynamicproperty
Run a ManageHook from handleEventHook when a window property changes.
You would use this to match e.g. browser windows whose title is not
"final" until after the on-load hooks of the loaded document complete.
2015-04-14 15:36:57 +00:00
Daniel Wagner
33c0e81a4a minor doc fixes to X.C.Mate 2015-03-30 18:07:52 +00:00
allbery.b
b5b8558acc mate-comment-fixup
Correct the docstrings / comments in X.C.Mate, which still referenced
gnomeConfig. Also update the session manager configuration to use
dconf and a current (on Mint at least) path for the session config.
2015-03-30 16:05:23 +00:00
Peter Jones
c2f00b8e61 Add the ability to specify padding used with Maximize 2015-03-09 23:29:39 +00:00
Peter Jones
a0cd3f92e5 Don't restore windows when changing workspaces 2015-03-10 20:17:09 +00:00
Peter Jones
e2e63440ee New layout modifier: Hidden
A layout modifer that is meant to work with the BinarySpacePartition
layout.  By removing windows from the window set and adding them back
at a later time, you can move windows to a different branch of the BSP
tree.
2015-03-09 22:30:36 +00:00
anton.pirogov
cf5739a484 Fixes to warnings with BSP layout 2015-03-15 10:00:41 +00:00
anton.pirogov
37f47d0bcb Improved BinarySpacePartition, added Equalize,Balance and FocusParent and mouse resize support 2015-03-12 14:52:20 +00:00
nzeh
00187576db New layout module X.L.Dwindle
This adds three layouts:  Spiral is a reimplementation of X.L.Spiral.spiral
with a (to me) more intuitive splitting policy.  Dwindle is similar but pushes
the smaller windows into a corner rather than into the center.  Squeeze just
stacks windows vertically or horizontally using geometrically decreasing sizes.
2015-03-15 13:09:13 +00:00
Adam Vogt
466f184c65 address warnings in P.Pass 2015-03-13 01:56:36 +00:00
ankaan
c8c5d28a9c X.L.AvoidFloats more useful default settings
Changed default settings with the simple layout modifier. Instead of asking for a bool indicating if all windows should be avoided, no such bool is asked for. No windows are avoided by default. I think this will be a more useful default setting since it would be annoying if dialogue windows are avoided. The same functionality is possible with the advanced constructor. This will be easier for new users.

This will break configurations using the old module, but this will not be much of an issue since the module has not been added to the repo as of this writing.
2015-03-10 21:20:22 +00:00
ankaan
3405d561b8 Resolve minor conflict in xmonad-contrib.cabal 2015-03-06 17:54:36 +00:00
ankaan
b2531a6f48 X.L.AvoidFloats, like avoidStruts but for floats
Checks for floating windows within the layout area and finds a maximum area
rectangle within that does not overlap with any of the floating windows.
This rectangle is used for all non-floating windows.

This new functionality introduced problems with the recommended configuration
of one of my other modules (X.A.FloatSnap.) A new and more reliable method of
distinguishing between clicks and drags where therefore introduced in the new
module X.A.AfterDrag.

This does not break any prior use of FloatSnap, but will require changes in
configuration if used together with AvoidFloats. (This is mentioned in the
docs for AvoidFloats and I recommend using the new configuration method even if
AvoidFloats is not in use.)
2015-03-06 17:17:02 +00:00
ankaan
16db912751 X.L.LayoutBuilder place active on top
Make sure that the active layout area is placed on top of all other areas when placing windows. This makes overlapping areas usable.
2015-03-06 16:42:00 +00:00
Dmitri Iouchtchenko
2f5e49919d Add rearrangers to X.A.GridSelect 2013-01-23 04:40:38 +00:00
Dmitri Iouchtchenko
2e1474f230 Avoid repainting elements in X.A.GridSelect 2013-01-23 04:38:50 +00:00
Dmitri Iouchtchenko
e98f0657bb Give a name to the initial state in X.A.GridSelect 2013-01-21 06:13:24 +00:00
Adam Vogt
45e4bd4ff6 Add XMonad.Config.Bepo (Yorick Laupa) 2015-03-10 21:43:14 +00:00
Adam Vogt
8ba4e0bed2 add instance Default WallpaperConf 2015-03-10 21:42:46 +00:00
Joachim Breitner
88fd1dd4fb XMonad.Prompt.Pass: Handle hierachical password stores
pass stores its passwords in directories, so the contents of the directory
store needs to be enumerated recursively. Alexander Sulfrian provided this
patch on the mailinglist, which I tested (it works) and cleaned up slightly.
2015-02-18 09:18:16 +00:00
Adam Vogt
9bb1f3b91e remove warnings and text dependency from H.WallpaperSetter 2015-03-10 19:29:33 +00:00
anton.pirogov
dcbff492fe Added the new hook WallpaperSetter 2015-02-28 16:23:35 +00:00
Adam Vogt
d82bfc6baf adjust an import to fix the build 2015-03-10 18:24:03 +00:00
Adam Vogt
e4fde08a0a merge conflicts in X.L.Spacing
I should have just applied Anton Pirogov March 4 patch.
2015-03-10 18:20:46 +00:00
anton.pirogov
0857f71938 Added messages to adjust the gap dynamically 2015-03-04 08:25:20 +00:00
Adam Vogt
80348bb4b7 X.L.Spacing needs -XPatternGuards now 2015-03-10 18:12:48 +00:00
Adam Vogt
c1abaa0183 add ConfirmPrompt (Antoine Beaupré) 2015-03-10 18:10:36 +00:00
anton.pirogov
20e69af48b Added messages to adjust the gap dynamically 2015-03-03 21:01:43 +00:00
Adam Vogt
6cbddae8c2 add another extension to actually fix the build with ghc-7.10-RC1 2015-01-24 11:19:39 +00:00
benweitzman
19860e2fa0 BinarySpacePartition downstream changes
Pulled in changes from my repo for this layout on github (https://github.com/benweitzman/BinarySpacePartition)
Includes a new mode for resizing windows in a more intuitive way, also contains a bug fix that was preventing users from
resiving a window up.

Includes changes from github users egasimus (Adam Avramov) and SolitaryCipher (Nick)
2014-11-10 20:22:59 +00:00
Adam Vogt
c115650d0d add XF86AudioMicMute to EZConfig (#582) 2014-12-22 04:53:06 +00:00
nrujac
5816a473dd Generalize new workspace addition functions to support arbitrary insertion.
The current DynamicWorkspaces module only supports adding new workspaces
at the start of the list of workspaces. This means when binding workspaces
to keys based on the position in the list, key bindings can change 
as workspaces are added in removed in a far more destructive way than
necessary. Instead, supporting appending and arbitrary insertion allows
the user to determine where the new workspace should be added.

This patch is a straight generalization of the addHiddenWorkspace' function.
Rather than always using `(:)` to insert the new workspace into the list
of workspaces, this patches causes it to use an arbitrary list insertion
function instead. A few new functions are added to prevent breakage of
external code while exported functions are left unchanged.

List of new functions:
  appendWorkspace
  appendWorkspacePrompt
  addWorkspaceAt
  addHiddenWorkspaceAt

Existing functions were modified to call their generalized brethren where possible
without changing functionality. This patch should not change behavior for any
existing users of this module.
2014-12-19 00:23:09 +00:00
Adam Vogt
0903f339b6 address another bitSize/finiteBitSize warning 2014-12-22 03:33:00 +00:00
Anton Vorontsov
201c25e7a4 X.L.Master: Add FixMaster layout modifier
This layout modifier is useful for the case if you desire to add a master
pane that has fixed width (it's fixed even if there is just one window
opened). Especially nice feature if you don't want to have too wide
terminal in a master pane.

The layout is implemented as an addition to Master layout, so it reuses
most of the code.
2014-12-20 01:13:39 +00:00
Adam Vogt
3b6d0c2458 filepath dependency for P.Pass was left out 2014-12-21 21:41:29 +00:00
Adam Vogt
7dac12829d remove unused imports 2014-08-15 05:12:34 +00:00
Adam Vogt
6d33617e1c fix build with ghc-6.12 2014-08-15 05:12:14 +00:00
Adam Vogt
8a195a2a48 use FiniteBitSize with ghc >= 7.8 2014-08-15 05:11:36 +00:00
Felix Crux
6c410a8a00 Layout.Spacing: Outer window edges now get as much spacing as inner ones
Layout.Spacing applies a customizable amount of space around the outside of each
window. At window edges where two windows meet, the total distance between them
is therefore twice the customized value (one space value from each window). At
the edge of the screen, however, the spacing is only applied once. This results
in uneven amounts of spacing and differently-sized gaps on the screen.

This patch extends the Spacing layout to include a further gap all around the
edge of the screen, thus making all spaces around windows equal in size.
2014-12-19 22:36:46 +00:00
Adam Vogt
95365822da add filepath package dependency needed by Prompt.Pass
filepath comes with ghc, and it's used by xmonad-core anyways
2014-09-09 14:52:16 +00:00
Devin Mullins
d0039a2f8b X.C.Prime: doc tweaks 2014-10-02 07:59:39 +00:00
Devin Mullins
c648a3959b X.A.Navigation2D: add convenience functions for setting config & keybindings
1. Added 'additionalNav2DKeys' which adds keybindings for the cartesian product
   of direction keys and (modifier, action) pairs given.
2. Added 'navigation2D' which combines that with 'withNavigation2DConfig'.
3. Added 'additionalNav2DKeysP' and 'navigation2DP' which do the same, but use
   the 'additionalKeysP' syntax.
2014-10-02 07:57:57 +00:00
Devin Mullins
0f21017370 X.C.Prime: doc fixes 2014-10-01 07:58:55 +00:00
Devin Mullins
6c96f4d5c6 X.C.Prime: add 'withScreens' and friends
The screen equivalent of 'withWorkspaces' lets you more easily define keys that
move/swap between screens.

Also, rename wsKeyspecs to wsKeys, and make a couple of doc tweaks.
2014-10-01 07:52:50 +00:00
Anton Vorontsov
27f4d5dafe Implement proper handling of dynamically changing hostname
The module implements a proper way of finding out whether the window is
remote or local.

Just checking for a hostname and WM_CLIENT_MACHINE being equal is often
not enough because the hostname is a changing subject (without any
established notification mechanisms), and thus WM_CLIENT_MACHINE and the
hostname can diverge even for a local window.

This module solves the problem. As soon as there is a new window created,
we check the hostname and WM_CLIENT_MACHINE, and then we cache the result
into the XMONAD_REMOTE property.

Notice that XMonad itself does not know anything about hostnames, nor does
it have any dependency on Network.* modules. For this module it is not a
problem: you can provide a mean to get the hostname through your config
file (see usage). Or, if you don't like the hassle of handling dynamic
hostnames (suppose your hostname never changes), it is also fine: this
module will fallback to using environment variables.
2014-09-01 07:21:58 +00:00
Anton Vorontsov
b2a885fe5a Add Stoppable layout for power saving
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.

Note that the stopped application won't be able to communicate with X11
clipboard. For this, the module actually stops applications after a
certain delay, giving a chance for a user to complete copy-paste sequence.
By default, the delay equals to 15 seconds, it is configurable via
'Stoppable' constructor.

The stoppable modifier prepends a mark (by default equals to "Stoppable")
to the layout description (alternatively, you can choose your own mark and
use it with 'Stoppable' constructor). The stoppable layout (identified by
a mark) spans to multiple workspaces, letting you to create groups of
stoppable workspaces that only stop processes when none of the workspaces
are visible, and conversely, unfreezing all processes even if one of the
stoppable workspaces are visible.

To stop the process we use signals, which works for most cases. For
processes that tinker with signal handling (debuggers), another
(Linux-centric) approach may be used. See
https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt
2014-09-01 07:21:41 +00:00
Devin Mullins
12ec2d0be4 X.C.Prime: doc changes 2014-09-25 20:30:37 +00:00
Devin Mullins
74c3f059b0 X.C.Prime: add withWorkspaces et al.
This allows easier configuration of workspaces and their keybindings. Required
generalizing the 'Prime' type, so lots of other lines changed in rather trivial
ways.
2014-09-25 20:30:34 +00:00
Devin Mullins
cbcd42dc83 X.C.Prime: add ifThenElse binding
This is necessary for if-then-else support in the user's config.
2014-09-24 19:15:09 +00:00
Devin Mullins
c5290be3c8 X.C.Prime: doc fixes 2014-09-15 08:06:01 +00:00
Devin Mullins
972ee2c19f X.C.Prime: fix 'def' hyperlink in doc 2014-09-14 07:53:52 +00:00
Devin Mullins
babbd208a6 XMonad.Config.Prime, a do-notation for config
Note that the use of RebindableSyntax is because of the need to vary the
layoutHook type throughout the config. The alternative, using the existential
Layout type, was rejected because it required TemplateHaskell in order to look
nice, and TemplateHaskell is not portable.

I've tried to make a version of (>>) that also worked on normal monads, but
have had no luck as of yet. Maybe some intrepid soul can add it later.
2014-09-14 06:48:28 +00:00
me
4ef0beab55 X.P.Shell: fix doc typo 2013-03-17 11:55:16 +00:00
nwfilardo
c073651cc2 reverse workspaces, so that switching to a dynamic workspace group restores the focus to the screen that was focused at group creation time 2014-09-13 17:41:18 +00:00
me
4efaa673fe add filepath dependency, needed by new X.P.Pass module 2014-09-13 07:09:26 +00:00
eniotna.t
9f453fdb58 add-new-xmonad-prompt-pass
This module provides 3 <XMonad.Prompt> to ease passwords manipulation (generate, read, remove):

- one to lookup passwords in the password-storage.

- one to generate a password for a given password label that the user inputs.

- one to delete a stored password for a given password label that the user inputs.

All those prompts benefit from the completion system provided by the module <XMonad.Prompt>.

The password store is setuped through an environment variable PASSWORD_STORE_DIR.
If this is set, use the content of the variable.
Otherwise, the password store is located on user's home @$HOME\/.password-store@.


Source:

- The password storage implementation is <http://git.zx2c4.com/password-store the password-store cli>.

- Inspired from <http://babushk.in/posts/combining-xmonad-and-pass.html>
2014-08-29 13:19:28 +00:00
Adam Vogt
6137b1e2ff use Data.Map instead of Data.Map.Strict to support containers < 0.5 2014-08-15 04:31:41 +00:00
allbery.b
7d4a083906 config-mate
Initial support for the Mate desktop environment (http://mate-desktop.org).
Based on existing Gnome 2 support, since Mate is a maintained fork of
Gnome 2.
2014-08-03 02:06:59 +00:00
allbery.b
56c6b9fef5 debug-managehook
A set of hooks, and convenience combinators, to help with ManageHook debugging.
Ordinary users may well want to use debugManageHookOn in normal configs,
specifying a key sequence which can be pressed before running a command in
order to capture debug information just for that command's main window.

This is especially useful when trying to diagnose issues such as programs
that do not play well with SpawnOn, or ManageHook matching on 'title' when
the program does not set the window title until after it is mapped.
2014-08-03 02:06:01 +00:00
allbery.b
ec0fb3ba8a debug-debug
Various fixes and enhancements to DebugWindow and DebugStack. ManageDebug
requires these fixes, but some of them are significant even if not using
ManageDebug.
2014-08-03 02:05:30 +00:00
Adam Vogt
11265ad69b derive Applicative instances to suppress AMP warning 2014-07-10 16:39:50 +00:00
Adam Vogt
8ff856a761 clean up cabal file and drop support for base < 3 2014-07-10 01:32:55 +00:00
eniotna.t
1173c6c54f add-duck-duck-go-search-engine 2014-06-17 17:42:46 +00:00
gwern
eca9d7318e XSelection: getSelection: fix connection exhaustion bug (issue #573); include warning 2014-06-01 02:50:19 +00:00
md143rbh7f
72a537cf46 Fix dbus-send call in XMonad.Config.Gnome
dbus-send --print-reply=string is invalid, but it was silently ignored until recently:
http://cgit.freedesktop.org/dbus/dbus/commit/tools/dbus-send.c?id=c690ee4351f99ed5e629ffcf5f4a2edcd418d103
I've changed XMonad.Config.Gnome to run --print-reply=literal, since that's what the old behavior was.
2014-01-29 03:21:14 +00:00
Adam Vogt
2f44f16fac warning police (unused variables) 2014-05-05 00:12:42 +00:00
linxray
2b7add99aa This patch makes the Ssh extension works with **user** arguments in ssh, .e.g ssh admin@localhost. 2014-05-04 09:11:20 +00:00
Adam Vogt
c9b63a8f40 remove trailing whitespace in L.BinarySpacePartition 2014-05-01 01:19:43 +00:00
Adam Vogt
fb7ca05a63 replace Bound with the equivalent Direction2D 2014-05-01 01:15:40 +00:00
Adam Vogt
fcf0545475 remove unused extension in BSP 2014-05-01 01:14:55 +00:00
benweitzman
ec56f2c47c Add BinarySpacePartition layout 2014-04-30 20:58:48 +00:00
Brent Yorgey
25b9a25925 X.Actions.DynamicWorkspaceGroups: export new function addRawWSGroup 2014-04-28 14:29:01 +00:00
Adam Vogt
6a2ad3f1ee Remove unneeded context with the IfMax layout instance
Extra constraints on instances are about as useful as -XDataTypeContexts
2014-04-22 22:11:05 +00:00
nrujac
e2ff50687e Adding side tabs and replacing TabbarLocation with Direction2D. 2014-02-19 20:08:11 +00:00
Daniel Wagner
fb3b9f59e4 warning police 2014-03-16 18:37:47 +00:00
Dmitry Bogatov
ca9961c1ca New module: XMonad.Util.WindowState
Save almost arbitary data per window
2014-02-18 10:02:29 +00:00
nrujac
0f6bed2ff7 Add side tabs to the tabbed layout. 2014-02-13 21:52:47 +00:00
cwills.dev
c1b8674aa0 SpawnNamedPipe hlint cleanup 2014-02-02 21:36:13 +00:00
cwills.dev
d88153d3be document and cleanup SpawnNamedPipe 2014-02-02 21:10:00 +00:00
cwills.dev
6b46603147 Added SpawnNamedPipe 2014-02-02 14:34:15 +00:00
md143rbh7f
9403542db0 Make commandToComplete in XMonad.Prompt.Shell complete last word
The following change from 2013-02-09 breaks shell completion for me:
    hunk ./XMonad/Prompt/Shell.hs 65
    +    commandToComplete _ c = c

It seems to be passing the entire string into compgen in order to get the file completions, but it should only pass the last word. I propose reverting this change. Comments are appreciated.
2014-01-30 20:00:50 +00:00
Daniel Wagner
35ed0601f4 expose and document X.L.IndependentScreens.marshallSort 2014-01-28 21:28:44 +00:00
Adam Vogt
df824edf5f ServerMode properly indent 2013-12-19 20:14:40 +00:00
Adam Vogt
78ed2e1a9e remove ServerMode tabs 2013-12-19 20:10:00 +00:00
Adam Vogt
f453a9a375 fix -Wall ServerMode 2013-12-19 18:10:30 +00:00
Adam Vogt
c6b91b546e documentation note that ServerMode is similar to wmctrl 2013-12-19 18:07:48 +00:00
polson2
7ccac6a9a0 Generalized XMonad.Hooks.ServerMode 2013-12-16 02:51:00 +00:00
Ilya Portnov
f10a18670a IfMax-Layout
This adds a new ("conditional") layout, IfMax, which simply runs one layout, if there are <= N windows, and else runs another layout.
2013-12-01 07:26:34 +00:00
Adam Vogt
ab3f5b3d5d fix UrgencyHook and add filterUrgencyHook 2013-09-24 22:47:38 +00:00
Adam Vogt
075b7d69ed export XMonad.Hooks.UrgencyHook.clearUrgency (issue 533) 2013-09-23 03:13:49 +00:00
Daniel Wagner
95372520bb minor documentation fix: manageDocks doesn't do anything with struts, so don't claim it does 2013-08-14 12:51:06 +00:00
Daniel Wagner
0906634f3a don't pretend to be LG3D in X.C.Dmwit because this confuses modern GTK 2013-08-13 21:16:36 +00:00
Liyang HU
fd23bd692b XMonad.Actions.UpdatePointer: generalise updatePointer 2013-07-30 07:10:07 +00:00
Liyang HU
2fe30c6730 XMonad.Actions.UpdatePointer: document TowardsCentre 2013-07-30 05:37:46 +00:00
Adam Vogt
8f712f0a04 Haddock formatting in H.Minimize 2013-07-23 15:56:58 +00:00
Adam Vogt
1a916d1c57 Bump version (and xmonad dependency) to 0.12
This makes a breakage due to missing patches in core a bit more obvious.
Previously you would have a build failure regarding some missing identifiers
(def re-exported by XMonad from Data.Default), while after applying this patch
it will be clear that xmonad-core needs to be updated.
2013-07-20 20:58:57 +00:00
Adam Vogt
7246defb90 Fix issue 551 by also getting manpath without -g flag.
Instead of taking Ondrej's approach of figuring out which man (man-db or
http://primates.ximian.com/~flucifredi/man/) is used by the system, just try
both sets of flags.
2013-07-16 03:05:36 +00:00
Adam Vogt
d3b2a01e3d Escape dzen markup and remove xmobar tags from window titles by default.
The issue was that window titles, such as those set by, for example a browser,
could set the window title to display something like

   <action=malicious shell command>normal title</action>

Which could be executed by xmobar (or dzen).

This adds a ppTitleSanitize which does the above functions. This way when users
override ppTitle, the benefits are not lost.

Thanks to Raúl Benencia and Joachim Breitner for bringing this to my attention.
2013-07-08 14:48:13 +00:00
gopsychonauts
129e98773e DynamicBars-use-ExtensibleState
Hooks.DynamicBars was previously using an MVar and the unsafePerformIO hack (
http://www.haskell.org/haskellwiki/Top_level_mutable_state ) to store bar
state. Since ExtensibleState exists to solve these sorts of problems, I've
switched the file over to use unsafePerformIO instead.

Some functions' types had to be changed to allow access to XState, but the
public API is unchanged.
2013-06-18 07:47:55 +00:00
Thomas Tuegel
7958f8905e Catch exceptions when finding commands on PATH in Prompt.Shell 2013-06-16 23:02:19 +00:00
Adam Vogt
646090a3d9 Fix haddock parse error in X.A.LinkWorkspaces 2013-05-28 13:34:48 +00:00
Daniel Wagner
0f1b6fb772 use Data.Default wherever possible, and deprecate the things it replaces 2013-05-28 01:39:09 +00:00
Daniel Wagner
daa2731d3d eliminate references to defaultConfig 2013-05-28 00:58:25 +00:00
Daniel Wagner
0287b2861c minimal change needed to get xmonad-contrib to build with xmonad's data-default patch 2013-05-28 00:10:40 +00:00
Francesco Ariis
e8259ebd43 Remove unneeded XSync call in Layout.ShowWName 2013-05-17 15:33:41 +00:00
Adam Vogt
12b91b9630 Remove misleading comment: we definitely don't support ghc-6.6 anymore 2013-05-14 21:58:51 +00:00
Adam Vogt
546b582a3d Fix module name in comment of X.L.Fullscreen 2013-05-14 21:57:27 +00:00
Adam Vogt
91a5d13005 Minor update to cabal file (adding modules & maintainership) 2013-05-14 21:56:32 +00:00
Adam Vogt
31ec8cc26a Remove trailing whitespace in X.A.LinkWorkspaces 2013-05-14 21:54:21 +00:00
quesel
0fcb4ae238 Update documentation of LinkWorkspaces Module 2011-03-28 07:28:13 +00:00
quesel
3722f48da9 Added a module for linking workspaces
This module provides a way to link certain workspaces in a multihead setup.
That way, when switching to the first one the other heads display the linked
workspaces.
2011-02-10 16:50:18 +00:00
Adam Vogt
00be056a1b Cache results from calcGap in ManageDocks
http://www.haskell.org/pipermail/xmonad/2013-April/013670.html
2013-04-25 15:58:11 +00:00
Adam Vogt
eae925fc29 Remove unnecessary contexts from L.MultiToggle 2013-02-17 16:33:56 +00:00
gopsychonauts
faa61bbbab Generalises modWorkspace to take any layout-transforming function
modWorkspace already was capable of modifying the layout with an arbitrary
layout -> layout function, but its original type restricted it such that it
could only apply a single LayoutModifier; this was often inconvenient, as for
example it was not possible simply to compose LayoutModifiers for use with
modWorkspace.

This patch also reimplements onWorkspaces in terms of modWorkspaces, since with
the latter's less restrictive type this is now possible.
2013-05-01 15:14:25 +00:00
Daniel Wagner
ac8aefbc92 since XMonad.Config.Dmwit mentions xmobar, we should include the associated .xmobarrc file 2013-05-03 19:40:55 +00:00
Daniel Wagner
469ff726a4 warning police 2013-05-02 01:27:00 +00:00
Daniel Wagner
e11d97137e XMonad.Config.Dmwit 2013-05-02 01:21:32 +00:00
Daniel Wagner
a56a135313 minor fixes to the haddock markup in X.L.IndependentScreens 2013-04-11 19:38:49 +00:00
Daniel Wagner
faf0997881 add whenCurrentOn to X.L.IndependentScreens 2013-04-08 22:52:51 +00:00
Paul Fertser
7dda5f976f Allow to specify the initial gaps' states in X.L.Gaps 2013-02-22 07:22:32 +00:00
Daniel Wagner
493db20cf0 should bump X11 dependency, too, to make sure we have getAtomName 2013-02-25 18:05:27 +00:00
Daniel Wagner
5c04a573db getAtomName is now defined in the X11 library 2013-02-25 18:03:23 +00:00
Paul Fertser
8bfe148416 Allow to limit maximum row count in X.Prompt completion window
On a keyboard-less device (such as a smartphone), where one has to use
an on-screen keyboard, the maximum completion window height must be
limited to avoid overlapping the keyboard.
2013-02-21 12:20:50 +00:00
Adam Vogt
945714f250 Note in U.NameActions that xmonad core can list default keys now 2013-02-17 23:30:26 +00:00
Adam Vogt
10ee484a59 Export U.NamedActions.addDescrKeys per evaryont's request. 2013-02-17 23:26:19 +00:00
Maarten de Vries
7e9c986217 Add EWMH DEMANDS_ATTENTION support to UrgencyHook.
Add support for the _NET_WM_STATE_DEMANDS_ATTENTION atom
by treating it the same way as the WM_HINTS urgency flag.
2013-02-12 18:12:29 +00:00
Adam Vogt
0aeef31c5d Unconditionally set _NET_WORKAREA in ManageDocks 2013-01-17 18:08:51 +00:00
c.lopez
34800741e5 spawn command when no completion is available (if alwaysHighlight is True); changes commandToComplete in Prompt/Shell to complete the whole word instead of using getLastWord 2013-02-09 19:04:56 +00:00
matthewhague
a45d8d38a6 order-unindexed-ws-last
Changes the WorkspaceCompare module's comparison by index to put workspaces without an index last (rather than first).
2012-07-03 22:27:26 +00:00
Adam Vogt
c0b0d52678 SpawnOn modification for issue 523
This moves the function to help clean up the `Spawner' to the ManageHook
rather than in functions like spawnOn. Probably it makes no difference, the
reason is because there's one manageSpawn function but many different so this
way there are less functions to write.
2013-01-14 01:46:42 +00:00
Adam Vogt
a33f355232 Update L.TrackFloating.useTransient example code
Suggest useTransient goes to the right of trackFloating which is the
configuration actually tested.
2013-01-12 04:12:39 +00:00
Adam Vogt
ced8f5e0f0 Adapt ideas of issue 306 patch to a new modifier in L.TrackFloating 2013-01-12 03:57:01 +00:00
Dmitri Iouchtchenko
498a50d109 Make X.A.CycleWS not rely on hidden WS order 2013-01-09 02:33:28 +00:00
Dmitri Iouchtchenko
5d93450b5e Add X.H.WorkspaceHistory 2013-01-09 02:33:07 +00:00
Dmitri Iouchtchenko
9b6ed4c505 Allow removing arbitrary workspaces 2012-12-31 21:43:43 +00:00
Dmitri Iouchtchenko
d83442b8eb Remove first-hidden restriction from X.A.DynamicWorkspaces.removeWorkspace' 2012-12-31 21:41:48 +00:00
Adam Vogt
78d44079c2 Add authorspellings file for `darcs show authors'.
This authorspellings file includes a couple people who've contributed to xmonad
(not XMonadContrib). When people have multiple addresses, the most recent one
has been picked.
2013-01-01 04:00:31 +00:00
377 changed files with 35762 additions and 8413 deletions

30
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,30 @@
### Problem Description
Describe the problem you are having and what you expect to happen
instead.
### Steps to Reproduce
Give detailed step-by-step instructions on how to reproduce the problem.
### Configuration File
Please include the smallest _full_ configuration file that reproduces
the problem you are experiencing:
```haskell
module Main (main) where
import XMonad
main :: IO ()
main = xmonad def
```
### Checklist
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- I tested my configuration
- [ ] With `xmonad` version XXX (commit XXX if using git)
- [ ] With `xmonad-contrib` version XXX (commit XXX if using git)

13
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,13 @@
### Description
Include a description for your changes, including the motivation
behind them.
### Checklist
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- [ ] I've considered how to best test these changes (property, unit,
manually, ...) and concluded: XXX
- [ ] I updated the `CHANGES.md` file

6
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -0,0 +1,134 @@
Piggy-back on the haskell-ci workflow for automatic releases to Hackage.
This extends the workflow with two additional triggers:
* When the Haskell-CI workflow is triggered manually with a non-empty version
input (matching the version in the cabal file), a candidate release is
uploaded to Hackage and docs are submitted for it as Hackage can't build
them itself (https://github.com/haskell/hackage-server/issues/925).
Note that promoting the candidate on Hackage discards the uploaded docs
(https://github.com/haskell/hackage-server/issues/70). Don't do that.
* When a release is created on GitHub, a final release is uploaded to Hackage
and docs are submitted for it.
The automation uses a special Hackage user: https://hackage.haskell.org/user/xmonad
and each repo (X11, xmonad, xmonad-contrib) has its own HACKAGE_API_KEY token
set in GitHub repository secrets.
--- .github/workflows/haskell-ci.yml.orig
+++ .github/workflows/haskell-ci.yml
@@ -14,8 +14,15 @@
#
name: Haskell-CI
on:
- - push
- - pull_request
+ push:
+ pull_request:
+ release:
+ types:
+ - published
+ workflow_dispatch:
+ inputs:
+ version:
+ description: candidate version (must match version in cabal file)
jobs:
linux:
name: Haskell-CI - Linux - ${{ matrix.compiler }}
@@ -33,6 +40,7 @@
compilerVersion: 9.8.1
setup-method: ghcup
allow-failure: false
+ upload: true
- compiler: ghc-9.6.4
compilerKind: ghc
compilerVersion: 9.6.4
@@ -257,6 +265,10 @@
- name: haddock
run: |
$CABAL v2-haddock --disable-documentation $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
+ - name: haddock for hackage
+ if: matrix.upload
+ run: |
+ $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH --haddock-for-hackage --builddir $GITHUB_WORKSPACE/haddock all
- name: unconstrained build
run: |
rm -f cabal.project.local
@@ -267,3 +279,75 @@
with:
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
path: ~/.cabal/store
+ - name: upload artifacts (sdist)
+ if: matrix.upload
+ uses: actions/upload-artifact@v3
+ with:
+ path: ${{ github.workspace }}/sdist/*.tar.gz
+ - name: upload artifacts (haddock)
+ if: matrix.upload
+ uses: actions/upload-artifact@v3
+ with:
+ path: ${{ github.workspace }}/haddock/*-docs.tar.gz
+ - name: hackage upload (candidate)
+ if: matrix.upload && github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
+ shell: bash
+ run: |
+ set -ex
+ PACKAGE_VERSION="${PACKAGE_VERSION#v}"
+ res=$(
+ curl \
+ --silent --show-error --output /dev/stderr --write-out '%{http_code}' \
+ --header "Accept: text/plain" \
+ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
+ --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \
+ https://hackage.haskell.org/packages/candidates/
+ )
+ [[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available
+ res=$(
+ curl \
+ --silent --show-error --output /dev/stderr --write-out '%{http_code}' \
+ -X PUT \
+ --header "Accept: text/plain" \
+ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
+ --header "Content-Type: application/x-tar" \
+ --header "Content-Encoding: gzip" \
+ --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \
+ https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/candidate/docs
+ )
+ [[ $res == 2?? ]]
+ env:
+ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
+ PACKAGE_NAME: ${{ github.event.repository.name }}
+ PACKAGE_VERSION: ${{ github.event.inputs.version }}
+ - name: hackage upload (release)
+ if: matrix.upload && github.event_name == 'release'
+ shell: bash
+ run: |
+ set -ex
+ PACKAGE_VERSION="${PACKAGE_VERSION#v}"
+ res=$(
+ curl \
+ --silent --show-error --output /dev/stderr --write-out '%{http_code}' \
+ --header "Accept: text/plain" \
+ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
+ --form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \
+ https://hackage.haskell.org/packages/
+ )
+ [[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available
+ res=$(
+ curl \
+ --silent --show-error --output /dev/stderr --write-out '%{http_code}' \
+ -X PUT \
+ --header "Accept: text/plain" \
+ --header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
+ --header "Content-Type: application/x-tar" \
+ --header "Content-Encoding: gzip" \
+ --data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \
+ https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/docs
+ )
+ [[ $res == 2?? ]]
+ env:
+ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
+ PACKAGE_NAME: ${{ github.event.repository.name }}
+ PACKAGE_VERSION: ${{ github.event.release.tag_name }}

341
.github/workflows/haskell-ci.yml vendored Normal file
View File

@@ -0,0 +1,341 @@
# This GitHub workflow config has been generated by a script via
#
# haskell-ci 'github' 'cabal.project'
#
# To regenerate the script (for example after adjusting tested-with) run
#
# haskell-ci regenerate
#
# For more information, see https://github.com/haskell-CI/haskell-ci
#
# version: 0.17.20240109
#
# REGENDATA ("0.17.20240109",["github","cabal.project"])
#
name: Haskell-CI
on:
push:
pull_request:
release:
types:
- published
workflow_dispatch:
inputs:
version:
description: candidate version (must match version in cabal file)
jobs:
linux:
name: Haskell-CI - Linux - ${{ matrix.compiler }}
runs-on: ubuntu-20.04
timeout-minutes:
60
container:
image: buildpack-deps:bionic
continue-on-error: ${{ matrix.allow-failure }}
strategy:
matrix:
include:
- compiler: ghc-9.8.1
compilerKind: ghc
compilerVersion: 9.8.1
setup-method: ghcup
allow-failure: false
upload: true
- compiler: ghc-9.6.4
compilerKind: ghc
compilerVersion: 9.6.4
setup-method: ghcup
allow-failure: false
- compiler: ghc-9.4.8
compilerKind: ghc
compilerVersion: 9.4.8
setup-method: ghcup
allow-failure: false
- compiler: ghc-9.2.8
compilerKind: ghc
compilerVersion: 9.2.8
setup-method: ghcup
allow-failure: false
- compiler: ghc-9.0.2
compilerKind: ghc
compilerVersion: 9.0.2
setup-method: ghcup
allow-failure: false
- compiler: ghc-8.10.7
compilerKind: ghc
compilerVersion: 8.10.7
setup-method: ghcup
allow-failure: false
- compiler: ghc-8.8.4
compilerKind: ghc
compilerVersion: 8.8.4
setup-method: hvr-ppa
allow-failure: false
- compiler: ghc-8.6.5
compilerKind: ghc
compilerVersion: 8.6.5
setup-method: hvr-ppa
allow-failure: false
fail-fast: false
steps:
- name: apt
run: |
apt-get update
apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5
if [ "${{ matrix.setup-method }}" = ghcup ]; then
mkdir -p "$HOME/.ghcup/bin"
curl -sL https://downloads.haskell.org/ghcup/0.1.20.0/x86_64-linux-ghcup-0.1.20.0 > "$HOME/.ghcup/bin/ghcup"
chmod a+x "$HOME/.ghcup/bin/ghcup"
"$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false)
"$HOME/.ghcup/bin/ghcup" install cabal 3.10.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
apt-get update
apt-get install -y libx11-dev libxext-dev libxft-dev libxinerama-dev libxrandr-dev libxss-dev
else
apt-add-repository -y 'ppa:hvr/ghc'
apt-get update
apt-get install -y "$HCNAME" libx11-dev libxext-dev libxft-dev libxinerama-dev libxrandr-dev libxss-dev
mkdir -p "$HOME/.ghcup/bin"
curl -sL https://downloads.haskell.org/ghcup/0.1.20.0/x86_64-linux-ghcup-0.1.20.0 > "$HOME/.ghcup/bin/ghcup"
chmod a+x "$HOME/.ghcup/bin/ghcup"
"$HOME/.ghcup/bin/ghcup" install cabal 3.10.2.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
fi
env:
HCKIND: ${{ matrix.compilerKind }}
HCNAME: ${{ matrix.compiler }}
HCVER: ${{ matrix.compilerVersion }}
- name: Set PATH and environment variables
run: |
echo "$HOME/.cabal/bin" >> $GITHUB_PATH
echo "LANG=C.UTF-8" >> "$GITHUB_ENV"
echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV"
echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV"
HCDIR=/opt/$HCKIND/$HCVER
if [ "${{ matrix.setup-method }}" = ghcup ]; then
HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER")
HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#')
HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#')
echo "HC=$HC" >> "$GITHUB_ENV"
echo "HCPKG=$HCPKG" >> "$GITHUB_ENV"
echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV"
echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.2.0 -vnormal+nowrap" >> "$GITHUB_ENV"
else
HC=$HCDIR/bin/$HCKIND
echo "HC=$HC" >> "$GITHUB_ENV"
echo "HCPKG=$HCDIR/bin/$HCKIND-pkg" >> "$GITHUB_ENV"
echo "HADDOCK=$HCDIR/bin/haddock" >> "$GITHUB_ENV"
echo "CABAL=$HOME/.ghcup/bin/cabal-3.10.2.0 -vnormal+nowrap" >> "$GITHUB_ENV"
fi
HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')
echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV"
echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV"
echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV"
echo "HEADHACKAGE=false" >> "$GITHUB_ENV"
echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV"
echo "GHCJSARITH=0" >> "$GITHUB_ENV"
env:
HCKIND: ${{ matrix.compilerKind }}
HCNAME: ${{ matrix.compiler }}
HCVER: ${{ matrix.compilerVersion }}
- name: env
run: |
env
- name: write cabal config
run: |
mkdir -p $CABAL_DIR
cat >> $CABAL_CONFIG <<EOF
remote-build-reporting: anonymous
write-ghc-environment-files: never
remote-repo-cache: $CABAL_DIR/packages
logs-dir: $CABAL_DIR/logs
world-file: $CABAL_DIR/world
extra-prog-path: $CABAL_DIR/bin
symlink-bindir: $CABAL_DIR/bin
installdir: $CABAL_DIR/bin
build-summary: $CABAL_DIR/logs/build.log
store-dir: $CABAL_DIR/store
install-dirs user
prefix: $CABAL_DIR
repository hackage.haskell.org
url: http://hackage.haskell.org/
EOF
cat >> $CABAL_CONFIG <<EOF
program-default-options
ghc-options: $GHCJOBS +RTS -M3G -RTS
EOF
cat $CABAL_CONFIG
- name: versions
run: |
$HC --version || true
$HC --print-project-git-commit-id || true
$CABAL --version || true
- name: update cabal index
run: |
$CABAL v2-update -v
- name: install cabal-plan
run: |
mkdir -p $HOME/.cabal/bin
curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.7.3.0/cabal-plan-0.7.3.0-x86_64-linux.xz > cabal-plan.xz
echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c -
xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan
rm -f cabal-plan.xz
chmod a+x $HOME/.cabal/bin/cabal-plan
cabal-plan --version
- name: checkout
uses: actions/checkout@v3
with:
path: source
- name: initial cabal.project for sdist
run: |
touch cabal.project
echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project
cat cabal.project
- name: sdist
run: |
mkdir -p sdist
$CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist
- name: unpack
run: |
mkdir -p unpacked
find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \;
- name: generate cabal.project
run: |
PKGDIR_xmonad_contrib="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/xmonad-contrib-[0-9.]*')"
echo "PKGDIR_xmonad_contrib=${PKGDIR_xmonad_contrib}" >> "$GITHUB_ENV"
rm -f cabal.project cabal.project.local
touch cabal.project
touch cabal.project.local
echo "packages: ${PKGDIR_xmonad_contrib}" >> cabal.project
echo "package xmonad-contrib" >> cabal.project
echo " ghc-options: -Werror=missing-methods" >> cabal.project
cat >> cabal.project <<EOF
source-repository-package
type: git
location: https://github.com/xmonad/xmonad
branch: master
optimization: False
package xmonad-contrib
flags: +pedantic
ghc-options: -j
EOF
$HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: $_ installed\n" unless /^(xmonad-contrib)$/; }' >> cabal.project.local
cat cabal.project
cat cabal.project.local
- name: dump install plan
run: |
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
cabal-plan
- name: restore cache
uses: actions/cache/restore@v3
with:
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
path: ~/.cabal/store
restore-keys: ${{ runner.os }}-${{ matrix.compiler }}-
- name: install dependencies
run: |
$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all
- name: build w/o tests
run: |
$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
- name: build
run: |
$CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always
- name: tests
run: |
$CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct
- name: cabal check
run: |
cd ${PKGDIR_xmonad_contrib} || false
${CABAL} -vnormal check
- name: haddock
run: |
$CABAL v2-haddock --disable-documentation $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
- name: haddock for hackage
if: matrix.upload
run: |
$CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH --haddock-for-hackage --builddir $GITHUB_WORKSPACE/haddock all
- name: unconstrained build
run: |
rm -f cabal.project.local
$CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
- name: save cache
uses: actions/cache/save@v3
if: always()
with:
key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
path: ~/.cabal/store
- name: upload artifacts (sdist)
if: matrix.upload
uses: actions/upload-artifact@v3
with:
path: ${{ github.workspace }}/sdist/*.tar.gz
- name: upload artifacts (haddock)
if: matrix.upload
uses: actions/upload-artifact@v3
with:
path: ${{ github.workspace }}/haddock/*-docs.tar.gz
- name: hackage upload (candidate)
if: matrix.upload && github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
shell: bash
run: |
set -ex
PACKAGE_VERSION="${PACKAGE_VERSION#v}"
res=$(
curl \
--silent --show-error --output /dev/stderr --write-out '%{http_code}' \
--header "Accept: text/plain" \
--header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
--form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \
https://hackage.haskell.org/packages/candidates/
)
[[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available
res=$(
curl \
--silent --show-error --output /dev/stderr --write-out '%{http_code}' \
-X PUT \
--header "Accept: text/plain" \
--header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
--header "Content-Type: application/x-tar" \
--header "Content-Encoding: gzip" \
--data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \
https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/candidate/docs
)
[[ $res == 2?? ]]
env:
HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
PACKAGE_NAME: ${{ github.event.repository.name }}
PACKAGE_VERSION: ${{ github.event.inputs.version }}
- name: hackage upload (release)
if: matrix.upload && github.event_name == 'release'
shell: bash
run: |
set -ex
PACKAGE_VERSION="${PACKAGE_VERSION#v}"
res=$(
curl \
--silent --show-error --output /dev/stderr --write-out '%{http_code}' \
--header "Accept: text/plain" \
--header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
--form package=@"${GITHUB_WORKSPACE}/sdist/${PACKAGE_NAME}-${PACKAGE_VERSION}.tar.gz" \
https://hackage.haskell.org/packages/
)
[[ $res == 2?? ]] # TODO: --fail-with-body once curl 7.76.0 is available
res=$(
curl \
--silent --show-error --output /dev/stderr --write-out '%{http_code}' \
-X PUT \
--header "Accept: text/plain" \
--header "Authorization: X-ApiKey $HACKAGE_API_KEY" \
--header "Content-Type: application/x-tar" \
--header "Content-Encoding: gzip" \
--data-binary @"${GITHUB_WORKSPACE}/haddock/${PACKAGE_NAME}-${PACKAGE_VERSION}-docs.tar.gz" \
https://hackage.haskell.org/package/${PACKAGE_NAME}-${PACKAGE_VERSION}/docs
)
[[ $res == 2?? ]]
env:
HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
PACKAGE_NAME: ${{ github.event.repository.name }}
PACKAGE_VERSION: ${{ github.event.release.tag_name }}

22
.github/workflows/hlint.yaml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: hlint
on:
push:
pull_request:
jobs:
hlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 'Set up HLint'
uses: haskell-actions/hlint-setup@v2
with:
version: '3.5'
- name: 'Run HLint'
uses: haskell-actions/hlint-run@v2
with:
path: '["XMonad/", "tests/", "scripts/"]'
fail-on: status

28
.github/workflows/nix.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Nix
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-20.04 # FIXME
name: Nix Flake - Linux
permissions:
contents: read
steps:
- name: Install Nix
uses: cachix/install-nix-action@v25
with:
install_url: https://nixos-nix-install-tests.cachix.org/serve/i6laym9jw3wg9mw6ncyrk6gjx4l34vvx/install
install_options: '--tarball-url-prefix https://nixos-nix-install-tests.cachix.org/serve'
extra_nix_config: |
experimental-features = nix-command flakes
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Clone project
uses: actions/checkout@v4
- name: Build
# "nix build" builds with full optimization and includes a profiling
# build, so just the build of xmonad-contrib itself takes 3 minutes.
# As a workaround, we invoke cabal manually here.
run: nix develop -c cabal v2-build -O0 -j

51
.github/workflows/packdeps.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Packdeps
on:
workflow_dispatch:
schedule:
# Run every Saturday
- cron: '0 3 * * 6'
jobs:
packdeps:
name: Packdeps
runs-on: ubuntu-latest
steps:
- name: Clone project
uses: actions/checkout@v4
- name: Setup Haskell
uses: haskell-actions/setup@v2
with:
# packdeps doesn't build with newer as of 2021-10
ghc-version: '8.8'
- name: Install packdeps
run: |
set -ex
cd # go somewhere without a cabal.project
cabal install packdeps
- name: Check package bounds (all)
continue-on-error: true
run: |
set -ex
packdeps \
--exclude X11 \
--exclude xmonad \
*.cabal
- name: Check package bounds (preferred)
run: |
set -ex
packdeps \
--preferred \
--exclude X11 \
--exclude xmonad \
*.cabal
workflow-keepalive:
runs-on: ubuntu-latest
steps:
- name: Re-enable workflow
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api -X PUT repos/${{ github.repository }}/actions/workflows/packdeps.yml/enable

93
.github/workflows/stack.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: Stack
on:
push:
pull_request:
jobs:
build:
name: Stack CI - Linux - ${{ matrix.resolver }} - ${{ matrix.yaml }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- resolver: lts-14 # GHC 8.6
yaml: stack.yaml
- resolver: lts-14 # GHC 8.6
yaml: stack-master.yaml
- resolver: lts-16 # GHC 8.8
yaml: stack-master.yaml
- resolver: lts-18 # GHC 8.10
yaml: stack-master.yaml
- resolver: lts-19 # GHC 9.0
yaml: stack-master.yaml
- resolver: lts-20 # GHC 9.2
yaml: stack-master.yaml
- resolver: lts-21 # GHC 9.4
yaml: stack.yaml
- resolver: lts-21 # GHC 9.4
yaml: stack-master.yaml
steps:
- name: Clone project
uses: actions/checkout@v4
- name: Install C dependencies
run: |
set -ex
sudo apt update -y
sudo apt install -y \
libx11-dev \
libxext-dev \
libxft-dev \
libxinerama-dev \
libxrandr-dev \
libxss-dev \
#
- name: Refresh caches once a month
id: cache-date
# GHA writes caches on the first miss and then never updates them again;
# force updating the cache at least once a month. Additionally, the
# date is prefixed with an epoch number to let us manually refresh the
# cache when needed. This is a workaround for https://github.com/actions/cache/issues/2
run: |
date +date=1-%Y-%m >> $GITHUB_OUTPUT
- name: Cache Haskell package metadata
uses: actions/cache@v4
with:
path: ~/.stack/pantry
key: stack-pantry-${{ runner.os }}-${{ steps.cache-date.outputs.date }}
- name: Cache Haskell dependencies
uses: actions/cache@v4
with:
path: |
~/.stack/*
!~/.stack/pantry
!~/.stack/programs
key: stack-${{ runner.os }}-${{ matrix.resolver }}-${{ steps.cache-date.outputs.date }}-${{ hashFiles(matrix.yaml) }}-${{ hashFiles('*.cabal') }}
restore-keys: |
stack-${{ runner.os }}-${{ matrix.resolver }}-${{ steps.cache-date.outputs.date }}-${{ hashFiles(matrix.yaml) }}-
stack-${{ runner.os }}-${{ matrix.resolver }}-${{ steps.cache-date.outputs.date }}-
- name: Update hackage index
# always update index to prevent the shared ~/.stack/pantry cache from being empty
run: |
set -ex
stack update
- name: Build and test
run: |
set -ex
# workaround for stack/pantry caching of github archives
sed -e "s/@{today}/@{$(date -u --iso-8601=seconds)}/" -i ${{ matrix.yaml }}
stack test \
--fast --no-terminal \
--stack-yaml=${{ matrix.yaml }} \
--resolver=${{ matrix.resolver }} --system-ghc \
--flag=xmonad-contrib:pedantic

32
.gitignore vendored Normal file
View File

@@ -0,0 +1,32 @@
.cabal-sandbox/
cabal.sandbox.config
.hpc/
*.hi
*.o
*.p_hi
*.prof
*.tix
cabal.config
dist
dist-*
# editor temp files
*#
.#*
*~
.*.swp
# TAGS files
TAGS
tags
# stack artifacts
/.stack-work/
/cabal.project.local
stack.yaml.lock
# nix artifacts
result
flake.lock

2
.hlint.yaml Normal file
View File

@@ -0,0 +1,2 @@
# Ignore these warnings.
- ignore: {name: "Evaluate"}

108
.mailmap Normal file
View File

@@ -0,0 +1,108 @@
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>
Bruce Forte <fuererb@student.ethz.ch>
Carlos Lopez-Camey <c.lopez@kmels.net>
Carsten Otto <xmonad@c-otto.de>
Cesar Crusius <ccrusius@google.com> <ccrusius@ccrusius-glaptop.roam.corp.google.com>
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@gmail.com> <asgaroth_@gmx.de>
Daniel Schoepe <daniel.schoepe@gmail.com> <daniel.schoepe@googlemail.com>
Daniel Wagner <me@dmwit.com> <daniel@wagner-home.com>
Dave Harrison <dave@nullcube.com>
Dave Macias <davama@gmail.com>
David Glasser <glasser@mit.edu>
David McLean <gopsychonauts@gmail.com>
Devin Mullins <devin.mullins@gmail.com> <devinmullins@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>
Evgeny Kurnevsky <kurnevsky@gmail.com>
Gwern Branwen <gwern@gwern.net>
Gwern Branwen <gwern@gwern.net> <gwern0@gmail.com>
Henrique Abreu <hgabreu@gmail.com>
Ilya Portnov <portnov84@rambler.ru>
Ivan Brennen <ivan.brennan@gmail.com>
Ivan Brennen <ivan.brennan@gmail.com> <ivanbrennan@users.noreply.github.com>
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>
Joan Milev <joantmilev@gmail.com> <51526053+exorcist365@users.noreply.github.com>
Joe Thornber <joe.thornber@gmail.com>
Joel Suovaniemi <joel.suovaniemi@iki.fi>
Johann Giwer <johanngiwer@web.de>
Jussi Maki <joamaki@gmail.com>
Konstantin Sobolev <konstantin.sobolev@gmail.com>
L. S. Leary <LSLeary@users.noreply.github.com>
Lanny Ripple <lan3ny@gmail.com>
Lei Chen <linxray@gmail.com>
Leon Kowarschick <lkowarschick@gmail.com>
Leon Kowarschick <lkowarschick@gmail.com> <5300871+elkowar@users.noreply.github.com>
Leonardo Serra <leoserra@minaslivre.org>
Luc Duzan <lduzan@linagora.com>
Luc Duzan <lduzan@linagora.com> <stroky.l@gmail.com>
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>
Michael G. Sloan <mgsloan@gmail.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 J. Jones <pjones@devalot.com>
Peter J. Jones <pjones@devalot.com> <pjones@pmade.com>
Peter Olson <polson2@hawk.iit.edu>
Quentin Moser <moserq@gmail.com>
Quentin Moser <moserq@gmail.com> <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>
Sean Escriva <sean.escriva@gmail.com>
Sean McEligot <seanmce33@gmail.com>
Sibi Prabakaran <sibi@psibi.in>
Spencer Janssen <spencerjanssen@gmail.com> <sjanssen@cse.unl.edu>
Timothy Hobbs <tim.thelion@gmail.com>
Tom Rauchenwald <its.sec@gmx.net>
Tom Smeets <tom.tsmeets@gmail.com> <Tom.TSmeets@Gmail.com>
Tomas Janousek <tomi@nomi.cz>
Tomohiro Matsuyama <matsuyama3@ariel-networks.com>
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>
Yclept Nemo <orbisvicis@gmail.com> <pscjtwjdjtAhnbjm/dpn>
Yecine Megdiche <yecine.megdiche@gmail.com> <megdiche@in.tum.de>
hexago.nl <xmonad-contrib@hexago.nl>
lithis <xmonad@selg.hethrael.org>
lithis <xmonad@selg.hethrael.org> <xmonad@s001.hethrael.com>
sam-barr <mail@samf.bar> <samfbarr@outlook.com>
slotThe <soliditsallgood@mailbox.org> <50166980+slotThe@users.noreply.github.com>
slotThe <soliditsallgood@mailbox.org> <soliditsallgood@tuta.io>
spoonm <spoonm@spoonm.org>

2161
CHANGES.md Normal file

File diff suppressed because it is too large Load Diff

5
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,5 @@
# Contributing to xmonad and xmonad-contrib
Please refer to XMonad's [CONTRIBUTING][gh:xmonad:contributing].
[gh:xmonad:contributing]: https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md

45
LICENSE
View File

@@ -1,27 +1,26 @@
Copyright (c) The Xmonad Community
Copyright (c) The Xmonad Community. All rights reserved.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the author nor the names of his contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

106
NIX.md Normal file
View File

@@ -0,0 +1,106 @@
# `nix` integration for XMonad
## Customizing the `nix-shell`
It's possible to use a file `develop.nix` to customize the `devShell`
provided by the flake. This is useful if e.g. you want to have the
`haskell-language-server` or other developer tools in the shell properly
configured (correct GHC versions, and the like).
Here is an example `develop.nix` for `haskell-language-server`:
``` nix
pkgs: devInputs: devInputs // {
nativeBuildInputs = with pkgs.haskellPackages;
[ cabal-install hlint ghcid ormolu implicit-hie haskell-language-server ];
}
```
## Selecting a Compiler
A `comp.nix` file can be used to set the compiler used for `nix build` etc. E.g.
```nix
{ compiler = "ghc924"; }
```
Note that you must `git add comp.nix`, or it will be invisible to the flake.
There is also a `prefix` option (see documentation below) but it doesn't really
work in this context, since the xmonad flakes don't see the effects of your
system overlays. Instead try the `--override-input` flag, e.g.
```sh
$ nix develop . --override-input nixpkgs 'github:NixOS/nixpkgs/nixos-unstable'
```
## NixOS Modules
The core and contrib flakes provide NixOS configuration modules.
You can bring them into your system flake like so:
```nix
{
inputs = {
nixpkgs.url = github:NixOS/nixpkgs/nixos-<version>;
# The xmonad-contrib flake depends upon and re-exports from the xmonad
# flake. As such, you don't need to use the latter directly. If you wish to
# use /only/ the xmonad flake, you should beware that the version of
# contrib you get from nixpkgs might not build against it.
xmonad-contrib.url = github:xmonad/xmonad-contrib;
};
outputs = { self, nixpkgs, xmonad-contrib }: {
nixosConfigurations.<hostname> = nixpkgs.lib.nixosSystem rec {
system = <system>;
# NixOS module composition is /not/ commutative; order matters.
# To avoid issues, add `xmonad-contrib.nixosModules` after your standard
# configuration, but before `modernise` or any module overlaying in a
# "prefix".
modules = [
./configuration.nix
./hardware-configuration.nix
<myMiscConfigModule>
] ++ xmonad-contrib.nixosModules ++ [
# `modernise` replaces the standard xmonad module and wrapper script
# with those from unstable. This is currently a necessary workaround to
# make Mod-q recompilation work.
xmonad-contrib.modernise.${system}
<myPrefixModule>
];
};
};
}
```
Note that `<thing>` should be replaced with a user-supplied `thing`.
`<version>`, `<hostname>` and `<system>` are necessary, while
` <myMiscConfigModule>` and `<myPrefixModule>` are entirely optional.
Having brought in `xmonad-contrib.nixosModules`, you can then set the provided
options in your `configuration.nix` under `flake`:
```nix
services.xserver.windowManager.xmonad = {
enable = true;
enableContribAndExtras = true;
flake = {
enable = true;
# prefix = "unstable";
compiler = "ghc924";
};
};
```
This will use core and contrib from git for your system xmonad, building your
config with the compiler of your choice.
With the flake enabled, the `xmonad.haskellPackages` option is not used
directly, and is instead set by the `flake.compiler` option. When `compiler` is
unset, the default `pkgs.haskellPackages` is used.
The `prefix` option is used if you wish to select your haskell packages from
within, e.g., unstable overlaid into `pkgs` as `pkgs.unstable`.
See the flakes themselves and nix flake documentation for full detail.
Additionally, a semi-walkthrough is available [here](https://tony-zorman.com/posts/xmonad-on-nixos.html).

82
README
View File

@@ -1,82 +0,0 @@
xmonad-contrib : third party extensions to the xmonad window manager
http://xmonad.org
You need the ghc compiler and xmonad window manager installed in
order to use these extensions.
For installation and configuration instructions, please see the
xmonad website, the documents included with the xmonad source
distribution, and online haddock documentation:
http://www.xmonad.org/xmonad-docs
------------------------------------------------------------------------
Changelogs
For a list of changes since the 0.8.x releases, see:
http://www.haskell.org/haskellwiki/Xmonad/Notable_changes_since_0.8
------------------------------------------------------------------------
Updates to XMonadContrib-0.9 that may Require Changes to ~/.xmonad/xmonad.hs
Please see the Changelogs and xmonad-contrib haddock documentation
links for further details regarding the following changes.
* XMonad.Hooks.EwmhDesktops no longer uses layoutHook, the
ewmhDesktopsLayout modifier has been removed from xmonad-contrib. It
uses logHook, handleEventHook, and startupHook instead and provides
a convenient function 'ewmh' to add EWMH support to a defaultConfig.
* Most DynamicLog users can continue with configs unchanged, but users
of the quickbar functions 'xmobar' or 'dzen' will need to change
xmonad.hs: their types have changed to allow easier composition with
other XConfig modifiers. The 'dynamicLogDzen' and 'dynamicLogXmobar'
functions have been removed.
* WindowGo or safeSpawn users may need to change command lines due to
safeSpawn changes.
* People explicitly referencing the "SP" scratchpad workspace should
change it to "NSP" which is also used by the new Util.NamedScratchpad.
* (Optional) People who explicitly use swapMaster in key or mouse
bindings should change it to shiftMaster. It's the current default
used where swapMaster had been used previously. It works better than
swapMaster when using floating and tiled windows together on the
same workspace.
------------------------------------------------------------------------
Getting or updating XMonadContrib
latest release: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/xmonad-contrib
darcs version: darcs get http://code.haskell.org/XMonadContrib
(To use darcs xmonad-contrib you must also use the darcs version
of xmonad.)
------------------------------------------------------------------------
Contributing
Haskell code contributed to this repo should live under the
appropriate subdivision of the 'XMonad.' namespace (currently
includes Actions, Config, Hooks, Layout, Prompt, and Util). For
example, to use the Grid layout, one would import:
XMonad.Layout.Grid
For further details, see the documentation for the
XMonad.Doc.Developing module and http://xmonad.org website.
------------------------------------------------------------------------
Code submitted to the contrib repo is licensed under the same license as
xmonad itself, with copyright held by the authors.
------------------------------------------------------------------------

82
README.md Normal file
View File

@@ -0,0 +1,82 @@
<p align="center">
<a href="https://xmonad.org/"><img alt="XMonad logo" src="https://xmonad.org/images/logo-wrapped.svg" height=150></a>
</p>
<p align="center">
<a href="https://hackage.haskell.org/package/xmonad-contrib"><img alt="Hackage" src="https://img.shields.io/hackage/v/xmonad-contrib?logo=haskell"></a>
<a href="https://github.com/xmonad/xmonad-contrib/blob/readme/LICENSE"><img alt="License" src="https://img.shields.io/github/license/xmonad/xmonad-contrib"></a>
<a href="https://haskell.org/"><img alt="Made in Haskell" src="https://img.shields.io/badge/Made%20in-Haskell-%235e5086?logo=haskell"></a>
<br>
<a href="https://github.com/xmonad/xmonad-contrib/actions/workflows/stack.yml"><img alt="Stack" src="https://img.shields.io/github/actions/workflow/status/xmonad/xmonad-contrib/stack.yml?label=Stack&logo=githubactions&logoColor=white"></a>
<a href="https://github.com/xmonad/xmonad-contrib/actions/workflows/haskell-ci.yml"><img alt="Cabal" src="https://img.shields.io/github/actions/workflow/status/xmonad/xmonad-contrib/haskell-ci.yml?label=Cabal&logo=githubactions&logoColor=white"></a>
<a href="https://github.com/xmonad/xmonad-contrib/actions/workflows/nix.yml"><img alt="Nix" src="https://img.shields.io/github/actions/workflow/status/xmonad/xmonad-contrib/nix.yml?label=Nix&logo=githubactions&logoColor=white"></a>
<br>
<a href="https://github.com/sponsors/xmonad"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/xmonad?label=GitHub%20Sponsors&logo=githubsponsors"></a>
<a href="https://opencollective.com/xmonad"><img alt="Open Collective" src="https://img.shields.io/opencollective/all/xmonad?label=Open%20Collective&logo=opencollective"></a>
<br>
<a href="https://web.libera.chat/#xmonad"><img alt="Chat on #xmonad@irc.libera.chat" src="https://img.shields.io/badge/%23%20chat-on%20libera-brightgreen"></a>
<a href="https://matrix.to/#/#xmonad:matrix.org"><img alt="Chat on #xmonad:matrix.org" src="https://img.shields.io/matrix/xmonad:matrix.org?logo=matrix"></a>
</p>
# xmonad-contrib
**Community-maintained extensions for the [XMonad][web:xmonad] window manager.**
[xmonad core][gh:xmonad] is minimal, stable, yet extensible.
[xmonad-contrib][gh:xmonad-contrib] is home to hundreds of additional tiling
algorithms and extension modules. The two combined make for a powerful X11
window-manager with endless customization possibilities. They are, quite
literally, libraries for creating your own window manager.
## Installation
For installation and configuration instructions, please see:
* [downloading and installing xmonad][web:download]
* [installing latest xmonad snapshot from git][web:install]
* [configuring xmonad][web:tutorial]
If you run into any trouble, consult our [documentation][web:documentation] or
ask the [community][web:community] for help.
## Contributing
We welcome all forms of contributions:
* [bug reports and feature ideas][gh:xmonad-contrib:issues]
(also to [xmonad][gh:xmonad:issues])
* [bug fixes, new features, new extensions][gh:xmonad-contrib:pulls]
(also to [xmonad][gh:xmonad:pulls])
* documentation fixes and improvements: [xmonad][gh:xmonad],
[xmonad-contrib][gh:xmonad-contrib], [xmonad-web][gh:xmonad-web]
* helping others in the [community][web:community]
* financial support: [GitHub Sponsors][gh:xmonad:sponsors],
[Open Collective][opencollective:xmonad]
Please do read the [CONTRIBUTING][gh:xmonad:contributing] document for more
information about bug reporting and code contributions. For a brief overview
of the architecture and code conventions, see the [documentation for the
`XMonad.Doc.Developing` module][doc:developing]. If in doubt, [talk to
us][web:community].
## License
Code submitted to the xmonad-contrib repo is licensed under the same license
as xmonad core itself, with copyright held by the authors.
[doc:developing]: https://xmonad.github.io/xmonad-docs/xmonad-contrib/XMonad-Doc-Developing.html
[gh:xmonad-contrib:issues]: https://github.com/xmonad/xmonad-contrib/issues
[gh:xmonad-contrib:pulls]: https://github.com/xmonad/xmonad-contrib/pulls
[gh:xmonad-contrib]: https://github.com/xmonad/xmonad-contrib
[gh:xmonad-web]: https://github.com/xmonad/xmonad-web
[gh:xmonad:contributing]: https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md
[gh:xmonad:issues]: https://github.com/xmonad/xmonad/issues
[gh:xmonad:pulls]: https://github.com/xmonad/xmonad/pulls
[gh:xmonad:sponsors]: https://github.com/sponsors/xmonad
[gh:xmonad]: https://github.com/xmonad/xmonad
[opencollective:xmonad]: https://opencollective.com/xmonad
[web:community]: https://xmonad.org/community.html
[web:documentation]: https://xmonad.org/documentation.html
[web:download]: https://xmonad.org/download.html
[web:install]: https://xmonad.org/INSTALL.html
[web:tutorial]: https://xmonad.org/TUTORIAL.html
[web:xmonad]: https://xmonad.org/

View File

@@ -0,0 +1,73 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.AfterDrag
-- Description : Allows you to add actions dependent on the current mouse drag.
-- Copyright : (c) 2014 Anders Engstrom <ankaan@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Anders Engstrom <ankaan@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Perform an action after the current mouse drag is completed.
-----------------------------------------------------------------------------
module XMonad.Actions.AfterDrag (
-- * Usage
-- $usage
afterDrag,
ifClick,
ifClick') where
import XMonad
import Data.Time (NominalDiffTime, diffUTCTime, getCurrentTime)
-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.AfterDrag
--
-- Then add appropriate mouse bindings, for example:
--
-- > , ((modm, button3), (\w -> focus w >> mouseResizeWindow w >> ifClick (windows $ W.float w $ W.RationalRect 0 0 1 1)))
--
-- This will allow you to resize windows as usual, but if you instead of
-- draging click the mouse button the window will be automatically resized to
-- fill the whole screen.
--
-- For detailed instructions on editing your mouse bindings, see
-- "XMonad.Doc.Extending#Editing_mouse_bindings".
--
-- More practical examples are available in "XMonad.Actions.FloatSnap".
-- | Schedule a task to take place after the current dragging is completed.
afterDrag
:: X () -- ^ The task to schedule.
-> X ()
afterDrag task = do drag <- gets dragging
case drag of
Nothing -> return () -- Not dragging
Just (motion, cleanup) -> modify $ \s -> s { dragging = Just(motion, cleanup >> task) }
-- | Take an action if the current dragging can be considered a click,
-- supposing the drag just started before this function is called.
-- A drag is considered a click if it is completed within 300 ms.
ifClick
:: X () -- ^ The action to take if the dragging turned out to be a click.
-> X ()
ifClick action = ifClick' 300 action (return ())
-- | Take an action if the current dragging is completed within a certain time (in milliseconds.)
ifClick'
:: Int -- ^ Maximum time of dragging for it to be considered a click (in milliseconds.)
-> X () -- ^ The action to take if the dragging turned out to be a click.
-> X () -- ^ The action to take if the dragging turned out to not be a click.
-> X ()
ifClick' ms click drag = do
start <- io getCurrentTime
afterDrag $ do
stop <- io getCurrentTime
if diffUTCTime stop start <= (fromIntegral ms / 10^(3 :: Integer) :: NominalDiffTime)
then click
else drag

View File

@@ -1,6 +1,7 @@
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.BluetileCommands
-- Description : Interface with the [Bluetile](https://hackage.haskell.org/package/bluetile) tiling window manager.
-- Copyright : (c) Jan Vornberger 2009
-- License : BSD3-style (see LICENSE)
--
@@ -24,26 +25,25 @@ module XMonad.Actions.BluetileCommands (
import XMonad
import qualified XMonad.StackSet as W
import XMonad.Layout.LayoutCombinators
import System.Exit
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Hooks.ServerMode
-- > import XMonad.Actions.BluetileCommands
--
-- Then edit your @handleEventHook@:
--
-- > main = xmonad defaultConfig { handleEventHook = serverModeEventHook' bluetileCommands }
-- > main = xmonad def { handleEventHook = serverModeEventHook' bluetileCommands }
--
-- See the documentation of "XMonad.Hooks.ServerMode" for details on
-- how to actually invoke the commands from external programs.
workspaceCommands :: Int -> X [(String, X ())]
workspaceCommands sid = asks (workspaces . config) >>= \spaces -> return
[(("greedyView" ++ show i),
[( "greedyView" ++ show i,
activateScreen sid >> windows (W.greedyView i))
| i <- spaces ]
@@ -66,7 +66,7 @@ masterAreaCommands sid = [ ("increase master n", activateScreen sid >>
]
quitCommands :: [(String, X ())]
quitCommands = [ ("quit bluetile", io (exitWith ExitSuccess))
quitCommands = [ ("quit bluetile", io exitSuccess)
, ("quit bluetile and start metacity", restart "metacity" False)
]

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Commands
-- Description : Run internal xmonad commands using a dmenu menu.
-- Copyright : (c) David Glasser 2007
-- License : BSD3
--
@@ -19,6 +20,7 @@ module XMonad.Actions.Commands (
-- $usage
commandMap,
runCommand,
runCommandConfig,
runCommand',
workspaceCommands,
screenCommands,
@@ -31,11 +33,11 @@ import XMonad.Util.Dmenu (dmenu)
import qualified Data.Map as M
import System.Exit
import Data.Maybe
import XMonad.Prelude
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.Commands
--
@@ -55,23 +57,23 @@ import Data.Maybe
-- bindings!)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Create a 'Data.Map.Map' from @String@s to xmonad actions from a
-- list of pairs.
commandMap :: [(String, X ())] -> M.Map String (X ())
commandMap c = M.fromList c
commandMap = M.fromList
-- | Generate a list of commands to switch to\/send windows to workspaces.
workspaceCommands :: X [(String, X ())]
workspaceCommands = asks (workspaces . config) >>= \spaces -> return
[((m ++ show i), windows $ f i)
[( m ++ show i, windows $ f i)
| i <- spaces
, (f, m) <- [(view, "view"), (shift, "shift")] ]
-- | Generate a list of commands dealing with multiple screens.
screenCommands :: [(String, X ())]
screenCommands = [((m ++ show sc), screenWorkspace (fromIntegral sc) >>= flip whenJust (windows . f))
screenCommands = [( m ++ show sc, screenWorkspace (fromIntegral sc) >>= flip whenJust (windows . f))
| sc <- [0, 1]::[Int] -- TODO: adapt to screen changes
, (f, m) <- [(view, "screen"), (shift, "screen-to-")]
]
@@ -99,15 +101,22 @@ defaultCommands = do
, ("swap-down" , windows swapDown )
, ("swap-master" , windows swapMaster )
, ("sink" , withFocused $ windows . sink )
, ("quit-wm" , io $ exitWith ExitSuccess )
, ("quit-wm" , io exitSuccess )
]
-- | Given a list of command\/action pairs, prompt the user to choose a
-- command and return the corresponding action.
-- command using dmenu and return the corresponding action.
runCommand :: [(String, X ())] -> X ()
runCommand cl = do
runCommand = runCommandConfig dmenu
-- | Given a list of command\/action pairs, prompt the user to choose a
-- command using dmenu-compatible launcher and return the corresponding action.
-- See X.U.Dmenu for compatible launchers.
runCommandConfig :: ([String] -> X String) -> [(String, X ())] -> X()
runCommandConfig f cl = do
let m = commandMap cl
choice <- dmenu (M.keys m)
choice <- f (M.keys m)
fromMaybe (return ()) (M.lookup choice m)
-- | Given the name of a command from 'defaultCommands', return the

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.ConstrainedResize
-- Description : Constrain the aspect ratio of a floating window.
-- Copyright : (c) Dougal Stanton
-- License : BSD3-style (see LICENSE)
--
@@ -25,7 +26,7 @@ import XMonad
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import qualified XMonad.Actions.ConstrainedResize as Sqr
--
@@ -43,9 +44,8 @@ import XMonad
-- | Resize (floating) window with optional aspect ratio constraints.
mouseResizeWindow :: Window -> Bool -> X ()
mouseResizeWindow w c = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
mouseResizeWindow w c = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
sh <- io $ getWMNormalHints d w
io $ warpPointer d none w 0 0 0 0 (fromIntegral (wa_width wa)) (fromIntegral (wa_height wa))
mouseDrag (\ex ey -> do
@@ -53,5 +53,6 @@ mouseResizeWindow w c = whenX (isClient w) $ withDisplay $ \d -> do
y = ey - fromIntegral (wa_y wa)
sz = if c then (max x y, max x y) else (x,y)
io $ resizeWindow d w `uncurry`
applySizeHintsContents sh sz)
applySizeHintsContents sh sz
float w)
(float w)

View File

@@ -1,7 +1,9 @@
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE RecordWildCards #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CopyWindow
-- Description : Duplicate a window on multiple workspaces.
-- Copyright : (c) David Roundy <droundy@darcs.net>, Ivan Veselov <veselov@gmail.com>, Lanny Ripple <lan3ny@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -18,22 +20,24 @@ module XMonad.Actions.CopyWindow (
-- * Usage
-- $usage
copy, copyToAll, copyWindow, runOrCopy
, killAllOtherCopies, kill1
, killAllOtherCopies, kill1, taggedWindows, copiesOfOn
-- * Highlight workspaces containing copies in logHook
-- $logHook
, wsContainingCopies
, wsContainingCopies, copiesPP
) where
import XMonad
import XMonad.Prelude
import Control.Arrow ((&&&))
import qualified Data.List as L
import XMonad.Actions.WindowGo
import XMonad.Hooks.StatusBar.PP (PP(..), WS(..), isHidden)
import qualified XMonad.StackSet as W
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.CopyWindow
--
@@ -73,21 +77,27 @@ import qualified XMonad.StackSet as W
-- > , ((modm .|. shiftMask, xK_v ), killAllOtherCopies) -- @@ Toggle window state back
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- $logHook
-- To distinguish workspaces containing copies of the focused window use
-- something like:
--
-- > sampleLogHook h = do
-- > copies <- wsContainingCopies
-- > let check ws | ws `elem` copies = pad . xmobarColor "red" "black" $ ws
-- > | otherwise = pad ws
-- > dynamicLogWithPP myPP {ppHidden = check, ppOutput = hPutStrLn h}
-- >
-- > main = do
-- > h <- spawnPipe "xmobar"
-- > xmonad defaultConfig { logHook = sampleLogHook h }
-- To distinguish workspaces containing copies of the focused window, use 'copiesPP'.
-- 'copiesPP' takes a pretty printer and makes it aware of copies of the focused window.
-- It can be applied when creating a 'XMonad.Hooks.StatusBar.StatusBarConfig'.
--
-- A sample config looks like this:
--
-- > mySB = statusBarProp "xmobar" (copiesPP (pad . xmobarColor "red" "black") xmobarPP)
-- > main = xmonad $ withEasySB mySB defToggleStrutsKey def
-- | Take a pretty printer and make it aware of copies by using the provided function
-- to show hidden workspaces that contain copies of the focused window.
copiesPP :: (WorkspaceId -> String) -> PP -> X PP
copiesPP wtoS pp = do
copies <- wsContainingCopies
let check WS{..} = W.tag wsWS `elem` copies
let printer = (asks (isHidden <&&> check) >>= guard) $> wtoS
return pp{ ppPrinters = printer <|> ppPrinters pp }
-- | Copy the focused window to a workspace.
copy :: (Eq s, Eq i, Eq a) => i -> W.StackSet i l a s sd -> W.StackSet i l a s sd
@@ -96,7 +106,7 @@ copy n s | Just w <- W.peek s = copyWindow w n s
-- | Copy the focused window to all workspaces.
copyToAll :: (Eq s, Eq i, Eq a) => W.StackSet i l a s sd -> W.StackSet i l a s sd
copyToAll s = foldr copy s $ map W.tag (W.workspaces s)
copyToAll s = foldr (copy . W.tag) s (W.workspaces s)
-- | Copy an arbitrary window to a workspace.
copyWindow :: (Eq a, Eq i, Eq s) => a -> i -> W.StackSet i l a s sd -> W.StackSet i l a s sd
@@ -104,10 +114,10 @@ copyWindow w n = copy'
where copy' s = if n `W.tagMember` s
then W.view (W.currentTag s) $ insertUp' w $ W.view n s
else s
insertUp' a s = W.modify (Just $ W.Stack a [] [])
insertUp' a = W.modify (Just $ W.Stack a [] [])
(\(W.Stack t l r) -> if a `elem` t:l++r
then Just $ W.Stack t l r
else Just $ W.Stack a (L.delete a l) (L.delete a (t:r))) s
else Just $ W.Stack a (L.delete a l) (L.delete a (t:r)))
-- | runOrCopy will run the provided shell command unless it can
@@ -142,9 +152,9 @@ killAllOtherCopies = do ss <- gets windowset
W.view (W.currentTag ss) .
delFromAllButCurrent w
where
delFromAllButCurrent w ss = foldr ($) ss $
map (delWinFromWorkspace w . W.tag) $
W.hidden ss ++ map W.workspace (W.visible ss)
delFromAllButCurrent w ss = foldr (delWinFromWorkspace w . W.tag)
ss
(W.hidden ss ++ map W.workspace (W.visible ss))
delWinFromWorkspace w wid = viewing wid $ W.modify Nothing (W.filter (/= w))
viewing wis f ss = W.view (W.currentTag ss) $ f $ W.view wis ss

View File

@@ -1,6 +1,11 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE MultiWayIf #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleRecentWS
-- Description : Cycle through most recently used workspaces.
-- Copyright : (c) Michal Janeczek <janeczek@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -19,21 +24,37 @@ module XMonad.Actions.CycleRecentWS (
-- * Usage
-- $usage
cycleRecentWS,
cycleWindowSets
cycleRecentNonEmptyWS,
cycleWindowSets,
toggleRecentWS,
toggleRecentNonEmptyWS,
toggleWindowSets,
recentWS,
#ifdef TESTING
unView,
#endif
) where
import XMonad.Actions.Repeatable (repeatableSt)
import XMonad hiding (workspaces)
import XMonad.StackSet
import XMonad.Prelude (void, when)
import XMonad.StackSet hiding (filter, modify)
import Control.Arrow ((&&&))
import Data.Function (on)
import Control.Monad.State (lift)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.CycleRecentWS
-- >
-- > , ((modm, xK_Tab), cycleRecentWS [xK_Alt_L] xK_Tab xK_grave)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Cycle through most recent workspaces with repeated presses of a key, while
-- a modifier key is held down. The recency of workspaces previewed while browsing
@@ -47,39 +68,91 @@ cycleRecentWS :: [KeySym] -- ^ A list of modifier keys used when invoking this a
-> KeySym -- ^ Key used to switch to previous (more recent) workspace.
-- If it's the same as the nextWorkspace key, it is effectively ignored.
-> X ()
cycleRecentWS = cycleWindowSets options
where options w = map (view `flip` w) (recentTags w)
recentTags w = map tag $ tail (workspaces w) ++ [head (workspaces w)]
cycleRecentWS = cycleWindowSets $ recentWS (const True)
cycref :: [a] -> Int -> a
cycref l i = l !! (i `mod` length l)
-- | Like 'cycleRecentWS', but restricted to non-empty workspaces.
cycleRecentNonEmptyWS :: [KeySym] -- ^ A list of modifier keys used when invoking this action.
-- As soon as one of them is released, the final switch is made.
-> KeySym -- ^ Key used to switch to next (less recent) workspace.
-> KeySym -- ^ Key used to switch to previous (more recent) workspace.
-- If it's the same as the nextWorkspace key, it is effectively ignored.
-> X ()
cycleRecentNonEmptyWS = cycleWindowSets $ recentWS (not . null . stack)
-- | Cycle through a finite list of WindowSets with repeated presses of a key, while
-- | Switch to the most recent workspace. The stack of most recently used workspaces
-- is updated, so repeated use toggles between a pair of workspaces.
toggleRecentWS :: X ()
toggleRecentWS = toggleWindowSets $ recentWS (const True)
-- | Like 'toggleRecentWS', but restricted to non-empty workspaces.
toggleRecentNonEmptyWS :: X ()
toggleRecentNonEmptyWS = toggleWindowSets $ recentWS (not . null . stack)
-- | Given a predicate @p@ and the current 'WindowSet' @w@, create a
-- list of workspaces to choose from. They are ordered by recency and
-- have to satisfy @p@.
recentWS :: (WindowSpace -> Bool) -- ^ A workspace predicate.
-> WindowSet -- ^ The current WindowSet
-> [WorkspaceId]
recentWS p w = map tag
$ filter p
$ map workspace (visible w)
++ hidden w
++ [workspace (current w)]
-- | Cycle through a finite list of workspaces with repeated presses of a key, while
-- a modifier key is held down. For best effects use the same modkey+key combination
-- as the one used to invoke this action.
cycleWindowSets :: (WindowSet -> [WindowSet]) -- ^ A function used to create a list of WindowSets to choose from
-> [KeySym] -- ^ A list of modifier keys used when invoking this action.
-- As soon as one of them is released, the final WindowSet is chosen and the action exits.
-> KeySym -- ^ Key used to preview next WindowSet from the list of generated options
-> KeySym -- ^ Key used to preview previous WindowSet from the list of generated options.
-- If it's the same as nextOption key, it is effectively ignored.
cycleWindowSets :: (WindowSet -> [WorkspaceId]) -- ^ A function used to create a list of workspaces to choose from
-> [KeySym] -- ^ A list of modifier keys used when invoking this action.
-- As soon as one of them is released, the final workspace is chosen and the action exits.
-> KeySym -- ^ Key used to preview next workspace from the list of generated options
-> KeySym -- ^ Key used to preview previous workspace from the list of generated options.
-- If it's the same as nextOption key, it is effectively ignored.
-> X ()
cycleWindowSets genOptions mods keyNext keyPrev = do
(options, unView') <- gets $ (genOptions &&& unView) . windowset
let
preview = do
i <- get
lift $ windows (view (options !! (i `mod` n)) . unView')
where n = length options
void . repeatableSt (-1) mods keyNext $ \t s -> when (t == keyPress) $ if
| s == keyNext -> modify succ >> preview
| s == keyPrev -> modify pred >> preview
| otherwise -> pure ()
-- | Given an old and a new 'WindowSet', which is __exactly__ one
-- 'view' away from the old one, restore the workspace order of the
-- former inside of the latter. This respects any new state that the
-- new 'WindowSet' may have accumulated.
unView :: forall i l a s sd. (Eq i, Eq s)
=> StackSet i l a s sd -> StackSet i l a s sd -> StackSet i l a s sd
unView w0 w1 = fixOrderH . fixOrderV . view' (currentTag w0) $ w1
where
view' = if screen (current w0) == screen (current w1) then greedyView else view
fixOrderV w | v : vs <- visible w = w{ visible = insertAt (pfxV (visible w0) vs) v vs }
| otherwise = w
fixOrderH w | h : hs <- hidden w = w{ hidden = insertAt (pfxH (hidden w0) hs) h hs }
| otherwise = w
pfxV = commonPrefix `on` fmap (tag . workspace)
pfxH = commonPrefix `on` fmap tag
insertAt :: Int -> x -> [x] -> [x]
insertAt n x xs = let (l, r) = splitAt n xs in l ++ [x] ++ r
commonPrefix :: Eq x => [x] -> [x] -> Int
commonPrefix a b = length $ takeWhile id $ zipWith (==) a b
-- | Given some function that generates a list of workspaces from a
-- given 'WindowSet', switch to the first generated workspace.
toggleWindowSets :: (WindowSet -> [WorkspaceId]) -> X ()
toggleWindowSets genOptions = do
options <- gets $ genOptions . windowset
XConf {theRoot = root, display = d} <- ask
let event = allocaXEvent $ \p -> do
maskEvent d (keyPressMask .|. keyReleaseMask) p
KeyEvent {ev_event_type = t, ev_keycode = c} <- getEvent p
s <- keycodeToKeysym d c 0
return (t, s)
let setOption n = do windows $ const $ options `cycref` n
(t, s) <- io event
case () of
() | t == keyPress && s == keyNext -> setOption (n+1)
| t == keyPress && s == keyPrev -> setOption (n-1)
| t == keyRelease && s `elem` mods -> return ()
| otherwise -> setOption n
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
setOption 0
io $ ungrabKeyboard d currentTime
case options of
[] -> return ()
o:_ -> windows (view o)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleSelectedLayouts
-- Description : Cycle through the given subset of layouts.
-- Copyright : (c) Roman Cheplyaka
-- License : BSD3-style (see LICENSE)
--
@@ -18,34 +19,29 @@ module XMonad.Actions.CycleSelectedLayouts (
cycleThroughLayouts) where
import XMonad
import Data.List (findIndex)
import Data.Maybe (fromMaybe)
import XMonad.Layout.LayoutCombinators (JumpToLayout(..))
import XMonad.Prelude (elemIndex, fromMaybe)
import qualified XMonad.StackSet as S
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad hiding ((|||))
-- > import XMonad.Layout.LayoutCombinators ((|||))
-- > import XMonad
-- > import XMonad.Actions.CycleSelectedLayouts
--
-- > , ((modm, xK_t ), cycleThroughLayouts ["Tall", "Mirror Tall"])
--
-- Make sure you are using NewSelect from XMonad.Layout.LayoutCombinators,
-- rather than the Select defined in xmonad core.
cycleToNext :: (Eq a) => [a] -> a -> Maybe a
cycleToNext lst a = do
-- not beautiful but simple and readable
ind <- findIndex (a==) lst
ind <- elemIndex a lst
return $ lst !! if ind == length lst - 1 then 0 else ind+1
-- | If the current layout is in the list, cycle to the next layout. Otherwise,
-- apply the first layout from list.
cycleThroughLayouts :: [String] -> X ()
cycleThroughLayouts lst = do
cycleThroughLayouts [] = pure ()
cycleThroughLayouts lst@(x: _) = do
winset <- gets windowset
let ld = description . S.layout . S.workspace . S.current $ winset
let newld = fromMaybe (head lst) (cycleToNext lst ld)
let newld = fromMaybe x (cycleToNext lst ld)
sendMessage $ JumpToLayout newld

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleWS
-- Description : Cycle through workspaces.
-- Copyright : (c) Joachim Breitner <mail@joachim-breitner.de>,
-- Nelson Elhage <nelhage@mit.edu> (`toggleWS' function)
-- License : BSD3-style (see LICENSE)
@@ -18,13 +19,13 @@
--
-- Note that this module now subsumes the functionality of the former
-- @XMonad.Actions.RotView@. Former users of @rotView@ can simply replace
-- @rotView True@ with @moveTo Next NonEmptyWS@, and so on.
-- @rotView True@ with @moveTo Next (Not emptyWS)@, and so on.
--
-- If you want to exactly replicate the action of @rotView@ (cycling
-- through workspace in order lexicographically by tag, instead of in
-- the order specified in the config), it can be implemented as:
--
-- > rotView b = do t <- findWorkspace getSortByTag (bToDir b) NonEmptyWS 1
-- > rotView b = do t <- findWorkspace getSortByTag (bToDir b) (Not emptyWS) 1
-- > windows . greedyView $ t
-- > where bToDir True = Next
-- > bToDir False = Prev
@@ -63,6 +64,11 @@ module XMonad.Actions.CycleWS (
, Direction1D(..)
, WSType(..)
, emptyWS
, hiddenWS
, anyWS
, wsTagGroup
, ignoringWSs
, shiftTo
, moveTo
@@ -78,17 +84,15 @@ module XMonad.Actions.CycleWS (
) where
import Control.Monad ( unless )
import Data.List ( findIndex )
import Data.Maybe ( isNothing, isJust )
import XMonad.Prelude (find, findIndex, isJust, isNothing, liftM2)
import XMonad hiding (workspaces)
import qualified XMonad.Hooks.WorkspaceHistory as WH
import XMonad.StackSet hiding (filter)
import XMonad.Util.Types
import XMonad.Util.WorkspaceCompare
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.CycleWS
-- >
@@ -112,13 +116,17 @@ import XMonad.Util.WorkspaceCompare
-- You can also get fancier with 'moveTo', 'shiftTo', and 'findWorkspace'.
-- For example:
--
-- > , ((modm , xK_f), moveTo Next EmptyWS) -- find a free workspace
-- > , ((modm , xK_f), moveTo Next emptyWS) -- find a free workspace
-- > , ((modm .|. controlMask, xK_Right), -- a crazy keybinding!
-- > do t <- findWorkspace getSortByXineramaRule Next NonEmptyWS 2
-- > do t <- findWorkspace getSortByXineramaRule Next (Not emptyWS) 2
-- > windows . view $ t )
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
--
-- When using the toggle functions, in order to ensure that the workspace
-- to which you switch is the previously viewed workspace, use the
-- 'logHook' in "XMonad.Hooks.WorkspaceHistory".
{- $moving
@@ -158,9 +166,7 @@ toggleWS = toggleWS' []
-- > -- Ignore the scratchpad workspace while toggling:
-- > ("M-b", toggleWS' ["NSP"])
toggleWS' :: [WorkspaceId] -> X ()
toggleWS' skips = do
hs' <- cleanHiddens skips
unless (null hs') (windows . view . tag $ head hs')
toggleWS' skips = lastViewedHiddenExcept skips >>= flip whenJust (windows . view)
-- | 'XMonad.StackSet.greedyView' a workspace, or if already there, view
-- the previously displayed workspace ala weechat. Change @greedyView@ to
@@ -184,10 +190,9 @@ toggleOrView = toggleOrDoSkip [] greedyView
toggleOrDoSkip :: [WorkspaceId] -> (WorkspaceId -> WindowSet -> WindowSet)
-> WorkspaceId -> X ()
toggleOrDoSkip skips f toWS = do
hs' <- cleanHiddens skips
cur <- gets (currentTag . windowset)
if toWS == cur
then unless (null hs') (windows . f . tag $ head hs')
then lastViewedHiddenExcept skips >>= flip whenJust (windows . f)
else windows (f toWS)
-- | List difference ('\\') for workspaces and tags. Removes workspaces
@@ -195,8 +200,15 @@ toggleOrDoSkip skips f toWS = do
skipTags :: (Eq i) => [Workspace i l a] -> [i] -> [Workspace i l a]
skipTags wss ids = filter ((`notElem` ids) . tag) wss
cleanHiddens :: [WorkspaceId] -> X [WindowSpace]
cleanHiddens skips = gets $ (flip skipTags) skips . hidden . windowset
-- | Ignoring the skips, find the best candidate for the last viewed hidden
-- workspace.
lastViewedHiddenExcept :: [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept skips = do
hs <- gets $ map tag . flip skipTags skips . hidden . windowset
choose hs . find (`elem` hs) <$> WH.workspaceHistory
where choose [] _ = Nothing
choose (h:_) Nothing = Just h
choose _ vh@(Just _) = vh
switchWorkspace :: Int -> X ()
switchWorkspace d = wsBy d >>= windows . greedyView
@@ -204,8 +216,8 @@ switchWorkspace d = wsBy d >>= windows . greedyView
shiftBy :: Int -> X ()
shiftBy d = wsBy d >>= windows . shift
wsBy :: Int -> X (WorkspaceId)
wsBy = findWorkspace getSortByIndex Next AnyWS
wsBy :: Int -> X WorkspaceId
wsBy = findWorkspace getSortByIndex Next anyWS
{- $taketwo
@@ -214,7 +226,7 @@ through subsets of workspaces.
For example,
> moveTo Next EmptyWS
> moveTo Next emptyWS
will move to the first available workspace with no windows, and
@@ -225,11 +237,19 @@ the letter 'p' in its name. =)
-}
{-# DEPRECATED EmptyWS "Use emptyWS instead." #-}
{-# DEPRECATED HiddenWS "Use hiddenWS instead." #-}
{-# DEPRECATED NonEmptyWS "Use Not emptyWS instead." #-}
{-# DEPRECATED HiddenNonEmptyWS "Use hiddenWS :&: Not emptyWS instead." #-}
{-# DEPRECATED HiddenEmptyWS "Use hiddenWS :&: emptyWS instead." #-}
{-# DEPRECATED AnyWS "Use anyWS instead." #-}
{-# DEPRECATED WSTagGroup "Use wsTagGroup instead." #-}
-- | What type of workspaces should be included in the cycle?
data WSType = EmptyWS -- ^ cycle through empty workspaces
| NonEmptyWS -- ^ cycle through non-empty workspaces
| HiddenWS -- ^ cycle through non-visible workspaces
| HiddenNonEmptyWS -- ^ cycle through non-empty non-visible workspaces
| HiddenEmptyWS -- ^ cycle through empty non-visible workspaces
| AnyWS -- ^ cycle through all workspaces
| WSTagGroup Char
-- ^ cycle through workspaces in the same group, the
@@ -238,6 +258,11 @@ data WSType = EmptyWS -- ^ cycle through empty workspaces
| WSIs (X (WindowSpace -> Bool))
-- ^ cycle through workspaces satisfying
-- an arbitrary predicate
| WSType :&: WSType -- ^ cycle through workspaces satisfying both
-- predicates.
| WSType :|: WSType -- ^ cycle through workspaces satisfying one of
-- the predicates.
| Not WSType -- ^ cycle through workspaces not satisfying the predicate
-- | Convert a WSType value to a predicate on workspaces.
wsTypeToPred :: WSType -> X (WindowSpace -> Bool)
@@ -248,11 +273,50 @@ wsTypeToPred HiddenWS = do hs <- gets (map tag . hidden . windowset)
wsTypeToPred HiddenNonEmptyWS = do ne <- wsTypeToPred NonEmptyWS
hi <- wsTypeToPred HiddenWS
return (\w -> hi w && ne w)
wsTypeToPred HiddenEmptyWS = do ne <- wsTypeToPred EmptyWS
hi <- wsTypeToPred HiddenWS
return (\w -> hi w && ne w)
wsTypeToPred AnyWS = return (const True)
wsTypeToPred (WSTagGroup sep) = do cur <- (groupName.workspace.current) `fmap` gets windowset
wsTypeToPred (WSTagGroup sep) = do cur <- groupName.workspace.current <$> gets windowset
return $ (cur ==).groupName
where groupName = takeWhile (/=sep).tag
wsTypeToPred (WSIs p) = p
wsTypeToPred (WSIs p ) = p
wsTypeToPred (p :&: q) = liftM2 (&&) <$> wsTypeToPred p <*> wsTypeToPred q
wsTypeToPred (p :|: q) = liftM2 (||) <$> wsTypeToPred p <*> wsTypeToPred q
wsTypeToPred (Not p ) = fmap not <$> wsTypeToPred p
-- | Cycle through empty workspaces
emptyWS :: WSType
emptyWS = WSIs . return $ isNothing . stack
-- | Cycle through non-visible workspaces
hiddenWS :: WSType
hiddenWS = WSIs $ do
hs <- gets (map tag . hidden . windowset)
return $ (`elem` hs) . tag
-- | Cycle through all workspaces
anyWS :: WSType
anyWS = WSIs . return $ const True
-- | Cycle through workspaces that are not in the given list. This could, for
-- example, be used for skipping the workspace reserved for
-- "XMonad.Util.NamedScratchpad":
--
-- > moveTo Next $ hiddenWS :&: Not emptyWS :&: ignoringWSs [scratchpadWorkspaceTag]
--
ignoringWSs :: [WorkspaceId] -> WSType
ignoringWSs ts = WSIs . return $ (`notElem` ts) . tag
-- | Cycle through workspaces in the same group, the
-- group name is all characters up to the first
-- separator character or the end of the tag
wsTagGroup :: Char -> WSType
wsTagGroup sep = WSIs $ do
cur <- groupName . workspace . current <$> gets windowset
return $ (cur ==) . groupName
where groupName = takeWhile (/= sep) . tag
-- | View the next workspace in the given direction that satisfies
-- the given condition.
@@ -286,7 +350,7 @@ findWorkspace :: X WorkspaceSort -> Direction1D -> WSType -> Int -> X WorkspaceI
findWorkspace s dir t n = findWorkspaceGen s (wsTypeToPred t) (maybeNegate dir n)
where
maybeNegate Next d = d
maybeNegate Prev d = (-d)
maybeNegate Prev d = -d
findWorkspaceGen :: X WorkspaceSort -> X (WindowSpace -> Bool) -> Int -> X WorkspaceId
findWorkspaceGen _ _ 0 = gets (currentTag . windowset)
@@ -296,7 +360,7 @@ findWorkspaceGen sortX wsPredX d = do
ws <- gets windowset
let cur = workspace (current ws)
sorted = sort (workspaces ws)
pivoted = let (a,b) = span ((/= (tag cur)) . tag) sorted in b ++ a
pivoted = let (a,b) = span ((/= tag cur) . tag) sorted in b ++ a
ws' = filter wsPred pivoted
mCurIx = findWsIndex cur ws'
d' = if d > 0 then d - 1 else d
@@ -308,7 +372,7 @@ findWorkspaceGen sortX wsPredX d = do
return $ tag next
findWsIndex :: WindowSpace -> [WindowSpace] -> Maybe Int
findWsIndex ws wss = findIndex ((== tag ws) . tag) wss
findWsIndex ws = findIndex ((== tag ws) . tag)
-- | View next screen
nextScreen :: X ()
@@ -336,7 +400,7 @@ the default screen keybindings:
> , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
-}
screenBy :: Int -> X (ScreenId)
screenBy :: Int -> X ScreenId
screenBy d = do ws <- gets windowset
--let ss = sortBy screen (screens ws)
let now = screen (current ws)

View File

@@ -1,6 +1,9 @@
{-# LANGUAGE ViewPatterns, MultiWayIf #-}
--------------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleWindows
-- Description : Cycle windows while maintaining focus in place.
-- Copyright : (c) Wirt Wolff <wirtwolff@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -47,18 +50,21 @@ module XMonad.Actions.CycleWindows (
-- $pointer
-- * Generic list rotations
-- $generic
rotUp, rotDown
) where
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import qualified Data.List.NonEmpty as NE
import XMonad.Actions.RotSlaves
import XMonad.Actions.Repeatable (repeatableSt)
import Control.Arrow (second)
import Control.Monad.Trans (lift)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.CycleWindows
-- > -- config
@@ -74,7 +80,7 @@ import Control.Arrow (second)
--
-- Also, if you use focus follows mouse, you will want to read the section
-- on updating the mouse pointer below. For detailed instructions on
-- editing your key bindings, see "XMonad.Doc.Extending#Editing_key_bindings".
-- editing your key bindings, see <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
{- $pointer
With FocusFollowsMouse == True, the focus is updated after binding
actions, possibly focusing a window you didn't intend to focus. Most
@@ -116,7 +122,7 @@ cycleRecentWindows :: [KeySym] -- ^ A list of modifier keys used when invoking t
-- If it's the same as the first key, it is effectively ignored.
-> X ()
cycleRecentWindows = cycleStacks' stacks where
stacks s = map (shiftToFocus' `flip` s) (wins s)
stacks s = map (`shiftToFocus'` s) (wins s)
wins (W.Stack t l r) = t : r ++ reverse l
@@ -134,27 +140,19 @@ cycleStacks' :: (W.Stack Window -> [W.Stack Window]) -- ^ A function to a finite
-> KeySym -- ^ Key used to select a \"previous\" stack.
-> X ()
cycleStacks' filteredPerms mods keyNext keyPrev = do
XConf {theRoot = root, display = d} <- ask
stacks <- gets $ maybe [] filteredPerms . W.stack . W.workspace . W.current . windowset
let evt = allocaXEvent $
\p -> do maskEvent d (keyPressMask .|. keyReleaseMask) p
KeyEvent {ev_event_type = t, ev_keycode = c} <- getEvent p
s <- keycodeToKeysym d c 0
return (t, s)
choose n (t, s)
| t == keyPress && s == keyNext = io evt >>= choose (n+1)
| t == keyPress && s == keyPrev = io evt >>= choose (n-1)
| t == keyPress && s `elem` [xK_0..xK_9] = io evt >>= choose (numKeyToN s)
| t == keyRelease && s `elem` mods = return ()
| otherwise = doStack n >> io evt >>= choose n
doStack n = windows . W.modify' . const $ stacks `cycref` n
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
io evt >>= choose 1
io $ ungrabKeyboard d currentTime
where cycref l i = l !! (i `mod` length l) -- modify' ensures l is never [], but must also be finite
numKeyToN = subtract 48 . read . show
stacks <- gets $ maybe [] filteredPerms
. W.stack . W.workspace . W.current . windowset
let
preview = do
i <- get
lift . windows . W.modify' . const $ stacks !! (i `mod` n)
where n = length stacks
void $ repeatableSt 0 mods keyNext $ \t s -> if
| t == keyPress && s == keyNext -> modify succ
| t == keyPress && s == keyPrev -> modify pred
| t == keyPress && s `elem` [xK_0..xK_9] -> put (numKeyToN s)
| otherwise -> preview
where numKeyToN = subtract 48 . read . show
-- | Given a stack element and a stack, shift or insert the element (window)
-- at the currently focused position.
@@ -178,7 +176,7 @@ rotOpposite' :: W.Stack a -> W.Stack a
rotOpposite' (W.Stack t l r) = W.Stack t' l' r'
where rrvl = r ++ reverse l
part = (length rrvl + 1) `div` 2
(l',t':r') = second reverse . splitAt (length l) $
(l', notEmpty -> t' :| r') = second reverse . splitAt (length l) $
reverse (take part rrvl ++ t : drop part rrvl)
@@ -204,8 +202,8 @@ rotFocusedDown = windows . W.modify' $ rotFocused' rotDown
rotFocused' :: ([a] -> [a]) -> W.Stack a -> W.Stack a
rotFocused' _ s@(W.Stack _ [] []) = s
rotFocused' f (W.Stack t [] (r:rs)) = W.Stack t' [] (r:rs') -- Master has focus
where (t':rs') = f (t:rs)
rotFocused' f s@(W.Stack _ _ _) = rotSlaves' f s -- otherwise
where (notEmpty -> t' :| rs') = f (t:rs)
rotFocused' f s@W.Stack{} = rotSlaves' f s -- otherwise
-- $unfocused
@@ -222,14 +220,5 @@ rotUnfocused' :: ([a] -> [a]) -> W.Stack a -> W.Stack a
rotUnfocused' _ s@(W.Stack _ [] []) = s
rotUnfocused' f s@(W.Stack _ [] _ ) = rotSlaves' f s -- Master has focus
rotUnfocused' f (W.Stack t ls rs) = W.Stack t (reverse revls') rs' -- otherwise
where (master:revls) = reverse ls
where (master :| revls) = NE.reverse (let l:ll = ls in l :| ll)
(revls',rs') = splitAt (length ls) (f $ master:revls ++ rs)
-- $generic
-- Generic list rotations such that @rotUp [1..4]@ is equivalent to
-- @[2,3,4,1]@ and @rotDown [1..4]@ to @[4,1,2,3]@. They both are
-- @id@ for null or singleton lists.
rotUp :: [a] -> [a]
rotUp l = drop 1 l ++ take 1 l
rotDown :: [a] -> [a]
rotDown = reverse . rotUp . reverse

View File

@@ -0,0 +1,111 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleWorkspaceByScreen
-- Description : Cycle workspaces in a screen-aware fashion.
-- Copyright : (c) 2017 Ivan Malison
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : IvanMalison@gmail.com
-- Stability : unstable
-- Portability : unportable
--
-- Cycle through previously viewed workspaces in the order they were viewed most
-- recently on the screen where cycling is taking place.
--
-----------------------------------------------------------------------------
module XMonad.Actions.CycleWorkspaceByScreen (
-- * Usage
-- $usage
cycleWorkspaceOnScreen
, cycleWorkspaceOnCurrentScreen
, handleKeyEvent
, repeatableAction
) where
import Data.IORef
import XMonad
import XMonad.Prelude
import XMonad.Hooks.WorkspaceHistory
import XMonad.Actions.Repeatable (repeatable)
import qualified XMonad.StackSet as W
-- $usage
--
-- To use this module, first import it as well as
-- "XMonad.Hooks.WorkspaceHistory":
--
-- > import XMonad.Hooks.WorkspaceHistory (workspaceHistoryHook)
-- > import XMonad.Actions.CycleWorkspaceByScreen
--
-- Then add 'workspaceHistoryHook' to your @logHook@ like this:
--
-- > main :: IO ()
-- > main = xmonad $ def
-- > { ...
-- > , logHook = workspaceHistoryHook >> ...
-- > }
--
-- Finally, define a new keybinding for cycling (seen) workspaces per
-- screen:
--
-- > , ((mod4Mask, xK_slash), cycleWorkspaceOnCurrentScreen [xK_Super_L] xK_slash xK_p)
{-# DEPRECATED repeatableAction "Use XMonad.Actions.Repeatable.repeatable" #-}
repeatableAction :: [KeySym] -> KeySym -> (EventType -> KeySym -> X ()) -> X ()
repeatableAction = repeatable
handleKeyEvent :: EventType
-> KeySym
-> X ()
-> EventType
-> KeySym
-> Maybe (X ())
handleKeyEvent eventType key action = helper
where
helper et k
| et == eventType && k == key = Just action
| otherwise = Nothing
runFirst :: [EventType -> KeySym -> Maybe (X ())] -> EventType -> KeySym -> X ()
runFirst matchers eventType key =
fromMaybe (return ()) $ join $ find isJust $ map (\fn -> fn eventType key) matchers
-- | Like 'XMonad.Actions.CycleRecentWS.cycleRecentWS', but only cycle
-- through the most recent workspaces on the given screen.
cycleWorkspaceOnScreen
:: ScreenId -- ^ The screen to cycle on.
-> [KeySym] -- ^ A list of modifier keys used when invoking this
-- action; as soon as one of them is released, the final
-- switch is made.
-> KeySym -- ^ Key used to switch to next workspace.
-> KeySym -- ^ Key used to switch to previous workspace.
-> X ()
cycleWorkspaceOnScreen screenId mods nextKey prevKey = workspaceHistoryTransaction $ do
startingHistory <- workspaceHistoryByScreen
currentWSIndex <- io $ newIORef 1
let cycleWorkspaces = fromMaybe [] $ lookup screenId startingHistory
getAndIncrementWS increment = do
current <- readIORef currentWSIndex
modifyIORef
currentWSIndex
((`mod` length cycleWorkspaces) . (+ increment))
return $ cycleWorkspaces !! current
focusIncrement i = io (getAndIncrementWS i) >>= (windows . W.greedyView)
repeatable mods nextKey $
runFirst
[ handleKeyEvent keyPress nextKey $ focusIncrement 1
, handleKeyEvent keyPress prevKey $ focusIncrement (-1)
]
return ()
-- | Like 'cycleWorkspaceOnScreen', but supply the currently focused
-- screen as the @screenId@.
cycleWorkspaceOnCurrentScreen
:: [KeySym] -> KeySym -> KeySym -> X ()
cycleWorkspaceOnCurrentScreen mods n p =
withWindowSet $ \ws ->
cycleWorkspaceOnScreen (W.screen $ W.current ws) mods n p

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DeManage
-- Description : Cease management of a window without unmapping it.
-- Copyright : (c) Spencer Janssen <spencerjanssen@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -38,7 +39,7 @@ import qualified XMonad.StackSet as W
import XMonad
-- $usage
-- To use demanage, add this import to your @~\/.xmonad\/xmonad.hs@:
-- To use demanage, add this import to your @xmonad.hs@:
--
-- > import XMonad.Actions.DeManage
--
@@ -47,7 +48,7 @@ import XMonad
-- > , ((modm, xK_d ), withFocused demanage)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Stop managing the currently focused window.
demanage :: Window -> X ()

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DwmPromote
-- Description : DWM-like swap function for xmonad.
-- Copyright : (c) Miikka Koskinen 2007
-- License : BSD3-style (see LICENSE)
--
@@ -24,10 +25,13 @@ module XMonad.Actions.DwmPromote (
import XMonad
import XMonad.StackSet
import XMonad.Prelude
import qualified Data.List.NonEmpty as NE
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.DwmPromote
--
@@ -36,7 +40,7 @@ import XMonad.StackSet
-- > , ((modm, xK_Return), dwmpromote)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Swap the focused window with the master window. If focus is in
-- the master, swap it with the next window in the stack. Focus
@@ -44,6 +48,6 @@ import XMonad.StackSet
dwmpromote :: X ()
dwmpromote = windows $ modify' $
\c -> case c of
Stack _ [] [] -> c
Stack t [] (x:rs) -> Stack x [] (t:rs)
Stack t ls rs -> Stack t [] (ys ++ x : rs) where (x:ys) = reverse ls
Stack _ [] [] -> c
Stack t [] (r:rs) -> Stack r [] (t:rs)
Stack t (l:ls) rs -> Stack t [] (ys ++ y : rs) where (y :| ys) = NE.reverse (l :| ls)

View File

@@ -0,0 +1,359 @@
--------------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicProjects
-- Description : Treat workspaces as individual project areas.
-- Copyright : (c) Peter J. Jones
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Peter Jones <pjones@devalot.com>
-- Stability : unstable
-- Portability : not portable
--
-- Imbues workspaces with additional features so they can be treated
-- as individual project areas.
--------------------------------------------------------------------------------
module XMonad.Actions.DynamicProjects
( -- * Overview
-- $overview
-- * Usage
-- $usage
-- * Types
Project (..)
, ProjectName
-- * Hooks
, dynamicProjects
-- * Bindings
, switchProjectPrompt
, shiftToProjectPrompt
, renameProjectPrompt
, changeProjectDirPrompt
-- * Helper Functions
, switchProject
, shiftToProject
, lookupProject
, currentProject
, activateProject
, modifyProject
) where
--------------------------------------------------------------------------------
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import System.Directory (setCurrentDirectory, getHomeDirectory, makeAbsolute)
import XMonad.Prelude
import XMonad
import XMonad.Actions.DynamicWorkspaces
import XMonad.Prompt
import XMonad.Prompt.Directory
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
--------------------------------------------------------------------------------
-- $overview
-- Inspired by @TopicSpace@, @DynamicWorkspaces@, and @WorkspaceDir@,
-- @DynamicProjects@ treats workspaces as projects while maintaining
-- compatibility with all existing workspace-related functionality in
-- XMonad.
--
-- Instead of using generic workspace names such as @3@ or @work@,
-- @DynamicProjects@ allows you to dedicate workspaces to specific
-- projects and then switch between projects easily.
--
-- A project is made up of a name, working directory, and a start-up
-- hook. When you switch to a workspace, @DynamicProjects@ changes
-- the working directory to the one configured for the matching
-- project. If the workspace doesn't have any windows, the project's
-- start-up hook is executed. This allows you to launch applications
-- or further configure the workspace/project.
--
-- When using the @switchProjectPrompt@ function, workspaces are
-- created as needed. This means you can create new project spaces
-- (and therefore workspaces) on the fly. (These dynamic projects are
-- not preserved across restarts.)
--
-- Additionally, frequently used projects can be configured statically
-- in your XMonad configuration. Doing so allows you to configure the
-- per-project start-up hook.
--------------------------------------------------------------------------------
-- $usage
-- To use @DynamicProjects@ you need to add it to your XMonad
-- configuration and then configure some optional key bindings.
--
-- > import XMonad.Actions.DynamicProjects
--
-- Start by defining some projects:
--
-- > projects :: [Project]
-- > projects =
-- > [ Project { projectName = "scratch"
-- > , projectDirectory = "~/"
-- > , projectStartHook = Nothing
-- > }
-- >
-- > , Project { projectName = "browser"
-- > , projectDirectory = "~/download"
-- > , projectStartHook = Just $ do spawn "conkeror"
-- > spawn "chromium"
-- > }
-- > ]
--
-- Then inject @DynamicProjects@ into your XMonad configuration:
--
-- > main = xmonad $ dynamicProjects projects def
--
-- And finally, configure some optional key bindings:
--
-- > , ((modm, xK_space), switchProjectPrompt def)
-- > , ((modm, xK_slash), shiftToProjectPrompt def)
--
-- For detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
--------------------------------------------------------------------------------
type ProjectName = String
type ProjectTable = Map ProjectName Project
--------------------------------------------------------------------------------
-- | Details about a workspace that represents a project.
data Project = Project
{ projectName :: !ProjectName -- ^ Workspace name.
, projectDirectory :: !FilePath -- ^ Working directory.
, projectStartHook :: !(Maybe (X ())) -- ^ Optional start-up hook.
}
--------------------------------------------------------------------------------
-- | Internal project state.
data ProjectState = ProjectState
{ projects :: !ProjectTable
, previousProject :: !(Maybe WorkspaceId)
}
--------------------------------------------------------------------------------
instance ExtensionClass ProjectState where
initialValue = ProjectState Map.empty Nothing
--------------------------------------------------------------------------------
-- Internal types for working with XPrompt.
data ProjectPrompt = ProjectPrompt XPConfig ProjectMode [ProjectName]
data ProjectMode = SwitchMode | ShiftMode | RenameMode | DirMode
instance XPrompt ProjectPrompt where
showXPrompt (ProjectPrompt _ submode _) =
case submode of
SwitchMode -> "Switch or Create Project: "
ShiftMode -> "Send Window to Project: "
RenameMode -> "New Project Name: "
DirMode -> "Change Project Directory: "
completionFunction (ProjectPrompt _ RenameMode _) = return . (:[])
completionFunction (ProjectPrompt c DirMode _) =
let xpt = directoryMultipleModes' (complCaseSensitivity c) "" (const $ return ())
in completionFunction xpt
completionFunction (ProjectPrompt c _ ns) = mkComplFunFromList' c ns
modeAction (ProjectPrompt _ SwitchMode _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
case Map.lookup name ps of
Just p -> switchProject p
Nothing | null name -> return ()
| otherwise -> switchProject (defProject name)
modeAction (ProjectPrompt _ ShiftMode _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
shiftToProject . fromMaybe (defProject name) $ Map.lookup name ps
modeAction (ProjectPrompt _ RenameMode _) name _ =
when (not (null name) && not (all isSpace name)) $ do
renameWorkspaceByName name
modifyProject (\p -> p { projectName = name })
modeAction (ProjectPrompt _ DirMode _) buf auto = do
let dir' = if null auto then buf else auto
dir <- io $ makeAbsolute dir'
modifyProject (\p -> p { projectDirectory = dir })
--------------------------------------------------------------------------------
-- | Add dynamic projects support to the given config.
dynamicProjects :: [Project] -> XConfig a -> XConfig a
dynamicProjects ps c =
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)
xstate <- XS.get
unless (Just name == previousProject xstate) $ do
XS.put (xstate {previousProject = Just name})
activateProject . fromMaybe (defProject name) $
Map.lookup name (projects xstate)
--------------------------------------------------------------------------------
-- | Start-up hook for recording configured projects.
dynamicProjectsStartupHook :: [Project] -> X ()
dynamicProjectsStartupHook ps = XS.modify go
where
go :: ProjectState -> ProjectState
go s = s {projects = update $ projects s}
update :: ProjectTable -> ProjectTable
update = Map.union (Map.fromList $ map entry ps)
entry :: Project -> (ProjectName, Project)
entry p = (projectName p, addDefaultHook p)
-- Force the hook to be a @Just@ so that it doesn't automatically
-- get deleted when switching away from a workspace with no
-- windows.
addDefaultHook :: Project -> Project
addDefaultHook p = p { projectStartHook = projectStartHook p <|>
Just (return ())
}
--------------------------------------------------------------------------------
-- | Find a project based on its name.
lookupProject :: ProjectName -> X (Maybe Project)
lookupProject name = Map.lookup name <$> XS.gets projects
--------------------------------------------------------------------------------
-- | Fetch the current project (the one being used for the currently
-- active workspace).
currentProject :: X Project
currentProject = do
name <- gets (W.tag . W.workspace . W.current . windowset)
proj <- lookupProject name
return $ fromMaybe (defProject name) proj
--------------------------------------------------------------------------------
-- | Modify the current project using a pure function.
modifyProject :: (Project -> Project) -> X ()
modifyProject f = do
p <- currentProject
ps <- XS.gets projects
-- If a project is renamed to match another project, the old project
-- will be removed and replaced with this one.
let new = f p
ps' = Map.insert (projectName new) new $ Map.delete (projectName p) ps
XS.modify $ \s -> s {projects = ps'}
activateProject new
--------------------------------------------------------------------------------
-- | Switch to the given project.
switchProject :: Project -> X ()
switchProject p = do
oldws <- gets (W.workspace . W.current . windowset)
oldp <- currentProject
let name = W.tag oldws
ws = W.integrate' (W.stack oldws)
-- 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)) $ do
removeWorkspaceByTag name -- also remove the old workspace
XS.modify (\s -> s {projects = Map.delete name $ projects s})
appendWorkspace (projectName p)
--------------------------------------------------------------------------------
-- | Prompt for a project name and then switch to it. Automatically
-- creates a project if a new name is returned from the prompt.
switchProjectPrompt :: XPConfig -> X ()
switchProjectPrompt = projectPrompt [ SwitchMode
, ShiftMode
, RenameMode
, DirMode
]
--------------------------------------------------------------------------------
-- | Shift the currently focused window to the given project.
shiftToProject :: Project -> X ()
shiftToProject p = do
addHiddenWorkspace (projectName p)
windows (W.shift $ projectName p)
--------------------------------------------------------------------------------
-- | Prompts for a project name and then shifts the currently focused
-- window to that project.
shiftToProjectPrompt :: XPConfig -> X ()
shiftToProjectPrompt = projectPrompt [ ShiftMode
, RenameMode
, SwitchMode
, DirMode
]
--------------------------------------------------------------------------------
-- | Rename the current project.
renameProjectPrompt :: XPConfig -> X ()
renameProjectPrompt = projectPrompt [ RenameMode
, DirMode
, SwitchMode
, ShiftMode
]
--------------------------------------------------------------------------------
-- | Change the working directory used for the current project.
--
-- NOTE: This will only affect new processed started in this project.
-- Existing processes will maintain the previous working directory.
changeProjectDirPrompt :: XPConfig -> X ()
changeProjectDirPrompt = projectPrompt [ DirMode
, SwitchMode
, ShiftMode
, RenameMode
]
--------------------------------------------------------------------------------
-- | Prompt for a project name.
projectPrompt :: [ProjectMode] -> XPConfig -> X ()
projectPrompt submodes c = do
ws <- map W.tag <$> gets (W.workspaces . windowset)
ps <- XS.gets projects
let names = sort (Map.keys ps `union` ws)
modes = map (\m -> XPT $ ProjectPrompt c m names) submodes
mkXPromptWithModes modes c
--------------------------------------------------------------------------------
-- | Activate a project by updating the working directory and
-- possibly running its start-up hook. This function is automatically
-- invoked when the workspace changes.
activateProject :: Project -> X ()
activateProject p = do
ws <- gets (W.integrate' . W.stack . W.workspace . W.current . windowset)
home <- io getHomeDirectory
-- Change to the project's directory.
catchIO (setCurrentDirectory $ expandHome home $ projectDirectory p)
-- Possibly run the project's startup hook.
when (null ws) $ fromMaybe (return ()) (projectStartHook p)
where
-- Replace an initial @~@ character with the home directory.
expandHome :: FilePath -> FilePath -> FilePath
expandHome home dir = case stripPrefix "~" dir of
Nothing -> dir
Just xs -> home ++ xs
--------------------------------------------------------------------------------
-- | Default project.
defProject :: ProjectName -> Project
defProject name = Project name "~/" Nothing

View File

@@ -1,8 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicWorkspaceGroups
-- Description : Dynamically manage workspace groups in multi-head setups.
-- Copyright : (c) Brent Yorgey 2009
-- License : BSD-style (see LICENSE)
--
@@ -23,6 +22,7 @@ module XMonad.Actions.DynamicWorkspaceGroups
WSGroupId
, addRawWSGroup
, addWSGroup
, addCurrentWSGroup
, forgetWSGroup
@@ -33,20 +33,25 @@ module XMonad.Actions.DynamicWorkspaceGroups
, promptWSGroupForget
, WSGPrompt
-- * TopicSpace Integration
-- $topics
, viewTopicGroup
, promptTopicGroupView
) where
import Data.List (find)
import Control.Arrow ((&&&))
import qualified Data.Map as M
import XMonad
import XMonad.Prelude (find, for_)
import qualified XMonad.StackSet as W
import XMonad.Prompt
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Actions.TopicSpace
-- $usage
-- You can use this module by importing it into your ~\/.xmonad\/xmonad.hs file:
-- You can use this module by importing it into your @xmonad.hs@ file:
--
-- > import XMonad.Actions.DynamicWorkspaceGroups
--
@@ -62,30 +67,35 @@ type WSGroup = [(ScreenId,WorkspaceId)]
type WSGroupId = String
data WSGroupStorage = WSG { unWSG :: M.Map WSGroupId WSGroup }
deriving (Typeable, Read, Show)
newtype WSGroupStorage = WSG { unWSG :: M.Map WSGroupId WSGroup }
deriving (Read, Show)
withWSG :: (M.Map WSGroupId WSGroup -> M.Map WSGroupId WSGroup) -> WSGroupStorage -> WSGroupStorage
withWSG f = WSG . f . unWSG
instance ExtensionClass WSGroupStorage where
initialValue = WSG $ M.empty
initialValue = WSG M.empty
extensionType = PersistentExtension
-- | Add a new workspace group of the given name, mapping to an
-- explicitly specified association between screen IDs and workspace
-- names. This function could be useful for, say, creating some
-- standard workspace groups in your startup hook.
addRawWSGroup :: WSGroupId -> [(ScreenId, WorkspaceId)] -> X ()
addRawWSGroup name = XS.modify . withWSG . M.insert name
-- | Add a new workspace group with the given name.
addWSGroup :: WSGroupId -> [WorkspaceId] -> X ()
addWSGroup name wids = withWindowSet $ \w -> do
let wss = map ((W.tag . W.workspace) &&& W.screen) $ W.screens w
wmap = mapM (strength . (flip lookup wss &&& id)) wids
case wmap of
Just ps -> XS.modify . withWSG . M.insert name $ ps
Nothing -> return ()
for_ wmap (addRawWSGroup name)
where strength (ma, b) = ma >>= \a -> return (a,b)
-- | Give a name to the current workspace group.
addCurrentWSGroup :: WSGroupId -> X ()
addCurrentWSGroup name = withWindowSet $ \w ->
addWSGroup name $ map (W.tag . W.workspace) (W.current w : W.visible w)
addWSGroup name $ map (W.tag . W.workspace) (reverse $ W.current w : W.visible w)
-- | Delete the named workspace group from the list of workspace
-- groups. Note that this has no effect on the workspaces involved;
@@ -95,20 +105,23 @@ forgetWSGroup = XS.modify . withWSG . M.delete
-- | View the workspace group with the given name.
viewWSGroup :: WSGroupId -> X ()
viewWSGroup name = do
WSG m <- XS.get
case M.lookup name m of
Just grp -> mapM_ (uncurry viewWS) grp
Nothing -> return ()
viewWSGroup = viewGroup (windows . W.greedyView)
-- | View the given workspace on the given screen.
viewWS :: ScreenId -> WorkspaceId -> X ()
viewWS sid wid = do
-- | Internal function for viewing a group.
viewGroup :: (WorkspaceId -> X ()) -> WSGroupId -> X ()
viewGroup fview name = do
WSG m <- XS.get
for_ (M.lookup name m) $
mapM_ (uncurry (viewWS fview))
-- | View the given workspace on the given screen, using the provided function.
viewWS :: (WorkspaceId -> X ()) -> ScreenId -> WorkspaceId -> X ()
viewWS fview sid wid = do
mw <- findScreenWS sid
case mw of
Just w -> do
windows $ W.view w
windows $ W.greedyView wid
fview wid
Nothing -> return ()
-- | Find the workspace which is currently on the given screen.
@@ -116,16 +129,20 @@ findScreenWS :: ScreenId -> X (Maybe WorkspaceId)
findScreenWS sid = withWindowSet $
return . fmap (W.tag . W.workspace) . find ((==sid) . W.screen) . W.screens
data WSGPrompt = WSGPrompt String
newtype WSGPrompt = WSGPrompt String
instance XPrompt WSGPrompt where
showXPrompt (WSGPrompt s) = s
-- | Prompt for a workspace group to view.
promptWSGroupView :: XPConfig -> String -> X ()
promptWSGroupView xp s = do
promptWSGroupView = promptGroupView viewWSGroup
-- | Internal function for making a prompt to view a workspace group
promptGroupView :: (WSGroupId -> X ()) -> XPConfig -> String -> X ()
promptGroupView fview xp s = do
gs <- fmap (M.keys . unWSG) XS.get
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' gs) viewWSGroup
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' xp gs) fview
-- | Prompt for a name for the current workspace group.
promptWSGroupAdd :: XPConfig -> String -> X ()
@@ -136,4 +153,25 @@ promptWSGroupAdd xp s =
promptWSGroupForget :: XPConfig -> String -> X ()
promptWSGroupForget xp s = do
gs <- fmap (M.keys . unWSG) XS.get
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' gs) forgetWSGroup
mkXPrompt (WSGPrompt s) xp (mkComplFunFromList' xp gs) forgetWSGroup
-- $topics
-- You can use this module with "XMonad.Actions.TopicSpace" — just replace
-- 'promptWSGroupView' with 'promptTopicGroupView':
--
-- > , ("M-y n", promptWSGroupAdd myXPConfig "Name this group: ")
-- > , ("M-y g", promptTopicGroupView myTopicConfig myXPConfig "Go to group: ")
-- > , ("M-y d", promptWSGroupForget myXPConfig "Forget group: ")
--
-- It's also a good idea to replace 'spawn' with
-- 'XMonad.Actions.SpawnOn.spawnOn' or 'XMonad.Actions.SpawnOn.spawnHere' in
-- your topic actions, so everything is spawned where it should be.
-- | Prompt for a workspace group to view, treating the workspaces as topics.
promptTopicGroupView :: TopicConfig -> XPConfig -> String -> X ()
promptTopicGroupView = promptGroupView . viewTopicGroup
-- | View the workspace group with the given name, treating the workspaces as
-- topics.
viewTopicGroup :: TopicConfig -> WSGroupId -> X ()
viewTopicGroup = viewGroup . switchTopic

View File

@@ -1,8 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicWorkspaceOrder
-- Description : Remember a dynamically updateable ordering on workspaces.
-- Copyright : (c) Brent Yorgey 2009
-- License : BSD-style (see LICENSE)
--
@@ -12,7 +11,7 @@
--
-- Remember a dynamically updateable ordering on workspaces, together
-- with tools for using this ordering with "XMonad.Actions.CycleWS"
-- and "XMonad.Hooks.DynamicLog".
-- and "XMonad.Hooks.StatusBar.PP".
--
-----------------------------------------------------------------------------
@@ -23,11 +22,16 @@ module XMonad.Actions.DynamicWorkspaceOrder
getWsCompareByOrder
, getSortByOrder
, swapWith
, swapWithCurrent
, swapOrder
, updateName
, removeName
, moveTo
, moveToGreedy
, shiftTo
, withNthWorkspace'
, withNthWorkspace
) where
@@ -41,11 +45,11 @@ import XMonad.Actions.CycleWS (findWorkspace, WSType(..), Direction1D(..), doTo)
import qualified Data.Map as M
import qualified Data.Set as S
import Data.Maybe (fromJust, fromMaybe)
import XMonad.Prelude (fromJust, fromMaybe)
import Data.Ord (comparing)
-- $usage
-- You can use this module by importing it into your ~\/.xmonad\/xmonad.hs file:
-- You can use this module by importing it into your @xmonad.hs@ file:
--
-- > import qualified XMonad.Actions.DynamicWorkspaceOrder as DO
--
@@ -64,10 +68,10 @@ import Data.Ord (comparing)
-- order of workspaces must be updated to use the auxiliary ordering.
--
-- To change the order in which workspaces are displayed by
-- "XMonad.Hooks.DynamicLog", use 'getSortByOrder' in your
-- 'XMonad.Hooks.DynamicLog.ppSort' field, for example:
-- "XMonad.Hooks.StatusBar.PP", use 'getSortByOrder' in your
-- 'XMonad.Hooks.StatusBar.PP.ppSort' field, for example:
--
-- > ... dynamicLogWithPP $ byorgeyPP {
-- > myPP = ... byorgeyPP {
-- > ...
-- > , ppSort = DO.getSortByOrder
-- > ...
@@ -86,8 +90,8 @@ import Data.Ord (comparing)
-- tweak as desired.
-- | Extensible state storage for the workspace order.
data WSOrderStorage = WSO { unWSO :: Maybe (M.Map WorkspaceId Int) }
deriving (Typeable, Read, Show)
newtype WSOrderStorage = WSO { unWSO :: Maybe (M.Map WorkspaceId Int) }
deriving (Read, Show)
instance ExtensionClass WSOrderStorage where
initialValue = WSO Nothing
@@ -148,10 +152,26 @@ swapOrder :: WorkspaceId -> WorkspaceId -> X ()
swapOrder w1 w2 = do
io $ print (w1,w2)
WSO (Just m) <- XS.get
let [i1,i2] = map (fromJust . flip M.lookup m) [w1,w2]
let i1 = fromJust (w1 `M.lookup` m)
let i2 = fromJust (w2 `M.lookup` m)
XS.modify (withWSO (M.insert w1 i2 . M.insert w2 i1))
windows id -- force a status bar update
-- | Update the name of a workspace in the stored order.
updateName :: WorkspaceId -> WorkspaceId -> X ()
updateName oldId newId = XS.modify . withWSO $ changeKey oldId newId
-- | Remove a workspace from the stored order.
removeName :: WorkspaceId -> X ()
removeName = XS.modify . withWSO . M.delete
-- | Update a key in a Map.
changeKey :: Ord k => k -> k -> M.Map k a -> M.Map k a
changeKey oldKey newKey oldMap =
case M.updateLookupWithKey (\_ _ -> Nothing) oldKey oldMap of
(Nothing, _) -> oldMap
(Just val, newMap) -> M.insert newKey val newMap
-- | View the next workspace of the given type in the given direction,
-- where \"next\" is determined using the dynamic workspace order.
moveTo :: Direction1D -> WSType -> X ()
@@ -166,13 +186,19 @@ moveToGreedy dir t = doTo dir t getSortByOrder (windows . W.greedyView)
shiftTo :: Direction1D -> WSType -> X ()
shiftTo dir t = doTo dir t getSortByOrder (windows . W.shift)
-- | Do something with the nth workspace in the dynamic order after
-- transforming it. The callback is given the workspace's tag as well
-- as the 'WindowSet' of the workspace itself.
withNthWorkspace' :: ([WorkspaceId] -> [WorkspaceId]) -> (String -> WindowSet -> WindowSet) -> Int -> X ()
withNthWorkspace' tr job wnum = do
sort <- getSortByOrder
ws <- gets (tr . map W.tag . sort . W.workspaces . windowset)
case drop wnum ws of
(w:_) -> windows $ job w
[] -> return ()
-- | Do something with the nth workspace in the dynamic order. The
-- callback is given the workspace's tag as well as the 'WindowSet'
-- of the workspace itself.
withNthWorkspace :: (String -> WindowSet -> WindowSet) -> Int -> X ()
withNthWorkspace job wnum = do
sort <- getSortByOrder
ws <- gets (map W.tag . sort . W.workspaces . windowset)
case drop wnum ws of
(w:_) -> windows $ job w
[] -> return ()
withNthWorkspace = withNthWorkspace' id

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicWorkspaces
-- Description : Provides bindings to add and delete workspaces.
-- Copyright : (c) David Roundy <droundy@darcs.net>
-- License : BSD3-style (see LICENSE)
--
@@ -16,28 +17,34 @@ module XMonad.Actions.DynamicWorkspaces (
-- * Usage
-- $usage
addWorkspace, addWorkspacePrompt,
appendWorkspace, appendWorkspacePrompt,
addWorkspaceAt,
removeWorkspace,
removeWorkspaceByTag,
removeEmptyWorkspace,
removeEmptyWorkspaceByTag,
removeEmptyWorkspaceAfter,
removeEmptyWorkspaceAfterExcept,
addHiddenWorkspace,
addHiddenWorkspace, addHiddenWorkspaceAt,
withWorkspace,
selectWorkspace, renameWorkspace,
renameWorkspaceByName,
toNthWorkspace, withNthWorkspace
toNthWorkspace, withNthWorkspace,
setWorkspaceIndex, withWorkspaceIndex,
WorkspaceIndex
) where
import XMonad.Prelude (find, isNothing, nub, when)
import XMonad hiding (workspaces)
import XMonad.StackSet hiding (filter, modify, delete)
import XMonad.Prompt.Workspace ( Wor(Wor), workspacePrompt )
import XMonad.Prompt ( XPConfig, mkXPrompt )
import XMonad.Prompt ( XPConfig, mkComplFunFromList', mkXPrompt )
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:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.DynamicWorkspaces
-- > import XMonad.Actions.CopyWindow(copy)
@@ -45,25 +52,60 @@ import Control.Monad (when)
-- Then add keybindings like the following:
--
-- > , ((modm .|. shiftMask, xK_BackSpace), removeWorkspace)
-- > , ((modm .|. shiftMask, xK_v ), selectWorkspace defaultXPConfig)
-- > , ((modm, xK_m ), withWorkspace defaultXPConfig (windows . W.shift))
-- > , ((modm .|. shiftMask, xK_m ), withWorkspace defaultXPConfig (windows . copy))
-- > , ((modm .|. shiftMask, xK_r ), renameWorkspace defaultXPConfig)
-- > , ((modm .|. shiftMask, xK_v ), selectWorkspace def)
-- > , ((modm, xK_m ), withWorkspace def (windows . W.shift))
-- > , ((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 'defaultXPConfig'.
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>. 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
mkCompl :: [String] -> String -> IO [String]
mkCompl l s = return $ filter (\x -> take (length s) x == s) l
-- | Internal dynamic project state that stores a mapping between
-- workspace indexes and workspace tags.
newtype DynamicWorkspaceState = DynamicWorkspaceState {workspaceIndexMap :: Map.Map WorkspaceIndex WorkspaceTag}
deriving (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 <$> XS.gets workspaceIndexMap
withWorkspace :: XPConfig -> (String -> X ()) -> X ()
withWorkspace c job = do ws <- gets (workspaces . windowset)
@@ -71,16 +113,21 @@ withWorkspace c job = do ws <- gets (workspaces . windowset)
let ts = map tag $ sort ws
job' t | t `elem` ts = job t
| otherwise = addHiddenWorkspace t >> job t
mkXPrompt (Wor "") c (mkCompl ts) job'
mkXPrompt (Wor "") c (mkComplFunFromList' c ts) job'
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 oldIM newIM = do
wmap <- XS.gets workspaceIndexMap
XS.modify $ \s -> s {workspaceIndexMap = Map.map (\t -> if t == oldIM then newIM else t) wmap}
toNthWorkspace :: (String -> X ()) -> Int -> X ()
toNthWorkspace job wnum = do sort <- getSortByIndex
@@ -107,20 +154,41 @@ selectWorkspace conf = workspacePrompt conf $ \w ->
-- workspace with the given name already exists; then switch to the
-- newly created workspace.
addWorkspace :: String -> X ()
addWorkspace newtag = addHiddenWorkspace newtag >> windows (greedyView newtag)
addWorkspace = addWorkspaceAt (:)
-- | Same as addWorkspace, but adds the workspace to the end of the list of workspaces
appendWorkspace :: String -> X()
appendWorkspace = addWorkspaceAt (flip (++) . return)
-- | Adds a new workspace with the given name to the current list of workspaces.
-- This function allows the user to pass a function that inserts an element
-- into a list at an arbitrary spot.
addWorkspaceAt :: (WindowSpace -> [WindowSpace] -> [WindowSpace]) -> String -> X ()
addWorkspaceAt add newtag = addHiddenWorkspaceAt add newtag >> windows (greedyView newtag)
-- | Prompt for the name of a new workspace, add it if it does not
-- already exist, and switch to it.
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
-- if it does not already exist, and switch to it.
appendWorkspacePrompt :: XPConfig -> X ()
appendWorkspacePrompt conf = mkXPrompt (Wor "New workspace name: ") conf (const (return [])) appendWorkspace
-- | Add a new hidden workspace with the given name, or do nothing if
-- a workspace with the given name already exists. Takes a function to insert
-- the workspace at an arbitrary spot in the list.
addHiddenWorkspaceAt :: (WindowSpace -> [WindowSpace] -> [WindowSpace]) -> String -> X ()
addHiddenWorkspaceAt add newtag =
whenX (gets (not . tagMember newtag . windowset)) $ do
l <- asks (layoutHook . config)
windows (addHiddenWorkspace' add newtag l)
-- | Add a new hidden workspace with the given name, or do nothing if
-- a workspace with the given name already exists.
addHiddenWorkspace :: String -> X ()
addHiddenWorkspace newtag =
whenX (gets (not . tagMember newtag . windowset)) $ do
l <- asks (layoutHook . config)
windows (addHiddenWorkspace' newtag l)
addHiddenWorkspace = addHiddenWorkspaceAt (:)
-- | Remove the current workspace if it contains no windows.
removeEmptyWorkspace :: X ()
@@ -130,12 +198,11 @@ removeEmptyWorkspace = gets (currentTag . windowset) >>= removeEmptyWorkspaceByT
removeWorkspace :: X ()
removeWorkspace = gets (currentTag . windowset) >>= removeWorkspaceByTag
-- | Remove workspace with specific tag if it contains no windows. Only works
-- on the current or the last workspace.
-- | Remove workspace with specific tag if it contains no windows.
removeEmptyWorkspaceByTag :: String -> X ()
removeEmptyWorkspaceByTag t = whenX (isEmpty t) $ removeWorkspaceByTag t
-- | Remove workspace with specific tag. Only works on the current or the last workspace.
-- | Remove workspace with specific tag.
removeWorkspaceByTag :: String -> X ()
removeWorkspaceByTag torem = do
s <- gets windowset
@@ -166,16 +233,21 @@ isEmpty t = do wsl <- gets $ workspaces . windowset
let mws = find (\ws -> tag ws == t) wsl
return $ maybe True (isNothing . stack) mws
addHiddenWorkspace' :: i -> l -> StackSet i l a sid sd -> StackSet i l a sid sd
addHiddenWorkspace' newtag l s@(StackSet { hidden = ws }) = s { hidden = Workspace newtag l Nothing:ws }
addHiddenWorkspace' :: (Workspace i l a -> [Workspace i l a] -> [Workspace i l a]) -> i -> l -> StackSet i l a sid sd -> StackSet i l a sid sd
addHiddenWorkspace' add newtag l s@StackSet{ hidden = ws } = s { hidden = add (Workspace newtag l Nothing) ws }
removeWorkspace' :: (Eq i) => i -> StackSet i l a sid sd -> StackSet i l a sid sd
removeWorkspace' torem s@(StackSet { current = scr@(Screen { workspace = wc })
, hidden = (w:ws) })
| tag w == torem = s { current = scr { workspace = wc { stack = meld (stack w) (stack wc) } }
, hidden = ws }
-- | Remove the hidden workspace with the given tag from the StackSet, if
-- it exists. All the windows in that workspace are moved to the current
-- workspace.
removeWorkspace' :: (Eq i, Eq a) => i -> StackSet i l a sid sd -> StackSet i l a sid sd
removeWorkspace' torem s@StackSet{ current = scr@Screen { workspace = wc }
, hidden = hs }
= let (xs, ys) = break ((== torem) . tag) hs
in removeWorkspace'' xs ys
where meld Nothing Nothing = Nothing
meld x Nothing = x
meld Nothing x = x
meld (Just x) (Just y) = differentiate (integrate x ++ integrate y)
removeWorkspace' _ s = s
meld (Just x) (Just y) = differentiate . nub $ integrate x ++ integrate y
removeWorkspace'' xs (y:ys) = s { current = scr { workspace = wc { stack = meld (stack y) (stack wc) } }
, hidden = xs ++ ys }
removeWorkspace'' _ _ = s

View File

@@ -0,0 +1,391 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.EasyMotion
-- Description : Focus a visible window using a key chord.
-- Copyright : (c) Matt Kingston <mattkingston@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : mattkingston@gmail.com
-- Stability : unstable
-- Portability : unportable
--
-- Provides functionality to use key chords to focus a visible window. Overlays a unique key chord
-- (a string) above each visible window and allows the user to select a window by typing that
-- chord.
-- Inspired by <https://github.com/easymotion/vim-easymotion vim-easymotion>.
-- Thanks to <https://github.com/larkery Tom Hinton> for some feature inspiration and window
-- sorting code.
--
-----------------------------------------------------------------------------
module XMonad.Actions.EasyMotion ( -- * Usage
-- $usage
selectWindow
-- * Configuration
, EasyMotionConfig(..)
, ChordKeys(..)
, def
-- * Creating overlays
, fullSize
, fixedSize
, textSize
, proportional
, bar
) where
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Util.Font (releaseXMF, initXMF, Align(AlignCenter), XMonadFont(..), textExtentsXMF)
import XMonad.Util.XUtils (createNewWindow, paintAndWrite, deleteWindow, showWindow)
import Control.Arrow ((&&&))
import qualified Data.Map.Strict as M (Map, elems, map, mapWithKey)
-- $usage
--
-- You can use this module's basic functionality with the following in your
-- @xmonad.hs@:
--
-- > import XMonad.Actions.EasyMotion (selectWindow)
--
-- To customise
--
-- > import XMonad.Actions.EasyMotion (selectWindow, EasyMotionConfig(..))
--
-- Then add a keybinding and an action to the 'selectWindow' function.
-- In this case @M-f@ to focus the selected window:
--
-- > , ((modm, xK_f), selectWindow def >>= (`whenJust` windows . W.focusWindow))
--
-- Similarly, to kill a window with @M-f@:
--
-- > , ((modm, xK_f), selectWindow def >>= (`whenJust` killWindow))
--
-- See 'EasyMotionConfig' for all configuration options. A short summary follows.
--
-- Default chord keys are @s,d,f,j,k,l@. To customise these and display options assign
-- different values to 'def' (the default configuration):
--
-- > , ((modm, xK_f), (selectWindow def{sKeys = AnyKeys [xK_f, xK_d]}) >>= (`whenJust` windows . W.focusWindow))
--
-- You must supply at least two different keys in the 'sKeys' list. Keys provided earlier in the list
-- will be used preferentially—therefore, keys you would like to use more frequently should be
-- earlier in the list.
--
-- To map different sets of keys to different screens. The following configuration maps keys @fdsa@
-- to screen 0 and @hjkl@ to screen 1. Keys provided earlier in the list will be used preferentially.
-- Providing the same key for multiple screens is possible but will break down in some scenarios.
--
-- > import qualified Data.Map.Strict as StrictMap (fromList)
-- > emConf :: EasyMotionConfig
-- > emConf = def { sKeys = PerScreenKeys $ StrictMap.fromList [(0, [xK_f, xK_d, xK_s, xK_a]), (1, [xK_h, xK_j, xK_k, xK_l])] }
-- > -- key bindings
-- > , ((modm, xK_f), selectWindow emConf >>= (`whenJust` windows . W.focusWindow))
--
-- To customise the font:
--
-- > , ((modm, xK_f), (selectWindow def{emFont = "xft: Sans-40"}) >>= (`whenJust` windows . W.focusWindow))
--
-- The 'emFont' field provided is supplied directly to the 'initXMF' function. The default is
-- @"xft:Sans-100"@. Some example options:
--
-- > "xft: Sans-40"
-- > "xft: Arial-100"
-- > "xft: Cambria-80"
--
-- Customise the overlay by supplying a function to 'overlayF'. The signature is
-- @'Position' -> 'Rectangle' -> 'Rectangle'@. The parameters are the height in pixels of
-- the selection chord and the rectangle of the window to be overlaid. Some are provided:
--
-- > import XMonad.Actions.EasyMotion (selectWindow, EasyMotionConfig(..), proportional, bar, fullSize)
-- > , ((modm, xK_f), (selectWindow def{ overlayF = proportional 0.3 }) >>= (`whenJust` windows . W.focusWindow))
-- > , ((modm, xK_f), (selectWindow def{ overlayF = bar 0.5 }) >>= (`whenJust` windows . W.focusWindow))
-- > , ((modm, xK_f), (selectWindow def{ overlayF = fullSize }) >>= (`whenJust` windows . W.focusWindow))
-- > , ((modm, xK_f), (selectWindow def{ overlayF = fixedSize 300 350 }) >>= (`whenJust` windows . W.focusWindow))
-- TODO:
-- - An overlay function that creates an overlay a proportion of the width XOR height of the
-- window it's over, and with a fixed w/h proportion? E.g. overlay-height = 0.3 *
-- target-window-height; overlay-width = 0.5 * overlay-height.
-- - An overlay function that creates an overlay of a fixed w,h, aligned mid,mid, or parametrised
-- alignment?
-- - Parametrise chord generation?
-- - W.shift example; bring window from other screen to current screen? Only useful if we don't
-- show chords on current workspace.
-- - Use stringToKeysym, keysymToKeycode, keycodeToKeysym, keysymToString to take a string from
-- the user?
-- - Think a bit more about improving functionality with floating windows.
-- - currently, floating window z-order is not respected
-- - could ignore floating windows
-- - may be able to calculate the visible section of a floating window, and display the chord in
-- that space
-- - Provide an option to prepend the screen key to the easymotion keys (i.e. w,e,r)?
-- - overlay alpha
-- - Delay after selection so the user can see what they've chosen? Min-delay: 0 seconds. If
-- there's a delay, perhaps keep the other windows covered briefly to naturally draw the user's
-- attention to the window they've selected? Or briefly highlight the border of the selected
-- window?
-- - Option to cover windows that will not be selected by the current chord, such that it's
-- slightly more obvious where to maintain focus.
-- - Something unpleasant happens when the user provides only two keys (let's say f, d) for
-- chords. When they have five windows open, the following chords are generated: ddd, ddf, dfd,
-- dff, fdd. When 'f' is pressed, all chords disappear unexpectedly because we know there are no
-- other valid options. The user expects to press 'fdd'. This is an optimisation in software but
-- pretty bad for usability, as the user continues firing keys into their
-- now-unexpectedly-active window. And is of course only one concrete example of a more general
-- problem.
-- Short-term solution:
-- - Keep displaying the chord until the user has fully entered it
-- Fix:
-- - Show the shortest possible chords
-- | Associates a user window, an overlay window created by this module and a rectangle
-- circumscribing these windows
data OverlayWindow =
OverlayWindow { win :: !Window -- ^ The window managed by xmonad
, attrs :: !WindowAttributes -- ^ Window attributes for @win@
, overlay :: !Window -- ^ Our window used to display the overlay
, rect :: !Rectangle -- ^ The rectangle of @overlay@
}
-- | An overlay window and the chord used to select it
data Overlay =
Overlay { overlayWin :: !OverlayWindow -- ^ The window managed by xmonad
, chord :: ![KeySym] -- ^ The chord we'll display in the overlay
}
-- | Maps keys to windows. 'AnyKeys' maps keys to windows regardless which screen they're on.
-- 'PerScreenKeys' maps keys to screens to windows. See @Usage@ for more examples.
data ChordKeys = AnyKeys ![KeySym]
| PerScreenKeys !(M.Map ScreenId [KeySym])
-- | Configuration options for EasyMotion.
--
-- All colors are hex strings, e.g. "#000000"
--
-- If the number of windows for which chords are required exceeds 'maxChordLen', chords
-- will simply not be generated for these windows. In this way, single-key selection may be
-- preferred over the ability to select any window.
--
-- 'cancelKey', @xK_BackSpace@ and any duplicates will be removed from 'sKeys' if included.
-- See @Usage@ for examples of 'sKeys'.
data EasyMotionConfig =
EMConf { txtCol :: !String -- ^ Color of the text displayed
, bgCol :: !String -- ^ Color of the window overlaid
, overlayF :: !(Position -> Rectangle -> Rectangle) -- ^ Function to generate overlay rectangle
, borderCol :: !String -- ^ Color of the overlay window borders
, sKeys :: !ChordKeys -- ^ Keys to use for window selection
, cancelKey :: !KeySym -- ^ Key to use to cancel selection
, emFont :: !String -- ^ Font for selection characters (passed to 'initXMF')
, borderPx :: !Int -- ^ Width of border in pixels
, maxChordLen :: !Int -- ^ Maximum chord length. Use 0 for no maximum.
}
instance Default EasyMotionConfig where
def =
EMConf { txtCol = "#ffffff"
, bgCol = "#000000"
, overlayF = proportional (0.3::Double)
, borderCol = "#ffffff"
, sKeys = AnyKeys [xK_s, xK_d, xK_f, xK_j, xK_k, xK_l]
, cancelKey = xK_q
, borderPx = 1
, maxChordLen = 0
#ifdef XFT
, emFont = "xft:Sans-100"
#else
, emFont = "-misc-fixed-*-*-*-*-200-*-*-*-*-*-*-*"
#endif
}
-- | Create overlay windows of the same size as the window they select
fullSize :: Position -> Rectangle -> Rectangle
fullSize _ = id
-- | Create overlay windows a proportion of the size of the window they select
proportional :: RealFrac f => f -> Position -> Rectangle -> Rectangle
proportional f th r = Rectangle { rect_width = newW
, rect_height = newH
, rect_x = rect_x r + fi (rect_width r - newW) `div` 2
, rect_y = rect_y r + fi (rect_height r - newH) `div` 2 }
where
newH = max (fi th) (round $ f * fi (rect_height r))
newW = newH
-- | Create fixed-size overlay windows
fixedSize :: (Integral a, Integral b) => a -> b -> Position -> Rectangle -> Rectangle
fixedSize w h th r = Rectangle { rect_width = rw
, rect_height = rh
, rect_x = rect_x r + fi (rect_width r - rw) `div` 2
, rect_y = rect_y r + fi (rect_height r - rh) `div` 2 }
where
rw = max (fi w) (fi th)
rh = max (fi h) (fi th)
-- | Create overlay windows the minimum size to contain their key chord
textSize :: Position -> Rectangle -> Rectangle
textSize th r = Rectangle { rect_width = fi th
, rect_height = fi th
, rect_x = rect_x r + (fi (rect_width r) - fi th) `div` 2
, rect_y = rect_y r + (fi (rect_height r) - fi th) `div` 2 }
-- | Create overlay windows the full width of the window they select, the minimum height to contain
-- their chord, and a proportion of the distance from the top of the window they select
bar :: RealFrac f => f -> Position -> Rectangle -> Rectangle
bar f th r = Rectangle { rect_width = rect_width r
, rect_height = fi th
, rect_x = rect_x r
, rect_y = rect_y r + round (f' * (fi (rect_height r) - fi th)) }
where
-- clamp f in [0,1] as other values will appear to lock up xmonad as the overlay will be
-- displayed off-screen
f' = min 0.0 $ max f 1.0
-- | Handles overlay display and window selection. Called after config has been sanitised.
handleSelectWindow :: EasyMotionConfig -> X (Maybe Window)
handleSelectWindow EMConf { sKeys = AnyKeys [] } = return Nothing
handleSelectWindow c = do
f <- initXMF $ emFont c
th <- (\(asc, dsc) -> asc + dsc + 2) <$> textExtentsXMF f (concatMap keysymToString (allKeys . sKeys $ c))
XConf { theRoot = rw, display = dpy } <- ask
XState { mapped = mappedWins, windowset = ws } <- get
-- build overlays depending on key configuration
overlays :: [Overlay] <- case sKeys c of
AnyKeys ks -> buildOverlays ks <$> sortedOverlayWindows
where
visibleWindows :: [Window]
visibleWindows = toList mappedWins
sortedOverlayWindows :: X [OverlayWindow]
sortedOverlayWindows = sortOverlayWindows <$> buildOverlayWindows th visibleWindows
PerScreenKeys m ->
fmap concat
$ sequence
$ M.elems
$ M.mapWithKey (\sid ks -> buildOverlays ks <$> sortedOverlayWindows sid) m
where
screenById :: ScreenId -> Maybe WindowScreen
screenById sid = find ((== sid) . W.screen) (W.screens ws)
visibleWindowsOnScreen :: ScreenId -> [Window]
visibleWindowsOnScreen sid = filter (`elem` toList mappedWins) $ W.integrate' $ screenById sid >>= W.stack . W.workspace
sortedOverlayWindows :: ScreenId -> X [OverlayWindow]
sortedOverlayWindows sid = sortOverlayWindows <$> buildOverlayWindows th (visibleWindowsOnScreen sid)
status <- io $ grabKeyboard dpy rw True grabModeAsync grabModeAsync currentTime
if status == grabSuccess
then do
resultWin <- handleKeyboard dpy (displayOverlay f) (cancelKey c) overlays []
io $ ungrabKeyboard dpy currentTime
mapM_ (deleteWindow . overlay . overlayWin) overlays
io $ sync dpy False
releaseXMF f
case resultWin of
-- focus the selected window
Selected o -> return . Just . win . overlayWin $ o
-- return focus correctly
_ -> whenJust (W.peek ws) (windows . W.focusWindow) $> Nothing
else releaseXMF f $> Nothing
where
allKeys :: ChordKeys -> [KeySym]
allKeys (AnyKeys ks) = ks
allKeys (PerScreenKeys m) = concat $ M.elems m
buildOverlays :: [KeySym] -> [OverlayWindow] -> [Overlay]
buildOverlays = appendChords (maxChordLen c)
buildOverlayWindows :: Position -> [Window] -> X [OverlayWindow]
buildOverlayWindows th = fmap (fromMaybe [] . sequenceA)
. traverse (buildOverlayWin th)
sortOverlayWindows :: [OverlayWindow] -> [OverlayWindow]
sortOverlayWindows = sortOn ((wa_x &&& wa_y) . attrs)
makeRect :: WindowAttributes -> Rectangle
makeRect wa = Rectangle (fi (wa_x wa)) (fi (wa_y wa)) (fi (wa_width wa)) (fi (wa_height wa))
buildOverlayWin :: Position -> Window -> X (Maybe OverlayWindow)
buildOverlayWin th w = safeGetWindowAttributes w >>= \case
Nothing -> pure Nothing
Just wAttrs -> do
let r = overlayF c th $ makeRect wAttrs
o <- createNewWindow r Nothing "" True
return . Just $ OverlayWindow { rect=r, overlay=o, win=w, attrs=wAttrs }
-- | Display an overlay with the provided formatting
displayOverlay :: XMonadFont -> Overlay -> X ()
displayOverlay f Overlay { overlayWin = OverlayWindow { rect = r, overlay = o }, chord = ch } = do
showWindow o
paintAndWrite o f (fi (rect_width r)) (fi (rect_height r)) (fi (borderPx c)) (bgCol c) (borderCol c) (txtCol c) (bgCol c) [AlignCenter] [concatMap keysymToString ch]
-- | Display overlay windows and chords for window selection
selectWindow :: EasyMotionConfig -> X (Maybe Window)
selectWindow conf =
handleSelectWindow conf { sKeys = sanitiseKeys (sKeys conf) }
where
-- make sure the key lists don't contain: backspace, our cancel key, or duplicates
sanitise :: [KeySym] -> [KeySym]
sanitise = nub . filter (`notElem` [xK_BackSpace, cancelKey conf])
sanitiseKeys :: ChordKeys -> ChordKeys
sanitiseKeys cKeys =
case cKeys of
AnyKeys ks -> AnyKeys . sanitise $ ks
PerScreenKeys m -> PerScreenKeys $ M.map sanitise m
-- | Take a list of overlays lacking chords, return a list of overlays with key chords
appendChords :: Int -> [KeySym] -> [OverlayWindow] -> [Overlay]
appendChords _ [] _ = []
appendChords maxUserSelectedLen ks overlayWins =
zipWith Overlay overlayWins chords
where
chords = replicateM chordLen ks
-- the minimum necessary chord length to assign a unique chord to each visible window
minCoverLen = -((-(length overlayWins)) `div` length ks)
-- if the user has specified a max chord length we use this even if it will not cover all
-- windows, as they may prefer to focus windows with fewer keys over the ability to focus any
-- window
chordLen = if maxUserSelectedLen <= 0 then minCoverLen else min minCoverLen maxUserSelectedLen
-- | A three-state result for handling user-initiated selection cancellation, successful selection,
-- or backspace.
data HandleResult = Exit | Selected Overlay | Backspace
-- | Handle key press events for window selection.
handleKeyboard :: Display -> (Overlay -> X()) -> KeySym -> [Overlay] -> [Overlay] -> X HandleResult
handleKeyboard _ _ _ [] _ = return Exit
handleKeyboard dpy drawFn cancel selected deselected = do
redraw
ev <- io $ allocaXEvent $ \e -> do
maskEvent dpy (keyPressMask .|. keyReleaseMask .|. buttonPressMask) e
getEvent e
if | ev_event_type ev == keyPress -> do
s <- io $ keycodeToKeysym dpy (ev_keycode ev) 0
if | s == cancel -> return Exit
| s == xK_BackSpace -> return Backspace
| isNextOverlayKey s -> handleNextOverlayKey s
| otherwise -> handleKeyboard dpy drawFn cancel selected deselected
| ev_event_type ev == buttonPress -> do
-- See XMonad.Prompt Note [Allow ButtonEvents]
io $ allowEvents dpy replayPointer currentTime
handleKeyboard dpy drawFn cancel selected deselected
| otherwise -> handleKeyboard dpy drawFn cancel selected deselected
where
redraw = mapM (mapM_ drawFn) [selected, deselected]
retryBackspace x =
case x of
Backspace -> redraw >> handleKeyboard dpy drawFn cancel selected deselected
_ -> return x
isNextOverlayKey keySym = isJust (find ((== Just keySym) . listToMaybe .chord) selected)
handleNextOverlayKey keySym =
case fg of
[x] -> return $ Selected x
_ -> handleKeyboard dpy drawFn cancel (trim fg) (clear bg) >>= retryBackspace
where
(fg, bg) = partition ((== Just keySym) . listToMaybe . chord) selected
trim = map (\o -> o { chord = drop 1 $ chord o })
clear = map (\o -> o { chord = [] })

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FindEmptyWorkspace
-- Description : Find an empty workspace.
-- Copyright : (c) Miikka Koskinen 2007
-- License : BSD3-style (see LICENSE)
--
@@ -18,15 +19,13 @@ module XMonad.Actions.FindEmptyWorkspace (
viewEmptyWorkspace, tagToEmptyWorkspace, sendToEmptyWorkspace
) where
import Data.List
import Data.Maybe ( isNothing )
import XMonad.Prelude
import XMonad
import XMonad.StackSet
-- $usage
--
-- To use, import this module into your @~\/.xmonad\/xmonad.hs@:
-- To use, import this module into your @xmonad.hs@:
--
-- > import XMonad.Actions.FindEmptyWorkspace
--
@@ -39,7 +38,7 @@ import XMonad.StackSet
-- will tag the current window to an empty workspace and view it.
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Find the first hidden empty workspace in a StackSet. Returns
-- Nothing if all workspaces are in use. Function searches currently

View File

@@ -1,8 +1,9 @@
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FlexibleManipulate
-- Description : Move and resize floating windows without warping the mouse.
-- Copyright : (c) Michael Sloan
-- License : BSD3-style (see LICENSE)
--
@@ -23,11 +24,12 @@ module XMonad.Actions.FlexibleManipulate (
) where
import XMonad
import XMonad.Prelude ((<&>), fi)
import qualified Prelude as P
import Prelude (($), (.), fst, snd, uncurry, const, id, Ord(..), Monad(..), fromIntegral, Double, Integer, map, round, otherwise)
import Prelude (Double, Integer, Ord (..), const, fromIntegral, fst, id, otherwise, round, snd, uncurry, ($))
-- $usage
-- First, add this import to your @~\/.xmonad\/xmonad.hs@:
-- First, add this import to your @xmonad.hs@:
--
-- > import qualified XMonad.Actions.FlexibleManipulate as Flex
--
@@ -78,43 +80,36 @@ position = const 0.5
-- | Given an interpolation function, implement an appropriate window
-- manipulation action.
mouseWindow :: (Double -> Double) -> Window -> X ()
mouseWindow f w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
[wpos, wsize] <- io $ getWindowAttributes d w >>= return . winAttrs
mouseWindow f w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
let wpos = (fi (wa_x wa), fi (wa_y wa))
wsize = (fi (wa_width wa), fi (wa_height wa))
sh <- io $ getWMNormalHints d w
pointer <- io $ queryPointer d w >>= return . pointerPos
pointer <- io $ queryPointer d w <&> pointerPos
let uv = (pointer - wpos) / wsize
fc = mapP f uv
mul = mapP (\x -> 2 P.- 2 P.* P.abs(x P.- 0.5)) fc --Fudge factors: interpolation between 1 when on edge, 2 in middle
atl = ((1, 1) - fc) * mul
abr = fc * mul
mouseDrag (\ex ey -> io $ do
mouseDrag (\ex ey -> do
let offset = (fromIntegral ex, fromIntegral ey) - pointer
npos = wpos + offset * atl
nbr = (wpos + wsize) + offset * abr
ntl = minP (nbr - (32, 32)) npos --minimum size
nwidth = applySizeHintsContents sh $ mapP (round :: Double -> Integer) (nbr - ntl)
moveResizeWindow d w (round $ fst ntl) (round $ snd ntl) `uncurry` nwidth
return ())
io $ moveResizeWindow d w (round $ fst ntl) (round $ snd ntl) `uncurry` nwidth
float w)
(float w)
float w
where
pointerPos (_,_,_,px,py,_,_,_) = (fromIntegral px,fromIntegral py) :: Pnt
winAttrs :: WindowAttributes -> [Pnt]
winAttrs x = pairUp $ map (fromIntegral . ($ x)) [wa_x, wa_y, wa_width, wa_height]
-- I'd rather I didn't have to do this, but I hate writing component 2d math
type Pnt = (Double, Double)
pairUp :: [a] -> [(a,a)]
pairUp [] = []
pairUp [_] = []
pairUp (x:y:xs) = (x, y) : (pairUp xs)
mapP :: (a -> b) -> (a, a) -> (b, b)
mapP f (x, y) = (f x, f y)
zipP :: (a -> b -> c) -> (a,a) -> (b,b) -> (c,c)
@@ -132,4 +127,3 @@ infixl 7 *, /
(*) = zipP (P.*)
(/) :: (P.Fractional a) => (a,a) -> (a,a) -> (a,a)
(/) = zipP (P./)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FlexibleResize
-- Description : Resize floating windows from any corner.
-- Copyright : (c) Lukas Mai
-- License : BSD3-style (see LICENSE)
--
@@ -20,11 +21,11 @@ module XMonad.Actions.FlexibleResize (
) where
import XMonad
import XMonad.Util.XUtils (fi)
import XMonad.Prelude (fi)
import Foreign.C.Types
-- $usage
-- To use, first import this module into your @~\/.xmonad\/xmonad.hs@ file:
-- To use, first import this module into your @xmonad.hs@ file:
--
-- > import qualified XMonad.Actions.FlexibleResize as Flex
--
@@ -49,29 +50,32 @@ mouseResizeEdgeWindow
:: Rational -- ^ The size of the area where only one edge is resized.
-> Window -- ^ The window to resize.
-> X ()
mouseResizeEdgeWindow edge w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
mouseResizeEdgeWindow edge w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
sh <- io $ getWMNormalHints d w
(_, _, _, _, _, ix, iy, _) <- io $ queryPointer d w
let
[pos_x, pos_y, width, height] = map (fi . ($ wa)) [wa_x, wa_y, wa_width, wa_height]
pos_x = fi $ wa_x wa
pos_y = fi $ wa_y wa
width = fi $ wa_width wa
height = fi $ wa_height wa
west = findPos ix width
north = findPos iy height
(cx, fx, gx) = mkSel west width pos_x
(cy, fy, gy) = mkSel north height pos_y
io $ warpPointer d none w 0 0 0 0 cx cy
mouseDrag (\ex ey -> do let (nw,nh) = applySizeHintsContents sh (gx ex, gy ey)
io $ moveResizeWindow d w (fx nw) (fy nh) nw nh)
io $ moveResizeWindow d w (fx nw) (fy nh) nw nh
float w)
(float w)
where
findPos :: CInt -> Position -> Maybe Bool
findPos m s = if p < 0.5 - edge/2
then Just True
else if p < 0.5 + edge/2
then Nothing
else Just False
where p = fi m / fi s
findPos m s
| p < 0.5 - edge/2 = Just True
| p < 0.5 + edge/2 = Nothing
| otherwise = Just False
where
p = fi m / fi s
mkSel :: Maybe Bool -> Position -> Position -> (Position, Dimension -> Position, Position -> Dimension)
mkSel b k p = case b of
Just True -> (0, (fi k + fi p -).fi, (fi k + fi p -).fi)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FloatKeys
-- Description : Move and resize floating windows.
-- Copyright : (c) Karsten Schoelzel <kuser@gmx.de>
-- License : BSD
--
@@ -18,13 +19,18 @@ module XMonad.Actions.FloatKeys (
keysMoveWindowTo,
keysResizeWindow,
keysAbsResizeWindow,
P, G,
directionMoveWindow,
directionResizeWindow,
Direction2D(..),
P, G, ChangeDim
) where
import XMonad
import XMonad.Prelude (fi)
import XMonad.Util.Types
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.FloatKeys
--
@@ -36,17 +42,44 @@ import XMonad
-- > , ((modm .|. shiftMask, xK_s ), withFocused (keysAbsResizeWindow (10,10) (1024,752)))
-- > , ((modm, xK_a ), withFocused (keysMoveWindowTo (512,384) (1%2,1%2)))
--
-- Using "XMonad.Util.EZConfig" syntax, we can easily build keybindings
-- where @M-\<arrow-keys\>@ moves the currently focused window and
-- @M-S-\<arrow-keys\>@ resizes it using 'directionMoveWindow' and
-- 'directionResizeWindow':
--
-- > [ ("M-" <> m <> k, withFocused $ f i)
-- > | (i, k) <- zip [U, D, R, L] ["<Up>", "<Down>", "<Right>", "<Left>"]
-- > , (f, m) <- [(directionMoveWindow 10, ""), (directionResizeWindow 10, "S-")]
-- > ]
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | @directionMoveWindow delta dir win@ moves the window @win@ by
-- @delta@ pixels in direction @dir@.
directionMoveWindow :: Int -> Direction2D -> Window -> X ()
directionMoveWindow delta dir win = case dir of
U -> keysMoveWindow (0, -delta) win
D -> keysMoveWindow (0, delta) win
R -> keysMoveWindow (delta, 0) win
L -> keysMoveWindow (-delta, 0) win
-- | @directionResizeWindow delta dir win@ resizes the window @win@ by
-- @delta@ pixels in direction @dir@.
directionResizeWindow :: Int -> Direction2D -> Window -> X ()
directionResizeWindow delta dir win = case dir of
U -> keysResizeWindow (0, -delta) (0, 0) win
D -> keysResizeWindow (0, delta) (0, 0) win
R -> keysResizeWindow (delta, 0) (0, 0) win
L -> keysResizeWindow (-delta, 0) (0, 0) win
-- | @keysMoveWindow (dx, dy)@ moves the window by @dx@ pixels to the
-- right and @dy@ pixels down.
keysMoveWindow :: D -> Window -> X ()
keysMoveWindow (dx,dy) w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
io $ moveWindow d w (fromIntegral (fromIntegral (wa_x wa) + dx))
(fromIntegral (fromIntegral (wa_y wa) + dy))
keysMoveWindow :: ChangeDim -> Window -> X ()
keysMoveWindow (dx,dy) w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
io $ moveWindow d w (fi (fi (wa_x wa) + dx))
(fi (fi (wa_y wa) + dy))
float w
-- | @keysMoveWindowTo (x, y) (gx, gy)@ moves the window relative
@@ -60,15 +93,15 @@ keysMoveWindow (dx,dy) w = whenX (isClient w) $ withDisplay $ \d -> do
-- > keysMoveWindowTo (512,384) (1%2, 1%2) -- center the window on screen
-- > keysMoveWindowTo (1024,0) (1, 0) -- put window in the top right corner
keysMoveWindowTo :: P -> G -> Window -> X ()
keysMoveWindowTo (x,y) (gx, gy) w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
io $ moveWindow d w (x - round (gx * fromIntegral (wa_width wa)))
(y - round (gy * fromIntegral (wa_height wa)))
keysMoveWindowTo (x,y) (gx, gy) w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
io $ moveWindow d w (x - round (gx * fi (wa_width wa)))
(y - round (gy * fi (wa_height wa)))
float w
type G = (Rational, Rational)
type P = (Position, Position)
type ChangeDim = (Int, Int)
-- | @keysResizeWindow (dx, dy) (gx, gy)@ changes the width by @dx@
-- and the height by @dy@, leaving the window-relative point @(gx,
@@ -80,7 +113,7 @@ type P = (Position, Position)
-- > keysResizeWindow (10, 0) (0, 1%2) -- does the same, unless sizeHints are applied
-- > keysResizeWindow (10, 10) (1%2, 1%2) -- add 5 pixels on each side
-- > keysResizeWindow (-10, -10) (0, 1) -- shrink the window in direction of the bottom-left corner
keysResizeWindow :: D -> G -> Window -> X ()
keysResizeWindow :: ChangeDim -> G -> Window -> X ()
keysResizeWindow = keysMoveResize keysResizeWindow'
-- | @keysAbsResizeWindow (dx, dy) (ax, ay)@ changes the width by @dx@
@@ -90,34 +123,34 @@ keysResizeWindow = keysMoveResize keysResizeWindow'
-- For example:
--
-- > keysAbsResizeWindow (10, 10) (0, 0) -- enlarge the window; if it is not in the top-left corner it will also be moved down and to the right.
keysAbsResizeWindow :: D -> D -> Window -> X ()
keysAbsResizeWindow :: ChangeDim -> D -> Window -> X ()
keysAbsResizeWindow = keysMoveResize keysAbsResizeWindow'
keysAbsResizeWindow' :: SizeHints -> P -> D -> D -> D -> (P,D)
keysAbsResizeWindow' :: SizeHints -> P -> D -> ChangeDim -> D -> (P,D)
keysAbsResizeWindow' sh (x,y) (w,h) (dx,dy) (ax, ay) = ((round nx, round ny), (nw, nh))
where
(nw, nh) = applySizeHintsContents sh (w + dx, h + dy)
-- The width and height of a window are positive and thus
-- converting to 'Dimension' should be safe.
(nw, nh) = applySizeHintsContents sh (fi w + dx, fi h + dy)
nx :: Rational
nx = fromIntegral (ax * w + nw * (fromIntegral x - ax)) / fromIntegral w
nx = fi (ax * w + nw * (fi x - ax)) / fi w
ny :: Rational
ny = fromIntegral (ay * h + nh * (fromIntegral y - ay)) / fromIntegral h
ny = fi (ay * h + nh * (fi y - ay)) / fi h
keysResizeWindow' :: SizeHints -> P -> D -> D -> G -> (P,D)
keysResizeWindow' :: SizeHints -> P -> D -> ChangeDim -> G -> (P,D)
keysResizeWindow' sh (x,y) (w,h) (dx,dy) (gx, gy) = ((nx, ny), (nw, nh))
where
(nw, nh) = applySizeHintsContents sh (w + dx, h + dy)
nx = round $ fromIntegral x + gx * fromIntegral w - gx * fromIntegral nw
ny = round $ fromIntegral y + gy * fromIntegral h - gy * fromIntegral nh
(nw, nh) = applySizeHintsContents sh (fi w + dx, fi h + dy)
nx = round $ fi x + gx * fi w - gx * fi nw
ny = round $ fi y + gy * fi h - gy * fi nh
keysMoveResize :: (SizeHints -> P -> D -> a -> b -> (P,D)) -> a -> b -> Window -> X ()
keysMoveResize f move resize w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
keysMoveResize f move resize w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
sh <- io $ getWMNormalHints d w
let wa_dim = (fromIntegral $ wa_width wa, fromIntegral $ wa_height wa)
wa_pos = (fromIntegral $ wa_x wa, fromIntegral $ wa_y wa)
let wa_dim = (fi $ wa_width wa, fi $ wa_height wa)
wa_pos = (fi $ wa_x wa, fi $ wa_y wa)
(wn_pos, wn_dim) = f sh wa_pos wa_dim move resize
io $ resizeWindow d w `uncurry` wn_dim
io $ moveWindow d w `uncurry` wn_pos
float w

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.FloatSnap
-- Description : Snap to other windows or the edge of the screen while moving or resizing.
-- Copyright : (c) 2009 Anders Engstrom <ankaan@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -21,21 +22,22 @@ module XMonad.Actions.FloatSnap (
snapShrink,
snapMagicMove,
snapMagicResize,
snapMagicMouseResize) where
snapMagicMouseResize,
afterDrag,
ifClick,
ifClick') where
import XMonad
import Control.Applicative((<$>))
import Data.List (sort)
import Data.Maybe (listToMaybe,fromJust,isNothing)
import XMonad.Prelude (fromJust, isNothing, listToMaybe, sort, when)
import qualified XMonad.StackSet as W
import qualified Data.Set as S
import XMonad.Hooks.ManageDocks (calcGap)
import XMonad.Util.Types (Direction2D(..))
import qualified Data.Set as S
import XMonad.Actions.AfterDrag
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.FloatSnap
--
@@ -51,19 +53,26 @@ import qualified Data.Set as S
-- > , ((modm .|. shiftMask, xK_Down), withFocused $ snapGrow D Nothing)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
--
-- And possibly add an appropriate mouse binding, for example:
-- And possibly add appropriate mouse bindings, for example:
--
-- > , ((modm, button1), (\w -> focus w >> mouseMoveWindow w >> snapMagicMove (Just 50) (Just 50) w))
-- > , ((modm .|. shiftMask, button1), (\w -> focus w >> mouseMoveWindow w >> snapMagicResize [L,R,U,D] (Just 50) (Just 50) w))
-- > , ((modm, button3), (\w -> focus w >> mouseResizeWindow w >> snapMagicResize [R,D] (Just 50) (Just 50) w))
-- > , ((modm, button1), (\w -> focus w >> mouseMoveWindow w >> ifClick (snapMagicMove (Just 50) (Just 50) w)))
-- > , ((modm .|. shiftMask, button1), (\w -> focus w >> mouseMoveWindow w >> ifClick (snapMagicResize [L,R,U,D] (Just 50) (Just 50) w)))
-- > , ((modm, button3), (\w -> focus w >> mouseResizeWindow w >> ifClick (snapMagicResize [R,D] (Just 50) (Just 50) w)))
--
-- For detailed instructions on editing your mouse bindings, see
-- "XMonad.Doc.Extending#Editing_mouse_bindings".
--
-- Using these mouse bindings, it will not snap while moving, but allow you to click the window once after it has been moved or resized to snap it into place.
-- Note that the order in which the commands are applied in the mouse bindings are important.
-- Note that the order in which the commands are applied in the mouse bindings are important. Snapping can also be used together with other window resizing
-- functions, such as those from "XMonad.Actions.FlexibleResize"
--
-- An alternative set of mouse bindings that will always snap after the drag is:
--
-- > , ((modm, button1), (\w -> focus w >> mouseMoveWindow w >> afterDrag (snapMagicMove (Just 50) (Just 50) w)))
-- > , ((modm .|. shiftMask, button1), (\w -> focus w >> mouseMoveWindow w >> afterDrag (snapMagicResize [L,R,U,D] (Just 50) (Just 50) w)))
-- > , ((modm, button3), (\w -> focus w >> mouseResizeWindow w >> afterDrag (snapMagicResize [R,D] (Just 50) (Just 50) w)))
--
-- Interesting values for the distance to look for window in the orthogonal axis are Nothing (to snap against every window), Just 0 (to only snap
-- against windows that we should collide with geometrically while moving) and Just 1 (to also snap against windows we brush against).
@@ -83,17 +92,17 @@ snapMagicMouseResize
-> Maybe Int -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.
-> Window -- ^ The window to move and resize.
-> X ()
snapMagicMouseResize middle collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do
wa <- io $ getWindowAttributes d w
snapMagicMouseResize middle collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
(_, _, _, px, py, _, _, _) <- io $ queryPointer d w
let x = (fromIntegral px - wx wa)/(ww wa)
y = (fromIntegral py - wy wa)/(wh wa)
ml = if x <= (0.5 - middle/2) then [L] else []
mr = if x > (0.5 + middle/2) then [R] else []
mu = if y <= (0.5 - middle/2) then [U] else []
md = if y > (0.5 + middle/2) then [D] else []
let x = (fromIntegral px - wx wa)/ww wa
y = (fromIntegral py - wy wa)/wh wa
ml = [L | x <= (0.5 - middle/2)]
mr = [R | x > (0.5 + middle/2)]
mu = [U | y <= (0.5 - middle/2)]
md = [D | y > (0.5 + middle/2)]
mdir = ml++mr++mu++md
dir = if mdir == []
dir = if null mdir
then [L,R,U,D]
else mdir
snapMagicResize dir collidedist snapdist w
@@ -110,19 +119,17 @@ snapMagicResize
-> Maybe Int -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.
-> Window -- ^ The window to move and resize.
-> X ()
snapMagicResize dir collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
snapMagicResize dir collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
(xbegin,xend) <- handleAxis True d wa
(ybegin,yend) <- handleAxis False d wa
let xbegin' = if L `elem` dir then xbegin else (wx wa)
xend' = if R `elem` dir then xend else (wx wa + ww wa)
ybegin' = if U `elem` dir then ybegin else (wy wa)
yend' = if D `elem` dir then yend else (wy wa + wh wa)
let xbegin' = if L `elem` dir then xbegin else wx wa
xend' = if R `elem` dir then xend else wx wa + ww wa
ybegin' = if U `elem` dir then ybegin else wy wa
yend' = if D `elem` dir then yend else wy wa + wh wa
io $ moveWindow d w (fromIntegral $ xbegin') (fromIntegral $ ybegin')
io $ moveWindow d w (fromIntegral xbegin') (fromIntegral ybegin')
io $ resizeWindow d w (fromIntegral $ xend' - xbegin') (fromIntegral $ yend' - ybegin')
float w
where
@@ -142,13 +149,13 @@ snapMagicResize dir collidedist snapdist w = whenX (isClient w) $ withDisplay $
(Nothing,Nothing) -> wpos wa
end = if fs
then wpos wa + wdim wa
else case (if mfl==(Just begin) then Nothing else mfl,mfr) of
else case (if mfl==Just begin then Nothing else mfl,mfr) of
(Just fl,Just fr) -> if wpos wa + wdim wa - fl < fr - wpos wa - wdim wa then fl else fr
(Just fl,Nothing) -> fl
(Nothing,Just fr) -> fr
(Nothing,Nothing) -> wpos wa + wdim wa
begin' = if isNothing snapdist || abs (begin - wpos wa) <= fromJust snapdist then begin else (wpos wa)
end' = if isNothing snapdist || abs (end - wpos wa - wdim wa) <= fromJust snapdist then end else (wpos wa + wdim wa)
begin' = if isNothing snapdist || abs (begin - wpos wa) <= fromJust snapdist then begin else wpos wa
end' = if isNothing snapdist || abs (end - wpos wa - wdim wa) <= fromJust snapdist then end else wpos wa + wdim wa
return (begin',end')
where
(wpos, wdim, _, _) = constructors horiz
@@ -160,10 +167,8 @@ snapMagicMove
-> Maybe Int -- ^ The maximum distance to snap. Use Nothing to not impose any boundary.
-> Window -- ^ The window to move.
-> X ()
snapMagicMove collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
snapMagicMove collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
nx <- handleAxis True d wa
ny <- handleAxis False d wa
@@ -184,8 +189,8 @@ snapMagicMove collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d ->
(Just fl,Nothing) -> fl
(Nothing,Just fr) -> fr
(Nothing,Nothing) -> wpos wa
newpos = if abs (b - wpos wa) <= abs (f - wpos wa - wdim wa) then b else (f - wdim wa)
in if isNothing snapdist || abs (newpos - wpos wa) <= fromJust snapdist then newpos else (wpos wa)
newpos = if abs (b - wpos wa) <= abs (f - wpos wa - wdim wa) then b else f - wdim wa
in if isNothing snapdist || abs (newpos - wpos wa) <= fromJust snapdist then newpos else wpos wa
where
(wpos, wdim, _, _) = constructors horiz
@@ -201,9 +206,8 @@ snapMove U = doSnapMove False True
snapMove D = doSnapMove False False
doSnapMove :: Bool -> Bool -> Maybe Int -> Window -> X ()
doSnapMove horiz rev collidedist w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
doSnapMove horiz rev collidedist w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
((bl,br,_),(fl,fr,_)) <- getSnap horiz collidedist d w
let (mb,mf) = if rev then (bl,fl)
@@ -241,9 +245,8 @@ snapShrink
snapShrink = snapResize False
snapResize :: Bool -> Direction2D -> Maybe Int -> Window -> X ()
snapResize grow dir collidedist w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
snapResize grow dir collidedist w = whenX (isClient w) $ withDisplay $ \d ->
withWindowAttributes d w $ \wa -> do
mr <- case dir of
L -> do ((mg,ms,_),(_,_,_)) <- getSnap True collidedist d w
return $ case (if grow then mg else ms) of
@@ -264,9 +267,8 @@ snapResize grow dir collidedist w = whenX (isClient w) $ withDisplay $ \d -> do
case mr of
Nothing -> return ()
Just (nx,ny,nw,nh) -> if nw>0 && nh>0 then do io $ moveWindow d w (fromIntegral nx) (fromIntegral ny)
io $ resizeWindow d w (fromIntegral nw) (fromIntegral nh)
else return ()
Just (nx,ny,nw,nh) -> when (nw>0 && nh>0) $ do io $ moveWindow d w (fromIntegral nx) (fromIntegral ny)
io $ resizeWindow d w (fromIntegral nw) (fromIntegral nh)
float w
where
wx = fromIntegral.wa_x
@@ -281,8 +283,8 @@ getSnap horiz collidedist d w = do
screen <- W.current <$> gets windowset
let sr = screenRect $ W.screenDetail screen
wl = W.integrate' . W.stack $ W.workspace screen
gr <- fmap ($sr) $ calcGap $ S.fromList [minBound .. maxBound]
wla <- filter (collides wa) `fmap` (io $ mapM (getWindowAttributes d) $ filter (/=w) wl)
gr <- ($ sr) <$> calcGap (S.fromList [minBound .. maxBound])
wla <- filter (collides wa) <$> io (mapM (getWindowAttributes d) $ filter (/=w) wl)
return ( neighbours (back wa sr gr wla) (wpos wa)
, neighbours (front wa sr gr wla) (wpos wa + wdim wa)
@@ -296,8 +298,8 @@ getSnap horiz collidedist d w = do
back wa sr gr wla = dropWhile (< rpos sr) $
takeWhile (< rpos sr + rdim sr) $
sort $ (rpos sr):(rpos gr):(rpos gr + rdim gr):
foldr (\a as -> (wpos a):(wpos a + wdim a + wborder a + wborder wa):as) [] wla
sort $ rpos sr:rpos gr:(rpos gr + rdim gr):
foldr (\a as -> wpos a:(wpos a + wdim a + wborder a + wborder wa):as) [] wla
front wa sr gr wla = dropWhile (<= rpos sr) $
takeWhile (<= rpos sr + rdim sr) $
@@ -311,8 +313,8 @@ getSnap horiz collidedist d w = do
collides wa oa = case collidedist of
Nothing -> True
Just dist -> ( refwpos oa - wborder oa < refwpos wa + refwdim wa + wborder wa + dist
&& refwpos wa - wborder wa - dist < refwpos oa + refwdim oa + wborder oa )
Just dist -> refwpos oa - wborder oa < refwpos wa + refwdim wa + wborder wa + dist
&& refwpos wa - wborder wa - dist < refwpos oa + refwdim oa + wborder oa
constructors :: Bool -> (WindowAttributes -> Int, WindowAttributes -> Int, Rectangle -> Int, Rectangle -> Int)

View File

@@ -1,6 +1,9 @@
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FocusNth
-- Description : Focus the nth window of the current workspace.
-- Copyright : (c) Karsten Schoelzel <kuser@gmx.de>
-- License : BSD
--
@@ -14,13 +17,15 @@
module XMonad.Actions.FocusNth (
-- * Usage
-- $usage
focusNth,focusNth') where
focusNth,focusNth',
swapNth,swapNth') where
import XMonad.StackSet
import XMonad
import XMonad.Prelude
import XMonad.StackSet
-- $usage
-- Add the import to your @~\/.xmonad\/xmonad.hs@:
-- Add the import to your @xmonad.hs@:
--
-- > import XMonad.Actions.FocusNth
--
@@ -31,20 +36,22 @@ import XMonad
-- > | (i, k) <- zip [0 .. 8] [xK_1 ..]]
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Give focus to the nth window of the current workspace.
focusNth :: Int -> X ()
focusNth = windows . modify' . focusNth'
focusNth' :: Int -> Stack a -> Stack a
focusNth' n s@(Stack _ ls rs) | (n < 0) || (n > length(ls) + length(rs)) = s
| otherwise = listToStack n (integrate s)
listToStack :: Int -> [a] -> Stack a
listToStack n l = Stack t ls rs
where
(t:rs) = drop n l
ls = reverse (take n l)
focusNth' n s | n >= 0, (ls, t:rs) <- splitAt n (integrate s) = Stack t (reverse ls) rs
| otherwise = 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, notEmpty -> nc :| nr) = splitAt (length l - n - 1) l in Stack nc (nl ++ c : nr) r
| otherwise = let (nl, notEmpty -> nc :| nr) = splitAt (n - length l - 1) r in Stack nc l (nl ++ c : nr)

View File

@@ -1,7 +1,8 @@
{-# LANGUAGE ScopedTypeVariables, GeneralizedNewtypeDeriving, TypeSynonymInstances, FlexibleInstances, OverlappingInstances #-}
{-# LANGUAGE ScopedTypeVariables, GeneralizedNewtypeDeriving, FlexibleInstances, TupleSections #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.GridSelect
-- Description : Display items in a 2D grid and select from it with the keyboard or the mouse.
-- Copyright : Clemens Fruhwirth <clemens@endorphin.org>
-- License : BSD-style (see LICENSE)
--
@@ -27,7 +28,7 @@ module XMonad.Actions.GridSelect (
-- * Configuration
GSConfig(..),
defaultGSConfig,
def,
TwoDPosition,
buildDefaultGSConfig,
@@ -38,6 +39,7 @@ module XMonad.Actions.GridSelect (
bringSelected,
goToSelected,
gridselectWorkspace,
gridselectWorkspace',
spawnSelected,
runSelectedAction,
@@ -46,6 +48,7 @@ module XMonad.Actions.GridSelect (
fromClassName,
stringColorizer,
colorRangeFromClassName,
stringToRatio,
-- * Navigation Mode assembly
TwoD,
@@ -65,22 +68,26 @@ module XMonad.Actions.GridSelect (
cancel,
transformSearchString,
-- * Rearrangers
-- $rearrangers
Rearranger,
noRearranger,
searchStringRearrangerGenerator,
-- * Screenshots
-- $screenshots
-- * Types
TwoDState,
) where
import Data.Maybe
import Control.Arrow ((***))
import Data.Bits
import Data.Char
import Data.Ord (comparing)
import Control.Applicative
import Control.Monad.State
import Control.Arrow
import Data.List as L
import qualified Data.Map as M
import XMonad hiding (liftX)
import XMonad.Prelude
import XMonad.Util.Font
import XMonad.Prompt (mkUnmanagedWindow)
import XMonad.StackSet as W
@@ -88,24 +95,25 @@ import XMonad.Layout.Decoration
import XMonad.Util.NamedWindows
import XMonad.Actions.WindowBringer (bringWindow)
import Text.Printf
import System.Random (mkStdGen, genRange, next)
import System.Random (mkStdGen, randomR)
import Data.Word (Word8)
import qualified Data.List.NonEmpty as NE
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.GridSelect
--
-- Then add a keybinding, e.g.
--
-- > , ((modm, xK_g), goToSelected defaultGSConfig)
-- > , ((modm, xK_g), goToSelected def)
--
-- This module also supports displaying arbitrary information in a grid and letting
-- the user select from it. E.g. to spawn an application from a given list, you
-- can use the following:
--
-- > , ((modm, xK_s), spawnSelected defaultGSConfig ["xterm","gmplayer","gvim"])
-- > , ((modm, xK_s), spawnSelected def ["xterm","gmplayer","gvim"])
-- $commonGSConfig
--
@@ -115,9 +123,9 @@ import Data.Word (Word8)
-- > {-# LANGUAGE NoMonomorphismRestriction #-}
-- > import XMonad
-- > ...
-- > gsconfig1 = defaultGSConfig { gs_cellheight = 30, gs_cellwidth = 100 }
-- > gsconfig1 = def { gs_cellheight = 30, gs_cellwidth = 100 }
--
-- An example where 'buildDefaultGSConfig' is used instead of 'defaultGSConfig'
-- An example where 'buildDefaultGSConfig' is used instead of 'def'
-- in order to specify a custom colorizer is @gsconfig2@ (found in
-- "XMonad.Actions.GridSelect#Colorizers"):
--
@@ -135,8 +143,8 @@ import Data.Word (Word8)
--
-- Then you can bind to:
--
-- > ,((modm, xK_g), goToSelected $ gsconfig2 myWinColorizer)
-- > ,((modm, xK_p), spawnSelected $ spawnSelected defaultColorizer)
-- > ,((modm, xK_g), goToSelected $ gsconfig2 myWinColorizer)
-- > ,((modm, xK_p), spawnSelected (gsconfig2 defaultColorizer) ["xterm","gvim"])
-- $keybindings
--
@@ -167,7 +175,7 @@ import Data.Word (Word8)
--
-- You can then define @gsconfig3@ which may be used in exactly the same manner as @gsconfig1@:
--
-- > gsconfig3 = defaultGSConfig
-- > gsconfig3 = def
-- > { gs_cellheight = 30
-- > , gs_cellwidth = 100
-- > , gs_navigate = myNavigation
@@ -183,6 +191,11 @@ import Data.Word (Word8)
--
-- <<http://haskell.org/wikiupload/3/35/Xmonad-gridselect-window-aavogt.png>>
-- | The 'Default' instance gives a basic configuration for 'gridselect', with
-- the colorizer chosen based on the type.
--
-- If you want to replace the 'gs_colorizer' field, use 'buildDefaultGSConfig'
-- instead of 'def' to avoid ambiguous type variables.
data GSConfig a = GSConfig {
gs_cellheight :: Integer,
gs_cellwidth :: Integer,
@@ -190,8 +203,10 @@ data GSConfig a = GSConfig {
gs_colorizer :: a -> Bool -> X (String, String),
gs_font :: String,
gs_navigate :: TwoD a (Maybe a),
gs_rearranger :: Rearranger a,
gs_originFractX :: Double,
gs_originFractY :: Double
gs_originFractY :: Double,
gs_bordercolor :: String
}
-- | That is 'fromClassName' if you are selecting a 'Window', or
@@ -207,17 +222,13 @@ instance HasColorizer Window where
instance HasColorizer String where
defaultColorizer = stringColorizer
instance HasColorizer a where
instance {-# OVERLAPPABLE #-} HasColorizer a where
defaultColorizer _ isFg =
let getColor = if isFg then focusedBorderColor else normalBorderColor
in asks $ flip (,) "black" . getColor . config
in asks $ (, "black") . getColor . config
-- | A basic configuration for 'gridselect', with the colorizer chosen based on the type.
--
-- If you want to replace the 'gs_colorizer' field, use 'buildDefaultGSConfig'
-- instead, to avoid ambiguous type variables.
defaultGSConfig :: HasColorizer a => GSConfig a
defaultGSConfig = buildDefaultGSConfig defaultColorizer
instance HasColorizer a => Default (GSConfig a) where
def = buildDefaultGSConfig defaultColorizer
type TwoDPosition = (Integer, Integer)
@@ -232,19 +243,24 @@ data TwoDState a = TwoDState { td_curpos :: TwoDPosition
, td_paneY :: Integer
, td_drawingWin :: Window
, td_searchString :: String
, td_elementmap :: TwoDElementMap a
}
td_elementmap :: TwoDState a -> [(TwoDPosition,(String,a))]
td_elementmap s = zipWith (,) positions sortedElements
generateElementmap :: TwoDState a -> X (TwoDElementMap a)
generateElementmap s = do
rearrangedElements <- rearranger searchString sortedElements
return $ zip positions rearrangedElements
where
TwoDState {td_availSlots = positions,
td_gsconfig = gsconfig,
td_searchString = searchString} = s
GSConfig {gs_rearranger = rearranger} = gsconfig
-- Filter out any elements that don't contain the searchString (case insensitive)
filteredElements = L.filter ((searchString `isInfixOfI`) . fst) (td_elements s)
-- Sorts the elementmap
sortedElements = orderElementmap searchString filteredElements
-- Case Insensitive version of isInfixOf
needle `isInfixOfI` haystack = (upper needle) `isInfixOf` (upper haystack)
needle `isInfixOfI` haystack = upper needle `isInfixOf` upper haystack
upper = map toUpper
@@ -270,11 +286,7 @@ orderElementmap searchString elements = if not $ null searchString then sortedEl
newtype TwoD a b = TwoD { unTwoD :: StateT (TwoDState a) X b }
deriving (Monad,Functor,MonadState (TwoDState a))
instance Applicative (TwoD a) where
(<*>) = ap
pure = return
deriving (Functor, Applicative, Monad, MonadState (TwoDState a))
liftX :: X a1 -> TwoD a a1
liftX = TwoD . lift
@@ -288,30 +300,30 @@ diamondLayer n =
-- tr = top right
-- r = ur ++ 90 degree clock-wise rotation of ur
let tr = [ (x,n-x) | x <- [0..n-1] ]
r = tr ++ (map (\(x,y) -> (y,-x)) tr)
in r ++ (map (negate *** negate) r)
r = tr ++ map (\(x,y) -> (y,-x)) tr
in r ++ map (negate *** negate) r
diamond :: (Enum a, Num a, Eq a) => [(a, a)]
diamond = concatMap diamondLayer [0..]
diamond :: (Enum a, Num a, Eq a) => Stream (a, a)
diamond = fromList $ concatMap diamondLayer [0..]
diamondRestrict :: Integer -> Integer -> Integer -> Integer -> [(Integer, Integer)]
diamondRestrict x y originX originY =
L.filter (\(x',y') -> abs x' <= x && abs y' <= y) .
map (\(x', y') -> (x' + fromInteger originX, y' + fromInteger originY)) .
take 1000 $ diamond
takeS 1000 $ diamond
findInElementMap :: (Eq a) => a -> [(a, b)] -> Maybe (a, b)
findInElementMap pos = find ((== pos) . fst)
drawWinBox :: Window -> XMonadFont -> (String, String) -> Integer -> Integer -> String -> Integer -> Integer -> Integer -> X ()
drawWinBox win font (fg,bg) ch cw text x y cp =
drawWinBox :: Window -> XMonadFont -> (String, String) -> String -> Integer -> Integer -> String -> Integer -> Integer -> Integer -> X ()
drawWinBox win font (fg,bg) bc ch cw text x y cp =
withDisplay $ \dpy -> do
gc <- liftIO $ createGC dpy win
bordergc <- liftIO $ createGC dpy win
liftIO $ do
Just fgcolor <- initColor dpy fg
Just bgcolor <- initColor dpy bg
Just bordercolor <- initColor dpy borderColor
Just bordercolor <- initColor dpy bc
setForeground dpy gc fgcolor
setBackground dpy gc bgcolor
setForeground dpy bordergc bordercolor
@@ -319,9 +331,12 @@ drawWinBox win font (fg,bg) ch cw text x y cp =
drawRectangle dpy win bordergc (fromInteger x) (fromInteger y) (fromInteger cw) (fromInteger ch)
stext <- shrinkWhile (shrinkIt shrinkText)
(\n -> do size <- liftIO $ textWidthXMF dpy font n
return $ size > (fromInteger (cw-(2*cp))))
return $ size > fromInteger (cw-(2*cp)))
text
printStringXMF dpy win font gc bg fg (fromInteger (x+cp)) (fromInteger (y+(div ch 2))) stext
-- calculate the offset to vertically centre the text based on the ascender and descender
(asc,desc) <- liftIO $ textExtentsXMF font stext
let offset = ((ch - fromIntegral (asc + desc)) `div` 2) + fromIntegral asc
printStringXMF dpy win font gc bg fg (fromInteger (x+cp)) (fromInteger (y+offset)) stext
liftIO $ freeGC dpy gc
liftIO $ freeGC dpy bordergc
@@ -331,11 +346,11 @@ updateAllElements =
s <- get
updateElements (td_elementmap s)
grayoutAllElements :: TwoD a ()
grayoutAllElements =
grayoutElements :: Int -> TwoD a ()
grayoutElements skip =
do
s <- get
updateElementsWithColorizer grayOnly (td_elementmap s)
updateElementsWithColorizer grayOnly $ drop skip (td_elementmap s)
where grayOnly _ _ = return ("#808080", "#808080")
updateElements :: TwoDElementMap a -> TwoD a ()
@@ -359,6 +374,7 @@ updateElementsWithColorizer colorizer elementmap = do
colors <- colorizer element (pos == curpos)
drawWinBox win font
colors
(gs_bordercolor gsconfig)
cellheight
cellwidth
text
@@ -368,10 +384,10 @@ updateElementsWithColorizer colorizer elementmap = do
mapM_ updateElement elementmap
stdHandle :: Event -> TwoD a (Maybe a) -> TwoD a (Maybe a)
stdHandle (ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y }) contEventloop
stdHandle ButtonEvent{ ev_event_type = t, ev_x = x, ev_y = y } contEventloop
| t == buttonRelease = do
s @ TwoDState { td_paneX = px, td_paneY = py,
td_gsconfig = (GSConfig ch cw _ _ _ _ _ _) } <- get
s@TwoDState { td_paneX = px, td_paneY = py,
td_gsconfig = (GSConfig ch cw _ _ _ _ _ _ _ _) } <- get
let gridX = (fi x - (px - cw) `div` 2) `div` cw
gridY = (fi y - (py - ch) `div` 2) `div` ch
case lookup (gridX,gridY) (td_elementmap s) of
@@ -379,7 +395,7 @@ stdHandle (ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y }) contEventloop
Nothing -> contEventloop
| otherwise = contEventloop
stdHandle (ExposeEvent { }) contEventloop = updateAllElements >> contEventloop
stdHandle ExposeEvent{} contEventloop = updateAllElements >> contEventloop
stdHandle _ contEventloop = contEventloop
@@ -392,10 +408,11 @@ makeXEventhandler keyhandler = fix $ \me -> join $ liftX $ withDisplay $ \d -> l
ev <- getEvent e
if ev_event_type ev == keyPress
then do
(ks,s) <- lookupString $ asKeyEvent e
(_, s) <- lookupString $ asKeyEvent e
ks <- keycodeToKeysym d (ev_keycode ev) 0
return $ do
mask <- liftX $ cleanMask (ev_state ev)
keyhandler (fromMaybe xK_VoidSymbol ks, s, mask)
mask <- liftX $ cleanKeyMask <*> pure (ev_state ev)
keyhandler (ks, s, mask)
else
return $ stdHandle ev me
@@ -411,7 +428,7 @@ shadowWithKeymap keymap dflt keyEvent@(ks,_,m') = fromMaybe (dflt keyEvent) (M.l
select :: TwoD a (Maybe a)
select = do
s <- get
return $ fmap (snd . snd) $ findInElementMap (td_curpos s) (td_elementmap s)
return $ snd . snd <$> findInElementMap (td_curpos s) (td_elementmap s)
-- | Closes gridselect returning no element.
cancel :: TwoD a (Maybe a)
@@ -426,7 +443,7 @@ setPos newPos = do
oldPos = td_curpos s
when (isJust newSelectedEl && newPos /= oldPos) $ do
put s { td_curpos = newPos }
updateElements (catMaybes [(findInElementMap oldPos elmap), newSelectedEl])
updateElements (catMaybes [findInElementMap oldPos elmap, newSelectedEl])
-- | Moves the cursor by the offsets specified
move :: (Integer, Integer) -> TwoD a ()
@@ -467,11 +484,17 @@ transformSearchString f = do
let oldSearchString = td_searchString s
newSearchString = f oldSearchString
when (newSearchString /= oldSearchString) $ do
-- FIXME: grayoutAllElements + updateAllElements paint some fields twice causing flickering
-- we would need a much smarter update strategy to fix that
when (length newSearchString > length oldSearchString) grayoutAllElements
-- FIXME curpos might end up outside new bounds
put s { td_searchString = newSearchString }
let s' = s { td_searchString = newSearchString }
m <- liftX $ generateElementmap s'
let s'' = s' { td_elementmap = m }
oldLen = length $ td_elementmap s
newLen = length $ td_elementmap s''
-- All the elements in the previous element map should be
-- grayed out, except for those which will be covered by
-- elements in the new element map.
when (newLen < oldLen) $ grayoutElements newLen
put s''
updateAllElements
-- | By default gridselect used the defaultNavigation action, which
@@ -520,7 +543,7 @@ navNSearch = makeXEventhandler $ shadowWithKeymap navNSearchKeyMap navNSearchDef
,((0,xK_Up) , move (0,-1) >> navNSearch)
,((0,xK_Tab) , moveNext >> navNSearch)
,((shiftMask,xK_Tab), movePrev >> navNSearch)
,((0,xK_BackSpace), transformSearchString (\s -> if (s == "") then "" else init s) >> navNSearch)
,((0,xK_BackSpace), transformSearchString (\s -> if s == "" then "" else init s) >> navNSearch)
]
-- The navigation handler ignores unknown key symbols, therefore we const
navNSearchDefaultHandler (_,s,_) = do
@@ -534,7 +557,7 @@ substringSearch returnNavigation = fix $ \me ->
let searchKeyMap = M.fromList [
((0,xK_Escape) , transformSearchString (const "") >> returnNavigation)
,((0,xK_Return) , returnNavigation)
,((0,xK_BackSpace), transformSearchString (\s -> if (s == "") then "" else init s) >> me)
,((0,xK_BackSpace), transformSearchString (\s -> if s == "" then "" else init s) >> me)
]
searchDefaultHandler (_,s,_) = do
transformSearchString (++ s)
@@ -546,8 +569,8 @@ substringSearch returnNavigation = fix $ \me ->
-- Conversion scheme as in http://en.wikipedia.org/wiki/HSV_color_space
hsv2rgb :: Fractional a => (Integer,a,a) -> (a,a,a)
hsv2rgb (h,s,v) =
let hi = (div h 60) `mod` 6 :: Integer
f = (((fromInteger h)/60) - (fromInteger hi)) :: Fractional a => a
let hi = div h 60 `mod` 6 :: Integer
f = ((fromInteger h/60) - fromInteger hi) :: Fractional a => a
q = v * (1-f)
p = v * (1-s)
t = v * (1-(1-f)*s)
@@ -564,19 +587,19 @@ hsv2rgb (h,s,v) =
stringColorizer :: String -> Bool -> X (String, String)
stringColorizer s active =
let seed x = toInteger (sum $ map ((*x).fromEnum) s) :: Integer
(r,g,b) = hsv2rgb ((seed 83) `mod` 360,
(fromInteger ((seed 191) `mod` 1000))/2500+0.4,
(fromInteger ((seed 121) `mod` 1000))/2500+0.4)
(r,g,b) = hsv2rgb (seed 83 `mod` 360,
fromInteger (seed 191 `mod` 1000)/2500+0.4,
fromInteger (seed 121 `mod` 1000)/2500+0.4)
in if active
then return ("#faff69", "black")
else return ("#" ++ concat (map (twodigitHex.(round :: Double -> Word8).(*256)) [r, g, b] ), "white")
else return ("#" ++ concatMap (twodigitHex.(round :: Double -> Word8).(*256)) [r, g, b], "white")
-- | Colorize a window depending on it's className.
fromClassName :: Window -> Bool -> X (String, String)
fromClassName w active = runQuery className w >>= flip defaultColorizer active
twodigitHex :: Word8 -> String
twodigitHex a = printf "%02x" a
twodigitHex = printf "%02x"
-- | A colorizer that picks a color inside a range,
-- and depending on the window's class.
@@ -605,15 +628,12 @@ mix (r1, g1, b1) (r2, g2, b2) r = (mix' r1 r2, mix' g1 g2, mix' b1 b2)
-- | Generates a Double from a string, trying to
-- achieve a random distribution.
-- We create a random seed from the sum of all characters
-- We create a random seed from the hash of all characters
-- in the string, and use it to generate a ratio between 0 and 1
stringToRatio :: String -> Double
stringToRatio "" = 0
stringToRatio s = let gen = mkStdGen $ sum $ map fromEnum s
range = (\(a, b) -> b - a) $ genRange gen
randomInt = foldr1 combine $ replicate 20 next
combine f1 f2 g = let (_, g') = f1 g in f2 g'
in fi (fst $ randomInt gen) / fi range
stringToRatio s = let gen = mkStdGen $ foldl' (\t c -> t * 31 + fromEnum c) 0 s
in fst $ randomR (0, 1) gen
-- | Brings up a 2D grid of elements in the center of the screen, and one can
-- select an element with cursors keys. The selected element is returned.
@@ -622,38 +642,42 @@ gridselect _ [] = return Nothing
gridselect gsconfig elements =
withDisplay $ \dpy -> do
rootw <- asks theRoot
s <- gets $ screenRect . W.screenDetail . W.current . windowset
scr <- gets $ screenRect . W.screenDetail . W.current . windowset
win <- liftIO $ mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw
(rect_x s) (rect_y s) (rect_width s) (rect_height s)
(rect_x scr) (rect_y scr) (rect_width scr) (rect_height scr)
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 s;
screenHeight = toInteger $ rect_height s;
selectedElement <- if (status == grabSuccess) then do
let screenWidth = toInteger $ rect_width scr
screenHeight = toInteger $ rect_height scr
selectedElement <- if status == grabSuccess then do
let restriction ss cs = (fromInteger ss/fromInteger (cs gsconfig)-1)/2 :: Double
restrictX = floor $ restriction screenWidth gs_cellwidth
restrictY = floor $ restriction screenHeight gs_cellheight
originPosX = floor $ ((gs_originFractX gsconfig) - (1/2)) * 2 * fromIntegral restrictX
originPosY = floor $ ((gs_originFractY gsconfig) - (1/2)) * 2 * fromIntegral restrictY
originPosX = floor $ (gs_originFractX gsconfig - (1/2)) * 2 * fromIntegral restrictX
originPosY = floor $ (gs_originFractY gsconfig - (1/2)) * 2 * fromIntegral restrictY
coords = diamondRestrict restrictX restrictY originPosX originPosY
evalTwoD (updateAllElements >> (gs_navigate gsconfig)) TwoDState { td_curpos = (head coords),
td_availSlots = coords,
td_elements = elements,
td_gsconfig = gsconfig,
td_font = font,
td_paneX = screenWidth,
td_paneY = screenHeight,
td_drawingWin = win,
td_searchString = "" }
s = TwoDState { td_curpos = NE.head (notEmpty coords),
td_availSlots = coords,
td_elements = elements,
td_gsconfig = gsconfig,
td_font = font,
td_paneX = screenWidth,
td_paneY = screenHeight,
td_drawingWin = win,
td_searchString = "",
td_elementmap = [] }
m <- generateElementmap s
evalTwoD (updateAllElements >> gs_navigate gsconfig)
(s { td_elementmap = m })
else
return Nothing
liftIO $ do
unmapWindow dpy win
destroyWindow dpy win
ungrabPointer dpy currentTime
sync dpy False
releaseXMF font
return selectedElement
@@ -668,27 +692,21 @@ gridselectWindow gsconf = windowMap >>= gridselect gsconf
withSelectedWindow :: (Window -> X ()) -> GSConfig Window -> X ()
withSelectedWindow callback conf = do
mbWindow <- gridselectWindow conf
case mbWindow of
Just w -> callback w
Nothing -> return ()
for_ mbWindow callback
windowMap :: X [(String,Window)]
windowMap = do
ws <- gets windowset
wins <- mapM keyValuePair (W.allWindows ws)
return wins
where keyValuePair w = flip (,) w `fmap` decorateName' w
mapM keyValuePair (W.allWindows ws)
where keyValuePair w = (, w) <$> decorateName' w
decorateName' :: Window -> X String
decorateName' w = do
fmap show $ getName w
show <$> getName w
-- | Builds a default gs config from a colorizer function.
buildDefaultGSConfig :: (a -> Bool -> X (String,String)) -> GSConfig a
buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultNavigation (1/2) (1/2)
borderColor :: String
borderColor = "white"
buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultNavigation noRearranger (1/2) (1/2) "white"
-- | Brings selected window to the current workspace.
bringSelected :: GSConfig Window -> X ()
@@ -721,6 +739,44 @@ runSelectedAction conf actions = do
-- > gridselectWorkspace (\ws -> W.greedyView ws . W.shift ws)
gridselectWorkspace :: GSConfig WorkspaceId ->
(WorkspaceId -> WindowSet -> WindowSet) -> X ()
gridselectWorkspace conf viewFunc = withWindowSet $ \ws -> do
gridselectWorkspace conf viewFunc = gridselectWorkspace' conf (windows . viewFunc)
-- | Select a workspace and run an arbitrary action on it.
gridselectWorkspace' :: GSConfig WorkspaceId -> (WorkspaceId -> X ()) -> X ()
gridselectWorkspace' conf func = withWindowSet $ \ws -> do
let wss = map W.tag $ W.hidden ws ++ map W.workspace (W.current ws : W.visible ws)
gridselect conf (zip wss wss) >>= flip whenJust (windows . viewFunc)
gridselect conf (zip wss wss) >>= flip whenJust func
-- $rearrangers
--
-- Rearrangers allow for arbitrary post-filter rearranging of the grid
-- elements.
--
-- For example, to be able to switch to a new dynamic workspace by typing
-- in its name, you can use the following keybinding action:
--
-- > import XMonad.Actions.DynamicWorkspaces (addWorkspace)
-- >
-- > gridselectWorkspace' def
-- > { gs_navigate = navNSearch
-- > , gs_rearranger = searchStringRearrangerGenerator id
-- > }
-- > addWorkspace
-- | A function taking the search string and a list of elements, and
-- returning a potentially rearranged list of elements.
type Rearranger a = String -> [(String, a)] -> X [(String, a)]
-- | A rearranger that leaves the elements unmodified.
noRearranger :: Rearranger a
noRearranger _ = return
-- | A generator for rearrangers that append a single element based on the
-- search string, if doing so would not be redundant (empty string or value
-- already present).
searchStringRearrangerGenerator :: (String -> a) -> Rearranger a
searchStringRearrangerGenerator f =
let r "" xs = return xs
r s xs | s `elem` map fst xs = return xs
| otherwise = return $ xs ++ [(s, f s)]
in r

View File

@@ -1,8 +1,8 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# language DeriveGeneric, DeriveAnyClass #-}
----------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.GroupNavigation
-- Description : Cycle through groups of windows across workspaces.
-- Copyright : (c) nzeh@cs.dal.ca
-- License : BSD3-style (see LICENSE)
--
@@ -16,7 +16,7 @@
-- query.
--
-- Also provides a method for jumping back to the most recently used
-- window in any given group.
-- window in any given group, and predefined groups.
--
----------------------------------------------------------------------
@@ -27,24 +27,33 @@ module XMonad.Actions.GroupNavigation ( -- * Usage
, nextMatchOrDo
, nextMatchWithThis
, historyHook
-- * Utilities
-- $utilities
, isOnAnyVisibleWS
) where
import Control.Monad.Reader
import Data.Foldable as Fold
import Data.Map as Map
import Data.Sequence as Seq
import Data.Set as Set
import Control.Monad.Reader (ask, asks)
import Control.Monad.State (gets)
import Control.DeepSeq
import Data.Map ((!))
import qualified Data.Map as Map
import Data.Sequence (Seq, ViewL (EmptyL, (:<)), viewl, (<|), (><), (|>))
import qualified Data.Sequence as Seq
import qualified Data.Set as Set
import Graphics.X11.Types
import Prelude hiding (concatMap, drop, elem, filter, null, reverse)
import GHC.Generics
import Prelude hiding (drop, elem, filter, null, reverse)
import XMonad.Core
import XMonad.ManageHook
import XMonad.Operations (windows, withFocused)
import XMonad.Prelude (elem, foldl', (>=>))
import qualified XMonad.StackSet as SS
import qualified XMonad.Util.ExtensibleState as XS
{- $usage
Import the module into your @~\/.xmonad\/xmonad.hs@:
Import the module into your @xmonad.hs@:
> import XMonad.Actions.GroupNavigation
@@ -73,7 +82,7 @@ Finally, you can define keybindings to jump to the most recent window
matching a certain Boolean query. To do this, you need to add
'historyHook' to your logHook:
> main = xmonad $ defaultConfig { logHook = historyHook }
> main = xmonad $ def { logHook = historyHook }
Then the following keybindings, for example, allow you to return to
the most recent xterm or emacs window or to simply to the most recent
@@ -120,14 +129,14 @@ focusNextMatchOrDo qry act = findM (runQuery qry)
>=> maybe act (windows . SS.focusWindow)
-- Returns the list of windows ordered by workspace as specified in
-- ~/.xmonad/xmonad.hs
-- @xmonad.hs@.
orderedWindowList :: Direction -> X (Seq Window)
orderedWindowList History = liftM (\(HistoryDB w ws) -> maybe ws (ws |>) w) XS.get
orderedWindowList History = fmap (\(HistoryDB w ws) -> maybe ws (ws |>) w) XS.get
orderedWindowList dir = withWindowSet $ \ss -> do
wsids <- asks (Seq.fromList . workspaces . config)
let wspcs = orderedWorkspaceList ss wsids
wins = dirfun dir
$ Fold.foldl' (><) Seq.empty
$ foldl' (><) Seq.empty
$ fmap (Seq.fromList . SS.integrate' . SS.stack) wspcs
cur = SS.peek ss
return $ maybe wins (rotfun wins) cur
@@ -136,13 +145,13 @@ orderedWindowList dir = withWindowSet $ \ss -> do
dirfun _ = id
rotfun wins x = rotate $ rotateTo (== x) wins
-- Returns the ordered workspace list as specified in ~/.xmonad/xmonad.hs
-- Returns the ordered workspace list as specified in @xmonad.hs@.
orderedWorkspaceList :: WindowSet -> Seq String -> Seq WindowSpace
orderedWorkspaceList ss wsids = rotateTo isCurWS wspcs'
where
wspcs = SS.workspaces ss
wspcsMap = Fold.foldl' (\m ws -> Map.insert (SS.tag ws) ws m) Map.empty wspcs
wspcs' = fmap (\wsid -> wspcsMap ! wsid) wsids
wspcsMap = foldl' (\m ws -> Map.insert (SS.tag ws) ws m) Map.empty wspcs
wspcs' = fmap (wspcsMap !) wsids
isCurWS ws = SS.tag ws == SS.tag (SS.workspace $ SS.current ss)
--- History navigation, requires a layout modifier -------------------
@@ -150,7 +159,7 @@ orderedWorkspaceList ss wsids = rotateTo isCurWS wspcs'
-- The state extension that holds the history information
data HistoryDB = HistoryDB (Maybe Window) -- currently focused window
(Seq Window) -- previously focused windows
deriving (Read, Show, Typeable)
deriving (Read, Show, Generic, NFData)
instance ExtensionClass HistoryDB where
@@ -160,33 +169,18 @@ instance ExtensionClass HistoryDB where
-- | Action that needs to be executed as a logHook to maintain the
-- focus history of all windows as the WindowSet changes.
historyHook :: X ()
historyHook = XS.get >>= updateHistory >>= XS.put
historyHook = (XS.put $!) . force =<< updateHistory =<< XS.get
-- Updates the history in response to a WindowSet change
updateHistory :: HistoryDB -> X HistoryDB
updateHistory (HistoryDB oldcur oldhist) = withWindowSet $ \ss -> do
updateHistory (HistoryDB oldcur oldhist) = withWindowSet $ \ss ->
let newcur = SS.peek ss
wins = Set.fromList $ SS.allWindows ss
newhist = flt (flip Set.member wins) (ins oldcur oldhist)
return $ HistoryDB newcur (del newcur newhist)
newhist = Seq.filter (`Set.member` wins) (ins oldcur oldhist)
in pure $ HistoryDB newcur (del newcur newhist)
where
ins x xs = maybe xs (<| xs) x
del x xs = maybe xs (\x' -> flt (/= x') xs) x
--- Two replacements for Seq.filter and Seq.breakl available only in
--- containers-0.3.0.0, which only ships with ghc 6.12. Once we
--- decide to no longer support ghc < 6.12, these should be replaced
--- with Seq.filter and Seq.breakl.
flt :: (a -> Bool) -> Seq a -> Seq a
flt p = Fold.foldl (\xs x -> if p x then xs |> x else xs) Seq.empty
brkl :: (a -> Bool) -> Seq a -> (Seq a, Seq a)
brkl p xs = flip Seq.splitAt xs
$ snd
$ Fold.foldr (\x (i, j) -> if p x then (i-1, i-1) else (i-1, j)) (l, l) xs
where
l = Seq.length xs
del x xs = maybe xs (\x' -> Seq.filter (/= x') xs) x
--- Some sequence helpers --------------------------------------------
@@ -200,7 +194,7 @@ rotate xs = rotate' (viewl xs)
-- Rotates the sequence until an element matching the given condition
-- is at the beginning of the sequence.
rotateTo :: (a -> Bool) -> Seq a -> Seq a
rotateTo cond xs = let (lxs, rxs) = brkl cond xs in rxs >< lxs
rotateTo cond xs = let (lxs, rxs) = Seq.breakl cond xs in rxs >< lxs
--- A monadic find ---------------------------------------------------
@@ -216,3 +210,21 @@ findM cond xs = findM' cond (viewl xs)
if isMatch
then return (Just x')
else findM qry xs'
-- $utilities
-- #utilities#
-- Below are handy queries for use with 'nextMatch', 'nextMatchOrDo',
-- and 'nextMatchWithThis'.
-- | A query that matches all windows on visible workspaces. This is
-- useful for configurations with multiple screens, and matches even
-- invisible windows.
isOnAnyVisibleWS :: Query Bool
isOnAnyVisibleWS = do
w <- ask
ws <- liftX $ gets windowset
let allVisible = concatMap (maybe [] SS.integrate . SS.stack . SS.workspace) (SS.current ws:SS.visible ws)
visibleWs = w `elem` allVisible
unfocused = Just w /= SS.peek ws
return $ visibleWs && unfocused

View File

@@ -1,7 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.KeyRemap
-- Description : Remap Keybinding on the fly.
-- Copyright : (c) Christian Dietrich
-- License : BSD-style (as xmonad)
--
@@ -27,14 +27,13 @@ module XMonad.Actions.KeyRemap (
) where
import XMonad
import XMonad.Prelude
import XMonad.Util.Paste
import Data.List
import qualified XMonad.Util.ExtensibleState as XS
import Control.Monad
data KeymapTable = KeymapTable [((KeyMask, KeySym), (KeyMask, KeySym))] deriving (Typeable, Show)
newtype KeymapTable = KeymapTable [((KeyMask, KeySym), (KeyMask, KeySym))] deriving (Show)
instance ExtensionClass KeymapTable where
initialValue = KeymapTable []
@@ -125,8 +124,8 @@ extractKeyMapping (KeymapTable table) mask sym =
buildKeyRemapBindings :: [KeymapTable] -> [((KeyMask, KeySym), X ())]
buildKeyRemapBindings keyremaps =
[((mask, sym), doKeyRemap mask sym) | (mask, sym) <- bindings]
where mappings = concat (map (\(KeymapTable table) -> table) keyremaps)
bindings = nub (map (\binding -> fst binding) mappings)
where mappings = concatMap (\(KeymapTable table) -> table) keyremaps
bindings = nub (map fst mappings)
-- Here come the Keymappings
@@ -138,7 +137,7 @@ emptyKeyRemap = KeymapTable []
dvorakProgrammerKeyRemap :: KeymapTable
dvorakProgrammerKeyRemap =
KeymapTable [((charToMask maskFrom, from), (charToMask maskTo, to)) |
(maskFrom, from, maskTo, to) <- (zip4 layoutUsShift layoutUsKey layoutDvorakShift layoutDvorakKey)]
(maskFrom, from, maskTo, to) <- zip4 layoutUsShift layoutUsKey layoutDvorakShift layoutDvorakKey]
where
layoutUs = map (fromIntegral . fromEnum) "`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?" :: [KeySym]
@@ -149,8 +148,6 @@ dvorakProgrammerKeyRemap =
layoutDvorakShift = map getShift layoutDvorak
layoutDvorakKey = map getKey layoutDvorak
getKey char = let Just index = elemIndex char layoutUs
in layoutUsKey !! index
getShift char = let Just index = elemIndex char layoutUs
in layoutUsShift !! index
getKey char = fromJust $ (layoutUsKey !?) =<< elemIndex char layoutUs
getShift char = fromJust $ (layoutUsShift !?) =<< elemIndex char layoutUs
charToMask char = if [char] == "0" then 0 else shiftMask

View File

@@ -1,5 +1,6 @@
{- |
Module : XMonad.Actions.Launcher
Description : A set of prompts for XMonad.
Copyright : (C) 2012 Carlos López-Camey
License : None; public domain
@@ -18,10 +19,9 @@ module XMonad.Actions.Launcher(
, launcherPrompt
) where
import Data.List (find, findIndex, isPrefixOf, tails)
import qualified Data.Map as M
import Data.Maybe (isJust)
import XMonad hiding (config)
import XMonad.Prelude
import XMonad.Prompt
import XMonad.Util.Run
@@ -34,10 +34,10 @@ import XMonad.Util.Run
To test it, modify your local .xmonad:
> import XMonad.Prompt(defaultXPConfig)
> import XMonad.Prompt(def)
> import XMonad.Actions.Launcher
> ((modm .|. controlMask, xK_l), launcherPrompt defaultXPConfig $ defaultLauncherModes launcherConfig)
> ((modm .|. controlMask, xK_l), launcherPrompt def $ defaultLauncherModes launcherConfig)
A LauncherConfig contains settings for the default modes, modify them accordingly.
@@ -45,7 +45,7 @@ import XMonad.Util.Run
Restart xmonad. Press Ctrl + Your_Modkey + L and the first prompt should pop up.
If you used 'defaultXPConfig', you can change mode with 'xK_grave'. If you are using your own 'XPConfig', define the value for 'changeModeKey'.
If you used the default 'XPConfig', you can change mode with 'xK_grave'. If you are using your own 'XPConfig', define the value for 'changeModeKey'.
-}
data HoogleMode = HMode FilePath String --path to hoogle and browser
@@ -62,15 +62,15 @@ type ExtensionActions = M.Map String (String -> X())
instance XPrompt CalculatorMode where
showXPrompt CalcMode = "calc %s> "
commandToComplete CalcMode = id --send the whole string to `calc`
completionFunction CalcMode = \s -> if (length s == 0) then return [] else do
fmap lines $ runProcessWithInput "calc" [s] ""
completionFunction CalcMode s = if null s then return [] else
lines <$> runProcessWithInput "calc" [s] ""
modeAction CalcMode _ _ = return () -- do nothing; this might copy the result to the clipboard
-- | Uses the program `hoogle` to search for functions
instance XPrompt HoogleMode where
showXPrompt _ = "hoogle %s> "
commandToComplete _ = id
completionFunction (HMode pathToHoogleBin' _) = \s -> completionFunctionWith pathToHoogleBin' ["--count","8",s]
completionFunction (HMode pathToHoogleBin' _) s = completionFunctionWith pathToHoogleBin' ["--count","8",s]
-- This action calls hoogle again to find the URL corresponding to the autocompleted item
modeAction (HMode pathToHoogleBin'' browser') query result = do
completionsWithLink <- liftIO $ completionFunctionWith pathToHoogleBin'' ["--count","5","--link",query]
@@ -88,7 +88,7 @@ instance XPrompt HoogleMode where
-- | Creates an autocompletion function for a programm given the program's name and a list of args to send to the command.
completionFunctionWith :: String -> [String] -> IO [String]
completionFunctionWith cmd args = do fmap lines $ runProcessWithInput cmd args ""
completionFunctionWith cmd args = lines <$> runProcessWithInput cmd args ""
-- | Creates a prompt with the given modes
launcherPrompt :: XPConfig -> [XPMode] -> X()

View File

@@ -0,0 +1,169 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.LinkWorkspaces
-- Description : Bindings to add and delete links between workspaces.
-- Copyright : (c) Jan-David Quesel <quesel@gmail.org>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : none
-- Stability : unstable
-- Portability : unportable
--
-- 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.
--
-----------------------------------------------------------------------------
module XMonad.Actions.LinkWorkspaces (
-- * Usage
-- $usage
switchWS,
removeAllMatchings,
unMatch,
toggleLinkWorkspaces,
defaultMessageConf,
MessageConfig(..)
) where
import XMonad
import XMonad.Prelude (for_)
import qualified XMonad.StackSet as W
import XMonad.Layout.IndependentScreens(countScreens)
import qualified XMonad.Util.ExtensibleState as XS (get, put)
import XMonad.Actions.OnScreen(Focus(FocusCurrent), onScreen')
import qualified Data.Map as M
( insert, delete, Map, lookup, empty, filter )
-- $usage
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.LinkWorkspaces
--
-- and add a function to print messages like
--
-- > message_command (S screen) = " dzen2 -p 1 -w 300 -xs " ++ show (screen + 1)
-- > message_color_func c1 c2 msg = dzenColor c1 c2 msg
-- > message screen c1 c2 msg = spawn $ "echo '" ++ (message_color_func c1 c2 msg) ++ "' | " ++ message_command screen
--
-- alternatively you can use the noMessages function as the argument
--
-- Then add keybindings like the following:
--
-- > ,((modm, xK_p), toggleLinkWorkspaces message)
-- > ,((modm .|. shiftMask, xK_p), removeAllMatchings message)
--
-- > [ ((modm .|. m, k), a i)
-- > | (a, m) <- [(switchWS (\y -> windows $ view y) message, 0),(switchWS (\x -> windows $ shift x . view x) message, shiftMask)]
-- > , (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]]
--
-- For detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
data MessageConfig = MessageConfig { messageFunction :: ScreenId -> [Char] -> [Char] -> [Char] -> X()
, foreground :: [Char]
, alertedForeground :: [Char]
, background :: [Char]
}
defaultMessageConf :: MessageConfig
defaultMessageConf = MessageConfig { messageFunction = noMessageFn
, background = "#000000"
, alertedForeground = "#ff7701"
, foreground = "#00ff00" }
noMessageFn :: ScreenId -> [Char] -> [Char] -> [Char] -> X()
noMessageFn _ _ _ _ = return () :: X ()
-- | Stuff for linking workspaces
newtype WorkspaceMap = WorkspaceMap (M.Map WorkspaceId WorkspaceId) deriving (Read, Show)
instance ExtensionClass WorkspaceMap
where initialValue = WorkspaceMap M.empty
extensionType = PersistentExtension
switchWS :: (WorkspaceId -> X ()) -> MessageConfig -> WorkspaceId -> X ()
switchWS f m ws = switchWS' f m ws Nothing
-- | Switch to the given workspace in a non greedy way, stop if we reached the first screen
-- | we already did switching on
switchWS' :: (WorkspaceId -> X ()) -> MessageConfig -> WorkspaceId -> Maybe ScreenId -> X ()
switchWS' switchFn message workspace stopAtScreen = do
ws <- gets windowset
nScreens <- countScreens
let now = W.screen (W.current ws)
let next = (now + 1) `mod` nScreens
switchFn workspace
case stopAtScreen of
Nothing -> sTM now next (Just now)
Just sId -> if sId == next then return () else sTM now next (Just sId)
where sTM = switchToMatching (switchWS' switchFn message) message workspace
-- | Switch to the workspace that matches the current one, executing switches for that workspace as well.
-- | The function switchWorkspaceNonGreedy' will take of stopping if we reached the first workspace again.
switchToMatching :: (WorkspaceId -> Maybe ScreenId -> X ()) -> MessageConfig -> WorkspaceId -> ScreenId
-> ScreenId -> Maybe ScreenId -> X ()
switchToMatching f message t now next stopAtScreen = do
WorkspaceMap matchings <- XS.get :: X WorkspaceMap
case M.lookup t matchings of
Nothing -> return () :: X()
Just newWorkspace -> do
onScreen' (f newWorkspace stopAtScreen) FocusCurrent next
messageFunction message now (foreground message) (background message) ("Switching to: " ++ (t ++ " and " ++ newWorkspace))
-- | Insert a mapping between t1 and t2 or remove it was already present
toggleMatching :: MessageConfig -> WorkspaceId -> WorkspaceId -> X ()
toggleMatching message t1 t2 = do
WorkspaceMap matchings <- XS.get :: X WorkspaceMap
case M.lookup t1 matchings of
Nothing -> setMatching message t1 t2 matchings
Just t -> if t == t2 then removeMatching' message t1 t2 matchings else setMatching message t1 t2 matchings
return ()
-- | Insert a mapping between t1 and t2 and display a message
setMatching :: MessageConfig -> WorkspaceId -> WorkspaceId -> M.Map WorkspaceId WorkspaceId -> X ()
setMatching message t1 t2 matchings = do
ws <- gets windowset
let now = W.screen (W.current ws)
XS.put $ WorkspaceMap $ M.insert t1 t2 matchings
messageFunction message now (foreground message) (background message) ("Linked: " ++ (t1 ++ " " ++ t2))
-- currently this function is called manually this means that if workspaces
-- were deleted, some links stay in the RAM even though they are not used
-- anymore... because of the small amount of memory used for those there is no
-- special cleanup so far
removeMatching' :: MessageConfig -> WorkspaceId -> WorkspaceId -> M.Map WorkspaceId WorkspaceId -> X ()
removeMatching' message t1 t2 matchings = do
ws <- gets windowset
let now = W.screen (W.current ws)
XS.put $ WorkspaceMap $ M.delete t1 matchings
messageFunction message now (alertedForeground message) (background message) ("Unlinked: " ++ t1 ++ " " ++ t2)
-- | Remove all maps between workspaces
removeAllMatchings :: MessageConfig -> X ()
removeAllMatchings message = do
ws <- gets windowset
let now = W.screen (W.current ws)
XS.put $ WorkspaceMap M.empty
messageFunction message now (alertedForeground message) (background message) "All links removed!"
-- | remove all matching regarding a given workspace
unMatch :: WorkspaceId -> X ()
unMatch workspace = do
WorkspaceMap matchings <- XS.get :: X WorkspaceMap
XS.put $ WorkspaceMap $ M.delete workspace (M.filter (/= workspace) matchings)
-- | Toggle the currently displayed workspaces as matching. Starting from the one with focus
-- | a linked list of workspaces is created that will later be iterated by switchToMatching.
toggleLinkWorkspaces :: MessageConfig -> X ()
toggleLinkWorkspaces message = withWindowSet $ \ws -> toggleLinkWorkspaces' (W.screen (W.current ws)) message
toggleLinkWorkspaces' :: ScreenId -> MessageConfig -> X ()
toggleLinkWorkspaces' first message = do
ws <- gets windowset
nScreens <- countScreens
let now = W.screen (W.current ws)
let next = (now + 1) `mod` nScreens
if next == first then return () else do -- this is also the case if there is only one screen
for_ (W.lookupWorkspace next ws)
(toggleMatching message (W.currentTag ws))
onScreen' (toggleLinkWorkspaces' first message) FocusCurrent next

View File

@@ -1,7 +1,9 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.MessageFeedback
-- Copyright : (c) Quentin Moser <moserq@gmail.com>
-- Description : An alternative @sendMessage@.
-- Copyright : (c) -- Quentin Moser <moserq@gmail.com>
-- 2018 Yclept Nemo
-- License : BSD3
--
-- Maintainer : orphaned
@@ -13,87 +15,212 @@
-- this facility.
-----------------------------------------------------------------------------
module XMonad.Actions.MessageFeedback (
-- * Usage
-- $usage
module XMonad.Actions.MessageFeedback
( -- * Usage
-- $usage
send
, tryMessage
, tryMessage_
, tryInOrder
, tryInOrder_
, sm
, sendSM
, sendSM_
) where
-- * Messaging variants
import XMonad.Core ( X (), Message, SomeMessage(..), LayoutClass(..), windowset, catchX )
import XMonad.StackSet ( current, workspace, layout, tag )
import XMonad.Operations ( updateLayout )
-- ** 'SomeMessage'
sendSomeMessageB, sendSomeMessage
, sendSomeMessageWithNoRefreshB, sendSomeMessageWithNoRefresh
, sendSomeMessageWithNoRefreshToCurrentB, sendSomeMessageWithNoRefreshToCurrent
import Control.Monad.State ( gets )
import Data.Maybe ( isJust )
import Control.Applicative ((<$>))
-- ** 'Message'
, sendMessageB
, sendMessageWithNoRefreshB
, sendMessageWithNoRefreshToCurrentB, sendMessageWithNoRefreshToCurrent
-- * Utility Functions
-- ** Send All
, sendSomeMessagesB, sendSomeMessages, sendMessagesB, sendMessages
-- ** Send Until
, tryInOrderB, tryInOrderWithNoRefreshToCurrentB, tryInOrderWithNoRefreshToCurrent
, tryMessageB, tryMessageWithNoRefreshToCurrentB, tryMessageWithNoRefreshToCurrent
-- ** Aliases
, sm
) where
import XMonad ( Window )
import XMonad.Core ( X(), Message, SomeMessage(..), LayoutClass(..), windowset, catchX, WorkspaceId, Layout, whenJust )
import XMonad.Operations ( updateLayout, windowBracket, modifyWindowSet )
import XMonad.Prelude
import XMonad.StackSet ( Workspace, current, workspace, layout, tag )
import Control.Monad.State ( gets )
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.MessageFeedback
--
-- You can then use this module's functions wherever an action is expected.
-- You can then use this module's functions wherever an action is expected. All
-- feedback variants are supported:
--
-- * message to any workspace with no refresh
-- * message to current workspace with no refresh
-- * message to current workspace with refresh
--
-- Except "message to any workspace with refresh" which makes little sense.
--
-- Note that most functions in this module have a return type of @X Bool@
-- whereas configuration options will expect a @X ()@ action.
-- For example, the key binding
-- whereas configuration options will expect a @X ()@ action. For example, the
-- key binding:
--
-- > -- Shrink the master area of a tiled layout, or move the focused window
-- > -- to the left in a WindowArranger-based layout
-- > ((modKey, xK_Left), tryMessage Shrink (MoveLeft 50))
-- > ((modKey, xK_Left), tryMessageWithNoRefreshToCurrentB Shrink (MoveLeft 50))
--
-- is mis-typed. For this reason, this module provides alternatives (ending with
-- an underscore, e.g. tryMessage_) that discard their result and return an @X ()@.
-- For example, to correct the previous example:
-- is mis-typed. For this reason, this module provides alternatives (not ending
-- with an uppercase \"B\", e.g. 'XMonad.Operations.sendMessage' rather than
-- 'sendMessageB') that discard their boolean result and return an @X ()@. For
-- example, to correct the previous example:
--
-- > ((modKey, xK_Left), tryMessage_ Shrink (MoveLeft 50))
-- > ((modKey, xK_Left), tryMessageWithNoRefreshToCurrent Shrink (MoveLeft 50))
--
-- This module also provides 'SomeMessage' variants of each 'Message' function
-- for when the messages are of differing types (but still instances of
-- 'Message'). First box each message using 'SomeMessage' or the convenience
-- alias 'sm'. Then, for example, to send each message:
--
-- > sendSomeMessages [sm messageOfTypeA, sm messageOfTypeB]
--
-- This is /not/ equivalent to the following example, which will not refresh
-- the workspace unless the last message is handled:
--
-- > sendMessageWithNoRefreshToCurrent messageOfTypeA >> sendMessage messageOfTypeB
-- | Behaves like 'XMonad.Operations.sendMessage', but returns True of the
-- message was handled by the layout, False otherwise.
send :: Message a => a -> X Bool
send = sendSM . sm
-- | Variant of 'XMonad.Operations.sendMessage'. Accepts 'SomeMessage'; to use
-- 'Message' see 'sendMessageB'. Returns @True@ if the message was handled,
-- @False@ otherwise. Instead of using 'sendSomeMessageWithNoRefreshToCurrentB'
-- for efficiency this is pretty much an exact copy of the
-- 'XMonad.Operations.sendMessage' code - foregoes the O(n) 'updateLayout'.
sendSomeMessageB :: SomeMessage -> X Bool
sendSomeMessageB m = windowBracket id $ do
w <- gets ((workspace . current) . windowset)
ml <- handleMessage (layout w) m `catchX` return Nothing
whenJust ml $ \l ->
modifyWindowSet $ \ws -> ws { current = (current ws)
{ workspace = (workspace $ current ws)
{ layout = l }}}
return $ isJust ml
-- | Sends the first message, and if it was not handled, sends the second.
-- Returns True if either message was handled, False otherwise.
tryMessage :: (Message a, Message b) => a -> b -> X Bool
tryMessage m1 m2 = do b <- send m1
if b then return True else send m2
-- | Variant of 'sendSomeMessageB' that discards the result.
sendSomeMessage :: SomeMessage -> X ()
sendSomeMessage = void . sendSomeMessageB
tryMessage_ :: (Message a, Message b) => a -> b -> X ()
tryMessage_ m1 m2 = tryMessage m1 m2 >> return ()
-- | Variant of 'XMonad.Operations.sendMessageWithNoRefresh'. Accepts
-- 'SomeMessage'; to use 'Message' see 'sendMessageWithNoRefreshB'. Returns
-- @True@ if the message was handled, @False@ otherwise.
sendSomeMessageWithNoRefreshB :: SomeMessage -> Workspace WorkspaceId (Layout Window) Window -> X Bool
sendSomeMessageWithNoRefreshB m w
= handleMessage (layout w) m `catchX` return Nothing
>>= liftA2 (>>) (updateLayout $ tag w) (return . isJust)
-- | Tries sending every message of the list in order until one of them
-- is handled. Returns True if one of the messages was handled, False otherwise.
tryInOrder :: [SomeMessage] -> X Bool
tryInOrder [] = return False
tryInOrder (m:ms) = do b <- sendSM m
if b then return True else tryInOrder ms
-- | Variant of 'sendSomeMessageWithNoRefreshB' that discards the result.
sendSomeMessageWithNoRefresh :: SomeMessage -> Workspace WorkspaceId (Layout Window) Window -> X ()
sendSomeMessageWithNoRefresh m = void . sendSomeMessageWithNoRefreshB m
tryInOrder_ :: [SomeMessage] -> X ()
tryInOrder_ ms = tryInOrder ms >> return ()
-- | Variant of 'XMonad.Operations.sendMessageWithNoRefresh' that sends the
-- message to the current layout. Accepts 'SomeMessage'; to use 'Message' see
-- 'sendMessageWithNoRefreshToCurrentB'. Returns @True@ if the message was
-- handled, @False@ otherwise. This function is somewhat of a cross between
-- 'XMonad.Operations.sendMessage' (sends to the current layout) and
-- 'XMonad.Operations.sendMessageWithNoRefresh' (does not refresh).
sendSomeMessageWithNoRefreshToCurrentB :: SomeMessage -> X Bool
sendSomeMessageWithNoRefreshToCurrentB m
= gets (workspace . current . windowset)
>>= sendSomeMessageWithNoRefreshB m
-- | Variant of 'sendSomeMessageWithNoRefreshToCurrentB' that discards the
-- result.
sendSomeMessageWithNoRefreshToCurrent :: SomeMessage -> X ()
sendSomeMessageWithNoRefreshToCurrent = void . sendSomeMessageWithNoRefreshToCurrentB
-- | Convenience shorthand for 'XMonad.Core.SomeMessage'.
-- | Variant of 'sendSomeMessageB' which like 'XMonad.Operations.sendMessage'
-- accepts 'Message' rather than 'SomeMessage'. Returns @True@ if the message
-- was handled, @False@ otherwise.
sendMessageB :: Message a => a -> X Bool
sendMessageB = sendSomeMessageB . SomeMessage
-- | Variant of 'sendSomeMessageWithNoRefreshB' which like
-- 'XMonad.Operations.sendMessageWithNoRefresh' accepts 'Message' rather than
-- 'SomeMessage'. Returns @True@ if the message was handled, @False@ otherwise.
sendMessageWithNoRefreshB :: Message a => a -> Workspace WorkspaceId (Layout Window) Window -> X Bool
sendMessageWithNoRefreshB = sendSomeMessageWithNoRefreshB . SomeMessage
-- | Variant of 'sendSomeMessageWithNoRefreshToCurrentB' which accepts
-- 'Message' rather than 'SomeMessage'. Returns @True@ if the message was
-- handled, @False@ otherwise.
sendMessageWithNoRefreshToCurrentB :: Message a => a -> X Bool
sendMessageWithNoRefreshToCurrentB = sendSomeMessageWithNoRefreshToCurrentB . SomeMessage
-- | Variant of 'sendMessageWithNoRefreshToCurrentB' that discards the result.
sendMessageWithNoRefreshToCurrent :: Message a => a -> X ()
sendMessageWithNoRefreshToCurrent = void . sendMessageWithNoRefreshToCurrentB
-- | Send each 'SomeMessage' to the current layout without refresh (using
-- 'sendSomeMessageWithNoRefreshToCurrentB') and collect the results. If any
-- message was handled, refresh. If you want to sequence a series of messages
-- that would have otherwise used 'XMonad.Operations.sendMessage' while
-- minimizing refreshes, use this.
sendSomeMessagesB :: [SomeMessage] -> X [Bool]
sendSomeMessagesB
= windowBracket or
. mapM sendSomeMessageWithNoRefreshToCurrentB
-- | Variant of 'sendSomeMessagesB' that discards the results.
sendSomeMessages :: [SomeMessage] -> X ()
sendSomeMessages = void . sendSomeMessagesB
-- | Variant of 'sendSomeMessagesB' which accepts 'Message' rather than
-- 'SomeMessage'. Use this if all the messages are of the same type.
sendMessagesB :: Message a => [a] -> X [Bool]
sendMessagesB = sendSomeMessagesB . map SomeMessage
-- | Variant of 'sendMessagesB' that discards the results.
sendMessages :: Message a => [a] -> X ()
sendMessages = void . sendMessagesB
-- | Apply the dispatch function in order to each message of the list until one
-- is handled. Returns @True@ if so, @False@ otherwise.
tryInOrderB :: (SomeMessage -> X Bool) -> [SomeMessage] -> X Bool
tryInOrderB _ [] = return False
tryInOrderB f (m:ms) = do b <- f m
if b then return True else tryInOrderB f ms
-- | Variant of 'tryInOrderB' that sends messages to the current layout without
-- refresh using 'sendSomeMessageWithNoRefreshToCurrentB'.
tryInOrderWithNoRefreshToCurrentB :: [SomeMessage] -> X Bool
tryInOrderWithNoRefreshToCurrentB = tryInOrderB sendSomeMessageWithNoRefreshToCurrentB
-- | Variant of 'tryInOrderWithNoRefreshToCurrent' that discards the results.
tryInOrderWithNoRefreshToCurrent :: [SomeMessage] -> X ()
tryInOrderWithNoRefreshToCurrent = void . tryInOrderWithNoRefreshToCurrentB
-- | Apply the dispatch function to the first message, and if it was not
-- handled, apply it to the second. Returns @True@ if either message was
-- handled, @False@ otherwise.
tryMessageB :: (Message a, Message b) => (SomeMessage -> X Bool) -> a -> b -> X Bool
tryMessageB f m1 m2 = tryInOrderB f [sm m1,sm m2]
-- | Variant of 'tryMessageB' that sends messages to the current layout without
-- refresh using 'sendMessageWithNoRefreshToCurrentB'.
tryMessageWithNoRefreshToCurrentB :: (Message a, Message b) => a -> b -> X Bool
tryMessageWithNoRefreshToCurrentB = tryMessageB sendSomeMessageWithNoRefreshToCurrentB
-- | Variant of 'tryMessage' that discards the results.
tryMessageWithNoRefreshToCurrent :: (Message a, Message b) => a -> b -> X ()
tryMessageWithNoRefreshToCurrent m = void . tryMessageWithNoRefreshToCurrentB m
-- | Convenience shorthand for 'SomeMessage'.
sm :: Message a => a -> SomeMessage
sm = SomeMessage
sendSM :: SomeMessage -> X Bool
sendSM m = do w <- workspace . current <$> gets windowset
ml' <- handleMessage (layout w) m `catchX` return Nothing
updateLayout (tag w) ml'
return $ isJust ml'
sendSM_ :: SomeMessage -> X ()
sendSM_ m = sendSM m >> return ()

147
XMonad/Actions/Minimize.hs Normal file
View File

@@ -0,0 +1,147 @@
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Minimize
-- Description : Actions for minimizing and maximizing windows.
-- Copyright : (c) Bogdan Sinitsyn (2016)
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Bogdan Sinitsyn <bogdan.sinitsyn@gmail.com>
-- Stability : unstable
-- Portability : not portable
--
-- Adds actions for minimizing and maximizing windows
--
-- This module should be used with "XMonad.Layout.Minimize". Add 'minimize' to your
-- layout modifiers as described in "XMonad.Layout.Minimize" and use actions from
-- this module
--
-- Possible keybindings:
--
-- > , ((modm, xK_m ), withFocused minimizeWindow)
-- > , ((modm .|. shiftMask, xK_m ), withLastMinimized maximizeWindowAndFocus)
--
-----------------------------------------------------------------------------
module XMonad.Actions.Minimize
( -- * Usage
-- $usage
minimizeWindow
, maximizeWindow
, maximizeWindowAndFocus
, withLastMinimized
, withLastMinimized'
, withFirstMinimized
, withFirstMinimized'
, withMinimized
) where
import XMonad
import XMonad.Prelude (fromMaybe, join, listToMaybe)
import qualified XMonad.StackSet as W
import qualified XMonad.Layout.BoringWindows as BW
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Minimize
import XMonad.Util.WindowProperties (getProp32)
import Foreign.C.Types (CLong)
import qualified Data.List as L
import qualified Data.Map as M
-- $usage
-- Import this module with "XMonad.Layout.Minimize" and "XMonad.Layout.BoringWindows":
--
-- > import XMonad.Actions.Minimize
-- > import XMonad.Layout.Minimize
-- > import qualified XMonad.Layout.BoringWindows as BW
--
-- Then apply 'minimize' and 'boringWindows' to your layout hook and use some
-- actions from this module:
--
-- > main = xmonad def { layoutHook = minimize . BW.boringWindows $ whatever }
--
-- Example keybindings:
--
-- > , ((modm, xK_m ), withFocused minimizeWindow )
-- > , ((modm .|. shiftMask, xK_m ), withLastMinimized maximizeWindow)
setMinimizedState :: Window -> Int -> (CLong -> [CLong] -> [CLong]) -> X ()
setMinimizedState win st f = do
setWMState win st
withDisplay $ \dpy -> do
wm_state <- getAtom "_NET_WM_STATE"
hidden <- fromIntegral <$> getAtom "_NET_WM_STATE_HIDDEN"
wstate <- fromMaybe [] <$> getProp32 wm_state win
io $ changeProperty32 dpy win wm_state aTOM propModeReplace (f hidden wstate)
setMinimized :: Window -> X ()
setMinimized win = setMinimizedState win iconicState (:)
setNotMinimized :: Window -> X ()
setNotMinimized win = setMinimizedState win normalState L.delete
-- It does not just set minimizedStack to newWindows because it should save
-- order in which elements were added (newer first)
modified :: (RectMap -> RectMap) -> X Bool
modified f = XS.modified $
\Minimized { rectMap = oldRectMap, minimizedStack = oldStack } ->
let newRectMap = f oldRectMap
newWindows = M.keys newRectMap
in Minimized { rectMap = newRectMap
, minimizedStack = (newWindows L.\\ oldStack)
++
(oldStack `L.intersect` newWindows)
}
-- | Minimize a window
minimizeWindow :: Window -> X ()
minimizeWindow w = withWindowSet $ \ws ->
whenX (modified $ M.insert w (M.lookup w $ W.floating ws)) $ do
setMinimized w
windows $ W.sink w
BW.focusDown
-- | Maximize window and apply a function to maximized window and 'WindowSet'
maximizeWindowAndChangeWSet :: (Window -> WindowSet -> WindowSet) -> Window -> X ()
maximizeWindowAndChangeWSet f w = do
mrect <- XS.gets (join . M.lookup w . rectMap)
whenX (modified $ M.delete w) $ do
setNotMinimized w
broadcastMessage BW.UpdateBoring
windows $ f w . maybe id (W.float w) mrect
-- | Just maximize a window without focusing
maximizeWindow :: Window -> X ()
maximizeWindow = maximizeWindowAndChangeWSet $ const id
-- | Maximize a window and then focus it
maximizeWindowAndFocus :: Window -> X ()
maximizeWindowAndFocus = maximizeWindowAndChangeWSet W.focusWindow
-- | Perform an action with first minimized window on current workspace
-- or do nothing if there is no minimized windows on current workspace
withFirstMinimized :: (Window -> X ()) -> X ()
withFirstMinimized action = withFirstMinimized' (`whenJust` action)
-- | Like withFirstMinimized but the provided action is always invoked with a
-- 'Maybe Window', that will be nothing if there is no first minimized window.
withFirstMinimized' :: (Maybe Window -> X ()) -> X ()
withFirstMinimized' action = withMinimized (action . listToMaybe . reverse)
-- | Perform an action with last minimized window on current workspace
-- or do nothing if there is no minimized windows on current workspace
withLastMinimized :: (Window -> X ()) -> X ()
withLastMinimized action = withLastMinimized' (`whenJust` action)
-- | Like withLastMinimized but the provided action is always invoked with a
-- 'Maybe Window', that will be nothing if there is no last minimized window.
withLastMinimized' :: (Maybe Window -> X ()) -> X ()
withLastMinimized' action = withMinimized (action . listToMaybe)
withMinimized :: ([Window] -> X a) -> X a
withMinimized action = do
minimized <- XS.gets minimizedStack
currentStack <- withWindowSet $ return . W.index
action $ minimized `L.intersect` currentStack

View File

@@ -0,0 +1,205 @@
{-# LANGUAGE NamedFieldPuns, GeneralizedNewtypeDeriving #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.MostRecentlyUsed
-- Description : Tab through windows by recency of use.
-- Copyright : (c) 2022 L. S. Leary
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : @LSLeary (on github)
-- Stability : unstable
-- Portability : unportable
--
-- Based on the Alt+Tab behaviour common outside of xmonad.
--
-----------------------------------------------------------------------------
-- --< Imports & Exports >-- {{{
module XMonad.Actions.MostRecentlyUsed (
-- * Usage
-- $usage
-- * Interface
configureMRU,
mostRecentlyUsed,
withMostRecentlyUsed,
Location(..),
) where
-- base
import Data.List.NonEmpty (nonEmpty)
import Data.IORef (newIORef, readIORef, writeIORef, modifyIORef)
import Control.Monad.IO.Class (MonadIO)
-- mtl
import Control.Monad.Trans (lift)
import Control.Monad.State (get, put, gets)
-- containers
import qualified Data.Map.Strict as M
-- xmonad
import XMonad
( Window, KeySym, keyPress, io
, Event (DestroyWindowEvent, UnmapEvent, ev_send_event, ev_window)
)
import XMonad.Core
( X, XConfig(..), windowset, WorkspaceId, ScreenId
, ExtensionClass(..), StateExtension(..)
, waitingUnmap
)
import XMonad.Operations (screenWorkspace)
import qualified XMonad.StackSet as W
-- xmonad-contrib
import qualified XMonad.Util.ExtensibleConf as XC
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.PureX
(handlingRefresh, curScreenId, curTag, greedyView, view, peek, focusWindow)
import XMonad.Util.History (History, origin, event, erase, ledger)
import XMonad.Actions.Repeatable (repeatableSt)
import XMonad.Prelude
-- }}}
-- --< Core Data Types: WindowHistory & Location >-- {{{
data WindowHistory = WinHist
{ busy :: !Bool
, hist :: !(History Window Location)
} deriving (Show, Read)
instance ExtensionClass WindowHistory where
initialValue = WinHist
{ busy = False
, hist = origin
}
extensionType = PersistentExtension
data Location = Location
{ workspace :: !WorkspaceId
, screen :: !ScreenId
} deriving (Show, Read, Eq, Ord)
-- }}}
-- --< Interface >-- {{{
-- $usage
--
-- 'configureMRU' must be applied to your config in order for 'mostRecentlyUsed'
-- to work.
--
-- > main :: IO ()
-- > main = xmonad . configureMRU . ... $ def
-- > { ...
-- > }
--
-- Once that's done, it can be used normally in keybinds:
--
-- > , ((mod1Mask, xK_Tab), mostRecentlyUsed [xK_Alt_L, xK_Alt_R] xK_Tab)
--
-- N.B.: This example assumes that 'mod1Mask' corresponds to alt, which is not
-- always the case, depending on how your system is configured.
-- | Configure xmonad to support 'mostRecentlyUsed'.
configureMRU :: XConfig l -> XConfig l
configureMRU = XC.once f (MRU ()) where
f cnf = cnf
{ logHook = logHook cnf <> logWinHist
, handleEventHook = handleEventHook cnf <> winHistEH
}
newtype MRU = MRU () deriving Semigroup
-- | An action to browse through the history of focused windows, taking
-- another step back with each tap of the key.
mostRecentlyUsed
:: [KeySym] -- ^ The 'KeySym's corresponding to the modifier to which the
-- action is bound.
-> KeySym -- ^ The 'KeySym' corresponding to the key to which the action
-- is bound.
-> X ()
mostRecentlyUsed mods key = do
(toUndo, undo) <- undoer
let undoably curThing withThing thing = curThing >>= \cur ->
when (cur /= thing) $ withThing thing >> toUndo (withThing cur)
withMostRecentlyUsed mods key $ \win Location{workspace,screen} ->
handlingRefresh $ do
undo
undoably curScreenId viewScreen screen
undoably curTag greedyView workspace
mi <- gets (W.findTag win . windowset)
for_ mi $ \i -> do
undoably curTag greedyView i
mfw <- peek
for_ mfw $ \fw -> do
undoably (pure fw) focusWindow win
where
undoer :: (MonadIO m, Monoid a) => m (m a -> m (), m a)
undoer = do
ref <- io . newIORef $ pure mempty
let toUndo = io . modifyIORef ref . liftA2 (<>)
undo = join (io $ readIORef ref)
<* io (writeIORef ref $ pure mempty)
pure (toUndo, undo)
viewScreen :: ScreenId -> X Any
viewScreen scr = screenWorkspace scr >>= foldMap view
-- | A version of 'mostRecentlyUsed' that allows you to customise exactly what
-- is done with each window you tab through (the default being to visit its
-- previous 'Location' and give it focus).
withMostRecentlyUsed
:: [KeySym] -- ^ The 'KeySym's corresponding to the
-- modifier to which the action is bound.
-> KeySym -- ^ The 'KeySym' corresponding to the key to
-- which the action is bound.
-> (Window -> Location -> X ()) -- ^ The function applied to each window.
-> X ()
withMostRecentlyUsed mods tab preview = do
wh@WinHist{busy,hist} <- XS.get
unless busy $ do
XS.put wh{ busy = True }
for_ (nonEmpty $ ledger hist) $ \ne -> do
mfw <- gets (W.peek . windowset)
let iSt = case cycleS ne of
(w, _) :~ s | mfw == Just w -> s
s -> s
repeatableSt iSt mods tab $ \t s ->
when (t == keyPress && s == tab) (pop >>= lift . uncurry preview)
XS.modify $ \ws@WinHist{} -> ws{ busy = False }
logWinHist
where
pop = do
h :~ t <- get
put t $> h
-- }}}
-- --< Raw Config >-- {{{
logWinHist :: X ()
logWinHist = do
wh@WinHist{busy,hist} <- XS.get
unless busy $ do
cs <- gets (W.current . windowset)
let cws = W.workspace cs
for_ (W.stack cws) $ \st -> do
let location = Location{ workspace = W.tag cws, screen = W.screen cs }
XS.put wh{ hist = event (W.focus st) location hist }
winHistEH :: Event -> X All
winHistEH ev = All True <$ case ev of
UnmapEvent{ ev_send_event = synth, ev_window = w } -> do
e <- gets (fromMaybe 0 . M.lookup w . waitingUnmap)
when (synth || e == 0) (collect w)
DestroyWindowEvent{ ev_window = w } -> collect w
_ -> pure ()
where collect w = XS.modify $ \wh@WinHist{hist} -> wh{ hist = erase w hist }
-- }}}

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.MouseGestures
-- Description : Support for simple mouse gestures.
-- Copyright : (c) Lukas Mai
-- License : BSD3-style (see LICENSE)
--
@@ -21,18 +22,17 @@ module XMonad.Actions.MouseGestures (
mkCollect
) where
import XMonad.Prelude
import XMonad
import XMonad.Util.Types (Direction2D(..))
import Data.IORef
import qualified Data.Map as M
import Data.Map (Map)
import Data.Maybe
import Control.Monad
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.MouseGestures
-- > import qualified XMonad.StackSet as W
@@ -79,17 +79,11 @@ gauge :: (Direction2D -> X ()) -> Pos -> IORef (Maybe (Direction2D, Pos)) -> Pos
gauge hook op st nx ny = do
let np = (nx, ny)
stx <- io $ readIORef st
let
(~(Just od), pivot) = case stx of
Nothing -> (Nothing, op)
Just (d, zp) -> (Just d, zp)
cont = do
guard $ significant np pivot
return $ do
let d' = dir pivot np
when (isNothing stx || od /= d') $ hook d'
io $ writeIORef st (Just (d', np))
fromMaybe (return ()) cont
let pivot = maybe op snd stx
when (significant np pivot) $ do
let d' = dir pivot np
when ((fst <$> stx) /= Just d') $ hook d'
io $ writeIORef st (Just (d', np))
where
significant a b = delta a b >= 10
@@ -111,7 +105,7 @@ mouseGestureH moveHook endHook = do
mouseGesture :: Map [Direction2D] (Window -> X ()) -> Window -> X ()
mouseGesture tbl win = do
(mov, end) <- mkCollect
mouseGestureH (\d -> mov d >> return ()) $ end >>= \gest ->
mouseGestureH (void . mov) $ end >>= \gest ->
case M.lookup gest tbl of
Nothing -> return ()
Just f -> f win

View File

@@ -1,8 +1,9 @@
{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses, PatternGuards, TypeSynonymInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.MouseResize
-- Description : A layout modifier to resize windows with the mouse.
-- Copyright : (c) 2007 Andrea Rossato
-- License : BSD-style (see xmonad/LICENSE)
--
@@ -36,27 +37,27 @@ import XMonad.Util.XUtils
-- "XMonad.Layout.SimpleFloat" or "XMonad.Layout.DecorationMadness".
--
-- You can use this module with the following in your
-- @~\/.xmonad\/xmonad.hs@:
-- @xmonad.hs@:
--
-- > import XMonad.Actions.MouseResize
-- > import XMonad.Layout.WindowArranger
--
-- Then edit your @layoutHook@ by modifying a given layout:
--
-- > myLayout = mouseResize $ windowArrange $ layoutHook defaultConfig
-- > myLayout = mouseResize $ windowArrange $ layoutHook def
--
-- and then:
--
-- > main = xmonad defaultConfig { layoutHook = myLayout }
-- > main = xmonad def { layoutHook = myLayout }
--
-- For more detailed instructions on editing the layoutHook see:
--
-- "XMonad.Doc.Extending#Editing_the_layout_hook"
-- For more detailed instructions on editing the layoutHook see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial> and
-- "XMonad.Doc.Extending#Editing_the_layout_hook".
mouseResize :: l a -> ModifiedLayout MouseResize l a
mouseResize = ModifiedLayout (MR [])
data MouseResize a = MR [((a,Rectangle),Maybe a)]
newtype MouseResize a = MR [((a,Rectangle),Maybe a)]
instance Show (MouseResize a) where show _ = ""
instance Read (MouseResize a) where readsPrec _ s = [(MR [], s)]
@@ -68,7 +69,7 @@ instance LayoutModifier MouseResize Window where
where
wrs' = wrs_to_state [] . filter (isInStack s . fst) $ wrs
initState = mapM createInputWindow wrs'
processState = mapM (deleteInputWin . snd) st >> mapM createInputWindow wrs'
processState = mapM_ (deleteInputWin . snd) st >> mapM createInputWindow wrs'
inputRectangle (Rectangle x y wh ht) = Rectangle (x + fi wh - 5) (y + fi ht - 5) 10 10
@@ -105,7 +106,7 @@ handleResize st ButtonEvent { ev_window = ew, ev_event_type = et }
handleResize _ _ = return ()
createInputWindow :: ((Window,Rectangle), Maybe Rectangle) -> X ((Window,Rectangle),Maybe Window)
createInputWindow ((w,r),mr) = do
createInputWindow ((w,r),mr) =
case mr of
Just tr -> withDisplay $ \d -> do
tw <- mkInputWindow d tr

View File

@@ -1,8 +1,9 @@
{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, PatternGuards, RankNTypes, TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses, PatternGuards, RankNTypes, TypeSynonymInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Layout.Navigation2D
-- Description : Directional navigation of windows and screens.
-- Copyright : (c) 2011 Norbert Zeh <nzeh@cs.dal.ca>
-- License : BSD3-style (see LICENSE)
--
@@ -32,12 +33,19 @@ module XMonad.Actions.Navigation2D ( -- * Usage
-- * Exported functions and types
-- #Exports#
withNavigation2DConfig
navigation2D
, navigation2DP
, additionalNav2DKeys
, additionalNav2DKeysP
, withNavigation2DConfig
, Navigation2DConfig(..)
, defaultNavigation2DConfig
, def
, Navigation2D
, lineNavigation
, centerNavigation
, sideNavigation
, sideNavigationWithBias
, hybridOf
, fullScreenRect
, singleWindowRect
, switchLayer
@@ -49,38 +57,86 @@ module XMonad.Actions.Navigation2D ( -- * Usage
, Direction2D(..)
) where
import Control.Applicative
import qualified Data.List as L
import qualified Data.Map as M
import Data.Maybe
import Control.Arrow (second)
import XMonad.Prelude
import XMonad hiding (Screen)
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.EZConfig (additionalKeys, additionalKeysP)
import XMonad.Util.Types
import qualified Data.List.NonEmpty as NE
-- $usage
-- #Usage#
-- Navigation2D provides directional navigation (go left, right, up, down) for
-- windows and screens. It treats floating and tiled windows as two separate
-- layers and provides mechanisms to navigate within each layer and to switch
-- between layers. Navigation2D provides two different navigation strategies
-- (see <#Technical_Discussion> for details): /Line navigation/ feels rather
-- 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.
-- between layers. Navigation2D provides three different navigation strategies
-- (see <#Technical_Discussion> for details): /Line navigation/ and
-- /Side navigation/ feel rather 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. Another option is to use a /Hybrid/ of the three strategies,
-- automatically choosing whichever first provides a suitable target window.
-- 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@:
-- You can use this module with (a subset of) the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.Navigation2D
--
-- Then edit your keybindings:
-- Then add the configuration of the module to your main function:
--
-- > main = xmonad $ navigation2D def
-- > (xK_Up, xK_Left, xK_Down, xK_Right)
-- > [(mod4Mask, windowGo ),
-- > (mod4Mask .|. shiftMask, windowSwap)]
-- > False
-- > $ def
--
-- /NOTE/: the @def@ argument to 'navigation2D' contains the strategy
-- that decides which windows actually get selected. While the default
-- behaviour tries to keep them into account, if you use modules that
-- influence tiling in some way, like "XMonad.Layout.Spacing" or
-- "XMonad.Layout.Gaps", you should think about using a different
-- strategy, if you find the default behaviour to be unnatural. Check
-- out the [finer points](#g:Finer_Points) below for more information.
--
-- Alternatively to 'navigation2D', you can use 'navigation2DP':
--
-- > main = xmonad $ navigation2DP def
-- > ("<Up>", "<Left>", "<Down>", "<Right>")
-- > [("M-", windowGo ),
-- > ("M-S-", windowSwap)]
-- > False
-- > $ def
--
-- That's it. If instead you'd like more control, you can combine
-- 'withNavigation2DConfig' and 'additionalNav2DKeys' or 'additionalNav2DKeysP':
--
-- > main = xmonad $ withNavigation2DConfig def
-- > $ additionalNav2DKeys (xK_Up, xK_Left, xK_Down, xK_Right)
-- > [(mod4Mask, windowGo ),
-- > (mod4Mask .|. shiftMask, windowSwap)]
-- > False
-- > $ additionalNav2DKeys (xK_u, xK_l, xK_d, xK_r)
-- > [(mod4Mask, screenGo ),
-- > (mod4Mask .|. shiftMask, screenSwap)]
-- > False
-- > $ def
--
-- Or you can add the configuration of the module to your main function:
--
-- > main = xmonad $ withNavigation2DConfig def $ def
--
-- And specify your keybindings normally:
--
-- > -- Switch between layers
-- > , ((modm, xK_space), switchLayers)
-- > , ((modm, xK_space), switchLayer)
-- >
-- > -- Directional navigation of windows
-- > , ((modm, xK_Right), windowGo R False)
@@ -112,14 +168,9 @@ import XMonad.Util.Types
-- > , ((modm .|. mod1Mask, xK_u ), windowToScreen U False)
-- > , ((modm .|. mod1Mask, xK_d ), windowToScreen D False)
--
-- and add the configuration of the module to your main function:
--
-- > main = xmonad $ withNavigation2DConfig defaultNavigation2DConfig
-- > $ defaultConfig
--
-- For detailed instruction on editing the key binding see:
--
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- $finer_points
-- #Finer_Points#
@@ -136,9 +187,19 @@ import XMonad.Util.Types
-- values in the above example to 'True'. You could also decide you want
-- wrapping only for a subset of the operations and no wrapping for others.
--
-- By default, all layouts use the 'defaultTiledNavigation' strategy specified
-- in the 'Navigation2DConfig' (by default, line navigation is used). To
-- override this behaviour for some layouts, add a pair (\"layout name\",
-- By default, all layouts use the 'defaultTiledNavigation' strategy
-- specified in the 'Navigation2DConfig' (by default, line navigation is
-- used). Many more navigation strategies are available; some may feel
-- more natural, depending on the layout and user:
--
-- * 'lineNavigation'
-- * 'centerNavigation'
-- * 'sideNavigation'
-- * 'sideNavigationWithBias'
--
-- There is also the ability to combine two strategies with 'hybridOf'.
--
-- To override the default behaviour for some layouts, add a pair (\"layout name\",
-- navigation strategy) to the 'layoutNavigation' list in the
-- 'Navigation2DConfig', where \"layout name\" is the string reported by the
-- layout's description method (normally what is shown as the layout name in
@@ -147,10 +208,10 @@ import XMonad.Util.Types
-- example, for the Full layout, is to switch to center navigation for the Full
-- layout:
--
-- > myNavigation2DConfig = defaultNavigation2DConfig { layoutNavigation = [("Full", centerNavigation)] }
-- > myNavigation2DConfig = def { layoutNavigation = [("Full", centerNavigation)] }
-- >
-- > main = xmonad $ withNavigation2DConfig myNavigation2DConfig
-- > $ defaultConfig
-- > $ def
--
-- The navigation between windows is based on their screen rectangles, which are
-- available /and meaningful/ only for mapped windows. Thus, as already said,
@@ -164,12 +225,12 @@ import XMonad.Util.Types
-- on top of each other so that only the frontmost one is visible. This can be
-- done as follows:
--
-- > myNavigation2DConfig = defaultNavigation2DConfig { layoutNavigation = [("Full", centerNavigation)]
-- > , unmappedWindowRect = [("Full", singleWindowRect)]
-- > }
-- > myNavigation2DConfig = def { layoutNavigation = [("Full", centerNavigation)]
-- > , unmappedWindowRect = [("Full", singleWindowRect)]
-- > }
-- >
-- > main = xmonad $ withNavigation2DConfig myNavigation2DConfig
-- > $ defaultConfig
-- > $ def
--
-- With this setup, Left/Up navigation behaves like standard
-- 'XMonad.StackSet.focusUp' and Right/Down navigation behaves like
@@ -279,7 +340,47 @@ lineNavigation = N 1 doLineNavigation
centerNavigation :: Navigation2D
centerNavigation = N 2 doCenterNavigation
-- | Stores the configuration of directional navigation
-- | Side navigation. Consider navigating to the right this time. The strategy
-- is to take the line segment forming the right boundary of the current window,
-- and push it to the right until it intersects with at least one other window.
-- Of those windows, one with a point that is the closest to the centre of the
-- line (+1) is selected. This is probably the most intuitive strategy for the
-- tiled layer when using "XMonad.Layout.Spacing".
sideNavigation :: Navigation2D
sideNavigation = N 1 (doSideNavigationWithBias 1)
-- | Side navigation with bias. Consider a case where the screen is divided
-- up into three vertical panes; the side panes occupied by one window each and
-- the central pane split across the middle by two windows. By the criteria
-- of side navigation, the two central windows are equally good choices when
-- navigating inwards from one of the side panes. Hence in order to be
-- equitable, symmetric and pleasant to use, different windows are chosen when
-- navigating from different sides. In particular, the lower is chosen when
-- going left and the higher when going right, causing L, L, R, R, L, L, etc to
-- cycle through the four windows clockwise. This is implemented by using a bias
-- of 1. /Bias/ is how many pixels off centre the vertical split can be before
-- this behaviour is lost and the same window chosen every time. A negative bias
-- swaps the preferred window for each direction. A bias of zero disables the
-- behaviour.
sideNavigationWithBias :: Int -> Navigation2D
sideNavigationWithBias b = N 1 (doSideNavigationWithBias b)
-- | Hybrid of two modes of navigation, preferring the motions of the first.
-- Use this if you want to fall back on a second strategy whenever the first
-- does not find a candidate window. E.g.
-- @hybridOf lineNavigation centerNavigation@ is a good strategy for the
-- floating layer, and @hybridOf sideNavigation centerNavigation@ will enable
-- you to take advantage of some of the latter strategy's more interesting
-- motions in the tiled layer.
hybridOf :: Navigation2D -> Navigation2D -> Navigation2D
hybridOf (N g1 s1) (N g2 s2) = N (max g1 g2) $ applyToBoth s1 s2
where
applyToBoth f g a b c = f a b c <|> g a b c
-- | 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
-- or rectangles for unmapped windows are defined for individual layouts.
data Navigation2DConfig = Navigation2DConfig
{ defaultTiledNavigation :: Navigation2D -- ^ default navigation strategy for the tiled layer
, floatNavigation :: Navigation2D -- ^ navigation strategy for the float layer
@@ -298,14 +399,64 @@ data Navigation2DConfig = Navigation2DConfig
-- function calculates a rectangle for a given unmapped
-- window from the screen it is on and its window ID.
-- See <#Finer_Points> for how to use this.
} deriving Typeable
}
-- | Shorthand for the tedious screen type
type Screen = W.Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
type Screen = WindowScreen
-- | Convenience function for enabling Navigation2D with typical keybindings.
-- Takes a Navigation2DConfig, an (up, left, down, right) tuple, a mapping from
-- modifier key to action, and a bool to indicate if wrapping should occur, and
-- returns a function from XConfig to XConfig.
-- Example:
--
-- > navigation2D def (xK_w, xK_a, xK_s, xK_d) [(mod4Mask, windowGo), (mod4Mask .|. shiftMask, windowSwap)] False myConfig
navigation2D :: Navigation2DConfig -> (KeySym, KeySym, KeySym, KeySym) -> [(ButtonMask, Direction2D -> Bool -> X ())] ->
Bool -> XConfig l -> XConfig l
navigation2D navConfig (u, l, d, r) modifiers wrap xconfig =
additionalNav2DKeys (u, l, d, r) modifiers wrap $
withNavigation2DConfig navConfig xconfig
-- | Convenience function for enabling Navigation2D with typical keybindings,
-- using the syntax defined in 'XMonad.Util.EZConfig.mkKeymap'. Takes a
-- Navigation2DConfig, an (up, left, down, right) tuple, a mapping from key
-- prefix to action, and a bool to indicate if wrapping should occur, and
-- returns a function from XConfig to XConfig. Example:
--
-- > navigation2DP def ("w", "a", "s", "d") [("M-", windowGo), ("M-S-", windowSwap)] False myConfig
navigation2DP :: Navigation2DConfig -> (String, String, String, String) -> [(String, Direction2D -> Bool -> X ())] ->
Bool -> XConfig l -> XConfig l
navigation2DP navConfig (u, l, d, r) modifiers wrap xconfig =
additionalNav2DKeysP (u, l, d, r) modifiers wrap $
withNavigation2DConfig navConfig xconfig
-- | Convenience function for adding keybindings. Takes an (up, left, down,
-- right) tuple, a mapping from key prefix to action, and a bool to indicate if
-- wrapping should occur, and returns a function from XConfig to XConfig.
-- Example:
--
-- > additionalNav2DKeys (xK_w, xK_a, xK_s, xK_d) [(mod4Mask, windowGo), (mod4Mask .|. shiftMask, windowSwap)] False myConfig
additionalNav2DKeys :: (KeySym, KeySym, KeySym, KeySym) -> [(ButtonMask, Direction2D -> Bool -> X ())] ->
Bool -> XConfig l -> XConfig l
additionalNav2DKeys (u, l, d, r) modifiers wrap =
flip additionalKeys [((modif, k), func dir wrap) | (modif, func) <- modifiers, (k, dir) <- dirKeys]
where dirKeys = [(u, U), (l, L), (d, D), (r, R)]
-- | Convenience function for adding keybindings, using the syntax defined in
-- 'XMonad.Util.EZConfig.mkKeymap'. Takes an (up, left, down, right) tuple, a
-- mapping from key prefix to action, and a bool to indicate if wrapping should
-- occur, and returns a function from XConfig to XConfig. Example:
--
-- > additionalNav2DKeysP ("w", "a", "s", "d") [("M-", windowGo), ("M-S-", windowSwap)] False myConfig
additionalNav2DKeysP :: (String, String, String, String) -> [(String, Direction2D -> Bool -> X ())] ->
Bool -> XConfig l -> XConfig l
additionalNav2DKeysP (u, l, d, r) modifiers wrap =
flip additionalKeysP [(modif ++ k, func dir wrap) | (modif, func) <- modifiers, (k, dir) <- dirKeys]
where dirKeys = [(u, U), (l, L), (d, D), (r, R)]
-- So we can store the configuration in extensible state
instance ExtensionClass Navigation2DConfig where
initialValue = defaultNavigation2DConfig
initialValue = def
-- | Modifies the xmonad configuration to store the Navigation2D configuration
withNavigation2DConfig :: Navigation2DConfig -> XConfig a -> XConfig a
@@ -313,12 +464,8 @@ withNavigation2DConfig conf2d xconf = xconf { startupHook = startupHook xconf
>> XS.put conf2d
}
-- | Default navigation configuration. It uses line navigation for the tiled
-- layer and for navigation between screens, and center navigation for the float
-- layer. No custom navigation strategies or rectangles for unmapped windows are
-- defined for individual layouts.
defaultNavigation2DConfig :: Navigation2DConfig
defaultNavigation2DConfig = Navigation2DConfig { defaultTiledNavigation = lineNavigation
instance Default Navigation2DConfig where
def = Navigation2DConfig { defaultTiledNavigation = hybridOf lineNavigation sideNavigation
, floatNavigation = centerNavigation
, screenNavigation = lineNavigation
, layoutNavigation = []
@@ -344,7 +491,7 @@ switchLayer = actOnLayer otherLayer
-- navigation should wrap around (e.g., from the left edge of the leftmost
-- screen to the right edge of the rightmost screen).
windowGo :: Direction2D -> Bool -> X ()
windowGo dir wrap = actOnLayer thisLayer
windowGo dir = actOnLayer thisLayer
( \ conf cur wins -> windows
$ doTiledNavigation conf dir W.focusWindow cur wins
)
@@ -354,7 +501,6 @@ windowGo dir wrap = actOnLayer thisLayer
( \ conf cur wspcs -> windows
$ doScreenNavigation conf dir W.view cur wspcs
)
wrap
-- | Swaps the current window with the next window in the given direction and in
-- the same layer as the current window. (In the floating layer, all that
@@ -363,7 +509,7 @@ windowGo dir wrap = actOnLayer thisLayer
-- window's screen but retains its position and size relative to the screen.)
-- The second argument indicates wrapping (see 'windowGo').
windowSwap :: Direction2D -> Bool -> X ()
windowSwap dir wrap = actOnLayer thisLayer
windowSwap dir = actOnLayer thisLayer
( \ conf cur wins -> windows
$ doTiledNavigation conf dir swap cur wins
)
@@ -371,32 +517,28 @@ windowSwap dir wrap = actOnLayer thisLayer
$ doFloatNavigation conf dir swap cur wins
)
( \ _ _ _ -> return () )
wrap
-- | Moves the current window to the next screen in the given direction. The
-- second argument indicates wrapping (see 'windowGo').
windowToScreen :: Direction2D -> Bool -> X ()
windowToScreen dir wrap = actOnScreens ( \ conf cur wspcs -> windows
windowToScreen dir = actOnScreens ( \ conf cur wspcs -> windows
$ doScreenNavigation conf dir W.shift cur wspcs
)
wrap
-- | Moves the focus to the next screen in the given direction. The second
-- argument indicates wrapping (see 'windowGo').
screenGo :: Direction2D -> Bool -> X ()
screenGo dir wrap = actOnScreens ( \ conf cur wspcs -> windows
screenGo dir = actOnScreens ( \ conf cur wspcs -> windows
$ doScreenNavigation conf dir W.view cur wspcs
)
wrap
-- | Swaps the workspace on the current screen with the workspace on the screen
-- in the given direction. The second argument indicates wrapping (see
-- 'windowGo').
screenSwap :: Direction2D -> Bool -> X ()
screenSwap dir wrap = actOnScreens ( \ conf cur wspcs -> windows
screenSwap dir = actOnScreens ( \ conf cur wspcs -> windows
$ doScreenNavigation conf dir W.greedyView cur wspcs
)
wrap
-- | Maps each window to a fullscreen rect. This may not be the same rectangle the
-- window maps to under the Full layout or a similar layout if the layout
@@ -488,11 +630,8 @@ actOnScreens act wrap = withWindowSet $ \winset -> do
-- | Determines whether a given window is mapped
isMapped :: Window -> X Bool
isMapped win = withDisplay
$ \dpy -> io
$ (waIsUnmapped /=)
. wa_map_state
<$> getWindowAttributes dpy win
isMapped = fmap (maybe False ((waIsUnmapped /=) . wa_map_state))
. safeGetWindowAttributes
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
@@ -516,7 +655,7 @@ doFocusClosestWindow (cur, rect) winrects
where
ctr = centerOf rect
winctrs = filter ((cur /=) . fst)
$ map (\(w, r) -> (w, centerOf r)) winrects
$ map (second centerOf) winrects
closer wc1@(_, c1) wc2@(_, c2) | lDist ctr c1 > lDist ctr c2 = wc2
| otherwise = wc1
@@ -536,8 +675,7 @@ doTiledNavigation conf dir act cur winrects winset
nav = maximum
$ map ( fromMaybe (defaultTiledNavigation conf)
. flip L.lookup (layoutNavigation conf)
)
$ layouts
) layouts
-- | Implements navigation for the float layer
doFloatNavigation :: Navigation2DConfig
@@ -582,7 +720,7 @@ doLineNavigation dir (cur, rect) winrects
-- The list of windows that are candidates to receive focus.
winrects' = filter dirFilter
$ filter ((cur /=) . fst)
. filter ((cur /=) . fst)
$ winrects
-- Decides whether a given window matches the criteria to be a candidate to
@@ -623,9 +761,8 @@ doCenterNavigation dir (cur, rect) winrects
-- center rotated so the right cone becomes the relevant cone.
-- The windows are ordered in the order they should be preferred
-- when they are otherwise tied.
winctrs = map (\(w, r) -> (w, dirTransform . centerOf $ r))
$ stackTransform
$ winrects
winctrs = map (second (dirTransform . centerOf))
$ stackTransform winrects
-- Give preference to windows later in the stack for going left or up and to
-- windows earlier in the stack for going right or down. (The stack order
@@ -647,8 +784,7 @@ doCenterNavigation dir (cur, rect) winrects
-- All the points that coincide with the current center and succeed it
-- in the (appropriately ordered) window stack.
onCtr' = L.tail $ L.dropWhile ((cur /=) . fst) onCtr
-- tail should be safe here because cur should be in onCtr
onCtr' = L.drop 1 $ L.dropWhile ((cur /=) . fst) onCtr
-- All the points that do not coincide with the current center and which
-- lie in the (rotated) right cone.
@@ -668,6 +804,54 @@ doCenterNavigation dir (cur, rect) winrects
-- or it has the same distance but comes later
-- in the window stack
-- x -y w h format is a pain. Let's use side coordinates. We assume x1 <= x2 and
-- y1 <= y2, and make the assumption valid by initialising SideRects with the
-- property and carefully preserving it over any individual transformation.
data SideRect = SideRect { x1 :: Int, x2 :: Int, y1 :: Int, y2 :: Int }
deriving Show
-- Conversion from Rectangle format to SideRect.
toSR :: Rectangle -> SideRect
toSR (Rectangle x y w h) = SideRect (fi x) (fi x + fi w) (-fi y - fi h) (-fi y)
-- Implements side navigation with bias.
doSideNavigationWithBias ::
Eq a => Int -> Direction2D -> Rect a -> [Rect a] -> Maybe a
doSideNavigationWithBias bias dir (cur, rect)
= fmap fst . listToMaybe
. L.sortOn dist . foldr acClosest []
. filter (`toRightOf` (cur, transform rect))
. map (fmap transform)
where
-- Getting the center of the current window so we can make it the new origin.
cOf r = ((x1 r + x2 r) `div` 2, (y1 r + y2 r) `div` 2)
(x0, y0) = cOf . toSR $ rect
-- Translate the given SideRect by (-x0, -y0).
translate r = SideRect (x1 r - x0) (x2 r - x0) (y1 r - y0) (y2 r - y0)
-- Rotate the given SideRect 90 degrees counter-clockwise about the origin.
rHalfPiCC r = SideRect (-y2 r) (-y1 r) (x1 r) (x2 r)
-- Apply the above function until d becomes synonymous with R (wolog).
rotateToR d = fromJust . lookup d . zip [R, D, L, U] . iterate rHalfPiCC
transform = rotateToR dir . translate . toSR
-- (_, r) `toRightOf` (_, c) iff r has points to the right of c that aren't
-- below or above c, i.e. iff:
-- [x1 r, x2 r] x [y1 r, y2 r] intersects (x2 c, infinity) x (y1 c, y2 c)
toRightOf (_, r) (_, c) = (x2 r > x2 c) && (y2 r > y1 c) && (y1 r < y2 c)
-- Greedily accumulate the windows tied for the leftmost left side.
acClosest (w, r) l@((_, r'):_) | x1 r == x1 r' = (w, r) : l
| x1 r > x1 r' = l
acClosest (w, r) _ = [(w, r)]
-- Given a (_, SideRect), calculate how far it is from the y=bias line.
dist (_, r) | (y1 r <= bias) && (bias <= y2 r) = 0
| otherwise = min (abs $ y1 r - bias) (abs $ y2 r - bias)
-- | Swaps the current window with the window given as argument
swap :: Window -> WindowSet -> WindowSet
swap win winset = W.focusWindow cur
@@ -683,7 +867,7 @@ swap win winset = W.focusWindow cur
visws = map W.workspace scrs
-- The focused windows of the visible workspaces
focused = mapMaybe (\ws -> W.focus <$> W.stack ws) visws
focused = mapMaybe (fmap W.focus . W.stack) visws
-- The window lists of the visible workspaces
wins = map (W.integrate' . W.stack) visws
@@ -700,22 +884,18 @@ swap win winset = W.focusWindow cur
-- Reconstruct the workspaces' window stacks to reflect the swap.
newvisws = zipWith (\ws wns -> ws { W.stack = W.differentiate wns }) visws newwins
newscrs = zipWith (\scr ws -> scr { W.workspace = ws }) scrs newvisws
newwinset = winset { W.current = head newscrs
, W.visible = tail newscrs
newwinset = winset { W.current = NE.head (notEmpty newscrs) -- Always at least one screen.
, W.visible = drop 1 newscrs
}
-- | Calculates the center of a rectangle
centerOf :: Rectangle -> (Position, Position)
centerOf r = (rect_x r + fi (rect_width r) `div` 2, rect_y r + fi (rect_height r) `div` 2)
-- | Shorthand for integer conversions
fi :: (Integral a, Num b) => a -> b
fi = fromIntegral
-- | Functions to choose the subset of windows to operate on
thisLayer, otherLayer :: a -> a -> a
thisLayer = curry fst
otherLayer = curry snd
thisLayer = const
otherLayer _ x = x
-- | Returns the list of visible workspaces and their screen rects
visibleWorkspaces :: WindowSet -> Bool -> [WSRect]
@@ -752,8 +932,8 @@ wrapOffsets winset = (max_x - min_x, max_y - min_y)
where
min_x = fi $ minimum $ map rect_x rects
min_y = fi $ minimum $ map rect_y rects
max_x = fi $ maximum $ map (\r -> rect_x r + (fi $ rect_width r)) rects
max_y = fi $ maximum $ map (\r -> rect_y r + (fi $ rect_height r)) rects
max_x = fi $ maximum $ map (\r -> rect_x r + fi (rect_width r)) rects
max_y = fi $ maximum $ map (\r -> rect_y r + fi (rect_height r)) rects
rects = map snd $ visibleWorkspaces winset False
@@ -763,16 +943,16 @@ sortedScreens :: WindowSet -> [Screen]
sortedScreens winset = L.sortBy cmp
$ W.screens winset
where
cmp s1 s2 | x1 < x2 = LT
| x1 > x2 = GT
| y1 < x2 = LT
| y1 > y2 = GT
cmp s1 s2 | x < x' = LT
| x > x' = GT
| y < x' = LT
| y > y' = GT
| otherwise = EQ
where
(x1, y1) = centerOf (screenRect . W.screenDetail $ s1)
(x2, y2) = centerOf (screenRect . W.screenDetail $ s2)
(x , y ) = centerOf (screenRect . W.screenDetail $ s1)
(x', y') = centerOf (screenRect . W.screenDetail $ s2)
-- | Calculates the L1-distance between two points.
lDist :: (Position, Position) -> (Position, Position) -> Int
lDist (x1, y1) (x2, y2) = abs (fi $ x1 - x2) + abs (fi $ y1 - y2)
lDist (x, y) (x', y') = abs (fi $ x - x') + abs (fi $ y - y')

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.NoBorders
-- Description : Helper functions for dealing with window borders.
-- Copyright : (c) Lukas Mai
-- License : BSD3-style (see LICENSE)
--
@@ -26,8 +27,7 @@ import XMonad
toggleBorder :: Window -> X ()
toggleBorder w = do
bw <- asks (borderWidth . config)
withDisplay $ \d -> io $ do
cw <- wa_border_width `fmap` getWindowAttributes d w
if cw == 0
withDisplay $ \d -> withWindowAttributes d w $ \wa -> io $
if wa_border_width wa == 0
then setWindowBorderWidth d w bw
else setWindowBorderWidth d w 0

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.OnScreen
-- Description : Control workspaces on different screens (in xinerama mode).
-- Copyright : (c) 2009 Nils Schweinsberg
-- License : BSD3-style (see LICENSE)
--
@@ -26,12 +27,9 @@ module XMonad.Actions.OnScreen (
) where
import XMonad
import XMonad.Prelude (fromMaybe, guard, empty)
import XMonad.StackSet hiding (new)
import Control.Monad (guard)
-- import Control.Monad.State.Class (gets)
import Data.Maybe (fromMaybe)
-- | Focus data definitions
data Focus = FocusNew -- ^ always focus the new screen
@@ -142,16 +140,15 @@ toggleOrView' f i st = fromMaybe (f i st) $ do
let st' = hidden st
-- make sure we actually have to do something
guard $ i == (tag . workspace $ current st)
guard $ not (null st')
-- finally, toggle!
return $ f (tag . head $ st') st
case st' of
[] -> empty
(h : _) -> return $ f (tag h) st -- finally, toggle!
-- $usage
--
-- This module provides an easy way to control, what you see on other screens in
-- xinerama mode without having to focus them. Put this into your
-- @~\/.xmonad\/xmonad.hs@:
-- @xmonad.hs@:
--
-- > import XMonad.Actions.OnScreen
--
@@ -185,4 +182,4 @@ toggleOrView' f i st = fromMaybe (f i st) $ do
-- where 0 is the first screen and \"1\" the workspace with the tag \"1\".
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

View File

@@ -0,0 +1,49 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.PerLayoutKeys
-- Description : Define key-bindings on per-layout basis.
-- Copyright : (c) brandon s allbery kf8nh 2022, Roman Cheplyaka, 2008
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : brandon s allbery kf8ng <allbery.b@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Define key-bindings on per-layout basis.
--
-----------------------------------------------------------------------------
module XMonad.Actions.PerLayoutKeys (
-- * Usage
-- $usage
chooseActionByLayout,
bindByLayout
) where
import XMonad
import XMonad.StackSet as S
-- $usage
--
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.PerLayoutKeys
--
-- > ,((0, xK_F2), bindByLayout [("Tall", spawn "rxvt"), ("Mirror Tall", spawn "xeyes"), ("", spawn "xmessage hello")])
--
-- For detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Uses supplied function to decide which action to run depending on current layout name.
chooseActionByLayout :: (String->X()) -> X()
chooseActionByLayout f = withWindowSet (f . description . S.layout. S.workspace . S.current)
-- | If current layout is listed, run appropriate action (only the first match counts!)
-- If it isn't listed, then run default action (marked with empty string, \"\"), or do nothing if default isn't supplied.
bindByLayout :: [(String, X())] -> X()
bindByLayout bindings = chooseActionByLayout chooser where
chooser l = case lookup l bindings of
Just action -> action
Nothing -> case lookup "" bindings of
Just action -> action
Nothing -> return ()

View File

@@ -0,0 +1,61 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.PerWindowKeys
-- Description : Define key-bindings on a per-window basis.
-- Copyright : (c) Wilson Sales, 2019
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Wilson Sales <spoonm@spoonm.org>
-- Stability : unstable
-- Portability : unportable
--
-- Define key-bindings on a per-window basis.
--
-----------------------------------------------------------------------------
module XMonad.Actions.PerWindowKeys (
-- * Usage
-- $usage
bindAll,
bindFirst
) where
import XMonad
-- $usage
--
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.PerWindowKeys
--
-- > ,((0, xK_F2), bindFirst [(className =? "firefox", spawn "dmenu"), (isFloat, withFocused $ windows . W.sink)])
--
-- > ,((0, xK_F3), bindAll [(isDialog, kill), (pure True, doSomething)])
--
-- If you want an action that will always run, but also want to do something for
-- other queries, you can use @'bindAll' [(query1, action1), ..., (pure True,
-- alwaysDoThisAction)]@.
--
-- Similarly, if you want a default action to be run if all the others failed,
-- you can use @'bindFirst' [(query1, action1), ..., (pure True,
-- doThisIfTheOthersFail)]@.
--
-- For detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Run an action if a Query holds true. Doesn't stop at the first one that
-- does, however, and could potentially run all actions.
bindAll :: [(Query Bool, X ())] -> X ()
bindAll = mapM_ choose where
choose (mh,action) = withFocused $ \w -> whenX (runQuery mh w) action
-- | Run the action paired with the first Query that holds true.
bindFirst :: [(Query Bool, X ())] -> X ()
bindFirst = withFocused . chooseOne
chooseOne :: [(Query Bool, X ())] -> Window -> X ()
chooseOne [] _ = return ()
chooseOne ((mh,a):bs) w = do
c <- runQuery mh w
if c then a
else chooseOne bs w

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.PerWorkspaceKeys
-- Description : Define key-bindings on per-workspace basis.
-- Copyright : (c) Roman Cheplyaka, 2008
-- License : BSD3-style (see LICENSE)
--
@@ -24,14 +25,14 @@ import XMonad.StackSet as S
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.PerWorkspaceKeys
--
-- > ,((0, xK_F2), bindOn [("1", spawn "rxvt"), ("2", spawn "xeyes"), ("", spawn "xmessage hello")])
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Uses supplied function to decide which action to run depending on current workspace name.
chooseAction :: (String->X()) -> X()
@@ -46,4 +47,3 @@ bindOn bindings = chooseAction chooser where
Nothing -> case lookup "" bindings of
Just action -> action
Nothing -> return ()

View File

@@ -2,6 +2,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.PhysicalScreens
-- Description : Manipulate screens ordered by physical location instead of ID.
-- Copyright : (c) Nelson Elhage <nelhage@mit.edu>
-- License : BSD
--
@@ -21,14 +22,18 @@ module XMonad.Actions.PhysicalScreens (
, sendToScreen
, onNextNeighbour
, onPrevNeighbour
, horizontalScreenOrderer
, verticalScreenOrderer
, ScreenComparator(ScreenComparator)
, getScreenIdAndRectangle
, screenComparatorById
, screenComparatorByRectangle
) where
import XMonad
import XMonad.Prelude (elemIndex, fromMaybe, on, sortBy)
import qualified XMonad.StackSet as W
import Data.List (sortBy,findIndex)
import Data.Function (on)
{- $usage
This module allows you name Xinerama screens from XMonad using their
@@ -36,17 +41,20 @@ physical location relative to each other (as reported by Xinerama),
rather than their @ScreenID@ s, which are arbitrarily determined by
your X server and graphics hardware.
Screens are ordered by the upper-left-most corner, from top-to-bottom
You can specify how to order the screen by giving a ScreenComparator.
To create a screen comparator you can use screenComparatorByRectangle or screenComparatorByScreenId.
The default ScreenComparator orders screens by the upper-left-most corner, from top-to-bottom
and then left-to-right.
Example usage in your @~\/.xmonad\/xmonad.hs@ file:
Example usage in your @xmonad.hs@ file:
> import XMonad.Actions.PhysicalScreens
> import Data.Default
> , ((modMask, xK_a), onPrevNeighbour W.view)
> , ((modMask, xK_o), onNextNeighbour W.view)
> , ((modMask .|. shiftMask, xK_a), onPrevNeighbour W.shift)
> , ((modMask .|. shiftMask, xK_o), onNextNeighbour W.shift)
> , ((modMask, xK_a), onPrevNeighbour def W.view)
> , ((modMask, xK_o), onNextNeighbour def W.view)
> , ((modMask .|. shiftMask, xK_a), onPrevNeighbour def W.shift)
> , ((modMask .|. shiftMask, xK_o), onNextNeighbour def W.shift)
> --
> -- mod-{w,e,r}, Switch to physical/Xinerama screens 1, 2, or 3
@@ -54,61 +62,87 @@ Example usage in your @~\/.xmonad\/xmonad.hs@ file:
> --
> [((modm .|. mask, key), f sc)
> | (key, sc) <- zip [xK_w, xK_e, xK_r] [0..]
> , (f, mask) <- [(viewScreen, 0), (sendToScreen, shiftMask)]]
> , (f, mask) <- [(viewScreen def, 0), (sendToScreen def, shiftMask)]]
For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings".
<https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-}
-- | The type of the index of a screen by location
newtype PhysicalScreen = P Int deriving (Eq,Ord,Show,Read,Enum,Num,Integral,Real)
-- | Translate a physical screen index to a "ScreenId"
getScreen :: PhysicalScreen -> X (Maybe ScreenId)
getScreen (P i) = do w <- gets windowset
let screens = W.current w : W.visible w
if i<0 || i >= length screens
then return Nothing
else let ss = sortBy (cmpScreen `on` (screenRect . W.screenDetail)) screens
in return $ Just $ W.screen $ ss !! i
getScreenIdAndRectangle :: W.Screen i l a ScreenId ScreenDetail -> (ScreenId, Rectangle)
getScreenIdAndRectangle screen = (W.screen screen, rect) where
rect = screenRect $ W.screenDetail screen
-- | Translate a physical screen index to a 'ScreenId'
getScreen:: ScreenComparator -> PhysicalScreen -> X (Maybe ScreenId)
getScreen (ScreenComparator cmpScreen) (P i) = do w <- gets windowset
let screens = W.current w : W.visible w
if i<0 || i >= length screens
then return Nothing
else let ss = sortBy (cmpScreen `on` getScreenIdAndRectangle) screens
in return $ Just $ W.screen $ ss !! i
-- | Switch to a given physical screen
viewScreen :: PhysicalScreen -> X ()
viewScreen p = do i <- getScreen p
whenJust i $ \s -> do
w <- screenWorkspace s
whenJust w $ windows . W.view
viewScreen :: ScreenComparator -> PhysicalScreen -> X ()
viewScreen sc p = do i <- getScreen sc p
whenJust i $ \s -> do
w <- screenWorkspace s
whenJust w $ windows . W.view
-- | Send the active window to a given physical screen
sendToScreen :: PhysicalScreen -> X ()
sendToScreen p = do i <- getScreen p
whenJust i $ \s -> do
w <- screenWorkspace s
whenJust w $ windows . W.shift
sendToScreen :: ScreenComparator -> PhysicalScreen -> X ()
sendToScreen sc p = do i <- getScreen sc p
whenJust i $ \s -> do
w <- screenWorkspace s
whenJust w $ windows . W.shift
-- | Compare two screens by their top-left corners, ordering
-- | top-to-bottom and then left-to-right.
cmpScreen :: Rectangle -> Rectangle -> Ordering
cmpScreen (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (y1,x1) (y2,x2)
-- | A ScreenComparator allow to compare two screen based on their coordonate and Xinerama Id
newtype ScreenComparator = ScreenComparator ((ScreenId, Rectangle) -> (ScreenId, Rectangle) -> Ordering)
-- | The default ScreenComparator orders screens by the upper-left-most corner, from top-to-bottom
instance Default ScreenComparator where
def= verticalScreenOrderer
-- | Compare screen only by their coordonate
screenComparatorByRectangle :: (Rectangle -> Rectangle -> Ordering) -> ScreenComparator
screenComparatorByRectangle rectComparator = ScreenComparator comparator where
comparator (_, rec1) (_, rec2) = rectComparator rec1 rec2
-- | Compare screen only by their Xinerama id
screenComparatorById :: (ScreenId -> ScreenId -> Ordering) -> ScreenComparator
screenComparatorById idComparator = ScreenComparator comparator where
comparator (id1, _) (id2, _) = idComparator id1 id2
-- | orders screens by the upper-left-most corner, from top-to-bottom
verticalScreenOrderer :: ScreenComparator
verticalScreenOrderer = screenComparatorByRectangle comparator where
comparator (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (y1, x1) (y2, x2)
-- | orders screens by the upper-left-most corner, from left-to-right
horizontalScreenOrderer :: ScreenComparator
horizontalScreenOrderer = screenComparatorByRectangle comparator where
comparator (Rectangle x1 y1 _ _) (Rectangle x2 y2 _ _) = compare (x1, y1) (x2, y2)
-- | Get ScreenId for neighbours of the current screen based on position offset.
getNeighbour :: Int -> X ScreenId
getNeighbour d = do w <- gets windowset
let ss = map W.screen $ sortBy (cmpScreen `on` (screenRect . W.screenDetail)) $ W.current w : W.visible w
curPos = maybe 0 id $ findIndex (== W.screen (W.current w)) ss
pos = (curPos + d) `mod` length ss
return $ ss !! pos
getNeighbour :: ScreenComparator -> Int -> X ScreenId
getNeighbour (ScreenComparator cmpScreen) d =
do w <- gets windowset
let ss = map W.screen $ sortBy (cmpScreen `on` getScreenIdAndRectangle) $ W.current w : W.visible w
curPos = fromMaybe 0 $ elemIndex (W.screen (W.current w)) ss
pos = (curPos + d) `mod` length ss
return $ ss !! pos
neighbourWindows :: Int -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
neighbourWindows d f = do s <- getNeighbour d
w <- screenWorkspace s
whenJust w $ windows . f
neighbourWindows :: ScreenComparator -> Int -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
neighbourWindows sc d f = do s <- getNeighbour sc d
w <- screenWorkspace s
whenJust w $ windows . f
-- | Apply operation on a WindowSet with the WorkspaceId of the next screen in the physical order as parameter.
onNextNeighbour :: (WorkspaceId -> WindowSet -> WindowSet) -> X ()
onNextNeighbour = neighbourWindows 1
onNextNeighbour :: ScreenComparator -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
onNextNeighbour sc = neighbourWindows sc 1
-- | Apply operation on a WindowSet with the WorkspaceId of the previous screen in the physical order as parameter.
onPrevNeighbour :: (WorkspaceId -> WindowSet -> WindowSet) -> X ()
onPrevNeighbour = neighbourWindows (-1)
onPrevNeighbour :: ScreenComparator -> (WorkspaceId -> WindowSet -> WindowSet) -> X ()
onPrevNeighbour sc = neighbourWindows sc (-1)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Plane
-- Description : Navigate through workspaces in a bidimensional manner.
-- Copyright : (c) Marco Túlio Gontijo e Silva <marcot@riseup.net>,
-- Leonardo Serra <leoserra@minaslivre.org>
-- License : BSD3-style (see LICENSE)
@@ -38,28 +39,27 @@ module XMonad.Actions.Plane
)
where
import Control.Monad
import Data.List
import Data.Map hiding (split)
import Data.Maybe
import Data.Map (Map, fromList)
import XMonad.Prelude hiding (fromList)
import XMonad
import XMonad.StackSet hiding (workspaces)
import XMonad.Util.Run
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.Plane
-- > import Data.Map (union)
-- >
-- > main = xmonad defaultConfig {keys = myKeys}
-- > main = xmonad def {keys = myKeys}
-- >
-- > myKeys conf = union (keys defaultConfig conf) $ myNewKeys conf
-- > myKeys conf = union (keys def conf) $ myNewKeys conf
-- >
-- > myNewkeys (XConfig {modMask = modm}) = planeKeys modm (Lines 3) Finite
-- > myNewKeys (XConfig {modMask = modm}) = planeKeys modm (Lines 3) Finite
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Direction to go in the plane.
data Direction = ToLeft | ToUp | ToRight | ToDown deriving Enum
@@ -226,4 +226,4 @@ gconftool :: String
gconftool = "gconftool-2"
parameters :: [String]
parameters = ["--get", "/apps/panel/applets/workspace_switcher_screen0/prefs/num_rows"]
parameters = ["--get", "/apps/panel/applets/workspace_switcher_screen0/prefs/num_rows"]

222
XMonad/Actions/Prefix.hs Normal file
View File

@@ -0,0 +1,222 @@
{-# LANGUAGE FlexibleContexts #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Prefix
-- Description : Use an Emacs-style prefix argument for commands.
-- Copyright : (c) Matus Goljer <matus.goljer@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Matus Goljer <matus.goljer@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- A module that allows the user to use a prefix argument (raw or numeric).
--
-----------------------------------------------------------------------------
module XMonad.Actions.Prefix
(
-- * Usage
-- $usage
-- * Installation
-- $installation
PrefixArgument(..)
, usePrefixArgument
, useDefaultPrefixArgument
, withPrefixArgument
, isPrefixRaw
, isPrefixNumeric
, orIfPrefixed
, ppFormatPrefix
) where
import qualified Data.Map as M
import XMonad.Prelude
import XMonad
import XMonad.Util.ExtensibleState as XS
import XMonad.Util.Paste (sendKey)
import XMonad.Actions.Submap (submapDefaultWithKey)
import XMonad.Util.EZConfig (readKeySequence)
import qualified Data.List.NonEmpty as NE
import Data.List.NonEmpty ((<|))
{- $usage
This module implements Emacs-style prefix argument. The argument
comes in two flavours, 'Raw' and 'Numeric'.
To initiate the "prefix mode" you hit the prefix keybinding (default
C-u). This sets the Raw argument value to 1. Repeatedly hitting this
key increments the raw value by 1. The Raw argument is usually used
as a toggle, changing the behaviour of the function called in some way.
An example might be calling "mpc add" to add new song to the playlist,
but with C-u we also clean up the playlist beforehand.
When in the "Raw mode", you can hit numeric keys 0..9 (with no
modifier) to enter a "Numeric argument". Numeric argument represents
a natural number. Hitting numeric keys in sequence produces the
decimal number that would result from typing them. That is, the
sequence C-u 4 2 sets the Numeric argument value to the number 42.
If you have a function which understands the prefix argument, for example:
> addMaybeClean :: PrefixArgument -> X ()
> addMaybeClean (Raw _) = spawn "mpc clear" >> spawn "mpc add <file>"
> addMaybeClean _ = spawn "mpc add <file>"
you can turn it into an X action with the function 'withPrefixArgument'.
Binding it in your config
> ((modm, xK_a), withPrefixArgument addMaybeClean)
Hitting MOD-a will add the @\<file\>@ to the playlist while C-u MOD-a will
clear the playlist and then add the file.
You can of course use an anonymous action, like so:
> ((modm, xK_a), withPrefixArgument $ \prefix -> do
> case prefix of ...
> )
If the prefix key is followed by a binding which is unknown to XMonad,
the prefix along with that binding is sent to the active window.
There is one caveat: when you use an application which has a nested
C-u binding, for example C-c C-u in Emacs org-mode, you have to hit
C-g (or any other non-recognized key really) to get out of the "xmonad
grab" and let the C-c C-u be sent to the application.
-}
{- $installation
The simplest way to enable this is to use 'useDefaultPrefixArgument'
> xmonad $ useDefaultPrefixArgument $ def { .. }
The default prefix argument is C-u. If you want to customize the
prefix argument, 'usePrefixArgument' can be used:
> xmonad $ usePrefixArgument "M-u" $ def { .. }
where the key is entered in Emacs style (or "XMonad.Util.EZConfig"
style) notation. The letter `M` stands for your chosen modifier. The
function defaults to C-u if the argument could not be parsed.
-}
data PrefixArgument = Raw Int | Numeric Int | None
deriving (Read, Show)
instance ExtensionClass PrefixArgument where
initialValue = None
extensionType = PersistentExtension
-- | Run 'job' in the 'X' monad and then execute 'cleanup'. In case
-- of exception, 'cleanup' is executed anyway.
--
-- Return the return value of 'job'.
finallyX :: X a -> X a -> X a
finallyX job cleanup = catchX (job >>= \r -> cleanup >> return r) cleanup
-- | Set up Prefix. Defaults to C-u when given an invalid key.
--
-- See usage section.
usePrefixArgument :: LayoutClass l Window
=> String
-> XConfig l
-> XConfig l
usePrefixArgument prefix conf =
conf{ keys = M.insert binding (handlePrefixArg (binding :| [])) . keys conf }
where
binding = case readKeySequence conf prefix of
Just (key :| []) -> key
_ -> (controlMask, xK_u)
-- | Set Prefix up with default prefix key (C-u).
useDefaultPrefixArgument :: LayoutClass l Window
=> XConfig l
-> XConfig l
useDefaultPrefixArgument = usePrefixArgument "C-u"
handlePrefixArg :: NonEmpty (KeyMask, KeySym) -> X ()
handlePrefixArg events = do
ks <- asks keyActions
logger <- asks (logHook . config)
flip finallyX (XS.put None >> logger) $ do
prefix <- XS.get
case prefix of
Raw a -> XS.put $ Raw (a + 1)
None -> XS.put $ Raw 1
_ -> return ()
logger
submapDefaultWithKey defaultKey ks
where defaultKey key@(m, k) =
if k `elem` (xK_0 : [xK_1 .. xK_9]) && m == noModMask
then do
prefix <- XS.get
let x = fromJust (Prelude.lookup k keyToNum)
case prefix of
Raw _ -> XS.put $ Numeric x
Numeric a -> XS.put $ Numeric $ a * 10 + x
None -> return () -- should never happen
handlePrefixArg (key <| events)
else do
prefix <- XS.get
mapM_ (uncurry sendKey) $ case prefix of
Raw a -> replicate a (NE.head events) ++ [key]
_ -> reverse (key : toList events)
keyToNum = (xK_0, 0) : zip [xK_1 .. xK_9] [1..9]
-- | Turn a prefix-aware X action into an X-action.
--
-- First, fetch the current prefix, then pass it as argument to the
-- original function. You should use this to "run" your commands.
withPrefixArgument :: (PrefixArgument -> X a) -> X a
withPrefixArgument = (>>=) XS.get
-- | Test if 'PrefixArgument' is 'Raw' or not.
isPrefixRaw :: PrefixArgument -> Bool
isPrefixRaw (Raw _) = True
isPrefixRaw _ = False
-- | Test if 'PrefixArgument' is 'Numeric' or not.
isPrefixNumeric :: PrefixArgument -> Bool
isPrefixNumeric (Numeric _) = True
isPrefixNumeric _ = False
-- | Execute the first action, unless any prefix argument is given,
-- in which case the second action is chosen instead.
--
-- > action1 `orIfPrefixed` action2
orIfPrefixed :: X a -> X a -> X a
orIfPrefixed xa xb = withPrefixArgument $ bool xa xb . isPrefixRaw
-- | Format the prefix using the Emacs convetion for use in a
-- statusbar, like xmobar.
--
-- To add this formatted prefix to printer output, you can set it up
-- like so
--
-- > myPrinter :: PP
-- > myPrinter = def { ppExtras = [ppFormatPrefix] }
--
-- And then add to your status bar using "XMonad.Hooks.StatusBar":
--
-- > mySB = statusBarProp "xmobar" myPrinter
-- > main = xmonad $ withEasySB mySB defToggleStrutsKey def
--
-- Or, directly in your 'logHook' configuration
--
-- > logHook = dynamicLogWithPP myPrinter
ppFormatPrefix :: X (Maybe String)
ppFormatPrefix = do
prefix <- XS.get
return $ case prefix of
Raw n -> Just $ foldr1 (\a b -> a ++ " " ++ b) $ replicate n "C-u"
Numeric n -> Just $ "C-u " ++ show n
None -> Nothing

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Promote
-- Description : Alternate promote function for xmonad.
-- Copyright : (c) Miikka Koskinen 2007
-- License : BSD3-style (see LICENSE)
--
@@ -27,7 +28,7 @@ import XMonad.StackSet
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.Promote
--
@@ -36,7 +37,7 @@ import XMonad.StackSet
-- > , ((modm, xK_Return), promote)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Move the focused window to the master pane. All other windows
-- retain their order. If focus is in the master, swap it with the

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.RandomBackground
-- Description : Start terminals with a random background color.
-- Copyright : (c) 2009 Anze Slosar
-- translation to Haskell by Adam Vogt
-- License : BSD3-style (see LICENSE)
@@ -24,7 +25,6 @@ module XMonad.Actions.RandomBackground (
import XMonad(X, XConf(config), XConfig(terminal), io, spawn,
MonadIO, asks)
import System.Random
import Control.Monad(liftM)
import Numeric(showHex)
-- $usage
@@ -55,7 +55,7 @@ randPermutation xs g = swap $ zip (randoms g) xs
-- | @randomBg'@ produces a random hex number in the form @'#xxyyzz'@
randomBg' :: (MonadIO m) => RandomColor -> m String
randomBg' (RGB l h) = io $ liftM (toHex . take 3 . randomRs (l,h)) newStdGen
randomBg' (RGB l h) = io $ fmap (toHex . take 3 . randomRs (l,h)) newStdGen
randomBg' (HSV s v) = io $ do
g <- newStdGen
let x = (^(2::Int)) $ fst $ randomR (0,sqrt $ pi / 3) g

View File

@@ -0,0 +1,84 @@
{-# LANGUAGE LambdaCase #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.RepeatAction
-- Description : Repeat the last performed action.
-- Copyright : (c) 2022 Martin Kozlovsky
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : <kozlovsky.m7@gmail.com>
-- Stability : unstable
-- Portability : not portable
--
-- Ability to repeat the last action.
--
-----------------------------------------------------------------------------
module XMonad.Actions.RepeatAction (
-- * Usage
-- $usage
rememberAction,
rememberActions,
repeatLast,
) where
import XMonad
import qualified XMonad.Util.ExtensibleState as XS
-- $usage
--
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.RepeatAction
--
-- Then join a dedicated key to run the last action with the rest of your
-- key bindings using the 'rememberActions':
--
-- > rememberActions (modm, xK_period) [((modm, xK_c), kill), …]
--
-- It can be also used in the same way for "XMonad.Util.EZConfig":
--
-- > rememberActions "M-." [("M-c", kill), …]
--
-- For example, if you use 'XMonad.Util.EZConfig.additionalKeysP',
--
-- > main = xmonad $ … $ def
-- > {
-- > …
-- > }
-- > `additionalKeysP` myKeys
--
-- you would adjust the call to 'XMonad.Util.EZConfig.additionalKeysP'
-- like so:
--
-- > `additionalKeysP` (rememberActions "M-." myKeys)
--
-- For more detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html the tutorial>.
newtype LastAction = LastAction { runLastAction :: X () }
instance ExtensionClass LastAction where
initialValue = LastAction $ pure ()
-- | Transforms an action into an action that can be remembered and repeated.
rememberAction :: X () -> X ()
rememberAction x = userCode x >>= \case
Nothing -> pure ()
Just () -> XS.put (LastAction x) -- Only remember action if nothing went wrong.
-- | Maps 'rememberAction' over a list of key bindings.
rememberActions' :: [(a, X ())] -> [(a, X ())]
rememberActions' = map (fmap rememberAction)
infixl 4 `rememberActions`
-- | Maps 'rememberAction' over a list of key bindings and adds a dedicated
-- key to repeat the last action.
rememberActions :: a -> [(a, X ())] -> [(a, X ())]
rememberActions key keyList = (key, repeatLast) : rememberActions' keyList
-- | Runs the last remembered action.
-- / Be careful not to include this action in the remembered actions! /
repeatLast :: X ()
repeatLast = XS.get >>= runLastAction

View File

@@ -0,0 +1,89 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Repeatable
-- Description : Actions you'd like to repeat.
-- Copyright : (c) 2022 L. S. Leary
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : @LSLeary (on github)
-- Stability : unstable
-- Portability : unportable
--
-- This module factors out the shared logic of "XMonad.Actions.CycleRecentWS",
-- "XMonad.Actions.CycleWorkspaceByScreen", "XMonad.Actions.CycleWindows" and
-- "XMonad.Actions.MostRecentlyUsed".
--
-- See the source of these modules for usage examples.
--
-----------------------------------------------------------------------------
module XMonad.Actions.Repeatable
( repeatable
, repeatableSt
, repeatableM
) where
-- mtl
import Control.Monad.State (StateT(..))
-- X11
import Graphics.X11.Xlib.Extras
-- xmonad
import XMonad
-- | An action that temporarily usurps and responds to key press/release events,
-- concluding when one of the modifier keys is released.
repeatable
:: [KeySym] -- ^ The list of 'KeySym's under the
-- modifiers used to invoke the action.
-> KeySym -- ^ The keypress that invokes the action.
-> (EventType -> KeySym -> X ()) -- ^ The keypress handler.
-> X ()
repeatable = repeatableM id
-- | A more general variant of 'repeatable' with a stateful handler,
-- accumulating a monoidal return value throughout the events.
repeatableSt
:: Monoid a
=> s -- ^ Initial state.
-> [KeySym] -- ^ The list of 'KeySym's under the
-- modifiers used to invoke the
-- action.
-> KeySym -- ^ The keypress that invokes the
-- action.
-> (EventType -> KeySym -> StateT s X a) -- ^ The keypress handler.
-> X (a, s)
repeatableSt iSt = repeatableM $ \m -> runStateT m iSt
-- | A more general variant of 'repeatable' with an arbitrary monadic handler,
-- accumulating a monoidal return value throughout the events.
repeatableM
:: (MonadIO m, Monoid a)
=> (m a -> X b) -- ^ How to run the monad in 'X'.
-> [KeySym] -- ^ The list of 'KeySym's under the
-- modifiers used to invoke the action.
-> KeySym -- ^ The keypress that invokes the action.
-> (EventType -> KeySym -> m a) -- ^ The keypress handler.
-> X b
repeatableM run mods key pressHandler = do
XConf{ theRoot = root, display = d } <- ask
run (repeatableRaw d root mods key pressHandler)
repeatableRaw
:: (MonadIO m, Monoid a)
=> Display -> Window
-> [KeySym] -> KeySym -> (EventType -> KeySym -> m a) -> m a
repeatableRaw d root mods key pressHandler = do
io (grabKeyboard d root False grabModeAsync grabModeAsync currentTime)
handleEvent (keyPress, key) <* io (ungrabKeyboard d currentTime)
where
getNextEvent = io $ allocaXEvent $ \p -> do
maskEvent d (keyPressMask .|. keyReleaseMask) p
KeyEvent{ ev_event_type = t, ev_keycode = c } <- getEvent p
s <- keycodeToKeysym d c 0
return (t, s)
handleEvent (t, s)
| t == keyRelease && s `elem` mods = pure mempty
| otherwise = (<>) <$> pressHandler t s <*> (getNextEvent >>= handleEvent)

View File

@@ -1,6 +1,9 @@
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.RotSlaves
-- Description : Rotate all windows except the master window and keep the focus in place.
-- Copyright : (c) Hans Philipp Annen <haphi@gmx.net>, Mischa Dieterle <der_m@freenet.de>
-- License : BSD3-style (see LICENSE)
--
@@ -14,11 +17,16 @@
module XMonad.Actions.RotSlaves (
-- $usage
rotSlaves', rotSlavesUp, rotSlavesDown,
rotAll', rotAllUp, rotAllDown
rotAll', rotAllUp, rotAllDown,
-- * Generic list rotations
-- $generic
rotUp, rotDown
) where
import XMonad.StackSet
import XMonad
import XMonad.StackSet
import XMonad.Prelude
-- $usage
--
@@ -35,28 +43,37 @@ import XMonad
-- TwoPane layout (see "XMonad.Layout.TwoPane").
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Rotate the windows in the current stack, excluding the first one
-- (master).
rotSlavesUp,rotSlavesDown :: X ()
rotSlavesUp = windows $ modify' (rotSlaves' (\l -> (tail l)++[head l]))
rotSlavesDown = windows $ modify' (rotSlaves' (\l -> [last l]++(init l)))
rotSlavesUp = windows $ modify' (rotSlaves' rotUp)
rotSlavesDown = windows $ modify' (rotSlaves' rotDown)
-- | The actual rotation, as a pure function on the window stack.
rotSlaves' :: ([a] -> [a]) -> Stack a -> Stack a
rotSlaves' _ s@(Stack _ [] []) = s
rotSlaves' f (Stack t [] rs) = Stack t [] (f rs) -- Master has focus
rotSlaves' f s@(Stack _ ls _ ) = Stack t' (reverse revls') rs' -- otherwise
where (master:ws) = integrate s
(revls',t':rs') = splitAt (length ls) (master:(f ws))
where (notEmpty -> master :| ws) = integrate s
(revls', notEmpty -> t' :| rs') = splitAt (length ls) (master:f ws)
-- | Rotate all the windows in the current stack.
rotAllUp,rotAllDown :: X ()
rotAllUp = windows $ modify' (rotAll' (\l -> (tail l)++[head l]))
rotAllDown = windows $ modify' (rotAll' (\l -> [last l]++(init l)))
rotAllUp = windows $ modify' (rotAll' rotUp)
rotAllDown = windows $ modify' (rotAll' rotDown)
-- | The actual rotation, as a pure function on the window stack.
rotAll' :: ([a] -> [a]) -> Stack a -> Stack a
rotAll' f s = Stack r (reverse revls) rs
where (revls,r:rs) = splitAt (length (up s)) (f (integrate s))
where (revls, notEmpty -> r :| rs) = splitAt (length (up s)) (f (integrate s))
-- $generic
-- Generic list rotations such that @rotUp [1..4]@ is equivalent to
-- @[2,3,4,1]@ and @rotDown [1..4]@ to @[4,1,2,3]@. They both are
-- @id@ for null or singleton lists.
rotUp :: [a] -> [a]
rotUp l = drop 1 l ++ take 1 l
rotDown :: [a] -> [a]
rotDown = reverse . rotUp . reverse

View File

@@ -0,0 +1,163 @@
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.RotateSome
-- Description : Rotate some elements around the stack.
-- Copyright : (c) 2020 Ivan Brennan <ivanbrennan@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Ivan Brennan <ivanbrennan@gmail.com>
-- Stability : stable
-- Portability : unportable
--
-- Functions for rotating some elements around the stack while keeping others
-- anchored in place. Useful in combination with layouts that dictate window
-- visibility based on stack position, such as "XMonad.Layout.LimitWindows".
--
-----------------------------------------------------------------------------
module XMonad.Actions.RotateSome (
-- * Usage
-- $usage
-- * Example
-- $example
surfaceNext,
surfacePrev,
rotateSome,
) where
import Control.Arrow ((***))
import XMonad.Prelude (NonEmpty(..), notEmpty, partition, sortOn, (\\))
import qualified Data.Map as M
import XMonad (Window, WindowSpace, Rectangle, X, runLayout, screenRect, windows, withWindowSet)
import XMonad.StackSet (Screen (Screen), Stack (Stack), current, floating, modify', stack)
import XMonad.Util.Stack (reverseS)
{- $usage
You can use this module with the following in your @xmonad.hs@:
> import XMonad.Actions.RotateSome
and add keybindings such as the following:
> , ((modMask .|. controlMask, xK_n), surfaceNext)
> , ((modMask .|. controlMask, xK_p), surfacePrev)
-}
{- $example
#Example#
Consider a workspace whose stack contains five windows A B C D E but whose
layout limits how many will actually be shown, showing only the first plus
two additional windows, starting with the third:
> ┌─────┬─────┐
> │ │ C │
> │ A ├─────┤
> │ │ D │
> └─────┴─────┘
>
> A B C D E
> _ ____
If C has focus and we'd like to replace it with one of the unshown windows,
'surfaceNext' will move the next unshown window, E, into the focused position:
> ┌─────┬─────┐ ┌─────┬─────┐
> │ │ *C* │ │ │ *E* │
> │ A ├─────┤ surfaceNext -> │ A ├─────┤
> │ │ D │ │ │ D │
> └─────┴─────┘ └─────┴─────┘
>
> A B *C* D E A C *E* D B
> _ ____ _ ____
This repositioned windows B C E by treating them as a sequence that can be
rotated through the focused stack position. Windows A and D remain anchored
to their original (visible) positions.
A second call to 'surfaceNext' moves B into focus:
> ┌─────┬─────┐ ┌─────┬─────┐
> │ │ *E* │ │ │ *B* │
> │ A ├─────┤ surfaceNext -> │ A ├─────┤
> │ │ D │ │ │ D │
> └─────┴─────┘ └─────┴─────┘
>
> A C *E* D B A E *B* D C
> _ ____ _ ____
A third call would complete the cycle, bringing C back into focus.
-}
-- |
-- Treating the focused window and any unshown windows as a ring that can be
-- rotated through the focused position, surface the next element in the ring.
surfaceNext :: X ()
surfaceNext = do
ring <- surfaceRing
windows . modify' $ rotateSome (`elem` ring)
-- | Like 'surfaceNext' in reverse.
surfacePrev :: X ()
surfacePrev = do
ring <- surfaceRing
windows . modify' $ reverseS . rotateSome (`elem` ring) . reverseS
-- |
-- Return a list containing the current focus plus any unshown windows. Note
-- that windows are shown if 'runLayout' provides them with a rectangle or if
-- they are floating.
surfaceRing :: X [Window]
surfaceRing = withWindowSet $ \wset -> do
let Screen wsp _ sd = current wset
case stack wsp >>= filter' (`M.notMember` floating wset) of
Nothing -> pure []
Just st -> go st <$> layoutWindows wsp {stack = Just st} (screenRect sd)
where
go :: Stack Window -> [Window] -> [Window]
go (Stack t ls rs) shown = t : ((ls ++ rs) \\ shown)
layoutWindows :: WindowSpace -> Rectangle -> X [Window]
layoutWindows wsp rect = map fst . fst <$> runLayout wsp rect
-- | Like "XMonad.StackSet.filter" but won't move focus.
filter' :: (a -> Bool) -> Stack a -> Maybe (Stack a)
filter' p (Stack f ls rs)
| p f = Just $ Stack f (filter p ls) (filter p rs)
| otherwise = Nothing
-- |
-- @'rotateSome' p stack@ treats the elements of @stack@ that satisfy predicate
-- @p@ as a ring that can be rotated, while all other elements remain anchored
-- in place.
rotateSome :: (a -> Bool) -> Stack a -> Stack a
rotateSome p (Stack t ls rs) =
let
-- Flatten the stack, index each element relative to the focused position,
-- then partition into movable and anchored elements.
(movables, anchors) =
partition (p . snd) $
zip
[negate (length ls)..]
(reverse ls ++ t : rs)
-- Pair each movable element with the index of its next movable neighbor.
-- Append anchored elements, along with their unchanged indices, and sort
-- by index. Separate lefts (negative indices) from the rest, and grab the
-- new focus from the head of the remaining elements.
(ls', notEmpty -> t' :| rs') =
(map snd *** map snd)
. span ((< 0) . fst)
. sortOn fst
. (++) anchors
$ zipWith (curry (fst *** snd)) movables (rotate movables)
in
Stack t' (reverse ls') rs'
rotate :: [a] -> [a]
rotate = uncurry (flip (++)) . splitAt 1

View File

@@ -1,4 +1,6 @@
{- | Module : XMonad.Actions.Search
{- |
Module : XMonad.Actions.Search
Description : Easily run Internet searches on web sites through xmonad.
Copyright : (C) 2007 Gwern Branwen
License : None; public domain
@@ -18,6 +20,7 @@ module XMonad.Actions.Search ( -- * Usage
searchEngineF,
promptSearch,
promptSearchBrowser,
promptSearchBrowser',
selectSearch,
selectSearchBrowser,
isPrefixOf,
@@ -28,29 +31,50 @@ module XMonad.Actions.Search ( -- * Usage
prefixAware,
namedEngine,
amazon,
alpha,
amazon,
arXiv,
aur,
clojureDocs,
codesearch,
cratesIo,
deb,
debbts,
debpts,
dictionary,
duckduckgo,
ebay,
flora,
github,
google,
hackage,
homeManager,
hoogle,
images,
imdb,
isohunt,
lucky,
maps,
mathworld,
ncatlab,
nixos,
noogle,
openstreetmap,
protondb,
rosettacode,
rustStd,
scholar,
sourcehut,
stackage,
steam,
thesaurus,
vocabulary,
voidpgks_x86_64,
voidpgks_x86_64_musl,
wayback,
wikipedia,
wiktionary,
youtube,
zbmath,
multi,
-- * Use case: searching with a submap
-- $tip
@@ -59,15 +83,16 @@ module XMonad.Actions.Search ( -- * Usage
Browser, Site, Query, Name, Search
) where
import Codec.Binary.UTF8.String (encode)
import Data.Char (isAlphaNum, isAscii)
import Data.List (isPrefixOf)
import Text.Printf
import XMonad (X(), MonadIO, liftIO)
import XMonad.Prompt (XPrompt(showXPrompt, nextCompletion, commandToComplete), mkXPrompt, XPConfig(), historyCompletionP, getNextCompletion)
import XMonad.Prompt.Shell (getBrowser)
import XMonad.Util.Run (safeSpawn)
import XMonad.Util.XSelection (getSelection)
import Codec.Binary.UTF8.String (encode)
import Text.Printf
import XMonad (X (), liftIO)
import XMonad.Prompt (XPConfig (), XPrompt (showXPrompt, nextCompletion, commandToComplete),
getNextCompletion,
historyCompletionP, mkXPrompt)
import XMonad.Prelude (isAlphaNum, isAscii, isPrefixOf)
import XMonad.Prompt.Shell (getBrowser)
import XMonad.Util.Run (safeSpawn)
import XMonad.Util.XSelection (getSelection)
{- $usage
@@ -94,12 +119,20 @@ import XMonad.Util.XSelection (getSelection)
The currently available search engines are:
* 'amazon' -- Amazon keyword search.
* 'alpha' -- Wolfram|Alpha query.
* 'amazon' -- Amazon keyword search.
* 'arXiv' -- Open-access preprint archive.
* 'aur' -- Arch User Repository.
* 'clojureDocs' -- Documentation and examples repository for Clojure.
* 'codesearch' -- Google Labs Code Search search.
* 'cratesIo' -- Rust crate registry.
* 'deb' -- Debian package search.
* 'debbts' -- Debian Bug Tracking System.
@@ -108,36 +141,72 @@ import XMonad.Util.XSelection (getSelection)
* 'dictionary' -- dictionary.reference.com search.
* 'duckduckgo' -- DuckDuckGo search engine.
* 'ebay' -- Ebay keyword search.
* 'flora' -- Prettier Haskell package database.
* 'github' -- GitHub keyword search.
* 'google' -- basic Google search.
* 'hackage' -- Hackage, the Haskell package database.
* 'homeManager' -- Search Nix's home-manager's options.
* 'hoogle' -- Hoogle, the Haskell libraries API search engine.
* 'images' -- Google images.
* 'imdb' -- the Internet Movie Database.
* 'isohunt' -- isoHunt search.
* 'lucky' -- Google "I'm feeling lucky" search.
* 'maps' -- Google maps.
* 'mathworld' -- Wolfram MathWorld search.
* 'ncatlab' -- Higer Algebra, Homotopy and Category Theory Wiki.
* 'nixos' -- Search NixOS packages and options.
* 'noogle' -- 'hoogle'-like Nix API search engine.
* 'openstreetmap' -- OpenStreetMap free wiki world map.
* 'protondb' -- Steam Proton Game Database.
* 'rosettacode' -- Programming chrestomathy wiki.
* 'rustStd' -- Rust standard library documentation.
* 'scholar' -- Google scholar academic search.
* 'thesaurus' -- thesaurus.reference.com search.
* 'sourcehut' -- Sourcehut projects search.
* 'stackage' -- Stackage, An alternative Haskell libraries API search engine.
* 'steam' -- Steam games search.
* 'thesaurus' -- thesaurus.com search.
* 'vocabulary' -- Dictionary search.
* 'voidpgks_x86_64' -- Void Linux packages search for @x86_64@.
* 'voidpgks_x86_64_musl' -- Void Linux packages search for @x86_64-musl@.
* 'wayback' -- the Wayback Machine.
* 'wikipedia' -- basic Wikipedia search.
* 'wiktionary' -- Wiktionary search.
* 'youtube' -- Youtube video search.
* 'zbmath' -- Open alternative to MathSciNet.
* 'multi' -- Search based on the prefix. \"amazon:Potter\" will use amazon, etc. With no prefix searches google.
Feel free to add more! -}
@@ -157,7 +226,7 @@ Then add the following to your key bindings:
> ...
> -- Search commands
> , ((modm, xK_s), SM.submap $ searchEngineMap $ S.promptSearch P.defaultXPConfig)
> , ((modm, xK_s), SM.submap $ searchEngineMap $ S.promptSearch P.def)
> , ((modm .|. shiftMask, xK_s), SM.submap $ searchEngineMap $ S.selectSearch)
>
> ...
@@ -173,14 +242,14 @@ Or in combination with XMonad.Util.EZConfig:
> ...
> ] -- end of regular keybindings
> -- Search commands
> ++ [("M-s " ++ k, S.promptSearch P.defaultXPConfig f) | (k,f) <- searchList ]
> ++ [("M-s " ++ k, S.promptSearch P.def f) | (k,f) <- searchList ]
> ++ [("M-S-s " ++ k, S.selectSearch f) | (k,f) <- searchList ]
>
> ...
>
> searchList :: [(String, S.SearchEngine)]
> searchList = [ ("g", S.google)
> , ("h", S.hoohle)
> , ("h", S.hoogle)
> , ("w", S.wikipedia)
> ]
@@ -199,7 +268,7 @@ engine.
Happy searching! -}
-- | A customized prompt indicating we are searching, and the name of the site.
data Search = Search Name
newtype Search = Search Name
instance XPrompt Search where
showXPrompt (Search name)= "Search [" ++ name ++ "]: "
nextCompletion _ = getNextCompletion
@@ -237,7 +306,7 @@ search browser site query = safeSpawn browser [site query]
appends it to the base. You can easily define a new engine locally using
exported functions without needing to modify "XMonad.Actions.Search":
> myNewEngine = searchEngine "site" "http://site.com/search="
> myNewEngine = searchEngine "site" "https://site.com/search="
The important thing is that the site has a interface which accepts the escaped query
string as part of the URL. Alas, the exact URL to feed searchEngine varies
@@ -246,21 +315,21 @@ search browser site query = safeSpawn browser [site query]
Generally, examining the resultant URL of a search will allow you to reverse-engineer
it if you can't find the necessary URL already described in other projects such as Surfraw. -}
searchEngine :: Name -> String -> SearchEngine
searchEngine name site = searchEngineF name (\s -> site ++ (escape s))
searchEngine name site = searchEngineF name (\s -> site ++ escape s)
{- | If your search engine is more complex than this (you may want to identify
the kind of input and make the search URL dependent on the input or put the query
inside of a URL instead of in the end) you can use the alternative 'searchEngineF' function.
> searchFunc :: String -> String
> searchFunc s | "wiki:" `isPrefixOf` s = "http://en.wikipedia.org/wiki/" ++ (escape $ tail $ snd $ break (==':') s)
> | "http://" `isPrefixOf` s = s
> | otherwise = (use google) s
> searchFunc s | "wiki:" `isPrefixOf` s = "https://en.wikipedia.org/wiki/" ++ (escape $ drop 1 $ snd $ break (==':') s)
> | "https://" `isPrefixOf` s = s
> | otherwise = (use google) s
> myNewEngine = searchEngineF "mymulti" searchFunc
@searchFunc@ here searches for a word in wikipedia if it has a prefix
of \"wiki:\" (you can use the 'escape' function to escape any forbidden characters), opens an address
directly if it starts with \"http:\/\/\" and otherwise uses the provided google search engine.
directly if it starts with \"https:\/\/\" and otherwise uses the provided google search engine.
You can use other engines inside of your own through the 'use' function as shown above to make
complex searches.
@@ -270,35 +339,57 @@ searchEngineF :: Name -> Site -> SearchEngine
searchEngineF = SearchEngine
-- The engines.
amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle,
images, imdb, isohunt, lucky, maps, mathworld, openstreetmap, scholar, thesaurus, wayback, wikipedia, wiktionary,
youtube :: SearchEngine
amazon = searchEngine "amazon" "http://www.amazon.com/exec/obidos/external-search?index=all&keyword="
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/"
debbts = searchEngine "debbts" "http://bugs.debian.org/"
debpts = searchEngine "debpts" "http://packages.qa.debian.org/"
dictionary = searchEngine "dict" "http://dictionary.reference.com/browse/"
google = searchEngine "google" "http://www.google.com/search?num=100&q="
hackage = searchEngine "hackage" "http://hackage.haskell.org/package/"
hoogle = searchEngine "hoogle" "http://www.haskell.org/hoogle/?q="
images = searchEngine "images" "http://images.google.fr/images?q="
imdb = searchEngine "imdb" "http://www.imdb.com/find?s=all&q="
isohunt = searchEngine "isohunt" "http://isohunt.com/torrents/?ihq="
lucky = searchEngine "lucky" "http://www.google.com/search?btnI&q="
maps = searchEngine "maps" "http://maps.google.com/maps?q="
mathworld = searchEngine "mathworld" "http://mathworld.wolfram.com/search/?query="
openstreetmap = searchEngine "openstreetmap" "http://gazetteer.openstreetmap.org/namefinder/?find="
scholar = searchEngine "scholar" "http://scholar.google.com/scholar?q="
thesaurus = searchEngine "thesaurus" "http://thesaurus.reference.com/search?q="
wikipedia = searchEngine "wiki" "http://en.wikipedia.org/wiki/Special:Search?go=Go&search="
wiktionary = searchEngine "wikt" "http://en.wiktionary.org/wiki/Special:Search?go=Go&search="
youtube = searchEngine "youtube" "http://www.youtube.com/results?search_type=search_videos&search_query="
wayback = searchEngineF "wayback" ("http://web.archive.org/web/*/"++)
alpha, amazon, arXiv, aur, clojureDocs, codesearch, cratesIo, deb, debbts, debpts, dictionary, duckduckgo, ebay, flora,
github, google, hackage, homeManager, hoogle, images, imdb, lucky, maps, mathworld, ncatlab, nixos, noogle, openstreetmap, protondb,
rosettacode, rustStd, scholar, sourcehut, stackage, steam, thesaurus, vocabulary, voidpgks_x86_64, voidpgks_x86_64_musl, wayback,
wikipedia, wiktionary, youtube, zbmath :: SearchEngine
alpha = searchEngine "alpha" "https://www.wolframalpha.com/input/?i="
amazon = searchEngine "amazon" "https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords="
arXiv = searchEngineF "arXiv" (\s -> "https://arxiv.org/search/?query=" <> s <> "&searchtype=all")
aur = searchEngine "aur" "https://aur.archlinux.org/packages?&K="
clojureDocs = searchEngine "clojureDocs" "https://clojuredocs.org/search?q="
codesearch = searchEngine "codesearch" "https://developers.google.com/s/results/code-search?q="
cratesIo = searchEngine "cratesIo" "https://crates.io/search?q="
deb = searchEngine "deb" "https://packages.debian.org/"
debbts = searchEngine "debbts" "https://bugs.debian.org/"
debpts = searchEngine "debpts" "https://packages.qa.debian.org/"
dictionary = searchEngine "dict" "https://dictionary.reference.com/browse/"
duckduckgo = searchEngine "duckduckgo" "https://duckduckgo.com/?t=lm&q="
ebay = searchEngine "ebay" "https://www.ebay.com/sch/i.html?_nkw="
flora = searchEngine "flora" "https://flora.pm/search?q="
github = searchEngine "github" "https://github.com/search?q="
google = searchEngine "google" "https://www.google.com/search?q="
hackage = searchEngine "hackage" "https://hackage.haskell.org/package/"
homeManager = searchEngine "homeManager" "https://mipmip.github.io/home-manager-option-search/?query="
hoogle = searchEngine "hoogle" "https://hoogle.haskell.org/?hoogle="
images = searchEngine "images" "https://images.google.fr/images?q="
imdb = searchEngine "imdb" "https://www.imdb.com/find?s=all&q="
lucky = searchEngine "lucky" "https://www.google.com/search?btnI&q="
maps = searchEngine "maps" "https://maps.google.com/maps?q="
mathworld = searchEngine "mathworld" "https://mathworld.wolfram.com/search/?query="
ncatlab = searchEngine "ncatlab" "https://ncatlab.org/nlab/search?query="
nixos = searchEngine "nixos" "https://search.nixos.org/packages?channel=unstable&from=0&size=200&sort=relevance&type=packages&query="
noogle = searchEngineF "noogle" (\s -> "https://noogle.dev/?search=" <> s <> "&page=1&to=any&from=any")
openstreetmap = searchEngine "openstreetmap" "https://www.openstreetmap.org/search?query="
protondb = searchEngine "protondb" "https://www.protondb.com/search?q="
rosettacode = searchEngine "rosettacode" "https://rosettacode.org/w/index.php?search="
rustStd = searchEngine "rustStd" "https://doc.rust-lang.org/std/index.html?search="
scholar = searchEngine "scholar" "https://scholar.google.com/scholar?q="
sourcehut = searchEngine "sourcehut" "https://sr.ht/projects?search="
stackage = searchEngine "stackage" "https://www.stackage.org/lts/hoogle?q="
steam = searchEngine "steam" "https://store.steampowered.com/search/?term="
thesaurus = searchEngine "thesaurus" "https://thesaurus.com/browse/"
vocabulary = searchEngine "vocabulary" "https://www.vocabulary.com/search?q="
voidpgks_x86_64 = searchEngine "voidpackages" "https://voidlinux.org/packages/?arch=x86_64&q="
voidpgks_x86_64_musl = searchEngine "voidpackages" "https://voidlinux.org/packages/?arch=x86_64-musl&q="
wayback = searchEngineF "wayback" ("https://web.archive.org/web/*/"++)
wikipedia = searchEngine "wiki" "https://en.wikipedia.org/wiki/Special:Search?go=Go&search="
wiktionary = searchEngine "wikt" "https://en.wiktionary.org/wiki/Special:Search?go=Go&search="
youtube = searchEngine "youtube" "https://www.youtube.com/results?search_type=search_videos&search_query="
zbmath = searchEngine "zbmath" "https://zbmath.org/?q="
multi :: SearchEngine
multi = namedEngine "multi" $ foldr1 (!>) [amazon, alpha, codesearch, deb, debbts, debpts, dictionary, google, hackage, hoogle, images, imdb, isohunt, lucky, maps, mathworld, openstreetmap, scholar, thesaurus, wayback, wikipedia, wiktionary, (prefixAware google)]
multi = namedEngine "multi" $ foldr1 (!>) [alpha, amazon, aur, codesearch, deb, debbts, debpts, dictionary, duckduckgo, ebay, flora, github, hackage, hoogle, images, imdb, lucky, maps, mathworld, ncatlab, openstreetmap, protondb, rosettacode, scholar, sourcehut, stackage, steam, thesaurus, vocabulary, voidpgks_x86_64, voidpgks_x86_64_musl, wayback, wikipedia, wiktionary, youtube, prefixAware google]
{- | This function wraps up a search engine and creates a new one, which works
like the argument, but goes directly to a URL if one is given rather than
@@ -306,9 +397,9 @@ multi = namedEngine "multi" $ foldr1 (!>) [amazon, alpha, codesearch, deb, debbt
> myIntelligentGoogleEngine = intelligent google
Now if you search for http:\/\/xmonad.org it will directly open in your browser-}
Now if you search for https:\/\/xmonad.org it will directly open in your browser-}
intelligent :: SearchEngine -> SearchEngine
intelligent (SearchEngine name site) = searchEngineF name (\s -> if (fst $ break (==':') s) `elem` ["http", "https", "ftp"] then s else (site s))
intelligent (SearchEngine name site) = searchEngineF name (\s -> if takeWhile (/= ':') s `elem` ["http", "https", "ftp"] then s else site s)
-- | > removeColonPrefix "foo://bar" ~> "//bar"
-- > removeColonPrefix "foo//bar" ~> "foo//bar"
@@ -328,6 +419,7 @@ removeColonPrefix s = if ':' `elem` s then drop 1 $ dropWhile (':' /=) s else s
google. The use of intelligent will make sure that URLs are opened directly. -}
(!>) :: SearchEngine -> SearchEngine -> SearchEngine
(SearchEngine name1 site1) !> (SearchEngine name2 site2) = searchEngineF (name1 ++ "/" ++ name2) (\s -> if (name1++":") `isPrefixOf` s then site1 (removeColonPrefix s) else site2 s)
infixr 6 !>
{- | Makes a search engine prefix-aware. Especially useful together with '!>'.
It will automatically remove the prefix from a query so that you don\'t end
@@ -344,8 +436,18 @@ namedEngine name (SearchEngine _ site) = searchEngineF name site
Prompt's result, passes it to a given searchEngine and opens it in a given
browser. -}
promptSearchBrowser :: XPConfig -> Browser -> SearchEngine -> X ()
promptSearchBrowser config browser (SearchEngine name site) =
mkXPrompt (Search name) config (historyCompletionP ("Search [" `isPrefixOf`)) $ search browser site
promptSearchBrowser config browser (SearchEngine name site) = do
hc <- historyCompletionP ("Search [" `isPrefixOf`)
mkXPrompt (Search name) config hc $ search browser site
{- | Like 'promptSearchBrowser', but only suggest previous searches for the
given 'SearchEngine' in the prompt. -}
promptSearchBrowser' :: XPConfig -> Browser -> SearchEngine -> X ()
promptSearchBrowser' config browser (SearchEngine name site) = do
hc <- historyCompletionP (searchName `isPrefixOf`)
mkXPrompt (Search name) config hc $ search browser site
where
searchName = showXPrompt (Search name)
{- | Like 'search', but in this case, the string is not specified but grabbed
from the user's response to a prompt. Example:

View File

@@ -1,7 +1,9 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiWayIf #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.ShowText
-- Description : Display text on the screen.
-- Copyright : (c) Mario Pastorelli (2012)
-- License : BSD-style (see xmonad/LICENSE)
--
@@ -16,17 +18,16 @@
module XMonad.Actions.ShowText
( -- * Usage
-- $usage
defaultSTConfig
def
, handleTimerEvent
, flashText
, ShowTextConfig(..)
) where
import Control.Monad (when)
import Data.Map (Map,empty,insert,lookup)
import Data.Monoid (mempty, All)
import Prelude hiding (lookup)
import XMonad
import XMonad.Prelude (All, fi, listToMaybe)
import XMonad.StackSet (current,screen)
import XMonad.Util.Font (Align(AlignCenter)
, initXMF
@@ -36,28 +37,27 @@ import XMonad.Util.Font (Align(AlignCenter)
import XMonad.Util.Timer (startTimer)
import XMonad.Util.XUtils (createNewWindow
, deleteWindow
, fi
, showWindow
, paintAndWrite)
import qualified XMonad.Util.ExtensibleState as ES
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.ShowText
--
-- Then add the event hook handler:
--
-- > xmonad { handleEventHook = myHandleEventHooks <+> handleTimerEvent }
-- > xmonad { handleEventHook = myHandleEventHooks <> handleTimerEvent }
--
-- You can then use flashText in your keybindings:
--
-- > ((modMask, xK_Right), flashText defaultSTConfig 1 "->" >> nextWS)
-- > ((modMask, xK_Right), flashText def 1 "->" >> nextWS)
--
-- | ShowText contains the map with timers as keys and created windows as values
newtype ShowText = ShowText (Map Atom Window)
deriving (Read,Show,Typeable)
deriving (Read,Show)
instance ExtensionClass ShowText where
initialValue = ShowText empty
@@ -72,9 +72,13 @@ data ShowTextConfig =
, st_fg :: String -- ^ Foreground color
}
defaultSTConfig :: ShowTextConfig
defaultSTConfig =
instance Default ShowTextConfig where
def =
#ifdef XFT
STC { st_font = "xft:monospace-20"
#else
STC { st_font = "-misc-fixed-*-*-*-*-20-*-*-*-*-*-*-*"
#endif
, st_bg = "black"
, st_fg = "white"
}
@@ -84,8 +88,9 @@ handleTimerEvent :: Event -> X All
handleTimerEvent (ClientMessageEvent _ _ _ dis _ mtyp d) = do
(ShowText m) <- ES.get :: X ShowText
a <- io $ internAtom dis "XMONAD_TIMER" False
when (mtyp == a && length d >= 1)
(whenJust (lookup (fromIntegral $ d !! 0) m) deleteWindow)
if | mtyp == a, Just dh <- listToMaybe d ->
whenJust (lookup (fromIntegral dh) m) deleteWindow
| otherwise -> pure ()
mempty
handleTimerEvent _ = mempty

56
XMonad/Actions/Sift.hs Normal file
View File

@@ -0,0 +1,56 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Sift
-- Description : Functions for sifting windows up and down.
-- Copyright : (c) 2020 Ivan Brennan <ivanbrennan@gmail.com>
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Ivan Brennan <ivanbrennan@gmail.com>
-- Stability : stable
-- Portability : unportable
--
-- Functions for sifting windows up and down. Sifts behave identically to
-- swaps (i.e. 'swapUp' and 'swapDown' from "XMonad.StackSet"), except in
-- the wrapping case: rather than rotating the entire stack by one position
-- like a swap would, a sift causes the windows at either end of the stack
-- to trade positions.
--
-----------------------------------------------------------------------------
module XMonad.Actions.Sift (
-- * Usage
-- $usage
siftUp,
siftDown,
) where
import XMonad.StackSet (Stack (Stack), StackSet, modify')
import XMonad.Util.Stack (reverseS)
-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.Sift
--
-- and add keybindings such as the following:
--
-- > , ((modMask .|. shiftMask, xK_j ), windows siftDown)
-- > , ((modMask .|. shiftMask, xK_k ), windows siftUp )
--
-- |
-- siftUp, siftDown. Exchange the focused window with its neighbour in
-- the stack ordering, wrapping if we reach the end. Unlike 'swapUp' and
-- 'swapDown', wrapping is handled by trading positions with the window
-- at the other end of the stack.
--
siftUp, siftDown :: StackSet i l a s sd -> StackSet i l a s sd
siftUp = modify' siftUp'
siftDown = modify' (reverseS . siftUp' . reverseS)
siftUp' :: Stack a -> Stack a
siftUp' (Stack t (l:ls) rs) = Stack t ls (l:rs)
siftUp' (Stack t [] rs) =
case reverse rs of
(x:xs) -> Stack t (xs ++ [x]) []
[] -> Stack t [] []

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SimpleDate
-- Description : An example external contrib module for XMonad.
-- Copyright : (c) Don Stewart 2007
-- License : BSD3-style (see LICENSE)
--
@@ -23,7 +24,7 @@ import XMonad.Core
import XMonad.Util.Run
-- $usage
-- To use, import this module into @~\/.xmonad\/xmonad.hs@:
-- To use, import this module into @xmonad.hs@:
--
-- > import XMonad.Actions.SimpleDate
--
@@ -34,7 +35,7 @@ import XMonad.Util.Run
-- In this example, a popup date menu will now be bound to @mod-d@.
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
date :: X ()
date = unsafeSpawn "(date; sleep 10) | dzen2"

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SinkAll
-- Description : (DEPRECATED) Push floating windows back into tiling.
-- License : BSD3-style (see LICENSE)
-- Stability : unstable
-- Portability : unportable
@@ -12,7 +13,7 @@
-- 'sinkAll' function for backwards compatibility.
-----------------------------------------------------------------------------
module XMonad.Actions.SinkAll (
module XMonad.Actions.SinkAll {-# DEPRECATED "Use XMonad.Actions.WithAll instead" #-} (
-- * Usage
-- $usage
@@ -22,7 +23,7 @@ import XMonad.Actions.WithAll (sinkAll)
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.SinkAll
--
@@ -31,4 +32,4 @@ import XMonad.Actions.WithAll (sinkAll)
-- > , ((modm .|. shiftMask, xK_t), sinkAll)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

View File

@@ -1,7 +1,9 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE LambdaCase #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SpawnOn
-- Description : Modify a window spawned by a command.
-- Copyright : (c) Spencer Janssen
-- License : BSD
--
@@ -20,6 +22,7 @@ module XMonad.Actions.SpawnOn (
-- $usage
Spawner,
manageSpawn,
manageSpawnWithGC,
spawnHere,
spawnOn,
spawnAndDo,
@@ -27,69 +30,77 @@ module XMonad.Actions.SpawnOn (
shellPromptOn
) where
import Data.List (isInfixOf)
import System.Posix.Types (ProcessID)
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Hooks.ManageHelpers
import XMonad.Prompt
import XMonad.Prompt.Shell
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Process (getPPIDChain)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.SpawnOn
--
-- > main = do
-- > xmonad defaultConfig {
-- > xmonad def {
-- > ...
-- > manageHook = manageSpawn <+> manageHook defaultConfig
-- > manageHook = manageSpawn <> manageHook def
-- > ...
-- > }
--
-- To ensure that application appears on a workspace it was launched at, add keybindings like:
--
-- > , ((mod1Mask,xK_o), spawnHere "urxvt")
-- > , ((mod1Mask,xK_s), shellPromptHere defaultXPConfig)
-- > , ((mod1Mask,xK_s), shellPromptHere def)
--
-- The module can also be used to apply other manage hooks to the window of
-- the spawned application(e.g. float or resize it).
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
newtype Spawner = Spawner {pidsRef :: [(ProcessID, ManageHook)]} deriving Typeable
newtype Spawner = Spawner {pidsRef :: [(ProcessID, ManageHook)]}
instance ExtensionClass Spawner where
initialValue = Spawner []
maxPids :: Int
maxPids = 5
-- | Get the current Spawner or create one if it doesn't exist.
modifySpawner :: ([(ProcessID, ManageHook)] -> [(ProcessID, ManageHook)]) -> X ()
modifySpawner f = XS.modify (Spawner . f . pidsRef)
modifySpawnerM :: ([(ProcessID, ManageHook)] -> X [(ProcessID, ManageHook)]) -> X ()
modifySpawnerM f = XS.modifyM (fmap Spawner . f . pidsRef)
-- | Provides a manage hook to react on process spawned with
-- 'spawnOn', 'spawnHere' etc.
manageSpawn :: ManageHook
manageSpawn = do
Spawner pids <- liftX XS.get
mp <- pid
case flip lookup pids =<< mp of
Nothing -> idHook
Just mh -> do
whenJust mp $ \p ->
liftX . modifySpawner $ filter ((/= p) . fst)
mh
manageSpawn = manageSpawnWithGC (return . take 20)
manageSpawnWithGC :: ([(ProcessID, ManageHook)] -> X [(ProcessID, ManageHook)])
-- ^ function to stop accumulation of entries for windows that never set @_NET_WM_PID@
-> ManageHook
manageSpawnWithGC garbageCollect = pid >>= \case
Nothing -> mempty
Just p -> do
Spawner pids <- liftX XS.get
ppid_chain <- io $ getPPIDChain p
case mapMaybe (`lookup` pids) ppid_chain of
[] -> mempty
mh : _ -> liftX (gc p) >> mh
where
gc p = modifySpawnerM $ garbageCollect . filter ((/= p) . fst)
mkPrompt :: (String -> X ()) -> XPConfig -> X ()
mkPrompt cb c = do
cmds <- io $ getCommands
mkXPrompt Shell c (getShellCompl cmds) cb
cmds <- io getCommands
mkXPrompt Shell c (getShellCompl cmds $ searchPredicate c) cb
-- | Replacement for Shell prompt ("XMonad.Prompt.Shell") which launches
-- application on current workspace.
@@ -109,13 +120,13 @@ spawnHere cmd = withWindowSet $ \ws -> spawnOn (W.currentTag ws) cmd
-- | Replacement for 'spawn' which launches
-- application on given workspace.
spawnOn :: WorkspaceId -> String -> X ()
spawnOn ws cmd = spawnAndDo (doShift ws) cmd
spawnOn ws = spawnAndDo (doShift ws)
-- | Spawn an application and apply the manage hook when it opens.
spawnAndDo :: ManageHook -> String -> X ()
spawnAndDo mh cmd = do
p <- spawnPID $ mangle cmd
modifySpawner $ (take maxPids . ((p,mh) :))
modifySpawner ((p,mh) :)
where
-- TODO this is silly, search for a better solution
mangle xs | any (`elem` metaChars) xs || "exec" `isInfixOf` xs = xs

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Submap
-- Description : Create a sub-mapping of key bindings.
-- Copyright : (c) Jason Creighton <jcreigh@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -16,19 +17,22 @@ module XMonad.Actions.Submap (
-- * Usage
-- $usage
submap,
submapDefault
visualSubmap,
submapDefault,
submapDefaultWithKey,
-- * Utilities
subName,
) where
import Data.Bits
import XMonad hiding (keys)
import qualified Data.Map as M
import Control.Monad.Fix (fix)
import XMonad hiding (keys)
import XMonad.Prelude (fix, fromMaybe, keyToString, cleanKeyMask)
import XMonad.Util.XUtils
{- $usage
First, import this module into your @~\/.xmonad\/xmonad.hs@:
First, import this module into your @xmonad.hs@:
> import XMonad.Actions.Submap
@@ -49,7 +53,7 @@ because that is a special value passed to XGrabKey() and not an actual
modifier.
For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings".
<https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-}
@@ -58,25 +62,81 @@ 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 visualise the relevant options.
--
-- ==== __Example__
--
-- > import qualified Data.Map as Map
-- > import XMonad.Actions.Submap
-- >
-- > gotoLayout :: [(String, X ())] -- for use with EZConfig
-- > gotoLayout = -- assumes you have a layout named "Tall" and one named "Full".
-- > [("M-l", visualSubmap def $ Map.fromList $ map (\(k, s, a) -> ((0, k), (s, a)))
-- > [ (xK_t, "Tall", switchToLayout "Tall") -- "M-l t" switches to "Tall"
-- > , (xK_r, "Full", switchToLayout "Full") -- "M-l r" switches to "full"
-- > ])]
--
-- One could alternatively also write @gotoLayout@ as
--
-- > gotoLayout = [("M-l", visualSubmap def $ Map.fromList $
-- > [ ((0, xK_t), subName "Tall" $ switchToLayout "Tall")
-- > , ((0, xK_r), subName "Full" $ switchToLayout "Full")
-- > ])]
visualSubmap :: WindowConfig -- ^ The config for the spawned window.
-> M.Map (KeyMask, KeySym) (String, X ())
-- ^ A map @keybinding -> (description, action)@.
-> X ()
visualSubmap wc keys =
withSimpleWindow wc descriptions waitForKeyPress >>= \(m', s) ->
maybe (pure ()) snd (M.lookup (m', s) keys)
where
descriptions :: [String]
descriptions =
zipWith (\key desc -> keyToString key <> ": " <> desc)
(M.keys keys)
(map fst (M.elems keys))
-- | Give a name to an action.
subName :: String -> X () -> (String, X ())
subName = (,)
-- | Like 'submap', but executes a default action if the key did not match.
submapDefault :: X () -> M.Map (KeyMask, KeySym) (X ()) -> X ()
submapDefault def keys = do
XConf { theRoot = root, display = d } <- ask
submapDefault = submapDefaultWithKey . const
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
-- | 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 = waitForKeyPress >>=
\(m', s) -> fromMaybe (defAction (m', s)) (M.lookup (m', s) keys)
-----------------------------------------------------------------------
-- Internal stuff
waitForKeyPress :: X (KeyMask, KeySym)
waitForKeyPress = do
XConf{ theRoot = root, display = dpy } <- ask
io $ do grabKeyboard dpy root False grabModeAsync grabModeAsync currentTime
grabPointer dpy root False buttonPressMask grabModeAsync grabModeAsync
none none currentTime
(m, s) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do
maskEvent d keyPressMask p
KeyEvent { ev_keycode = code, ev_state = m } <- getEvent p
keysym <- keycodeToKeysym d code 0
if isModifierKey keysym
then nextkey
else return (m, keysym)
-- Remove num lock mask and Xkb group state bits
m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1)
io $ ungrabKeyboard d currentTime
maybe def id (M.lookup (m', s) keys)
maskEvent dpy (keyPressMask .|. buttonPressMask) p
ev <- getEvent p
case ev of
KeyEvent { ev_keycode = code, ev_state = m } -> do
keysym <- keycodeToKeysym dpy code 0
if isModifierKey keysym
then nextkey
else return (m, keysym)
_ -> return (0, 0)
m' <- cleanKeyMask <*> pure m
io $ do ungrabPointer dpy currentTime
ungrabKeyboard dpy currentTime
sync dpy False
pure (m', s)

View File

@@ -0,0 +1,404 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SwapPromote
-- Description : Track the master window history per workspace.
-- Copyright : (c) 2018 Yclept Nemo
-- License : BSD-style (see LICENSE)
--
-- Maintainer :
-- Stability : unstable
-- Portability : unportable
--
-- Module for tracking master window history per workspace, and associated
-- functions for manipulating the stack using such history.
--
-----------------------------------------------------------------------------
module XMonad.Actions.SwapPromote
( -- * Usage
-- $usage
MasterHistory (..)
-- * State Accessors
, getMasterHistoryMap
, getMasterHistoryFromTag
, getMasterHistoryCurrent
, getMasterHistoryFromWindow
, modifyMasterHistoryFromTag
, modifyMasterHistoryCurrent
-- * Log Hook
, masterHistoryHook
-- * Log Hook Building Blocks
, masterHistoryHook'
, updateMasterHistory
-- * Actions
, swapPromote
, swapPromote'
, swapIn
, swapIn'
, swapHybrid
, swapHybrid'
-- * Action Building Blocks
, swapApply
, swapPromoteStack
, swapInStack
, swapHybridStack
-- * List Utilities
, cycleN
, split
, split'
, merge
, merge'
-- * Stack Utilities
, stackSplit
, stackMerge
) where
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
import qualified Data.Map as M
import qualified Data.Set as S
import Control.Arrow
import qualified Data.List.NonEmpty as NE
-- $usage
-- Given your configuration file, import this module:
--
-- > import XMonad.Actions.SwapPromote
--
-- First add 'masterHistoryHook' to your 'logHook' to track master windows per
-- workspace:
--
-- > myLogHook = otherHook >> masterHistoryHook
--
-- Then replace xmonad's default promote keybinding with 'swapPromote'':
--
-- > , ((mod1Mask, xK_Return), swapPromote' False)
--
-- Depending on your xmonad configuration or window actions the master history
-- may be empty. If this is the case you can still chain another promotion
-- function:
--
-- > import XMonad.Actions.DwmPromote
-- > , ((mod1Mask, xK_Return), whenX (swapPromote False) dwmpromote)
--
-- To be clear, this is only called when the lack of master history hindered
-- the swap and not other conditions, such as having a only a single window.
--
-- While 'swapPromote' preserves window focus, 'swapIn' preserves the focus
-- position - effectively "swapping" new windows into focus without moving the
-- zipper. A mix of both, 'swapHybrid' promotes focused non-master windows
-- while swapping windows into the focused master. This works well on layouts
-- with large masters. Both come with chainable variants, see 'swapIn'' and
-- 'swapHybrid''.
--
-- So far floating windows have been treated no differently than tiled windows
-- even though their positions are independent of the stack. Often, yanking
-- floating windows in and out of the workspace will obliterate the stack
-- history - particularly frustrating with "XMonad.Util.Scratchpad" since it is
-- toggled so frequenty and always replaces the master window. That's why the
-- swap functions accept a boolean argument; when @True@ non-focused floating
-- windows will be ignored.
--
-- All together:
--
-- > , ((mod1Mask, xK_Return), whenX (swapHybrid True) dwmpromote)
-- | Mapping from workspace tag to master history list. The current master is
-- the head of the list, the previous master the second element, and so on.
-- Without history, the list is empty.
newtype MasterHistory = MasterHistory
{ getMasterHistory :: M.Map WorkspaceId [Window]
} deriving (Read,Show)
instance ExtensionClass MasterHistory where
initialValue = MasterHistory M.empty
-- | Return the master history map from the state.
getMasterHistoryMap :: X (M.Map WorkspaceId [Window])
getMasterHistoryMap = XS.gets getMasterHistory
-- | Return the master history list of a given tag. The master history list may
-- be empty. An invalid tag will also result in an empty list.
getMasterHistoryFromTag :: WorkspaceId -> X [Window]
getMasterHistoryFromTag t = M.findWithDefault [] t <$> getMasterHistoryMap
-- | Return the master history list of the current workspace.
getMasterHistoryCurrent :: X [Window]
getMasterHistoryCurrent = gets (W.currentTag . windowset)
>>= getMasterHistoryFromTag
-- | Return the master history list of the workspace containing the given
-- window. Return an empty list if the window is not in the stackset.
getMasterHistoryFromWindow :: Window -> X [Window]
getMasterHistoryFromWindow w = gets (W.findTag w . windowset)
>>= maybe (return []) getMasterHistoryFromTag
-- | Modify the master history list of a given workspace, or the empty list of
-- no such workspace is mapped. The result is then re-inserted into the master
-- history map.
modifyMasterHistoryFromTag :: WorkspaceId -> ([Window] -> [Window]) -> X ()
modifyMasterHistoryFromTag t f = XS.modify $ \(MasterHistory m) ->
let l = M.findWithDefault [] t m
in MasterHistory $ M.insert t (f l) m
-- | Modify the master history list of the current workspace. While the current
-- workspace is guaranteed to exist; its master history may not. For more
-- information see 'modifyMasterHistoryFromTag'.
modifyMasterHistoryCurrent :: ([Window] -> [Window]) -> X ()
modifyMasterHistoryCurrent f = gets (W.currentTag . windowset)
>>= flip modifyMasterHistoryFromTag f
-- | A 'logHook' to update the master history mapping. Non-existent workspaces
-- are removed, and the master history list for the current workspaces is
-- updated. See 'masterHistoryHook''.
masterHistoryHook :: X ()
masterHistoryHook = masterHistoryHook' True updateMasterHistory
-- | Backend for 'masterHistoryHook'.
masterHistoryHook' :: Bool
-- ^ If @True@, remove non-existent workspaces.
-> ([Window] -> [Window] -> [Window])
-- ^ Function used to update the master history list of
-- the current workspace. First argument is the master
-- history, second is the integrated stack. See
-- 'updateMasterHistory' for more details.
-> X ()
masterHistoryHook' removeWorkspaces historyModifier = do
wset <- gets windowset
let W.Workspace wid _ mst = W.workspace . W.current $ wset
tags = map W.tag $ W.workspaces wset
st = W.integrate' mst
XS.modify $ \(MasterHistory mm) ->
let mm' = if removeWorkspaces
then restrictKeys mm $ S.fromList tags
else mm
ms = M.findWithDefault [] wid mm'
ms' = historyModifier ms st
in MasterHistory $ M.insert wid ms' mm'
-- | Less efficient version of 'M.restrictKeys'. Given broader eventual
-- adoption, replace this with 'M.restrictKeys'.
restrictKeys :: Ord k => M.Map k a -> S.Set k -> M.Map k a
restrictKeys m s = M.filterWithKey (\k _ -> k `S.member` s) m
-- | Given the current master history list and an integrated stack, return the
-- new master history list. The current master is either moved (if it exists
-- within the history) or added to the head of the list, and all missing (i.e.
-- closed) windows are removed.
updateMasterHistory :: [Window] -- ^ The master history list.
-> [Window] -- ^ The integrated stack.
-> [Window]
updateMasterHistory _ [] = []
updateMasterHistory ms ws@(w:_) = (w : delete w ms) `intersect` ws
-- | Wrap 'swapPromoteStack'; see also 'swapApply'.
swapPromote :: Bool -> X Bool
swapPromote = flip swapApply swapPromoteStack
-- | Like 'swapPromote'' but discard the result.
swapPromote' :: Bool -> X ()
swapPromote' = void . swapPromote
-- | Wrap 'swapInStack'; see also 'swapApply'.
swapIn :: Bool -> X Bool
swapIn = flip swapApply swapInStack
-- | Like 'swapIn'' but discard the result.
swapIn' :: Bool -> X ()
swapIn' = void . swapIn
-- | Wrap 'swapHybridStack'; see also 'swapApply'.
swapHybrid :: Bool -> X Bool
swapHybrid = flip swapApply swapHybridStack
-- | Like 'swapHybrid'' but discard the result.
swapHybrid' :: Bool -> X ()
swapHybrid' = void . swapHybrid
-- | Apply the given master history stack modifier to the current stack. If
-- given @True@, all non-focused floating windows will be ignored. Return
-- @True@ if insufficient history; if so use 'whenX' to sequence a backup
-- promotion function.
swapApply :: Bool
-> (Maybe Window -> W.Stack Window -> (Bool,W.Stack Window))
-> X Bool
swapApply ignoreFloats swapFunction = do
fl <- gets $ W.floating . windowset
st <- gets $ W.stack . W.workspace . W.current . windowset
ch <- getMasterHistoryCurrent
let swapApply' s1 =
let fl' = if ignoreFloats then M.keysSet fl else S.empty
ff = (||) <$> (`S.notMember` fl') <*> (== W.focus s1)
fh = filter ff ch
pm = listToMaybe . drop 1 $ fh
(r,s2) = stackSplit s1 fl' :: ([(Int,Window)],W.Stack Window)
(b,s3) = swapFunction pm s2
s4 = stackMerge s3 r
mh = let w = NE.head . notEmpty . W.integrate $ s3
in const $ w : delete w ch
in (b,Just s4,mh)
(x,y,z) = maybe (False,Nothing,id) swapApply' st
-- Any floating master windows will be added to the history when 'windows'
-- calls the log hook.
modifyMasterHistoryCurrent z
windows $ W.modify Nothing . const $ y
return x
-- | If the focused window is the master window and there is no previous
-- master, do nothing. Otherwise swap the master with the previous master. If
-- the focused window is not the master window, swap it with the master window.
-- In either case focus follows the original window, i.e. the focused window
-- does not change, only its position.
--
-- The first argument is the previous master (which may not exist), the second
-- a window stack. Return @True@ if the master history hindered the swap; the
-- history is either empty or out-of-sync. Though the latter shouldn't happen
-- this function never changes the stack under such circumstances.
swapPromoteStack :: Maybe Window -> W.Stack Window -> (Bool,W.Stack Window)
swapPromoteStack _ st@(W.Stack _x [] []) = (False,st)
swapPromoteStack Nothing st@(W.Stack _x [] _r) = (True,st)
swapPromoteStack (Just pm) (W.Stack x [] r) =
let (r',l') = (reverse *** cycleN 1) $ span (/= pm) $ reverse r
st' = W.Stack x l' r'
b = null l'
in (b,st')
swapPromoteStack _ (W.Stack x l r) =
let r' = (++ r) . cycleN 1 . reverse $ l
st' = W.Stack x [] r'
in (False,st')
-- | Perform the same swap as 'swapPromoteStack'. However the new window
-- receives the focus; it appears to "swap into" the position of the original
-- window. Under this model focus follows stack position and the zipper does
-- not move.
--
-- See 'swapPromoteStack' for more details regarding the parameters.
swapInStack :: Maybe Window -> W.Stack Window -> (Bool,W.Stack Window)
swapInStack _ st@(W.Stack _x [] []) = (False,st)
swapInStack Nothing st@(W.Stack _x [] _r) = (True,st)
swapInStack (Just pm) (W.Stack x [] r) =
let (x',r') = case span (/= pm) r of
(__,[]) -> (x,r)
(sl,sr) -> (pm,sl ++ x : drop 1 sr)
st' = W.Stack x' [] r'
b = x' == x
in (b,st')
swapInStack _ (W.Stack x l r) =
let l' = init l ++ [x]
x' = last l
st' = W.Stack x' l' r
in (False,st')
-- | If the focused window is the master window, use 'swapInStack'. Otherwise use
-- 'swapPromoteStack'.
--
-- See 'swapPromoteStack' for more details regarding the parameters.
swapHybridStack :: Maybe Window -> W.Stack Window -> (Bool,W.Stack Window)
swapHybridStack m st@(W.Stack _ [] _) = swapInStack m st
swapHybridStack m st = swapPromoteStack m st
-- | Cycle a list by the given count. If positive, cycle to the left. If
-- negative, cycle to the right:
--
-- >>> cycleN 2 [1,2,3,4,5]
-- [3,4,5,1,2]
-- >>> cycleN (-2) [1,2,3,4,5]
-- [4,5,1,2,3]
cycleN :: Int -> [a] -> [a]
cycleN n ls =
let l = length ls
in take l $ drop (n `mod` l) $ cycle ls
-- | Wrap 'split'' with an initial index of @0@, discarding the list's length.
split :: (Num a, Enum a) => (b -> Bool) -> [b] -> ([(a,b)],[b])
split p l =
let (_,ys,ns) = split' p 0 l
in (ys,ns)
-- | Given a predicate, an initial index and a list, return a tuple containing:
--
-- * List length.
-- * Indexed list of elements which satisfy the predicate. An indexed element
-- is a tuple containing the element index (offset by the initial index) and
-- the element.
-- * List of elements which do not satisfy the predicate.
--
-- The initial index and length of the list simplify chaining calls to this
-- function, such as for zippers of lists.
split' :: (Num a, Enum a) => (b -> Bool) -> a -> [b] -> (a,[(a,b)],[b])
split' p i l =
let accumulate e (c,ys,ns) = if p (snd e)
then (c+1,e:ys,ns)
else (c+1,ys,e:ns)
(c',ys',ns') = foldr accumulate (0,[],[]) $ zip [i..] l
in (c',ys',map snd ns')
-- | Wrap 'merge'' with an initial virtual index of @0@. Return only the
-- unindexed list with elements from the leftover indexed list appended.
merge :: (Ord a, Num a) => [(a,b)] -> [b] -> [b]
merge il ul =
let (_,il',ul') = merge' 0 il ul
in ul' ++ map snd il'
-- | Inverse of 'split'. Merge an indexed list with an unindexed list (see
-- 'split''). Given a virtual index, an indexed list and an unindexed list,
-- return a tuple containing:
--
-- * Virtual index /after/ the unindexed list
-- * Remainder of the indexed list
-- * Merged unindexed list
--
-- If the indexed list is empty, this functions consumes the entire unindexed
-- list. If the unindexed list is empty, this function consumes only adjacent
-- indexed elements. For example, @[(10,"ten"),(12,"twelve")]@ implies missing
-- unindexed elements and so once @(10,"ten")@ is consumed this function
-- concludes.
--
-- The indexed list is assumed to have been created by 'split'' and not checked
-- for correctness. Indices are assumed to be ascending, i.e.
-- > [(1,"one"),(2,"two"),(4,"four")]
--
-- The initial and final virtual indices simplify chaining calls to the this
-- function, as as for zippers of lists. Positive values shift the unindexed
-- list towards the tail, as if preceded by that many elements.
merge' :: (Ord a, Num a) => a -> [(a,b)] -> [b] -> (a,[(a,b)],[b])
merge' i il@((j,a):ps) ul@(b:bs) = if j <= i
then let (x,y,z) = merge' (i+1) ps ul
in (x,y,a:z)
else let (x,y,z) = merge' (i+1) il bs
in (x,y,b:z)
merge' i [] (b:bs) =
let (x,y,z) = merge' (i+1) [] bs
in (x,y,b:z)
merge' i il@((j,a):ps) [] = if j <= i
then let (x,y,z) = merge' (i+1) ps []
in (x,y,a:z)
else (i,il,[])
merge' i [] [] =
(i,[],[])
-- | Remove all elements of the set from the stack. Skip the currently focused
-- member. Return an indexed list of excluded elements and the modified stack.
-- Use 'stackMerge' to re-insert the elements using this list.
stackSplit :: (Num a, Enum a, Ord b) => W.Stack b -> S.Set b -> ([(a,b)],W.Stack b)
stackSplit (W.Stack x l r) s =
let (c,fl,tl) = split' (`S.member` s) 0 (reverse l)
(_,fr,tr) = split' (`S.member` s) (c+1) r
in (fl++fr,W.Stack x (reverse tl) tr)
-- | Inverse of 'stackSplit'. Given a list of elements and their original
-- indices, re-insert the elements into these same positions within the stack.
-- Skip the currently focused member. Works best if the stack's length hasn't
-- changed, though if shorter any leftover elements will be tacked on.
stackMerge :: (Ord a, Num a) => W.Stack b -> [(a,b)] -> W.Stack b
stackMerge (W.Stack x l r) il =
let (i,il1,l') = merge' 0 il (reverse l)
(_,il2,r') = merge' (i+1) il1 r
in W.Stack x (reverse l') (r' ++ map snd il2)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SwapWorkspaces
-- Description : Swap workspace tags without having to move individual windows.
-- Copyright : (c) Devin Mullins <me@twifkak.com>
-- License : BSD3-style (see LICENSE)
--
@@ -29,7 +30,7 @@ import XMonad.Util.WorkspaceCompare
-- $usage
-- Add this import to your @~\/.xmonad\/xmonad.hs@:
-- Add this import to your @xmonad.hs@:
--
-- > import XMonad.Actions.SwapWorkspaces
--
@@ -43,7 +44,7 @@ import XMonad.Util.WorkspaceCompare
-- will swap workspaces 1 and 5.
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Swaps the currently focused workspace with the given workspace tag, via
-- @swapWorkspaces@.
@@ -53,12 +54,13 @@ swapWithCurrent t s = swapWorkspaces t (currentTag s) s
-- | Say @swapTo Next@ or @swapTo Prev@ to move your current workspace.
-- This is an @X ()@ so can be hooked up to your keybindings directly.
swapTo :: Direction1D -> X ()
swapTo dir = findWorkspace getSortByIndex dir AnyWS 1 >>= windows . swapWithCurrent
swapTo dir = findWorkspace getSortByIndex dir anyWS 1 >>= windows . swapWithCurrent
-- | Takes two workspace tags and an existing XMonad.StackSet and returns a new
-- one with the two corresponding workspaces' tags swapped.
swapWorkspaces :: Eq i => i -> i -> StackSet i l a s sd -> StackSet i l a s sd
swapWorkspaces t1 t2 = mapWorkspace swap
where swap w = if tag w == t1 then w { tag = t2 }
else if tag w == t2 then w { tag = t1 }
else w
where swap w
| tag w == t1 = w { tag = t2 }
| tag w == t2 = w { tag = t1 }
| otherwise = w

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TagWindows
-- Description : Functions for tagging windows and selecting them by tags.
-- Copyright : (c) Karsten Schoelzel <kuser@gmx.de>
-- License : BSD
--
@@ -26,21 +27,19 @@ module XMonad.Actions.TagWindows (
TagPrompt,
) where
import Data.List (nub,sortBy)
import Control.Monad
import Control.Exception as E
import XMonad.StackSet hiding (filter)
import XMonad.Prompt
import XMonad hiding (workspaces)
import XMonad.Prelude
import XMonad.Prompt
import XMonad.StackSet hiding (filter)
econst :: Monad m => a -> IOException -> m a
econst = const . return
-- $usage
--
-- To use window tags, import this module into your @~\/.xmonad\/xmonad.hs@:
-- To use window tags, import this module into your @xmonad.hs@:
--
-- > import XMonad.Actions.TagWindows
-- > import XMonad.Prompt -- to use tagPrompt
@@ -53,19 +52,19 @@ econst = const . return
-- > , ((modm, xK_d ), withTaggedP "abc" (W.shiftWin "2"))
-- > , ((modm .|. shiftMask, xK_d ), withTaggedGlobalP "abc" shiftHere)
-- > , ((modm .|. controlMask, xK_d ), focusUpTaggedGlobal "abc")
-- > , ((modm, xK_g ), tagPrompt defaultXPConfig (\s -> withFocused (addTag s)))
-- > , ((modm .|. controlMask, xK_g ), tagDelPrompt defaultXPConfig)
-- > , ((modm .|. shiftMask, xK_g ), tagPrompt defaultXPConfig (\s -> withTaggedGlobal s float))
-- > , ((modWinMask, xK_g ), tagPrompt defaultXPConfig (\s -> withTaggedP s (W.shiftWin "2")))
-- > , ((modWinMask .|. shiftMask, xK_g ), tagPrompt defaultXPConfig (\s -> withTaggedGlobalP s shiftHere))
-- > , ((modWinMask .|. controlMask, xK_g ), tagPrompt defaultXPConfig (\s -> focusUpTaggedGlobal s))
-- > , ((modm, xK_g ), tagPrompt def (\s -> withFocused (addTag s)))
-- > , ((modm .|. controlMask, xK_g ), tagDelPrompt def)
-- > , ((modm .|. shiftMask, xK_g ), tagPrompt def (\s -> withTaggedGlobal s float))
-- > , ((modWinMask, xK_g ), tagPrompt def (\s -> withTaggedP s (W.shiftWin "2")))
-- > , ((modWinMask .|. shiftMask, xK_g ), tagPrompt def (\s -> withTaggedGlobalP s shiftHere))
-- > , ((modWinMask .|. controlMask, xK_g ), tagPrompt def (\s -> focusUpTaggedGlobal s))
--
-- NOTE: Tags are saved as space separated strings and split with
-- 'unwords'. Thus if you add a tag \"a b\" the window will have
-- the tags \"a\" and \"b\" but not \"a b\".
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | set multiple tags for a window at once (overriding any previous tags)
setTags :: [String] -> Window -> X ()
@@ -84,18 +83,17 @@ getTags w = withDisplay $ \d ->
io $ E.catch (internAtom d "_XMONAD_TAGS" False >>=
getTextProperty d w >>=
wcTextPropertyToTextList d)
(econst [[]])
>>= return . words . unwords
(econst [[]]) <&> (words . unwords)
-- | check a window for the given tag
hasTag :: String -> Window -> X Bool
hasTag s w = (s `elem`) `fmap` getTags w
hasTag s w = (s `elem`) <$> getTags w
-- | add a tag to the existing ones
addTag :: String -> Window -> X ()
addTag s w = do
tags <- getTags w
if (s `notElem` tags) then setTags (s:tags) w else return ()
when (s `notElem` tags) $ setTags (s:tags) w
-- | remove a tag from a window, if it exists
delTag :: String -> Window -> X ()
@@ -136,11 +134,6 @@ focusTagged' :: (WindowSet -> [Window]) -> String -> X ()
focusTagged' wl t = gets windowset >>= findM (hasTag t) . wl >>=
maybe (return ()) (windows . focusWindow)
findM :: (Monad m) => (a -> m Bool) -> [a] -> m (Maybe a)
findM _ [] = return Nothing
findM p (x:xs) = do b <- p x
if b then return (Just x) else findM p xs
-- | apply a pure function to windows with a tag
withTaggedP, withTaggedGlobalP :: String -> (Window -> WindowSet -> WindowSet) -> X ()
withTaggedP t f = withTagged' t (winMap f)
@@ -158,7 +151,7 @@ withTagged' t m = gets windowset >>= filterM (hasTag t) . index >>= m
withTaggedGlobal' :: String -> ([Window] -> X ()) -> X ()
withTaggedGlobal' t m = gets windowset >>=
filterM (hasTag t) . concat . map (integrate' . stack) . workspaces >>= m
filterM (hasTag t) . concatMap (integrate' . stack) . workspaces >>= m
withFocusedP :: (Window -> WindowSet -> WindowSet) -> X ()
withFocusedP f = withFocused $ windows . f
@@ -167,7 +160,7 @@ shiftHere :: (Ord a, Eq s, Eq i) => a -> StackSet i l a s sd -> StackSet i l a s
shiftHere w s = shiftWin (currentTag s) w s
shiftToScreen :: (Ord a, Eq s, Eq i) => s -> a -> StackSet i l a s sd -> StackSet i l a s sd
shiftToScreen sid w s = case filter (\m -> sid /= screen m) ((current s):(visible s)) of
shiftToScreen sid w s = case filter (\m -> sid /= screen m) (current s:visible s) of
[] -> s
(t:_) -> shiftWin (tag . workspace $ t) w s
@@ -180,20 +173,19 @@ instance XPrompt TagPrompt where
tagPrompt :: XPConfig -> (String -> X ()) -> X ()
tagPrompt c f = do
sc <- tagComplList
mkXPrompt TagPrompt c (mkComplFunFromList' sc) f
mkXPrompt TagPrompt c (mkComplFunFromList' c sc) f
tagComplList :: X [String]
tagComplList = gets (concat . map (integrate' . stack) . workspaces . windowset) >>=
mapM getTags >>=
return . nub . concat
tagComplList = gets (concatMap (integrate' . stack) . workspaces . windowset)
>>= mapM getTags
<&> nub . concat
tagDelPrompt :: XPConfig -> X ()
tagDelPrompt c = do
sc <- tagDelComplList
if (sc /= [])
then mkXPrompt TagPrompt c (mkComplFunFromList' sc) (\s -> withFocused (delTag s))
else return ()
when (sc /= []) $
mkXPrompt TagPrompt c (mkComplFunFromList' c sc) (withFocused . delTag)
tagDelComplList :: X [String]
tagDelComplList = gets windowset >>= maybe (return []) getTags . peek

View File

@@ -0,0 +1,92 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TiledWindowDragging
-- Description : Change the position of windows by dragging them.
-- Copyright : (c) 2020 Leon Kowarschick
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Leon Kowarschick. <thereal.elkowar@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- Provides an action that allows you to change the position of windows by dragging them around.
--
-----------------------------------------------------------------------------
module XMonad.Actions.TiledWindowDragging
(
-- * Usage
-- $usage
dragWindow
)
where
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Layout.DraggingVisualizer
-- $usage
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.TiledWindowDragging
-- > import XMonad.Layout.DraggingVisualizer
--
-- then edit your 'layoutHook' by adding the draggingVisualizer to your layout:
--
-- > myLayout = draggingVisualizer $ layoutHook def
--
-- Then add a mouse binding for 'dragWindow':
--
-- > , ((modMask .|. shiftMask, button1), dragWindow)
--
-- For detailed instructions on editing your mouse bindings, see
-- "XMonad.Doc.Extending#Editing_mouse_bindings".
-- | Create a mouse binding for this to be able to drag your windows around.
-- You need "XMonad.Layout.DraggingVisualizer" for this to look good.
dragWindow :: Window -> X ()
dragWindow window = whenX (isClient window) $ withDisplay $ \dpy ->
withWindowAttributes dpy window $ \wa -> do
focus window
(offsetX, offsetY) <- getPointerOffset window
let (winX, winY, winWidth, winHeight) = getWindowPlacement wa
mouseDrag
(\posX posY ->
let rect = Rectangle (fi (fi winX + (posX - fi offsetX)))
(fi (fi winY + (posY - fi offsetY)))
(fi winWidth)
(fi winHeight)
in sendMessage $ DraggingWindow window rect
)
(sendMessage DraggingStopped >> performWindowSwitching window)
-- | get the pointer offset relative to the given windows root coordinates
getPointerOffset :: Window -> X (Int, Int)
getPointerOffset win = do
(_, _, _, oX, oY, _, _, _) <- withDisplay (\d -> io $ queryPointer d win)
return (fi oX, fi oY)
-- | return a tuple of windowX, windowY, windowWidth, windowHeight
getWindowPlacement :: WindowAttributes -> (Int, Int, Int, Int)
getWindowPlacement wa = (fi $ wa_x wa, fi $ wa_y wa, fi $ wa_width wa, fi $ wa_height wa)
performWindowSwitching :: Window -> X ()
performWindowSwitching win = do
root <- asks theRoot
(_, _, selWin, _, _, _, _, _) <- withDisplay (\d -> io $ queryPointer d root)
ws <- gets windowset
let allWindows = W.index ws
when ((win `elem` allWindows) && (selWin `elem` allWindows)) $ do
let allWindowsSwitched = map (switchEntries win selWin) allWindows
(ls, t : rs) <- pure $ break (== win) allWindowsSwitched
let newStack = W.Stack t (reverse ls) rs
windows $ W.modify' $ const newStack
where
switchEntries a b x | x == a = b
| x == b = a
| otherwise = x

View File

@@ -0,0 +1,122 @@
-- |
-- Module : XMonad.Actions.ToggleFullFloat
-- Description : Fullscreen (float) a window while remembering its original state.
-- Copyright : (c) 2022 Tomáš Janoušek <tomi@nomi.cz>
-- License : BSD3
-- Maintainer : Tomáš Janoušek <tomi@nomi.cz>
--
module XMonad.Actions.ToggleFullFloat (
-- * Usage
-- $usage
toggleFullFloatEwmhFullscreen,
toggleFullFloat,
fullFloat,
unFullFloat,
gcToggleFullFloat,
) where
import qualified Data.Map.Strict as M
import XMonad
import XMonad.Prelude
import XMonad.Hooks.EwmhDesktops (setEwmhFullscreenHooks)
import XMonad.Hooks.ManageHelpers
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
-- ---------------------------------------------------------------------
-- $usage
--
-- The main use-case is to make 'ewmhFullscreen' (re)store the size and
-- position of floating windows instead of just unconditionally sinking them
-- into the floating layer. To enable this, you'll need this in your
-- @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Actions.ToggleFullFloat
-- > import XMonad.Hooks.EwmhDesktops
-- >
-- > main = xmonad $ … . toggleFullFloatEwmhFullscreen . ewmhFullscreen . ewmh . … $ def{…}
--
-- Additionally, this "smart" fullscreening can be bound to a key and invoked
-- manually whenever one needs a larger window temporarily:
--
-- > , ((modMask .|. shiftMask, xK_t), withFocused toggleFullFloat)
newtype ToggleFullFloat = ToggleFullFloat{ fromToggleFullFloat :: M.Map Window (Maybe W.RationalRect) }
deriving (Show, Read)
instance ExtensionClass ToggleFullFloat where
extensionType = PersistentExtension
initialValue = ToggleFullFloat mempty
-- | Full-float a window, remembering its state (tiled/floating and
-- position/size).
fullFloat :: Window -> X ()
fullFloat = windows . appEndo <=< runQuery doFullFloatSave
-- | Restore window to its remembered state.
unFullFloat :: Window -> X ()
unFullFloat = windows . appEndo <=< runQuery doFullFloatRestore
-- | Full-float a window, if it's not already full-floating. Otherwise,
-- restore its original state.
toggleFullFloat :: Window -> X ()
toggleFullFloat w = ifM (isFullFloat w) (unFullFloat w) (fullFloat w)
isFullFloat :: Window -> X Bool
isFullFloat w = gets $ (Just fullRect ==) . M.lookup w . W.floating . windowset
where
fullRect = W.RationalRect 0 0 1 1
doFullFloatSave :: ManageHook
doFullFloatSave = do
w <- ask
liftX $ do
f <- gets $ M.lookup w . W.floating . windowset
-- @M.insertWith const@ = don't overwrite stored original state
XS.modify' $ ToggleFullFloat . M.insertWith const w f . fromToggleFullFloat
doFullFloat
doFullFloatRestore :: ManageHook
doFullFloatRestore = do
w <- ask
mf <- liftX $ do
mf <- XS.gets $ M.lookup w . fromToggleFullFloat
XS.modify' $ ToggleFullFloat . M.delete w . fromToggleFullFloat
pure mf
doF $ case mf of
Just (Just f) -> W.float w f -- was floating before
Just Nothing -> W.sink w -- was tiled before
Nothing -> W.sink w -- fallback when not found in ToggleFullFloat
-- | Install ToggleFullFloat garbage collection hooks.
--
-- Note: This is included in 'toggleFullFloatEwmhFullscreen', only needed if
-- using the 'toggleFullFloat' separately from the EWMH hook.
gcToggleFullFloat :: XConfig a -> XConfig a
gcToggleFullFloat c = c { startupHook = startupHook c <> gcToggleFullFloatStartupHook
, handleEventHook = handleEventHook c <> gcToggleFullFloatEventHook }
-- | ToggleFullFloat garbage collection: drop windows when they're destroyed.
gcToggleFullFloatEventHook :: Event -> X All
gcToggleFullFloatEventHook DestroyWindowEvent{ev_window = w} = do
XS.modify' $ ToggleFullFloat . M.delete w . fromToggleFullFloat
mempty
gcToggleFullFloatEventHook _ = mempty
-- | ToggleFullFloat garbage collection: restrict to existing windows at
-- startup.
gcToggleFullFloatStartupHook :: X ()
gcToggleFullFloatStartupHook = withWindowSet $ \ws ->
XS.modify' $ ToggleFullFloat . M.filterWithKey (\w _ -> w `W.member` ws) . fromToggleFullFloat
-- | Hook this module into 'XMonad.Hooks.EwmhDesktops.ewmhFullscreen'. This
-- makes windows restore their original state (size and position if floating)
-- instead of unconditionally sinking into the tiling layer.
--
-- ('gcToggleFullFloat' is included here.)
toggleFullFloatEwmhFullscreen :: XConfig a -> XConfig a
toggleFullFloatEwmhFullscreen =
setEwmhFullscreenHooks doFullFloatSave doFullFloatRestore .
gcToggleFullFloat

View File

@@ -1,7 +1,8 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE NamedFieldPuns #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TopicSpace
-- Description : Turns your workspaces into a more topic oriented system.
-- Copyright : (c) Nicolas Pouillard
-- License : BSD-style (see LICENSE)
--
@@ -19,20 +20,49 @@ module XMonad.Actions.TopicSpace
-- * Usage
-- $usage
Topic
-- * Types for Building Topics
Topic
, Dir
, TopicConfig(..)
, defaultTopicConfig
, getLastFocusedTopics
, setLastFocusedTopic
, reverseLastFocusedTopics
, pprWindowSet
, TopicItem(..)
-- * Managing 'TopicItem's
, topicNames
, tiActions
, tiDirs
, noAction
, inHome
-- * Switching and Shifting Topics
, switchTopic
, switchNthLastFocused
, switchNthLastFocusedByScreen
, switchNthLastFocusedExclude
, shiftNthLastFocused
-- * Topic Actions
, topicActionWithPrompt
, topicAction
, currentTopicAction
, switchTopic
, switchNthLastFocused
, shiftNthLastFocused
-- * Getting the Topic History
, getLastFocusedTopics
, workspaceHistory
, workspaceHistoryByScreen
-- * Modifying the Topic History
, setLastFocusedTopic
, reverseLastFocusedTopics
-- * History hooks
, workspaceHistoryHook
, workspaceHistoryHookExclude
-- * Pretty Printing
, pprWindowSet
-- * Utility
, currentTopicDir
, checkTopicConfig
, (>*>)
@@ -40,25 +70,26 @@ module XMonad.Actions.TopicSpace
where
import XMonad
import XMonad.Prelude
import Data.List
import Data.Maybe (fromMaybe, isNothing, listToMaybe, fromJust)
import Data.Ord
import qualified Data.Map as M
import Control.Monad (liftM2,when,unless,replicateM_)
import System.IO
import qualified Data.Map.Strict as M
import qualified XMonad.Hooks.StatusBar.PP as SBPP
import qualified XMonad.StackSet as W
import qualified XMonad.StackSet as W
import Data.Map (Map)
import XMonad.Prompt
import XMonad.Prompt.Workspace
import XMonad.Prompt (XPConfig)
import XMonad.Prompt.Workspace (workspacePrompt)
import XMonad.Hooks.UrgencyHook
import XMonad.Hooks.DynamicLog (PP(..))
import qualified XMonad.Hooks.DynamicLog as DL
import XMonad.Util.Run (spawnPipe)
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Hooks.StatusBar.PP (PP(ppHidden, ppVisible))
import XMonad.Hooks.UrgencyHook (readUrgents)
import XMonad.Hooks.WorkspaceHistory
( workspaceHistory
, workspaceHistoryByScreen
, workspaceHistoryHook
, workspaceHistoryHookExclude
, workspaceHistoryModify
)
-- $overview
-- This module allows to organize your workspaces on a precise topic basis. So
@@ -72,112 +103,133 @@ import qualified XMonad.Util.ExtensibleState as XS
-- display your topics in an historical way using a custom `pprWindowSet'
-- function. You can also easily switch to recent topics using this history
-- of last focused topics.
--
-- A blog post highlighting some features of this module can be found
-- <https://tony-zorman.com/posts/topic-space/2022-09-11-topic-spaces.html here>.
-- $usage
-- Here is an example of configuration using TopicSpace:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > -- The list of all topics/workspaces of your xmonad configuration.
-- > -- The order is important, new topics must be inserted
-- > -- at the end of the list if you want hot-restarting
-- > -- to work.
-- > myTopics :: [Topic]
-- > myTopics =
-- > [ "dashboard" -- the first one
-- > , "admin", "build", "cleaning", "conf", "darcs", "haskell", "irc"
-- > , "mail", "movie", "music", "talk", "text", "tools", "web", "xmonad"
-- > , "yi", "documents", "twitter", "pdf"
-- > ]
-- > import qualified Data.Map.Strict as M
-- > import qualified XMonad.StackSet as W
-- >
-- > import XMonad.Actions.TopicSpace
-- > import XMonad.Util.EZConfig -- for the keybindings
-- > import XMonad.Prompt.Workspace -- if you want to use the prompt
--
-- You will then have to
--
-- * Define a new 'TopicConfig' via 'TopicItem's
--
-- * Add the appropriate keybindings
--
-- * Replace the @workspaces@ field in your 'XConfig' with a list of
-- your topics names
--
-- * Optionally, if you want to use the history features, add
-- 'workspaceHistoryHook' from "XMonad.Hooks.WorkspaceHistory"
-- (re-exported by this module) or an equivalent function to your
-- @logHook@. See the documentation of
-- "XMonad.Hooks.WorkspaceHistory" for further details
--
-- Let us go through a full example together.
--
-- A 'TopicItem' consists of three things: the name of the topic, its
-- root directory, and the action associated to it—to be executed if the
-- topic is empty or the action is forced via a keybinding.
--
-- We start by specifying our chosen topics as a list of such
-- 'TopicItem's:
--
-- > topicItems :: [TopicItem]
-- > topicItems =
-- > [ inHome "1:WEB" (spawn "firefox")
-- > , noAction "2" "."
-- > , noAction "3:VID" "videos"
-- > , TI "4:VPN" "openvpn" (spawn "urxvt -e randomVPN.sh")
-- > , inHome "5:IM" (spawn "signal" *> spawn "telegram")
-- > , inHome "6:IRC" (spawn "urxvt -e weechat")
-- > , TI "dts" ".dotfiles" spawnShell
-- > , TI "xm-con" "hs/xm-con" (spawnShell *> spawnShellIn "hs/xm")
-- > ]
--
-- Then we just need to put together our topic config:
--
-- > myTopicConfig :: TopicConfig
-- > myTopicConfig = defaultTopicConfig
-- > { topicDirs = M.fromList $
-- > [ ("conf", "w/conf")
-- > , ("dashboard", "Desktop")
-- > , ("yi", "w/dev-haskell/yi")
-- > , ("darcs", "w/dev-haskell/darcs")
-- > , ("haskell", "w/dev-haskell")
-- > , ("xmonad", "w/dev-haskell/xmonad")
-- > , ("tools", "w/tools")
-- > , ("movie", "Movies")
-- > , ("talk", "w/talks")
-- > , ("music", "Music")
-- > , ("documents", "w/documents")
-- > , ("pdf", "w/documents")
-- > ]
-- > , defaultTopicAction = const $ spawnShell >*> 3
-- > , defaultTopic = "dashboard"
-- > , topicActions = M.fromList $
-- > [ ("conf", spawnShell >> spawnShellIn "wd/ertai/private")
-- > , ("darcs", spawnShell >*> 3)
-- > , ("yi", spawnShell >*> 3)
-- > , ("haskell", spawnShell >*> 2 >>
-- > spawnShellIn "wd/dev-haskell/ghc")
-- > , ("xmonad", spawnShellIn "wd/x11-wm/xmonad" >>
-- > spawnShellIn "wd/x11-wm/xmonad/contrib" >>
-- > spawnShellIn "wd/x11-wm/xmonad/utils" >>
-- > spawnShellIn ".xmonad" >>
-- > spawnShellIn ".xmonad")
-- > , ("mail", mailAction)
-- > , ("irc", ssh somewhere)
-- > , ("admin", ssh somewhere >>
-- > ssh nowhere)
-- > , ("dashboard", spawnShell)
-- > , ("twitter", spawnShell)
-- > , ("web", spawn browserCmd)
-- > , ("movie", spawnShell)
-- > , ("documents", spawnShell >*> 2 >>
-- > spawnShellIn "Documents" >*> 2)
-- > , ("pdf", spawn pdfViewerCmd)
-- > ]
-- > myTopicConfig = def
-- > { topicDirs = tiDirs topicItems
-- > , topicActions = tiActions topicItems
-- > , defaultTopicAction = const (pure ()) -- by default, do nothing
-- > , defaultTopic = "1:WEB" -- fallback
-- > }
-- >
-- > -- extend your keybindings
-- > myKeys conf@XConfig{modMask=modm} =
-- > [ ((modm , xK_n ), spawnShell) -- %! Launch terminal
-- > , ((modm , xK_a ), currentTopicAction myTopicConfig)
-- > , ((modm , xK_g ), promptedGoto)
-- > , ((modm .|. shiftMask, xK_g ), promptedShift)
-- > {- more keys ... -}
-- > ]
-- > ++
-- > [ ((modm, k), switchNthLastFocused myTopicConfig i)
-- > | (i, k) <- zip [1..] workspaceKeys]
-- >
--
-- Above, we have used the `spawnShell` and `spawnShellIn` helper
-- functions; here they are:
--
-- > spawnShell :: X ()
-- > spawnShell = currentTopicDir myTopicConfig >>= spawnShellIn
-- >
-- > spawnShellIn :: Dir -> X ()
-- > spawnShellIn dir = spawn $ "urxvt '(cd ''" ++ dir ++ "'' && " ++ myShell ++ " )'"
-- >
-- > spawnShellIn dir = spawn $ "alacritty --working-directory " ++ dir
--
-- Next, we define some other other useful helper functions. It is
-- rather common to have a lot of topics—much more than available keys!
-- In a situation like that, it's very convenient to switch topics with
-- a prompt; the following use of 'workspacePrompt' does exactly that.
--
-- > goto :: Topic -> X ()
-- > goto = switchTopic myTopicConfig
-- >
-- > promptedGoto :: X ()
-- > promptedGoto = workspacePrompt myXPConfig goto
-- > promptedGoto = workspacePrompt def goto
-- >
-- > promptedShift :: X ()
-- > promptedShift = workspacePrompt myXPConfig $ windows . W.shift
-- >
-- > myConfig = do
-- > checkTopicConfig myTopics myTopicConfig
-- > myLogHook <- makeMyLogHook
-- > return $ defaultConfig
-- > { borderWidth = 1 -- Width of the window border in pixels.
-- > , workspaces = myTopics
-- > , layoutHook = myModifiers myLayout
-- > , manageHook = myManageHook
-- > , logHook = myLogHook
-- > , handleEventHook = myHandleEventHook
-- > , terminal = myTerminal -- The preferred terminal program.
-- > , normalBorderColor = "#3f3c6d"
-- > , focusedBorderColor = "#4f66ff"
-- > , XMonad.modMask = mod1Mask
-- > , keys = myKeys
-- > , mouseBindings = myMouseBindings
-- > }
-- > promptedShift = workspacePrompt def $ windows . W.shift
-- >
-- > -- Toggle between the two most recently used topics, but keep
-- > -- screens separate. This needs @workspaceHistoryHook@.
-- > toggleTopic :: X ()
-- > toggleTopic = switchNthLastFocusedByScreen myTopicConfig 1
--
-- Hopefully you've gotten a general feeling of how to define these kind of
-- small helper functions using what's provided in this module.
--
-- Adding the appropriate keybindings works as it normally would. Here,
-- we'll use "XMonad.Util.EZConfig" syntax:
--
-- > myKeys :: [(String, X ())]
-- > myKeys =
-- > [ ("M-n" , spawnShell)
-- > , ("M-a" , currentTopicAction myTopicConfig)
-- > , ("M-g" , promptedGoto)
-- > , ("M-S-g" , promptedShift)
-- > , ("M-S-<Space>", toggleTopic)
-- > ]
-- > ++
-- > -- The following does two things:
-- > -- 1. Switch topics (no modifier)
-- > -- 2. Move focused window to topic N (shift modifier)
-- > [ ("M-" ++ m ++ k, f i)
-- > | (i, k) <- zip (topicNames topicItems) (map show [1 .. 9 :: Int])
-- > , (f, m) <- [(goto, ""), (windows . W.shift, "S-")]
-- > ]
--
-- This makes @M-1@ to @M-9@ switch to the first nine topics that we
-- have specified in @topicItems@.
--
-- You can also switch to the nine last-used topics instead:
--
-- > [ ("M-" ++ show i, switchNthLastFocused myTopicConfig i)
-- > | i <- [1 .. 9]
-- > ]
--
-- We can now put the whole configuration together with the following:
--
-- > main :: IO ()
-- > main = xmonad =<< myConfig
-- > main = xmonad $ def
-- > { workspaces = topicNames topicItems
-- > }
-- > `additionalKeysP` myKeys
-- | An alias for @flip replicateM_@
(>*>) :: Monad m => m a -> Int -> m ()
@@ -187,81 +239,79 @@ infix >*>
-- | 'Topic' is just an alias for 'WorkspaceId'
type Topic = WorkspaceId
-- | 'Dir' is just an alias for 'FilePath' but should points to a directory.
-- | 'Dir' is just an alias for 'FilePath', but should point to a directory.
type Dir = FilePath
-- | Here is the topic space configuration area.
data TopicConfig = TopicConfig { topicDirs :: M.Map Topic Dir
-- ^ This mapping associate a directory to each topic.
, topicActions :: M.Map Topic (X ())
-- ^ This mapping associate an action to trigger when
data TopicConfig = TopicConfig { topicDirs :: Map Topic Dir
-- ^ This mapping associates a directory to each topic.
, topicActions :: Map Topic (X ())
-- ^ This mapping associates an action to trigger when
-- switching to a given topic which workspace is empty.
, defaultTopicAction :: Topic -> X ()
-- ^ This is the default topic action.
, defaultTopic :: Topic
-- ^ This is the default topic.
-- ^ This is the default (= fallback) topic.
, maxTopicHistory :: Int
-- ^ This setups the maximum depth of topic history, usually
-- 10 is a good default since we can bind all of them using
-- numeric keypad.
-- ^ This specifies the maximum depth of the topic history;
-- usually 10 is a good default since we can bind all of
-- them using numeric keypad.
}
{-# DEPRECATED maxTopicHistory "This field will be removed in the future; history is now handled by XMonad.Hooks.WorkspaceHistory" #-}
instance Default TopicConfig where
def = TopicConfig { topicDirs = M.empty
, topicActions = M.empty
, defaultTopicAction = const (ask >>= spawn . terminal . config)
, defaultTopic = "1"
, maxTopicHistory = 10
}
defaultTopicConfig :: TopicConfig
defaultTopicConfig = TopicConfig { topicDirs = M.empty
, topicActions = M.empty
, defaultTopicAction = const (ask >>= spawn . terminal . config)
, defaultTopic = "1"
, maxTopicHistory = 10
}
-- | Return the (possibly empty) list of last focused topics.
getLastFocusedTopics :: X [Topic]
getLastFocusedTopics = workspaceHistory
{-# DEPRECATED getLastFocusedTopics "Use XMonad.Hooks.WorkspaceHistory.workspaceHistory (re-exported by this module) instead" #-}
newtype PrevTopics = PrevTopics { getPrevTopics :: [String] } deriving (Read,Show,Typeable)
instance ExtensionClass PrevTopics where
initialValue = PrevTopics []
extensionType = PersistentExtension
-- | Returns the list of last focused workspaces the empty list otherwise.
getLastFocusedTopics :: X [String]
getLastFocusedTopics = XS.gets getPrevTopics
-- | Given a 'TopicConfig', the last focused topic, and a predicate that will
-- select topics that one want to keep, this function will set the property
-- of last focused topics.
setLastFocusedTopic :: Topic -> (Topic -> Bool) -> X ()
setLastFocusedTopic w predicate =
XS.modify $ PrevTopics
. seqList . nub . (w:) . filter predicate
. getPrevTopics
where seqList xs = length xs `seq` xs
-- | Given a 'TopicConfig', a topic, and a predicate to select topics that one
-- wants to keep, this function will cons the topic in front of the list of
-- last focused topics and filter it according to the predicate. Note that we
-- prune the list in case that its length exceeds 'maxTopicHistory'.
setLastFocusedTopic :: TopicConfig -> Topic -> (Topic -> Bool) -> X ()
setLastFocusedTopic tc w predicate = do
sid <- gets $ W.screen . W.current . windowset
workspaceHistoryModify $
take (maxTopicHistory tc) . nub . filter (predicate . snd) . ((sid, w) :)
{-# DEPRECATED setLastFocusedTopic "Use XMonad.Hooks.WorkspaceHistory instead" #-}
-- | Reverse the list of "last focused topics"
reverseLastFocusedTopics :: X ()
reverseLastFocusedTopics =
XS.modify $ PrevTopics . reverse . getPrevTopics
reverseLastFocusedTopics = workspaceHistoryModify reverse
-- | This function is a variant of 'DL.pprWindowSet' which takes a topic configuration
-- and a pretty-printing record 'PP'. It will show the list of topics sorted historically
-- and highlighting topics with urgent windows.
-- | This function is a variant of 'SBPP.pprWindowSet' which takes a topic
-- configuration and a pretty-printing record 'PP'. It will show the list of
-- topics sorted historically and highlight topics with urgent windows.
pprWindowSet :: TopicConfig -> PP -> X String
pprWindowSet tg pp = do
winset <- gets windowset
urgents <- readUrgents
let empty_workspaces = map W.tag $ filter (isNothing . W.stack) $ W.workspaces winset
maxDepth = maxTopicHistory tg
setLastFocusedTopic (W.tag . W.workspace . W.current $ winset)
(`notElem` empty_workspaces)
lastWs <- getLastFocusedTopics
let depth topic = fromJust $ elemIndex topic (lastWs ++ [topic])
add_depth proj topic = proj pp . (((topic++":")++) . show) . depth $ topic
pp' = pp { ppHidden = add_depth ppHidden, ppVisible = add_depth ppVisible }
sortWindows = take maxDepth . sortBy (comparing $ depth . W.tag)
return $ DL.pprWindowSet sortWindows urgents pp' winset
winset <- gets windowset
urgents <- readUrgents
let empty_workspaces = map W.tag $ filter (isNothing . W.stack) $ W.workspaces winset
maxDepth = maxTopicHistory tg
setLastFocusedTopic tg
(W.tag . W.workspace . W.current $ winset)
(`notElem` empty_workspaces)
lastWs <- workspaceHistory
let depth topic = fromJust $ elemIndex topic (lastWs ++ [topic])
add_depth proj topic = proj pp . (((topic++":")++) . show) . depth $ topic
pp' = pp { ppHidden = add_depth ppHidden, ppVisible = add_depth ppVisible }
sortWindows = take maxDepth . sortOn (depth . W.tag)
return $ SBPP.pprWindowSet sortWindows urgents pp' winset
-- | Given a prompt configuration and a topic configuration, triggers the action associated with
-- | Given a prompt configuration and a topic configuration, trigger the action associated with
-- the topic given in prompt.
topicActionWithPrompt :: XPConfig -> TopicConfig -> X ()
topicActionWithPrompt xp tg = workspacePrompt xp (liftM2 (>>) (switchTopic tg) (topicAction tg))
topicActionWithPrompt xp tg = workspacePrompt xp (liftA2 (>>) (switchTopic tg) (topicAction tg))
-- | Given a configuration and a topic, triggers the action associated with the given topic.
-- | Given a configuration and a topic, trigger the action associated with the given topic.
topicAction :: TopicConfig -> Topic -> X ()
topicAction tg topic = fromMaybe (defaultTopicAction tg topic) $ M.lookup topic $ topicActions tg
@@ -271,46 +321,94 @@ currentTopicAction tg = topicAction tg =<< gets (W.tag . W.workspace . W.current
-- | Switch to the given topic.
switchTopic :: TopicConfig -> Topic -> X ()
switchTopic tg topic = do
switchTopic tc topic = do
-- Switch to topic and add it to the last seen topics
windows $ W.greedyView topic
-- If applicable, execute the topic action
wins <- gets (W.integrate' . W.stack . W.workspace . W.current . windowset)
when (null wins) $ topicAction tg topic
when (null wins) $ topicAction tc topic
-- | Switch to the Nth last focused topic or failback to the 'defaultTopic'.
-- | Switch to the Nth last focused topic or fall back to the 'defaultTopic'.
switchNthLastFocused :: TopicConfig -> Int -> X ()
switchNthLastFocused tg depth = do
lastWs <- getLastFocusedTopics
switchTopic tg $ (lastWs ++ repeat (defaultTopic tg)) !! depth
switchNthLastFocused = switchNthLastFocusedExclude []
-- | Shift the focused window to the Nth last focused topic, or fallback to doing nothing.
-- | Like 'switchNthLastFocused', but also filter out certain topics.
switchNthLastFocusedExclude :: [Topic] -> TopicConfig -> Int -> X ()
switchNthLastFocusedExclude excludes tc depth = do
lastWs <- filter (`notElem` excludes) <$> workspaceHistory
switchTopic tc $ (lastWs ++ repeat (defaultTopic tc)) !! depth
-- | Like 'switchNthLastFocused', but only consider topics that used to
-- be on the current screen.
--
-- For example, the following function allows one to toggle between the
-- currently focused and the last used topic, while treating different
-- screens completely independently from one another.
--
-- > toggleTopicScreen = switchNthLastFocusedByScreen myTopicConfig 1
switchNthLastFocusedByScreen :: TopicConfig -> Int -> X ()
switchNthLastFocusedByScreen tc depth = do
sid <- gets $ W.screen . W.current . windowset
sws <- fromMaybe []
. listToMaybe
. map snd
. filter ((== sid) . fst)
<$> workspaceHistoryByScreen
switchTopic tc $ (sws ++ repeat (defaultTopic tc)) !! depth
-- | Shift the focused window to the Nth last focused topic, or fall back to doing nothing.
shiftNthLastFocused :: Int -> X ()
shiftNthLastFocused n = do
ws <- fmap (listToMaybe . drop n) getLastFocusedTopics
ws <- fmap (listToMaybe . drop n) workspaceHistory
whenJust ws $ windows . W.shift
-- | Returns the directory associated with current topic returns the empty string otherwise.
currentTopicDir :: TopicConfig -> X String
-- | Return the directory associated with the current topic, or return the empty
-- string if the topic could not be found.
currentTopicDir :: TopicConfig -> X FilePath
currentTopicDir tg = do
topic <- gets (W.tag . W.workspace . W.current . windowset)
return . fromMaybe "" . M.lookup topic $ topicDirs tg
-- | Check the given topic configuration for duplicates topics or undefined topics.
-- | Check the given topic configuration for duplicate or undefined topics.
checkTopicConfig :: [Topic] -> TopicConfig -> IO ()
checkTopicConfig tags tg = do
-- tags <- gets $ map W.tag . workspaces . windowset
-- tags <- gets $ map W.tag . workspaces . windowset
let
seenTopics = nub $ sort $ M.keys (topicDirs tg) ++ M.keys (topicActions tg)
dups = tags \\ nub tags
diffTopic = seenTopics \\ sort tags
check lst msg = unless (null lst) $ xmessage $ msg ++ " (tags): " ++ show lst
let
seenTopics = nub $ sort $ M.keys (topicDirs tg) ++ M.keys (topicActions tg)
dups = tags \\ nub tags
diffTopic = seenTopics \\ sort tags
check lst msg = unless (null lst) $ xmessage $ msg ++ " (tags): " ++ show lst
check diffTopic "Seen but missing topics/workspaces"
check dups "Duplicate topics/workspaces"
check diffTopic "Seen but missing topics/workspaces"
check dups "Duplicate topics/workspaces"
-- | Display the given message using the @xmessage@ program.
xmessage :: String -> IO ()
xmessage s = do
h <- spawnPipe "xmessage -file -"
hPutStr h s
hClose h
-- | Convenience type for specifying topics.
data TopicItem = TI
{ tiName :: !Topic -- ^ 'Topic' ≡ 'String'
, tiDir :: !Dir -- ^ Directory associated with topic; 'Dir' ≡ 'String'
, tiAction :: !(X ()) -- ^ Startup hook when topic is empty
}
-- | Extract the names from a given list of 'TopicItem's.
topicNames :: [TopicItem] -> [Topic]
topicNames = map tiName
-- | From a list of 'TopicItem's, build a map that can be supplied as
-- the 'topicDirs'.
tiDirs :: [TopicItem] -> Map Topic Dir
tiDirs = M.fromList . map (\TI{ tiName, tiDir } -> (tiName, tiDir))
-- | From a list of 'TopicItem's, build a map that can be supplied as
-- the 'topicActions'.
tiActions :: [TopicItem] -> Map Topic (X ())
tiActions = M.fromList . map (\TI{ tiName, tiAction } -> (tiName, tiAction))
-- | Associate a directory with the topic, but don't spawn anything.
noAction :: Topic -> Dir -> TopicItem
noAction n d = TI n d (pure ())
-- | Topic with @tiDir = ~/@.
inHome :: Topic -> X () -> TopicItem
inHome n = TI n "."

View File

@@ -0,0 +1,677 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE LambdaCase #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.TreeSelect
-- Description : Display workspaces or actions in a tree-like format.
-- 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
, def
-- * Navigation
-- $navigation
, defaultNavigation
, select
, cancel
, moveParent
, moveChild
, moveNext
, movePrev
, moveHistBack
, moveHistForward
, moveTo
-- * Advanced usage
-- $advusage
, TSNode(..)
, treeselect
, treeselectAt
) where
import Control.Monad.Reader
import Control.Monad.State
import Data.Tree
import Foreign (shiftL, shiftR, (.&.))
import System.IO
import XMonad hiding (liftX)
import XMonad.Prelude
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 qualified Data.List.NonEmpty as NE
import Graphics.X11.Xrender
import Graphics.X11.Xft
#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 $ def { ...
-- > , 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 'def'
--
-- > 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
-- > }
-- $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
-- green = 0xff00ff00
-- blue = 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
{-# DEPRECATED tsDefaultConfig "Use def (from Data.Default, and re-exported by XMonad.Actions.TreeSelect) instead." #-}
-- | 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
w <- createWindow display rootw rect_x rect_y rect_width rect_height 0 (visualInfo_depth vinfo) inputOutput (visualInfo_visual vinfo) (cWColormap .|. cWBorderPixel .|. cWBackPixel) attributes
setClassHint display w (ClassHint "xmonad-tree_select" "xmonad")
pure w
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
xmessage msg
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 >>= \case
Just a -> void a
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 = gets (Just . (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 .|. buttonPressMask) e
ev <- getEvent e
if | ev_event_type ev == keyPress -> do
ks <- keycodeToKeysym d (ev_keycode ev) 0
return $ do
mask <- liftX $ cleanKeyMask <*> pure (ev_state ev)
f <- asks ts_navigate
fromMaybe navigate $ M.lookup (mask, ks) f
| ev_event_type ev == buttonPress -> do
-- See XMonad.Prompt Note [Allow ButtonEvents]
allowEvents d replayPointer currentTime
return navigate
| otherwise -> 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 + ts_originX) (iy * ts_node_height + ts_originY)
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 fnts -> do
withXftDraw display window visual colormap $
\ft_draw -> withXftColorValue display visual colormap (fromARGB col) $
#if MIN_VERSION_X11_xft(0, 3, 4)
\ft_color -> xftDrawStringFallback ft_draw ft_color (NE.toList fnts) (fi x) (fi y) text
#else
\ft_color -> xftDrawString ft_draw ft_color (NE.head fnts) x y text
#endif
-- | Convert 'Pixel' to 'XRenderColor'
--
-- Note that it uses short to represent its components
fromARGB :: Pixel -> XRenderColor
fromARGB x =
#if MIN_VERSION_X11_xft(0, 3, 3)
XRenderColor r g b a
#else
-- swapped green/blue as a workaround for the faulty Storable instance in X11-xft < 0.3.3
XRenderColor r b g a
#endif
where
r = fromIntegral $ 0xff00 .&. shiftR x 8
g = fromIntegral $ 0xff00 .&. x
b = fromIntegral $ 0xff00 .&. shiftL x 8
a = fromIntegral $ 0xff00 .&. shiftR x 16
#endif

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.UpdateFocus
-- Description : Updates the focus on mouse move in unfocused windows.
-- Copyright : (c) Daniel Schoepe
-- License : BSD3-style (see LICENSE)
--
@@ -16,20 +17,20 @@ module XMonad.Actions.UpdateFocus (
-- * Usage
-- $usage
focusOnMouseMove,
adjustEventInput
adjustEventInput,
focusUnderPointer,
) where
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import Control.Monad (when)
import Data.Monoid
-- $usage
-- To make the focus update on mouse movement within an unfocused window, add the
-- following to your @~\/.xmonad\/xmonad.hs@:
-- following to your @xmonad.hs@:
--
-- > import XMonad.Actions.UpdateFocus
-- > xmonad $ defaultConfig {
-- > xmonad $ def {
-- > ..
-- > startupHook = adjustEventInput
-- > handleEventHook = focusOnMouseMove
@@ -40,7 +41,7 @@ import Data.Monoid
-- | Changes the focus if the mouse is moved within an unfocused window.
focusOnMouseMove :: Event -> X All
focusOnMouseMove (MotionEvent { ev_x = x, ev_y = y, ev_window = root }) = do
focusOnMouseMove MotionEvent{ ev_x = x, ev_y = y, ev_window = root } = do
-- check only every 15 px to avoid excessive calls to translateCoordinates
when (x `mod` 15 == 0 || y `mod` 15 == 0) $ do
dpy <- asks display
@@ -57,4 +58,26 @@ adjustEventInput = withDisplay $ \dpy -> do
rootw <- asks theRoot
io $ selectInput dpy rootw $ substructureRedirectMask .|. substructureNotifyMask
.|. enterWindowMask .|. leaveWindowMask .|. structureNotifyMask
.|. buttonPressMask .|. pointerMotionMask
.|. buttonPressMask .|. pointerMotionMask
-- | Focus the window under the mouse pointer, unless we're currently changing
-- focus with the mouse or dragging. This is the inverse to
-- "XMonad.Actions.UpdatePointer": instead of moving the mouse pointer to
-- match the focus, we change the focus to match the mouse pointer.
--
-- This is meant to be used together with
-- 'XMonad.Actions.UpdatePointer.updatePointer' in individual key bindings.
-- Bindings that change focus should invoke
-- 'XMonad.Actions.UpdatePointer.updatePointer' at the end, bindings that
-- switch workspaces or change layouts should call 'focusUnderPointer' at the
-- end. Neither should go to 'logHook', as that would override the other.
--
-- This is more finicky to set up than 'focusOnMouseMove', but ensures that
-- focus is updated immediately, without having to touch the mouse.
focusUnderPointer :: X ()
focusUnderPointer = whenX (not <$> (asks mouseFocused <||> gets (isJust . dragging))) $ do
dpy <- asks display
root <- asks theRoot
(_, _, w', _, _, _, _, _) <- io $ queryPointer dpy root
w <- gets (W.peek . windowset)
when (w' /= none && Just w' /= w) (focus w')

View File

@@ -1,7 +1,9 @@
{-# LANGUAGE ScopedTypeVariables #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.UpdatePointer
-- Copyright : (c) Robert Marlow <robreim@bobturf.org>
-- Description : Causes the pointer to follow whichever window focus changes to.
-- Copyright : (c) Robert Marlow <robreim@bobturf.org>, 2015 Evgeny Kurnevsky
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Robert Marlow <robreim@bobturf.org>
@@ -19,87 +21,94 @@ module XMonad.Actions.UpdatePointer
-- * Usage
-- $usage
updatePointer
, PointerPosition (..)
)
where
import XMonad
import XMonad.Util.XUtils (fi)
import Control.Monad
import XMonad.Prelude
import XMonad.StackSet (member, peek, screenDetail, current)
import Data.Maybe
import Control.Arrow ((&&&), (***))
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Actions.UpdatePointer
--
-- Enable it by including it in your logHook definition. Eg:
-- Enable it by including it in your logHook definition, e.g.:
--
-- > logHook = updatePointer Nearest
-- > logHook = updatePointer (0.5, 0.5) (1, 1)
--
-- which will move the pointer to the nearest point of a newly focused window, or
-- which will move the pointer to the nearest point of a newly focused
-- window. The first argument establishes a reference point within the
-- newly-focused window, while the second argument linearly interpolates
-- between said reference point and the edges of the newly-focused window to
-- obtain a bounding box for the pointer.
--
-- > logHook = updatePointer (Relative 0.5 0.5)
--
-- which will move the pointer to the center of a newly focused window.
-- > logHook = updatePointer (0.5, 0.5) (0, 0) -- exact centre of window
-- > logHook = updatePointer (0.25, 0.25) (0.25, 0.25) -- near the top-left
-- > logHook = updatePointer (0.5, 0.5) (1.1, 1.1) -- within 110% of the edge
--
-- To use this with an existing logHook, use >> :
--
-- > logHook = dynamicLog
-- > >> updatePointer (Relative 1 1)
-- > >> updatePointer (1, 1) (0, 0)
--
-- which moves the pointer to the bottom-right corner of the focused window.
data PointerPosition = Nearest | Relative Rational Rational | TowardsCentre Rational Rational
deriving (Read,Show)
-- | Update the pointer's location to the currently focused
-- window or empty screen unless it's already there, or unless the user was changing
-- focus with the mouse
updatePointer :: PointerPosition -> X ()
updatePointer p = do
--
-- See also 'XMonad.Actions.UpdateFocus.focusUnderPointer' for an inverse
-- operation that updates the focus instead. The two can be combined in a
-- single config if neither goes into 'logHook' but are invoked explicitly in
-- individual key bindings.
updatePointer :: (Rational, Rational) -> (Rational, Rational) -> X ()
updatePointer refPos ratio = do
ws <- gets windowset
dpy <- asks display
let defaultRect = screenRect $ screenDetail $ current ws
rect <- case peek ws of
Nothing -> return $ (screenRect . screenDetail .current) ws
Just w -> windowAttributesToRectangle `fmap` io (getWindowAttributes dpy w)
Nothing -> return defaultRect
Just w -> maybe defaultRect windowAttributesToRectangle
<$> safeGetWindowAttributes w
root <- asks theRoot
mouseIsMoving <- asks mouseFocused
(_sameRoot,_,currentWindow,rootx,rooty,_,_,_) <- io $ queryPointer dpy root
(_sameRoot,_,currentWindow,rootX,rootY,_,_,_) <- io $ queryPointer dpy root
drag <- gets dragging
unless (pointWithin (fi rootx) (fi rooty) rect
unless (pointWithin (fi rootX) (fi rootY) rect
|| mouseIsMoving
|| isJust drag
|| not (currentWindow `member` ws || currentWindow == none)) $
case p of
Nearest -> do
let x = moveWithin (fi rootx) (rect_x rect) (fi (rect_x rect) + fi (rect_width rect))
y = moveWithin (fi rooty) (rect_y rect) (fi (rect_y rect) + fi (rect_height rect))
io $ warpPointer dpy none root 0 0 0 0 x y
TowardsCentre xfrc yfrc -> do
let cx = fi (rect_width rect) / 2 + fi (rect_x rect)
cy = fi (rect_height rect) / 2 + fi (rect_y rect)
x,y,cx,cy :: Rational
x = moveWithin (fi rootx) (fi $ rect_x rect) (fi (rect_x rect) + fi (rect_width rect))
y = moveWithin (fi rooty) (fi $ rect_y rect) (fi (rect_y rect) + fi (rect_height rect))
io $ warpPointer dpy none root 0 0 0 0 (round $ x + xfrc*(cx-x)) (round $ y + yfrc*(cy-y))
Relative h v ->
io $ warpPointer dpy none root 0 0 0 0
(rect_x rect + fraction h (rect_width rect))
(rect_y rect + fraction v (rect_height rect))
where fraction x y = floor (x * fromIntegral y)
|| not (currentWindow `member` ws || currentWindow == none)) $ let
-- focused rectangle
(rectX, rectY) = (rect_x &&& rect_y) rect
(rectW, rectH) = (fi . rect_width &&& fi . rect_height) rect
-- reference position, with (0,0) and (1,1) being top-left and bottom-right
refX = lerp (fst refPos) rectX (rectX + rectW)
refY = lerp (snd refPos) rectY (rectY + rectH)
-- final pointer bounds, lerped *outwards* from reference position
boundsX = join (***) (lerp (fst ratio) refX) (rectX, rectX + rectW)
boundsY = join (***) (lerp (snd ratio) refY) (rectY, rectY + rectH)
-- ideally we ought to move the pointer in a straight line towards the
-- reference point until it is within the above bounds, but…
in io $ warpPointer dpy none root 0 0 0 0
(round . clip boundsX $ fi rootX)
(round . clip boundsY $ fi rootY)
windowAttributesToRectangle :: WindowAttributes -> Rectangle
windowAttributesToRectangle wa = Rectangle (fi (wa_x wa))
(fi (wa_y wa))
(fi (wa_width wa + 2 * wa_border_width wa))
(fi (wa_height wa + 2 * wa_border_width wa))
moveWithin :: Ord a => a -> a -> a -> a
moveWithin now lower upper =
if now < lower
then lower
else if now > upper
then upper
else now
lerp :: (RealFrac r, Real a, Real b) => r -> a -> b -> r
lerp r a b = (1 - r) * realToFrac a + r * realToFrac b
clip :: Ord a => (a, a) -> a -> a
clip (lower, upper) x
| x < lower = lower
| x > upper = upper
| otherwise = x

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Warp
-- Description : Warp the pointer to a given window or screen.
-- Copyright : (c) daniel@wagner-home.com
-- License : BSD3-style (see LICENSE)
--
@@ -22,12 +23,12 @@ module XMonad.Actions.Warp (
warpToWindow
) where
import Data.List
import XMonad.Prelude
import XMonad
import XMonad.StackSet as W
{- $usage
You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
You can use this module with the following in your @xmonad.hs@:
> import XMonad.Actions.Warp
@@ -44,7 +45,7 @@ Note that warping to a particular screen may change the focus.
-}
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
data Corner = UpperLeft | UpperRight | LowerLeft | LowerRight
@@ -90,18 +91,16 @@ warp w x y = withDisplay $ \d -> io $ warpPointer d none w 0 0 0 0 x y
-- | Warp the pointer to a given position relative to the currently
-- focused window. Top left = (0,0), bottom right = (1,1).
warpToWindow :: Rational -> Rational -> X ()
warpToWindow h v =
withDisplay $ \d ->
withFocused $ \w -> do
wa <- io $ getWindowAttributes d w
warp w (fraction h (wa_width wa)) (fraction v (wa_height wa))
warpToWindow h v = withDisplay $ \d -> withFocused $ \w ->
withWindowAttributes d w $ \wa ->
warp w (fraction h (wa_width wa)) (fraction v (wa_height wa))
-- | Warp the pointer to the given position (top left = (0,0), bottom
-- right = (1,1)) on the given screen.
warpToScreen :: ScreenId -> Rational -> Rational -> X ()
warpToScreen n h v = do
root <- asks theRoot
(StackSet {current = x, visible = xs}) <- gets windowset
StackSet{current = x, visible = xs} <- gets windowset
whenJust (fmap (screenRect . W.screenDetail) . find ((n==) . W.screen) $ x : xs)
$ \r ->
warp root (rect_x r + fraction h (rect_width r))

View File

@@ -1,6 +1,8 @@
{-# LANGUAGE TupleSections #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WindowBringer
-- Description : Dmenu operations to bring windows to you, and bring you to windows.
-- Copyright : Devin Mullins <me@twifkak.com>
-- License : BSD-style (see LICENSE)
--
@@ -17,24 +19,24 @@
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, windowAppMap, windowMap', bringWindow, actionMenu
) where
import Data.Char (toLower)
import Control.Monad
import qualified Data.Map as M
import qualified XMonad.StackSet as W
import XMonad
import qualified XMonad as X
import XMonad.Util.Dmenu (menuMapArgs)
import XMonad.Util.NamedWindows (getName)
import XMonad.Util.NamedWindows (getName, getNameWMClass)
-- $usage
--
-- Import the module into your @~\/.xmonad\/xmonad.hs@:
-- Import the module into your @xmonad.hs@:
--
-- > import XMonad.Actions.WindowBringer
--
@@ -44,56 +46,78 @@ import XMonad.Util.NamedWindows (getName)
-- > , ((modm .|. shiftMask, xK_b ), bringMenu)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | 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
, windowFilter :: Window -> X Bool -- ^ Filter function to decide which windows to consider
}
instance Default WindowBringerConfig where
def = WindowBringerConfig{ menuCommand = "dmenu"
, menuArgs = ["-i"]
, windowTitler = decorateName
, windowFilter = \_ -> return True
}
-- | 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 +125,43 @@ 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 c@WindowBringerConfig{ menuCommand = cmd, menuArgs = args } action =
windowMap' c >>= 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
ws <- gets X.windowset
M.fromList `fmap` concat `fmap` 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
windowMap = windowMap' def
-- | A map from application executable names to Windows.
windowAppMap :: X (M.Map String Window)
windowAppMap = windowMap' def { windowTitler = decorateAppName }
-- | A map from window names to Windows, given a windowTitler function.
windowMap' :: WindowBringerConfig -> X (M.Map String Window)
windowMap' WindowBringerConfig{ windowTitler = titler, windowFilter = include } = do
windowSet <- gets X.windowset
M.fromList . concat <$> mapM keyValuePairs (W.workspaces windowSet)
where keyValuePairs ws = let wins = W.integrate' (W.stack ws)
in mapM (keyValuePair ws) =<< filterM include wins
keyValuePair ws w = (, 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 ++ "]"
-- | Returns the window name as will be listed in dmenu. This will
-- return the executable name of the window along with it's workspace
-- ID.
decorateAppName :: X.WindowSpace -> Window -> X String
decorateAppName ws w = do
name <- show <$> getNameWMClass w
return $ name ++ " [" ++ W.tag ws ++ "]"

View File

@@ -1,5 +1,8 @@
{-# LANGUAGE ViewPatterns #-}
{- |
Module : XMonad.Actions.WindowGo
Description : Operations for raising (traveling to) windows.
License : Public domain
Maintainer : <gwern0@gmail.com>
@@ -21,6 +24,7 @@ module XMonad.Actions.WindowGo (
runOrRaiseNext,
raiseMaybe,
raiseNextMaybe,
raiseNextMaybeCustomFocus,
raiseBrowser,
raiseEditor,
@@ -35,19 +39,20 @@ module XMonad.Actions.WindowGo (
module XMonad.ManageHook
) where
import Control.Monad
import Data.Char (toLower)
import Data.Monoid
import XMonad (Query(), X(), ManageHook, withWindowSet, runQuery, liftIO, ask)
import qualified Data.List as L (nub,sortBy)
import XMonad.Prelude
import XMonad (Query(), X(), ManageHook, WindowSet, withWindowSet, runQuery, liftIO, ask)
import Graphics.X11 (Window)
import XMonad.ManageHook
import XMonad.Operations (windows)
import XMonad.Prompt.Shell (getBrowser, getEditor)
import qualified XMonad.StackSet as W (allWindows, peek, swapMaster, focusWindow)
import qualified XMonad.StackSet as W (peek, swapMaster, focusWindow, workspaces, StackSet, Workspace, integrate', tag, stack)
import XMonad.Util.Run (safeSpawnProg)
import qualified Data.List.NonEmpty as NE
{- $usage
Import the module into your @~\/.xmonad\/xmonad.hs@:
Import the module into your @xmonad.hs@:
> import XMonad.Actions.WindowGo
@@ -63,14 +68,23 @@ appropriate one, or cover your bases by using instead something like:
> (className =? "Firefox" <||> className =? "Firefox-bin")
For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings". -}
<https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-}
-- | Get the list of workspaces sorted by their tag
workspacesSorted :: Ord i => W.StackSet i l a s sd -> [W.Workspace i l a]
workspacesSorted s = L.sortBy (\u t -> W.tag u `compare` W.tag t) $ W.workspaces s
-- | Get a list of all windows in the 'StackSet' with an absolute ordering of workspaces
allWindowsSorted :: Ord i => Eq a => W.StackSet i l a s sd -> [a]
allWindowsSorted = L.nub . concatMap (W.integrate' . W.stack) . workspacesSorted
-- | If windows that satisfy the query exist, apply the supplied
-- function to them, otherwise run the action given as
-- second parameter.
ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X ()
ifWindows qry f el = withWindowSet $ \wins -> do
matches <- filterM (runQuery qry) $ W.allWindows wins
matches <- filterM (runQuery qry) $ allWindowsSorted wins
case matches of
[] -> el
ws -> f ws
@@ -78,7 +92,10 @@ ifWindows qry f el = withWindowSet $ \wins -> do
-- | The same as ifWindows, but applies a ManageHook to the first match
-- instead and discards the other matches
ifWindow :: Query Bool -> ManageHook -> X () -> X ()
ifWindow qry mh = ifWindows qry (windows . appEndo <=< runQuery mh . head)
ifWindow qry mh = ifWindows qry (windows . appEndo <=< runQuery mh . NE.head . notEmpty)
-- ifWindows guarantees that the list given to the function is
-- non-empty. This should really use Data.List.NonEmpty, but, alas,
-- that would be a breaking change.
{- | 'action' is an executable to be run via 'safeSpawnProg' (of "XMonad.Util.Run") if the Window cannot be found.
Presumably this executable is the same one that you were looking for.
@@ -137,16 +154,24 @@ 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
Just w | w `elem` ws ->
let (notEmpty -> _ :| (notEmpty -> y :| _)) = dropWhile (/=w) $ cycle ws
-- cannot fail to match
in windows $ focusFn y
_ -> windows . focusFn . NE.head . notEmpty $ ws
-- ws is non-empty by ifWindows's definition.
-- | 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 +192,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 +208,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

@@ -1,6 +1,7 @@
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WindowMenu
-- Description : Display window management actions in the center of the focused window.
-- Copyright : (c) Jan Vornberger 2009
-- License : BSD3-style (see LICENSE)
--
@@ -28,12 +29,12 @@ import XMonad
import qualified XMonad.StackSet as W
import XMonad.Actions.GridSelect
import XMonad.Layout.Maximize
import XMonad.Layout.Minimize
import XMonad.Util.XUtils (fi)
import XMonad.Actions.Minimize
import XMonad.Prelude (fi)
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.WindowMenu
--
@@ -50,9 +51,9 @@ colorizer _ isFg = do
else (nBC, fBC)
windowMenu :: X ()
windowMenu = withFocused $ \w -> do
windowMenu = withFocused $ \w -> withDisplay $ \d -> withWindowAttributes d w $ \wa -> do
tags <- asks (workspaces . config)
Rectangle x y wh ht <- getSize w
let Rectangle x y wh ht = getSize wa
Rectangle sx sy swh sht <- gets $ screenRect . W.screenDetail . W.current . windowset
let originFractX = (fi x - fi sx + fi wh / 2) / fi swh
originFractY = (fi y - fi sy + fi ht / 2) / fi sht
@@ -68,12 +69,10 @@ windowMenu = withFocused $ \w -> do
| tag <- tags ]
runSelectedAction gsConfig actions
getSize :: Window -> X (Rectangle)
getSize w = do
d <- asks display
wa <- io $ getWindowAttributes d w
getSize :: WindowAttributes -> Rectangle
getSize wa =
let x = fi $ wa_x wa
y = fi $ wa_y wa
wh = fi $ wa_width wa
ht = fi $ wa_height wa
return (Rectangle x y wh ht)
in Rectangle x y wh ht

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WindowNavigation
-- Description : Experimental rewrite of "XMonad.Layout.WindowNavigation".
-- Copyright : (c) 2007 David Roundy <droundy@darcs.net>,
-- Devin Mullins <me@twifkak.com>
-- Maintainer : Devin Mullins <me@twifkak.com>
@@ -40,17 +41,14 @@ module XMonad.Actions.WindowNavigation (
) where
import XMonad
import XMonad.Prelude (catMaybes, fromMaybe, listToMaybe, sortOn)
import XMonad.Util.Types (Direction2D(..))
import qualified XMonad.StackSet as W
import Control.Applicative ((<$>))
import Control.Arrow (second)
import Data.IORef
import Data.List (sortBy)
import Data.Map (Map())
import qualified Data.Map as M
import Data.Maybe (catMaybes, fromMaybe, listToMaybe)
import Data.Ord (comparing)
import qualified Data.Set as S
-- $usage
@@ -62,9 +60,14 @@ import qualified Data.Set as S
--
-- > main = do
-- > config <- withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
-- > $ defaultConfig { ... }
-- > $ def { ... }
-- > xmonad config
--
-- Or, for the brave souls:
--
-- > main = xmonad =<< withWindowNavigation (xK_w, xK_a, xK_s, xK_d)
-- > $ def { ... }
--
-- Here, we pass in the keys for navigation in counter-clockwise order from up.
-- It creates keybindings for @modMask@ to move to window, and @modMask .|. shiftMask@
-- to swap windows.
@@ -124,10 +127,13 @@ swap = withTargetWindow swapWithFocused
Just currentWin -> W.focusWindow currentWin $
mapWindows (swapWin currentWin targetWin) winSet
Nothing -> winSet
mapWindows f ss = W.mapWorkspace (mapWindows' f) ss
mapWindows' f ws@(W.Workspace { W.stack = s }) = ws { W.stack = mapWindows'' f <$> s }
mapWindows f = W.mapWorkspace (mapWindows' f)
mapWindows' f ws@W.Workspace{ W.stack = s } = ws { W.stack = mapWindows'' f <$> s }
mapWindows'' f (W.Stack focused up down) = W.Stack (f focused) (map f up) (map f down)
swapWin win1 win2 win = if win == win1 then win2 else if win == win2 then win1 else win
swapWin win1 win2 win
| win == win1 = win2
| win == win2 = win1
| otherwise = win
withTargetWindow :: (Window -> WindowSet -> WindowSet) -> IORef WNState -> Direction2D -> X ()
withTargetWindow adj posRef dir = fromCurrentPoint posRef $ \win pos -> do
@@ -137,11 +143,11 @@ withTargetWindow adj posRef dir = fromCurrentPoint posRef $ \win pos -> do
setPosition posRef pos targetRect
trackMovement :: IORef WNState -> X ()
trackMovement posRef = fromCurrentPoint posRef $ \win pos -> do
trackMovement posRef = fromCurrentPoint posRef $ \win pos ->
windowRect win >>= flip whenJust (setPosition posRef pos . snd)
fromCurrentPoint :: IORef WNState -> (Window -> Point -> X ()) -> X ()
fromCurrentPoint posRef f = withFocused $ \win -> do
fromCurrentPoint posRef f = withFocused $ \win ->
currentPosition posRef >>= f win
-- Gets the current position from the IORef passed in, or if nothing (say, from
@@ -193,7 +199,7 @@ windowRects = fmap catMaybes . mapM windowRect . S.toList =<< gets mapped
windowRect :: Window -> X (Maybe (Window, Rectangle))
windowRect win = withDisplay $ \dpy -> do
(_, x, y, w, h, bw, _) <- io $ getGeometry dpy win
return $ Just $ (win, Rectangle x y (w + 2 * bw) (h + 2 * bw))
return $ Just (win, Rectangle x y (w + 2 * bw) (h + 2 * bw))
`catchX` return Nothing
-- Modified from droundy's implementation of WindowNavigation:
@@ -203,13 +209,13 @@ inr D (Point px py) (Rectangle rx ry w h) = px >= rx && px < rx + fromIntegral w
py < ry + fromIntegral h
inr U (Point px py) (Rectangle rx ry w _) = px >= rx && px < rx + fromIntegral w &&
py > ry
inr R (Point px py) (Rectangle rx ry _ h) = px < rx &&
inr R (Point px py) (Rectangle rx ry w h) = px < rx + fromIntegral w &&
py >= ry && py < ry + fromIntegral h
inr L (Point px py) (Rectangle rx ry w h) = px > rx + fromIntegral w &&
inr L (Point px py) (Rectangle rx ry _ h) = px > rx &&
py >= ry && py < ry + fromIntegral h
sortby :: Direction2D -> [(a,Rectangle)] -> [(a,Rectangle)]
sortby D = sortBy $ comparing (rect_y . snd)
sortby R = sortBy $ comparing (rect_x . snd)
sortby D = sortOn (rect_y . snd)
sortby R = sortOn (rect_x . snd)
sortby U = reverse . sortby D
sortby L = reverse . sortby R

View File

@@ -1,28 +1,30 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WithAll
-- Description : Perform a given action on all or certain groups of windows.
-- License : BSD3-style (see LICENSE)
-- Stability : unstable
-- Portability : unportable
--
-- Provides functions for performing a given action on all windows of
-- the current workspace.
-- Provides functions for performing a given action on all or certain
-- groups of windows on the current workspace.
-----------------------------------------------------------------------------
module XMonad.Actions.WithAll (
-- * Usage
-- $usage
sinkAll, withAll,
withAll', killAll) where
withAll', killAll,
killOthers) where
import Data.Foldable hiding (foldr)
import XMonad.Prelude hiding (foldr)
import XMonad
import XMonad.StackSet
-- $usage
--
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.WithAll
--
@@ -31,7 +33,7 @@ import XMonad.StackSet
-- , ((modm .|. shiftMask, xK_t), sinkAll)
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Un-float all floating windows on the current workspace.
sinkAll :: X ()
@@ -49,4 +51,8 @@ withAll f = withWindowSet $ \ws -> let all' = integrate' . stack . workspace . c
-- | Kill all the windows on the current workspace.
killAll :: X()
killAll = withAll killWindow
killAll = withAll killWindow
-- | Kill all the unfocused windows on the current workspace.
killOthers :: X ()
killOthers = withUnfocused killWindow

View File

@@ -1,6 +1,9 @@
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Workscreen
-- Description: Display a set of workspaces on several screens.
-- Copyright : (c) 2012 kedals0
-- License : BSD3-style (see LICENSE)
--
@@ -20,7 +23,6 @@
-- 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.
-----------------------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
module XMonad.Actions.Workscreen (
-- * Usage
@@ -31,15 +33,17 @@ module XMonad.Actions.Workscreen (
,shiftToWorkscreen
,fromWorkspace
,expandWorkspace
,WorkscreenId
) where
import XMonad hiding (workspaces)
import XMonad.Prelude
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Actions.OnScreen
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
-- You can use this module with the following in your @xmonad.hs@:
--
-- > import XMonad.Actions.Workscreen
-- > myWorkspaces = let myOldWorkspaces = ["adm","work","mail"]
@@ -54,26 +58,26 @@ import XMonad.Actions.OnScreen
-- > , (f, m) <- [(Workscreen.viewWorkscreen, 0), (Workscreen.shiftToWorkscreen, shiftMask)]]
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
data Workscreen = Workscreen{workscreenId::Int,workspaces::[WorkspaceId]} deriving (Show,Typeable)
data Workscreen = Workscreen{workscreenId::Int,workspaces::[WorkspaceId]} deriving (Show)
type WorkscreenId=Int
data WorkscreenStorage = WorkscreenStorage WorkscreenId [Workscreen] deriving (Show,Typeable)
data WorkscreenStorage = WorkscreenStorage WorkscreenId [Workscreen] deriving (Show)
instance ExtensionClass WorkscreenStorage where
initialValue = WorkscreenStorage 0 []
-- | Helper to group workspaces. Multiply workspace by screens number.
expandWorkspace :: Int -> [WorkspaceId] -> [WorkspaceId]
expandWorkspace nscr ws = concat $ map expandId ws
expandWorkspace nscr = concatMap expandId
where expandId wsId = let t = wsId ++ "_"
in map ((++) t . show ) [1..nscr]
-- | Create workscreen list from workspace list. Group workspaces to
-- packets of screens number size.
fromWorkspace :: Int -> [WorkspaceId] -> [Workscreen]
fromWorkspace n ws = map (\(a,b) -> Workscreen a b) $ zip [0..] (fromWorkspace' n ws)
fromWorkspace n ws = zipWith Workscreen [0..] (fromWorkspace' n ws)
fromWorkspace' :: Int -> [WorkspaceId] -> [[WorkspaceId]]
fromWorkspace' _ [] = []
fromWorkspace' n ws = take n ws : fromWorkspace' n (drop n ws)
@@ -89,7 +93,7 @@ viewWorkscreen wscrId = do (WorkscreenStorage c a) <- XS.get
let wscr = if wscrId == c
then Workscreen wscrId $ shiftWs (workspaces $ a !! wscrId)
else a !! wscrId
(x,_:ys) = splitAt wscrId a
(x, notEmpty -> _ :| ys) = splitAt wscrId a
newWorkscreenStorage = WorkscreenStorage wscrId (x ++ [wscr] ++ ys)
windows (viewWorkscreen' wscr)
XS.put newWorkscreenStorage
@@ -105,5 +109,6 @@ shiftWs a = drop 1 a ++ take 1 a
-- @WorkscreenId@.
shiftToWorkscreen :: WorkscreenId -> X ()
shiftToWorkscreen wscrId = do (WorkscreenStorage _ a) <- XS.get
let ws = head . workspaces $ a !! wscrId
windows $ W.shift ws
case workspaces (a !! wscrId) of
[] -> pure ()
(w : _) -> windows $ W.shift w

View File

@@ -1,7 +1,8 @@
{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WorkspaceCursors
-- Description : Like "XMonad.Actions.Plane" for an arbitrary number of dimensions.
-- Copyright : (c) 2009 Adam Vogt <vogt.adam@gmail.com>
-- License : BSD
--
@@ -46,14 +47,10 @@ import qualified XMonad.StackSet as W
import XMonad.Actions.FocusNth(focusNth')
import XMonad.Layout.LayoutModifier(ModifiedLayout(..),
LayoutModifier(handleMess, redoLayout))
import XMonad(Typeable, Message, WorkspaceId, X, XState(windowset),
import XMonad(Message, WorkspaceId, X, XState(windowset),
fromMessage, sendMessage, windows, gets)
import Control.Monad((<=<), guard, liftM, liftM2, when)
import Control.Applicative((<$>))
import Data.Foldable(Foldable(foldMap), toList)
import Data.Maybe(fromJust, listToMaybe)
import Data.Monoid(Monoid(mappend, mconcat))
import Data.Traversable(sequenceA)
import XMonad.Util.Stack (reverseS)
import XMonad.Prelude
-- $usage
--
@@ -61,16 +58,13 @@ import Data.Traversable(sequenceA)
--
-- > import XMonad
-- > import XMonad.Actions.WorkspaceCursors
-- > import XMonad.Hooks.DynamicLog
-- > import XMonad.Util.EZConfig
-- > import qualified XMonad.StackSet as W
-- >
-- > main = do
-- > x <- xmobar conf
-- > xmonad x
-- > main = xmonad conf
-- >
-- > conf = additionalKeysP defaultConfig
-- > { layoutHook = workspaceCursors myCursors $ layoutHook defaultConfig
-- > conf = additionalKeysP def
-- > { layoutHook = workspaceCursors myCursors $ layoutHook def
-- > , workspaces = toList myCursors } $
-- > [("M-"++shift++control++[k], f direction depth)
-- > | (f,shift) <- zip [modifyLayer,shiftModifyLayer] ["","S-"]
@@ -92,7 +86,8 @@ import Data.Traversable(sequenceA)
-- workspaces. Or change it such that workspaces are created when you try to
-- view it.
--
-- * Function for pretty printing for DynamicLog that groups workspaces by
-- * Function for pretty printing for "XMonad.Hooks.StatusBar.PP" that groups
-- workspaces by
-- common prefixes
--
-- * Examples of adding workspaces to the cursors, having them appear multiple
@@ -100,10 +95,10 @@ import Data.Traversable(sequenceA)
-- | makeCursors requires a nonempty string, and each sublist must be nonempty
makeCursors :: [[String]] -> Cursors String
makeCursors [] = error "Workspace Cursors cannot be empty"
makeCursors a = concat . reverse <$> foldl addDim x xs
where x = end $ map return $ head a
xs = map (map return) $ tail a
makeCursors [] = error "Workspace Cursors cannot be empty"
makeCursors (a : as) = concat . reverse <$> foldl addDim x xs
where x = end $ map return a
xs = map (map return) as
-- this could probably be simplified, but this true:
-- toList . makeCursors == map (concat . reverse) . sequence . reverse . map (map (:[]))
-- the strange order is used because it makes the regular M-1..9
@@ -118,7 +113,7 @@ end = Cons . fromJust . W.differentiate . map End
data Cursors a
= Cons (W.Stack (Cursors a))
| End a deriving (Eq,Show,Read,Typeable)
| End a deriving (Eq,Show,Read)
instance Foldable Cursors where
foldMap f (End x) = f x
@@ -144,7 +139,7 @@ getFocus (End x) = x
-- This could be made more efficient, if the fact that the suffixes are grouped
focusTo :: (Eq t) => t -> Cursors t -> Maybe (Cursors t)
focusTo x = listToMaybe . filter ((x==) . getFocus) . changeFocus (const True)
focusTo x = find ((x==) . getFocus) . changeFocus (const True)
-- | non-wrapping version of 'W.focusUp''
noWrapUp :: W.Stack t -> W.Stack t
@@ -153,20 +148,19 @@ noWrapUp x@(W.Stack _ [] _ ) = x
-- | non-wrapping version of 'W.focusDown''
noWrapDown :: W.Stack t -> W.Stack t
noWrapDown = reverseStack . noWrapUp . reverseStack
where reverseStack (W.Stack t ls rs) = W.Stack t rs ls
noWrapDown = reverseS . noWrapUp . reverseS
focusDepth :: Cursors t -> Int
focusDepth (Cons x) = 1 + focusDepth (W.focus x)
focusDepth (End _) = 0
descend :: Monad m =>(W.Stack (Cursors a) -> m (W.Stack (Cursors a)))-> Int-> Cursors a-> m (Cursors a)
descend f 1 (Cons x) = Cons `liftM` f x
descend f n (Cons x) | n > 1 = liftM Cons $ descend f (pred n) `onFocus` x
descend f 1 (Cons x) = Cons <$> f x
descend f n (Cons x) | n > 1 = fmap Cons $ descend f (pred n) `onFocus` x
descend _ _ x = return x
onFocus :: (Monad m) => (a1 -> m a1) -> W.Stack a1 -> m (W.Stack a1)
onFocus f st = (\x -> st { W.focus = x}) `liftM` f (W.focus st)
onFocus f st = (\x -> st { W.focus = x}) <$> f (W.focus st)
-- | @modifyLayer@ is used to change the focus at a given depth
modifyLayer :: (W.Stack (Cursors String) -> W.Stack (Cursors String)) -> Int -> X ()
@@ -192,10 +186,10 @@ modifyLayer' :: (W.Stack (Cursors String) -> X (W.Stack (Cursors String))) -> In
modifyLayer' f depth = modifyCursors (descend f depth)
modifyCursors :: (Cursors String -> X (Cursors String)) -> X ()
modifyCursors = sendMessage . ChangeCursors . (liftM2 (>>) updateXMD return <=<)
modifyCursors = sendMessage . ChangeCursors . (liftA2 (>>) updateXMD return <=<)
data WorkspaceCursors a = WorkspaceCursors (Cursors String)
deriving (Typeable,Read,Show)
newtype WorkspaceCursors a = WorkspaceCursors (Cursors String)
deriving (Read,Show)
-- | The state is stored in the 'WorkspaceCursors' layout modifier. Put this as
-- your outermost modifier, unless you want different cursors at different
@@ -203,8 +197,7 @@ data WorkspaceCursors a = WorkspaceCursors (Cursors String)
workspaceCursors :: Cursors String -> l a -> ModifiedLayout WorkspaceCursors l a
workspaceCursors = ModifiedLayout . WorkspaceCursors
data ChangeCursors = ChangeCursors { unWrap :: Cursors String -> X (Cursors String) }
deriving (Typeable)
newtype ChangeCursors = ChangeCursors { unWrap :: Cursors String -> X (Cursors String) }
instance Message ChangeCursors
@@ -219,4 +212,4 @@ instance LayoutModifier WorkspaceCursors a where
return (arrs,WorkspaceCursors <$> focusTo cws cs)
handleMess (WorkspaceCursors cs) m =
sequenceA $ fmap WorkspaceCursors . ($ cs) . unWrap <$> fromMessage m
traverse (fmap WorkspaceCursors . ($ cs) . unWrap) (fromMessage m)

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.WorkspaceNames
-- Description : Persistently rename workspace and swap them along with their names.
-- Copyright : (c) Tomas Janousek <tomi@nomi.cz>
-- License : BSD3-style (see LICENSE)
--
@@ -8,23 +9,23 @@
-- Stability : experimental
-- Portability : unportable
--
-- Provides bindings to rename workspaces, show these names in DynamicLog and
-- Provides bindings to rename workspaces, show these names in a status bar 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.
--
-----------------------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
module XMonad.Actions.WorkspaceNames (
-- * Usage
-- $usage
-- * Workspace naming
renameWorkspace,
workspaceNamesPP,
getWorkspaceNames',
getWorkspaceNames,
getWorkspaceName,
getCurrentWorkspaceName,
setWorkspaceName,
setCurrentWorkspaceName,
@@ -32,35 +33,50 @@ module XMonad.Actions.WorkspaceNames (
swapTo,
swapTo',
swapWithCurrent,
-- * Workspace prompt
workspaceNamePrompt,
-- * StatusBar, EwmhDesktops integration
workspaceNamesPP,
workspaceNamesEwmh,
) where
import XMonad
import XMonad.Prelude (fromMaybe, isInfixOf, (<&>), (>=>))
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Actions.CycleWS (findWorkspace, WSType(..), Direction1D(..))
import XMonad.Actions.CycleWS (findWorkspace, WSType(..), Direction1D(..), anyWS)
import qualified XMonad.Actions.SwapWorkspaces as Swap
import XMonad.Hooks.DynamicLog (PP(..))
import XMonad.Prompt (mkXPrompt, XPConfig)
import XMonad.Hooks.StatusBar.PP (PP(..))
import XMonad.Hooks.EwmhDesktops (addEwmhWorkspaceRename)
import XMonad.Prompt (mkXPrompt, XPConfig, historyCompletionP)
import XMonad.Prompt.Workspace (Wor(Wor))
import XMonad.Util.WorkspaceCompare (getSortByIndex)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
-- You can use this module with the following in your @xmonad.hs@ file:
--
-- > import XMonad.Actions.WorkspaceNames
--
-- Then add keybindings like the following:
--
-- > , ((modm .|. shiftMask, xK_r ), renameWorkspace defaultXPConfig)
-- > , ((modm .|. shiftMask, xK_r ), renameWorkspace def)
--
-- and apply workspaceNamesPP to your DynamicLog pretty-printer:
-- and apply workspaceNamesPP to your pretty-printer:
--
-- > myLogHook =
-- > workspaceNamesPP xmobarPP >>= dynamicLogString >>= xmonadPropLog
-- > myPP = workspaceNamesPP xmobarPP
--
-- Check "XMonad.Hooks.StatusBar" for more information on how to incorprate
-- this into your status bar.
--
-- To expose workspace names to pagers and other EWMH clients, integrate this
-- with "XMonad.Hooks.EwmhDesktops":
--
-- > main = xmonad $ … . workspaceNamesEwmh . ewmh . … $ def{…}
--
-- We also provide a modification of "XMonad.Actions.SwapWorkspaces"\'s
-- functionality, which may be used this way:
@@ -72,26 +88,38 @@ import Data.Maybe (fromMaybe)
-- > | (i, k) <- zip workspaces [xK_1 ..]]
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.
-- | Workspace names container.
newtype WorkspaceNames = WorkspaceNames (M.Map WorkspaceId String)
deriving (Typeable, Read, Show)
deriving (Read, Show)
instance ExtensionClass WorkspaceNames where
initialValue = WorkspaceNames M.empty
extensionType = PersistentExtension
-- | 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
-- | Returns a lookup function that maps workspace tags to workspace names.
getWorkspaceNames' :: X (WorkspaceId -> Maybe String)
getWorkspaceNames' = do
WorkspaceNames m <- XS.get
return $ \wks -> case M.lookup wks m of
Nothing -> wks
Just s -> wks ++ ":" ++ s
return (`M.lookup` m)
-- | Returns a function for 'ppRename' that appends @sep@ and the workspace
-- name, if set.
getWorkspaceNames :: String -> X (String -> WindowSpace -> String)
getWorkspaceNames sep = ren <$> getWorkspaceNames'
where
ren name s w = s ++ maybe "" (sep ++) (name (W.tag w))
-- | Gets the name of a workspace, if set, otherwise returns nothing.
getWorkspaceName :: WorkspaceId -> X (Maybe String)
getWorkspaceName w = ($ w) <$> getWorkspaceNames'
-- | Gets the name of the current workspace. See 'getWorkspaceName'
getCurrentWorkspaceName :: X (Maybe String)
getCurrentWorkspaceName = getWorkspaceName =<< gets (W.currentTag . windowset)
-- | Sets the name of a workspace. Empty string makes the workspace unnamed
-- again.
@@ -110,26 +138,14 @@ setCurrentWorkspaceName name = do
-- | Prompt for a new name for the current workspace and set it.
renameWorkspace :: XPConfig -> X ()
renameWorkspace conf = do
mkXPrompt pr conf (const (return [])) setCurrentWorkspaceName
where pr = Wor "Workspace name: "
-- | Modify "XMonad.Hooks.DynamicLog"\'s pretty-printing format to show
-- workspace names as well.
workspaceNamesPP :: PP -> X PP
workspaceNamesPP pp = do
names <- getWorkspaceNames
return $
pp {
ppCurrent = ppCurrent pp . names,
ppVisible = ppVisible pp . names,
ppHidden = ppHidden pp . names,
ppHiddenNoWindows = ppHiddenNoWindows pp . names,
ppUrgent = ppUrgent pp . names
}
completion <- historyCompletionP (prompt ==)
mkXPrompt (Wor prompt) conf completion setCurrentWorkspaceName
where
prompt = "Workspace name: "
-- | See 'XMonad.Actions.SwapWorkspaces.swapTo'. This is the same with names.
swapTo :: Direction1D -> X ()
swapTo dir = swapTo' dir AnyWS
swapTo dir = swapTo' dir anyWS
-- | Swap with the previous or next workspace of the given type.
swapTo' :: Direction1D -> WSType -> X ()
@@ -149,4 +165,27 @@ swapNames w1 w2 = do
WorkspaceNames m <- XS.get
let getname w = fromMaybe "" $ M.lookup w m
set w name m' = if null name then M.delete w m' else M.insert w name m'
XS.put $ WorkspaceNames $ set w1 (getname w2) $ set w2 (getname w1) $ m
XS.put $ WorkspaceNames $ set w1 (getname w2) $ set w2 (getname w1) m
-- | Same behavior than 'XMonad.Prompt.Workspace.workspacePrompt' excepted it acts on the workspace name provided by this module.
workspaceNamePrompt :: XPConfig -> (WorkspaceId -> X ()) -> X ()
workspaceNamePrompt conf job = do
myWorkspaces <- gets $ W.workspaces . windowset
myWorkspacesName <- getWorkspaceNames ":" <&> \n -> [n (W.tag w) w | w <- myWorkspaces]
let pairs = zip myWorkspacesName (map W.tag myWorkspaces)
mkXPrompt (Wor "Select workspace: ") conf
(contains myWorkspacesName)
(job . toWsId pairs)
where toWsId pairs name = fromMaybe "" (lookup name pairs)
contains completions input =
return $ filter (isInfixOf input) completions
-- | Modify 'XMonad.Hooks.StatusBar.PP.PP'\'s pretty-printing format to show
-- workspace names as well.
workspaceNamesPP :: PP -> X PP
workspaceNamesPP pp = getWorkspaceNames ":" <&> \ren -> pp{ ppRename = ppRename pp >=> ren }
-- | Tell "XMonad.Hooks.EwmhDesktops" to append workspace names to desktop
-- names.
workspaceNamesEwmh :: XConfig l -> XConfig l
workspaceNamesEwmh = addEwmhWorkspaceRename $ getWorkspaceNames ":"

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Arossato
-- Description : Andrea Rossato's xmonad configuration.
-- Copyright : (c) Andrea Rossato 2007
-- License : BSD3-style (see LICENSE)
--
@@ -15,6 +16,7 @@
------------------------------------------------------------------------
module XMonad.Config.Arossato
{-# DEPRECATED "This module contains a personal configuration, to be removed from xmonad-contrib. If you use this module, please copy the relevant parts to your configuration or obtain a copy of it on https://xmonad.org/configurations.html and include it as a local module." #-}
( -- * Usage
-- $usage
arossatoConfig
@@ -22,7 +24,7 @@ module XMonad.Config.Arossato
import qualified Data.Map as M
import XMonad hiding ( (|||) )
import XMonad
import qualified XMonad.StackSet as W
import XMonad.Actions.CycleWS
@@ -30,13 +32,11 @@ import XMonad.Hooks.DynamicLog hiding (xmobar)
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ServerMode
import XMonad.Layout.Accordion
import XMonad.Layout.LayoutCombinators
import XMonad.Layout.Magnifier
import XMonad.Layout.NoBorders
import XMonad.Layout.SimpleFloat
import XMonad.Layout.Tabbed
import XMonad.Layout.WindowArranger
import XMonad.Prompt
import XMonad.Prompt.Shell
import XMonad.Prompt.Ssh
import XMonad.Prompt.Theme
@@ -47,7 +47,7 @@ import XMonad.Util.Themes
-- $usage
-- The simplest way to use this configuration module is to use an
-- @~\/.xmonad\/xmonad.hs@ like this:
-- @xmonad.hs@ like this:
--
-- > module Main (main) where
-- >
@@ -64,7 +64,7 @@ import XMonad.Util.Themes
--
-- You can use this module also as a starting point for writing your
-- own configuration module from scratch. Save it as your
-- @~\/.xmonad\/xmonad.hs@ and:
-- @xmonad.hs@ and:
--
-- 1. Change the module name from
--
@@ -86,7 +86,7 @@ import XMonad.Util.Themes
arossatoConfig = do
xmobar <- spawnPipe "xmobar" -- REMOVE this line if you do not have xmobar installed!
return $ defaultConfig
return $ def
{ workspaces = ["home","var","dev","mail","web","doc"] ++
map show [7 .. 9 :: Int]
, logHook = myDynLog xmobar -- REMOVE this line if you do not have xmobar installed!
@@ -120,7 +120,7 @@ arossatoConfig = do
newManageHook = myManageHook
-- xmobar
myDynLog h = dynamicLogWithPP defaultPP
myDynLog h = dynamicLogWithPP def
{ ppCurrent = xmobarColor "yellow" "" . wrap "[" "]"
, ppTitle = xmobarColor "green" "" . shorten 40
, ppVisible = wrap "(" ")"
@@ -128,7 +128,7 @@ arossatoConfig = do
}
-- key bindings stuff
defKeys = keys defaultConfig
defKeys = keys def
delKeys x = foldr M.delete (defKeys x) (toRemove x)
newKeys x = foldr (uncurry M.insert) (delKeys x) (toAdd x)
-- remove some of the default key bindings
@@ -144,12 +144,12 @@ arossatoConfig = do
[(shiftMask .|. modMask x, k) | k <- [xK_1 .. xK_9]]
-- These are my personal key bindings
toAdd x =
[ ((modMask x , xK_F12 ), xmonadPrompt defaultXPConfig )
, ((modMask x , xK_F3 ), shellPrompt defaultXPConfig )
, ((modMask x , xK_F4 ), sshPrompt defaultXPConfig )
, ((modMask x , xK_F5 ), themePrompt defaultXPConfig )
, ((modMask x , xK_F6 ), windowPromptGoto defaultXPConfig )
, ((modMask x , xK_F7 ), windowPromptBring defaultXPConfig )
[ ((modMask x , xK_F12 ), xmonadPrompt def )
, ((modMask x , xK_F3 ), shellPrompt def )
, ((modMask x , xK_F4 ), sshPrompt def )
, ((modMask x , xK_F5 ), themePrompt def )
, ((modMask x , xK_F6 ), windowPrompt def Goto allWindows )
, ((modMask x , xK_F7 ), windowPrompt def Bring allWindows )
, ((modMask x , xK_comma ), prevWS )
, ((modMask x , xK_period), nextWS )
, ((modMask x , xK_Right ), windows W.focusDown )

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Azerty
-- Description : Fix some keybindings for users of French keyboard layouts.
-- Copyright : (c) Devin Mullins <me@twifkak.com>
-- License : BSD
--
@@ -17,7 +18,7 @@
module XMonad.Config.Azerty (
-- * Usage
-- $usage
azertyConfig, azertyKeys
azertyConfig, azertyKeys, belgianConfig, belgianKeys
) where
import XMonad
@@ -26,7 +27,7 @@ import qualified XMonad.StackSet as W
import qualified Data.Map as M
-- $usage
-- To use this module, start with the following @~\/.xmonad\/xmonad.hs@:
-- To use this module, start with the following @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Config.Azerty
@@ -36,13 +37,25 @@ 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 = defaultConfig { keys = azertyKeys <+> keys defaultConfig }
azertyConfig = def { keys = azertyKeys <> keys def }
azertyKeys conf@(XConfig {modMask = modm}) = M.fromList $
belgianConfig = def { keys = belgianKeys <> keys def }
azertyKeys = azertyKeysTop [0x26,0xe9,0x22,0x27,0x28,0x2d,0xe8,0x5f,0xe7,0xe0]
belgianKeys = azertyKeysTop [0x26,0xe9,0x22,0x27,0x28,0xa7,0xe8,0x21,0xe7,0xe0]
azertyKeysTop topRow conf@XConfig{modMask = modm} = M.fromList $
[((modm, xK_semicolon), sendMessage (IncMasterN (-1)))]
++
[((m .|. modm, k), windows $ f i)
| (i, k) <- zip (workspaces conf) [0x26,0xe9,0x22,0x27,0x28,0x2d,0xe8,0x5f,0xe7,0xe0],
| (i, k) <- zip (workspaces conf) topRow,
(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)]]

47
XMonad/Config/Bepo.hs Normal file
View File

@@ -0,0 +1,47 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Bepo
-- Description : Fix keybindings for the BEPO keyboard layout.
-- Copyright : (c) Yorick Laupa <yo.eight@gmail.com>
-- License : BSD
--
-- Maintainer : Yorick Laupa <yo.eight@gmail.com>
-- Stability : stable
-- Portability : unportable
--
-- This module fixes some of the keybindings for the francophone among you who
-- use a BEPO keyboard layout. Based on XMonad.Config.Azerty
module XMonad.Config.Bepo (
-- * Usage
-- $usage
bepoConfig, bepoKeys
) where
import XMonad
import qualified XMonad.StackSet as W
import qualified Data.Map as M
-- $usage
-- To use this module, start with the following @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Config.Bepo
-- >
-- > main = xmonad bepoConfig
--
-- If you prefer, an bepoKeys function is provided which you can use as so:
--
-- > import qualified Data.Map as M
-- > main = xmonad someConfig { keys = \c -> bepoKeys c `M.union` keys someConfig c }
bepoConfig = def { keys = bepoKeys <> keys def }
bepoKeys conf@XConfig { modMask = modm } = M.fromList $
((modm, xK_semicolon), sendMessage (IncMasterN (-1)))
: [((m .|. modm, k), windows $ f i)
| (i, k) <- zip (workspaces conf) [0x22,0xab,0xbb,0x28,0x29,0x40,0x2b,0x2d,0x2f,0x2a],
(f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]

View File

@@ -1,7 +1,9 @@
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS -fno-warn-missing-signatures #-}
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Bluetile
-- Description : Default configuration of [Bluetile](http://projects.haskell.org/bluetile/).
-- Copyright : (c) Jan Vornberger 2009
-- License : BSD3-style (see LICENSE)
--
@@ -24,25 +26,25 @@ module XMonad.Config.Bluetile (
bluetileConfig
) where
import XMonad hiding ( (|||) )
import XMonad
import XMonad.Layout.BorderResize
import XMonad.Layout.BoringWindows
import XMonad.Layout.BoringWindows hiding (Replace)
import XMonad.Layout.ButtonDecoration
import XMonad.Layout.Decoration
import XMonad.Layout.DecorationAddons
import XMonad.Layout.DraggingVisualizer
import XMonad.Layout.LayoutCombinators
import XMonad.Layout.Maximize
import XMonad.Layout.Minimize
import XMonad.Layout.MouseResizableTile
import XMonad.Layout.Named
import XMonad.Layout.Renamed
import XMonad.Layout.NoBorders
import XMonad.Layout.PositionStoreFloat
import XMonad.Layout.WindowSwitcherDecoration
import XMonad.Actions.BluetileCommands
import XMonad.Actions.CycleWS
import XMonad.Actions.Minimize
import XMonad.Actions.WindowMenu
import XMonad.Hooks.CurrentWorkspaceOnTop
@@ -60,11 +62,10 @@ import qualified XMonad.StackSet as W
import qualified Data.Map as M
import System.Exit
import Data.Monoid
import Control.Monad(when)
import XMonad.Prelude(when)
-- $usage
-- To use this module, start with the following @~\/.xmonad\/xmonad.hs@:
-- To use this module, start with the following @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Config.Bluetile
@@ -80,7 +81,7 @@ bluetileWorkspaces :: [String]
bluetileWorkspaces = ["1","2","3","4","5","6","7","8","9","0"]
bluetileKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
bluetileKeys conf@(XConfig {XMonad.modMask = modMask'}) = M.fromList $
bluetileKeys conf@XConfig{XMonad.modMask = modMask'} = M.fromList $
-- launching and killing programs
[ ((modMask' , xK_Return), spawn $ XMonad.terminal conf) -- %! Launch terminal
, ((modMask', xK_p ), gnomeRun) -- %! Launch Gnome "Run application" dialog
@@ -111,14 +112,14 @@ bluetileKeys conf@(XConfig {XMonad.modMask = modMask'}) = M.fromList $
-- floating layer support
, ((modMask', xK_t ), withFocused $ windows . W.sink) -- %! Push window back into tiling
, ((modMask' .|. shiftMask, xK_t ), withFocused $ float ) -- %! Float window
, ((modMask' .|. shiftMask, xK_t ), withFocused float ) -- %! Float window
-- increase or decrease number of windows in the master area
, ((modMask' , xK_comma ), sendMessage (IncMasterN 1)) -- %! Increment the number of windows in the master area
, ((modMask' , xK_period), sendMessage (IncMasterN (-1))) -- %! Deincrement the number of windows in the master area
-- quit, or restart
, ((modMask' .|. shiftMask, xK_q ), io (exitWith ExitSuccess)) -- %! Quit
, ((modMask' .|. shiftMask, xK_q ), io exitSuccess) -- %! Quit
, ((modMask' , xK_q ), restart "xmonad" True) -- %! Restart
-- Metacity-like workspace switching
@@ -142,7 +143,7 @@ bluetileKeys conf@(XConfig {XMonad.modMask = modMask'}) = M.fromList $
-- Minimizing
, ((modMask', xK_m ), withFocused minimizeWindow)
, ((modMask' .|. shiftMask, xK_m ), sendMessage RestoreNextMinimizedWin)
, ((modMask' .|. shiftMask, xK_m ), withLastMinimized maximizeWindow)
]
++
-- mod-[1..9] ++ [0] %! Switch to workspace N
@@ -158,19 +159,19 @@ bluetileKeys conf@(XConfig {XMonad.modMask = modMask'}) = M.fromList $
, (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
bluetileMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
bluetileMouseBindings (XConfig {XMonad.modMask = modMask'}) = M.fromList $
bluetileMouseBindings XConfig{XMonad.modMask = modMask'} = M.fromList
-- mod-button1 %! Move a floated window by dragging
[ ((modMask', button1), (\w -> isFloating w >>= \isF -> when (isF) $
focus w >> mouseMoveWindow w >> windows W.shiftMaster))
[ ((modMask', button1), \w -> isFloating w >>= \isF -> when isF $
focus w >> mouseMoveWindow w >> windows W.shiftMaster)
-- mod-button2 %! Switch to next and first layout
, ((modMask', button2), (\_ -> sendMessage NextLayout))
, ((modMask' .|. shiftMask, button2), (\_ -> sendMessage $ JumpToLayout "Floating"))
, ((modMask', button2), \_ -> sendMessage NextLayout)
, ((modMask' .|. shiftMask, button2), \_ -> sendMessage $ JumpToLayout "Floating")
-- mod-button3 %! Resize a floated window by dragging
, ((modMask', button3), (\w -> isFloating w >>= \isF -> when (isF) $
focus w >> mouseResizeWindow w >> windows W.shiftMaster))
, ((modMask', button3), \w -> isFloating w >>= \isF -> when isF $
focus w >> mouseResizeWindow w >> windows W.shiftMaster)
]
isFloating :: Window -> X (Bool)
isFloating :: Window -> X Bool
isFloating w = do
ws <- gets windowset
return $ M.member w (W.floating ws)
@@ -179,33 +180,30 @@ bluetileManageHook :: ManageHook
bluetileManageHook = composeAll
[ workspaceByPos, positionStoreManageHook (Just defaultThemeWithButtons)
, className =? "MPlayer" --> doFloat
, isFullscreen --> doFullFloat
, manageDocks]
, isFullscreen --> doFullFloat]
bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $ (
named "Floating" floating |||
named "Tiled1" tiled1 |||
named "Tiled2" tiled2 |||
named "Fullscreen" fullscreen
)
bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $
renamed [Replace "Floating"] floating |||
renamed [Replace "Tiled1"] tiled1 |||
renamed [Replace "Tiled2"] tiled2 |||
renamed [Replace "Fullscreen"] fullscreen
where
floating = floatingDeco $ maximize $ borderResize $ positionStoreFloat
tiled1 = tilingDeco $ maximize $ mouseResizableTileMirrored
tiled2 = tilingDeco $ maximize $ mouseResizableTile
floating = floatingDeco $ maximize $ borderResize positionStoreFloat
tiled1 = tilingDeco $ maximize mouseResizableTileMirrored
tiled2 = tilingDeco $ maximize mouseResizableTile
fullscreen = tilingDeco $ maximize $ smartBorders Full
tilingDeco l = windowSwitcherDecorationWithButtons shrinkText defaultThemeWithButtons (draggingVisualizer l)
floatingDeco l = buttonDeco shrinkText defaultThemeWithButtons l
floatingDeco = buttonDeco shrinkText defaultThemeWithButtons
bluetileConfig =
defaultConfig
docks . ewmhFullscreen . ewmh $
def
{ modMask = mod4Mask, -- logo key
manageHook = bluetileManageHook,
layoutHook = bluetileLayoutHook,
logHook = currentWorkspaceOnTop >> ewmhDesktopsLogHook,
handleEventHook = ewmhDesktopsEventHook
`mappend` fullscreenEventHook
`mappend` minimizeEventHook
logHook = currentWorkspaceOnTop,
handleEventHook = minimizeEventHook
`mappend` serverModeEventHook' bluetileCommands
`mappend` positionStoreEventHook,
workspaces = bluetileWorkspaces,

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Desktop
-- Description : Core settings for interfacing with desktop environments.
-- Copyright : (c) Spencer Janssen <spencerjanssen@gmail.com>
-- License : BSD
--
@@ -22,7 +23,8 @@ module XMonad.Config.Desktop (
-- the DE via a subset of the Extended Window Manager Hints (EWMH)
-- specification. Extra xmonad settings unique to specific DE's are
-- added by overriding or modifying @desktopConfig@ fields in the
-- same way that @defaultConfig@ is customized in @~\/.xmonad/xmonad.hs@.
-- same way that the default configuration is customized in
-- @xmonad.hs@.
--
-- For more information about EWMH see:
--
@@ -56,6 +58,7 @@ module XMonad.Config.Desktop (
import XMonad
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.EwmhDesktops
import XMonad.Layout.LayoutModifier (ModifiedLayout)
import XMonad.Util.Cursor
import qualified Data.Map as M
@@ -69,7 +72,7 @@ import qualified Data.Map as M
-- <http://haskell.org/haskellwiki/Xmonad>
--
-- To configure xmonad for use with a DE or with DE tools like panels
-- and pagers, in place of @defaultConfig@ in your @~\/.xmonad/xmonad.hs@,
-- and pagers, in place of @def@ in your @xmonad.hs@,
-- use @desktopConfig@ or one of the other desktop configs from the
-- @XMonad.Config@ namespace. The following setup and customization examples
-- work the same way for the other desktop configs as for @desktopConfig@.
@@ -88,7 +91,7 @@ import qualified Data.Map as M
-- $customizing
-- To customize a desktop config, modify its fields as is illustrated with
-- @defaultConfig@ in "XMonad.Doc.Extending#Extending xmonad".
-- the default configuration @def@ in <https://xmonad.org/TUTORIAL.html the tutorial>.
-- $layouts
-- See also "XMonad.Util.EZConfig" for more options for modifying key bindings.
@@ -103,7 +106,7 @@ import qualified Data.Map as M
-- > main =
-- > xmonad $ desktopConfig {
-- > -- add manage hooks while still ignoring panels and using default manageHooks
-- > manageHook = myManageHook <+> manageHook desktopConfig
-- > manageHook = myManageHook <> manageHook desktopConfig
-- >
-- > -- add a fullscreen tabbed layout that does not avoid covering
-- > -- up desktop panels before the desktop layouts
@@ -126,7 +129,7 @@ import qualified Data.Map as M
-- To add to the logHook while still sending workspace and window information
-- to DE apps use something like:
--
-- > , logHook = myLogHook <+> logHook desktopConfig
-- > , logHook = myLogHook <> logHook desktopConfig
--
-- Or for more elaborate logHooks you can use @do@:
--
@@ -140,7 +143,7 @@ import qualified Data.Map as M
-- To customize xmonad's event handling while still having it respond
-- to EWMH events from pagers, task bars:
--
-- > , handleEventHook = myEventHooks <+> handleEventHook desktopConfig
-- > , handleEventHook = myEventHooks <> handleEventHook desktopConfig
--
-- or 'mconcat' if you write a list event of event hooks
--
@@ -154,7 +157,7 @@ import qualified Data.Map as M
-- $startupHook
-- To run the desktop startupHook, plus add further actions to be run each
-- time xmonad starts or restarts, use '<+>' to combine actions as in the
-- time xmonad starts or restarts, use '<>' to combine actions as in the
-- logHook example, or something like:
--
-- > , startupHook = do
@@ -163,14 +166,16 @@ import qualified Data.Map as M
-- > adjustEventInput
--
desktopConfig = ewmh defaultConfig
{ startupHook = setDefaultCursor xC_left_ptr
, layoutHook = desktopLayoutModifiers $ layoutHook defaultConfig
, manageHook = manageHook defaultConfig <+> manageDocks
, keys = desktopKeys <+> keys defaultConfig }
desktopConfig :: XConfig (ModifiedLayout AvoidStruts
(Choose Tall (Choose (Mirror Tall) Full)))
desktopConfig = docks $ ewmh def
{ startupHook = setDefaultCursor xC_left_ptr <> startupHook def
, layoutHook = desktopLayoutModifiers $ layoutHook def
, keys = desktopKeys <> keys def }
desktopKeys (XConfig {modMask = modm}) = M.fromList $
desktopKeys :: XConfig l -> M.Map (KeyMask, KeySym) (X ())
desktopKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_b), sendMessage ToggleStruts) ]
desktopLayoutModifiers layout = avoidStruts layout
desktopLayoutModifiers :: LayoutClass l a => l a -> ModifiedLayout AvoidStruts l a
desktopLayoutModifiers = avoidStruts

324
XMonad/Config/Dmwit.hs Normal file
View File

@@ -0,0 +1,324 @@
-- boilerplate {{{
{-# LANGUAGE ExistentialQuantification, NoMonomorphismRestriction, TypeSynonymInstances, ViewPatterns, LambdaCase #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-type-defaults #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Dmwit
-- Description : Daniel Wagner's xmonad configuration.
--
------------------------------------------------------------------------
module XMonad.Config.Dmwit {-# DEPRECATED "This module contains a personal configuration, to be removed from xmonad-contrib. If you use this module, please copy the relevant parts to your configuration or obtain a copy of it on https://xmonad.org/configurations.html and include it as a local module." #-} where
-- system imports
import Control.Monad.Trans
import Data.Map (Map, fromList)
import Data.Ratio
import Data.Word
import GHC.Real
import System.Environment
import System.Exit
import System.IO
import System.Process
-- xmonad core
import XMonad
import XMonad.StackSet hiding (workspaces)
-- xmonad contrib
import XMonad.Actions.SpawnOn
import XMonad.Actions.Warp
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Layout.Grid
import XMonad.Layout.IndependentScreens hiding (withScreen)
import XMonad.Layout.Magnifier
import XMonad.Layout.NoBorders
import XMonad.Prelude hiding (fromList)
import XMonad.Util.Dzen hiding (x, y)
import XMonad.Util.SpawnOnce
-- }}}
-- volume {{{
outputOf :: String -> IO String
outputOf s = do
uninstallSignalHandlers
(hIn, hOut, hErr, p) <- runInteractiveCommand s
mapM_ hClose [hIn, hErr]
hGetContents hOut <* waitForProcess p <* installSignalHandlers
geomMean :: Floating a => [a] -> a
geomMean xs = product xs ** (recip . fromIntegral . length $ xs)
arithMean :: Floating a => [a] -> a
arithMean xs = sum xs / fromIntegral (length xs)
namedNumbers n s = do
l <- lines s
guard (sentinel `isPrefixOf` l)
return (drop (length sentinel) l)
where sentinel = n ++ " #"
-- Data.List.Split.splitOn ":", but without involving an extra dependency
splitColon xs = case break (==':') xs of
(a, ':':b) -> a : splitColon b
(a, _) -> [a]
parse s = arithMean $ do
l <- lines s
guard ("\tVolume: " `isPrefixOf` l)
part <- splitColon l
(n,'%':_) <- reads part
return n
modVolume :: String -> Integer -> IO Double
modVolume kind n = do
is <- namedNumbers parseKind <$> outputOf listCommand
forM_ is (outputOf . setCommand)
parse <$> outputOf listCommand
where
sign | n > 0 = "+" | otherwise = "-"
ctlKind = map (\c -> if c == ' ' then '-' else c) kind
parseKind = unwords . map (\(notEmpty -> c :| cs) -> toUpper c : cs) . words $ kind
setCommand i = "pactl set-" ++ ctlKind ++ "-volume " ++ i ++ " -- " ++ sign ++ show (abs n) ++ "%"
listCommand = "pactl list " ++ ctlKind ++ "s"
-- }}}
-- convenient actions {{{
centerMouse = warpToWindow (1/2) (1/2)
statusBarMouse = warpToScreen 0 (5/1600) (5/1200)
withScreen s f = screenWorkspace s >>= flip whenJust (windows . f)
makeLauncher yargs run exec close = concat
["exe=`yeganesh ", yargs, "` && ", run, " ", exec, "$exe", close]
launcher = makeLauncher "" "eval" "\"exec " "\""
termLauncher = makeLauncher "-p withterm" "exec urxvt -e" "" ""
viewShift i = view i . shift i
floatAll = composeAll . map (\s -> className =? s --> doFloat)
sinkFocus = peek >>= maybe id sink
showMod k n = liftIO (modVolume k n) >>= volumeDzen . show . round
volumeDzen = dzenConfig $ onCurr (center 170 66) >=> font "-*-helvetica-*-r-*-*-64-*-*-*-*-*-*-*,-*-terminus-*-*-*-*-64-*-*-*-*-*-*-*"
-- }}}
altMask = mod1Mask
bright = "#80c0ff"
dark = "#13294e"
-- manage hooks for mplayer {{{
fullscreen43on169 = expand $ RationalRect 0 (-1/6) 1 (4/3) where
expand (RationalRect x y w h) = RationalRect (x - bwx) (y - bwy) (w + 2 * bwx) (h + 2 * bwy)
bwx = 2 / 1920 -- borderwidth
bwy = 2 / 1080
fullscreenMPlayer = className =? "MPlayer" --> do
dpy <- liftX $ asks display
win <- ask
hints <- liftIO $ getWMNormalHints dpy win
case fmap (approx . fst) (sh_aspect hints) of
Just ( 4 :% 3) -> viewFullOn 0 "5" win
Just (16 :% 9) -> viewFullOn 1 "5" win
_ -> doFloat
where
approx (n, d) = approxRational (fi n / fi d) (1/100)
operationOn f s n w = do
let ws = marshall s n
currws <- liftX $ screenWorkspace s
doF $ view ws . maybe id view currws . shiftWin ws w . f w
viewFullOn = operationOn sink
centerWineOn = operationOn (`XMonad.StackSet.float` RationalRect (79/960) (-1/540) (401/480) (271/270))
-- }}}
-- debugging {{{
class Show a => PPrint a where
pprint :: Int -> a -> String
pprint _ = show
data PPrintable = forall a. PPrint a => P a
instance Show PPrintable where show (P x) = show x
instance PPrint PPrintable where pprint n (P x) = pprint n x
record :: String -> Int -> [(String, PPrintable)] -> String
record s n xs = preamble ++ intercalate newline fields ++ postlude where
indentation = '\n' : replicate n '\t'
preamble = s ++ " {" ++ indentation
postlude = indentation ++ "}"
newline = ',' : indentation
fields = map (\(name, value) -> name ++ " = " ++ pprint (n+1) value) xs
instance PPrint a => PPrint (Maybe a) where
pprint n (Just x) = "Just (" ++ pprint n x ++ ")"
pprint _ x = show x
instance PPrint a => PPrint [a] where
pprint _ [] = "[]"
pprint n xs = preamble ++ intercalate newline allLines ++ postlude where
indentation = '\n' : replicate n '\t'
preamble = "[" ++ indentation
allLines = map (pprint (n+1)) xs
newline = ',' : indentation
postlude = indentation ++ "]"
instance PPrint Rectangle where
pprint n x = record "Rectangle" n [
("rect_x", P (rect_x x)),
("rect_y", P (rect_y x)),
("rect_width", P (rect_width x)),
("rect_height", P (rect_height x))
]
instance PPrint a => PPrint (Stack a) where
pprint n x = record "Stack" n [
("focus", P (XMonad.StackSet.focus x)),
("up", P (up x)),
("down", P (down x))
]
instance (PPrint i, PPrint l, PPrint a) => PPrint (Workspace i l a) where
pprint n x = record "Workspace" n [
("tag", P (tag x)),
("layout", P (layout x)),
("stack", P (stack x))
]
instance PPrint ScreenDetail where
pprint n x = record "SD" n [("screenRect", P (screenRect x))]
instance (PPrint i, PPrint l, PPrint a, PPrint sid, PPrint sd) => PPrint (XMonad.StackSet.Screen i l a sid sd) where
pprint n x = record "Screen" n [
("workspace", P (workspace x)),
("screen", P (screen x)),
("screenDetail", P (screenDetail x))
]
instance (PPrint i, PPrint l, PPrint a, PPrint sid, PPrint sd) => PPrint (StackSet i l a sid sd) where
pprint n x = record "StackSet" n [
("current", P (current x)),
("visible", P (visible x)),
("hidden", P (hidden x)),
("floating", P (floating x))
]
instance PPrint (Layout a)
instance PPrint Int
instance PPrint XMonad.Screen
instance PPrint Integer
instance PPrint Position
instance PPrint Dimension
instance PPrint Char
instance PPrint Word64
instance PPrint ScreenId
instance (Show a, Show b) => PPrint (Map a b)
-- }}}
-- main {{{
dmwitConfig nScreens = docks $ def {
borderWidth = 2,
workspaces = withScreens nScreens (map show [1..5]),
terminal = "urxvt",
normalBorderColor = dark,
focusedBorderColor = bright,
modMask = mod4Mask,
keys = keyBindings,
layoutHook = magnifierOff $ avoidStruts (GridRatio 0.9) ||| noBorders Full,
manageHook = (title =? "CGoban: Main Window" --> doF sinkFocus)
<> (className =? "Wine" <&&> (appName =? "hl2.exe" <||> appName =? "portal2.exe") --> ask >>= viewFullOn {-centerWineOn-} 1 "5")
<> (className =? "VirtualBox" --> ask >>= viewFullOn 1 "5")
<> (isFullscreen --> doFullFloat) -- TF2 matches the "isFullscreen" criteria, so its manage hook should appear after (e.g., to the left of a <> compared to) this one
<> (appName =? "huludesktop" --> doRectFloat fullscreen43on169)
<> fullscreenMPlayer
<> floatAll ["Gimp", "Wine"]
<> manageSpawn,
logHook = allPPs nScreens,
startupHook = refresh
>> mapM_ (spawnOnce . xmobarCommand) [0 .. nScreens-1]
}
main = countScreens >>= xmonad . dmwitConfig
-- }}}
-- keybindings {{{
keyBindings conf = let m = modMask conf in fromList . anyMask $ [
((m , xK_BackSpace ), spawnHere "urxvt"),
((m , xK_p ), spawnHere launcher),
((m .|. shiftMask , xK_p ), spawnHere termLauncher),
((m .|. shiftMask , xK_c ), kill),
((m , xK_q ), restart "xmonad" True),
((m .|. shiftMask , xK_q ), io exitSuccess),
((m , xK_grave ), sendMessage NextLayout),
((m .|. shiftMask , xK_grave ), setLayout $ layoutHook conf),
((m , xK_o ), sendMessage Toggle),
((m , xK_x ), withFocused (windows . sink)),
((m , xK_Home ), windows focusUp),
((m .|. shiftMask , xK_Home ), windows swapUp),
((m , xK_End ), windows focusDown),
((m .|. shiftMask , xK_End ), windows swapDown),
((m , xK_a ), windows focusMaster),
((m .|. shiftMask , xK_a ), windows swapMaster),
((m , xK_Control_L ), withScreen 0 view),
((m .|. shiftMask , xK_Control_L ), withScreen 0 viewShift),
((m , xK_Alt_L ), withScreen 1 view),
((m .|. shiftMask , xK_Alt_L ), withScreen 1 viewShift),
((m , xK_u ), centerMouse),
((m .|. shiftMask , xK_u ), statusBarMouse),
((m , xK_s ), spawnHere "chromium --password-store=gnome"),
((m , xK_n ), spawnHere "gvim todo"),
((m , xK_t ), spawnHere "mpc toggle"),
((m , xK_h ), spawnHere "urxvt -e alsamixer"),
((m , xK_d ), spawnHere "wyvern"),
((m , xK_l ), spawnHere "urxvt -e sup"),
((m , xK_r ), spawnHere "urxvt -e ncmpcpp"),
((m , xK_c ), spawnHere "urxvt -e ghci"),
((m , xK_g ), spawnHere "slock" >> spawnHere "xscreensaver-command -lock"),
((m , xK_f ), spawnHere "gvim ~/.xmonad/xmonad.hs"),
(( noModMask , xK_F8 ), showMod "sink input" (-4)),
(( noModMask , xK_F9 ), showMod "sink input" 4 ),
(( shiftMask , xK_F8 ), showMod "sink" (-4)),
(( shiftMask , xK_F9 ), showMod "sink" 4 ),
(( noModMask , xK_Super_L ), return ()) -- make VirtualBox ignore stray hits of the Windows key
] ++ [
((m .|. e , key ), windows (onCurrentScreen f ws))
| (key, ws) <- zip [xK_1..xK_9] (workspaces' conf)
, (e, f) <- [(0, view), (shiftMask, viewShift)]
]
atSchool school home = do
host <- liftIO (getEnv "HOST")
return $ case host of
"sorghum" -> home
"buckwheat" -> home
_ -> school
anyMask xs = do
((mask, key), action) <- xs
extraMask <- [0, controlMask, altMask, controlMask .|. altMask]
return ((mask .|. extraMask, key), action)
-- }}}
-- logHook {{{
pipeName n s = "/home/dmwit/.xmonad/pipe-" ++ n ++ "-" ++ show s
xmobarCommand (S s) = unwords ["xmobar",
"-x", show s,
"-t", template s,
"-C", pipeReader
]
where
template 0 = "}%focus%{%workspaces%"
template _ = "%date%}%focus%{%workspaces%"
pipeReader = "'[\
\Run PipeReader \"" ++ pipeName "focus" s ++ "\" \"focus\",\
\Run PipeReader \"" ++ pipeName "workspaces" s ++ "\" \"workspaces\"\
\]'"
allPPs nScreens = sequence_ [dynamicLogWithPP (pp s) | s <- [0..nScreens-1], pp <- [ppFocus, ppWorkspaces]]
color c = xmobarColor c ""
ppFocus s@(S s_) = whenCurrentOn s def {
ppOrder = \case{ _:_:windowTitle:_ -> [windowTitle]; _ -> [] },
ppOutput = appendFile (pipeName "focus" s_) . (++ "\n")
}
ppWorkspaces s@(S s_) = marshallPP s def {
ppCurrent = color "white",
ppVisible = color "white",
ppHiddenNoWindows = color dark,
ppUrgent = color "red",
ppSep = "",
ppOrder = \case{ wss:_layout:_title:_ -> [wss]; _ -> [] },
ppOutput = appendFile (pipeName "workspaces" s_) . (++"\n")
}
-- }}}

View File

@@ -1,25 +1,27 @@
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE TupleSections #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-orphans #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Droundy
-- Description : David Roundy's xmonad config.
-- Copyright : (c) Spencer Janssen 2007
-- License : BSD3-style (see LICENSE)
--
------------------------------------------------------------------------
module XMonad.Config.Droundy {-# DEPRECATED "This module contains a personal configuration, to be removed from xmonad-contrib. If you use this module, please copy the relevant parts to your configuration or obtain a copy of it on https://xmonad.org/configurations.html and include it as a local module." #-} ( config, mytab ) where
module XMonad.Config.Droundy ( config, mytab ) where
import XMonad hiding (keys, config, (|||))
import XMonad hiding (keys, config)
import qualified XMonad (keys)
import qualified XMonad.StackSet as W
import qualified Data.Map as M
import System.Exit ( exitWith, ExitCode(ExitSuccess) )
import System.Exit ( exitSuccess )
import XMonad.Layout.Tabbed ( tabbed, defaultTheme,
import XMonad.Layout.Tabbed ( tabbed,
shrinkText, Shrinker, shrinkIt, CustomShrink(CustomShrink) )
import XMonad.Layout.Combo ( combineTwo )
import XMonad.Layout.Named ( named )
import XMonad.Layout.Renamed ( Rename(Replace), renamed )
import XMonad.Layout.LayoutCombinators
import XMonad.Layout.Square ( Square(Square) )
import XMonad.Layout.WindowNavigation ( Navigate(Move,Swap,Go), Direction2D(U,D,R,L),
@@ -32,22 +34,22 @@ import XMonad.Layout.ToggleLayouts ( toggleLayouts, ToggleLayout(ToggleLayout) )
import XMonad.Layout.ShowWName ( showWName )
import XMonad.Layout.Magnifier ( maximizeVertical, MagnifyMsg(Toggle) )
import XMonad.Prompt ( defaultXPConfig, font, height, XPConfig )
import XMonad.Prompt ( font, height, XPConfig )
import XMonad.Prompt.Layout ( layoutPrompt )
import XMonad.Prompt.Shell ( shellPrompt )
import XMonad.Actions.CopyWindow ( kill1, copy )
import XMonad.Actions.DynamicWorkspaces ( withNthWorkspace, withWorkspace,
selectWorkspace, renameWorkspace, removeWorkspace )
import XMonad.Actions.CycleWS ( moveTo, WSType( HiddenNonEmptyWS ),
Direction1D( Prev, Next) )
import XMonad.Actions.CycleWS ( moveTo, hiddenWS, emptyWS,
Direction1D( Prev, Next), WSType ((:&:), Not) )
import XMonad.Hooks.ManageDocks ( avoidStruts, manageDocks )
import XMonad.Hooks.ManageDocks ( avoidStruts, docks )
import XMonad.Hooks.EwmhDesktops ( ewmh )
myXPConfig :: XPConfig
myXPConfig = defaultXPConfig {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*"
,height=22}
myXPConfig = def {font="-*-lucida-medium-r-*-*-14-*-*-*-*-*-*-*"
,height=22}
------------------------------------------------------------------------
@@ -77,11 +79,11 @@ keys x = M.fromList $
, ((modMask x, xK_t ), withFocused $ windows . W.sink) -- %! Push window back into tiling
-- quit, or restart
, ((modMask x .|. shiftMask, xK_Escape), io (exitWith ExitSuccess)) -- %! Quit xmonad
, ((modMask x .|. shiftMask, xK_Escape), io exitSuccess) -- %! Quit xmonad
, ((modMask x , xK_Escape), restart "xmonad" True) -- %! Restart xmonad
, ((modMask x .|. shiftMask, xK_Right), moveTo Next HiddenNonEmptyWS)
, ((modMask x .|. shiftMask, xK_Left), moveTo Prev HiddenNonEmptyWS)
, ((modMask x .|. shiftMask, xK_Right), moveTo Next $ hiddenWS :&: Not emptyWS)
, ((modMask x .|. shiftMask, xK_Left), moveTo Prev $ hiddenWS :&: Not emptyWS)
, ((modMask x, xK_Right), sendMessage $ Go R)
, ((modMask x, xK_Left), sendMessage $ Go L)
, ((modMask x, xK_Up), sendMessage $ Go U)
@@ -113,23 +115,22 @@ keys x = M.fromList $
]
++
zip (zip (repeat $ modMask x) [xK_F1..xK_F12]) (map (withNthWorkspace W.greedyView) [0..])
zip (map (modMask x,) [xK_F1..xK_F12]) (map (withNthWorkspace W.greedyView) [0..])
++
zip (zip (repeat (modMask x .|. shiftMask)) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..])
zip (map (modMask x .|. shiftMask,) [xK_F1..xK_F12]) (map (withNthWorkspace copy) [0..])
config = ewmh defaultConfig
config = docks $ ewmh def
{ borderWidth = 1 -- Width of the window border in pixels.
, XMonad.workspaces = ["mutt","iceweasel"]
, layoutHook = showWName $ workspaceDir "~" $
boringWindows $ smartBorders $ windowNavigation $
maximizeVertical $ toggleLayouts Full $ avoidStruts $
named "tabbed" mytab |||
named "xclock" (mytab ****//* combineTwo Square mytab mytab) |||
named "three" (mytab **//* mytab *//* combineTwo Square mytab mytab) |||
named "widescreen" ((mytab *||* mytab)
renamed [Replace "tabbed"] mytab |||
renamed [Replace "xclock"] (mytab ****//* combineTwo Square mytab mytab) |||
renamed [Replace "three"] (mytab **//* mytab *//* combineTwo Square mytab mytab) |||
renamed [Replace "widescreen"] ((mytab *||* mytab)
****//* combineTwo Square mytab mytab) -- |||
--mosaic 0.25 0.5
, manageHook = manageHook defaultConfig <+> manageDocks -- add panel-handling
, terminal = "xterm" -- The preferred terminal program.
, normalBorderColor = "#222222" -- Border color for unfocused windows.
, focusedBorderColor = "#00ff00" -- Border color for focused windows.
@@ -137,7 +138,7 @@ config = ewmh defaultConfig
, XMonad.keys = keys
}
mytab = tabbed CustomShrink defaultTheme
mytab = tabbed CustomShrink def
instance Shrinker CustomShrink where
shrinkIt shr s | Just s' <- dropFromHead " " s = shrinkIt shr s'

79
XMonad/Config/Example.hs Normal file
View File

@@ -0,0 +1,79 @@
--------------------------------------------------------------------------------
-- | Example.hs
--
-- Example configuration file for xmonad using the latest recommended
-- features (e.g., 'desktopConfig').
module Main (main) where
--------------------------------------------------------------------------------
import System.Exit
import XMonad
import XMonad.Config.Desktop
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageHelpers
import XMonad.Layout.BinarySpacePartition (emptyBSP)
import XMonad.Layout.NoBorders (noBorders)
import XMonad.Layout.ResizableTile (ResizableTall(..))
import XMonad.Layout.ToggleLayouts (ToggleLayout(..), toggleLayouts)
import XMonad.Prompt
import XMonad.Prompt.ConfirmPrompt
import XMonad.Prompt.Shell
import XMonad.Util.EZConfig
--------------------------------------------------------------------------------
main = do
spawn "xmobar" -- Start a task bar such as xmobar.
-- Start xmonad using the main desktop configuration with a few
-- simple overrides:
xmonad $ desktopConfig
{ modMask = mod4Mask -- Use the "Win" key for the mod key
, manageHook = myManageHook <> manageHook desktopConfig
, layoutHook = desktopLayoutModifiers myLayouts
, logHook = (dynamicLogString def >>= xmonadPropLog)
<> logHook desktopConfig
}
`additionalKeysP` -- Add some extra key bindings:
[ ("M-S-q", confirmPrompt myXPConfig "exit" (io exitSuccess))
, ("M-p", shellPrompt myXPConfig)
, ("M-<Esc>", sendMessage (Toggle "Full"))
]
--------------------------------------------------------------------------------
-- | Customize layouts.
--
-- This layout configuration uses two primary layouts, 'ResizableTall'
-- and 'BinarySpacePartition'. You can also use the 'M-<Esc>' key
-- binding defined above to toggle between the current layout and a
-- full screen layout.
myLayouts = toggleLayouts (noBorders Full) others
where
others = ResizableTall 1 (1.5/100) (3/5) [] ||| emptyBSP
--------------------------------------------------------------------------------
-- | Customize the way 'XMonad.Prompt' looks and behaves. It's a
-- great replacement for dzen.
myXPConfig = def
{ position = Top
, alwaysHighlight = True
, promptBorderWidth = 0
, font = "xft:monospace:size=9"
}
--------------------------------------------------------------------------------
-- | Manipulate windows as they are created. The list given to
-- @composeOne@ is processed from top to bottom. The first matching
-- rule wins.
--
-- Use the `xprop' tool to get the info you need for these matches.
-- For className, use the second value that xprop gives you.
myManageHook = composeOne
-- Handle floating windows:
[ transience -- move transient windows to their parent
, isDialog -?> doCenterFloat
] <> composeAll
[ className =? "Pidgin" --> doFloat
, className =? "XCalc" --> doFloat
, className =? "mpv" --> doFloat
]

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Gnome
-- Description : Config for integrating xmonad with GNOME.
-- Copyright : (c) Spencer Janssen <spencerjanssen@gmail.com>
-- License : BSD
--
@@ -18,7 +19,8 @@ module XMonad.Config.Gnome (
-- $usage
gnomeConfig,
gnomeRun,
gnomeRegister
gnomeRegister,
desktopLayoutModifiers
) where
import XMonad
@@ -30,7 +32,7 @@ import qualified Data.Map as M
import System.Environment (getEnvironment)
-- $usage
-- To use this module, start with the following @~\/.xmonad\/xmonad.hs@:
-- To use this module, start with the following @xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Config.Gnome
@@ -41,12 +43,12 @@ import System.Environment (getEnvironment)
gnomeConfig = desktopConfig
{ terminal = "gnome-terminal"
, keys = gnomeKeys <+> keys desktopConfig
, keys = gnomeKeys <> keys desktopConfig
, startupHook = gnomeRegister >> startupHook desktopConfig }
gnomeKeys (XConfig {modMask = modm}) = M.fromList $
gnomeKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), gnomeRun)
, ((modm .|. shiftMask, xK_q), spawn "gnome-session-save --kill") ]
, ((modm .|. shiftMask, xK_q), spawn "gnome-session-quit --logout") ]
-- | Launch the "Run Application" dialog. gnome-panel must be running for this
-- to work.
@@ -71,10 +73,10 @@ gnomeRun = withDisplay $ \dpy -> do
-- > gconftool-2 -s /desktop/gnome/session/required_components/windowmanager xmonad --type string
gnomeRegister :: MonadIO m => m ()
gnomeRegister = io $ do
x <- lookup "DESKTOP_AUTOSTART_ID" `fmap` getEnvironment
x <- lookup "DESKTOP_AUTOSTART_ID" <$> getEnvironment
whenJust x $ \sessionId -> safeSpawn "dbus-send"
["--session"
,"--print-reply=string"
,"--print-reply=literal"
,"--dest=org.gnome.SessionManager"
,"/org/gnome/SessionManager"
,"org.gnome.SessionManager.RegisterClient"

Some files were not shown because too many files have changed in this diff Show More