897 Commits

Author SHA1 Message Date
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
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
Ulf Jasper
ed32ccd080 Add passEditPrompt to Xmonad.Prompt.Pass 2018-06-05 19:34:06 +02:00
Markus Ongyerth
b1f28e64d7 Add -dock to dzen command 2017-07-08 08:37:35 +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
340 changed files with 15329 additions and 6000 deletions

View File

@@ -1,12 +1,16 @@
### Problem Description
Describe the problem you are having, what you expect to happen
instead, and how to reproduce the problem.
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 configuration file that reproduces the
problem you are experiencing:
Please include the smallest _full_ configuration file that reproduces
the problem you are experiencing:
```haskell
module Main (main) where
@@ -21,4 +25,6 @@ main = xmonad def
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- [ ] I tested my configuration with [xmonad-testing](https://github.com/xmonad/xmonad-testing)
- I tested my configuration
- [ ] With `xmonad` version XXX (commit XXX if using git)
- [ ] With `xmonad-contrib` version XXX (commit XXX if using git)

View File

@@ -7,6 +7,7 @@ behind them.
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- [ ] I tested my changes with [xmonad-testing](https://github.com/xmonad/xmonad-testing)
- [ ] I've considered how to best test these changes (property, unit,
manually, ...) and concluded: XXX
- [ ] I updated the `CHANGES.md` file

View File

@@ -0,0 +1,115 @@
Piggy-back on the haskell-ci workflow for automatic releases to Hackage.
This extends the workflow with two additional triggers:
* When a release is created on GitHub, 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).
* To make a final release, the workflow can be triggered manually by entering
the correct version number matching the version in the cabal file. This is
here because promoting the candidate on Hackage discards the uploaded docs
(https://github.com/haskell/hackage-server/issues/70).
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,17 @@
#
name: Haskell-CI
on:
- - push
- - pull_request
+ push:
+ pull_request:
+ release:
+ types:
+ - published
+ workflow_dispatch:
+ inputs:
+ version:
+ # releases to Hackage are final and cannot be reverted, thus require
+ # manual entry of version as a poor man's mistake avoidance
+ description: version (must match version in cabal file)
jobs:
linux:
name: Haskell-CI - Linux - ${{ matrix.compiler }}
@@ -28,6 +37,7 @@
include:
- compiler: ghc-9.0.1
allow-failure: false
+ upload: true
- compiler: ghc-8.10.4
allow-failure: false
- compiler: ghc-8.8.4
@@ -171,8 +181,66 @@
${CABAL} -vnormal check
- name: haddock
run: |
- $CABAL v2-haddock $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
+ $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: upload artifacts (sdist)
+ if: matrix.upload
+ uses: actions/upload-artifact@v2
+ with:
+ path: ${{ github.workspace }}/sdist/*.tar.gz
+ - name: upload artifacts (haddock)
+ if: matrix.upload
+ uses: actions/upload-artifact@v2
+ with:
+ path: ${{ github.workspace }}/haddock/*-docs.tar.gz
+ - name: hackage upload (candidate)
+ if: matrix.upload && github.event_name == 'release'
+ run: |
+ set -ex
+ PACKAGE_VERSION="${PACKAGE_VERSION#v}"
+ curl \
+ --silent --show-error --fail \
+ --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/
+ curl \
+ --silent --show-error --fail \
+ -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
+ env:
+ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
+ PACKAGE_NAME: ${{ github.event.repository.name }}
+ PACKAGE_VERSION: ${{ github.event.release.tag_name }}
+ - name: hackage upload (release)
+ if: matrix.upload && github.event_name == 'workflow_dispatch'
+ run: |
+ set -ex
+ PACKAGE_VERSION="${PACKAGE_VERSION#v}"
+ curl \
+ --silent --show-error --fail \
+ --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/
+ curl \
+ --silent --show-error --fail \
+ -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
+ env:
+ HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
+ PACKAGE_NAME: ${{ github.event.repository.name }}
+ PACKAGE_VERSION: ${{ github.event.inputs.version }}

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

@@ -0,0 +1,268 @@
# 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.12
#
# REGENDATA ("0.12",["github","cabal.project"])
#
name: Haskell-CI
on:
push:
pull_request:
release:
types:
- published
workflow_dispatch:
inputs:
version:
# releases to Hackage are final and cannot be reverted, thus require
# manual entry of version as a poor man's mistake avoidance
description: version (must match version in cabal file)
jobs:
linux:
name: Haskell-CI - Linux - ${{ matrix.compiler }}
runs-on: ubuntu-18.04
container:
image: buildpack-deps:bionic
continue-on-error: ${{ matrix.allow-failure }}
strategy:
matrix:
include:
- compiler: ghc-9.0.1
allow-failure: false
upload: true
- compiler: ghc-8.10.4
allow-failure: false
- compiler: ghc-8.8.4
allow-failure: false
- compiler: ghc-8.6.5
allow-failure: false
- compiler: ghc-8.4.4
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
apt-add-repository -y 'ppa:hvr/ghc'
apt-get update
apt-get install -y $CC cabal-install-3.4 libx11-dev libxext-dev libxft-dev libxinerama-dev libxrandr-dev libxss-dev
env:
CC: ${{ matrix.compiler }}
- 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=$(echo "/opt/$CC" | sed 's/-/\//')
HCNAME=ghc
HC=$HCDIR/bin/$HCNAME
echo "HC=$HC" >> $GITHUB_ENV
echo "HCPKG=$HCDIR/bin/$HCNAME-pkg" >> $GITHUB_ENV
echo "HADDOCK=$HCDIR/bin/haddock" >> $GITHUB_ENV
echo "CABAL=/opt/cabal/3.4/bin/cabal -vnormal+nowrap" >> $GITHUB_ENV
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=--$HCNAME --with-compiler=$HC" >> $GITHUB_ENV
echo "GHCJSARITH=0" >> $GITHUB_ENV
env:
CC: ${{ matrix.compiler }}
- 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
- 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: cache (tools)
uses: actions/cache@v2
with:
key: ${{ runner.os }}-${{ matrix.compiler }}-tools-6c71d9d3
path: ~/.haskell-ci-tools
- name: install cabal-plan
run: |
mkdir -p $HOME/.cabal/bin
curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.6.2.0/cabal-plan-0.6.2.0-x86_64-linux.xz > cabal-plan.xz
echo 'de73600b1836d3f55e32d80385acc055fd97f60eaa0ab68a755302685f5d81bc 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: install hlint
run: |
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then HLINTVER=$(cd /tmp && (${CABAL} v2-install -v $ARG_COMPILER --dry-run hlint --constraint='hlint >=3.2 && <3.3' | perl -ne 'if (/\bhlint-(\d+(\.\d+)*)\b/) { print "$1"; last; }')); echo "HLint version $HLINTVER" ; fi
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then if [ ! -e $HOME/.haskell-ci-tools/hlint-$HLINTVER/hlint ]; then echo "Downloading HLint version $HLINTVER"; mkdir -p $HOME/.haskell-ci-tools; curl --write-out 'Status Code: %{http_code} Redirects: %{num_redirects} Total time: %{time_total} Total Dsize: %{size_download}\n' --silent --location --output $HOME/.haskell-ci-tools/hlint-$HLINTVER.tar.gz "https://github.com/ndmitchell/hlint/releases/download/v$HLINTVER/hlint-$HLINTVER-x86_64-linux.tar.gz"; tar -xzv -f $HOME/.haskell-ci-tools/hlint-$HLINTVER.tar.gz -C $HOME/.haskell-ci-tools; fi ; fi
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then mkdir -p $CABAL_DIR/bin && ln -sf "$HOME/.haskell-ci-tools/hlint-$HLINTVER/hlint" $CABAL_DIR/bin/hlint ; fi
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then hlint --version ; fi
- name: checkout
uses: actions/checkout@v2
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
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: cache
uses: actions/cache@v2
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: hlint
run: |
if [ $((HCNUMVER >= 90000)) -ne 0 ] ; then (cd ${PKGDIR_xmonad_contrib} && hlint -h ${GITHUB_WORKSPACE}/source/.hlint.yaml .) ; fi
- name: cabal check
run: |
cd ${PKGDIR_xmonad_contrib} || false
${CABAL} -vnormal check
- name: haddock
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: upload artifacts (sdist)
if: matrix.upload
uses: actions/upload-artifact@v2
with:
path: ${{ github.workspace }}/sdist/*.tar.gz
- name: upload artifacts (haddock)
if: matrix.upload
uses: actions/upload-artifact@v2
with:
path: ${{ github.workspace }}/haddock/*-docs.tar.gz
- name: hackage upload (candidate)
if: matrix.upload && github.event_name == 'release'
run: |
set -ex
PACKAGE_VERSION="${PACKAGE_VERSION#v}"
curl \
--silent --show-error --fail \
--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/
curl \
--silent --show-error --fail \
-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
env:
HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
PACKAGE_NAME: ${{ github.event.repository.name }}
PACKAGE_VERSION: ${{ github.event.release.tag_name }}
- name: hackage upload (release)
if: matrix.upload && github.event_name == 'workflow_dispatch'
run: |
set -ex
PACKAGE_VERSION="${PACKAGE_VERSION#v}"
curl \
--silent --show-error --fail \
--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/
curl \
--silent --show-error --fail \
-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
env:
HACKAGE_API_KEY: ${{ secrets.HACKAGE_API_KEY }}
PACKAGE_NAME: ${{ github.event.repository.name }}
PACKAGE_VERSION: ${{ github.event.inputs.version }}

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-latest
name: Nix Flake - Linux
permissions:
contents: read
steps:
- name: Install Nix
uses: cachix/install-nix-action@v13
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@v2
- 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

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

@@ -0,0 +1,42 @@
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@v2
- name: Setup Haskell
uses: haskell/actions/setup@v1
with:
# packdeps doesn't build with newer as of 2021-10
ghc-version: '8.8'
- name: Install packdeps
run: |
set -ex
echo "$HOME/.cabal/bin" >> $GITHUB_PATH
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

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

@@ -0,0 +1,113 @@
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:
# XXX: temporarily disabled until xmonad 0.17 release
# - resolver: lts-12
# ghc: 8.4.4
# yaml: stack.yaml
- resolver: lts-12
ghc: 8.4.4
yaml: stack-master.yaml
- resolver: lts-14
ghc: 8.6.5
yaml: stack-master.yaml
- resolver: lts-16
ghc: 8.8.4
yaml: stack-master.yaml
# - resolver: lts-17
# ghc: 8.10.4
# yaml: stack.yaml
- resolver: lts-17
ghc: 8.10.4
yaml: stack-master.yaml
- resolver: lts-18
ghc: 8.10.7
yaml: stack-master.yaml
steps:
- name: Clone project
uses: actions/checkout@v2
- name: Prepare apt sources
run: |
set -ex
sudo add-apt-repository -y ppa:hvr/ghc
sudo apt update -y
- name: Install C dependencies
run: |
set -ex
sudo apt install -y \
libx11-dev \
libxext-dev \
libxft-dev \
libxinerama-dev \
libxrandr-dev \
libxss-dev \
#
- name: Install GHC
# use system ghc (if available) in stack, don't waste GH Actions cache space
continue-on-error: true
run: |
set -ex
sudo apt install -y ghc-${{ matrix.ghc }}
echo /opt/ghc/${{ matrix.ghc }}/bin >> $GITHUB_PATH
- 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
run: |
echo "::set-output name=date::$(date +%Y-%m)"
- name: Cache Haskell package metadata
uses: actions/cache@v2
with:
path: ~/.stack/pantry
key: stack-pantry-${{ runner.os }}-${{ steps.cache-date.outputs.date }}
restore-keys: |
stack-pantry-${{ runner.os }}-
- name: Cache Haskell dependencies
uses: actions/cache@v2
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 }}-
stack-${{ runner.os }}-${{ matrix.resolver }}-
- 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

3
.gitignore vendored
View File

@@ -24,3 +24,6 @@ tags
# stack artifacts
/.stack-work/
/cabal.project.local
stack.yaml.lock

2
.hlint.yaml Normal file
View File

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

View File

@@ -13,90 +13,96 @@ 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@googlemail.com> <asgaroth_@gmx.de>
Daniel Schoepe <daniel.schoepe@googlemail.com> <daniel.schoepe@gmail.com>
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>
intrigeri <intrigeri@boum.org>
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>
Joel Suovaniemi <joel.suovaniemi@iki.fi>
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 <quentin.moser@unifr.ch>
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>
Sibi Prabakaran <sibi@psibi.in> <psibi2000@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>
Tomohiro Matsuyama <matsuyama3@ariel-networks.com>
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>
brian <brian@lorf.org>
cardboard42 <cardboard42@gmail.com>
daedalusinfinity <daedalusinfinity@gmail.com>
hexago.nl <xmonad-contrib@hexago.nl>
intrigeri <intrigeri@boum.org>
jakob <jakob@pipefour.org>
kedals0 <kedals0@gmail.com>
lithis <xmonad@selg.hethrael.org>
lithis <xmonad@selg.hethrael.org> <xmonad@s001.hethrael.com>
longpoke <longpoke@gmail.com>
md143rbh7f <md143rbh7f@gmail.com>
perlkat <perlkat@katspace.org>
rupa <rupa@lrrr.us> <rupa@lrrr.us>
timthelion <tim.thelion@gmail.com>
# for core only
Neil Mitchell <http://www.cs.york.ac.uk/~ndm/>, Neil Mitchell
Nick Burlett <nickburlett@mac.com>
Sam Hughes <hughes@rpi.edu>
Shae Erisson <shae@ScannedInAvian.com>
Conrad Irwin <conrad.irwin@gmail.com>
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>

View File

@@ -1,104 +0,0 @@
# This file has been generated -- see https://github.com/hvr/multi-ghc-travis
language: c
sudo: false
cache:
directories:
- $HOME/.cabsnap
- $HOME/.cabal/packages
before_cache:
- rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
- rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
matrix:
include:
- env: GHCVER=8.4.3 CABALVER=2.2
compiler: ": #GHC 8.4.3"
addons: { apt: { packages: [cabal-install-2.2, ghc-8.4.3, libxrandr-dev]
, sources: [hvr-ghc]
} }
- env: GHCVER=8.2.2 CABALVER=2.0
compiler: ": #GHC 8.2.2"
addons: { apt: { packages: [cabal-install-2.0, ghc-8.2.2, libxrandr-dev]
, sources: [hvr-ghc]
} }
- env: GHCVER=8.0.1 CABALVER=1.24
compiler: ": #GHC 8.0.1"
addons: { apt: { packages: [cabal-install-1.24, ghc-8.0.1, libxrandr-dev]
, sources: [hvr-ghc]
} }
- env: GHCVER=7.10.3 CABALVER=1.22
compiler: ": #GHC 7.10.3"
addons: { apt: { packages: [cabal-install-1.22, ghc-7.10.3, libxrandr-dev]
, sources: [hvr-ghc]
} }
- env: GHCVER=7.8.4 CABALVER=1.18
compiler: ": #GHC 7.8.4"
addons: { apt: { packages: [cabal-install-1.18, ghc-7.8.4, libxrandr-dev]
, sources: [hvr-ghc]
} }
before_install:
- unset CC
- export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH
install:
- cabal --version
- echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"
- if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];
then
zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >
$HOME/.cabal/packages/hackage.haskell.org/00-index.tar;
fi
- travis_retry cabal update -v
# build xmonad from HEAD
- git clone https://github.com/xmonad/xmonad.git
- cabal install xmonad/
- sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config
- cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt
- sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
# check whether current requested install-plan matches cached package-db snapshot
- if diff -u $HOME/.cabsnap/installplan.txt installplan.txt;
then
echo "cabal build-cache HIT";
rm -rfv .ghc;
cp -a $HOME/.cabsnap/ghc $HOME/.ghc;
cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;
else
echo "cabal build-cache MISS";
rm -rf $HOME/.cabsnap;
mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;
fi
- cabal install --only-dependencies --enable-tests --enable-benchmarks;
# snapshot package-db on cache miss
- if [ ! -d $HOME/.cabsnap ];
then
echo "snapshotting package-db to build-cache";
mkdir $HOME/.cabsnap;
cp -a $HOME/.ghc $HOME/.cabsnap/ghc;
cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;
fi
# Here starts the actual work to be performed for the package under test;
# any command which exits with a non-zero exit code causes the build to fail.
script:
- if [ -f configure.ac ]; then autoreconf -i; fi
- cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging
- cabal build # this builds all libraries and executables (including tests/benchmarks)
- cabal test
# - cabal check # complains about -Werror even though it is
# hidden behind a manual flag with default false
- cabal sdist # tests that a source-distribution can be generated
# Check that the resulting source distribution can be built & installed.
# If there are no other `.tar.gz` files in `dist`, this can be even simpler:
# `cabal install --force-reinstalls dist/*-*.tar.gz`
- SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
(cd dist && cabal install --force-reinstalls "$SRC_TGZ")
# EOF

View File

@@ -1,5 +1,931 @@
# Change Log / Release Notes
## 0.17.0 (October 27, 2021)
### Breaking Changes
* All modules that export bitmap fonts as their default
- If xmonad is compiled with XFT support (the default), use an XFT
font instead. The previous default expected an X11 misc font
(PCF), which is not supported in pango 1.44 anymore and thus some
distributions have stopped shipping these.
This fixes the silent `user error (createFontSet)`; this would
break the respective modules.
* `XMonad.Prompt`
- Now `mkComplFunFromList` and `mkComplFunFromList'` take an
additional `XPConfig` argument, so that they can take into
account the given `searchPredicate`.
- A `complCaseSensitivity` field has been added to `XPConfig`, indicating
whether case-sensitivity is desired when performing completion.
- `historyCompletion` and `historyCompletionP` now both have an `X`
constraint (was: `IO`), due to changes in how the xmonad core handles XDG
directories.
- The prompt window now sets a `WM_CLASS` property. This allows
other applications, like compositors, to properly match on it.
* `XMonad.Hooks.EwmhDesktops`
- It is no longer recommended to use `fullscreenEventHook` directly.
Instead, use `ewmhFullscreen` which additionally advertises fullscreen
support in `_NET_SUPPORTED` and fixes fullscreening of applications that
explicitly check it, e.g. mupdf-gl, sxiv, …
`XMonad.Layout.Fullscreen.fullscreenSupport` now advertises it as well,
and no configuration changes are required in this case.
- Deprecated `ewmhDesktopsLogHookCustom` and `ewmhDesktopsEventHookCustom`;
these are now replaced by a composable `XMonad.Util.ExtensibleConf`-based
interface. Users are advised to just use the `ewmh` XConfig combinator
and customize behaviour using the provided `addEwmhWorkspaceSort`,
`addEwmhWorkspaceRename` functions, or better still, use integrations
provided by modules such as `XMonad.Actions.WorkspaceNames`.
This interface now additionally allows customization of what happens
when clients request window activation. This can be used to ignore
activation of annoying applications, to mark windows as urgent instead
of focusing them, and more. There's also a new `XMonad.Hooks.Focus`
module extending the ManageHook EDSL with useful combinators.
- Ordering of windows that are set to `_NET_CLIENT_LIST` and `_NET_CLIENT_LIST_STACKING`
was changed to be closer to the spec. From now these two lists will have
differently sorted windows.
- `_NET_WM_STATE_DEMANDS_ATTENTION` was added to the list of supported
hints (as per `_NET_SUPPORTED`). This hint has long been understood by
`UrgencyHook`. This enables certain applications (e.g. kitty terminal
emulator) that check whether the hint is supported to use it.
* All modules still exporting a `defaultFoo` constructor
- All of these were now removed. You can use the re-exported `def` from
`Data.Default` instead.
* `XMonad.Hooks.Script`
- `execScriptHook` now has an `X` constraint (was: `MonadIO`), due to changes
in how the xmonad core handles XDG directories.
* `XMonad.Actions.WorkspaceNames`
- The type of `getWorkspaceNames` was changed to fit into the new `ppRename`
field of `PP`.
* `XMonad.Hooks.StatusBar`, `XMonad.Hooks.StatusBar.PP` (previously
`XMonad.Hooks.DynamicLog`) and `XMonad.Util.Run`
- `spawnPipe` no longer uses binary mode handles but defaults to the
current locale encoding instead.
`dynamicLogString`, the output of which usually goes directly into such
a handle, no longer encodes its output in UTF-8, but returns a normal
`String` of Unicode codepoints instead.
When these two are used together, everything should continue to work as
it always has, but in isolation behaviour might change.
(To get the old `spawnPipe` behaviour, `spawnPipeWithNoEncoding` can now
be used, and `spawnPipeWithUtf8Encoding` was added as well to force
UTF-8 regardless of locale. These shouldn't normally be necessary, though.)
- `xmonadPropLog` and `xmonadPropLog'` now encode the String in UTF-8.
Again, no change when used together with `dynamicLogString`, but other
uses of these in user configs might need to be adapted.
* `XMonad.Actions.TopicSpace`
- Deprecated the `maxTopicHistory` field, as well as the
`getLastFocusedTopics` and `setLastFocusedTopic` functions. It is
now recommended to directly use `XMonad.Hooks.WorkspaceHistory`
instead.
- Added `TopicItem`, as well as the helper functions `topicNames`,
`tiActions`, `tiDirs`, `noAction`, and `inHome` for a more
convenient specification of topics.
* `XMonad.Actions.CycleRecentWS`
- Changed the signature of `recentWS` to return a `[WorkspaceId]`
instead of a `[WindowSet]`, while `cycleWindowSets` and
`toggleWindowSets` now take a function `WindowSet ->
[WorkspaceId]` instead of one to `[WindowSet]` as their first
argument. This fixes the interplay between this module and any
layout that stores state.
* `XMonad.Layout.LayoutCombinators`
- Moved the alternative `(|||)` function and `JumpToLayout` to the
xmonad core. They are re-exported by the module, but do not add any
new functionality. `NewSelect` now exists as a deprecated type
alias to `Choose`.
- Removed the `Wrap` and `NextLayoutNoWrap` data constructors.
- `XMonad.Actions.CycleWS`
- Deprecated `EmptyWS`, `HiddenWS`, `NonEmptyWS`, `HiddenNonEmptyWS`,
`HiddenEmptyWS`, `AnyWS` and `WSTagGroup`.
- `XMonad.Actions.GridSelect`
- `colorRangeFromClassName` now uses different hash function,
so colors of inactive window tiles will be different (but still inside
the provided color range).
* `XMonad.Actions.Search`
- Removed outdated `isohunt` search engine.
- Updated URLs for `codesearch`, `openstreetmap`, and `thesaurus`
search engines.
- Added `github` search engine.
### New Modules
* `XMonad.Layout.FixedAspectRatio`
Layout modifier for user provided per-window aspect ratios.
* `XMonad.Hooks.TaffybarPagerHints`
Add a module that exports information about XMonads internal state that is
not available through EWMH that is used by the taffybar status bar.
* `XMonad.Hooks.StatusBar.PP`
Originally contained inside `XMonad.Hooks.DynamicLog`, this module provides the
pretty-printing abstraction and utilities, used primarly with `logHook`.
Below are changes from `XMonad.Hooks.DynamicLog`, that now are included in
this module:
- Added `shortenLeft` function, like existing `shorten` but shortens by
truncating from left instead of right. Useful for showing directories.
- Added `shorten'` and `shortenLeft'` functions with customizable overflow
markers.
- Added `filterOutWsPP` for filtering out certain workspaces from being
displayed.
- Added `xmobarBorder` for creating borders around strings and
`xmobarFont` for selecting an alternative font.
- Added `ppRename` to `PP`, which makes it possible for extensions like
`workspaceNamesPP`, `marshallPP` and/or `clickablePP` (which need to
access the original `WorkspaceId`) to compose intuitively.
- Added `ppPrinters`, `WSPP` and `fallbackPrinters` as a generalization of
the `ppCurrent`, `ppVisible`… sextet, which makes it possible for
extensions like `copiesPP` (which acts as if there was a
`ppHiddenWithCopies`) to compose intuitively.
* `XMonad.Hooks.StatusBar`
This module provides a new interface that replaces `XMonad.Hooks.DynamicLog`,
by providing composoble status bars. Supports property-based as well
as pipe-based status bars.
* `XMonad.Util.Hacks`
A collection of hacks and fixes that should be easily acessible to users:
- `windowedFullscreenFix` fixes fullscreen behaviour of chromium based
applications when using windowed fullscreen.
- `javaHack` helps when dealing with Java applications that might not work
well with xmonad.
- `trayerAboveXmobarEventHook` reliably stacks trayer on top of xmobar and
below other windows
* `XMonad.Util.ActionCycle`
A module providing a simple way to implement "cycling" `X` actions,
useful for things like alternating toggle-style keybindings.
* `XMonad.Actions.RotateSome`
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`.
Export `surfaceNext` and `surfacePrev` actions, which treat the focused window
and any hidden windows as a ring that can be rotated through the focused position.
Export `rotateSome`, a pure function that rotates some elements around a stack
while keeping others anchored in place.
* `XMonad.Actions.Sift`
Provide `siftUp` and `siftDown` actions, which behave like `swapUp` and `swapDown`
but handle the wrapping case by exchanging the windows at either end of the stack
instead of rotating the stack.
* `XMonad.Hooks.DynamicIcons`
Dynamically augment workspace names logged to a status bar via DynamicLog
based on the contents (windows) of the workspace.
* `XMonad.Hooks.WindowSwallowing`
HandleEventHooks that implement window swallowing or sublayouting:
Hide parent windows like terminals when opening other programs (like image viewers) from within them,
restoring them once the child application closes.
* `XMonad.Actions.TiledWindowDragging`
An action that allows you to change the position of windows by dragging them around.
* `XMonad.Layout.ResizableThreeColumns`
A layout based on `XMonad.Layout.ThreeColumns` but with each slave window's
height resizable.
* `XMonad.Layout.TallMastersCombo`
A layout combinator that support Shrink, Expand, and IncMasterN just as
the `Tall` layout, and also support operations of two master windows:
a main master, which is the original master window;
a sub master, the first window of the second pane.
This combinator can be nested, and has a good support for using
`XMonad.Layout.Tabbed` as a sublayout.
* `XMonad.Actions.PerWindowKeys`
Create actions that run on a `Query Bool`, usually associated with
conditions on a window, basis. Useful for creating bindings that are
excluded or exclusive for some windows.
* `XMonad.Util.DynamicScratchpads`
Declare any window as a scratchpad on the fly. Once declared, the
scratchpad behaves like `XMonad.Util.NamedScratchpad`.
* `XMonad.Prompt.Zsh`
A version of `XMonad.Prompt.Shell` that lets you use completions supplied by
zsh.
* `XMonad.Util.ClickableWorkspaces`
Provides `clickablePP`, which when applied to the `PP` pretty-printer used by
`XMonad.Hooks.StatusBar.PP`, will make the workspace tags clickable in XMobar
(for switching focus).
* `XMonad.Layout.VoidBorders`
Provides a modifier that semi-permanently (requires manual intervention)
disables borders for windows from the layout it modifies.
* `XMonad.Hooks.Focus`
Extends ManageHook EDSL to work on focused windows and current workspace.
* `XMonad.Config.LXQt`
This module provides a config suitable for use with the LXQt desktop
environment.
* `XMonad.Prompt.OrgMode`
A prompt for interacting with [org-mode](https://orgmode.org/). It
can be used to quickly save TODOs, NOTEs, and the like with the
additional capability to schedule/deadline a task, or use the
primary selection as the contents of the note.
* `XMonad.Util.ExtensibleConf`
Extensible and composable configuration for contrib modules. 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 more.
* `XMonad.Hooks.Rescreen`
Custom hooks for screen (xrandr) configuration changes. These can be used
to restart/reposition status bars or systrays automatically after xrandr,
as well as to actually invoke xrandr or autorandr when an output is
(dis)connected.
* `XMonad.Actions.EasyMotion`
A new module that allows selection of visible screens using a key chord.
Inspired by [vim-easymotion](https://github.com/easymotion/vim-easymotion). See the animation
in the vim-easymotion repo to get some idea of the functionality of this
EasyMotion module.
### Bug Fixes and Minor Changes
* Add support for GHC 9.0.1.
* `XMonad.Actions.WithAll`
- Added `killOthers`, which kills all unfocused windows on the
current workspace.
* `XMonad.Prompt.XMonad`
- Added `xmonadPromptCT`, which allows you to create an XMonad
prompt with a custom title.
* `XMonad.Actions.DynamicWorkspaceGroups`
- Add support for `XMonad.Actions.TopicSpace` through `viewTopicGroup` and
`promptTopicGroupView`.
* `XMonad.Actions.TreeSelect`
- Fix swapped green/blue in foreground when using Xft.
- The spawned tree-select window now sets a `WM_CLASS` property.
This allows other applications, like compositors, to properly
match on it.
* `XMonad.Layout.Fullscreen`
- Add fullscreenSupportBorder which uses smartBorders to remove
window borders when the window is fullscreen.
* `XMonad.Config.Mate`
- Split out the logout dialog and add a shutdown dialog. The default behavior
remains the same but there are now `mateLogout` and `mateShutdown` actions
available.
- Add mod-d keybinding to open the Mate main menu.
* `XMonad.Actions.DynamicProjects`
- The `changeProjectDirPrompt` function respects the `complCaseSensitivity` field
of `XPConfig` when performing directory completion.
- `modifyProject` is now exported.
* `XMonad.Layout.WorkspaceDir`
- The `changeDir` function respects the `complCaseSensitivity` field of `XPConfig`
when performing directory completion.
- `Chdir` message is exported, so it's now possible to change the
directory programmaticaly, not just via a user prompt.
* `XMonad.Prompt.Directory`
- Added `directoryMultipleModes'`, like `directoryMultipleModes` with an additional
`ComplCaseSensitivity` argument.
- Directory completions are now sorted.
- The `Dir` constructor now takes an additional `ComplCaseSensitivity`
argument to indicate whether directory completion is case sensitive.
* `XMonad.Prompt.FuzzyMatch`
- `fuzzySort` will now accept cases where the input is not a subsequence of
every completion.
* `XMonad.Prompt.Shell`
- Added `getShellCompl'`, like `getShellCompl` with an additional `ComplCaseSensitivity`
argument.
- Added `compgenDirectories` and `compgenFiles` to get the directory/filename completion
matches returned by the compgen shell builtin.
- Added `safeDirPrompt`, which is like `safePrompt`, but optimized
for the use-case of a program that needs a file as an argument.
* `XMonad.Prompt.Unicode`
- Reworked internally to call `spawnPipe` (asynchronous) instead of
`runProcessWithInput` (synchronous), which fixes `typeUnicodePrompt`.
- Now respects `searchPredicate` and `sorter` from user-supplied `XPConfig`.
* `XMonad.Hooks.DynamicLog`
- Added `xmobarProp`, for property-based alternative to `xmobar`.
- Add the -dock argument to the dzen spawn arguments
- The API for this module is frozen: this is now a compatibility wrapper.
- References for this module are updated to point to `X.H.StatusBar` or
`X.H.StatusBar.PP`
* `XMonad.Layout.BoringWindows`
- Added boring-aware `swapUp`, `swapDown`, `siftUp`, and `siftDown` functions.
- Added `markBoringEverywhere` function, to mark the currently
focused window boring on all layouts, when using `XMonad.Actions.CopyWindow`.
* `XMonad.Util.NamedScratchpad`
- Added two new exported functions to the module:
- `customRunNamedScratchpadAction`
(provides the option to customize the `X ()` action the scratchpad is launched by)
- `spawnHereNamedScratchpadAction`
(uses `XMonad.Actions.SpawnOn.spawnHere` to initially start the scratchpad on the workspace it was launched on)
- Deprecated `namedScratchpadFilterOutWorkspace` and
`namedScratchpadFilterOutWorkspacePP`. Use
`XMonad.Util.WorkspaceCompare.filterOutWs` respectively
`XMonad.Hooks.DynamicLog.filterOutWsPP` instead.
- Exported the `scratchpadWorkspaceTag`.
- Added a new logHook `nsHideOnFocusLoss` for hiding scratchpads
when they lose focus.
* `XMonad.Prompt.Window`
- Added `allApplications` function which maps application executable
names to its underlying window.
- Added a `WithWindow` constructor to `WindowPrompt` to allow executing
actions of type `Window -> X ()` on the chosen window.
* `XMonad.Prompt.WindowBringer`
- Added `windowAppMap` function which maps application executable
names to its underlying window.
- A new field `windowFilter` was added to the config, which allows the user
to provide a function which will decide whether each window should be
included in the window bringer menu.
* `XMonad.Actions.Search`
- The `hoogle` function now uses the new URL `hoogle.haskell.org`.
- Added `promptSearchBrowser'` function to only suggest previous searches of
the selected search engine (instead of all search engines).
* `XMonad.Layout.MouseResizableTile`
- When we calculate dragger widths, we first try to get the border width of
the focused window, before failing over to using the initial `borderWidth`.
* `XMonad.Actions.CycleRecentWS`
- Added `cycleRecentNonEmptyWS` function which behaves like `cycleRecentWS`
but is constrainded to non-empty workspaces.
- Added `toggleRecentWS` and `toggleRecentNonEmptyWS` functions which toggle
between the current and most recent workspace, and continue to toggle back
and forth on repeated presses, rather than cycling through other workspaces.
- Added `recentWS` function which allows the recency list to be filtered with
a user-provided predicate.
* `XMonad.Layout.Hidden`
- Export `HiddenWindows` type constructor.
- Export `popHiddenWindow` function restoring a specific window.
* `XMonad.Hooks.ManageDocks`
- Export `AvoidStruts` constructor
- Restored compatibility with pre-0.13 configs by making the startup hook
unnecessary for correct functioning (strut cache is initialized on-demand).
This is a temporary measure, however. The individual hooks are now
deprecated in favor of the `docks` combinator, `xmonad --recompile` now
reports deprecation warnings, and the hooks will be removed soon.
- Fixed ignoring of strut updates from override-redirect windows, which is
default for xmobar.
Previously, if one wanted xmobar to reposition itself after xrandr
changes and have xmonad handle that repositioning, one would need to
configure xmobar with `overrideRedirect = False`, which would disable
lowering on start and thus cause other problems. This is no longer
necessary.
* `XMonad.Hooks.ManageHelpers`
- Export `doSink`
- Added `doLower` and `doRaise`
- Added `shiftToSame` and `clientLeader` which allow a hook to be created
that shifts a window to the workspace of other windows of the application
(using either the `WM_CLIENT_LEADER` or `_NET_WM_PID` property).
- Added `windowTag`
- Added `(^?)`, `(~?)` and `($?)` operators as infix versions of `isPrefixOf`, `isInfixOf`
and `isSuffixOf` working with `ManageHook`s.
* `XMonad.Util.EZConfig`
- Added support for XF86Bluetooth.
* `XMonad.Util.Loggers`
- Make `battery` and `loadAvg` distro-independent.
- Added `logTitleOnScreen`, `logCurrentOnScreen` and `logLayoutOnScreen`
as screen-specific variants of `logTitle`, `logCurrent` and `logLayout`.
- Added `logWhenActive` to have loggers active only when a certain
screen is active.
- Added `logConst` to log a constant `String`, and `logDefault` (infix: `.|`)
to combine loggers.
- Added `logTitles` to log all window titles (focused and unfocused
ones) on the focused workspace, as well as `logTitlesOnScreen` as
a screen-specific variant thereof.
* `XMonad.Layout.Minimize`
- Export `Minimize` type constructor.
* `XMonad.Actions.WorkspaceNames`
- Added `workspaceNamesEwmh` which makes workspace names visible to
external pagers.
* `XMonad.Util.PureX`
- Added `focusWindow` and `focusNth` which don't refresh (and thus
possibly flicker) when they happen to be a no-op.
- Added `shiftWin` as a refresh tracking version of `W.shiftWin`.
* Several `LayoutClass` instances now have an additional `Typeable`
constraint which may break some advanced configs. The upside is that we
can now add `Typeable` to `LayoutClass` in `XMonad.Core` and make it
possible to introspect the current layout and its modifiers.
* `XMonad.Actions.TopicSpace`
- `switchTopic` now correctly updates the last used topics.
- `setLastFocusedTopic` will now check whether we have exceeded the
`maxTopicHistory` and prune the topic history as necessary, as well as
cons the given topic onto the list __before__ filtering it.
- Added `switchNthLastFocusedExclude`, which works like
`switchNthLastFocused` but is able to exclude certain topics.
- Added `switchTopicWith`, which works like `switchTopic`, but one is able
to give `setLastFocusedTopic` a custom filtering function as well.
- Instead of a hand-rolled history, use the one from
`XMonad.Hooks.WorkspaceHistory`.
- Added the screen-aware functions `getLastFocusedTopicsByScreen` and
`switchNthLastFocusedByScreen`.
* `XMonad.Hooks.WorkspaceHistory`
- Added `workspaceHistoryModify` to modify the workspace history with a pure
function.
- Added `workspaceHistoryHookExclude` for excluding certain
workspaces to ever enter the history.
* `XMonad.Util.DebugWindow`
- Fixed a bottom in `debugWindow` when used on windows with UTF8 encoded titles.
* `XMonad.Config.Xfce`
- Set `terminal` to `xfce4-terminal`.
* `XMonad.Hooks.WorkspaceCompare`
- Added `filterOutWs` for workspace filtering.
* `XMonad.Prompt`
- Accommodate completion of multiple words even when `alwaysHighlight` is
enabled.
- Made the history respect words that were "completed" by `alwaysHighlight`
upon confirmation of the selection by the user.
- Fixed a crash when focusing a new window while the prompt was up
by allowing pointer events to pass through the custom prompt event
loop.
- The prompt now cycles through its suggestions if one hits the ends
of the suggestion list and presses `TAB` again.
- Added `maxComplColumns` field to `XPConfig`, to limit the number of
columns in the completion window.
- Redefine `ComplCaseSensitivity` to a proper sum type as opposed to
a `newtype` wrapper around `Bool`.
* `XMonad.Actions.TreeSelect`
- Fixed a crash when focusing a new window while the tree select
window was up by allowing pointer events to pass through the
custom tree select event loop.
* `XMonad.Layout.NoBorders`
- Fixed handling of floating window borders in multihead setups that was
broken since 0.14.
- Added `OnlyFloat` constructor to `Ambiguity` to unconditionally
remove all borders on floating windows.
* `XMonad.Hooks.UrgencyHook`
- It's now possible to clear urgency of selected windows only using the
newly exported `clearUrgents'` function. Also, this and `clearUrgents`
now clear the `_NET_WM_STATE_DEMANDS_ATTENTION` bit as well.
- Added a variant of `filterUrgencyHook` that takes a generic `Query Bool`
to select which windows should never be marked urgent.
- Added `askUrgent` and a `doAskUrgent` manage hook helper for marking
windows as urgent from inside of xmonad. This can be used as a less
intrusive action for windows requesting focus.
* `XMonad.Hooks.ServerMode`
- To make it easier to use, the `xmonadctl` client is now included in
`scripts/`.
* `XMonad.Layout.TrackFloating`
- Fixed a bug that prevented changing focus on inactive workspaces.
* `XMonad.Layout.Magnifier`
- Added `magnifierczOff` and `magnifierczOff'` for custom-size
magnifiers that start out with magnifying disabled.
- Added `magnify` as a more general combinator, including the
ability to postpone magnifying until there are a certain number of
windows on the workspace.
* `XMonad.Layout.Renamed`
- Added `KeepWordsLeft` and `KeepWordsRight` for keeping certain number of
words in left or right direction in layout description.
* `XMonad.Hooks.WallpaperSetter`
- Added `defWPNamesPng`, which works like `defWPNames` but maps
`ws-name` to `ws-name.png` instead of `ws-name.jpg`.
- Added `defWPNamesJpg` as an alias to `defWPNames` and deprecated
the latter.
* `XMonad.Layout.SubLayouts`
- Floating windows are no longer moved to the end of the window stack.
* `XMonad.Layout.BinarySpacePartition`
- Add the ability to increase/decrease the window size by a custom
rational number. E.g: `sendMessage $ ExpandTowardsBy L 0.02`
* `XMonad.Layout.Decoration`
- The decoration window now sets a `WM_CLASS` property. This allows
other applications, like compositors, to properly match on it.
* `XMonad.Layout.IndependentScreens`
- Fixed a bug where `marshallPP` always sorted workspace names
lexically. This changes the default behaviour of `marshallPP`—the
given `ppSort` now operates in the _physical_ workspace names.
The documentation of `marshallSort` contains an example of how to
get the old behaviour, where `ppSort` operates in virtual names,
back.
- 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.
- Added a few useful utility functions related to simplify using the
module; namely `workspaceOnScreen`, `focusWindow'`, `focusScreen`,
`nthWorkspace`, and `withWspOnScreen`.
- Fixed wrong type-signature of `onCurrentScreen`.
* `XMonad.Actions.CopyWindow`
- Added `copiesPP` to make a `PP` aware of copies of the focused
window.
- `XMonad.Actions.CycleWS`
- Added `:&:`, `:|:` and `Not` data constructors to `WSType` to logically
combine predicates.
- Added `hiddenWS`, `emptyWS` and `anyWS` to replace deprecated
constructors.
- Added `ingoringWSs` as a `WSType` predicate to skip workspaces having a
tag in a given list.
- `XMonad.Actions.DynamicWorkspaceOrder`
- Added `swapWithCurrent` and `swapOrder` to the list of exported names.
- `XMonad.Actions.Submap`, `XMonad.Util.Ungrab`:
- Fixed issue with keyboard/pointer staying grabbed when a blocking action
like `runProcessWithInput` was invoked.
- `XMonad.Actions.UpdateFocus`
- Added `focusUnderPointer`, that updates the focus based on pointer
position, an inverse of `X.A.UpdatePointer`, which moves the mouse
pointer to match the focused window). Together these can be used to
ensure focus stays in sync with mouse.
- `XMonad.Layout.MultiToggle`
- Added `isToggleActive` for querying the toggle state of transformers.
Useful to show the state in a status bar.
* `XMonad.Layout.Spacing`
- Removed deprecations for `spacing`, `spacingWithEdge`,
`smartSpacing`, and `smartSpacingWithEdge`.
* `XMonad.Actions.DynamicWorkspaces`
- Fixed a system freeze when using `X.A.CopyWindow.copy` in
combination with `removeWorkspace`.
## 0.16
### Breaking Changes
* `XMonad.Layout.Decoration`
- Added `Theme` record fields for controlling decoration border width for active/inactive/urgent windows.
* `XMonad.Prompt`
- Prompt ships a vim-like keymap, see `vimLikeXPKeymap` and
`vimLikeXPKeymap'`. A reworked event loop supports new vim-like prompt
actions.
- Prompt supports dynamic colors. Colors are now specified by the `XPColor`
type in `XPState` while `XPConfig` colors remain unchanged for backwards
compatibility.
- Fixes `showCompletionOnTab`.
- The behavior of `moveWord` and `moveWord'` has changed; brought in line
with the documentation and now internally consistent. The old keymaps
retain the original behavior; see the documentation to do the same your
XMonad configuration.
* `XMonad.Util.Invisble`
- Requires `MonadFail` for `Read` instance
### New Modules
* `XMonad.Layout.TwoPanePersistent`
A layout that is like TwoPane but keeps track of the slave window that is
currently beside the master. In TwoPane, the default behavior when the master
is focused is to display the next window in the stack on the slave pane. This
is a problem when a different slave window is selected without changing the stack
order.
* `XMonad.Util.ExclusiveScratchpads`
Named scratchpads that can be mutually exclusive: This new module extends the
idea of named scratchpads such that you can define "families of scratchpads"
that are exclusive on the same screen. It also allows to remove this
constraint of being mutually exclusive with another scratchpad.
* `XMonad.Actions.Prefix`
A module that allows the user to use an Emacs-style prefix
argument (raw or numeric).
### Bug Fixes and Minor Changes
* `XMonad.Layout.Tabbed`
tabbedLeft and tabbedRight will set their tabs' height and width according to decoHeight/decoWidth
* `XMonad.Prompt`
Added `sorter` to `XPConfig` used to sort the possible completions by how
well they match the search string (example: `XMonad.Prompt.FuzzyMatch`).
Fixes a potential bug where an error during prompt execution would
leave the window open and keep the keyboard grabbed. See issue
[#180](https://github.com/xmonad/xmonad-contrib/issues/180).
Fixes [issue #217](https://github.com/xmonad/xmonad-contrib/issues/217), where
using tab to wrap around the completion rows would fail when maxComplRows is
restricting the number of rows of output.
* `XMonad.Prompt.Pass`
Added 'passOTPPrompt' to support getting OTP type password. This require
pass-otp (https://github.com/tadfisher/pass-otp) has been setup in the running
machine.
Added 'passGenerateAndCopyPrompt', which both generates a new password and
copies it to the clipboard. These two actions are commonly desirable to
take together, e.g. when establishing a new account.
Made password prompts traverse symlinks when gathering password names for
autocomplete.
* `XMonad.Actions.DynamicProjects`
Make the input directory read from the prompt in `DynamicProjects`
absolute wrt the current directory.
Before this, the directory set by the prompt was treated like a relative
directory. This means that when you switch from a project with directory
`foo` into a project with directory `bar`, xmonad actually tries to `cd`
into `foo/bar`, instead of `~/bar` as expected.
* `XMonad.Actions.DynamicWorkspaceOrder`
Add a version of `withNthWorkspace` that takes a `[WorkspaceId] ->
[WorkspaceId]` transformation to apply over the list of workspace tags
resulting from the dynamic order.
* `XMonad.Actions.GroupNavigation`
Add a utility function `isOnAnyVisibleWS :: Query Bool` to allow easy
cycling between all windows on all visible workspaces.
* `XMonad.Hooks.WallpaperSetter`
Preserve the aspect ratio of wallpapers that xmonad sets. When previous
versions would distort images to fit the screen size, it will now find a
best fit by cropping instead.
* `XMonad.Util.Themes`
Add adwaitaTheme and adwaitaDarkTheme to match their respective
GTK themes.
* 'XMonad.Layout.BinarySpacePartition'
Add a new `SplitShiftDirectional` message that allows moving windows by
splitting its neighbours.
* `XMonad.Prompt.FuzzyMatch`
Make fuzzy sort show shorter strings first.
## 0.15
### Breaking Changes
* `XMonad.Layout.Groups` & `XMonad.Layout.Groups.Helpers`
The layout will no longer perform refreshes inside of its message handling.
If you have been relying on it to in your xmonad.hs, you will need to start
sending its messages in a manner that properly handles refreshing, e.g. with
`sendMessage`.
### New Modules
* `XMonad.Util.Purex`
Unlike the opaque `IO` actions that `X` actions can wrap, regular reads from
the `XConf` and modifications to the `XState` are fundamentally pure --
contrary to the current treatment of such actions in most xmonad code. Pure
modifications to the `WindowSet` can be readily composed, but due to the
need for those modifications to be properly handled by `windows`, other pure
changes to the `XState` cannot be interleaved with those changes to the
`WindowSet` without superfluous refreshes, hence breaking composability.
This module aims to rectify that situation by drawing attention to it and
providing `PureX`: a pure type with the same monadic interface to state as
`X`. The `XLike` typeclass enables writing actions generic over the two
monads; if pure, existing `X` actions can be generalised with only a change
to the type signature. Various other utilities are provided, in particular
the `defile` function which is needed by end-users.
### Bug Fixes and Minor Changes
* Add support for GHC 8.6.1.
* `XMonad.Actions.MessageHandling`
Refresh-performing functions updated to better reflect the new `sendMessage`.
## 0.14
### Breaking Changes
@@ -126,6 +1052,12 @@
Provides a simple transformer for use with `XMonad.Layout.MultiToggle` to
dynamically toggle `XMonad.Layout.TabBarDecoration`.
* `XMonad.Hooks.RefocusLast`
Provides hooks and actions that keep track of recently focused windows on a
per workspace basis and automatically refocus the last window on loss of the
current (if appropriate as determined by user specified criteria).
* `XMonad.Layout.StateFull`
Provides `StateFull`: a stateful form of `Full` that does not misbehave when
@@ -276,7 +1208,8 @@
* `XMonad.Hooks.ManageHelpers`
Make type of ManageHook combinators more general.
- Make type of ManageHook combinators more general.
- New manage hook `doSink` for sinking windows (as upposed to the `doFloat` manage hook)
* `XMonad.Prompt`
@@ -311,6 +1244,8 @@
- New function `passTypePrompt` which uses `xdotool` to type in a password
from the store, bypassing the clipboard.
- New function `passEditPrompt` for editing a password from the
store.
- Now handles password labels with spaces and special characters inside
them.
@@ -372,6 +1307,12 @@
* `XMonad.Prompt` now stores its history file in the XMonad cache
directory in a file named `prompt-history`.
* `XMonad.Hooks.ManageDocks` now requires an additional startup hook to be
added to configuration in addition to the other 3 hooks, otherwise docks
started before xmonad are covered by windows. It's recommended to use the
newly introduced `docks` function to add all necessary hooks to xmonad
config.
### New Modules
* `XMonad.Layout.SortedLayout`
@@ -405,7 +1346,7 @@
### Bug Fixes and Minor Changes
* `XMonad.Hooks.ManageDocks`,
* `XMonad.Hooks.ManageDocks`
- Fix a very annoying bug where taskbars/docs would be
covered by windows.

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.

110
README.md
View File

@@ -1,43 +1,97 @@
# xmonad-contrib: Third Party Extensions to the xmonad Window Manager
<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/workflow/status/xmonad/xmonad-contrib/Stack?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/workflow/status/xmonad/xmonad-contrib/Haskell-CI?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/workflow/status/xmonad/xmonad-contrib/Nix?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>
</p>
[![Build Status](https://travis-ci.org/xmonad/xmonad-contrib.svg?branch=master)](https://travis-ci.org/xmonad/xmonad-contrib)
[![Open Source Helpers](https://www.codetriage.com/xmonad/xmonad-contrib/badges/users.svg)](https://www.codetriage.com/xmonad/xmonad-contrib)
# xmonad-contrib
You need the ghc compiler and xmonad window manager installed in
order to use these extensions.
**Community-maintained extensions for the [XMonad][web:xmonad] window manager.**
For installation and configuration instructions, please see the
[xmonad website][xmonad], the documents included with the
[xmonad source distribution][xmonad-git], and the
[online haddock documentation][xmonad-docs].
[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.
## Getting or Updating XMonadContrib
## Installation
* Latest release: <https://hackage.haskell.org/package/xmonad-contrib>
For installation and configuration instructions, please see:
* Git version: <https://github.com/xmonad/xmonad-contrib>
* [downloading and installing xmonad][web:download]
* [installing latest xmonad snapshot from git][web:install]
* [configuring xmonad][web:tutorial]
(To use git xmonad-contrib you must also use the
[git version of xmonad][xmonad-git].)
If you run into any trouble, consult our [documentation][web:documentation] or
ask the [community][web:community] for help.
## 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:
We welcome all forms of contributions:
XMonad.Layout.Grid
* [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]
For further details, see the [documentation][developing] for the
`XMonad.Doc.Developing` module, XMonad's [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md) and the [xmonad website][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 contrib repo is licensed under the same license as
xmonad itself, with copyright held by the authors.
[xmonad]: http://xmonad.org
[xmonad-git]: https://github.com/xmonad/xmonad
[xmonad-docs]: http://hackage.haskell.org/package/xmonad
[developing]: http://hackage.haskell.org/package/xmonad-contrib/docs/XMonad-Doc-Developing.html
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

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- 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)
--
@@ -19,7 +20,8 @@ module XMonad.Actions.AfterDrag (
ifClick') where
import XMonad
import System.Time
import Data.Time (NominalDiffTime, diffUTCTime, getCurrentTime)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -53,7 +55,7 @@ afterDrag task = do drag <- gets dragging
-- 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 ()
-> X ()
ifClick action = ifClick' 300 action (return ())
-- | Take an action if the current dragging is completed within a certain time (in milliseconds.)
@@ -61,11 +63,11 @@ 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 ()
-> X ()
ifClick' ms click drag = do
start <- io $ getClockTime
afterDrag $ do
stop <- io $ getClockTime
if diffClockTimes stop start <= noTimeDiff { tdPicosec = fromIntegral ms * 10^(9 :: Integer) }
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,7 +25,6 @@ module XMonad.Actions.BluetileCommands (
import XMonad
import qualified XMonad.StackSet as W
import XMonad.Layout.LayoutCombinators
import System.Exit
-- $usage
@@ -43,7 +43,7 @@ import System.Exit
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
--
@@ -32,7 +33,7 @@ import XMonad.Util.Dmenu (dmenu)
import qualified Data.Map as M
import System.Exit
import Data.Maybe
import XMonad.Prelude
-- $usage
--
@@ -61,18 +62,18 @@ import Data.Maybe
-- | 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-")]
]
@@ -100,7 +101,7 @@ 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

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)
--
@@ -44,7 +45,6 @@ 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
sh <- io $ getWMNormalHints d w
io $ warpPointer d none w 0 0 0 0 (fromIntegral (wa_width wa)) (fromIntegral (wa_height wa))
@@ -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,17 +20,19 @@ 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
@@ -76,18 +80,24 @@ import qualified XMonad.StackSet as W
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- $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 def { 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
@@ -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,10 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternGuards #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleRecentWS
-- Description : Cycle through most recently used workspaces.
-- Copyright : (c) Michal Janeczek <janeczek@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -19,11 +23,23 @@ module XMonad.Actions.CycleRecentWS (
-- * Usage
-- $usage
cycleRecentWS,
cycleWindowSets
cycleRecentNonEmptyWS,
cycleWindowSets,
toggleRecentWS,
toggleRecentNonEmptyWS,
toggleWindowSets,
recentWS,
#ifdef TESTING
unView,
#endif
) where
import XMonad hiding (workspaces)
import XMonad.StackSet
import XMonad.StackSet hiding (filter)
import Control.Arrow ((&&&))
import Data.Function (on)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
@@ -47,33 +63,61 @@ 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 <- gets $ genOptions . windowset
(options, unView') <- gets $ (genOptions &&& unView) . 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
let setOption n = do windows $ view (options `cycref` n) . unView'
(t, s) <- io event
case () of
() | t == keyPress && s == keyNext -> setOption (n+1)
@@ -83,3 +127,37 @@ cycleWindowSets genOptions mods keyNext keyPrev = do
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
setOption 0
io $ ungrabKeyboard d currentTime
where
cycref :: [a] -> Int -> a
cycref l i = l !! (i `mod` length l)
-- | 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
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,27 +19,21 @@ 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@:
--
-- > 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,

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,9 +84,7 @@ module XMonad.Actions.CycleWS (
) where
import Data.List ( find, 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)
@@ -112,9 +116,9 @@ 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
@@ -201,8 +205,7 @@ skipTags wss ids = filter ((`notElem` ids) . tag) wss
lastViewedHiddenExcept :: [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept skips = do
hs <- gets $ map tag . flip skipTags skips . hidden . windowset
vs <- WH.workspaceHistory
return $ choose hs (find (`elem` hs) vs)
choose hs . find (`elem` hs) <$> WH.workspaceHistory
where choose [] _ = Nothing
choose (h:_) Nothing = Just h
choose _ vh@(Just _) = vh
@@ -213,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
@@ -223,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
@@ -234,6 +237,13 @@ 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
@@ -248,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)
@@ -262,10 +277,46 @@ 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.
@@ -299,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)
@@ -309,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
@@ -321,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 ()
@@ -349,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,7 @@
--------------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleWindows
-- Description : Cycle windows while maintaining focus in place.
-- Copyright : (c) Wirt Wolff <wirtwolff@gmail.com>
-- License : BSD3-style (see LICENSE)
--
@@ -116,7 +117,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
@@ -205,7 +206,7 @@ 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
rotFocused' f s@W.Stack{} = rotSlaves' f s -- otherwise
-- $unfocused

View File

@@ -1,7 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.CycleWorkspaceByScreen
-- Description : Cycle workspaces in a screen-aware fashion.
-- Copyright : (c) 2017 Ivan Malison
-- License : BSD3-style (see LICENSE)
--
@@ -23,14 +23,12 @@ module XMonad.Actions.CycleWorkspaceByScreen (
, repeatableAction
) where
import Control.Monad
import Data.IORef
import Data.List
import Data.Maybe
import Graphics.X11.Xlib.Extras
import XMonad
import XMonad.Prelude
import XMonad.Hooks.WorkspaceHistory
import qualified XMonad.StackSet as W
@@ -51,7 +49,7 @@ repeatableAction mods pressHandler = do
return (t, s)
handleEvent (t, s)
| t == keyRelease && s `elem` mods = return ()
| otherwise = (pressHandler t s) >> getNextEvent >>= handleEvent
| otherwise = pressHandler t s >> getNextEvent >>= handleEvent
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
getNextEvent >>= handleEvent
@@ -83,9 +81,9 @@ cycleWorkspaceOnScreen screenId mods nextKey prevKey = workspaceHistoryTransacti
current <- readIORef currentWSIndex
modifyIORef
currentWSIndex
((`mod` (length cycleWorkspaces)) . (+ increment))
((`mod` length cycleWorkspaces) . (+ increment))
return $ cycleWorkspaces !! current
focusIncrement i = (io $ getAndIncrementWS i) >>= (windows . W.greedyView)
focusIncrement i = io (getAndIncrementWS i) >>= (windows . W.greedyView)
focusIncrement 1 -- Do the first workspace cycle
repeatableAction mods $

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)
--

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)
--

View File

@@ -1,8 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
--------------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicProjects
-- Description : Treat workspaces as individual project areas.
-- Copyright : (c) Peter J. Jones
-- License : BSD3-style (see LICENSE)
--
@@ -39,18 +38,14 @@ module XMonad.Actions.DynamicProjects
, lookupProject
, currentProject
, activateProject
, modifyProject
) where
--------------------------------------------------------------------------------
import Control.Applicative ((<|>))
import Control.Monad (when, unless)
import Data.Char (isSpace)
import Data.List (sort, union, stripPrefix)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe (fromMaybe, isNothing)
import Data.Monoid ((<>))
import System.Directory (setCurrentDirectory, getHomeDirectory)
import System.Directory (setCurrentDirectory, getHomeDirectory, makeAbsolute)
import XMonad.Prelude
import XMonad
import XMonad.Actions.DynamicWorkspaces
import XMonad.Prompt
@@ -130,14 +125,14 @@ data Project = Project
{ projectName :: !ProjectName -- ^ Workspace name.
, projectDirectory :: !FilePath -- ^ Working directory.
, projectStartHook :: !(Maybe (X ())) -- ^ Optional start-up hook.
} deriving Typeable
}
--------------------------------------------------------------------------------
-- | Internal project state.
data ProjectState = ProjectState
{ projects :: !ProjectTable
, previousProject :: !(Maybe WorkspaceId)
} deriving Typeable
}
--------------------------------------------------------------------------------
instance ExtensionClass ProjectState where
@@ -145,24 +140,24 @@ instance ExtensionClass ProjectState where
--------------------------------------------------------------------------------
-- Internal types for working with XPrompt.
data ProjectPrompt = ProjectPrompt ProjectMode [ProjectName]
data ProjectPrompt = ProjectPrompt XPConfig ProjectMode [ProjectName]
data ProjectMode = SwitchMode | ShiftMode | RenameMode | DirMode
instance XPrompt ProjectPrompt where
showXPrompt (ProjectPrompt submode _) =
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 DirMode _) =
let xpt = directoryMultipleModes "" (const $ return ())
completionFunction (ProjectPrompt _ RenameMode _) = return . (:[])
completionFunction (ProjectPrompt c DirMode _) =
let xpt = directoryMultipleModes' (complCaseSensitivity c) "" (const $ return ())
in completionFunction xpt
completionFunction (ProjectPrompt _ ns) = mkComplFunFromList' ns
completionFunction (ProjectPrompt c _ ns) = mkComplFunFromList' c ns
modeAction (ProjectPrompt SwitchMode _) buf auto = do
modeAction (ProjectPrompt _ SwitchMode _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
@@ -171,18 +166,19 @@ instance XPrompt ProjectPrompt where
Nothing | null name -> return ()
| otherwise -> switchProject (defProject name)
modeAction (ProjectPrompt ShiftMode _) buf auto = do
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 _ =
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
modeAction (ProjectPrompt _ DirMode _) buf auto = do
let dir' = if null auto then buf else auto
dir <- io $ makeAbsolute dir'
modifyProject (\p -> p { projectDirectory = dir })
--------------------------------------------------------------------------------
@@ -230,7 +226,7 @@ dynamicProjectsStartupHook ps = XS.modify go
--------------------------------------------------------------------------------
-- | Find a project based on its name.
lookupProject :: ProjectName -> X (Maybe Project)
lookupProject name = Map.lookup name `fmap` XS.gets projects
lookupProject name = Map.lookup name <$> XS.gets projects
--------------------------------------------------------------------------------
-- | Fetch the current project (the one being used for the currently
@@ -326,11 +322,11 @@ changeProjectDirPrompt = projectPrompt [ DirMode
-- | Prompt for a project name.
projectPrompt :: [ProjectMode] -> XPConfig -> X ()
projectPrompt submodes c = do
ws <- map W.tag `fmap` gets (W.workspaces . windowset)
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 m names) submodes
modes = map (\m -> XPT $ ProjectPrompt c m names) submodes
mkXPromptWithModes modes c

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)
--
@@ -34,17 +33,22 @@ 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:
@@ -63,14 +67,14 @@ 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
@@ -85,9 +89,7 @@ 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 -> addRawWSGroup 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.
@@ -103,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.
@@ -124,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 ()
@@ -144,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,6 +22,8 @@ module XMonad.Actions.DynamicWorkspaceOrder
getWsCompareByOrder
, getSortByOrder
, swapWith
, swapWithCurrent
, swapOrder
, updateName
, removeName
@@ -30,6 +31,7 @@ module XMonad.Actions.DynamicWorkspaceOrder
, moveToGreedy
, shiftTo
, withNthWorkspace'
, withNthWorkspace
) where
@@ -43,7 +45,7 @@ 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
@@ -66,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
-- > ...
@@ -88,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
@@ -183,13 +185,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,8 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.DynamicWorkspaces
-- Description : Provides bindings to add and delete workspaces.
-- Copyright : (c) David Roundy <droundy@darcs.net>
-- License : BSD3-style (see LICENSE)
--
@@ -35,14 +34,12 @@ module XMonad.Actions.DynamicWorkspaces (
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.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
@@ -88,8 +85,8 @@ type WorkspaceIndex = Int
-- | Internal dynamic project state that stores a mapping between
-- workspace indexes and workspace tags.
data DynamicWorkspaceState = DynamicWorkspaceState {workspaceIndexMap :: Map.Map WorkspaceIndex WorkspaceTag}
deriving (Typeable, Read, Show)
newtype DynamicWorkspaceState = DynamicWorkspaceState {workspaceIndexMap :: Map.Map WorkspaceIndex WorkspaceTag}
deriving (Read, Show)
instance ExtensionClass DynamicWorkspaceState where
initialValue = DynamicWorkspaceState Map.empty
@@ -108,7 +105,7 @@ withWorkspaceIndex job widx = do
maybe (return ()) (windows . job) wtag
where
ilookup :: WorkspaceIndex -> X (Maybe WorkspaceTag)
ilookup idx = Map.lookup idx `fmap` XS.gets workspaceIndexMap
ilookup idx = Map.lookup idx <$> XS.gets workspaceIndexMap
mkCompl :: [String] -> String -> IO [String]
@@ -127,14 +124,14 @@ renameWorkspace conf = workspacePrompt conf renameWorkspaceByName
renameWorkspaceByName :: String -> X ()
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 }
windows $ \s -> let sett wk = wk { tag = w }
setscr scr = scr { workspace = sett $ workspace scr }
sets q = q { current = setscr $ current q }
in sets $ removeWorkspace' w s
updateIndexMap old w
where updateIndexMap old new = do
updateIndexMap old w
where updateIndexMap oldIM newIM = do
wmap <- XS.gets workspaceIndexMap
XS.modify $ \s -> s {workspaceIndexMap = Map.map (\t -> if t == old then new else t) wmap}
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
@@ -241,20 +238,20 @@ isEmpty t = do wsl <- gets $ workspaces . windowset
return $ maybe True (isNothing . stack) mws
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 }
addHiddenWorkspace' add newtag l s@StackSet{ hidden = ws } = s { hidden = add (Workspace newtag l Nothing) 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) => i -> StackSet i l a sid sd -> StackSet i l a sid sd
removeWorkspace' torem s@(StackSet { current = scr@(Screen { workspace = wc })
, hidden = hs })
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)
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,388 @@
{-# LANGUAGE CPP #-}
{-# 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\/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 dpy th visibleWindows
PerScreenKeys m ->
fmap concat
$ sequence
$ M.elems
$ M.mapWithKey (\sid ks -> buildOverlays ks <$> sortedOverlayWindows sid) m
where
screenById :: ScreenId -> Maybe (W.Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail)
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 dpy 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 ks = appendChords (maxChordLen c) ks
buildOverlayWindows :: Display -> Position -> [Window] -> X [OverlayWindow]
buildOverlayWindows dpy th ws = sequence $ buildOverlayWin dpy th <$> ws
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 :: Display -> Position -> Window -> X OverlayWindow
buildOverlayWin dpy th w = do
wAttrs <- io $ getWindowAttributes dpy w
let r = overlayF c th $ makeRect wAttrs
o <- createNewWindow r Nothing "" True
return 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 = tail $ 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,9 +19,7 @@ module XMonad.Actions.FindEmptyWorkspace (
viewEmptyWorkspace, tagToEmptyWorkspace, sendToEmptyWorkspace
) where
import Data.List
import Data.Maybe ( isNothing )
import XMonad.Prelude
import XMonad
import XMonad.StackSet

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,8 +24,9 @@ module XMonad.Actions.FlexibleManipulate (
) where
import XMonad
import XMonad.Prelude ((<&>))
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, map, otherwise, round, snd, uncurry, ($), (.))
-- $usage
-- First, add this import to your @~\/.xmonad\/xmonad.hs@:
@@ -79,24 +81,23 @@ position = const 0.5
-- 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
[wpos, wsize] <- io $ getWindowAttributes d w <&> winAttrs
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
@@ -113,7 +114,7 @@ type Pnt = (Double, Double)
pairUp :: [a] -> [(a,a)]
pairUp [] = []
pairUp [_] = []
pairUp (x:y:xs) = (x, y) : (pairUp xs)
pairUp (x:y:xs) = (x, y) : pairUp xs
mapP :: (a -> b) -> (a, a) -> (b, b)
mapP f (x, y) = (f x, f y)
@@ -132,4 +133,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,7 +21,7 @@ module XMonad.Actions.FlexibleResize (
) where
import XMonad
import XMonad.Util.XUtils (fi)
import XMonad.Prelude (fi)
import Foreign.C.Types
-- $usage
@@ -50,7 +51,6 @@ mouseResizeEdgeWindow
-> Window -- ^ The window to resize.
-> X ()
mouseResizeEdgeWindow edge w = whenX (isClient w) $ withDisplay $ \d -> do
io $ raiseWindow d w
wa <- io $ getWindowAttributes d w
sh <- io $ getWMNormalHints d w
(_, _, _, _, _, ix, iy, _) <- io $ queryPointer d w
@@ -62,16 +62,17 @@ mouseResizeEdgeWindow edge w = whenX (isClient w) $ withDisplay $ \d -> do
(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
--
@@ -22,6 +23,7 @@ module XMonad.Actions.FloatKeys (
) where
import XMonad
import XMonad.Prelude (fi)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -43,10 +45,9 @@ import XMonad
-- 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))
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
@@ -61,14 +62,14 @@ keysMoveWindow (dx,dy) w = whenX (isClient w) $ withDisplay $ \d -> do
-- > 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)))
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 +81,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 +91,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
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)
--
@@ -27,9 +28,7 @@ module XMonad.Actions.FloatSnap (
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
@@ -96,14 +95,14 @@ snapMagicMouseResize
snapMagicMouseResize middle collidedist snapdist w = whenX (isClient w) $ withDisplay $ \d -> do
wa <- io $ getWindowAttributes d w
(_, _, _, 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
@@ -121,18 +120,17 @@ snapMagicResize
-> 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
(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
@@ -152,13 +150,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
@@ -171,7 +169,6 @@ snapMagicMove
-> 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
nx <- handleAxis True d wa
@@ -194,8 +191,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
@@ -212,7 +209,6 @@ 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
((bl,br,_),(fl,fr,_)) <- getSnap horiz collidedist d w
@@ -252,7 +248,6 @@ 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
mr <- case dir of
L -> do ((mg,ms,_),(_,_,_)) <- getSnap True collidedist d w
@@ -274,9 +269,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
@@ -291,8 +285,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)
@@ -306,8 +300,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) $
@@ -321,8 +315,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,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.FocusNth
-- Description : Focus the nth window of the current workspace.
-- Copyright : (c) Karsten Schoelzel <kuser@gmx.de>
-- License : BSD
--
@@ -39,7 +40,7 @@ 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
focusNth' n s@(Stack _ ls rs) | (n < 0) || (n > length ls + length rs) = s
| otherwise = listToStack n (integrate s)
-- | Swap current window with nth. Focus stays in the same position
@@ -51,12 +52,9 @@ swapNth' n s@(Stack c l r)
| (n < 0) || (n > length l + length r) || (n == length l) = s
| n < length l = let (nl, nc:nr) = splitAt (length l - n - 1) l in Stack nc (nl ++ c : nr) r
| otherwise = let (nl, nc:nr) = splitAt (n - length l - 1) r in Stack nc l (nl ++ c : nr)
listToStack :: Int -> [a] -> Stack a
listToStack n l = Stack t ls rs
where
(t:rs) = drop n l
ls = reverse (take n l)

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)
--
@@ -28,7 +29,6 @@ module XMonad.Actions.GridSelect (
-- * Configuration
GSConfig(..),
def,
defaultGSConfig,
TwoDPosition,
buildDefaultGSConfig,
@@ -48,6 +48,7 @@ module XMonad.Actions.GridSelect (
fromClassName,
stringColorizer,
colorRangeFromClassName,
stringToRatio,
-- * Navigation Mode assembly
TwoD,
@@ -79,16 +80,14 @@ module XMonad.Actions.GridSelect (
-- * 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
@@ -96,7 +95,7 @@ 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)
-- $usage
@@ -107,13 +106,13 @@ import Data.Word (Word8)
--
-- 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
--
@@ -123,7 +122,7 @@ 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'
-- in order to specify a custom colorizer is @gsconfig2@ (found in
@@ -222,18 +221,14 @@ 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
instance HasColorizer a => Default (GSConfig a) where
def = buildDefaultGSConfig defaultColorizer
{-# DEPRECATED defaultGSConfig "Use def (from Data.Default, and re-exported from XMonad.Actions.GridSelect) instead." #-}
defaultGSConfig :: HasColorizer a => GSConfig a
defaultGSConfig = def
type TwoDPosition = (Integer, Integer)
type TwoDElementMap a = [(TwoDPosition,(String,a))]
@@ -264,7 +259,7 @@ generateElementmap s = do
-- 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
@@ -308,8 +303,8 @@ 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..]
@@ -339,7 +334,7 @@ drawWinBox win font (fg,bg) bc 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
-- calculate the offset to vertically centre the text based on the ascender and descender
(asc,desc) <- liftIO $ textExtentsXMF font stext
@@ -392,9 +387,9 @@ 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,
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
@@ -403,7 +398,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
@@ -435,7 +430,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)
@@ -450,7 +445,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 ()
@@ -550,7 +545,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
@@ -564,7 +559,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)
@@ -576,8 +571,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)
@@ -594,19 +589,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.
@@ -635,15 +630,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.
@@ -662,14 +654,14 @@ gridselect gsconfig elements =
font <- initXMF (gs_font gsconfig)
let screenWidth = toInteger $ rect_width scr
screenHeight = toInteger $ rect_height scr
selectedElement <- if (status == grabSuccess) then do
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
s = TwoDState { td_curpos = (head coords),
s = TwoDState { td_curpos = head coords,
td_availSlots = coords,
td_elements = elements,
td_gsconfig = gsconfig,
@@ -680,7 +672,7 @@ gridselect gsconfig elements =
td_searchString = "",
td_elementmap = [] }
m <- generateElementmap s
evalTwoD (updateAllElements >> (gs_navigate gsconfig))
evalTwoD (updateAllElements >> gs_navigate gsconfig)
(s { td_elementmap = m })
else
return Nothing
@@ -702,20 +694,17 @@ 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
@@ -770,7 +759,7 @@ gridselectWorkspace' conf func = withWindowSet $ \ws -> do
--
-- > import XMonad.Actions.DynamicWorkspaces (addWorkspace)
-- >
-- > gridselectWorkspace' defaultGSConfig
-- > gridselectWorkspace' def
-- > { gs_navigate = navNSearch
-- > , gs_rearranger = searchStringRearrangerGenerator id
-- > }
@@ -789,7 +778,7 @@ noRearranger _ = return
-- already present).
searchStringRearrangerGenerator :: (String -> a) -> Rearranger a
searchStringRearrangerGenerator f =
let r "" xs = return $ xs
r s xs | s `elem` map fst xs = return $ xs
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,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
----------------------------------------------------------------------
-- |
-- 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 +15,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,18 +26,25 @@ 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.State
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 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
@@ -122,12 +128,12 @@ focusNextMatchOrDo qry act = findM (runQuery qry)
-- Returns the list of windows ordered by workspace as specified in
-- ~/.xmonad/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
@@ -141,8 +147,8 @@ 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 +156,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)
instance ExtensionClass HistoryDB where
@@ -167,26 +173,11 @@ updateHistory :: HistoryDB -> X HistoryDB
updateHistory (HistoryDB oldcur oldhist) = withWindowSet $ \ss -> do
let newcur = SS.peek ss
wins = Set.fromList $ SS.allWindows ss
newhist = flt (flip Set.member wins) (ins oldcur oldhist)
newhist = Seq.filter (`Set.member` wins) (ins oldcur oldhist)
return $ 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 +191,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 +207,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 = concat $ 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]

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
@@ -62,8 +62,8 @@ 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
@@ -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

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- 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)
--
@@ -14,7 +15,6 @@
--
-----------------------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
module XMonad.Actions.LinkWorkspaces (
-- * Usage
-- $usage
@@ -27,6 +27,7 @@ module XMonad.Actions.LinkWorkspaces (
) 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)
@@ -59,7 +60,7 @@ import qualified Data.Map as M
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
data MessageConfig = MessageConfig { messageFunction :: (ScreenId -> [Char] -> [Char] -> [Char] -> X())
data MessageConfig = MessageConfig { messageFunction :: ScreenId -> [Char] -> [Char] -> [Char] -> X()
, foreground :: [Char]
, alertedForeground :: [Char]
, background :: [Char]
@@ -75,8 +76,8 @@ noMessageFn :: ScreenId -> [Char] -> [Char] -> [Char] -> X()
noMessageFn _ _ _ _ = return () :: X ()
-- | Stuff for linking workspaces
data WorkspaceMap = WorkspaceMap (M.Map WorkspaceId WorkspaceId) deriving (Read, Show, Typeable)
instance ExtensionClass WorkspaceMap
newtype WorkspaceMap = WorkspaceMap (M.Map WorkspaceId WorkspaceId) deriving (Read, Show)
instance ExtensionClass WorkspaceMap
where initialValue = WorkspaceMap M.empty
extensionType = PersistentExtension
@@ -85,12 +86,12 @@ 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' :: (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)
let next = (now + 1) `mod` nScreens
switchFn workspace
case stopAtScreen of
Nothing -> sTM now next (Just now)
@@ -99,21 +100,21 @@ switchWS' switchFn message workspace stopAtScreen = do
-- | 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 :: (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
case M.lookup t matchings of
Nothing -> return () :: X()
Just newWorkspace -> do
onScreen' (f newWorkspace stopAtScreen) FocusCurrent next
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
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 ()
@@ -142,7 +143,7 @@ removeAllMatchings :: MessageConfig -> X ()
removeAllMatchings message = do
ws <- gets windowset
let now = W.screen (W.current ws)
XS.put $ WorkspaceMap $ M.empty
XS.put $ WorkspaceMap M.empty
messageFunction message now (alertedForeground message) (background message) "All links removed!"
-- | remove all matching regarding a given workspace
@@ -163,7 +164,6 @@ toggleLinkWorkspaces' first message = do
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
case (W.lookupWorkspace next ws) of
Nothing -> return ()
Just name -> toggleMatching message (W.currentTag ws) (name)
for_ (W.lookupWorkspace next ws)
(toggleMatching message (W.currentTag ws))
onScreen' (toggleLinkWorkspaces' first message) FocusCurrent next

View File

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.MessageFeedback
-- Description : An alternative @sendMessage@.
-- Copyright : (c) -- Quentin Moser <moserq@gmail.com>
-- 2018 Yclept Nemo
-- License : BSD3
@@ -51,13 +52,11 @@ module XMonad.Actions.MessageFeedback
import XMonad ( Window )
import XMonad.Core ( X(), Message, SomeMessage(..), LayoutClass(..), windowset, catchX, WorkspaceId, Layout, whenJust )
import XMonad.Operations ( updateLayout, windowBracket, modifyWindowSet )
import XMonad.Prelude ( isJust, liftA2, void )
import XMonad.StackSet ( Workspace, current, workspace, layout, tag )
import XMonad.Operations ( updateLayout, refresh, windows )
import Data.Maybe ( isJust )
import Control.Monad ( when, void )
import Control.Monad.State ( gets )
import Control.Applicative ( (<$>), liftA2 )
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -107,11 +106,11 @@ import Control.Applicative ( (<$>), liftA2 )
-- 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 = do
w <- workspace . current <$> gets windowset
sendSomeMessageB m = windowBracket id $ do
w <- gets ((workspace . current) . windowset)
ml <- handleMessage (layout w) m `catchX` return Nothing
whenJust ml $ \l ->
windows $ \ws -> ws { current = (current ws)
modifyWindowSet $ \ws -> ws { current = (current ws)
{ workspace = (workspace $ current ws)
{ layout = l }}}
return $ isJust ml
@@ -140,7 +139,7 @@ sendSomeMessageWithNoRefresh m = void . sendSomeMessageWithNoRefreshB m
-- 'XMonad.Operations.sendMessageWithNoRefresh' (does not refresh).
sendSomeMessageWithNoRefreshToCurrentB :: SomeMessage -> X Bool
sendSomeMessageWithNoRefreshToCurrentB m
= (gets $ workspace . current . windowset)
= gets (workspace . current . windowset)
>>= sendSomeMessageWithNoRefreshB m
-- | Variant of 'sendSomeMessageWithNoRefreshToCurrentB' that discards the
@@ -178,9 +177,9 @@ sendMessageWithNoRefreshToCurrent = void . sendMessageWithNoRefreshToCurrentB
-- that would have otherwise used 'XMonad.Operations.sendMessage' while
-- minimizing refreshes, use this.
sendSomeMessagesB :: [SomeMessage] -> X [Bool]
sendSomeMessagesB m
= mapM sendSomeMessageWithNoRefreshToCurrentB m
>>= liftA2 (>>) (flip when refresh . or) return
sendSomeMessagesB
= windowBracket or
. mapM sendSomeMessageWithNoRefreshToCurrentB
-- | Variant of 'sendSomeMessagesB' that discards the results.
sendSomeMessages :: [SomeMessage] -> X ()

View File

@@ -1,6 +1,7 @@
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Minimize
-- Description : Actions for minimizing and maximizing windows.
-- Copyright : (c) Bogdan Sinitsyn (2016)
-- License : BSD3-style (see LICENSE)
--
@@ -35,6 +36,7 @@ module XMonad.Actions.Minimize
) where
import XMonad
import XMonad.Prelude (fromMaybe, join, listToMaybe)
import qualified XMonad.StackSet as W
import qualified XMonad.Layout.BoringWindows as BW
@@ -43,9 +45,6 @@ import XMonad.Util.Minimize
import XMonad.Util.WindowProperties (getProp32)
import Foreign.C.Types (CLong)
import Control.Applicative((<$>))
import Control.Monad (join)
import Data.Maybe (fromMaybe, listToMaybe)
import qualified Data.List as L
import qualified Data.Map as M
@@ -120,7 +119,7 @@ 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' (flip whenJust action)
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.
@@ -130,7 +129,7 @@ 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' (flip whenJust action)
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.

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,14 +22,13 @@ 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
--
@@ -111,7 +111,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)
--
@@ -56,7 +57,7 @@ import XMonad.Util.XUtils
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)
--
@@ -39,7 +40,6 @@ module XMonad.Actions.Navigation2D ( -- * Usage
, withNavigation2DConfig
, Navigation2DConfig(..)
, def
, defaultNavigation2DConfig
, Navigation2D
, lineNavigation
, centerNavigation
@@ -58,11 +58,10 @@ 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 Data.Ord (comparing)
import Control.Arrow (second)
import XMonad.Prelude
import XMonad hiding (Screen)
import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS
@@ -386,7 +385,7 @@ 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
@@ -451,10 +450,6 @@ withNavigation2DConfig conf2d xconf = xconf { startupHook = startupHook xconf
>> XS.put conf2d
}
{-# DEPRECATED defaultNavigation2DConfig "Use def (from Data.Default, and re-exported from XMonad.Actions.Navigation2D) instead." #-}
defaultNavigation2DConfig :: Navigation2DConfig
defaultNavigation2DConfig = def
instance Default Navigation2DConfig where
def = Navigation2DConfig { defaultTiledNavigation = lineNavigation
, floatNavigation = centerNavigation
@@ -482,7 +477,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
)
@@ -492,7 +487,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
@@ -501,7 +495,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
)
@@ -509,32 +503,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
@@ -654,7 +644,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
@@ -674,8 +664,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
@@ -720,7 +709,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
@@ -761,9 +750,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
@@ -821,7 +809,7 @@ doSideNavigationWithBias ::
Eq a => Int -> Direction2D -> Rect a -> [Rect a] -> Maybe a
doSideNavigationWithBias bias dir (cur, rect)
= fmap fst . listToMaybe
. L.sortBy (comparing dist) . foldr acClosest []
. L.sortOn dist . foldr acClosest []
. filter (`toRightOf` (cur, transform rect))
. map (fmap transform)
where
@@ -849,7 +837,7 @@ doSideNavigationWithBias bias dir (cur, rect)
-- 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) : []
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
@@ -870,7 +858,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
@@ -895,14 +883,10 @@ swap win winset = W.focusWindow cur
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]
@@ -939,8 +923,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
@@ -950,16 +934,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)
--
@@ -27,7 +28,7 @@ toggleBorder :: Window -> X ()
toggleBorder w = do
bw <- asks (borderWidth . config)
withDisplay $ \d -> io $ do
cw <- wa_border_width `fmap` getWindowAttributes d w
cw <- wa_border_width <$> getWindowAttributes d w
if cw == 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)
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

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\/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
-- "XMonad.Doc.Extending#Editing_key_bindings".
-- | 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)
--
@@ -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
--
@@ -30,11 +31,9 @@ module XMonad.Actions.PhysicalScreens (
) 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
@@ -63,7 +62,7 @@ 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 def, shiftMask)]]
> , (f, mask) <- [(viewScreen def, 0), (sendToScreen def, shiftMask)]]
For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings".
@@ -72,7 +71,7 @@ For detailed instructions on editing your key bindings, see
-- | The type of the index of a screen by location
newtype PhysicalScreen = P Int deriving (Eq,Ord,Show,Read,Enum,Num,Integral,Real)
getScreenIdAndRectangle :: (W.Screen i l a ScreenId ScreenDetail) -> (ScreenId, Rectangle)
getScreenIdAndRectangle :: W.Screen i l a ScreenId ScreenDetail -> (ScreenId, Rectangle)
getScreenIdAndRectangle screen = (W.screen screen, rect) where
rect = screenRect $ W.screenDetail screen
@@ -89,8 +88,8 @@ getScreen (ScreenComparator cmpScreen) (P i) = do w <- gets windowset
viewScreen :: ScreenComparator -> PhysicalScreen -> X ()
viewScreen sc p = do i <- getScreen sc p
whenJust i $ \s -> do
w <- screenWorkspace s
whenJust w $ windows . W.view
w <- screenWorkspace s
whenJust w $ windows . W.view
-- | Send the active window to a given physical screen
sendToScreen :: ScreenComparator -> PhysicalScreen -> X ()
@@ -131,7 +130,7 @@ 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 = maybe 0 id $ findIndex (== W.screen (W.current w)) ss
curPos = fromMaybe 0 $ elemIndex (W.screen (W.current w)) ss
pos = (curPos + d) `mod` length ss
return $ ss !! pos

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,11 +39,9 @@ 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
import XMonad
import XMonad.StackSet hiding (workspaces)
import XMonad.Util.Run

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

@@ -0,0 +1,212 @@
{-# 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
, 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)
{- $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 :: [(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 (head events) ++ [key]
_ -> reverse (key: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 ()) -> X ()
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
-- | 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)
--

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

@@ -1,6 +1,7 @@
-----------------------------------------------------------------------------
-- |
-- 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)
--
@@ -40,8 +41,8 @@ import XMonad
-- | 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' (\l -> tail l++[head l]))
rotSlavesDown = windows $ modify' (rotSlaves' (\l -> last l : init l))
-- | The actual rotation, as a pure function on the window stack.
rotSlaves' :: ([a] -> [a]) -> Stack a -> Stack a
@@ -49,12 +50,12 @@ 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))
(revls',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' (\l -> tail l++[head l]))
rotAllDown = windows $ modify' (rotAll' (\l -> last l : init l))
-- | The actual rotation, as a pure function on the window stack.
rotAll' :: ([a] -> [a]) -> Stack a -> Stack a

View File

@@ -0,0 +1,161 @@
-----------------------------------------------------------------------------
-- |
-- 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 (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\/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', 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,
@@ -35,12 +38,13 @@ module XMonad.Actions.Search ( -- * Usage
debbts,
debpts,
dictionary,
ebay,
github,
google,
hackage,
hoogle,
images,
imdb,
isohunt,
lucky,
maps,
mathworld,
@@ -63,13 +67,12 @@ module XMonad.Actions.Search ( -- * Usage
) where
import Codec.Binary.UTF8.String (encode)
import Data.Char (isAlphaNum, isAscii)
import Data.List (isPrefixOf)
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)
@@ -113,6 +116,10 @@ import XMonad.Util.XSelection (getSelection)
* 'dictionary' -- dictionary.reference.com search.
* 'ebay' -- Ebay keyword search.
* 'github' -- GitHub keyword search.
* 'google' -- basic Google search.
* 'hackage' -- Hackage, the Haskell package database.
@@ -125,8 +132,6 @@ import XMonad.Util.XSelection (getSelection)
* 'imdb' -- the Internet Movie Database.
* 'isohunt' -- isoHunt search.
* 'lucky' -- Google "I'm feeling lucky" search.
* 'maps' -- Google maps.
@@ -137,7 +142,7 @@ import XMonad.Util.XSelection (getSelection)
* 'scholar' -- Google scholar academic search.
* 'thesaurus' -- thesaurus.reference.com search.
* 'thesaurus' -- thesaurus.com search.
* 'wayback' -- the Wayback Machine.
@@ -191,7 +196,7 @@ Or in combination with XMonad.Util.EZConfig:
>
> searchList :: [(String, S.SearchEngine)]
> searchList = [ ("g", S.google)
> , ("h", S.hoohle)
> , ("h", S.hoogle)
> , ("w", S.wikipedia)
> ]
@@ -210,7 +215,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
@@ -248,7 +253,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
@@ -257,21 +262,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 $ tail $ 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.
@@ -281,38 +286,39 @@ 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, stackage, thesaurus, vocabulary, wayback, wikipedia, wiktionary,
amazon, alpha, codesearch, deb, debbts, debpts, dictionary, ebay, github, google, hackage, hoogle,
images, imdb, lucky, maps, mathworld, openstreetmap, scholar, stackage, thesaurus, vocabulary, wayback, wikipedia, wiktionary,
youtube, duckduckgo :: SearchEngine
amazon = searchEngine "amazon" "http://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords="
alpha = searchEngine "alpha" "http://www.wolframalpha.com/input/?i="
codesearch = searchEngine "codesearch" "http://www.google.com/codesearch?q="
deb = searchEngine "deb" "http://packages.debian.org/"
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="
stackage = searchEngine "stackage" "www.stackage.org/lts/hoogle?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/*/"++)
vocabulary = searchEngine "vocabulary" "http://www.vocabulary.com/search?q="
amazon = searchEngine "amazon" "https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords="
alpha = searchEngine "alpha" "https://www.wolframalpha.com/input/?i="
codesearch = searchEngine "codesearch" "https://developers.google.com/s/results/code-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/"
ebay = searchEngine "ebay" "https://www.ebay.com/sch/i.html?_nkw="
github = searchEngine "github" "https://github.com/search?q="
google = searchEngine "google" "https://www.google.com/search?num=100&q="
hackage = searchEngine "hackage" "https://hackage.haskell.org/package/"
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="
openstreetmap = searchEngine "openstreetmap" "https://www.openstreetmap.org/search?query="
scholar = searchEngine "scholar" "https://scholar.google.com/scholar?q="
stackage = searchEngine "stackage" "https://www.stackage.org/lts/hoogle?q="
thesaurus = searchEngine "thesaurus" "https://thesaurus.com/browse/"
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="
wayback = searchEngineF "wayback" ("https://web.archive.org/web/*/"++)
vocabulary = searchEngine "vocabulary" "https://www.vocabulary.com/search?q="
duckduckgo = searchEngine "duckduckgo" "https://duckduckgo.com/?t=lm&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, duckduckgo, (prefixAware google)]
multi = namedEngine "multi" $ foldr1 (!>) [amazon, alpha, codesearch, deb, debbts, debpts, dictionary, ebay, github, google, hackage, hoogle, images, imdb, lucky, maps, mathworld, openstreetmap, scholar, thesaurus, wayback, wikipedia, wiktionary, duckduckgo, 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
@@ -320,9 +326,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"
@@ -342,6 +348,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
@@ -358,8 +365,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,8 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.ShowText
-- Description : Display text on the screen.
-- Copyright : (c) Mario Pastorelli (2012)
-- License : BSD-style (see xmonad/LICENSE)
--
@@ -17,17 +18,15 @@ module XMonad.Actions.ShowText
( -- * Usage
-- $usage
def
, defaultSTConfig
, 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, when)
import XMonad.StackSet (current,screen)
import XMonad.Util.Font (Align(AlignCenter)
, initXMF
@@ -37,7 +36,6 @@ 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
@@ -58,7 +56,7 @@ import qualified XMonad.Util.ExtensibleState as ES
-- | 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
@@ -75,22 +73,22 @@ data ShowTextConfig =
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"
}
{-# DEPRECATED defaultSTConfig "Use def (from Data.Default, and re-exported by XMonad.Actions.ShowText) instead." #-}
defaultSTConfig :: ShowTextConfig
defaultSTConfig = def
-- | Handles timer events that notify when a window should be removed
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)
when (mtyp == a && not (null d))
(whenJust (lookup (fromIntegral $ head d) m) deleteWindow)
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\/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)
--

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

