GithubHelp home page GithubHelp logo

herbstluftwm / herbstluftwm Goto Github PK

View Code? Open in Web Editor NEW
1.1K 33.0 66.0 5.21 MB

A manual tiling window manager for X11

Home Page: http://herbstluftwm.org/

License: Other

Makefile 0.15% C 2.26% Shell 3.22% C++ 58.95% Python 34.10% CSS 0.60% CMake 0.71%
herbstluftwm tiling window-manager

herbstluftwm's Introduction

herbstluftwm

badge badge

herbstluftwm is a manual tiling window manager for X. It licensed under the "Simplified BSD License" (see LICENSE).

  • the layout is based on splitting frames into subframes which can be split again or can be filled with windows (similar to i3/ musca)

  • tags (or workspaces or virtual desktops or …) can be added/removed at runtime. Each tag contains an own layout

  • exactly one tag is viewed on each monitor. The tags are monitor independent (similar to xmonad)

  • it is configured at runtime via ipc calls from herbstclient. So the configuration file is just a script which is run on startup. (similar to wmii/musca)

For more, see the herbstluftwm homepage — in particular the herbstluftwm tutorial for the first steps (also available as man herbstluftwm-tutorial after installing herbstluftwm on your system).

You are welcome to join the IRC channel #herbstluftwm on irc.libera.chat.

Installation

If you want to build herbstluftwm from source, see the INSTALL file.

herbstluftwm's People

Contributors

apm256 avatar baskerville avatar blarz avatar bmwiedemann avatar ctx avatar dario23 avatar dnnr avatar enzbang avatar flowdalic avatar gravndal avatar hpdeifel avatar ideasman42 avatar johnlate avatar juacq97 avatar madroach avatar manuelcoenenvwd avatar nehemie avatar nkrkv avatar ooesili avatar rudis avatar samtinel avatar siccegge avatar stettberger avatar svanrossem avatar t-wissmann avatar tg-x avatar the-compiler avatar wilriker avatar xiaq avatar ypnos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

herbstluftwm's Issues

Better exit status for lock_tag/unlock_tag

By milomouse in the Arch forum:

