From 9da78669e77b3b026bc9e18eb91fd21eaea9cbd8 Mon Sep 17 00:00:00 2001 From: Luc DUZAN Date: Thu, 22 Dec 2016 22:48:23 +0100 Subject: [PATCH 01/28] Add HiddenEmptyWS to CycleWS When I have multiscreen I think it's usefull to get the next empty workspace that is not already displayed. --- XMonad/Actions/CycleWS.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/XMonad/Actions/CycleWS.hs b/XMonad/Actions/CycleWS.hs index 74d9acb1..62687d76 100644 --- a/XMonad/Actions/CycleWS.hs +++ b/XMonad/Actions/CycleWS.hs @@ -239,6 +239,7 @@ data WSType = EmptyWS -- ^ cycle through empty workspaces | NonEmptyWS -- ^ cycle through non-empty workspaces | HiddenWS -- ^ cycle through non-visible workspaces | HiddenNonEmptyWS -- ^ cycle through non-empty non-visible workspaces + | HiddenEmptyWS -- ^ cycle through empty non-visible workspaces | AnyWS -- ^ cycle through all workspaces | WSTagGroup Char -- ^ cycle through workspaces in the same group, the @@ -257,6 +258,9 @@ wsTypeToPred HiddenWS = do hs <- gets (map tag . hidden . windowset) wsTypeToPred HiddenNonEmptyWS = do ne <- wsTypeToPred NonEmptyWS hi <- wsTypeToPred HiddenWS return (\w -> hi w && ne w) +wsTypeToPred HiddenEmptyWS = do ne <- wsTypeToPred EmptyWS + hi <- wsTypeToPred HiddenWS + return (\w -> hi w && ne w) wsTypeToPred AnyWS = return (const True) wsTypeToPred (WSTagGroup sep) = do cur <- (groupName.workspace.current) `fmap` gets windowset return $ (cur ==).groupName From 5bf4b270541cdd728c266f75413e1f4a8e1a4d62 Mon Sep 17 00:00:00 2001 From: sgf Date: Sun, 25 Dec 2016 14:59:30 +0300 Subject: [PATCH 02/28] Fix CHANGES.md after b9d8f6c . --- CHANGES.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 259ae8e2..0fa52a3f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -42,12 +42,6 @@ EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since you will usually be taken to the `NSP` workspace by them. - * `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. - ### Minor Changes * `XMonad.Layout.LayoutBuilder` @@ -71,6 +65,12 @@ - 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. + ## 0.12 (December 14, 2015) From 74b281b5d331156520d7dbe7a0b863a79d8e18e8 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 4 Jan 2017 14:39:00 -0700 Subject: [PATCH 03/28] 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 --- XMonad/Prompt.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/XMonad/Prompt.hs b/XMonad/Prompt.hs index ae5250b3..1c040e02 100644 --- a/XMonad/Prompt.hs +++ b/XMonad/Prompt.hs @@ -91,7 +91,6 @@ import Data.List import qualified Data.Map as M import Data.Maybe (fromMaybe) import Data.Set (fromList, toList) -import System.Directory (getAppUserDataDirectory) import System.IO import System.Posix.Files @@ -1064,7 +1063,7 @@ emptyHistory :: History emptyHistory = M.empty getHistoryFile :: IO FilePath -getHistoryFile = fmap (++ "/history") $ getAppUserDataDirectory "xmonad" +getHistoryFile = fmap (++ "/prompt-history") getXMonadCacheDir readHistory :: IO History readHistory = readHist `E.catch` \(SomeException _) -> return emptyHistory @@ -1170,7 +1169,7 @@ breakAtSpace s -- | 'historyCompletion' provides a canned completion function much like -- '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 = historyCompletionP (const True) From 4dd60756ea75bb3b89886394490b9b813f3b346b Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 4 Jan 2017 14:47:20 -0700 Subject: [PATCH 04/28] Update the change log --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 0fa52a3f..989e9568 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,9 @@ * New constructor `CenteredAt Rational Rational` added for `XMonad.Prompt.XPPosition`. + * `XMonad.Prompt` now stores its history file in the XMonad cache + directory in a file named `prompt-history`. + ### New Modules * `XMonad.Layout.SortedLayout` From 33c805fadcda8144a086c9d53aad932bbbc3e81b Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 12 Jan 2017 12:27:11 -0700 Subject: [PATCH 05/28] Add GitHub templates --- .github/ISSUE_TEMPLATE.md | 24 ++++++++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 12 ++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..d837a673 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -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) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..52e31f08 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -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 From 52087953fda5c286c8a4b558021b0fd77e6b6e59 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Sun, 5 Feb 2017 19:31:41 -0700 Subject: [PATCH 06/28] Add `directoryMultipleModes' Allow X.P.Directory to be used with `mkXPromptWithModes` --- XMonad/Prompt/Directory.hs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/XMonad/Prompt/Directory.hs b/XMonad/Prompt/Directory.hs index 35317ff7..fe3088fc 100644 --- a/XMonad/Prompt/Directory.hs +++ b/XMonad/Prompt/Directory.hs @@ -16,7 +16,8 @@ module XMonad.Prompt.Directory ( -- * Usage -- $usage directoryPrompt, - Dir, + directoryMultipleModes, + Dir ) where import XMonad @@ -26,13 +27,23 @@ import XMonad.Util.Run ( runProcessWithInput ) -- $usage -- For an example usage see "XMonad.Layout.WorkspaceDir" -data Dir = Dir String +data Dir = Dir String (String -> X ()) 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 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 s = (filter notboring . lines) `fmap` From bdec8df4c6c821c0003397e514b4cb0c2a039cd5 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Sun, 5 Feb 2017 19:36:30 -0700 Subject: [PATCH 07/28] Improve prompts for X.A.DynamicProjects --- CHANGES.md | 7 ++ XMonad/Actions/DynamicProjects.hs | 143 ++++++++++++++++++++---------- 2 files changed, 104 insertions(+), 46 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 989e9568..405edba6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -75,6 +75,13 @@ as we do for wrong key press. + * `XMonad.Actions.DynamicProjects` + + - 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) ### Breaking Changes diff --git a/XMonad/Actions/DynamicProjects.hs b/XMonad/Actions/DynamicProjects.hs index fe89908f..c0b082b0 100644 --- a/XMonad/Actions/DynamicProjects.hs +++ b/XMonad/Actions/DynamicProjects.hs @@ -31,6 +31,7 @@ module XMonad.Actions.DynamicProjects , switchProjectPrompt , shiftToProjectPrompt , renameProjectPrompt + , changeProjectDirPrompt -- * Helper Functions , switchProject @@ -43,6 +44,7 @@ module XMonad.Actions.DynamicProjects -------------------------------------------------------------------------------- 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 @@ -52,8 +54,7 @@ import System.Directory (setCurrentDirectory, getHomeDirectory) import XMonad import XMonad.Actions.DynamicWorkspaces import XMonad.Prompt -import XMonad.Prompt.Directory (directoryPrompt) -import XMonad.Prompt.Workspace (Wor(..)) +import XMonad.Prompt.Directory import qualified XMonad.StackSet as W import qualified XMonad.Util.ExtensibleState as XS @@ -142,6 +143,48 @@ data ProjectState = ProjectState instance ExtensionClass ProjectState where 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. dynamicProjects :: [Project] -> XConfig a -> XConfig a @@ -198,6 +241,21 @@ currentProject = do proj <- lookupProject name return $ fromMaybe (defProject name) proj +-------------------------------------------------------------------------------- +-- | Modify the current project using a pure function. +modifyProject :: (Project -> Project) -> X () +modifyProject f = do + p <- currentProject + ps <- XS.gets projects + + -- If a project is renamed to match another project, the old project + -- will be removed and replaced with this one. + let new = f p + ps' = Map.insert (projectName new) new $ Map.delete (projectName p) ps + + XS.modify $ \s -> s {projects = ps'} + activateProject new + -------------------------------------------------------------------------------- -- | Switch to the given project. switchProject :: Project -> X () @@ -220,22 +278,11 @@ switchProject p = do -- | Prompt for a project name and then switch to it. Automatically -- creates a project if a new name is returned from the prompt. switchProjectPrompt :: XPConfig -> X () -switchProjectPrompt c = projectPrompt c switch - where - switch :: ProjectTable -> ProjectName -> X () - switch ps name = case Map.lookup name ps of - 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 +switchProjectPrompt = projectPrompt [ SwitchMode + , ShiftMode + , RenameMode + , DirMode + ] -------------------------------------------------------------------------------- -- | 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 -- window to that project. shiftToProjectPrompt :: XPConfig -> X () -shiftToProjectPrompt c = projectPrompt c go - where - go :: ProjectTable -> ProjectName -> X () - go ps name = shiftToProject . fromMaybe (defProject name) $ - 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) +shiftToProjectPrompt = projectPrompt [ ShiftMode + , RenameMode + , SwitchMode + , DirMode + ] -------------------------------------------------------------------------------- -- | Rename the current project. renameProjectPrompt :: XPConfig -> X () -renameProjectPrompt c = mkXPrompt (Wor "New Project Name: ") c (return . (:[])) go - where - go :: String -> X () - go name = do - p <- currentProject - ps <- XS.gets projects - renameWorkspaceByName name +renameProjectPrompt = projectPrompt [ RenameMode + , DirMode + , SwitchMode + , ShiftMode + ] - 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 From 57c00b1086359b0061ae5ce33aafc8b615e43ddb Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Sun, 5 Feb 2017 19:38:00 -0700 Subject: [PATCH 08/28] 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.) --- XMonad/Prompt.hs | 67 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/XMonad/Prompt.hs b/XMonad/Prompt.hs index 1c040e02..fc01cadb 100644 --- a/XMonad/Prompt.hs +++ b/XMonad/Prompt.hs @@ -520,24 +520,59 @@ completionHandle c ks@(sym,_) (KeyEvent { ev_event_type = t, ev_state = m }) = d alwaysHlight <- gets $ alwaysHighlight . config mCleaned <- cleanMask m case () of - () | t == keyPress && (mCleaned,sym) == complKey -> - do - st <- get - let updateState l = case alwaysHlight of - -- modify the buffer's value - False -> let newCommand = nextCompletion (currentXPMode st) (command st) l - in modify $ \s -> setCommand newCommand $ s { offset = length newCommand, highlightedCompl = Just newCommand} - --TODO: Scroll or paginate results - True -> let complIndex' = nextComplIndex st (length l) - highlightedCompl' = highlightedItem st { complIndex = complIndex'} c - in modify $ \s -> setHighlightedCompl highlightedCompl' $ s { complIndex = complIndex' } - updateWins l = redrawWindows l >> eventLoop (completionHandle l) - case c of - [] -> updateWindows >> eventLoop handle - [x] -> updateState [x] >> getCompletions >>= updateWins - l -> updateState l >> updateWins l + () | t == keyPress && (mCleaned,sym) == complKey -> do + st <- get + + let updateWins l = redrawWindows l >> eventLoop (completionHandle l) + updateState l = case alwaysHlight of + False -> simpleComplete l st + True | Just (command st) /= highlightedCompl st -> alwaysHighlightCurrent st + | otherwise -> alwaysHighlightNext l st + + case c of + [] -> updateWindows >> eventLoop handle + [x] -> updateState [x] >> getCompletions >>= updateWins + l -> updateState l >> updateWins l | t == keyRelease && (mCleaned,sym) == complKey -> eventLoop (completionHandle c) | 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 completionHandle _ k e = handle k e From 4f3020313d2709b2569483f5efc4cc9762efc721 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 7 Feb 2017 13:37:32 -0700 Subject: [PATCH 09/28] Don't use `windows' in X.L.Hidden, it might cause an infinite loop Fixes #132 --- XMonad/Layout/Hidden.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/XMonad/Layout/Hidden.hs b/XMonad/Layout/Hidden.hs index e171e098..b5e6999b 100644 --- a/XMonad/Layout/Hidden.hs +++ b/XMonad/Layout/Hidden.hs @@ -110,7 +110,7 @@ popNewestHiddenWindow = sendMessage PopNewestHiddenWindow -------------------------------------------------------------------------------- hideWindowMsg :: HiddenWindows a -> Window -> X (Maybe (HiddenWindows a)) hideWindowMsg (HiddenWindows hidden) win = do - windows (W.delete' win) + modify (\s -> s { windowset = W.delete' win $ windowset s }) return . Just . HiddenWindows $ hidden ++ [win] -------------------------------------------------------------------------------- @@ -130,4 +130,5 @@ popOldestMsg (HiddenWindows (win:rest)) = do -------------------------------------------------------------------------------- restoreWindow :: Window -> X () -restoreWindow = windows . W.insertUp +restoreWindow win = + modify (\s -> s { windowset = W.insertUp win $ windowset s }) From de4a3bd0edd52eb3d1418721eb4318aa6e64a64a Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 7 Feb 2017 14:49:01 -0700 Subject: [PATCH 10/28] 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 --- XMonad/Hooks/UrgencyHook.hs | 17 ++++++++--------- XMonad/Layout/WindowNavigation.hs | 4 +++- XMonad/Util/Font.hs | 16 ++++++++++++++++ XMonad/Util/XUtils.hs | 2 +- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/XMonad/Hooks/UrgencyHook.hs b/XMonad/Hooks/UrgencyHook.hs index afc5b169..f9360c51 100644 --- a/XMonad/Hooks/UrgencyHook.hs +++ b/XMonad/Hooks/UrgencyHook.hs @@ -339,7 +339,7 @@ getNetWMState :: Window -> X [CLong] getNetWMState w = do a_wmstate <- getAtom "_NET_WM_STATE" fromMaybe [] `fmap` getProp32 a_wmstate w - + -- The Non-ICCCM Manifesto: -- Note: Some non-standard choices have been made in this implementation to @@ -497,14 +497,14 @@ data BorderUrgencyHook = BorderUrgencyHook { urgencyBorderColor :: !String } instance UrgencyHook BorderUrgencyHook where urgencyHook BorderUrgencyHook { urgencyBorderColor = cs } w = - withDisplay $ \dpy -> io $ do - c' <- initColor dpy cs + withDisplay $ \dpy -> do + c' <- io (initColor dpy cs) case c' of - Just c -> setWindowBorder dpy w c - _ -> hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor " - ,show cs - ," in BorderUrgencyHook" - ] + Just c -> setWindowBorderWithFallback dpy w cs c + _ -> io $ hPutStrLn stderr $ concat ["Warning: bad urgentBorderColor " + ,show cs + ," in BorderUrgencyHook" + ] -- | 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. @@ -543,4 +543,3 @@ filterUrgencyHook skips w = do Just tag -> when (tag `elem` skips) $ adjustUrgents (delete w) _ -> return () - diff --git a/XMonad/Layout/WindowNavigation.hs b/XMonad/Layout/WindowNavigation.hs index 84e3aed6..94b153cd 100644 --- a/XMonad/Layout/WindowNavigation.hs +++ b/XMonad/Layout/WindowNavigation.hs @@ -195,7 +195,9 @@ navigable :: Direction2D -> Point -> [(Window, Rectangle)] -> [(Window, Rectangl navigable d pt = sortby d . filter (inr d pt . snd) 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 x y w h) = P (fromIntegral x + fromIntegral w/2) (fromIntegral y + fromIntegral h/2) diff --git a/XMonad/Util/Font.hs b/XMonad/Util/Font.hs index 031a7060..0df98ffa 100644 --- a/XMonad/Util/Font.hs +++ b/XMonad/Util/Font.hs @@ -29,6 +29,7 @@ module XMonad.Util.Font , textExtentsXMF , printStringXMF , stringToPixel + , pixelToString , fi ) where @@ -37,6 +38,8 @@ import Foreign import Control.Applicative import Control.Exception as E import Data.Maybe +import Data.Bits (shiftR) +import Text.Printf (printf) #ifdef XFT import Data.List @@ -61,6 +64,19 @@ stringToPixel d s = fromMaybe fallBack <$> io getIt where getIt = initColor d s 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 = const diff --git a/XMonad/Util/XUtils.hs b/XMonad/Util/XUtils.hs index b7e0fec2..b12a6112 100644 --- a/XMonad/Util/XUtils.hs +++ b/XMonad/Util/XUtils.hs @@ -28,6 +28,7 @@ module XMonad.Util.XUtils , paintAndWrite , paintTextAndIcons , stringToPixel + , pixelToString , fi ) where @@ -208,4 +209,3 @@ mkWindow d s rw x y w h p o = do set_background_pixel attributes p createWindow d rw x y w h 0 (defaultDepthOfScreen s) inputOutput visual attrmask attributes - From 0a8e68b4589539e093c1dc9168fdd2197418fd00 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 7 Feb 2017 15:42:35 -0700 Subject: [PATCH 11/28] Delete _NET_WORKAREA instead of setting it References: * https://github.com/awesomeWM/awesome/commit/9c020877dd1357d7d42a29526d3567586f3db330 * https://github.com/qtile/qtile/issues/847 * https://github.com/i3/i3/commit/eec80838ab39377f18e3f68dc8a27923ae19e57e * https://github.com/xmonad/xmonad-contrib/pull/79 --- XMonad/Hooks/ManageDocks.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/XMonad/Hooks/ManageDocks.hs b/XMonad/Hooks/ManageDocks.hs index d11d8110..0e0e9d6c 100644 --- a/XMonad/Hooks/ManageDocks.hs +++ b/XMonad/Hooks/ManageDocks.hs @@ -246,7 +246,9 @@ instance Message SetStruts instance LayoutModifier AvoidStruts a where modifyLayout (AvoidStruts ss) w r = do 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 pureMess as@(AvoidStruts ss) m @@ -262,13 +264,11 @@ instance LayoutModifier AvoidStruts a where toggleOne x xs | x `S.member` xs = S.delete x xs | otherwise = x `S.insert` xs -setWorkarea :: Rectangle -> X () -setWorkarea (Rectangle x y w h) = withDisplay $ \dpy -> do +rmWorkarea :: X () +rmWorkarea = withDisplay $ \dpy -> do a <- getAtom "_NET_WORKAREA" - c <- getAtom "CARDINAL" 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). From cd96de53782f04a60adfa5f0bc588e51ff735e40 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 7 Feb 2017 15:58:55 -0700 Subject: [PATCH 12/28] Manage struts even when _NET_WM_WINDOW_TYPE isn't a dock Relates to #21 --- XMonad/Hooks/ManageDocks.hs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/XMonad/Hooks/ManageDocks.hs b/XMonad/Hooks/ManageDocks.hs index d11d8110..47d588ab 100644 --- a/XMonad/Hooks/ManageDocks.hs +++ b/XMonad/Hooks/ManageDocks.hs @@ -140,12 +140,11 @@ docksEventHook (MapNotifyEvent { ev_window = w }) = do return (All True) docksEventHook (PropertyEvent { ev_window = w , ev_atom = a }) = do - whenX (runQuery checkDock w) $ do - nws <- getAtom "_NET_WM_STRUT" - nwsp <- getAtom "_NET_WM_STRUT_PARTIAL" - when (a == nws || a == nwsp) $ do - strut <- getStrut w - whenX (updateStrutCache w strut) refreshDocks + nws <- getAtom "_NET_WM_STRUT" + nwsp <- getAtom "_NET_WM_STRUT_PARTIAL" + when (a == nws || a == nwsp) $ do + strut <- getStrut w + whenX (updateStrutCache w strut) refreshDocks return (All True) docksEventHook (DestroyWindowEvent {ev_window = w}) = do whenX (deleteFromStructCache w) refreshDocks From cb344d14b9a6145395f5b2b6d121846729684581 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 9 Feb 2017 16:12:55 -0700 Subject: [PATCH 13/28] Bump version to 0.13 --- xmonad-contrib.cabal | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal index 87e26ce5..da9c0ae0 100644 --- a/xmonad-contrib.cabal +++ b/xmonad-contrib.cabal @@ -1,5 +1,5 @@ name: xmonad-contrib -version: 0.12 +version: 0.13 homepage: http://xmonad.org/ synopsis: Third party extensions for xmonad description: @@ -63,8 +63,8 @@ library random, mtl >= 1 && < 3, unix, - X11>=1.6.1 && < 1.8, - xmonad>=0.12 && < 0.13, + X11>=1.6.1 && < 1.9, + xmonad>=0.13 && < 0.14, utf8-string if flag(use_xft) From b064d22c2dcb0a2866c23fa13dc1f7ae6fc6e36d Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 9 Feb 2017 16:25:24 -0700 Subject: [PATCH 14/28] Add a release date --- CHANGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 405edba6..b9b46107 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,12 +1,12 @@ # Change Log / Release Notes -## 0.13 +## 0.13 (February 10, 2017) ### Breaking Changes * The type of `completionKey` (of `XPConfig` record) has been changed from `KeySym` to `(KeyMask, KeySym)`. The default value - for this is still binded to `Tab` key. + for this is still bound to the `Tab` key. * New constructor `CenteredAt Rational Rational` added for `XMonad.Prompt.XPPosition`. From e4e20da8f02b150e895270b9be34152666d337bb Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 10 Feb 2017 16:02:41 -0700 Subject: [PATCH 15/28] Clean up the change log just a bit --- CHANGES.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b9b46107..942b1c66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -45,21 +45,21 @@ EWMH taskbars and pagers. Useful for `NamedScratchpad` windows, since 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` Merge all functionality from `XMonad.Layout.LayoutBuilderP` into `XMonad.Layout.LayoutBuilder`. - * `XMonad.Actions.DynamicProjects` - - - Switching away from a dynamic project that contains no windows - automatically deletes that project's workspace. - - The project itself was already being deleted, this just deletes - the workspace created for it as well. - * `XMonad.Actions.WindowGo` - Fix `raiseNextMaybe` cycling between 2 workspaces only. @@ -74,9 +74,14 @@ submap key press. And terminate submap at button press in the same way, as we do for wrong key press. - * `XMonad.Actions.DynamicProjects` + - Switching away from a dynamic project that contains no windows + automatically deletes that project's workspace. + + The project itself was already being deleted, this just deletes + the workspace created for it as well. + - Added function to change the working directory (`changeProjectDirPrompt`) - All of the prompts are now multiple mode prompts. Try using the From 615f007fe458b92061cddac134aa0f77a8e2a3cc Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 10 Feb 2017 16:04:33 -0700 Subject: [PATCH 16/28] Add a cabal.project file --- .gitignore | 1 + cabal.project | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 cabal.project diff --git a/.gitignore b/.gitignore index cba063f4..8dc33bad 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ tags # stack artifacts /.stack-work/ +/cabal.project.local diff --git a/cabal.project b/cabal.project new file mode 100644 index 00000000..97bc9c8b --- /dev/null +++ b/cabal.project @@ -0,0 +1,3 @@ +packages: ./ + ../xmonad/ + ../x11/ From ca9b7d9dfcaf972152731420fe9f1ef01d967f5d Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 10 Feb 2017 16:20:42 -0700 Subject: [PATCH 17/28] Add a `stack.yaml` file for testing and easy Hackage upload --- stack.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 stack.yaml diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 00000000..95579aa3 --- /dev/null +++ b/stack.yaml @@ -0,0 +1,9 @@ +resolver: lts-7.19 + +packages: + - ./ + - ../xmonad + +extra-deps: + - X11-1.8 + - X11-xft-0.3.1 From 878987071b390860dc5eaa7e8a991cddc3c751d0 Mon Sep 17 00:00:00 2001 From: Mekeor Melire Date: Sat, 21 Jan 2017 14:08:48 +0100 Subject: [PATCH 18/28] Better description of 'font' field of 'XPC' record Describe how to use the 'font' field of 'XPC' record by adding two different examples. --- XMonad/Prompt.hs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/XMonad/Prompt.hs b/XMonad/Prompt.hs index 1c040e02..6b13c139 100644 --- a/XMonad/Prompt.hs +++ b/XMonad/Prompt.hs @@ -126,7 +126,10 @@ data XPState = } data XPConfig = - XPC { font :: String -- ^ Font; use the prefix @"xft:"@ for TrueType fonts + XPC { font :: String -- ^ Font. For TrueType fonts, use something like + -- @"xft:Hack:pixelsize=1"@. Alternatively, use X Logical Font + -- Description, i.e. something like + -- @"-*-dejavu sans mono-medium-r-normal--*-80-*-*-*-*-iso10646-1"@. , bgColor :: String -- ^ Background color , fgColor :: String -- ^ Font color , fgHLight :: String -- ^ Font color of a highlighted completion entry From 298e51f93954684e5ade769848ede5c154e4e298 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Mon, 13 Feb 2017 16:15:05 -0700 Subject: [PATCH 19/28] Correctly mark functions in X.P.Window as deprecated --- XMonad/Prompt/Window.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/XMonad/Prompt/Window.hs b/XMonad/Prompt/Window.hs index 66f1ce2d..e16c551d 100644 --- a/XMonad/Prompt/Window.hs +++ b/XMonad/Prompt/Window.hs @@ -80,6 +80,9 @@ instance XPrompt WindowPrompt where nextCompletion _ = getNextCompletion -- | Deprecated. Use windowPrompt instead. +{-# DEPRECATED windowPromptGoto "Use windowPrompt instead." #-} +{-# DEPRECATED windowPromptBring "Use windowPrompt instead." #-} +{-# DEPRECATED windowPromptBringCopy "Use windowPrompt instead." #-} windowPromptGoto, windowPromptBring, windowPromptBringCopy :: XPConfig -> X () windowPromptGoto c = windowPrompt c Goto windowMap windowPromptBring c = windowPrompt c Bring windowMap From 0f9a6015e48a251c28f8bb1821f3ea420937d46b Mon Sep 17 00:00:00 2001 From: Sam Doshi Date: Wed, 15 Feb 2017 14:45:11 +0000 Subject: [PATCH 20/28] export BinarySpacePartition type --- XMonad/Layout/BinarySpacePartition.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/XMonad/Layout/BinarySpacePartition.hs b/XMonad/Layout/BinarySpacePartition.hs index 206e13a7..1fb17bec 100644 --- a/XMonad/Layout/BinarySpacePartition.hs +++ b/XMonad/Layout/BinarySpacePartition.hs @@ -20,6 +20,7 @@ module XMonad.Layout.BinarySpacePartition ( -- * Usage -- $usage emptyBSP + , BinarySpacePartition , Rotate(..) , Swap(..) , ResizeDirectional(..) From 025433c6582553aa60a14ba4e9a1bff27402f975 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 15 Feb 2017 09:36:35 -0700 Subject: [PATCH 21/28] X.U.WindowProperties: Added the ability to test if a window has a tag from `X.A.TagWindows` New data constructor `Tagged` that uses `hasTag` from `X.A.TagWindows`. This is great for building layouts based off of window tags. --- CHANGES.md | 9 +++++++++ XMonad/Util/WindowProperties.hs | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 942b1c66..8c4f28a5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,14 @@ # Change Log / Release Notes +## 0.14 (Not Yet) + +### Bug Fixes and Minor Changes + + * `XMonad.Util.WindowProperties` + + - Added the ability to test if a window has a tag from + `XMonad.Actions.TagWindows` + ## 0.13 (February 10, 2017) ### Breaking Changes diff --git a/XMonad/Util/WindowProperties.hs b/XMonad/Util/WindowProperties.hs index d4fe517c..be881e35 100644 --- a/XMonad/Util/WindowProperties.hs +++ b/XMonad/Util/WindowProperties.hs @@ -21,10 +21,12 @@ module XMonad.Util.WindowProperties ( -- $helpers getProp32, getProp32s) where -import XMonad -import qualified XMonad.StackSet as W -import Foreign.C.Types (CLong) + import Control.Monad +import Foreign.C.Types (CLong) +import XMonad +import XMonad.Actions.TagWindows (hasTag) +import qualified XMonad.StackSet as W -- $edsl -- Allows to specify window properties, such as title, classname or @@ -43,6 +45,7 @@ data Property = Title String | Or Property Property | Not Property | Const Bool + | Tagged String -- ^ Tagged via 'XMonad.Actions.TagWindows' deriving (Read, Show) infixr 9 `And` infixr 8 `Or` @@ -78,6 +81,7 @@ propertyToQuery (And p1 p2) = propertyToQuery p1 <&&> propertyToQuery p2 propertyToQuery (Or p1 p2) = propertyToQuery p1 <||> propertyToQuery p2 propertyToQuery (Not p) = not `fmap` propertyToQuery p propertyToQuery (Const b) = return b +propertyToQuery (Tagged s) = ask >>= \w -> liftX (hasTag s w) -- $helpers From b1dee9b0b4cc51896b07d36fb7e186bf426ec3b3 Mon Sep 17 00:00:00 2001 From: Sam Doshi Date: Thu, 16 Feb 2017 19:12:57 +0000 Subject: [PATCH 22/28] allow border colour to be specified in GSConfig --- CHANGES.md | 6 ++++++ XMonad/Actions/GridSelect.hs | 17 ++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8c4f28a5..21d154e1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,12 @@ ## 0.14 (Not Yet) +### Breaking Changes + + * `XMonad.Actions.GridSelect` + + - Added field `gs_bordercolor` to `GSConfig` to specify border color. + ### Bug Fixes and Minor Changes * `XMonad.Util.WindowProperties` diff --git a/XMonad/Actions/GridSelect.hs b/XMonad/Actions/GridSelect.hs index 0760dbd5..5d3c6e90 100644 --- a/XMonad/Actions/GridSelect.hs +++ b/XMonad/Actions/GridSelect.hs @@ -205,7 +205,8 @@ data GSConfig a = GSConfig { gs_navigate :: TwoD a (Maybe a), gs_rearranger :: Rearranger a, gs_originFractX :: Double, - gs_originFractY :: Double + gs_originFractY :: Double, + gs_bordercolor :: String } -- | That is 'fromClassName' if you are selecting a 'Window', or @@ -322,15 +323,15 @@ diamondRestrict x y originX originY = findInElementMap :: (Eq a) => a -> [(a, b)] -> Maybe (a, b) findInElementMap pos = find ((== pos) . fst) -drawWinBox :: Window -> XMonadFont -> (String, String) -> Integer -> Integer -> String -> Integer -> Integer -> Integer -> X () -drawWinBox win font (fg,bg) ch cw text x y cp = +drawWinBox :: Window -> XMonadFont -> (String, String) -> String -> Integer -> Integer -> String -> Integer -> Integer -> Integer -> X () +drawWinBox win font (fg,bg) bc ch cw text x y cp = withDisplay $ \dpy -> do gc <- liftIO $ createGC dpy win bordergc <- liftIO $ createGC dpy win liftIO $ do Just fgcolor <- initColor dpy fg Just bgcolor <- initColor dpy bg - Just bordercolor <- initColor dpy borderColor + Just bordercolor <- initColor dpy bc setForeground dpy gc fgcolor setBackground dpy gc bgcolor setForeground dpy bordergc bordercolor @@ -378,6 +379,7 @@ updateElementsWithColorizer colorizer elementmap = do colors <- colorizer element (pos == curpos) drawWinBox win font colors + (gs_bordercolor gsconfig) cellheight cellwidth text @@ -390,7 +392,7 @@ stdHandle :: Event -> TwoD a (Maybe a) -> TwoD a (Maybe a) stdHandle (ButtonEvent { ev_event_type = t, ev_x = x, ev_y = y }) contEventloop | t == buttonRelease = do s @ TwoDState { td_paneX = px, td_paneY = py, - td_gsconfig = (GSConfig ch cw _ _ _ _ _ _ _) } <- get + td_gsconfig = (GSConfig ch cw _ _ _ _ _ _ _ _) } <- get let gridX = (fi x - (px - cw) `div` 2) `div` cw gridY = (fi y - (py - ch) `div` 2) `div` ch case lookup (gridX,gridY) (td_elementmap s) of @@ -714,10 +716,7 @@ decorateName' w = do -- | Builds a default gs config from a colorizer function. buildDefaultGSConfig :: (a -> Bool -> X (String,String)) -> GSConfig a -buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultNavigation noRearranger (1/2) (1/2) - -borderColor :: String -borderColor = "white" +buildDefaultGSConfig col = GSConfig 50 130 10 col "xft:Sans-8" defaultNavigation noRearranger (1/2) (1/2) "white" -- | Brings selected window to the current workspace. bringSelected :: GSConfig Window -> X () From a79a116934ce64e01c727d8397f325ad546ccf54 Mon Sep 17 00:00:00 2001 From: Sam Doshi Date: Sat, 18 Feb 2017 13:46:30 +0000 Subject: [PATCH 23/28] improve the vertical centring in X.A.GridSelect --- CHANGES.md | 4 ++++ XMonad/Actions/GridSelect.hs | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 21d154e1..b7232834 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,10 @@ ### Bug Fixes and Minor Changes + * `XMonad.Actions.GridSelect` + + - The vertical centring of text in each cell has been improved. + * `XMonad.Util.WindowProperties` - Added the ability to test if a window has a tag from diff --git a/XMonad/Actions/GridSelect.hs b/XMonad/Actions/GridSelect.hs index 5d3c6e90..90eef16f 100644 --- a/XMonad/Actions/GridSelect.hs +++ b/XMonad/Actions/GridSelect.hs @@ -341,7 +341,10 @@ drawWinBox win font (fg,bg) bc ch cw text x y cp = (\n -> do size <- liftIO $ textWidthXMF dpy font n return $ size > (fromInteger (cw-(2*cp)))) text - printStringXMF dpy win font gc bg fg (fromInteger (x+cp)) (fromInteger (y+(div ch 2))) stext + -- calculate the offset to vertically centre the text based on the ascender and descender + (asc,desc) <- liftIO $ textExtentsXMF font stext + let offset = ((ch - fromIntegral (asc + desc)) `div` 2) + fromIntegral asc + printStringXMF dpy win font gc bg fg (fromInteger (x+cp)) (fromInteger (y+offset)) stext liftIO $ freeGC dpy gc liftIO $ freeGC dpy bordergc From a372b455dc9adf25447fb0d6abe907d6a92dab70 Mon Sep 17 00:00:00 2001 From: geekosaur Date: Sat, 18 Feb 2017 17:19:59 -0500 Subject: [PATCH 24/28] typo in navigation2DP example The example code in the documentation uses `navigation2D` instead of `navigation2DP`, evidently a simple copy/paste error. No actual code change. --- XMonad/Actions/Navigation2D.hs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/XMonad/Actions/Navigation2D.hs b/XMonad/Actions/Navigation2D.hs index 42b3a53f..fa2646a7 100644 --- a/XMonad/Actions/Navigation2D.hs +++ b/XMonad/Actions/Navigation2D.hs @@ -96,11 +96,11 @@ import XMonad.Util.Types -- -- Alternatively, you can use navigation2DP: -- --- > main = xmonad $ navigation2D def --- > ("", "", "", "") --- > [("M-", windowGo ), --- > ("M-S-", windowSwap)] --- > False +-- > main = xmonad $ navigation2DP def +-- > ("", "", "", "") +-- > [("M-", windowGo ), +-- > ("M-S-", windowSwap)] +-- > False -- > $ def -- -- That's it. If instead you'd like more control, you can combine From 4c00eb58486f445addd78518f37c101efc13c574 Mon Sep 17 00:00:00 2001 From: Brent Yorgey Date: Sun, 19 Feb 2017 20:45:43 -0600 Subject: [PATCH 25/28] fix ThreeColMid window shuffling Fixes #137. --- XMonad/Layout/ThreeColumns.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/XMonad/Layout/ThreeColumns.hs b/XMonad/Layout/ThreeColumns.hs index 0a353f95..458f37a0 100644 --- a/XMonad/Layout/ThreeColumns.hs +++ b/XMonad/Layout/ThreeColumns.hs @@ -97,8 +97,8 @@ split3HorizontallyBy :: Bool -> Rational -> Rectangle -> (Rectangle, Rectangle, split3HorizontallyBy middle f (Rectangle sx sy sw sh) = if middle then ( Rectangle (sx + fromIntegral r3w) sy r1w sh - , Rectangle (sx + fromIntegral r3w + fromIntegral r1w) sy r2w sh - , Rectangle sx sy r3w sh ) + , Rectangle sx sy r3w sh + , Rectangle (sx + fromIntegral r3w + fromIntegral r1w) sy r2w sh ) else ( Rectangle sx sy r1w sh , Rectangle (sx + fromIntegral r1w) sy r2w sh , Rectangle (sx + fromIntegral r1w + fromIntegral r2w) sy r3w sh ) From 1b96c646c1b36ac2f996d80f9e9c8a10297ff821 Mon Sep 17 00:00:00 2001 From: Mitchell Rosen Date: Sat, 25 Feb 2017 09:55:31 -0500 Subject: [PATCH 26/28] Respect number of master windows in Magnify layout --- CHANGES.md | 4 +++ XMonad/Layout/Magnifier.hs | 54 ++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b7232834..1088807c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,10 @@ - Added the ability to test if a window has a tag from `XMonad.Actions.TagWindows` + * `XMonad.Layout.Magnifier` + + - Handle `IncMasterN` messages. + ## 0.13 (February 10, 2017) ### Breaking Changes diff --git a/XMonad/Layout/Magnifier.hs b/XMonad/Layout/Magnifier.hs index 90a577bd..910341cf 100644 --- a/XMonad/Layout/Magnifier.hs +++ b/XMonad/Layout/Magnifier.hs @@ -83,63 +83,65 @@ import XMonad.Util.XUtils -- | Increase the size of the window that has focus magnifier :: l a -> ModifiedLayout Magnifier l a -magnifier = ModifiedLayout (Mag (1.5,1.5) On All) +magnifier = ModifiedLayout (Mag 1 (1.5,1.5) On All) -- | Change the size of the window that has focus by a custom zoom magnifiercz :: Rational -> l a -> ModifiedLayout Magnifier l a -magnifiercz cz = ModifiedLayout (Mag (fromRational cz, fromRational cz) On All) +magnifiercz cz = ModifiedLayout (Mag 1 (fromRational cz, fromRational cz) On All) --- | Increase the size of the window that has focus, unless if it is the --- master window. +-- | Increase the size of the window that has focus, unless if it is one of the +-- master windows. magnifier' :: l a -> ModifiedLayout Magnifier l a -magnifier' = ModifiedLayout (Mag (1.5,1.5) On NoMaster) +magnifier' = ModifiedLayout (Mag 1 (1.5,1.5) On NoMaster) -- | Magnifier that defaults to Off magnifierOff :: l a -> ModifiedLayout Magnifier l a -magnifierOff = ModifiedLayout (Mag (1.5,1.5) Off All) +magnifierOff = ModifiedLayout (Mag 1 (1.5,1.5) Off All) -- | Increase the size of the window that has focus by a custom zoom, --- unless if it is the master window. +-- unless if it is one of the the master windows. magnifiercz' :: Rational -> l a -> ModifiedLayout Magnifier l a -magnifiercz' cz = ModifiedLayout (Mag (fromRational cz, fromRational cz) On NoMaster) +magnifiercz' cz = ModifiedLayout (Mag 1 (fromRational cz, fromRational cz) On NoMaster) -- | A magnifier that greatly magnifies just the vertical direction maximizeVertical :: l a -> ModifiedLayout Magnifier l a -maximizeVertical = ModifiedLayout (Mag (1,1000) Off All) +maximizeVertical = ModifiedLayout (Mag 1 (1,1000) Off All) data MagnifyMsg = MagnifyMore | MagnifyLess | ToggleOn | ToggleOff | Toggle deriving ( Typeable ) instance Message MagnifyMsg -data Magnifier a = Mag (Double,Double) Toggle MagnifyMaster deriving (Read, Show) +data Magnifier a = Mag !Int (Double,Double) Toggle MagnifyMaster deriving (Read, Show) data Toggle = On | Off deriving (Read, Show) data MagnifyMaster = All | NoMaster deriving (Read, Show) instance LayoutModifier Magnifier Window where - redoLayout (Mag z On All ) r (Just s) wrs = applyMagnifier z r s wrs - redoLayout (Mag z On NoMaster) r (Just s) wrs = unlessMaster (applyMagnifier z) r s wrs + redoLayout (Mag _ z On All ) r (Just s) wrs = applyMagnifier z r s wrs + redoLayout (Mag n z On NoMaster) r (Just s) wrs = unlessMaster n (applyMagnifier z) r s wrs redoLayout _ _ _ wrs = return (wrs, Nothing) - handleMess (Mag z On t) m - | Just MagnifyMore <- fromMessage m = return . Just $ (Mag (z `addto` 0.1 ) On t) - | Just MagnifyLess <- fromMessage m = return . Just $ (Mag (z `addto` (-0.1)) On t) - | Just ToggleOff <- fromMessage m = return . Just $ (Mag (z ) Off t) - | Just Toggle <- fromMessage m = return . Just $ (Mag (z ) Off t) + handleMess (Mag n z On t) m + | Just MagnifyMore <- fromMessage m = return . Just $ Mag n (z `addto` 0.1 ) On t + | Just MagnifyLess <- fromMessage m = return . Just $ Mag n (z `addto` (-0.1)) On t + | Just ToggleOff <- fromMessage m = return . Just $ Mag n z Off t + | Just Toggle <- fromMessage m = return . Just $ Mag n z Off t + | Just (IncMasterN d) <- fromMessage m = return . Just $ Mag (max 0 (n+d)) z On t where addto (x,y) i = (x+i,y+i) - handleMess (Mag z Off t) m - | Just ToggleOn <- fromMessage m = return . Just $ (Mag z On t) - | Just Toggle <- fromMessage m = return . Just $ (Mag z On t) + handleMess (Mag n z Off t) m + | Just ToggleOn <- fromMessage m = return . Just $ Mag n z On t + | Just Toggle <- fromMessage m = return . Just $ Mag n z On t + | Just (IncMasterN d) <- fromMessage m = return . Just $ Mag (max 0 (n+d)) z Off t handleMess _ _ = return Nothing - modifierDescription (Mag _ On All ) = "Magnifier" - modifierDescription (Mag _ On NoMaster) = "Magnifier NoMaster" - modifierDescription (Mag _ Off _ ) = "Magnifier (off)" + modifierDescription (Mag _ _ On All ) = "Magnifier" + modifierDescription (Mag _ _ On NoMaster) = "Magnifier NoMaster" + modifierDescription (Mag _ _ Off _ ) = "Magnifier (off)" type NewLayout a = Rectangle -> Stack a -> [(Window, Rectangle)] -> X ([(Window, Rectangle)], Maybe (Magnifier a)) -unlessMaster :: NewLayout a -> NewLayout a -unlessMaster mainmod r s wrs = if null (up s) then return (wrs, Nothing) - else mainmod r s wrs +unlessMaster :: Int -> NewLayout a -> NewLayout a +unlessMaster n mainmod r s wrs = if null (drop (n-1) (up s)) then return (wrs, Nothing) + else mainmod r s wrs applyMagnifier :: (Double,Double) -> Rectangle -> t -> [(Window, Rectangle)] -> X ([(Window, Rectangle)], Maybe a) From 057af44998f5d5d44ca0fc725f35cc01fec13181 Mon Sep 17 00:00:00 2001 From: Brent Yorgey Date: Sun, 26 Mar 2017 22:02:48 -0500 Subject: [PATCH 27/28] X.U.EZConfig: include Latin1 keys --- XMonad/Util/EZConfig.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/XMonad/Util/EZConfig.hs b/XMonad/Util/EZConfig.hs index 841b8786..fdf89901 100644 --- a/XMonad/Util/EZConfig.hs +++ b/XMonad/Util/EZConfig.hs @@ -427,7 +427,11 @@ parseKey = parseRegular +++ parseSpecial -- | Parse a regular key name (represented by itself). parseRegular :: ReadP KeySym parseRegular = choice [ char s >> return k - | (s,k) <- zip ['!'..'~'] [xK_exclam..xK_asciitilde] + | (s,k) <- zip ['!' .. '~' ] -- ASCII + [xK_exclam .. xK_asciitilde] + + ++ zip ['\xa0' .. '\xff' ] -- Latin1 + [xK_nobreakspace .. xK_ydiaeresis] ] -- | Parse a special key name (one enclosed in angle brackets). From 4ba56ee388500e8468aa778c113e9c666ef1bf65 Mon Sep 17 00:00:00 2001 From: Brent Yorgey Date: Sun, 26 Mar 2017 22:06:05 -0500 Subject: [PATCH 28/28] update CHANGES for EZConfig Latin1 changes --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1088807c..b23e07b2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,11 @@ - Handle `IncMasterN` messages. + * `XMonad.Util.EZConfig` + + - Can now parse Latin1 keys, to better accommodate users with + non-US keyboards. + ## 0.13 (February 10, 2017) ### Breaking Changes