View File

@@ -1,7 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SpawnOn
-- Description : Modify a window spawned by a command.
-- Copyright : (c) Spencer Janssen
-- License : BSD
--
@@ -29,15 +29,13 @@ module XMonad.Actions.SpawnOn (
) where
import Control.Exception (tryJust)
import Control.Monad (guard)
import Data.List (isInfixOf)
import Data.Maybe (isJust)
import System.IO.Error (isDoesNotExistError)
import System.IO.Unsafe (unsafePerformIO)
import System.Posix.Types (ProcessID)
import Text.Printf (printf)
import XMonad
import XMonad.Prelude
import qualified XMonad.StackSet as W
import XMonad.Hooks.ManageHelpers
@@ -68,15 +66,15 @@ import qualified XMonad.Util.ExtensibleState as XS
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
newtype Spawner = Spawner {pidsRef :: [(ProcessID, ManageHook)]} deriving Typeable
newtype Spawner = Spawner {pidsRef :: [(ProcessID, ManageHook)]}
instance ExtensionClass Spawner where
initialValue = Spawner []
getPPIDOf :: ProcessID -> Maybe ProcessID
getPPIDOf pid =
case unsafePerformIO . tryJust (guard . isDoesNotExistError) . readFile . printf "/proc/%d/stat" $ toInteger pid of
getPPIDOf thisPid =
case unsafePerformIO . tryJust (guard . isDoesNotExistError) . readFile . printf "/proc/%d/stat" $ toInteger thisPid of
Left _ -> Nothing
Right contents -> case lines contents of
[] -> Nothing
@@ -85,11 +83,11 @@ getPPIDOf pid =
_ -> Nothing
getPPIDChain :: ProcessID -> [ProcessID]
getPPIDChain pid' = ppid_chain pid' []
where ppid_chain pid acc =
if pid == 0
getPPIDChain thisPid = ppid_chain thisPid []
where ppid_chain pid' acc =
if pid' == 0
then acc
else case getPPIDOf pid of
else case getPPIDOf pid' of
Nothing -> acc
Just ppid -> ppid_chain ppid (ppid : acc)
@@ -126,7 +124,7 @@ manageSpawnWithGC garbageCollect = do
mkPrompt :: (String -> X ()) -> XPConfig -> X ()
mkPrompt cb c = do
cmds <- io $ getCommands
cmds <- io getCommands
mkXPrompt Shell c (getShellCompl cmds $ searchPredicate c) cb
-- | Replacement for Shell prompt ("XMonad.Prompt.Shell") which launches
@@ -147,13 +145,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 $ ((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)
--
@@ -20,10 +21,9 @@ module XMonad.Actions.Submap (
submapDefaultWithKey
) where
import Data.Bits
import Data.Maybe (fromMaybe)
import XMonad.Prelude (fix, fromMaybe)
import XMonad hiding (keys)
import qualified Data.Map as M
import Control.Monad.Fix (fix)
{- $usage
@@ -93,5 +93,6 @@ submapDefaultWithKey defAction keys = do
io $ ungrabPointer d currentTime
io $ ungrabKeyboard d currentTime
io $ sync d False
fromMaybe (defAction (m', s)) (M.lookup (m', s) keys)

View File

@@ -1,8 +1,7 @@
{-# LANGUAGE DeriveDataTypeable #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.SwapPromote
-- Description : Track the master window history per workspace.
-- Copyright : (c) 2018 Yclept Nemo
-- License : BSD-style (see LICENSE)
--
@@ -57,16 +56,13 @@ module XMonad.Actions.SwapPromote
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 Data.List
import Data.Maybe
import Control.Arrow
import Control.Applicative ((<$>),(<*>))
import Control.Monad
-- $usage
@@ -118,7 +114,7 @@ import Control.Monad
-- Without history, the list is empty.
newtype MasterHistory = MasterHistory
{ getMasterHistory :: M.Map WorkspaceId [Window]
} deriving (Read,Show,Typeable)
} deriving (Read,Show)
instance ExtensionClass MasterHistory where
initialValue = MasterHistory M.empty
@@ -341,7 +337,7 @@ split' p i l =
then (c+1,e:ys,ns)
else (c+1,ys,e:ns)
(c',ys',ns') = foldr accumulate (0,[],[]) $ zip [i..] l
in (c',ys',snd . unzip $ ns')
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.

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)
--
@@ -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,14 +27,12 @@ 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
@@ -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 ()
@@ -158,7 +156,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 +165,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 +178,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,94 @@
-----------------------------------------------------------------------------
-- |
-- 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\/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) $ do
focus window
(offsetX, offsetY) <- getPointerOffset window
(winX, winY, winWidth, winHeight) <- getWindowPlacement window
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 :: Window -> X (Int, Int, Int, Int)
getWindowPlacement window = do
wa <- withDisplay (\d -> io $ getWindowAttributes d window)
return (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
let (ls, t : rs) = 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

@@ -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,21 +20,49 @@ module XMonad.Actions.TopicSpace
-- * Usage
-- $usage
Topic
-- * Types for Building Topics
Topic
, Dir
, TopicConfig(..)
, def
, 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
, (>*>)
@@ -41,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
@@ -75,110 +105,128 @@ import qualified XMonad.Util.ExtensibleState as XS
-- of last focused topics.
-- $usage
-- Here is an example of configuration using TopicSpace:
-- You can use this module with the following in your @~\/.xmonad\/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 = def
-- > { 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)
-- > ]
-- > { 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 $ def
-- > { 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 ()
@@ -188,85 +236,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
}
def = TopicConfig { topicDirs = M.empty
, topicActions = M.empty
, defaultTopicAction = const (ask >>= spawn . terminal . config)
, defaultTopic = "1"
, maxTopicHistory = 10
}
{-# DEPRECATED defaultTopicConfig "Use def (from Data.Default, and re-exported by XMonad.Actions.TopicSpace) instead." #-}
defaultTopicConfig :: TopicConfig
defaultTopicConfig = def
-- | 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
@@ -276,46 +318,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

@@ -1,9 +1,12 @@
{-# 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)
--
@@ -39,6 +42,7 @@ module XMonad.Actions.TreeSelect
, TSConfig(..)
, tsDefaultConfig
, def
-- * Navigation
-- $navigation
@@ -60,16 +64,13 @@ module XMonad.Actions.TreeSelect
, treeselectAt
) where
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.State
import Data.List (find)
import Data.Maybe
import Data.Tree
import Foreign
import Foreign (shiftL, shiftR, (.&.))
import System.IO
import System.Posix.Process (forkProcess, executeFile)
import XMonad hiding (liftX)
import XMonad.Prelude
import XMonad.StackSet as W
import XMonad.Util.Font
import XMonad.Util.NamedWindows
@@ -113,10 +114,10 @@ import Graphics.X11.Xrender
--
-- Optionally, if you add 'workspaceHistoryHook' to your 'logHook' you can use the \'o\' and \'i\' keys to select from previously-visited workspaces
--
-- > xmonad $ defaultConfig { ...
-- > , workspaces = toWorkspaces myWorkspaces
-- > , logHook = workspaceHistoryHook
-- > }
-- > 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
--
@@ -131,22 +132,22 @@ import Graphics.X11.Xrender
-- $config
-- The selection menu is very configurable, you can change the font, all colors and the sizes of the boxes.
--
-- The default config defined as 'tsDefaultConfig'
-- The default config defined as 'def'
--
-- > tsDefaultConfig = TSConfig { ts_hidechildren = True
-- > , ts_background = 0xc0c0c0c0
-- > , ts_font = "xft:Sans-16"
-- > , ts_node = (0xff000000, 0xff50d0db)
-- > , ts_nodealt = (0xff000000, 0xff10b8d6)
-- > , ts_highlight = (0xffffffff, 0xffff0000)
-- > , ts_extra = 0xff000000
-- > , ts_node_width = 200
-- > , ts_node_height = 30
-- > , ts_originX = 0
-- > , ts_originY = 0
-- > , ts_indent = 80
-- > , ts_navigate = defaultNavigation
-- > }
-- > 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
--
@@ -160,8 +161,8 @@ import Graphics.X11.Xrender
-- white = 0xffffffff
-- black = 0xff000000
-- red = 0xffff0000
-- blue = 0xff00ff00
-- green = 0xff0000ff
-- green = 0xff00ff00
-- blue = 0xff0000ff
-- transparent = 0x00000000
-- @
@@ -258,6 +259,7 @@ defaultNavigation = M.fromList
-- 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
@@ -316,7 +318,9 @@ treeselectAt conf@TSConfig{..} zipper hist = withDisplay $ \display -> do
set_colormap attributes colormap
set_background_pixel attributes ts_background
set_border_pixel attributes 0
createWindow display rootw rect_x rect_y rect_width rect_height 0 (visualInfo_depth vinfo) inputOutput (visualInfo_visual vinfo) (cWColormap .|. cWBorderPixel .|. cWBackPixel) attributes
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?
@@ -405,7 +409,7 @@ treeselectWorkspace c xs f = do
, "XConfig.workspaces: "
] ++ map tag ws
hPutStrLn stderr msg
_ <- forkProcess $ executeFile "xmessage" True [msg] Nothing
xmessage msg
return ()
where
mkNode n w = do
@@ -448,8 +452,8 @@ splitPath i = case break (== '.') i of
-- > ]
-- > ]
treeselectAction :: TSConfig (X a) -> Forest (TSNode (X a)) -> X ()
treeselectAction c xs = treeselect c xs >>= \x -> case x of
Just a -> a >> return ()
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]
@@ -461,7 +465,7 @@ mapMTree f (Node x xs) = Node <$> f x <*> mapM (mapMTree f) xs
-- | Quit returning the currently selected node
select :: TreeSelect a (Maybe a)
select = Just <$> gets (tsn_value . cursor . tss_tree)
select = gets (Just . (tsn_value . cursor . tss_tree))
-- | Quit without returning anything
cancel :: TreeSelect a (Maybe a)
@@ -523,18 +527,21 @@ moveWith f = do
-- | wait for keys and run navigation
navigate :: TreeSelect a (Maybe a)
navigate = gets tss_display >>= \d -> join . liftIO . allocaXEvent $ \e -> do
maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask) e
maskEvent d (exposureMask .|. keyPressMask .|. buttonReleaseMask .|. buttonPressMask) e
ev <- getEvent e
if ev_event_type ev == keyPress
then do
(ks, _) <- lookupString $ asKeyEvent e
return $ do
mask <- liftX $ cleanMask (ev_state ev)
f <- asks ts_navigate
fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f
else return navigate
if | ev_event_type ev == keyPress -> do
(ks, _) <- lookupString $ asKeyEvent e
return $ do
mask <- liftX $ cleanMask (ev_state ev)
f <- asks ts_navigate
fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f
| 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 ()
@@ -599,7 +606,7 @@ drawNode ix iy TSNode{..} col = do
colormap <- gets tss_colormap
visual <- gets tss_visual
liftIO $ drawWinBox window display visual colormap gc font col tsn_name ts_extra tsn_extra
(ix * ts_indent) (iy * ts_node_height)
(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)
@@ -650,8 +657,16 @@ drawStringXMF display window visual colormap gc font col x y text = case font of
--
-- Note that it uses short to represent its components
fromARGB :: Pixel -> XRenderColor
fromARGB x = XRenderColor (fromIntegral $ 0xff00 .&. shiftR x 8) -- red
(fromIntegral $ 0xff00 .&. x) -- green
(fromIntegral $ 0xff00 .&. shiftL x 8) -- blue
(fromIntegral $ 0xff00 .&. shiftR x 16) -- alpha
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,13 +17,13 @@ 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
@@ -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
@@ -58,3 +59,25 @@ adjustEventInput = withDisplay $ \dpy -> do
io $ selectInput dpy rootw $ substructureRedirectMask .|. substructureNotifyMask
.|. enterWindowMask .|. leaveWindowMask .|. structureNotifyMask
.|. 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

