43 Commits

Author SHA1 Message Date
Peter Jones
ca9b7d9dfc Add a stack.yaml file for testing and easy Hackage upload 2017-02-10 16:20:42 -07:00
Peter Jones
615f007fe4 Add a cabal.project file 2017-02-10 16:04:33 -07:00
Peter Jones
e4e20da8f0 Clean up the change log just a bit 2017-02-10 16:02:41 -07:00
Peter Jones
b064d22c2d Add a release date 2017-02-09 16:25:24 -07:00
Peter Jones
d2ffb75031 Merge remote-tracking branch 'origin/pjones/rmworkarea' into release-0.13 2017-02-09 16:13:36 -07:00
Peter Jones
cb344d14b9 Bump version to 0.13 2017-02-09 16:12:55 -07:00
Peter J. Jones
d1a5f9cf91 Merge pull request #141 from pjones/pjones/prompt-complete
Better completion when using `alwaysHighlight'
2017-02-09 15:10:27 -07:00
Peter J. Jones
3b1c43cced Merge pull request #142 from pjones/pjones/border
Use `setWindowBorderWithFallback' to support windows with RGBA color maps
2017-02-09 15:10:13 -07:00
Peter J. Jones
76b1771a31 Merge pull request #144 from pjones/pjones/dzen
Manage struts even when _NET_WM_WINDOW_TYPE isn't a dock
2017-02-09 15:07:40 -07:00
Peter Jones
cd96de5378 Manage struts even when _NET_WM_WINDOW_TYPE isn't a dock
Relates to #21
2017-02-07 15:58:55 -07:00
Peter Jones
0a8e68b458 Delete _NET_WORKAREA instead of setting it
References:

  * 9c020877dd

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

  * eec80838ab

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

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

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

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

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

This also fixes xmonad/xmonad-contrib#68
2017-01-04 14:39:00 -07:00
Peter J. Jones
77e5e5190d Merge pull request #131 from sgf-dma/fix-changes.md
Fix CHANGES.md after b9d8f6c .
2017-01-03 15:49:09 -07:00
sgf
5bf4b27054 Fix CHANGES.md after b9d8f6c . 2016-12-25 14:59:30 +03:00
Brent Yorgey
8956684ff5 Merge pull request #130 from strokyl/add_HiddenEmptyWS_to_CycleWS
Add HiddenEmptyWS to CycleWS
2016-12-23 23:50:52 -05:00
Luc DUZAN
9da78669e7 Add HiddenEmptyWS to CycleWS
When I have multiscreen I think it's usefull to get the next empty workspace
that is not already displayed.
2016-12-22 22:48:23 +01:00
Peter J. Jones
c0cf18def2 Merge pull request #17 from kurnevsky/update_pointer_bugfix
UpdatePointer bugfix.
2016-12-14 14:48:52 -07:00
Peter Jones
d5aa562282 Add build status badge from Travis 2016-12-14 14:44:15 -07:00
Peter Jones
f1de0413da Update GHC versions to a more reasonable list 2016-12-14 14:29:52 -07:00
Peter Jones
6eac81cf51 Bump X11 version upper-bounds to 1.8 2016-12-14 14:11:30 -07:00
Kurnevsky Evgeny
a8d290b830 Update CHANGES.md 2016-12-14 11:49:28 +03:00
Kurnevsky Evgeny
86280c5063 Rewrite XMonad.Actions.UpdatePointer bugfix with Control.Exception.try. 2016-12-14 09:03:26 +03:00
Kurnevsky Evgeny
11e0d683af UpdatePointer bugfix. 2016-12-14 09:03:26 +03:00
geekosaur
061edbd954 Merge pull request #127 from bennofs/patch-1
DynamicProperty: execute other hooks
2016-12-09 23:10:06 -05:00
Benno Fünfstück
0949b9ec91 DynamicProperty: execute other hooks
All False short-cuts the default behavior for the event, which leads to a non-functioning window manager. Returning mempty ensures that the default action is still executed,
2016-12-09 22:35:11 +01:00
Peter J. Jones
f837a4fb36 Merge pull request #6 from sgf-dma/master
X.A.Submap: establish pointer grab to avoid freezing X.
2016-12-09 08:34:47 -07:00
sgf
b9d8f6ce34 X.A.Submap: establish pointer grab to avoid freezing X.
Establish active asynchronous pointer grab before entering infinity cycle.
Because xmonad already has passive synchronous pointer grab, this overwrites
it temporary and avoids freezing X, when button press occurs after submap key
press.

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

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

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

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

Bug: https://github.com/xmonad/xmonad-contrib/issues/123
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
2016-11-27 10:03:17 +00:00
25 changed files with 352 additions and 146 deletions

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

@@ -0,0 +1,24 @@
### Problem Description
Describe the problem you are having, what you expect to happen
instead, and how to reproduce the problem.
### Configuration File
Please include the smallest configuration file that reproduces the
problem you are experiencing:
```haskell
module Main (main) where
import XMonad
main :: IO ()
main = xmonad def
```
### Checklist
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- [ ] I tested my configuration with [xmonad-testing](https://github.com/xmonad/xmonad-testing)

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

@@ -0,0 +1,12 @@
### Description
Include a description for your changes, including the motivation
behind them.
### Checklist
- [ ] I've read [CONTRIBUTING.md](https://github.com/xmonad/xmonad/blob/master/CONTRIBUTING.md)
- [ ] I tested my changes with [xmonad-testing](https://github.com/xmonad/xmonad-testing)
- [ ] I updated the `CHANGES.md` file

1
.gitignore vendored
View File

@@ -23,3 +23,4 @@ tags
# stack artifacts # stack artifacts
/.stack-work/ /.stack-work/
/cabal.project.local

View File

@@ -13,18 +13,18 @@ before_cache:
matrix: matrix:
include: include:
- env: CABALVER=1.16 GHCVER=7.4.2
compiler: ": #GHC 7.4.2"
addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
- env: CABALVER=1.16 GHCVER=7.6.3 - env: CABALVER=1.16 GHCVER=7.6.3
compiler: ": #GHC 7.6.3" compiler: ": #GHC 7.6.3"
addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}} addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
- env: CABALVER=1.18 GHCVER=7.8.4 - env: CABALVER=1.18 GHCVER=7.8.4
compiler: ": #GHC 7.8.4" compiler: ": #GHC 7.8.4"
addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}} addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
- env: CABALVER=1.22 GHCVER=7.10.2 - env: CABALVER=1.22 GHCVER=7.10.3
compiler: ": #GHC 7.10.2" compiler: ": #GHC 7.10.3"
addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}} addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
- env: CABALVER=1.24 GHCVER=8.0.1
compiler: ": #GHC 8.0.1"
addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
before_install: before_install:
- unset CC - unset CC
@@ -47,7 +47,7 @@ install:
- sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt
# check whether current requested install-plan matches cached package-db snapshot # check whether current requested install-plan matches cached package-db snapshot
- if diff -u installplan.txt $HOME/.cabsnap/installplan.txt; - if diff -u $HOME/.cabsnap/installplan.txt installplan.txt;
then then
echo "cabal build-cache HIT"; echo "cabal build-cache HIT";
rm -rfv .ghc; rm -rfv .ghc;

