mwm: Make sure clients managed by mwm are in NormalState
Sharing of individual windows in Google Meets is not working because
the client state is not set, causing the windows not to be recognized
as sharable.
This commit makes sure the client state is set to NormalState when a
client is attached to (i.e. managed by) mwm.
monitor: Update indicator geometry when monitor geometry changes
The indicator geometry is not updated when the monitor geometry is
changed, causing the indicator size and/or position to be wrong when
the resolution or position of a monitor is changed.
This commit makes sure the indicator geometry is updated when the
geometry of the containing monitor is changed.
Matthias Kruk [Mon, 21 Jun 2021 21:55:18 +0000 (06:55 +0900)]
monitor: Use double-buffering to draw the status bar
The status bar sometimes flickers when it is redrawn because the
displayed bar is redrawn directly, without getting buffered.
This commit adds an intermediary buffer that is used to render the
status bar before its contents are copied into its window.
Matthias Kruk [Sat, 12 Jun 2021 05:31:08 +0000 (14:31 +0900)]
mwm: Implement rendering text vertically (not 縦書き)
To write status messages on vertical client indicators, we need to
be able to render text vertically.
This commit adds the mwm_render_text_vertical() function, which
renders text and rotates it 90 degrees clockwise.
Matthias Kruk [Thu, 10 Jun 2021 23:37:30 +0000 (08:37 +0900)]
monitor: Allow rendering of text on horizontal client indicators
The client indicators provide a lot of space that could be used to
display useful information.
This commit implements rendering of text on horizontal client
indicators.
Matthias Kruk [Thu, 10 Jun 2021 00:17:46 +0000 (09:17 +0900)]
monitor: Don't XMapRaise() statusbar every time it is redrawn
The statusbar is mapped raised everytime it is redrawn, even if it is
obscured by another window. If the other window is not tiled (that is,
its position and size are not controlled by mwm), it will try to bring
itself back to the front, and the two windows end up competing to be
on top of the stack.
This commit makes sure the statusbar is mapped only once, when it is
initialized. Since statusbars are never unmapped, there is no need to
map them every time they are redrawn.
Matthias Kruk [Wed, 9 Jun 2021 23:16:23 +0000 (08:16 +0900)]
mwm: Always set the border width
The border width is not set in _mwm_configure_request() if the client
did not request a specific border width. That means that clients that
leave their border width unspecified will end up with the default
border width (which is not zero).
This commit modifies _mwm_configure_request() to always set the
border width of a client to 0.
Matthias Kruk [Mon, 24 May 2021 21:51:53 +0000 (06:51 +0900)]
Fix a number of focus-related issues
The are a couple of issues with the way focusing is implemented (or
rather, neglected):
- Focusing on a different client does not change the keyboard focus
- The keyboard focus does not follow the pointer
- The keyboard focus does not change when clicking on a window
- The pointer does not follow the focus
This commit fixes the above issues by making the following changes:
- Focus on a client when the pointer enters it
- When focusing on a client, also move the keyboard focus
- When focusing on a client, move the pointer over the client
Matthias Kruk [Sun, 23 May 2021 22:09:01 +0000 (07:09 +0900)]
client: Redraw clients if their geometry has changed
If the geometry of a client has been changed using client_set_geometry(),
the client should be redrawn. This commit makes the function mark the
client as needing a redraw, so that it will be redrawn the next time that
the monitor/workspace is redrawn.
Matthias Kruk [Sun, 23 May 2021 22:00:24 +0000 (07:00 +0900)]
monitor: Draw the background of the status bar in the background color
The background of the status bar is drawn in the focus color of the
current palette, meaning that the bar has a different background color
on focused and non-focused screens. This is no problem per-se, but it
makes it hard to predict if a status message will be readable or not,
especially if it uses colored text.
This commit changes the status bar to be drawn in the background color
and the focus color be used to draw a border on the left and bottom
sides of the status bar.
Matthias Kruk [Sun, 23 May 2021 21:49:56 +0000 (06:49 +0900)]
monitor: Don't rearrange clients if monitor doesn't need redrawing
The monitor_redraw() function unconditionally rearranges the visible
clients when it is called. However, if redrawing was not explicitly
requested, this is not necessary.
This commit changes the monitor_redraw() function not to rearrange
clients if a redraw is not necessary, so that only the status bar
and indicators will be redrawn.
Matthias Kruk [Sun, 23 May 2021 21:41:46 +0000 (06:41 +0900)]
workspace: Don't redraw workspace if it doesn't need redrawing
The mwm_redraw() function is called to redraw the clients as well as
the status bar and other indicators. The current implementation calls
monitor_redraw() and workspace_redraw() on all monitors and workspaces,
respectively, so these functions must make sure not to redraw anything
if it isn't necessary.
This commit changes the workspace_redraw() function so it does not
redraw the workspace if it was not explicitly requested.
Matthias Kruk [Sun, 23 May 2021 21:29:25 +0000 (06:29 +0900)]
mwm: Ignore BadWindow errors
There are windows that cannot be reconfigured when running on Xorg
with xdm (I'm not sure about other configurations, but at least this
does not affect Xephyr). Avoid the problem by ignoring BadWindow
errors until a proper solution is found.
Matthias Kruk [Sun, 23 May 2021 21:20:50 +0000 (06:20 +0900)]
mwm: Add missing command names
The array of command names in mwm_cmd() is incomplete, causing the
window manager to crash if debugging is enabled and a command is
executed whose name is not in the array.
This commit adds the missing names to the array and changes the way
the index is determined so that similar issues will not occur in the
future.
Matthias Kruk [Sun, 23 May 2021 21:14:17 +0000 (06:14 +0900)]
mwm: Use stderr for debug output
The timing of debug messages written with printf() is wrong because
stdout is buffered by glibc. This commit changes debug output to be
written to stderr.
Matthias Kruk [Sun, 23 May 2021 21:03:17 +0000 (06:03 +0900)]
mwm: Manage clients that were started before the window manager
The current implementation of mwm will not manage windows of clients
that were started before the window manager itself. This commit makes
mwm scan for existing clients during initialization.
Matthias Kruk [Fri, 21 May 2021 22:47:24 +0000 (07:47 +0900)]
mwm: Handle as many events as possible before redrawing
The current implementation redraws the monitors (where necessary) after
each handled event. This leads to problems when an application destroys
or unmaps multiple windows in one go, because mwm will attempt to redraw
the destroyed windows for which it hasn't processed the destroy/unmap
event yet.
This commit changes the mwm_run() function to handle all queued events
before redrawing anything.
Matthias Kruk [Fri, 21 May 2021 21:14:33 +0000 (06:14 +0900)]
workspace: When the focused client is detached, focus on the next one
When the focused client is detached from a workspace, the focus is moved
to the first client of the workspace. However, from a user point-of-view,
it seems better to move the focus to the next client.
This commit changes the workspace_detach_client() function to shift the
focus to the next client, if the focused client is removed.
Matthias Kruk [Wed, 19 May 2021 21:19:59 +0000 (06:19 +0900)]
kbptr: Implement keyboard pointer
The pointer is typically very awkward to use, especially on devices with mice or
similar input devices. This commit adds an experimental keyboard pointer, which
allows the user to move the pointer and perform clicks through the keyboard.
The keyboard pointer follows this basic idea: The user can move the pointer in
four directions: North, East, South, West. The pointer has a horizontal stride
and a vertical stride (the size of a step in horizontal or vertical direction,
respectively). With each step, the respective stride is reduced by half.
The origin of the pointer is the center of the focused window, and the initial
horizontal and vertical stride are a quarter of the window's width and height,
respectively.
For example in a 100x100px window (the point (0, 0) being the top left corner),
the pointer's origin is (50, 50). If the pointer makes one step north, it will
be at (50, 25). Moving another step north will put the pointer at (50, 12.5).
The user can also hold the shift key while moving, which will cause the stride
to be reduced once before the movement and once after the movement (this seemed
useful for targets that are close to the pointer).
This pointer behavior has two implications:
1. If the stride reaches zero, the pointer can't be moved anymore
2. The pointer can never leave the window (it asymptotically approaches the
outermost pixel, strictly speaking)
Re-centering the pointer also replenishes the stride. If a user misses their
target, they have to start over from the center of the window. If a user wants
to point at another window, they have to move the focus to that window first.
Matthias Kruk [Wed, 19 May 2021 00:08:03 +0000 (09:08 +0900)]
mwm: Add functions for managing monitors, workspaces, clients, and more
This commit makes several enhancements to the mwm type. It adds functions
for:
- attaching, detaching, and searching monitors
- attaching, detaching, and searching workspaces
- attaching, detaching, and searching clients
- rendering UTF-8 using Pango and Xft
- dealing with X11 Graphic Contexts
- initializing colors and getting color values
- executing MWM commands (for keyboard shortcuts)
- dealing with X11 atoms
- reading the root window title
Matthias Kruk [Wed, 19 May 2021 00:02:56 +0000 (09:02 +0900)]
monitor: Implement statusbar and indicator bars
This implements the statusbar that indicates the active workspace
and displays the name of the root window (as status text).
This commit also implements the indicator bars, which highlight the
active/focused client (and will be used to display information about
clients in later versions).
Matthias Kruk [Tue, 18 May 2021 23:52:30 +0000 (08:52 +0900)]
workspace: Add functions for managing clients in workspaces
This commit adds functions to add and remove clients from workspaces,
arrange clients according to the monitor's layout function, and to
shift client positions within the workspace.
Matthias Kruk [Tue, 18 May 2021 23:34:09 +0000 (08:34 +0900)]
config: Add file for customization of themes and keyboard shortcuts
This commit adds a file that defines the mwm theme and a set of
keyboard shortcuts. This is where future customizations should be
added (and where other customizable settings should be moved).
Matthias Kruk [Tue, 18 May 2021 23:27:12 +0000 (08:27 +0900)]
theme: Add definitions for colors, palettes, and themes
Common definitions for colors, palettes, and themes are necessary
to make the style of mwm easily-customizable.
This commit adds a set of style-related types.
Matthias Kruk [Tue, 18 May 2021 23:23:05 +0000 (08:23 +0900)]
common: Add functions for comparing geoms and pointers
The loop_find() function needs a fallback comparison function to use
if no other comparison function was provided. This commit adds a
comparison function that compares two pointers.
Further, this commit adds a function that calculates the intersecting
area of two geometries.
Matthias Kruk [Tue, 18 May 2021 23:19:30 +0000 (08:19 +0900)]
layout: Add infrastructure and client layout functions
Infrastructure to support layout functions, and layout functions
themselves are necessary to correctly display a workspace. This
commit adds the necessary infrastructure to enable swift
implementations of layout functions.
Further, this commit adds a horizontal and a vertical layout
function.
Matthias Kruk [Tue, 18 May 2021 23:15:16 +0000 (08:15 +0900)]
main: Keep a pointer to the mwm instance in a global variable
There are cases when we cannot pass a pointer to the mwm context
directly. In these cases, we will need to refer to the mwm instance
through a global variable. This commit adds the global reference.
Matthias Kruk [Tue, 18 May 2021 23:10:38 +0000 (08:10 +0900)]
array: Remove type
All arrays that had been used for storing workspaces, clients, etc
have been replaced with loops. This removes the array implementation
since it is not used anymore.
Matthias Kruk [Tue, 18 May 2021 23:03:51 +0000 (08:03 +0900)]
loop: Add convenience functions and a foreach function without data
This commit adds convenience functions to the loop data type that
allow the caller to find the elements that come before or after an
element in a loop.
This further adds functions to shift the position of an element in
the loop to the back or the front, and a foreach function that
passes only the element pointer to the callback (this is useful for
calling things like free() from the foreach function).
Matthias Kruk [Sat, 8 May 2021 01:18:33 +0000 (10:18 +0900)]
loop: Fix several issues in the loop implementation
There were several bugs in the loop implementation, most notably
in the search and remove methods. This commit fixes the bugs so
that it is possible to retrieve elements and remove elements
from loop structures.
Matthias Kruk [Mon, 3 May 2021 21:31:01 +0000 (06:31 +0900)]
mwm: Use loopy lists to keep track of workspaces and monitors
The arrays used by the mwm type to track workspaces and monitors are
not ideal for some operations if they are sparsely populated.
This commit replaces them with cyclic lists.
Matthias Kruk [Mon, 3 May 2021 21:27:50 +0000 (06:27 +0900)]
workspace: Add type for keeping track of workspaces
A data type is needed that clients can be attached to, and that monitors
can be associated with so that they display a set of clients.
This commit adds the workspace type that keeps track of a set of clients
and can be displayed by a monitor.
Matthias Kruk [Mon, 3 May 2021 21:18:24 +0000 (06:18 +0900)]
loop: Add cyclic list type
Since we will often cycle through monitors, workspaces, and clients, it
would be beneficial to have a data structure that assists with that.
This commit adds the loop type, which implements a cyclic doubly-linked
list.
Matthias Kruk [Mon, 3 May 2021 00:25:10 +0000 (09:25 +0900)]
mwm: Implement monitor detection
Monitors connected to the X Server have to be detected in order to
provide meaningful window manager functionality.
This commit implements dynamic detection of monitors and adds events
that a callback can be connected to, so that it will be executed when
a monitor has been added.
Matthias Kruk [Sun, 2 May 2021 11:39:05 +0000 (20:39 +0900)]
array: Make array_get() return an error if an element wasn't set
The array_get() function returns success when an entry is retrieved that
was never set. This makes it hard to distinguish uninitialized entries.
This commit changes array_get() to return an error if the caller is
attempting to retrieve an uninitialized entry.
Matthias Kruk [Sun, 2 May 2021 00:56:27 +0000 (09:56 +0900)]
main: Instantiate and run mwm
The main() function currently does nothing but parse teh commandline.
This commit changes the main() function so that it creates an mwm
instance and subsequently initializes and executes it.
Matthias Kruk [Sun, 2 May 2021 00:51:26 +0000 (09:51 +0900)]
monitor: Add data type for monitor management
To keep track of connected monitors, a data type is necessary.
This commit adds the monitor datatype that is used to keep track
of the size and position of a monitor.