@@ -2,6 +2,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonadContrib.UpdatePointer
-- 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)
--
@@ -24,12 +25,11 @@ module XMonad.Actions.UpdatePointer
where
import XMonad
import XMonad.Util.XUtils (fi)
import Control.Arrow
import Control.Monad
import XMonad.Prelude
import XMonad.StackSet (member, peek, screenDetail, current)
import Data.Maybe
import Control.Exception
import Control.Exception (SomeException, try)
import Control.Arrow ((&&&), (***))
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -61,6 +61,11 @@ import Control.Exception
-- | 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
--
-- 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
@@ -105,6 +110,7 @@ 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 = if x < lower then lower
else if x > upper then upper else x
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,7 +23,7 @@ module XMonad.Actions.Warp (
warpToWindow
) where
import Data.List
import XMonad.Prelude
import XMonad
import XMonad.StackSet as W
@@ -101,7 +102,7 @@ warpToWindow h v =
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

@@ -2,6 +2,7 @@
-----------------------------------------------------------------------------
-- |
-- 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)
--
@@ -21,17 +22,17 @@ module XMonad.Actions.WindowBringer (
WindowBringerConfig(..),
gotoMenu, gotoMenuConfig, gotoMenu', gotoMenuArgs, gotoMenuArgs',
bringMenu, bringMenuConfig, bringMenu', bringMenuArgs, bringMenuArgs',
windowMap, windowMap', bringWindow, actionMenu
windowMap, windowAppMap, windowMap', bringWindow, actionMenu
) where
import Control.Applicative((<$>))
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
--
@@ -51,12 +52,14 @@ 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
@@ -123,11 +126,8 @@ 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 :: WindowBringerConfig -> (Window -> X.WindowSet -> X.WindowSet) -> X ()
actionMenu WindowBringerConfig{ menuCommand = cmd
, menuArgs = args
, windowTitler = titler
} action
= windowMap' titler >>= menuMapFunction >>= flip X.whenJust (windows . action)
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 = menuMapArgs cmd args
@@ -135,15 +135,20 @@ actionMenu WindowBringerConfig{ menuCommand = cmd
-- | A map from window names to Windows.
windowMap :: X (M.Map String Window)
windowMap = windowMap' decorateName
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' :: (X.WindowSpace -> Window -> X String) -> X (M.Map String Window)
windowMap' titler = do
ws <- gets X.windowset
M.fromList . concat <$> mapM keyValuePairs (W.workspaces ws)
where keyValuePairs ws = mapM (keyValuePair ws) $ W.integrate' (W.stack ws)
keyValuePair ws w = flip (,) w <$> titler ws w
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.
-- Tagged with the workspace ID, to guarantee uniqueness, and to let the user
@@ -152,3 +157,11 @@ decorateName :: X.WindowSpace -> Window -> X String
decorateName ws w = do
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,6 @@
{- |
Module : XMonad.Actions.WindowGo
Description : Operations for raising (traveling to) windows.
License : Public domain
Maintainer : <gwern0@gmail.com>
@@ -36,10 +37,8 @@ module XMonad.Actions.WindowGo (
module XMonad.ManageHook
) where
import Control.Monad
import Data.Char (toLower)
import qualified Data.List as L (nub,sortBy)
import Data.Monoid
import XMonad.Prelude
import XMonad (Query(), X(), ManageHook, WindowSet, withWindowSet, runQuery, liftIO, ask)
import Graphics.X11 (Window)
import XMonad.ManageHook

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)
--
@@ -29,7 +30,7 @@ import qualified XMonad.StackSet as W
import XMonad.Actions.GridSelect
import XMonad.Layout.Maximize
import XMonad.Actions.Minimize
import XMonad.Util.XUtils (fi)
import XMonad.Prelude (fi)
-- $usage
--
@@ -68,7 +69,7 @@ windowMenu = withFocused $ \w -> do
| tag <- tags ]
runSelectedAction gsConfig actions
getSize :: Window -> X (Rectangle)
getSize :: Window -> X Rectangle
getSize w = do
d <- asks display
wa <- io $ getWindowAttributes d w

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
@@ -65,6 +63,11 @@ import qualified Data.Set as S
-- > $ 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.
@@ -125,9 +128,12 @@ swap = withTargetWindow swapWithFocused
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 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:
@@ -209,7 +215,7 @@ inr L (Point px py) (Rectangle rx ry w h) = px > rx + fromIntegral w
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,21 +1,23 @@
-----------------------------------------------------------------------------
-- |
-- 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
@@ -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,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Actions.Workscreen
-- Description: Display a set of workspaces on several screens.
-- Copyright : (c) 2012 kedals0
-- License : BSD3-style (see LICENSE)
--
@@ -20,7 +21,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
@@ -58,23 +58,23 @@ import XMonad.Actions.OnScreen
-- "XMonad.Doc.Extending#Editing_key_bindings".
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)

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 (find, fromJust, guard, liftA2, toList, when, (<=<))
-- $usage
--
@@ -61,13 +58,10 @@ 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 def
-- > { layoutHook = workspaceCursors myCursors $ layoutHook def
@@ -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
@@ -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

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,22 +9,19 @@
-- 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,
@@ -37,23 +35,27 @@ module XMonad.Actions.WorkspaceNames (
swapWithCurrent,
-- * Workspace prompt
workspaceNamePrompt
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.Hooks.StatusBar.PP (PP(..))
import XMonad.Hooks.EwmhDesktops (addEwmhWorkspaceRename)
import XMonad.Prompt (mkXPrompt, XPConfig)
import XMonad.Prompt.Workspace (Wor(Wor))
import XMonad.Util.WorkspaceCompare (getSortByIndex)
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.List (isInfixOf)
-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
@@ -64,10 +66,17 @@ import Data.List (isInfixOf)
--
-- > , ((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:
@@ -85,7 +94,7 @@ import Data.List (isInfixOf)
-- | 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
@@ -97,21 +106,20 @@ getWorkspaceNames' = do
WorkspaceNames m <- XS.get
return (`M.lookup` m)
-- | Returns a function that maps workspace tag @\"t\"@ to @\"t:name\"@ for
-- workspaces with a name, and to @\"t\"@ otherwise.
getWorkspaceNames :: X (WorkspaceId -> String)
getWorkspaceNames = do
lookup <- getWorkspaceNames'
return $ \wks -> wks ++ maybe "" (':' :) (lookup wks)
-- | 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) `fmap` getWorkspaceNames'
getWorkspaceName w = ($ w) <$> getWorkspaceNames'
-- | Gets the name of the current workspace. See 'getWorkspaceName'
getCurrentWorkspaceName :: X (Maybe String)
getCurrentWorkspaceName = do
getWorkspaceName =<< gets (W.currentTag . windowset)
getCurrentWorkspaceName = getWorkspaceName =<< gets (W.currentTag . windowset)
-- | Sets the name of a workspace. Empty string makes the workspace unnamed
-- again.
@@ -129,27 +137,13 @@ setCurrentWorkspaceName name = do
-- | Prompt for a new name for the current workspace and set it.
renameWorkspace :: XPConfig -> X ()
renameWorkspace conf = do
renameWorkspace conf =
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
}
-- | 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 ()
@@ -169,19 +163,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 -> (String -> X ()) -> X ()
workspaceNamePrompt :: XPConfig -> (WorkspaceId -> X ()) -> X ()
workspaceNamePrompt conf job = do
myWorkspaces <- gets $ map W.tag . W.workspaces . windowset
myWorkspacesName <- getWorkspaceNames >>= \f -> return $ map f myWorkspaces
let pairs = zip myWorkspacesName myWorkspaces
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 = case lookup name pairs of
Nothing -> ""
Just i -> i
where toWsId pairs name = fromMaybe "" (lookup name pairs)
contains completions input =
return $ filter (Data.List.isInfixOf input) completions
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)
--
@@ -22,7 +23,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,7 +31,6 @@ 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
@@ -147,8 +147,8 @@ arossatoConfig = do
, ((modMask x , xK_F3 ), shellPrompt def )
, ((modMask x , xK_F4 ), sshPrompt def )
, ((modMask x , xK_F5 ), themePrompt def )
, ((modMask x , xK_F6 ), windowPromptGoto def )
, ((modMask x , xK_F7 ), windowPromptBring 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
--
@@ -46,7 +47,7 @@ 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 $
azertyKeysTop topRow conf@XConfig{modMask = modm} = M.fromList $
[((modm, xK_semicolon), sendMessage (IncMasterN (-1)))]
++
[((m .|. modm, k), windows $ f i)

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Bepo
-- Description : Fix keybindings for the BEPO keyboard layout.
-- Copyright : (c) Yorick Laupa <yo.eight@gmail.com>
-- License : BSD
--
@@ -39,9 +40,8 @@ import qualified Data.Map as M
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)]]
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

