Compare commits

...

248 commits

Author SHA1 Message Date
tokyo4j
cd1a823fee seat: use CONNECT_SIGNAL() for new_virtual_pointer event 2025-10-25 20:41:38 +02:00
elviosak
4cdc6c435b
input/cursor.c: avoid consuming scroll on client mousebind 2025-10-24 22:26:18 +02:00
Johan Malm
df8e3d819c docs/: remove XML declarations in .xml files
...because we don't like them anymore and libxml2 does not consider them
mandatory.
2025-10-21 12:30:32 +09:00
John Lindgren
28cd504067 desktop: work around client-side rounding issues at right/bottom pixel
This also avoids a similar server-side rounding issue with some
combinations of wlroots and libwayland versions. See:

- https://gitlab.freedesktop.org/wayland/wayland/-/issues/555
- https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5159

Tested with qmpanel (similar to lxqt-panel) at 1x and 2x output scale.
Does not help if scaling is done client-side, e.g. QT_SCALE_FACTOR=2.

Fixes: #2379
Fixes: #3099
2025-10-20 20:11:08 +01:00
Johan Malm
1e406dd649 labnag: use overlay layer by default
Some checks failed
labwc.github.io / notify (push) Has been cancelled
...so that the dialog is still visible when some client is using
fullscreen mode.
2025-10-20 01:24:31 +02:00
Johan Malm
df3ed58d5b NEWS.md: interim update 2025-10-19 20:23:02 +01:00
tokyo4j
261ec3c509 scripts/check: run style check for test files
Co-authored-by: @johanmalm
2025-10-20 04:12:38 +09:00
tokyo4j
d8260feef2 CI: also run on t/ changes 2025-10-20 04:12:38 +09:00
tokyo4j
be44991def tests: remove placeholders for arguments 2025-10-20 04:12:38 +09:00
tokyo4j
7f67b9c866 Don't remove newlines when parsing config, menu and XBM
Removing newlines in rc.xml and menu.xml caused parser error with
following content:

<!--
 -
 - Some comments
 -
-->

...though it is a valid XML.

Let's not do that. I moved `grab_file()` to `buf.c` and renamed it to
`buf_from_file()`, because it now directly touches `struct buf` and
I don't like having a source file only for one function.
2025-10-17 22:08:41 +09:00
Weblate
eebf5b3e4e Translation updates from weblate
Co-authored-by: alvaroelpob <alvaropobladoresteban9@gmail.com>
Co-authored-by: p-bo <pavel.borecki@gmail.com>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ca/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/cs/
Translation: Labwc/labwc
2025-10-14 21:48:28 +01:00
tokyo4j
89fab2d449 theme: replace THEME_(IN)ACTIVE with SSD_(IN)ACTIVE
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-10-14 07:48:27 +02:00
Tomi Ollila
c78a0fe1b4 windowswitcher: show 's' as "state" for shaded views
While at it sorted the code to show 'm' before 's' and 's' before 'M'
- from the least visible to the most visible state.
2025-10-13 22:57:23 +02:00
Tobias Bengfort
77a11568a7 implement is_modal_dialog() for xdg shell 2025-10-14 04:19:08 +09:00
tokyo4j
953249249c rcxml: call labnag with --keyboard-focus on-demand by default
Some checks are pending
labwc.github.io / notify (push) Waiting to run
2025-10-13 19:03:43 +01:00
tokyo4j
ef73431367 labnag: add --keyboard-focus option
The new `--keyboard-focus [none|on-demand|exclusive]` option (default:
`none`) allows to some keyboard controls in labnag:

  Right-arrow or Tab: move the button selection to the right
  Left-arrow or Shift-Tab: move the button selection to the left
  Enter: press the selected button
  Escape: close labnag

The selected button is highlighted with the inner 1px border. Maybe we can
instead use different colors for the selected button, but I prefer the
inner border for now because it doesn't require us to add new color
options or make them inherit labwc's theme.
2025-10-13 19:03:43 +01:00
tokyo4j
03c70e8a5e labnag: remove redundant lines in conf_init() 2025-10-13 19:03:43 +01:00
tokyo4j
2b3aadb6af labnag: s/LAB_EXIT_TIMEOUT/LAB_EXIT_CANCELLED/ 2025-10-13 19:03:43 +01:00
Consolatis
364a1d5207 osd: allow window switcher to temporary unshade windows
This can be configured with a new unshade="yes|no"
argument for windowSwitcher in rc.xml

Fixes: #3111
2025-10-13 19:45:46 +02:00
tokyo4j
babd7af8f8 view: store title/app_id in view
This simplifies our codes and eliminates duplicated
`view.events.new_{title,app_id}` events. This should not change any
behaviors.
2025-10-14 02:27:13 +09:00
tokyo4j
27cc738985 osd-thumbnail: make sure item->{normal,active}_title are non-null
The if-statement doesn't make sense, because `view_get_string_prop()`
never returns NULL. And if it did, it would cause segfault in
`osd_thumbnail_update()`.
2025-10-14 02:27:13 +09:00
John Lindgren
da96513e70 menu: remove redundant cast
Some checks are pending
labwc.github.io / notify (push) Waiting to run
2025-10-12 14:15:19 -04:00
John Lindgren
40eed3915a osd,ssd: don't cast away const 2025-10-12 14:15:19 -04:00
John Lindgren
e6f54a0fc8 menu: use xmlFree() for return value of xmlGetProp() 2025-10-12 14:15:19 -04:00
tokyo4j
5e8df27f84 osd-classic: add theme options for selected window item
This commit adds new theme options:
- osd.window-switcher.style-classic.item.active.border.color
- osd.window-switcher.style-classic.item.active.bg.color

These theme options configures the border/background of selected window
item in the `classic` style window switcher. Their default values are
identical to `thumbnail` style window switcher, which means the default
border color is now `osd.label.text.color` with 50% opacity and the
default background color is now `osd.label.text.color` with 15% opacity.
2025-10-13 01:46:43 +09:00
tokyo4j
5f981226c2 action: simplify action_prompt_command() 2025-10-11 23:53:02 +09:00
tokyo4j
2f96664670 build: fix build with libinput as a subproject
Unfortunately, has_header_symbol() doesn't work with internal dependencies.

Ref: https://github.com/mesonbuild/meson/issues/13553
2025-10-11 23:51:28 +09:00
Johan Malm
70e5beb5ec build: bump version to 0.9.2
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-10-10 19:53:23 +01:00
tokyo4j
d94e5da815 view: fix unexpected view->tiled with SnapToEdge against centered view
In 2ac4811, I was missing that windows can be tiled to "center".
As a result, after executing
`<action name="SnapToEdge" combined="yes" direction="left" />` against a
center-tiled window, `view->tiled` is set to `CENTER|LEFT`.
2025-10-10 19:48:42 +01:00
Johan Malm
e44a489530 NEWS.md: update notes for 0.9.2 2025-10-10 19:37:40 +01:00
tokyo4j
6cdfe32af0 rcxml: move <maximizedDecoration> from <core> to <theme> 2025-10-09 22:01:05 +01:00
Tobias Bengfort
e1820adcd3 fix typo in comment 2025-10-10 00:19:22 +09:00
Tobias Bengfort
474c513ed6 fix double free for libxml2 < 2.13
xmlAddChild() only unlinks the second argument since libxml2 2.13.

regression from 503af105
2025-10-10 00:19:22 +09:00
tokyo4j
c27d4955a4 desktop-entry: fix wrong description of sfdo-icon flags 2025-10-09 00:59:43 +02:00
Consolatis
7166efe7bf CI: also run on clients/ changes 2025-10-08 22:17:48 +02:00
Johan Malm
017152da52 build: use spaces instead of tab 2025-10-08 21:05:25 +01:00
Consolatis
814af0ae4d desktop-entry.c: don't demote error messages with LABWC_DEBUG_LIBSFDO
Also add additional logging to tell users how to get
more information about failures to load the icon theme.
2025-10-08 20:23:12 +01:00
Consolatis
cb0a4b875e desktop-entry.c: on detecting a broken icon theme, fall back to hicolor
Fixes: #3126
Reported-By: Kreevoz
2025-10-08 20:23:12 +01:00
tokyo4j
998ff9e7b5 osd-thumbnail: update default colors of selected window item
Some checks failed
labwc.github.io / notify (push) Has been cancelled
Previously, the default values of
`osd.window-switcher.style-thumbnail.item.active.{bg,border}.color`
were blue. But they caused the selected window title in the window
switcher to be unreadable due to duplicated colors of the text and
background with Openbox themes like Numix.

Instead, this commit updates them to follow other themes configurations.
The default border color of the selected window item is now
`osd.label.text.color` with 50% opacity and the background is
`osd.label.text.color` with 15% opacity.

For subpixel antialiasing to work, the background color is calculated by
manually blending `osd.label.text.color` and `osd.bg.color`, rather than
just updating the alpha with 50% or 15%.
2025-10-07 19:47:50 +01:00
Johan Malm
bed0be8a88 src/common/graphic-helpers.c: fix declaration/definition arg name difference
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-10-01 21:18:44 +01:00
Johan Malm
0d0d1075cc include/common/scene-helpers: fix declaration/definition arg name difference 2025-10-01 21:18:44 +01:00
Johan Malm
4c1e66f6c8 include/common/buf.h: fix declaration/definition arg name difference 2025-10-01 21:18:44 +01:00
Johan Malm
389cef9c3b include/common/box.h: fix declaration/definition arg name difference 2025-10-01 21:18:44 +01:00
tokyo4j
e558d0d619 labnag: rename options for color 2025-10-01 20:10:33 +01:00
Johan Malm
c8581b3fed include/common/xml.h: fix declaration/definition arg name difference 2025-09-30 02:38:13 +02:00
Johan Malm
60d536304b Privatize view_append_children() 2025-09-29 20:22:46 +01:00
Johan Malm
9ec49144ac Privatize desktop_topmost_focusable_view() 2025-09-29 20:22:46 +01:00
Johan Malm
eb41c6a3b0 Privatize view_contains_window_type() 2025-09-29 20:22:46 +01:00
Johan Malm
2ea0f6fff4 Privatize output_manager_init() 2025-09-29 20:22:46 +01:00
Johan Malm
950c634cea Privatize xwayland_surface_from_view() 2025-09-29 20:22:46 +01:00
Johan Malm
286005e121 Privatize rcxml_parse_xml() 2025-09-29 20:22:46 +01:00
Johan Malm
040e25f38e Privatize private view_get_root() 2025-09-29 20:22:46 +01:00
Johan Malm
27f3097f8f build: add 'sections' option to show unused functions 2025-09-29 20:22:46 +01:00
tokyo4j
c5cd1f691d CI: use libwlroots-0.19-dev build-dep for Debian 2025-09-29 19:41:32 +01:00
tokyo4j
46bd1fef95 CI: add unit tests 2025-09-29 19:41:32 +01:00
tokyo4j
7e27f78662 test/xml: use xmlBufferContent()
xmlBuffer->content has been deprecated.
2025-09-29 19:41:32 +01:00
tokyo4j
1043a9becc test: fix build error in t/xml.c
38a1a9b broke `t/xml.c` due to `macros.h` requiring `wlr/version.h`.
This commit fixes it by adding `wlroots` as a direct dependency of the
test executables.
2025-09-29 19:41:32 +01:00
Johan Malm
94c980c6be action: fix UAF when using prompt during reconfigure
Reported-by: @jlindgren90

Fixes #3106
2025-09-26 21:25:34 +01:00
Johan Malm
c9030dcc5b CI: fix broken FreeBSD CI by setting -Dlibsfdo:b_ndebug=false
...because with with

    meson setup build -Dbuildtype=release -Db_ndebug=true \
        --werror --force-fallback-for=libsfdo