View File

@@ -1,16 +1,19 @@
# Change Log / Release Notes # Change Log / Release Notes
## 0.13 ## 0.13 (February 10, 2017)
### Breaking Changes ### Breaking Changes
* The type of `completionKey` (of `XPConfig` record) has been * The type of `completionKey` (of `XPConfig` record) has been
changed from `KeySym` to `(KeyMask, KeySym)`. The default value changed from `KeySym` to `(KeyMask, KeySym)`. The default value
for this is still binded to `Tab` key. for this is still bound to the `Tab` key.
* New constructor `CenteredAt Rational Rational` added for * New constructor `CenteredAt Rational Rational` added for
`XMonad.Prompt.XPPosition`. `XMonad.Prompt.XPPosition`.
* `XMonad.Prompt` now stores its history file in the XMonad cache
directory in a file named `prompt-history`.
### New Modules ### New Modules
* `XMonad.Layout.SortedLayout` * `XMonad.Layout.SortedLayout`
@@ -42,13 +45,35 @@
EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since
you will usually be taken to the `NSP` workspace by them. you will usually be taken to the `NSP` workspace by them.
### Minor Changes ### Bug Fixes and Minor Changes
* `XMonad.Hooks.ManageDocks`,
- Fix a very annoying bug where taskbars/docs would be
covered by windows.
- Also fix a bug that caused certain Gtk and Qt application to
have issues displaying menus and popups.
* `XMonad.Layout.LayoutBuilder` * `XMonad.Layout.LayoutBuilder`
Merge all functionality from `XMonad.Layout.LayoutBuilderP` into Merge all functionality from `XMonad.Layout.LayoutBuilderP` into
`XMonad.Layout.LayoutBuilder`. `XMonad.Layout.LayoutBuilder`.
* `XMonad.Actions.WindowGo`
- Fix `raiseNextMaybe` cycling between 2 workspaces only.
* `XMonad.Actions.UpdatePointer`
- Fix bug when cursor gets stuck in one of the corners.
* `XMonad.Actions.Submap`
Establish pointer grab to avoid freezing X, when button press occurs after
submap key press. And terminate submap at button press in the same way,
as we do for wrong key press.
* `XMonad.Actions.DynamicProjects` * `XMonad.Actions.DynamicProjects`
- Switching away from a dynamic project that contains no windows - Switching away from a dynamic project that contains no windows
@@ -57,6 +82,11 @@
The project itself was already being deleted, this just deletes The project itself was already being deleted, this just deletes
the workspace created for it as well. the workspace created for it as well.
- Added function to change the working directory (`changeProjectDirPrompt`)
- All of the prompts are now multiple mode prompts. Try using the
`changeModeKey` in a prompt and see what happens!
## 0.12 (December 14, 2015) ## 0.12 (December 14, 2015)
### Breaking Changes ### Breaking Changes

View File