@@ -3,6 +3,7 @@
----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Bluetile
-- Description : Default configuration of [Bluetile](http://projects.haskell.org/bluetile/).
-- Copyright : (c) Jan Vornberger 2009
-- License : BSD3-style (see LICENSE)
--
@@ -25,7 +26,7 @@ module XMonad.Config.Bluetile (
bluetileConfig
) where
import XMonad hiding ( (|||) )
import XMonad
import XMonad.Layout.BorderResize
import XMonad.Layout.BoringWindows
@@ -33,7 +34,6 @@ 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
@@ -62,8 +62,7 @@ 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@:
@@ -82,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
@@ -113,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
@@ -160,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)
@@ -183,31 +182,28 @@ bluetileManageHook = composeAll
, className =? "MPlayer" --> doFloat
, isFullscreen --> doFullFloat]
bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $ (
bluetileLayoutHook = avoidStruts $ minimize $ boringWindows $
named "Floating" floating |||
named "Tiled1" tiled1 |||
named "Tiled2" tiled2 |||
named "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
bluetileConfig =
docks $
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
--
@@ -57,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
@@ -164,13 +166,16 @@ import qualified Data.Map as M
-- > adjustEventInput
--
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

View File

@@ -1,14 +1,16 @@
-- boilerplate {{{
{-# LANGUAGE ExistentialQuantification, NoMonomorphismRestriction, TypeSynonymInstances #-}
{-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-type-defaults #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Dmwit
-- Description : Daniel Wagner's xmonad configuration.
--
------------------------------------------------------------------------
module XMonad.Config.Dmwit where
-- system imports
import Control.Applicative
import Control.Monad
import Control.Monad.Trans
import Data.Char
import Data.List
import Data.Map (Map, fromList)
import Data.Ratio
import Data.Word
@@ -29,9 +31,10 @@ import XMonad.Hooks.DynamicLog
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Layout.Grid
import XMonad.Layout.IndependentScreens
import XMonad.Layout.IndependentScreens hiding (withScreen)
import XMonad.Layout.Magnifier
import XMonad.Layout.NoBorders
import XMonad.Prelude
import XMonad.Util.Dzen hiding (x, y)
import XMonad.Util.SpawnOnce
-- }}}
@@ -112,7 +115,6 @@ fullscreenMPlayer = className =? "MPlayer" --> do
Just (16 :% 9) -> viewFullOn 1 "5" win
_ -> doFloat
where
fi = fromIntegral :: Dimension -> Double
approx (n, d) = approxRational (fi n / fi d) (1/100)
operationOn f s n w = do
@@ -236,7 +238,7 @@ keyBindings conf = let m = modMask conf in fromList . anyMask $ [
((m .|. shiftMask , xK_p ), spawnHere termLauncher),
((m .|. shiftMask , xK_c ), kill),
((m , xK_q ), restart "xmonad" True),
((m .|. shiftMask , xK_q ), io (exitWith ExitSuccess)),
((m .|. shiftMask , xK_q ), io exitSuccess),
((m , xK_grave ), sendMessage NextLayout),
((m .|. shiftMask , xK_grave ), setLayout $ layoutHook conf),
((m , xK_o ), sendMessage Toggle),

View File

@@ -2,19 +2,20 @@
{-# 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 ( 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,
shrinkText, Shrinker, shrinkIt, CustomShrink(CustomShrink) )
@@ -39,8 +40,8 @@ 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, docks )
import XMonad.Hooks.EwmhDesktops ( ewmh )
@@ -77,11 +78,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)

View File

@@ -29,8 +29,9 @@ main = do
xmonad $ desktopConfig
{ modMask = mod4Mask -- Use the "Win" key for the mod key
, manageHook = myManageHook <+> manageHook desktopConfig
, layoutHook = desktopLayoutModifiers $ myLayouts
, logHook = dynamicLogString def >>= xmonadPropLog
, layoutHook = desktopLayoutModifiers myLayouts
, logHook = (dynamicLogString def >>= xmonadPropLog)
<+> logHook desktopConfig
}
`additionalKeysP` -- Add some extra key bindings:
@@ -68,11 +69,11 @@ myXPConfig = def
-- 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
[ className =? "Pidgin" -?> doFloat
, className =? "XCalc" -?> doFloat
, className =? "mpv" -?> doFloat
-- Handle floating windows:
[ transience -- move transient windows to their parent
, isDialog -?> doCenterFloat
-- Move transient windows to their parent:
, transience
] <+> 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
--
@@ -45,7 +46,7 @@ gnomeConfig = 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-quit --logout") ]
@@ -72,7 +73,7 @@ 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=literal"

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Kde
-- Description : Config for integrating xmonad with KDE.
-- Copyright : (c) Spencer Janssen <spencerjanssen@gmail.com>
-- License : BSD
--
@@ -47,12 +48,12 @@ kde4Config = desktopConfig
{ terminal = "konsole"
, keys = kde4Keys <+> keys desktopConfig }
kdeKeys (XConfig {modMask = modm}) = M.fromList $
kdeKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), spawn "dcop kdesktop default popupExecuteCommand")
, ((modm .|. shiftMask, xK_q), spawn "dcop kdesktop default logout")
]
kde4Keys (XConfig {modMask = modm}) = M.fromList $
kde4Keys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), spawn "krunner")
, ((modm .|. shiftMask, xK_q), spawn "dbus-send --print-reply --dest=org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout int32:1 int32:0 int32:1")
]

