diff options
41 files changed, 1130 insertions, 703 deletions
diff --git a/.drone.yml b/.woodpecker.yml index 4b6e816..f8aeae3 100644 --- a/.drone.yml +++ b/.woodpecker.yml @@ -1,9 +1,10 @@ matrix: GHC_VERSION: - - 9 + - 9.6 + - 9.4 - 8 -pipeline: +steps: test: image: haskell:${GHC_VERSION} commands: diff --git a/changelog.md b/changelog.md index b4f5009..6306c03 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,51 @@ +## Version 0.49 (unreleased) + +## Version 0.48 (April, 2024) + +- The `Kbd` monitor is now clickable (thanks, Enrico Maria) +- Fix zombie processes left by `<action>` tag and low battery action (thanks, + Ulrik) +- Fix plugins such as `Alsa` and `Com` not working when configuration is + recompiled (#657, ditto) +- New `Lock'` monitor with configurable labels (thanks, Enrico Maria) + +## Version 0.47.4 (March, 2024) + +- Bug fixes (launching processes from self-compiled instances) + +## Version 0.47.3 (February, 2024) + +- New flag `with_shared` to use xmobar with dynamic linking (see PR #690) +- Fix for actions invoked from recompiled xmobar instances (issue #688) +- Maximum base version bumped to 4.20 + +## Version 0.47.2 (November, 2023) + +- Compatibility with GHC 9.6 + +## Version 0.47.1 (September, 2023) + +- Allow compilation with libmpd even with GHC > 9.4, by requesting it + explicitly with `with_mpd`. See #667 for further details. + +## Version 0.47 (August, 2023) + +- Fix: center middle section for templates of the for }M{ +- Documentation fixes and improvements +- Better error handling in network connections +- Dependency fixes (libmpd excluded for GHC > 9.2) + +## Version 0.46 (January, 2023) + +- New bar position specifiers TopHM, BottomHM. +- New configuration option, `dpi`, to set the font scaling factor. +- Fixes and extensions for section alignment behaviour (#650, #655). +- Fix: honour fc/bg specs for icons (#663). + +## Version 0.45 (October, 2022) + +- New cairo/pango font drawing backend, substituting the direct X11/Xft one. + ## Version 0.44.2 (August, 2022) - Documentation improvements. diff --git a/doc/compiling.org b/doc/compiling.org index 4e0125e..977ef2b 100644 --- a/doc/compiling.org +++ b/doc/compiling.org @@ -85,7 +85,9 @@ enters a high-CPU regime right after starting. - =with_xrender= Enables the main bar background alpha parameter. Requires - the [[http://hackage.haskell.org/package/X11-xft/][X11-xft]] package. + the [[http://hackage.haskell.org/package/X11-xft/][X11-xft]] package. The Xrender extension is not compatible with 10-bit + colour modes, i.e., setting ~DefaultDepth~ to 30 in your Xorg + configuration. See discussion in [[https://codeberg.org/xmobar/xmobar/issues/651][issue 651]] for details. - =with_xpm= Support for xpm image file format. This will allow loading .xpm files in =<icon>=. Requires the [[http://cgit.freedesktop.org/xorg/lib/libXpm][libXpm]] C library. diff --git a/doc/plugins.org b/doc/plugins.org index 2199659..ebe5a5b 100644 --- a/doc/plugins.org +++ b/doc/plugins.org @@ -16,11 +16,11 @@ to a certain monitor. All Monitors accept a common set of arguments, described below in - [[Default Monitor Arguments]]. Some monitors also accept additional + [[#default-arguments][Default Monitor Arguments]]. Some monitors also accept additional options that are specific to them. When specifying the list of arguments in your configuration, the common options come first, followed by =--=, followed by any monitor-specific options. For - example, the following [[=Battery Args RefreshRate=][Battery]] configuration first sets the global + example, the following [[#batteryp-dirs-args-refreshrate][Battery]] configuration first sets the global =template= and =Low= arguments and then specifies the battery-specific =off= option. @@ -60,6 +60,9 @@ brightness value. ** Default monitor arguments + :PROPERTIES: + :CUSTOM_ID: default-arguments + :END: These are the options available for all monitors: @@ -655,8 +658,9 @@ ** Keyboard and screen monitors *** =Kbd Opts= - - Registers to XKB/X11-Events and output the currently active keyboard - layout. Supports replacement of layout names. + - Registers to XKB/X11-Events, output the currently active keyboard + layout, and maps left and right clicks to switching to next and + previous layouts respectively. Supports replacement of layout names. - Aliases to =kbd= @@ -694,18 +698,37 @@ #+begin_src haskell Run Brightness ["-t", "<bar>"] 60 #+end_src + *** =Locks= - Displays the status of Caps Lock, Num Lock and Scroll Lock. - Aliases to =locks= + - Contructors: + + - =Locks= is nullary and uses the strings =CAPS=, =NUM=, =SCROLL= to signal + that a lock is enabled (and empty strings to signal it's disabled) + + - =Locks'= allow customizing the strings for the enabled/disabled states + of the 3 locks by accepting an assoc list of type =[(String, (String, String))]=, + which is expected to contain exactly 3 elements with keys + ="CAPS"=, ="NUM"=, ="SCROLL"=. + - Example: #+begin_src haskell + -- using default labels Run Locks #+end_src + #+begin_src haskell + -- using custom labels + Run $ Locks' [("CAPS" , ("<fc=#00ff00>\xf023</fc>", "<fc=#777777>\xf09c</fc>") ) + ,("NUM" , ("<fc=#777777>\xf047</fc>", "<fc=#00ff00>\xf047</fc>" ) ) + ,("SCROLL", ("SlOCK", "" ))] + #+end_src + ** Load and Process monitors *** =Load Args RefreshRate= @@ -814,6 +837,9 @@ ** Volume monitors *** =Volume Mixer Element Args RefreshRate= + :PROPERTIES: + :CUSTOM_ID: volume + :END: - Aliases to the mixer name and element name separated by a colon. Thus, =Volume "default" "Master" [] 10= can be used as @@ -889,7 +915,7 @@ *** =Alsa Mixer Element Args= - Like [[=Volume Mixer Element Args RefreshRate=][Volume]] but with the following differences: + Like [[#volume][Volume]] but with the following differences: - Uses event-based refreshing via =alsactl monitor= instead of polling, so it will refresh instantly when there's a volume change, and won't @@ -1355,6 +1381,9 @@ (re)start xmobar outside xmonad. *** =UnsafeXMonadLog= + :PROPERTIES: + :CUSTOM_ID: UnsafeXMonadLog + :END: - Aliases to UnsafeXMonadLog - Displays any text received by xmobar on the =_XMONAD_LOG= atom. @@ -1385,7 +1414,7 @@ - Aliases to =PropName= - Reads the X property named by =PropName= (a string) and displays its - value. The [[../etc/xmonadpropwrite.hs][etc/xmonadpropwrite.hs script]] in xmobar's distribution can be + value. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmonadpropwrite.hs][etc/xmonadpropwrite.hs script]] in xmobar's distribution can be used to set the given property from the output of any other program or script. @@ -1421,7 +1450,7 @@ - Aliases to UnsafeStdinReader - Displays any text received by xmobar on its standard input. - - Similar to [[=UnsafeXMonadLog=][UnsafeXMonadLog]], in the sense that it does not strip any + - Similar to [[#UnsafeXMonadLog][UnsafeXMonadLog]], in the sense that it does not strip any actions from the received text, only using =stdin= and not a property atom of the root window. Please be equally carefully when using this as when using =UnsafeXMonadLog=! @@ -1480,7 +1509,7 @@ =/tmp/xmobar_status= will reveal xmonad for 1.5 seconds and temporarily overwrite the window titles. - - Take a look at [[../etc/status.sh][etc/status.sh]] + - Take a look at [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/status.sh][etc/status.sh]] - Expands environment variables for the pipe path diff --git a/doc/quick-start.org b/doc/quick-start.org index d711138..fecd953 100644 --- a/doc/quick-start.org +++ b/doc/quick-start.org @@ -1,12 +1,12 @@ #+title: Quick start: using xmobar -Xmobar can either be configured using the configuration language, or [[file:using-haskell.org][used as a +Xmobar can either be configured using the configuration language, or [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][used as a Haskell library]] (similar to xmonad) and compiled with your specific configuration. For an example of a configuration file using the plain -configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you can have a look at -[[../etc/xmobar.hs][etc/xmobar.hs]] for an example of how to write your own xmobar using Haskell. +configuration language, see [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.config][etc/xmobar.config]], and you can have a look at +[[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] for an example of how to write your own xmobar using Haskell. -* Command Line Options +* Command line options xmobar can be either configured with a configuration file or with command line options. In the second case, the command line options will @@ -20,7 +20,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you This is the list of command line options (the output of =xmobar --help=): - #+begin_src shell + #+begin_example Usage: xmobar [OPTION...] [FILE] Options: -h, -? --help This help @@ -38,187 +38,350 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you -o --top Place xmobar at the top of the screen -b --bottom Place xmobar at the bottom of the screen -d --dock Don't override redirect from WM and function as a dock - -a alignsep --alignsep=alignsep Separators for left, center and right text - alignment. Default: '}{' - -s char --sepchar=char Character used to separate commands in - the output template. Default '%' - -t template --template=template Output template - -c commands --commands=commands List of commands to be executed - -C command --add-command=command Add to the list of commands to be executed - -x screen --screen=screen On which X screen number to start - -p position --position=position Specify position of xmobar. Same syntax as in config file - -T [format] --text[=format] Write output to stdout - - Mail bug reports and suggestions to <mail@jao.io> - #+end_src -* Configuration Options + -a alignsep --alignsep=alignsep Separators for left, center and right text + alignment. Default: '}{' + -s char --sepchar=char Character used to separate commands in + the output template. Default '%' + -t template --template=template Output template + -c commands --commands=commands List of commands to be executed + -C command --add-command=command Add to the list of commands to be executed + -x screen --screen=screen On which X screen number to start + -p position --position=position Specify position of xmobar. Same syntax as in config file + -T [format] --text[=format] Write output to stdout + -D dpi --dpi=dpi The DPI scaling factor. Default 96.0 + + Mail bug reports and suggestions to <mail@jao.io> + #+end_example + +* Configuration options :PROPERTIES: :CUSTOM_ID: configuration-options :END: ** Global options - Here are all the global configuration options that you can set within - the =Config= block in your configuration. + Here are all the global options that you can set within the =Config= block in + your configuration and will define the overall behaviour and looks of your + bar. - - =font= Name of the font to be used. +*** Fonts + :PROPERTIES: + :CUSTOM_ID: fonts + :END: - - =additionalFonts= Haskell-style list of fonts to be used with the - =fn=-template. See also =textOffsets= below. For example: + The following configuration options control the fonts used by xmobar: - #+begin_src haskell - additionalFonts = [iconFont, altIconFont] - #+end_src + - =font= Name, as a string, of the default font to use. - - =bgColor= Background color. + - =additionalFonts= Haskell-style list of fonts to us with the + =fn=-template. See also =textOffsets= below. For example: - - =fgColor= Default font color. + #+begin_src haskell + additionalFonts = [iconFont, altIconFont] + #+end_src + + - =dpi= The DPI scaling factor, as a decimal, to use. If 0, negative, or not + given, the default of 96 will be used, which corresponds to an average + screen. A 10pt font will therefore scale to 10pt * (1/72 pt/inch) * (96 + pixel/inch) = 13.3 pixel. This is especially useful for HiDPI displays. + + The global font is used by default when none of the others is specified + using the ~<fn=n>...</fn>~ markup, with ~n~ a 1-based index in the + ~additionalFonts~ array. So, for instance + + #+begin_src + <fn=2>some text</fn> + #+end_src - - =alpha= The transparency. 0 is transparent, 255 is opaque. + will use, in the configuration above, ~altIconFont~ to display "some text". - - =position= Top, TopH, TopP, TopW, TopSize, Bottom, BottomH, - BottomP, BottomW, BottomSize or Static (with x, y, width and height). + Font names use the [[https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html][Pango format]]. Here are a few simple examples: - TopP and BottomP take 2 arguments: left padding and right padding. + #+begin_example + DejaVu Sans Mono 10 - TopW and BottomW take 2 arguments: an alignment parameter (L for left, - C for centered, R for Right) and an integer for the percentage width - xmobar window will have in respect to the screen width. + Iosevka Comfy Semi-Bold Italic 12 - TopSize and BottomSize take 3 arguments: an alignment parameter, an - integer for the percentage width, and an integer for the minimum pixel - height that the xmobar window will have. + Noto Color Emoji 10 + #+end_example - TopH and BottomH take one argument (Int) which adjusts the bar height. + We start with a family name (DejaVu Sans Mono, Iosevka Comfy, etc.), + followed by optional, space-separated /style options/ (Semi-Bold Italic in + the second example above), and ending with a size, in points. - For example: + There are many possible style options (if your font supports them). They + can be - #+begin_src haskell - position = TopH 30 - #+end_src + - *Plain styles*: Normal, Roman, Oblique, Italic. + - *Variants*: Small-Caps, All-Small-Caps, Petite-Caps, All-Petite-Caps, + Unicase, Title-Caps. + - *Weights*: Thin, Ultra-Light, Extra-Light, Light, Semi-Ligh, Demi-Light, + Book, Regular, Medium, Semi-Bold, Demi-Bold, Bold, Ultra-Bold, + Extra-Bold, Heavy, Black, Ultra-Black, Extra-Black. + - *Strectch values:* Thin, Ultra-Light, Extra-Light, Light, Semi-Light, + Demi-Light, Book, Regular, Medium, Semi-Bold, Demi-Bold, Bold, + Ultra-Bold, Extra-Bold, Heavy, Black, Ultra-Black, Extra-Black. + - *Gravity values*: Not-Rotated, South, Upside-Down, North, Rotated-Left, + East, Rotated-Right, West. - to make a 30 tall bar on the top, or + So you can add up to 5 style options per family: - #+begin_src haskell - position = BottomH 30 - #+end_src + #+begin_example + Monospace Italic All-Small-Caps Extra-Light Thin North 12 + #+end_example - to make a 30 tall bar on the bottom of the screen. + It's also possible to specify a list of fonts, separating them by commas, + so that they act as fallbacks when the preceding one is not able to display + a given glyph. A bit confusingly, the styles and sizes come in reverse + order after the families: - #+begin_src haskell - position = BottomW C 75 - #+end_src + #+begin_example + Family 1, Family 2 Styles 2 Size 2, Styles 1 Size 1 + #+end_example - to place xmobar at the bottom, centered with the 75% of the screen - width. Or + For instance you could have: - #+begin_src haskell - position = BottomP 120 0 - #+end_src + #+begin_example + Souce Code Pro, Noto Color Emoji Regular 12, Semi-Bold 10 + #+end_example - to place xmobar at the bottom, with 120 pixel indent of the left. Or + to use Source Code Pro Semi-Bold 10 when possible, and fall back to Noto + Color Emoji Regular 12 for characters that the former cannot display. - #+begin_src haskell - position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 } - #+end_src +**** X11 Bitmap fonts - or + If you want to use traditional, non-aliased X11 fonts, you can do so via + the [[https://www.cl.cam.ac.uk/~mgk25/ucs-fonts.html][Unicode fonts and tools for X11]] package, which provides bitmap + versions of them, with a specification of the stytle ~"Fixed 8"~ for what + in the old days would have been something like + ~-Misc-Fixed-Medium-R-Normal--13-120-75-75-C-70-ISO10646-1~. See also + discussion in [[https://codeberg.org/xmobar/xmobar/issues/658][issue #658]]. - #+begin_src haskell - position = Top - #+end_src +*** Colors - - =textOffset= The vertical offset, in pixels, for the text baseline. If - negative or not given, xmobar will try to center text vertically. + - =bgColor= Background color. - - =textOffsets= A list of vertical offsets, in pixels, for the text - baseline, to be used with the each of the fonts in =additionalFonts= - (if any). If negative or not given, xmobar will try to center text - vertically for that font. + - =fgColor= Default font color. - - =iconOffset= The vertical offset, in pixels, for icons bottom line. If - negative or not given, xmobar will try to center icons vertically. + - =alpha= The transparency. 0 is transparent, 255 is opaque. - - =lowerOnStart= When True the window is sent the bottom of the window - stack initially. +*** Vertical offsets - - =hideOnStart= When set to True the window is initially not mapped, - i.e. hidden. It then can be toggled manually (for example using the - dbus interface) or automatically (by a plugin) to make it reappear. + By default, all text and icons in the bar will be vertically centered + according to the configured height of the bar. You can override that + behaviour with the following options: - - =allDesktops= When set to True (the default), xmobar will tell the - window manager explicitly to be shown in all desktops, by setting - =_NET_WM_DESKTOP= to 0xffffffff. + - =textOffset= The vertical offset, in pixels, for the text baseline. If + negative or not given, xmobar will try to center text vertically. - - =overrideRedirect= If you're running xmobar in a tiling window - manager, you might need to set this option to =False= so that it - behaves as a docked application. Defaults to =True=. + - =textOffsets= A list of vertical offsets, in pixels, for the text + baseline, to be used with the each of the fonts in =additionalFonts= + (if any). If negative or not given, xmobar will try to center text + vertically for that font. - - =pickBroadest= When multiple displays are available, xmobar will - choose by default the first one to place itself. With this flag set to - =True= (the default is =False=) it will choose the broadest one - instead. + - =iconOffset= The vertical offset, in pixels, for icons bottom line. If + negative or not given, xmobar will try to center icons vertically. - - =persistent= When True the window status is fixed i.e. hiding or - revealing is not possible. This option can be toggled at runtime. - Defaults to False. +*** Borders + + - =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder + (default). + + TopB, BottomB, FullB take no arguments, and request drawing a border + at the top, bottom or around xmobar's window, respectively. + + TopBM, BottomBM, FullBM take an integer argument, which is the margin, + in pixels, between the border of the window and the drawn border. + + - =borderColor= Border color. + + - =borderWidth= Border width in pixels. + + - =iconRoot= Root folder where icons are stored. For =<icon=path/>= if + path start with =/=, =./= or =../= it is interpreted as it is. + Otherwise it will have + + #+begin_src haskell + iconRoot ++ "/" + #+end_src - - =border= TopB, TopBM, BottomB, BottomBM, FullB, FullBM or NoBorder - (default). + prepended to it. Default is =.=. - TopB, BottomB, FullB take no arguments, and request drawing a border - at the top, bottom or around xmobar's window, respectively. +*** Bar position - TopBM, BottomBM, FullBM take an integer argument, which is the margin, - in pixels, between the border of the window and the drawn border. + - =position= Top, TopH, TopHM, TopP, TopW, TopSize, Bottom, BottomH, BottomHM, + BottomP, BottomW, BottomSize or Static (with x, y, width and height). - - =borderColor= Border color. + TopP and BottomP take 2 arguments: left padding and right padding. - - =borderWidth= Border width in pixels. + TopW and BottomW take 2 arguments: an alignment parameter (L for left, + C for centered, R for Right) and an integer for the percentage width + xmobar window will have in respect to the screen width. - - =iconRoot= Root folder where icons are stored. For =<icon=path/>= if - path start with =/=, =./= or =../= it is interpreted as it is. - Otherwise it will have + TopSize and BottomSize take 3 arguments: an alignment parameter, an + integer for the percentage width, and an integer for the minimum pixel + height that the xmobar window will have. - #+begin_src haskell - iconRoot ++ "/" - #+end_src + TopH and BottomH take one argument (Int) which adjusts the bar height. - prepended to it. Default is =.=. + For example: - - =commands= For setting the options of the programs to run (optional). + #+begin_src haskell + position = TopH 30 + #+end_src + + to make a 30 tall bar on the top, or + + #+begin_src haskell + position = BottomH 30 + #+end_src + + to make a 30 tall bar on the bottom of the screen. The corresponding + variants ~TopHM~ and ~BottomHM~ allow you to specify, in addition to a + height, margins (in pixels) with the borders of the screen (left, right + top and bottom); so they take five integers as arguments. For instance, + if you one a margin of 2 pixels to the left of the top bar in the above + example and 4 to its right and top, you could use: + + #+begin_src haskell + position = TopHM 30 2 4 4 0 + #+end_src + + and similarly for ~BottomHM~. + + #+begin_src haskell + position = BottomW C 75 + #+end_src + + to place xmobar at the bottom, centered with the 75% of the screen + width. Or + + #+begin_src haskell + position = BottomP 120 0 + #+end_src + + to place xmobar at the bottom, with 120 pixel indent of the left. Or + + #+begin_src haskell + position = Static { xpos = 0 , ypos = 0, width = 1024, height = 15 } + #+end_src - - =sepChar= The character to be used for indicating commands in the - output template (default '%'). + or + + #+begin_src haskell + position = Top + #+end_src + + - =lowerOnStart= When True the window is sent the bottom of the window + stack initially. + + - =hideOnStart= When set to True the window is initially not mapped, + i.e. hidden. It then can be toggled manually (for example using the + dbus interface) or automatically (by a plugin) to make it reappear. + + - =allDesktops= When set to True (the default), xmobar will tell the + window manager explicitly to be shown in all desktops, by setting + =_NET_WM_DESKTOP= to 0xffffffff. + + - =overrideRedirect= If you're running xmobar in a tiling window + manager, you might need to set this option to =False= so that it + behaves as a docked application. Defaults to =True=. + + - =pickBroadest= When multiple displays are available, xmobar will + choose by default the first one to place itself. With this flag set to + =True= (the default is =False=) it will choose the broadest one + instead. + + - =persistent= When True the window status is fixed i.e. hiding or + revealing is not possible. This option can be toggled at runtime. + Defaults to False. + + - =wmClass= The value for the window's X11 ~WM_CLASS~ property. Defaults + to "xmobar". + + - =wmName= The value for the window's X11 ~WM_NAME~ property. Defaults to + "xmobar". + +*** Text output + + - =textOutput= When True, instead of running as an X11 application, + write output to stdout, with optional color escape sequences. In + this mode, icon and action specifications are ignored. Default is + False. + + - =textOutputFormat= Plain, Ansi or Pango, to emit, when in text + mode, escape color sequences using ANSI controls (for terminals) or + pango markup. Default is Plain. + +*** Commands and monitors + + - =commands= The list of monitors and plugins to run, together with their + individual configurations. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugin documentation]] details all the + available monitors, and you can also create new ones using Haskell. See + the [[#commands-list][commands list section]] below for more. + + - =sepChar= The character to be used for indicating commands in the + output template (defaults to '%'). + + - =alignSep= a 2-character string for aligning text in the output + template. See [[#bar-sections][this section]] for details. + + - =template= The output template: a string telling xmobar how to display the + outputs of all the =commands= above. See [[#output-template][the next section]] for a full + description. + +** The =commands= list + :PROPERTIES: + :CUSTOM_ID: commands-list + :END: + + The =commands= configuration option is a list of commands information + and arguments to be used by xmobar when parsing the output template. + Each member of the list consists in a command prefixed by the =Run= + keyword. Each command has arguments to control the way xmobar is going + to execute it. + + The options consist in a list of commands separated by a comma and enclosed + by square parenthesis. + + Example: + + #+begin_src haskell + [Run Memory ["-t","Mem: <usedratio>%"] 10, Run Swap [] 10] + #+end_src - - =alignSep= a 2 character string for aligning text in the output - template. The text before the first character will be align to left, - the text in between the 2 characters will be centered, and the text - after the second character will be align to the right. + to run the Memory monitor plugin with the specified template, and the + swap monitor plugin, with default options, every second. And here's an + example of a template for the commands above using an icon: - - =template= The output template. + #+begin_src haskell + template = "<icon=/home/jao/.xmobar/mem.xbm/><memory> <swap>" + #+end_src - - =wmClass= The value for the window's X11 ~WM_CLASS~ property. Defaults - to "xmobar". + This example will run "xclock" command when date is clicked: - - =wmName= The value for the window's X11 ~WM_NAME~ property. Defaults to - "xmobar". + #+begin_src haskell + template = "<action=`xclock`>%date%</action>" + #+end_src - - =textOutput= When True, instead of running as an X11 application, - write output to stdout, with optional color escape sequences. In - this mode, icon and action specifications are ignored. Default is - False. + The only internal available command is =Com= (see below Executing + External Commands). All other commands are provided by plugins. xmobar + comes with some plugins, providing a set of system monitors, a standard + input reader, an Unix named pipe reader, a configurable date plugin, and + much more: we list all available plugins below. - - =textOutputFormat= Plain, Ansi or Pango, to emit, when in text - mode, escape color sequences using ANSI controls (for terminals) or - pango markup. Default is Plain. + Other commands can be created as plugins with the Plugin infrastructure. + See below. ** The output =template= + :PROPERTIES: + :CUSTOM_ID: output-template + :END: The output template is how xmobar will end up printing all of your configured commands. It must contain at least one command. Xmobar will parse the template and search for the command to be executed in the =commands= configuration option. First an =alias= will be searched (some plugins, such as =Weather= or =Network=, have default - aliases, see the [[./plugins.org][plugin documentation]]). After that, the command + aliases, see the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugin documentation]]). After that, the command name will be tried. If a command is found, the arguments specified in the =commands= list will be used. @@ -242,7 +405,8 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you opacity, with two additional hex digits (e.g. #FF00000aa). - =<fn=1>string</fn>= will print =string= with the first font from - =additionalFonts=. The index =0= corresponds to the standard font. + =additionalFonts=. The index =0= corresponds to the standard font. The + standard font is also used if the index is out of bounds. - =<hspace=X/>= will insert a blank horizontal space of =X= pixels. For example, to add a blank horizontal space of 123 pixels, @@ -284,6 +448,37 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you See the subsections below for more information on ~<box/>~, ~<icon/>~ and ~<action/>~. + - The special characters =}= and ={= are used to delimit up to three sections + in the bar that are drawn and aligned independently. See [[#bar-sections][this section]] + for more. + +*** Bar sections + :PROPERTIES: + :CUSTOM_ID: bar-sections + :END: + + You can use the special characters =}= and ={= are used to delimit up to three + sections in the bar, which are aligned and, if needed, overlapped + according to these rules: + + - If the template has the form =L}M{R=, with L, R, M arbitrary specs, the + monitors in =L= are drawn first, aligned to the left, then =R=, aligned to + the right, and finally =M= is drawn centered in the bar. =R= is trimmed to + the space left by =L=, and =M= is trimmed to the space left by =L= and =R=. As + a particular case, =}M{= will draw a single segment centered in the bar. + + - If the template has the form =L}{R=, =L= is drawn aligned to the left first + and then =R=, aligned to the right and trimmed if needed to fit in the + space left by =L=. + + - If the template has the form =}L{R=, =R= is drawn first, aligned to the + right, and then =L=, aligned to the left and trimmed to the space left by + =R=. + + When needed, sections are always trimmed on the right. The section + delimiters can be changed using the configuration option =alignSep,= a + two-character string. + *** Boxes around text - =<box>string</box>= will print string surrounded by a box in the @@ -319,7 +514,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you types, colors and widths are valid too, but margins and offsets are ignored. -*** Bitmap Icons +*** Bitmap icons It's possible to insert in the global templates icon directives of the form: @@ -344,7 +539,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you Icons are ignored when xmobar is run in text output mode. -*** Action Directives +*** Mouse actions It's also possible to use action directives of the form: @@ -359,46 +554,6 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you Actions work also when xmobar is run in text mode and used as the status command of swaybar. -** The =commands= configuration option - - The =commands= configuration option is a list of commands information - and arguments to be used by xmobar when parsing the output template. - Each member of the list consists in a command prefixed by the =Run= - keyword. Each command has arguments to control the way xmobar is going - to execute it. - - The option consists in a list of commands separated by a comma and - enclosed by square parenthesis. - - Example: - - #+begin_src haskell - [Run Memory ["-t","Mem: <usedratio>%"] 10, Run Swap [] 10] - #+end_src - - to run the Memory monitor plugin with the specified template, and the - swap monitor plugin, with default options, every second. And here's an - example of a template for the commands above using an icon: - - #+begin_src haskell - template = "<icon=/home/jao/.xmobar/mem.xbm/><memory> <swap>" - #+end_src - - This example will run "xclock" command when date is clicked: - - #+begin_src haskell - template = "<action=`xclock`>%date%</action>" - #+end_src - - The only internal available command is =Com= (see below Executing - External Commands). All other commands are provided by plugins. xmobar - comes with some plugins, providing a set of system monitors, a standard - input reader, an Unix named pipe reader, a configurable date plugin, and - much more: we list all available plugins below. - - Other commands can be created as plugins with the Plugin infrastructure. - See below. - * Runtime behaviour ** Running xmobar in text mode :PROPERTIES: @@ -430,7 +585,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you Other options are ~Ansi~, ~Pango~, and ~Swaybar~. ** Showing xmobar output in Emacs tab or mode line Using xmobar's ANSI color text ouput, one can plug it inside Emacs, and - display your monitors in the mode line or the tab bar. The [[../etc/xmobar.el][xmobar.el + display your monitors in the mode line or the tab bar. The [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.el][xmobar.el package]] provides a simple way of doing it. ** Using xmobar in wayland with swaybar or waybar :PROPERTIES: @@ -474,7 +629,7 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you dynamically xmobar's size and run it alongside a system tray widget such as trayer or stalonetray (although the idea is not limited to trays, really). For your convenience, there is a version of Jonas' script in - [[../etc/padding-icon.sh][etc/padding-icon.sh]]. + [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/padding-icon.sh][etc/padding-icon.sh]]. ** Signal handling @@ -484,10 +639,10 @@ configuration language, see [[../etc/xmobar.config][etc/xmobar.config]], and you - After receiving ~SIGUSR2~ xmobar repositions itself on the current screen. -* The DBus Interface +* The DBus interface When compiled with the optional =with_dbus= flag, xmobar can be controlled - over dbus. All signals defined in [[../src/Xmobar/System/Signal.hs][src/Signal.hs]] as =data SignalType= can now + over dbus. All signals defined in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/System/Signal.hs][src/Signal.hs]] as =data SignalType= can now be sent over dbus to xmobar. Due to current limitations of the implementation only one process of xmobar diff --git a/doc/using-haskell.org b/doc/using-haskell.org index 4020557..9fd3d88 100644 --- a/doc/using-haskell.org +++ b/doc/using-haskell.org @@ -26,7 +26,7 @@ config :: Config config = defaultConfig - { font = "xft:Terminus-8", + { font = "DejaVu Sans Mono 9", allDesktops = True, alpha = 200, commands = @@ -40,7 +40,7 @@ } main :: IO () - main = xmobar config + main = xmobar config -- or: configFromArgs config >>= xmobar #+end_src You can then for instance run =ghc --make xmobar.hs= to create a new xmobar @@ -49,6 +49,14 @@ system-wide xmobar, it will notice that you have your own implementation and (re)compile and run it as needed. +* Using dynamic linking + + Setting the =with_shared= flag, which is off by default, enables (re)building + of xmobar with shared libraries. By default, =xmobar= rebuilds itself with + static linking, as is the common practice with Haskell programs, but some + distributions use dynamic linking in their packages, or you might also be so + inclined. If so, this is your flag. + * Writing a plugin :PROPERTIES: :CUSTOM_ID: writing-a-plugin @@ -75,8 +83,8 @@ =run= can be used for simpler plugins. If you define only =run= the plugin will be run every second. To overwrite this default you just need to implement =rate=, which must return the number of tenth of seconds between - every successive runs. See [[../etc/xmobar.hs][etc/xmobar.hs]] for an example of a plugin - that runs just once, and [[../src/Xmobar/Plugins/Date.hs][src/Xmobar/Plugins/Date.hs]] for one that + every successive runs. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] for an example of a plugin + that runs just once, and [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Date.hs][src/Xmobar/Plugins/Date.hs]] for one that implements =rate=. Notice that Date could be implemented as: @@ -107,14 +115,14 @@ If your plugin only implements =alias= and =start=, then it is advisable to put it into the =Xmobar/Plugins/Monitors= directory and use one of the many - =run*= functions in [[../src/Xmobar/Plugins/Monitors/Common/Run.hs][Xmobar.Plugins.Monitors.Run]] in order to define - =start=. The =Exec= instance should then live in [[../src/Xmobar/Plugins/Monitors.hs][Xmobar.Plugins.Monitors]]. + =run*= functions in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Monitors/Common/Run.hs][Xmobar.Plugins.Monitors.Run]] in order to define + =start=. The =Exec= instance should then live in [[https://codeberg.org/xmobar/xmobar/src/branch/master/src/Xmobar/Plugins/Monitors.hs][Xmobar.Plugins.Monitors]]. * Using a plugin To use your new plugin, you just need to use a pure Haskell configuration for xmobar (as explained [[#xmobar-in-haskell][above]]) and load your definitions in your =xmobar.hs= - file. You can see an example in [[../etc/xmobar.hs][etc/xmobar.hs]] showing you how to write + file. You can see an example in [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.hs][etc/xmobar.hs]] showing you how to write a Haskell configuration that uses a new plugin, all in one file. When xmobar runs with the full path to that Haskell file as its argument @@ -26,9 +26,27 @@ output, in a variety of formats. [[file:doc/screenshots/xmobar-exwm.png]] -Check [[./changelog.md][the change log]] for our release history. We also have an IRC +Check [[https://codeberg.org/xmobar/xmobar/src/branch/master/changelog.md][the change log]] for our release history. We also have an IRC channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. +* Breaking news + + - Starting with version 0.47.1, we are excluding MPD from the extensions + included with ~all_extensions~ when GHC version is 9.4 or greater, because + that seems to break cabal compilation. However, it's been reported that + in some installations compilation with ~libmpd~ works fine: just add + explicitly the ~with_mpd~ flag to include MPD and check for yourself. + Compilation with stack has also been reported to work. Please see the + comments in issue #679 for details. + - Starting with version 0.45, we use cairo/pango as our drawing engine + (instead of plain X11/Xft). From a user's point of view, that change + should be mostly transparent, except for the facts that it's allowed + fixing quite a few bugs and that your /font names/ in your configuration, if + you used ~xft~ ones, might need to be adapted to Pango's syntax: please see + [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#fonts][this section of the documentation]] for all the details. If you're + compiling your own xmobar, there's a new dependency on libpango (see + [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#c-libraries][C library dependencies]]). + * Installation :PROPERTIES: :CUSTOM_ID: installation @@ -64,10 +82,15 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. emerge --ask xmobar #+end_src + - FreeBSD + #+begin_src shell + pkg install hs-xmobar + #+end_src + ** Using cabal or stack Xmobar is available from [[http://hackage.haskell.org/package/xmobar/][Hackage]], and you can compile and install it using - =cabal-install=, making sure the [[doc/compiling.org#c-libraries][required C libraries]] are in place. For a + =cabal-install=, making sure the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#c-libraries][required C libraries]] are in place. For a full build with all available extensions: #+begin_src shell @@ -82,10 +105,10 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. Starting with version 0.35.1, xmobar requires at least GHC version 8.4.x. to build. See [[https://codeberg.org/xmobar/xmobar/issues/461][this issue]] for more information. - See [[file:doc/compiling.org#optional-features][here]] for a list of optional compilation flags that will enable some + See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org#optional-features][here]] for a list of optional compilation flags that will enable some optional plugins. - See [[file:doc/compiling.org][compiling]] for full compilation instructions starting from source. + See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/compiling.org][compiling]] for full compilation instructions starting from source. * Running xmobar ** Running xmobar with a configuration file @@ -106,7 +129,7 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. or =~/.xmobarrc=. All the available command line switches and configuration parameters are - described in [[file:quick-start.org][the quick start guide]] and [[file:doc/plugins.org][the plugins index]]. + described in [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org][the quick start guide]] and [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][the plugins index]]. ** Writing your own xmobar in Haskell @@ -116,7 +139,7 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. Haskell instead of using a configuration file. (This is very similar to how [[http://xmonad.org][xmonad]] works.) That gives you the ability of using Haskell and its libraries to extend xmobar to your heart's content. If you are a - programmer, take a look [[file:doc/using-haskell.org][here]] to learn more. + programmer, take a look [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][here]] to learn more. ** Running xmobar in text mode @@ -124,63 +147,62 @@ channel, ~#xmobar~, at [[ircs://irc.libera.chat][Libera]]. it is possible to redirect xmobar's output to the standard output, optionally with color escape sequences. In this mode, xmobar can be run inside a terminal o console, or its output piped to other applications, and - there is no need for an X11 display. See [[./doc/quick-start.org#text-mode][Running xmobar in text mode]] for - details. Using this mode, you could [[file:doc/quick-start.org#wayland][pipe xmobar's output to, say, swaybar]], - and use it in wayland, or, with the [[./etc/xmobar.el][xmobar.el]] package, show it in Emacs's + there is no need for an X11 display. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#text-mode][Running xmobar in text mode]] for + details. Using this mode, you could [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org#wayland][pipe xmobar's output to, say, swaybar]], + and use it in wayland, or, with the [[https://codeberg.org/xmobar/xmobar/src/branch/master/etc/xmobar.el][xmobar.el]] package, show it in Emacs's tab bar. * Configuration and further documentation - If you want to jump straight into running xmobar, head over to the - [[./doc/quick-start.org][quick start guide]]. + [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/quick-start.org][quick start guide]]. - If you want to get a detailed overview of all available plugins and - monitors, visit the [[./doc/plugins.org][plugins index]]. + monitors, visit the [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/plugins.org][plugins index]]. - For more information on how to use xmobar as a Haskell library see the - [[file:doc/using-haskell.org][using Haskell guide]]. + [[https://codeberg.org/xmobar/xmobar/src/branch/master/doc/using-haskell.org][using Haskell guide]]. - If you want to know how to contribute to the xmobar project, check out - [[contributing.org][contributing]]. + [[https://codeberg.org/xmobar/xmobar/src/branch/master/contributing.org][contributing]]. * Authors and credits - Andrea Rossato originally designed and implemented xmobar up to - version 0.11.1. Since then, it is maintained and developed by [[https://jao.io][jao]], - with the help of the greater xmobar and Haskell communities. - - In particular, xmobar incorporates patches by Mohammed Alshiekh, - Alex Ameen, Axel Angel, Dhananjay Balan, Claudio Bley, Dragos Boca, - Ben Boeckel, Ivan Brennan, Duncan Burke, Roman Cheplyaka, Patrick - Chilton, Antoine Eiche, Nathaniel Wesley Filardo, Guy Gastineau, - John Goerzen, Patrick Günther, Reto Hablützel, Juraj Hercek, Tomáš - Janoušek, Ada Joule, Spencer Janssen, Roman Joost, Pavel Kalugin, - Jochen Keil, Sam Kirby, Lennart Kolmodin, Krzysztof Kosciuszkiewicz, - Dmitry Kurochkin, Todd Lunter, Vanessa McHale, Robert J. Macomber, - Dmitry Malikov, David McLean, Joan MIlev, Marcin Mikołajczyk, Dino - Morelli, Tony Morris, Eric Mrak, Thiago Negri, Edward O'Callaghan, - Svein Ove, Martin Perner, Jens Petersen, Alexander Polakov, Sibi - Prabakaran, Pavan Rikhi, Petr Rockai, Andrew Emmanuel Rosa, - Sackville-West, Amir Saeid, Markus Scherer, Daniel Schüssler, - Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter - Simons, Alexander Solovyov, Will Song, John Soo, John Soros, Felix - Springer, Travis Staton, Artem Tarasov, Samuli Thomasson, Edward - Tjörnhammar, Sergei Trofimovich, Thomas Tuegel, John Tyree, Jan - Vornberger, Anton Vorontsov, Daniel Wagner, Zev Weiss, Phil Xiaojun - Hu, Nikolay Yakimov, Edward Z. Yang, Leo Zhang, Norbert Zeh, and - Michał Zielonka. - - Andrea wants to thank Robert Manea and Spencer Janssen for their - help in understanding how X works. They gave him suggestions on how - to solve many problems with xmobar. He also thanks Claus Reinke for - making him understand existential types (or at least for letting him - think he grasps existential types...;-). + Andrea Rossato originally designed and implemented xmobar up to version + 0.11.1. Since then, it is maintained and developed by [[https://jao.io][jao]], with the help of + the greater xmobar and Haskell communities. + + In particular, xmobar incorporates patches by Kostas Agnantis, Mohammed + Alshiekh, Alex Ameen, Axel Angel, Enrico Maria De Angelis, Dhananjay Balan, + Claudio Bley, Dragos Boca, Ben Boeckel, Ivan Brennan, Duncan Burke, Roman + Cheplyaka, Patrick Chilton, Antoine Eiche, Nathaniel Wesley Filardo, Guy + Gastineau, John Goerzen, Jonathan Grochowski, Patrick Günther, Reto + Hablützel, Corey Halpin, Juraj Hercek, Jaroslaw Jantura, Tomáš Janoušek, Ada + Joule, Spencer Janssen, Roman Joost, Pavel Kalugin, Jochen Keil, Sam Kirby, + Lennart Kolmodin, Krzysztof Kosciuszkiewicz, Dmitry Kurochkin, Todd Lunter, + Vanessa McHale, Robert J. Macomber, Dmitry Malikov, David McLean, Ulrik de + Muelenaere, Joan Milev, Marcin Mikołajczyk, Dino Morelli, Tony Morris, Eric + Mrak, Thiago Negri, Edward O'Callaghan, Svein Ove, Martin Perner, Jens + Petersen, Alexander Polakov, Sibi Prabakaran, Pavan Rikhi, Petr Rockai, + Andrew Emmanuel Rosa, Sackville-West, Amir Saeid, Markus Scherer, Daniel + Schüssler, Olivier Schneider, Alexander Shabalin, Valentin Shirokov, Peter + Simons, Alexander Solovyov, Will Song, John Soo, John Soros, Felix Springer, + Travis Staton, Artem Tarasov, Samuli Thomasson, Edward Tjörnhammar, Sergei + Trofimovich, Thomas Tuegel, John Tyree, Jan Vornberger, Anton Vorontsov, + Daniel Wagner, Zev Weiss, Phil Xiaojun Hu, Nikolay Yakimov, Edward Z. Yang, + Leo Zhang, Norbert Zeh, and Michał Zielonka. + + Andrea wants to thank Robert Manea and Spencer Janssen for their help in + understanding how X works. They gave him suggestions on how to solve many + problems with xmobar. He also thanks Claus Reinke for making him understand + existential types (or at least for letting him think he grasps existential + types...;-). * License This software is released under a BSD-style license. See [[https://codeberg.org/xmobar/xmobar/src/branch/master/license][license]] for more details. - Copyright © 2010-2022 Jose Antonio Ortega Ruiz + Copyright © 2010-2024 Jose Antonio Ortega Ruiz Copyright © 2007-2010 Andrea Rossato diff --git a/src/Xmobar/App/Compile.hs b/src/Xmobar/App/Compile.hs index 80dbac7..5d1f48d 100644 --- a/src/Xmobar/App/Compile.hs +++ b/src/Xmobar/App/Compile.hs @@ -20,20 +20,17 @@ module Xmobar.App.Compile(recompile, trace, xmessage) where import Control.Monad.IO.Class -import Control.Monad.Fix (fix) -import Control.Exception.Extensible (try, bracket, SomeException(..)) +import Control.Exception.Extensible (bracket, SomeException(..)) import qualified Control.Exception.Extensible as E import Control.Monad (filterM, when) import Data.List ((\\)) -import Data.Maybe (isJust) import System.FilePath((</>), takeExtension) import System.IO import System.Directory import System.Process import System.Exit -import System.Posix.Process(executeFile, forkProcess, getAnyProcessStatus) +import System.Posix.Process(executeFile, forkProcess) import System.Posix.Types(ProcessID) -import System.Posix.Signals isExecutable :: FilePath -> IO Bool isExecutable f = @@ -144,14 +141,12 @@ recompile confDir dataDir execName force verb = liftIO $ do else shouldRecompile verb src bin lib if sc then do - uninstallSignalHandlers status <- bracket (openFile err WriteMode) hClose $ \errHandle -> waitForProcess =<< if useScript then runScript script bin confDir errHandle else runGHC bin confDir errHandle - installSignalHandlers if status == ExitSuccess then trace verb "Xmobar recompilation process exited with success!" else do @@ -168,24 +163,9 @@ recompile confDir dataDir execName force verb = liftIO $ do #ifdef RTSOPTS ++ ["-rtsopts", "-with-rtsopts", "-V0"] #endif +#ifdef SHARED_LIBRARIES + ++ ["-dynamic"] +#endif ++ ["-o", bin] runGHC bin = runProc "ghc" (opts bin) runScript script bin = runProc script [bin] - --- | Ignore SIGPIPE to avoid termination when a pipe is full, and SIGCHLD to --- avoid zombie processes, and clean up any extant zombie processes. -installSignalHandlers :: MonadIO m => m () -installSignalHandlers = liftIO $ do - installHandler openEndedPipe Ignore Nothing - installHandler sigCHLD Ignore Nothing - (try :: IO a -> IO (Either SomeException a)) - $ fix $ \more -> do - x <- getAnyProcessStatus False False - when (isJust x) more - return () - -uninstallSignalHandlers :: MonadIO m => m () -uninstallSignalHandlers = liftIO $ do - installHandler openEndedPipe Default Nothing - installHandler sigCHLD Default Nothing - return () diff --git a/src/Xmobar/App/Config.hs b/src/Xmobar/App/Config.hs index a284973..5c2f362 100644 --- a/src/Xmobar/App/Config.hs +++ b/src/Xmobar/App/Config.hs @@ -67,6 +67,7 @@ defaultConfig = , signal = SignalChan Nothing , textOutput = False , textOutputFormat = Plain + , dpi = 96.0 } -- | Return the path to the xmobar data directory. This directory is diff --git a/src/Xmobar/App/Opts.hs b/src/Xmobar/App/Opts.hs index 3a6b4e7..36da745 100644 --- a/src/Xmobar/App/Opts.hs +++ b/src/Xmobar/App/Opts.hs @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.Opts --- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2018, 2019, 2020, 2022, 2023, 2024 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -52,6 +52,7 @@ data Opts = Help | Position String | WmClass String | WmName String + | Dpi String deriving (Show, Eq) options :: [OptDescr Opts] @@ -95,6 +96,8 @@ options = "On which X screen number to start" , Option "p" ["position"] (ReqArg Position "position") "Specify position of xmobar. Same syntax as in config file" + , Option "D" ["dpi"] (ReqArg Dpi "dpi") + "The DPI scaling factor. Default 96.0" ] getOpts :: [String] -> IO ([Opts], [String]) @@ -113,7 +116,7 @@ usage = usageInfo header options ++ footer info :: String info = "xmobar " ++ showVersion version - ++ "\n (C) 2010 - 2022 Jose A Ortega Ruiz" + ++ "\n (C) 2010 - 2024 Jose A Ortega Ruiz" ++ "\n (C) 2007 - 2010 Andrea Rossato\n " ++ mail ++ "\n" ++ license ++ "\n" @@ -161,6 +164,7 @@ doOpts conf (o:oo) = Right x -> doOpts' (conf {commands = commands conf ++ x}) Left e -> putStr (e ++ usage) >> exitWith (ExitFailure 1) Position s -> readPosition s + Dpi d -> doOpts' (conf {dpi = read d}) where readCom c str = case readStr str of [x] -> Right x diff --git a/src/Xmobar/Config/Parse.hs b/src/Xmobar/Config/Parse.hs index 16af3db..0b41267 100644 --- a/src/Xmobar/Config/Parse.hs +++ b/src/Xmobar/Config/Parse.hs @@ -19,7 +19,8 @@ module Xmobar.Config.Parse(readConfig , parseConfig , indexedFont - , indexedOffset) where + , indexedOffset + , colorComponents) where import Text.ParserCombinators.Parsec import Text.ParserCombinators.Parsec.Number (int) @@ -31,6 +32,14 @@ import Xmobar.Config.Types import qualified System.IO as S (readFile) +-- | Splits a colors string into its two components +colorComponents :: Config -> String -> (String, String) +colorComponents conf c = + case break (==',') c of + (f,',':b) -> (f, b) + (f, _) -> (f, bgColor conf) + + stripComments :: String -> String stripComments = unlines . map (drop 5 . strip False . (replicate 5 ' '++)) . lines @@ -63,7 +72,7 @@ parseConfig defaultConfig = <|?> pAllDesktops <|?> pOverrideRedirect <|?> pPickBroadest <|?> pLowerOnStart <|?> pPersistent <|?> pIconRoot <|?> pCommands <|?> pSepChar <|?> pAlignSep <|?> pTemplate - <|?> pVerbose <|?> pSignal + <|?> pVerbose <|?> pSignal <|?> pDpi fields = [ "font", "additionalFonts", "bgColor", "fgColor" , "wmClass", "wmName", "sepChar" @@ -72,7 +81,7 @@ parseConfig defaultConfig = , "allDesktops", "overrideRedirect", "pickBroadest" , "hideOnStart", "lowerOnStart", "persistent", "iconRoot" , "alpha", "commands", "verbose", "signal", "textOutput" - , "textOutputFormat" + , "textOutputFormat", "dpi" ] pTextOutput = readField textOutput "textOutput" @@ -103,6 +112,7 @@ parseConfig defaultConfig = pIconRoot = readField iconRoot "iconRoot" pAlpha = readField alpha "alpha" pVerbose = readField verbose "verbose" + pDpi = readField dpi "dpi" pSignal = field signal "signal" $ fail "signal is meant for use with Xmobar as a library.\n It is not meant for use in the configuration file." diff --git a/src/Xmobar/Config/Template.hs b/src/Xmobar/Config/Template.hs new file mode 100644 index 0000000..ad30c3d --- /dev/null +++ b/src/Xmobar/Config/Template.hs @@ -0,0 +1,188 @@ +------------------------------------------------------------------------------ +-- | +-- Module: Xmobar.Config.Template +-- Copyright: (c) 2022 jao +-- License: BSD3-style (see LICENSE) +-- +-- Maintainer: mail@jao.io +-- Stability: unstable +-- Portability: portable +-- Created: Fri Sep 30, 2022 06:33 +-- +-- +-- Parsing template strings +-- +------------------------------------------------------------------------------ + + +module Xmobar.Config.Template (parseString) where + +import Data.Maybe (fromMaybe) +import qualified Control.Monad as CM + +import Text.Parsec ((<|>)) +import Text.Read (readMaybe) + +import qualified Text.Parsec as P +import qualified Text.Parsec.Combinator as C + +import Text.ParserCombinators.Parsec (Parser) + +import qualified Xmobar.Config.Types as T + +type Context = (T.TextRenderInfo, T.FontIndex, Maybe [T.Action]) + +retSegment :: Context -> T.Widget -> Parser [T.Segment] +retSegment (i, idx, as) widget = return [(widget, i, idx, as)] + +-- | Run the template string parser for the given config, producing a list of +-- drawable segment specifications. +parseString :: T.Config -> String -> [T.Segment] +parseString c s = + case P.parse (stringParser ci) "" s of + Left _ -> [(T.Text $ "Could not parse string: " ++ s, ti, 0, Nothing)] + Right x -> concat x + where ci = (ti , 0, Nothing) + ti = T.TextRenderInfo (T.fgColor c) 0 0 [] + +-- Top level parser reading the full template string +stringParser :: Context -> Parser [[T.Segment]] +stringParser c = C.manyTill (allParsers c) C.eof + +allParsers :: Context -> Parser [T.Segment] +allParsers c = C.choice (textParser c:map (\f -> P.try (f c)) parsers) + where parsers = [ iconParser, hspaceParser, rawParser, actionParser + , fontParser, boxParser, colorParser ] + +-- Wrapper for notFollowedBy that returns the result of the first parser. +-- Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy +-- accepts only parsers with return type Char. +notFollowedBy' :: Parser a -> Parser b -> Parser a +notFollowedBy' p e = do x <- p + C.notFollowedBy $ P.try (e >> return '*') + return x + +-- Parse a maximal string without markup +textParser :: Context -> Parser [T.Segment] +textParser c = + C.many1 (P.noneOf "<" <|> P.try (notFollowedBy' (P.char '<') suffixes)) + >>= retSegment c . T.Text + where suffixes = C.choice $ map (P.try . P.string) + [ "icon=" , "hspace=", "raw=" + , "action=", "/action>", "fn=", "/fn>" + , "box", "/box>", "fc=", "/fc>" ] + +-- Parse a "raw" tag, which we use to prevent other tags from creeping in. +-- The format here is net-string-esque: a literal "<raw=" followed by a string +-- of digits (base 10) denoting the length of the raw string, a literal ":" as +-- digit-string-terminator, the raw string itself, and then a literal "/>". +rawParser :: Context -> Parser [T.Segment] +rawParser c = do + P.string "<raw=" + lenstr <- C.many1 P.digit + P.char ':' + case reads lenstr of + [(len,[])] -> do + CM.guard ((len :: Integer) <= fromIntegral (maxBound :: Int)) + s <- C.count (fromIntegral len) P.anyChar + P.string "/>" + retSegment c (T.Text s) + _ -> CM.mzero + +iconParser :: Context -> Parser [T.Segment] +iconParser c = do + P.string "<icon=" + i <- C.manyTill (P.noneOf ">") (P.try (P.string "/>")) + retSegment c (T.Icon i) + +hspaceParser :: Context -> Parser [T.Segment] +hspaceParser c = do + P.string "<hspace=" + pVal <- C.manyTill P.digit (P.try (P.string "/>")) + retSegment c (T.Hspace (fromMaybe 0 $ readMaybe pVal)) + +actionParser :: Context -> Parser [T.Segment] +actionParser (ti, fi, act) = do + P.string "<action=" + command <- C.between (P.char '`') (P.char '`') (C.many1 (P.noneOf "`")) + <|> C.many1 (P.noneOf ">") + buttons <- (P.char '>' >> return "1") <|> (P.space >> P.spaces >> + C.between (P.string "button=") (P.string ">") (C.many1 (P.oneOf "12345"))) + let a = T.Spawn (toButtons buttons) command + a' = case act of + Nothing -> Just [a] + Just act' -> Just $ a : act' + s <- C.manyTill (allParsers (ti, fi, a')) (P.try $ P.string "</action>") + return (concat s) + +toButtons :: String -> [T.Button] +toButtons = map (\x -> read [x]) + +colorParser :: Context -> Parser [T.Segment] +colorParser (T.TextRenderInfo _ _ _ bs, fidx, a) = do + c <- C.between (P.string "<fc=") (P.string ">") (C.many1 colorc) + let colorParts = break (==':') c + let (ot,ob) = case break (==',') (drop 1 $ snd colorParts) of + (top,',':btm) -> (top, btm) + (top, _) -> (top, top) + tri = T.TextRenderInfo (fst colorParts) + (fromMaybe (-1) $ readMaybe ot) + (fromMaybe (-1) $ readMaybe ob) + bs + s <- C.manyTill (allParsers (tri, fidx, a)) (P.try $ P.string "</fc>") + return (concat s) + where colorc = P.alphaNum <|> P.oneOf ",:#" + +boxParser :: Context -> Parser [T.Segment] +boxParser (T.TextRenderInfo cs ot ob bs, f, a) = do + c <- C.between (P.string "<box") (P.string ">") + (C.option "" (C.many1 (P.alphaNum <|> P.oneOf "= #,"))) + let b = T.Box T.BBFull (T.BoxOffset T.C 0) 1 cs (T.BoxMargins 0 0 0 0) + let g = boxReader b (words c) + s <- C.manyTill + (allParsers (T.TextRenderInfo cs ot ob (g : bs), f, a)) + (P.try $ P.string "</box>") + return (concat s) + +boxReader :: T.Box -> [String] -> T.Box +boxReader b [] = b +boxReader b (x:xs) = boxReader (boxParamReader b param val) xs + where (param,val) = case break (=='=') x of + (p,'=':v) -> (p, v) + (p, _) -> (p, "") + +boxParamReader :: T.Box -> String -> String -> T.Box +boxParamReader b _ "" = b + +boxParamReader (T.Box bb off lw fc mgs) "type" val = + T.Box (fromMaybe bb $ readMaybe ("BB" ++ val)) off lw fc mgs + +boxParamReader (T.Box bb (T.BoxOffset alg off) lw fc mgs) "offset" (a:o) = + T.Box bb (T.BoxOffset align offset) lw fc mgs + where offset = fromMaybe off $ readMaybe o + align = fromMaybe alg $ readMaybe [a] + +boxParamReader (T.Box bb off lw fc mgs) "width" val = + T.Box bb off (fromMaybe lw $ readMaybe val) fc mgs + +boxParamReader (T.Box bb off lw _ mgs) "color" val = + T.Box bb off lw val mgs + +boxParamReader (T.Box bb off lw fc mgs@(T.BoxMargins mt mr mb ml)) ('m':pos) v = + let mgs' = case pos of + "t" -> T.BoxMargins (maybeVal mt) mr mb ml + "r" -> T.BoxMargins mt (maybeVal mr) mb ml + "b" -> T.BoxMargins mt mr (maybeVal mb) ml + "l" -> T.BoxMargins mt mr mb (maybeVal ml) + _ -> mgs + maybeVal d = fromMaybe d (readMaybe v) + in T.Box bb off lw fc mgs' + +boxParamReader b _ _ = b + +fontParser :: Context -> Parser [T.Segment] +fontParser (i, _, a) = do + f <- C.between (P.string "<fn=") (P.string ">") (C.many1 P.digit) + s <- C.manyTill (allParsers (i, fromMaybe 0 $ readMaybe f, a)) + (P.try $ P.string "</fn>") + return (concat s) diff --git a/src/Xmobar/Config/Types.hs b/src/Xmobar/Config/Types.hs index 4959aa1..785b55b 100644 --- a/src/Xmobar/Config/Types.hs +++ b/src/Xmobar/Config/Types.hs @@ -15,14 +15,28 @@ module Xmobar.Config.Types ( Config (..) , XPosition (..), Align (..), Border (..), TextOutputFormat (..) + , Segment , FontIndex + , Box(..) + , BoxBorder(..) + , BoxOffset(..) + , BoxMargins(..) + , TextRenderInfo(..) + , Widget(..) , SignalChan (..) + , Action (..) + , Button ) where import qualified Control.Concurrent.STM as STM import qualified Xmobar.Run.Runnable as R import qualified Xmobar.System.Signal as S +import Data.Int (Int32) +import Foreign.C.Types (CInt) + +import Xmobar.Run.Actions (Action (..), Button) + -- $config -- Configuration data type @@ -71,20 +85,94 @@ data Config = , template :: String -- ^ The output template , verbose :: Bool -- ^ Emit additional debug messages , signal :: SignalChan -- ^ Channel to send signals to xmobar + , dpi :: Double -- ^ DPI scaling factor for fonts } deriving (Read, Show) -data XPosition = Top - | TopH Int - | TopW Align Int - | TopSize Align Int Int - | TopP Int Int +-- | The position datatype +data XPosition = Top -- ^ Top of the screen, full width, auto height + + | TopH -- ^ Top of the screen, full width with + -- specific height + Int -- ^ Height (in pixels) + + -- | Top of the screen, full width with + -- specific height and margins + | TopHM + Int -- ^ Height (in pixels) + Int -- ^ Left margin (in pixels) + Int -- ^ Right margin (in pixels) + Int -- ^ Top margin (in pixels) + Int -- ^ Bottom margin (in pixels) + + -- | Top of the screen with specific width + -- (as screen percentage) and alignment + | TopW + Align -- ^ Alignement (L|C|R) + Int -- ^ Width as screen percentage (0-100) + + -- | Top of the screen with specific width + -- (as screen percentage), height and + -- alignment + | TopSize + Align -- ^ Alignement (L|C|R) + Int -- ^ Width as screen percentage (0-100) + Int -- ^ Height (in pixels) + + -- | Top of the screen with specific left/right + -- margins + | TopP + Int -- ^ Left margin (in pixels) + Int -- ^ Right margin (in pixels) + + -- | Bottom of the screen, full width, auto height | Bottom - | BottomH Int - | BottomP Int Int - | BottomW Align Int - | BottomSize Align Int Int - | Static {xpos, ypos, width, height :: Int} - | OnScreen Int XPosition + + | BottomH -- ^ Bottom of the screen, full width, with + -- specific height + Int -- ^ Height (in pixels) + + -- | Bottom of the screen with specific height + -- and margins + | BottomHM + Int -- ^ Height (in pixels) + Int -- ^ Left margin (in pixels) + Int -- ^ Right margin (in pixels) + Int -- ^ Top margin (in pixels) + Int -- ^ Bottom margin (in pixels) + + -- | Bottom of the screen with specific + -- left/right margins + | BottomP + Int -- ^ Left margin (in pixels) + Int -- ^ Bottom margin (in pixels) + + -- | Bottom of the screen with specific width + -- (as screen percentage) and alignment + -- and alignment + | BottomW + Align -- ^ Alignement (L|C|R) + Int -- ^ Width as screen percentage (0-100) + + -- | Bottom of the screen with specific width + -- (as screen percentage), height + -- and alignment + | BottomSize + Align -- ^ Alignement (L|C|R) + Int -- ^ Width as screen percentage (0-100) + Int -- ^ Height (in pixels) + + -- | Static position and specific size + | Static { xpos :: Int -- ^ Position X (in pixels) + , ypos :: Int -- ^ Position Y (in pixels) + , width :: Int -- ^ Width (in pixels) + , height :: Int -- ^ Height (in pixels) + } + + -- | Along with the position characteristics + -- specify the screen to display the bar + | OnScreen + Int -- ^ Screen id (primary is 0) + XPosition -- ^ Position deriving ( Read, Show, Eq ) data Align = L | R | C deriving ( Read, Show, Eq ) @@ -110,3 +198,34 @@ instance Read SignalChan where instance Show SignalChan where show (SignalChan (Just _)) = "SignalChan (Just <tmvar>)" show (SignalChan Nothing) = "SignalChan Nothing" + +data Widget = Icon String | Text String | Hspace Int32 deriving Show + +data BoxOffset = BoxOffset Align Int32 deriving (Eq, Show) + +-- margins: Top, Right, Bottom, Left +data BoxMargins = BoxMargins Int32 Int32 Int32 Int32 deriving (Eq, Show) + +data BoxBorder = BBTop + | BBBottom + | BBVBoth + | BBLeft + | BBRight + | BBHBoth + | BBFull + deriving (Read, Eq, Show) + +data Box = Box { bBorder :: BoxBorder + , bOffset :: BoxOffset + , bWidth :: CInt + , bColor :: String + , bMargins :: BoxMargins + } deriving (Eq, Show) + +data TextRenderInfo = TextRenderInfo { tColorsString :: String + , tBgTopOffset :: Int32 + , tBgBottomOffset :: Int32 + , tBoxes :: [Box] + } deriving Show + +type Segment = (Widget, TextRenderInfo, FontIndex, Maybe [Action]) diff --git a/src/Xmobar/Draw/Boxes.hs b/src/Xmobar/Draw/Boxes.hs index 1358805..ff55ab3 100644 --- a/src/Xmobar/Draw/Boxes.hs +++ b/src/Xmobar/Draw/Boxes.hs @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.X11.Boxes --- Copyright: (c) 2022 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2022, 2024 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -16,7 +16,6 @@ module Xmobar.Draw.Boxes (Line, boxLines, BoxRect, borderRect) where import qualified Xmobar.Config.Types as T -import qualified Xmobar.Run.Parsers as P type Line = (Double, Double, Double, Double) type BoxRect = (Double, Double, Double, Double) @@ -25,30 +24,29 @@ type BoxRect = (Double, Double, Double, Double) -- The Box is to be positioned between x0 and x1, with height ht, and drawn -- with line width lw. The returned lists are coordinates of the beginning -- and end of each line. -boxLines :: P.Box -> Double -> Double -> Double -> [Line] -boxLines (P.Box bd offset lw _ margins) ht x0 x1 = +boxLines :: T.Box -> Double -> Double -> Double -> [Line] +boxLines (T.Box bd offset lw _ margins) ht x0 x1 = case bd of - P.BBTop -> [rtop] - P.BBBottom -> [rbot] - P.BBVBoth -> [rtop, rbot] - P.BBLeft -> [rleft] - P.BBRight -> [rright] - P.BBHBoth -> [rleft, rright] - P.BBFull -> [rtop, rbot, rleft, rright] + T.BBTop -> [rtop] + T.BBBottom -> [rbot] + T.BBVBoth -> [rtop, rbot] + T.BBLeft -> [rleft] + T.BBRight -> [rright] + T.BBHBoth -> [rleft, rright] + T.BBFull -> [rtop, rbot, rleft, rright] where - (P.BoxMargins top right bot left) = margins - (P.BoxOffset align m) = offset + (T.BoxMargins top right bot left) = margins + (T.BoxOffset align m) = offset ma = fromIntegral m (p0, p1) = case align of T.L -> (0, -ma) T.C -> (ma, -ma) T.R -> (ma, 0) lc = fromIntegral lw / 2 - [mt, mr, mb, ml] = map fromIntegral [top, right, bot, left] - xmin = x0 - ml - lc - xmax = x1 + mr + lc - ymin = mt + lc - ymax = ht - mb - lc + xmin = x0 - fromIntegral left - lc + xmax = x1 + fromIntegral right + lc + ymin = fromIntegral top + lc + ymax = ht - fromIntegral bot - lc rtop = (xmin + p0, ymin, xmax + p1, ymin) rbot = (xmin + p0, ymax, xmax + p1, ymax) rleft = (xmin, ymin + p0, xmin, ymax + p1) diff --git a/src/Xmobar/Draw/Cairo.hs b/src/Xmobar/Draw/Cairo.hs index 7e22df4..2338b10 100644 --- a/src/Xmobar/Draw/Cairo.hs +++ b/src/Xmobar/Draw/Cairo.hs @@ -2,7 +2,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.X11.Cairo --- Copyright: (c) 2022 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2022, 2023, 2024 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -29,14 +29,13 @@ import Graphics.Rendering.Cairo.Types(Surface) import qualified Xmobar.Config.Types as C import qualified Xmobar.Config.Parse as ConfigParse -import qualified Xmobar.Run.Parsers as P import qualified Xmobar.Text.Pango as TextPango import qualified Xmobar.Draw.Boxes as Boxes import qualified Xmobar.Draw.Types as T -type Renderinfo = (P.Segment, Surface -> Double -> Double -> IO (), Double) -type BoundedBox = (Double, Double, [P.Box]) +type Renderinfo = (C.Segment, Surface -> Double -> Double -> IO (), Double) +type BoundedBox = (Double, Double, [C.Box]) type Acc = (Double, T.Actions, [BoundedBox]) readColourName :: String -> (SRGB.Colour Double, Double) @@ -63,10 +62,10 @@ renderLines color wd lns = do mapM_ (\(x0, y0, x1, y1) -> Cairo.moveTo x0 y0 >> Cairo.lineTo x1 y1 >> Cairo.stroke) lns -segmentMarkup :: C.Config -> P.Segment -> String -segmentMarkup conf (P.Text txt, info, idx, _actions) = +segmentMarkup :: C.Config -> C.Segment -> String +segmentMarkup conf (C.Text txt, info, idx, _actions) = let fnt = TextPango.fixXft $ ConfigParse.indexedFont conf idx - (fg, bg) = P.colorComponents conf (P.tColorsString info) + (fg, bg) = ConfigParse.colorComponents conf (C.tColorsString info) attrs = [Pango.FontDescr fnt, Pango.FontForeground fg] attrs' = if bg == C.bgColor conf then attrs @@ -74,8 +73,8 @@ segmentMarkup conf (P.Text txt, info, idx, _actions) = in Pango.markSpan attrs' $ Pango.escapeMarkup txt segmentMarkup _ _ = "" -withRenderinfo :: Pango.PangoContext -> T.DrawContext -> P.Segment -> IO Renderinfo -withRenderinfo ctx dctx seg@(P.Text _, inf, idx, a) = do +withRenderinfo :: Pango.PangoContext -> T.DrawContext -> C.Segment -> IO Renderinfo +withRenderinfo ctx dctx seg@(C.Text _, inf, idx, a) = do let conf = T.dcConfig dctx lyt <- Pango.layoutEmpty ctx mk <- Pango.layoutSetMarkup lyt (segmentMarkup conf seg) :: IO String @@ -88,25 +87,28 @@ withRenderinfo ctx dctx seg@(P.Text _, inf, idx, a) = do Pango.layoutSetEllipsize lyt Pango.EllipsizeEnd Pango.layoutSetWidth lyt (Just $ mx - off) Cairo.renderWith s $ Cairo.moveTo off voff >> Pango.showLayout lyt - return ((P.Text mk, inf, idx, a), slyt, wd) + return ((C.Text mk, inf, idx, a), slyt, wd) -withRenderinfo _ _ seg@(P.Hspace w, _, _, _) = +withRenderinfo _ _ seg@(C.Hspace w, _, _, _) = return (seg, \_ _ _ -> return (), fromIntegral w) -withRenderinfo _ dctx seg@(P.Icon p, _, _, _) = do +withRenderinfo _ dctx seg@(C.Icon p, info, _, _) = do let (wd, _) = T.dcIconLookup dctx p ioff = C.iconOffset (T.dcConfig dctx) vpos = T.dcHeight dctx / 2 + fromIntegral ioff - render _ off mx = when (off + wd <= mx) $ T.dcIconDrawer dctx off vpos p + conf = T.dcConfig dctx + (fg, bg) = ConfigParse.colorComponents conf (C.tColorsString info) + render _ off mx = when (off + wd <= mx) $ + T.dcIconDrawer dctx off vpos p fg bg return (seg, render, wd) -drawBox :: T.DrawContext -> Surface -> Double -> Double -> P.Box -> IO () -drawBox dctx surf x0 x1 box@(P.Box _ _ w color _) = +drawBox :: T.DrawContext -> Surface -> Double -> Double -> C.Box -> IO () +drawBox dctx surf x0 x1 box@(C.Box _ _ w color _) = Cairo.renderWith surf $ renderLines color (fromIntegral w) (Boxes.boxLines box (T.dcHeight dctx) x0 x1) drawSegmentBackground :: - T.DrawContext -> Surface -> P.TextRenderInfo -> Double -> Double -> IO () + T.DrawContext -> Surface -> C.TextRenderInfo -> Double -> Double -> IO () drawSegmentBackground dctx surf info x0 x1 = when (bg /= C.bgColor conf && (top >= 0 || bot >= 0)) $ Cairo.renderWith surf $ do @@ -114,19 +116,20 @@ drawSegmentBackground dctx surf info x0 x1 = Cairo.rectangle x0 top (x1 - x0) (T.dcHeight dctx - bot - top) Cairo.fillPreserve where conf = T.dcConfig dctx - (_, bg) = P.colorComponents conf (P.tColorsString info) - top = fromIntegral $ P.tBgTopOffset info - bot = fromIntegral $ P.tBgBottomOffset info + (_, bg) = ConfigParse.colorComponents conf (C.tColorsString info) + top = fromIntegral $ C.tBgTopOffset info + bot = fromIntegral $ C.tBgBottomOffset info drawSegment :: T.DrawContext -> Surface -> Double -> Acc -> Renderinfo -> IO Acc drawSegment dctx surface maxoff (off, acts, boxs) (segment, render, lwidth) = do let end = min maxoff (off + lwidth) (_, info, _, a) = segment acts' = case a of Just as -> (as, off, end):acts; _ -> acts - bs = P.tBoxes info + bs = C.tBoxes info boxs' = if null bs then boxs else (off, end, bs):boxs - drawSegmentBackground dctx surface info off end - render surface off maxoff + when (end > off) $ do + drawSegmentBackground dctx surface info off end + render surface off maxoff return (off + lwidth, acts', boxs') renderOuterBorder :: C.Config -> Double -> Double -> Cairo.Render () @@ -166,25 +169,27 @@ drawCairoBackground dctx surf = do drawSegments :: T.DrawContext -> Surface -> IO T.Actions drawSegments dctx surf = do - let [left, center, right] = take 3 $ T.dcSegments dctx ++ repeat [] + let segs = take 3 $ T.dcSegments dctx ++ repeat [] dh = T.dcHeight dctx dw = T.dcWidth dctx conf = T.dcConfig dctx sWidth = foldl (\a (_,_,w) -> a + w) 0 ctx <- Pango.cairoCreateContext Nothing - llyts <- mapM (withRenderinfo ctx dctx) left - rlyts <- mapM (withRenderinfo ctx dctx) right - clyts <- mapM (withRenderinfo ctx dctx) center + Pango.cairoContextSetResolution ctx $ C.dpi conf + llyts <- mapM (withRenderinfo ctx dctx) (head segs) + rlyts <- mapM (withRenderinfo ctx dctx) (segs !! 2) + clyts <- mapM (withRenderinfo ctx dctx) (segs !! 1) #ifndef XRENDER drawCairoBackground dctx surf #endif (lend, as, bx) <- foldM (drawSegment dctx surf dw) (0, [], []) llyts let rw = sWidth rlyts - rstart = max (lend + 1) (dw - rw - 1) - cmax = rstart - 1 cw = sWidth clyts - cstart = lend + 1 + max 0 (dw - rw - lend - cw) / 2.0 - (_, as', bx') <- foldM (drawSegment dctx surf cmax) (cstart, as, bx) clyts + rstart = max lend (dw - rw) + cstart = if lend > 1 || rw == 0 then max lend ((dw - cw) / 2.0) else lend + (_, as', bx') <- if cw > 0 + then foldM (drawSegment dctx surf rstart) (cstart, as, bx) clyts + else return (0, as, bx) (_, as'', bx'') <- foldM (drawSegment dctx surf dw) (rstart, as', bx') rlyts drawBoxes dctx surf (reverse bx'') when (C.borderWidth conf > 0) (drawBorder conf dw dh surf) diff --git a/src/Xmobar/Draw/Types.hs b/src/Xmobar/Draw/Types.hs index 75dd714..1a076b3 100644 --- a/src/Xmobar/Draw/Types.hs +++ b/src/Xmobar/Draw/Types.hs @@ -17,16 +17,15 @@ module Xmobar.Draw.Types where -import Xmobar.Config.Types (Config) +import Xmobar.Config.Types (Config, Segment) import Xmobar.Run.Actions (Action) -import Xmobar.Run.Parsers (Segment) type Position = Double type ActionPos = ([Action], Position, Position) type Actions = [ActionPos] type IconLookup = String -> (Double, Double) -type IconDrawer = Double -> Double -> String -> IO () +type IconDrawer = Double -> Double -> String -> String -> String -> IO () data DrawContext = DC { dcIconDrawer :: IconDrawer , dcIconLookup :: IconLookup diff --git a/src/Xmobar/Plugins/EWMH.hs b/src/Xmobar/Plugins/EWMH.hs index 94fd7d7..78f1cc0 100644 --- a/src/Xmobar/Plugins/EWMH.hs +++ b/src/Xmobar/Plugins/EWMH.hs @@ -19,6 +19,7 @@ module Xmobar.Plugins.EWMH (EWMH(..)) where import Control.Applicative (Applicative(..)) import Control.Monad.State +import Control.Monad import Control.Monad.Reader import Graphics.X11 hiding (Modifier, Color) import Graphics.X11.Xlib.Extras diff --git a/src/Xmobar/Plugins/Kbd.hs b/src/Xmobar/Plugins/Kbd.hs index 2214628..3871ca8 100644 --- a/src/Xmobar/Plugins/Kbd.hs +++ b/src/Xmobar/Plugins/Kbd.hs @@ -14,9 +14,11 @@ module Xmobar.Plugins.Kbd(Kbd(..)) where -import Data.List (isPrefixOf) +import Data.Bifunctor (bimap) +import Data.List (find, tails, isPrefixOf) import Data.Maybe (fromMaybe) -import Data.Char (toLower) +import Data.Char (toLower, isLetter) +import Data.Function ((&)) import Control.Monad (forever) import Control.Applicative ((<|>)) import Graphics.X11.Xlib @@ -26,6 +28,13 @@ import Xmobar.Run.Exec import Xmobar.X11.Events (nextEvent') import Xmobar.System.Kbd +-- some strong typing +newtype Lay = Lay String deriving (Eq) +newtype Sym = Sym String +instance Show Sym where show (Sym s) = s +type KbdOpts' = [(Lay, Sym)] +typed :: [(String, String)] -> [(Lay, Sym)] +typed = map (bimap Lay Sym) -- 'Bad' prefixes of layouts noLaySymbols :: [String] @@ -49,15 +58,22 @@ split p s = case break p s of (pref, "") -> [pref] -- replaces input string if on search list (exact match) with corresponding --- element on replacement list. +-- element on replacement list, and returns it paired with the following item -- --- if not found, return string unchanged -searchReplaceLayout :: KbdOpts -> String -> String -searchReplaceLayout opts s = fromMaybe s $ lookup s opts - --- returns the active layout -getKbdLay :: Display -> KbdOpts -> IO String -getKbdLay dpy opts = do +-- if not found, return string unchanged, paired with empty string +searchReplaceLayout :: KbdOpts' -> String -> (Lay, Lay, Sym) +searchReplaceLayout opts curr + = maybe (Lay "", Lay "", Sym curr) + pickSymWithAdjLays + (find currLayout (tails $ cycle opts)) + where + pickSymWithAdjLays ((l1, _):(_, s):(l2, _):_) = (l1, l2, s) + pickSymWithAdjLays _ = error "This should never happen" + currLayout = (Lay curr ==) . (!! 1) . map fst + +-- returns the active layout and the following one +getCurAndNextKbdLays :: Display -> KbdOpts' -> IO (Lay, Lay, Sym) +getCurAndNextKbdLays dpy opts = do lay <- splitLayout <$> getLayoutStr dpy grps <- map (map toLower . take 2) <$> getGrpNames dpy curLay <- getKbdLayout dpy @@ -73,6 +89,37 @@ getKbdLay dpy opts = do newtype Kbd = Kbd [(String, String)] deriving (Read, Show) +attachClickAction :: (Lay, Lay, Sym) -> Sym +attachClickAction (Lay prv, Lay nxt, txt) = txt & linkTo nxt `onKey` "1" + & linkTo prv `onKey` "3" + where + splitLayParensPhon :: String -> (String, String, String) + splitLayParensPhon = (\(a, (b, c)) -> (a, b, c)) + . second (second (drop 1) . break (== ')') . drop 1) + . break (== '(') + parseLayPhon :: String -> (Maybe String, Maybe String) + parseLayPhon s = let (l, p, i) = splitLayParensPhon s + l' = if all isLetter l + then Just ("-layout " ++ l) + else Nothing + p' = if (p, i) == ("phonetic", "") + then Just "-variant phonetic" + else Nothing + in (l', p') + linkTo :: String -> String -> Sym -> Sym + linkTo linked button currLay = Sym $ case parseLayPhon linked of + (Nothing, _) -> "??" + (Just linkedLay, phon) -> wrapIn setxkbmap button currLay + where + setxkbmap = unwords ["setxkbmap", linkedLay, fromMaybe "" phon] + wrapIn :: String -> String -> Sym -> String + wrapIn action buttons (Sym sym) = openingTag ++ sym ++ closingTag + where + openingTag = "<action=`" ++ action ++ "` button=" ++ buttons ++ ">" + closingTag = "</action>" + onKey = ($) + second = fmap + instance Exec Kbd where alias (Kbd _) = "kbd" start (Kbd opts) cb = do @@ -80,7 +127,7 @@ instance Exec Kbd where dpy <- openDisplay "" -- initial set of layout - cb =<< getKbdLay dpy opts + cb . show . attachClickAction =<< getCurAndNextKbdLays dpy (typed opts) -- enable listing for -- group changes @@ -91,7 +138,6 @@ instance Exec Kbd where allocaXEvent $ \e -> forever $ do nextEvent' dpy e _ <- getEvent e - cb =<< getKbdLay dpy opts + cb . show . attachClickAction =<< getCurAndNextKbdLays dpy (typed opts) closeDisplay dpy - return () diff --git a/src/Xmobar/Plugins/Kraken.hs b/src/Xmobar/Plugins/Kraken.hs index 2345b3d..5d565e0 100644 --- a/src/Xmobar/Plugins/Kraken.hs +++ b/src/Xmobar/Plugins/Kraken.hs @@ -36,7 +36,7 @@ instance Exec Kraken where cb (display g) loop mv g - loop mvar (Map.fromList $ zip ps (repeat 0.0)) + loop mvar (Map.fromList $ map (, 0.0) ps) where display :: Map.Map String Double -> String diff --git a/src/Xmobar/Plugins/Locks.hs b/src/Xmobar/Plugins/Locks.hs index 9176312..35a3f97 100644 --- a/src/Xmobar/Plugins/Locks.hs +++ b/src/Xmobar/Plugins/Locks.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE TupleSections #-} ----------------------------------------------------------------------------- -- | -- Module : Plugins.Locks @@ -16,45 +17,70 @@ module Xmobar.Plugins.Locks(Locks(..)) where import Graphics.X11 import Data.List +import Data.List.Extra (trim) import Data.Bits +import Data.Maybe (fromJust) import Control.Monad +import Control.Monad.Extra (ifM) import Graphics.X11.Xlib.Extras import Xmobar.Run.Exec import Xmobar.System.Kbd import Xmobar.X11.Events (nextEvent') -data Locks = Locks +data Locks = Locks | Locks' [(String, (String, String))] deriving (Read, Show) locks :: [ ( KeySym, String )] -locks = [ ( xK_Caps_Lock, "CAPS" ) - , ( xK_Num_Lock, "NUM" ) +locks = [ ( xK_Caps_Lock, "CAPS" ) + , ( xK_Num_Lock, "NUM" ) , ( xK_Scroll_Lock, "SCROLL" ) ] -run' :: Display -> Window -> IO String -run' d root = do +type Labels = [ ( String, (String, String) )] +defaultLabels :: Labels +defaultLabels = let nms = map snd locks + in zip nms (map (, mempty) nms) + +type LabelledLock = (KeySym, String, String, String) + +attach :: (KeySym, String) -> Labels -> LabelledLock +(key, lock) `attach` lbls = let (enb, dis) = fromJust $ lookup lock lbls + in (key, lock, enb, dis) + +enabled :: (a, b, c, d) -> c +enabled (_, _, c, _) = c +disabled :: (a, b, c, d) -> d +disabled (_, _, _, d) = d + +isEnabled :: (Bits a1, Foldable t, Foldable t1, Integral a) + => Display -> t (a, t1 KeyCode) -> a1 -> (KeySym, b, c, d) -> IO Bool +isEnabled d modMap m ( ks, _, _, _ ) = do + kc <- keysymToKeycode d ks + return $ case find (elem kc . snd) modMap of + Nothing -> False + Just ( i, _ ) -> testBit m (fromIntegral i) + +run' :: Display -> Window -> Labels -> IO String +run' d root labels = do modMap <- getModifierMapping d ( _, _, _, _, _, _, _, m ) <- queryPointer d root - ls <- filterM ( \( ks, _ ) -> do - kc <- keysymToKeycode d ks - return $ case find (elem kc . snd) modMap of - Nothing -> False - Just ( i, _ ) -> testBit m (fromIntegral i) - ) locks - - return $ unwords $ map snd ls + ls' <- forM (map (`attach` labels) locks) + (\l -> ifM (isEnabled d modMap m l) + (return (enabled l)) + (return (disabled l))) + return $ trim $ unwords ls' instance Exec Locks where - alias Locks = "locks" - start Locks cb = do + alias _ = "locks" + start Locks cb = start (Locks' defaultLabels) cb + start (Locks' labels) cb = do d <- openDisplay "" root <- rootWindow d (defaultScreen d) _ <- xkbSelectEventDetails d xkbUseCoreKbd xkbIndicatorStateNotify m m allocaXEvent $ \ep -> forever $ do - cb =<< run' d root + cb =<< run' d root labels nextEvent' d ep getEvent ep diff --git a/src/Xmobar/Plugins/Monitors/Alsa.hs b/src/Xmobar/Plugins/Monitors/Alsa.hs index dfc7329..8d02931 100644 --- a/src/Xmobar/Plugins/Monitors/Alsa.hs +++ b/src/Xmobar/Plugins/Monitors/Alsa.hs @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Alsa --- Copyright : (c) 2018 Daniel Schüssler +-- Copyright : (c) 2018, 2024 Daniel Schüssler -- License : BSD-style (see LICENSE) -- -- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org> @@ -25,6 +25,7 @@ import Control.Concurrent.Async import Control.Exception import Control.Monad import Data.IORef +import Data.Maybe (fromJust) import Data.Time.Clock import Xmobar.Plugins.Monitors.Common import qualified Xmobar.Plugins.Monitors.Volume as Volume; @@ -129,7 +130,8 @@ alsaReaderThread mixerName alsaCtlPath outputCallback mvar = {std_out = CreatePipe} runAlsaOnce = - withCreateProcess createProc $ \_ (Just alsaOut) _ _ -> do + withCreateProcess createProc $ \_ out _ _ -> do + let alsaOut = fromJust out hSetBuffering alsaOut LineBuffering tryPutMVar mvar () -- Refresh immediately after restarting alsactl diff --git a/src/Xmobar/Plugins/Monitors/Batt/Common.hs b/src/Xmobar/Plugins/Monitors/Batt/Common.hs index 3262b78..ddb2b8c 100644 --- a/src/Xmobar/Plugins/Monitors/Batt/Common.hs +++ b/src/Xmobar/Plugins/Monitors/Batt/Common.hs @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Batt.Common --- Copyright : (c) 2010, 2011, 2012, 2013, 2015, 2016, 2018, 2019 Jose A Ortega +-- Copyright : (c) 2010-2016, 2018, 2019, 2024 Jose A Ortega -- (c) 2010 Andrea Rossato, Petr Rockai -- License : BSD-style (see LICENSE) -- @@ -18,7 +18,7 @@ module Xmobar.Plugins.Monitors.Batt.Common (BattOpts(..) , Status(..) , maybeAlert) where -import System.Process (system) +import System.Process (spawnCommand, waitForProcess) import Control.Monad (unless, void) import Xmobar.Plugins.Monitors.Common @@ -54,4 +54,4 @@ maybeAlert opts left = case onLowAction opts of Nothing -> return () Just x -> unless (isNaN left || actionThreshold opts < 100 * left) - $ void $ system x + $ void $ spawnCommand (x ++ " &") >>= waitForProcess diff --git a/src/Xmobar/Plugins/Monitors/Common/Output.hs b/src/Xmobar/Plugins/Monitors/Common/Output.hs index bd60710..c0a00ab 100644 --- a/src/Xmobar/Plugins/Monitors/Common/Output.hs +++ b/src/Xmobar/Plugins/Monitors/Common/Output.hs @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.Plugins.Monitors.Strings --- Copyright: (c) 2018, 2019, 2020, 2022 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2018, 2019, 2020, 2022, 2024 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -88,9 +88,9 @@ pShowWithColors p f x = do pColorizeString :: (Num a, Ord a, MonadIO m) => MonitorConfig -> a -> String -> m String pColorizeString p x s = do let col = pSetColor p s - [ll,hh] = map fromIntegral $ sort [pLow p, pHigh p] -- consider high < low - pure $ head $ [col pHighColor | x > hh ] ++ - [col pNormalColor | x > ll ] ++ + cols = map fromIntegral $ sort [pLow p, pHigh p] -- consider high < low + pure $ head $ [col pHighColor | x > (cols !! 1) ] ++ + [col pNormalColor | x > head cols ] ++ [col pLowColor | True] pSetColor :: MonitorConfig -> String -> PSelector (Maybe String) -> String @@ -140,7 +140,7 @@ showWithUnits d n x padString :: Int -> Int -> String -> Bool -> String -> String -> String padString mnw mxw pad pr ellipsis s = let len = length s - rmin = if mnw < 0 then 0 else mnw + rmin = max mnw 0 rmax = if mxw <= 0 then max len rmin else mxw (rmn, rmx) = if rmin <= rmax then (rmin, rmax) else (rmax, rmin) rlen = min (max rmn len) rmx @@ -197,9 +197,9 @@ colorizeString x s = do h <- getConfigValue high l <- getConfigValue low let col = setColor s - [ll,hh] = map fromIntegral $ sort [l, h] -- consider high < low - head $ [col highColor | x > hh ] ++ - [col normalColor | x > ll ] ++ + cols = map fromIntegral $ sort [l, h] -- consider high < low + head $ [col highColor | x > cols !! 1 ] ++ + [col normalColor | x > head cols ] ++ [col lowColor | True] showWithColors :: (Num a, Ord a) => (a -> String) -> a -> Monitor String @@ -260,11 +260,11 @@ logScaling f v = do h <- fromIntegral `fmap` getConfigValue high l <- fromIntegral `fmap` getConfigValue low bw <- fromIntegral `fmap` getConfigValue barWidth - let [ll, hh] = sort [l, h] + let ws = sort [l, h] bw' = if bw > 0 then bw else 10 scaled x | x == 0.0 = 0 - | x <= ll = 1 / bw' - | otherwise = f + logBase 2 (x / hh) / bw' + | x <= head ws = 1 / bw' + | otherwise = f + logBase 2 (x / ws !! 1) / bw' return $ scaled v showLogBar :: Float -> Float -> Monitor String diff --git a/src/Xmobar/Plugins/Monitors/Disk.hs b/src/Xmobar/Plugins/Monitors/Disk.hs index 47d1eac..95bcff6 100644 --- a/src/Xmobar/Plugins/Monitors/Disk.hs +++ b/src/Xmobar/Plugins/Monitors/Disk.hs @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Plugins.Monitors.Disk --- Copyright : (c) 2010, 2011, 2012, 2014, 2018, 2019 Jose A Ortega Ruiz +-- Copyright : (c) 2010-2012, 2014, 2018, 2019, 2024 Jose A Ortega Ruiz -- License : BSD-style (see LICENSE) -- -- Maintainer : Jose A Ortega Ruiz <jao@gnu.org> @@ -131,10 +131,9 @@ startDiskIO disks args rate cb = do runM args diskIOConfig (runDiskIO dref disks) rate cb runDiskU' :: DiskUOpts -> String -> [Integer] -> Monitor String -runDiskU' opts tmp stat = do +runDiskU' opts tmp (total:free:diff:_) = do setConfigValue tmp template - let [total, free, diff] = stat - strs = map sizeToStr [free, diff] + let strs = map sizeToStr [free, diff] freep = if total > 0 then free * 100 `div` total else 0 fr = fromIntegral freep / 100 s <- zipWithM showWithColors' strs [freep, 100 - freep] @@ -146,6 +145,7 @@ runDiskU' opts tmp stat = do uvb <- showVerticalBar (fromIntegral $ 100 - freep) (1 - fr) uipat <- showIconPattern (usedIconPattern opts) (1 - fr) parseTemplate $ [sizeToStr total] ++ s ++ sp ++ [fb,fvb,fipat,ub,uvb,uipat] +runDiskU' _ _ _ = return "" runDiskU :: [(String, String)] -> [String] -> Monitor String runDiskU disks argv = do diff --git a/src/Xmobar/Plugins/Monitors/Mem/Linux.hs b/src/Xmobar/Plugins/Monitors/Mem/Linux.hs index 79dcc9d..7a81c6d 100644 --- a/src/Xmobar/Plugins/Monitors/Mem/Linux.hs +++ b/src/Xmobar/Plugins/Monitors/Mem/Linux.hs @@ -25,9 +25,13 @@ parseMEM = let content = map words $ take 8 $ lines file info = M.fromList $ map ( \line -> (head line, (read $ line !! 1 :: Float) / 1024)) content - [total, free, buffer, cache] = - map (info M.!) ["MemTotal:", "MemFree:", "Buffers:", "Cached:"] - available = M.findWithDefault (free + buffer + cache) "MemAvailable:" info + info' x = info M.! (x ++ ":") + total = info' "MemTotal" + free = info' "MemFree" + buffer = info' "Buffers" + cache = info' "Cached" + available = + M.findWithDefault (free + buffer + cache) "MemAvailable:" info used = total - available usedratio = used / total freeratio = free / total diff --git a/src/Xmobar/Plugins/Monitors/Net/Linux.hs b/src/Xmobar/Plugins/Monitors/Net/Linux.hs index 9306497..f9cbc28 100644 --- a/src/Xmobar/Plugins/Monitors/Net/Linux.hs +++ b/src/Xmobar/Plugins/Monitors/Net/Linux.hs @@ -47,7 +47,10 @@ isUp d = flip catchIOError (const $ return False) $ do return $! (head . B.lines) operstate `elem` ["up", "unknown"] readNetDev :: [String] -> IO NetDevRawTotal -readNetDev ~[d, x, y] = do +readNetDev ds = do + let (d, x, y) = case ds of + d':x':y':_ -> (d', x', y') + _ -> ("", "", "") up <- unsafeInterleaveIO $ isUp d return $ N d (if up then ND (r x) (r y) else NI) where r s | s == "" = 0 diff --git a/src/Xmobar/Run/Actions.hs b/src/Xmobar/Run/Actions.hs index 2a49312..cbc10c5 100644 --- a/src/Xmobar/Run/Actions.hs +++ b/src/Xmobar/Run/Actions.hs @@ -16,7 +16,7 @@ module Xmobar.Run.Actions ( Button , runAction' , stripActions) where -import System.Process (system) +import System.Process (spawnCommand, waitForProcess) import Control.Monad (void) import Text.Regex (Regex, subRegex, mkRegex, matchRegex) import Data.Word (Word32) @@ -26,11 +26,11 @@ type Button = Word32 data Action = Spawn [Button] String deriving (Eq, Read, Show) runAction :: Action -> IO () -runAction (Spawn _ s) = void $ system (s ++ "&") +runAction (Spawn _ s) = void $ spawnCommand (s ++ " &") >>= waitForProcess -- | Run action with stdout redirected to stderr runAction' :: Action -> IO () -runAction' (Spawn _ s) = void $ system (s ++ " 1>&2 &") +runAction' (Spawn _ s) = void $ spawnCommand (s ++ " 1>&2 &") >>= waitForProcess stripActions :: String -> String stripActions s = case matchRegex actionRegex s of diff --git a/src/Xmobar/Run/Parsers.hs b/src/Xmobar/Run/Parsers.hs deleted file mode 100644 index 9b36786..0000000 --- a/src/Xmobar/Run/Parsers.hs +++ /dev/null @@ -1,244 +0,0 @@ -{-# LANGUAGE FlexibleContexts #-} - ------------------------------------------------------------------------------ --- | --- Module : Xmobar.Run.Parsers --- Copyright : (c) Andrea Rossato --- License : BSD-style (see LICENSE) --- --- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org> --- Stability : unstable --- Portability : portable --- --- Parsing for template substrings --- ------------------------------------------------------------------------------ - -module Xmobar.Run.Parsers ( parseString - , colorComponents - , Segment - , FontIndex - , Box(..) - , BoxBorder(..) - , BoxOffset(..) - , BoxMargins(..) - , TextRenderInfo(..) - , Widget(..)) where - -import Control.Monad (guard, mzero) -import Data.Maybe (fromMaybe) -import Data.Int (Int32) -import Text.ParserCombinators.Parsec -import Text.Read (readMaybe) -import Foreign.C.Types (CInt) - -import Xmobar.Config.Types -import Xmobar.Run.Actions - -data Widget = Icon String | Text String | Hspace Int32 deriving Show - -data BoxOffset = BoxOffset Align Int32 deriving (Eq, Show) - --- margins: Top, Right, Bottom, Left -data BoxMargins = BoxMargins Int32 Int32 Int32 Int32 deriving (Eq, Show) - -data BoxBorder = BBTop - | BBBottom - | BBVBoth - | BBLeft - | BBRight - | BBHBoth - | BBFull - deriving (Read, Eq, Show) - -data Box = Box { bBorder :: BoxBorder - , bOffset :: BoxOffset - , bWidth :: CInt - , bColor :: String - , bMargins :: BoxMargins - } deriving (Eq, Show) - -data TextRenderInfo = TextRenderInfo { tColorsString :: String - , tBgTopOffset :: Int32 - , tBgBottomOffset :: Int32 - , tBoxes :: [Box] - } deriving Show - -type Segment = (Widget, TextRenderInfo, FontIndex, Maybe [Action]) - --- | Runs the string parser -parseString :: Config -> String -> IO [Segment] -parseString c s = - case parse (stringParser ci 0 Nothing) "" s of - Left _ -> return [(Text $ "Could not parse string: " ++ s - , ci - , 0 - , Nothing)] - Right x -> return (concat x) - where ci = TextRenderInfo (fgColor c) 0 0 [] - --- | Splits a colors string into its two components -colorComponents :: Config -> String -> (String, String) -colorComponents conf c = - case break (==',') c of - (f,',':b) -> (f, b) - (f, _) -> (f, bgColor conf) - -allParsers :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -allParsers c f a = textParser c f a - <|> try (iconParser c f a) - <|> try (hspaceParser c f a) - <|> try (rawParser c f a) - <|> try (actionParser c f a) - <|> try (fontParser c a) - <|> try (boxParser c f a) - <|> colorParser c f a - --- | Gets the string and combines the needed parsers -stringParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [[Segment]] -stringParser c f a = manyTill (allParsers c f a) eof - --- | Parses a maximal string without markup. -textParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -textParser c f a = do s <- many1 $ - noneOf "<" <|> - try (notFollowedBy' (char '<') - (try (string "fc=") <|> - try (string "box") <|> - try (string "fn=") <|> - try (string "action=") <|> - try (string "/action>") <|> - try (string "icon=") <|> - try (string "hspace=") <|> - try (string "raw=") <|> - try (string "/fn>") <|> - try (string "/box>") <|> - string "/fc>")) - return [(Text s, c, f, a)] - --- | Parse a "raw" tag, which we use to prevent other tags from creeping in. --- The format here is net-string-esque: a literal "<raw=" followed by a --- string of digits (base 10) denoting the length of the raw string, --- a literal ":" as digit-string-terminator, the raw string itself, and --- then a literal "/>". -rawParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -rawParser c f a = do - string "<raw=" - lenstr <- many1 digit - char ':' - case reads lenstr of - [(len,[])] -> do - guard ((len :: Integer) <= fromIntegral (maxBound :: Int)) - s <- count (fromIntegral len) anyChar - string "/>" - return [(Text s, c, f, a)] - _ -> mzero - --- | Wrapper for notFollowedBy that returns the result of the first parser. --- Also works around the issue that, at least in Parsec 3.0.0, notFollowedBy --- accepts only parsers with return type Char. -notFollowedBy' :: Parser a -> Parser b -> Parser a -notFollowedBy' p e = do x <- p - notFollowedBy $ try (e >> return '*') - return x - -iconParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -iconParser c f a = do - string "<icon=" - i <- manyTill (noneOf ">") (try (string "/>")) - return [(Icon i, c, f, a)] - -hspaceParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -hspaceParser c f a = do - string "<hspace=" - pVal <- manyTill digit (try (string "/>")) - return [(Hspace (fromMaybe 0 $ readMaybe pVal), c, f, a)] - -actionParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -actionParser c f act = do - string "<action=" - command <- choice [between (char '`') (char '`') (many1 (noneOf "`")), - many1 (noneOf ">")] - buttons <- (char '>' >> return "1") <|> (space >> spaces >> - between (string "button=") (string ">") (many1 (oneOf "12345"))) - let a = Spawn (toButtons buttons) command - a' = case act of - Nothing -> Just [a] - Just act' -> Just $ a : act' - s <- manyTill (allParsers c f a') (try $ string "</action>") - return (concat s) - -toButtons :: String -> [Button] -toButtons = map (\x -> read [x]) - --- | Parsers a string wrapped in a color specification. -colorParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -colorParser (TextRenderInfo _ _ _ bs) fidx a = do - c <- between (string "<fc=") (string ">") colors - let colorParts = break (==':') c - let (ot,ob) = case break (==',') (Prelude.drop 1 $ snd colorParts) of - (top,',':btm) -> (top, btm) - (top, _) -> (top, top) - tri = TextRenderInfo (fst colorParts) - (fromMaybe (-1) $ readMaybe ot) - (fromMaybe (-1) $ readMaybe ob) - bs - s <- manyTill (allParsers tri fidx a) (try $ string "</fc>") - return (concat s) - --- | Parses a string wrapped in a box specification. -boxParser :: TextRenderInfo -> FontIndex -> Maybe [Action] -> Parser [Segment] -boxParser (TextRenderInfo cs ot ob bs) f a = do - c <- between (string "<box") (string ">") - (option "" (many1 (alphaNum - <|> char '=' - <|> char ' ' - <|> char '#' - <|> char ','))) - let b = Box BBFull (BoxOffset C 0) 1 cs (BoxMargins 0 0 0 0) - let g = boxReader b (words c) - s <- manyTill - (allParsers (TextRenderInfo cs ot ob (g : bs)) f a) - (try $ string "</box>") - return (concat s) - -boxReader :: Box -> [String] -> Box -boxReader b [] = b -boxReader b (x:xs) = do - let (param,val) = case break (=='=') x of - (p,'=':v) -> (p, v) - (p, _) -> (p, "") - boxReader (boxParamReader b param val) xs - -boxParamReader :: Box -> String -> String -> Box -boxParamReader b _ "" = b -boxParamReader (Box bb off lw fc mgs) "type" val = - Box (fromMaybe bb $ readMaybe ("BB" ++ val)) off lw fc mgs -boxParamReader (Box bb (BoxOffset alg off) lw fc mgs) "offset" (a:o) = - Box bb (BoxOffset align offset) lw fc mgs - where offset = fromMaybe off $ readMaybe o - align = fromMaybe alg $ readMaybe [a] -boxParamReader (Box bb off lw fc mgs) "width" val = - Box bb off (fromMaybe lw $ readMaybe val) fc mgs -boxParamReader (Box bb off lw _ mgs) "color" val = - Box bb off lw val mgs -boxParamReader (Box bb off lw fc mgs@(BoxMargins mt mr mb ml)) ('m':pos) val = do - let mgs' = case pos of - "t" -> BoxMargins (fromMaybe mt $ readMaybe val) mr mb ml - "r" -> BoxMargins mt (fromMaybe mr $ readMaybe val) mb ml - "b" -> BoxMargins mt mr (fromMaybe mb $ readMaybe val) ml - "l" -> BoxMargins mt mr mb (fromMaybe ml $ readMaybe val) - _ -> mgs - Box bb off lw fc mgs' -boxParamReader b _ _ = b - --- | Parsers a string wrapped in a font specification. -fontParser :: TextRenderInfo -> Maybe [Action] -> Parser [Segment] -fontParser c a = do - f <- between (string "<fn=") (string ">") colors - s <- manyTill (allParsers c (fromMaybe 0 $ readMaybe f) a) (try $ string "</fn>") - return (concat s) - --- | Parses a color specification (hex or named) -colors :: Parser String -colors = many1 (alphaNum <|> char ',' <|> char ':' <|> char '#') diff --git a/src/Xmobar/Run/Template.hs b/src/Xmobar/Run/Template.hs index 87c84d3..68feacb 100644 --- a/src/Xmobar/Run/Template.hs +++ b/src/Xmobar/Run/Template.hs @@ -77,5 +77,6 @@ splitTemplate alignSep template = (ce,_:ri) -> [le, ce, ri] _ -> def _ -> def - where [l, r] = if length alignSep == 2 then alignSep else defaultAlign + where sep = if length alignSep == 2 then alignSep else defaultAlign + (l, r) = (head sep, sep !! 1) def = [template, "", ""] diff --git a/src/Xmobar/System/DBus.hs b/src/Xmobar/System/DBus.hs index 103a5a9..90bee2a 100644 --- a/src/Xmobar/System/DBus.hs +++ b/src/Xmobar/System/DBus.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : DBus @@ -17,9 +18,10 @@ module Xmobar.System.DBus (runIPC) where import DBus import DBus.Client hiding (interfaceName) import qualified DBus.Client as DC +import DBus.Socket import Data.Maybe (isNothing) import Control.Concurrent.STM -import Control.Exception (handle) +import Control.Exception import System.IO (stderr, hPutStrLn) import Control.Monad.IO.Class (liftIO) @@ -35,10 +37,10 @@ interfaceName :: InterfaceName interfaceName = interfaceName_ "org.Xmobar.Control" runIPC :: TMVar SignalType -> IO () -runIPC mvst = handle printException exportConnection +runIPC mvst = exportConnection `catches` [ + Handler(\ (ex :: ClientError) -> hPutStrLn stderr (clientErrorMessage ex)), + Handler(\ (ex :: SocketError) -> hPutStrLn stderr (socketErrorMessage ex))] where - printException :: ClientError -> IO () - printException = hPutStrLn stderr . clientErrorMessage exportConnection = do client <- connectSession requestName client busName [ nameDoNotQueue ] diff --git a/src/Xmobar/System/Environment.hs b/src/Xmobar/System/Environment.hs index 25802fe..0491bcc 100644 --- a/src/Xmobar/System/Environment.hs +++ b/src/Xmobar/System/Environment.hs @@ -13,14 +13,14 @@ ----------------------------------------------------------------------------- module Xmobar.System.Environment(expandEnv) where -import Data.Maybe (fromMaybe) -import System.Environment (lookupEnv) +import qualified Data.Maybe as M +import qualified System.Environment as E expandEnv :: String -> IO String expandEnv "" = return "" expandEnv (c:s) = case c of '$' -> do - envVar <- fromMaybe "" <$> lookupEnv e + envVar <- M.fromMaybe "" <$> E.lookupEnv e remainder <- expandEnv s' return $ envVar ++ remainder where (e, s') = getVar s @@ -36,12 +36,13 @@ expandEnv (c:s) = case c of False -> do remainder <- expandEnv $ drop 1 s return $ escString s ++ remainder - where escString s' = let (cc:_) = s' in + where escString (cc:_) = case cc of 't' -> "\t" 'n' -> "\n" '$' -> "$" _ -> [cc] + escString [] = "" _ -> do remainder <- expandEnv s diff --git a/src/Xmobar/Text/Loop.hs b/src/Xmobar/Text/Loop.hs index 05379cd..5d2c43f 100644 --- a/src/Xmobar/Text/Loop.hs +++ b/src/Xmobar/Text/Loop.hs @@ -45,4 +45,4 @@ eventLoop cfg signal tv = do updateString :: Config -> TVar [String] -> IO String updateString conf v = do s <- readTVarIO v - format conf (concat s) + return $ format conf (concat s) diff --git a/src/Xmobar/Text/Output.hs b/src/Xmobar/Text/Output.hs index 783a5bb..677b6d2 100644 --- a/src/Xmobar/Text/Output.hs +++ b/src/Xmobar/Text/Output.hs @@ -15,13 +15,15 @@ module Xmobar.Text.Output (initLoop, format) where -import Xmobar.Config.Types (Config(textOutputFormat, additionalFonts, font) - , TextOutputFormat(..)) -import Xmobar.Run.Parsers ( Segment - , Widget(..) - , parseString - , tColorsString - , colorComponents) +import Xmobar.Config.Types ( Config (..) + , TextOutputFormat (..) + , Segment + , Widget (..) + , tColorsString) + + +import Xmobar.Config.Parse (colorComponents) +import Xmobar.Config.Template (parseString) import Xmobar.Text.Ansi (withAnsiColor) import Xmobar.Text.Pango (withPangoMarkup) @@ -47,9 +49,9 @@ formatWithColor conf (Hspace n, i, x, y) = formatWithColor conf (Text $ replicate (fromIntegral n) ' ', i, x, y) formatWithColor _ _ = "" -format :: Config -> String -> IO String +format :: Config -> String -> String format conf s = do - segments <- parseString conf s + let segments = parseString conf s case textOutputFormat conf of - Swaybar -> return $ formatSwaybar conf segments - _ -> return (concatMap (formatWithColor conf) segments) + Swaybar -> formatSwaybar conf segments + _ -> concatMap (formatWithColor conf) segments diff --git a/src/Xmobar/Text/Swaybar.hs b/src/Xmobar/Text/Swaybar.hs index a2fc585..355de06 100644 --- a/src/Xmobar/Text/Swaybar.hs +++ b/src/Xmobar/Text/Swaybar.hs @@ -24,16 +24,16 @@ import Data.ByteString.Lazy.UTF8 (toString) import GHC.Generics -import Xmobar.Config.Types (Config (additionalFonts)) - -import Xmobar.Run.Parsers ( Segment - , Widget(..) - , Box(..) - , BoxBorder(..) - , FontIndex - , tBoxes - , tColorsString - , colorComponents) +import Xmobar.Config.Types ( Config (additionalFonts) + , Segment + , Widget(..) + , Box(..) + , BoxBorder(..) + , FontIndex + , tBoxes + , tColorsString) + +import Xmobar.Config.Parse (colorComponents) import Xmobar.Text.SwaybarClicks (startHandler) import Xmobar.Text.Pango (withPangoFont) diff --git a/src/Xmobar/X11/Bitmap.hs b/src/Xmobar/X11/Bitmap.hs index b14356f..c5304d9 100644 --- a/src/Xmobar/X11/Bitmap.hs +++ b/src/Xmobar/X11/Bitmap.hs @@ -2,7 +2,7 @@ ----------------------------------------------------------------------------- -- | -- Module : X11.Bitmap --- Copyright : (C) 2013, 2015, 2017, 2018, 2022 Alexander Polakov +-- Copyright : (C) 2013, 2015, 2017, 2018, 2022, 2024 Alexander Polakov -- License : BSD3 -- -- Maintainer : jao@gnu.org @@ -116,8 +116,9 @@ loadBitmap d w p = do drawBitmap :: Display -> Drawable -> GC -> String -> String -> Position -> Position -> Bitmap -> IO () drawBitmap d p gc fc bc x y i = - withColors d [fc, bc] $ \[fc', bc'] -> do - let w = width i + withColors d [fc, bc] $ \cs -> do + let (fc', bc') = (head cs, cs !! 1) + w = width i h = height i y' = 1 + y - fromIntegral h `div` 2 setForeground d gc fc' diff --git a/src/Xmobar/X11/Draw.hs b/src/Xmobar/X11/Draw.hs index a056136..a1ec901 100644 --- a/src/Xmobar/X11/Draw.hs +++ b/src/Xmobar/X11/Draw.hs @@ -25,7 +25,6 @@ import Foreign.C.Types as FT import qualified Graphics.X11.Xlib as X11 import qualified Xmobar.Config.Types as C -import qualified Xmobar.Run.Parsers as P import qualified Xmobar.Draw.Types as D import qualified Xmobar.Draw.Cairo as DC @@ -38,11 +37,8 @@ import qualified Xmobar.X11.XRender as XRender #endif drawXBitmap :: T.XConf -> X11.GC -> X11.Pixmap -> D.IconDrawer -drawXBitmap xconf gc p h v path = do +drawXBitmap xconf gc p h v path fc bc = do let disp = T.display xconf - conf = T.config xconf - fc = C.fgColor conf - bc = C.bgColor conf case M.lookup path (T.iconCache xconf) of Just bm -> liftIO $ B.drawBitmap disp p gc fc bc (round h) (round v) bm Nothing -> return () @@ -69,7 +65,7 @@ withPixmap disp win (X11.Rectangle _ _ w h) depth action = do X11.sync disp True return res -draw :: [[P.Segment]] -> T.X [D.ActionPos] +draw :: [[C.Segment]] -> T.X [D.ActionPos] draw segments = do xconf <- ask let disp = T.display xconf @@ -89,7 +85,7 @@ draw segments = do #ifdef XRENDER color = C.bgColor conf alph = C.alpha conf - XRender.drawBackground disp p color alph (X11.Rectangle 0 0 w h) + XRender.drawBackground disp p color alph rect #endif CS.withXlibSurface disp p vis (fromIntegral w) (fromIntegral h) render diff --git a/src/Xmobar/X11/Events.hs b/src/Xmobar/X11/Events.hs index 4334f6b..fbd2bd0 100644 --- a/src/Xmobar/X11/Events.hs +++ b/src/Xmobar/X11/Events.hs @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.X11.Events --- Copyright: (c) 2018 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2018, 2022 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -17,20 +17,19 @@ module Xmobar.X11.Events(nextEvent') where -import Control.Concurrent -import System.Posix.Types (Fd(..)) +import qualified Control.Concurrent as C +import qualified System.Posix.Types as T -import Graphics.X11.Xlib ( - Display(..), XEventPtr, nextEvent, pending, connectionNumber) +import qualified Graphics.X11.Xlib as X -- | A version of nextEvent that does not block in foreign calls. -nextEvent' :: Display -> XEventPtr -> IO () +nextEvent' :: X.Display -> X.XEventPtr -> IO () nextEvent' d p = do - pend <- pending d + pend <- X.pending d if pend /= 0 - then nextEvent d p + then X.nextEvent d p else do - threadWaitRead (Fd fd) + C.threadWaitRead (T.Fd fd) nextEvent' d p where - fd = connectionNumber d + fd = X.connectionNumber d diff --git a/src/Xmobar/X11/Loop.hs b/src/Xmobar/X11/Loop.hs index 599e680..2dfb34d 100644 --- a/src/Xmobar/X11/Loop.hs +++ b/src/Xmobar/X11/Loop.hs @@ -3,7 +3,7 @@ ------------------------------------------------------------------------------ -- | -- Module: Xmobar.App.X11EventLoop --- Copyright: (c) 2018, 2020, 2022 Jose Antonio Ortega Ruiz +-- Copyright: (c) 2018, 2020, 2022, 2023, 2024 Jose Antonio Ortega Ruiz -- License: BSD3-style (see LICENSE) -- -- Maintainer: jao@gnu.org @@ -22,6 +22,7 @@ import Prelude hiding (lookup) import Control.Concurrent as Concurrent import Control.Concurrent.STM as STM +import Control.Monad as MR import Control.Monad.Reader as MR import Data.Bits (Bits((.|.))) @@ -35,10 +36,10 @@ import qualified Graphics.X11.Xinerama as Xinerama import qualified Graphics.X11.Xrandr as Xrandr import qualified Xmobar.Config.Types as C +import qualified Xmobar.Config.Template as CT import qualified Xmobar.Run.Actions as A import qualified Xmobar.Run.Loop as L -import qualified Xmobar.Run.Parsers as P import qualified Xmobar.System.Utils as U import qualified Xmobar.System.Signal as S @@ -145,15 +146,14 @@ signalLoop xc@(T.XConf d r w fs is cfg) actions signalv strs = do r' <- W.repositionWin d w (NE.head fs) rcfg signalLoop (T.XConf d r' w fs is rcfg) actions signalv strs -parseSegments :: C.Config -> STM.TVar [String] -> IO [[P.Segment]] +parseSegments :: C.Config -> STM.TVar [String] -> IO [[C.Segment]] parseSegments conf v = do s <- STM.readTVarIO v - let l:c:r:_ = s ++ repeat "" - MR.liftIO $ mapM (P.parseString conf) [l, c, r] + return $ map (CT.parseString conf) (take 3 $ s ++ repeat "") -updateIconCache :: T.XConf -> [[P.Segment]] -> IO T.XConf +updateIconCache :: T.XConf -> [[C.Segment]] -> IO T.XConf updateIconCache xc@(T.XConf d _ w _ c cfg) segs = do - let paths = [p | (P.Icon p, _, _, _) <- concat segs] + let paths = [p | (C.Icon p, _, _, _) <- concat segs] c' <- Bitmap.updateCache d w c (C.iconRoot cfg) paths return $ xc {T.iconCache = c'} diff --git a/src/Xmobar/X11/Window.hs b/src/Xmobar/X11/Window.hs index ad7ebf7..87d56f4 100644 --- a/src/Xmobar/X11/Window.hs +++ b/src/Xmobar/X11/Window.hs @@ -86,10 +86,14 @@ setPosition c p rs ht = T.Top -> X.Rectangle rx ry rw h T.TopP l r -> X.Rectangle (rx + fi l) ry (rw - fi l - fi r) h T.TopH ch -> X.Rectangle rx ry rw (mh ch) + T.TopHM ch l r t _ -> + X.Rectangle (rx + fi l) (ry + fi t) (rw - fi l - fi r) (mh ch) T.TopW a i -> X.Rectangle (ax a i) ry (nw i) h T.TopSize a i ch -> X.Rectangle (ax a i) ry (nw i) (mh ch) T.Bottom -> X.Rectangle rx ny rw h T.BottomH ch -> X.Rectangle rx (ny' ch) rw (mh ch) + T.BottomHM ch l r _ b -> + X.Rectangle (rx + fi l) (ry + fi rh - fi b - fi (mh ch)) (rw - fi l - fi r) (mh ch) T.BottomW a i -> X.Rectangle (ax a i) ny (nw i) h T.BottomP l r -> X.Rectangle (rx + fi l) ny (rw - fi l - fi r) h T.BottomSize a i ch -> X.Rectangle (ax a i) (ny' ch) (nw i) (mh ch) @@ -160,18 +164,20 @@ getRootWindowHeight srs = maximum (map getMaxScreenYCoord srs) getStrutValues :: X.Rectangle -> T.XPosition -> Int -> [Int] getStrutValues r@(X.Rectangle x y w h) p rwh = case p of - T.OnScreen _ p' -> getStrutValues r p' rwh - T.Top -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0] - T.TopH _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0] - T.TopP _ _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0] - T.TopW _ _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0] - T.TopSize {} -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0] - T.Bottom -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw] - T.BottomH _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw] - T.BottomP _ _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw] - T.BottomW _ _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw] - T.BottomSize {} -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw] - T.Static {} -> getStaticStrutValues p rwh + T.OnScreen _ p' -> getStrutValues r p' rwh + T.Top -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.TopH _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.TopHM _ _ _ _ b -> [0, 0, st+b, 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.TopP _ _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.TopW _ _ -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.TopSize {} -> [0, 0, st , 0 , 0, 0, 0, 0, nx, nw, 0 , 0 ] + T.Bottom -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw] + T.BottomH _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw] + T.BottomHM _ _ _ t _ -> [0, 0, 0 , sb+t, 0, 0, 0, 0, 0 , 0 , nx, nw] + T.BottomP _ _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw] + T.BottomW _ _ -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw] + T.BottomSize {} -> [0, 0, 0 , sb , 0, 0, 0, 0, 0 , 0 , nx, nw] + T.Static {} -> getStaticStrutValues p rwh where st = fi y + fi h sb = rwh - fi y nx = fi x @@ -12,6 +12,10 @@ flags: extra-deps: - netlink-1.1.1.0 - libmpd-0.9.2.0 + - cairo-0.13.8.2 + - pango-0.13.8.2 + - glib-0.13.8.2 + - gtk2hs-buildtools-0.13.8.3 nix: packages: - alsaLib diff --git a/xmobar.cabal b/xmobar.cabal index 8b331f5..e6de840 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -1,5 +1,5 @@ name: xmobar -version: 0.45 +version: 0.49 homepage: https://codeberg.org/xmobar/xmobar synopsis: A Minimalistic Text Based Status Bar description: Xmobar is a minimalistic text based status bar. @@ -84,6 +84,10 @@ flag with_rtsopts description: Use -with-rtsopts=-V0 to reduce wakeups. default: True +flag with_shared + description: Use shared libraries. Required when dependencies are built as shared libraries. + default: False + flag with_weather description: Enable weather plugin. default: True @@ -109,13 +113,13 @@ library other-modules: Paths_xmobar, Xmobar.Config.Types, Xmobar.Config.Parse, + Xmobar.Config.Template, Xmobar.Run.Types, Xmobar.Run.Timer, Xmobar.Run.Template, Xmobar.Run.Exec, Xmobar.Run.Runnable Xmobar.Run.Actions, - Xmobar.Run.Parsers, Xmobar.Run.Loop, Xmobar.Draw.Boxes, Xmobar.Draw.Cairo, @@ -194,15 +198,16 @@ library build-depends: aeson >= 1.4.7.1, async, - base >= 4.11.0 && < 4.17, + base >= 4.11.0 && < 4.20, bytestring >= 0.10.8.2, cairo >= 0.13, colour >= 2.3.6, containers, directory, + extra, extensible-exceptions == 0.1.*, filepath, - mtl >= 2.1 && < 2.3, + mtl >= 2.1 && < 2.4, old-locale, pango >= 0.13, parsec == 3.1.*, @@ -232,6 +237,9 @@ library if flag(with_rtsopts) cpp-options: -DRTSOPTS + if flag(with_shared) + cpp-options: -DSHARED_LIBRARIES + if flag(with_xrender) build-depends: X11-xft >= 0.2 other-modules: Xmobar.X11.XRender @@ -255,7 +263,7 @@ library cereal >= 0.5.8.1 cpp-options: -DUSE_NL80211 - if flag(with_mpd) || flag(all_extensions) + if flag(with_mpd) || (flag(all_extensions) && impl(ghc < 9.4)) build-depends: libmpd >= 0.9.2.0 other-modules: Xmobar.Plugins.Monitors.MPD cpp-options: -DLIBMPD |