@@ -1,5 +1,7 @@
# xmonad-contrib: Third Party Extensions to the xmonad Window Manager # xmonad-contrib: Third Party Extensions to the xmonad Window Manager
[![Build Status](https://travis-ci.org/xmonad/xmonad-contrib.svg?branch=master)](https://travis-ci.org/xmonad/xmonad-contrib)
You need the ghc compiler and xmonad window manager installed in You need the ghc compiler and xmonad window manager installed in
order to use these extensions. order to use these extensions.

View File

@@ -239,6 +239,7 @@ data WSType = EmptyWS -- ^ cycle through empty workspaces
| NonEmptyWS -- ^ cycle through non-empty workspaces | NonEmptyWS -- ^ cycle through non-empty workspaces
| HiddenWS -- ^ cycle through non-visible workspaces | HiddenWS -- ^ cycle through non-visible workspaces
| HiddenNonEmptyWS -- ^ cycle through non-empty non-visible workspaces | HiddenNonEmptyWS -- ^ cycle through non-empty non-visible workspaces
| HiddenEmptyWS -- ^ cycle through empty non-visible workspaces
| AnyWS -- ^ cycle through all workspaces | AnyWS -- ^ cycle through all workspaces
| WSTagGroup Char | WSTagGroup Char
-- ^ cycle through workspaces in the same group, the -- ^ cycle through workspaces in the same group, the
@@ -257,6 +258,9 @@ wsTypeToPred HiddenWS = do hs <- gets (map tag . hidden . windowset)
wsTypeToPred HiddenNonEmptyWS = do ne <- wsTypeToPred NonEmptyWS wsTypeToPred HiddenNonEmptyWS = do ne <- wsTypeToPred NonEmptyWS
hi <- wsTypeToPred HiddenWS hi <- wsTypeToPred HiddenWS
return (\w -> hi w && ne w) return (\w -> hi w && ne w)
wsTypeToPred HiddenEmptyWS = do ne <- wsTypeToPred EmptyWS
hi <- wsTypeToPred HiddenWS
return (\w -> hi w && ne w)
wsTypeToPred AnyWS = return (const True) wsTypeToPred AnyWS = return (const True)
wsTypeToPred (WSTagGroup sep) = do cur <- (groupName.workspace.current) `fmap` gets windowset wsTypeToPred (WSTagGroup sep) = do cur <- (groupName.workspace.current) `fmap` gets windowset
return $ (cur ==).groupName return $ (cur ==).groupName

View File

@@ -31,6 +31,7 @@ module XMonad.Actions.DynamicProjects
, switchProjectPrompt , switchProjectPrompt
, shiftToProjectPrompt , shiftToProjectPrompt
, renameProjectPrompt , renameProjectPrompt
, changeProjectDirPrompt
-- * Helper Functions -- * Helper Functions
, switchProject , switchProject
@@ -43,6 +44,7 @@ module XMonad.Actions.DynamicProjects
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Control.Applicative ((<|>)) import Control.Applicative ((<|>))
import Control.Monad (when, unless) import Control.Monad (when, unless)
import Data.Char (isSpace)
import Data.List (sort, union, stripPrefix) import Data.List (sort, union, stripPrefix)
import Data.Map.Strict (Map) import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
@@ -52,8 +54,7 @@ import System.Directory (setCurrentDirectory, getHomeDirectory)
import XMonad import XMonad
import XMonad.Actions.DynamicWorkspaces import XMonad.Actions.DynamicWorkspaces
import XMonad.Prompt import XMonad.Prompt
import XMonad.Prompt.Directory (directoryPrompt) import XMonad.Prompt.Directory
import XMonad.Prompt.Workspace (Wor(..))
import qualified XMonad.StackSet as W import qualified XMonad.StackSet as W
import qualified XMonad.Util.ExtensibleState as XS import qualified XMonad.Util.ExtensibleState as XS
@@ -142,6 +143,48 @@ data ProjectState = ProjectState
instance ExtensionClass ProjectState where instance ExtensionClass ProjectState where
initialValue = ProjectState Map.empty Nothing initialValue = ProjectState Map.empty Nothing
--------------------------------------------------------------------------------
-- Internal types for working with XPrompt.
data ProjectPrompt = ProjectPrompt ProjectMode [ProjectName]
data ProjectMode = SwitchMode | ShiftMode | RenameMode | DirMode
instance XPrompt ProjectPrompt where
showXPrompt (ProjectPrompt submode _) =
case submode of
SwitchMode -> "Switch or Create Project: "
ShiftMode -> "Send Window to Project: "
RenameMode -> "New Project Name: "
DirMode -> "Change Project Directory: "
completionFunction (ProjectPrompt RenameMode _) = return . (:[])
completionFunction (ProjectPrompt DirMode _) =
let xpt = directoryMultipleModes "" (const $ return ())
in completionFunction xpt
completionFunction (ProjectPrompt _ ns) = mkComplFunFromList' ns
modeAction (ProjectPrompt SwitchMode _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
case Map.lookup name ps of
Just p -> switchProject p
Nothing | null name -> return ()
| otherwise -> switchProject (defProject name)
modeAction (ProjectPrompt ShiftMode _) buf auto = do
let name = if null auto then buf else auto
ps <- XS.gets projects
shiftToProject . fromMaybe (defProject name) $ Map.lookup name ps
modeAction (ProjectPrompt RenameMode _) name _ =
when (not (null name) && not (all isSpace name)) $ do
renameWorkspaceByName name
modifyProject (\p -> p { projectName = name })
modeAction (ProjectPrompt DirMode _) buf auto = do
let dir = if null auto then buf else auto
modifyProject (\p -> p { projectDirectory = dir })
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Add dynamic projects support to the given config. -- | Add dynamic projects support to the given config.
dynamicProjects :: [Project] -> XConfig a -> XConfig a dynamicProjects :: [Project] -> XConfig a -> XConfig a
@@ -198,6 +241,21 @@ currentProject = do
proj <- lookupProject name proj <- lookupProject name
return $ fromMaybe (defProject name) proj return $ fromMaybe (defProject name) proj
--------------------------------------------------------------------------------
-- | Modify the current project using a pure function.
modifyProject :: (Project -> Project) -> X ()
modifyProject f = do
p <- currentProject
ps <- XS.gets projects
-- If a project is renamed to match another project, the old project
-- will be removed and replaced with this one.
let new = f p
ps' = Map.insert (projectName new) new $ Map.delete (projectName p) ps
XS.modify $ \s -> s {projects = ps'}
activateProject new
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Switch to the given project. -- | Switch to the given project.
switchProject :: Project -> X () switchProject :: Project -> X ()
@@ -220,22 +278,11 @@ switchProject p = do
-- | Prompt for a project name and then switch to it. Automatically -- | Prompt for a project name and then switch to it. Automatically
-- creates a project if a new name is returned from the prompt. -- creates a project if a new name is returned from the prompt.
switchProjectPrompt :: XPConfig -> X () switchProjectPrompt :: XPConfig -> X ()
switchProjectPrompt c = projectPrompt c switch switchProjectPrompt = projectPrompt [ SwitchMode
where , ShiftMode
switch :: ProjectTable -> ProjectName -> X () , RenameMode
switch ps name = case Map.lookup name ps of , DirMode
Just p -> switchProject p ]
Nothing | null name -> return ()
| otherwise -> directoryPrompt dirC "Project Dir: " (mkProject name)
dirC :: XPConfig
dirC = c { alwaysHighlight = False } -- Fix broken tab completion.
mkProject :: ProjectName -> FilePath -> X ()
mkProject name dir = do
let p = Project name dir Nothing
XS.modify $ \s -> s {projects = Map.insert name p $ projects s}
switchProject p
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Shift the currently focused window to the given project. -- | Shift the currently focused window to the given project.
@@ -248,40 +295,44 @@ shiftToProject p = do
-- | Prompts for a project name and then shifts the currently focused -- | Prompts for a project name and then shifts the currently focused
-- window to that project. -- window to that project.
shiftToProjectPrompt :: XPConfig -> X () shiftToProjectPrompt :: XPConfig -> X ()
shiftToProjectPrompt c = projectPrompt c go shiftToProjectPrompt = projectPrompt [ ShiftMode
where , RenameMode
go :: ProjectTable -> ProjectName -> X () , SwitchMode
go ps name = shiftToProject . fromMaybe (defProject name) $ , DirMode
Map.lookup name ps ]
--------------------------------------------------------------------------------
-- | Prompt for a project name.
projectPrompt :: XPConfig -> (ProjectTable -> ProjectName -> X ()) -> X ()
projectPrompt c f = do
ws <- map W.tag `fmap` gets (W.workspaces . windowset)
ps <- XS.gets projects
let names = sort (Map.keys ps `union` ws)
label = "Switch or Create Project: "
mkXPrompt (Wor label) c (mkComplFunFromList' names) (f ps)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Rename the current project. -- | Rename the current project.
renameProjectPrompt :: XPConfig -> X () renameProjectPrompt :: XPConfig -> X ()
renameProjectPrompt c = mkXPrompt (Wor "New Project Name: ") c (return . (:[])) go renameProjectPrompt = projectPrompt [ RenameMode
where , DirMode
go :: String -> X () , SwitchMode
go name = do , ShiftMode
p <- currentProject ]
ps <- XS.gets projects
renameWorkspaceByName name
let p' = fromMaybe (p { projectName = name }) $ Map.lookup name ps --------------------------------------------------------------------------------
ps' = Map.insert name p' $ Map.delete (projectName p) ps -- | Change the working directory used for the current project.
--
-- NOTE: This will only affect new processed started in this project.
-- Existing processes will maintain the previous working directory.
changeProjectDirPrompt :: XPConfig -> X ()
changeProjectDirPrompt = projectPrompt [ DirMode
, SwitchMode
, ShiftMode
, RenameMode
]
XS.modify $ \s -> s {projects = ps'} --------------------------------------------------------------------------------
activateProject p' -- | Prompt for a project name.
projectPrompt :: [ProjectMode] -> XPConfig -> X ()
projectPrompt submodes c = do
ws <- map W.tag `fmap` gets (W.workspaces . windowset)
ps <- XS.gets projects
let names = sort (Map.keys ps `union` ws)
modes = map (\m -> XPT $ ProjectPrompt m names) submodes
mkXPromptWithModes modes c
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Activate a project by updating the working directory and -- | Activate a project by updating the working directory and

View File

@@ -75,17 +75,23 @@ submapDefaultWithKey defAction keys = do
XConf { theRoot = root, display = d } <- ask XConf { theRoot = root, display = d } <- ask
io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime
io $ grabPointer d root False buttonPressMask grabModeAsync grabModeAsync
none none currentTime
(m, s) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do (m, s) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do
maskEvent d keyPressMask p maskEvent d (keyPressMask .|. buttonPressMask) p
KeyEvent { ev_keycode = code, ev_state = m } <- getEvent p ev <- getEvent p
keysym <- keycodeToKeysym d code 0 case ev of
if isModifierKey keysym KeyEvent { ev_keycode = code, ev_state = m } -> do
then nextkey keysym <- keycodeToKeysym d code 0
else return (m, keysym) if isModifierKey keysym
then nextkey
else return (m, keysym)
_ -> return (0, 0)
-- Remove num lock mask and Xkb group state bits -- Remove num lock mask and Xkb group state bits
m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1) m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1)
io $ ungrabPointer d currentTime
io $ ungrabKeyboard d currentTime io $ ungrabKeyboard d currentTime
fromMaybe (defAction (m', s)) (M.lookup (m', s) keys) fromMaybe (defAction (m', s)) (M.lookup (m', s) keys)

View File

@@ -1,7 +1,8 @@
{-# LANGUAGE ScopedTypeVariables #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
-- Module : XMonadContrib.UpdatePointer -- Module : XMonadContrib.UpdatePointer
-- Copyright : (c) Robert Marlow <robreim@bobturf.org> -- Copyright : (c) Robert Marlow <robreim@bobturf.org>, 2015 Evgeny Kurnevsky
-- License : BSD3-style (see LICENSE) -- License : BSD3-style (see LICENSE)
-- --
-- Maintainer : Robert Marlow <robreim@bobturf.org> -- Maintainer : Robert Marlow <robreim@bobturf.org>
@@ -28,6 +29,7 @@ import Control.Arrow
import Control.Monad import Control.Monad
import XMonad.StackSet (member, peek, screenDetail, current) import XMonad.StackSet (member, peek, screenDetail, current)
import Data.Maybe import Data.Maybe
import Control.Exception
-- $usage -- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
@@ -63,9 +65,13 @@ updatePointer :: (Rational, Rational) -> (Rational, Rational) -> X ()
updatePointer refPos ratio = do updatePointer refPos ratio = do
ws <- gets windowset ws <- gets windowset
dpy <- asks display dpy <- asks display
let defaultRect = screenRect $ screenDetail $ current ws
rect <- case peek ws of rect <- case peek ws of
Nothing -> return $ (screenRect . screenDetail .current) ws Nothing -> return defaultRect
Just w -> windowAttributesToRectangle `fmap` io (getWindowAttributes dpy w) Just w -> do tryAttributes <- io $ try $ getWindowAttributes dpy w
return $ case tryAttributes of
Left (_ :: SomeException) -> defaultRect
Right attributes -> windowAttributesToRectangle attributes
root <- asks theRoot root <- asks theRoot
mouseIsMoving <- asks mouseFocused mouseIsMoving <- asks mouseFocused
(_sameRoot,_,currentWindow,rootX,rootY,_,_,_) <- io $ queryPointer dpy root (_sameRoot,_,currentWindow,rootX,rootY,_,_,_) <- io $ queryPointer dpy root

View File

@@ -38,13 +38,14 @@ module XMonad.Actions.WindowGo (
import Control.Monad import Control.Monad
import Data.Char (toLower) import Data.Char (toLower)
import qualified Data.List as L (nub,sortBy)
import Data.Monoid import Data.Monoid
import XMonad (Query(), X(), ManageHook, WindowSet, withWindowSet, runQuery, liftIO, ask) import XMonad (Query(), X(), ManageHook, WindowSet, withWindowSet, runQuery, liftIO, ask)
import Graphics.X11 (Window) import Graphics.X11 (Window)
import XMonad.ManageHook import XMonad.ManageHook
import XMonad.Operations (windows) import XMonad.Operations (windows)
import XMonad.Prompt.Shell (getBrowser, getEditor) import XMonad.Prompt.Shell (getBrowser, getEditor)
import qualified XMonad.StackSet as W (allWindows, peek, swapMaster, focusWindow) import qualified XMonad.StackSet as W (peek, swapMaster, focusWindow, workspaces, StackSet, Workspace, integrate', tag, stack)
import XMonad.Util.Run (safeSpawnProg) import XMonad.Util.Run (safeSpawnProg)
{- $usage {- $usage
@@ -66,12 +67,20 @@ appropriate one, or cover your bases by using instead something like:
For detailed instructions on editing your key bindings, see For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings". -} "XMonad.Doc.Extending#Editing_key_bindings". -}
-- | Get the list of workspaces sorted by their tag
workspacesSorted :: Ord i => W.StackSet i l a s sd -> [W.Workspace i l a]
workspacesSorted s = L.sortBy (\u t -> W.tag u `compare` W.tag t) $ W.workspaces s
-- | Get a list of all windows in the 'StackSet' with an absolute ordering of workspaces
allWindowsSorted :: Ord i => Eq a => W.StackSet i l a s sd -> [a]
allWindowsSorted = L.nub . concatMap (W.integrate' . W.stack) . workspacesSorted
-- | If windows that satisfy the query exist, apply the supplied -- | If windows that satisfy the query exist, apply the supplied
-- function to them, otherwise run the action given as -- function to them, otherwise run the action given as
-- second parameter. -- second parameter.
ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X () ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X ()
ifWindows qry f el = withWindowSet $ \wins -> do ifWindows qry f el = withWindowSet $ \wins -> do
matches <- filterM (runQuery qry) $ W.allWindows wins matches <- filterM (runQuery qry) $ allWindowsSorted wins
case matches of case matches of
[] -> el [] -> el
ws -> f ws ws -> f ws

View File

@@ -58,8 +58,8 @@ dynamicPropertyChange prop hook PropertyEvent { ev_window = w, ev_atom = a, ev_p
when (ps == propertyNewValue && a == pa) $ do when (ps == propertyNewValue && a == pa) $ do
g <- appEndo <$> userCodeDef (Endo id) (runQuery hook w) g <- appEndo <$> userCodeDef (Endo id) (runQuery hook w)
windows g windows g
return (All False) -- so anything else also processes it return mempty -- so anything else also processes it
dynamicPropertyChange _ _ _ = return (All False) dynamicPropertyChange _ _ _ = return mempty
-- | A shorthand for the most common case, dynamic titles -- | A shorthand for the most common case, dynamic titles
dynamicTitle :: ManageHook -> Event -> X All dynamicTitle :: ManageHook -> Event -> X All

View File

@@ -140,12 +140,11 @@ docksEventHook (MapNotifyEvent { ev_window = w }) = do
return (All True) return (All True)
docksEventHook (PropertyEvent { ev_window = w docksEventHook (PropertyEvent { ev_window = w
, ev_atom = a }) = do , ev_atom = a }) = do
whenX (runQuery checkDock w) $ do nws <- getAtom "_NET_WM_STRUT"
nws <- getAtom "_NET_WM_STRUT" nwsp <- getAtom "_NET_WM_STRUT_PARTIAL"
nwsp <- getAtom "_NET_WM_STRUT_PARTIAL" when (a == nws || a == nwsp) $ do
when (a == nws || a == nwsp) $ do strut <- getStrut w
strut <- getStrut w whenX (updateStrutCache w strut) refreshDocks
whenX (updateStrutCache w strut) refreshDocks
return (All True) return (All True)
docksEventHook (DestroyWindowEvent {ev_window = w}) = do docksEventHook (DestroyWindowEvent {ev_window = w}) = do
whenX (deleteFromStructCache w) refreshDocks whenX (deleteFromStructCache w) refreshDocks
@@ -246,7 +245,9 @@ instance Message SetStruts
instance LayoutModifier AvoidStruts a where instance LayoutModifier AvoidStruts a where
modifyLayout (AvoidStruts ss) w r = do modifyLayout (AvoidStruts ss) w r = do
srect <- fmap ($ r) (calcGap ss) srect <- fmap ($ r) (calcGap ss)
setWorkarea srect -- Ensure _NET_WORKAREA is not set.
-- See: https://github.com/xmonad/xmonad-contrib/pull/79
rmWorkarea
runLayout w srect runLayout w srect
pureMess as@(AvoidStruts ss) m pureMess as@(AvoidStruts ss) m
@@ -262,13 +263,11 @@ instance LayoutModifier AvoidStruts a where
toggleOne x xs | x `S.member` xs = S.delete x xs toggleOne x xs | x `S.member` xs = S.delete x xs
| otherwise = x `S.insert` xs | otherwise = x `S.insert` xs
setWorkarea :: Rectangle -> X () rmWorkarea :: X ()
setWorkarea (Rectangle x y w h) = withDisplay $ \dpy -> do rmWorkarea = withDisplay $ \dpy -> do
a <- getAtom "_NET_WORKAREA" a <- getAtom "_NET_WORKAREA"
c <- getAtom "CARDINAL"
r <- asks theRoot r <- asks theRoot
io $ changeProperty32 dpy r a c propModeReplace [fi x, fi y, fi w, fi h] io (deleteProperty dpy r a)
-- | (Direction, height\/width, initial pixel, final pixel). -- | (Direction, height\/width, initial pixel, final pixel).

View File

@@ -497,14 +497,14 @@ data BorderUrgencyHook = BorderUrgencyHook { urgencyBorderColor :: !String }
instance UrgencyHook BorderUrgencyHook where instance UrgencyHook BorderUrgencyHook where
urgencyHook BorderUrgencyHook { urgencyBorderColor = cs } w = urgencyHook BorderUrgencyHook { urgencyBorderColor = cs } w =
withDisplay $ \dpy -> io $ do withDisplay $ \dpy -> do
c' <- initColor dpy cs c' <- io (initColor dpy cs)
case c' of case c' of
Just c -> setWindowBorder dpy w c Just c -> setWindowBorderWithFallback dpy w cs c
_ -> hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor " _ -> io $ hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor "
,show cs ,show cs
," in BorderUrgencyHook" ," in BorderUrgencyHook"
] ]
-- | Flashes when a window requests your attention and you can't see it. -- | Flashes when a window requests your attention and you can't see it.
-- Defaults to a duration of five seconds, and no extra args to dzen. -- Defaults to a duration of five seconds, and no extra args to dzen.
@@ -543,4 +543,3 @@ filterUrgencyHook skips w = do
Just tag -> when (tag `elem` skips) Just tag -> when (tag `elem` skips)
$ adjustUrgents (delete w) $ adjustUrgents (delete w)
_ -> return () _ -> return ()

View File

@@ -1,5 +1,5 @@
{-# OPTIONS_GHC -fno-warn-missing-signatures #-} {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
{-# LANGUAGE MultiParamTypeClasses, Rank2Types, ImpredicativeTypes #-} {-# LANGUAGE MultiParamTypeClasses, Rank2Types #-}
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- | -- |
@@ -178,7 +178,7 @@ focusFloatDown = focusHelper id id
-- ** Groups-specific actions -- ** Groups-specific actions
wrap :: G.ModifySpec -> X () wrap :: G.ModifySpec -> X ()
wrap = sendMessage . G.Modify wrap x = sendMessage (G.Modify x)
-- | Swap the focused group with the previous one -- | Swap the focused group with the previous one
swapGroupUp :: X () swapGroupUp :: X ()

View File

@@ -110,7 +110,7 @@ popNewestHiddenWindow = sendMessage PopNewestHiddenWindow
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
hideWindowMsg :: HiddenWindows a -> Window -> X (Maybe (HiddenWindows a)) hideWindowMsg :: HiddenWindows a -> Window -> X (Maybe (HiddenWindows a))
hideWindowMsg (HiddenWindows hidden) win = do hideWindowMsg (HiddenWindows hidden) win = do
windows (W.delete' win) modify (\s -> s { windowset = W.delete' win $ windowset s })
return . Just . HiddenWindows $ hidden ++ [win] return . Just . HiddenWindows $ hidden ++ [win]
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@@ -130,4 +130,5 @@ popOldestMsg (HiddenWindows (win:rest)) = do
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
restoreWindow :: Window -> X () restoreWindow :: Window -> X ()
restoreWindow = windows . W.insertUp restoreWindow win =
modify (\s -> s { windowset = W.insertUp win $ windowset s })

View File

@@ -195,7 +195,9 @@ navigable :: Direction2D -> Point -> [(Window, Rectangle)] -> [(Window, Rectangl
navigable d pt = sortby d . filter (inr d pt . snd) navigable d pt = sortby d . filter (inr d pt . snd)
sc :: Pixel -> Window -> X () sc :: Pixel -> Window -> X ()
sc c win = withDisplay $ \dpy -> io $ setWindowBorder dpy win c sc c win = withDisplay $ \dpy -> do
colorName <- io (pixelToString dpy c)
setWindowBorderWithFallback dpy win colorName c
center :: Rectangle -> Point center :: Rectangle -> Point
center (Rectangle x y w h) = P (fromIntegral x + fromIntegral w/2) (fromIntegral y + fromIntegral h/2) center (Rectangle x y w h) = P (fromIntegral x + fromIntegral w/2) (fromIntegral y + fromIntegral h/2)

View File

@@ -91,7 +91,6 @@ import Data.List
import qualified Data.Map as M import qualified Data.Map as M
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Set (fromList, toList) import Data.Set (fromList, toList)
import System.Directory (getAppUserDataDirectory)
import System.IO import System.IO
import System.Posix.Files import System.Posix.Files
@@ -521,24 +520,59 @@ completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = d
alwaysHlight <- gets $ alwaysHighlight . config alwaysHlight <- gets $ alwaysHighlight . config
mCleaned <- cleanMask m mCleaned <- cleanMask m
case () of case () of
() | t == keyPress && (mCleaned,sym) == complKey -> () | t == keyPress && (mCleaned,sym) == complKey -> do
do st <- get
st <- get
let updateState l = case alwaysHlight of let updateWins l = redrawWindows l >> eventLoop (completionHandle l)
-- modify the buffer's value updateState l = case alwaysHlight of
False -> let newCommand = nextCompletion (currentXPMode st) (command st) l False -> simpleComplete l st
in modify $ \s -> setCommand newCommand $ s { offset = length newCommand, highlightedCompl = Just newCommand} True | Just (command st) /= highlightedCompl st -> alwaysHighlightCurrent st
--TODO: Scroll or paginate results | otherwise -> alwaysHighlightNext l st
True -> let complIndex' = nextComplIndex st (length l)
highlightedCompl' = highlightedItem st { complIndex = complIndex'} c case c of
in modify $ \s -> setHighlightedCompl highlightedCompl' $ s { complIndex = complIndex' } [] -> updateWindows >> eventLoop handle
updateWins l = redrawWindows l >> eventLoop (completionHandle l) [x] -> updateState [x] >> getCompletions >>= updateWins
case c of l -> updateState l >> updateWins l
[] -> updateWindows >> eventLoop handle
[x] -> updateState [x] >> getCompletions >>= updateWins
l -> updateState l >> updateWins l
| t == keyRelease && (mCleaned,sym) == complKey -> eventLoop (completionHandle c) | t == keyRelease && (mCleaned,sym) == complKey -> eventLoop (completionHandle c)
| otherwise -> keyPressHandle mCleaned ks -- some other key, handle it normally | otherwise -> keyPressHandle mCleaned ks -- some other key, handle it normally
where
-- When alwaysHighlight is off, just complete based on what the
-- user has typed so far.
simpleComplete :: [String] -> XPState -> XP ()
simpleComplete l st = do
let newCommand = nextCompletion (currentXPMode st) (command st) l
modify $ \s -> setCommand newCommand $
s { offset = length newCommand
, highlightedCompl = Just newCommand
}
-- If alwaysHighlight is on, and this is the first use of the
-- completion key, update the buffer so that it contains the
-- current completion item.
alwaysHighlightCurrent :: XPState -> XP ()
alwaysHighlightCurrent st = do
let newCommand = fromMaybe (command st) $ highlightedItem st c
modify $ \s -> setCommand newCommand $
setHighlightedCompl (Just newCommand) $
s { offset = length newCommand
}
-- If alwaysHighlight is on, and the user wants the next
-- completion, move to the next completion item and update the
-- buffer to reflect that.
--
--TODO: Scroll or paginate results
alwaysHighlightNext :: [String] -> XPState -> XP ()
alwaysHighlightNext l st = do
let complIndex' = nextComplIndex st (length l)
highlightedCompl' = highlightedItem st { complIndex = complIndex'} c
newCommand = fromMaybe (command st) $ highlightedCompl'
modify $ \s -> setHighlightedCompl highlightedCompl' $
setCommand newCommand $
s { complIndex = complIndex'
, offset = length newCommand
}
-- some other event: go back to main loop -- some other event: go back to main loop
completionHandle _ k e = handle k e completionHandle _ k e = handle k e
@@ -1064,7 +1098,7 @@ emptyHistory :: History
emptyHistory = M.empty emptyHistory = M.empty
getHistoryFile :: IO FilePath getHistoryFile :: IO FilePath
getHistoryFile = fmap (++ "/history") $ getAppUserDataDirectory "xmonad" getHistoryFile = fmap (++ "/prompt-history") getXMonadCacheDir
readHistory :: IO History readHistory :: IO History
readHistory = readHist `E.catch` \(SomeException _) -> return emptyHistory readHistory = readHist `E.catch` \(SomeException _) -> return emptyHistory
@@ -1170,7 +1204,7 @@ breakAtSpace s
-- | 'historyCompletion' provides a canned completion function much like -- | 'historyCompletion' provides a canned completion function much like
-- 'getShellCompl'; you pass it to mkXPrompt, and it will make completions work -- 'getShellCompl'; you pass it to mkXPrompt, and it will make completions work
-- from the query history stored in ~\/.xmonad\/history. -- from the query history stored in the XMonad cache directory.
historyCompletion :: ComplFunction historyCompletion :: ComplFunction
historyCompletion = historyCompletionP (const True) historyCompletion = historyCompletionP (const True)

View File

@@ -16,7 +16,8 @@ module XMonad.Prompt.Directory (
-- * Usage -- * Usage
-- $usage -- $usage
directoryPrompt, directoryPrompt,
Dir, directoryMultipleModes,
Dir
) where ) where
import XMonad import XMonad
@@ -26,13 +27,23 @@ import XMonad.Util.Run ( runProcessWithInput )
-- $usage -- $usage
-- For an example usage see "XMonad.Layout.WorkspaceDir" -- For an example usage see "XMonad.Layout.WorkspaceDir"
data Dir = Dir String data Dir = Dir String (String -> X ())
instance XPrompt Dir where instance XPrompt Dir where
showXPrompt (Dir x) = x showXPrompt (Dir x _) = x
completionFunction _ = getDirCompl
modeAction (Dir _ f) buf auto =
let dir = if null auto then buf else auto
in f dir
directoryPrompt :: XPConfig -> String -> (String -> X ()) -> X () directoryPrompt :: XPConfig -> String -> (String -> X ()) -> X ()
directoryPrompt c prom = mkXPrompt (Dir prom) c getDirCompl directoryPrompt c prom f = mkXPrompt (Dir prom f) c getDirCompl f
-- | A @XPType@ entry suitable for using with @mkXPromptWithModes@.
directoryMultipleModes :: String -- ^ Prompt.
-> (String -> X ()) -- ^ Action.
-> XPType
directoryMultipleModes p f = XPT (Dir p f)
getDirCompl :: String -> IO [String] getDirCompl :: String -> IO [String]
getDirCompl s = (filter notboring . lines) `fmap` getDirCompl s = (filter notboring . lines) `fmap`

View File

@@ -4,11 +4,9 @@
-- Copyright : (c) 2007 Valery V. Vorotyntsev -- Copyright : (c) 2007 Valery V. Vorotyntsev
-- License : BSD3-style (see LICENSE) -- License : BSD3-style (see LICENSE)
-- --
-- Maintainer : Valery V. Vorotynsev <valery.vv@gmail.com>
--
-- Customized key bindings. -- Customized key bindings.
-- --
-- (See also "XMonad.Util.EZConfig" in xmonad-contrib.) -- See also "XMonad.Util.EZConfig" in xmonad-contrib.
-------------------------------------------------------------------- --------------------------------------------------------------------
module XMonad.Util.CustomKeys ( module XMonad.Util.CustomKeys (
@@ -25,38 +23,30 @@ import qualified Data.Map as M
-- $usage -- $usage
-- --
-- 1. In @~\/.xmonad\/xmonad.hs@ add: -- In @~\/.xmonad\/xmonad.hs@ add:
-- --
-- > import XMonad.Util.CustomKeys -- > import XMonad.Util.CustomKeys
-- --
-- 2. Set key bindings with 'customKeys': -- Set key bindings with 'customKeys':
-- --
-- > main = xmonad def { keys = customKeys delkeys inskeys } -- > main = xmonad def { keys = customKeys delkeys inskeys }
-- > where -- > where
-- > delkeys :: XConfig l -> [(KeyMask, KeySym)] -- > delkeys :: XConfig l -> [(KeyMask, KeySym)]
-- > delkeys XConfig {modMask = modm} = -- > delkeys XConfig {modMask = modm} =
-- > -- we're preferring Futurama to Xinerama here -- > [ (modm .|. shiftMask, xK_Return) -- > terminal
-- > [ (modm .|. m, k) | (m, k) <- zip [0, shiftMask] [xK_w, xK_e, xK_r] ] -- > , (modm .|. shiftMask, xK_c) -- > close the focused window
-- > ]
-- > ++
-- > [ (modm .|. m, k) | m <- [0, shiftMask], k <- [xK_w, xK_e, xK_r] ]
-- > -- >
-- > inskeys :: XConfig l -> [((KeyMask, KeySym), X ())] -- > inskeys :: XConfig l -> [((KeyMask, KeySym), X ())]
-- > inskeys conf@(XConfig {modMask = modm}) = -- > inskeys conf@(XConfig {modMask = modm}) =
-- > [ ((mod1Mask, xK_F2 ), spawn $ terminal conf) -- > [ ((mod1Mask, xK_F2 ), spawn $ terminal conf) -- mod1-f2 %! Run a terminal emulator
-- > , ((modm, xK_Delete), kill) -- %! Close the focused window
-- > , ((modm .|. controlMask, xK_F11 ), spawn "xscreensaver-command -lock") -- > , ((modm .|. controlMask, xK_F11 ), spawn "xscreensaver-command -lock")
-- > , ((mod1Mask, xK_Down), spawn "amixer set Master 1-") -- > , ((mod1Mask, xK_Down), spawn "amixer set Master 1-")
-- > , ((mod1Mask, xK_Up ), spawn "amixer set Master 1+") -- > , ((mod1Mask, xK_Up ), spawn "amixer set Master 1+")
-- > ] -- > ]
--
-- 0 (/hidden feature/). You can always replace bindings map
-- entirely. No need to import "CustomKeys" this time:
--
-- > import XMonad
-- > import System.Exit
-- > import qualified Data.Map as M
-- >
-- > main = xmonad def {
-- > keys = \_ -> M.fromList [
-- > -- Let me out of here! I want my KDE back! Help! Help!
-- > ( (0, xK_Escape), io (exitWith ExitSuccess) ) ] }
-- | Customize 'XMonad.Config.def' -- delete needless -- | Customize 'XMonad.Config.def' -- delete needless
-- shortcuts and insert those you will use. -- shortcuts and insert those you will use.

View File

@@ -29,6 +29,7 @@ module XMonad.Util.Font
, textExtentsXMF , textExtentsXMF
, printStringXMF , printStringXMF
, stringToPixel , stringToPixel
, pixelToString
, fi , fi
) where ) where
@@ -37,6 +38,8 @@ import Foreign
import Control.Applicative import Control.Applicative
import Control.Exception as E import Control.Exception as E
import Data.Maybe import Data.Maybe
import Data.Bits (shiftR)
import Text.Printf (printf)
#ifdef XFT #ifdef XFT
import Data.List import Data.List
@@ -61,6 +64,19 @@ stringToPixel d s = fromMaybe fallBack <$> io getIt
where getIt = initColor d s where getIt = initColor d s
fallBack = blackPixel d (defaultScreen d) fallBack = blackPixel d (defaultScreen d)
-- | Convert a @Pixel@ into a @String@.
pixelToString :: (MonadIO m) => Display -> Pixel -> m String
pixelToString d p = do
let cm = defaultColormap d (defaultScreen d)
(Color _ r g b _) <- io (queryColor d cm $ Color p 0 0 0 0)
return ("#" ++ hex r ++ hex g ++ hex b)
where
-- NOTE: The @Color@ type has 16-bit values for red, green, and
-- blue, even though the actual type in X is only 8 bits wide. It
-- seems that the upper and lower 8-bit sections of the @Word16@
-- values are the same. So, we just discard the lower 8 bits.
hex = printf "%02x" . (`shiftR` 8)
econst :: a -> IOException -> a econst :: a -> IOException -> a
econst = const econst = const

View File

@@ -28,6 +28,7 @@ module XMonad.Util.XUtils
, paintAndWrite , paintAndWrite
, paintTextAndIcons , paintTextAndIcons
, stringToPixel , stringToPixel
, pixelToString
, fi , fi
) where ) where
@@ -208,4 +209,3 @@ mkWindow d s rw x y w h p o = do
set_background_pixel attributes p set_background_pixel attributes p
createWindow d rw x y w h 0 (defaultDepthOfScreen s) createWindow d rw x y w h 0 (defaultDepthOfScreen s)
inputOutput visual attrmask attributes inputOutput visual attrmask attributes

3
cabal.project Normal file
View File

@@ -0,0 +1,3 @@
packages: ./
../xmonad/
../x11/

9
stack.yaml Normal file
View File

@@ -0,0 +1,9 @@
resolver: lts-7.19
packages:
- ./
- ../xmonad
extra-deps:
- X11-1.8
- X11-xft-0.3.1

View File

@@ -1,5 +1,5 @@
name: xmonad-contrib name: xmonad-contrib
version: 0.12 version: 0.13
homepage: http://xmonad.org/ homepage: http://xmonad.org/
synopsis: Third party extensions for xmonad synopsis: Third party extensions for xmonad
description: description:
@@ -35,10 +35,7 @@ cabal-version: >= 1.6
build-type: Simple build-type: Simple
bug-reports: https://github.com/xmonad/xmonad-contrib/issues bug-reports: https://github.com/xmonad/xmonad-contrib/issues
tested-with: tested-with: GHC==7.6.3, GHC==7.8.4, GHC==7.10.3, GHC==8.0.1
GHC==7.6.3,
GHC==7.8.4,
GHC==7.10.2
source-repository head source-repository head
type: git type: git
@@ -66,8 +63,8 @@ library
random, random,
mtl >= 1 && < 3, mtl >= 1 && < 3,
unix, unix,
X11>=1.7 && < 1.8, X11>=1.6.1 && < 1.9,
xmonad>=0.12 && < 0.13, xmonad>=0.13 && < 0.14,
utf8-string utf8-string
if flag(use_xft) if flag(use_xft)