I notice that some commands always return 0 even if they've already been issued such as "lock_tag" and "unlock_tag", but I expect it's because they ran without error. This is fine but would it be possible for these commands (and maybe other similars I haven't checked yet) to return a non-zero exit status if they've already been executed correctly once before?

Feature request: rotate grid

As per Florian's suggestion, am posting this request submitted to the mailing list:

One feature I find convenient (coming from bspwm) is the ability to rotate a grid, much like the rotate (frame) action. I am hoping your rotate frame facility might make this easy enough to implement (with value +/- 1 for bi-directional control, of course)!

[ Regarding the "rotate" command, a nice-to-have would be a +/- 1 value to specify the direction of rotation, if possible. Reverse rotation (effectively 270 degrees) is easy enough to script but causes extra screen redraws and a noticeable flickering effect (system dependent). ] Just reread the detailed docs.. and found the lock/unlock example for rotate frame! Nice!

Having a blast with herbstluftwm coming from bspwm. Kudos to developers!
Regards, Steven

Window creation problems

Some clients have problems creating windows. This seems to be related to Java UI. Observed and reproducable with IntelliJ IDE, MySQL Workbench (both Java).

I observe two problems:

  • Sometimes the new window is too small (pseudotile)
  • Sometimes only a part of the window is drawn/handled
  • Sometimes both

In the second/third cases, this means that the client both only draws and accepts mouse input on a part of the window, as if it does not realize the window's real size. In some cases the window is also completely empty. It all can happen also in floating mode and it is pretty random (opening the same window several types leads to several different outcomes).

To investigate this further, I had the idea of maybe the window manager providing several window sizes to the application which might not keep up with the changes.

Below is some xev output (filtered all property setting etc. messages). The main difference I see is that hlwm reconfigures the window after it is already visible (but doesn't really change anything). Another observation is that in tiling mode, the window is first configured in the size requested by the client several times before it is eventually configured to fit into the layout.

For now I don't see a specific reason for the clients stumbling.

Tiling mode

CreateNotify event, serial 11, synthetic NO, window 0x5e00001,
    parent 0x5e00001, window 0x5e00002, (10,10), width 50, height 50
border_width 4, override NO

ConfigureNotify event, serial 28, synthetic NO, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (0,0), width 178, height 178,
    border_width 0, above 0x5600007, override NO

ReparentNotify event, serial 28, synthetic NO, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, parent 0x6466e4,
    (40,40), override NO

ConfigureNotify event, serial 28, synthetic NO, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (3,3), width 178, height 178,
    border_width 0, above 0x6466e5, override NO

ConfigureNotify event, serial 28, synthetic YES, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (0,0), width 178, height 178,
    border_width 0, above 0x0, override NO

ConfigureNotify event, serial 28, synthetic NO, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (3,3), width 1672, height 1041,
    border_width 0, above 0x6466e5, override NO

ConfigureNotify event, serial 28, synthetic YES, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (1924,4), width 1672, height 1041,
    border_width 0, above 0x0, override NO

VisibilityNotify event, serial 29, synthetic NO, window 0x5e00001,
    state VisibilityUnobscured

ConfigureNotify event, serial 29, synthetic YES, window 0x5e00001,
    event 0x5e00001, window 0x5e00001, (1924,4), width 1672, height 1041,
    border_width 0, above 0x0, override NO

Floating mode

Outer window is 0x6200001, inner window is 0x6200002

CreateNotify event, serial 11, synthetic NO, window 0x6200001,
    parent 0x6200001, window 0x6200002, (10,10), width 50, height 50
border_width 4, override NO

ConfigureNotify event, serial 28, synthetic NO, window 0x6200001,
    event 0x6200001, window 0x6200001, (0,0), width 178, height 178,
    border_width 0, above 0x5e00007, override NO

ReparentNotify event, serial 28, synthetic NO, window 0x6200001,
    event 0x6200001, window 0x6200001, parent 0x64698a,
    (40,40), override NO

ConfigureNotify event, serial 28, synthetic NO, window 0x6200001,
    event 0x6200001, window 0x6200001, (3,3), width 178, height 178,
    border_width 0, above 0x64698b, override NO

ConfigureNotify event, serial 28, synthetic YES, window 0x6200001,
    event 0x6200001, window 0x6200001, (0,0), width 178, height 178,
    border_width 0, above 0x0, override NO

ConfigureNotify event, serial 28, synthetic YES, window 0x6200001,
    event 0x6200001, window 0x6200001, (3,3), width 178, height 178,
    border_width 0, above 0x0, override NO

VisibilityNotify event, serial 28, synthetic NO, window 0x6200001,
    state VisibilityUnobscured

ConfigureNotify event, serial 28, synthetic YES, window 0x6200001,
    event 0x6200001, window 0x6200001, (3,3), width 178, height 178,
    border_width 0, above 0x0, override NO

OpenBox:

CreateNotify event, serial 11, synthetic NO, window 0x400001,
    parent 0x400001, window 0x400002, (10,10), width 50, height 50
border_width 4, override NO

ReparentNotify event, serial 18, synthetic NO, window 0x400001,
    event 0x400001, window 0x400001, parent 0x200534,
    (0,0), override NO

ConfigureNotify event, serial 20, synthetic NO, window 0x400001,
    event 0x400001, window 0x400001, (0,0), width 178, height 178,
    border_width 0, above 0x200560, override NO

ConfigureNotify event, serial 20, synthetic NO, window 0x400001,
    event 0x400001, window 0x400001, (1,20), width 178, height 178,
    border_width 0, above 0x200560, override NO

ConfigureNotify event, serial 21, synthetic YES, window 0x400001,
    event 0x400001, window 0x400001, (409,418), width 178, height 178,
    border_width 2, above 0x0, override NO

VisibilityNotify event, serial 34, synthetic NO, window 0x400001,
    state VisibilityUnobscured

Title doesn't get updated correctly with Qt applications

When a Qt application changes its window title, somehow hlwm doesn't recognize the title has changed. I can reproduce this with PyQt5 (qutebrowser) and Qt4 (otter browser) applications.

PyQt example:

import sys

from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication, QWidget

app = QApplication(sys.argv)
w = QWidget()
w.setWindowTitle("Hello")
w.show()
QTimer.singleShot(1000, lambda: w.setWindowTitle("World"))
app.exec_()

After a second, the title changes from "Hello" to "World". What I found out so far:

  • xprop | grep '^_NET_WM_NAME' shows the updated title
  • The window_title_changed hook is never emitted.
  • When I unfocus the window and focus it again, focus_changed is emitted with the old title ("Hello")
  • When I switch tags and switch back, the title is then updated (I get focus_changed with "World" when focusing it)

herbstshell

It'd be nice to have an example script which is essentially a REPL/shell for herbstclient.

Title in panel doesn't update when closing single window in frame

When there's a frame with a single window and it's closed, the title of that window persists in the panel.

window_title_changed is not emitted, and the panel doesn't update the title on tag_flags because that'd be too much noise.

We probably should emit window_title_changed without arguments in that situation.

original mail:

Simplest case: a tag, one frame and an xterm in it. I am running panel.sh,
to display tags, window title, date and time. For xterm, the window title
is the shell prompt string and current directory. If you simply exit from
the shell, say with ctrl-d, the window title remains in the panel. Switch
to another tag and then back to the original tag, and the title gets
updated correctly. I note that panel.sh does look for the
window_title_changed event, so I'm guessing that the window manager itself
is failing to generate the event in this case, but I haven't researched
this carefully so it's just a guess.

Note that if you have two xterms in the frame with different current
directories and thus different window titles, if you exit from one, the
window title in the panel gets updated correctly.

This is not an xterm-specific problem -- I'm just using xterm as a simple
way to reproduce this. If you have just a browser in a frame and close it,
the same problem occurs.

I'm running herbstluftwm 0.6.2-2 on an up-to-date 64-bit Arch Linux system.

discussion:

21:56 <The-Compiler> thorsten`: what do you think about the bug on the ML? Should hlwm emit title_changed when a window gets closed and none is active? Should panel.sh update the title on tag_flags?
22:00 <thorsten`> The-Compiler: Either window_title_changed or a new window_closed (which is only emitted if the focused window is closed). panel.sh shouldn't update the title on tag_flags because then, panel.sh has to think too much
22:01 <ypnos> do you really want to introduce new hooks at this point
22:01 <ypnos> it is getting pretty random
22:01 <thorsten`> yep
22:02 <thorsten`> so you prefer re-emitting window_title_changed?
22:02 <ypnos> if the current window disappears because it is moved to another tag window_closed might be expected but is not the right hook
22:02 <thorsten`> oh right
22:02 <thorsten`> then window_closed isn't the right way
22:03 <The-Compiler> +1 for window_title_changed fwiw
22:04 <The-Compiler> damn, that has a WINID
22:04 <The-Compiler> just emit window_title_changed with WINID 0 or -1 or so?
22:04 <ypnos> 0 is the root window, right?
22:04 <thorsten`> or without any arguments

Group commands/settings in manpage

The commands/settings get a bit much in the manpage. It might make sense to split them into logical groups (e.g. frames/tags/monitors/scripting/... commands)

Realtime view of resize in floating mode?

Is it possible to have the a real time view of the window when you re-size applications? Currently mouse left click and drag tries to resize it but it fills a color. Is it possible to make it real time?

hidden tags / monitors

Having some hidden-attribute for special tags/monitors so they don't show up in the panel and are ignored when cycling, for floatmon, etc.

There are some home-brewed solutions (custom attribute) but it'd make sense to have something standard here.

Also, IMHO these should not show up in tag_status or list_monitors unless some --all flag is passed.

Focus stealing bug

Sometimes, dwb or mpv steal the focus, and switching keyboard focus does not work (immediately focuses back to dwb/mpv again).

Maybe related (?): Some clients (steam) create windows which have focus without having the focus borde

Window contents move when focused

When focusing a window, the contents briefly move their positions and then move back which is a bit irritating. It's as if the thicker border caused the window to get a wrong size/position for a very short time.

Feature request: Lock workspace to specified monitor

Using 2 screens, you can have all workspaces on whatever monitor you desire. I would like an option so lock a workspace to a specified monitor. Say workspace 8 to monitor 2.
If you press the key combination to get to that workspace, it would move your mouse and focus to the workspace on the screen it's locked to. This makes it for example easy to have a web-browser on a second monitor at all times (except when you manually move the window to a different container/workspace of course).

Tray for panel.sh

Many people want a tray, but like the default panel.sh otherwise. We should provide some option to add a stalone/trayer with panel.sh.

object tree: Writable custom attributes

With frame objects, there are some custom attributes (notably layout) for which it would make sense to make it writable - but that's currently not possible.

hc rerule command

There should be a command to re-apply all rules to all current clients (suggested by rudi_s).

index argument for hc load

hc load could have an index argument which loads a layout into an existing frame instead of the root-frame.

Add an option to close all open windows

I would like to have an option added to herbstclient to close all open windows. Something like

herbstclient close all

This would make it easy to gracefully close all windows before issuing a reboot or shutdown command.

Update focus objects when removing a tag

When you remove a tag the tags.focus object gets deleted:

See the bug in action:

$ herbstclient chain , add testtag , merge_tag testtag
$ herbstclient attr tags.focus.name
Invalid path "tags.focus.name": No child "focus" in object tags
Invalid path "tags.focus.name": No child "focus" in object tags

And this patch seems to fix it:

diff --git a/src/tag.cpp b/src/tag.cpp
index d731819..a041b60 100644
--- a/src/tag.cpp
+++ b/src/tag.cpp
@@ -375,6 +375,7 @@ int tag_remove_command(int argc, char** argv, GString* output) {
     ewmh_update_desktops();
     ewmh_update_desktop_names();
     clientlist_foreach(client_update_tag, NULL);
+    tag_update_focus_objects();
     tag_set_flags_dirty();
     hook_emit_list("tag_removed", oldname, target->name->str, NULL);
     g_free(oldname);

There would be no need for this call when you remove an unfocused tag. But I couldn't find out how the tags.focus object gets deleted.

Single window floating

We could probably check how other tiling WMs with an internal tree (i3/bspwm come to mind) solves this issue.

Better multi-monitor tag switching

Some people find tag switching with multiple monitors confusing. Some ideas:

  • if tag X is shown on any monitor, focus it. If not, show tag on current monitor. (bl1nk in IRC)
  • mimic i3 behaviour -- lock a set of tags on a monitor, and then they always stay there (Rasi)

Compile warnings with -Wextra

Compiling with -Wextra gives us some additional warnings - maybe we should fix/workaround them and then compile using -Wextra for additional warnings? I caught some bugs in the wild in some of my programs this way.

Also, -Wextra still doesn't mean "all warnings"...

"auto" layout

Aligns windows either horizontally or vertically, depending on what's the longer side.

Not sure if it's too confusing though.

Negative offsets for rectangles

According to some standard (I don't remember which one it was...) HxW+X+Y also should accept negative offsets.

Probably minor, feel free to close if you disagree ;)

XFetchName doesn't always return a name.

Even though a window might have a WM_NAME property, XFetchName doesn't always return a name - for some reason. Googling around a bit I couldn't figure out why though. I noticed that herbstluftwm didn't name Steam's windows. Steam windows don't have a _NET_WM_NAME property, so herbstluftwm falls back to calling XFetchName to get the WM_NAME property.
Running herbstluftwm in verbose, it prints that "no title for window xxx found, using ''" when a Steam window is focused, where xxx is the ID of a Steam window. This means that XFetchName returned 0, even though using xprop shows the window to indeed have a WM_NAME property.

I did a test of the XGetWMName function, using code from this stack overflow thread [1], which returned the correct name, where XFetchName returned no name.

I propose to change XFetchName to XGetWMName.

[1] https://stackoverflow.com/questions/8825661/xfetchname-always-returns-0

move_previous option does not exist

There is a herbstclient command for use_previous, but not one for move_previous. I expected that option to exist since there are both a use_index and move_index.

Could we add the use_previous function?

Feature request: Make herbstclient -i interactive

Instead of "idle", the herbstclient -i option should correspond to "interactive". That means that it receives commands, like in a basic interactive shell. The idea is that scripts can use hold a connection open for a longer time and perform atomic operations. They can also directly respond to hook messages.

To perform an atomic operation, there need be a new locking/unlocking command. This would hold back processing of all other party's input until the operation is finished. An exception is any single reload commands. Keybindings could also be made a general exception as an option to the locking command.

This makes it possible to perform more complex and atomic operations with herbstluftwm outside of hlwm's shell-like capabilities, by using a scripting language of choice.

While this feature can also be implemented in the main branch, it was derived in a discussion about winterbreeze, where mktemp might not be implemented.

Spurious focus for client under mouse cursor

Whenever the focus is changed, the client under the mouse cursor temporarily gets focus. That is, it is sent focus in and focus out events.

This seems to happen on all focus changes, even if they happen in other frames etc.

It is easy to test this behavior with an application that reacts to focus (e.g. a terminal that changes the cursor shape) or xev.

Testbench

We should have some kind of automatic testbench using Xephyr.

We could probably get some ideas from i3 and other tiling WMs with testbenches.

I'd imagine using libherbstclient from #4 with python's unittest, but probably something else is possible as well.

Maximize command

A command like fullscreen, but still leaving padding intact.

WIP: http://git.the-compiler.org/herbstluftwm/log/?h=pseudofullscreen

Rough todo:

  • Rebase on master
  • Make sure everything is renamed from pseudofullscreen to maximize
  • Check if EWMH fullscreen stuff is handled correctly
  • Check on which slice the window should be on
  • Maybe the window should be raised in tiling mode and not in floating mode?

objecttree: foreach

Some people wanted a hc foreach tags ... to do some action for each child of an object in the tree. This pushes one step closer to a turing-complete hlwm but still should not cause any possible hangs.

Moving window to focused tag not (always) in view on tag

I implemented a simple hide window function which simply moves the focused window to (tick) 'tag

Subsequently restoring the pseudo hidden window from 'tag to the tag in focus with

herbstclient chain . lock . use "'$tag" . move $tag . use $tag . unlock

occaisionally results in the "restored" window not in view. Clicking the mouse in the resulting empty window region, focuses the window into view. This doesn't happen all the time and appears to be tied to ncurses terminal apps and the last remaining window moved from 'tag (though, I haven't run enough scenarios to be 100% certain it's always the last remaining window).

The problem is solved simply by bringing the window instead with:

herbstclient chain . lock . use "'$tag"
winid=$(herbstclient attr clients.focus | grep 's - winid' | cut -d'"' -f2)
herbstclient chain . use $tag . bring $winid . unlock

Not sure if this is a bug or not (I would think the window should at least be in view). As reported, MOST of the time, the moved window to the tag in focus, was visible and had focus (without the raise command). Bring made this 100% reliable.

Update _NET_WM_DESKTOP atom for all clients when removing a tag

When you remove a tag, you need to update the _NET_WM_DESKTOP atom for all clients.

  • Steps to reproduce this bug:
    • start an EWMH panel like bmpanel2 or lxpanel (or look at the _NET_WM_DESKTOP atoms)
    • create 3 tags with at least one client on the second and third tag (A,B,C)
    • remove the first tag (A)
  • What you would expect:
    • the panel shows the clients on the correct tag
  • What happens (on the panel):
    • on the first tag (B) there is no client
    • on the second tag (C) you can see the client(s) from the previously second tag (B)
    • the client(s) of the second tag (C) are not shown on any tag

I couldn't find a way to ignore clients on tags with a lower index than the removed one.

This patch fixes the bug for me:

diff --git a/src/tag.cpp b/src/tag.cpp
index 8869bd0..d731819 100644
--- a/src/tag.cpp
+++ b/src/tag.cpp
@@ -301,6 +301,15 @@ int tag_rename_command(int argc, char** argv, GString* output) {
     return tag_rename(tag, argv[2], output);
 }

+static void client_update_tag(void* key, void* client_void, void* data) {
+    (void) key;
+    (void) data;
+    HSClient* client = (HSClient*)client_void;
+    if (client) {
+        ewmh_window_update_tag(client->window, client->tag);
+    }
+}
+
 int tag_remove_command(int argc, char** argv, GString* output) {
     // usage: remove TAG [TARGET]
     // it removes an TAG and moves all its wins to TARGET
@@ -365,6 +374,7 @@ int tag_remove_command(int argc, char** argv, GString* output) {
     ewmh_update_current_desktop();
     ewmh_update_desktops();
     ewmh_update_desktop_names();
+    clientlist_foreach(client_update_tag, NULL);
     tag_set_flags_dirty();
     hook_emit_list("tag_removed", oldname, target->name->str, NULL);
     g_free(oldname)

--skip-used/--skip-free for use-index

Jump to the next/previous tag with/without a client shown

Some people want that feature, and implementing it in a script with wraparound etc. is possible but ugly

Addressing of monitor by negative relative index doesn't wrap around 0

Example:

1) hc keybind $Mod-e focus_monitor +1
2) hc keybind $Mod-w focus_monitor -1

In case 1) when current monitor is the last one, +1 will match monitor with index 0 (wraps around end of the "list"). In case 2) when current monitor is the first one (0), -1 would not wrap around to match last monitor as one would expect from consistency point of view.

Feature request: Client size exposure/handling

It is not possible to set the window size for a pseudotile window. A current workaround is to switch to floating mode, resize the window, switch back.

In winterbreeze we should add width, height attributes that are exposed and can be set via object tree. Setting them needs to trigger the resp. updates.

A typical use-case is file open dialogs. Dialogs are pseudotile in many configurations, and the default dialog window size is unnecessary small. Blowing it up to the whole frame might also be inconvenient. Another example is a GUI calculator.

As a bonus, we could implement increment/decrement operation to the integer attribute setter. E.g. setting the attribute width to "+10" increases the window size by 10 pixels. However, this would not work when negative values are allowed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.