diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 33cb225e..ef6ca30a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -98,7 +98,7 @@ Some distributions carry labwc in their repositories or user repositories.
- @adcdam (Slackware)
- @bdantas (Tiny Core Linux)
- @Visone-Selektah (Venom Linux)
-- @tranzystorek-io (Void Linux)
+- @tranzystorekk (Void Linux)
kindly maintain the packages in their respective distro.
@@ -354,10 +354,10 @@ 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
generate their `MY_LOCALE.po` file in a few steps:
-1. Edit the `po/LINGUAS` file to add their locale name by adding a space
- to the end of the field and typing the locale code.
-2. Copy the po/labwc.pot to po/MY_LOCALE.po
-3. Edit the newly generated MY_LOCALE.po file with some of their
+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
translation strings under each English string.
diff --git a/NEWS.md b/NEWS.md
index 11c0cebd..dbafc05f 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -9,7 +9,7 @@ The format is based on [Keep a Changelog]
| Date | All Changes | wlroots version | lines-of-code |
|------------|---------------|-----------------|---------------|
-| 2024-01-23 | [unreleased] | 0.17.1 | |
+| 2024-03-01 | [0.7.1] | 0.17.1 | 18624 |
| 2023-12-22 | [0.7.0] | 0.17.1 | 16576 |
| 2023-11-25 | [0.6.6] | 0.16.2 | 15796 |
| 2023-09-23 | [0.6.5] | 0.16.2 | 14809 |
@@ -28,10 +28,33 @@ The format is based on [Keep a Changelog]
| 2021-03-05 | [0.1.0] | 0.12.0 | 4627 |
-## [unreleased]
+## [0.7.1]
### Added
+- Support libinput option sendEventsMode to allow enabling/disabling devices.
+ Co-Authored-By: @Sachin-Bhat
+
+```xml
+
+
+ yes|no|disabledOnExternalMouse
+
+
+```
+
+- Add click method libinput option. Written-by: @datMaffin
+
+```xml
+
+
+ none|buttonAreas|clickfinger
+
+
+```
+
+- Add `data/labwc.svg` & `data/labwc-symbolic.svg`, and specify icon name
+ in labwc.desktop to enable Display Managers to show an icons for labwc.
- Expose output configuration test to clients. For example, this enables
`wlr-randr --dryrun`
- Add window-edge resistance for interactive moves/resizes and support negative
@@ -90,6 +113,7 @@ The format is based on [Keep a Changelog]
- Add config option `` with supported values `center`,
`cursor` and `automatic`. The latter minimizes overlap with other windows
already on screen and is similar to Openbox's smart window placement.
+ The placement policies honour ``.
Written-by: @ahesford #1312
```xml
@@ -100,6 +124,13 @@ The format is based on [Keep a Changelog]
### Fixed
+- Delay popup-unconstrain until after first commit in response to a changed
+ wlroots 0.17 interface and to get rid of the error message below. Issue #1372
+
+ [types/xdg_shell/wlr_xdg_surface.c:169] A configure is scheduled for an uninitialized xdg_surface
+
+- Notify clients about configuration errors when changing output settings.
+ Issue #1528.
- Fix output configuration bug causing compositor crash when refresh rate is
zero. Issue #1458
- Fix disappearing cursor bug on view destruction. Issue #1393
@@ -124,6 +155,8 @@ The format is based on [Keep a Changelog]
### Changed
+- Make `MoveToCursor` honour ``. Issue #1494
+- Add `Roll Up/Down` client-menu entry for `ToggleShade`
- When a Wayland-native window is snapped to a screen edges or user-defined
region, labwc will notify the application that it is "tiled", allowing the
application to better adapt its rendering to constrained layouts. Windows
@@ -1043,7 +1076,8 @@ 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.7.0...HEAD
+[unreleased]: https://github.com/labwc/labwc/compare/0.7.1...HEAD
+[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
diff --git a/README.md b/README.md
index f2c4c375..10339da7 100644
--- a/README.md
+++ b/README.md
@@ -127,8 +127,11 @@ High-level summary of items that Labwc supports:
The obligatory screenshot:
-
-
+
+
+
+
+ Screenshot description
## 2. Build and Installation
diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd
index 9d55f63f..facb2d68 100644
--- a/docs/labwc-actions.5.scd
+++ b/docs/labwc-actions.5.scd
@@ -163,7 +163,7 @@ Actions are used in menus and keyboard/mouse bindings.
to the center of the window. If the given output does not contain
any windows, the cursor is centered on the given output.
-**
+**
Moves active window to other output, unless the window state is
fullscreen.
@@ -172,6 +172,9 @@ Actions are used in menus and keyboard/mouse bindings.
be one of "left", "right", "up" or "down" to indicate that the window
should be moved to the next output in that direction (if one exists).
+ *wrap* [yes|no] When using the direction attribute, wrap around from
+ right-to-left or top-to-bottom, and vice versa. Default no.
+
**
Resizes active window size to width and height of the output when the
window size exceeds the output size.
diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd
index 13751813..57e76bdc 100644
--- a/docs/labwc-config.5.scd
+++ b/docs/labwc-config.5.scd
@@ -8,7 +8,7 @@ labwc - configuration files
Labwc uses openbox-3.6 specification for configuration and theming, but does not
support all options. The following files form the basis of the labwc
-configuration: rc.xml, menu.xml, autostart and environment.
+configuration: rc.xml, menu.xml, autostart, shutdown and environment.
No configuration files are needed to start and run labwc.
@@ -34,11 +34,8 @@ alternative.
The configuration directory location can be override with the -C command line
option.
-All configuration and theme files except autostart are re-loaded on receiving
-signal SIGHUP.
-
-The *autostart* file is executed as a shell script. This is the place for
-executing clients for handling background images, panels and similar.
+All configuration and theme files except autostart and shutdown are re-loaded on
+receiving signal SIGHUP.
The *environment* file is parsed as *variable=value* and sets environment
variables accordingly. It is recommended to specify keyboard layout settings and
@@ -48,6 +45,20 @@ sourced prior to running openbox.
Note: Tilde (~) and environment variables in the value are expanded, but
subshell syntax and apostrophes are ignored.
+The *autostart* file is executed as a shell script after labwc has read its
+configuration and set variables defined in the environment file. Additionally,
+the environment variables WAYLAND_DISPLAY and (when labwc is built with Xwayland
+support) DISPLAY will be defined. This is the place for executing clients for
+handling background images, panels and other tasks that should run automatically
+when labwc launches.
+
+The *shutdown* file is executed as a shell script when labwc is preparing to
+terminate itself. All environment variables, including WAYLAND_DISPLAY and
+DISPLAY, will be available to the script. However, because the script runs
+asynchronously with other termination tasks, the shutdown file should not assume
+that the display will be usable. This file is useful to perform any custom
+operations necessary to finalize a labwc session.
+
The *menu.xml* file defines the context/root-menus and is described in
labwc-menu(5).
@@ -511,7 +522,7 @@ extending outward from the snapped edge.
```
**
- A touch configuration can be bound to a specifc device. If device
+ A touch configuration can be bound to a specific device. If device
name is left empty, the touch configuration applies to all touch
devices or functions as a fallback. Multiple touch configurations
can exist.
@@ -592,6 +603,8 @@ extending outward from the snapped edge.
+
+
```
@@ -667,6 +680,36 @@ extending outward from the snapped edge.
any motion events while a keyboard is typing, and for a short while
after as well.
+** [none|buttonAreas|clickfinger]
+ Configure the method by which physical clicks on a touchpad are mapped to
+ mouse-button events.
+
+ The click methods available are:
+ - *buttonAreas* - The bottom of the touchpad is divided into distinct
+ regions corresponding to left, middle and right buttons; clicking within
+ the region will trigger the corresponding event. Clicking the main area
+ further up produces a left button event.
+ - *clickfinger* - Clicking with one, two or three finger(s) will produce
+ left, right or middle button event without regard to the location of a
+ click.
+ - *none* - Physical clicks will not produce button events.
+
+ The default method depends on the touchpad hardware.
+
+** [yes|no|disabledOnExternalMouse]
+ Optionally enable or disable sending any device events.
+
+ The options available are:
+ - *yes* - Events are sent as usual
+ - *no* - No events are sent from this device
+ - *disabledOnExternalMouse* - This device does not send events if an
+ external mouse has been detected.
+
+ It is possible to prevent events from a device in the config and then do
+ a Reconfigure to temporarily enable / disable specific devices.
+
+ By default, this setting is not configured.
+
## WINDOW RULES
Two types of window rules are supported, actions and properties. They are
diff --git a/docs/rc.xml b/docs/rc.xml
index 3bf2d116..edcca868 100644
--- a/docs/rc.xml
+++ b/docs/rc.xml
@@ -7,10 +7,6 @@
-
- 10
-
-
8
diff --git a/docs/rc.xml.all b/docs/rc.xml.all
index 423bcb74..c3586ae0 100644
--- a/docs/rc.xml.all
+++ b/docs/rc.xml.all
@@ -465,13 +465,15 @@
non-touch, default or the name of a device. You can obtain device names by
running *libinput list-devices* as root or member of the input group.
- Tap is set to *yes* be default. All others are left blank in order to use
+ Tap is set to *yes* by default. All others are left blank in order to use
device defaults.
All values are [yes|no] except for:
- pointerSpeed [-1.0 to 1.0]
- accelProfile [flat|adaptive]
- tapButtonMap [lrm|lmr]
+ - clickMethod [none|buttonAreas|clickfinger]
+ - sendEventsMode [yes|no|disabledOnExternalMouse]
-->
@@ -485,6 +487,8 @@
+
+
diff --git a/include/common/string-helpers.h b/include/common/string-helpers.h
index 4e204302..6d0ec905 100644
--- a/include/common/string-helpers.h
+++ b/include/common/string-helpers.h
@@ -43,4 +43,23 @@ void string_truncate_at_pattern(char *buf, const char *pattern);
*/
char *strdup_printf(const char *fmt, ...);
+/**
+ * str_join - format and join an array of strings with a separator
+ * @parts: NULL-terminated array of string parts to be joined
+ * @fmt: printf-style format string applied to each part
+ * @sep: separator inserted between parts when joining
+ *
+ * A new string is allocated to hold the joined result. The user must free the
+ * returned string. Returns NULL on error.
+ *
+ * Each part of the array is converted via the equivalent of sprintf(output,
+ * fmt, part), so fmt should include a single "%s" format specification. If fmt
+ * is NULL, a default "%s" will be used to copy each part verbatim.
+ *
+ * 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);
+
#endif /* LABWC_STRING_HELPERS_H */
diff --git a/include/config/libinput.h b/include/config/libinput.h
index 4ec0ebb7..912009ea 100644
--- a/include/config/libinput.h
+++ b/include/config/libinput.h
@@ -23,11 +23,13 @@ struct libinput_category {
int left_handed;
enum libinput_config_tap_state tap;
enum libinput_config_tap_button_map tap_button_map;
- int tap_and_drag; /* -1 or libinput_config_drag_state */
- int drag_lock; /* -1 or libinput_config_drag_lock_state */
- int accel_profile; /* -1 or libinput_config_accel_profile */
- int middle_emu; /* -1 or libinput_config_middle_emulation_state */
- int dwt; /* -1 or libinput_config_dwt_state */
+ int tap_and_drag; /* -1 or libinput_config_drag_state */
+ int drag_lock; /* -1 or libinput_config_drag_lock_state */
+ int accel_profile; /* -1 or libinput_config_accel_profile */
+ int middle_emu; /* -1 or libinput_config_middle_emulation_state */
+ int dwt; /* -1 or libinput_config_dwt_state */
+ int click_method; /* -1 or libinput_config_click_method */
+ int send_events_mode; /* -1 or libinput_config_send_events_mode */
};
enum lab_libinput_device_type get_device_type(const char *s);
diff --git a/include/config/session.h b/include/config/session.h
index d1efbb60..6de5f05d 100644
--- a/include/config/session.h
+++ b/include/config/session.h
@@ -15,4 +15,10 @@ void session_environment_init(void);
*/
void session_autostart_init(void);
+/**
+ * session_shutdown - run session shutdown file as shell script
+ * Note: Same as `sh ~/.config/labwc/shutdown` (or equivalent XDG config dir)
+ */
+void session_shutdown(void);
+
#endif /* LABWC_SESSION_H */
diff --git a/include/layers.h b/include/layers.h
index d64c434f..52583035 100644
--- a/include/layers.h
+++ b/include/layers.h
@@ -28,6 +28,7 @@ struct lab_layer_popup {
/* To simplify moving popup nodes from the bottom to the top layer */
struct wlr_box output_toplevel_sx_box;
+ struct wl_listener commit;
struct wl_listener destroy;
struct wl_listener new_popup;
};
diff --git a/include/view.h b/include/view.h
index c24fa3d3..b0cb8471 100644
--- a/include/view.h
+++ b/include/view.h
@@ -503,7 +503,8 @@ void view_on_output_destroy(struct view *view);
void view_connect_map(struct view *view, struct wlr_surface *surface);
void view_destroy(struct view *view);
-struct output *view_get_adjacent_output(struct view *view, enum view_edge edge);
+struct output *view_get_adjacent_output(struct view *view, enum view_edge edge,
+ bool wrap);
enum view_axis view_axis_parse(const char *direction);
enum view_edge view_edge_parse(const char *direction);
diff --git a/meson.build b/meson.build
index a0a43263..adbd5455 100644
--- a/meson.build
+++ b/meson.build
@@ -1,7 +1,7 @@
project(
'labwc',
'c',
- version: '0.7.0',
+ version: '0.7.1',
license: 'GPL-2.0-only',
meson_version: '>=0.59.0',
default_options: [
diff --git a/po/LINGUAS b/po/LINGUAS
index 58f25cb0..1b2407b5 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1 +1 @@
-de es et eu fi gl id it ja ka lt nl pa pl pt ru sv tr uk zh_CN
+cs de es et eu fi gl hu id it ja ka lt nl pa pl pt ru sv tr uk zh_CN
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 00000000..104e5012
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,69 @@
+# Labwc pot file
+# Copyright (C) 2024
+# This file is distributed under the same license as the labwc package.
+# zenobit , 2024.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: labwc\n"
+"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
+"POT-Creation-Date: 2024-01-15 16:00-0500\n"
+"PO-Revision-Date: 2024-03-02 02:00+0100\n"
+"Last-Translator: zenobit \n"
+"Language-Team: Czech \n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/menu/menu.c:697
+msgid "Reconfigure"
+msgstr "Překonfigurovat"
+
+#: src/menu/menu.c:699
+msgid "Exit"
+msgstr "Odejít"
+
+#: src/menu/menu.c:715
+msgid "Minimize"
+msgstr "Minimalizovat"
+
+#: src/menu/menu.c:717
+msgid "Maximize"
+msgstr "Maximalizovat"
+
+#: src/menu/menu.c:719
+msgid "Fullscreen"
+msgstr "Na celou obrazovku"
+
+#: src/menu/menu.c:721
+msgid "Roll up/down"
+msgstr "Rolovat nahoru/dolů"
+
+#: src/menu/menu.c:723
+msgid "Decorations"
+msgstr "Dekorace"
+
+#: src/menu/menu.c:725
+msgid "Always on Top"
+msgstr "Vždy nahoře"
+
+#: src/menu/menu.c:730
+msgid "Move left"
+msgstr "Posunout doleva"
+
+#: src/menu/menu.c:737
+msgid "Move right"
+msgstr "Posunout doprava"
+
+#: src/menu/menu.c:742
+msgid "Always on Visible Workspace"
+msgstr "Vždy na viditelné Pracovní Ploše"
+
+#: src/menu/menu.c:745
+msgid "Workspace"
+msgstr "Pracovní Plocha"
+
+#: src/menu/menu.c:748
+msgid "Close"
+msgstr "Zavřít"
diff --git a/po/fi.po b/po/fi.po
index d67d0355..b5021b65 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -8,13 +8,16 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: Automatically generated\n"
-"Language-Team: none\n"
+"PO-Revision-Date: 2024-02-29 14:23+0000\n"
+"Last-Translator: Jouni Järvinen \n"
+"Language-Team: Finnish \n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.2.1\n"
#: src/menu/menu.c:697
msgid "Reconfigure"
@@ -22,7 +25,7 @@ msgstr ""
#: src/menu/menu.c:699
msgid "Exit"
-msgstr ""
+msgstr "Poistu"
#: src/menu/menu.c:715
msgid "Minimize"
diff --git a/po/hu.po b/po/hu.po
new file mode 100644
index 00000000..da861355
--- /dev/null
+++ b/po/hu.po
@@ -0,0 +1,72 @@
+# Labwc pot file
+# Copyright (C) 2024
+# This file is distributed under the same license as the labwc package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: labwc\n"
+"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
+"POT-Creation-Date: 2024-01-15 16:00-0500\n"
+"PO-Revision-Date: 2024-02-19 21:23+0000\n"
+"Last-Translator: winerysearch \n"
+"Language-Team: Hungarian \n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.2.1\n"
+
+#: src/menu/menu.c:697
+msgid "Reconfigure"
+msgstr "Rekonfigurál"
+
+#: src/menu/menu.c:699
+msgid "Exit"
+msgstr "Kilépés"
+
+#: src/menu/menu.c:715
+msgid "Minimize"
+msgstr "Kis méret"
+
+#: src/menu/menu.c:717
+msgid "Maximize"
+msgstr "Teljes méret"
+
+#: src/menu/menu.c:719
+msgid "Fullscreen"
+msgstr "Teljes képernyő"
+
+#: src/menu/menu.c:721
+msgid "Roll up/down"
+msgstr "Felhúz / Legördül"
+
+#: src/menu/menu.c:723
+msgid "Decorations"
+msgstr "Dekorációk"
+
+#: src/menu/menu.c:725
+msgid "Always on Top"
+msgstr "Mindig felül"
+
+#: src/menu/menu.c:730
+msgid "Move left"
+msgstr "Balra dokkol"
+
+#: src/menu/menu.c:737
+msgid "Move right"
+msgstr "Jobbra dokkol"
+
+#: src/menu/menu.c:742
+msgid "Always on Visible Workspace"
+msgstr "Kitűz"
+
+#: src/menu/menu.c:745
+msgid "Workspace"
+msgstr "Munkaasztal"
+
+#: src/menu/menu.c:748
+msgid "Close"
+msgstr "Bezárás"
diff --git a/po/lt.po b/po/lt.po
index 65ab1166..7ac63f85 100644
--- a/po/lt.po
+++ b/po/lt.po
@@ -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-01-15 16:00-0500\n"
-"PO-Revision-Date: 2024-01-04 15:23+0000\n"
+"PO-Revision-Date: 2024-02-29 14:23+0000\n"
"Last-Translator: Moo \n"
-"Language-Team: Lithuanian \n"
+"Language-Team: Lithuanian \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:697
@@ -40,7 +43,7 @@ msgstr "Visas ekranas"
#: src/menu/menu.c:721
msgid "Roll up/down"
-msgstr ""
+msgstr "Užraityti/atraityti"
#: src/menu/menu.c:723
msgid "Decorations"
diff --git a/po/pa.po b/po/pa.po
index 77cd6b2c..655a83b1 100644
--- a/po/pa.po
+++ b/po/pa.po
@@ -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-01-15 16:00-0500\n"
-"PO-Revision-Date: 2023-12-26 07:23+0000\n"
+"PO-Revision-Date: 2024-02-21 14:23+0000\n"
"Last-Translator: A S Alam \n"
-"Language-Team: Punjabi \n"
+"Language-Team: Punjabi \n"
"Language: pa\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -40,7 +41,7 @@ msgstr "ਪੂਰੀ ਸਕਰੀਨ"
#: src/menu/menu.c:721
msgid "Roll up/down"
-msgstr ""
+msgstr "ਉੱਤੇ/ਹੇਠਾਂ ਸਕਰਾਓ"
#: src/menu/menu.c:723
msgid "Decorations"
diff --git a/po/ru.po b/po/ru.po
index f9e34051..be979099 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
"POT-Creation-Date: 2024-01-15 16:00-0500\n"
-"PO-Revision-Date: 2024-01-30 08:23+0000\n"
-"Last-Translator: pixis1 \n"
+"PO-Revision-Date: 2024-02-26 12:23+0000\n"
+"Last-Translator: Alice Ventus \n"
"Language-Team: Russian \n"
"Language: ru\n"
@@ -41,7 +41,6 @@ msgid "Fullscreen"
msgstr "На весь экран"
#: src/menu/menu.c:721
-#, fuzzy
msgid "Roll up/down"
msgstr "Свернуть/развернуть в заголовок"
diff --git a/po/tr.po b/po/tr.po
index 64ad85f6..20505905 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -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-01-15 16:00-0500\n"
-"PO-Revision-Date: 2023-12-26 09:00+0000\n"
+"PO-Revision-Date: 2024-02-24 22:23+0000\n"
"Last-Translator: Sabri Ünal \n"
-"Language-Team: Turkish \n"
+"Language-Team: Turkish \n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -40,7 +41,7 @@ msgstr "Tam Ekran"
#: src/menu/menu.c:721
msgid "Roll up/down"
-msgstr ""
+msgstr "Yukarı/aşağı katla"
#: src/menu/menu.c:723
msgid "Decorations"
diff --git a/src/action.c b/src/action.c
index e1187906..1cf8960a 100644
--- a/src/action.c
+++ b/src/action.c
@@ -397,6 +397,10 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char
}
goto cleanup;
}
+ if (!strcmp(argument, "wrap")) {
+ action_arg_add_bool(action, argument, parse_bool(content, false));
+ goto cleanup;
+ }
break;
case ACTION_TYPE_VIRTUAL_OUTPUT_ADD:
case ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE:
@@ -924,10 +928,15 @@ actions_run(struct view *activator, struct server *server,
} else {
/* Config parsing makes sure that direction is a valid direction */
enum view_edge edge = action_get_int(action, "direction", 0);
- target = view_get_adjacent_output(view, edge);
+ bool wrap = action_get_bool(action, "wrap", false);
+ target = view_get_adjacent_output(view, edge, wrap);
}
if (!target) {
- wlr_log(WLR_ERROR, "Invalid output.");
+ /*
+ * Most likely because we're already on the
+ * output furthest in the requested direction.
+ */
+ wlr_log(WLR_DEBUG, "Invalid output");
break;
}
view_move_to_output(view, target);
diff --git a/src/common/string-helpers.c b/src/common/string-helpers.c
index 37fdf4d0..0a1a8c81 100644
--- a/src/common/string-helpers.c
+++ b/src/common/string-helpers.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include
#include
#include
#include
@@ -83,3 +84,73 @@ strdup_printf(const char *fmt, ...)
}
return p;
}
+
+char *
+str_join(const char * const parts[],
+ const char *restrict fmt, const char *restrict sep)
+{
+ assert(parts);
+
+ if (!fmt) {
+ fmt = "%s";
+ }
+
+ if (!sep) {
+ sep = " ";
+ }
+
+ size_t size = 0;
+ size_t n_parts = 0;
+
+ size_t sep_len = strlen(sep);
+
+ /* Count the length of each formatted string */
+ for (const char *const *s = parts; *s; ++s) {
+ int n = snprintf(NULL, 0, fmt, *s);
+ if (n < 0) {
+ return NULL;
+ }
+ size += (size_t)n;
+ ++n_parts;
+ }
+
+ if (n_parts < 1) {
+ return NULL;
+ }
+
+ /* Need (n_parts - 1) separators, plus one NULL terminator */
+ size += (n_parts - 1) * sep_len + 1;
+
+ /* Concatenate the strings and separators */
+ char *buf = xzalloc(size);
+ char *p = buf;
+ for (const char *const *s = parts; *s; ++s) {
+ int n = 0;
+
+ if (p != buf) {
+ n = snprintf(p, size, "%s", sep);
+ if (n < 0 || (size_t)n >= size) {
+ p = NULL;
+ break;
+ }
+ size -= (size_t)n;
+ p += (size_t)n;
+ }
+
+ n = snprintf(p, size, fmt, *s);
+ if (n < 0 || (size_t)n >= size) {
+ p = NULL;
+ break;
+ }
+ size -= (size_t)n;
+ p += (size_t)n;
+ }
+
+ if (!p) {
+ free(buf);
+ return NULL;
+ }
+
+ return buf;
+}
+
diff --git a/src/config/libinput.c b/src/config/libinput.c
index 7ce62b79..93ab9af2 100644
--- a/src/config/libinput.c
+++ b/src/config/libinput.c
@@ -23,6 +23,8 @@ libinput_category_init(struct libinput_category *l)
l->accel_profile = -1;
l->middle_emu = -1;
l->dwt = -1;
+ l->click_method = -1;
+ l->send_events_mode = -1;
}
enum lab_libinput_device_type
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
index 61784e13..56f93e36 100644
--- a/src/config/rcxml.c
+++ b/src/config/rcxml.c
@@ -461,6 +461,29 @@ get_accel_profile(const char *s)
return -1;
}
+static int
+get_send_events_mode(const char *s)
+{
+ if (!s) {
+ goto err;
+ }
+
+ int ret = parse_bool(s, -1);
+ if (ret >= 0) {
+ return ret
+ ? LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
+ : LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
+ }
+
+ if (!strcasecmp(s, "disabledOnExternalMouse")) {
+ return LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
+ }
+
+err:
+ wlr_log(WLR_INFO, "Not a recognised send events mode");
+ return -1;
+}
+
static void
fill_libinput_category(char *nodename, char *content)
{
@@ -563,6 +586,22 @@ fill_libinput_category(char *nodename, char *content)
current_libinput_category->dwt = ret
? LIBINPUT_CONFIG_DWT_ENABLED
: LIBINPUT_CONFIG_DWT_DISABLED;
+ } else if (!strcasecmp(nodename, "clickMethod")) {
+ if (!strcasecmp(content, "none")) {
+ current_libinput_category->click_method =
+ LIBINPUT_CONFIG_CLICK_METHOD_NONE;
+ } else if (!strcasecmp(content, "clickfinger")) {
+ current_libinput_category->click_method =
+ LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
+ } else if (!strcasecmp(content, "buttonAreas")) {
+ current_libinput_category->click_method =
+ LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
+ } else {
+ wlr_log(WLR_ERROR, "invalid clickMethod");
+ }
+ } else if (!strcasecmp(nodename, "sendEventsMode")) {
+ current_libinput_category->send_events_mode =
+ get_send_events_mode(content);
}
}
diff --git a/src/config/session.c b/src/config/session.c
index 6d89531d..73ecb49b 100644
--- a/src/config/session.c
+++ b/src/config/session.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
#define _POSIX_C_SOURCE 200809L
+#include
#include
#include
#include
@@ -9,11 +10,23 @@
#include "common/buf.h"
#include "common/dir.h"
#include "common/file-helpers.h"
+#include "common/mem.h"
#include "common/spawn.h"
#include "common/string-helpers.h"
#include "config/session.h"
#include "labwc.h"
+static const char *const env_vars[] = {
+ "DISPLAY",
+ "WAYLAND_DISPLAY",
+ "XDG_CURRENT_DESKTOP",
+ "XCURSOR_SIZE",
+ "XCURSOR_THEME",
+ "XDG_SESSION_TYPE",
+ "LABWC_PID",
+ NULL
+};
+
static void
process_line(char *line)
{
@@ -65,7 +78,7 @@ read_environment_file(const char *filename)
}
static void
-update_activation_env(const char *env_keys)
+update_activation_env(bool initialize)
{
if (!getenv("DBUS_SESSION_BUS_ADDRESS")) {
/* Prevent accidentally auto-launching a dbus session */
@@ -75,13 +88,22 @@ update_activation_env(const char *env_keys)
}
wlr_log(WLR_INFO, "Updating dbus execution environment");
- char *cmd = strdup_printf("dbus-update-activation-environment %s", env_keys);
+ char *env_keys = str_join(env_vars, "%s", " ");
+ char *env_unset_keys = initialize ? NULL : str_join(env_vars, "%s=", " ");
+
+ char *cmd =
+ strdup_printf("dbus-update-activation-environment %s",
+ initialize ? env_keys : env_unset_keys);
spawn_async_no_shell(cmd);
free(cmd);
- cmd = strdup_printf("systemctl --user import-environment %s", env_keys);
+ cmd = strdup_printf("systemctl --user %s %s",
+ initialize ? "import-environment" : "unset-environment", env_keys);
spawn_async_no_shell(cmd);
free(cmd);
+
+ free(env_keys);
+ free(env_unset_keys);
}
void
@@ -120,15 +142,11 @@ session_environment_init(void)
paths_destroy(&paths);
}
-void
-session_autostart_init(void)
+static void
+run_session_script(const char *script)
{
- /* Update dbus and systemd user environment, each may fail gracefully */
- update_activation_env("DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP "
- "XCURSOR_SIZE XCURSOR_THEME XDG_SESSION_TYPE LABWC_PID");
-
struct wl_list paths;
- paths_config_create(&paths, "autostart");
+ paths_config_create(&paths, script);
bool should_merge_config = rc.merge_config;
struct wl_list *(*iter)(struct wl_list *list);
@@ -139,7 +157,7 @@ session_autostart_init(void)
if (!file_exists(path->string)) {
continue;
}
- wlr_log(WLR_INFO, "run autostart file %s", path->string);
+ wlr_log(WLR_INFO, "run session script %s", path->string);
char *cmd = strdup_printf("sh %s", path->string);
spawn_async_no_shell(cmd);
free(cmd);
@@ -150,3 +168,20 @@ session_autostart_init(void)
}
paths_destroy(&paths);
}
+
+void
+session_autostart_init(void)
+{
+ /* Update dbus and systemd user environment, each may fail gracefully */
+ update_activation_env(/* initialize */ true);
+ run_session_script("autostart");
+}
+
+void
+session_shutdown(void)
+{
+ run_session_script("shutdown");
+
+ /* Clear the dbus and systemd user environment, each may fail gracefully */
+ update_activation_env(/* initialize */ false);
+}
diff --git a/src/layers.c b/src/layers.c
index 79cffe94..20e9e683 100644
--- a/src/layers.c
+++ b/src/layers.c
@@ -260,14 +260,35 @@ popup_handle_destroy(struct wl_listener *listener, void *data)
wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->new_popup.link);
+
+ /* Usually already removed unless there was no commit at all */
+ if (popup->commit.notify) {
+ wl_list_remove(&popup->commit.link);
+ }
+
free(popup);
}
+static void
+popup_handle_commit(struct wl_listener *listener, void *data)
+{
+ struct lab_layer_popup *popup =
+ wl_container_of(listener, popup, commit);
+
+ if (popup->wlr_popup->base->initial_commit) {
+ wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup,
+ &popup->output_toplevel_sx_box);
+
+ /* Prevent getting called over and over again */
+ wl_list_remove(&popup->commit.link);
+ popup->commit.notify = NULL;
+ }
+}
+
static void popup_handle_new_popup(struct wl_listener *listener, void *data);
static struct lab_layer_popup *
-create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent,
- struct wlr_box *output_toplevel_sx_box)
+create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent)
{
struct lab_layer_popup *popup = znew(*popup);
popup->wlr_popup = wlr_popup;
@@ -282,10 +303,13 @@ create_popup(struct wlr_xdg_popup *wlr_popup, struct wlr_scene_tree *parent,
popup->destroy.notify = popup_handle_destroy;
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
+
popup->new_popup.notify = popup_handle_new_popup;
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
- wlr_xdg_popup_unconstrain_from_box(wlr_popup, output_toplevel_sx_box);
+ popup->commit.notify = popup_handle_commit;
+ wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
+
return popup;
}
@@ -297,8 +321,7 @@ popup_handle_new_popup(struct wl_listener *listener, void *data)
wl_container_of(listener, lab_layer_popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
struct lab_layer_popup *new_popup = create_popup(wlr_popup,
- lab_layer_popup->scene_tree,
- &lab_layer_popup->output_toplevel_sx_box);
+ lab_layer_popup->scene_tree);
new_popup->output_toplevel_sx_box =
lab_layer_popup->output_toplevel_sx_box;
}
@@ -357,8 +380,7 @@ handle_new_popup(struct wl_listener *listener, void *data)
.width = output_box.width,
.height = output_box.height,
};
- struct lab_layer_popup *popup = create_popup(wlr_popup,
- surface->tree, &output_toplevel_sx_box);
+ struct lab_layer_popup *popup = create_popup(wlr_popup, surface->tree);
popup->output_toplevel_sx_box = output_toplevel_sx_box;
if (surface->layer_surface->current.layer
diff --git a/src/main.c b/src/main.c
index 9bfe3a1d..d4a12a80 100644
--- a/src/main.c
+++ b/src/main.c
@@ -178,6 +178,8 @@ main(int argc, char *argv[])
wl_display_run(server.wl_display);
+ session_shutdown();
+
server_finish(&server);
menu_finish(&server);
diff --git a/src/output.c b/src/output.c
index 6d05ee94..e1c615e7 100644
--- a/src/output.c
+++ b/src/output.c
@@ -405,10 +405,11 @@ output_update_for_layout_change(struct server *server)
cursor_update_image(&server->seat);
}
-static void
+static bool
output_config_apply(struct server *server,
struct wlr_output_configuration_v1 *config)
{
+ bool success = true;
server->pending_output_layout_change++;
struct wlr_output_configuration_head_v1 *head;
@@ -436,8 +437,15 @@ output_config_apply(struct server *server,
output_enable_adaptive_sync(o, head->state.adaptive_sync_enabled);
}
if (!wlr_output_commit(o)) {
- wlr_log(WLR_ERROR, "Output config commit failed");
- continue;
+ /*
+ * FIXME: This is only part of the story, we should revert
+ * all previously commited outputs as well here.
+ *
+ * See https://github.com/labwc/labwc/pull/1528
+ */
+ wlr_log(WLR_INFO, "Output config commit failed: %s", o->name);
+ success = false;
+ break;
}
/* Only do Layout specific actions if the commit went trough */
@@ -477,6 +485,7 @@ output_config_apply(struct server *server,
server->pending_output_layout_change--;
do_output_layout_change(server);
+ return success;
}
static bool
@@ -509,11 +518,17 @@ verify_output_config_v1(const struct wlr_output_configuration_v1 *config)
if (wlr_output_is_wl(head->state.output) && refresh != 0) {
/* Wayland backend does not support refresh rates */
- err_msg = "Wayland backend refresh rate unsupported";
+ err_msg = "Wayland backend refresh rates unsupported";
goto custom_mode_failed;
}
}
+ if (wlr_output_is_wl(head->state.output)
+ && !head->state.adaptive_sync_enabled) {
+ err_msg = "Wayland backend requires adaptive sync";
+ goto custom_mode_failed;
+ }
+
/*
* Ensure the new output state can be applied on
* its own and inform the client when it can not.
@@ -569,8 +584,7 @@ handle_output_manager_apply(struct wl_listener *listener, void *data)
bool config_is_good = verify_output_config_v1(config);
- if (config_is_good) {
- output_config_apply(server, config);
+ if (config_is_good && output_config_apply(server, config)) {
wlr_output_configuration_v1_send_succeeded(config);
} else {
wlr_output_configuration_v1_send_failed(config);
diff --git a/src/seat.c b/src/seat.c
index 52b1b5d0..e4e69efe 100644
--- a/src/seat.c
+++ b/src/seat.c
@@ -91,6 +91,24 @@ get_category(struct wlr_input_device *device)
static void
configure_libinput(struct wlr_input_device *wlr_input_device)
{
+ /*
+ * TODO: We do not check any return values for the various
+ * libinput_device_config_*_set_*() calls. It would
+ * be nice if we could inform the users via log file
+ * that some libinput setting could not be applied.
+ *
+ * TODO: We are currently using int32_t with -1 as default
+ * to desribe the not-configured state. This is not
+ * really optimal as we can't properly deal with
+ * enum values that are 0. After some discussion via
+ * IRC the best way forward seem to be to use a
+ * uint32_t instead and UINT32_MAX as indicator for
+ * a not-configured state. This allows to properly
+ * test the enum being a member of a bitset via
+ * mask & value == value. All libinput enums are
+ * way below UINT32_MAX.
+ */
+
if (!wlr_input_device) {
wlr_log(WLR_ERROR, "no wlr_input_device");
return;
@@ -189,6 +207,36 @@ configure_libinput(struct wlr_input_device *wlr_input_device)
wlr_log(WLR_INFO, "dwt configured");
libinput_device_config_dwt_set_enabled(libinput_dev, dc->dwt);
}
+
+ if ((dc->click_method != LIBINPUT_CONFIG_CLICK_METHOD_NONE
+ && (libinput_device_config_click_get_methods(libinput_dev)
+ & dc->click_method) == 0)
+ || dc->click_method < 0) {
+ wlr_log(WLR_INFO, "click method not configured");
+ } else {
+ wlr_log(WLR_INFO, "click method configured");
+
+ /*
+ * Note, the documentation claims that:
+ * > [...] The device may require changing to a neutral state
+ * > first before activating the new method.
+ *
+ * However, just setting the method seems to work without
+ * issues.
+ */
+
+ libinput_device_config_click_set_method(libinput_dev, dc->click_method);
+ }
+
+ if ((dc->send_events_mode != LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
+ && (libinput_device_config_send_events_get_modes(libinput_dev)
+ & dc->send_events_mode) == 0)
+ || dc->send_events_mode < 0) {
+ wlr_log(WLR_INFO, "send events mode not configured");
+ } else {
+ wlr_log(WLR_INFO, "send events mode configured");
+ libinput_device_config_send_events_set_mode(libinput_dev, dc->send_events_mode);
+ }
}
static struct wlr_output *
diff --git a/src/view.c b/src/view.c
index 87b29e00..52627643 100644
--- a/src/view.c
+++ b/src/view.c
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include "common/macros.h"
#include "common/match.h"
#include "common/mem.h"
@@ -1519,8 +1520,44 @@ view_on_output_destroy(struct view *view)
view->output = NULL;
}
+static enum wlr_direction
+opposite_direction(enum wlr_direction direction)
+{
+ switch (direction) {
+ case WLR_DIRECTION_RIGHT:
+ return WLR_DIRECTION_LEFT;
+ case WLR_DIRECTION_LEFT:
+ return WLR_DIRECTION_RIGHT;
+ case WLR_DIRECTION_DOWN:
+ return WLR_DIRECTION_UP;
+ case WLR_DIRECTION_UP:
+ return WLR_DIRECTION_DOWN;
+ default:
+ return 0;
+ }
+}
+
+static enum wlr_direction
+get_wlr_direction(enum view_edge edge)
+{
+ switch (edge) {
+ case VIEW_EDGE_LEFT:
+ return WLR_DIRECTION_LEFT;
+ case VIEW_EDGE_RIGHT:
+ return WLR_DIRECTION_RIGHT;
+ case VIEW_EDGE_UP:
+ return WLR_DIRECTION_UP;
+ case VIEW_EDGE_DOWN:
+ return WLR_DIRECTION_DOWN;
+ case VIEW_EDGE_CENTER:
+ case VIEW_EDGE_INVALID:
+ default:
+ return 0;
+ }
+}
+
struct output *
-view_get_adjacent_output(struct view *view, enum view_edge edge)
+view_get_adjacent_output(struct view *view, enum view_edge edge, bool wrap)
{
assert(view);
struct output *output = view->output;
@@ -1530,32 +1567,31 @@ view_get_adjacent_output(struct view *view, enum view_edge edge)
return NULL;
}
+ struct wlr_box box = output_usable_area_in_layout_coords(output);
+ int lx = box.x + box.width / 2;
+ int ly = box.y + box.height / 2;
+
/* Determine any adjacent output in the appropriate direction */
struct wlr_output *new_output = NULL;
struct wlr_output *current_output = output->wlr_output;
struct wlr_output_layout *layout = view->server->output_layout;
- switch (edge) {
- case VIEW_EDGE_LEFT:
- new_output = wlr_output_layout_adjacent_output(
- layout, WLR_DIRECTION_LEFT, current_output, 1, 0);
- break;
- case VIEW_EDGE_RIGHT:
- new_output = wlr_output_layout_adjacent_output(
- layout, WLR_DIRECTION_RIGHT, current_output, 1, 0);
- break;
- case VIEW_EDGE_UP:
- new_output = wlr_output_layout_adjacent_output(
- layout, WLR_DIRECTION_UP, current_output, 0, 1);
- break;
- case VIEW_EDGE_DOWN:
- new_output = wlr_output_layout_adjacent_output(
- layout, WLR_DIRECTION_DOWN, current_output, 0, 1);
- break;
- default:
- break;
+ enum wlr_direction direction = get_wlr_direction(edge);
+ new_output = wlr_output_layout_adjacent_output(layout, direction,
+ current_output, lx, ly);
+
+ /*
+ * Optionally wrap around from top-to-bottom or left-to-right, and vice
+ * versa.
+ */
+ if (wrap && !new_output) {
+ new_output = wlr_output_layout_farthest_output(layout,
+ opposite_direction(direction), current_output, lx, ly);
}
- /* When "adjacent" output is the same as the original, there is no adjacent */
+ /*
+ * When "adjacent" output is the same as the original, there is no
+ * adjacent
+ */
if (!new_output || new_output == current_output) {
return NULL;
}
@@ -1629,7 +1665,8 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind
}
/* Otherwise, move to edge of next adjacent display, if possible */
- struct output *output = view_get_adjacent_output(view, direction);
+ struct output *output =
+ view_get_adjacent_output(view, direction, /* wrap */ false);
if (!output) {
return;
}
@@ -1788,7 +1825,7 @@ view_snap_to_edge(struct view *view, enum view_edge edge,
if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) {
/* We are already tiled for this edge; try to switch outputs */
- output = view_get_adjacent_output(view, edge);
+ output = view_get_adjacent_output(view, edge, /* wrap */ false);
if (!output) {
/*
diff --git a/src/xdg-popup.c b/src/xdg-popup.c
index 496c5c0c..65c13e8d 100644
--- a/src/xdg-popup.c
+++ b/src/xdg-popup.c
@@ -16,15 +16,17 @@ struct xdg_popup {
struct view *parent_view;
struct wlr_xdg_popup *wlr_popup;
+ struct wl_listener commit;
struct wl_listener destroy;
struct wl_listener new_popup;
};
static void
-popup_unconstrain(struct view *view, struct wlr_xdg_popup *popup)
+popup_unconstrain(struct xdg_popup *popup)
{
+ struct view *view = popup->parent_view;
struct server *server = view->server;
- struct wlr_box *popup_box = &popup->current.geometry;
+ struct wlr_box *popup_box = &popup->wlr_popup->current.geometry;
struct wlr_output_layout *output_layout = server->output_layout;
struct wlr_output *wlr_output = wlr_output_layout_output_at(
output_layout, view->current.x + popup_box->x,
@@ -39,7 +41,7 @@ popup_unconstrain(struct view *view, struct wlr_xdg_popup *popup)
.width = output_box.width,
.height = output_box.height,
};
- wlr_xdg_popup_unconstrain_from_box(popup, &output_toplevel_box);
+ wlr_xdg_popup_unconstrain_from_box(popup->wlr_popup, &output_toplevel_box);
}
static void
@@ -48,9 +50,28 @@ handle_xdg_popup_destroy(struct wl_listener *listener, void *data)
struct xdg_popup *popup = wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->new_popup.link);
+
+ /* Usually already removed unless there was no commit at all */
+ if (popup->commit.notify) {
+ wl_list_remove(&popup->commit.link);
+ }
free(popup);
}
+static void
+handle_xdg_popup_commit(struct wl_listener *listener, void *data)
+{
+ struct xdg_popup *popup = wl_container_of(listener, popup, commit);
+
+ if (popup->wlr_popup->base->initial_commit) {
+ popup_unconstrain(popup);
+
+ /* Prevent getting called over and over again */
+ wl_list_remove(&popup->commit.link);
+ popup->commit.notify = NULL;
+ }
+}
+
static void
popup_handle_new_xdg_popup(struct wl_listener *listener, void *data)
{
@@ -75,9 +96,13 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
popup->destroy.notify = handle_xdg_popup_destroy;
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
+
popup->new_popup.notify = popup_handle_new_xdg_popup;
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
+ popup->commit.notify = handle_xdg_popup_commit;
+ wl_signal_add(&wlr_popup->base->surface->events.commit, &popup->commit);
+
/*
* We must add xdg popups to the scene graph so they get rendered. The
* wlroots scene graph provides a helper for this, but to use it we must
@@ -100,6 +125,4 @@ xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup)
wlr_scene_xdg_surface_create(parent_tree, wlr_popup->base);
node_descriptor_create(wlr_popup->base->surface->data,
LAB_NODE_DESC_XDG_POPUP, view);
-
- popup_unconstrain(view, wlr_popup);
}