we get the following warning:

    In file included from ../subprojects/libsfdo/common/dirs.c:5:
    ../subprojects/libsfdo/include/common/membuild.h: In function ‘sfdo_membuild_validate’:
    ../subprojects/libsfdo/include/common/membuild.h:29:65: error: unused parameter ‘membuild’ [-Werror=unused-parameter]
       29 | static inline void sfdo_membuild_validate(struct sfdo_membuild *membuild) {

...because `sfdo_membuild_validate()` contains nothing but an `assert()`
and that therefore results in an `unused-parameter` warning with `NDEBUG`.

https://gitlab.freedesktop.org/vyivel/libsfdo/-/blob/main/include/common/membuild.h?ref_type=heads#L30
2025-09-26 19:06:21 +02:00
Johan Malm
26bd02d457 Add translate.h for HAVE_NLS includes/defines
...to shrink labwc.h footprint
2025-09-26 10:43:23 -04:00
Johan Malm
1692c47fa0 Remove unused function key_state_nr_pressed_keys() 2025-09-26 10:41:21 -04:00
Johan Malm
bdc8e1c546 Remove unused function lab_xml_get_node() 2025-09-26 10:41:21 -04:00
Johan Malm
ee87b4fc30 Remove unused function trim_last_field() 2025-09-26 10:41:21 -04:00
Johan Malm
34e52a40c7 Remove unused function node_layer_popup_from_node() 2025-09-26 10:41:21 -04:00
Johan Malm
139a5f0383 Remove unused function output_max_scale() 2025-09-26 10:41:21 -04:00
Johan Malm
0bf2678f9d Remove unused function scaled_font_buffer_set_max_width() 2025-09-26 10:41:21 -04:00
Johan Malm
6bbdc3c6dc Remove unused function menu_call_actions() 2025-09-26 10:41:21 -04:00
Johan Malm
7a5b7aa378 rcxml.h: minor tweaks to order of variables 2025-09-25 21:12:36 +01:00
Johan Malm
5fdebedcd9 labwc-config(5): document <promptCommand>
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-09-24 20:13:51 +01:00
Johan Malm
5765586636 config: add <core><promptCommand>
...to enable configuration of the action prompt command.

Also set some better defaults for labnag.

The new default command is:

    labnag \
        --message '%m' \
        --button-dismiss '%n' \
        --button-dismiss '%y' \
        --background '%b' \
        --text '%t' \
        --border '%t' \
        --border-bottom '%t' \
        --button-background '%b' \
        --button-text '%t' \
        --border-bottom-size 1 \
        --button-border-size 3 \
        --timeout 0

...where the conversion specifiers are defined as follows:

    %m: the `<prompt>` message option
    %n: _("No")
    %y: _("Yes")
    %b: osd.bg.color
    %t: osd.label.text.color

This config options also enables the use of a different dialog client, for
example like this:

    <core>
      <promptCommand>zenity --question --text="%m"</promptCommand>
    </core>
2025-09-24 20:13:51 +01:00
Johan Malm
7028e65154 labnag: fix segfault caused by providing --timeout as long option 2025-09-24 20:13:51 +01:00
tokyo4j
ebce406b11 font: remove 4px padding on the right
Added `menu.items.padding.x` padding between item text and arrow instead.

Replaced `if (!string)` with `if (string_null_or_empty(string))` in
`font_extents()` just as a minor optimization.
2025-09-22 18:23:33 +01:00
Johan Malm
141f932efa README.md: remove high-level scope summary
...as it is very old and not relevant anymore.
2025-09-21 20:50:59 +09:00
tokyo4j
24f39e3a41 default-bindings.h: set combine="yes" for SnapToEdge keybinds
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-09-19 16:23:23 +09:00
tokyo4j
2ac48116e1 action: allow SnapToEdge to combine two cardinal directions
This patch adds `combine` argument to (Toggle)SnapToEdge actions.
This allows to snap a window to e.g. up-left by running two actions:
- `<action name="SnapToEdge" direction="left" combine="yes" />`
- `<action name="SnapToEdge" direction="up" combine="yes" />`

Then running `<action name="SnapToEdge" direction="down" combine="yes" />`
snaps it to left again. This behavior is almost the same as KWin, except
that snapping a up-right-tiled window to right doesn't move it to the
right-adjacent output, but makes it right-tiled first.
2025-09-19 16:23:23 +09:00
tokyo4j
af6a0df231 view: remove an obsolete code in view_snap_to_edge()
We no longer need to call view_apply_tiled_geometry() there, since we now
clear view->tiled when dragging a tiled window since 9f51384.
2025-09-19 16:23:23 +09:00
Johan Malm
0db3b9309b libsfdo.wrap: update revision to v0.1.4 2025-09-18 23:42:53 +02:00
Johan Malm
387e62d87b README.md: remove yambar reference as discontinued 2025-09-17 22:38:35 +02:00
cunlem
c6503e299f Update labwc-actions.5.scd
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-09-16 20:27:02 +01:00
Johan Malm
268ef857db NEWS.md: interim update 2025-09-16 20:21:10 +01:00
tokyo4j
f09ace51bf view: fix <query monitor="current|left|right" />
Before this commit, <else> branch was always executed with
monitor="current", monitor="left" or monitor="right" queries.

For example:

<action name="If">
  <query monitor="current" />
  <then>
    <action />
  </then>
  <else>
    <action />
  </else>
</action>
2025-09-15 03:45:05 +09:00
John Lindgren
d54051d9c1 clang-format: tweak to match existing code a little better
"clang-format -i src/view.c" before:
  1 file changed, 204 insertions(+), 169 deletions(-)

"clang-format -i src/view.c" after:
  1 file changed, 181 insertions(+), 146 deletions(-)
2025-09-13 12:06:52 +01:00
John Lindgren
5ce20b2b95 rcxml: use const char* for string literals 2025-09-13 12:06:52 +01:00
John Lindgren
072d45d4b2 osd-thumbnail: put designated initializers in order 2025-09-13 12:06:52 +01:00
John Lindgren
0ce10f6afa interactive: add braces around case containing declaration 2025-09-13 12:06:52 +01:00
John Lindgren
bca0ec07ac rcxml: use fixed arrays for rc.title_buttons_*
These are just lists of enum lab_node_type, with a bounded size and
no middle-insertions/removals, so linked lists are overkill.

Also, the use of wl_list_for_each[_reverse] just to access the first or
last entry in the list (corner button) was weird.
2025-09-13 12:06:52 +01:00
thatonecoder (formerly Coccocoa's Helper)
e17ec0203c CONTRIBUTING.md: fix some typos, lots of Oxford commas
The primary change is “Github”/“github” ⇾ “GitHub”, but there are plenty of others.
2025-09-11 21:15:44 +01:00
Johan Malm
f2639226c7 labwc-config(5): add example for autoEnableOutputs
Some checks failed
labwc.github.io / notify (push) Has been cancelled
...with inspiration from example in #3059 by @jlindgren90
2025-09-09 21:34:22 +01:00
tokyo4j
9f7e532852 desktop: refactor get_cursor_context()
This patch should not change any behaviors.

This clarifies the semantics of cursor_context returned by
get_cursor_context() as I described in cursor.h; when cursor is on a
subsurface (e.g. xdg/x11/layer/session-lock), the returned ctx.surface
and ctx.node points to the subsurface rather than its parent.
2025-09-09 18:50:20 +09:00
tokyo4j
3a3b873d0e desktop: let get_cursor_context() return layer-popup subsurface
With this change, when a layer-popup has a subsurface and cursor is on
it, wl_pointer.enter/motion events are sent to the subsurface rather
than its parent layer-popup surface. I think this follows wayland spec
more closely.

Tested with my demo: https://github.com/tokyo4j/wayland-demo/tree/layer-popup
2025-09-09 18:50:20 +09:00
tokyo4j
3d670b772d desktop: don't use LAB_NODE_LAYER_SUBSURFACE node type
Instead, set ctx.type = LAB_NODE_LAYER_SURFACE for both layer-surfaces
and layer-subsurfaces.

This patch preserves the existing behaviors:
- Pressing a subsurface of an on-demand layer-surface gives pointer
  focus to the subsurface, but gives keyboard focus to the parent
  layer-surface (related: a5fcbfaf).
- Pressing a subsurface of a layer-surface doesn't close a popup
  (related: a89bcc3c).
2025-09-09 18:50:20 +09:00
tokyo4j
574b20fbff ssd: attach LAB_NODE_SSD_ROOT to ssd->tree
This doesn't change any behaviors.

Attaching LAB_NODE_NONE node-descriptor to ssd->tree looks strange, this
patch uses new LAB_NODE_SSD_ROOT instead. The node-descriptor attached to
ssd->tree is needed for get_cursor_context() to detect cursor hovering on
borders/extents.

I also updated get_cursor_context() to make my intent clearer.
2025-09-08 15:46:36 +09:00
tokyo4j
b9b23f5931 output: remove node descriptors 2025-09-08 15:46:36 +09:00
tokyo4j
fb3dcb7959 scaled-buffer: remove *_from_node() functions 2025-09-08 15:46:36 +09:00
tokyo4j
3923b27384 desktop.c: don't print errors when cursor is on resize-indicator
In f347a81, I thought there are only window contents and SSD under
`view->scene_tree` and forgot about the resize-indicator.

I also refactored the logic around it:
- Remove `ret.node->type == WLR_SCENE_NODE_BUFFER` check since it's
  already done by `lab_wlr_surface_from_node()`
- Eliminate duplicated call to `lab_wlr_surface_from_node()`
2025-09-07 22:00:01 +01:00
Consolatis
b02d7d0e18 src/output.c: restore drm lease include
Introduced in #3062.

Its usage is guarded by a wlroots version check
which prevented the CI to detect the issue.

When compiled with a wlroots version > 0.19.0
(like the chase 0.20 PR) the error shows up.
2025-09-08 00:51:22 +09:00
John Lindgren
d2ce31fcc9 tree-wide: use forward declarations for wlr types 2025-09-07 19:34:30 +09:00
John Lindgren
b00873a988 src: remove unused #includes (via include-what-you-use) 2025-09-07 19:34:30 +09:00
John Lindgren
7c185c1a85 include: reduce unnecessary #includes 2025-09-07 19:34:30 +09:00
John Lindgren
e9f17dc4a2 array: use die_if_null() from common/mem.c 2025-09-07 19:17:18 +09:00
John Lindgren
a29bf5366f idle_manager: remove unused parameter and field
wlr_seat isn't used anywhere.
2025-09-07 19:17:18 +09:00
Weblate
2b26a2c73f Translation updates from weblate
Co-authored-by: virtual-hand <handvirtual@tutamail.com>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/pt_BR/
Translation: Labwc/labwc
2025-09-06 16:39:14 -04:00
John Lindgren
d14f5ca228 ssd: update comments referencing ssd_part/ssd_part_type 2025-09-06 16:00:20 -04:00
John Lindgren
f129571779 ssd: unify struct ssd_part with struct node_descriptor
struct ssd_part and struct node_descriptor seem to have essentially the
same purpose: tag a wlr_scene_node with some extra data indicating what
we're using it for.

Also, as with enum ssd_part_type (now lab_node_type), ssd_part is used
for several types of nodes that are not part of SSD.

So instead of the current chaining (node_descriptor -> ssd_part), let's
flatten/unify the two structs.

In detail:

- First, merge node_descriptor_type into lab_node_type.
- Add a separate view pointer in node_descriptor, since in the case of
  SSD buttons we need separate view and button data pointers.
- Rename ssd_part_button to simply ssd_button. It no longer contains
  an ssd_part as base.
- Add node_try_ssd_button_from_node() which replaces
  node_ssd_part_from_node() + button_try_from_ssd_part().
- Factor out ssd_button_free() to be called in node descriptor destroy.
- Finally, get_cursor_context() needs a little reorganization to handle
  the unified structs.

Overall, this simplifies the code a bit, and in my opinion makes it
easier to understand. No functional change intended.
2025-09-06 16:00:20 -04:00
John Lindgren
ba426e2271 ssd: eliminate ssd_hover_state (addressing a FIXME) 2025-09-06 16:00:20 -04:00
John Lindgren
1188534876 common: add node-type.c/h (renaming ssd_part_type to lab_node_type)
ssd_part_type contains several node types that are not actually part of
server-side decorations (ROOT, MENU, OSD, etc.)

Rename it accordingly and move it to a common location, along with some
related conversion/comparison functions.
2025-09-06 16:00:20 -04:00
John Lindgren
502473f343 theme: fix spelling of LAB_BS_HOVERED 2025-09-06 16:00:20 -04:00
tokyo4j
98c77cd6a7 ssd-titlebar: don't bind ssd_part to ssd->tree
Fixes up f347a81. This mistake didn't cause misbehaviors because the
ssd_part bound to ssd->tree is just a placeholder to let
get_cursor_context() call ssd_get_resizing_type() when the cursor is on
border/extents.
2025-09-06 16:00:20 -04:00
tokyo4j
130bbc9e6f view.c: remove cruft in view_apply_maximized_geometry() 2025-09-05 03:41:21 +09:00
Johan Malm
a9f927047a default-bindings.h: focus & raise on border press
...because it is probably what most people expect and it makes the
behavior consistent with that of Openbox.

Fixes: #3039
2025-09-04 15:54:37 +09:00
Johan Malm
f1f8782bb0 labnag: s/nag/labnag/ in usage string
Fixes #3051
2025-09-04 00:21:15 +02:00
tokyo4j
074b27fd47 scaled-scene-buffer: restructure source files
Some checks failed
labwc.github.io / notify (push) Has been cancelled
- Rename `scaled_scene_buffer` to `scaled_buffer`. This makes it clear
  that `scaled_{font,img,icon}_buffers` are implementations of it.
- Move the files from `src/common` to `src/scaled-buffer` as
  `scaled_icon_buffer` heavily depends on `server` and `view` etc.
2025-09-02 21:31:19 +01:00
tokyo4j
02be24bf59 mousebind: support Border context
This new context includes `Top`...`BRCorner` and makes it easier to modify
the mousebinds bound to them.
2025-09-02 21:29:10 +01:00
Johan Malm
b5b257092d NEWS.md: link from TOC to each section 2025-09-02 08:14:39 +09:00
John Lindgren
f9f4219ed4 interactive: un-maximize only axes that are being resized
When resizing in only one axis (horizontal/vertical), there's no reason
to un-maximize the other axis.

Supporting logic was landed in the previous commit and in ebd39dfe0d
(which fixed the client-initiated resize case), so all that remains is
to make a small change in interactive_begin().
2025-09-01 20:44:09 +01:00
John Lindgren
6d2140c4b7 view: expose view_set_maximized() instead of view_restore_to()
view_restore_to() (which is just set_maximized() + view_move_resize())
hasn't aged well and doesn't line up with typical usage anymore:

 - it's missing view_set_untiled(), which has to be called separately
 - it always forces view_move_resize() even when that's not needed
 - it doesn't allow un-maximizing only one axis (see next commit)
 - the fullscreen check is unnecessary (already checked in callers)

Eliminate it and just expose view_set_maximized() instead.

No functional change intended in this commit.
2025-09-01 20:44:09 +01:00
tokyo4j
72a5df16ea view: restore initially-maximized window position after unplug/plug
`update_last_layout_geometry()` stores `view->natural_geometry` in
`view->last_layout_geometry`, but it's empty for initially-maximized
windows, so their positions were not restored after outputs are
unplugged and plugged (also when VT switching in wlroots 0.19.0).

This commit sets the fallback natural geometry (at the center of the
output) so that initially-maximized windows reappears in the same output.
2025-09-01 20:16:37 +01:00
tokyo4j
e6b5d91b63 view: let view_set_fallback_natural_geometry() return wlr_box 2025-09-01 20:16:37 +01:00
tokyo4j
164b17c279 view: use fixed default window width
Now it's not very reasonable to determine the default window width based
on the titlebar geometry, as the titlebar can be shrunk to 1px.

Let's use the fixed value of 100px for simplification.
2025-09-01 20:13:00 +01:00
tokyo4j
6ed2617394 view.c: remove outdated comment
Since a5d89a2, xdg-shell views can request very small window geometry.
2025-09-01 20:13:00 +01:00
tokyo4j
66e26cd28a overlay: refactor
- Use a single `lab_scene_rect` for both overlay background and outlines,
  like I described in the TODO comment in ffd4005.
- Simplify the resource management by destroying the overlay tree when
  it's hidden. I think its overhead is pretty minimal.
- Share a single `lab_scene_rect` for both region/edge overlays.
2025-08-31 13:24:51 +01:00
tokyo4j
78d47c5c37 overlay.h: reduce included headers 2025-08-31 13:24:51 +01:00
01micko
d1a9529239 docs/labnag.1.scd: fix missed escape
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-08-30 21:27:46 +09:00
01micko
f0ccbfed18 docs/labnag.1.scd: add a labnag example 2025-08-30 12:38:05 +01:00
01micko
3499f40a6b meson.build: move lab-sensible-terminal install routine.
Moved to clients/meson.build as per the comment in meson.build.
2025-08-30 11:14:07 +01:00
tokyo4j
a382389e5e scaled-icon-buffer: fix large client-side icon not being loaded
This commit fixes that client-side icons were not loaded when the rendered
icon size is larger than icon sizes from the client. This bug has become
more likely to happen due to the new thumnail-style window switcher.

The cause was `abs(INT_MIN)` becomes `INT_MIN` due to integer overflow.
2025-08-30 08:50:03 +01:00
tokyo4j
2e9292b7a3 osd: support window switcher with thumbnails
The new-style window switcher can be enabled with
<windowSwitcher style="thumbnail">.

New theme entries:

osd.window-switcher.style-thumbnail.width.max: 80%
osd.window-switcher.style-thumbnail.padding: 4
osd.window-switcher.style-thumbnail.item.width: 300
osd.window-switcher.style-thumbnail.item.height: 250
osd.window-switcher.style-thumbnail.item.padding: 10
osd.window-switcher.style-thumbnail.item.active.border.width: 2
osd.window-switcher.style-thumbnail.item.active.border.color: #589bda
osd.window-switcher.style-thumbnail.item.active.bg.color: #c7e2fc
osd.window-switcher.style-thumbnail.item.icon.size: 60
2025-08-29 20:42:01 +01:00
tokyo4j
6e2805f692 theme: move osd.window-switcher.* to osd.window-switcher.style-classic.*
Backward compatibility is preserved.
2025-08-29 20:42:01 +01:00
tokyo4j
92ee5083f0 osd: split to osd.c and osd-classic.c 2025-08-29 20:42:01 +01:00
tokyo4j
57a1ea6cb5 Move osd.c and osd-field.c into src/osd 2025-08-29 20:42:01 +01:00
tokyo4j
f347a818e3 ssd: clean up scene management
Our codebase for ssd scenes has grown with a lot of technical debts:
- We needed to call `ssd_get_part()` everywhere to get the scene node of a
  ssd part. We then needed to cast it to `wlr_scene_rect` and
  `wlr_scene_buffer`. This bloated our codebase and even blocked
  duplicated button types in `<titlebar><layout>`.
- `ssd_get_part_type()` was a dirty hack. It compared parent, grandparent
  and grandgrandparent of a node with each subtree in the ssd to get the
  part type of the node.

To resolve this issues, this commit changes how ssd scenes are managed:
- Access scene rects and scene buffers just as a member of `struct ssd`.
- `ssd_part` is now a attachment to a scene node that can be accessed via
  node_descriptor->data, with a new node-descriptor type
  `LAB_NODE_DESC_SSD_PART`. `LAB_NODE_DESC_SSD_BUTTON` is unified into it.

Now the scene graph under ssd->tree looks like below. The parentheses
indicate the type of ssd_part attached to the node:

ssd->tree (LAB_SSD_NONE)
+--titlebar (LAB_SSD_PART_TITLEBAR)
|  +--inactive
|  |  +--background bar
|  |  +--left corner
|  |  +--right corner
|  |  +--title (LAB_SSD_PART_TITLE)
|  |  +--iconify button (LAB_SSD_BUTTON_ICONIFY)
|  |  |  +--normal close icon image
|  |  |  +--hovered close icon image
|  |  |  +--...
|  |  +--window icon (LAB_SSD_BUTTON_WINDOW_ICON)
|  |  |  +--window icon image
|  |  +--...
|  +--active
|     +--...
+--border
|  +--inactive
|  |  +--top
|  |  +--...
|  +--active
|     +--top
|     +--...
+--shadow
|  +--inactive
|  |  +--top
|  |  +--...
|  +--active
|     +--top
|     +--...
+--extents
   +--top
   +--...

When hovering on SSD, `get_cursor_context()` traverses this scene node
from the leaf. If it finds a `ssd_part` attached to the node, it returns
`ssd_part_type` that represents the resizing direction, button types or
`Title`/`Titlebar`.
2025-08-28 21:06:51 +01:00
tokyo4j
aa3dbb4f85 ssd-extents: factor out resize_extent_within_usable() 2025-08-28 21:06:51 +01:00
tokyo4j
a59f98525e ssd-titlebar: create title buffer in ssd_titlebar_create() 2025-08-28 21:06:51 +01:00
Johan Malm
da90e62346 NEWS.md: interim update 2025-08-27 21:58:05 +01:00
John Lindgren
c8943ca242 seat: improve debug logging when configuring input devices
Some checks failed
labwc.github.io / notify (push) Has been cancelled
I needed to debug an input configuration issue and found the debug
output not-super-helpful, so I made some improvements:

- Print the name and "sysname" (e.g. event11) of the device being
  configured. Note that the name alone isn't enough since there can
  be multiple identically-named devices.

- Print the config category matched for each device.

- Print the config values (if any) being applied. For enums, only the
  numeric value is printed since I'm lazy.

- Don't print "pointer acceleration configured" if neither a pointer
  speed nor acceleration profile is configured (it's confusing).
2025-08-27 13:07:01 -04:00
John Lindgren
80b28f16c7 tree-wide: use enum types/constants where appropriate
- add LAB_WINDOW_TYPE_INVALID in place of literal -1
- document more clearly that enum lab_view_criteria is a bitset
- other one-off replacements of integer values/types for consistency

Note: variables of type enum lab_view_criteria are already used
extensively throughout the code to contain combinations of the declared
enum values. I am not introducing any new usage here, just changing the
single uint32_t to be consistent with all the other usages.
2025-08-28 01:33:23 +09:00
John Lindgren
ef766d16f0 common: flesh out enum lab_edge and prefer over wlr_edges/wlr_direction
I like the new common/edge.h. I don't like how inconsistently we use it.

Current situation:

 - enum wlr_edges and wlr_direction are designed to be used as bitset,
   and are defined compatibly

 - enum lab_edge is *also* designed to be used as bitset, but
   incompatible with the others (LEFT/RIGHT come before UP/DOWN)

 - we use an inconsistent mix of all three *AND* uint32_t (usually with
   the WLR_EDGE constants rather than the LAB_EDGE constants), and
   convert between them on an ad-hoc basis, sometimes implicitly

Let's clean this up:

 - reorder enum lab_edge to be compatible with the two wlr enums
   (check this by static_assert)

 - use TOP/BOTTOM naming rather than UP/DOWN (matches wlr_edges)

 - add constants for the remaining possible combinations of the 4 edges

 - use lab_edge for all internal edge/direction fields, consistently

 - add lab_edge_is_cardinal() as a sanity check before casting to
   enum wlr_direction, and then eliminate all of direction.c/h

Instead of "enum wlr_edges direction", we now have
"enum lab_edge direction" which is not that much better. At least we
are now clear that we're overloading one enum with two meanings.
2025-08-26 20:36:43 -04:00
David Barr
4d1be7eada
menu: add brackets around minimised window titles in client-list menu (#3002) 2025-08-26 21:08:31 +01:00
Rainer Kuemmerle
657c08aaa1 action: add toggle for GoToDesktop
Adds an option "toogle" to GoToDesktop.
In case the target is already where we are, we go back to the last desktop
instead.

Example of rc.xml

<keybind key="C-F1">
  <action name="GoToDesktop">
    <to>1</to>
    <toggle>yes</toggle>
  </action>
</keybind>
2025-08-26 21:03:06 +01:00
tokyo4j
55ee96761a window-rules: fix window rules not being applied
In 943f5751, I initialized heap-allocated `view_query` used for
`If` actions with `decoration=LAB_SSD_MODE_INVALID`, but I forgot to do
that for stack-allocated `view_query` used for window rules.
2025-08-25 23:42:00 +09:00
John Lindgren
ebd39dfe0d view: respect client-initiated resize of non-maximized axis
Some checks failed
labwc.github.io / notify (push) Has been cancelled
When implementing single-axis maximize some time ago, I made the
simplifying assumption that a view couldn't be resized while maximized
(even in only one axis). And indeed for compositor-initiated resize,
we always unmaximize the view first.

However, I didn't account for the client resizing the non-maximized
axis, which we can't (and shouldn't) prevent. When this happens, we
should also update the natural geometry of that single axis so that we
don't undo the resize when un-maximizing.

P.S. xdg-shell clients resizing the *maximized* axis is still an
unsolved problem, exacerbated by the fact that xdg-shell protocol
doesn't allow clients to even know about single-axis maximize.

P.P.S. the view_invalidate_last_layout_geometry() logic may need
similar updates, I'm not sure.
2025-08-24 23:05:59 +09:00
tokyo4j
888dbedeed ssd: allow hiding titlebar on maximization
<core disableMaximizedServerDecor="yes"> hides the titlebar when a window
is maximized.

Co-authored-by: @CosmicFusion
2025-08-24 12:41:41 +01:00
tokyo4j
943f5751ee view: unify ssd_enabled and ssd_titlebar_hidden to ssd_mode 2025-08-24 12:41:41 +01:00
tokyo4j
48ba23fc8d Add common/edge.c
Some checks failed
labwc.github.io / notify (push) Has been cancelled
2025-08-21 21:17:52 +01:00
01micko
1b575ce816 docs/labnag.1.scd: fix typo 2025-08-21 21:05:04 +01:00
John Lindgren
beb3c0fa09 config: add comment to enum lab_motion 2025-08-21 16:55:25 +09:00
John Lindgren
9d49d19cd2 include: add config/types.h 2025-08-21 16:55:25 +09:00
Marvin Dostal
6dea8c0dcc desktop-entry: fix partial string matching
Use the base instead of the full string for the comparison.
2025-08-20 21:15:35 +01:00
01micko
3ee12b1e95 clients/labnag.c: add newline to color errors. 2025-08-20 21:10:21 +01:00
01micko
35ec696bd9 docs/rc.xml.all: clean up libinput section.
- add alternative accepted values for [yes|no]
- re #3006
2025-08-20 02:47:33 +09:00
tokyo4j
d1d4037335 seat.c: reset libinput device config on reconfigure
Before this commit, setting empty values in <libinput> entires and
executing Reconfigure left libinput devices with old configurations.

This commit makes sure that default values are set in libinput devices
on every Reconfigure to make rc.xml more declarative.
2025-08-19 17:18:08 +09:00
tokyo4j
7041accb56 rcxml: allow empty values in <libinput>
This restores the old behavior prior to a0d2e6a6.
2025-08-19 17:18:08 +09:00
Weblate
b1a8eb7d3a Translation updates from weblate
Co-authored-by: Qayyum Yazid <purrnama@proton.me>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ms/
Translation: Labwc/labwc
2025-08-18 21:25:50 +01:00
John Lindgren
6574c82aed keybind: refactor update_keycodes_iter() to reduce nesting
update_keycodes_iter() currently has 4(!) levels of nested loops, which
makes the logic (especially the break/continue statements) difficult to
understand. The logic also appears to continue looping uselessly after
a given keycode has already been added to a keybind.

Refactor by adding some small utility functions:

- keybind_contains_keycode()
- keybind_contains_keysym()
- keybind_contains_any_keysym()

No functional change intended.
2025-08-18 19:54:18 +01:00
Weblate
28513cbdbe Translation updates from weblate
Co-authored-by: Ettore Atalan <atalanttore@googlemail.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/de/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/uk/
Translation: Labwc/labwc
2025-08-17 15:12:59 +01:00
Johan Malm
8d60fb27cd labwc-menu(5): reflect use of client-send-to-menu in client menu 2025-08-16 14:54:48 +01:00
Johan Malm
8bcea29a1c menu: fix leak in update_client_send_to_menu() 2025-08-16 14:54:48 +01:00
Johan Malm
6fe61f8846 menu: use client-send-to-menu as 'Workspace' submenu
...because that is more flexible and how it is in openbox.

I have had in mind that we should do this since the original
implementation, and #2994 just jogged my memory.
2025-08-16 14:54:48 +01:00
John Lindgren
d9f7ccf3aa menu: fix use-after-free at exit with sub-menu selected
Sequence of events:

- menu_finish() frees the sub-menu first
- the selection.menu of the parent menu is now dangling
- menu_finish() frees the parent menu
- menu_free() calls menu_close_root() on the parent menu
- menu_close_root() tries to close the (freed) sub-menu
- boom

Extending nullify_item_pointing_to_this_menu() avoids the crash.
2025-08-15 18:46:34 +09:00
John Lindgren
6e949e623a input/cursor: fix assignment/equality mix-up 2025-08-15 06:48:19 +01:00
tokyo4j
72e1945a4c menu: allow overwriting submenu icon
Allow overwriting the icon of item linking to another menu like below
(the icon for "krita" should be shown):

<openbox_menu>
  <menu id="static-menu" label="Static Menu" icon="mpv" />
  <menu id="root-menu" label="Root">
    <menu id="static-menu" icon="krita" />
  </menu>
</openbox_menu>

This commit also fixes my mistake in 17d66e5 (s/parent->icon/menu->icon/)
that showed incorrect icon in an item linking to another menu.
2025-08-14 20:47:43 +01:00
tokyo4j
2a039d4f24 menu: fix client-send-to-menu
Fixes 17d66e5
2025-08-13 20:29:23 +01:00
tokyo4j
2ce3f39c1f menu: allow client-{list-combined,send-to}-menu as submenu of static menu
Also, their labels are changed to "Windows" and "Send to desktop" which
are the same as Openbox.
2025-08-13 20:29:23 +01:00
Weblate
01a7ac7995 Translation updates from weblate
Co-authored-by: Oliver Chiasson <olivierchiasson@hotmail.fr>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/fr/
Translation: Labwc/labwc
2025-08-13 20:10:06 +01:00
Narrat
e05b924e4d docs/menu.xml: adjust labnag example
It was missing the respective closing tag
2025-08-12 22:35:19 +01:00
Johan Malm
09b4e9605e labnag: return special value on timeout
...to avoid taking either of the <then> or <else> branches on timeout.
2025-08-12 03:10:14 +09:00
tokyo4j
073fd02300 osd: add null-check for output->osd_scene.tree
`wlr_scene_node_destroy(&output->osd_scene.tree->node);` does nothing
for null pointer, but ASAN is unhappy about accessing (NULL)->node.
2025-08-09 12:03:41 +01:00
Johan Malm
7c3a587015 action: fix labnag button order 2025-08-09 11:04:36 +01:00
Johan Malm
6c3cf84b07 labnag: fix FreeBSD signalfd() build error 2025-08-09 10:44:03 +01:00
Johan Malm
8a5a04cc1a labwc-action(5): describe If action <prompt> 2025-08-09 10:44:03 +01:00
Johan Malm
c63d35c942 Add labnag
Based on swaynag (https://github.com/swaywm/sway/tree/master/swaynag)

Copied at commit:
03483ff370

Contains the following modifiations:

- Some functional changes including:
  - Disable exclusive-zone by default (Written-by: @Consolatis) and add
    command line option -x|--exclusive-zone
  - Add close timeout (Written-by: @Consolatis) and -t|--timeout option
  - Use index of button (from right-to-left) for exit code
  - Disable reading from config file and remove associated --type option
- Refactoring including:
  - Use wlr_log() instead of the log.{c,h} functions
  - Use wl_list instead of sway's list.c implementation
  - In the pango wrapper functions, use glib's g_strdup_vprintf() rather
    than the original stringop.c functions
- Align with labwc coding style to pass checkpatch.pl
- Re-licenced from MIT to GPL-2.0, and add Copyright notices for original
  authors

v2

- Remove option -s|--dismiss-button and the default "X" button. To get
  such a button, "-Z X :"
- Remove options -b and -z because there is no requirement to run
  in a terminal.
- Remove *-no-terminal from options --button and --button-dismiss because
  commands are now always run directly without a terminal.

v3

- Allow -B/-Z options without action-argument
- Invert button order of -B/-Z so that `labnag -m foo -Z x -Z y -Z z`
  results in three buttons with "x" furthest to the left, and "z" on the
  right (rather than the other way around).
- Use signalfd() to prevent race conditions on SIGTERM

v4

- Limit number of stdin lines to 200 to avoid hogging CPU

Co-Authored-by: tokyo4j
2025-08-09 10:44:03 +01:00
Johan Malm
6fd14987dd build: refactor in preparation for man page not beginning with 'labwc-'
No functional change intended.
2025-08-09 10:44:03 +01:00
Consolatis
fba73a0036 action: add support for <prompt> in 'If' actions
...and allow If Action without activator view.

For example:

    <action name="If">
      <prompt message="Toggle maximize?"/>
      <then>
        <action name="ToggleMaximize" />
      </then>
    </action>

Also revert the change in b9c84f9 that <else> branch is always taken when
no window is focused.

Co-Authored-by: johanmalm
Co-Authored-by: tokyo4j
2025-08-09 10:44:03 +01:00
Consolatis
32e308b5d5 scaled-icon-buffer: prevent accidental downcasting of scale
This causes blurry icons on non-integer scales and triggers
an assert within cairo when using a output scale < 1.

Fixes: #2983
2025-08-09 16:52:10 +09:00
tokyo4j
418f9cb059 ime: fix segfault when IME is killed
Fixes up e530f43.

When IME (e.g. fcitx5) is killed, relay->input_method is destroyed and
then relay->input_method->keyboard_grab is destroyed, which causes null
pointer dereference and crashes labwc.

Possible solutions are:
- Let wlroots keep emitting keyboard grab as `data` from keyboard grab's
  destroy handler just like before
- Let wlroots destroy keyboard grab before input method
- Let compositor store keyboard grab as relay->keyboard_grab

But let's just revert the change in e530f43 for now.
2025-08-08 20:52:23 +09:00
John Lindgren
02df0a15d7 foreign-toplevel: simplify and fully separate ext-foreign/wlr-foreign
Currently, the dependencies between foreign-toplevel[-internal],
ext-foreign, and wlr-foreign are cyclical and a bit complex.

I suggest we reorganize it into a simpler hierarchy:

  foreign-toplevel/
    -> foreign.c/h
      -> (depends on) ext-foreign.c/h
      -> (depends on) wlr-foreign.c/h

The refactored code is smaller and (IMO) easier to follow.

In detail:

- Add include/foreign-toplevel folder mirroring src/foreign-toplevel
- Split foreign-toplevel-internal.h to ext-foreign.h and wlr-foreign.h
- Eliminate ext-/wlr-foreign.c -> foreign.c reverse dependencies
  (including internal signals and foreign_request* functions)
- Make struct foreign_toplevel private to foreign.c

Lightly tested with qmpanel (which uses wlr-foreign-toplevel).

v2: reorder foreign-toplevel internal API funcs
2025-08-07 23:27:04 -04:00
John Lindgren
55b495f398 foreign-toplevel: disconnect internal signals from handle_handle_destroy()
If the handle gets destroyed from the wlroots side before the view
is destroyed, the internal signals (emitted from the view) are not
disconnected and will assert() if invoked.
2025-08-07 23:27:04 -04:00
Johan Malm
d87ef7568a common/xml.c: fix memory leak in lab_xml_get_bool() 2025-08-06 21:11:42 +01:00
John Lindgren
508df093c4 xdg: try to keep view on the same output in timeout case 2025-08-06 18:14:24 +09:00
John Lindgren
9557091a1a xdg: don't try to reposition unmapped view in timeout handler 2025-08-06 18:14:24 +09:00
tokyo4j
e530f43708 ime: don't use data argument in some signal handlers
In wlroots 0.20, the those data argument will be just NULL.
2025-08-05 11:43:09 +09:00
John Lindgren
2547f96984 view: assert internal signals are disconnected before destroy
If they are not empty, then we are headed for use-after-free shortly.
An assert() failure is easier to debug than UAF, so let's fail early.

Inspired by:
8f56f7ca43
2025-08-05 04:20:57 +02:00
John Lindgren
bc34461977 output: make autoEnableOutputs=no apply only to drm outputs
It is not really useful for other output backends and just results
in no outputs being enabled at all. (This is mainly an annoyance for
developers normally running with drm but occasionally nested.)
2025-08-05 04:18:43 +02:00
tokyo4j
17d66e5603 menu: refactor parser
...with the same approach as rcxml.c

- `If` actions now works for menus
- `name` argument no longer have to be the first argument of <action>
- `label` argument no longer have to be the first argument of <item>
2025-08-04 21:41:14 +01:00
tokyo4j
bfaab101af Make append_actions() public
Also rename it to append_parsed_actions()
2025-08-04 21:41:14 +01:00
tokyo4j
2f183cdcb6 interactive: allow snapping to corner edges
In addition to <snapping><range>, <snapping><cornerRange> configures the
distance from the screen corner to trigger quater window snapping.

Also, new values "up-left", "up-right", "down-left" and "down-right" are
allowed for <action name="(Toggle)SnapToEdge" direction="[value]"> and
<query tiled="[value]">.
2025-08-04 21:24:12 +01:00
tokyo4j
b0ff2911b6 src/overlay.c: minor refactor 2025-08-04 21:24:12 +01:00
tokyo4j
6441bd58f3 view: don't use bitset for VIEW_EDGE_ALL
We will use bitset for views snapped to corner (e.g. top-left = TOP|LEFT)
2025-08-04 21:24:12 +01:00
tokyo4j
4b0ac0234c view: refactor view_edge_parse() 2025-08-04 21:24:12 +01:00
tokyo4j
03004cf44b menu: fix segfault with toplevel <separator>
Before this patch, labwc crashed menu.xml like this:

<openbox_menu>
  <separator />
</openbox_menu>
2025-08-03 15:07:35 +01:00
tokyo4j
00ed40454d common/xml: parse CDATA as text
Before this patch, <![CDATA[xxx]]> was ignored in many cases.

For example, this didn't work:

  <core>
    <gap><![CDATA[10]]></gap>
  </core>
2025-08-03 15:05:53 +01:00
tokyo4j
5a50d87ee2 common/xml: let LAB_XML_FOR_EACH() skip first child text nodes
Before this patch, first text nodes like the spaces between <a> and <b>
below were also travered by LAB_XML_FOR_EACH():

  <a>  <b>foo</b></a>
2025-08-03 15:05:53 +01:00
tokyo4j
b9c84f9c38 action: allow if-action without activator view
..in preparation for If/ForEach action with <prompt>, which should be
executed whether or not any window is focused.

This patch makes <If> actions execute <else> branch if no window is
focused or hovered.
2025-08-02 13:19:35 +01:00
tokyo4j
15e3c32b5b action.c: split actions_run() 2025-08-02 13:19:35 +01:00
Johan Malm
6c50a62817 NEWS.md: update notes for 0.9.1 2025-08-02 12:45:11 +01:00
Weblate
9fe1509e33 Translation updates from weblate
Co-authored-by: Dimitrios Glentadakis <dglent@free.fr>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: 이정희 <daemul72@gmail.com>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/el/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ko/
Translation: Labwc/labwc
2025-08-02 12:32:17 +01:00
tokyo4j
6e7c4a181e overlay: take into account <core><gap> for region overlay 2025-08-02 12:31:16 +01:00
tokyo4j
38e57891b5 overlay: take into account <core><gap> for edge overlay
This also deduplicates get_edge_snap_box() in interactive.c and
view_get_edge_snap_box() in view.c.
2025-08-02 12:31:16 +01:00
tokyo4j
ca8d98e80f cursor: fix Scroll mousebinds not inhibited with ToggleKeybinds
fixup for 024ab280
2025-08-02 12:27:26 +01:00
tokyo4j
d5c03ab7fb include/edges.h: remove unimplemented function 2025-08-02 16:40:04 +09:00
Weblate
b966a1ed73 Translation updates from weblate
Co-authored-by: BigELK176 ≡ <BigELK176@gmail.com>
Co-authored-by: Valera <ValeraDX@yandex.ru>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ru/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/zh_TW/
Translation: Labwc/labwc
2025-07-30 21:05:19 +01:00
John Lindgren
2e6b30eb50 include: move a few types from labwc.h to better locations 2025-07-30 21:04:31 +01:00
John Lindgren
e1475a1e47 include: reduce global includes in labwc.h 2025-07-30 21:04:31 +01:00
John Lindgren
e21fc065c4 include: split output.h from labwc.h 2025-07-30 21:04:31 +01:00
tokyo4j
2f414a438b rcxml: simplify the logic to traverse xml tree 2025-07-30 20:36:27 +01:00
tokyo4j
ad970544e1 string-helper: add str_space_only() 2025-07-30 20:36:27 +01:00
tokyo4j
67f36d9e13 rcxml: rewrite <tablet><map> parser 2025-07-30 20:36:27 +01:00
tokyo4j
619cae67fa rcxml: rewrite <theme><font> parser 2025-07-30 20:36:27 +01:00
tokyo4j
a865cc0777 rcxml: reorder functions 2025-07-30 20:36:27 +01:00
tokyo4j
ba00f57dad rcxml: rewrite <windowRules> parser 2025-07-30 20:36:27 +01:00
tokyo4j
936c5f6df1 rcxml: rewrite <windowSwitcher><fields> parser 2025-07-30 20:36:27 +01:00
tokyo4j
73dd3b8de1 rcxml: rewrite <region> parser 2025-07-30 20:36:27 +01:00
tokyo4j
a0d2e6a64b rcxml: rewrite <libinput> parser 2025-07-30 20:36:27 +01:00
tokyo4j
7adbfe88aa rcxml: rewrite <touch> parser 2025-07-30 20:36:27 +01:00
tokyo4j
8ae2d72cef rcxml: rewrite <margin> parser 2025-07-30 20:36:27 +01:00
tokyo4j
be31df097c rcxml: rewrite <mousebind> parser 2025-07-30 20:36:27 +01:00
tokyo4j
433168457f rcxml: rewrite <keybind> parser 2025-07-30 20:36:27 +01:00
tokyo4j
9462457cc2 rcxml: rewrite action parser
This commit rewrites the nested action parser into append_actions() which
is used by following commits. At this point, it's not used yet and parsing
"If" action is temporarily disabled.
2025-07-30 20:36:27 +01:00
tokyo4j
8881841098 common/xml: add helpers to parse rc.xml 2025-07-30 20:36:27 +01:00
tokyo4j
503af10505 rcxml: convert dotted properties into nested nodes before processing
For example, the following node:

  <keybind name.action="ShowMenu" menu.action="root-menu"
            x.position.action="1" y.position.action="2" />

is converted to:

 <keybind>
   <action>
     <name>ShowMenu</name>
     <menu>root-menu</menu>
     <position>
       <x>1</x>
       <y>2</y>
     </position>
   </action>
 </keybind>

...before processing the entire xml tree. This is a preparation to prevent
breaking changes when we refactor rcxml.c to use recursion instead of
encoding nodes into dotted strings.
2025-07-30 20:36:27 +01:00
John Lindgren
330c55e1b2 CONTRIBUTING.md: add section on include order 2025-07-29 21:51:56 +01:00
John Lindgren
0d396f84a7 CONTRIBUTING.md: minor updates
- style "GLib" with two capitals as in its own upstream docs
- use title-case consistently for headings
- add missing heading to table of contents
- update dead GLib documentation URL
2025-07-29 21:51:56 +01:00
John Lindgren
31d42b50e2 src: include primary header first
This is a common practice in C projects, which simply enforces that
each header must compile cleanly without implicit dependencies on
other headers (see also the previous commit).
2025-07-29 21:51:56 +01:00
John Lindgren
c9b576982d include: add missing header dependencies
Ensure that headers compile correctly regardless of include order.
2025-07-29 21:51:56 +01:00
Johan Malm
69b9122194 NEWS.md: update with notes on wlroots changes 2025-07-29 21:06:21 +01:00
tokyo4j
bdaf85eda1 Fix some warnings from clang-tidy
Notably this fixes a possible null pointer dereference in warp_cursor()
when output_nearest_to_cursor() returns null.
2025-07-28 15:27:45 +02:00
Weblate
b3b6715cdf Translation updates from weblate
Co-authored-by: Abdullah Albaroty <albaroty@gmail.com>
Co-authored-by: Hugo Carvalho <hugokarvalho@hotmail.com>
Co-authored-by: Moo <hazap@hotmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: kmephistoh <kanhaosmile@gmail.com>
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ar/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/lt/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/pt/
Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/zh_CN/
Translation: Labwc/labwc
2025-07-27 17:26:27 +01:00
tokyo4j
024ab280a0 cursor: also toggle mousebinds with ToggleKeybinds
Mousebinds can still be applied when the cursor is over their decoration
2025-07-28 00:06:52 +09:00
tokyo4j
73095f75cb Remove seat->nr_inhibited_keybind_views 2025-07-28 00:06:52 +09:00
Consolatis
f7702af9e4 src/xdg.c: prevent interacting with un-initialized xdg toplevels after unmap
Fixes: #2937
Fixes: #2944

Originally-Reported-By: tranzystorekk via IRC
2025-07-27 23:51:28 +09:00
tokyo4j
0d9384de74 style: remove newlines after wl_list_for_each_reverse() 2025-07-27 08:26:39 +09:00
John Lindgren
d96656ccdc menu: add struct menu_parse_context to reduce static vars
The lifetime of the "current_" variables (current_menu, current_item,
current_item_action) is very difficult to understand from reading the
code. It appears that e.g. current_menu could still point to a previous
menu when starting to parse a new one, with unpredictable results.

Let's use a context struct when parsing, and consistently initialize
it when beginning to build a new menu.

Lightly tested with:

- default menus (no menu.xml)
- example static menu from labwc.github.io/getting-started.html
- an added "client-list-combined-menu" sub-menu
- pipe menu generated by `labwc-menu-generator -p`

v2: style fix
2025-07-24 15:35:29 +09:00
tokyo4j
cb79eccea1 cursor: prevent hi-res mice triggering scroll actions too often
Hi-res mice produces mulitple scroll events with `delta_discrete` != 0
during a single "click". This patch makes them trigger `Scroll` actions
only when the accumulated `delta_discrete` exceeds 120 (= 1 click).

See https://lists.freedesktop.org/archives/wayland-devel/2019-April/040377.html
for how hi-res scroll events are reported.
2025-07-22 19:31:55 +09:00
John Lindgren
1747d9e961 buf: avoid 'new' as variable name
It's just good practice to avoid C++ keywords, in case someone
someday wants to compile this code as C++.
2025-07-21 16:51:10 +02:00
John Lindgren
7d2b5150e8 session-lock: eliminate pointless compound literal
In C++, this would have caused a use-after-free. In C, the unnamed
array remains in scope longer, so it's okay, but still pointless.
2025-07-21 16:51:10 +02:00
John Lindgren
4afbfac528 src: put designated initializers in member order
Out-of-order named initializers are allowed in C (unlike in C++) but
are still surprising - I don't see a reason not to put them in order.
2025-07-21 16:51:10 +02:00
John Lindgren
a802d6b20a src: avoid tentative definitions of static data
Having multiple declarations of the same static data (where one is
considered "tentative") is kind of an obscure C feature -- I didn't
even know the name of it until today. It's also forbidden in C++.

In the case of circular dependencies between static data <-> function,
the more typical pattern is to forward-declare the function, then the
data, then provide the function definition. Let's follow that pattern.
2025-07-21 16:51:10 +02:00
John Lindgren
407a29aa23 string-helpers: remove restrict qualifier
'restrict' is harmful as it encourages the compiler to make dangerous
assumptions while increasing cognitive load on the human programmer.

The extra 1% (or whatever) of performance here is not worth the cost.
2025-07-21 16:51:10 +02:00
John Lindgren
681f9e9a7b src: add braces to switch cases containing declarations
This limits the scope of the declarations to avoid accidents.
2025-07-21 16:51:10 +02:00
John Lindgren
b48c250177 src: prefer 'if' over 'goto' where convenient
'goto' should not be used for normal control flow.

v2 add comment in lieu of goto label
2025-07-21 16:51:10 +02:00
John Lindgren
8b7ae52a91 src: avoid implicit int/bool -> enum conversions
Use the defined enum constants instead.
2025-07-21 16:51:10 +02:00
John Lindgren
cd8a8c2bf6 keybind: pointer to string literal should be const
Assigning to (char*) creates a mutable string literal, which was
likely not intended here and wasn't necessary.
2025-07-21 16:51:10 +02:00
John Lindgren
ac47be3019 menu: do not modify literal string constants
Mutable string literals are a "legacy" C feature best avoided.

v2: move string_truncate_at_pattern() outside fill_item()
2025-07-21 16:51:10 +02:00
lynxy
2bcd8277c4 comments: added short description to view_edge enum 2025-07-19 12:29:55 +09:00
lynxy
254f526f71 actions: prevent users entering invalid direction=any value 2025-07-19 12:29:55 +09:00
lynxy
13ff64f6e4 actions: added query tiled=any comparison for rc.xml simplification 2025-07-19 12:29:55 +09:00
John Lindgren
359dd8f3c7 img: fix apparent double-free in img_svg_render() failure path
img_svg_render() calls g_object_unref() on the RsvgHandle in its
error path, but the handle is owned by the shared lab_img_data
struct and will be double-freed later by lab_img_destroy().

The double-free was introduced when img_svg_load() was split from
img_svg_render(). The g_object_unref() should have been removed from
img_svg_render() but was missed.

Fixes: 16dbdc64e5
("ssd: rework titlebar button rendering")
2025-07-13 16:43:56 +09:00
John Lindgren
bb2d34a5c1 xwayland: fix swapped width/height in _NET_WM_ICON stride calculation
Probably slipped through since most window icons are square anyway.
2025-07-13 03:51:40 +02:00
222 changed files with 9667 additions and 6257 deletions

View file

@ -12,14 +12,21 @@ UseTab: Always
IndentWidth: 8
ContinuationIndentWidth: 8
AlignAfterOpenBracket: DontAlign
AlignOperands: false
AlwaysBreakAfterDefinitionReturnType: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Linux
IndentCaseLabels: false
PenaltyBreakOpenParenthesis: 100
PenaltyReturnTypeOnItsOwnLine: 500
SpaceBeforeParens: ControlStatementsExceptControlMacros
ForEachMacros: ['for_each_view',
'for_each_view_reverse',
'wl_array_for_each',
'wl_list_for_each',
'wl_list_for_each_reverse',
'wl_list_for_each_reverse_safe',
'wl_list_for_each_safe']
IncludeCategories:
- Regex: '<.*>'
- Regex: '.*'

View file

@ -17,6 +17,8 @@ on:
- 'src/**'
- 'include/**'
- 'protocols/**'
- 'clients/**'
- 't/**'
- 'scripts/**'
- '.github/workflows/**'
@ -82,7 +84,7 @@ jobs:
pacman -Syu --noconfirm
pacman -S --noconfirm git meson clang wlroots0.19 libdrm libinput \
wayland-protocols cairo pango libxml2 xorg-xwayland librsvg \
libdisplay-info gdb ttf-dejavu foot libsfdo
libdisplay-info gdb ttf-dejavu foot libsfdo cmocka
- name: Install Debian Testing dependencies
if: matrix.name == 'Debian'
@ -92,7 +94,7 @@ jobs:
apt-get upgrade -y
apt-get install -y git gcc clang gdb xwayland
apt-get build-dep -y labwc
apt-get build-dep -y libwlroots-0.18-dev
apt-get build-dep -y libwlroots-0.19-dev
- name: Install FreeBSD dependencies
if: matrix.name == 'FreeBSD'
@ -103,7 +105,8 @@ jobs:
sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
pkg set -yn pkg:mesa-dri # hack to skip llvm dependency
pkg install -y git meson gcc pkgconf cairo pango evdev-proto \
hwdata wayland-protocols wlroots019 libdisplay-info
hwdata wayland-protocols libdisplay-info libepoll-shim \
wlroots019
run: echo "setup done"
- name: Install Void Linux dependencies
@ -167,6 +170,7 @@ jobs:
meson setup build-gcc-release -Dxwayland=enabled \
-Dbuildtype=release -Db_ndebug=true --werror
meson configure build-gcc-release -Dwlroots:b_ndebug=false || true
meson configure build-gcc-release -Dlibsfdo:b_ndebug=false || true
meson compile -C build-gcc-release
' | $TARGET
@ -189,6 +193,7 @@ jobs:
meson setup build-clang-release -Dxwayland=enabled \
-Dbuildtype=release -Db_ndebug=true --werror
meson configure build-clang-release -Dwlroots:b_ndebug=false || true
meson configure build-clang-release -Dlibsfdo:b_ndebug=false || true
meson compile -C build-clang-release
' | $TARGET
@ -204,6 +209,18 @@ jobs:
meson compile -C build-gcc-no-feature
' | $TARGET
# Unit tests, run on Arch only
- name: Build with gcc - unit test
if: matrix.name == 'Arch'
run: |
echo '
cd "$GITHUB_WORKSPACE"
export CC=gcc
meson setup build-gcc-unit-test -Dtest=enabled --werror
meson compile -C build-gcc-unit-test
meson test -C build-gcc-unit-test --print-errorlogs
' | $TARGET
# Runtime tests, these run on Arch and Void only (the later due to libmusl being used)
- name: Build with gcc - runtime test
if: matrix.name == 'Arch'

View file

@ -10,9 +10,11 @@
- [4.2 Devault Deviations](#devault-deviations)
- [4.3 Labwc Specifics](#labwc-specifics)
- [4.3.1 API](#api)
- [4.3.2 The Use of glib](#the-use-of-glib)
- [4.3.3 The use of GNU extensions](#the-use-of-gnu-extensions)
- [4.3.2 The Use of GLib](#the-use-of-glib)
- [4.3.3 The Use of GNU Extensions](#the-use-of-gnu-extensions)
- [4.3.4 Naming Conventions](#naming-conventions)
- [4.3.5 Switch Statements with Variable Declarations](#switch-statements-with-variable-declarations)
- [4.3.6 Order of #includes](#order-of-includes)
- [5. Commit Messages](#commit-messages)
- [6. Unit Tests](#unit-tests)
- [7. Submitting Patches](#submitting-patches)
@ -21,14 +23,14 @@
# How to Contribute
1. Report bugs as github issues. We use a template prompting you to provide
1. Report bugs as GitHub issues. We use a template prompting you to provide
some sensible information such as what happened, what you expected to happen
and steps to reproduce. If applicable try with default configuration. If
you are able to, try to do some debugging (guidelines below).
and steps to reproduce. If applicable try with default configuration. If
you are able to, try debugging (guidelines below).
2. Submit patches as github pull-requests. If you wish to introduces significant
2. Submit patches as GitHub pull requests. If you wish to introduce significant
changes or new features, consult the [scope document], discuss on IRC or via
a github issue first.
a GitHub issue first.
# Debugging
@ -242,21 +244,21 @@ We have a very small, modest API and encourage you to use it.
[common/array.h]: https://github.com/labwc/labwc/blob/master/include/common/array.h
[common/macros.h]: https://github.com/labwc/labwc/blob/master/include/common/macros.h
### The Use of glib
### The Use of GLib
We try to keep the use of glib pretty minimal for the following reasons:
We try to keep the use of GLib pretty minimal for the following reasons:
- The use of glib has been known to make AddressSanitiser diagnose false
- The use of GLib has been known to make AddressSanitiser diagnose false
positives and negatives.
- Log messages coming from glib functions look inconsistent.
- The use of glib functions, naming-conventions and iterators in a code base
- Log messages coming from GLib functions look inconsistent.
- The use of GLib functions, naming-conventions and iterators in a codebase
that is predominantly ANSI C creates a clash which makes readability and
maintainability harder.
- Mixing gmalloc()/malloc() and respective free()s can create problems with
memory pools [^1]
Having said that, with our use of cairo and pango we depend on glib-2.0 anyway
so linking with it and making use of some of its helper functions comes for free
Having said that, with our use of cairo and pango we depend on glib-2.0 anyway,
so linking with it and making use of some of its helper functions comes for free,
and can keep the code simpler.
For example, if we were going to carry out extensive string manipulation,
@ -272,7 +274,7 @@ devs:
- `g_pattern_match_simple()`
When using these types of functions it is often desirable to support with some
glib code, which is okay provided it is kept local and self-contained. See
GLib code, which is okay provided it is kept local and self-contained. See
example from `src/theme.c`:
```
@ -287,9 +289,9 @@ match(const gchar *pattern, const gchar *string)
}
```
### The use of GNU extensions
### The Use of GNU Extensions
We avoid [GNU C extensions] because we want to fit into the eco-system
We avoid [GNU C extensions] because we want to fit into the ecosystem
(wayland and wlroots) we live in.
We do use `__typeof__` which strictly speaking is a GNU C extension (`typeof`)
@ -298,18 +300,18 @@ but through the use of `__` is supported by gcc and clang without defining
in the [`wl_container_of()`] macro which is needed in `wl_list*` and it
does provide pretty big benefits in terms of type safety.
We compile with `-std=c11` because that's what 'wlroots' uses and we do not
We compile with `-std=c11` because that's what 'wlroots' uses, and we do not
want to increase the entry-level for OSs without good reason (and currently
we can't think of one).
### Naming Conventions
There are three types of coordinate systems: surface, output and layout - for
There are three types of coordinate systems: surface, output, and layout — for
which the variables (sx, sy), (ox, oy) and (lx, ly) are used respectively in
line with wlroots.
With the introduction of the scene-graph API, some wlroots functions also use
node coordinates (nx, ny) but we prefer (sx, sy) where possible.
node coordinates (nx, ny), but we prefer (sx, sy) where possible.
We do not worry about namespace issues too much and we try to not make the code
a pain to use just to uniquify names. If we were writing a library we would
@ -323,7 +325,7 @@ We use the prefix `handle_` for signal-handler-functions in order to be
consistent with sway and rootston. For example
`view->request_resize.notify = handle_request_resize`
### Switch statements with variable declarations
### Switch Statements with Variable Declarations
Unlike many modern languages, C doesn't create a new scope after `case FOO:`.
Therefore, we wrap codes following `case FOO:` that include variable
@ -349,6 +351,26 @@ case BAZ:
But please also consider refactoring the code into a separate function if it
becomes lengthy.
### Order of #includes
In new files, please order `#include` lines as follows:
- In each `.c` file, first include the matching `.h` file, if there is
one. For example, `#include "common/font.h"` should come first in
`src/common/font.c`. This practice helps to ensure that each header
compiles cleanly on its own, without implicit dependencies on other
headers being included first.
- Then list any "system" headers (those not part of labwc) in alphabetical
order, using angle brackets. This includes 3rd-party library headers
such as `<cairo.h>`, as well as wlroots headers.
- Then list any other labwc headers in alphabetical order, using quotation
marks and relative to the `include/` folder. Subfolders below `include/`,
such as `common/`, should be specified even when including one header
from another in the same folder (for example, `#include "common/buf.h"`
from `include/common/grab-file.h`).
# Commit Messages
The log messages that explain changes are just as important as the changes
@ -366,11 +388,11 @@ This first line should:
- In most cases be prefixed with "area: " where area refers to a filename
or identifier for the general area of the code being modified.
- Not capitalize the first word following the "area: " prefix, unless
it's a name, acronym or similar.
it's a name, acronym, or similar.
- Skip the full stop
And please wrap the commit message at max 74 characters, otherwise `git log`
and similar look so weird. URLs and other references are exempt.
and similar look very weird. URLs and other references are exempt.
# Unit Tests
@ -382,9 +404,9 @@ In the bigger scheme of validating that the compositor meets users' needs, unit
tests do not contribute a great deal. However, they have a role to play in
providing some verification that stand-alone functions behave as expected.
On this project, writing unit-tests is not compulsory nor do we measure
On this project, writing unit-tests is not compulsory, nor do we measure
coverage. The inclusion of the t/ directory does not signify a move towards
test-driven development. We intend to use unit tests sparingly and only when
test-driven development. We intend to use unit tests sparingly, and only when
devs find them useful.
## Usage
@ -410,17 +432,17 @@ and use the web interface. Adding new languages should work, otherwise the
administrators can be contacted. Suggestions for improving existing translations
can be added without account.
### Github Pull Request
### GitHub Pull Request
Translators can add their `MY_LOCALE.po` files to the `po` directory
based on `po/labwc.pot` and issue a pull request. To do this they can
based on `po/labwc.pot`, and issue a pull request. To do this they can
generate their `MY_LOCALE.po` file in a few steps:
1. Edit the `po/LINGUAS` file to add their locale code in English
alphabetical order to the field of locale codes.
2. Copy the `po/labwc.pot` to `po/MY_LOCALE.po`
3. Edit the newly generated `MY_LOCALE.po` file with some of their
contact and locale details in the header of the file then add the
contact and locale details in the header of the file. Then, add the
translation strings under each English string.
[See this tutorial for further guidance](https://www.labri.fr/perso/fleury/posts/programming/a-quick-gettext-tutorial.html)
@ -461,13 +483,13 @@ follow the steps to be taken:
2. Update `NEWS.md` with the release details and run
`git commit -m 'NEWS.md: update notes for X.Y.Z'`
Note: If new dependencies are needed, make this clear.
3. In `meson.build` update the version and (if required) the wlroots
3. In `meson.build`, update the version, and (if required) the wlroots
dependency version. Then run `git commit -m 'build: bump version to X.Y.Z'`
4. Run `git tag -a X.Y.Z`. The first line of the commit message should be
"labwc X.Y.Z" and the body should be the `NEWS.md` additions removing
hash characters (#) from the headings as these will otherwise be
ignored by git.
5. On github, create a 'Release' as some distros use this as a trigger. Set it
5. On GitHub, create a 'Release' as some distros use this as a trigger. Set it
as 'latest release'.
[scope document]: https://github.com/labwc/labwc-scope#readme
@ -481,11 +503,10 @@ follow the steps to be taken:
[GNU C extensions]: https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
[`wl_container_of()`]: https://github.com/wayland-project/wayland/blob/985ab55d59db45ea62795c76dff5949343e86b2f/src/wayland-util.h#L409
[^1]: The reference documentation for glib notes that:
[^1]: The reference documentation for GLib notes that:
"It's important to match g_malloc() with g_free(), plain malloc() with
free(), and (if you're using C++) new with delete and new[] with
delete[]. Otherwise bad things can happen, since these allocators may use
different memory pools (and new/delete call constructors and
destructors)."
See: https://developer.gimp.org/api/2.0/glib/glib-Memory-Allocation.html
See: https://docs.gtk.org/glib/memory.html

458
NEWS.md
View file

@ -9,6 +9,8 @@ The format is based on [Keep a Changelog]
| Date | All Changes | wlroots version | lines-of-code |
|------------|---------------|-----------------|---------------|
| 2025-10-10 | [0.9.2] | 0.19.1 | 28818 |
| 2025-08-02 | [0.9.1] | 0.19.0 | 28605 |
| 2025-07-11 | [0.9.0] | 0.19.0 | 28586 |
| 2025-05-02 | [0.8.4] | 0.18.2 | 27679 |
| 2025-02-21 | [0.8.3] | 0.18.2 | 27671 |
@ -36,13 +38,58 @@ The format is based on [Keep a Changelog]
| 2021-04-15 | [0.2.0] | 0.13.0 | 5011 |
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
## [0.9.0]
[unreleased]: NEWS.md#unreleased
[0.9.2]: NEWS.md#092---2025-10-10
[0.9.1]: NEWS.md#091---2025-08-02
[0.9.0]: NEWS.md#090---2025-07-11
[0.8.4]: NEWS.md#084---2025-05-02
[0.8.3]: NEWS.md#083---2025-02-21
[0.8.2]: NEWS.md#082---2024-12-13
[0.8.1]: NEWS.md#081---2024-10-25
[0.8.0]: NEWS.md#080---2024-08-16
[0.7.4]: NEWS.md#074---2024-06-19
[0.7.3]: NEWS.md#073---2024-06-12
[0.7.2]: NEWS.md#072---2024-05-10
[0.7.1]: NEWS.md#071---2024-03-01
[0.7.0]: NEWS.md#070---2023-12-22
[0.6.6]: NEWS.md#065---2023-11-25
[0.6.5]: NEWS.md#064---2023-09-23
[0.6.4]: NEWS.md#063---2023-07-14
[0.6.3]: NEWS.md#062---2023-05-08
[0.6.2]: NEWS.md#061---2023-03-20
[0.6.1]: NEWS.md#060---2023-01-29
[0.6.0]: NEWS.md#060---2022-11-17
[0.5.3]: NEWS.md#053---2022-07-15
[0.5.2]: NEWS.md#052---2022-05-17
[0.5.1]: NEWS.md#051---2022-04-08
[0.5.0]: NEWS.md#050---2022-02-18
[0.4.0]: NEWS.md#040---2021-12-31
[0.3.0]: NEWS.md#030---2021-06-28
[0.2.0]: NEWS.md#020---2021-04-15
[0.1.0]: NEWS.md#010---2021-03-05
The main focus has been to port labwc to wlroots 0.19 [#2388] and fix associated
issues. Special thanks to @Consolatis @jlindgren90 for this.
## Notes on wlroots-0.19
There is a regression warning worth noting for the switch to wlroots 0.19:
There are some regression warnings worth noting for the switch to wlroots 0.19:
- The DRM backend now destroys/recreates outputs on VT switch and in some cases
on suspend/resume too. The reason for this change was that (i) the KMS state
is undefined when a VT is switched away; and (ii) the previous outputs had
issues with restoration, particularly when the output configuration had
changed whilst switched away. This change causes two issues for users:
- Some layer-shell clients do not re-appear on output re-connection, or may
appear on a different output. Whilst this has always been the case, it will
now also happen in said situations. We recommend layer-shell clients to
handle the new-output and surface-destroy signals to achieve desired
behaviours.
- Some Gtk clients issue critical warnings as they assume that at least one
output is always available. This will be fixed in `Gtk-3.24.50`. It is
believed to be a harmless warning, but it can be avoided by running labwc
with the environment variable `LABWC_FALLBACK_OUTPUT=NOOP-fallback` to
temporarily create a fallback-output when the last physical display
disconnects. [#2914] [#2939] [wlroots-4878] [gtk-8792]
- Due to a single-pixel protocol issue, `waylock` and `chayang` do not work.
This will be fixed in `wlroots-0.19.1`. [#2943] [wlroots-5098]
- Menu item can no longer be activated in any Gtk applications with a single
press-drag-release mouse action. For context: This is due to ambiguity in the
specifications and contrary implementations. For example, Gtk applications are
@ -54,6 +101,204 @@ There is a regression warning worth noting for the switch to wlroots 0.19:
around a bug on the wlroots side which is expected to be fixed in wlroots
`0.19.1` [#2887]
With wlroots compiled with libwayland (>= 1.24.0), there is an invisible margin
preventing pointer focus on some layer-shell surfaces including those created by
Gtk. In simple words, this is because libwayland now rounds floats a bit
differently [#3099]. There is a pending fix [wlroots-5159].
[wlroots-4878]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4878
[wlroots-5098]:https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5098
[wlroots-5159]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5159
[gtk-8792]: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/8792
## unreleased
[unreleased-commits]
### Added
- With the window-switcher custom field state specifiers 's' and 'S', show 's'
for shaded window @domo141 [#2895]
- Support `xdg-dialog` protocol to enable better handling of modal dialogs @xi
[#3134]
- labnag: add --keyboard-focus option @tokyo4j [#3120]
- Allow window switcher to temporarily unshade windows using config option
`<windowSwitcher unshade="yes|no"/>` @Amodio @Consolatis [#3124]
- For the 'classic' style window-switcher, add the following theme options:
- `osd.window-switcher.style-classic.item.active.border.color`
- `osd.window-switcher.style-classic.item.active.bg.color`
@tokyo4j [#3118]
### Fixed
- Don't remove newlines when parsing config, menu and XBM because doing so can
cause parser error in some unusual situations like the one shown below.
@tokyo4j [#3148]
```
<!--
-
- Some comments
-
-->
```
### Changed
- If XML documents (like rc.xml and menu.xml) have an XML declaration (typically
`<?xml version="1.0"?>`), this XML declaration must be the first thing in the
document. In previous versions, line breaks (`\n`) were allowed before due to
the way the files were parsed, but this is approach caused other issues like
[#3145] and is contrary to XML syntax. [#3148] [#3153]
- With the window-switcher custom field state specifiers 's' and 'S', change the
display order from M|m|F to m|s|M|F; and increase the size from three
characters wide to four. @domo141 [#2895]
- Call labnag with on-demand keyboard interactivity by default @tokyo4j [#3120]
- Temporarily unshade windows when switching windows. Restore old behaviour with
`<windowSwitcher unshade="no"/>` @Amodio @Consolatis [#3124]
- In the classic style window-switcher, the default color of the selected window
item has been changed to inherit the border color but with 15% opacity
@tokyo4j [#3118]
## 0.9.2 - 2025-10-10
[0.9.2-commits]
### Added
- Allow `SnapToEdge` and `ToggleSnapToEdge` to combine two cardinal directions
with the config option `combine="yes|no"`. [#3081] @tokyo4j
- Support `Border` context for mousebinds as an alias for `Top`...`BRCorner` to
make configuration easier. @tokyo4j [#3047]
- Add window-switcher mode with thumbnails. This can be enabled with:
`<windowSwitcher style="thumbnail">`. @tokyo4j [#2981]
- Add `toggle` option to `GoToDesktop` action. This has the effect of going back
to the last desktop if already on the target. @RainerKuemmerle [#3024]
- Add `<theme maximizedDecoration="titlebar|none"/>` to allow hiding titlebar
when window is maximized. @CosmicFusion @tokyo4j [#3015]
- Use client-send-to-menu as 'Workspace' submenu in built-in client-menu
@johanmalm [#2995]
- Allow overwriting submenu icon to increase flexibility and enhance Openbox
compatibility. @tokyo4j [#2998]
- Allow client-{list-combined,send-to}-menu as submenu of static menu @tokyo4j
[#2994]
- Add `labnag` (a dialog client with message and buttons) and associated
`<prompt>` option in 'If' actions. @johanmalm @Consolatis @tokyo4j [#2699]
- Support config option `<core><promptCommand>` @johanmalm [#3097]
- Allow snapping to corner edges during interactive move with associated config
options `<snapping><cornerRange>`. @tokyo4j [#2885]
- Support new values "up-left", "up-right", "down-left" and "down-right" with
`<action name="(Toggle)SnapToEdge" direction="[value]">` and
`<query tiled="[value]">`. @tokyo4j [#2885]
- XML parsing improvements as listed below. @tokyo4j [#2667] [#2967] [#2971]
- Support nested `If` and `ForEach` actions
- Parse CDATA as text all nodes
- Remove ordering constraint of attributes in `<keybind>`, `<mousebind>` and
`<windowRule>`
- `If` actions now works for menus
- For menus, the `name` argument no longer has to be the first argument of
`<action>`; and the `label` argument no longer has to be the first argument
of `<item>`
- Toggle mousebinds with the `ToggleKeybinds` action @tokyo4j [#2942]
- Add support for direction value 'any' with tiled queries. This allows users
to query for any snap directions without using multiple query statements
@lynxy [#2883]
### Fixed
- On detecting broken icon theme, fall back on 'hicolor' @Consolatis [#3126]
- Restore initially-maximized window position after unplug/plug @tokyo4j [#3042]
- Fix large client-side icon not being loaded when the rendered icon size is
larger than icon sizes from the client. @tokyo4j [#3033]
- Improve debug logging for configuring input devices @jlindgren90 [#3028]
- Fix false positives when matching desktop entries @datMaffin [#3004]
- Prevent accidental downcasting of scale in scaled-icon-buffer to avoid blurry
icons on non-integer scales and a cairo assert when using a output scale < 1.
@Consolatis #2984
- Fix xdg-shell windows moving between outputs due to configure timeout
@jlindgren90 [#2976]
- Fix segfault with toplevel `<separator>` in `menu.xml` @tokyo4j [#2970]
- Prevent hi-res mice triggering scroll actions too often @tokyo4j [#2933]
### Changed
- Change default keybind `W-<arrow>` to combine cardinal directions to support
resizing of windows to fill a quarter of an output. This only affects users
who do not use an `rc.xml` (thereby using default keybinds) or use the
`<keyboard><default/>` option. Previous behavior can be restored by setting
`combine="no"` as shown below. [#3081] @tokyo4j
```
<keybind key="W-Left">
<action name="SnapToEdge" direction="left" combine="no" />
</keybind>
<keybind key="W-Right">
<action name="SnapToEdge" direction="right" combine="no" />
</keybind>
<keybind key="W-Up">
<action name="SnapToEdge" direction="up" combine="no" />
</keybind>
<keybind key="W-Down">
<action name="SnapToEdge" direction="down" combine="no" />
</keybind>
```
- `Focus` and `Raise` on window border press because it is probably what most
people expect and it makes the behavior consistent with that of Openbox.
@johanmalm [#3039] [#3049]
- On interactive resize, only un-maximize the axis/axes that are being resized.
@jlindgren90 [#3043]
- Change theme setting `osd.window-switcher.*` to
`osd.window-switcher.style-classic.*`. Backward compatibility is preserved.
@tokyo4j [#2981]
- In client-list menu, add brackets around the titles of any minimised windows
@davidphilipbarr [#3002]
- Respect client-initiated window resize of non-maximized axis, for example
remember the width of vertically-maximized window resizing itself
horizontally. @jlindgren90 [#3020]
- Remember position of window along non-maximized axis during interactive move.
@jlindgren90 [#3020]
- Restore default libinput device values on reconfigure with empty value, rather
than leaving the old configuration. This makes rc.xml more declarative.
@tokyo4j [#3011]
- Change `If` action when used without a focused window to execute the `<else>`
branch (previously it was just ignored). The reason for this is to make things
more consistent with `<prompt>`. It is not anticipated that this will affect
anyone's workflow but is mentioned here for completeness.
- Make `autoEnableOutputs=no` apply only to drm outputs @jlindgren90 [#2972]
- Take into account `<core><gap>` for edge and region overlays @tokyo4j [#2965]
## 0.9.1 - 2025-08-02
[0.9.1-commits]
This is an earlier-than-usual release containinig bug fixes only. It has been
done on a separate branch to avoid the inclusion of refactoring and new
features.
```
0.9.1 <--- bug-fixes only
/
/
0.8.4--------0.9.0-------- <-- master
```
### Fixed
- Prevent interaction with un-initialized xdg-shell windows after unmap to fix a
bug exposed by `wlroots-0.19.0` resulting in a compositor crash in certain
(unusual) circumstances [#2948] [#2937] [#2944] @Consolatis
- Fix double-free in `img_svg_render()` failure path [#2910] @jlindgren90
- Fix swapped width/height in XWayland client `_NET_WM_ICON` stride calculation
[#2909] @jlindgren90
## 0.9.0 - 2025-07-11
[0.9.0-commits]
The main focus has been to port labwc to wlroots 0.19 [#2388] and fix associated
issues. Special thanks to @Consolatis @jlindgren90 for this.
### Added
- Add client `lab-sensible-terminal` and add a `Terminal` entry to the default
@ -170,7 +415,9 @@ window.*.title.bg.colorTo.splitTo:
</libinput>
```
## [0.8.4]
## 0.8.4 - 2025-05-02
[0.8.4-commits]
This release predominantly consists of bug-fixes, code simplification and
usability improvements. Amongst the new features the most noteworthy is the
@ -234,7 +481,9 @@ release.
- Increase default `<snapping><range>` to 10 to make it easier to snap windows
on the edge between two monitors. @johanmalm [#2602] [#2608]
## [0.8.3]
## 0.8.3 - 2025-02-21
[0.8.3-commits]
The eye-catching new features of this release are undoubtedly:
1. Support for the `ext-workspace` protocol with big thanks to @Consolatis
@ -352,7 +601,9 @@ Notes to package maintainers:
and followMouseRequiresMovement="no" in rc.xml, keyboard-focus semantics
have subtly changed when using the window-switcher. [#2455]
## [0.8.2]
## 0.8.2 - 2024-12-13
[0.8.2-commits]
This is a shorter release cycle compared with the usual 10-week one because it
contains a significant number of stability and cleanliness fixes which warrant
@ -491,7 +742,9 @@ menu.border.color: #aaaaaa
Openbox's behavior and (ii) behave as already described in our own
documentation. [#2380]
## [0.8.1]
## 0.8.1 - 2024-10-25
[0.8.1-commits]
The most noteworthy additions in this release are:
@ -639,7 +892,9 @@ window.inactive.button.shade.unpressed.image.color
per-device configuration of scroll factor (e.g. setting different scroll
factors for mice and touchpads). [#2057]
## [0.8.0]
## 0.8.0 - 2024-08-16
[0.8.0-commits]
The main focus in this release has been to port labwc to wlroots 0.18 and to
grind out associated regressions. Nonetheless, it contains a few non-related
@ -720,7 +975,9 @@ have been attributed with a 'Written-by' against each relevant log entry.
- Make windows stay fullscreen when associated output is disconnected. [#2040]
## [0.7.4]
## 0.7.4 - 2024-06-19
[0.7.4-commits]
### Fixed
@ -728,7 +985,9 @@ have been attributed with a 'Written-by' against each relevant log entry.
- Fix magnifier by disabling direct scanout when active. [#1989]
- Fix crash triggered by pipemenu without parent `<menu>` element. [#1988]
## [0.7.3]
## 0.7.3 - 2024-06-12
[0.7.3-commits]
Following a couple of big releases, this one feels like more steady with lots of
focus on bug fixes and stability. In terms of new features the most noteworthy
@ -817,7 +1076,9 @@ joint effort by @spl237 and @Consolatis.
- Action `MoveToCursor` is deprecated in favour of:
`<action name="AutoPlace" policy="cursor"/>`.
## [0.7.2]
## 0.7.2 - 2024-05-10
[0.7.2-commits]
This release shaped up to be the second in a row that is larger than usual in
terms of both fixes and new features. Significant additions include
@ -1085,7 +1346,9 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff
the DRM backend or by explicit request using environment variable
`LABWC_UPDATE_ACTIVATION_ENV`.
## [0.7.1]
## 0.7.1 - 2024-03-01
[0.7.1-commits]
### Added
@ -1256,7 +1519,9 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff
full `app_id`. Consult the labwc-config(5) manual page for more details.
[#1309]
## [0.7.0] - 2023-12-22
## 0.7.0 - 2023-12-22
[0.7.0-commits]
The main effort in this release has gone into porting labwc to wlroots 0.17
and tidying up regressions. Nonetheless, it contains a significant number of
@ -1316,7 +1581,9 @@ Should bug fixes be required against `0.6.6` (built with wlroots `0.16`), a
- Use the GTK3 notebook header color as the default active title color
(small change from `#dddad6` to `#e1dedb`). Written-by: @dimkr
## [0.6.6] - 2023-11-25
## 0.6.6 - 2023-11-25
[0.6.6-commits]
We do not normally call out contributions by core devs in the changelog,
but a special thanks goes to @jlindgren90 in this release for lots of work
@ -1430,7 +1697,9 @@ relating to surface focus and keyboard issues, amongst others.
will not appear anymore.
- Always switch to the workspace containing the view being focused.
## [0.6.5] - 2023-09-23
## 0.6.5 - 2023-09-23
[0.6.5-commits]
### Added
@ -1506,7 +1775,9 @@ relating to surface focus and keyboard issues, amongst others.
- Do not expand environment variables in `Exec` action `<command>`
argument (but still resolve tilde).
## [0.6.4] - 2023-07-14
## 0.6.4 - 2023-07-14
[0.6.4-commits]
### Added
@ -1547,7 +1818,9 @@ relating to surface focus and keyboard issues, amongst others.
- Make `ToggleKeybinds` applicable only to the window that has keyboard focus
when the action is executed.
## [0.6.3] - 2023-05-08
## 0.6.3 - 2023-05-08
[0.6.3-commits]
### Added
@ -1619,7 +1892,9 @@ relating to surface focus and keyboard issues, amongst others.
- Default to follow="true" for SendToDesktop action as per Openbox 3.6
specification.
## [0.6.2] - 2023-03-20
## 0.6.2 - 2023-03-20
[0.6.2-commits]
This release contains refactoring and simplification relating to
view-output association and xdg/xwayland configure/map events.
@ -1681,7 +1956,9 @@ Unless otherwise stated all contributions are by the core-devs
</core>
```
## [0.6.1] - 2023-01-29
## 0.6.1 - 2023-01-29
[0.6.1-commits]
As usual, this release contains lots of refactoring and bug fixes with
particular thanks going to @Consolatis, @jlindgren90, @bi4k8, @Flrian and
@ -1744,7 +2021,9 @@ particular thanks going to @Consolatis, @jlindgren90, @bi4k8, @Flrian and
VS Code and Discord lagging over time. [#553] Written-by: @Joshua-Ashton
- Do not switch output on SnapToEdge if view is maximized. Written-by: @Flrian
## [0.6.0] - 2022-11-17
## 0.6.0 - 2022-11-17
[0.6.0-commits]
This release contains significant refactoring to use the wlroots
scene-graph API. This touches many areas of the code, particularly
@ -1911,7 +2190,9 @@ reported, tested and fixed issues. Particular mentions go to @bi4k8,
exited the compositor by mistake trying to get out of alt-tab cycling
or similar.
## [0.5.3] - 2022-07-15
## 0.5.3 - 2022-07-15
[0.5.3-commits]
### Added
@ -1933,7 +2214,9 @@ reported, tested and fixed issues. Particular mentions go to @bi4k8,
- Do not segfault on missing drag icon. Written-by: @Consolatis
- Fix windows erratically sticking to edges during move/resize [#331] [#309]
## [0.5.2] - 2022-05-17
## 0.5.2 - 2022-05-17
[0.5.2-commits]
This is a minor bugfix release mostly to ease packaging.
@ -1941,7 +2224,9 @@ This is a minor bugfix release mostly to ease packaging.
- Properly use system provided wlroots. Written-by: @eli-schwartz
## [0.5.1] - 2022-04-08
## 0.5.1 - 2022-04-08
[0.5.1-commits]
### Added
@ -1968,7 +2253,9 @@ This is a minor bugfix release mostly to ease packaging.
- Fix qt application crash on touchpad scroll [#225]
Written-by: @Consolatis
## [0.5.0] - 2022-02-18
## 0.5.0 - 2022-02-18
[0.5.0-commits]
As usual, this release contains a bunch of fixes and improvements, of
which the most notable feature-type changes are listed below. A big
@ -2005,7 +2292,9 @@ This release contains the following two breaking changes:
updating any local `rc.xml` settings in accordance with
`docs/rc.xml.all`
## [0.4.0] - 2021-12-31
## 0.4.0 - 2021-12-31
[0.4.0-commits]
Compile with wlroots 0.15.0
@ -2080,7 +2369,9 @@ feature-type changes are listed below.
- The config option `<lab><xdg_shell_server_side_deco>` has changed to
`<core><decoration>` (breaking change)
## [0.3.0] - 2021-06-28
## 0.3.0 - 2021-06-28
[0.3.0-commits]
Compile with wlroots 0.14.0
@ -2091,7 +2382,9 @@ Compile with wlroots 0.14.0
- Do not use Clearlooks-3.4 theme by default, just use built-in theme
- Fix bug which triggered Qt application segfault
## [0.2.0] - 2021-04-15
## 0.2.0 - 2021-04-15
[0.2.0-commits]
Compile with wlroots 0.13.0
@ -2104,7 +2397,9 @@ Compile with wlroots 0.13.0
- Add labwc-environment(5)
- Call `wlr_output_enable_adaptive_sync()` if `LABWC_ADAPTIVE_SYNC` set
## [0.1.0] - 2021-03-05
## 0.1.0 - 2021-03-05
[0.1.0-commits]
Compile with wlroots 0.12.0 and wayland-server >=1.16
@ -2123,33 +2418,35 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
ShowMenu
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[unreleased]: https://github.com/labwc/labwc/compare/0.9.0...HEAD
[0.9.0]: https://github.com/labwc/labwc/compare/0.8.4...0.9.0
[0.8.4]: https://github.com/labwc/labwc/compare/0.8.3...0.8.4
[0.8.3]: https://github.com/labwc/labwc/compare/0.8.2...0.8.3
[0.8.2]: https://github.com/labwc/labwc/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/labwc/labwc/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/labwc/labwc/compare/0.7.3...0.8.0
[0.7.4]: https://github.com/labwc/labwc/compare/0.7.3...0.7.4
[0.7.3]: https://github.com/labwc/labwc/compare/0.7.2...0.7.3
[0.7.2]: https://github.com/labwc/labwc/compare/0.7.1...0.7.2
[0.7.1]: https://github.com/labwc/labwc/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/labwc/labwc/compare/0.6.6...0.7.0
[0.6.6]: https://github.com/labwc/labwc/compare/0.6.5...0.6.6
[0.6.5]: https://github.com/labwc/labwc/compare/0.6.4...0.6.5
[0.6.4]: https://github.com/labwc/labwc/compare/0.6.3...0.6.4
[0.6.3]: https://github.com/labwc/labwc/compare/0.6.2...0.6.3
[0.6.2]: https://github.com/labwc/labwc/compare/0.6.1...0.6.2
[0.6.1]: https://github.com/labwc/labwc/compare/0.6.0...0.6.1
[0.6.0]: https://github.com/labwc/labwc/compare/0.5.0...0.6.0
[0.5.3]: https://github.com/labwc/labwc/compare/0.5.2...0.5.3
[0.5.2]: https://github.com/labwc/labwc/compare/0.5.1...0.5.2
[0.5.1]: https://github.com/labwc/labwc/compare/0.5.0...0.5.1
[0.5.0]: https://github.com/labwc/labwc/compare/0.4.0...0.5.0
[0.4.0]: https://github.com/labwc/labwc/compare/0.3.0...0.4.0
[0.3.0]: https://github.com/labwc/labwc/compare/0.2.0...0.3.0
[0.2.0]: https://github.com/labwc/labwc/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/labwc/labwc/compare/081339e...0.1.0
[unreleased-commits]: https://github.com/labwc/labwc/compare/0.9.2...HEAD
[0.9.2-commits]: https://github.com/labwc/labwc/compare/0.9.1...0.9.2
[0.9.1-commits]: https://github.com/labwc/labwc/compare/0.9.0...0.9.1
[0.9.0-commits]: https://github.com/labwc/labwc/compare/0.8.4...0.9.0
[0.8.4-commits]: https://github.com/labwc/labwc/compare/0.8.3...0.8.4
[0.8.3-commits]: https://github.com/labwc/labwc/compare/0.8.2...0.8.3
[0.8.2-commits]: https://github.com/labwc/labwc/compare/0.8.1...0.8.2
[0.8.1-commits]: https://github.com/labwc/labwc/compare/0.8.0...0.8.1
[0.8.0-commits]: https://github.com/labwc/labwc/compare/0.7.3...0.8.0
[0.7.4-commits]: https://github.com/labwc/labwc/compare/0.7.3...0.7.4
[0.7.3-commits]: https://github.com/labwc/labwc/compare/0.7.2...0.7.3
[0.7.2-commits]: https://github.com/labwc/labwc/compare/0.7.1...0.7.2
[0.7.1-commits]: https://github.com/labwc/labwc/compare/0.7.0...0.7.1
[0.7.0-commits]: https://github.com/labwc/labwc/compare/0.6.6...0.7.0
[0.6.6-commits]: https://github.com/labwc/labwc/compare/0.6.5...0.6.6
[0.6.5-commits]: https://github.com/labwc/labwc/compare/0.6.4...0.6.5
[0.6.4-commits]: https://github.com/labwc/labwc/compare/0.6.3...0.6.4
[0.6.3-commits]: https://github.com/labwc/labwc/compare/0.6.2...0.6.3
[0.6.2-commits]: https://github.com/labwc/labwc/compare/0.6.1...0.6.2
[0.6.1-commits]: https://github.com/labwc/labwc/compare/0.6.0...0.6.1
[0.6.0-commits]: https://github.com/labwc/labwc/compare/0.5.0...0.6.0
[0.5.3-commits]: https://github.com/labwc/labwc/compare/0.5.2...0.5.3
[0.5.2-commits]: https://github.com/labwc/labwc/compare/0.5.1...0.5.2
[0.5.1-commits]: https://github.com/labwc/labwc/compare/0.5.0...0.5.1
[0.5.0-commits]: https://github.com/labwc/labwc/compare/0.4.0...0.5.0
[0.4.0-commits]: https://github.com/labwc/labwc/compare/0.3.0...0.4.0
[0.3.0-commits]: https://github.com/labwc/labwc/compare/0.2.0...0.3.0
[0.2.0-commits]: https://github.com/labwc/labwc/compare/0.1.0...0.2.0
[0.1.0-commits]: https://github.com/labwc/labwc/compare/081339e...0.1.0
[#162]: https://github.com/labwc/labwc/pull/162
[#163]: https://github.com/labwc/labwc/pull/163
@ -2496,12 +2793,14 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#2652]: https://github.com/labwc/labwc/pull/2652
[#2653]: https://github.com/labwc/labwc/pull/2653
[#2657]: https://github.com/labwc/labwc/pull/2657
[#2667]: https://github.com/labwc/labwc/pull/2667
[#2669]: https://github.com/labwc/labwc/pull/2669
[#2678]: https://github.com/labwc/labwc/pull/2678
[#2686]: https://github.com/labwc/labwc/pull/2686
[#2688]: https://github.com/labwc/labwc/pull/2688
[#2692]: https://github.com/labwc/labwc/pull/2692
[#2693]: https://github.com/labwc/labwc/pull/2693
[#2699]: https://github.com/labwc/labwc/pull/2699
[#2700]: https://github.com/labwc/labwc/pull/2700
[#2710]: https://github.com/labwc/labwc/pull/2710
[#2713]: https://github.com/labwc/labwc/pull/2713
@ -2545,6 +2844,53 @@ Compile with wlroots 0.12.0 and wayland-server >=1.16
[#2873]: https://github.com/labwc/labwc/pull/2873
[#2874]: https://github.com/labwc/labwc/pull/2874
[#2877]: https://github.com/labwc/labwc/pull/2877
[#2883]: https://github.com/labwc/labwc/pull/2883
[#2885]: https://github.com/labwc/labwc/pull/2885
[#2886]: https://github.com/labwc/labwc/pull/2886
[#2887]: https://github.com/labwc/labwc/pull/2887
[#2891]: https://github.com/labwc/labwc/pull/2891
[#2895]: https://github.com/labwc/labwc/pull/2895
[#2909]: https://github.com/labwc/labwc/pull/2909
[#2910]: https://github.com/labwc/labwc/pull/2910
[#2914]: https://github.com/labwc/labwc/pull/2914
[#2933]: https://github.com/labwc/labwc/pull/2933
[#2937]: https://github.com/labwc/labwc/pull/2937
[#2939]: https://github.com/labwc/labwc/pull/2939
[#2942]: https://github.com/labwc/labwc/pull/2942
[#2943]: https://github.com/labwc/labwc/pull/2943
[#2944]: https://github.com/labwc/labwc/pull/2944
[#2948]: https://github.com/labwc/labwc/pull/2948
[#2965]: https://github.com/labwc/labwc/pull/2965
[#2967]: https://github.com/labwc/labwc/pull/2967
[#2970]: https://github.com/labwc/labwc/pull/2970
[#2971]: https://github.com/labwc/labwc/pull/2971
[#2972]: https://github.com/labwc/labwc/pull/2972
[#2976]: https://github.com/labwc/labwc/pull/2976
[#2981]: https://github.com/labwc/labwc/pull/2981
[#2994]: https://github.com/labwc/labwc/pull/2994
[#2995]: https://github.com/labwc/labwc/pull/2995
[#2998]: https://github.com/labwc/labwc/pull/2998
[#3002]: https://github.com/labwc/labwc/pull/3002
[#3004]: https://github.com/labwc/labwc/pull/3004
[#3011]: https://github.com/labwc/labwc/pull/3011
[#3015]: https://github.com/labwc/labwc/pull/3015
[#3020]: https://github.com/labwc/labwc/pull/3020
[#3024]: https://github.com/labwc/labwc/pull/3024
[#3028]: https://github.com/labwc/labwc/pull/3028
[#3033]: https://github.com/labwc/labwc/pull/3033
[#3039]: https://github.com/labwc/labwc/pull/3039
[#3042]: https://github.com/labwc/labwc/pull/3042
[#3043]: https://github.com/labwc/labwc/pull/3043
[#3047]: https://github.com/labwc/labwc/pull/3047
[#3049]: https://github.com/labwc/labwc/pull/3049
[#3081]: https://github.com/labwc/labwc/pull/3081
[#3097]: https://github.com/labwc/labwc/pull/3097
[#3099]: https://github.com/labwc/labwc/pull/3099
[#3118]: https://github.com/labwc/labwc/pull/3118
[#3120]: https://github.com/labwc/labwc/pull/3120
[#3124]: https://github.com/labwc/labwc/pull/3124
[#3126]: https://github.com/labwc/labwc/pull/3126
[#3134]: https://github.com/labwc/labwc/pull/3134
[#3145]: https://github.com/labwc/labwc/pull/3145
[#3148]: https://github.com/labwc/labwc/pull/3148
[#3153]: https://github.com/labwc/labwc/pull/3153

View file

@ -101,21 +101,8 @@ spend our effort.
A lot of emphasis is put on code simplicity when considering features.
The main development effort is focused on producing a solid foundation for a
stacking compositor rather than adding configuration and theming options.
See [scope] for full details on implemented features.
High-level summary of items that Labwc supports:
- [x] Config files (rc.xml, autostart, shutdown, environment, menu.xml)
- [x] Theme files and xbm/png/svg icons
- [x] Basic desktop and client menus
- [x] HiDPI
- [x] wlroots protocols such as `output-management`, `layer-shell` and
`foreign-toplevel`
- [x] Optionally xwayland
### 1.5 Videos
| video link | date | duration
@ -249,7 +236,7 @@ Suggested apps to use with Labwc:
- Screen shooter: [grim]
- Screen recorder: [wf-recorder]
- Background image: [swaybg]
- Panel: [waybar], [yambar], [lavalauncher], [sfwbar], [xfce4-panel]
- Panel: [waybar], [lavalauncher], [sfwbar], [xfce4-panel]
- Launchers: [bemenu], [fuzzel], [wofi]
- Output managers: [wlopm], [kanshi], [wlr-randr]
- Screen locker: [swaylock]
@ -292,7 +279,6 @@ The default window bar menu can be translated on the [weblate platform](https://
[wf-recorder]: https://github.com/ammen99/wf-recorder
[swaybg]: https://github.com/swaywm/swaybg
[waybar]: https://github.com/Alexays/Waybar
[yambar]: https://codeberg.org/dnkl/yambar
[lavalauncher]: https://sr.ht/~leon_plickat/LavaLauncher
[sfwbar]: https://github.com/LBCrion/sfwbar
[xfce4-panel]: https://gitlab.xfce.org/xfce/xfce4-panel

1874
clients/labnag.c Normal file

File diff suppressed because it is too large Load diff

59
clients/meson.build Normal file
View file

@ -0,0 +1,59 @@
wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor')
nag_sources = files(
'labnag.c',
'pool-buffer.c',
)
wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
protocols = [
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
'../protocols/wlr-layer-shell-unstable-v1.xml',
]
foreach xml : protocols
nag_sources += custom_target(
xml.underscorify() + '_c',
input: xml,
output: '@BASENAME@-protocol.c',
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
)
nag_sources += custom_target(
xml.underscorify() + '_client_h',
input: xml,
output: '@BASENAME@-client-protocol.h',
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
)
endforeach
if host_machine.system() in ['freebsd', 'openbsd']
# For signalfd()
epoll_dep = dependency('epoll-shim')
else
epoll_dep = []
endif
executable(
'labnag',
nag_sources,
dependencies: [
cairo,
pangocairo,
glib,
wayland_client,
wayland_cursor,
wlroots,
server_protos,
epoll_dep,
xkbcommon,
],
include_directories: [labwc_inc],
install: true,
)
clients = files('lab-sensible-terminal')
install_data(clients, install_dir: get_option('bindir'))

141
clients/pool-buffer.c Normal file
View file

@ -0,0 +1,141 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copied from https://github.com/swaywm/sway
*
* Copyright (C) 2016-2017 Drew DeVault
*/
#define _POSIX_C_SOURCE 200809L
#include <cairo.h>
#include <errno.h>
#include <fcntl.h>
#include <pango/pangocairo.h>
#include <stdio.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include "pool-buffer.h"
static int anonymous_shm_open(void)
{
int retries = 100;
do {
// try a probably-unique name
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
pid_t pid = getpid();
char name[50];
snprintf(name, sizeof(name), "/labnag-%x-%x",
(unsigned int)pid, (unsigned int)ts.tv_nsec);
// shm_open guarantees that O_CLOEXEC is set
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd >= 0) {
shm_unlink(name);
return fd;
}
--retries;
} while (retries > 0 && errno == EEXIST);
return -1;
}
static void buffer_release(void *data, struct wl_buffer *wl_buffer)
{
struct pool_buffer *buffer = data;
buffer->busy = false;
}
static const struct wl_buffer_listener buffer_listener = {
.release = buffer_release
};
static struct pool_buffer *create_buffer(struct wl_shm *shm,
struct pool_buffer *buf, int32_t width, int32_t height,
uint32_t format)
{
uint32_t stride = width * 4;
size_t size = stride * height;
int fd = anonymous_shm_open();
if (fd == -1) {
return NULL;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return NULL;
}
void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size);
buf->buffer = wl_shm_pool_create_buffer(pool, 0,
width, height, stride, format);
wl_shm_pool_destroy(pool);
close(fd);
buf->size = size;
buf->width = width;
buf->height = height;
buf->data = data;
buf->surface = cairo_image_surface_create_for_data(data,
CAIRO_FORMAT_ARGB32, width, height, stride);
buf->cairo = cairo_create(buf->surface);
buf->pango = pango_cairo_create_context(buf->cairo);
wl_buffer_add_listener(buf->buffer, &buffer_listener, buf);
return buf;
}
void destroy_buffer(struct pool_buffer *buffer)
{
if (buffer->buffer) {
wl_buffer_destroy(buffer->buffer);
buffer->buffer = NULL;
}
if (buffer->cairo) {
cairo_destroy(buffer->cairo);
buffer->cairo = NULL;
}
if (buffer->surface) {
cairo_surface_destroy(buffer->surface);
buffer->surface = NULL;
}
if (buffer->pango) {
g_object_unref(buffer->pango);
buffer->pango = NULL;
}
if (buffer->data) {
munmap(buffer->data, buffer->size);
buffer->data = NULL;
}
}
struct pool_buffer *get_next_buffer(struct wl_shm *shm,
struct pool_buffer pool[static 2], uint32_t width, uint32_t height)
{
struct pool_buffer *buffer = NULL;
for (size_t i = 0; i < 2; ++i) {
if (pool[i].busy) {
continue;
}
buffer = &pool[i];
}
if (!buffer) {
return NULL;
}
if (buffer->width != width || buffer->height != height) {
destroy_buffer(buffer);
}
if (!buffer->buffer) {
if (!create_buffer(shm, buffer, width, height,
WL_SHM_FORMAT_ARGB8888)) {
return NULL;
}
}
buffer->busy = true;
return buffer;
}

30
clients/pool-buffer.h Normal file
View file

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copied from https://github.com/swaywm/sway
*
* Copyright (C) 2016-2017 Drew DeVault
*/
#ifndef LAB_POOL_BUFFER_H
#define LAB_POOL_BUFFER_H
#include <cairo.h>
#include <pango/pangocairo.h>
#include <stdbool.h>
#include <stdint.h>
#include <wayland-client.h>
struct pool_buffer {
struct wl_buffer *buffer;
cairo_surface_t *surface;
cairo_t *cairo;
PangoContext *pango;
uint32_t width, height;
void *data;
size_t size;
bool busy;
};
struct pool_buffer *get_next_buffer(struct wl_shm *shm,
struct pool_buffer pool[static 2], uint32_t width, uint32_t height);
void destroy_buffer(struct pool_buffer *buffer);
#endif /* LAB_POOL_BUFFER_H */

143
docs/labnag.1.scd Normal file
View file

@ -0,0 +1,143 @@
labnag(1)
# NAME
labnag - Show dialog with message and buttons
# SYNOPSIS
_labnag_ [options...]
# OPTIONS
*-B, --button* <text> [<action>]
Create a button with the text _text_ that optionally executes _action_
when pressed. Multiple buttons can be defined by providing the flag
multiple times. Buttons will appear in the order they are provided from
left to right.
*-Z, --button-dismiss* <text> [<action>]
Create a button with the text _text_ that optionally executes _action_
when pressed, and dismisses labnag. Multiple buttons can be defined by
providing the flag multiple times. Buttons will appear in the order
they are provided from left to right.
*-d, --debug*
Enable debugging.
*-e, --edge* top|bottom
Set the edge to use.
*-y, --layer* overlay|top|bottom|background
Set the layer to use.
*-k, --keyboard-focus none|exclusive|on-demand*
Set the policy for keyboard focus.
*-f, --font* <font>
Set the font to use.
*-h, --help*
Show help message and quit.
*-l, --detailed-message*
Read a detailed message from stdin. A button to toggle details will be
added. Details are shown in a scrollable multi-line text area.
*-L, --detailed-button* <text>
Set the text for the button that toggles details. This has no effect if
there is not a detailed message. The default is _Toggle details_.
*-m, --message* <msg>
Set the message text.
*-o, --output* <output>
Set the output to use. This should be the name of a _xdg\_output_.
*-t, --timeout*
Set duration to close dialog. Default is 5 seconds.
*-x, --exclusive-zone*
Use exclusive zone. Default is false.
*-v, --version*
Show the version number and quit.
# APPEARANCE OPTIONS
*--background-color* <RRGGBB[AA]>
Set the color of the background.
*--button-border-color* <RRGGBB[AA]>
Set the color of the button border.
*--border-bottom-color* <RRGGBB[AA]>
Set the color of the bottom border.
*--button-background-color* <RRGGBB[AA]>
Set the color for the background for buttons.
*--text-color* <RRGGBB[AA]>
Set the text color.
*--button-text-color* <RRGGBB[AA]>
Set the button text color.
*--border-bottom-size* <size>
Set the thickness of the bottom border.
*--message-padding* <padding>
Set the padding for the message.
*--details-background-color* <RRGGBB[AA]>
Set the color for the background for details.
*--details-border-size* <size>
Set the thickness for the details border.
*--button-border-size* <size>
Set the thickness for the button border.
*--button-gap* <gap>
Set the size of the gap between buttons.
*--button-dismiss-gap* <gap>
Set the size of the gap between the dismiss button and another button.
*--button-margin-right* <margin>
Set the margin from the right of the dismiss button to edge.
*--button-padding* <padding>
Set the padding for the button text.
# EXAMPLE
This is a simple example of a _labnag_ logout GUI.
```
#!/bin/sh
# logout with labnag
labnag \\
-f "Hack Regular 10"\\
-m "Choose your logout option"\\
-Z " Lock " "gtklock -d"\\
-Z " Logout " "labwc -e"\\
-Z "Shutdown " "systemctl poweroff"\\
-Z " Reboot " "systemctl reboot"\\
-Z "Hibernate" "systemctl hibernate"\\
-Z " Suspend " "systemctl suspend"\\
-Z " Cancel "\\
--background-color 00ffff\\
--button-background-color 00ffff\\
--button-border-color 00ccccaa\\
--text-color 000000\\
--button-text-color 000000\\
--button-gap 8\\
--button-margin-right 0\\
--button-padding 5\\
--button-border-size 2\\
-t 60
```

View file

@ -92,10 +92,18 @@ Actions are used in menus and keyboard/mouse bindings.
Move window relative to its current position. Positive value of x moves
it right, negative left. Positive value of y moves it down, negative up.
*<action name="ToggleSnapToEdge" direction="value" />*++
*<action name="SnapToEdge" direction="value" />*
Resize window to fill half the output in the given direction. Supports
directions "left", "up", "right", "down" and "center".
*<action name="ToggleSnapToEdge" direction="value" combine="value" />*++
*<action name="SnapToEdge" direction="value" combine="value" />*
Resize window to fill half or quarter the output in the given direction.
*direction* [up|down|left|right|up-left|up-right|down-left|down-right|center]
Direction in which to snap the window.
*combine* [yes|no]
Allows to snap a window to an output corner by combining two
directions. For example, snapping a window to *right* and then
to *up* places it in the *up-right* quarter of the output.
Default is no.
ToggleSnapToEdge additionally toggles the active window between
tiled to the given direction and its untiled position.
@ -227,10 +235,10 @@ Actions are used in menus and keyboard/mouse bindings.
window.
*<action name="ToggleKeybinds" />*
Stop handling keybinds other than ToggleKeybinds itself.
This can be used to allow A-Tab and similar keybinds to be delivered
to Virtual Machines, VNC clients or nested compositors.
A second call will restore all original keybinds.
Stop handling keybinds/mousebinds other than ToggleKeybinds itself.
This can be used to allow A-Tab and similar keybinds/mousebinds to be
delivered to Virtual Machines, VNC clients or nested compositors.
A second call will restore all original keybinds/mousebinds.
This action will only affect the window that had keyboard focus when
the binding was executed. Thus when switching to another window, all
@ -277,7 +285,7 @@ Actions are used in menus and keyboard/mouse bindings.
Resizes active window size to width and height of the output when the
window size exceeds the output size.
*<action name="GoToDesktop" to="value" wrap="yes" />*
*<action name="GoToDesktop" to="value" wrap="yes" toggle="no" />*
Switch to workspace.
*to* The workspace to switch to. Supported values are "current", "last",
@ -287,6 +295,9 @@ Actions are used in menus and keyboard/mouse bindings.
*wrap* [yes|no] Wrap around from last desktop to first, and vice
versa. Default yes.
*toggle* [yes|no] Toggle to “last” if already on the workspace that
would be the actual destination. Default no.
*<action name="SendToDesktop" to="value" follow="yes" wrap="yes" />*
Send active window to workspace.
@ -422,6 +433,7 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
```
<action name="If">
<query/>
<prompt message=""/>
<then><action/></then>
<else><action/></else>
</action>
@ -474,7 +486,7 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
The "left" , "right", "left-occupied" and
"right-occupied" directions will not wrap.
*tiled* [up|right|down|left|center]
*tiled* [up|right|down|left|up-left|up-right|down-left|down-right|center|any]
Whether the client is tiled (snapped) along the the
indicated screen edge.
@ -493,6 +505,26 @@ Actions that execute other actions. Used in keyboard/mouse bindings.
This argument is optional.
*prompt*
Display a yes/no prompt dialog (labnag by default). If 'yes' is
selected, the *then* branch will be taken; and similarly with
'no' and *else*. This argument is optional. Note that the syntax
is different to that of Openbox where a prompt element is not
tied to If-actions but would just be a child of the downstream
action. The reason for this difference is increased flexibility
and functionality gained by optionally using an *else* branch.
```
<keybind key="W-q">
<action name="If">
<prompt message="Quit?"/>
<then>
<action name="Exit"/>
</then>
</action>
</keybind>
```
*then*
A list of actions to be executed if the window matches any
query. This argument is optional.

View file

@ -178,6 +178,7 @@ this is for compatibility with Openbox.
<reuseOutputMode>no</reuseOutputMode>
<xwaylandPersistence>no</xwaylandPersistence>
<primarySelection>yes</primarySelection>
<promptCommand>[see details below]</promptCommand>
</core>
```
@ -216,12 +217,29 @@ this is for compatibility with Openbox.
*<core><autoEnableOutputs>* [yes|no]
Automatically enable outputs at startup and when new outputs are
connected. Default is yes.
connected. This option applies only to drm outputs. Default is yes.
Caution: Disabling this option will make the labwc session unusable
unless an external tool such as `wlr-randr` or `kanshi` is used to
manage outputs.
The reason for the existance of this option is that after losing signal
from the PC (e.g. by `wlopm -off`), some monitors do an input detection
that makes it appear (from the PC side) to disconnect and reconnect a
few seconds later, causing the monitor to turn back on again (as labwc
auto-enables newly connected outputs by default).
An example usage pattern to avoid the above behavior looks as follows:
- Set *<core><autoEnableOutputs>* to *no*
- Run kanshi (e.g. from autostart) and rely on it to enable new outputs
- Have swayidle kill and restart kanshi when entering powersave as
follows:
```
swayidle -w timeout 600 \\
'pkill kanshi ; wlopm --off \*' resume 'kanshi & wlopm --on \*'
```
*<core><reuseOutputMode>* [yes|no]
Try to re-use the existing output mode (resolution / refresh rate).
This may prevent unnecessary screenblank delays when starting labwc
@ -242,6 +260,55 @@ this is for compatibility with Openbox.
up/down) in Chromium and electron based clients without inadvertantly
pasting the primary clipboard. Default is yes.
*<core><promptCommand>*
Set command to be invoked for an action prompt (*<action><prompt>*)
The following conversion specifiers are supported:
- *%m*: the *<prompt>* message option
- *%n*: "No" (in local language if translation is available)
- *%y*: "Yes" (in local language if translation is available)
- *%b*: osd.bg.color
- *%t*: osd.label.text.color
The default prompt command is:
```
labnag \\
--message '%m' \\
--button-dismiss '%n' \\
--button-dismiss '%y' \\
--background-color '%b' \\
--text-color '%t' \\
--button-border-color '%t' \\
--border-bottom-color '%t' \\
--button-background-color '%b' \\
--button-text-color '%t' \\
--border-bottom-size 1 \\
--button-border-size 3 \\
--keyboard-focus on-demand \\
--layer overlay \\
--timeout 0
```
Example 1: The prompt can be configured to use a different dialog client
```
<core>
<promptCommand>zenity --question --text="%m"</promptCommand>
</core>
```
Example 2: A more complex zenity command could be used:
```
zenity \\
--question \\
--title="" \\
--text="%m" \\
--ok-label="%y" \\
--cancel-label="%n"
```
## PLACEMENT
```
@ -272,7 +339,7 @@ this is for compatibility with Openbox.
## WINDOW SWITCHER
```
<windowSwitcher show="yes" preview="yes" outlines="yes" allWorkspaces="no">
<windowSwitcher show="yes" style="classic" preview="yes" outlines="yes" allWorkspaces="no">
<fields>
<field content="icon" width="5%" />
<field content="desktop_entry_name" width="30%" />
@ -281,10 +348,14 @@ this is for compatibility with Openbox.
</windowSwitcher>
```
*<windowSwitcher show="" preview="" outlines="" allWorkspaces="">*
*<windowSwitcher show="" style="" preview="" outlines="" allWorkspaces="" unshade="">*
*show* [yes|no] Draw the OnScreenDisplay when switching between
windows. Default is yes.
*style* [classic|thumbnail] Configures the style of the OnScreenDisplay.
"classic" displays window information like icons and titles in a vertical list.
"thumbnail" shows window thumbnail, icon and title in grids.
*preview* [yes|no] Preview the contents of the selected window when
switching between windows. Default is yes.
@ -295,8 +366,11 @@ this is for compatibility with Openbox.
they are on. Default no (that is only windows on the current workspace
are shown).
*unshade* [yes|no] Temporarily unshade windows when switching between
them and permanently unshade on the final selection. Default is yes.
*<windowSwitcher><fields><field content="" width="%">*
Define window switcher fields.
Define window switcher fields when using *<windowSwitcher style="classic" />*.
*content* defines what the field shows and can be any of:
@ -328,9 +402,9 @@ this is for compatibility with Openbox.
fields are:
- 'B' - shell type, values [xwayland|xdg-shell]
- 'b' - shell type (short form), values [X|W]
- 'S' - state of window, values [M|m|F] (3 spaces allocated)
(maximized, minimized, fullscreen)
- 's' - state of window (short form), values [M|m|F] (1 space)
- 'S' - state of window, values [m|s|M|F] (4 spaces allocated)
(minimized, shaded, maximized, fullscreen)
- 's' - state of window (short form), values [m|s|M|F] (1 space)
- 'I' - wm-class/app-id
- 'i' - wm-class/app-id trimmed, remove "org." if available
- 'n' - desktop entry/file application name, falls back to
@ -412,11 +486,13 @@ activated with SnapToEdge actions or, optionally, by dragging windows to the
edges of an output. Edge snapping causes a window to occupy half of its output,
extending outward from the snapped edge.
*<snapping><range>*
If an interactive move ends with the cursor a maximum distance *range*,
(in pixels) from the edge of an output, the move will trigger a
SnapToEdge action for that edge. A *range* of 0 disables snapping via
interactive moves. Default is 10.
*<snapping><range>*++
*<snapping><cornerRange>*
If an interactive move ends with the cursor within *<range>* pixels of an
output edge, the window is snapped to the edge. If it's also within
*<cornerRange>* pixels of an output corner, the window is snapped to the
corner instead. A *<range>* of 0 disables snapping.
Default is 10 for *<range>* and 50 for *<cornerRange>*.
*<snapping><overlay><enabled>* [yes|no]
Show an overlay when snapping to a window to an edge. Default is yes.
@ -526,6 +602,11 @@ extending outward from the snapped edge.
Even when disabling server side decorations via ToggleDecorations,
keep a small border (and resize area) around the window. Default is yes.
*<theme><maximizedDecoration>* [titlebar|none]
Specify how server side decorations are shown for maximized windows.
*titlebar* shows titlebar above a maximized window. *none* shows no server
side decorations around a maximized window. Default is titlebar.
*<theme><dropShadows>* [yes|no]
Should drop-shadows be rendered behind windows. Default is no.
@ -698,7 +779,7 @@ extending outward from the snapped edge.
W-Return - lab-sensible-terminal
A-F4 - close window
W-a - toggle maximize
W-<arrow> - resize window to fill half the output
W-<arrow> - resize window to fill half or quarter of the output
A-Space - show window menu
```
@ -735,6 +816,7 @@ extending outward from the snapped edge.
- AllDesktops: A button that, by default, toggles omnipresence of a
window.
- Close: A button that, by default, closses a window.
- Border: The window's border including Top...BRCorner below.
- Top: The top edge of the window's border.
- Bottom: The bottom edge of the window's border.
- Left: The left edge of the window's border.

View file

@ -303,32 +303,79 @@ all are supported.
Text color of on-screen-display. Inherits
*window.active.label.text.color* if not set.
*osd.window-switcher.width*
Width of window switcher in pixels. Default is 600.
Width can also be percent of the width of the monitor.
% is mandatory as last character in this case, max 100%
*osd.window-switcher.style-classic*
Theme for window switcher when using <windowSwitcher style="classic" />.
See below for details.
*osd.window-switcher.padding*
*osd.window-switcher.style-classic.width*
Width of window switcher in pixels. Width can also be a percentage of the
monitor width by adding '%' as suffix (e.g. 70%). Default is 600.
*osd.window-switcher.style-classic.padding*
Padding of window switcher in pixels. This is the space between the
window-switcher border and its items. Default is 4.
*osd.window-switcher.item.padding.x*
*osd.window-switcher.style-classic.item.padding.x*
Horizontal padding of window switcher entries in pixels.
Default is 10.
*osd.window-switcher.item.padding.y*
*osd.window-switcher.style-classic.item.padding.y*
Vertical padding of window switcher entries in pixels.
Default is 1.
*osd.window-switcher.item.active.border.width*
*osd.window-switcher.style-classic.item.active.border.width*
Border width of the selection box in the window switcher in pixels.
Default is 2.
*osd.window-switcher.item.icon.size*
*osd.window-switcher.style-classic.item.active.border.color*
Border color around the selected window switcher item.
Default is *osd.label.text.color* with 50% opacity.
*osd.window-switcher.style-classic.item.active.bg.color*
Background color of the selected window switcher item.
Default is *osd.label.text.color* with 15% opacity.
*osd.window-switcher.style-classic.item.icon.size*
Size of the icon in window switcher, in pixels.
If not set, the font size derived from <theme><font place="OnScreenDisplay">
is used.
*osd.window-switcher.style-thumbnail*
Theme for window switcher when using <windowSwitcher style="thumbnail" />.
See below for details.
*osd.window-switcher.style-thumbnail.width.max*
Maximum width of window switcher in pixels. Width can also be a percentage of
the monitor width by adding '%' as suffix (e.g. 70%). Default is 80%.
*osd.window-switcher.style-thumbnail.padding*
Padding of window switcher in pixels. This is the space between the
window-switcher border and its items. Default is 4.
*osd.window-switcher.style-thumbnail.item.width*
Width of window switcher items in pixels. Default is 300.
*osd.window-switcher.style-thumbnail.item.height*
Height of window switcher items in pixels. Default is 250.
*osd.window-switcher.style-thumbnail.item.padding*
Padding of window switcher items in pixels. This is the space between the
border around selected items and window thumbnail. Default is 2.
*osd.window-switcher.style-thumbnail.item.active.border.width*
Border width of selected window switcher items in pixels. Default is 2.
*osd.window-switcher.style-thumbnail.item.active.border.color*
Color of border around selected window switcher items.
Default is *osd.label.text.color* with 50% opacity.
*osd.window-switcher.style-thumbnail.item.active.bg.color*
Color of selected window switcher items.
Default is *osd.label.text.color* with 15% opacity.
*osd.window-switcher.style-thumbnail.item.icon.size*
Size of window icons in window switcher items in pixels. Default is 60.
*osd.window-switcher.preview.border.width*
Border width of the outlines shown as the preview of the window selected
by window switcher. Inherits *osd.border.width* if not set.

View file

@ -134,8 +134,7 @@ example: *LABWC_DEBUG_FOO=1 labwc*.
Increase logging of paths for config files (for example rc.xml,
autostart, environment and menu.xml) as well as titlebar buttons.
*LABWC_DEBUG_CONFIG_NODENAMES*++
*LABWC_DEBUG_MENU_NODENAMES*
*LABWC_DEBUG_CONFIG_NODENAMES*
Enable logging of all nodenames (for example *policy.placement: Cascade*
for *<placement><policy>Cascade</policy></placement>*) for config and
menu files respectively.

View file

@ -1,5 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<openbox_menu>
<!-- Note: for localization support of menu items "client-menu" has to be removed here -->
<menu id="client-menu">
@ -25,18 +23,7 @@
Any menu with the id "workspaces" will be hidden
if there is only a single workspace available.
-->
<menu id="workspaces" label="Workspace">
<item label="Move Left">
<action name="SendToDesktop" to="left" />
</item>
<item label="Move Right">
<action name="SendToDesktop" to="right" />
</item>
<separator />
<item label="Always on Visible Workspace">
<action name="ToggleOmnipresent" />
</item>
</menu>
<menu id="client-send-to-menu"/>
<!--
openbox default workspace selector
to use replace above workspace menu with the example below
@ -65,6 +52,17 @@
<item label="Exit">
<action name="Exit" />
</item>
<!--
# A prompt can be used as follows:
<item label="Exit">
<action name="If">
<prompt message="Do you really want to exit the compositor?"/>
<then>
<action name="Exit"/>
</then>
</action>
</item>
-->
</menu>
<menu id="some-custom-menu">

View file

@ -1,16 +1,16 @@
scdoc = find_program('scdoc', required: get_option('man-pages'))
if scdoc.found()
sections = [
'.1',
'-actions.5',
'-config.5',
'-menu.5',
'-theme.5',
manpages = [
'labwc.1',
'labwc-actions.5',
'labwc-config.5',
'labwc-menu.5',
'labwc-theme.5',
'labnag.1',
]
foreach s : sections
markdown = 'labwc' + s + '.scd'
manpage = 'labwc' + s
foreach manpage : manpages
markdown = manpage + '.scd'
custom_target(
manpage,
input: markdown,
@ -19,7 +19,7 @@ if scdoc.found()
feed: true,
capture: true,
install: true,
install_dir: join_paths(get_option('mandir'), 'man' + s.split('.')[-1])
install_dir: join_paths(get_option('mandir'), 'man' + manpage.split('.')[-1])
)
endforeach
endif

View file

@ -1,5 +1,3 @@
<?xml version="1.0"?>
<!--
This is a very simple config file with many options missing. For a complete
set of options with comments, see docs/rc.xml.all

View file

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<!--
This file contains all supported config elements & attributes with
default values.
Values for [yes|no] can be replaced by [true|false], [on|off] or [1|0].
-->
<labwc_config>
@ -16,6 +16,10 @@
<reuseOutputMode>no</reuseOutputMode>
<xwaylandPersistence>no</xwaylandPersistence>
<primarySelection>yes</primarySelection>
<!--
# See labwc-config(5) for details
<promptCommand></promptCommand>
-->
</core>
<placement>
@ -38,6 +42,7 @@
</titlebar>
<cornerRadius>8</cornerRadius>
<keepBorder>yes</keepBorder>
<maximizedDecoration>titlebar</maximizedDecoration>
<dropShadows>no</dropShadows>
<dropShadowsOnTiled>no</dropShadowsOnTiled>
<font place="ActiveWindow">
@ -72,7 +77,8 @@
</font>
</theme>
<windowSwitcher show="yes" preview="yes" outlines="yes" allWorkspaces="no">
<windowSwitcher show="yes" style="classic" preview="yes"
outlines="yes" allWorkspaces="no" unshade="yes">
<fields>
<field content="icon" width="5%" />
<field content="desktop_entry_name" width="30%" />
@ -155,6 +161,7 @@
<snapping>
<!-- Set range to 0 to disable window snapping completely -->
<range>10</range>
<cornerRange>50</cornerRange>
<overlay enabled="yes">
<delay inner="500" outer="500" />
</overlay>
@ -267,16 +274,16 @@
<action name="ToggleMaximize" />
</keybind>
<keybind key="W-Left">
<action name="SnapToEdge" direction="left" />
<action name="SnapToEdge" direction="left" combine="yes" />
</keybind>
<keybind key="W-Right">
<action name="SnapToEdge" direction="right" />
<action name="SnapToEdge" direction="right" combine="yes" />
</keybind>
<keybind key="W-Up">
<action name="SnapToEdge" direction="up" />
<action name="SnapToEdge" direction="up" combine="yes" />
</keybind>
<keybind key="W-Down">
<action name="SnapToEdge" direction="down" />
<action name="SnapToEdge" direction="down" combine="yes" />
</keybind>
<keybind key="A-Space">
<action name="ShowMenu" menu="client-menu" atCursor="no" />
@ -371,42 +378,11 @@
</mousebind>
</context>
<context name="Top">
<mousebind button="Left" action="Drag">
<action name="Resize" />
<context name="Border">
<mousebind button="Left" action="Press">
<action name="Focus" />
<action name="Raise" />
</mousebind>
</context>
<context name="Left">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="Right">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="Bottom">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="TRCorner">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="BRCorner">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="TLCorner">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
</context>
<context name="BLCorner">
<mousebind button="Left" action="Drag">
<action name="Resize" />
</mousebind>
@ -608,7 +584,13 @@
- sendEventsMode [yes|no|disabledOnExternalMouse]
- calibrationMatrix [six float values split by space]
- scrollFactor [float]
The following <libinput>...</libinput> block may not be complete for
your requirements. Default values are device specific. Only set an option
if you require to override the default. Valid values must be inserted.
-->
<libinput>
<device category="default">
<naturalScroll></naturalScroll>

View file

@ -91,14 +91,27 @@ osd.label.text.color: #000000
# width can be set as percent (of screen width)
# example 50% or 75% instead of 600, max 100%
osd.window-switcher.width: 600
osd.window-switcher.style-classic.width: 600
osd.window-switcher.padding: 4
osd.window-switcher.item.padding.x: 10
osd.window-switcher.item.padding.y: 1
osd.window-switcher.item.active.border.width: 2
osd.window-switcher.style-classic.padding: 4
osd.window-switcher.style-classic.item.padding.x: 10
osd.window-switcher.style-classic.item.padding.y: 1
osd.window-switcher.style-classic.item.active.border.width: 2
osd.window-switcher.style-classic.item.active.border.color: #706f6d
osd.window-switcher.style-classic.item.active.bg.color: #bfbcba
# The icon size the same as the font size by default
# osd.window-switcher.item.icon.size: 50
# osd.window-switcher.style-classic.item.icon.size: 50
osd.window-switcher.style-thumbnail.width.max: 80%
osd.window-switcher.style-thumbnail.padding: 4
osd.window-switcher.style-thumbnail.item.width: 300
osd.window-switcher.style-thumbnail.item.height: 250
osd.window-switcher.style-thumbnail.item.padding: 10
osd.window-switcher.style-thumbnail.item.active.border.width: 2
osd.window-switcher.style-thumbnail.item.active.border.color: #706f6d
osd.window-switcher.style-thumbnail.item.active.bg.color: #bfbcba
osd.window-switcher.style-thumbnail.item.icon.size: 60
osd.window-switcher.preview.border.width: 1
osd.window-switcher.preview.border.color: #dddda6,#000000,#dddda6

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_ACTION_PROMPT_CODES_H
#define LABWC_ACTION_PROMPT_CODES_H
#define LAB_EXIT_FAILURE 255
#define LAB_EXIT_CANCELLED 254
#define LAB_EXIT_SUCCESS 0
#endif /* LABWC_ACTION_PROMPT_CODES_H */

View file

@ -3,6 +3,7 @@
#define LABWC_ACTION_H
#include <stdbool.h>
#include <sys/types.h>
#include <wayland-util.h>
struct view;
@ -22,6 +23,8 @@ struct action {
struct action *action_create(const char *action_name);
const char *action_get_str(struct action *action, const char *key,
const char *default_value);
bool action_is_valid(struct action *action);
bool action_is_show_menu(struct action *action);
@ -47,6 +50,9 @@ bool actions_contain_toggle_keybinds(struct wl_list *action_list);
void actions_run(struct view *activator, struct server *server,
struct wl_list *actions, struct cursor_context *ctx);
void action_prompts_destroy(void);
bool action_check_prompt_result(pid_t pid, int exit_code);
void action_free(struct action *action);
void action_list_free(struct wl_list *action_list);

View file

@ -1,9 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_ARRAY_H
#define LABWC_ARRAY_H
#include <stdio.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include "common/mem.h"
/*
* Wayland's wl_array API is a bit sparse consisting only of
@ -66,10 +66,7 @@ wl_array_len(struct wl_array *array)
#define array_add(_arr, _val) do { \
__typeof__(_val) *_entry = wl_array_add( \
(_arr), sizeof(__typeof__(_val))); \
if (!_entry) { \
perror("Failed to allocate memory"); \
exit(EXIT_FAILURE); \
} \
die_if_null(_entry); \
*_entry = (_val); \
} while (0)

View file

@ -18,7 +18,7 @@ void box_union(struct wlr_box *box_dest, struct wlr_box *box_a,
* The returned x & y coordinates are the centered content position
* relative to the top-left corner of the bounding box.
*/
struct wlr_box box_fit_within(int width, int height, struct wlr_box *bounding_box);
struct wlr_box box_fit_within(int width, int height, struct wlr_box *bound);
struct wlr_fbox box_to_fbox(struct wlr_box *box);

View file

@ -50,6 +50,17 @@ void buf_expand_shell_variables(struct buf *s);
*/
void buf_add_fmt(struct buf *s, const char *fmt, ...);
/**
* buf_add_hex_color - add rgb color as hex string to C string buffer
* @s: buffer
* @color: rgb color to be added
*
* For example:
* - With the input 'red' (defined as red[4] = { 1.0f, 0.0f, 0.0f, 1.0f}) the
* string "#ff0000ff" will be written to the buffer.
*/
void buf_add_hex_color(struct buf *s, float color[4]);
/**
* buf_add - add data to C string buffer
* @s: buffer
@ -60,9 +71,9 @@ void buf_add(struct buf *s, const char *data);
/**
* buf_add_char - add single char to C string buffer
* @s: buffer
* @data: char to be added
* @ch: char to be added
*/
void buf_add_char(struct buf *s, char data);
void buf_add_char(struct buf *s, char ch);
/**
* buf_clear - clear the buffer, internal allocations are preserved
@ -98,4 +109,11 @@ void buf_reset(struct buf *s);
*/
void buf_move(struct buf *dst, struct buf *src);
/**
* buf_from_file - read file into memory buffer
* @filename: file to read
* Free returned buffer with buf_reset().
*/
struct buf buf_from_file(const char *filename);
#endif /* LABWC_BUF_H */

View file

@ -1,10 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_DIRECTION_H
#define LABWC_DIRECTION_H
#include "view.h"
enum wlr_direction direction_from_view_edge(enum view_edge edge);
enum wlr_direction direction_get_opposite(enum wlr_direction direction);
#endif /* LABWC_DIRECTION_H */

81
include/common/edge.h Normal file
View file

@ -0,0 +1,81 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_EDGE_H
#define LABWC_EDGE_H
#include <stdbool.h>
/**
* Unified/overloaded enum representing edges, corners, and directions.
* Used in many different contexts (moving, resizing, tiling) and with
* somewhat different semantics depending on context.
*
* Examples:
* - LAB_EDGE_TOP can also mean "up" or "north".
* - LAB_EDGES_TOP_LEFT can mean "top left corner" or "northwest".
*
* The enum is designed to be used as a bitset, and combinations of
* edges typically mean what you'd expect from the context. For example,
* LAB_EDGES_TOP_LEFT is used when resizing a view from its top-left
* corner, or when tiling a view in the top-left corner of an output.
*
* All 16 possible combinations of TOP/BOTTOM/LEFT/RIGHT are listed for
* completeness. Not all combinations make sense in all contexts.
*
* LAB_EDGE_NONE is sometimes used to mean "invalid".
*
* LAB_EDGE_ANY means "any edge or combination of edges (except NONE)"
* and is distinct from LAB_EDGE_ALL (which means all 4 edges).
*
* LAB_EDGE_TOP/BOTTOM/LEFT/RIGHT match the corresponding values of
* enum wlr_edges and enum wlr_direction, so that conversion between
* enums can be done with a simple cast.
*/
enum lab_edge {
LAB_EDGE_NONE = 0,
LAB_EDGE_TOP = (1 << 0), /* or UP */
LAB_EDGE_BOTTOM = (1 << 1), /* or DOWN */
LAB_EDGE_LEFT = (1 << 2),
LAB_EDGE_RIGHT = (1 << 3),
LAB_EDGE_CENTER = (1 << 4), /* for window tiling */
LAB_EDGE_ANY = (1 << 5), /* for window rules */
/* corners or ordinal directions (NW/NE/SW/SE) */
LAB_EDGES_TOP_LEFT = (LAB_EDGE_TOP | LAB_EDGE_LEFT),
LAB_EDGES_TOP_RIGHT = (LAB_EDGE_TOP | LAB_EDGE_RIGHT),
LAB_EDGES_BOTTOM_LEFT = (LAB_EDGE_BOTTOM | LAB_EDGE_LEFT),
LAB_EDGES_BOTTOM_RIGHT = (LAB_EDGE_BOTTOM | LAB_EDGE_RIGHT),
/* opposite edges */
LAB_EDGES_TOP_BOTTOM = (LAB_EDGE_TOP | LAB_EDGE_BOTTOM),
LAB_EDGES_LEFT_RIGHT = (LAB_EDGE_LEFT | LAB_EDGE_RIGHT),
/* all 4 edges */
LAB_EDGES_ALL = (LAB_EDGE_TOP | LAB_EDGE_BOTTOM |
LAB_EDGE_LEFT | LAB_EDGE_RIGHT),
/* 3-edge combinations (for completeness) */
LAB_EDGES_EXCEPT_TOP = (LAB_EDGES_ALL ^ LAB_EDGE_TOP),
LAB_EDGES_EXCEPT_BOTTOM = (LAB_EDGES_ALL ^ LAB_EDGE_BOTTOM),
LAB_EDGES_EXCEPT_LEFT = (LAB_EDGES_ALL ^ LAB_EDGE_LEFT),
LAB_EDGES_EXCEPT_RIGHT = (LAB_EDGES_ALL ^ LAB_EDGE_RIGHT),
};
enum lab_edge lab_edge_parse(const char *direction, bool tiled, bool any);
/**
* Returns true if edge is TOP, BOTTOM, LEFT, or RIGHT
* (i.e. one of the four cardinal directions N/S/W/E)
*/
bool lab_edge_is_cardinal(enum lab_edge edge);
/**
* lab_edge_invert() - select the opposite of a provided edge
*
* Returns LAB_EDGE_NONE for edges other than TOP/BOTTOM/LEFT/RIGHT.
*
* @edge: edge to be inverted
*/
enum lab_edge lab_edge_invert(enum lab_edge edge);
#endif /* LABWC_EDGE_H */

View file

@ -1,20 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Read file into memory
*
* Copyright Johan Malm 2020
*/
#ifndef LABWC_GRAB_FILE_H
#define LABWC_GRAB_FILE_H
#include "common/buf.h"
/**
* grab_file - read file into memory buffer
* @filename: file to read
* Free returned buffer with buf_reset().
*/
struct buf grab_file(const char *filename);
#endif /* LABWC_GRAB_FILE_H */

View file

@ -2,6 +2,8 @@
#ifndef LABWC_GRAPHIC_HELPERS_H
#define LABWC_GRAPHIC_HELPERS_H
#include <stdbool.h>
#include <stdint.h>
#include <cairo.h>
struct wlr_fbox;

View file

@ -4,6 +4,12 @@
#include <stdlib.h>
/*
* If ptr is NULL, prints an error (based on errno) and exits.
* Suitable for checking the return value of malloc() etc.
*/
void die_if_null(void *ptr);
/*
* As defined in busybox, weston, etc.
* Allocates zero-filled memory; calls exit() on error.

View file

@ -0,0 +1,75 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_NODE_TYPE_H
#define LABWC_NODE_TYPE_H
#include "common/edge.h"
/*
* In labwc, "node type" indicates the role of a wlr_scene_node in the
* overall desktop. It also maps more-or-less to the openbox concept of
* "context" (as used when defining mouse bindings).
*
* Some types (BUTTON, BORDER, etc.) refer to groups or categories of
* other node types rather than individual nodes. These categories are
* defined as ranges (e.g. BUTTON means anything from BUTTON_FIRST to
* BUTTON_LAST), therefore order is significant.
*
* Be sure to keep node_type_contains() in sync with any changes!
*/
enum lab_node_type {
LAB_NODE_NONE = 0,
LAB_NODE_BUTTON_CLOSE = 1,
LAB_NODE_BUTTON_MAXIMIZE,
LAB_NODE_BUTTON_ICONIFY,
LAB_NODE_BUTTON_WINDOW_ICON,
LAB_NODE_BUTTON_WINDOW_MENU,
LAB_NODE_BUTTON_SHADE,
LAB_NODE_BUTTON_OMNIPRESENT,
LAB_NODE_BUTTON_FIRST = LAB_NODE_BUTTON_CLOSE,
LAB_NODE_BUTTON_LAST = LAB_NODE_BUTTON_OMNIPRESENT,
LAB_NODE_BUTTON,
LAB_NODE_TITLEBAR,
LAB_NODE_TITLE,
LAB_NODE_CORNER_TOP_LEFT,
LAB_NODE_CORNER_TOP_RIGHT,
LAB_NODE_CORNER_BOTTOM_RIGHT,
LAB_NODE_CORNER_BOTTOM_LEFT,
LAB_NODE_BORDER_TOP,
LAB_NODE_BORDER_RIGHT,
LAB_NODE_BORDER_BOTTOM,
LAB_NODE_BORDER_LEFT,
LAB_NODE_BORDER,
LAB_NODE_CLIENT,
LAB_NODE_FRAME,
LAB_NODE_ROOT,
LAB_NODE_MENUITEM,
LAB_NODE_OSD,
LAB_NODE_LAYER_SURFACE,
LAB_NODE_UNMANAGED,
LAB_NODE_ALL,
/* translated to LAB_NODE_CLIENT by get_cursor_context() */
LAB_NODE_VIEW,
LAB_NODE_XDG_POPUP,
LAB_NODE_LAYER_POPUP,
LAB_NODE_SESSION_LOCK_SURFACE,
LAB_NODE_IME_POPUP,
/*
* translated to LAB_CORNER_* or LAB_BORDER* by
* ssd_get_resizing_type()
*/
LAB_NODE_SSD_ROOT,
};
enum lab_node_type node_type_parse(const char *context);
bool node_type_contains(enum lab_node_type whole, enum lab_node_type part);
enum lab_edge node_type_to_edges(enum lab_node_type type);
#endif /* LABWC_NODE_TYPE_H */

View file

@ -4,7 +4,6 @@
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <stdio.h>
/**
* nodename - give xml node an ascii name

View file

@ -1,17 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_PARSE_BOOL_H
#define LABWC_PARSE_BOOL_H
#include <stdbool.h>
#include "common/three-state.h"
#include "config/types.h"
/**
* parse_three_state() - Parse boolean value of string as a three-state enum.
* parse_tristate() - Parse boolean value of string as a three-state enum.
* @string: String to interpret. This check is case-insensitive.
*
* Return: LAB_STATE_DISABLED for false; LAB_STATE_ENABLED for true;
* LAB_STATE_UNSPECIFIED for non-boolean
*/
enum three_state parse_three_state(const char *str);
enum lab_tristate parse_tristate(const char *str);
/**
* parse_bool() - Parse boolean value of string.

View file

@ -20,6 +20,6 @@ struct wlr_scene_node *lab_wlr_scene_get_prev_node(struct wlr_scene_node *node);
/* A variant of wlr_scene_output_commit() that respects wlr_output->pending */
bool lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
struct wlr_output_state *output_state);
struct wlr_output_state *state);
#endif /* LABWC_SCENE_HELPERS_H */

View file

@ -10,13 +10,10 @@
bool string_null_or_empty(const char *s);
/**
* trim_last_field() - Trim last field of string splitting on provided delim
* @buf: string to trim
* @delim: delimitator
*
* Example: With delim='_' and buf="foo_bar_baz" the return value is "foo_bar"
* str_space_only - Check if the string only contains white-space characters
* @s: string to check
*/
void trim_last_field(char *buf, char delim);
bool str_space_only(const char *s);
/**
* string_strip - strip white space left and right
@ -59,8 +56,7 @@ char *strdup_printf(const char *fmt, ...);
* The separator is arbitrary. When the separator is NULL, a single space will
* be used.
*/
char *str_join(const char *const parts[],
const char *restrict fmt, const char *restrict sep);
char *str_join(const char *const parts[], const char *fmt, const char *sep);
/**
* str_endswith - indicate whether a string ends with a given suffix

View file

@ -1,16 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_SURFACE_HELPERS_H
#define LABWC_SURFACE_HELPERS_H
struct wlr_surface;
struct wlr_layer_surface_v1;
/**
* subsurface_parent_layer() - Get wlr_layer_surface from layer-subsurface
* @wlr_surface: The wlr_surface of the wlr_subsurface for which to get the
* layer-surface.
*/
struct wlr_layer_surface_v1 *subsurface_parent_layer(
struct wlr_surface *wlr_surface);
#endif /* LABWC_SURFACE_HELPERS_H */

View file

@ -1,11 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_THREE_STATE_H
#define LABWC_THREE_STATE_H
enum three_state {
LAB_STATE_UNSPECIFIED = 0,
LAB_STATE_ENABLED,
LAB_STATE_DISABLED
};
#endif /* LABWC_THREE_STATE_H */

66
include/common/xml.h Normal file
View file

@ -0,0 +1,66 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_XML_H
#define LABWC_XML_H
#include <libxml/tree.h>
#include <stdbool.h>
/*
* Converts dotted attributes into nested nodes.
* For example, the following node:
*
* <keybind name.action="ShowMenu" menu.action="root-menu"
* x.position.action="1" y.position.action="2" />
*
* is converted to:
*
* <keybind>
* <action>
* <name>ShowMenu</name>
* <menu>root-menu</menu>
* <position>
* <x>1</x>
* <y>2</y>
* </position>
* </action>
* </keybind>
*/
void lab_xml_expand_dotted_attributes(xmlNode *parent);
/* Returns true if the node only contains a string or is empty */
bool lab_xml_node_is_leaf(xmlNode *node);
bool lab_xml_get_string(xmlNode *node, const char *key, char *s, size_t len);
bool lab_xml_get_int(xmlNode *node, const char *key, int *i);
bool lab_xml_get_bool(xmlNode *node, const char *key, bool *b);
/* also skips other unusual nodes like comments */
static inline xmlNode *
lab_xml_skip_text(xmlNode *child)
{
while (child && child->type != XML_ELEMENT_NODE) {
child = child->next;
}
return child;
}
static inline void
lab_xml_get_key_and_content(xmlNode *node, char **name, char **content)
{
if (node) {
*name = (char *)node->name;
*content = (char *)xmlNodeGetContent(node);
}
}
#define LAB_XML_FOR_EACH(parent, child, key, content) \
for ((child) = lab_xml_skip_text((parent)->children), \
lab_xml_get_key_and_content((child), &(key), &(content)); \
\
(child); \
\
xmlFree((xmlChar *)(content)), \
(child) = lab_xml_skip_text((child)->next), \
lab_xml_get_key_and_content((child), &(key), &(content)))
#endif /* LABWC_XML_H */

View file

@ -35,6 +35,10 @@ static struct key_combos {
.name = "direction",
.value = "left",
},
.attributes[1] = {
.name = "combine",
.value = "yes",
},
}, {
.binding = "W-Right",
.action = "SnapToEdge",
@ -42,6 +46,10 @@ static struct key_combos {
.name = "direction",
.value = "right",
},
.attributes[1] = {
.name = "combine",
.value = "yes",
},
}, {
.binding = "W-Up",
.action = "SnapToEdge",
@ -49,6 +57,10 @@ static struct key_combos {
.name = "direction",
.value = "up",
},
.attributes[1] = {
.name = "combine",
.value = "yes",
},
}, {
.binding = "W-Down",
.action = "SnapToEdge",
@ -56,6 +68,10 @@ static struct key_combos {
.name = "direction",
.value = "down",
},
.attributes[1] = {
.name = "combine",
.value = "yes",
},
}, {
.binding = "A-Space",
.action = "ShowMenu",
@ -143,42 +159,17 @@ static struct mouse_combos {
const char *name, *value;
} attributes[2];
} mouse_combos[] = { {
.context = "Left",
.context = "Border",
.button = "Left",
.event = "Drag",
.action = "Resize",
.event = "Press",
.action = "Focus",
}, {
.context = "Top",
.context = "Border",
.button = "Left",
.event = "Drag",
.action = "Resize",
.event = "Press",
.action = "Raise",
}, {
.context = "Bottom",
.button = "Left",
.event = "Drag",
.action = "Resize",
}, {
.context = "Right",
.button = "Left",
.event = "Drag",
.action = "Resize",
}, {
.context = "TLCorner",
.button = "Left",
.event = "Drag",
.action = "Resize",
}, {
.context = "TRCorner",
.button = "Left",
.event = "Drag",
.action = "Resize",
}, {
.context = "BRCorner",
.button = "Left",
.event = "Drag",
.action = "Resize",
}, {
.context = "BLCorner",
.context = "Border",
.button = "Left",
.event = "Drag",
.action = "Resize",

View file

@ -2,7 +2,8 @@
#ifndef LABWC_KEYBIND_H
#define LABWC_KEYBIND_H
#include <wlr/types/wlr_keyboard.h>
#include <stdbool.h>
#include <wayland-util.h>
#include <xkbcommon/xkbcommon.h>
#define MAX_KEYSYMS 32
@ -41,5 +42,8 @@ uint32_t parse_modifier(const char *symname);
bool keybind_the_same(struct keybind *a, struct keybind *b);
bool keybind_contains_keycode(struct keybind *keybind, xkb_keycode_t keycode);
bool keybind_contains_keysym(struct keybind *keybind, xkb_keysym_t keysym);
void keybind_update_keycodes(struct server *server);
#endif /* LABWC_KEYBIND_H */

View file

@ -38,6 +38,7 @@ struct libinput_category {
};
enum lab_libinput_device_type get_device_type(const char *s);
const char *libinput_device_type_name(enum lab_libinput_device_type type);
struct libinput_category *libinput_category_create(void);
struct libinput_category *libinput_category_get_default(void);

View file

@ -2,9 +2,9 @@
#ifndef LABWC_MOUSEBIND_H
#define LABWC_MOUSEBIND_H
#include <stdbool.h>
#include <wayland-util.h>
#include "ssd.h"
#include "config/keybind.h"
#include "common/node-type.h"
enum mouse_event {
MOUSE_ACTION_NONE = 0,
@ -25,7 +25,7 @@ enum direction {
};
struct mousebind {
enum ssd_part_type context;
enum lab_node_type context;
/* ex: BTN_LEFT, BTN_RIGHT from linux/input_event_codes.h */
uint32_t button;

View file

@ -3,28 +3,19 @@
#define LABWC_RCXML_H
#include <stdbool.h>
#include <stdio.h>
#include <wayland-server-core.h>
#include <wlr/util/box.h>
#include <libxml/tree.h>
#include "common/border.h"
#include "common/buf.h"
#include "common/font.h"
#include "common/three-state.h"
#include "config/touch.h"
#include "config/tablet.h"
#include "config/tablet-tool.h"
#include "config/libinput.h"
#include "resize-indicator.h"
#include "ssd.h"
#include "theme.h"
#include "common/node-type.h"
#include "config/types.h"
enum view_placement_policy {
LAB_PLACE_INVALID = 0,
LAB_PLACE_CENTER,
LAB_PLACE_CURSOR,
LAB_PLACE_AUTOMATIC,
LAB_PLACE_CASCADE,
};
#define BUTTON_MAP_MAX 16
/* max of one button of each type (no repeats) */
#define TITLE_BUTTONS_MAX ((LAB_NODE_BUTTON_LAST + 1) - LAB_NODE_BUTTON_FIRST)
enum adaptive_sync_mode {
LAB_ADAPTIVE_SYNC_DISABLED,
@ -32,6 +23,12 @@ enum adaptive_sync_mode {
LAB_ADAPTIVE_SYNC_FULLSCREEN,
};
enum resize_indicator_mode {
LAB_RESIZE_INDICATOR_NEVER = 0,
LAB_RESIZE_INDICATOR_ALWAYS,
LAB_RESIZE_INDICATOR_NON_PIXEL
};
enum tearing_mode {
LAB_TEARING_DISABLED = 0,
LAB_TEARING_ENABLED,
@ -47,9 +44,11 @@ enum tiling_events_mode {
(LAB_TILING_EVENTS_REGION | LAB_TILING_EVENTS_EDGE),
};
struct title_button {
enum ssd_part_type type;
struct wl_list link;
struct buf;
struct button_map_entry {
uint32_t from;
uint32_t to;
};
struct usable_area_override {
@ -66,14 +65,18 @@ struct rcxml {
/* core */
bool xdg_shell_server_side_deco;
bool hide_maximized_window_titlebar;
int gap;
enum adaptive_sync_mode adaptive_sync;
enum tearing_mode allow_tearing;
bool auto_enable_outputs;
bool reuse_output_mode;
enum view_placement_policy placement_policy;
bool xwayland_persistence;
bool primary_selection;
char *prompt_command;
/* placement */
enum lab_placement_policy placement_policy;
int placement_cascade_offset_x;
int placement_cascade_offset_y;
@ -86,8 +89,12 @@ struct rcxml {
char *theme_name;
char *icon_theme_name;
char *fallback_app_icon_name;
struct wl_list title_buttons_left;
struct wl_list title_buttons_right;
enum lab_node_type title_buttons_left[TITLE_BUTTONS_MAX];
int nr_title_buttons_left;
enum lab_node_type title_buttons_right[TITLE_BUTTONS_MAX];
int nr_title_buttons_right;
int corner_radius;
bool show_title;
bool title_layout_loaded;
@ -109,7 +116,7 @@ struct rcxml {
/* keyboard */
int repeat_rate;
int repeat_delay;
enum three_state kb_numlock_enable;
enum lab_tristate kb_numlock_enable;
bool kb_layout_per_window;
struct wl_list keybinds; /* struct keybind.link */
@ -125,12 +132,12 @@ struct rcxml {
bool force_mouse_emulation;
char *output_name;
struct wlr_fbox box;
enum rotation rotation;
enum lab_rotation rotation;
uint16_t button_map_count;
struct button_map_entry button_map[BUTTON_MAP_MAX];
} tablet;
struct tablet_tool_config {
enum motion motion;
enum lab_motion motion;
double relative_motion_sensitivity;
} tablet_tool;
@ -145,6 +152,7 @@ struct rcxml {
/* window snapping */
int snap_edge_range;
int snap_edge_corner_range;
bool snap_overlay_enabled;
int snap_overlay_delay_inner;
int snap_overlay_delay_outer;
@ -171,8 +179,10 @@ struct rcxml {
bool show;
bool preview;
bool outlines;
uint32_t criteria;
bool unshade;
enum lab_view_criteria criteria;
struct wl_list fields; /* struct window_switcher_field.link */
enum window_switcher_style style;
} window_switcher;
struct wl_list window_rules; /* struct window_rule.link */
@ -191,8 +201,13 @@ struct rcxml {
extern struct rcxml rc;
void rcxml_parse_xml(struct buf *b);
void rcxml_read(const char *filename);
void rcxml_finish(void);
/*
* Parse the child <action> nodes and append them to the list.
* FIXME: move this function to somewhere else.
*/
void append_parsed_actions(xmlNode *node, struct wl_list *list);
#endif /* LABWC_RCXML_H */

View file

@ -2,13 +2,8 @@
#ifndef LABWC_TABLET_TOOL_CONFIG_H
#define LABWC_TABLET_TOOL_CONFIG_H
#include <stdint.h>
#include "config/types.h"
enum motion {
LAB_TABLET_MOTION_ABSOLUTE = 0,
LAB_TABLET_MOTION_RELATIVE,
};
enum motion tablet_parse_motion(const char *name);
enum lab_motion tablet_parse_motion(const char *name);
#endif /* LABWC_TABLET_TOOL_CONFIG_H */

View file

@ -3,22 +3,10 @@
#define LABWC_TABLET_CONFIG_H
#include <stdint.h>
enum rotation {
LAB_ROTATE_NONE = 0,
LAB_ROTATE_90,
LAB_ROTATE_180,
LAB_ROTATE_270,
};
#define BUTTON_MAP_MAX 16
struct button_map_entry {
uint32_t from;
uint32_t to;
};
#include "config/types.h"
double tablet_get_dbl_if_positive(const char *content, const char *name);
enum rotation tablet_parse_rotation(int value);
enum lab_rotation tablet_parse_rotation(int value);
uint32_t tablet_button_from_str(const char *button);
void tablet_button_mapping_add(uint32_t from, uint32_t to);
void tablet_load_default_button_mappings(void);

View file

@ -2,7 +2,7 @@
#ifndef LABWC_TOUCH_CONFIG_H
#define LABWC_TOUCH_CONFIG_H
#include <stdint.h>
#include <stdbool.h>
#include <wayland-util.h>
struct touch_config_entry {

115
include/config/types.h Normal file
View file

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_CONFIG_TYPES_H
#define LABWC_CONFIG_TYPES_H
/*
* Shared (basic) types related to user configuration.
*
* Please try to keep dependencies on other headers minimal,
* since config/types.h gets included in many source files.
*
* For the full config struct, see config/rcxml.h.
*/
/**
* Indicates whether tablet tool motion events should be reported using
* absolute or relative coordinates
*/
enum lab_motion {
LAB_MOTION_ABSOLUTE = 0,
LAB_MOTION_RELATIVE,
};
enum lab_placement_policy {
LAB_PLACE_INVALID = 0,
LAB_PLACE_CENTER,
LAB_PLACE_CURSOR,
LAB_PLACE_AUTOMATIC,
LAB_PLACE_CASCADE,
};
enum lab_rotation {
LAB_ROTATE_NONE = 0,
LAB_ROTATE_90,
LAB_ROTATE_180,
LAB_ROTATE_270,
};
enum lab_ssd_mode {
LAB_SSD_MODE_NONE = 0,
LAB_SSD_MODE_BORDER,
LAB_SSD_MODE_FULL,
LAB_SSD_MODE_INVALID,
};
enum lab_tristate {
LAB_STATE_UNSPECIFIED = 0,
LAB_STATE_ENABLED,
LAB_STATE_DISABLED
};
/*
* This enum type is a set of bit flags where each set bit makes the
* criteria more restrictive. For example:
*
* (LAB_VIEW_CRITERIA_FULLSCREEN | LAB_VIEW_CRITERIA_CURRENT_WORKSPACE)
* matches only fullscreen views on the current workspace, while
*
* (LAB_VIEW_CRITERIA_ALWAYS_ON_TOP | LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP)
* would be contradictory and match nothing at all.
*/
enum lab_view_criteria {
/* No filter -> all focusable views */
LAB_VIEW_CRITERIA_NONE = 0,
/*
* Includes always-on-top views, e.g.
* what is visible on the current workspace
*/
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
/* Positive criteria */
LAB_VIEW_CRITERIA_FULLSCREEN = 1 << 1,
LAB_VIEW_CRITERIA_ALWAYS_ON_TOP = 1 << 2,
LAB_VIEW_CRITERIA_ROOT_TOPLEVEL = 1 << 3,
/* Negative criteria */
LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 6,
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 7,
LAB_VIEW_CRITERIA_NO_OMNIPRESENT = 1 << 8,
};
/*
* Window types are based on the NET_WM constants from X11. See:
* https://specifications.freedesktop.org/wm-spec/1.4/ar01s05.html#id-1.6.7
*
* The enum constants are intended to match wlr_xwayland_net_wm_window_type.
* Redefining the same constants here may seem redundant, but is necessary
* to make them available even in builds with xwayland support disabled.
*/
enum lab_window_type {
LAB_WINDOW_TYPE_INVALID = -1,
LAB_WINDOW_TYPE_DESKTOP = 0,
LAB_WINDOW_TYPE_DOCK,
LAB_WINDOW_TYPE_TOOLBAR,
LAB_WINDOW_TYPE_MENU,
LAB_WINDOW_TYPE_UTILITY,
LAB_WINDOW_TYPE_SPLASH,
LAB_WINDOW_TYPE_DIALOG,
LAB_WINDOW_TYPE_DROPDOWN_MENU,
LAB_WINDOW_TYPE_POPUP_MENU,
LAB_WINDOW_TYPE_TOOLTIP,
LAB_WINDOW_TYPE_NOTIFICATION,
LAB_WINDOW_TYPE_COMBO,
LAB_WINDOW_TYPE_DND,
LAB_WINDOW_TYPE_NORMAL,
LAB_WINDOW_TYPE_LEN
};
enum window_switcher_style {
WINDOW_SWITCHER_CLASSIC,
WINDOW_SWITCHER_THUMBNAIL,
};
#endif /* LABWC_CONFIG_TYPES_H */

View file

@ -4,7 +4,7 @@
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include "common/edge.h"
#include "common/macros.h"
struct border;
@ -101,9 +101,6 @@ typedef void (*edge_validator_t)(int *best, struct edge current,
void edges_initialize(struct border *edges);
void edges_adjust_geom(struct view *view, struct border edges,
uint32_t resize_edges, struct wlr_box *geom);
void edges_find_neighbors(struct border *nearest_edges, struct view *view,
struct wlr_box origin, struct wlr_box target,
struct output *output, edge_validator_t validator, bool ignore_hidden);
@ -116,9 +113,10 @@ void edges_adjust_move_coords(struct view *view, struct border edges,
int *x, int *y, bool use_pending);
void edges_adjust_resize_geom(struct view *view, struct border edges,
uint32_t resize_edges, struct wlr_box *geom, bool use_pending);
enum lab_edge resize_edges, struct wlr_box *geom, bool use_pending);
bool edges_traverse_edge(struct edge current, struct edge target, struct edge edge);
void edges_calculate_visibility(struct server *server, struct view *ignored_view);
#endif /* LABWC_EDGES_H */

View file

@ -1,83 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_FOREIGN_TOPLEVEL_INTERNAL_H
#define LABWC_FOREIGN_TOPLEVEL_INTERNAL_H
#include <stdbool.h>
#include <wayland-server-core.h>
#include "foreign-toplevel.h"
struct foreign_toplevel {
struct view *view;
/* *-toplevel implementations */
struct wlr_foreign_toplevel {
struct wlr_foreign_toplevel_handle_v1 *handle;
/* Client side events */
struct {
struct wl_listener request_maximize;
struct wl_listener request_minimize;
struct wl_listener request_fullscreen;
struct wl_listener request_activate;
struct wl_listener request_close;
struct wl_listener handle_destroy;
} on;
/* Compositor side state updates */
struct {
struct wl_listener new_app_id;
struct wl_listener new_title;
struct wl_listener new_outputs;
struct wl_listener maximized;
struct wl_listener minimized;
struct wl_listener fullscreened;
struct wl_listener activated;
} on_view;
/* Internal signals */
struct {
struct wl_listener toplevel_parent;
struct wl_listener toplevel_destroy;
} on_foreign_toplevel;
} wlr_toplevel;
struct ext_foreign_toplevel {
struct wlr_ext_foreign_toplevel_handle_v1 *handle;
/* Client side events */
struct {
struct wl_listener handle_destroy;
} on;
/* Compositor side state updates */
struct {
struct wl_listener new_app_id;
struct wl_listener new_title;
} on_view;
/* Internal signals */
struct {
struct wl_listener toplevel_destroy;
} on_foreign_toplevel;
} ext_toplevel;
/* TODO: add struct xdg_x11_mapped_toplevel at some point */
struct {
struct wl_signal toplevel_parent; /* struct view *parent */
struct wl_signal toplevel_destroy;
} events;
};
void ext_foreign_toplevel_init(struct foreign_toplevel *toplevel);
void wlr_foreign_toplevel_init(struct foreign_toplevel *toplevel);
void foreign_request_minimize(struct foreign_toplevel *toplevel, bool minimized);
void foreign_request_maximize(struct foreign_toplevel *toplevel, enum view_axis axis);
void foreign_request_fullscreen(struct foreign_toplevel *toplevel, bool fullscreen);
void foreign_request_activate(struct foreign_toplevel *toplevel);
void foreign_request_close(struct foreign_toplevel *toplevel);
#endif /* LABWC_FOREIGN_TOPLEVEL_INTERNAL_H */

View file

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_EXT_FOREIGN_TOPLEVEL_H
#define LABWC_EXT_FOREIGN_TOPLEVEL_H
#include <wayland-server-core.h>
struct ext_foreign_toplevel {
struct view *view;
struct wlr_ext_foreign_toplevel_handle_v1 *handle;
/* Client side events */
struct {
struct wl_listener handle_destroy;
} on;
/* Compositor side state updates */
struct {
struct wl_listener new_app_id;
struct wl_listener new_title;
} on_view;
};
void ext_foreign_toplevel_init(struct ext_foreign_toplevel *ext_toplevel,
struct view *view);
void ext_foreign_toplevel_finish(struct ext_foreign_toplevel *ext_toplevel);
#endif /* LABWC_EXT_FOREIGN_TOPLEVEL_H */

View file

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_WLR_FOREIGN_TOPLEVEL_H
#define LABWC_WLR_FOREIGN_TOPLEVEL_H
#include <wayland-server-core.h>
struct wlr_foreign_toplevel {
struct view *view;
struct wlr_foreign_toplevel_handle_v1 *handle;
/* Client side events */
struct {
struct wl_listener request_maximize;
struct wl_listener request_minimize;
struct wl_listener request_fullscreen;
struct wl_listener request_activate;
struct wl_listener request_close;
struct wl_listener handle_destroy;
} on;
/* Compositor side state updates */
struct {
struct wl_listener new_app_id;
struct wl_listener new_title;
struct wl_listener new_outputs;
struct wl_listener maximized;
struct wl_listener minimized;
struct wl_listener fullscreened;
struct wl_listener activated;
} on_view;
};
void wlr_foreign_toplevel_init(struct wlr_foreign_toplevel *wlr_toplevel,
struct view *view);
void wlr_foreign_toplevel_set_parent(struct wlr_foreign_toplevel *wlr_toplevel,
struct wlr_foreign_toplevel *parent);
void wlr_foreign_toplevel_finish(struct wlr_foreign_toplevel *wlr_toplevel);
#endif /* LABWC_WLR_FOREIGN_TOPLEVEL_H */

View file

@ -5,7 +5,7 @@
struct wl_display;
struct wlr_seat;
void idle_manager_create(struct wl_display *display, struct wlr_seat *wlr_seat);
void idle_manager_create(struct wl_display *display);
void idle_manager_notify_activity(struct wlr_seat *seat);
#endif /* LABWC_IDLE_H */

View file

@ -4,7 +4,6 @@
#include <cairo.h>
#include <stdbool.h>
#include <stdint.h>
#include <wayland-util.h>
enum lab_img_type {

View file

@ -2,16 +2,17 @@
#ifndef LABWC_CURSOR_H
#define LABWC_CURSOR_H
#include <wlr/types/wlr_cursor.h>
#include <wlr/util/edges.h>
#include "ssd.h"
#include <wayland-server-protocol.h>
#include "common/edge.h"
#include "common/node-type.h"
struct view;
struct seat;
struct server;
struct wlr_input_device;
struct wlr_cursor;
struct wlr_surface;
struct wlr_scene_node;
enum wl_pointer_button_state;
/* Cursors used internally by labwc */
enum lab_cursors {
@ -33,35 +34,25 @@ struct cursor_context {
struct view *view;
struct wlr_scene_node *node;
struct wlr_surface *surface;
enum ssd_part_type type;
enum lab_node_type type;
double sx, sy;
};
/**
* get_cursor_context - find view and scene_node at cursor
* get_cursor_context - find view, surface and scene_node at cursor
*
* Behavior if node points to a surface:
* - If surface is a layer-surface, type will be
* set to LAB_SSD_LAYER_SURFACE and view will be NULL.
* If the cursor is on a client-drawn surface:
* - ctx.{surface,node} points to the surface, which may be a subsurface.
* - ctx.view is set if the node is associated to a xdg/x11 window.
* - ctx.type is LAYER_SURFACE or UNMANAGED if the node is a layer-shell
* surface or an X11 unmanaged surface. Otherwise, CLIENT is set.
*
* - If surface is a 'lost' unmanaged xsurface (one
* with a never-mapped parent view), type will
* be set to LAB_SSD_UNMANAGED and view will be NULL.
*
* 'Lost' unmanaged xsurfaces are usually caused by
* X11 applications opening popups without setting
* the main window as parent. Example: VLC submenus.
*
* - Any other surface will cause type to be set to
* LAB_SSD_CLIENT and return the attached view.
*
* Behavior if node points to internal elements:
* - type will be set to the appropriate enum value
* and view will be NULL if the node is not part of the SSD.
*
* If no node is found for the given layout coordinates,
* type will be set to LAB_SSD_ROOT and view will be NULL.
* If the cursor is on a server-side component (SSD part and menu item):
* - ctx.node points to the root node of that component
* - ctx.view is set if the component is a SSD part
* - ctx.type specifies the component (e.g. MENU_ITEM, BORDER_TOP, BUTTON_ICONIFY)
*
* If no node is found at cursor, ctx.type is set to ROOT.
*/
struct cursor_context get_cursor_context(struct server *server);
@ -85,20 +76,19 @@ void cursor_set_visible(struct seat *seat, bool visible);
* This is mostly important when either resizing a window using a
* keyboard modifier or when using the Resize action from a keybind.
*/
uint32_t cursor_get_resize_edges(struct wlr_cursor *cursor,
enum lab_edge cursor_get_resize_edges(struct wlr_cursor *cursor,
struct cursor_context *ctx);
/**
* cursor_get_from_edge - translate wlroots edge enum to lab_cursor enum
* @resize_edges - WLR_EDGE_ combination like WLR_EDGE_TOP | WLR_EDGE_RIGHT
* cursor_get_from_edge - translate lab_edge enum to lab_cursor enum
* @resize_edges - edge(s) being resized
*
* Returns LAB_CURSOR_DEFAULT on WLR_EDGE_NONE
* Returns the appropriate lab_cursors enum if @resize_edges
* is one of the 4 corners or one of the 4 edges.
*
* Asserts on invalid edge combinations like WLR_EDGE_LEFT | WLR_EDGE_RIGHT
* Returns LAB_CURSOR_DEFAULT on any other value.
*/
enum lab_cursors cursor_get_from_edge(uint32_t resize_edges);
enum lab_cursors cursor_get_from_edge(enum lab_edge resize_edges);
/**
* cursor_update_focus - update cursor focus, may update the cursor icon

View file

@ -3,11 +3,10 @@
#ifndef LABWC_IME_H
#define LABWC_IME_H
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_input_method_v2.h>
#include "labwc.h"
#include <wayland-server-core.h>
struct keyboard;
struct wlr_keyboard_key_event;
/*
* The relay structure manages the relationship between text-inputs and

View file

@ -2,7 +2,16 @@
#ifndef LABWC_INPUT_H
#define LABWC_INPUT_H
struct seat;
#include <wayland-server-core.h>
struct input {
struct wlr_input_device *wlr_input_device;
struct seat *seat;
/* Set for pointer/touch devices */
double scroll_factor;
struct wl_listener destroy;
struct wl_list link; /* seat.inputs */
};
void input_handlers_init(struct seat *seat);
void input_handlers_finish(struct seat *seat);

View file

@ -24,6 +24,5 @@ void key_state_store_pressed_key_as_bound(uint32_t keycode);
bool key_state_corresponding_press_event_was_bound(uint32_t keycode);
void key_state_bound_key_remove(uint32_t keycode);
int key_state_nr_bound_keys(void);
int key_state_nr_pressed_keys(void);
#endif /* LABWC_KEY_STATE_H */

View file

@ -4,10 +4,25 @@
#include <stdbool.h>
#include <xkbcommon/xkbcommon.h>
#include "input/input.h"
struct seat;
struct keyboard;
struct wlr_keyboard;
/*
* Virtual keyboards should not belong to seat->keyboard_group. As a result we
* need to be able to ascertain which wlr_keyboard key/modifier events come from
* and we achieve that by using `struct keyboard` which inherits `struct input`
* and adds keyboard specific listeners and a wlr_keyboard pointer.
*/
struct keyboard {
struct input base;
struct wlr_keyboard *wlr_keyboard;
bool is_virtual;
struct wl_listener modifiers;
struct wl_listener key;
/* key repeat for compositor keybinds */
uint32_t keybind_repeat_keycode;
int32_t keybind_repeat_rate;
struct wl_event_source *keybind_repeat;
};
void keyboard_reset_current_keybind(void);
void keyboard_configure(struct seat *seat, struct wlr_keyboard *kb,

View file

@ -3,7 +3,6 @@
#define LABWC_TABLET_PAD_H
#include <wayland-server-core.h>
#include <wlr/types/wlr_tablet_v2.h>
struct seat;
struct wlr_device;

View file

@ -3,7 +3,7 @@
#define LABWC_TABLET_H
#include <wayland-server-core.h>
#include <wlr/types/wlr_tablet_v2.h>
#include "config/types.h"
struct seat;
struct wlr_device;
@ -20,7 +20,7 @@ struct drawing_tablet_tool {
*/
bool force_mouse_emulation;
enum motion motion_mode;
enum lab_motion motion_mode;
double x, y, dx, dy;
double distance;
double pressure;

View file

@ -2,64 +2,17 @@
#ifndef LABWC_H
#define LABWC_H
#include "config.h"
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <wayland-server-core.h>
#include <wlr/backend.h>
#include <wlr/render/allocator.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_management_v1.h>
#include <wlr/types/wlr_output_power_management_v1.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_activation_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_drm_lease_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_tearing_control_v1.h>
#include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_tablet_v2.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
#include "common/set.h"
#include "config/keybind.h"
#include "config/rcxml.h"
#include "input/cursor.h"
#include "overlay.h"
#include "regions.h"
#include "session-lock.h"
#if HAVE_NLS
#include <libintl.h>
#include <locale.h>
#define _ gettext
#else
#define _(s) (s)
#endif
#define XCURSOR_DEFAULT "left_ptr"
#define XCURSOR_SIZE 24
struct wlr_xdg_popup;
enum input_mode {
LAB_INPUT_STATE_PASSTHROUGH = 0,
LAB_INPUT_STATE_MOVE,
@ -68,33 +21,6 @@ enum input_mode {
LAB_INPUT_STATE_WINDOW_SWITCHER,
};
struct input {
struct wlr_input_device *wlr_input_device;
struct seat *seat;
/* Set for pointer/touch devices */
double scroll_factor;
struct wl_listener destroy;
struct wl_list link; /* seat.inputs */
};
/*
* Virtual keyboards should not belong to seat->keyboard_group. As a result we
* need to be able to ascertain which wlr_keyboard key/modifier events come from
* and we achieve that by using `struct keyboard` which inherits `struct input`
* and adds keyboard specific listeners and a wlr_keyboard pointer.
*/
struct keyboard {
struct input base;
struct wlr_keyboard *wlr_keyboard;
bool is_virtual;
struct wl_listener modifiers;
struct wl_listener key;
/* key repeat for compositor keybinds */
uint32_t keybind_repeat_keycode;
int32_t keybind_repeat_rate;
struct wl_event_source *keybind_repeat;
};
struct seat {
struct wlr_seat *seat;
struct server *server;
@ -111,9 +37,10 @@ struct seat {
bool cursor_visible;
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_manager;
struct {
double x, y;
} smooth_scroll_offset;
struct accumulated_scroll {
double delta;
double delta_discrete;
} accumulated_scrolls[2]; /* indexed by wl_pointer_axis */
bool cursor_scroll_wheel_emulation;
/*
@ -128,9 +55,6 @@ struct seat {
struct wlr_pointer_constraint_v1 *current_constraint;
/* In support for ToggleKeybinds */
uint32_t nr_inhibited_keybind_views;
/* Used to hide the workspace OSD after switching workspaces */
struct wl_event_source *workspace_osd_timer;
bool workspace_osd_shown_by_modifier;
@ -218,21 +142,12 @@ struct seat {
struct wl_listener pressed_surface_destroy;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
struct wl_listener virtual_pointer_new;
struct wl_listener new_virtual_pointer;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
struct wl_listener new_virtual_keyboard;
};
struct lab_data_buffer;
struct workspace;
enum lab_cycle_dir {
LAB_CYCLE_DIR_NONE,
LAB_CYCLE_DIR_FORWARD,
LAB_CYCLE_DIR_BACKWARD,
};
struct server {
struct wl_display *wl_display;
struct wl_event_loop *wl_event_loop; /* Can be used for timer events */
@ -288,7 +203,7 @@ struct server {
double grab_x, grab_y;
/* View geometry when interactive move/resize is requested */
struct wlr_box grab_box;
uint32_t resize_edges;
enum lab_edge resize_edges;
/*
* 'active_view' is generally the view with keyboard-focus, updated with
@ -304,7 +219,7 @@ struct server {
*/
struct view *active_view;
struct ssd_hover_state *ssd_hover_state;
struct ssd_button *hovered_button;
/* Tree for all non-layer xdg/xwayland-shell surfaces */
struct wlr_scene_tree *view_tree;
@ -388,6 +303,7 @@ struct server {
/* Set when in cycle (alt-tab) mode */
struct osd_state {
struct view *cycle_view;
bool preview_was_shaded;
bool preview_was_enabled;
struct wlr_scene_node *preview_node;
struct wlr_scene_tree *preview_parent;
@ -405,45 +321,6 @@ struct server {
pid_t primary_client_pid;
};
#define LAB_NR_LAYERS (4)
struct output {
struct wl_list link; /* server.outputs */
struct server *server;
struct wlr_output *wlr_output;
struct wlr_output_state pending;
struct wlr_scene_output *scene_output;
struct wlr_scene_tree *layer_tree[LAB_NR_LAYERS];
struct wlr_scene_tree *layer_popup_tree;
struct wlr_scene_tree *osd_tree;
struct wlr_scene_tree *session_lock_tree;
struct wlr_scene_buffer *workspace_osd;
struct osd_scene {
struct wl_array items; /* struct osd_scene_item */
struct wlr_scene_tree *tree;
} osd_scene;
/* In output-relative scene coordinates */
struct wlr_box usable_area;
struct wl_list regions; /* struct region.link */
struct wl_listener destroy;
struct wl_listener frame;
struct wl_listener request_state;
bool gamma_lut_changed;
};
#undef LAB_NR_LAYERS
struct constraint {
struct seat *seat;
struct wlr_pointer_constraint_v1 *constraint;
struct wl_listener destroy;
};
void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
void xdg_shell_init(struct server *server);
void xdg_shell_finish(struct server *server);
@ -483,7 +360,6 @@ void desktop_focus_view_or_surface(struct seat *seat, struct view *view,
void desktop_arrange_all_views(struct server *server);
void desktop_focus_output(struct output *output);
struct view *desktop_topmost_focusable_view(struct server *server);
/**
* Toggles the (output local) visibility of the layershell top layer
@ -544,50 +420,20 @@ void seat_focus_override_end(struct seat *seat);
*/
void interactive_anchor_to_cursor(struct server *server, struct wlr_box *geo);
void interactive_begin(struct view *view, enum input_mode mode, uint32_t edges);
void interactive_begin(struct view *view, enum input_mode mode,
enum lab_edge edges);
void interactive_finish(struct view *view);
void interactive_cancel(struct view *view);
/* Possibly returns VIEW_EDGE_CENTER if <topMaximize> is yes */
enum view_edge edge_from_cursor(struct seat *seat, struct output **dest_output);
void output_init(struct server *server);
void output_finish(struct server *server);
void output_manager_init(struct server *server);
struct output *output_from_wlr_output(struct server *server,
struct wlr_output *wlr_output);
struct output *output_from_name(struct server *server, const char *name);
struct output *output_nearest_to(struct server *server, int lx, int ly);
struct output *output_nearest_to_cursor(struct server *server);
/**
* output_get_adjacent() - get next output, in a given direction,
* from a given output
*
* @output: reference output
* @edge: direction in which to look for the nearest output
* @wrap: if true, wrap around at layout edge
*
* Note: if output is NULL, the output nearest the cursor will be used as the
* reference instead.
* Returns the edge to snap a window to.
* For example, if the output-relative cursor position (x,y) fulfills
* x <= (<snapping><cornerRange>) and y <= (<snapping><range>),
* then edge1=LAB_EDGE_TOP and edge2=LAB_EDGE_LEFT.
* The value of (edge1|edge2) can be passed to view_snap_to_edge().
*/
struct output *output_get_adjacent(struct output *output,
enum view_edge edge, bool wrap);
bool output_is_usable(struct output *output);
void output_update_usable_area(struct output *output);
void output_update_all_usable_areas(struct server *server, bool layout_changed);
bool output_get_tearing_allowance(struct output *output);
struct wlr_box output_usable_area_in_layout_coords(struct output *output);
void handle_output_power_manager_set_mode(struct wl_listener *listener,
void *data);
void output_enable_adaptive_sync(struct output *output, bool enabled);
/**
* output_max_scale() - get maximum scale factor of all usable outputs.
* Used when loading/rendering resources (e.g. icons) that may be
* displayed on any output.
*/
float output_max_scale(struct server *server);
bool edge_from_cursor(struct seat *seat, struct output **dest_output,
enum lab_edge *edge1, enum lab_edge *edge2);
void handle_tearing_new_object(struct wl_listener *listener, void *data);

View file

@ -1,8 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_LAYERS_H
#define LABWC_LAYERS_H
#include <wayland-server.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wayland-server-core.h>
#include <wlr/util/box.h>
struct server;
struct output;

View file

@ -100,18 +100,6 @@ void menu_open_root(struct menu *menu, int x, int y);
*/
void menu_process_cursor_motion(struct wlr_scene_node *node);
/**
* menu_call_actions - call actions associated with a menu node
*
* If menuitem connected to @node does not just open a submenu:
* - associated actions will be called
* - server->menu_current will be closed
* - server->menu_current will be set to NULL
*
* Returns true if actions have actually been executed
*/
bool menu_call_actions(struct wlr_scene_node *node);
/**
* menu_close_root- close root menu
*

View file

@ -1,31 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_NODE_DESCRIPTOR_H
#define LABWC_NODE_DESCRIPTOR_H
#include <wlr/types/wlr_scene.h>
struct view;
struct lab_layer_surface;
struct lab_layer_popup;
struct menuitem;
struct ssd_button;
struct scaled_scene_buffer;
#include <wayland-server-core.h>
#include "common/node-type.h"
enum node_descriptor_type {
LAB_NODE_DESC_NODE = 0,
LAB_NODE_DESC_VIEW,
LAB_NODE_DESC_XDG_POPUP,
LAB_NODE_DESC_LAYER_SURFACE,
LAB_NODE_DESC_LAYER_POPUP,
LAB_NODE_DESC_SESSION_LOCK_SURFACE,
LAB_NODE_DESC_IME_POPUP,
LAB_NODE_DESC_MENUITEM,
LAB_NODE_DESC_TREE,
LAB_NODE_DESC_SCALED_SCENE_BUFFER,
LAB_NODE_DESC_SSD_BUTTON,
};
struct wlr_scene_node;
struct node_descriptor {
enum node_descriptor_type type;
enum lab_node_type type;
struct view *view;
void *data;
struct wl_listener destroy;
};
@ -38,16 +22,15 @@ struct node_descriptor {
*
* @scene_node: wlr_scene_node to attached node_descriptor to
* @type: node descriptor type
* @view: associated view
* @data: struct to point to as follows:
* - LAB_NODE_DESC_VIEW struct view
* - LAB_NODE_DESC_XDG_POPUP struct view
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
* - LAB_NODE_DESC_MENUITEM struct menuitem
* - LAB_NODE_DESC_SSD_BUTTON struct ssd_button
* - LAB_NODE_LAYER_SURFACE struct lab_layer_surface
* - LAB_NODE_LAYER_POPUP struct lab_layer_popup
* - LAB_NODE_MENUITEM struct menuitem
* - LAB_NODE_BUTTON_* struct ssd_button
*/
void node_descriptor_create(struct wlr_scene_node *scene_node,
enum node_descriptor_type type, void *data);
enum lab_node_type type, struct view *view, void *data);
/**
* node_view_from_node - return view struct from node
@ -62,13 +45,6 @@ struct view *node_view_from_node(struct wlr_scene_node *wlr_scene_node);
struct lab_layer_surface *node_layer_surface_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_layer_popup_from_node - return lab_layer_popup struct from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct lab_layer_popup *node_layer_popup_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_menuitem_from_node - return menuitem struct from node
* @wlr_scene_node: wlr_scene_node from which to return data
@ -77,17 +53,10 @@ struct menuitem *node_menuitem_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_ssd_button_from_node - return ssd_button struct from node
* node_try_ssd_button_from_node - return ssd_button or NULL from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct ssd_button *node_ssd_button_from_node(
struct wlr_scene_node *wlr_scene_node);
/**
* node_scaled_scene_buffer_from_node - return scaled_scene_buffer from node
* @wlr_scene_node: wlr_scene_node from which to return data
*/
struct scaled_scene_buffer *node_scaled_scene_buffer_from_node(
struct ssd_button *node_try_ssd_button_from_node(
struct wlr_scene_node *wlr_scene_node);
#endif /* LABWC_NODE_DESCRIPTOR_H */

View file

@ -5,6 +5,14 @@
#include <stdbool.h>
#include <wayland-server-core.h>
struct output;
enum lab_cycle_dir {
LAB_CYCLE_DIR_NONE,
LAB_CYCLE_DIR_FORWARD,
LAB_CYCLE_DIR_BACKWARD,
};
/* TODO: add field with keyboard layout? */
enum window_switcher_field_content {
LAB_FIELD_NONE = 0,
@ -37,7 +45,6 @@ struct window_switcher_field {
struct buf;
struct view;
struct server;
enum lab_cycle_dir;
/* Begin window switcher */
void osd_begin(struct server *server, enum lab_cycle_dir direction);
@ -56,10 +63,26 @@ void osd_field_get_content(struct window_switcher_field *field,
struct buf *buf, struct view *view);
/* Used by rcxml.c when parsing the config */
struct window_switcher_field *osd_field_create(void);
void osd_field_arg_from_xml_node(struct window_switcher_field *field,
const char *nodename, const char *content);
bool osd_field_is_valid(struct window_switcher_field *field);
void osd_field_free(struct window_switcher_field *field);
/* Internal API */
struct osd_impl {
/*
* Create a scene-tree of OSD for an output.
* This sets output->osd_scene.{items,tree}.
*/
void (*create)(struct output *output, struct wl_array *views);
/*
* Update output->osd_scene.tree to highlight
* server->osd_state.cycle_view.
*/
void (*update)(struct output *output);
};
extern struct osd_impl osd_classic_impl;
extern struct osd_impl osd_thumbnail_impl;
#endif // LABWC_OSD_H

72
include/output.h Normal file
View file

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_OUTPUT_H
#define LABWC_OUTPUT_H
#include <wlr/types/wlr_output.h>
#include "common/edge.h"
#define LAB_NR_LAYERS (4)
struct output {
struct wl_list link; /* server.outputs */
struct server *server;
struct wlr_output *wlr_output;
struct wlr_output_state pending;
struct wlr_scene_output *scene_output;
struct wlr_scene_tree *layer_tree[LAB_NR_LAYERS];
struct wlr_scene_tree *layer_popup_tree;
struct wlr_scene_tree *osd_tree;
struct wlr_scene_tree *session_lock_tree;
struct wlr_scene_buffer *workspace_osd;
struct osd_scene {
struct wl_array items; /* struct osd_scene_item */
struct wlr_scene_tree *tree;
} osd_scene;
/* In output-relative scene coordinates */
struct wlr_box usable_area;
struct wl_list regions; /* struct region.link */
struct wl_listener destroy;
struct wl_listener frame;
struct wl_listener request_state;
bool gamma_lut_changed;
};
#undef LAB_NR_LAYERS
void output_init(struct server *server);
void output_finish(struct server *server);
struct output *output_from_wlr_output(struct server *server,
struct wlr_output *wlr_output);
struct output *output_from_name(struct server *server, const char *name);
struct output *output_nearest_to(struct server *server, int lx, int ly);
struct output *output_nearest_to_cursor(struct server *server);
/**
* output_get_adjacent() - get next output, in a given direction,
* from a given output
*
* @output: reference output
* @edge: direction in which to look for the nearest output
* @wrap: if true, wrap around at layout edge
*
* Note: if output is NULL, the output nearest the cursor will be used as the
* reference instead.
*/
struct output *output_get_adjacent(struct output *output,
enum lab_edge edge, bool wrap);
bool output_is_usable(struct output *output);
void output_update_usable_area(struct output *output);
void output_update_all_usable_areas(struct server *server, bool layout_changed);
bool output_get_tearing_allowance(struct output *output);
struct wlr_box output_usable_area_in_layout_coords(struct output *output);
void handle_output_power_manager_set_mode(struct wl_listener *listener,
void *data);
void output_enable_adaptive_sync(struct output *output, bool enabled);
#endif // LABWC_OUTPUT_H

View file

@ -2,24 +2,12 @@
#ifndef LABWC_OVERLAY_H
#define LABWC_OVERLAY_H
#include <wlr/util/box.h>
#include "common/graphic-helpers.h"
#include "regions.h"
#include "view.h"
#include "common/edge.h"
/* TODO: replace this with single lab_scene_rect */
struct overlay_rect {
struct wlr_scene_tree *tree;
bool bg_enabled;
struct wlr_scene_rect *bg_rect;
bool border_enabled;
struct lab_scene_rect *border_rect;
};
struct seat;
struct overlay {
struct overlay_rect region_rect, edge_rect;
struct lab_scene_rect *rect;
/* Represents currently shown or delayed overlay */
struct {
@ -27,7 +15,7 @@ struct overlay {
struct region *region;
/* Snap-to-edge overlay */
enum view_edge edge;
enum lab_edge edge;
struct output *output;
} active;
@ -35,15 +23,13 @@ struct overlay {
struct wl_event_source *timer;
};
void overlay_reconfigure(struct seat *seat);
/* Calls overlay_hide() internally if there's no overlay to show */
/*
* Shows or updates an overlay when the grabbed window can be snapped to
* a region or an output edge. Calls overlay_finish() otherwise.
*/
void overlay_update(struct seat *seat);
/* This function must be called when server->grabbed_view is destroyed */
void overlay_hide(struct seat *seat);
/* This function is called to clean up the timer on exit */
/* Destroys the overlay if it exists */
void overlay_finish(struct seat *seat);
#endif

View file

@ -4,7 +4,8 @@
#include <stdbool.h>
#include <wlr/util/box.h>
#include "view.h"
struct view;
bool placement_find_best(struct view *view, struct wlr_box *geometry);

View file

@ -1,7 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_RESISTANCE_H
#define LABWC_RESISTANCE_H
#include "labwc.h"
#include <stdbool.h>
#include <wlr/util/box.h>
struct view;
/**
* resistance_unsnap_apply() - Apply resistance when dragging a

View file

@ -5,12 +5,6 @@
struct server;
struct view;
enum resize_indicator_mode {
LAB_RESIZE_INDICATOR_NEVER = 0,
LAB_RESIZE_INDICATOR_ALWAYS,
LAB_RESIZE_INDICATOR_NON_PIXEL
};
void resize_indicator_reconfigure(struct server *server);
void resize_indicator_show(struct view *view);
void resize_indicator_update(struct view *view);

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_SCALED_SCENE_BUFFER_H
#define LABWC_SCALED_SCENE_BUFFER_H
#ifndef LABWC_SCALED_BUFFER_H
#define LABWC_SCALED_BUFFER_H
#include <wayland-server-core.h>
@ -9,20 +9,20 @@
struct wlr_buffer;
struct wlr_scene_tree;
struct lab_data_buffer;
struct scaled_scene_buffer;
struct scaled_buffer;
struct scaled_scene_buffer_impl {
struct scaled_buffer_impl {
/* Return a new buffer optimized for the new scale */
struct lab_data_buffer *(*create_buffer)
(struct scaled_scene_buffer *scaled_buffer, double scale);
(struct scaled_buffer *scaled_buffer, double scale);
/* Might be NULL or used for cleaning up */
void (*destroy)(struct scaled_scene_buffer *scaled_buffer);
void (*destroy)(struct scaled_buffer *scaled_buffer);
/* Returns true if the two buffers are visually the same */
bool (*equal)(struct scaled_scene_buffer *scaled_buffer_a,
struct scaled_scene_buffer *scaled_buffer_b);
bool (*equal)(struct scaled_buffer *scaled_buffer_a,
struct scaled_buffer *scaled_buffer_b);
};
struct scaled_scene_buffer {
struct scaled_buffer {
struct wlr_scene_buffer *scene_buffer;
int width; /* unscaled, read only */
int height; /* unscaled, read only */
@ -35,7 +35,7 @@ struct scaled_scene_buffer {
struct wl_list cache; /* struct scaled_buffer_cache_entry.link */
struct wl_listener destroy;
struct wl_listener outputs_update;
const struct scaled_scene_buffer_impl *impl;
const struct scaled_buffer_impl *impl;
struct wl_list link; /* all_scaled_buffers */
};
@ -78,22 +78,22 @@ struct scaled_scene_buffer {
* to handle the majority of use cases where a view is moved between no more
* than two different scales.
*
* scaled_scene_buffer will clean up automatically once the internal
* scaled_buffer will clean up automatically once the internal
* wlr_scene_buffer is being destroyed. If implementation->destroy is set
* it will also get called so a consumer of this API may clean up its own
* allocations.
*
* Besides caching buffers for each scale per scaled_scene_buffer, we also
* store all the scaled_scene_buffers from all the implementers in a list
* Besides caching buffers for each scale per scaled_buffer, we also
* store all the scaled_buffers from all the implementers in a list
* in order to reuse backing buffers for visually duplicated
* scaled_scene_buffers found via impl->equal().
* scaled_buffers found via impl->equal().
*
* All requested lab_data_buffers via impl->create_buffer() will be locked
* during the lifetime of the buffer in the internal cache and unlocked
* when being evacuated from the cache (due to LAB_SCALED_BUFFER_MAX_CACHE
* or the internal wlr_scene_buffer being destroyed).
*
* If drop_buffer was set during creation of the scaled_scene_buffer, the
* If drop_buffer was set during creation of the scaled_buffer, the
* backing wlr_buffer behind a lab_data_buffer will also get dropped
* (via wlr_buffer_drop). If there are no more locks (consumers) of the
* respective buffer this will then cause the lab_data_buffer to be free'd.
@ -103,21 +103,21 @@ struct scaled_scene_buffer {
* destroyed until the buffer is evacuated from the internal cache and thus
* unlocked.
*
* This allows using scaled_scene_buffer for an autoscaling font_buffer
* This allows using scaled_buffer for an autoscaling font_buffer
* (which gets free'd automatically) and also for theme components like
* rounded corner images or button icons whose buffers only exist once but
* are references by multiple windows with their own scaled_scene_buffers.
* are references by multiple windows with their own scaled_buffers.
*
* The rough idea is: use drop_buffer = true for one-shot buffers and false
* for buffers that should outlive the scaled_scene_buffer instance itself.
* for buffers that should outlive the scaled_buffer instance itself.
*/
struct scaled_scene_buffer *scaled_scene_buffer_create(
struct scaled_buffer *scaled_buffer_create(
struct wlr_scene_tree *parent,
const struct scaled_scene_buffer_impl *implementation,
const struct scaled_buffer_impl *implementation,
bool drop_buffer);
/**
* scaled_scene_buffer_request_update - mark the buffer that needs to be
* scaled_buffer_request_update - mark the buffer that needs to be
* updated
* @width: the width of the buffer to be rendered, in scene coordinates
* @height: the height of the buffer to be rendered, in scene coordinates
@ -125,22 +125,22 @@ struct scaled_scene_buffer *scaled_scene_buffer_create(
* This function should be called when the states bound to the buffer are
* updated and ready for rendering.
*/
void scaled_scene_buffer_request_update(struct scaled_scene_buffer *self,
void scaled_buffer_request_update(struct scaled_buffer *self,
int width, int height);
/**
* scaled_scene_buffer_invalidate_sharing - clear the list of entire cached
* scaled_scene_buffers used to share visually dupliated buffers. This should
* scaled_buffer_invalidate_sharing - clear the list of entire cached
* scaled_buffers used to share visually dupliated buffers. This should
* be called on Reconfigure to force updates of newly created
* scaled_scene_buffers rather than reusing ones created before Reconfigure.
* scaled_buffers rather than reusing ones created before Reconfigure.
*/
void scaled_scene_buffer_invalidate_sharing(void);
void scaled_buffer_invalidate_sharing(void);
/* Private */
struct scaled_scene_buffer_cache_entry {
struct wl_list link; /* struct scaled_scene_buffer.cache */
struct scaled_buffer_cache_entry {
struct wl_list link; /* struct scaled_buffer.cache */
struct wlr_buffer *buffer;
double scale;
};
#endif /* LABWC_SCALED_SCENE_BUFFER_H */
#endif /* LABWC_SCALED_BUFFER_H */

View file

@ -6,7 +6,7 @@
struct wlr_scene_tree;
struct wlr_scene_buffer;
struct scaled_scene_buffer;
struct scaled_buffer;
struct scaled_font_buffer {
struct wlr_scene_buffer *scene_buffer;
@ -19,7 +19,7 @@ struct scaled_font_buffer {
float color[4];
float bg_color[4];
struct font font;
struct scaled_scene_buffer *scaled_buffer;
struct scaled_buffer *scaled_buffer;
/*
* The following fields are used only for the titlebar, where
@ -34,7 +34,7 @@ struct scaled_font_buffer {
/**
* Create an auto scaling font buffer, providing a wlr_scene_buffer node for
* display. It gets destroyed automatically when the backing scaled_scene_buffer
* display. It gets destroyed automatically when the backing scaled_buffer
* is being destroyed which in turn happens automatically when the backing
* wlr_scene_buffer (or one of its parents) is being destroyed.
*
@ -73,12 +73,4 @@ void scaled_font_buffer_update(struct scaled_font_buffer *self, const char *text
int max_width, struct font *font, const float *color,
const float *bg_color);
/**
* Update the max width of an existing auto scaling font buffer
* and force a new render.
*
* No steps are taken to detect if its actually required to render a new buffer.
*/
void scaled_font_buffer_set_max_width(struct scaled_font_buffer *self, int max_width);
#endif /* LABWC_SCALED_FONT_BUFFER_H */

View file

@ -10,7 +10,7 @@ struct wlr_scene_node;
struct wlr_scene_buffer;
struct scaled_icon_buffer {
struct scaled_scene_buffer *scaled_buffer;
struct scaled_buffer *scaled_buffer;
struct wlr_scene_buffer *scene_buffer;
struct server *server;
/* for window icon */
@ -34,7 +34,7 @@ struct scaled_icon_buffer {
/*
* Create an auto scaling icon buffer, providing a wlr_scene_buffer node for
* display. It gets destroyed automatically when the backing scaled_scene_buffer
* display. It gets destroyed automatically when the backing scaled_buffer
* is being destroyed which in turn happens automatically when the backing
* wlr_scene_buffer (or one of its parents) is being destroyed.
*/
@ -48,7 +48,4 @@ void scaled_icon_buffer_set_view(struct scaled_icon_buffer *self,
void scaled_icon_buffer_set_icon_name(struct scaled_icon_buffer *self,
const char *icon_name);
/* Obtain scaled_icon_buffer from wlr_scene_node */
struct scaled_icon_buffer *scaled_icon_buffer_from_node(struct wlr_scene_node *node);
#endif /* LABWC_SCALED_ICON_BUFFER_H */

View file

@ -2,15 +2,13 @@
#ifndef LABWC_SCALED_IMG_BUFFER_H
#define LABWC_SCALED_IMG_BUFFER_H
#include <stdbool.h>
struct wlr_scene_tree;
struct wlr_scene_node;
struct wlr_scene_buffer;
struct lab_img;
struct scaled_img_buffer {
struct scaled_scene_buffer *scaled_buffer;
struct scaled_buffer *scaled_buffer;
struct wlr_scene_buffer *scene_buffer;
struct lab_img *img;
int width;
@ -56,7 +54,7 @@ struct scaled_img_buffer {
/*
* Create an auto scaling image buffer, providing a wlr_scene_buffer node for
* display. It gets destroyed automatically when the backing scaled_scene_buffer
* display. It gets destroyed automatically when the backing scaled_buffer
* is being destroyed which in turn happens automatically when the backing
* wlr_scene_buffer (or one of its parents) is being destroyed.
*
@ -66,7 +64,4 @@ struct scaled_img_buffer {
struct scaled_img_buffer *scaled_img_buffer_create(struct wlr_scene_tree *parent,
struct lab_img *img, int width, int height);
/* Obtain scaled_img_buffer from wlr_scene_node */
struct scaled_img_buffer *scaled_img_buffer_from_node(struct wlr_scene_node *node);
#endif /* LABWC_SCALED_IMG_BUFFER_H */

View file

@ -2,7 +2,7 @@
#ifndef LABWC_SESSION_LOCK_H
#define LABWC_SESSION_LOCK_H
#include <wlr/types/wlr_session_lock_v1.h>
#include <wayland-server-core.h>
struct output;
struct server;

View file

@ -2,21 +2,19 @@
#ifndef LABWC_SNAP_CONSTRAINTS_H
#define LABWC_SNAP_CONSTRAINTS_H
#include <wlr/util/edges.h>
#include "common/border.h"
#include "view.h"
#include "common/edge.h"
struct view;
struct wlr_box;
void snap_constraints_set(struct view *view,
enum wlr_edges direction, struct wlr_box geom);
void snap_constraints_set(struct view *view, enum lab_edge direction,
struct wlr_box geom);
void snap_constraints_invalidate(struct view *view);
void snap_constraints_update(struct view *view);
struct wlr_box snap_constraints_effective(struct view *view,
enum wlr_edges direction, bool use_pending);
enum lab_edge direction, bool use_pending);
#endif /* LABWC_SNAP_CONSTRAINTS_H */

View file

@ -2,19 +2,19 @@
#ifndef LABWC_SNAP_H
#define LABWC_SNAP_H
#include "common/border.h"
#include "view.h"
#include "common/edge.h"
struct view;
struct wlr_box;
void snap_move_to_edge(struct view *view,
enum view_edge direction, bool snap_to_windows, int *dx, int *dy);
enum lab_edge direction, bool snap_to_windows, int *dx, int *dy);
void snap_grow_to_next_edge(struct view *view,
enum view_edge direction, struct wlr_box *geo);
enum lab_edge direction, struct wlr_box *geo);
void snap_shrink_to_next_edge(struct view *view,
enum view_edge direction, struct wlr_box *geo);
enum lab_edge direction, struct wlr_box *geo);
void snap_invalidate_edge_cache(struct view *view);
void snap_update_cache_geometry(struct view *view);

View file

@ -3,51 +3,54 @@
#define LABWC_SSD_INTERNAL_H
#include <wlr/util/box.h>
#include "common/macros.h"
#include "ssd.h"
#include "common/border.h"
#include "theme.h"
#include "view.h"
#define FOR_EACH(tmp, ...) \
{ \
__typeof__(tmp) _x[] = { __VA_ARGS__, NULL }; \
size_t _i = 0; \
for ((tmp) = _x[_i]; _i < ARRAY_SIZE(_x) - 1; (tmp) = _x[++_i])
#define FOR_EACH_END }
struct ssd_button {
struct view *view;
enum ssd_part_type type;
/*
* Bitmap of lab_button_state that represents a combination of
* hover/toggled/rounded states.
*/
uint8_t state_set;
/*
* Image buffers for each combination of hover/toggled/rounded states.
* img_buffers[state_set] is displayed. Some of these can be NULL
* (e.g. img_buffers[LAB_BS_ROUNDED] is set only for corner buttons).
*
* When "type" is LAB_SSD_BUTTON_WINDOW_ICON, these are all NULL and
* window_icon is used instead.
*/
struct scaled_img_buffer *img_buffers[LAB_BS_ALL + 1];
struct scaled_icon_buffer *window_icon;
struct wl_listener destroy;
};
struct ssd_sub_tree {
struct wlr_scene_tree *tree;
struct wl_list parts; /* ssd_part.link */
};
struct ssd_state_title_width {
int width;
bool truncated;
};
/*
* The scene-graph of SSD looks like below. The parentheses indicate the
* type of each node (enum lab_node_type, stored in the node_descriptor
* attached to the wlr_scene_node).
*
* ssd->tree (LAB_NODE_SSD_ROOT)
* +--titlebar (LAB_NODE_TITLEBAR)
* | +--inactive
* | | +--background bar
* | | +--left corner
* | | +--right corner
* | | +--title (LAB_NODE_TITLE)
* | | +--iconify button (LAB_NODE_BUTTON_ICONIFY)
* | | | +--normal close icon image
* | | | +--hovered close icon image
* | | | +--...
* | | +--window icon (LAB_NODE_BUTTON_WINDOW_ICON)
* | | | +--window icon image
* | | +--...
* | +--active
* | +--...
* +--border
* | +--inactive
* | | +--top
* | | +--...
* | +--active
* | +--top
* | +--...
* +--shadow
* | +--inactive
* | | +--top
* | | +--...
* | +--active
* | +--top
* | +--...
* +--extents
* +--top
* +--...
*/
struct ssd {
struct view *view;
struct wlr_scene_tree *tree;
@ -80,33 +83,48 @@ struct ssd {
struct wlr_box geometry;
struct ssd_state_title {
char *text;
struct ssd_state_title_width active;
struct ssd_state_title_width inactive;
/* indexed by enum ssd_active_state */
struct ssd_state_title_width dstates[2];
} title;
} state;
/* An invisible area around the view which allows resizing */
struct ssd_sub_tree extents;
struct ssd_extents_scene {
struct wlr_scene_tree *tree;
struct wlr_scene_rect *top, *bottom, *left, *right;
} extents;
/* The top of the view, containing buttons, title, .. */
struct {
struct ssd_titlebar_scene {
int height;
struct wlr_scene_tree *tree;
struct ssd_sub_tree active;
struct ssd_sub_tree inactive;
struct ssd_titlebar_subtree {
struct wlr_scene_tree *tree;
struct wlr_scene_buffer *corner_left;
struct wlr_scene_buffer *corner_right;
struct wlr_scene_buffer *bar;
struct scaled_font_buffer *title;
struct wl_list buttons_left; /* ssd_button.link */
struct wl_list buttons_right; /* ssd_button.link */
} subtrees[2]; /* indexed by enum ssd_active_state */
} titlebar;
/* Borders allow resizing as well */
struct {
struct ssd_border_scene {
struct wlr_scene_tree *tree;
struct ssd_sub_tree active;
struct ssd_sub_tree inactive;
struct ssd_border_subtree {
struct wlr_scene_tree *tree;
struct wlr_scene_rect *top, *bottom, *left, *right;
} subtrees[2]; /* indexed by enum ssd_active_state */
} border;
struct {
struct ssd_shadow_scene {
struct wlr_scene_tree *tree;
struct ssd_sub_tree active;
struct ssd_sub_tree inactive;
struct ssd_shadow_subtree {
struct wlr_scene_tree *tree;
struct wlr_scene_buffer *top, *bottom, *left, *right,
*top_left, *top_right, *bottom_left, *bottom_right;
} subtrees[2]; /* indexed by enum ssd_active_state */
} shadow;
/*
@ -117,47 +135,39 @@ struct ssd {
struct border margin;
};
struct ssd_part {
enum ssd_part_type type;
/* Buffer pointer. May be NULL */
struct scaled_font_buffer *buffer;
/* This part represented in scene graph */
struct ssd_button {
struct wlr_scene_node *node;
enum lab_node_type type;
struct wl_list link;
};
/*
* Bitmap of lab_button_state that represents a combination of
* hover/toggled/rounded states.
*/
uint8_t state_set;
/*
* Image buffers for each combination of hover/toggled/rounded states.
* img_buffers[state_set] is displayed. Some of these can be NULL
* (e.g. img_buffers[LAB_BS_ROUNDED] is set only for corner buttons).
*
* When the button type is LAB_NODE_BUTTON_WINDOW_ICON,
* these are all NULL and window_icon is used instead.
*/
struct scaled_img_buffer *img_buffers[LAB_BS_ALL + 1];
struct ssd_hover_state {
struct view *view;
struct ssd_button *button;
struct scaled_icon_buffer *window_icon;
struct wl_list link; /* ssd_titlebar_subtree.buttons_{left,right} */
};
struct wlr_buffer;
struct wlr_scene_tree;
/* SSD internal helpers to create various SSD elements */
/* TODO: Replace some common args with a struct */
struct ssd_part *add_scene_part(
struct wl_list *part_list, enum ssd_part_type type);
struct ssd_part *add_scene_rect(
struct wl_list *list, enum ssd_part_type type,
struct wlr_scene_tree *parent, int width, int height, int x, int y,
float color[4]);
struct ssd_part *add_scene_buffer(
struct wl_list *list, enum ssd_part_type type,
struct wlr_scene_tree *parent, struct wlr_buffer *buffer, int x, int y);
struct ssd_part *add_scene_button(struct wl_list *part_list,
enum ssd_part_type type, struct wlr_scene_tree *parent,
struct lab_img *buffers[LAB_BS_ALL + 1], int x, int y,
struct ssd_button *attach_ssd_button(struct wl_list *button_parts,
enum lab_node_type type, struct wlr_scene_tree *parent,
struct lab_img *imgs[LAB_BS_ALL + 1], int x, int y,
struct view *view);
/* SSD internal helpers */
struct ssd_part *ssd_get_part(
struct wl_list *part_list, enum ssd_part_type type);
void ssd_destroy_parts(struct wl_list *list);
/* SSD internal */
void ssd_titlebar_create(struct ssd *ssd);
void ssd_titlebar_update(struct ssd *ssd);

View file

@ -2,8 +2,15 @@
#ifndef LABWC_SSD_H
#define LABWC_SSD_H
#include <wayland-server-core.h>
#include "common/border.h"
#include "common/node-type.h"
#include "config/types.h"
enum ssd_active_state {
SSD_INACTIVE = 0,
SSD_ACTIVE = 1,
};
#define FOR_EACH_ACTIVE_STATE(active) for (active = SSD_INACTIVE; active <= SSD_ACTIVE; active++)
struct wlr_cursor;
@ -14,64 +21,10 @@ struct wlr_cursor;
*/
#define SSD_SHADOW_INSET 0.3
/*
* Sequence these according to the order they should be processed for
* press and hover events. Bear in mind that some of their respective
* interactive areas overlap, so for example buttons need to come before title.
*/
enum ssd_part_type {
LAB_SSD_NONE = 0,
LAB_SSD_BUTTON_CLOSE = 1,
LAB_SSD_BUTTON_MAXIMIZE,
LAB_SSD_BUTTON_ICONIFY,
LAB_SSD_BUTTON_WINDOW_ICON,
LAB_SSD_BUTTON_WINDOW_MENU,
LAB_SSD_BUTTON_SHADE,
LAB_SSD_BUTTON_OMNIPRESENT,
/* only for internal use */
LAB_SSD_BUTTON_FIRST = LAB_SSD_BUTTON_CLOSE,
LAB_SSD_BUTTON_LAST = LAB_SSD_BUTTON_OMNIPRESENT,
LAB_SSD_BUTTON,
LAB_SSD_PART_TITLEBAR,
LAB_SSD_PART_TITLEBAR_CORNER_RIGHT,
LAB_SSD_PART_TITLEBAR_CORNER_LEFT,
LAB_SSD_PART_TITLE,
/* shared by shadows, borders and extents */
LAB_SSD_PART_CORNER_TOP_LEFT,
LAB_SSD_PART_CORNER_TOP_RIGHT,
LAB_SSD_PART_CORNER_BOTTOM_RIGHT,
LAB_SSD_PART_CORNER_BOTTOM_LEFT,
LAB_SSD_PART_TOP,
LAB_SSD_PART_RIGHT,
LAB_SSD_PART_BOTTOM,
LAB_SSD_PART_LEFT,
LAB_SSD_CLIENT,
LAB_SSD_FRAME,
LAB_SSD_ROOT,
LAB_SSD_MENU,
LAB_SSD_OSD,
LAB_SSD_LAYER_SURFACE,
LAB_SSD_LAYER_SUBSURFACE,
LAB_SSD_UNMANAGED,
LAB_SSD_ALL,
LAB_SSD_END_MARKER
};
enum ssd_mode {
LAB_SSD_MODE_INVALID,
LAB_SSD_MODE_NONE,
LAB_SSD_MODE_BORDER,
LAB_SSD_MODE_FULL,
};
/* Forward declare arguments */
struct server;
struct ssd;
struct ssd_button;
struct ssd_hover_state;
struct view;
struct wlr_scene;
struct wlr_scene_node;
@ -98,19 +51,20 @@ void ssd_set_titlebar(struct ssd *ssd, bool enabled);
void ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable);
void ssd_enable_shade(struct ssd *ssd, bool enable);
struct ssd_hover_state *ssd_hover_state_new(void);
void ssd_update_button_hover(struct wlr_scene_node *node,
struct ssd_hover_state *hover_state);
void ssd_update_hovered_button(struct server *server,
struct wlr_scene_node *node);
enum ssd_part_type ssd_button_get_type(const struct ssd_button *button);
struct view *ssd_button_get_view(const struct ssd_button *button);
void ssd_button_free(struct ssd_button *button);
/* Public SSD helpers */
enum ssd_part_type ssd_get_part_type(const struct ssd *ssd,
struct wlr_scene_node *node, struct wlr_cursor *cursor);
uint32_t ssd_resize_edges(enum ssd_part_type type);
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
enum ssd_mode ssd_mode_parse(const char *mode);
/*
* Returns a part type that represents a mouse context like "Top", "Left" and
* "TRCorner" when the cursor is on the window border or resizing handle.
*/
enum lab_node_type ssd_get_resizing_type(const struct ssd *ssd,
struct wlr_cursor *cursor);
enum lab_ssd_mode ssd_mode_parse(const char *mode);
/* TODO: clean up / update */
struct border ssd_thickness(struct view *view);

View file

@ -9,8 +9,8 @@
#define LABWC_THEME_H
#include <cairo.h>
#include <wlr/render/wlr_renderer.h>
#include "ssd.h"
#include <stdbool.h>
#include "common/node-type.h"
struct lab_img;
@ -41,11 +41,11 @@ struct theme_snapping_overlay {
enum lab_button_state {
LAB_BS_DEFAULT = 0,
LAB_BS_HOVERD = 1 << 0,
LAB_BS_HOVERED = 1 << 0,
LAB_BS_TOGGLED = 1 << 1,
LAB_BS_ROUNDED = 1 << 2,
LAB_BS_ALL = LAB_BS_HOVERD | LAB_BS_TOGGLED | LAB_BS_ROUNDED,
LAB_BS_ALL = LAB_BS_HOVERED | LAB_BS_TOGGLED | LAB_BS_ROUNDED,
};
struct theme_background {
@ -83,14 +83,14 @@ struct theme {
/*
* Themes/textures for each active/inactive window. Indexed by
* THEME_INACTIVE and THEME_ACTIVE.
* ssd_active_state.
*/
struct {
/* title background pattern (solid or gradient) */
struct theme_background title_bg;
/* TODO: add toggled/hover/pressed/disabled colors for buttons */
float button_colors[LAB_SSD_BUTTON_LAST + 1][4];
float button_colors[LAB_NODE_BUTTON_LAST + 1][4];
float border_color[4];
float toggled_keybinds_color[4];
@ -104,12 +104,12 @@ struct theme {
* The texture of a window buttons for each hover/toggled/rounded
* state. This can be accessed like:
*
* buttons[LAB_SSD_BUTTON_ICONIFY][LAB_BS_HOVERD | LAB_BS_TOGGLED]
* buttons[LAB_NODE_BUTTON_ICONIFY][LAB_BS_HOVERED | LAB_BS_TOGGLED]
*
* Elements in buttons[0] are all NULL since LAB_SSD_BUTTON_FIRST is 1.
* Elements in buttons[0] are all NULL since LAB_NODE_BUTTON_FIRST is 1.
*/
struct lab_img *button_imgs
[LAB_SSD_BUTTON_LAST + 1][LAB_BS_ALL + 1];
[LAB_NODE_BUTTON_LAST + 1][LAB_BS_ALL + 1];
/*
* The titlebar background is specified as a cairo_pattern
@ -164,13 +164,39 @@ struct theme {
float osd_border_color[4];
float osd_label_text_color[4];
int osd_window_switcher_width;
int osd_window_switcher_padding;
int osd_window_switcher_item_padding_x;
int osd_window_switcher_item_padding_y;
int osd_window_switcher_item_active_border_width;
int osd_window_switcher_item_icon_size;
bool osd_window_switcher_width_is_percent;
struct window_switcher_classic_theme {
int width;
int padding;
int item_padding_x;
int item_padding_y;
int item_active_border_width;
float item_active_border_color[4];
float item_active_bg_color[4];
int item_icon_size;
bool width_is_percent;
/*
* Not set in rc.xml/themerc, but derived from the tallest
* titlebar object plus 2 * window_titlebar_padding_height
*/
int item_height;
} osd_window_switcher_classic;
struct window_switcher_thumbnail_theme {
int max_width;
int padding;
int item_width;
int item_height;
int item_padding;
int item_active_border_width;
float item_active_border_color[4];
float item_active_bg_color[4];
int item_icon_size;
bool max_width_is_percent;
int title_height;
} osd_window_switcher_thumbnail;
int osd_window_switcher_preview_border_width;
float osd_window_switcher_preview_border_color[3][4];
@ -181,20 +207,11 @@ struct theme {
struct theme_snapping_overlay
snapping_overlay_region, snapping_overlay_edge;
/*
* Not set in rc.xml/themerc, but derived from the tallest titlebar
* object plus 2 * window_titlebar_padding_height
*/
int osd_window_switcher_item_height;
/* magnifier */
float mag_border_color[4];
int mag_border_width;
};
#define THEME_INACTIVE 0
#define THEME_ACTIVE 1
struct server;
/**

14
include/translate.h Normal file
View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_TRANSLATE_H
#define LABWC_TRANSLATE_H
#include "config.h"
#if HAVE_NLS
#include <libintl.h>
#include <locale.h>
#define _ gettext
#else
#define _(s) (s)
#endif
#endif /* LABWC_TRANSLATE_H */

View file

@ -2,16 +2,20 @@
#ifndef LABWC_VIEW_H
#define LABWC_VIEW_H
#include "config/rcxml.h"
#include "config.h"
#include "ssd.h"
#include <stdbool.h>
#include <stdint.h>
#include <wayland-util.h>
#include <wlr/util/box.h>
#include <xkbcommon/xkbcommon.h>
#include "common/three-state.h"
#include "common/edge.h"
#include "config.h"
#include "config/types.h"
/*
* Default minimal window size. Clients can explicitly set smaller values via
* e.g. xdg_toplevel::set_min_size.
*/
#define LAB_MIN_VIEW_WIDTH 100
#define LAB_MIN_VIEW_HEIGHT 60
/*
@ -28,7 +32,6 @@
* In labwc, a view is a container for surfaces which can be moved around by
* the user. In practice this means XDG toplevel and XWayland windows.
*/
enum view_type {
LAB_XDG_SHELL_VIEW,
#if HAVE_XWAYLAND
@ -59,16 +62,6 @@ enum view_axis {
VIEW_AXIS_INVALID = (1 << 2),
};
enum view_edge {
VIEW_EDGE_INVALID = 0,
VIEW_EDGE_LEFT,
VIEW_EDGE_RIGHT,
VIEW_EDGE_UP,
VIEW_EDGE_DOWN,
VIEW_EDGE_CENTER,
};
enum view_wants_focus {
/* View does not want focus */
VIEW_WANTS_FOCUS_NEVER = 0,
@ -89,33 +82,6 @@ enum view_wants_focus {
VIEW_WANTS_FOCUS_UNLIKELY,
};
/*
* Window types are based on the NET_WM constants from X11. See:
* https://specifications.freedesktop.org/wm-spec/1.4/ar01s05.html#id-1.6.7
*
* The enum constants are intended to match wlr_xwayland_net_wm_window_type.
* Redefining the same constants here may seem redundant, but is necessary
* to make them available even in builds with xwayland support disabled.
*/
enum window_type {
NET_WM_WINDOW_TYPE_DESKTOP = 0,
NET_WM_WINDOW_TYPE_DOCK,
NET_WM_WINDOW_TYPE_TOOLBAR,
NET_WM_WINDOW_TYPE_MENU,
NET_WM_WINDOW_TYPE_UTILITY,
NET_WM_WINDOW_TYPE_SPLASH,
NET_WM_WINDOW_TYPE_DIALOG,
NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
NET_WM_WINDOW_TYPE_POPUP_MENU,
NET_WM_WINDOW_TYPE_TOOLTIP,
NET_WM_WINDOW_TYPE_NOTIFICATION,
NET_WM_WINDOW_TYPE_COMBO,
NET_WM_WINDOW_TYPE_DND,
NET_WM_WINDOW_TYPE_NORMAL,
WINDOW_TYPE_LEN
};
struct view;
struct wlr_surface;
struct foreign_toplevel;
@ -140,7 +106,6 @@ struct view_size_hints {
struct view_impl {
void (*configure)(struct view *view, struct wlr_box geo);
void (*close)(struct view *view);
const char *(*get_string_prop)(struct view *view, const char *prop);
void (*map)(struct view *view);
void (*set_activated)(struct view *view, bool activated);
void (*set_fullscreen)(struct view *view, bool fullscreen);
@ -165,7 +130,7 @@ struct view_impl {
bool (*has_strut_partial)(struct view *self);
/* returns true if view declared itself a window type */
bool (*contains_window_type)(struct view *view,
enum window_type window_type);
enum lab_window_type window_type);
/* returns the client pid that this view belongs to */
pid_t (*get_pid)(struct view *view);
};
@ -207,21 +172,24 @@ struct view {
struct wlr_scene_tree *scene_tree;
struct wlr_scene_tree *content_tree;
/* These are never NULL and an empty string is set instead. */
char *title;
char *app_id; /* WM_CLASS for xwayland windows */
bool mapped;
bool been_mapped;
bool ssd_enabled;
bool ssd_titlebar_hidden;
enum lab_ssd_mode ssd_mode;
enum ssd_preference ssd_preference;
bool shaded;
bool minimized;
enum view_axis maximized;
bool fullscreen;
bool tearing_hint;
enum three_state force_tearing;
enum lab_tristate force_tearing;
bool visible_on_all_workspaces;
enum view_edge tiled;
uint32_t edges_visible; /* enum wlr_edges bitset */
bool inhibits_keybinds;
enum lab_edge tiled;
enum lab_edge edges_visible;
bool inhibits_keybinds; /* also inhibits mousebinds */
xkb_layout_index_t keyboard_layout;
/* Pointer to an output owned struct region, may be NULL */
@ -314,18 +282,18 @@ struct view_query {
struct wl_list link;
char *identifier;
char *title;
int window_type;
enum lab_window_type window_type;
char *sandbox_engine;
char *sandbox_app_id;
enum three_state shaded;
enum lab_tristate shaded;
enum view_axis maximized;
enum three_state iconified;
enum three_state focused;
enum three_state omnipresent;
enum view_edge tiled;
enum lab_tristate iconified;
enum lab_tristate focused;
enum lab_tristate omnipresent;
enum lab_edge tiled;
char *tiled_region;
char *desktop;
enum ssd_mode decoration;
enum lab_ssd_mode decoration;
char *monitor;
};
@ -339,28 +307,6 @@ struct xdg_toplevel_view {
struct wl_listener new_popup;
};
/* All criteria is applied in AND logic */
enum lab_view_criteria {
/* No filter -> all focusable views */
LAB_VIEW_CRITERIA_NONE = 0,
/*
* Includes always-on-top views, e.g.
* what is visible on the current workspace
*/
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
/* Positive criteria */
LAB_VIEW_CRITERIA_FULLSCREEN = 1 << 1,
LAB_VIEW_CRITERIA_ALWAYS_ON_TOP = 1 << 2,
LAB_VIEW_CRITERIA_ROOT_TOPLEVEL = 1 << 3,
/* Negative criteria */
LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 6,
LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 7,
LAB_VIEW_CRITERIA_NO_OMNIPRESENT = 1 << 8,
};
/**
* view_from_wlr_surface() - returns the view associated with a
* wlr_surface, or NULL if the surface has no associated view.
@ -482,16 +428,11 @@ void view_array_append(struct server *server, struct wl_array *views,
enum lab_view_criteria criteria);
enum view_wants_focus view_wants_focus(struct view *view);
bool view_contains_window_type(struct view *view, enum window_type window_type);
/**
* view_edge_invert() - select the opposite of a provided edge
*
* VIEW_EDGE_CENTER and VIEW_EDGE_INVALID both map to VIEW_EDGE_INVALID.
*
* @edge: edge to be inverted
*/
enum view_edge view_edge_invert(enum view_edge edge);
/* If view is NULL, the size of SSD is not considered */
struct wlr_box view_get_edge_snap_box(struct view *view, struct output *output,
enum lab_edge edge);
struct wlr_box view_get_region_snap_box(struct view *view, struct region *region);
/**
* view_is_focusable() - Check whether or not a view can be focused
@ -513,11 +454,15 @@ bool view_is_focusable(struct view *view);
*/
void view_offer_focus(struct view *view);
struct wlr_box view_get_edge_snap_box(struct view *view, struct output *output,
enum lab_edge edge);
void mappable_connect(struct mappable *mappable, struct wlr_surface *surface,
wl_notify_func_t notify_map, wl_notify_func_t notify_unmap);
void mappable_disconnect(struct mappable *mappable);
void view_toggle_keybinds(struct view *view);
bool view_inhibits_actions(struct view *view, struct wl_list *actions);
void view_set_activated(struct view *view, bool activated);
void view_set_output(struct view *view, struct output *output);
@ -541,7 +486,7 @@ void view_moved(struct view *view);
void view_minimize(struct view *view, bool minimized);
bool view_compute_centered_position(struct view *view,
const struct wlr_box *ref, int w, int h, int *x, int *y);
void view_set_fallback_natural_geometry(struct view *view);
struct wlr_box view_get_fallback_natural_geometry(struct view *view);
void view_store_natural_geometry(struct view *view);
/**
@ -572,10 +517,10 @@ void view_center(struct view *view, const struct wlr_box *ref);
* @policy: placement policy to apply
*/
void view_place_by_policy(struct view *view, bool allow_cursor,
enum view_placement_policy policy);
enum lab_placement_policy policy);
void view_constrain_size_to_that_of_usable_area(struct view *view);
void view_restore_to(struct view *view, struct wlr_box geometry);
void view_set_maximized(struct view *view, enum view_axis maximized);
void view_set_untiled(struct view *view);
void view_maximize(struct view *view, enum view_axis axis,
bool store_natural_geometry);
@ -595,24 +540,22 @@ bool view_is_tiled(struct view *view);
bool view_is_tiled_and_notify_tiled(struct view *view);
bool view_is_floating(struct view *view);
void view_move_to_workspace(struct view *view, struct workspace *workspace);
enum ssd_mode view_get_ssd_mode(struct view *view);
void view_set_ssd_mode(struct view *view, enum ssd_mode mode);
void view_set_decorations(struct view *view, enum ssd_mode mode, bool force_ssd);
bool view_titlebar_visible(struct view *view);
void view_set_ssd_mode(struct view *view, enum lab_ssd_mode mode);
void view_set_decorations(struct view *view, enum lab_ssd_mode mode, bool force_ssd);
void view_toggle_fullscreen(struct view *view);
void view_invalidate_last_layout_geometry(struct view *view);
void view_adjust_for_layout_change(struct view *view);
void view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_windows);
void view_grow_to_edge(struct view *view, enum view_edge direction);
void view_shrink_to_edge(struct view *view, enum view_edge direction);
void view_snap_to_edge(struct view *view, enum view_edge direction,
bool across_outputs, bool store_natural_geometry);
void view_move_to_edge(struct view *view, enum lab_edge direction, bool snap_to_windows);
void view_grow_to_edge(struct view *view, enum lab_edge direction);
void view_shrink_to_edge(struct view *view, enum lab_edge direction);
void view_snap_to_edge(struct view *view, enum lab_edge direction,
bool across_outputs, bool combine, bool store_natural_geometry);
void view_snap_to_region(struct view *view, struct region *region, bool store_natural_geometry);
void view_move_to_output(struct view *view, struct output *output);
void view_move_to_front(struct view *view);
void view_move_to_back(struct view *view);
struct view *view_get_root(struct view *view);
void view_append_children(struct view *view, struct wl_array *children);
/**
* view_get_modal_dialog() - returns any modal dialog found among this
@ -631,11 +574,9 @@ bool view_on_output(struct view *view, struct output *output);
*/
bool view_has_strut_partial(struct view *view);
const char *view_get_string_prop(struct view *view, const char *prop);
void view_update_title(struct view *view);
void view_update_app_id(struct view *view);
void view_set_title(struct view *view, const char *title);
void view_set_app_id(struct view *view, const char *app_id);
void view_reload_ssd(struct view *view);
int view_get_min_width(void);
void view_set_shade(struct view *view, bool shaded);
@ -654,8 +595,7 @@ void view_init(struct view *view);
void view_destroy(struct view *view);
enum view_axis view_axis_parse(const char *direction);
enum view_edge view_edge_parse(const char *direction);
enum view_placement_policy view_placement_parse(const char *policy);
enum lab_placement_policy view_placement_parse(const char *policy);
/* xdg.c */
struct wlr_xdg_surface *xdg_surface_from_view(struct view *view);

View file

@ -4,6 +4,7 @@
#include <stdbool.h>
#include <wayland-util.h>
#include "config/types.h"
enum window_rule_event {
LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP = 0,
@ -24,7 +25,7 @@ enum property {
struct window_rule {
char *identifier;
char *title;
int window_type;
enum lab_window_type window_type;
char *sandbox_engine;
char *sandbox_app_id;
bool match_once;

View file

@ -65,8 +65,6 @@ void xwayland_unmanaged_create(struct server *server,
void xwayland_view_create(struct server *server,
struct wlr_xwayland_surface *xsurface, bool mapped);
struct wlr_xwayland_surface *xwayland_surface_from_view(struct view *view);
void xwayland_server_init(struct server *server,
struct wlr_compositor *compositor);
void xwayland_server_finish(struct server *server);

View file

@ -1,7 +1,7 @@
project(
'labwc',
'c',
version: '0.9.0',
version: '0.9.2',
license: 'GPL-2.0-only',
meson_version: '>=0.59.0',
default_options: [
@ -127,13 +127,24 @@ conf_data.set10('HAVE_RSVG', have_rsvg)
conf_data.set10('HAVE_LIBSFDO', have_libsfdo)
foreach sym : ['LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY', 'LIBINPUT_CONFIG_3FG_DRAG_ENABLED_3FG']
conf_data.set10('HAVE_' + sym, cc.has_header_symbol('libinput.h', sym, dependencies: input))
has_sym = input.type_name() != 'internal' \
and cc.has_header_symbol('libinput.h', sym, dependencies: input)
conf_data.set10('HAVE_' + sym, has_sym)
endforeach
if get_option('static_analyzer').enabled()
add_project_arguments(['-fanalyzer'], language: 'c')
endif
link_args = []
if get_option('sections').enabled()
add_project_arguments(['-ffunction-sections'], language: 'c')
link_args += [
'-Wl,--gc-sections',
'-Wl,--print-gc-sections',
]
endif
msgfmt = find_program('msgfmt', required: get_option('nls'))
if msgfmt.found()
source_root = meson.current_source_dir()
@ -180,6 +191,7 @@ endif
subdir('include')
subdir('src')
subdir('docs')
subdir('clients')
dep_cmocka = dependency('cmocka', required: get_option('test'))
if dep_cmocka.found()
@ -192,16 +204,13 @@ executable(
include_directories: [labwc_inc],
dependencies: labwc_deps,
install: true,
link_args: link_args,
)
install_data('data/labwc.desktop', install_dir: get_option('datadir') / 'wayland-sessions')
install_data('data/labwc-portals.conf', install_dir: get_option('datadir') / 'xdg-desktop-portal')
# TODO: move this to clients/meson.build after the labnag PR
clients = files('clients/lab-sensible-terminal')
install_data(clients, install_dir: get_option('bindir'))
icons = ['labwc-symbolic.svg', 'labwc.svg']
foreach icon : icons
icon_path = join_paths('data', icon)

View file

@ -5,3 +5,4 @@ option('icon', type: 'feature', value: 'enabled', description: 'Enable window ic
option('nls', type: 'feature', value: 'auto', description: 'Enable native language support')
option('static_analyzer', type: 'feature', value: 'disabled', description: 'Run gcc static analyzer')
option('test', type: 'feature', value: 'disabled', description: 'Run tests')
option('sections', type: 'feature', value: 'disabled', description: 'Show unused functions')

View file

@ -1 +1 @@
ar ca cs da de el es et eu fa fi fr gl hu id it ja ka ko lt ms nl pa pl pt pt_BR ru sk sv tr uk zh_CN
ar ca cs da de el es et eu fa fi fr gl hu id it ja ka ko lt ms nl pa pl pt pt_BR ru sk sv tr uk zh_CN zh_TW

View file

@ -8,14 +8,16 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-09-23 20:01+0000\n"
"PO-Revision-Date: 2025-07-17 07:22+0000\n"
"Last-Translator: Abdullah Albaroty <albaroty@gmail.com>\n"
"Language-Team: Arabic <https://translate.lxqt-project.org/projects/labwc/labwc/ar/>\n"
"Language-Team: Arabic <https://translate.lxqt-project.org/projects/labwc/"
"labwc/ar/>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:1016
@ -24,7 +26,7 @@ msgstr "اذهب هناك..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "الطرفية"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2025-03-29 11:25+0000\n"
"Last-Translator: Davidmp <opensusecatala@gmail.com>\n"
"Language-Team: Catalan <https://translate.lxqt-project.org/projects/labwc/labwc/ca/>\n"
"PO-Revision-Date: 2025-10-11 20:01+0000\n"
"Last-Translator: alvaroelpob <alvaropobladoresteban9@gmail.com>\n"
"Language-Team: Catalan <https://translate.lxqt-project.org/projects/labwc/"
"labwc/ca/>\n"
"Language: ca\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Ves-hi..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,29 +8,32 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-03-02 02:00+0100\n"
"Last-Translator: zenobit <zenobit@disroot.org>\n"
"Language-Team: Czech <zenobit@disroot.org>\n"
"PO-Revision-Date: 2025-10-11 20:01+0000\n"
"Last-Translator: p-bo <pavel.borecki@gmail.com>\n"
"Language-Team: Czech <https://translate.lxqt-project.org/projects/labwc/"
"labwc/cs/>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:1016
msgid "Go there..."
msgstr ""
msgstr "Přejít tam..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminál"
#: src/menu/menu.c:1040
msgid "Reconfigure"
msgstr "Překonfigurovat"
msgstr "Přenastavit"
#: src/menu/menu.c:1042
msgid "Exit"
msgstr "Odejít"
msgstr "Ukončit"
#: src/menu/menu.c:1056
msgid "Minimize"
@ -46,7 +49,7 @@ msgstr "Na celou obrazovku"
#: src/menu/menu.c:1062
msgid "Roll Up/Down"
msgstr "Rolovat nahoru/dolů"
msgstr "Posouvat nahoru/dolů"
#: src/menu/menu.c:1064
msgid "Decorations"
@ -66,11 +69,11 @@ msgstr "Posunout doprava"
#: src/menu/menu.c:1083
msgid "Always on Visible Workspace"
msgstr "Vždy na viditelné Pracovní Ploše"
msgstr "Vždy na viditelné Pracovní ploše"
#: src/menu/menu.c:1086
msgid "Workspace"
msgstr "Pracovní Plocha"
msgstr "Pracovní plocha"
#: src/menu/menu.c:1089
msgid "Close"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-11-05 21:01+0000\n"
"PO-Revision-Date: 2025-08-15 20:01+0000\n"
"Last-Translator: Ettore Atalan <atalanttore@googlemail.com>\n"
"Language-Team: German <https://translate.lxqt-project.org/projects/labwc/labwc/de/>\n"
"Language-Team: German <https://translate.lxqt-project.org/projects/labwc/"
"labwc/de/>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Dorthin gehen..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-09-25 20:01+0000\n"
"Last-Translator: Giannis Antypas <gianni.antypas@gmail.com>\n"
"Language-Team: Greek <https://translate.lxqt-project.org/projects/labwc/labwc/el/>\n"
"PO-Revision-Date: 2025-08-02 08:01+0000\n"
"Last-Translator: Dimitrios Glentadakis <dglent@free.fr>\n"
"Language-Team: Greek <https://translate.lxqt-project.org/projects/labwc/"
"labwc/el/>\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Πήγαινε εκεί..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Τερματικό"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-12-15 01:13+0000\n"
"Last-Translator: vTT <vttfreebsd@gmail.com>\n"
"Language-Team: French <https://translate.lxqt-project.org/projects/labwc/labwc/fr/>\n"
"PO-Revision-Date: 2025-08-11 00:27+0000\n"
"Last-Translator: Oliver Chiasson <olivierchiasson@hotmail.fr>\n"
"Language-Team: French <https://translate.lxqt-project.org/projects/labwc/"
"labwc/fr/>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Y aller…"
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-12-10 02:04+0000\n"
"PO-Revision-Date: 2025-08-02 03:27+0000\n"
"Last-Translator: 이정희 <daemul72@gmail.com>\n"
"Language-Team: Korean <https://translate.lxqt-project.org/projects/labwc/labwc/ko/>\n"
"Language-Team: Korean <https://translate.lxqt-project.org/projects/labwc/"
"labwc/ko/>\n"
"Language: ko\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "빨리 가기..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "터미널"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,14 +8,17 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-11-13 21:01+0000\n"
"PO-Revision-Date: 2025-07-19 18:47+0000\n"
"Last-Translator: Moo <hazap@hotmail.com>\n"
"Language-Team: Lithuanian <https://translate.lxqt-project.org/projects/labwc/labwc/lt/>\n"
"Language-Team: Lithuanian <https://translate.lxqt-project.org/projects/labwc/"
"labwc/lt/>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? 1 : 2);\n"
"Plural-Forms: nplurals=3; plural=(n % 10 == 1 && (n % 100 < 11 || n % 100 > "
"19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? "
"1 : 2);\n"
"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:1016
@ -24,7 +27,7 @@ msgstr "Eiti ten..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminalas"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2025-04-08 05:25+0000\n"
"PO-Revision-Date: 2025-08-18 20:01+0000\n"
"Last-Translator: Qayyum Yazid <purrnama@proton.me>\n"
"Language-Team: Malay <https://translate.lxqt-project.org/projects/labwc/labwc/ms/>\n"
"Language-Team: Malay <https://translate.lxqt-project.org/projects/labwc/"
"labwc/ms/>\n"
"Language: ms\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Pergi sana..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-09-21 20:01+0000\n"
"PO-Revision-Date: 2025-07-13 08:01+0000\n"
"Last-Translator: Hugo Carvalho <hugokarvalho@hotmail.com>\n"
"Language-Team: Portuguese <https://translate.lxqt-project.org/projects/labwc/labwc/pt/>\n"
"Language-Team: Portuguese <https://translate.lxqt-project.org/projects/labwc/"
"labwc/pt/>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Ir lá..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,9 +8,10 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2025-02-04 21:01+0000\n"
"Last-Translator: EggSupernova <leomelo34@protonmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://translate.lxqt-project.org/projects/labwc/labwc/pt_BR/>\n"
"PO-Revision-Date: 2025-09-06 04:27+0000\n"
"Last-Translator: virtual-hand <handvirtual@tutamail.com>\n"
"Language-Team: Portuguese (Brazil) <https://translate.lxqt-project.org/"
"projects/labwc/labwc/pt_BR/>\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -24,7 +25,7 @@ msgstr "Vá para..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Terminal"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,14 +8,16 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-12-08 21:01+0000\n"
"Last-Translator: unabomberlive <7alinchik@mail.ru>\n"
"Language-Team: Russian <https://translate.lxqt-project.org/projects/labwc/labwc/ru/>\n"
"PO-Revision-Date: 2025-07-30 08:01+0000\n"
"Last-Translator: Valera <ValeraDX@yandex.ru>\n"
"Language-Team: Russian <https://translate.lxqt-project.org/projects/labwc/"
"labwc/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:1016
@ -24,7 +26,7 @@ msgstr "Перейти..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Терминал"
#: src/menu/menu.c:1040
msgid "Reconfigure"

View file

@ -8,14 +8,16 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-09-19 21:09+1000\n"
"PO-Revision-Date: 2024-09-24 08:01+0000\n"
"PO-Revision-Date: 2025-08-16 20:01+0000\n"
"Last-Translator: Ihor Hordiichuk <igor_ck@outlook.com>\n"
"Language-Team: Ukrainian <https://translate.lxqt-project.org/projects/labwc/labwc/uk/>\n"
"Language-Team: Ukrainian <https://translate.lxqt-project.org/projects/labwc/"
"labwc/uk/>\n"
"Language: uk\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:1016
@ -24,7 +26,7 @@ msgstr "Перейти до..."
#: src/menu/menu.c:1034
msgid "Terminal"
msgstr ""
msgstr "Термінал"
#: src/menu/menu.c:1040
msgid "Reconfigure"

Some files were not shown because too many files have changed in this diff Show more