46
XMonad/Config/LXQt.hs Normal file
View File

@@ -0,0 +1,46 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.LXQt
-- Description : Config for integrating xmonad with LXQt.
-- Copyright : (c) Petr Shevtsov <petr.shevtsov@gmail.com>
-- License : BSD
--
-- Maintainer : none
-- Stability : unstable
-- Portability : unportable
--
-- This module provides a config suitable for use with the LXQt desktop
-- environment.
module XMonad.Config.LXQt (
-- * Usage
-- $usage
lxqtConfig,
desktopLayoutModifiers
) where
import XMonad
import XMonad.Config.Desktop
import qualified Data.Map as M
-- $usage
-- To use this module, start with the following @~\/.xmonad\/xmonad.hs@:
--
-- > import XMonad
-- > import XMonad.Config.LXQt
-- >
-- > main = xmonad lxqtConfig
--
-- For example of how to further customize @lxqtConfig@ see "XMonad.Config.Desktop".
lxqtConfig = desktopConfig
{ terminal = "qterminal"
, keys = lxqtKeys <+> keys desktopConfig }
lxqtKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), spawn "lxqt-runner")
, ((modm .|. shiftMask, xK_q), spawn "lxqt-leave")
]

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Mate
-- Description : Config for integrating xmonad with MATE.
-- Copyright : (c) Brandon S Allbery KF8NH, 2014
-- License : BSD
--
@@ -20,13 +21,18 @@ module XMonad.Config.Mate (
-- $usage
mateConfig,
mateRun,
matePanel,
mateRegister,
mateLogout,
mateShutdown,
desktopLayoutModifiers
) where
import XMonad
import XMonad.Config.Desktop
import XMonad.Util.Run (safeSpawn)
import XMonad.Util.Ungrab
import XMonad.Prelude (toUpper)
import qualified Data.Map as M
@@ -47,21 +53,29 @@ mateConfig = desktopConfig
, keys = mateKeys <+> keys desktopConfig
, startupHook = mateRegister >> startupHook desktopConfig }
mateKeys (XConfig {modMask = modm}) = M.fromList $
mateKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), mateRun)
, ((modm .|. shiftMask, xK_q), spawn "mate-session-save --logout-dialog") ]
, ((modm, xK_d), unGrab >> matePanel "MAIN_MENU")
, ((modm .|. shiftMask, xK_q), mateLogout) ]
-- | Launch the "Run Application" dialog. mate-panel must be running for this
-- to work.
-- to work. partial application for existing keybinding compatibility.
mateRun :: X ()
mateRun = withDisplay $ \dpy -> do
mateRun = matePanel "RUN_DIALOG"
-- | Launch a panel action. Either the "Run Application" dialog ("run_dialog" parameter,
-- see above) or the main menu ("main_menu" parameter). mate-panel must be running
-- for this to work.
matePanel :: String -> X ()
matePanel action = withDisplay $ \dpy -> do
let panel = "_MATE_PANEL_ACTION"
rw <- asks theRoot
mate_panel <- getAtom "_MATE_PANEL_ACTION"
panel_run <- getAtom "_MATE_PANEL_ACTION_RUN_DIALOG"
mate_panel <- getAtom panel
panel_action <- getAtom (panel ++ "_" ++ map toUpper action)
io $ allocaXEvent $ \e -> do
setEventType e clientMessage
setClientMessageEvent e rw mate_panel 32 panel_run 0
setClientMessageEvent e rw mate_panel 32 panel_action 0
sendEvent dpy rw False structureNotifyMask e
sync dpy False
@@ -77,7 +91,7 @@ mateRun = withDisplay $ \dpy -> do
-- (the extra quotes are required by dconf)
mateRegister :: MonadIO m => m ()
mateRegister = io $ do
x <- lookup "DESKTOP_AUTOSTART_ID" `fmap` getEnvironment
x <- lookup "DESKTOP_AUTOSTART_ID" <$> getEnvironment
whenJust x $ \sessionId -> safeSpawn "dbus-send"
["--session"
,"--print-reply=literal"
@@ -86,3 +100,12 @@ mateRegister = io $ do
,"org.mate.SessionManager.RegisterClient"
,"string:xmonad"
,"string:"++sessionId]
-- | Display MATE logout dialog. This is the default mod-q action.
mateLogout :: MonadIO m => m ()
mateLogout = spawn "mate-session-save --logout-dialog"
-- | Display MATE shutdown dialog. You can override mod-q to invoke this, or bind it
-- to another key if you prefer.
mateShutdown :: MonadIO m => m ()
mateShutdown = spawn "mate-session-save --shutdown-dialog"

