From 8be9c384602233389f58f1a3d2ab3b4159319b00 Mon Sep 17 00:00:00 2001 From: Marvin Dostal Date: Wed, 21 Feb 2024 18:19:48 +0100 Subject: [PATCH 01/23] Add click method libinput option (#1416) none|buttonAreas|clickfinger --- docs/labwc-config.5.scd | 17 +++++++++++++++++ docs/rc.xml.all | 4 +++- include/config/libinput.h | 1 + src/config/libinput.c | 1 + src/config/rcxml.c | 13 +++++++++++++ src/seat.c | 18 ++++++++++++++++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 13751813..bc8cf59b 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -592,6 +592,7 @@ extending outward from the snapped edge. + ``` @@ -667,6 +668,22 @@ 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. + ## WINDOW RULES Two types of window rules are supported, actions and properties. They are diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 423bcb74..5d0c4cff 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -465,13 +465,14 @@ 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] --> @@ -485,6 +486,7 @@ + diff --git a/include/config/libinput.h b/include/config/libinput.h index 4ec0ebb7..dffeea98 100644 --- a/include/config/libinput.h +++ b/include/config/libinput.h @@ -28,6 +28,7 @@ struct libinput_category { 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 */ }; enum lab_libinput_device_type get_device_type(const char *s); diff --git a/src/config/libinput.c b/src/config/libinput.c index 7ce62b79..a8de5e7b 100644 --- a/src/config/libinput.c +++ b/src/config/libinput.c @@ -23,6 +23,7 @@ libinput_category_init(struct libinput_category *l) l->accel_profile = -1; l->middle_emu = -1; l->dwt = -1; + l->click_method = -1; } enum lab_libinput_device_type diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 61784e13..f18cce32 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -563,6 +563,19 @@ 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"); + } } } diff --git a/src/seat.c b/src/seat.c index 52b1b5d0..0f421987 100644 --- a/src/seat.c +++ b/src/seat.c @@ -189,6 +189,24 @@ 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 ((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); + } } static struct wlr_output * From d00d3ec00ba32c57483eec5b144a8f6011eeda12 Mon Sep 17 00:00:00 2001 From: Weblate Date: Wed, 21 Feb 2024 15:23:23 +0100 Subject: [PATCH 02/23] Translation updates from weblate Co-authored-by: A S Alam Co-authored-by: Weblate Co-authored-by: winerysearch Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/hu/ Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/pa/ Translation: Labwc/labwc --- po/LINGUAS | 2 +- po/hu.po | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ po/pa.po | 7 +++--- 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 po/hu.po diff --git a/po/LINGUAS b/po/LINGUAS index 58f25cb0..b27cc570 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 +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/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/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" From 1aa906e0de740a6af96c7365e03c137f84bbc414 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Mon, 19 Feb 2024 22:01:27 +0000 Subject: [PATCH 03/23] README.md: Add screenshot description ...and use the png files on the labwc website rather than imgur. Fixes: #1363 --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 From d69faffc4edcf179396c820eaea0d4d18b30ca1f Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:22:28 +0100 Subject: [PATCH 04/23] src/output.c: notify clients about config errors Preliminary fix for #1525. Based on the protocol we should also revert all previously correctly committed outputs. #1528 is doing just that but may cause regressions so we need a short term solution and then deal with potential issues in #1528 after the release. --- src/output.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/output.c b/src/output.c index 6d05ee94..28ee298f 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 @@ -569,8 +578,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); From 7adf5533f975736be1b1a20b25dcaa650b32c0e0 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:24:05 +0100 Subject: [PATCH 05/23] src/output.c: log when disabling adaptive_sync on a nested labwc --- src/output.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/output.c b/src/output.c index 28ee298f..e1c615e7 100644 --- a/src/output.c +++ b/src/output.c @@ -518,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. From 9456b50983e2a90d72c3cb5de80636bed4ce728f Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Sat, 24 Feb 2024 19:12:56 +0100 Subject: [PATCH 06/23] seat: fix configure condition for click method Exclude none (zero) from the bitmask test , otherwise the bitmask test is always true when click method is configured to 'none' and as a result the configuration will be skipped. --- src/seat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/seat.c b/src/seat.c index 0f421987..635945b1 100644 --- a/src/seat.c +++ b/src/seat.c @@ -189,8 +189,10 @@ 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 ((libinput_device_config_click_get_methods(libinput_dev) - & dc->click_method) == 0 + + 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 { From 6fb06c54c28c4063a87f189e1fc08c0a0d4d5485 Mon Sep 17 00:00:00 2001 From: Sachin Bhat Date: Mon, 26 Jun 2023 07:36:54 +0800 Subject: [PATCH 07/23] config: support libinput sendEventsMode This allows to enable / disable libinput devices. Co-Authored-By: @Consolatis --- docs/labwc-config.5.scd | 14 ++++++++++++++ docs/rc.xml.all | 2 ++ include/config/libinput.h | 13 +++++++------ src/config/libinput.c | 1 + src/config/rcxml.c | 26 ++++++++++++++++++++++++++ src/seat.c | 28 ++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 6 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index bc8cf59b..223eae0a 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -684,6 +684,20 @@ extending outward from the snapped edge. 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.all b/docs/rc.xml.all index 5d0c4cff..c3586ae0 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -473,6 +473,7 @@ - accelProfile [flat|adaptive] - tapButtonMap [lrm|lmr] - clickMethod [none|buttonAreas|clickfinger] + - sendEventsMode [yes|no|disabledOnExternalMouse] --> @@ -487,6 +488,7 @@ + diff --git a/include/config/libinput.h b/include/config/libinput.h index dffeea98..912009ea 100644 --- a/include/config/libinput.h +++ b/include/config/libinput.h @@ -23,12 +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 click_method; /* -1 or libinput_config_click_method */ + 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/src/config/libinput.c b/src/config/libinput.c index a8de5e7b..93ab9af2 100644 --- a/src/config/libinput.c +++ b/src/config/libinput.c @@ -24,6 +24,7 @@ libinput_category_init(struct libinput_category *l) 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 f18cce32..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) { @@ -576,6 +599,9 @@ fill_libinput_category(char *nodename, char *content) } 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/seat.c b/src/seat.c index 635945b1..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; @@ -209,6 +227,16 @@ configure_libinput(struct wlr_input_device *wlr_input_device) 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 * From fb1a0a2bdf9aa8ddec782b4a51b219ab54b2a0b6 Mon Sep 17 00:00:00 2001 From: Weblate Date: Sat, 24 Feb 2024 23:23:23 +0100 Subject: [PATCH 08/23] Translation updates from weblate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sabri Ünal Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/tr/ Translation: Labwc/labwc --- po/tr.po | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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" From 598ab9bcff4ea9f3a152b75d3e824b2c6bcb7dc9 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Sat, 24 Feb 2024 23:05:02 +0100 Subject: [PATCH 09/23] src/layers.c: delay popup unconstrain until after first commit Fixes: #1372 --- include/layers.h | 1 + src/layers.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 7 deletions(-) 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/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 From ccbc75571a8d1e8fbae477db1b3401eb031ed335 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Sat, 24 Feb 2024 23:16:55 +0100 Subject: [PATCH 10/23] src/xdg-popup.c: delay popup unconstrain until after first commit Fixes: #1372 --- src/xdg-popup.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) 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); } From 7110b7cf3e4146240c1651c4218230ad46b32856 Mon Sep 17 00:00:00 2001 From: Jens Peters Date: Sun, 25 Feb 2024 20:31:16 +0100 Subject: [PATCH 11/23] docs: add sendEventsMode to libinput snippet --- docs/labwc-config.5.scd | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 223eae0a..e634a27c 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -593,6 +593,7 @@ extending outward from the snapped edge. + ``` From d3c5b0ebb8125001f16211c7bbcdebeeac3596eb Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:28:51 +0100 Subject: [PATCH 12/23] CONTRIBUTING.md: Void maintainer nick change --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 33cb225e..1a5b41fa 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. From 43e29f1f8d66bb5c14a2fc57402da69ec6d849ef Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Wed, 28 Feb 2024 21:37:04 +0100 Subject: [PATCH 13/23] docs/rc.xml: remove gap from the example config Some distro packages install the example config at /etc/xdg/labwc/rc.xml and thus users of those packages were having a gap 10 setting by default. Lets remove the gap from the example config to match our intended default. --- docs/rc.xml | 4 ---- 1 file changed, 4 deletions(-) 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 From 9b47a5e11ebc88624fbfdb9c889cbae78cfbb0e5 Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 29 Feb 2024 15:23:25 +0100 Subject: [PATCH 14/23] Translation updates from weblate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alice Ventus Co-authored-by: Jouni Järvinen Co-authored-by: Moo Co-authored-by: Weblate Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/fi/ Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/lt/ Translate-URL: https://translate.lxqt-project.org/projects/labwc/labwc/ru/ Translation: Labwc/labwc --- po/fi.po | 11 +++++++---- po/lt.po | 11 +++++++---- po/ru.po | 5 ++--- 3 files changed, 16 insertions(+), 11 deletions(-) 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/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/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 "Свернуть/развернуть в заголовок" From e7345199909138ed43dbe64f10bd25c19272a60d Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Fri, 2 Feb 2024 20:55:16 +0000 Subject: [PATCH 15/23] NEWS.md: update for 0.7.1 --- NEWS.md | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) 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 From 59014e507175971e84af2b846b6b3a2c232cce7f Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Fri, 1 Mar 2024 21:16:21 +0000 Subject: [PATCH 16/23] build: bump version to 0.7.1 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: [ From 5a70027e3075e63280d087676575d6f19b33d390 Mon Sep 17 00:00:00 2001 From: zenobit Date: Sat, 2 Mar 2024 01:01:22 +0100 Subject: [PATCH 17/23] Add cs language --- po/LINGUAS | 2 +- po/cs.po | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 po/cs.po diff --git a/po/LINGUAS b/po/LINGUAS index b27cc570..1b2407b5 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1 +1 @@ -de es et eu fi gl hu 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" From 5b2b1c31ab483349b5baa272fdbb08fe2c580972 Mon Sep 17 00:00:00 2001 From: 01micko <01micko#gmail.com> Date: Sat, 2 Mar 2024 11:39:36 +1000 Subject: [PATCH 18/23] CONTRIBUTING.md: correct the instructions for adding a locale code --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a5b41fa..ef6ca30a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. From 1ea7e8b4944d56d21e08d409212e07a15c5f5c09 Mon Sep 17 00:00:00 2001 From: Birger Schacht <1143280+b1rger@users.noreply.github.com> Date: Sat, 2 Mar 2024 08:41:13 +0100 Subject: [PATCH 19/23] fix: typo in labwc-config.5.scd specifc -> specific --- docs/labwc-config.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index e634a27c..ec887f72 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -511,7 +511,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. From 7e338fc365d49f7ffb6bbb3050a142d05f373b59 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sat, 2 Mar 2024 15:34:52 +0000 Subject: [PATCH 20/23] view: fix view_get_adjacent_output() bug ...when using more than two outputs. Use the centre of the view's output as the reference coordinate when seeking adjacent outputs. Fixes: #1582 --- src/view.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/view.c b/src/view.c index 87b29e00..e297b725 100644 --- a/src/view.c +++ b/src/view.c @@ -1530,6 +1530,10 @@ view_get_adjacent_output(struct view *view, enum view_edge edge) return NULL; } + struct wlr_box box = output_usable_area_in_layout_coords(view->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; @@ -1537,19 +1541,19 @@ view_get_adjacent_output(struct view *view, enum view_edge edge) switch (edge) { case VIEW_EDGE_LEFT: new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_LEFT, current_output, 1, 0); + layout, WLR_DIRECTION_LEFT, current_output, lx, ly); break; case VIEW_EDGE_RIGHT: new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_RIGHT, current_output, 1, 0); + layout, WLR_DIRECTION_RIGHT, current_output, lx, ly); break; case VIEW_EDGE_UP: new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_UP, current_output, 0, 1); + layout, WLR_DIRECTION_UP, current_output, lx, ly); break; case VIEW_EDGE_DOWN: new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_DOWN, current_output, 0, 1); + layout, WLR_DIRECTION_DOWN, current_output, lx, ly); break; default: break; From 3c3bcc2765aa06c9fcf1e7e65862628de1ad33d1 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sat, 2 Mar 2024 15:42:05 +0000 Subject: [PATCH 21/23] view: add MoveToOutput `wrap` attribute Support `wrap` in view_get_adjacent_output(). This means that when seeking an adjacent output in a particular direction from an output that is already furthest in that direction within the layout, rather than returning NULL, wrap around from the leftmost to the rightmost, or topmost to the bottommost and vice versa. Example usage: Wrap is disabled by default to keep the user interface consistent. --- docs/labwc-actions.5.scd | 5 ++- include/view.h | 3 +- src/action.c | 7 +++- src/view.c | 81 ++++++++++++++++++++++++++++------------ 4 files changed, 69 insertions(+), 27 deletions(-) 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/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/src/action.c b/src/action.c index e1187906..953f62e7 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,7 +928,8 @@ 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."); diff --git a/src/view.c b/src/view.c index e297b725..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,7 +1567,7 @@ view_get_adjacent_output(struct view *view, enum view_edge edge) return NULL; } - struct wlr_box box = output_usable_area_in_layout_coords(view->output); + 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; @@ -1538,28 +1575,23 @@ view_get_adjacent_output(struct view *view, enum view_edge edge) 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, lx, ly); - break; - case VIEW_EDGE_RIGHT: - new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_RIGHT, current_output, lx, ly); - break; - case VIEW_EDGE_UP: - new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_UP, current_output, lx, ly); - break; - case VIEW_EDGE_DOWN: - new_output = wlr_output_layout_adjacent_output( - layout, WLR_DIRECTION_DOWN, current_output, lx, ly); - 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; } @@ -1633,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; } @@ -1792,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) { /* From 4ddeb3cd4224628c0a48fec5edc72b64a1ba08d7 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sat, 2 Mar 2024 19:40:33 +0000 Subject: [PATCH 22/23] action: reduce MoveToOutput logging --- src/action.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/action.c b/src/action.c index 953f62e7..1cf8960a 100644 --- a/src/action.c +++ b/src/action.c @@ -932,7 +932,11 @@ actions_run(struct view *activator, struct server *server, 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); From f90b7dca2a3e862ca64ced14165181c70938b6d7 Mon Sep 17 00:00:00 2001 From: "Andrew J. Hesford" Date: Sun, 18 Feb 2024 12:23:14 -0500 Subject: [PATCH 23/23] session: run shutdown script, clean up activation env before exit --- docs/labwc-config.5.scd | 23 ++++++++--- include/common/string-helpers.h | 19 +++++++++ include/config/session.h | 6 +++ src/common/string-helpers.c | 71 +++++++++++++++++++++++++++++++++ src/config/session.c | 52 +++++++++++++++++++----- src/main.c | 2 + 6 files changed, 157 insertions(+), 16 deletions(-) diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index ec887f72..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). 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/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/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/session.c b/src/config/session.c index c87b0865..bc9f6d47 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,19 @@ #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", + NULL, +}; + static void process_line(char *line) { @@ -65,7 +74,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 +84,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,14 +138,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"); - 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); @@ -138,7 +153,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); @@ -149,3 +164,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/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);