View File

@@ -20,7 +20,7 @@ module XMonad.Config.Monad where
import XMonad hiding (terminal, keys)
import qualified XMonad as X
import Control.Monad.Writer
import Data.Monoid
import XMonad.Prelude
import Data.Accessor
import Data.Accessor.Basic hiding (set)
@@ -45,5 +45,5 @@ add r x = tell (mkW (r ^: mappend x))
--
example :: Config ()
example = do
add layout $ LL [Layout $ Full] -- make this better
add layout $ LL [Layout Full] -- make this better
set terminal "urxvt"

View File

@@ -1,8 +1,9 @@
{-# LANGUAGE FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, MultiParamTypeClasses, UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, UndecidableInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Prime
-- Description : Draft of a brand new config syntax for xmonad.
-- Copyright : Devin Mullins <devin.mullins@gmail.com>
-- License : BSD-style (see LICENSE)
--
@@ -115,7 +116,7 @@ ifThenElse,
import Prelude hiding ((>>), mod)
import qualified Prelude as P ((>>=), (>>))
import Data.Monoid (All)
import XMonad.Prelude (All)
import XMonad hiding (xmonad, XConfig(..))
import XMonad (XConfig(XConfig))
@@ -478,7 +479,7 @@ wsActions = Summable wsActions_ (\x c -> c { wsActions_ = x }) (++)
-- > wsSetName 1 "mail"
-- > wsSetName 2 "web"
wsSetName :: Int -> String -> Arr WorkspaceConfig WorkspaceConfig
wsSetName index newName = wsNames =. (map maybeSet . zip [0..])
wsSetName index newName = wsNames =. zipWith (curry maybeSet) [0..]
where maybeSet (i, oldName) | i == (index - 1) = newName
| otherwise = oldName
@@ -497,8 +498,8 @@ withScreens :: Arr ScreenConfig ScreenConfig -> Prime l l
withScreens sarr xconf = (P.>>=) (sarr def) $ \sconf -> sprime sconf xconf
where sprime :: ScreenConfig -> Prime l l
sprime sconf =
(keys =+ [(mod ++ key, action sid) | (sid, key) <- zip [0..] (sKeys_ sconf),
(mod, action) <- sActions_ sconf])
keys =+ [(mod ++ key, action sid) | (sid, key) <- zip [0..] (sKeys_ sconf),
(mod, action) <- sActions_ sconf]
data ScreenConfig = ScreenConfig {
sKeys_ :: [String],

View File

@@ -58,7 +58,7 @@ myStartupHook = do
spawnOnOnce "emacs" "emacs"
spawnNOnOnce 4 "xterms" "xterm"
myLayoutHook = smartBorders $ avoidStruts $ standardLayouts
myLayoutHook = smartBorders $ avoidStruts standardLayouts
where standardLayouts = tiled ||| mosaic 2 [3,2] ||| Mirror tiled ||| Full
tiled = ResizableTall nmaster delta ratio []
nmaster = 1
@@ -68,7 +68,7 @@ myLayoutHook = smartBorders $ avoidStruts $ standardLayouts
myLogHook p = do
copies <- wsContainingCopies
let check ws | ws == "NSP" = "" -- Hide the scratchpad workspace
| ws `elem` copies = xmobarColor "red" "black" $ ws -- Workspaces with copied windows are red on black
| ws `elem` copies = xmobarColor "red" "black" ws -- Workspaces with copied windows are red on black
| otherwise = ws
dynamicLogWithPP $ xmobarPP { ppHidden = check
, ppOutput = hPutStrLn p
@@ -76,4 +76,3 @@ myLogHook p = do
, ppTitle = xmobarColor "green" "" . shorten 180
}
fadeInactiveLogHook 0.6

View File

@@ -1,4 +1,10 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Sjanssen
-- Description : Spencer Janssen's xmonad config.
--
------------------------------------------------------------------------
module XMonad.Config.Sjanssen (sjanssenConfig) where
import XMonad hiding (Tall(..))
@@ -24,10 +30,10 @@ sjanssenConfig =
docks $ ewmh $ def
{ terminal = "exec urxvt"
, workspaces = ["irc", "web"] ++ map show [3 .. 9 :: Int]
, mouseBindings = \(XConfig {modMask = modm}) -> M.fromList $
[ ((modm, button1), (\w -> focus w >> mouseMoveWindow w))
, ((modm, button2), (\w -> focus w >> windows W.swapMaster))
, ((modm.|. shiftMask, button1), (\w -> focus w >> mouseResizeWindow w)) ]
, mouseBindings = \XConfig {modMask = modm} -> M.fromList
[ ((modm, button1), \w -> focus w >> mouseMoveWindow w)
, ((modm, button2), \w -> focus w >> windows W.swapMaster)
, ((modm.|. shiftMask, button1), \w -> focus w >> mouseResizeWindow w) ]
, keys = \c -> mykeys c `M.union` keys def c
, logHook = dynamicLogString sjanssenPP >>= xmonadPropLog
, layoutHook = modifiers layouts
@@ -50,12 +56,12 @@ sjanssenConfig =
, "trayer --transparent true --expand true --align right "
++ "--edge bottom --widthtype request" ]
mykeys (XConfig {modMask = modm}) = M.fromList $
mykeys XConfig{modMask = modm} = M.fromList
[((modm, xK_p ), shellPromptHere myPromptConfig)
,((modm .|. shiftMask, xK_Return), spawnHere =<< asks (terminal . config))
,((modm .|. shiftMask, xK_c ), kill1)
,((modm .|. shiftMask .|. controlMask, xK_c ), kill)
,((modm .|. shiftMask, xK_0 ), windows $ copyToAll)
,((modm .|. shiftMask, xK_0 ), windows copyToAll)
,((modm, xK_z ), layoutScreens 2 $ TwoPane 0.5 0.5)
,((modm .|. shiftMask, xK_z ), rescreen)
, ((modm , xK_b ), sendMessage ToggleStruts)

View File

@@ -3,6 +3,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : XMonad.Config.Xfce
-- Description : Config for integrating xmonad with Xfce.
-- Copyright : (c) Ivan Miljenovic <Ivan.Miljenovic@gmail.com>
-- License : BSD
--
@@ -36,10 +37,10 @@ import qualified Data.Map as M
-- For examples of how to further customize @xfceConfig@ see "XMonad.Config.Desktop".
xfceConfig = desktopConfig
{ terminal = "Terminal"
{ terminal = "xfce4-terminal"
, keys = xfceKeys <+> keys desktopConfig }
xfceKeys (XConfig {modMask = modm}) = M.fromList $
xfceKeys XConfig{modMask = modm} = M.fromList
[ ((modm, xK_p), spawn "xfrun4")
, ((modm .|. shiftMask, xK_p), spawn "xfce4-appfinder")
, ((modm .|. shiftMask, xK_q), spawn "xfce4-session-logout")

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